Merge branch 'master' into cmake
This commit is contained in:
commit
58c065d970
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ 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;
|
||||
|
|
@ -283,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;
|
||||
|
|
@ -297,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.
|
||||
|
|
@ -312,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;
|
||||
}
|
||||
|
|
@ -326,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;
|
||||
|
|
@ -339,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':
|
||||
|
|
@ -356,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;
|
||||
|
|
@ -369,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;
|
||||
|
|
@ -382,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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
@ -78,21 +78,21 @@ PUBLISHED:
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -94,7 +94,12 @@ append_text(PyObject *text) {
|
|||
#if PY_VERSION_HEX >= 0x03030000
|
||||
Py_ssize_t len;
|
||||
const char *str = PyUnicode_AsUTF8AndSize(text, &len);
|
||||
_this->append_text(std::string(str, 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));
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -680,6 +680,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:
|
||||
|
|
@ -946,8 +949,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")
|
||||
|
|
@ -1334,9 +1335,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':
|
||||
|
|
@ -1596,6 +1598,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)
|
||||
|
||||
|
|
@ -3159,10 +3163,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')
|
||||
|
|
@ -3295,7 +3299,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')
|
||||
|
|
@ -3816,7 +3819,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"])
|
||||
|
|
@ -3875,6 +3878,31 @@ 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/display/
|
||||
#
|
||||
|
||||
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')
|
||||
|
||||
OPTS=['DIR:panda/src/display', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
|
||||
IGATEFILES.remove("renderBuffer.h")
|
||||
TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display'])
|
||||
TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"])
|
||||
TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx')
|
||||
TargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx')
|
||||
TargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx')
|
||||
|
||||
if RTDIST and GetTarget() == 'darwin':
|
||||
OPTS=['DIR:panda/src/display']
|
||||
TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
|
||||
TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/chan/
|
||||
#
|
||||
|
|
@ -3922,30 +3950,6 @@ if (not RUNTIME):
|
|||
TargetAdd('libp3dgraph.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph'])
|
||||
TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"])
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/display/
|
||||
#
|
||||
|
||||
if (not RUNTIME):
|
||||
OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
|
||||
TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
|
||||
TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
|
||||
|
||||
OPTS=['DIR:panda/src/display', 'PYTHON']
|
||||
IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
|
||||
IGATEFILES.remove("renderBuffer.h")
|
||||
TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
|
||||
TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display'])
|
||||
TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"])
|
||||
TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx')
|
||||
TargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx')
|
||||
TargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx')
|
||||
|
||||
if RTDIST and GetTarget() == 'darwin':
|
||||
OPTS=['DIR:panda/src/display']
|
||||
TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
|
||||
TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
|
||||
|
||||
#
|
||||
# DIRECTORY: panda/src/device/
|
||||
#
|
||||
|
|
@ -4167,6 +4171,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')
|
||||
|
|
@ -6346,21 +6351,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
#include "graphicsPipeSelection.cxx"
|
||||
#include "graphicsStateGuardian.cxx"
|
||||
#include "graphicsThreadingModel.cxx"
|
||||
#include "graphicsWindow.cxx"
|
||||
#include "graphicsWindowProc.cxx"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -5240,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;
|
||||
|
||||
|
|
@ -5304,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;
|
||||
}
|
||||
|
|
@ -5329,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)) {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -8925,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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -291,8 +291,8 @@ output(std::ostream &out) const {
|
|||
*/
|
||||
void TextNode::
|
||||
write(std::ostream &out, int indent_level) const {
|
||||
MutexHolder holder(_lock);
|
||||
PandaNode::write(out, indent_level);
|
||||
MutexHolder holder(_lock);
|
||||
TextProperties::write(out, indent_level + 2);
|
||||
indent(out, indent_level + 2)
|
||||
<< "transform is: " << *TransformState::make_mat(_transform) << "\n";
|
||||
|
|
|
|||
|
|
@ -778,9 +778,9 @@ register_twindow_class() {
|
|||
#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_wgl (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;
|
||||
|
||||
|
|
@ -842,7 +842,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;
|
||||
}
|
||||
|
|
@ -867,10 +867,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_wgl (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_wgl (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
|
||||
}
|
||||
|
||||
if (SetDeviceGammaRamp (hdc, ramp)) {
|
||||
|
|
|
|||
|
|
@ -293,13 +293,29 @@ set_properties_now(WindowProperties &properties) {
|
|||
_properties.set_fixed_size(properties.get_fixed_size());
|
||||
properties.clear_fixed_size();
|
||||
}
|
||||
// When switching undecorated mode, Windows will keep the window at the
|
||||
// current outer size, whereas we want to keep it with the configured
|
||||
// inner size. Store the current size and origin.
|
||||
LPoint2i top_left = _properties.get_origin();
|
||||
LPoint2i bottom_right = top_left + _properties.get_size();
|
||||
|
||||
DWORD window_style = make_style(_properties);
|
||||
SetWindowLong(_hWnd, GWL_STYLE, window_style);
|
||||
|
||||
// Now calculate the proper size and origin with the new window style.
|
||||
RECT view_rect;
|
||||
SetRect(&view_rect, top_left[0], top_left[1],
|
||||
bottom_right[0], bottom_right[1]);
|
||||
WINDOWINFO wi;
|
||||
GetWindowInfo(_hWnd, &wi);
|
||||
AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle);
|
||||
|
||||
// We need to call this to ensure that the style change takes effect.
|
||||
SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
|
||||
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE |
|
||||
SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
SetWindowPos(_hWnd, HWND_NOTOPMOST, view_rect.left, view_rect.top,
|
||||
view_rect.right - view_rect.left,
|
||||
view_rect.bottom - view_rect.top,
|
||||
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED |
|
||||
SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
if (properties.has_title()) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "eggBackPointer.h"
|
||||
|
||||
#include "pnotify.h"
|
||||
|
||||
|
||||
TypeHandle EggBackPointer::_type_handle;
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
|
||||
class EggJointPointer;
|
||||
class LMatrix4d;
|
||||
|
||||
/**
|
||||
* This class is used during joint optimization or restructuring to store the
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
|
||||
#include "eggJointData.h"
|
||||
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggJointNodePointer.h"
|
||||
#include "eggMatrixTablePointer.h"
|
||||
#include "pvector.h"
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@
|
|||
#include "eggJointNodePointer.h"
|
||||
|
||||
#include "dcast.h"
|
||||
#include "eggObject.h"
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggObject.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
*/
|
||||
|
||||
#include "eggMatrixTablePointer.h"
|
||||
|
||||
#include "dcast.h"
|
||||
#include "eggCharacterDb.h"
|
||||
#include "eggSAnimData.h"
|
||||
#include "eggXfmAnimData.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "textureImage.h"
|
||||
#include "palettizer.h"
|
||||
#include "paletteImage.h"
|
||||
#include "sourceTextureImage.h"
|
||||
|
||||
#include "indent.h"
|
||||
#include "datagram.h"
|
||||
|
|
|
|||
|
|
@ -1,55 +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 config_softegg.cxx
|
||||
* @author masad
|
||||
* @date 2003-09-25
|
||||
*/
|
||||
|
||||
#include "config_softegg.h"
|
||||
#include "softEggGroupUserData.h"
|
||||
#include "softNodeDesc.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_softegg);
|
||||
NotifyCategoryDef(softegg, ":soft");
|
||||
|
||||
ConfigureFn(config_softegg) {
|
||||
init_libsoftegg();
|
||||
}
|
||||
|
||||
// These control the default behavior of the softegg converter, but not
|
||||
// necessarily the default behavior of the soft2egg command-line tool (which
|
||||
// has its own defaults).
|
||||
|
||||
// Should we respect the Soft? double-sided flag (true) or ignore it and
|
||||
// assume everything is single-sided (false)?
|
||||
ConfigVariableBool soft_default_double_sided("soft-default-double-sided", false);
|
||||
|
||||
// Should we apply vertex color even when a texture is applied (true) or only
|
||||
// when no texture is applied or the vertex-color egg flag is set (false)?
|
||||
ConfigVariableBool soft_default_vertex_color("soft-default-vertex-color", true);
|
||||
|
||||
/**
|
||||
* Initializes the library. This must be called at least once before any of
|
||||
* the functions or classes in this library can be used. Normally it will be
|
||||
* called by the static initializers and need not be called explicitly, but
|
||||
* special cases exist.
|
||||
*/
|
||||
void
|
||||
init_libsoftegg() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
SoftEggGroupUserData::init_type();
|
||||
SoftNodeDesc::init_type();
|
||||
}
|
||||
|
|
@ -1,28 +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 config_softegg.h
|
||||
* @author masad
|
||||
* @date 2003-09-25
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_SOFTEGG_H
|
||||
#define CONFIG_SOFTEGG_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "configVariableBool.h"
|
||||
|
||||
NotifyCategoryDeclNoExport(softegg);
|
||||
|
||||
extern ConfigVariableBool soft_default_double_sided;
|
||||
extern ConfigVariableBool soft_default_vertex_color;
|
||||
|
||||
extern void init_libsoftegg();
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,44 +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 softEggGroupUserData.I
|
||||
* @author masad
|
||||
* @date 2003-09-25
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE SoftEggGroupUserData::
|
||||
SoftEggGroupUserData() {
|
||||
_vertex_color = false;
|
||||
_double_sided = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE SoftEggGroupUserData::
|
||||
SoftEggGroupUserData(const SoftEggGroupUserData ©) :
|
||||
EggUserData(copy),
|
||||
_vertex_color(copy._vertex_color),
|
||||
_double_sided(copy._double_sided)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE void SoftEggGroupUserData::
|
||||
operator = (const SoftEggGroupUserData ©) {
|
||||
EggUserData::operator = (copy);
|
||||
_vertex_color = copy._vertex_color;
|
||||
_double_sided = copy._double_sided;
|
||||
}
|
||||
|
|
@ -1,16 +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 softEggGroupUserData.cxx
|
||||
* @author masad
|
||||
* @date 2003-09-25
|
||||
*/
|
||||
|
||||
#include "softEggGroupUserData.h"
|
||||
|
||||
TypeHandle SoftEggGroupUserData::_type_handle;
|
||||
|
|
@ -1,53 +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 softEggGroupUserData.h
|
||||
* @author masad
|
||||
* @date 2003-09-25
|
||||
*/
|
||||
|
||||
#ifndef SOFTEGGGROUPUSERDATA_H
|
||||
#define SOFTEGGGROUPUSERDATA_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "eggUserData.h"
|
||||
|
||||
/**
|
||||
* This class contains extra user data which is piggybacked onto EggGroup
|
||||
* objects for the purpose of the softimage converter.
|
||||
*/
|
||||
class SoftEggGroupUserData : public EggUserData {
|
||||
public:
|
||||
INLINE SoftEggGroupUserData();
|
||||
INLINE SoftEggGroupUserData(const SoftEggGroupUserData ©);
|
||||
INLINE void operator = (const SoftEggGroupUserData ©);
|
||||
|
||||
bool _vertex_color;
|
||||
bool _double_sided;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
EggUserData::init_type();
|
||||
register_type(_type_handle, "SoftEggGroupUserData",
|
||||
EggUserData::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "softEggGroupUserData.I"
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,159 +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 softNodeDesc.h
|
||||
* @author masad
|
||||
* @date 2003-10-03
|
||||
*/
|
||||
|
||||
#ifndef SOFTNODEDESC_H
|
||||
#define SOFTNODEDESC_H
|
||||
|
||||
#ifdef _MIN
|
||||
#undef _MIN
|
||||
#endif
|
||||
#ifdef _MAX
|
||||
#undef _MAX
|
||||
#endif
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "eggVertex.h"
|
||||
#include "eggVertexPool.h"
|
||||
#include "referenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "namable.h"
|
||||
|
||||
#include <SAA.h>
|
||||
|
||||
class EggGroup;
|
||||
class EggTable;
|
||||
class EggXfmSAnim;
|
||||
|
||||
/**
|
||||
* Describes a single instance of a node aka element in the Soft scene graph,
|
||||
* relating it to the corresponding egg structures (e.g. node, group, or
|
||||
* table entry) that will be created.
|
||||
*/
|
||||
class SoftNodeDesc : public ReferenceCount, public Namable {
|
||||
public:
|
||||
SoftNodeDesc(SoftNodeDesc *parent=nullptr, const std::string &name = std::string());
|
||||
~SoftNodeDesc();
|
||||
|
||||
void set_parent(SoftNodeDesc *parent);
|
||||
void force_set_parent(SoftNodeDesc *parent);
|
||||
void set_model(SAA_Elem *model);
|
||||
bool has_model() const;
|
||||
SAA_Elem *get_model() const;
|
||||
|
||||
bool is_joint() const;
|
||||
bool is_junk() const;
|
||||
void set_joint();
|
||||
bool is_joint_parent() const;
|
||||
bool is_partial(char *search_prefix);
|
||||
|
||||
SoftNodeDesc *_parent;
|
||||
SoftNodeDesc *_parentJoint; // keep track of who is your parent joint
|
||||
typedef pvector< PT(SoftNodeDesc) > Children;
|
||||
Children _children;
|
||||
|
||||
private:
|
||||
void clear_egg();
|
||||
void mark_joint_parent();
|
||||
void check_joint_parent();
|
||||
void check_junk(bool parent_junk);
|
||||
void check_pseudo_joints(bool joint_above);
|
||||
|
||||
void set_parentJoint(SAA_Scene *scene, SoftNodeDesc *lastJoint);
|
||||
|
||||
SAA_ModelType type;
|
||||
|
||||
SAA_Elem *_model;
|
||||
|
||||
EggGroup *_egg_group;
|
||||
EggTable *_egg_table;
|
||||
EggXfmSAnim *_anim;
|
||||
|
||||
enum JointType {
|
||||
JT_none, // Not a joint.
|
||||
JT_joint, // An actual joint in Soft.
|
||||
JT_pseudo_joint, // Not a joint in Soft, but treated just like a
|
||||
// joint for the purposes of the converter.
|
||||
JT_joint_parent, // A parent or ancestor of a joint or pseudo joint.
|
||||
JT_junk, // originated from con-/fly-/car_rig/bars etc.
|
||||
};
|
||||
JointType _joint_type;
|
||||
|
||||
public:
|
||||
|
||||
char **texNameArray;
|
||||
int *uRepeat, *vRepeat;
|
||||
PN_stdfloat matrix[4][4];
|
||||
|
||||
const char *fullname;
|
||||
|
||||
int numTri;
|
||||
// int numShapes;
|
||||
int numTexLoc;
|
||||
int numTexGlb;
|
||||
int *numTexTri;
|
||||
|
||||
// if the node is a MNSRF
|
||||
int numNurbTexLoc;
|
||||
int numNurbTexGlb;
|
||||
int numNurbMats;
|
||||
|
||||
PN_stdfloat *uScale;
|
||||
PN_stdfloat *vScale;
|
||||
PN_stdfloat *uOffset;
|
||||
PN_stdfloat *vOffset;
|
||||
|
||||
SAA_Boolean valid;
|
||||
SAA_Boolean uv_swap;
|
||||
// SAA_Boolean visible;
|
||||
SAA_Elem *textures;
|
||||
SAA_Elem *materials;
|
||||
SAA_SubElem *triangles;
|
||||
SAA_GeomType gtype;
|
||||
|
||||
EggGroup *get_egg_group()const {return _egg_group;}
|
||||
|
||||
void get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global);
|
||||
void get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim, bool global);
|
||||
void load_poly_model(SAA_Scene *scene, SAA_ModelType type);
|
||||
void load_nurbs_model(SAA_Scene *scene, SAA_ModelType type);
|
||||
|
||||
void make_morph_table(PN_stdfloat time);
|
||||
void make_linear_morph_table(int numShapes, PN_stdfloat time);
|
||||
void make_weighted_morph_table(int numShapes, PN_stdfloat time);
|
||||
void make_expression_morph_table(int numShapes, PN_stdfloat time);
|
||||
|
||||
void make_vertex_offsets(int numShapes);
|
||||
int find_shape_vert(LPoint3d p3d, SAA_DVector *vertices, int numVert);
|
||||
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ReferenceCount::init_type();
|
||||
Namable::init_type();
|
||||
register_type(_type_handle, "SoftNodeDesc",
|
||||
ReferenceCount::get_class_type(),
|
||||
Namable::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class SoftNodeTree;
|
||||
};
|
||||
|
||||
class SoftToEggConverter;
|
||||
extern SoftToEggConverter stec;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,561 +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 softNodeTree.cxx
|
||||
* @author masad
|
||||
* @date 2003-09-26
|
||||
*/
|
||||
|
||||
// Includes
|
||||
|
||||
#include "softNodeTree.h"
|
||||
#include "softEggGroupUserData.h"
|
||||
#include "config_softegg.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
#include "eggData.h"
|
||||
#include "softToEggConverter.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <SAA.h>
|
||||
|
||||
using std::endl;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SoftNodeTree::
|
||||
SoftNodeTree() {
|
||||
_root = new SoftNodeDesc(nullptr, "----root");
|
||||
_root->fullname = "----root";
|
||||
_fps = 0.0;
|
||||
_use_prefix = 0;
|
||||
_search_prefix = nullptr;
|
||||
_egg_data = nullptr;
|
||||
_egg_root = nullptr;
|
||||
_skeleton_node = nullptr;
|
||||
}
|
||||
/**
|
||||
* Given an element, return a copy of the element's name WITHOUT prefix.
|
||||
*/
|
||||
char *SoftNodeTree::
|
||||
GetName( SAA_Scene *scene, SAA_Elem *element ) {
|
||||
int nameLen;
|
||||
char *name;
|
||||
|
||||
// get the name
|
||||
SAA_elementGetNameLength( scene, element, &nameLen );
|
||||
name = new char[++nameLen];
|
||||
SAA_elementGetName( scene, element, nameLen, name );
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an element, return a copy of the element's name complete with prefix.
|
||||
*/
|
||||
char *SoftNodeTree::
|
||||
GetFullName( SAA_Scene *scene, SAA_Elem *element )
|
||||
{
|
||||
int nameLen, prefixLen;
|
||||
char *name, *prefix;
|
||||
|
||||
// get the name length
|
||||
SAA_elementGetNameLength( scene, element, &nameLen );
|
||||
// get the prefix length
|
||||
SAA_elementGetPrefixLength( scene, element, &prefixLen );
|
||||
// allocate the array to hold name
|
||||
name = new char[++nameLen];
|
||||
// allocate the array to hold prefix and length + hyphen
|
||||
prefix = new char[++prefixLen + nameLen + 4];
|
||||
// get the name
|
||||
SAA_elementGetName( scene, element, nameLen, name );
|
||||
// get the prefix
|
||||
SAA_elementGetPrefix( scene, element, prefixLen, prefix );
|
||||
// add 'em together
|
||||
strcat(prefix, "-");
|
||||
strcat(prefix, name);
|
||||
|
||||
// return string
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an element, return a string containing the contents of its MODEL NOTE
|
||||
* entry
|
||||
*/
|
||||
char *SoftNodeTree::
|
||||
GetModelNoteInfo( SAA_Scene *scene, SAA_Elem *model ) {
|
||||
int size;
|
||||
char *modelNote = nullptr;
|
||||
SAA_Boolean bigEndian;
|
||||
|
||||
SAA_elementGetUserDataSize( scene, model, "MNOT", &size );
|
||||
|
||||
if ( size != 0 ) {
|
||||
// allocate modelNote string
|
||||
modelNote = new char[size + 1];
|
||||
|
||||
// get ModelNote data from this model
|
||||
SAA_elementGetUserData( scene, model, "MNOT", size,
|
||||
&bigEndian, (void *)modelNote );
|
||||
|
||||
// strip off newline, if present
|
||||
char *eol = (char *)memchr( modelNote, '\n', size );
|
||||
if ( eol != nullptr)
|
||||
*eol = '\0';
|
||||
else
|
||||
modelNote[size] = '\0';
|
||||
|
||||
softegg_cat.spam() << "\nmodelNote = " << modelNote << endl;
|
||||
}
|
||||
|
||||
return modelNote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string, return a copy of the string up to the first occurence of
|
||||
* '-'.
|
||||
*/
|
||||
char *SoftNodeTree::
|
||||
GetRootName( const char *name ) {
|
||||
const char *hyphen;
|
||||
char *root;
|
||||
int len;
|
||||
|
||||
hyphen = strchr( name, '-' );
|
||||
len = hyphen-name;
|
||||
|
||||
if ( (hyphen != nullptr) && len ) {
|
||||
root = new char[len+1];
|
||||
strncpy( root, name, len );
|
||||
root[len] = '\0';
|
||||
}
|
||||
else {
|
||||
root = new char[strlen(name)+1];
|
||||
strcpy( root, name );
|
||||
}
|
||||
return( root );
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks through the complete Soft hierarchy and builds up the corresponding
|
||||
* tree.
|
||||
*/
|
||||
bool SoftNodeTree::
|
||||
build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database) {
|
||||
SI_Error status;
|
||||
SoftNodeDesc *node;
|
||||
|
||||
// Get the entire Soft scene.
|
||||
int numModels;
|
||||
SAA_Elem *models;
|
||||
|
||||
SAA_sceneGetNbModels( &scene, &numModels );
|
||||
softegg_cat.spam() << "Scene has " << numModels << " model(s)...\n";
|
||||
|
||||
// This while loop walks through the entire Soft hierarchy, one node at a
|
||||
// time.
|
||||
bool all_ok = true;
|
||||
if ( numModels ) {
|
||||
// allocate array of models
|
||||
models = (SAA_Elem *) new SAA_Elem[numModels];
|
||||
if ( models != nullptr ) {
|
||||
if ((status = SAA_sceneGetModels( &scene, numModels, models )) != SI_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
for ( int i = 0; i < numModels; i++ ) {
|
||||
int level;
|
||||
status = SAA_elementGetHierarchyLevel( &scene, &models[i], &level );
|
||||
softegg_cat.spam() << "model[" << i << "]" << endl;
|
||||
softegg_cat.spam() << " level " << level << endl;
|
||||
softegg_cat.spam() << " status is " << status << "\n";
|
||||
|
||||
node = build_node(&scene, &models[i]);
|
||||
if (!level && node)
|
||||
node->set_parent(_root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
softegg_cat.spam() << "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n";
|
||||
|
||||
// check the nodes that are junk for animationartist control purposes
|
||||
_root->check_junk(false);
|
||||
|
||||
softegg_cat.spam() << "jpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjp\n";
|
||||
|
||||
// check the nodes that are parent of ancestors of a joint
|
||||
_root->check_joint_parent();
|
||||
|
||||
softegg_cat.spam() << "pppppppppppppppppppppppppppppppppppppppppppppppppppppppp\n";
|
||||
|
||||
// check the nodes that are pseudo joints
|
||||
_root->check_pseudo_joints(false);
|
||||
|
||||
softegg_cat.spam() << "========================================================\n";
|
||||
|
||||
// find _parentJoint for each node
|
||||
_root->set_parentJoint(&scene, nullptr);
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
#if 0
|
||||
/**
|
||||
* Walks through the selected subset of the Soft hierarchy (or the complete
|
||||
* hierarchy, if nothing is selected) and builds up the corresponding tree.
|
||||
*/
|
||||
bool SoftNodeTree::
|
||||
build_selected_hierarchy(char *scene_name) {
|
||||
MStatus status;
|
||||
|
||||
MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
|
||||
if (!status) {
|
||||
status.perror("MItDag constructor");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get only the selected geometry.
|
||||
MSelectionList selection;
|
||||
status = MGlobal::getActiveSelectionList(selection);
|
||||
if (!status) {
|
||||
status.perror("MGlobal::getActiveSelectionList");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the selected geometry only if the selection is nonempty; otherwise,
|
||||
// get the whole scene anyway.
|
||||
if (selection.isEmpty()) {
|
||||
softegg_cat.info()
|
||||
<< "Selection list is empty.\n";
|
||||
return build_complete_hierarchy();
|
||||
}
|
||||
|
||||
bool all_ok = true;
|
||||
unsigned int length = selection.length();
|
||||
for (unsigned int i = 0; i < length; i++) {
|
||||
MDagPath root_path;
|
||||
status = selection.getDagPath(i, root_path);
|
||||
if (!status) {
|
||||
status.perror("MSelectionList::getDagPath");
|
||||
} else {
|
||||
// Now traverse through the selected dag path and all nested dag paths.
|
||||
dag_iterator.reset(root_path);
|
||||
while (!dag_iterator.isDone()) {
|
||||
MDagPath dag_path;
|
||||
status = dag_iterator.getPath(dag_path);
|
||||
if (!status) {
|
||||
status.perror("MItDag::getPath");
|
||||
} else {
|
||||
build_node(dag_path);
|
||||
}
|
||||
|
||||
dag_iterator.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (all_ok) {
|
||||
_root->check_pseudo_joints(false);
|
||||
}
|
||||
|
||||
return all_ok;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Returns the total number of nodes in the hierarchy, not counting the root
|
||||
* node.
|
||||
*/
|
||||
int SoftNodeTree::
|
||||
get_num_nodes() const {
|
||||
return _nodes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nth node in the hierarchy, in an arbitrary ordering.
|
||||
*/
|
||||
SoftNodeDesc *SoftNodeTree::
|
||||
get_node(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_nodes.size(), nullptr);
|
||||
return _nodes[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node named 'name' in the hierarchy, in an arbitrary ordering.
|
||||
*/
|
||||
SoftNodeDesc *SoftNodeTree::
|
||||
get_node(std::string name) const {
|
||||
NodesByName::const_iterator ni = _nodes_by_name.find(name);
|
||||
if (ni != _nodes_by_name.end())
|
||||
return (*ni).second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the references to generated egg structures from the tree,
|
||||
* and prepares the tree for generating new egg structures.
|
||||
*/
|
||||
void SoftNodeTree::
|
||||
clear_egg(EggData *egg_data, EggGroupNode *egg_root,
|
||||
EggGroupNode *skeleton_node) {
|
||||
_root->clear_egg();
|
||||
_egg_data = egg_data;
|
||||
_egg_root = egg_root;
|
||||
_skeleton_node = skeleton_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the EggGroupNode corresponding to the group or joint for the
|
||||
* indicated node. Creates the group node if it has not already been created.
|
||||
*/
|
||||
EggGroup *SoftNodeTree::
|
||||
get_egg_group(SoftNodeDesc *node_desc) {
|
||||
nassertr(_egg_root != nullptr, nullptr);
|
||||
|
||||
// lets print some relationship
|
||||
softegg_cat.spam() << " group " << node_desc->get_name() << "(" << node_desc->_egg_group << ")";
|
||||
if (node_desc->_parent)
|
||||
softegg_cat.spam() << " parent " << node_desc->_parent->get_name() << "(" << node_desc->_parent << ")";
|
||||
else
|
||||
softegg_cat.spam() << " parent " << node_desc->_parent;
|
||||
softegg_cat.spam() << endl;
|
||||
|
||||
if (node_desc->_egg_group == nullptr) {
|
||||
// We need to make a new group node.
|
||||
EggGroup *egg_group;
|
||||
|
||||
egg_group = new EggGroup(node_desc->get_name());
|
||||
if (node_desc->is_joint()) {
|
||||
egg_group->set_group_type(EggGroup::GT_joint);
|
||||
}
|
||||
|
||||
if (stec.flatten || (!node_desc->_parentJoint || node_desc->_parentJoint == _root)) {
|
||||
// The parent is the root.
|
||||
softegg_cat.spam() << "came hereeeee\n";
|
||||
_egg_root->add_child(egg_group);
|
||||
} else {
|
||||
// The parent is another node.
|
||||
EggGroup *parent_egg_group = get_egg_group(node_desc->_parentJoint);
|
||||
parent_egg_group->add_child(egg_group);
|
||||
}
|
||||
|
||||
node_desc->_egg_group = egg_group;
|
||||
}
|
||||
|
||||
return node_desc->_egg_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the EggTable corresponding to the joint for the indicated node.
|
||||
* Creates the table node if it has not already been created.
|
||||
*/
|
||||
EggTable *SoftNodeTree::
|
||||
get_egg_table(SoftNodeDesc *node_desc) {
|
||||
nassertr(_skeleton_node != nullptr, nullptr);
|
||||
nassertr(node_desc->is_joint(), nullptr);
|
||||
|
||||
// lets print some relationship
|
||||
softegg_cat.spam() << " group " << node_desc->get_name() << "(" << node_desc->_egg_group << ")";
|
||||
if (node_desc->_parent)
|
||||
softegg_cat.spam() << " parent " << node_desc->_parent->get_name() << "(" << node_desc->_parent << ")";
|
||||
else
|
||||
softegg_cat.spam() << " parent " << node_desc->_parent;
|
||||
softegg_cat.spam() << endl;
|
||||
|
||||
if (node_desc->_egg_table == nullptr) {
|
||||
softegg_cat.spam() << "creating a new table\n";
|
||||
// We need to make a new table node. nassertr(node_desc->_parent !=
|
||||
// (SoftNodeDesc *)NULL, NULL);
|
||||
|
||||
EggTable *egg_table = new EggTable(node_desc->get_name());
|
||||
node_desc->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
|
||||
node_desc->_anim->set_fps(_fps);
|
||||
egg_table->add_child(node_desc->_anim);
|
||||
|
||||
if (stec.flatten || (!node_desc->_parentJoint || node_desc->_parentJoint == _root)) {
|
||||
// if (!node_desc->_parent->is_joint()) { The parent is not a joint; put
|
||||
// it at the top.
|
||||
_skeleton_node->add_child(egg_table);
|
||||
} else {
|
||||
// The parent is another joint.
|
||||
EggTable *parent_egg_table = get_egg_table(node_desc->_parentJoint);
|
||||
parent_egg_table->add_child(egg_table);
|
||||
}
|
||||
|
||||
node_desc->_egg_table = egg_table;
|
||||
}
|
||||
|
||||
return node_desc->_egg_table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the anim table corresponding to the joint for the indicated node.
|
||||
* Creates the table node if it has not already been created.
|
||||
*/
|
||||
EggXfmSAnim *SoftNodeTree::
|
||||
get_egg_anim(SoftNodeDesc *node_desc) {
|
||||
get_egg_table(node_desc);
|
||||
return node_desc->_anim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets joint information for MNILL node
|
||||
*/
|
||||
void SoftNodeTree::
|
||||
handle_null(SAA_Scene *scene, SoftNodeDesc *node_desc, const char *node_name) {
|
||||
const char *name = node_name;
|
||||
SAA_AlgorithmType algo;
|
||||
SAA_Elem *model = node_desc->get_model();
|
||||
|
||||
SAA_modelGetAlgorithm( scene, model, &algo );
|
||||
softegg_cat.spam() << " null algorithm: " << algo << endl;
|
||||
|
||||
if ( algo == SAA_ALG_INV_KIN ) {
|
||||
// MakeJoint( &scene, lastJoint, lastAnim, model, name );
|
||||
node_desc->set_joint();
|
||||
softegg_cat.spam() << " encountered IK root: " << name << endl;
|
||||
}
|
||||
else if ( algo == SAA_ALG_INV_KIN_LEAF ) {
|
||||
// MakeJoint( &scene, lastJoint, lastAnim, model, name );
|
||||
node_desc->set_joint();
|
||||
softegg_cat.spam() << " encountered IK leaf: " << name << endl;
|
||||
}
|
||||
else if ( algo == SAA_ALG_STANDARD ) {
|
||||
SAA_Boolean isSkeleton = FALSE;
|
||||
softegg_cat.spam() << " encountered Standard null: " << name << endl;
|
||||
|
||||
SAA_modelIsSkeleton( scene, model, &isSkeleton );
|
||||
|
||||
// check to see if this NULL is used as a skeleton or is animated via
|
||||
// constraint only ( these nodes are tagged by the animator with the
|
||||
// keyword "joint" somewhere in the nodes name)
|
||||
if ( isSkeleton || (strstr( name, "joint" ) != nullptr) ) {
|
||||
// MakeJoint( &scene, lastJoint, lastAnim, model, name );
|
||||
node_desc->set_joint();
|
||||
softegg_cat.spam() << " animating Standard null!!!\n";
|
||||
softegg_cat.spam() << "isSkeleton: " << isSkeleton << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
softegg_cat.spam() << " encountered some other NULL: " << algo << endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the node corresponding to the indicated dag_path
|
||||
* object, creating it first if necessary.
|
||||
*/
|
||||
SoftNodeDesc *SoftNodeTree::
|
||||
build_node(SAA_Scene *scene, SAA_Elem *model) {
|
||||
char *name, *fullname;
|
||||
std::string node_name;
|
||||
int numChildren;
|
||||
int thisChild;
|
||||
SAA_Elem *children;
|
||||
SAA_ModelType type;
|
||||
SAA_Boolean isSkeleton = FALSE;
|
||||
|
||||
fullname = GetFullName(scene, model);
|
||||
if (_use_prefix)
|
||||
name = fullname;
|
||||
else
|
||||
name = GetName(scene, model);
|
||||
|
||||
node_name = name;
|
||||
|
||||
SoftNodeDesc *node_desc = r_build_node(nullptr, node_name);
|
||||
|
||||
node_desc->fullname = fullname;
|
||||
node_desc->set_model(model);
|
||||
SAA_modelIsSkeleton( scene, model, &isSkeleton );
|
||||
|
||||
// find out what type of node we're dealing with
|
||||
SAA_modelGetType( scene, node_desc->get_model(), &type );
|
||||
|
||||
if (type == SAA_MJNT || isSkeleton || (strstr(node_desc->get_name().c_str(), "joint") != nullptr))
|
||||
node_desc->set_joint();
|
||||
|
||||
// treat the MNILL differently, because it needs to detect and set some
|
||||
// joints
|
||||
if (type == SAA_MNILL)
|
||||
handle_null(scene, node_desc, name);
|
||||
|
||||
if (node_desc->is_joint())
|
||||
softegg_cat.spam() << "type: " << type << " isSkeleton: " << isSkeleton << endl;
|
||||
|
||||
// get to the children
|
||||
SAA_modelGetNbChildren( scene, model, &numChildren );
|
||||
softegg_cat.spam() << " Model " << node_name << " children: " << numChildren << endl;
|
||||
|
||||
if ( numChildren ) {
|
||||
children = new SAA_Elem[numChildren];
|
||||
SAA_modelGetChildren( scene, model, numChildren, children );
|
||||
if (!children)
|
||||
softegg_cat.info() << "Not enough Memory for children...\n";
|
||||
|
||||
for ( thisChild = 0; thisChild < numChildren; thisChild++ ) {
|
||||
fullname = GetFullName(scene, &children[thisChild]);
|
||||
if (_use_prefix)
|
||||
node_name = fullname;
|
||||
else
|
||||
node_name = GetName(scene, &children[thisChild]);
|
||||
|
||||
softegg_cat.spam() << " building child " << thisChild << "...";
|
||||
|
||||
SoftNodeDesc *node_child = r_build_node(node_desc, node_name);
|
||||
|
||||
node_child->fullname = fullname;
|
||||
node_child->set_model(&children[thisChild]);
|
||||
SAA_modelIsSkeleton( scene, &children[thisChild], &isSkeleton );
|
||||
|
||||
// find out what type of node we're dealing with
|
||||
SAA_modelGetType( scene, node_child->get_model(), &type );
|
||||
|
||||
if (type == SAA_MJNT || isSkeleton || (strstr(node_child->get_name().c_str(), "joint") != nullptr))
|
||||
node_child->set_joint();
|
||||
|
||||
// treat the MNILL differently, because it needs to detect and set some
|
||||
// joints
|
||||
if (type == SAA_MNILL)
|
||||
handle_null(scene, node_child, node_name.c_str());
|
||||
|
||||
if (node_child->is_joint())
|
||||
softegg_cat.spam() << "type: " << type << " isSkeleton: " << isSkeleton << endl;
|
||||
}
|
||||
}
|
||||
return node_desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* The recursive implementation of build_node().
|
||||
*/
|
||||
SoftNodeDesc *SoftNodeTree::
|
||||
r_build_node(SoftNodeDesc *parent_node, const std::string &name) {
|
||||
SoftNodeDesc *node_desc;
|
||||
|
||||
// If we have already encountered this pathname, return the corresponding
|
||||
// SoftNodeDesc immediately.
|
||||
NodesByName::const_iterator ni = _nodes_by_name.find(name);
|
||||
if (ni != _nodes_by_name.end()) {
|
||||
softegg_cat.spam() << " already built node " << (*ni).first;
|
||||
node_desc = (*ni).second;
|
||||
node_desc->set_parent(parent_node);
|
||||
return node_desc;
|
||||
}
|
||||
|
||||
// Otherwise, we have to create it. Do this recursively, so we create each
|
||||
// node along the path.
|
||||
node_desc = new SoftNodeDesc(parent_node, name);
|
||||
|
||||
softegg_cat.spam() << " node name : " << name << endl;
|
||||
_nodes.push_back(node_desc);
|
||||
|
||||
_nodes_by_name.insert(NodesByName::value_type(name, node_desc));
|
||||
|
||||
return node_desc;
|
||||
}
|
||||
|
|
@ -1,78 +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 softNodeTree.h
|
||||
* @author masad
|
||||
* @date 2003-10-03
|
||||
*/
|
||||
|
||||
#ifndef SOFTNODETREE_H
|
||||
#define SOFTNODETREE_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "softNodeDesc.h"
|
||||
|
||||
#include <SAA.h>
|
||||
|
||||
class EggGroup;
|
||||
class EggTable;
|
||||
class EggXfmSAnim;
|
||||
class EggData;
|
||||
class EggGroupNode;
|
||||
|
||||
|
||||
/**
|
||||
* Describes a complete tree of soft nodes for conversion.
|
||||
*/
|
||||
class SoftNodeTree {
|
||||
public:
|
||||
SoftNodeTree();
|
||||
SoftNodeDesc *build_node(SAA_Scene *scene, SAA_Elem *model);
|
||||
bool build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database);
|
||||
void handle_null(SAA_Scene *scene, SoftNodeDesc *node_desc, const char *node_name);
|
||||
// bool build_selected_hierarchy(SAA_Scene *s, SAA_Database *d, char
|
||||
// *scene_name);
|
||||
|
||||
int get_num_nodes() const;
|
||||
SoftNodeDesc *get_node(int n) const;
|
||||
SoftNodeDesc *get_node(std::string name) const;
|
||||
|
||||
char *GetRootName(const char *);
|
||||
char *GetModelNoteInfo(SAA_Scene *, SAA_Elem *);
|
||||
char *GetName(SAA_Scene *scene, SAA_Elem *element);
|
||||
char *GetFullName(SAA_Scene *scene, SAA_Elem *element);
|
||||
|
||||
EggGroupNode *get_egg_root() {return _egg_root;}
|
||||
EggGroup *get_egg_group(SoftNodeDesc *node_desc);
|
||||
EggTable *get_egg_table(SoftNodeDesc *node_desc);
|
||||
EggXfmSAnim *get_egg_anim(SoftNodeDesc *node_desc);
|
||||
|
||||
void clear_egg(EggData *egg_data, EggGroupNode *egg_root, EggGroupNode *skeleton_node);
|
||||
|
||||
PT(SoftNodeDesc) _root;
|
||||
PN_stdfloat _fps;
|
||||
int _use_prefix;
|
||||
char *_search_prefix;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
EggData *_egg_data;
|
||||
EggGroupNode *_egg_root;
|
||||
EggGroupNode *_skeleton_node;
|
||||
|
||||
SoftNodeDesc *r_build_node(SoftNodeDesc *parent_node, const std::string &path);
|
||||
|
||||
typedef pmap<std::string, SoftNodeDesc *> NodesByName;
|
||||
NodesByName _nodes_by_name;
|
||||
|
||||
typedef pvector<SoftNodeDesc *> Nodes;
|
||||
Nodes _nodes;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,179 +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 softToEggConverter.h
|
||||
* @author masad
|
||||
* @date 2003-09-25
|
||||
*/
|
||||
|
||||
#ifndef SOFTTOEGGCONVERTER_H
|
||||
#define SOFTTOEGGCONVERTER_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "somethingToEggConverter.h"
|
||||
#include "softNodeTree.h"
|
||||
|
||||
#include "eggTextureCollection.h"
|
||||
#include "distanceUnit.h"
|
||||
#include "coordinateSystem.h"
|
||||
|
||||
#ifdef _MIN
|
||||
#undef _MIN
|
||||
#endif
|
||||
#ifdef _MAX
|
||||
#undef _MAX
|
||||
#endif
|
||||
|
||||
#include <SAA.h>
|
||||
#include <SI_macros.h>
|
||||
|
||||
class EggData;
|
||||
class EggGroup;
|
||||
class EggTable;
|
||||
class EggVertexPool;
|
||||
class EggNurbsCurve;
|
||||
class EggPrimitive;
|
||||
class EggXfmSAnim;
|
||||
class EggSAnimData;
|
||||
|
||||
|
||||
/**
|
||||
* This class supervises the construction of an EggData structure from a
|
||||
* single Softimage file, or from the data already in th cout << "egg name
|
||||
* = " << eggFilename << endl;e global Softimage model space.
|
||||
*
|
||||
*/
|
||||
class SoftToEggConverter : public SomethingToEggConverter {
|
||||
public:
|
||||
SoftToEggConverter(const std::string &program_name = "");
|
||||
SoftToEggConverter(const SoftToEggConverter ©);
|
||||
virtual ~SoftToEggConverter();
|
||||
|
||||
void Help();
|
||||
void Usage();
|
||||
void ShowOpts();
|
||||
|
||||
bool HandleGetopts(int &idx, int argc, char **argv);
|
||||
bool DoGetopts(int &argc, char **&argv);
|
||||
|
||||
SoftNodeDesc *find_node(std::string name);
|
||||
int *FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert );
|
||||
|
||||
virtual SomethingToEggConverter *make_copy();
|
||||
virtual std::string get_name() const;
|
||||
virtual std::string get_extension() const;
|
||||
|
||||
virtual bool convert_file(const Filename &filename);
|
||||
bool convert_soft(bool from_selection);
|
||||
bool open_api();
|
||||
void close_api();
|
||||
|
||||
private:
|
||||
bool convert_flip(double start_frame, double end_frame,
|
||||
double frame_inc, double output_frame_rate);
|
||||
|
||||
bool make_soft_skin();
|
||||
bool cleanup_soft_skin();
|
||||
bool convert_char_chan();
|
||||
bool convert_char_model();
|
||||
bool convert_hierarchy(EggGroupNode *egg_root);
|
||||
bool process_model_node(SoftNodeDesc *node_desc);
|
||||
|
||||
void make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type);
|
||||
void make_nurb_surface(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type);
|
||||
void add_knots( vector <double> &eggKnots, double *knots, int numKnots, SAA_Boolean closed, int degree );
|
||||
|
||||
void set_shader_attributes(SoftNodeDesc *node_desc, EggPrimitive &primitive, int idx);
|
||||
void apply_texture_properties(EggTexture &tex, int uRepeat, int vRepeat);
|
||||
|
||||
bool reparent_decals(EggGroupNode *egg_parent);
|
||||
|
||||
std::string _program_name;
|
||||
bool _from_selection;
|
||||
|
||||
SI_Error result;
|
||||
SAA_Elem model;
|
||||
SAA_Database database;
|
||||
|
||||
public:
|
||||
|
||||
SoftNodeTree _tree;
|
||||
|
||||
SAA_Scene scene;
|
||||
|
||||
char *_getopts;
|
||||
|
||||
// This is argv[0].
|
||||
const char *_commandName;
|
||||
|
||||
// This is the entire command line.
|
||||
char _commandLine[4096];
|
||||
|
||||
char *rsrc_path;
|
||||
char *database_name;
|
||||
char *scene_name;
|
||||
char *model_name;
|
||||
char *eggFileName;
|
||||
char *animFileName;
|
||||
char *eggGroupName;
|
||||
char *tex_path;
|
||||
char *tex_filename;
|
||||
char *search_prefix;
|
||||
|
||||
int nurbs_step;
|
||||
int anim_start;
|
||||
int anim_end;
|
||||
int anim_rate;
|
||||
int pose_frame;
|
||||
int verbose;
|
||||
int flatten;
|
||||
int shift_textures;
|
||||
int ignore_tex_offsets;
|
||||
int use_prefix;
|
||||
|
||||
bool foundRoot;
|
||||
bool geom_as_joint;
|
||||
bool make_anim;
|
||||
bool make_nurbs;
|
||||
bool make_poly;
|
||||
bool make_soft;
|
||||
bool make_morph;
|
||||
bool make_duv;
|
||||
bool make_dart;
|
||||
bool has_morph;
|
||||
bool make_pose;
|
||||
|
||||
|
||||
char *GetTextureName( SAA_Scene *scene, SAA_Elem *texture );
|
||||
|
||||
EggTextureCollection _textures;
|
||||
|
||||
bool _polygon_output;
|
||||
double _polygon_tolerance;
|
||||
|
||||
enum TransformType {
|
||||
TT_invalid,
|
||||
TT_all,
|
||||
TT_model,
|
||||
TT_dcs,
|
||||
TT_none,
|
||||
};
|
||||
TransformType _transform_type;
|
||||
|
||||
static TransformType string_transform_type(const std::string &arg);
|
||||
|
||||
typedef pvector<EggSAnimData *> MorphTable;
|
||||
MorphTable _morph_table;
|
||||
|
||||
EggTable *morph_node;
|
||||
EggSAnimData *find_morph_table(char *name);
|
||||
};
|
||||
|
||||
extern const int TEX_PER_MAT;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,588 +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 softCVS.cxx
|
||||
* @author drose
|
||||
* @date 2000-11-10
|
||||
*/
|
||||
|
||||
#include "softCVS.h"
|
||||
|
||||
#include "pnotify.h"
|
||||
#include "multifile.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using std::string;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SoftCVS::
|
||||
SoftCVS() {
|
||||
_cvs_binary = "cvs";
|
||||
|
||||
set_program_brief("prepare a SoftImage database directory for adding to CVS");
|
||||
set_program_description
|
||||
("softcvs is designed to prepare a directory hierarchy "
|
||||
"representing a SoftImage database for adding to CVS. "
|
||||
"First, it eliminates SoftImage's silly filename-based "
|
||||
"versioning system by renaming versioned filenames higher "
|
||||
"than 1-0 back to version 1-0. Then, it rolls up all the "
|
||||
"files for each scene except the texture images into a Panda "
|
||||
"multifile, which is added to CVS; the texture images are "
|
||||
"directly added to CVS where they are.\n\n"
|
||||
|
||||
"The reduction of hundreds of SoftImage files per scene down to one "
|
||||
"multifile and a handle of texture images should greatly improve "
|
||||
"the update and commit times of CVS.\n\n"
|
||||
|
||||
"You must run this from within the root of a SoftImage database "
|
||||
"directory; e.g. the directory that contains SCENES, PICTURES, MODELS, "
|
||||
"and so on.");
|
||||
|
||||
clear_runlines();
|
||||
add_runline("[opts]");
|
||||
|
||||
add_option
|
||||
("nc", "", 80,
|
||||
"Do not attempt to add newly-created files to CVS. The default "
|
||||
"is to add them.",
|
||||
&SoftCVS::dispatch_none, &_no_cvs);
|
||||
|
||||
add_option
|
||||
("cvs", "cvs_binary", 80,
|
||||
"Specify how to run the cvs program for adding newly-created files. "
|
||||
"The default is simply \"cvs\".",
|
||||
&SoftCVS::dispatch_string, nullptr, &_cvs_binary);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void SoftCVS::
|
||||
run() {
|
||||
// First, check for the scenes directory. If it doesn't exist, we must not
|
||||
// be in the root of a soft database.
|
||||
Filename scenes = "SCENES/.";
|
||||
if (!scenes.exists()) {
|
||||
nout << "No SCENES directory found; you are not in the root of a "
|
||||
"SoftImage database.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Also, if we're expecting to use CVS, make sure the CVS directory exists.
|
||||
Filename cvs_entries = "CVS/Entries";
|
||||
if (!_no_cvs && !cvs_entries.exists()) {
|
||||
nout << "You do not appear to be within a CVS-controlled source "
|
||||
"directory.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Scan all the files in the database.
|
||||
traverse_root();
|
||||
|
||||
// Collapse out the higher-versioned scene files.
|
||||
collapse_scene_files();
|
||||
|
||||
// Now determine which element files are actually referenced by at least one
|
||||
// of the scene files.
|
||||
if (!get_scenes()) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Finally, remove all the element files that are no longer referenced by
|
||||
// any scenes.
|
||||
remove_unused_elements();
|
||||
|
||||
// Now do all the cvs adding and removing we need.
|
||||
if (!_no_cvs) {
|
||||
cvs_add_or_remove("remove", _cvs_remove);
|
||||
cvs_add_or_remove("add -kb", _cvs_add);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all of the toplevel directory names, e.g. SCENES, MATERIALS, etc.,
|
||||
* and traverses them.
|
||||
*/
|
||||
void SoftCVS::
|
||||
traverse_root() {
|
||||
Filename root(".");
|
||||
|
||||
// Get the list of subdirectories.
|
||||
vector_string subdirs;
|
||||
if (!root.scan_directory(subdirs)) {
|
||||
nout << "Unable to scan directory.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
vector_string::const_iterator di;
|
||||
for (di = subdirs.begin(); di != subdirs.end(); ++di) {
|
||||
Filename subdir = (*di);
|
||||
if (subdir.is_directory() && subdir != "CVS") {
|
||||
traverse_subdir(subdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the directory indicated by prefix and identifies all of the SoftImage
|
||||
* files stored there.
|
||||
*/
|
||||
void SoftCVS::
|
||||
traverse_subdir(const Filename &directory) {
|
||||
// Get the list of files in the directory.
|
||||
vector_string files;
|
||||
if (!directory.scan_directory(files)) {
|
||||
nout << "Unable to scan directory " << directory << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to know the set of files in this directory that are CVS elements.
|
||||
pset<string> cvs_elements;
|
||||
bool in_cvs = false;
|
||||
if (!_no_cvs) {
|
||||
in_cvs = scan_cvs(directory, cvs_elements);
|
||||
}
|
||||
|
||||
bool is_scenes = false;
|
||||
bool keep_all = false;
|
||||
bool wants_cvs = false;
|
||||
|
||||
// Now make some special-case behavior based on the particular SoftImage
|
||||
// subdirectory we're in.
|
||||
string dirname = directory.get_basename();
|
||||
if (dirname == "SCENES") {
|
||||
is_scenes = true;
|
||||
|
||||
} else if (dirname == "CAMERAS") {
|
||||
// We don't want anything in the cameras directory. These may change
|
||||
// arbitrarily and have no bearing on the model or animation that we will
|
||||
// extract, so avoid them altogether.
|
||||
return;
|
||||
|
||||
} else if (dirname == "PICTURES") {
|
||||
// In the pictures directory, we must keep everything, since the scene
|
||||
// files don't explicitly reference these but they're still important.
|
||||
// Textures that are no longer used will pile up; we leave this as the
|
||||
// user's problem.
|
||||
|
||||
// We not only keep the textures, but we also move them into CVS, since
|
||||
// (again) they're not part of the scene files and thus won't get added to
|
||||
// the multifiles. Also, some textures are shared between different
|
||||
// scenes, and it would be wasteful to add them to each scene multifile;
|
||||
// furthermore, some scenes are used for animation only, and we don't want
|
||||
// to modify these multifiles when the textures change.
|
||||
|
||||
keep_all = true;
|
||||
wants_cvs = !_no_cvs;
|
||||
}
|
||||
|
||||
vector_string::const_iterator fi;
|
||||
for (fi = files.begin(); fi != files.end(); ++fi) {
|
||||
const string &filename = (*fi);
|
||||
if (filename == "CVS") {
|
||||
// This special filename is not to be considered.
|
||||
|
||||
} else if (filename == "Chapter.rsrc") {
|
||||
// This special filename should not be considered, except to add it to
|
||||
// the multifiles.
|
||||
_global_files.push_back(Filename(directory, filename));
|
||||
|
||||
} else {
|
||||
SoftFilename soft(directory, filename);
|
||||
|
||||
if (cvs_elements.count(filename) != 0) {
|
||||
// This file is known to be in CVS.
|
||||
soft.set_in_cvs(true);
|
||||
}
|
||||
|
||||
if (keep_all) {
|
||||
soft.increment_use_count();
|
||||
}
|
||||
if (wants_cvs && !in_cvs) {
|
||||
// Try to CVSify the directory.
|
||||
cvs_add(directory);
|
||||
in_cvs = true;
|
||||
}
|
||||
soft.set_wants_cvs(wants_cvs);
|
||||
|
||||
if (is_scenes && soft.has_version() && soft.get_extension() == ".dsc") {
|
||||
_scene_files.push_back(soft);
|
||||
} else {
|
||||
_element_files.insert(soft);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks through the list of scene files found, and renames the higher-
|
||||
* versioned ones to version 1-0, removing the intervening versions.
|
||||
*/
|
||||
void SoftCVS::
|
||||
collapse_scene_files() {
|
||||
// Get a copy of the scene files vector so we can modify it. Also empty out
|
||||
// the _scene_files at the same time so we can fill it up again.
|
||||
SceneFiles versions;
|
||||
versions.swap(_scene_files);
|
||||
|
||||
// And sort them into order so we can easily compare higher and lower
|
||||
// versions.
|
||||
sort(versions.begin(), versions.end());
|
||||
|
||||
SceneFiles::iterator vi;
|
||||
vi = versions.begin();
|
||||
while (vi != versions.end()) {
|
||||
SoftFilename &file = (*vi);
|
||||
|
||||
if (!file.is_1_0()) {
|
||||
// Here's a file that needs to be renamed. But first, identify all the
|
||||
// other versions of the same file.
|
||||
SceneFiles::iterator start_vi;
|
||||
start_vi = vi;
|
||||
while (vi != versions.end() && (*vi).is_same_file(file)) {
|
||||
++vi;
|
||||
}
|
||||
|
||||
rename_file(start_vi, vi);
|
||||
|
||||
} else {
|
||||
++vi;
|
||||
}
|
||||
|
||||
file.make_1_0();
|
||||
_scene_files.push_back(file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks through the list of scene files and looks for the set of element
|
||||
* files referenced by each one, updating multifile accordingly.
|
||||
*/
|
||||
bool SoftCVS::
|
||||
get_scenes() {
|
||||
bool okflag = true;
|
||||
|
||||
// We will be added the multifiles to CVS if they're not already added, so
|
||||
// we have to know which files are in CVS already.
|
||||
pset<string> cvs_elements;
|
||||
if (!_no_cvs) {
|
||||
scan_cvs(".", cvs_elements);
|
||||
}
|
||||
|
||||
SceneFiles::const_iterator vi;
|
||||
for (vi = _scene_files.begin(); vi != _scene_files.end(); ++vi) {
|
||||
const SoftFilename &sf = (*vi);
|
||||
Filename file(sf.get_dirname(), sf.get_filename());
|
||||
|
||||
file.set_text();
|
||||
std::ifstream in;
|
||||
if (!file.open_read(in)) {
|
||||
nout << "Unable to read " << file << "\n";
|
||||
} else {
|
||||
nout << "Scanning " << file << "\n";
|
||||
|
||||
Multifile multifile;
|
||||
Filename multifile_name = sf.get_base() + "mf";
|
||||
|
||||
if (!multifile.open_read_write(multifile_name)) {
|
||||
nout << "Unable to open " << multifile_name << " for updating.\n";
|
||||
okflag = false;
|
||||
|
||||
} else {
|
||||
if (!scan_scene_file(in, multifile)) {
|
||||
okflag = false;
|
||||
}
|
||||
|
||||
// Add all the global files to the multifile too. These probably
|
||||
// can't take compression (since in SoftImage they're just the
|
||||
// Chapter.rsrc files, each very tiny).
|
||||
vector_string::const_iterator gi;
|
||||
for (gi = _global_files.begin(); gi != _global_files.end(); ++gi) {
|
||||
if (multifile.update_subfile((*gi), (*gi), 0).empty()) {
|
||||
nout << "Unable to add " << (*gi) << "\n";
|
||||
okflag = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Also add the scene file itself.
|
||||
if (multifile.update_subfile(file, file, 6).empty()) {
|
||||
nout << "Unable to add " << file << "\n";
|
||||
okflag = false;
|
||||
}
|
||||
|
||||
bool flushed = false;
|
||||
if (multifile.needs_repack()) {
|
||||
flushed = multifile.repack();
|
||||
} else {
|
||||
flushed = multifile.flush();
|
||||
}
|
||||
if (!flushed) {
|
||||
nout << "Failed to write " << multifile_name << ".\n";
|
||||
okflag = false;
|
||||
} else {
|
||||
nout << "Wrote " << multifile_name << ".\n";
|
||||
|
||||
if (!_no_cvs && cvs_elements.count(multifile_name) == 0) {
|
||||
// Add the multifile to CVS.
|
||||
_cvs_add.push_back(multifile_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return okflag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove all the element files that weren't referenced by any scene file.
|
||||
* Also plan to cvs add all those that were referenced.
|
||||
*/
|
||||
void SoftCVS::
|
||||
remove_unused_elements() {
|
||||
ElementFiles::const_iterator fi;
|
||||
for (fi = _element_files.begin(); fi != _element_files.end(); ++fi) {
|
||||
const SoftFilename &sf = (*fi);
|
||||
Filename file(sf.get_dirname(), sf.get_filename());
|
||||
|
||||
if (sf.get_use_count() == 0) {
|
||||
nout << file << " is unused.\n";
|
||||
|
||||
if (!file.unlink()) {
|
||||
nout << "Unable to remove " << file << ".\n";
|
||||
|
||||
} else if (sf.get_in_cvs()) {
|
||||
_cvs_remove.push_back(file);
|
||||
}
|
||||
|
||||
} else if (sf.get_wants_cvs() && !sf.get_in_cvs()) {
|
||||
_cvs_add.push_back(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Renames the first file in the indicated list to a version 1-0 filename,
|
||||
* superceding all the other files in the list. Returns true if the file is
|
||||
* renamed, false otherwise.
|
||||
*/
|
||||
bool SoftCVS::
|
||||
rename_file(SoftCVS::SceneFiles::iterator begin,
|
||||
SoftCVS::SceneFiles::iterator end) {
|
||||
int length = end - begin;
|
||||
nassertr(length > 0, false);
|
||||
|
||||
SoftFilename &orig = (*begin);
|
||||
|
||||
string dirname = orig.get_dirname();
|
||||
string source_filename = orig.get_filename();
|
||||
string dest_filename = orig.get_1_0_filename();
|
||||
|
||||
if (length > 2) {
|
||||
nout << source_filename << " supercedes:\n";
|
||||
SceneFiles::const_iterator p;
|
||||
for (p = begin + 1; p != end; ++p) {
|
||||
nout << " " << (*p).get_filename() << "\n";
|
||||
}
|
||||
|
||||
} else if (length == 2) {
|
||||
nout << source_filename << " supercedes "
|
||||
<< (*(begin + 1)).get_filename() << ".\n";
|
||||
|
||||
} else {
|
||||
nout << source_filename << " renamed.\n";
|
||||
}
|
||||
|
||||
// Now remove all of the "wrong" files.
|
||||
|
||||
SceneFiles::const_iterator p;
|
||||
for (p = begin + 1; p != end; ++p) {
|
||||
Filename file((*p).get_dirname(), (*p).get_filename());
|
||||
if (!file.unlink()) {
|
||||
nout << "Unable to remove " << file << ".\n";
|
||||
}
|
||||
}
|
||||
|
||||
// And rename the good one.
|
||||
Filename source(dirname, source_filename);
|
||||
Filename dest(dirname, dest_filename);
|
||||
|
||||
if (!source.rename_to(dest)) {
|
||||
nout << "Unable to rename " << source << " to " << dest_filename << ".\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the CVS repository in the indicated directory to determine which
|
||||
* files are already versioned elements. Returns true if the directory is
|
||||
* CVS-controlled, false otherwise.
|
||||
*/
|
||||
bool SoftCVS::
|
||||
scan_cvs(const string &dirname, pset<string> &cvs_elements) {
|
||||
Filename cvs_entries = dirname + "/CVS/Entries";
|
||||
if (!cvs_entries.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ifstream in;
|
||||
cvs_entries.set_text();
|
||||
if (!cvs_entries.open_read(in)) {
|
||||
nout << "Unable to read CVS directory.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
string line;
|
||||
std::getline(in, line);
|
||||
while (!in.fail() && !in.eof()) {
|
||||
if (!line.empty() && line[0] == '/') {
|
||||
size_t slash = line.find('/', 1);
|
||||
if (slash != string::npos) {
|
||||
string filename = line.substr(1, slash - 1);
|
||||
|
||||
if (line.substr(slash + 1, 2) == "-1") {
|
||||
// If the first number after the slash is -1, the file used to be
|
||||
// here but was recently cvs removed. It counts as no longer being
|
||||
// an element.
|
||||
} else {
|
||||
cvs_elements.insert(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::getline(in, line);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a scene file, looking for references to element files. For each
|
||||
* reference found, increments the appropriate element file's reference count.
|
||||
*/
|
||||
bool SoftCVS::
|
||||
scan_scene_file(std::istream &in, Multifile &multifile) {
|
||||
bool okflag = true;
|
||||
|
||||
int c = in.get();
|
||||
while (!in.eof() && !in.fail()) {
|
||||
// Skip whitespace.
|
||||
while (isspace(c) && !in.eof() && !in.fail()) {
|
||||
c = in.get();
|
||||
}
|
||||
|
||||
// Now begin a word.
|
||||
string word;
|
||||
while (!isspace(c) && !in.eof() && !in.fail()) {
|
||||
word += c;
|
||||
c = in.get();
|
||||
}
|
||||
|
||||
if (!word.empty()) {
|
||||
SoftFilename v("", word);
|
||||
|
||||
// Increment the use count on all matching elements of the multiset.
|
||||
std::pair<ElementFiles::iterator, ElementFiles::iterator> range;
|
||||
range = _element_files.equal_range(v);
|
||||
|
||||
ElementFiles::iterator ei;
|
||||
for (ei = range.first; ei != range.second; ++ei) {
|
||||
// We cheat and get a non-const reference to the filename out of the
|
||||
// set. We can safely do this because incrementing the use count
|
||||
// won't change its position in the set.
|
||||
SoftFilename &sf = (SoftFilename &)(*ei);
|
||||
sf.increment_use_count();
|
||||
|
||||
Filename file(sf.get_dirname(), sf.get_filename());
|
||||
if (multifile.update_subfile(file, file, 6).empty()) {
|
||||
nout << "Unable to add " << file << "\n";
|
||||
okflag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return okflag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes CVS to add just the named file to the repository. Returns true on
|
||||
* success, false on failure.
|
||||
*/
|
||||
bool SoftCVS::
|
||||
cvs_add(const string &path) {
|
||||
string command = _cvs_binary + " add -kb " + path;
|
||||
nout << command << "\n";
|
||||
int result = system(command.c_str());
|
||||
|
||||
if (result != 0) {
|
||||
nout << "Failure invoking cvs.\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes CVS to add (or remove) all of the files in the indicated vector.
|
||||
* Returns true on success, false on failure.
|
||||
*/
|
||||
bool SoftCVS::
|
||||
cvs_add_or_remove(const string &cvs_command, const vector_string &paths) {
|
||||
static const int max_command = 4096;
|
||||
|
||||
if (!paths.empty()) {
|
||||
string command = _cvs_binary + " " + cvs_command;
|
||||
vector_string::const_iterator pi;
|
||||
pi = paths.begin();
|
||||
while (pi != paths.end()) {
|
||||
const string &path = (*pi);
|
||||
|
||||
if ((int)command.length() + 1 + (int)path.length() >= max_command) {
|
||||
// Fire off the command now.
|
||||
nout << command << "\n";
|
||||
int result = system(command.c_str());
|
||||
|
||||
if (result != 0) {
|
||||
nout << "Failure invoking cvs.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
command = _cvs_binary + " " + cvs_command;
|
||||
}
|
||||
|
||||
command += ' ';
|
||||
command += path;
|
||||
|
||||
++pi;
|
||||
}
|
||||
nout << command << "\n";
|
||||
int result = system(command.c_str());
|
||||
|
||||
if (result != 0) {
|
||||
nout << "Failure invoking cvs.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
SoftCVS prog;
|
||||
prog.parse_command_line(argc, argv);
|
||||
prog.run();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,70 +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 softCVS.h
|
||||
* @author drose
|
||||
* @date 2000-11-10
|
||||
*/
|
||||
|
||||
#ifndef SOFTCVS_H
|
||||
#define SOFTCVS_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "softFilename.h"
|
||||
|
||||
#include "programBase.h"
|
||||
#include "vector_string.h"
|
||||
#include "filename.h"
|
||||
|
||||
#include "pvector.h"
|
||||
#include "pset.h"
|
||||
|
||||
class Multifile;
|
||||
|
||||
/**
|
||||
* This program prepares a SoftImage database for CVS by renaming everything
|
||||
* to version 1-0, and adding new files to CVS.
|
||||
*/
|
||||
class SoftCVS : public ProgramBase {
|
||||
public:
|
||||
SoftCVS();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
typedef pvector<SoftFilename> SceneFiles;
|
||||
typedef pmultiset<SoftFilename> ElementFiles;
|
||||
|
||||
void traverse_root();
|
||||
void traverse_subdir(const Filename &directory);
|
||||
|
||||
void collapse_scene_files();
|
||||
bool get_scenes();
|
||||
void remove_unused_elements();
|
||||
|
||||
bool rename_file(SceneFiles::iterator begin, SceneFiles::iterator end);
|
||||
bool scan_cvs(const std::string &dirname, pset<std::string> &cvs_elements);
|
||||
bool scan_scene_file(std::istream &in, Multifile &multifile);
|
||||
|
||||
bool cvs_add(const std::string &path);
|
||||
bool cvs_add_or_remove(const std::string &cvs_command,
|
||||
const vector_string &paths);
|
||||
|
||||
SceneFiles _scene_files;
|
||||
ElementFiles _element_files;
|
||||
vector_string _global_files;
|
||||
|
||||
vector_string _cvs_add;
|
||||
vector_string _cvs_remove;
|
||||
|
||||
bool _no_cvs;
|
||||
std::string _cvs_binary;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,291 +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 softFilename.cxx
|
||||
* @author drose
|
||||
* @date 2000-11-10
|
||||
*/
|
||||
|
||||
#include "softFilename.h"
|
||||
|
||||
#include "pnotify.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SoftFilename::
|
||||
SoftFilename(const string &dirname, const string &filename) :
|
||||
_dirname(dirname),
|
||||
_filename(filename)
|
||||
{
|
||||
_has_version = false;
|
||||
_major = 0;
|
||||
_minor = 0;
|
||||
_in_cvs = false;
|
||||
_wants_cvs = false;
|
||||
_use_count = 0;
|
||||
|
||||
_base = _filename;
|
||||
|
||||
// Scan for a version number and an optional extension after each dot in the
|
||||
// filename.
|
||||
size_t dot = _filename.find('.');
|
||||
while (dot != string::npos) {
|
||||
size_t m = dot + 1;
|
||||
const char *fstr = _filename.c_str();
|
||||
char *endptr;
|
||||
// Check for a numeric version number.
|
||||
int major = strtol(fstr + m , &endptr, 10);
|
||||
if (endptr != fstr + m && *endptr == '-') {
|
||||
// We got a major number, is there a minor number?
|
||||
m = (endptr - fstr) + 1;
|
||||
int minor = strtol(fstr + m, &endptr, 10);
|
||||
if (endptr != fstr + m && (*endptr == '.' || *endptr == '\0')) {
|
||||
// We got a minor number too!
|
||||
_has_version = true;
|
||||
_base = _filename.substr(0, dot + 1);
|
||||
_major = major;
|
||||
_minor = minor;
|
||||
_ext = endptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// That wasn't a version number. Is there more?
|
||||
dot = _filename.find('.', dot + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SoftFilename::
|
||||
SoftFilename(const SoftFilename ©) :
|
||||
_dirname(copy._dirname),
|
||||
_filename(copy._filename),
|
||||
_has_version(copy._has_version),
|
||||
_base(copy._base),
|
||||
_major(copy._major),
|
||||
_minor(copy._minor),
|
||||
_ext(copy._ext),
|
||||
_in_cvs(copy._in_cvs),
|
||||
_wants_cvs(copy._wants_cvs),
|
||||
_use_count(copy._use_count)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void SoftFilename::
|
||||
operator = (const SoftFilename ©) {
|
||||
_dirname = copy._dirname;
|
||||
_filename = copy._filename;
|
||||
_has_version = copy._has_version;
|
||||
_base = copy._base;
|
||||
_major = copy._major;
|
||||
_minor = copy._minor;
|
||||
_ext = copy._ext;
|
||||
_in_cvs = copy._in_cvs;
|
||||
_wants_cvs = copy._wants_cvs;
|
||||
_use_count = copy._use_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the directory this file was found in.
|
||||
*/
|
||||
const string &SoftFilename::
|
||||
get_dirname() const {
|
||||
return _dirname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual filename as found in the directory.
|
||||
*/
|
||||
const string &SoftFilename::
|
||||
get_filename() const {
|
||||
return _filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the filename had a version number, false otherwise.
|
||||
*/
|
||||
bool SoftFilename::
|
||||
has_version() const {
|
||||
return _has_version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns what the filename would be if it were version 1-0.
|
||||
*/
|
||||
string SoftFilename::
|
||||
get_1_0_filename() const {
|
||||
nassertr(_has_version, string());
|
||||
return _base + "1-0" + _ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base part of the filename. This is everything before the
|
||||
* version number.
|
||||
*/
|
||||
const string &SoftFilename::
|
||||
get_base() const {
|
||||
nassertr(_has_version, _filename);
|
||||
return _base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the major version number.
|
||||
*/
|
||||
int SoftFilename::
|
||||
get_major() const {
|
||||
nassertr(_has_version, 0);
|
||||
return _major;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minor version number.
|
||||
*/
|
||||
int SoftFilename::
|
||||
get_minor() const {
|
||||
nassertr(_has_version, 0);
|
||||
return _minor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension part of the filename. This is everything after the
|
||||
* version number.
|
||||
*/
|
||||
const string &SoftFilename::
|
||||
get_extension() const {
|
||||
nassertr(_has_version, _ext);
|
||||
return _ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename part, without the extension.
|
||||
*/
|
||||
string SoftFilename::
|
||||
get_non_extension() const {
|
||||
nassertr(_has_version, _filename);
|
||||
nassertr(_ext.length() < _filename.length(), _filename);
|
||||
return _filename.substr(0, _filename.length() - _ext.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a version 1_0 filename, false otherwise.
|
||||
*/
|
||||
bool SoftFilename::
|
||||
is_1_0() const {
|
||||
nassertr(_has_version, false);
|
||||
return (_major == 1 && _minor == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this a 1_0 filename.
|
||||
*/
|
||||
void SoftFilename::
|
||||
make_1_0() {
|
||||
_has_version = true;
|
||||
_major = 1;
|
||||
_minor = 0;
|
||||
_filename = get_1_0_filename();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this file has the same base and extension as the other,
|
||||
* disregarding the version number; false otherwise.
|
||||
*/
|
||||
bool SoftFilename::
|
||||
is_same_file(const SoftFilename &other) const {
|
||||
return _base == other._base && _ext == other._ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts filenames in order such that the files with the same base are sorted
|
||||
* together, ignoring extension; and within files with the same base, files
|
||||
* are sorted in decreasing version number order so that the most recent
|
||||
* version appears first.
|
||||
*/
|
||||
bool SoftFilename::
|
||||
operator < (const SoftFilename &other) const {
|
||||
if (_base != other._base) {
|
||||
return _base < other._base;
|
||||
}
|
||||
|
||||
if (_has_version != other._has_version) {
|
||||
// If one has a version and the other one doesn't, the one without a
|
||||
// version comes first.
|
||||
return _has_version < other._has_version;
|
||||
}
|
||||
|
||||
if (_has_version) {
|
||||
if (_major != other._major) {
|
||||
return _major > other._major;
|
||||
}
|
||||
if (_minor != other._minor) {
|
||||
return _minor > other._minor;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag that indicates whether this file is known to be entered into
|
||||
* the CVS database.
|
||||
*/
|
||||
void SoftFilename::
|
||||
set_in_cvs(bool in_cvs) {
|
||||
_in_cvs = in_cvs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this file is known to be entered in the CVS database, false
|
||||
* if it is not.
|
||||
*/
|
||||
bool SoftFilename::
|
||||
get_in_cvs() const {
|
||||
return _in_cvs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flag that indicates whether this file should be entered into the
|
||||
* CVS database.
|
||||
*/
|
||||
void SoftFilename::
|
||||
set_wants_cvs(bool wants_cvs) {
|
||||
_wants_cvs = wants_cvs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this file should be entered into the CVS database, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool SoftFilename::
|
||||
get_wants_cvs() const {
|
||||
return _wants_cvs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this filename is referenced by one more scene file.
|
||||
*/
|
||||
void SoftFilename::
|
||||
increment_use_count() {
|
||||
_use_count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of scene files that referenced this filename.
|
||||
*/
|
||||
int SoftFilename::
|
||||
get_use_count() const {
|
||||
return _use_count;
|
||||
}
|
||||
|
|
@ -1,73 +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 softFilename.h
|
||||
* @author drose
|
||||
* @date 2000-11-10
|
||||
*/
|
||||
|
||||
#ifndef SOFTFILENAME_H
|
||||
#define SOFTFILENAME_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
/**
|
||||
* This encapsulates a SoftImage versioned filename, of the form base.v-v.ext:
|
||||
* it consists of a directory name, a base, a major and minor version number,
|
||||
* and an optional extension.
|
||||
*
|
||||
* It also keeps track of whether the named file has been added to CVS, and
|
||||
* how many scene files it is referenced by,
|
||||
*/
|
||||
class SoftFilename {
|
||||
public:
|
||||
SoftFilename(const std::string &dirname, const std::string &filename);
|
||||
SoftFilename(const SoftFilename ©);
|
||||
void operator = (const SoftFilename ©);
|
||||
|
||||
const std::string &get_dirname() const;
|
||||
const std::string &get_filename() const;
|
||||
bool has_version() const;
|
||||
|
||||
std::string get_1_0_filename() const;
|
||||
|
||||
const std::string &get_base() const;
|
||||
int get_major() const;
|
||||
int get_minor() const;
|
||||
const std::string &get_extension() const;
|
||||
std::string get_non_extension() const;
|
||||
|
||||
bool is_1_0() const;
|
||||
void make_1_0();
|
||||
|
||||
bool is_same_file(const SoftFilename &other) const;
|
||||
bool operator < (const SoftFilename &other) const;
|
||||
|
||||
void set_in_cvs(bool in_cvs);
|
||||
bool get_in_cvs() const;
|
||||
|
||||
void set_wants_cvs(bool wants_cvs);
|
||||
bool get_wants_cvs() const;
|
||||
|
||||
void increment_use_count();
|
||||
int get_use_count() const;
|
||||
|
||||
private:
|
||||
std::string _dirname;
|
||||
std::string _filename;
|
||||
bool _has_version;
|
||||
std::string _base;
|
||||
int _major;
|
||||
int _minor;
|
||||
std::string _ext;
|
||||
bool _in_cvs;
|
||||
bool _wants_cvs;
|
||||
int _use_count;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include "eggTexture.h"
|
||||
#include "eggPrimitive.h"
|
||||
#include "datagram.h"
|
||||
#include "config_xfile.h"
|
||||
|
||||
#include <string.h> // for strcmp, strdup
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "xFileMesh.h"
|
||||
#include "xFileToEggConverter.h"
|
||||
#include "xFileFace.h"
|
||||
#include "xFileVertex.h"
|
||||
#include "xFileNormal.h"
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
#include "eggVertexPool.h"
|
||||
#include "eggVertex.h"
|
||||
#include "eggPolygon.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggGroupNode.h"
|
||||
|
||||
using std::min;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include "namable.h"
|
||||
#include "coordinateSystem.h"
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
class XFileNode;
|
||||
class XFileDataNode;
|
||||
class XFileMesh;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "eggData.h"
|
||||
#include "eggGroup.h"
|
||||
#include "eggTable.h"
|
||||
#include "eggXfmSAnim.h"
|
||||
#include "eggGroupUniquifier.h"
|
||||
#include "datagram.h"
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from _pytest.outcomes import Failed
|
|||
# The reset() function serves to prevent the _triggered variable from being
|
||||
# optimized out in the case that the assertions are being optimized out.
|
||||
GLSL_COMPUTE_TEMPLATE = """#version {version}
|
||||
{extensions}
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1) in;
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ void main() {{
|
|||
"""
|
||||
|
||||
|
||||
def run_glsl_test(gsg, body, preamble="", inputs={}, version=430):
|
||||
def run_glsl_test(gsg, body, preamble="", inputs={}, version=130, exts=set()):
|
||||
""" Runs a GLSL test on the given GSG. The given body is executed in the
|
||||
main function and should call assert(). The preamble should contain all
|
||||
of the shader inputs. """
|
||||
|
|
@ -48,11 +49,20 @@ def run_glsl_test(gsg, body, preamble="", inputs={}, version=430):
|
|||
if not gsg.supports_buffer_texture:
|
||||
pytest.skip("buffer textures not supported")
|
||||
|
||||
exts = exts | {'GL_ARB_compute_shader', 'GL_ARB_shader_image_load_store'}
|
||||
missing_exts = sorted(ext for ext in exts if not gsg.has_extension(ext))
|
||||
if missing_exts:
|
||||
pytest.skip("missing extensions: " + ' '.join(missing_exts))
|
||||
|
||||
extensions = ''
|
||||
for ext in exts:
|
||||
extensions += '#extension {ext} : require\n'.format(ext=ext)
|
||||
|
||||
__tracebackhide__ = True
|
||||
|
||||
preamble = preamble.strip()
|
||||
body = body.rstrip().lstrip('\n')
|
||||
code = GLSL_COMPUTE_TEMPLATE.format(version=version, preamble=preamble, body=body)
|
||||
code = GLSL_COMPUTE_TEMPLATE.format(version=version, extensions=extensions, preamble=preamble, body=body)
|
||||
line_offset = code[:code.find(body)].count('\n') + 1
|
||||
shader = core.Shader.make_compute(core.Shader.SL_GLSL, code)
|
||||
assert shader, code
|
||||
|
|
@ -122,7 +132,7 @@ def test_glsl_sampler(gsg):
|
|||
assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1));
|
||||
assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0));
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}), code
|
||||
run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
|
||||
|
||||
|
||||
def test_glsl_image(gsg):
|
||||
|
|
@ -142,7 +152,7 @@ def test_glsl_image(gsg):
|
|||
assert(imageLoad(tex1, 0) == vec4(0, 2 / 255.0, 1, 1));
|
||||
assert(imageLoad(tex2, ivec2(0, 0)) == vec4(1.0, 2.0, -3.14, 0.0));
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}), code
|
||||
run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
|
||||
|
||||
|
||||
def test_glsl_ssbo(gsg):
|
||||
|
|
@ -164,7 +174,10 @@ def test_glsl_ssbo(gsg):
|
|||
assert(value1 == 1234567);
|
||||
assert(value2 == -1234567);
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, {'buffer1': buffer1, 'buffer2': buffer2}), code
|
||||
run_glsl_test(gsg, code, preamble, {'buffer1': buffer1, 'buffer2': buffer2},
|
||||
exts={'GL_ARB_shader_storage_buffer_object',
|
||||
'GL_ARB_uniform_buffer_object',
|
||||
'GL_ARB_shading_language_420pack'})
|
||||
|
||||
|
||||
def test_glsl_int(gsg):
|
||||
|
|
@ -197,8 +210,8 @@ def test_glsl_uint(gsg):
|
|||
uniform uint intmax;
|
||||
"""
|
||||
code = """
|
||||
assert(zero == 0);
|
||||
assert(intmax == 0x7fffffff);
|
||||
assert(zero == 0u);
|
||||
assert(intmax == 0x7fffffffu);
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, inputs)
|
||||
|
||||
|
|
@ -243,7 +256,7 @@ def test_glsl_pta_int(gsg):
|
|||
assert(pta[2] == 2);
|
||||
assert(pta[3] == 3);
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, {'pta': pta}), code
|
||||
run_glsl_test(gsg, code, preamble, {'pta': pta})
|
||||
|
||||
|
||||
def test_glsl_pta_ivec4(gsg):
|
||||
|
|
@ -256,7 +269,7 @@ def test_glsl_pta_ivec4(gsg):
|
|||
assert(pta[0] == ivec4(0, 1, 2, 3));
|
||||
assert(pta[1] == ivec4(4, 5, 6, 7));
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, {'pta': pta}), code
|
||||
run_glsl_test(gsg, code, preamble, {'pta': pta})
|
||||
|
||||
|
||||
def test_glsl_pta_mat4(gsg):
|
||||
|
|
@ -278,7 +291,7 @@ def test_glsl_pta_mat4(gsg):
|
|||
assert(pta[1][2] == vec4(24, 25, 26, 27));
|
||||
assert(pta[1][3] == vec4(28, 29, 30, 31));
|
||||
"""
|
||||
run_glsl_test(gsg, code, preamble, {'pta': pta}), code
|
||||
run_glsl_test(gsg, code, preamble, {'pta': pta})
|
||||
|
||||
|
||||
def test_glsl_write_extract_image_buffer(gsg):
|
||||
|
|
@ -299,12 +312,12 @@ def test_glsl_write_extract_image_buffer(gsg):
|
|||
layout(r32i) uniform iimageBuffer tex2;
|
||||
"""
|
||||
code = """
|
||||
assert(imageLoad(tex1, 0).r == 0);
|
||||
assert(imageLoad(tex1, 0).r == 0u);
|
||||
assert(imageLoad(tex2, 0).r == 0);
|
||||
imageStore(tex1, 0, uvec4(123));
|
||||
imageStore(tex2, 0, ivec4(-456));
|
||||
memoryBarrier();
|
||||
assert(imageLoad(tex1, 0).r == 123);
|
||||
assert(imageLoad(tex1, 0).r == 123u);
|
||||
assert(imageLoad(tex2, 0).r == -456);
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from panda3d import core
|
||||
import pytest
|
||||
import threading
|
||||
import time
|
||||
import sys
|
||||
|
||||
|
|
@ -39,7 +38,11 @@ def test_future_timeout():
|
|||
fut.result(0.001)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not core.Thread.is_threading_supported(),
|
||||
reason="Threading support disabled")
|
||||
def test_future_wait():
|
||||
threading = pytest.importorskip("direct.stdpy.threading")
|
||||
|
||||
fut = core.AsyncFuture()
|
||||
|
||||
# Launch a thread to set the result value.
|
||||
|
|
@ -59,7 +62,11 @@ def test_future_wait():
|
|||
assert fut.result() is None
|
||||
|
||||
|
||||
@pytest.mark.skipif(not core.Thread.is_threading_supported(),
|
||||
reason="Threading support disabled")
|
||||
def test_future_wait_cancel():
|
||||
threading = pytest.importorskip("direct.stdpy.threading")
|
||||
|
||||
fut = core.AsyncFuture()
|
||||
|
||||
# Launch a thread to cancel the future.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,13 @@
|
|||
from panda3d import core
|
||||
|
||||
|
||||
def test_textnode_write():
|
||||
out = core.StringStream()
|
||||
text = core.TextNode("test")
|
||||
text.write(out, 0)
|
||||
assert out.data.startswith(b"TextNode test")
|
||||
|
||||
|
||||
def test_textnode_card_as_margin():
|
||||
text = core.TextNode("test")
|
||||
text.text = "Test"
|
||||
|
|
|
|||
Loading…
Reference in New Issue