Merge branch 'master' into input-overhaul
This commit is contained in:
commit
357b6d3093
|
|
@ -77,7 +77,10 @@ class FunctionInterval(Interval.Interval):
|
|||
|
||||
@staticmethod
|
||||
def makeUniqueName(func, suffix = ''):
|
||||
name = 'Func-%s-%d' % (getattr(func, '__name__', str(func)), FunctionInterval.functionIntervalNum)
|
||||
func_name = getattr(func, '__name__', None)
|
||||
if func_name is None:
|
||||
func_name = str(func)
|
||||
name = 'Func-%s-%d' % (func_name, FunctionInterval.functionIntervalNum)
|
||||
FunctionInterval.functionIntervalNum += 1
|
||||
if suffix:
|
||||
name = '%s-%s' % (name, str(suffix))
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
HOW TO INSTALL MAX PANDA PLUGINS.
|
||||
|
||||
Step 1. Install the visual studio 2008 runtime by
|
||||
running "vcredist_x86-sp1.exe" as administrator.
|
||||
As a convenience, this installer is included with panda.
|
||||
|
||||
Step 2. Make sure that there is only one copy of panda
|
||||
in your system PATH. If you only have one copy of panda
|
||||
installed, you can skip this step.
|
||||
|
||||
Step 3. Copy the relevant DLLs for your version
|
||||
of max from the panda plugins directory to the
|
||||
max plugins directory. For instance, if you are
|
||||
using Max 9, copy maxegg9.dlo and maxeggimport9.dlo
|
||||
|
||||
HOW TO INSTALL MAYA PANDA PLUGINS.
|
||||
|
||||
(To be written)
|
||||
|
||||
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
------------------------ RELEASE 1.0.0 ---------------------------------
|
||||
|
||||
* We now have working exporters for Max5, Max6, Max7, Maya5, Maya6
|
||||
|
||||
* The Max exporter is dramatically improved:
|
||||
|
||||
- it now includes support for character studio.
|
||||
- the polygon winding bug has been fixed.
|
||||
|
||||
* Panda no longer requires any registry keys or environment
|
||||
variables. This means it is now possible to:
|
||||
|
||||
- run panda directly from a compact disc
|
||||
- install multiple copies of panda on a single machine
|
||||
- install panda by copying the tree from another computer
|
||||
|
||||
Note that the installer does add the panda 'bin' directory to
|
||||
your PATH, and it does store an uninstall key in the registry,
|
||||
but neither of these is needed for panda to function.
|
||||
|
||||
* The 'makepanda' build system is now capable of building
|
||||
prepackaged games for Windows. These prepackaged games are simply
|
||||
copies of panda with the game code included, some of the
|
||||
unnecessary stuff stripped out, and some changes to the start
|
||||
menu. See "Airblade - Installer" on the panda downloads page
|
||||
for an example.
|
||||
|
||||
* All of the sample programs have been tested. The ones that didn't
|
||||
work have been removed, the ones that do work have been (lightly)
|
||||
documented.
|
||||
|
||||
* This is the first release to include not just a binary installer
|
||||
for windows, but:
|
||||
|
||||
- a binary installer (RPM) for Fedora 2
|
||||
- a binary installer (RPM) for Fedora 3
|
||||
- a binary installer (RPM) for Redhat 9
|
||||
- a binary installer for windows, as always
|
||||
- a source tar-ball for linux
|
||||
- a source zip-file for windows
|
||||
|
||||
------------------------ RELEASE 2004-12-13 ---------------------------------
|
||||
|
||||
* Basic server-client networking support is back in Panda3D. There is a
|
||||
networking sample in the samples directory. This uses the Panda3d
|
||||
distributed object system.The README file will explain how to run this.
|
||||
Documentation of this if forthcoming.
|
||||
|
||||
* Panda3d now reduces the number of environment variables such that only 2
|
||||
are needed now - PRC_PATH and PLAYER.
|
||||
|
||||
* GraphicsChannel and GraphicsLayer class have been removed from the
|
||||
panda/src/display directory. Most Panda applications won't need to be
|
||||
changed, since most applications simply use ShowBase.py (which has been
|
||||
adjustedappropriately) to open a window and do the initial setup. For
|
||||
those rare applications where you need to create your own DisplayRegions,
|
||||
the makeDisplayRegion() interface has been moved from GraphicsLayer to
|
||||
GraphicsWindow (actually, to GraphicsOutput, which is the base class of
|
||||
GraphicsWindow). You can modify your application to call
|
||||
base.win.makeDisplayRegion() accordingly. If you have something like
|
||||
displayRegion.getLayer(), replace it with displayRegion.getWindow()
|
||||
instead.
|
||||
|
||||
* Effective with the current version of Panda, the way that HPR angles are
|
||||
calculated will be changing. The change will make a difference to existing
|
||||
code or databases that store a hard-coded rotation as a HPR, but only when
|
||||
R is involved, or both H and P are involved together. That is to say more
|
||||
precisely, HPR angles with (R != 0 || (H != 0 && P != 0)) now represent a
|
||||
different rotation than they used to. If you find some legacy code that no
|
||||
longer works correctly (e.g. it introduces crazy rotations), try putting
|
||||
the following in your Config.prc file:
|
||||
|
||||
temp-hpr-fix 0
|
||||
|
||||
To turn off the correct behavior and return to the old, broken behavior.
|
||||
Note that a longer-term solution will be to represent the HPR angles
|
||||
correctly in all legacy code. The function oldToNewHpr() is provided to
|
||||
aid this transition.
|
||||
|
||||
* PandaNode definition has been changed to support setting an
|
||||
into_collide_mask for any arbitrary node, in particular for any GeomNode.
|
||||
It used to be that only CollisionNodes had an into_collide_mask. This
|
||||
change obviates the need for CollisionNode::set_collide_geom(), which is
|
||||
now a deprecated interface and will be removed at some point in the future.
|
||||
|
||||
Details:
|
||||
There's now a NodePath::set_collide_mask() and
|
||||
NodePath::get_collide_mask(), which operate on all CollisionNodes and
|
||||
GeomNodes at and below the current node. By default, set_collide_mask()
|
||||
will replace the entire collide mask, but you may also specify (via a
|
||||
second parameter) the subset of bits that are to be changed; other bits
|
||||
will be left alone. You can also specify a particular type of node to
|
||||
modify via a third parameter, e.g. you can adjust the masks for GeomNodes
|
||||
or CollisionNodes only.
|
||||
|
||||
The NodePath set_collide_mask() interface changes the into_collide_mask.
|
||||
Those familiar with the collision system will recall that a CollisionNode
|
||||
(but only a CollisionNode) also has a from_collide_mask. The
|
||||
from_collide_mask of the active mover is compared with the into_collide_mask
|
||||
of each object in the world; a collision is only possible if there are some
|
||||
bits in common.
|
||||
|
||||
It used to be that only other CollisionNodes had an into_collide_mask. A
|
||||
mover would only test for collisions with CollisionNodes that matched its
|
||||
collide_mask. If you wanted to make your mover detect collisions with
|
||||
visible geometry which had no into_collide_mask, you had to call
|
||||
set_collide_geom(1). This allowed the mover to detect collisions with *all*
|
||||
visible geometry; it was either an all-or-none thing.
|
||||
|
||||
Now that GeomNodes also have an into_collide_mask, there's no longer a need
|
||||
for set_collide_geom(). A mover will detect collisions with any
|
||||
CollisionNodes or GeomNodes that match its collide_mask. This means, for
|
||||
the purposes of collision detection, you can use CollisionNodes and
|
||||
GeomNodes pretty much interchangeably; simply set the appropriate bits on
|
||||
the objects you want to collide with, regardless of whether they are
|
||||
invisible collision solids or visible geometry.
|
||||
|
||||
(This should not be taken as a license to avoid using CollisionNodes
|
||||
altogether. The intersection computation with visible geometry is still
|
||||
less efficient than the same computation with collision solids. And visible
|
||||
geometry tends to be many times more complex than is strictly necessary for
|
||||
collisions.)
|
||||
|
||||
There's one more detail: every GeomNode, by default, has one bit set on in
|
||||
its collide_mask, unless it is explicitly turned off. This bit is
|
||||
GeomNode::get_default_collide_mask(). This bit is provided for the
|
||||
convenience of programmers who still want the old behavior of
|
||||
set_collide_geom(): it allows you to easily create a CollisionNode that
|
||||
will collide with all visible geometry in the world.
|
||||
|
||||
Along the same lines, there's also CollisionNode::get_default_collide_mask(),
|
||||
which is 0x000fffff. This is the default mask that is created for a new
|
||||
CollisionNode (and it does not include the bit reserved for GeomNodes,
|
||||
above). Previously, a new CollisionNode would have all bits on by default.
|
||||
|
||||
|
||||
|
||||
------------------------ RELEASE 2004-11-11 -----------------------------------
|
||||
|
||||
* Multiple mice can now be used with Panda3D. showbase has a list called
|
||||
pointerWatcherNodes. The first mouse on this list is the system mouse. The
|
||||
getMouseX() and getMouseY() will return coordinates relative to the
|
||||
application window. The rest of the mice on the list will give raw mouse
|
||||
positions and will change when they are moved on the screen.
|
||||
|
||||
In addition there are new events for mouse buttons. Each mouse will be have
|
||||
a corresponding event. mouse1 will send mousedev1-mouse1, mousedev1-mouse2
|
||||
and mousedev1-mouse3 events. mouse2 and any other mouse attached
|
||||
will send similar events mousedev2-mouse1 etc.
|
||||
|
||||
The old mouse buttons work too. mouse1, mouse2, mouse3 events will be
|
||||
triggered if that button is pressed on any mouse
|
||||
|
||||
------------------------ RELEASE 2004-10-13 -----------------------------------
|
||||
|
||||
General
|
||||
|
||||
* Release notes: Each release will now have an entry associated with
|
||||
it in this document. This will be updated in reverse-chronological order.
|
||||
|
||||
Panda3D
|
||||
* Distributed with this release is a working version of the SceneEditor
|
||||
created in Spring 2004 at the ETC. Documentation will be forthcoming on the
|
||||
website. This can be found in <InstallPath>/SceneEditor
|
||||
|
||||
* The latest version of FMOD is distributed with this release. The latest
|
||||
version is 3.73.
|
||||
|
||||
* AudioSound object now allows more types of sound. These include wma and
|
||||
ogg vorbis formats. This is valid when using the fmod sound system. Midi,
|
||||
Mod, s3m, it, xm and such sequencer type file formats are not supported.
|
||||
Exception - Midi files can be played. This is not fully implemented.
|
||||
|
||||
* A bug in SoundInterval is fixed. SoundInterval looping would incorrectly
|
||||
add a minimum of 1.5 seconds to the sound. This has been fixed. Sound
|
||||
looping problems in general should be fixed. Midi's still don't support
|
||||
looping through the AudioSound object. They should loop through
|
||||
SoundIntervals though.
|
||||
|
||||
* Cg support has been added to Panda3D. Documentation for this is
|
||||
forthcoming.
|
||||
|
||||
|
||||
|
|
@ -306,7 +306,6 @@ is_trivial() const {
|
|||
}
|
||||
|
||||
// Now look for functions that are virtual or con/destructors.
|
||||
bool is_default_constructible = true;
|
||||
CPPScope::Functions::const_iterator fi;
|
||||
for (fi = _scope->_functions.begin(); fi != _scope->_functions.end(); ++fi) {
|
||||
CPPFunctionGroup *fgroup = (*fi).second;
|
||||
|
|
@ -343,9 +342,6 @@ is_trivial() const {
|
|||
// Same for the default constructor.
|
||||
return false;
|
||||
}
|
||||
// The presence of a non-default constructor makes the class not
|
||||
// default-constructible.
|
||||
is_default_constructible = false;
|
||||
}
|
||||
|
||||
if (fgroup->_name == "operator =") {
|
||||
|
|
@ -356,7 +352,7 @@ is_trivial() const {
|
|||
}
|
||||
|
||||
// Finally, the class must be default-constructible.
|
||||
return is_default_constructible;
|
||||
return is_default_constructible(V_public);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -62,4 +62,12 @@ default_thread_consider_yield() {
|
|||
void (*global_thread_yield)() = default_thread_yield;
|
||||
void (*global_thread_consider_yield)() = default_thread_consider_yield;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
static PyThreadState *
|
||||
default_thread_state_swap(PyThreadState *state) {
|
||||
return nullptr;
|
||||
}
|
||||
PyThreadState *(*global_thread_state_swap)(PyThreadState *tstate) = default_thread_state_swap;
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#endif // HAVE_THREADS && SIMPLE_THREADS
|
||||
|
|
|
|||
|
|
@ -63,8 +63,10 @@
|
|||
/* Windows likes to define min() and max() macros, which will conflict with
|
||||
std::min() and std::max() respectively, unless we do this: */
|
||||
#ifdef WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
|
|
|
|||
|
|
@ -233,6 +233,15 @@ INLINE void thread_consider_yield() {
|
|||
(*global_thread_consider_yield)();
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
typedef struct _ts PyThreadState;
|
||||
extern EXPCL_DTOOL_DTOOLBASE PyThreadState *(*global_thread_state_swap)(PyThreadState *tstate);
|
||||
|
||||
INLINE PyThreadState *thread_state_swap(PyThreadState *tstate) {
|
||||
return (*global_thread_state_swap)(tstate);
|
||||
}
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#else
|
||||
|
||||
INLINE void thread_yield() {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
#include "filename_ext.cxx"
|
||||
#include "globPattern_ext.cxx"
|
||||
#include "textEncoder_ext.cxx"
|
||||
|
|
|
|||
|
|
@ -53,5 +53,5 @@ StringUtf8Decoder(const std::string &input) : StringDecoder(input) {
|
|||
*
|
||||
*/
|
||||
INLINE StringUnicodeDecoder::
|
||||
StringUnicodeDecoder(const std::string &input) : StringDecoder(input) {
|
||||
StringUtf16Decoder(const std::string &input) : StringDecoder(input) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ StringDecoder::
|
|||
/**
|
||||
* Returns the next character in sequence.
|
||||
*/
|
||||
int StringDecoder::
|
||||
char32_t StringDecoder::
|
||||
get_next_character() {
|
||||
if (test_eof()) {
|
||||
return -1;
|
||||
|
|
@ -57,19 +57,20 @@ get_notify_ptr() {
|
|||
|
||||
/*
|
||||
In UTF-8, each 16-bit Unicode character is encoded as a sequence of
|
||||
one, two, or three 8-bit bytes, depending on the value of the
|
||||
one, two, three or four 8-bit bytes, depending on the value of the
|
||||
character. The following table shows the format of such UTF-8 byte
|
||||
sequences (where the "free bits" shown by x's in the table are
|
||||
combined in the order shown, and interpreted from most significant to
|
||||
least significant):
|
||||
|
||||
Binary format of bytes in sequence:
|
||||
Number of Maximum expressible
|
||||
1st byte 2nd byte 3rd byte free bits: Unicode value:
|
||||
Number of Maximum expressible
|
||||
1st byte 2nd byte 3rd byte 4th byte free bits: Unicode value:
|
||||
|
||||
0xxxxxxx 7 007F hex (127)
|
||||
110xxxxx 10xxxxxx (5+6)=11 07FF hex (2047)
|
||||
1110xxxx 10xxxxxx 10xxxxxx (4+6+6)=16 FFFF hex (65535)
|
||||
0xxxxxxx 7 007F hex (127)
|
||||
110xxxxx 10xxxxxx (5+6)=11 07FF hex (2047)
|
||||
1110xxxx 10xxxxxx 10xxxxxx (4+6+6)=16 FFFF hex (65535)
|
||||
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (4+6*3)=21 10FFFF hex (1114111)
|
||||
|
||||
The value of each individual byte indicates its UTF-8 function, as follows:
|
||||
|
||||
|
|
@ -77,12 +78,13 @@ The value of each individual byte indicates its UTF-8 function, as follows:
|
|||
80 to BF hex (128 to 191): continuing byte in a multi-byte sequence.
|
||||
C2 to DF hex (194 to 223): first byte of a two-byte sequence.
|
||||
E0 to EF hex (224 to 239): first byte of a three-byte sequence.
|
||||
F0 to F7 hex (240 to 247): first byte of a four-byte sequence.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the next character in sequence.
|
||||
*/
|
||||
int StringUtf8Decoder::
|
||||
char32_t StringUtf8Decoder::
|
||||
get_next_character() {
|
||||
unsigned int result;
|
||||
while (!test_eof()) {
|
||||
|
|
@ -125,6 +127,35 @@ get_next_character() {
|
|||
unsigned int three = (unsigned char)_input[_p++];
|
||||
result = ((result & 0x0f) << 12) | ((two & 0x3f) << 6) | (three & 0x3f);
|
||||
return result;
|
||||
|
||||
} else if ((result & 0xf8) == 0xf0) {
|
||||
// First byte of four.
|
||||
if (test_eof()) {
|
||||
if (_notify_ptr != nullptr) {
|
||||
(*_notify_ptr)
|
||||
<< "utf-8 encoded string '" << _input << "' ends abruptly.\n";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
unsigned int two = (unsigned char)_input[_p++];
|
||||
if (test_eof()) {
|
||||
if (_notify_ptr != nullptr) {
|
||||
(*_notify_ptr)
|
||||
<< "utf-8 encoded string '" << _input << "' ends abruptly.\n";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
unsigned int three = (unsigned char)_input[_p++];
|
||||
if (test_eof()) {
|
||||
if (_notify_ptr != nullptr) {
|
||||
(*_notify_ptr)
|
||||
<< "utf-8 encoded string '" << _input << "' ends abruptly.\n";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
unsigned int four = (unsigned char)_input[_p++];
|
||||
result = ((result & 0x07) << 18) | ((two & 0x3f) << 12) | ((three & 0x3f) << 6) | (four & 0x3f);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Otherwise--the high bit is set but it is not one of the introductory
|
||||
|
|
@ -144,7 +175,7 @@ get_next_character() {
|
|||
/**
|
||||
* Returns the next character in sequence.
|
||||
*/
|
||||
int StringUnicodeDecoder::
|
||||
char32_t StringUtf16Decoder::
|
||||
get_next_character() {
|
||||
if (test_eof()) {
|
||||
return -1;
|
||||
|
|
@ -159,5 +190,33 @@ get_next_character() {
|
|||
return -1;
|
||||
}
|
||||
unsigned int low = (unsigned char)_input[_p++];
|
||||
return ((high << 8) | low);
|
||||
int ch = ((high << 8) | low);
|
||||
|
||||
/*
|
||||
using std::swap;
|
||||
|
||||
if (ch == 0xfffe) {
|
||||
// This is a byte-swapped byte-order-marker. That means we need to swap
|
||||
// the endianness of the rest of the stream.
|
||||
char *data = (char *)_input.data();
|
||||
for (size_t p = _p; p < _input.size() - 1; p += 2) {
|
||||
std::swap(data[p], data[p + 1]);
|
||||
}
|
||||
ch = 0xfeff;
|
||||
}
|
||||
*/
|
||||
|
||||
if (ch >= 0xd800 && ch < 0xdc00 && (_p + 1) < _input.size()) {
|
||||
// This is a high surrogate. Look for a subsequent low surrogate.
|
||||
unsigned int high = (unsigned char)_input[_p];
|
||||
unsigned int low = (unsigned char)_input[_p + 1];
|
||||
int ch2 = ((high << 8) | low);
|
||||
if (ch2 >= 0xdc00 && ch2 < 0xe000) {
|
||||
// Yes, this is a low surrogate.
|
||||
_p += 2;
|
||||
return 0x10000 + ((ch - 0xd800) << 10) + (ch2 - 0xdc00);
|
||||
}
|
||||
}
|
||||
// No, this is just a regular character, or an unpaired surrogate.
|
||||
return ch;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public:
|
|||
INLINE StringDecoder(const std::string &input);
|
||||
virtual ~StringDecoder();
|
||||
|
||||
virtual int get_next_character();
|
||||
virtual char32_t get_next_character();
|
||||
INLINE bool is_eof();
|
||||
|
||||
static void set_notify_ptr(std::ostream *ptr);
|
||||
|
|
@ -48,20 +48,23 @@ class StringUtf8Decoder : public StringDecoder {
|
|||
public:
|
||||
INLINE StringUtf8Decoder(const std::string &input);
|
||||
|
||||
virtual int get_next_character();
|
||||
virtual char32_t get_next_character();
|
||||
};
|
||||
|
||||
/**
|
||||
* This decoder extracts characters two at a time to get a plain wide
|
||||
* character sequence.
|
||||
* character sequence. It supports surrogate pairs.
|
||||
*/
|
||||
class StringUnicodeDecoder : public StringDecoder {
|
||||
class StringUtf16Decoder : public StringDecoder {
|
||||
public:
|
||||
INLINE StringUnicodeDecoder(const std::string &input);
|
||||
INLINE StringUtf16Decoder(const std::string &input);
|
||||
|
||||
virtual int get_next_character();
|
||||
virtual char32_t get_next_character();
|
||||
};
|
||||
|
||||
// Deprecated alias of StringUtf16Encoder.
|
||||
typedef StringUtf16Decoder StringUnicodeDecoder;
|
||||
|
||||
#include "stringDecoder.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ set_text(const std::string &text) {
|
|||
if (!has_text() || _text != text) {
|
||||
_text = text;
|
||||
_flags = (_flags | F_got_text) & ~F_got_wtext;
|
||||
text_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +102,11 @@ set_text(const std::string &text) {
|
|||
*/
|
||||
INLINE void TextEncoder::
|
||||
set_text(const std::string &text, TextEncoder::Encoding encoding) {
|
||||
set_wtext(decode_text(text, encoding));
|
||||
if (encoding == _encoding) {
|
||||
set_text(text);
|
||||
} else {
|
||||
set_wtext(decode_text(text, encoding));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,6 +117,7 @@ clear_text() {
|
|||
_text = std::string();
|
||||
_wtext = std::wstring();
|
||||
_flags |= (F_got_text | F_got_wtext);
|
||||
text_changed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,8 +157,11 @@ get_text(TextEncoder::Encoding encoding) const {
|
|||
*/
|
||||
INLINE void TextEncoder::
|
||||
append_text(const std::string &text) {
|
||||
_text = get_text() + text;
|
||||
_flags = (_flags | F_got_text) & ~F_got_wtext;
|
||||
if (!text.empty()) {
|
||||
_text = get_text() + text;
|
||||
_flags = (_flags | F_got_text) & ~F_got_wtext;
|
||||
text_changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -160,9 +169,25 @@ append_text(const std::string &text) {
|
|||
* wide character, up to 16 bits in Unicode.
|
||||
*/
|
||||
INLINE void TextEncoder::
|
||||
append_unicode_char(int character) {
|
||||
append_unicode_char(char32_t character) {
|
||||
#if WCHAR_MAX >= 0x10FFFF
|
||||
// wchar_t might be UTF-32.
|
||||
_wtext = get_wtext() + std::wstring(1, (wchar_t)character);
|
||||
#else
|
||||
if ((character & ~0xffff) == 0) {
|
||||
_wtext = get_wtext() + std::wstring(1, (wchar_t)character);
|
||||
} else {
|
||||
// Encode as a surrogate pair.
|
||||
uint32_t v = (uint32_t)character - 0x10000u;
|
||||
wchar_t wstr[2] = {
|
||||
(wchar_t)((v >> 10u) | 0xd800u),
|
||||
(wchar_t)((v & 0x3ffu) | 0xdc00u),
|
||||
};
|
||||
_wtext = get_wtext() + std::wstring(wstr, 2);
|
||||
}
|
||||
#endif
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
text_changed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -195,11 +220,12 @@ get_unicode_char(size_t index) const {
|
|||
* according to set_encoding().
|
||||
*/
|
||||
INLINE void TextEncoder::
|
||||
set_unicode_char(size_t index, int character) {
|
||||
set_unicode_char(size_t index, char32_t character) {
|
||||
get_wtext();
|
||||
if (index < _wtext.length()) {
|
||||
_wtext[index] = character;
|
||||
_flags &= ~F_got_text;
|
||||
text_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +283,7 @@ reencode_text(const std::string &text, TextEncoder::Encoding from,
|
|||
* otherwise. This is akin to ctype's isalpha(), extended to Unicode.
|
||||
*/
|
||||
INLINE bool TextEncoder::
|
||||
unicode_isalpha(int character) {
|
||||
unicode_isalpha(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
return false;
|
||||
|
|
@ -271,7 +297,7 @@ unicode_isalpha(int character) {
|
|||
* otherwise. This is akin to ctype's isdigit(), extended to Unicode.
|
||||
*/
|
||||
INLINE bool TextEncoder::
|
||||
unicode_isdigit(int character) {
|
||||
unicode_isdigit(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
// The digits aren't actually listed in the map.
|
||||
|
|
@ -286,11 +312,11 @@ unicode_isdigit(int character) {
|
|||
* otherwise. This is akin to ctype's ispunct(), extended to Unicode.
|
||||
*/
|
||||
INLINE bool TextEncoder::
|
||||
unicode_ispunct(int character) {
|
||||
unicode_ispunct(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
// Some punctuation marks aren't listed in the map.
|
||||
return (character >= 0 && character < 128 && ispunct(character));
|
||||
return (character < 128 && ispunct(character));
|
||||
}
|
||||
return entry->_char_type == UnicodeLatinMap::CT_punct;
|
||||
}
|
||||
|
|
@ -300,7 +326,7 @@ unicode_ispunct(int character) {
|
|||
* otherwise. This is akin to ctype's isupper(), extended to Unicode.
|
||||
*/
|
||||
INLINE bool TextEncoder::
|
||||
unicode_isupper(int character) {
|
||||
unicode_isupper(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
return false;
|
||||
|
|
@ -313,7 +339,7 @@ unicode_isupper(int character) {
|
|||
* otherwise. This is akin to ctype's isspace(), extended to Unicode.
|
||||
*/
|
||||
INLINE bool TextEncoder::
|
||||
unicode_isspace(int character) {
|
||||
unicode_isspace(char32_t character) {
|
||||
switch (character) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
|
|
@ -330,7 +356,7 @@ unicode_isspace(int character) {
|
|||
* otherwise. This is akin to ctype's islower(), extended to Unicode.
|
||||
*/
|
||||
INLINE bool TextEncoder::
|
||||
unicode_islower(int character) {
|
||||
unicode_islower(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
return false;
|
||||
|
|
@ -343,7 +369,7 @@ unicode_islower(int character) {
|
|||
* akin to ctype's toupper(), extended to Unicode.
|
||||
*/
|
||||
INLINE int TextEncoder::
|
||||
unicode_toupper(int character) {
|
||||
unicode_toupper(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
return character;
|
||||
|
|
@ -356,7 +382,7 @@ unicode_toupper(int character) {
|
|||
* akin to ctype's tolower(), extended to Unicode.
|
||||
*/
|
||||
INLINE int TextEncoder::
|
||||
unicode_tolower(int character) {
|
||||
unicode_tolower(char32_t character) {
|
||||
const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
|
||||
if (entry == nullptr) {
|
||||
return character;
|
||||
|
|
@ -418,6 +444,7 @@ set_wtext(const std::wstring &wtext) {
|
|||
if (!has_text() || _wtext != wtext) {
|
||||
_wtext = wtext;
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
text_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -439,8 +466,11 @@ get_wtext() const {
|
|||
*/
|
||||
INLINE void TextEncoder::
|
||||
append_wtext(const std::wstring &wtext) {
|
||||
_wtext = get_wtext() + wtext;
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
if (!wtext.empty()) {
|
||||
_wtext = get_wtext() + wtext;
|
||||
_flags = (_flags | F_got_wtext) & ~F_got_text;
|
||||
text_changed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ using std::ostream;
|
|||
using std::string;
|
||||
using std::wstring;
|
||||
|
||||
TextEncoder::Encoding TextEncoder::_default_encoding = TextEncoder::E_iso8859;
|
||||
TextEncoder::Encoding TextEncoder::_default_encoding = TextEncoder::E_utf8;
|
||||
|
||||
/**
|
||||
* Adjusts the text stored within the encoder to all uppercase letters
|
||||
|
|
@ -35,6 +35,7 @@ make_upper() {
|
|||
(*si) = unicode_toupper(*si);
|
||||
}
|
||||
_flags &= ~F_got_text;
|
||||
text_changed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,6 +50,7 @@ make_lower() {
|
|||
(*si) = unicode_tolower(*si);
|
||||
}
|
||||
_flags &= ~F_got_text;
|
||||
text_changed();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,11 +109,11 @@ is_wtext() const {
|
|||
}
|
||||
|
||||
/**
|
||||
* Encodes a single wide char into a one-, two-, or three-byte string,
|
||||
* according to the given encoding system.
|
||||
* Encodes a single Unicode character into a one-, two-, three-, or four-byte
|
||||
* string, according to the given encoding system.
|
||||
*/
|
||||
string TextEncoder::
|
||||
encode_wchar(wchar_t ch, TextEncoder::Encoding encoding) {
|
||||
encode_wchar(char32_t ch, TextEncoder::Encoding encoding) {
|
||||
switch (encoding) {
|
||||
case E_iso8859:
|
||||
if ((ch & ~0xff) == 0) {
|
||||
|
|
@ -143,17 +145,38 @@ encode_wchar(wchar_t ch, TextEncoder::Encoding encoding) {
|
|||
return
|
||||
string(1, (char)((ch >> 6) | 0xc0)) +
|
||||
string(1, (char)((ch & 0x3f) | 0x80));
|
||||
} else {
|
||||
} else if ((ch & ~0xffff) == 0) {
|
||||
return
|
||||
string(1, (char)((ch >> 12) | 0xe0)) +
|
||||
string(1, (char)(((ch >> 6) & 0x3f) | 0x80)) +
|
||||
string(1, (char)((ch & 0x3f) | 0x80));
|
||||
} else {
|
||||
return
|
||||
string(1, (char)((ch >> 18) | 0xf0)) +
|
||||
string(1, (char)(((ch >> 12) & 0x3f) | 0x80)) +
|
||||
string(1, (char)(((ch >> 6) & 0x3f) | 0x80)) +
|
||||
string(1, (char)((ch & 0x3f) | 0x80));
|
||||
}
|
||||
|
||||
case E_unicode:
|
||||
return
|
||||
string(1, (char)(ch >> 8)) +
|
||||
string(1, (char)(ch & 0xff));
|
||||
case E_utf16be:
|
||||
if ((ch & ~0xffff) == 0) {
|
||||
// Note that this passes through surrogates and BOMs unharmed.
|
||||
return
|
||||
string(1, (char)(ch >> 8)) +
|
||||
string(1, (char)(ch & 0xff));
|
||||
} else {
|
||||
// Use a surrogate pair.
|
||||
uint32_t v = (uint32_t)ch - 0x10000u;
|
||||
uint16_t hi = (v >> 10u) | 0xd800u;
|
||||
uint16_t lo = (v & 0x3ffu) | 0xdc00u;
|
||||
char encoded[4] = {
|
||||
(char)(hi >> 8),
|
||||
(char)(hi & 0xff),
|
||||
(char)(lo >> 8),
|
||||
(char)(lo & 0xff),
|
||||
};
|
||||
return string(encoded, 4);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
|
|
@ -167,8 +190,25 @@ string TextEncoder::
|
|||
encode_wtext(const wstring &wtext, TextEncoder::Encoding encoding) {
|
||||
string result;
|
||||
|
||||
for (wstring::const_iterator pi = wtext.begin(); pi != wtext.end(); ++pi) {
|
||||
result += encode_wchar(*pi, encoding);
|
||||
for (size_t i = 0; i < wtext.size(); ++i) {
|
||||
wchar_t ch = wtext[i];
|
||||
|
||||
// On some systems, wstring may be UTF-16, and contain surrogate pairs.
|
||||
#if WCHAR_MAX < 0x10FFFF
|
||||
if (ch >= 0xd800 && ch < 0xdc00 && (i + 1) < wtext.size()) {
|
||||
// This is a high surrogate. Look for a subsequent low surrogate.
|
||||
wchar_t ch2 = wtext[i + 1];
|
||||
if (ch2 >= 0xdc00 && ch2 < 0xe000) {
|
||||
// Yes, this is a low surrogate.
|
||||
char32_t code_point = 0x10000 + ((ch - 0xd800) << 10) + (ch2 - 0xdc00);
|
||||
result += encode_wchar(code_point, encoding);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
result += encode_wchar(ch, encoding);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -187,9 +227,9 @@ decode_text(const string &text, TextEncoder::Encoding encoding) {
|
|||
return decode_text_impl(decoder);
|
||||
}
|
||||
|
||||
case E_unicode:
|
||||
case E_utf16be:
|
||||
{
|
||||
StringUnicodeDecoder decoder(text);
|
||||
StringUtf16Decoder decoder(text);
|
||||
return decode_text_impl(decoder);
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +251,7 @@ decode_text_impl(StringDecoder &decoder) {
|
|||
wstring result;
|
||||
// bool expand_amp = get_expand_amp();
|
||||
|
||||
wchar_t character = decoder.get_next_character();
|
||||
char32_t character = decoder.get_next_character();
|
||||
while (!decoder.is_eof()) {
|
||||
/*
|
||||
if (character == '&' && expand_amp) {
|
||||
|
|
@ -219,7 +259,14 @@ decode_text_impl(StringDecoder &decoder) {
|
|||
character = expand_amp_sequence(decoder);
|
||||
}
|
||||
*/
|
||||
result += character;
|
||||
if (character <= WCHAR_MAX) {
|
||||
result += character;
|
||||
} else {
|
||||
// We need to encode this as a surrogate pair.
|
||||
uint32_t v = (uint32_t)character - 0x10000u;
|
||||
result += (wchar_t)((v >> 10u) | 0xd800u);
|
||||
result += (wchar_t)((v & 0x3ffu) | 0xdc00u);
|
||||
}
|
||||
character = decoder.get_next_character();
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +361,12 @@ expand_amp_sequence(StringDecoder &decoder) const {
|
|||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called whenever the text has been changed.
|
||||
*/
|
||||
void TextEncoder::
|
||||
text_changed() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -327,8 +380,8 @@ operator << (ostream &out, TextEncoder::Encoding encoding) {
|
|||
case TextEncoder::E_utf8:
|
||||
return out << "utf8";
|
||||
|
||||
case TextEncoder::E_unicode:
|
||||
return out << "unicode";
|
||||
case TextEncoder::E_utf16be:
|
||||
return out << "utf16be";
|
||||
};
|
||||
|
||||
return out << "**invalid TextEncoder::Encoding(" << (int)encoding << ")**";
|
||||
|
|
@ -346,8 +399,9 @@ operator >> (istream &in, TextEncoder::Encoding &encoding) {
|
|||
encoding = TextEncoder::E_iso8859;
|
||||
} else if (word == "utf8" || word == "utf-8") {
|
||||
encoding = TextEncoder::E_utf8;
|
||||
} else if (word == "unicode") {
|
||||
encoding = TextEncoder::E_unicode;
|
||||
} else if (word == "unicode" || word == "utf16be" || word == "utf-16be" ||
|
||||
word == "utf16-be" || word == "utf-16-be") {
|
||||
encoding = TextEncoder::E_utf16be;
|
||||
} else {
|
||||
ostream *notify_ptr = StringDecoder::get_notify_ptr();
|
||||
if (notify_ptr != nullptr) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class StringDecoder;
|
|||
|
||||
/**
|
||||
* This class can be used to convert text between multiple representations,
|
||||
* e.g. utf-8 to Unicode. You may use it as a static class object, passing
|
||||
* e.g. UTF-8 to UTF-16. You may use it as a static class object, passing
|
||||
* the encoding each time, or you may create an instance and use that object,
|
||||
* which will record the current encoding and retain the current string.
|
||||
*
|
||||
|
|
@ -35,12 +35,17 @@ PUBLISHED:
|
|||
enum Encoding {
|
||||
E_iso8859,
|
||||
E_utf8,
|
||||
E_unicode
|
||||
E_utf16be,
|
||||
|
||||
// Deprecated alias for E_utf16be
|
||||
E_unicode = E_utf16be,
|
||||
};
|
||||
|
||||
INLINE TextEncoder();
|
||||
INLINE TextEncoder(const TextEncoder ©);
|
||||
|
||||
virtual ~TextEncoder() = default;
|
||||
|
||||
INLINE void set_encoding(Encoding encoding);
|
||||
INLINE Encoding get_encoding() const;
|
||||
|
||||
|
|
@ -48,35 +53,46 @@ PUBLISHED:
|
|||
INLINE static Encoding get_default_encoding();
|
||||
MAKE_PROPERTY(default_encoding, get_default_encoding, set_default_encoding);
|
||||
|
||||
#ifdef CPPPARSER
|
||||
EXTEND void set_text(PyObject *text);
|
||||
EXTEND void set_text(PyObject *text, Encoding encoding);
|
||||
#else
|
||||
INLINE void set_text(const std::string &text);
|
||||
INLINE void set_text(const std::string &text, Encoding encoding);
|
||||
#endif
|
||||
INLINE void clear_text();
|
||||
INLINE bool has_text() const;
|
||||
|
||||
void make_upper();
|
||||
void make_lower();
|
||||
|
||||
#ifdef CPPPARSER
|
||||
EXTEND PyObject *get_text() const;
|
||||
EXTEND PyObject *get_text(Encoding encoding) const;
|
||||
EXTEND void append_text(PyObject *text);
|
||||
#else
|
||||
INLINE std::string get_text() const;
|
||||
INLINE std::string get_text(Encoding encoding) const;
|
||||
INLINE void append_text(const std::string &text);
|
||||
INLINE void append_unicode_char(int character);
|
||||
#endif
|
||||
INLINE void append_unicode_char(char32_t character);
|
||||
INLINE size_t get_num_chars() const;
|
||||
INLINE int get_unicode_char(size_t index) const;
|
||||
INLINE void set_unicode_char(size_t index, int character);
|
||||
INLINE void set_unicode_char(size_t index, char32_t character);
|
||||
INLINE std::string get_encoded_char(size_t index) const;
|
||||
INLINE std::string get_encoded_char(size_t index, Encoding encoding) const;
|
||||
INLINE std::string get_text_as_ascii() const;
|
||||
|
||||
INLINE static std::string reencode_text(const std::string &text, Encoding from, Encoding to);
|
||||
|
||||
INLINE static bool unicode_isalpha(int character);
|
||||
INLINE static bool unicode_isdigit(int character);
|
||||
INLINE static bool unicode_ispunct(int character);
|
||||
INLINE static bool unicode_islower(int character);
|
||||
INLINE static bool unicode_isupper(int character);
|
||||
INLINE static bool unicode_isspace(int character);
|
||||
INLINE static int unicode_toupper(int character);
|
||||
INLINE static int unicode_tolower(int character);
|
||||
INLINE static bool unicode_isalpha(char32_t character);
|
||||
INLINE static bool unicode_isdigit(char32_t character);
|
||||
INLINE static bool unicode_ispunct(char32_t character);
|
||||
INLINE static bool unicode_islower(char32_t character);
|
||||
INLINE static bool unicode_isupper(char32_t character);
|
||||
INLINE static bool unicode_isspace(char32_t character);
|
||||
INLINE static int unicode_toupper(char32_t character);
|
||||
INLINE static int unicode_tolower(char32_t character);
|
||||
|
||||
INLINE static std::string upper(const std::string &source);
|
||||
INLINE static std::string upper(const std::string &source, Encoding encoding);
|
||||
|
|
@ -91,11 +107,24 @@ PUBLISHED:
|
|||
std::wstring get_wtext_as_ascii() const;
|
||||
bool is_wtext() const;
|
||||
|
||||
static std::string encode_wchar(wchar_t ch, Encoding encoding);
|
||||
#ifdef CPPPARSER
|
||||
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
|
||||
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
|
||||
|
||||
MAKE_PROPERTY(text, get_text, set_text);
|
||||
|
||||
protected:
|
||||
virtual void text_changed();
|
||||
|
||||
private:
|
||||
enum Flags {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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 textEncoder_ext.I
|
||||
* @author rdb
|
||||
* @date 2018-10-08
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encodes a wide-text string into a single-char string, according to the
|
||||
* current encoding.
|
||||
*/
|
||||
INLINE PyObject *Extension<TextEncoder>::
|
||||
encode_wtext(const std::wstring &wtext) const {
|
||||
return encode_wtext(wtext, _this->get_encoding());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given wstring decoded to a single-byte string, via the current
|
||||
* encoding system.
|
||||
*/
|
||||
INLINE PyObject *Extension<TextEncoder>::
|
||||
decode_text(PyObject *text) const {
|
||||
return decode_text(text, _this->get_encoding());
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
* 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 textEncoder_ext.cxx
|
||||
* @author rdb
|
||||
* @date 2018-09-29
|
||||
*/
|
||||
|
||||
#include "textEncoder_ext.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
/**
|
||||
* Sets the text as a Unicode string. In Python 2, if a regular str is given,
|
||||
* it is assumed to be in the TextEncoder's specified encoding.
|
||||
*/
|
||||
void Extension<TextEncoder>::
|
||||
set_text(PyObject *text) {
|
||||
if (PyUnicode_Check(text)) {
|
||||
#if PY_VERSION_HEX >= 0x03030000
|
||||
Py_ssize_t len;
|
||||
const char *str = PyUnicode_AsUTF8AndSize(text, &len);
|
||||
_this->set_text(std::string(str, len), TextEncoder::E_utf8);
|
||||
#else
|
||||
Py_ssize_t len = PyUnicode_GET_SIZE(text);
|
||||
wchar_t *str = (wchar_t *)alloca(sizeof(wchar_t) * (len + 1));
|
||||
PyUnicode_AsWideChar((PyUnicodeObject *)text, str, len);
|
||||
_this->set_wtext(std::wstring(str, len));
|
||||
#endif
|
||||
} else {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Dtool_Raise_TypeError("expected string");
|
||||
#else
|
||||
char *str;
|
||||
Py_ssize_t len;
|
||||
if (PyString_AsStringAndSize(text, (char **)&str, &len) != -1) {
|
||||
_this->set_text(std::string(str, len));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text as an encoded byte string of the given encoding.
|
||||
*/
|
||||
void Extension<TextEncoder>::
|
||||
set_text(PyObject *text, TextEncoder::Encoding encoding) {
|
||||
char *str;
|
||||
Py_ssize_t len;
|
||||
if (PyBytes_AsStringAndSize(text, &str, &len) >= 0) {
|
||||
_this->set_text(std::string(str, len), encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text as a string. In Python 2, the returned string is in the
|
||||
* TextEncoder's specified encoding. In Python 3, it is returned as unicode.
|
||||
*/
|
||||
PyObject *Extension<TextEncoder>::
|
||||
get_text() const {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
std::wstring text = _this->get_wtext();
|
||||
return PyUnicode_FromWideChar(text.data(), (Py_ssize_t)text.size());
|
||||
#else
|
||||
std::string text = _this->get_text();
|
||||
return PyString_FromStringAndSize((char *)text.data(), (Py_ssize_t)text.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text as a bytes object in the given encoding.
|
||||
*/
|
||||
PyObject *Extension<TextEncoder>::
|
||||
get_text(TextEncoder::Encoding encoding) const {
|
||||
std::string text = _this->get_text(encoding);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)text.data(), (Py_ssize_t)text.size());
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)text.data(), (Py_ssize_t)text.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the text as a string (or Unicode object in Python 2).
|
||||
*/
|
||||
void Extension<TextEncoder>::
|
||||
append_text(PyObject *text) {
|
||||
if (PyUnicode_Check(text)) {
|
||||
#if PY_VERSION_HEX >= 0x03030000
|
||||
Py_ssize_t len;
|
||||
const char *str = PyUnicode_AsUTF8AndSize(text, &len);
|
||||
std::string text_str(str, len);
|
||||
if (_this->get_encoding() == TextEncoder::E_utf8) {
|
||||
_this->append_text(text_str);
|
||||
} else {
|
||||
_this->append_wtext(TextEncoder::decode_text(text_str, TextEncoder::E_utf8));
|
||||
}
|
||||
#else
|
||||
Py_ssize_t len = PyUnicode_GET_SIZE(text);
|
||||
wchar_t *str = (wchar_t *)alloca(sizeof(wchar_t) * (len + 1));
|
||||
PyUnicode_AsWideChar((PyUnicodeObject *)text, str, len);
|
||||
_this->append_wtext(std::wstring(str, len));
|
||||
#endif
|
||||
} else {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Dtool_Raise_TypeError("expected string");
|
||||
#else
|
||||
char *str;
|
||||
Py_ssize_t len;
|
||||
if (PyString_AsStringAndSize(text, (char **)&str, &len) != -1) {
|
||||
_this->append_text(std::string(str, len));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given wide character as byte string in the given encoding.
|
||||
*/
|
||||
PyObject *Extension<TextEncoder>::
|
||||
encode_wchar(char32_t ch, TextEncoder::Encoding encoding) {
|
||||
std::string value = TextEncoder::encode_wchar(ch, encoding);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a wide-text string into a single-char string, according to the
|
||||
* given encoding.
|
||||
*/
|
||||
PyObject *Extension<TextEncoder>::
|
||||
encode_wtext(const wstring &wtext, TextEncoder::Encoding encoding) {
|
||||
std::string value = TextEncoder::encode_wtext(wtext, encoding);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)value.data(), (Py_ssize_t)value.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given wstring decoded to a single-byte string, via the given
|
||||
* encoding system.
|
||||
*/
|
||||
PyObject *Extension<TextEncoder>::
|
||||
decode_text(PyObject *text, TextEncoder::Encoding encoding) {
|
||||
char *str;
|
||||
Py_ssize_t len;
|
||||
if (PyBytes_AsStringAndSize(text, &str, &len) >= 0) {
|
||||
return Dtool_WrapValue(TextEncoder::decode_text(std::string(str, len), encoding));
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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 textEncoder_ext.h
|
||||
* @author rdb
|
||||
* @date 2018-09-29
|
||||
*/
|
||||
|
||||
#ifndef TEXTENCODER_EXT_H
|
||||
#define TEXTENCODER_EXT_H
|
||||
|
||||
#include "dtoolbase.h"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
#include "extension.h"
|
||||
#include "textEncoder.h"
|
||||
#include "py_panda.h"
|
||||
|
||||
/**
|
||||
* This class defines the extension methods for TextEncoder, which are called
|
||||
* instead of any C++ methods with the same prototype.
|
||||
*/
|
||||
template<>
|
||||
class Extension<TextEncoder> : public ExtensionBase<TextEncoder> {
|
||||
public:
|
||||
void set_text(PyObject *text);
|
||||
void set_text(PyObject *text, TextEncoder::Encoding encoding);
|
||||
|
||||
PyObject *get_text() const;
|
||||
PyObject *get_text(TextEncoder::Encoding encoding) const;
|
||||
void append_text(PyObject *text);
|
||||
|
||||
static PyObject *encode_wchar(char32_t ch, TextEncoder::Encoding encoding);
|
||||
INLINE PyObject *encode_wtext(const std::wstring &wtext) const;
|
||||
static PyObject *encode_wtext(const std::wstring &wtext, TextEncoder::Encoding encoding);
|
||||
INLINE PyObject *decode_text(PyObject *text) const;
|
||||
static PyObject *decode_text(PyObject *text, TextEncoder::Encoding encoding);
|
||||
};
|
||||
|
||||
#include "textEncoder_ext.I"
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#endif // TEXTENCODER_EXT_H
|
||||
|
|
@ -1378,7 +1378,7 @@ static const wchar_t combining_accent_map[] = {
|
|||
* Returns the Entry associated with the indicated character, if there is one.
|
||||
*/
|
||||
const UnicodeLatinMap::Entry *UnicodeLatinMap::
|
||||
look_up(wchar_t character) {
|
||||
look_up(char32_t character) {
|
||||
if (!_initialized) {
|
||||
init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,17 +112,17 @@ public:
|
|||
|
||||
class Entry {
|
||||
public:
|
||||
wchar_t _character;
|
||||
char32_t _character;
|
||||
CharType _char_type;
|
||||
char _ascii_equiv;
|
||||
char _ascii_additional;
|
||||
wchar_t _tolower_character;
|
||||
wchar_t _toupper_character;
|
||||
char32_t _tolower_character;
|
||||
char32_t _toupper_character;
|
||||
AccentType _accent_type;
|
||||
int _additional_flags;
|
||||
};
|
||||
|
||||
static const Entry *look_up(wchar_t character);
|
||||
static const Entry *look_up(char32_t character);
|
||||
|
||||
static wchar_t get_combining_accent(AccentType accent);
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ private:
|
|||
static void init();
|
||||
static bool _initialized;
|
||||
|
||||
typedef phash_map<wchar_t, const Entry *, integer_hash<wchar_t> > ByCharacter;
|
||||
typedef phash_map<char32_t, const Entry *, integer_hash<char32_t> > ByCharacter;
|
||||
static ByCharacter *_by_character;
|
||||
enum { max_direct_chars = 256 };
|
||||
static const Entry *_direct_chars[max_direct_chars];
|
||||
|
|
|
|||
|
|
@ -1389,7 +1389,8 @@ scan_element(CPPInstance *element, CPPStructType *struct_type,
|
|||
// We can only generate a getter and a setter if we can talk about the
|
||||
// type it is.
|
||||
|
||||
if (parameter_type->as_struct_type() != nullptr) {
|
||||
if (parameter_type->as_struct_type() != nullptr &&
|
||||
!parameter_type->is_trivial()) {
|
||||
// Wrap the type in a const reference.
|
||||
parameter_type = TypeManager::wrap_const_reference(parameter_type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -722,7 +722,10 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
|
||||
// Extract the __file__ attribute, if present.
|
||||
Filename main_dir;
|
||||
PyObject *file_attr = PyObject_GetAttrString(main_module, "__file__");
|
||||
PyObject *file_attr = nullptr;
|
||||
if (main_module != nullptr) {
|
||||
file_attr = PyObject_GetAttrString(main_module, "__file__");
|
||||
}
|
||||
if (file_attr == nullptr) {
|
||||
// Must be running in the interactive interpreter. Use the CWD.
|
||||
main_dir = ExecutionEnvironment::get_cwd();
|
||||
|
|
@ -752,6 +755,11 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
|
|||
ExecutionEnvironment::shadow_environment_variable("MAIN_DIR", main_dir.to_os_specific());
|
||||
PyErr_Clear();
|
||||
initialized_main_dir = true;
|
||||
|
||||
// Also, while we are at it, initialize the thread swap hook.
|
||||
#if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
|
||||
global_thread_state_swap = PyThreadState_Swap;
|
||||
#endif
|
||||
}
|
||||
|
||||
PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ typedef _typeobject PyTypeObject;
|
|||
typedef struct {} PyStringObject;
|
||||
typedef struct {} PyUnicodeObject;
|
||||
|
||||
class PyThreadState;
|
||||
typedef struct _ts PyThreadState;
|
||||
typedef int Py_ssize_t;
|
||||
typedef struct bufferinfo Py_buffer;
|
||||
|
||||
|
|
|
|||
|
|
@ -82,26 +82,6 @@ is_debug() const {
|
|||
// Instruct the compiler to optimize for the usual case.
|
||||
return UNLIKELY(is_on(NS_debug));
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* When NOTIFY_DEBUG is not defined, the categories are never set to "spam" or
|
||||
* "debug" severities, and these methods are redefined to be static to make it
|
||||
* more obvious to the compiler.
|
||||
*/
|
||||
constexpr bool NotifyCategory::
|
||||
is_spam() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When NOTIFY_DEBUG is not defined, the categories are never set to "spam" or
|
||||
* "debug" severities, and these methods are redefined to be static to make it
|
||||
* more obvious to the compiler.
|
||||
*/
|
||||
constexpr bool NotifyCategory::
|
||||
is_debug() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ PUBLISHED:
|
|||
INLINE bool is_spam() const;
|
||||
INLINE bool is_debug() const;
|
||||
#else
|
||||
constexpr static bool is_spam();
|
||||
constexpr static bool is_debug();
|
||||
constexpr static bool is_spam() { return false; }
|
||||
constexpr static bool is_debug() { return false; }
|
||||
#endif
|
||||
INLINE bool is_info() const;
|
||||
INLINE bool is_warning() const;
|
||||
|
|
|
|||
|
|
@ -72,12 +72,6 @@ is_spam() {
|
|||
// Instruct the compiler to optimize for the usual case.
|
||||
return UNLIKELY(get_unsafe_ptr()->is_spam());
|
||||
}
|
||||
#else
|
||||
template<class GetCategory>
|
||||
constexpr bool NotifyCategoryProxy<GetCategory>::
|
||||
is_spam() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -90,12 +84,6 @@ is_debug() {
|
|||
// Instruct the compiler to optimize for the usual case.
|
||||
return UNLIKELY(get_unsafe_ptr()->is_debug());
|
||||
}
|
||||
#else
|
||||
template<class GetCategory>
|
||||
constexpr bool NotifyCategoryProxy<GetCategory>::
|
||||
is_debug() {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -75,8 +75,8 @@ public:
|
|||
INLINE bool is_spam();
|
||||
INLINE bool is_debug();
|
||||
#else
|
||||
constexpr static bool is_spam();
|
||||
constexpr static bool is_debug();
|
||||
constexpr static bool is_spam() { return false; }
|
||||
constexpr static bool is_debug() { return false; }
|
||||
#endif
|
||||
INLINE bool is_info();
|
||||
INLINE bool is_warning();
|
||||
|
|
|
|||
|
|
@ -681,6 +681,9 @@ if (COMPILER == "MSVC"):
|
|||
IncDirectory("FCOLLADA", GetThirdpartyDir() + "fcollada/include/FCollada")
|
||||
if (PkgSkip("ASSIMP")==0):
|
||||
LibName("ASSIMP", GetThirdpartyDir() + "assimp/lib/assimp.lib")
|
||||
path = GetThirdpartyDir() + "assimp/lib/IrrXML.lib"
|
||||
if os.path.isfile(path):
|
||||
LibName("ASSIMP", GetThirdpartyDir() + "assimp/lib/IrrXML.lib")
|
||||
IncDirectory("ASSIMP", GetThirdpartyDir() + "assimp/include/assimp")
|
||||
if (PkgSkip("SQUISH")==0):
|
||||
if GetOptimize() <= 2:
|
||||
|
|
@ -947,8 +950,6 @@ if (COMPILER=="GCC"):
|
|||
|
||||
if GetTarget() == 'darwin':
|
||||
LibName("ALWAYS", "-framework AppKit")
|
||||
if (PkgSkip("OPENCV")==0):
|
||||
LibName("OPENCV", "-framework QuickTime")
|
||||
LibName("AGL", "-framework AGL")
|
||||
LibName("CARBON", "-framework Carbon")
|
||||
LibName("COCOA", "-framework Cocoa")
|
||||
|
|
@ -1335,9 +1336,10 @@ def CompileCxx(obj,src,opts):
|
|||
# Work around Apple compiler bug.
|
||||
cmd += " -U__EXCEPTIONS"
|
||||
|
||||
if 'RTTI' not in opts:
|
||||
target = GetTarget()
|
||||
if 'RTTI' not in opts and target != "darwin":
|
||||
# We always disable RTTI on Android for memory usage reasons.
|
||||
if optlevel >= 4 or GetTarget() == "android":
|
||||
if optlevel >= 4 or target == "android":
|
||||
cmd += " -fno-rtti"
|
||||
|
||||
if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm") and arch != 'aarch64':
|
||||
|
|
@ -1597,6 +1599,8 @@ def CompileLib(lib, obj, opts):
|
|||
else:
|
||||
cmd = GetAR() + ' cru ' + BracketNameWithQuotes(lib)
|
||||
for x in obj:
|
||||
if GetLinkAllStatic() and x.endswith('.a'):
|
||||
continue
|
||||
cmd += ' ' + BracketNameWithQuotes(x)
|
||||
oscmd(cmd)
|
||||
|
||||
|
|
@ -3161,10 +3165,10 @@ CopyAllHeaders('panda/src/movies')
|
|||
CopyAllHeaders('panda/src/pgraphnodes')
|
||||
CopyAllHeaders('panda/src/pgraph')
|
||||
CopyAllHeaders('panda/src/cull')
|
||||
CopyAllHeaders('panda/src/display')
|
||||
CopyAllHeaders('panda/src/chan')
|
||||
CopyAllHeaders('panda/src/char')
|
||||
CopyAllHeaders('panda/src/dgraph')
|
||||
CopyAllHeaders('panda/src/display')
|
||||
CopyAllHeaders('panda/src/device')
|
||||
CopyAllHeaders('panda/src/pnmtext')
|
||||
CopyAllHeaders('panda/src/text')
|
||||
|
|
@ -3297,7 +3301,6 @@ if (PkgSkip("PANDATOOL")==0):
|
|||
CopyAllHeaders('pandatool/src/ptloader')
|
||||
CopyAllHeaders('pandatool/src/miscprogs')
|
||||
CopyAllHeaders('pandatool/src/pstatserver')
|
||||
CopyAllHeaders('pandatool/src/softprogs')
|
||||
CopyAllHeaders('pandatool/src/text-stats')
|
||||
CopyAllHeaders('pandatool/src/vrmlprogs')
|
||||
CopyAllHeaders('pandatool/src/win-stats')
|
||||
|
|
@ -3553,6 +3556,7 @@ IGATEFILES += [
|
|||
"dSearchPath.h",
|
||||
"executionEnvironment.h",
|
||||
"textEncoder.h",
|
||||
"textEncoder_ext.h",
|
||||
"filename.h",
|
||||
"filename_ext.h",
|
||||
"globPattern.h",
|
||||
|
|
@ -3817,7 +3821,7 @@ if (not RUNTIME):
|
|||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/gobj', 'BUILDING:PANDA', 'NVIDIACG', 'ZLIB', 'SQUISH']
|
||||
TargetAdd('p3gobj_composite1.obj', opts=OPTS, input='p3gobj_composite1.cxx')
|
||||
TargetAdd('p3gobj_composite2.obj', opts=OPTS, input='p3gobj_composite2.cxx')
|
||||
TargetAdd('p3gobj_composite2.obj', opts=OPTS+['BIGOBJ'], input='p3gobj_composite2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/gobj', 'NVIDIACG', 'ZLIB', 'SQUISH', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/gobj', ["*.h", "*_composite*.cxx"])
|
||||
|
|
@ -3876,38 +3880,6 @@ if (not RUNTIME):
|
|||
TargetAdd('libp3cull.in', opts=['IMOD:panda3d.core', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull'])
|
||||
TargetAdd('libp3cull_igate.obj', input='libp3cull.in', opts=["DEPENDENCYONLY"])
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/chan/
|
||||
#
|
||||
|
||||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/chan', 'BUILDING:PANDA']
|
||||
TargetAdd('p3chan_composite1.obj', opts=OPTS, input='p3chan_composite1.cxx')
|
||||
TargetAdd('p3chan_composite2.obj', opts=OPTS, input='p3chan_composite2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/chan', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/chan', ["*.h", "*_composite*.cxx"])
|
||||
IGATEFILES.remove('movingPart.h')
|
||||
IGATEFILES.remove('animChannelFixed.h')
|
||||
TargetAdd('libp3chan.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3chan.in', opts=['IMOD:panda3d.core', 'ILIB:libp3chan', 'SRCDIR:panda/src/chan'])
|
||||
TargetAdd('libp3chan_igate.obj', input='libp3chan.in', opts=["DEPENDENCYONLY"])
|
||||
|
||||
|
||||
# DIRECTORY: panda/src/char/
|
||||
#
|
||||
|
||||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/char', 'BUILDING:PANDA']
|
||||
TargetAdd('p3char_composite1.obj', opts=OPTS, input='p3char_composite1.cxx')
|
||||
TargetAdd('p3char_composite2.obj', opts=OPTS, input='p3char_composite2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/char', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/char', ["*.h", "*_composite*.cxx"])
|
||||
TargetAdd('libp3char.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3char.in', opts=['IMOD:panda3d.core', 'ILIB:libp3char', 'SRCDIR:panda/src/char'])
|
||||
TargetAdd('libp3char_igate.obj', input='libp3char.in', opts=["DEPENDENCYONLY"])
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/dgraph/
|
||||
#
|
||||
|
|
@ -3944,6 +3916,7 @@ if (not RUNTIME):
|
|||
|
||||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
|
||||
TargetAdd('p3display_graphicsStateGuardian.obj', opts=OPTS, input='graphicsStateGuardian.cxx')
|
||||
TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
|
||||
TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
|
||||
|
||||
|
|
@ -3962,6 +3935,38 @@ if (not RUNTIME):
|
|||
TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
|
||||
TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/chan/
|
||||
#
|
||||
|
||||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/chan', 'BUILDING:PANDA']
|
||||
TargetAdd('p3chan_composite1.obj', opts=OPTS, input='p3chan_composite1.cxx')
|
||||
TargetAdd('p3chan_composite2.obj', opts=OPTS, input='p3chan_composite2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/chan', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/chan', ["*.h", "*_composite*.cxx"])
|
||||
IGATEFILES.remove('movingPart.h')
|
||||
IGATEFILES.remove('animChannelFixed.h')
|
||||
TargetAdd('libp3chan.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3chan.in', opts=['IMOD:panda3d.core', 'ILIB:libp3chan', 'SRCDIR:panda/src/chan'])
|
||||
TargetAdd('libp3chan_igate.obj', input='libp3chan.in', opts=["DEPENDENCYONLY"])
|
||||
|
||||
|
||||
# DIRECTORY: panda/src/char/
|
||||
#
|
||||
|
||||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/char', 'BUILDING:PANDA']
|
||||
TargetAdd('p3char_composite1.obj', opts=OPTS, input='p3char_composite1.cxx')
|
||||
TargetAdd('p3char_composite2.obj', opts=OPTS, input='p3char_composite2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/char', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/char', ["*.h", "*_composite*.cxx"])
|
||||
TargetAdd('libp3char.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3char.in', opts=['IMOD:panda3d.core', 'ILIB:libp3char', 'SRCDIR:panda/src/char'])
|
||||
TargetAdd('libp3char_igate.obj', input='libp3char.in', opts=["DEPENDENCYONLY"])
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/pnmtext/
|
||||
#
|
||||
|
|
@ -4169,6 +4174,7 @@ if (not RUNTIME):
|
|||
TargetAdd('libpanda.dll', input='p3device_composite2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3dgraph_composite1.obj')
|
||||
TargetAdd('libpanda.dll', input='p3dgraph_composite2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian.obj')
|
||||
TargetAdd('libpanda.dll', input='p3display_composite1.obj')
|
||||
TargetAdd('libpanda.dll', input='p3display_composite2.obj')
|
||||
TargetAdd('libpanda.dll', input='p3pipeline_composite1.obj')
|
||||
|
|
@ -6348,21 +6354,6 @@ if (PkgSkip("PANDATOOL")==0):
|
|||
TargetAdd('p3pstatserver_composite1.obj', opts=OPTS, input='p3pstatserver_composite1.cxx')
|
||||
TargetAdd('libp3pstatserver.lib', input='p3pstatserver_composite1.obj')
|
||||
|
||||
#
|
||||
# DIRECTORY: pandatool/src/softprogs/
|
||||
#
|
||||
|
||||
if (PkgSkip("PANDATOOL")==0):
|
||||
OPTS=['DIR:pandatool/src/softprogs', 'OPENSSL']
|
||||
TargetAdd('softcvs_softCVS.obj', opts=OPTS, input='softCVS.cxx')
|
||||
TargetAdd('softcvs_softFilename.obj', opts=OPTS, input='softFilename.cxx')
|
||||
TargetAdd('softcvs.exe', input='softcvs_softCVS.obj')
|
||||
TargetAdd('softcvs.exe', input='softcvs_softFilename.obj')
|
||||
TargetAdd('softcvs.exe', input='libp3progbase.lib')
|
||||
TargetAdd('softcvs.exe', input='libp3pandatoolbase.lib')
|
||||
TargetAdd('softcvs.exe', input=COMMON_PANDA_LIBS)
|
||||
TargetAdd('softcvs.exe', opts=['ADVAPI'])
|
||||
|
||||
#
|
||||
# DIRECTORY: pandatool/src/text-stats/
|
||||
#
|
||||
|
|
|
|||
|
|
@ -4770,12 +4770,6 @@
|
|||
<File RelativePath="..\pandatool\src\ptloader\config_ptloader.h"></File>
|
||||
<File RelativePath="..\pandatool\src\ptloader\loaderFileTypePandatool.h"></File>
|
||||
</Filter>
|
||||
<Filter Name="softprogs">
|
||||
<File RelativePath="..\pandatool\src\softprogs\softCVS.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\softprogs\softFilename.h"></File>
|
||||
<File RelativePath="..\pandatool\src\softprogs\softCVS.h"></File>
|
||||
<File RelativePath="..\pandatool\src\softprogs\softFilename.cxx"></File>
|
||||
</Filter>
|
||||
<Filter Name="imageprogs">
|
||||
<File RelativePath="..\pandatool\src\imageprogs\imageTrans.h"></File>
|
||||
<File RelativePath="..\pandatool\src\imageprogs\imageTransformColors.cxx"></File>
|
||||
|
|
@ -5305,20 +5299,6 @@
|
|||
<File RelativePath="..\pandatool\src\lwo\lwoSurfaceBlockImage.h"></File>
|
||||
<File RelativePath="..\pandatool\src\lwo\lwoSurfaceBlockCoordSys.cxx"></File>
|
||||
</Filter>
|
||||
<Filter Name="softegg">
|
||||
<File RelativePath="..\pandatool\src\softegg\soft2Egg.c"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softNodeTree.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softNodeDesc.h"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softEggGroupUserData.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softEggGroupUserData.I"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\config_softegg.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softToEggConverter.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softNodeTree.h"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\config_softegg.h"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softNodeDesc.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softToEggConverter.h"></File>
|
||||
<File RelativePath="..\pandatool\src\softegg\softEggGroupUserData.h"></File>
|
||||
</Filter>
|
||||
<Filter Name="xfileprogs">
|
||||
<File RelativePath="..\pandatool\src\xfileprogs\eggToX.cxx"></File>
|
||||
<File RelativePath="..\pandatool\src\xfileprogs\xFileTrans.cxx"></File>
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ AnimControl(const std::string &name, PartBundle *part,
|
|||
Namable(name),
|
||||
_pending_lock(name),
|
||||
_pending_cvar(_pending_lock),
|
||||
_bound_joints(BitArray::all_on())
|
||||
_bound_joints(BitArray::all_on()),
|
||||
_part(part)
|
||||
{
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
MemoryUsage::update_type(this, get_class_type());
|
||||
#endif
|
||||
|
||||
_pending = true;
|
||||
_part = part;
|
||||
_anim = nullptr;
|
||||
_channel_index = -1;
|
||||
set_frame_rate(frame_rate);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ class EXPCL_PANDA_CHAN AnimControl : public TypedReferenceCount, public AnimInte
|
|||
public:
|
||||
AnimControl(const std::string &name, PartBundle *part,
|
||||
double frame_rate, int num_frames);
|
||||
AnimControl(const AnimControl ©) = delete;
|
||||
|
||||
void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
|
||||
const BitArray &bound_joints);
|
||||
void set_bound_joints(const BitArray &bound_joints);
|
||||
|
|
@ -82,7 +84,7 @@ private:
|
|||
// This is a PT(PartGroup) instead of a PT(PartBundle), just because we
|
||||
// can't include partBundle.h for circular reasons. But it actually keeps a
|
||||
// pointer to a PartBundle.
|
||||
PT(PartGroup) _part;
|
||||
const PT(PartGroup) _part;
|
||||
PT(AnimBundle) _anim;
|
||||
int _channel_index;
|
||||
|
||||
|
|
|
|||
|
|
@ -556,8 +556,15 @@ control_removed(AnimControl *control) {
|
|||
CDStageWriter cdata(_cycler, pipeline_stage);
|
||||
ChannelBlend::iterator cbi = cdata->_blend.find(control);
|
||||
if (cbi != cdata->_blend.end()) {
|
||||
cdata->_net_blend -= cbi->second;
|
||||
cdata->_blend.erase(cbi);
|
||||
cdata->_anim_changed = true;
|
||||
|
||||
// We need to make sure that any _effective_channel pointers that point
|
||||
// to this control are cleared.
|
||||
if (pipeline_stage == 0) {
|
||||
determine_effective_channels(cdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
||||
|
|
|
|||
|
|
@ -134,6 +134,12 @@ get_properties(FrameBufferProperties &properties, NSOpenGLPixelFormat* pixel_for
|
|||
if (accelerated) {
|
||||
properties.set_force_hardware(1);
|
||||
}
|
||||
|
||||
// Cautiously setting this to true. It appears that macOS framebuffers are
|
||||
// sRGB-capable, but I don't really know how to verify this.
|
||||
if (color_size == 32 && !color_float) {
|
||||
properties.set_srgb_color(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#import "cocoaPandaApp.h"
|
||||
#include "config_cocoadisplay.h"
|
||||
|
||||
@implementation CocoaPandaApp
|
||||
- (void) sendEvent: (NSEvent *) event {
|
||||
|
|
|
|||
|
|
@ -1254,7 +1254,7 @@ compare_collider_to_geom(CollisionEntry &entry, const Geom *geom,
|
|||
|
||||
if (geom->get_primitive_type() == Geom::PT_polygons) {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CPT(GeomVertexData) data = geom->get_vertex_data()->animate_vertices(true, current_thread);
|
||||
CPT(GeomVertexData) data = geom->get_animated_vertex_data(true, current_thread);
|
||||
GeomVertexReader vertex(data, InternalName::get_vertex());
|
||||
|
||||
int num_primitives = geom->get_num_primitives();
|
||||
|
|
|
|||
|
|
@ -753,7 +753,7 @@ render_frame() {
|
|||
// frames, so we won't have to recompute it each frame.
|
||||
int num_drs = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_drs; ++i) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
PT(DisplayRegion) dr = win->get_active_display_region(i);
|
||||
if (dr != nullptr) {
|
||||
NodePath camera_np = dr->get_camera(current_thread);
|
||||
if (!camera_np.is_empty()) {
|
||||
|
|
@ -1359,7 +1359,7 @@ is_scene_root(const PandaNode *node) {
|
|||
if (win->is_active() && win->get_gsg()->is_active()) {
|
||||
int num_display_regions = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_display_regions; i++) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
PT(DisplayRegion) dr = win->get_active_display_region(i);
|
||||
if (dr != nullptr) {
|
||||
NodePath camera = dr->get_camera();
|
||||
if (camera.is_empty()) {
|
||||
|
|
@ -1435,7 +1435,7 @@ cull_and_draw_together(GraphicsEngine::Windows wlist,
|
|||
|
||||
int num_display_regions = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_display_regions; i++) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
PT(DisplayRegion) dr = win->get_active_display_region(i);
|
||||
if (dr != nullptr) {
|
||||
cull_and_draw_together(win, dr, current_thread);
|
||||
}
|
||||
|
|
@ -1539,7 +1539,7 @@ cull_to_bins(GraphicsEngine::Windows wlist, Thread *current_thread) {
|
|||
PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
|
||||
int num_display_regions = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_display_regions; ++i) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
PT(DisplayRegion) dr = win->get_active_display_region(i);
|
||||
if (dr != nullptr) {
|
||||
PT(SceneSetup) scene_setup;
|
||||
PT(CullResult) cull_result;
|
||||
|
|
@ -1659,7 +1659,7 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
}
|
||||
int num_display_regions = win->get_num_active_display_regions();
|
||||
for (int i = 0; i < num_display_regions; ++i) {
|
||||
DisplayRegion *dr = win->get_active_display_region(i);
|
||||
PT(DisplayRegion) dr = win->get_active_display_region(i);
|
||||
if (dr != nullptr) {
|
||||
do_draw(win, gsg, dr, current_thread);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -697,9 +697,6 @@ void GraphicsOutput::
|
|||
remove_all_display_regions() {
|
||||
LightMutexHolder holder(_lock);
|
||||
|
||||
CDWriter cdata(_cycler, true);
|
||||
cdata->_active_display_regions_stale = true;
|
||||
|
||||
TotalDisplayRegions::iterator dri;
|
||||
for (dri = _total_display_regions.begin();
|
||||
dri != _total_display_regions.end();
|
||||
|
|
@ -713,6 +710,12 @@ remove_all_display_regions() {
|
|||
}
|
||||
_total_display_regions.clear();
|
||||
_total_display_regions.push_back(_overlay_display_region);
|
||||
|
||||
OPEN_ITERATE_ALL_STAGES(_cycler) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage);
|
||||
cdata->_active_display_regions_stale = true;
|
||||
}
|
||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -740,13 +743,8 @@ set_overlay_display_region(DisplayRegion *display_region) {
|
|||
*/
|
||||
int GraphicsOutput::
|
||||
get_num_display_regions() const {
|
||||
determine_display_regions();
|
||||
int result;
|
||||
{
|
||||
LightMutexHolder holder(_lock);
|
||||
result = _total_display_regions.size();
|
||||
}
|
||||
return result;
|
||||
LightMutexHolder holder(_lock);
|
||||
return _total_display_regions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1504,13 +1502,15 @@ do_remove_display_region(DisplayRegion *display_region) {
|
|||
find(_total_display_regions.begin(), _total_display_regions.end(), drp);
|
||||
if (dri != _total_display_regions.end()) {
|
||||
// Let's aggressively clean up the display region too.
|
||||
CDWriter cdata(_cycler, true);
|
||||
display_region->cleanup();
|
||||
display_region->_window = nullptr;
|
||||
_total_display_regions.erase(dri);
|
||||
|
||||
cdata->_active_display_regions_stale = true;
|
||||
|
||||
OPEN_ITERATE_ALL_STAGES(_cycler) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage);
|
||||
cdata->_active_display_regions_stale = true;
|
||||
}
|
||||
CLOSE_ITERATE_ALL_STAGES(_cycler);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -394,6 +394,7 @@ protected:
|
|||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
typedef CycleDataReader<CData> CDReader;
|
||||
typedef CycleDataWriter<CData> CDWriter;
|
||||
typedef CycleDataStageWriter<CData> CDStageWriter;
|
||||
|
||||
protected:
|
||||
int _creation_flags;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
#include "load_dso.h"
|
||||
#include "config_display.h"
|
||||
#include "typeRegistry.h"
|
||||
#include "pset.h"
|
||||
#include "config_putil.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -61,8 +60,8 @@ GraphicsPipeSelection() : _lock("GraphicsPipeSelection") {
|
|||
|
||||
// Also get the set of modules named in the various aux-display Config
|
||||
// variables. We'll want to know this when we call load_modules() later.
|
||||
int num_aux = aux_display.get_num_unique_values();
|
||||
for (int i = 0; i < num_aux; i++) {
|
||||
size_t num_aux = aux_display.get_num_unique_values();
|
||||
for (size_t i = 0; i < num_aux; ++i) {
|
||||
string name = aux_display.get_unique_value(i);
|
||||
if (name != _default_display_module) {
|
||||
_display_modules.push_back(name);
|
||||
|
|
@ -124,9 +123,7 @@ print_pipe_types() const {
|
|||
|
||||
LightMutexHolder holder(_lock);
|
||||
nout << "Known pipe types:" << std::endl;
|
||||
PipeTypes::const_iterator pi;
|
||||
for (pi = _pipe_types.begin(); pi != _pipe_types.end(); ++pi) {
|
||||
const PipeType &pipe_type = (*pi);
|
||||
for (const PipeType &pipe_type : _pipe_types) {
|
||||
nout << " " << pipe_type._type << "\n";
|
||||
}
|
||||
if (_display_modules.empty()) {
|
||||
|
|
@ -187,11 +184,9 @@ make_pipe(const string &type_name, const string &module_name) {
|
|||
PT(GraphicsPipe) GraphicsPipeSelection::
|
||||
make_pipe(TypeHandle type) {
|
||||
LightMutexHolder holder(_lock);
|
||||
PipeTypes::const_iterator ti;
|
||||
|
||||
// First, look for an exact match of the requested type.
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
if (ptype._type == type) {
|
||||
// Here's an exact match.
|
||||
PT(GraphicsPipe) pipe = (*ptype._constructor)();
|
||||
|
|
@ -202,8 +197,7 @@ make_pipe(TypeHandle type) {
|
|||
}
|
||||
|
||||
// Now look for a more-specific type.
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
if (ptype._type.is_derived_from(type)) {
|
||||
// Here's an approximate match.
|
||||
PT(GraphicsPipe) pipe = (*ptype._constructor)();
|
||||
|
|
@ -215,8 +209,7 @@ make_pipe(TypeHandle type) {
|
|||
|
||||
// Couldn't find any match; load the default module and try again.
|
||||
load_default_module();
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
if (ptype._type.is_derived_from(type)) {
|
||||
// Here's an approximate match.
|
||||
PT(GraphicsPipe) pipe = (*ptype._constructor)();
|
||||
|
|
@ -260,13 +253,11 @@ make_default_pipe() {
|
|||
load_default_module();
|
||||
|
||||
LightMutexHolder holder(_lock);
|
||||
PipeTypes::const_iterator ti;
|
||||
|
||||
if (!_default_pipe_name.empty()) {
|
||||
// First, look for an exact match of the default type name from the
|
||||
// Configrc file (excepting case and hyphenunderscore).
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
|
||||
// Here's an exact match.
|
||||
PT(GraphicsPipe) pipe = (*ptype._constructor)();
|
||||
|
|
@ -278,8 +269,7 @@ make_default_pipe() {
|
|||
|
||||
// No match; look for a substring match.
|
||||
string preferred_name = downcase(_default_pipe_name);
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
string ptype_name = downcase(ptype._type.get_name());
|
||||
if (ptype_name.find(preferred_name) != string::npos) {
|
||||
// Here's a substring match.
|
||||
|
|
@ -292,8 +282,7 @@ make_default_pipe() {
|
|||
}
|
||||
|
||||
// Couldn't find a matching pipe type; choose the first one on the list.
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
PT(GraphicsPipe) pipe = (*ptype._constructor)();
|
||||
if (pipe != nullptr) {
|
||||
return pipe;
|
||||
|
|
@ -310,9 +299,8 @@ make_default_pipe() {
|
|||
*/
|
||||
void GraphicsPipeSelection::
|
||||
load_aux_modules() {
|
||||
DisplayModules::iterator di;
|
||||
for (di = _display_modules.begin(); di != _display_modules.end(); ++di) {
|
||||
load_named_module(*di);
|
||||
for (const string &module : _display_modules) {
|
||||
load_named_module(module);
|
||||
}
|
||||
|
||||
_display_modules.clear();
|
||||
|
|
@ -337,9 +325,7 @@ add_pipe_type(TypeHandle type, PipeConstructorFunc *func) {
|
|||
|
||||
// First, make sure we don't already have a GraphicsPipe of this type.
|
||||
LightMutexHolder holder(_lock);
|
||||
PipeTypes::const_iterator ti;
|
||||
for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
|
||||
const PipeType &ptype = (*ti);
|
||||
for (const PipeType &ptype : _pipe_types) {
|
||||
if (ptype._type == type) {
|
||||
display_cat->warning()
|
||||
<< "Attempt to register GraphicsPipe type " << type
|
||||
|
|
@ -375,8 +361,8 @@ do_load_default_module() {
|
|||
load_named_module(_default_display_module);
|
||||
|
||||
DisplayModules::iterator di =
|
||||
find(_display_modules.begin(), _display_modules.end(),
|
||||
_default_display_module);
|
||||
std::find(_display_modules.begin(), _display_modules.end(),
|
||||
_default_display_module);
|
||||
if (di != _display_modules.end()) {
|
||||
_display_modules.erase(di);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include "renderBuffer.h"
|
||||
#include "light.h"
|
||||
#include "planeNode.h"
|
||||
#include "ambientLight.h"
|
||||
#include "throw_event.h"
|
||||
#include "clockObject.h"
|
||||
#include "pStatTimer.h"
|
||||
|
|
@ -60,7 +59,6 @@
|
|||
#include "fogAttrib.h"
|
||||
#include "config_pstatclient.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
|
||||
using std::string;
|
||||
|
|
@ -932,12 +930,12 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
}
|
||||
case Shader::SMO_frame_time: {
|
||||
PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
|
||||
t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_frame_delta: {
|
||||
PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
|
||||
t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_texpad_x: {
|
||||
|
|
@ -949,7 +947,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
double cx = (sx * 0.5) / tex->get_x_size();
|
||||
double cy = (sy * 0.5) / tex->get_y_size();
|
||||
double cz = (sz * 0.5) / tex->get_z_size();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cx, cy, cz, 0);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_texpix_x: {
|
||||
|
|
@ -958,7 +956,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
double px = 1.0 / tex->get_x_size();
|
||||
double py = 1.0 / tex->get_y_size();
|
||||
double pz = 1.0 / tex->get_z_size();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, px, py, pz, 0);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_attr_material: {
|
||||
|
|
@ -966,7 +964,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
_target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
|
||||
// Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
|
||||
if (target_material->is_off()) {
|
||||
t = LMatrix4(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0);
|
||||
t.set(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
return &t;
|
||||
}
|
||||
Material *m = target_material->get_material();
|
||||
|
|
@ -975,17 +973,17 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
LVecBase4 const &emm = m->get_emission();
|
||||
LVecBase4 spc = m->get_specular();
|
||||
spc[3] = m->get_shininess();
|
||||
t = LMatrix4(amb[0],amb[1],amb[2],amb[3],
|
||||
dif[0],dif[1],dif[2],dif[3],
|
||||
emm[0],emm[1],emm[2],emm[3],
|
||||
spc[0],spc[1],spc[2],spc[3]);
|
||||
t.set(amb[0], amb[1], amb[2], amb[3],
|
||||
dif[0], dif[1], dif[2], dif[3],
|
||||
emm[0], emm[1], emm[2], emm[3],
|
||||
spc[0], spc[1], spc[2], spc[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_attr_material2: {
|
||||
const MaterialAttrib *target_material = (const MaterialAttrib *)
|
||||
_target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
|
||||
if (target_material->is_off()) {
|
||||
t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||
return &t;
|
||||
}
|
||||
Material *m = target_material->get_material();
|
||||
|
|
@ -1000,7 +998,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
return &LMatrix4::ones_mat();
|
||||
}
|
||||
LVecBase4 c = target_color->get_color();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_attr_colorscale: {
|
||||
|
|
@ -1010,7 +1008,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
return &LMatrix4::ones_mat();
|
||||
}
|
||||
LVecBase4 cs = target_color->get_scale();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cs[0],cs[1],cs[2],cs[3]);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cs[0], cs[1], cs[2], cs[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_attr_fog: {
|
||||
|
|
@ -1022,7 +1020,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
}
|
||||
PN_stdfloat start, end;
|
||||
fog->get_linear_range(start, end);
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,fog->get_exp_density(),start,end,1.0f/(end-start));
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
fog->get_exp_density(), start, end, 1.0f / (end - start));
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_attr_fogcolor: {
|
||||
|
|
@ -1033,7 +1032,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
return &LMatrix4::ones_mat();
|
||||
}
|
||||
LVecBase4 c = fog->get_color();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_alight_x: {
|
||||
|
|
@ -1042,7 +1041,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
AmbientLight *lt;
|
||||
DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
|
||||
LColor const &c = lt->get_color();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_satten_x: {
|
||||
|
|
@ -1052,7 +1051,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
|
||||
LVecBase3 const &a = lt->get_attenuation();
|
||||
PN_stdfloat x = lt->get_exponent();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,a[0],a[1],a[2],x);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a[0], a[1], a[2], x);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_dlight_x: {
|
||||
|
|
@ -1069,7 +1068,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
d.normalize();
|
||||
LVecBase3 h = d + LVecBase3(0,-1,0);
|
||||
h.normalize();
|
||||
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],c[3],d[0],d[1],d[2],0,h[0],h[1],h[2],0);
|
||||
t.set(c[0], c[1], c[2], c[3],
|
||||
s[0], s[1], s[2], c[3],
|
||||
d[0], d[1], d[2], 0,
|
||||
h[0], h[1], h[2], 0);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_plight_x: {
|
||||
|
|
@ -1087,7 +1089,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
Lens *lens = lt->get_lens(0);
|
||||
PN_stdfloat lnear = lens->get_near();
|
||||
PN_stdfloat lfar = lens->get_far();
|
||||
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],lnear,a[0],a[1],a[2],lfar);
|
||||
t.set(c[0], c[1], c[2], c[3],
|
||||
s[0], s[1], s[2], s[3],
|
||||
p[0], p[1], p[2], lnear,
|
||||
a[0], a[1], a[2], lfar);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_slight_x: {
|
||||
|
|
@ -1105,7 +1110,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
_scene_setup->get_world_transform()->get_mat();
|
||||
LVecBase3 p = t.xform_point(lens->get_nodal_point());
|
||||
LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
|
||||
t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff);
|
||||
t.set(c[0], c[1], c[2], c[3],
|
||||
s[0], s[1], s[2], s[3],
|
||||
p[0], p[1], p[2], 0,
|
||||
d[0], d[1], d[2], cutoff);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_light_ambient: {
|
||||
|
|
@ -1149,7 +1157,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
|
||||
index < ta->get_num_on_stages()) {
|
||||
LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,scale[0],scale[1],scale[2],0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, scale[0], scale[1], scale[2], 0);
|
||||
return &t;
|
||||
} else {
|
||||
return &LMatrix4::ident_mat();
|
||||
|
|
@ -1173,7 +1181,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
index < ta->get_num_on_stages()) {
|
||||
TextureStage *ts = ta->get_on_stage(index);
|
||||
PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,v,v,v,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v, v, v, 0);
|
||||
return &t;
|
||||
} else {
|
||||
return &LMatrix4::zeros_mat();
|
||||
|
|
@ -1185,7 +1193,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
const PlaneNode *plane_node;
|
||||
DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
|
||||
LPlane p = plane_node->get_plane();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, p[0], p[1], p[2], p[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_clipplane_x: {
|
||||
|
|
@ -1235,10 +1243,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
case Shader::SMO_vec_constant_x: {
|
||||
const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
|
||||
const PN_stdfloat *data = input.get_data();
|
||||
t = LMatrix4(data[0],data[1],data[2],data[3],
|
||||
data[0],data[1],data[2],data[3],
|
||||
data[0],data[1],data[2],data[3],
|
||||
data[0],data[1],data[2],data[3]);
|
||||
t.set(data[0], data[1], data[2], data[3],
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[0], data[1], data[2], data[3]);
|
||||
return &t;
|
||||
}
|
||||
case Shader::SMO_world_to_view: {
|
||||
|
|
@ -1394,10 +1402,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
|
|||
// There is an input specifying precisely this whole thing, with dot and
|
||||
// all. Support this, even if only for backward compatibility.
|
||||
const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
|
||||
t = LMatrix4(data[0],data[1],data[2],data[3],
|
||||
data[0],data[1],data[2],data[3],
|
||||
data[0],data[1],data[2],data[3],
|
||||
data[0],data[1],data[2],data[3]);
|
||||
t.set(data[0], data[1], data[2], data[3],
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[0], data[1], data[2], data[3],
|
||||
data[0], data[1], data[2], data[3]);
|
||||
return &t;
|
||||
}
|
||||
|
||||
|
|
@ -1578,11 +1586,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
|
|||
|
||||
} else if (attrib == IN_position) {
|
||||
if (np.is_empty()) {
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
|
||||
return &t;
|
||||
} else if (node->is_ambient_light()) {
|
||||
// Ambient light has no position.
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
return &t;
|
||||
} else if (node->is_of_type(DirectionalLight::get_class_type())) {
|
||||
DirectionalLight *light;
|
||||
|
|
@ -1591,7 +1599,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
|
|||
CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
|
||||
LVector3 dir = -(light->get_direction() * transform->get_mat());
|
||||
dir *= _scene_setup->get_cs_world_transform()->get_mat();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 0);
|
||||
return &t;
|
||||
} else {
|
||||
LightLensNode *light;
|
||||
|
|
@ -1611,11 +1619,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
|
|||
|
||||
} else if (attrib == IN_halfVector) {
|
||||
if (np.is_empty()) {
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
|
||||
return &t;
|
||||
} else if (node->is_ambient_light()) {
|
||||
// Ambient light has no half-vector.
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
return &t;
|
||||
} else if (node->is_of_type(DirectionalLight::get_class_type())) {
|
||||
DirectionalLight *light;
|
||||
|
|
@ -1627,7 +1635,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
|
|||
dir.normalize();
|
||||
dir += LVector3(0, 0, 1);
|
||||
dir.normalize();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],1);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 1);
|
||||
return &t;
|
||||
} else {
|
||||
LightLensNode *light;
|
||||
|
|
@ -1644,7 +1652,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
|
|||
pos.normalize();
|
||||
pos += LVector3(0, 0, 1);
|
||||
pos.normalize();
|
||||
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,pos[0],pos[1],pos[2],1);
|
||||
t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pos[0],pos[1],pos[2], 1);
|
||||
return &t;
|
||||
}
|
||||
|
||||
|
|
@ -2722,7 +2730,7 @@ do_issue_color_scale() {
|
|||
}
|
||||
|
||||
if (_alpha_scale_via_texture && !_has_scene_graph_color &&
|
||||
target_color_scale->has_alpha_scale()) {
|
||||
_vertex_colors_enabled && target_color_scale->has_alpha_scale()) {
|
||||
// This color scale will set a special texture--so again, clear the
|
||||
// texture.
|
||||
_state_mask.clear_bit(TextureAttrib::get_class_slot());
|
||||
|
|
@ -3168,6 +3176,17 @@ determine_light_color_scale() {
|
|||
_scene_graph_color[3] * _current_color_scale[3]);
|
||||
}
|
||||
|
||||
} else if (!_vertex_colors_enabled) {
|
||||
// We don't have a scene graph color, but we don't want to enable vertex
|
||||
// colors either, so we still need to force a white material color in
|
||||
// absence of any other color.
|
||||
_has_material_force_color = true;
|
||||
_material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
_light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
if (!_color_blend_involves_color_scale && _color_scale_enabled) {
|
||||
_material_force_color.componentwise_mult(_current_color_scale);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Otherise, leave the materials alone, but we might still scale the
|
||||
// lights.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class GraphicsWindow;
|
|||
class EXPCL_PANDA_DISPLAY GraphicsWindowProc {
|
||||
public:
|
||||
GraphicsWindowProc();
|
||||
virtual ~GraphicsWindowProc() = default;
|
||||
#if defined(__WIN32__) || defined(_WIN32)
|
||||
virtual LONG wnd_proc(GraphicsWindow* graphicsWindow, HWND hwnd,
|
||||
UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include "graphicsPipeSelection.cxx"
|
||||
#include "graphicsStateGuardian.cxx"
|
||||
#include "graphicsThreadingModel.cxx"
|
||||
#include "graphicsWindow.cxx"
|
||||
#include "graphicsWindowProc.cxx"
|
||||
|
|
|
|||
|
|
@ -12,10 +12,14 @@
|
|||
*/
|
||||
|
||||
#include "standardMunger.h"
|
||||
#include "renderState.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
|
||||
#include "config_gobj.h"
|
||||
|
||||
#include "displayRegion.h"
|
||||
#include "graphicsStateGuardian.h"
|
||||
#include "lightAttrib.h"
|
||||
#include "materialAttrib.h"
|
||||
#include "renderState.h"
|
||||
|
||||
TypeHandle StandardMunger::_type_handle;
|
||||
|
||||
|
|
@ -55,24 +59,10 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
|
|||
const ColorScaleAttrib *color_scale_attrib;
|
||||
|
||||
if (state->get_attrib(color_attrib) &&
|
||||
color_attrib->get_color_type() == ColorAttrib::T_flat) {
|
||||
color_attrib->get_color_type() != ColorAttrib::T_vertex) {
|
||||
|
||||
if (!get_gsg()->get_color_scale_via_lighting()) {
|
||||
// We only need to munge the color directly if the GSG says it can't
|
||||
// cheat the color via lighting (presumably, in this case, by applying
|
||||
// a material).
|
||||
_color = color_attrib->get_color();
|
||||
if (state->get_attrib(color_scale_attrib) &&
|
||||
color_scale_attrib->has_scale()) {
|
||||
const LVecBase4 &cs = color_scale_attrib->get_scale();
|
||||
_color.set(_color[0] * cs[0],
|
||||
_color[1] * cs[1],
|
||||
_color[2] * cs[2],
|
||||
_color[3] * cs[3]);
|
||||
}
|
||||
_munge_color = true;
|
||||
_should_munge_state = true;
|
||||
}
|
||||
// In this case, we don't need to munge anything as we can apply the
|
||||
// color and color scale via glColor4f.
|
||||
|
||||
} else if (state->get_attrib(color_scale_attrib) &&
|
||||
color_scale_attrib->has_scale()) {
|
||||
|
|
|
|||
|
|
@ -51,12 +51,13 @@ private:
|
|||
NumericType _numeric_type;
|
||||
Contents _contents;
|
||||
|
||||
bool _munge_color;
|
||||
bool _munge_color_scale;
|
||||
bool _auto_shader;
|
||||
bool _shader_skinning;
|
||||
bool _remove_material;
|
||||
|
||||
protected:
|
||||
bool _munge_color;
|
||||
bool _munge_color_scale;
|
||||
LColor _color;
|
||||
LVecBase4 _color_scale;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
#include "graphicsEngine.h"
|
||||
#include "config_display.h"
|
||||
#include "nativeWindowHandle.h"
|
||||
#include "mouseButton.h"
|
||||
#include "throw_event.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
|
|
|||
|
|
@ -484,8 +484,7 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) {
|
|||
const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv;
|
||||
|
||||
// Iterate through all the vertices in the Geom.
|
||||
CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
|
||||
vdata = vdata->animate_vertices(true, current_thread);
|
||||
CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(true, current_thread);
|
||||
|
||||
CPT(GeomVertexFormat) vformat = vdata->get_format();
|
||||
if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) {
|
||||
|
|
@ -507,7 +506,7 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) {
|
|||
PT(GeomVertexData) modify_vdata = geom->modify_vertex_data();
|
||||
|
||||
// Maybe the vdata has animation that we should consider.
|
||||
CPT(GeomVertexData) animated_vdata = geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread);
|
||||
CPT(GeomVertexData) animated_vdata = geom->get_animated_vertex_data(true, current_thread);
|
||||
|
||||
GeomVertexWriter texcoord(modify_vdata, _texcoord_name, current_thread);
|
||||
GeomVertexWriter color(modify_vdata, current_thread);
|
||||
|
|
@ -674,9 +673,8 @@ make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) {
|
|||
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(Geom) new_geom = geom->make_copy();
|
||||
new_geom->set_vertex_data(new_geom->get_animated_vertex_data(false, current_thread));
|
||||
PT(GeomVertexData) vdata = new_geom->modify_vertex_data();
|
||||
new_geom->set_vertex_data(vdata->animate_vertices(false, current_thread));
|
||||
vdata = new_geom->modify_vertex_data();
|
||||
GeomVertexRewriter vertex(vdata, InternalName::get_vertex());
|
||||
while (!vertex.is_at_end()) {
|
||||
LVertex vert = vertex.get_data3();
|
||||
|
|
|
|||
|
|
@ -10,34 +10,3 @@
|
|||
* @author drose
|
||||
* @date 2005-03-11
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE DXGeomMunger9::
|
||||
DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
StandardMunger(gsg, state, 1, NT_packed_dabc, C_color),
|
||||
_texture(nullptr),
|
||||
_tex_gen(nullptr)
|
||||
{
|
||||
const TextureAttrib *texture = nullptr;
|
||||
const TexGenAttrib *tex_gen = nullptr;
|
||||
state->get_attrib(texture);
|
||||
state->get_attrib(tex_gen);
|
||||
_texture = texture;
|
||||
_tex_gen = tex_gen;
|
||||
|
||||
_filtered_texture = nullptr;
|
||||
_reffed_filtered_texture = false;
|
||||
if (texture != nullptr) {
|
||||
_filtered_texture = texture->filter_to_max(gsg->get_max_texture_stages());
|
||||
if (_filtered_texture != texture) {
|
||||
_filtered_texture->ref();
|
||||
_reffed_filtered_texture = true;
|
||||
}
|
||||
}
|
||||
// Set a callback to unregister ourselves when either the Texture or the
|
||||
// TexGen object gets deleted.
|
||||
_texture.add_callback(this);
|
||||
_tex_gen.add_callback(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,66 @@
|
|||
GeomMunger *DXGeomMunger9::_deleted_chain = nullptr;
|
||||
TypeHandle DXGeomMunger9::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
DXGeomMunger9::
|
||||
DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state) :
|
||||
StandardMunger(gsg, state, 1, NT_packed_dabc, C_color),
|
||||
_texture(nullptr),
|
||||
_tex_gen(nullptr)
|
||||
{
|
||||
const TextureAttrib *texture = nullptr;
|
||||
const TexGenAttrib *tex_gen = nullptr;
|
||||
state->get_attrib(texture);
|
||||
state->get_attrib(tex_gen);
|
||||
_texture = texture;
|
||||
_tex_gen = tex_gen;
|
||||
|
||||
if (!gsg->get_color_scale_via_lighting()) {
|
||||
// We might need to munge the colors, if we are overriding the vertex
|
||||
// colors and the GSG can't cheat the color via lighting.
|
||||
|
||||
const ColorAttrib *color_attrib;
|
||||
const ShaderAttrib *shader_attrib;
|
||||
state->get_attrib_def(shader_attrib);
|
||||
|
||||
if (!shader_attrib->auto_shader() &&
|
||||
shader_attrib->get_shader() == nullptr &&
|
||||
state->get_attrib(color_attrib) &&
|
||||
color_attrib->get_color_type() != ColorAttrib::T_vertex) {
|
||||
|
||||
if (color_attrib->get_color_type() == ColorAttrib::T_off) {
|
||||
_color.set(1, 1, 1, 1);
|
||||
} else {
|
||||
_color = color_attrib->get_color();
|
||||
}
|
||||
|
||||
const ColorScaleAttrib *color_scale_attrib;
|
||||
if (state->get_attrib(color_scale_attrib) &&
|
||||
color_scale_attrib->has_scale()) {
|
||||
_color.componentwise_mult(color_scale_attrib->get_scale());
|
||||
}
|
||||
_munge_color = true;
|
||||
_should_munge_state = true;
|
||||
}
|
||||
}
|
||||
|
||||
_filtered_texture = nullptr;
|
||||
_reffed_filtered_texture = false;
|
||||
if (texture != nullptr) {
|
||||
_filtered_texture = texture->filter_to_max(gsg->get_max_texture_stages());
|
||||
if (_filtered_texture != texture) {
|
||||
_filtered_texture->ref();
|
||||
_reffed_filtered_texture = true;
|
||||
}
|
||||
}
|
||||
// Set a callback to unregister ourselves when either the Texture or the
|
||||
// TexGen object gets deleted.
|
||||
_texture.add_callback(this);
|
||||
_tex_gen.add_callback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
class EXPCL_PANDADX DXGeomMunger9 : public StandardMunger, public WeakPointerCallback {
|
||||
public:
|
||||
INLINE DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state);
|
||||
DXGeomMunger9(GraphicsStateGuardian *gsg, const RenderState *state);
|
||||
virtual ~DXGeomMunger9();
|
||||
ALLOC_DELETED_CHAIN(DXGeomMunger9);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ DXGraphicsStateGuardian9(GraphicsEngine *engine, GraphicsPipe *pipe) :
|
|||
|
||||
_last_fvf = 0;
|
||||
_num_bound_streams = 0;
|
||||
_white_vbuffer = nullptr;
|
||||
|
||||
_vertex_shader_version_major = 0;
|
||||
_vertex_shader_version_minor = 0;
|
||||
|
|
@ -798,9 +799,9 @@ clear(DrawableRegion *clearable) {
|
|||
main_flags |= D3DCLEAR_TARGET;
|
||||
}
|
||||
|
||||
if (clearable->get_clear_depth_active()) {
|
||||
if (clearable->get_clear_depth_active() &&
|
||||
_screen->_presentation_params.EnableAutoDepthStencil) {
|
||||
aux_flags |= D3DCLEAR_ZBUFFER;
|
||||
nassertv(_screen->_presentation_params.EnableAutoDepthStencil);
|
||||
}
|
||||
|
||||
if (clearable->get_clear_stencil_active()) {
|
||||
|
|
@ -4545,6 +4546,11 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *presentation_params,
|
|||
release_all_vertex_buffers();
|
||||
release_all_index_buffers();
|
||||
|
||||
if (_white_vbuffer != nullptr) {
|
||||
_white_vbuffer->Release();
|
||||
_white_vbuffer = nullptr;
|
||||
}
|
||||
|
||||
// must be called before reset
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
_prepared_objects->begin_frame(this, current_thread);
|
||||
|
|
@ -5234,9 +5240,9 @@ calc_fb_properties(DWORD cformat, DWORD dformat,
|
|||
#define GAMMA_1 (255.0 * 256.0)
|
||||
|
||||
static bool _gamma_table_initialized = false;
|
||||
static unsigned short _orignial_gamma_table [256 * 3];
|
||||
static unsigned short _original_gamma_table [256 * 3];
|
||||
|
||||
void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
|
||||
void _create_gamma_table_dx9 (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
|
||||
int i;
|
||||
double gamma_correction;
|
||||
|
||||
|
|
@ -5298,7 +5304,7 @@ get_gamma_table(void) {
|
|||
HDC hdc = GetDC(nullptr);
|
||||
|
||||
if (hdc) {
|
||||
if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
|
||||
if (GetDeviceGammaRamp (hdc, (LPVOID) _original_gamma_table)) {
|
||||
_gamma_table_initialized = true;
|
||||
get = true;
|
||||
}
|
||||
|
|
@ -5323,10 +5329,10 @@ static_set_gamma(bool restore, PN_stdfloat gamma) {
|
|||
unsigned short ramp [256 * 3];
|
||||
|
||||
if (restore && _gamma_table_initialized) {
|
||||
_create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
|
||||
_create_gamma_table_dx9 (gamma, &_original_gamma_table [0], &_original_gamma_table [256], &_original_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
|
||||
}
|
||||
else {
|
||||
_create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
|
||||
_create_gamma_table_dx9 (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
|
||||
}
|
||||
|
||||
if (SetDeviceGammaRamp (hdc, ramp)) {
|
||||
|
|
@ -5404,6 +5410,40 @@ set_cg_device(LPDIRECT3DDEVICE9 cg_device) {
|
|||
#endif // HAVE_CG
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vertex buffer containing only a full-white color.
|
||||
*/
|
||||
LPDIRECT3DVERTEXBUFFER9 DXGraphicsStateGuardian9::
|
||||
get_white_vbuffer() {
|
||||
if (_white_vbuffer != nullptr) {
|
||||
return _white_vbuffer;
|
||||
}
|
||||
|
||||
LPDIRECT3DVERTEXBUFFER9 vbuffer;
|
||||
HRESULT hr;
|
||||
hr = _screen->_d3d_device->CreateVertexBuffer(sizeof(D3DCOLOR), D3DUSAGE_WRITEONLY, D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, &vbuffer, nullptr);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "CreateVertexBuffer failed" << D3DERRORSTRING(hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3DCOLOR *local_pointer;
|
||||
hr = vbuffer->Lock(0, sizeof(D3DCOLOR), (void **) &local_pointer, D3DLOCK_DISCARD);
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "VertexBuffer::Lock failed" << D3DERRORSTRING(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
*local_pointer = D3DCOLOR_ARGB(255, 255, 255, 255);
|
||||
|
||||
vbuffer->Unlock();
|
||||
_white_vbuffer = vbuffer;
|
||||
return vbuffer;
|
||||
}
|
||||
|
||||
typedef std::string KEY;
|
||||
|
||||
typedef struct _KEY_ELEMENT
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ public:
|
|||
static void set_cg_device(LPDIRECT3DDEVICE9 cg_device);
|
||||
virtual bool get_supports_cg_profile(const std::string &name) const;
|
||||
|
||||
LPDIRECT3DVERTEXBUFFER9 get_white_vbuffer();
|
||||
|
||||
protected:
|
||||
void do_issue_transform();
|
||||
|
|
@ -274,12 +275,6 @@ protected:
|
|||
|
||||
RenderBuffer::Type _cur_read_pixel_buffer; // source for copy_pixel_buffer operation
|
||||
|
||||
PN_stdfloat _material_ambient;
|
||||
PN_stdfloat _material_diffuse;
|
||||
PN_stdfloat _material_specular;
|
||||
PN_stdfloat _material_shininess;
|
||||
PN_stdfloat _material_emission;
|
||||
|
||||
enum DxgsgFogType {
|
||||
None,
|
||||
PerVertexFog=D3DRS_FOGVERTEXMODE,
|
||||
|
|
@ -320,6 +315,7 @@ protected:
|
|||
|
||||
DWORD _last_fvf;
|
||||
int _num_bound_streams;
|
||||
LPDIRECT3DVERTEXBUFFER9 _white_vbuffer;
|
||||
|
||||
// Cache the data necessary to bind each particular light each frame, so if
|
||||
// we bind a given light multiple times, we only have to compute its data
|
||||
|
|
|
|||
|
|
@ -1,269 +0,0 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file dxInput9.cxx
|
||||
* @author angelina jolie
|
||||
* @date 1999-10-07
|
||||
*/
|
||||
|
||||
#include "config_wdxdisplay9.h"
|
||||
#include "dxInput9.h"
|
||||
|
||||
#define AXIS_RESOLUTION 2000 // use this many levels of resolution by default (could be more if needed and device supported it)
|
||||
#define AXIS_RANGE_CENTERED // if defined, axis range is centered on 0, instead of starting on 0
|
||||
|
||||
using std::endl;
|
||||
|
||||
BOOL CALLBACK EnumGameCtrlsCallback( const DIDEVICEINSTANCE* pdidInstance,
|
||||
VOID* pContext ) {
|
||||
DI_DeviceInfos *pDevInfos = (DI_DeviceInfos *)pContext;
|
||||
|
||||
(*pDevInfos).push_back(*pdidInstance);
|
||||
|
||||
if(wdxdisplay_cat.is_debug())
|
||||
wdxdisplay_cat.debug() << "Found DevType 0x" << (void*)pdidInstance->dwDevType << ": " << pdidInstance->tszInstanceName << ": " << pdidInstance->tszProductName <<endl;
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
extern BOOL CALLBACK EnumObjectsCallbackJoystick(const DIDEVICEOBJECTINSTANCE* pdidoi,VOID* pContext);
|
||||
|
||||
DInput9Info::DInput9Info() {
|
||||
_pDInput9 = nullptr;
|
||||
_hDInputDLL = nullptr;
|
||||
_JoystickPollTimer = nullptr;
|
||||
}
|
||||
|
||||
DInput9Info::~DInput9Info() {
|
||||
for(UINT i=0;i<_DeviceList.size();i++) {
|
||||
_DeviceList[i]->Unacquire();
|
||||
SAFE_RELEASE(_DeviceList[i]);
|
||||
}
|
||||
|
||||
// bugbug: need to handle this if(_JoystickPollTimer!=NULL) KillTimer(...)
|
||||
|
||||
SAFE_RELEASE(_pDInput9);
|
||||
if(_hDInputDLL) {
|
||||
FreeLibrary(_hDInputDLL);
|
||||
_hDInputDLL=nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool DInput9Info::InitDirectInput() {
|
||||
HRESULT hr;
|
||||
|
||||
// assumes dx9 exists use dynamic load so non-dinput programs don't have
|
||||
// to load dinput
|
||||
#define DLLNAME "dinput9.dll"
|
||||
#define DINPUTCREATE "DirectInput9Create"
|
||||
|
||||
HINSTANCE _hDInputDLL = LoadLibrary(DLLNAME);
|
||||
if(_hDInputDLL == 0) {
|
||||
wdxdisplay_cat.fatal() << "LoadLibrary(" << DLLNAME <<") failed!, error=" << GetLastError() << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
typedef HRESULT (WINAPI * LPDIRECTINPUT9CREATE)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
|
||||
LPDIRECTINPUT9CREATE pDInputCreate9;
|
||||
|
||||
pDInputCreate9 = (LPDIRECTINPUT9CREATE) GetProcAddress(_hDInputDLL,DINPUTCREATE);
|
||||
if(pDInputCreate9 == nullptr) {
|
||||
wdxdisplay_cat.fatal() << "GetProcAddr failed for " << DINPUTCREATE << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Register with the DirectInput subsystem and get a pointer to a
|
||||
// IDirectInput interface we can use. Create a DInput object
|
||||
if( FAILED( hr = (*pDInputCreate9)(GetModuleHandle(nullptr), DIRECTINPUT_VERSION,
|
||||
IID_IDirectInput9, (VOID**)&_pDInput9, nullptr ) ) ) {
|
||||
wdxdisplay_cat.error() << DINPUTCREATE << "failed" << D3DERRORSTRING(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// enum all the joysticks,etc (but not keybdmouse)
|
||||
if( FAILED( hr = _pDInput9->EnumDevices(DI9DEVCLASS_GAMECTRL,
|
||||
EnumGameCtrlsCallback,
|
||||
(LPVOID)&_DevInfos, DIEDFL_ATTACHEDONLY ) ) ) {
|
||||
wdxdisplay_cat.error() << "EnumDevices failed" << D3DERRORSTRING(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DInput9Info::CreateJoystickOrPad(HWND _window) {
|
||||
bool bFoundDev = false;
|
||||
UINT devnum=0;
|
||||
char *errstr=nullptr;
|
||||
|
||||
// look through the list for the first joystick or gamepad
|
||||
for(;devnum<_DevInfos.size();devnum++) {
|
||||
DWORD devType = GET_DIDEVICE_TYPE(_DevInfos[devnum].dwDevType);
|
||||
if((devType==DI9DEVTYPE_GAMEPAD) ||(devType==DI9DEVTYPE_JOYSTICK)) {
|
||||
bFoundDev=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bFoundDev) {
|
||||
wdxdisplay_cat.error() << "Cant find an attached Joystick or GamePad!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
LPDIRECTINPUTDEVICE9 pJoyDevice;
|
||||
|
||||
// Obtain an interface to the enumerated joystick.
|
||||
HRESULT hr = _pDInput9->CreateDevice(_DevInfos[devnum].guidInstance, &pJoyDevice, nullptr );
|
||||
if(FAILED(hr)) {
|
||||
errstr="CreateDevice";
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
assert(pJoyDevice!=nullptr);
|
||||
_DeviceList.push_back(pJoyDevice);
|
||||
|
||||
// Set the data format to "simple joystick" - a predefined data format A
|
||||
// data format specifies which controls on a device we are interested in,
|
||||
// and how they should be reported. This tells DInput that we will be
|
||||
// passing a DIJOYSTATE2 structure to
|
||||
// IDirectInputDevice::GetDeviceState().
|
||||
hr = pJoyDevice->SetDataFormat(&c_dfDIJoystick2);
|
||||
if(FAILED(hr)) {
|
||||
errstr="SetDataFormat";
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
// must be called AFTER SetDataFormat to get all the proper flags
|
||||
DX_DECLARE_CLEAN(DIDEVCAPS, DIDevCaps);
|
||||
hr = pJoyDevice->GetCapabilities(&DIDevCaps);
|
||||
assert(SUCCEEDED(hr));
|
||||
|
||||
_DevCaps.push_back(DIDevCaps);
|
||||
|
||||
if(wdxdisplay_cat.is_debug())
|
||||
wdxdisplay_cat.debug() << "Joy/Pad has " << DIDevCaps.dwAxes << " Axes, " << DIDevCaps.dwButtons << " Buttons, " << DIDevCaps.dwPOVs << " POVs" << endl;
|
||||
|
||||
// Set the cooperative level to let DInput know how this device should
|
||||
// interact with the system and with other DInput applications.
|
||||
hr = pJoyDevice->SetCooperativeLevel( _window, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
if(FAILED(hr)) {
|
||||
errstr="SetCooperativeLevel";
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
// set the minmax values property for discovered axes.
|
||||
hr = pJoyDevice->EnumObjects(EnumObjectsCallbackJoystick, (LPVOID)pJoyDevice, DIDFT_AXIS);
|
||||
if(FAILED(hr)) {
|
||||
errstr="EnumObjects";
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
handle_error:
|
||||
wdxdisplay_cat.error() << errstr << " failed for (" << _DevInfos[devnum].tszInstanceName << ":" << _DevInfos[devnum].tszProductName << ")" << D3DERRORSTRING(hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// -- Name: EnumObjectsCallback() Desc: Callback function for enumerating
|
||||
// objects (axes, buttons, POVs) on a joystick. This function enables user
|
||||
// interface elements for objects that are found to exist, and scales axes
|
||||
// minmax values. -----------------------------------------------------------
|
||||
// ------------------
|
||||
BOOL CALLBACK EnumObjectsCallbackJoystick( const DIDEVICEOBJECTINSTANCE* pdidoi,
|
||||
VOID* pContext ) {
|
||||
|
||||
LPDIRECTINPUTDEVICE9 pJoyDevice = (LPDIRECTINPUTDEVICE9) pContext;
|
||||
HRESULT hr;
|
||||
|
||||
// For axes that are returned, set the DIPROP_RANGE property for the
|
||||
// enumerated axis in order to scale minmax values.
|
||||
if( pdidoi->dwType & DIDFT_AXIS ) {
|
||||
DIPROPRANGE diprg;
|
||||
diprg.diph.dwSize = sizeof(DIPROPRANGE);
|
||||
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
diprg.diph.dwHow = DIPH_BYID;
|
||||
diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis
|
||||
|
||||
#ifdef AXIS_RANGE_CENTERED
|
||||
diprg.lMin = -AXIS_RESOLUTION/2;
|
||||
diprg.lMax = +AXIS_RESOLUTION/2;
|
||||
#else
|
||||
diprg.lMin = 0;
|
||||
diprg.lMax = +AXIS_RESOLUTION;
|
||||
#endif
|
||||
|
||||
// Set the range for the axis
|
||||
hr = pJoyDevice->SetProperty( DIPROP_RANGE, &diprg.diph);
|
||||
if(FAILED(hr)) {
|
||||
wdxdisplay_cat.error() << "SetProperty on axis failed" << D3DERRORSTRING(hr);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
bool DInput9Info::ReadJoystick(int devnum, DIJOYSTATE2 &js) {
|
||||
LPDIRECTINPUTDEVICE9 pJoystick = _DeviceList[devnum];
|
||||
assert(pJoystick!=nullptr);
|
||||
HRESULT hr;
|
||||
char *errstr;
|
||||
|
||||
// Poll the device to read the current state
|
||||
|
||||
hr = pJoystick->Poll();
|
||||
|
||||
if( FAILED(hr) ) {
|
||||
// DInput is telling us that the input stream has been interrupted.
|
||||
// We aren't tracking any state between polls, so we don't have any
|
||||
// special reset that needs to be done. We just re-acquire and try
|
||||
// again.
|
||||
|
||||
if((hr==DIERR_NOTACQUIRED)||(hr == DIERR_INPUTLOST)) {
|
||||
hr = pJoystick->Acquire();
|
||||
|
||||
if(FAILED(hr)) {
|
||||
if(wdxdisplay_cat.is_spam())
|
||||
wdxdisplay_cat.spam() << "Acquire failed" << D3DERRORSTRING(hr);
|
||||
|
||||
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This may
|
||||
// occur when the app is minimized or in the process of
|
||||
// switching, so just try again later
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = pJoystick->Poll();
|
||||
if(FAILED(hr)) {
|
||||
// should never happen!
|
||||
errstr = "Poll after successful Acquire failed";
|
||||
goto handle_error;
|
||||
}
|
||||
} else {
|
||||
errstr = "Unknown Poll failure";
|
||||
goto handle_error;
|
||||
}
|
||||
}
|
||||
|
||||
// should we make a vector of devstate dataformats to generalize this fn
|
||||
// for all device types?
|
||||
|
||||
// Get the input's device state
|
||||
hr = pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js);
|
||||
if(FAILED(hr)) {
|
||||
errstr = "GetDeviceState failed";
|
||||
goto handle_error;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
handle_error:
|
||||
wdxdisplay_cat.fatal() << errstr << D3DERRORSTRING(hr);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file dxInput9.h
|
||||
* @author blllyjo
|
||||
* @date 1999-10-07
|
||||
*/
|
||||
|
||||
#ifndef DXINPUT9_H
|
||||
#define DXINPUT9_H
|
||||
|
||||
#define DIRECTINPUT_VERSION 0x900
|
||||
#include <dinput.h>
|
||||
typedef std::vector<DIDEVICEINSTANCE> DI_DeviceInfos;
|
||||
typedef std::vector<DIDEVICEOBJECTINSTANCE> DI_DeviceObjInfos;
|
||||
|
||||
class DInput9Info {
|
||||
public:
|
||||
DInput9Info();
|
||||
~DInput9Info();
|
||||
bool InitDirectInput();
|
||||
bool CreateJoystickOrPad(HWND _window);
|
||||
bool ReadJoystick(int devnum, DIJOYSTATE2 &js);
|
||||
|
||||
HINSTANCE _hDInputDLL;
|
||||
UINT_PTR _JoystickPollTimer;
|
||||
LPDIRECTINPUT8 _pDInput9;
|
||||
DI_DeviceInfos _DevInfos;
|
||||
// arrays for all created devices. Should probably put these together in a
|
||||
// struct, along with the data fmt info
|
||||
std::vector<LPDIRECTINPUTDEVICE8> _DeviceList;
|
||||
std::vector<DIDEVCAPS> _DevCaps;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -390,6 +390,8 @@ update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg, bool force) {
|
|||
// arrays ("streams"), and we repeatedly iterate the parameters to pull
|
||||
// out only those for a single stream.
|
||||
|
||||
bool apply_white_color = false;
|
||||
|
||||
int number_of_arrays = gsg->_data_reader->get_num_arrays();
|
||||
for (int array_index = 0; array_index < number_of_arrays; ++array_index) {
|
||||
const GeomVertexArrayDataHandle* array_reader =
|
||||
|
|
@ -423,6 +425,11 @@ update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg, bool force) {
|
|||
}
|
||||
}
|
||||
|
||||
if (name == InternalName::get_color() && !gsg->_vertex_colors_enabled) {
|
||||
apply_white_color = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
const GeomVertexArrayDataHandle *param_array_reader;
|
||||
Geom::NumericType numeric_type;
|
||||
int num_values, start, stride;
|
||||
|
|
@ -435,6 +442,9 @@ update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg, bool force) {
|
|||
// shader parameter, which can cause Bad Things to happen so I'd
|
||||
// like to at least get a hint as to what's gone wrong.
|
||||
dxgsg9_cat.info() << "Geometry contains no data for shader parameter " << *name << "\n";
|
||||
if (name == InternalName::get_color()) {
|
||||
apply_white_color = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -564,6 +574,19 @@ update_shader_vertex_arrays(DXShaderContext9 *prev, GSG *gsg, bool force) {
|
|||
|
||||
_num_bound_streams = number_of_arrays;
|
||||
|
||||
if (apply_white_color) {
|
||||
// The shader needs a vertex color, but vertex colors are disabled.
|
||||
// Bind a vertex buffer containing only one white colour.
|
||||
int array_index = number_of_arrays;
|
||||
LPDIRECT3DVERTEXBUFFER9 vbuffer = gsg->get_white_vbuffer();
|
||||
hr = device->SetStreamSource(array_index, vbuffer, 0, 0);
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.error() << "SetStreamSource failed" << D3DERRORSTRING(hr);
|
||||
}
|
||||
vertex_element_array->add_diffuse_color_vertex_element(array_index, 0);
|
||||
++_num_bound_streams;
|
||||
}
|
||||
|
||||
if (_vertex_element_array != nullptr &&
|
||||
_vertex_element_array->add_end_vertex_element()) {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
|
|
|
|||
|
|
@ -1229,7 +1229,10 @@ init_resized_window() {
|
|||
DWORD flags;
|
||||
D3DCOLOR clear_color;
|
||||
|
||||
flags = D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER;
|
||||
flags = D3DCLEAR_TARGET;
|
||||
if (_fb_properties.get_depth_bits() > 0) {
|
||||
flags |= D3DCLEAR_ZBUFFER;
|
||||
}
|
||||
clear_color = 0x00000000;
|
||||
hr = _wcontext._d3d_device-> Clear (0, nullptr, flags, clear_color, 0.0f, 0);
|
||||
if (FAILED(hr)) {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include "pandabase.h"
|
||||
#include "winGraphicsWindow.h"
|
||||
#include "dxGraphicsStateGuardian9.h"
|
||||
#include "dxInput9.h"
|
||||
#include "wdxGraphicsPipe9.h"
|
||||
|
||||
class wdxGraphicsPipe9;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ INLINE void set_matrix_view(Py_buffer &view, int flags, int length, int size, bo
|
|||
} else if (size == 4 && double_prec) {
|
||||
mat_size = sizeof(UnalignedLMatrix4d);
|
||||
} else {
|
||||
assert(false);
|
||||
nassertv_always(false);
|
||||
return; // Make sure compiler knows control flow doesn't proceed.
|
||||
}
|
||||
|
||||
view.len = length * mat_size;
|
||||
|
|
|
|||
|
|
@ -97,11 +97,11 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
|||
|
||||
#ifdef _MSC_VER
|
||||
// Ugh... MSVC needs this because they still don't have a decent linker.
|
||||
#include "PTA_uchar.h"
|
||||
#include "PTA_ushort.h"
|
||||
#include "PTA_float.h"
|
||||
#include "PTA_double.h"
|
||||
#include "PTA_int.h"
|
||||
#include "pta_uchar.h"
|
||||
#include "pta_ushort.h"
|
||||
#include "pta_float.h"
|
||||
#include "pta_double.h"
|
||||
#include "pta_int.h"
|
||||
|
||||
template class EXPORT_THIS Extension<PTA_uchar>;
|
||||
template class EXPORT_THIS Extension<PTA_ushort>;
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
// OpenGL ES 2 has no fixed-function pipeline.
|
||||
#undef SUPPORT_FIXED_FUNCTION
|
||||
|
||||
#ifdef IS_OSX
|
||||
#ifdef BUILD_IPHONE
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
// #include <OpenGLESES2glext.h>
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
#define __glext_h_
|
||||
#define ES1_GLEXT_H_GUARD
|
||||
|
||||
#ifdef IS_OSX
|
||||
#ifdef BUILD_IPHONE
|
||||
#include <OpenGLES/ES1/gl.h>
|
||||
// #include <OpenGLESES1glext.h>
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -226,12 +226,14 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
|
|||
if (!resource) {
|
||||
resource = "unknown";
|
||||
}
|
||||
GLCAT.error()
|
||||
<< "Could not find Cg varying " << cgGetParameterName(p);
|
||||
if (attribname) {
|
||||
GLCAT.error(false) << " : " << attribname;
|
||||
if (GLCAT.is_debug()) {
|
||||
GLCAT.debug()
|
||||
<< "Could not find Cg varying " << cgGetParameterName(p);
|
||||
if (attribname) {
|
||||
GLCAT.debug(false) << " : " << attribname;
|
||||
}
|
||||
GLCAT.debug(false) << " (" << resource << ") in the compiled GLSL program.\n";
|
||||
}
|
||||
GLCAT.error(false) << " (" << resource << ") in the compiled GLSL program.\n";
|
||||
|
||||
} else if (loc != 0 && bind._id._name == "vtx_position") {
|
||||
// We really have to bind the vertex position to attribute 0, since
|
||||
|
|
@ -312,10 +314,10 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
|
|||
GLCAT.debug(false)
|
||||
<< " is bound to a conventional attribute (" << resource << ")\n";
|
||||
}
|
||||
}
|
||||
if (loc == CA_unknown) {
|
||||
// Suggest fix to developer.
|
||||
GLCAT.error() << "Try using a different semantic.\n";
|
||||
if (loc == CA_unknown) {
|
||||
// Suggest fix to developer.
|
||||
GLCAT.debug() << "Try using a different semantic.\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1097,6 +1097,15 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
|
|||
#endif
|
||||
glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rbm[slot]);
|
||||
GLuint format = GL_DEPTH_COMPONENT;
|
||||
#ifndef OPENGLES
|
||||
if (_fb_properties.get_float_depth()) {
|
||||
if (!glgsg->_use_remapped_depth_range) {
|
||||
format = GL_DEPTH_COMPONENT32F;
|
||||
} else {
|
||||
format = GL_DEPTH_COMPONENT32F_NV;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (tex) {
|
||||
switch (tex->get_format()) {
|
||||
case Texture::F_depth_component16:
|
||||
|
|
|
|||
|
|
@ -4392,7 +4392,8 @@ update_standard_vertex_arrays(bool force) {
|
|||
GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
} else
|
||||
#endif // NDEBUG
|
||||
if (_data_reader->get_color_info(array_reader, num_values, numeric_type,
|
||||
if (_vertex_colors_enabled &&
|
||||
_data_reader->get_color_info(array_reader, num_values, numeric_type,
|
||||
start, stride)) {
|
||||
if (!setup_array_data(client_pointer, array_reader, force)) {
|
||||
return false;
|
||||
|
|
@ -4409,7 +4410,13 @@ update_standard_vertex_arrays(bool force) {
|
|||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
// Since we don't have per-vertex color, the implicit color is white.
|
||||
GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
if (_color_scale_via_lighting) {
|
||||
GLPf(Color4)(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
} else {
|
||||
LColor color = _scene_graph_color;
|
||||
color.componentwise_mult(_current_color_scale);
|
||||
GLPf(Color4)(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
}
|
||||
|
||||
// Now set up each of the active texture coordinate stages--or at least
|
||||
|
|
@ -8918,6 +8925,9 @@ get_panda_wrap_mode(GLenum wm) {
|
|||
case GL_REPEAT:
|
||||
return SamplerState::WM_repeat;
|
||||
|
||||
case GL_MIRRORED_REPEAT:
|
||||
return SamplerState::WM_mirror;
|
||||
|
||||
#ifndef OPENGLES
|
||||
case GL_MIRROR_CLAMP_EXT:
|
||||
case GL_MIRROR_CLAMP_TO_EDGE_EXT:
|
||||
|
|
|
|||
|
|
@ -2440,9 +2440,9 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
|
|||
if (p == _color_attrib_index) {
|
||||
// Vertex colors are disabled or not present. Apply flat color.
|
||||
#ifdef STDFLOAT_DOUBLE
|
||||
_glgsg->_glVertexAttrib4dv(p, color_attrib->get_color().get_data());
|
||||
_glgsg->_glVertexAttrib4dv(p, _glgsg->_scene_graph_color.get_data());
|
||||
#else
|
||||
_glgsg->_glVertexAttrib4fv(p, color_attrib->get_color().get_data());
|
||||
_glgsg->_glVertexAttrib4fv(p, _glgsg->_scene_graph_color.get_data());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,6 +286,28 @@ make_nonindexed(bool composite_only) {
|
|||
return num_changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a GeomVertexData that represents the results of computing the
|
||||
* vertex animation on the CPU for this Geom's vertex data.
|
||||
*
|
||||
* If there is no CPU-defined vertex animation on this object, this just
|
||||
* returns the original object.
|
||||
*
|
||||
* If there is vertex animation, but the VertexTransform values have not
|
||||
* changed since last time, this may return the same pointer it returned
|
||||
* previously. Even if the VertexTransform values have changed, it may still
|
||||
* return the same pointer, but with its contents modified (this is preferred,
|
||||
* since it allows the graphics backend to update vertex buffers optimally).
|
||||
*
|
||||
* If force is false, this method may return immediately with stale data, if
|
||||
* the vertex data is not completely resident. If force is true, this method
|
||||
* will never return stale data, but may block until the data is available.
|
||||
*/
|
||||
CPT(GeomVertexData) Geom::
|
||||
get_animated_vertex_data(bool force, Thread *current_thread) const {
|
||||
return get_vertex_data()->animate_vertices(force, current_thread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the ith GeomPrimitive object stored within the Geom with the new
|
||||
* object.
|
||||
|
|
@ -1311,8 +1333,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
|
|||
int num_vertices = 0;
|
||||
|
||||
// Get the vertex data, after animation.
|
||||
CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer(current_thread);
|
||||
vertex_data = vertex_data->animate_vertices(true, current_thread);
|
||||
CPT(GeomVertexData) vertex_data = get_animated_vertex_data(true, current_thread);
|
||||
|
||||
// Now actually compute the bounding volume. We do this by using
|
||||
// calc_tight_bounds to determine our box first.
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ PUBLISHED:
|
|||
void offset_vertices(const GeomVertexData *data, int offset);
|
||||
int make_nonindexed(bool composite_only);
|
||||
|
||||
CPT(GeomVertexData) get_animated_vertex_data(bool force, Thread *current_thread) const;
|
||||
|
||||
INLINE bool is_empty() const;
|
||||
|
||||
INLINE size_t get_num_primitives() const;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ has_column(const InternalName *name) const {
|
|||
*/
|
||||
INLINE int GeomVertexArrayData::
|
||||
get_num_rows() const {
|
||||
return get_handle()->get_num_rows();
|
||||
CDReader cdata(_cycler);
|
||||
nassertr(_array_format->get_stride() != 0, 0);
|
||||
return cdata->_buffer.get_size() / _array_format->get_stride();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -60,9 +60,20 @@ has_column(const InternalName *name) const {
|
|||
*/
|
||||
INLINE int GeomVertexData::
|
||||
get_num_rows() const {
|
||||
GeomVertexDataPipelineReader reader(this, Thread::get_current_thread());
|
||||
reader.check_array_readers();
|
||||
return reader.get_num_rows();
|
||||
CPT(GeomVertexArrayData) array;
|
||||
{
|
||||
CDReader cdata(_cycler);
|
||||
nassertr(cdata->_format->get_num_arrays() == cdata->_arrays.size(), 0);
|
||||
|
||||
if (cdata->_arrays.size() == 0) {
|
||||
// No arrays means no rows. Weird but legal.
|
||||
return 0;
|
||||
}
|
||||
|
||||
array = cdata->_arrays[0].get_read_pointer();
|
||||
}
|
||||
|
||||
return array->get_num_rows();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -761,7 +772,9 @@ set_object(const GeomVertexData *object) {
|
|||
_cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
|
||||
_got_array_readers = false;
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
_cdata->ref();
|
||||
#endif // DO_PIPELINING
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -621,13 +621,26 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
|
|||
const TransformBlend &blend = blend_table->get_blend(from.get_data1i());
|
||||
LVecBase4 weights = LVecBase4::zero();
|
||||
LVecBase4i indices(0, 0, 0, 0);
|
||||
nassertv(blend.get_num_transforms() <= 4);
|
||||
|
||||
for (size_t i = 0; i < blend.get_num_transforms(); i++) {
|
||||
weights[i] = blend.get_weight(i);
|
||||
indices[i] = add_transform(transform_table, blend.get_transform(i),
|
||||
already_added);
|
||||
if (blend.get_num_transforms() <= 4) {
|
||||
for (size_t i = 0; i < blend.get_num_transforms(); i++) {
|
||||
weights[i] = blend.get_weight(i);
|
||||
indices[i] = add_transform(transform_table, blend.get_transform(i),
|
||||
already_added);
|
||||
}
|
||||
} else {
|
||||
// Limit the number of blends to the four with highest weights.
|
||||
TransformBlend blend2(blend);
|
||||
blend2.limit_transforms(4);
|
||||
blend2.normalize_weights();
|
||||
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
weights[i] = blend2.get_weight(i);
|
||||
indices[i] = add_transform(transform_table, blend2.get_transform(i),
|
||||
already_added);
|
||||
}
|
||||
}
|
||||
|
||||
if (weight.has_column()) {
|
||||
weight.set_data4(weights);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1619,8 +1619,8 @@ begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
|
|||
++qsi) {
|
||||
Shader *shader = qsi->first;
|
||||
ShaderContext *sc = shader->prepare_now(this, gsg);
|
||||
if (qti->second != nullptr) {
|
||||
qti->second->set_result(sc);
|
||||
if (qsi->second != nullptr) {
|
||||
qsi->second->set_result(sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ do_task() {
|
|||
// become a kind of a leak (if the texture is never rendered again on
|
||||
// this GSG, we'll just end up carrying the texture memory in RAM
|
||||
// forever, instead of dumping it as soon as it gets prepared).
|
||||
_texture->prepare(_pgo);
|
||||
_pgo->enqueue_texture(_texture);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ operator = (const TextureStage &other) {
|
|||
_combine_rgb_operand2 = other._combine_rgb_operand2;
|
||||
_combine_alpha_mode = other._combine_alpha_mode;
|
||||
_combine_alpha_source0 = other._combine_alpha_source0;
|
||||
_combine_alpha_operand0 = _combine_alpha_operand0;
|
||||
_combine_alpha_operand0 = other._combine_alpha_operand0;
|
||||
_combine_alpha_source1 = other._combine_alpha_source1;
|
||||
_combine_alpha_operand1 = other._combine_alpha_operand1;
|
||||
_combine_alpha_source2 = other._combine_alpha_source2;
|
||||
|
|
|
|||
|
|
@ -866,7 +866,7 @@ transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name,
|
|||
PT(Geom) geom = orig_geom->make_copy();
|
||||
|
||||
// Ensure that any vertex animation has been applied.
|
||||
geom->set_vertex_data(geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread));
|
||||
geom->set_vertex_data(geom->get_animated_vertex_data(true, current_thread));
|
||||
|
||||
// Now get a modifiable pointer to the vertex data in the new Geom. This
|
||||
// will actually perform a deep copy of the vertex data.
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ do_flush() {
|
|||
if (data_sent > 0) {
|
||||
total_sent += data_sent;
|
||||
}
|
||||
double last_report = 0;
|
||||
|
||||
while (!okflag && tcp->Active() &&
|
||||
(data_sent > 0 || tcp->GetLastError() == LOCAL_BLOCKING_ERROR)) {
|
||||
if (data_sent == 0) {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ private:
|
|||
CGGammaValue _gOriginalRedTable[ 256 ];
|
||||
CGGammaValue _gOriginalGreenTable[ 256 ];
|
||||
CGGammaValue _gOriginalBlueTable[ 256 ];
|
||||
CGTableCount _sampleCount;
|
||||
uint32_t _sampleCount;
|
||||
CGDisplayErr _cgErr;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ write(std::ostream &out, int indent) const {
|
|||
out.width(indent+2); out<<""; out<<"_lifespan "<<_lifespan<<"\n";
|
||||
out.width(indent+2); out<<""; out<<"_alive "<<_alive<<"\n";
|
||||
out.width(indent+2); out<<""; out<<"_index "<<_index<<"\n";
|
||||
out.width(indent+2); out<<""; out<<"_last_position "<<_last_position<<"\n";
|
||||
PhysicsObject::write(out, indent+2);
|
||||
#endif //] NDEBUG
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ private:
|
|||
PN_stdfloat _lifespan;
|
||||
bool _alive;
|
||||
int _index;
|
||||
|
||||
LPoint3 _last_position;
|
||||
};
|
||||
|
||||
#include "baseParticle.I"
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ make_off() {
|
|||
*/
|
||||
CPT(RenderAttrib) ColorAttrib::
|
||||
make_default() {
|
||||
return make_off();
|
||||
return make_vertex();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public:
|
|||
register_type(_type_handle, "ColorAttrib",
|
||||
RenderAttrib::get_class_type());
|
||||
_attrib_slot = register_slot(_type_handle, 100,
|
||||
new ColorAttrib(T_off, LColor(1, 1, 1, 1)));
|
||||
new ColorAttrib(T_vertex, LColor::zero()));
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ apply_transform_and_state(CullTraverser *trav) {
|
|||
CPT(TransformState) node_transform = _node_reader.get_transform();
|
||||
node_effects->cull_callback(trav, *this, node_transform, node_state);
|
||||
apply_transform(node_transform);
|
||||
|
||||
// The cull callback may have changed the node properties.
|
||||
_node_reader.check_cached(false);
|
||||
}
|
||||
|
||||
if (!node_state->is_empty()) {
|
||||
|
|
|
|||
|
|
@ -376,8 +376,7 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
|
|||
geom = transformer.premunge_geom(geom, munger);
|
||||
|
||||
// Prepare each of the vertex arrays in the munged Geom.
|
||||
CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
|
||||
vdata = vdata->animate_vertices(false, current_thread);
|
||||
CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(false, current_thread);
|
||||
GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
|
||||
int num_arrays = vdata_reader.get_num_arrays();
|
||||
for (int i = 0; i < num_arrays; ++i) {
|
||||
|
|
@ -474,7 +473,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
|
|||
for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
|
||||
CPT(Geom) geom = (*gi)._geom.get_read_pointer();
|
||||
geom->calc_tight_bounds(min_point, max_point, found_any,
|
||||
geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread),
|
||||
geom->get_animated_vertex_data(true, current_thread),
|
||||
!next_transform->is_identity(), mat,
|
||||
current_thread);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ garbage_collect() {
|
|||
}
|
||||
|
||||
num_this_pass = std::min(num_this_pass, size);
|
||||
size_t stop_at_element = (_garbage_index + num_this_pass) % size;
|
||||
size_t stop_at_element = (si + num_this_pass) % size;
|
||||
|
||||
do {
|
||||
RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
|
||||
|
|
@ -229,6 +229,9 @@ garbage_collect() {
|
|||
// still need to visit.
|
||||
--size;
|
||||
--si;
|
||||
if (stop_at_element > 0) {
|
||||
--stop_at_element;
|
||||
}
|
||||
}
|
||||
|
||||
si = (si + 1) % size;
|
||||
|
|
|
|||
|
|
@ -950,6 +950,9 @@ garbage_collect() {
|
|||
// still need to visit.
|
||||
--size;
|
||||
--si;
|
||||
if (stop_at_element > 0) {
|
||||
--stop_at_element;
|
||||
}
|
||||
}
|
||||
|
||||
si = (si + 1) % size;
|
||||
|
|
|
|||
|
|
@ -1216,6 +1216,9 @@ garbage_collect() {
|
|||
// still need to visit.
|
||||
--size;
|
||||
--si;
|
||||
if (stop_at_element > 0) {
|
||||
--stop_at_element;
|
||||
}
|
||||
}
|
||||
|
||||
si = (si + 1) % size;
|
||||
|
|
|
|||
|
|
@ -11,14 +11,6 @@
|
|||
* @date 2007-06-20
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE BlockerSimple::
|
||||
BlockerSimple() {
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
class EXPCL_PANDA_PIPELINE BlockerSimple {
|
||||
protected:
|
||||
INLINE BlockerSimple();
|
||||
constexpr BlockerSimple() = default;
|
||||
INLINE ~BlockerSimple();
|
||||
|
||||
protected:
|
||||
|
|
@ -38,7 +38,7 @@ protected:
|
|||
F_has_waiters = 0x40000000,
|
||||
};
|
||||
|
||||
unsigned int _flags;
|
||||
unsigned int _flags = 0;
|
||||
|
||||
friend class ThreadSimpleManager;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,7 +71,10 @@ init_libpipeline() {
|
|||
}
|
||||
initialized = true;
|
||||
|
||||
#ifdef DO_PIPELINING
|
||||
CycleData::init_type();
|
||||
#endif
|
||||
|
||||
MainThread::init_type();
|
||||
ExternalThread::init_type();
|
||||
GenericThread::init_type();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
/* Filename: contextSwitch_longjmp_src.c
|
||||
* Created by: drose (15Apr10)
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
|
|
@ -10,7 +6,10 @@
|
|||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
* @file contextSwitch_longjmp_src.c
|
||||
* @author drose
|
||||
* @date 2010-04-15
|
||||
*/
|
||||
|
||||
/* This is the implementation of user-space context switching using
|
||||
setmp() / longjmp(). This is the hackier implementation,
|
||||
|
|
@ -90,14 +89,14 @@ void
|
|||
cs_longjmp(cs_jmp_buf env) {
|
||||
_asm {
|
||||
mov eax, env;
|
||||
|
||||
|
||||
mov ebx, [eax + 0];
|
||||
mov edi, [eax + 4];
|
||||
mov esi, [eax + 8];
|
||||
mov ebp, [eax + 12];
|
||||
mov esp, [eax + 16];
|
||||
mov edx, [eax + 20];
|
||||
|
||||
|
||||
frstor [eax + 24]; /* restore floating-point state */
|
||||
|
||||
mov eax, 1; /* return 1 from setjmp: pass 2 return */
|
||||
|
|
@ -251,7 +250,7 @@ setup_context_1(void) {
|
|||
}
|
||||
|
||||
void
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
unsigned char *stack, size_t stack_size,
|
||||
ThreadFunction *thread_func, void *data) {
|
||||
/* Copy all of the input parameters to static variables, then begin
|
||||
|
|
@ -263,7 +262,7 @@ init_thread_context(struct ThreadContext *context,
|
|||
st_data = data;
|
||||
|
||||
setup_context_1();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
save_thread_context(struct ThreadContext *context,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
/* Filename: contextSwitch_posix_src.c
|
||||
* Created by: drose (15Apr10)
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
|
|
@ -10,7 +6,10 @@
|
|||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
* @file contextSwitch_posix_src.c
|
||||
* @author drose
|
||||
* @date 2010-04-15
|
||||
*/
|
||||
|
||||
/* This is the implementation of user-space context switching using
|
||||
posix threads to manage the different execution contexts. This
|
||||
|
|
@ -44,7 +43,7 @@ struct ThreadContext {
|
|||
pthread_mutex_t _ready_mutex;
|
||||
pthread_cond_t _ready_cvar;
|
||||
int _ready_flag;
|
||||
|
||||
|
||||
/* This is set FALSE while the thread is alive, and TRUE if the
|
||||
thread is to be terminated when it next wakes up. */
|
||||
int _terminated;
|
||||
|
|
@ -83,19 +82,19 @@ thread_main(void *data) {
|
|||
}
|
||||
|
||||
void
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
unsigned char *stack, size_t stack_size,
|
||||
ThreadFunction *thread_func, void *data) {
|
||||
context->_thread_func = thread_func;
|
||||
context->_data = data;
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, stack_size);
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||
|
||||
pthread_create(&(context->_thread), &attr, thread_main, context);
|
||||
pthread_attr_destroy(&attr);
|
||||
pthread_create(&(context->_thread), &attr, thread_main, context);
|
||||
pthread_attr_destroy(&attr);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -142,7 +141,7 @@ switch_to_thread_context(struct ThreadContext *from_context,
|
|||
/* We've been rudely terminated. Exit gracefully. */
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Now we have been signaled again, and we're ready to resume the
|
||||
thread. */
|
||||
longjmp(from_context->_jmp_context, 1);
|
||||
|
|
@ -164,7 +163,7 @@ alloc_thread_context() {
|
|||
pthread_mutexattr_init(&attr);
|
||||
// The symbol PTHREAD_MUTEX_DEFAULT isn't always available?
|
||||
// pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
|
||||
int result = pthread_mutex_init(&context->_ready_mutex, &attr);
|
||||
pthread_mutex_init(&context->_ready_mutex, &attr);
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
pthread_cond_init(&context->_ready_cvar, NULL);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
/* Filename: contextSwitch_ucontext_src.c
|
||||
* Created by: drose (15Apr10)
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
|
|
@ -10,7 +6,10 @@
|
|||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
* @file contextSwitch_ucontext_src.c
|
||||
* @author drose
|
||||
* @date 2010-04-15
|
||||
*/
|
||||
|
||||
/* This is the implementation of user-space context switching using
|
||||
getcontext() / setcontext(). This is the preferred implementation,
|
||||
|
|
@ -43,7 +42,7 @@ begin_context(ThreadFunction *thread_func, void *data) {
|
|||
}
|
||||
|
||||
void
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
unsigned char *stack, size_t stack_size,
|
||||
ThreadFunction *thread_func, void *data) {
|
||||
if (getcontext(&context->_ucontext) != 0) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
/* Filename: contextSwitch_windows_src.c
|
||||
* Created by: drose (15Apr10)
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
*
|
||||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
|
|
@ -10,7 +6,10 @@
|
|||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
* @file contextSwitch_windows_src.c
|
||||
* @author drose
|
||||
* @date 2010-04-15
|
||||
*/
|
||||
|
||||
/* This is the implementation of user-space context switching using
|
||||
native Windows threading constructs to manage the different
|
||||
|
|
@ -37,7 +36,7 @@ struct ThreadContext {
|
|||
/* This event is in the signaled state when the thread is ready to
|
||||
roll. */
|
||||
HANDLE _ready;
|
||||
|
||||
|
||||
/* This is set FALSE while the thread is alive, and TRUE if the
|
||||
thread is to be terminated when it next wakes up. */
|
||||
int _terminated;
|
||||
|
|
@ -71,13 +70,13 @@ thread_main(LPVOID data) {
|
|||
}
|
||||
|
||||
void
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
init_thread_context(struct ThreadContext *context,
|
||||
unsigned char *stack, size_t stack_size,
|
||||
ThreadFunction *thread_func, void *data) {
|
||||
context->_thread_func = thread_func;
|
||||
context->_data = data;
|
||||
|
||||
context->_thread = CreateThread(NULL, stack_size,
|
||||
context->_thread = CreateThread(NULL, stack_size,
|
||||
thread_main, context, 0, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +116,7 @@ switch_to_thread_context(struct ThreadContext *from_context,
|
|||
/* We've been rudely terminated. Exit gracefully. */
|
||||
ExitThread(1);
|
||||
}
|
||||
|
||||
|
||||
/* Now we have been signaled again, and we're ready to resume the
|
||||
thread. */
|
||||
longjmp(from_context->_jmp_context, 1);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ public:
|
|||
INLINE CycleData(const CycleData ©) = default;
|
||||
virtual ~CycleData();
|
||||
|
||||
CycleData &operator = (CycleData &&from) = default;
|
||||
CycleData &operator = (const CycleData ©) = default;
|
||||
|
||||
virtual CycleData *make_copy() const=0;
|
||||
|
||||
virtual void write_datagram(BamWriter *, Datagram &) const;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,19 @@ CycleDataLockedReader(const CycleDataLockedReader<CycleDataType> ©) :
|
|||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
CycleDataLockedReader(CycleDataLockedReader<CycleDataType> &&from) noexcept :
|
||||
_cycler(from._cycler),
|
||||
_current_thread(from._current_thread),
|
||||
_pointer(from._pointer)
|
||||
{
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -61,19 +74,6 @@ operator = (const CycleDataLockedReader<CycleDataType> ©) {
|
|||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedReader<CycleDataType>::
|
||||
CycleDataLockedReader(CycleDataLockedReader<CycleDataType> &&from) noexcept :
|
||||
_cycler(from._cycler),
|
||||
_current_thread(from._current_thread),
|
||||
_pointer(from._pointer)
|
||||
{
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -177,6 +177,18 @@ operator = (const CycleDataLockedReader<CycleDataType> ©) {
|
|||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataLockedReader<CycleDataType>::
|
||||
operator = (CycleDataLockedReader<CycleDataType> &&from) noexcept {
|
||||
nassertv(_pointer == nullptr);
|
||||
|
||||
_pointer = from._pointer;
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -47,6 +47,20 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> ©
|
|||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
|
||||
_cycler(from._cycler),
|
||||
_current_thread(from._current_thread),
|
||||
_pointer(from._pointer),
|
||||
_stage(from._stage)
|
||||
{
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -64,20 +78,6 @@ operator = (const CycleDataLockedStageReader<CycleDataType> ©) {
|
|||
_cycler->increment_read(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
|
||||
_cycler(from._cycler),
|
||||
_current_thread(from._current_thread),
|
||||
_pointer(from._pointer),
|
||||
_stage(from._stage)
|
||||
{
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -174,6 +174,17 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> ©
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataLockedStageReader<CycleDataType>::
|
||||
CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
|
||||
_pointer(from._cycler)
|
||||
{
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -183,6 +194,18 @@ operator = (const CycleDataLockedStageReader<CycleDataType> ©) {
|
|||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataLockedStageReader<CycleDataType>::
|
||||
operator = (CycleDataLockedStageReader<CycleDataType> &&from) noexcept {
|
||||
nassertv(_pointer == nullptr);
|
||||
|
||||
_pointer = from._pointer;
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -62,23 +62,6 @@ CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> ©) :
|
|||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageWriter<CycleDataType>::
|
||||
operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
||||
nassertv(_pointer == nullptr);
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
_stage = copy._stage;
|
||||
|
||||
nassertv(_pointer != nullptr);
|
||||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* This flavor of the constructor elevates the pointer from the
|
||||
* CycleDataLockedStageReader from a read to a write pointer (and invalidates
|
||||
|
|
@ -128,6 +111,23 @@ CycleDataStageWriter(CycleDataStageWriter<CycleDataType> &&from) noexcept :
|
|||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageWriter<CycleDataType>::
|
||||
operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
||||
nassertv(_pointer == nullptr);
|
||||
nassertv(_current_thread == copy._current_thread);
|
||||
|
||||
_cycler = copy._cycler;
|
||||
_pointer = copy._pointer;
|
||||
_stage = copy._stage;
|
||||
|
||||
nassertv(_pointer != nullptr);
|
||||
_cycler->increment_write(_pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -227,6 +227,17 @@ CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> ©) :
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE CycleDataStageWriter<CycleDataType>::
|
||||
CycleDataStageWriter(CycleDataStageWriter<CycleDataType> &&from) noexcept :
|
||||
_pointer(from._pointer)
|
||||
{
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -236,6 +247,18 @@ operator = (const CycleDataStageWriter<CycleDataType> ©) {
|
|||
_pointer = copy._pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
template<class CycleDataType>
|
||||
INLINE void CycleDataStageWriter<CycleDataType>::
|
||||
operator = (CycleDataStageWriter<CycleDataType> &&from) noexcept {
|
||||
nassertv(_pointer == nullptr);
|
||||
|
||||
_pointer = from._pointer;
|
||||
from._pointer = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This flavor of the constructor elevates the pointer from the
|
||||
* CycleDataLockedStageReader from a read to a write pointer (and invalidates
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ call_python_func(PyObject *function, PyObject *args) {
|
|||
|
||||
} else {
|
||||
// No exception. Restore the thread state normally.
|
||||
PyThreadState *state = PyThreadState_Swap(orig_thread_state);
|
||||
PyThreadState_Swap(orig_thread_state);
|
||||
thread_states.push_back(new_thread_state);
|
||||
// PyThreadState_Clear(new_thread_state);
|
||||
// PyThreadState_Delete(new_thread_state);
|
||||
|
|
|
|||
|
|
@ -51,14 +51,6 @@ is_threading_supported() {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool ThreadSimpleImpl::
|
||||
is_true_threads() {
|
||||
return (is_os_threads != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ start(ThreadPriority priority, bool joinable) {
|
|||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Query the current Python thread state.
|
||||
_python_state = PyThreadState_Swap(nullptr);
|
||||
PyThreadState_Swap(_python_state);
|
||||
_python_state = thread_state_swap(nullptr);
|
||||
thread_state_swap(_python_state);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
init_thread_context(_context, _stack, _stack_size, st_begin_thread, this);
|
||||
|
|
@ -201,6 +201,14 @@ prepare_for_exit() {
|
|||
manager->prepare_for_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
bool ThreadSimpleImpl::
|
||||
is_true_threads() {
|
||||
return (is_os_threads != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -238,7 +246,7 @@ st_begin_thread(void *data) {
|
|||
void ThreadSimpleImpl::
|
||||
begin_thread() {
|
||||
#ifdef HAVE_PYTHON
|
||||
PyThreadState_Swap(_python_state);
|
||||
thread_state_swap(_python_state);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#ifdef HAVE_POSIX_THREADS
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
INLINE static void bind_thread(Thread *thread);
|
||||
INLINE static bool is_threading_supported();
|
||||
INLINE static bool is_true_threads();
|
||||
static bool is_true_threads();
|
||||
INLINE static bool is_simple_threads();
|
||||
INLINE static void sleep(double seconds);
|
||||
INLINE static void yield();
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
#include "mainThread.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -235,7 +237,7 @@ next_context() {
|
|||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Save the current Python thread state.
|
||||
_current_thread->_python_state = PyThreadState_Swap(nullptr);
|
||||
_current_thread->_python_state = thread_state_swap(nullptr);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
|
|
@ -256,7 +258,7 @@ next_context() {
|
|||
#endif // DO_PSTATS
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
PyThreadState_Swap(_current_thread->_python_state);
|
||||
thread_state_swap(_current_thread->_python_state);
|
||||
#endif // HAVE_PYTHON
|
||||
}
|
||||
|
||||
|
|
@ -468,16 +470,6 @@ init_pointers() {
|
|||
_pointers_initialized = true;
|
||||
_global_ptr = new ThreadSimpleManager;
|
||||
Thread::get_main_thread();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Ensure that the Python threading system is initialized and ready to go.
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03020000
|
||||
Py_Initialize();
|
||||
#endif
|
||||
|
||||
PyEval_InitThreads();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1010,61 +1010,6 @@ clear_glyph_shift() {
|
|||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the text that is displayed under the TextNode.
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
set_text(const std::string &text) {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::set_text(text);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* The two-parameter version of set_text() accepts an explicit encoding; the
|
||||
* text is immediately decoded and stored as a wide-character string.
|
||||
* Subsequent calls to get_text() will return the same text re-encoded using
|
||||
* whichever encoding is specified by set_encoding().
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
set_text(const std::string &text, TextNode::Encoding encoding) {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::set_text(text, encoding);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the text from the TextNode.
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
clear_text() {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::clear_text();
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the indicates string to the end of the stored text.
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
append_text(const std::string &text) {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::append_text(text);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a single character to the end of the stored text. This may be a
|
||||
* wide character, up to 16 bits in Unicode.
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
append_unicode_char(wchar_t character) {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::append_unicode_char(character);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that represents the contents of the text, as it has been
|
||||
* formatted by wordwrap rules.
|
||||
|
|
@ -1086,28 +1031,6 @@ calc_width(const std::string &line) const {
|
|||
return calc_width(decode_text(line));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the text that is displayed under the TextNode, with a wide text.
|
||||
* This automatically sets the string reported by get_text() to the 8-bit
|
||||
* encoded version of the same string.
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
set_wtext(const std::wstring &wtext) {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::set_wtext(wtext);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the indicates string to the end of the stored wide-character text.
|
||||
*/
|
||||
INLINE void TextNode::
|
||||
append_wtext(const std::wstring &wtext) {
|
||||
MutexHolder holder(_lock);
|
||||
TextEncoder::append_wtext(wtext);
|
||||
invalidate_with_measure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wstring that represents the contents of the text, as it has been
|
||||
* formatted by wordwrap rules.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue