optimize is_of_type(), in theory
This commit is contained in:
parent
06cb23cd73
commit
764aea593e
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "indent.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@
|
|||
#include "eggGroup.h"
|
||||
#include "eggBin.h"
|
||||
|
||||
#include <notify.h>
|
||||
#include "dcast.h"
|
||||
#include "notify.h"
|
||||
|
||||
TypeHandle EggBinMaker::_type_handle;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,12 @@
|
|||
#ifndef EGGPOLYSETMAKER_H
|
||||
#define EGGPOLYSETMAKER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "eggBinMaker.h"
|
||||
|
||||
#include "dcast.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : EggPolysetMaker
|
||||
// Description : A specialization on EggBinMaker for making polysets
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@
|
|||
#include "pt_EggTexture.h"
|
||||
#include "pt_EggMaterial.h"
|
||||
|
||||
#include <string_utils.h>
|
||||
#include <filename.h>
|
||||
#include <luse.h>
|
||||
#include <lmatrix.h>
|
||||
#include <coordinateSystem.h>
|
||||
|
||||
#include "string_utils.h"
|
||||
#include "filename.h"
|
||||
#include "luse.h"
|
||||
#include "lmatrix.h"
|
||||
#include "coordinateSystem.h"
|
||||
#include "pvector.h"
|
||||
#include "dcast.h"
|
||||
|
||||
// Because our token type contains objects of type string, which
|
||||
// require correct copy construction (and not simply memcpying), we
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
datagramGenerator.h datagramInputFile.I datagramInputFile.h \
|
||||
datagramIterator.I datagramIterator.h datagramOutputFile.I \
|
||||
datagramOutputFile.h datagramSink.I datagramSink.h \
|
||||
dcast.T dcast.h \
|
||||
error_utils.h \
|
||||
get_config_path.h hashGeneratorBase.I hashGeneratorBase.h \
|
||||
hashVal.I hashVal.h indent.I indent.h littleEndian.h \
|
||||
|
|
@ -31,10 +32,13 @@
|
|||
pointerToArray.I pointerToArray.h \
|
||||
profileTimer.I profileTimer.h \
|
||||
pta_uchar.h referenceCount.I referenceCount.h \
|
||||
register_type.I register_type.h \
|
||||
reversedNumericData.I reversedNumericData.h tokenBoard.I \
|
||||
tokenBoard.h trueClock.I trueClock.h typeHandle.I \
|
||||
typeHandle.h typedObject.I typedObject.h \
|
||||
typedReferenceCount.I typedReferenceCount.h typedef.h \
|
||||
typeRegistry.I typeRegistry.h \
|
||||
typeRegistryNode.I typeRegistryNode.h \
|
||||
vector_uchar.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
|
|
@ -47,10 +51,10 @@
|
|||
memoryInfo.cxx memoryUsage.cxx memoryUsagePointerCounts.cxx \
|
||||
memoryUsagePointers.cxx multifile.cxx namable.cxx \
|
||||
nativeNumericData.cxx profileTimer.cxx \
|
||||
pta_uchar.cxx referenceCount.cxx \
|
||||
pta_uchar.cxx referenceCount.cxx register_type.cxx \
|
||||
reversedNumericData.cxx trueClock.cxx typeHandle.cxx \
|
||||
typedObject.cxx typedReferenceCount.cxx \
|
||||
vector_uchar.cxx
|
||||
typeRegistry.cxx typeRegistryNode.cxx vector_uchar.cxx
|
||||
|
||||
#define IF_CRYPTO_SOURCES \
|
||||
crypto_utils.cxx crypto_utils.h \
|
||||
|
|
@ -63,7 +67,8 @@
|
|||
datagramGenerator.I datagramGenerator.h datagramInputFile.I \
|
||||
datagramInputFile.h datagramIterator.I datagramIterator.h \
|
||||
datagramOutputFile.I datagramOutputFile.h datagramSink.I \
|
||||
datagramSink.h error_utils.h get_config_path.h hashGeneratorBase.I \
|
||||
datagramSink.h dcast.T dcast.h \
|
||||
error_utils.h get_config_path.h hashGeneratorBase.I \
|
||||
hashGeneratorBase.h hashVal.I hashVal.h indent.I indent.h \
|
||||
littleEndian.h memoryInfo.I memoryInfo.h memoryUsage.I \
|
||||
memoryUsage.h memoryUsagePointerCounts.I \
|
||||
|
|
@ -73,11 +78,26 @@
|
|||
patchfile.I patchfile.h pointerTo.I pointerTo.h \
|
||||
pointerToArray.I pointerToArray.h profileTimer.I \
|
||||
profileTimer.h pta_uchar.h referenceCount.I referenceCount.h \
|
||||
register_type.I register_type.h \
|
||||
reversedNumericData.I reversedNumericData.h tokenBoard.I \
|
||||
tokenBoard.h trueClock.I trueClock.h typeHandle.I typeHandle.h \
|
||||
typedObject.I typedObject.h typedReferenceCount.I \
|
||||
typedReferenceCount.h typedef.h vector_uchar.h
|
||||
typedReferenceCount.h typedef.h \
|
||||
typeRegistry.I typeRegistry.h \
|
||||
typeRegistryNode.I typeRegistryNode.h \
|
||||
vector_uchar.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_types
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] express
|
||||
#define OTHER_LIBS pystub
|
||||
|
||||
#define SOURCES \
|
||||
test_types.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
// Filename: dcast.T
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast_get_typehandle
|
||||
// Description: Returns the TypeHandle associated with the type of
|
||||
// the parameter, if it can be determined. This is a
|
||||
// support function for _dcast, below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE TypeHandle
|
||||
_dcast_get_typehandle(WantType *) {
|
||||
TypeHandle handle = WantType::get_class_type();
|
||||
if (handle == TypeHandle::none()) {
|
||||
// This type handle is unregistered. Oops!
|
||||
WantType::init_type();
|
||||
handle = WantType::get_class_type();
|
||||
express_cat->warning()
|
||||
<< "Type " << handle << " was unregistered!\n";
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast
|
||||
// Description: The implementation of the DCAST macro, this checks
|
||||
// the actual type of the pointer before performing a
|
||||
// downcast operation. In NDEBUG mode, it simply
|
||||
// downcasts.
|
||||
//
|
||||
// This flavor of _dcast works on non-const pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE WantType *
|
||||
_dcast(WantType *, TypedObject *ptr) {
|
||||
#ifndef NDEBUG
|
||||
TypeHandle want_handle = _dcast_get_typehandle((WantType *)0);
|
||||
#if defined(_DEBUG) && defined(_WIN32)
|
||||
if ((ptr == (TypedObject *)NULL) || IsBadWritePtr(ptr,sizeof(TypedObject))) {
|
||||
#else
|
||||
if (ptr == (TypedObject *)NULL) {
|
||||
#endif
|
||||
express_cat->warning()
|
||||
<< "Attempt to cast NULL pointer to " << want_handle << "\n";
|
||||
return (WantType *)NULL;
|
||||
}
|
||||
if (!ptr->is_of_type(want_handle)) {
|
||||
express_cat->error()
|
||||
<< "Attempt to cast pointer from " << ptr->get_type()
|
||||
<< " to " << want_handle << "\n";
|
||||
if (ptr->get_type() == TypedObject::get_class_type()) {
|
||||
express_cat->error(false)
|
||||
<< "Perhaps pointer was inadvertently deleted?\n";
|
||||
}
|
||||
return (WantType *)NULL;
|
||||
}
|
||||
#endif
|
||||
return (WantType *)ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast
|
||||
// Description: The implementation of the DCAST macro, this checks
|
||||
// the actual type of the pointer before performing a
|
||||
// downcast operation. In NDEBUG mode, it simply
|
||||
// downcasts.
|
||||
//
|
||||
// This flavor of _dcast works on const pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE const WantType *
|
||||
_dcast(WantType *, const TypedObject *ptr) {
|
||||
#ifndef NDEBUG
|
||||
TypeHandle want_handle = _dcast_get_typehandle((WantType *)0);
|
||||
if (ptr == (const TypedObject *)NULL) {
|
||||
express_cat->warning()
|
||||
<< "Attempt to cast NULL pointer to " << want_handle << "\n";
|
||||
return (const WantType *)NULL;
|
||||
}
|
||||
if (!ptr->is_of_type(want_handle)) {
|
||||
express_cat->error()
|
||||
<< "Attempt to cast pointer from " << ptr->get_type()
|
||||
<< " to " << want_handle << "\n";
|
||||
if (ptr->get_type() == TypedObject::get_class_type()) {
|
||||
express_cat->error(false)
|
||||
<< "Perhaps pointer was inadvertently deleted?\n";
|
||||
}
|
||||
return (const WantType *)NULL;
|
||||
}
|
||||
#endif
|
||||
return (const WantType *)ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast_ref
|
||||
// Description: Similar to the above, with a pointer reference as the
|
||||
// first parameter. Just for fiddly compiler reasons;
|
||||
// the reference isn't used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE WantType *
|
||||
_dcast_ref(WantType *&, TypedObject *ptr) {
|
||||
return _dcast((WantType *)NULL, ptr);
|
||||
}
|
||||
|
||||
template<class WantType>
|
||||
INLINE const WantType *
|
||||
_dcast_ref(WantType *&, const TypedObject *ptr) {
|
||||
return _dcast((WantType *)NULL, ptr);
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// Filename: dcast.h
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DCAST_H
|
||||
#define DCAST_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typeHandle.h"
|
||||
#include "typedObject.h"
|
||||
|
||||
#if defined(_DEBUG) && defined(_WIN32)
|
||||
#include <windows.h> // for IsBadWritePtr()
|
||||
#endif
|
||||
|
||||
// The DCAST (downcast) macro is defined as a convenience for
|
||||
// downcasting from some TypedObject pointer (or a PointerTo). It's
|
||||
// just a normal C++-style downcast, except it first checks get_type()
|
||||
// to make sure the downcasting is safe. If you compile with NDEBUG,
|
||||
// this check is removed.
|
||||
|
||||
// DCAST will return NULL if the downcasting is unsafe. If you'd
|
||||
// rather it abort out of the function (ala nassertv/nassertr), then
|
||||
// see DCAST_INTO_V and DCAST_INTO_R, below.
|
||||
|
||||
template<class WantType>
|
||||
INLINE WantType *_dcast(WantType *, TypedObject *ptr);
|
||||
template<class WantType>
|
||||
INLINE const WantType *_dcast(WantType *, const TypedObject *ptr);
|
||||
|
||||
// Note: it is important that DCAST not repeat the pointer parameter,
|
||||
// since many users of DCAST may want to use the result of a function
|
||||
// as the pointer parameter, and it could be terribly confusing and
|
||||
// difficult to trace if the function were inadvertently executed
|
||||
// twice. This happened!
|
||||
#define DCAST(want_type, pointer) _dcast((want_type*)0, pointer)
|
||||
|
||||
// DCAST_INTO_V and DCAST_INTO_R are similar in purpose to DCAST,
|
||||
// except they: (a) automatically assign a variable instead of
|
||||
// returning the downcasted pointer, and (b) they immediately return
|
||||
// out of the function if the downcasting fails. DCAST_INTO_V is for
|
||||
// use in a void function and returns nothing; DCAST_INTO_R is for use
|
||||
// in a non-void function and returns the indicated value.
|
||||
|
||||
// Both DCAST_INTO_V and DCAST_INTO_R accept as the first parameter a
|
||||
// variable of type (want_type *) or (const want_type *), instead of
|
||||
// the name of the type. This variable will be filled with the new
|
||||
// pointer.
|
||||
|
||||
|
||||
// _dcast_ref is used to implement DCAST_INTO_V and DCAST_INTO_R. Its
|
||||
// difference from _dcast is that it takes a reference to a pointer as
|
||||
// a first parameter. The main point of this is to shut up the
|
||||
// compiler about pointers used before their value is assigned.
|
||||
template<class WantType>
|
||||
INLINE WantType *_dcast_ref(WantType *&, TypedObject *ptr);
|
||||
template<class WantType>
|
||||
INLINE const WantType *_dcast_ref(WantType *&, const TypedObject *ptr);
|
||||
|
||||
|
||||
#define DCAST_INTO_V(to_pointer, from_pointer) \
|
||||
{ \
|
||||
(to_pointer) = _dcast_ref(to_pointer, from_pointer); \
|
||||
nassertv((void *)(to_pointer) != (void *)NULL); \
|
||||
}
|
||||
|
||||
#define DCAST_INTO_R(to_pointer, from_pointer, return_value) \
|
||||
{ \
|
||||
(to_pointer) = _dcast_ref(to_pointer, from_pointer); \
|
||||
nassertr((void *)(to_pointer) != (void *)NULL, return_value); \
|
||||
}
|
||||
|
||||
#include "dcast.T"
|
||||
|
||||
#endif
|
||||
|
|
@ -5,10 +5,13 @@
|
|||
#include "profileTimer.cxx"
|
||||
#include "pta_uchar.cxx"
|
||||
#include "referenceCount.cxx"
|
||||
#include "register_type.cxx"
|
||||
#include "reversedNumericData.cxx"
|
||||
#include "trueClock.cxx"
|
||||
#include "typeHandle.cxx"
|
||||
#include "typedObject.cxx"
|
||||
#include "typedReferenceCount.cxx"
|
||||
#include "typeRegistry.cxx"
|
||||
#include "typeRegistryNode.cxx"
|
||||
#include "vector_uchar.cxx"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
// Filename: register_type.I
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_type
|
||||
// Description: This inline function is just a convenient way to call
|
||||
// TypeRegistry::register_type(), along with zero to four
|
||||
// record_derivation()s. If for some reason you have a
|
||||
// class that has more than four base classes (you're
|
||||
// insane!), then you will need to call Register() and
|
||||
// record_derivation() yourself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name) {
|
||||
TypeRegistry::ptr()->register_type(type_handle, name);
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
}
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
}
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
}
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent4);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_dynamic_type
|
||||
// Description: This is essentially similar to register_type(),
|
||||
// except that it doesn't store a reference to any
|
||||
// TypeHandle passed in and it therefore doesn't
|
||||
// complain if the type is registered more than once to
|
||||
// different TypeHandle reference.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name) {
|
||||
return TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name, TypeHandle parent1) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
return type_handle;
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
return type_handle;
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
return type_handle;
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent4);
|
||||
return type_handle;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// Filename: register_type.cxx
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "register_type.h"
|
||||
|
||||
|
||||
TypeHandle long_type_handle;
|
||||
TypeHandle int_type_handle;
|
||||
TypeHandle short_type_handle;
|
||||
TypeHandle char_type_handle;
|
||||
TypeHandle bool_type_handle;
|
||||
TypeHandle double_type_handle;
|
||||
TypeHandle float_type_handle;
|
||||
|
||||
TypeHandle long_p_type_handle;
|
||||
TypeHandle int_p_type_handle;
|
||||
TypeHandle short_p_type_handle;
|
||||
TypeHandle char_p_type_handle;
|
||||
TypeHandle bool_p_type_handle;
|
||||
TypeHandle double_p_type_handle;
|
||||
TypeHandle float_p_type_handle;
|
||||
TypeHandle void_p_type_handle;
|
||||
|
||||
void init_system_type_handles() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
done = true;
|
||||
register_type(long_type_handle, "long");
|
||||
register_type(int_type_handle, "int");
|
||||
register_type(short_type_handle, "short");
|
||||
register_type(char_type_handle, "char");
|
||||
register_type(bool_type_handle, "bool");
|
||||
register_type(double_type_handle, "double");
|
||||
register_type(float_type_handle, "float");
|
||||
|
||||
register_type(int_p_type_handle, "int*");
|
||||
register_type(short_p_type_handle, "short*");
|
||||
register_type(char_p_type_handle, "char*");
|
||||
register_type(bool_p_type_handle, "bool*");
|
||||
register_type(double_p_type_handle, "double*");
|
||||
register_type(float_p_type_handle, "float*");
|
||||
register_type(void_p_type_handle, "void*");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
// Filename: register_type.h
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef REGISTER_TYPE_H
|
||||
#define REGISTER_TYPE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typeHandle.h"
|
||||
#include "typeRegistry.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_type
|
||||
// Description: This inline function is just a convenient way to call
|
||||
// TypeRegistry::register_type(), along with zero to four
|
||||
// record_derivation()s. If for some reason you have a
|
||||
// class that has more than four base classes (you're
|
||||
// insane!), then you will need to call Register() and
|
||||
// record_derivation() yourself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_dynamic_type
|
||||
// Description: This is essentially similar to register_type(),
|
||||
// except that it doesn't store a reference to any
|
||||
// TypeHandle passed in and it therefore doesn't
|
||||
// complain if the type is registered more than once to
|
||||
// different TypeHandle reference.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name, TypeHandle parent1);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4);
|
||||
|
||||
|
||||
// A few system-wide TypeHandles are defined for some basic types.
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS long_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS int_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS short_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS char_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS bool_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS double_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS float_type_handle;
|
||||
|
||||
extern TypeHandle long_p_type_handle;
|
||||
extern TypeHandle int_p_type_handle;
|
||||
extern TypeHandle short_p_type_handle;
|
||||
extern TypeHandle char_p_type_handle;
|
||||
extern TypeHandle bool_p_type_handle;
|
||||
extern TypeHandle double_p_type_handle;
|
||||
extern TypeHandle float_p_type_handle;
|
||||
extern TypeHandle void_p_type_handle;
|
||||
|
||||
void EXPCL_PANDAEXPRESS init_system_type_handles();
|
||||
|
||||
// The following template function and its specializations will return
|
||||
// a TypeHandle for any type in the world, from a pointer to that
|
||||
// type.
|
||||
|
||||
template<class T>
|
||||
INLINE TypeHandle _get_type_handle(const T *) {
|
||||
return T::get_class_type();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const long *) {
|
||||
return long_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const int *) {
|
||||
return int_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const short *) {
|
||||
return short_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const char *) {
|
||||
return char_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const bool *) {
|
||||
return bool_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const double *) {
|
||||
return double_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const float *) {
|
||||
return float_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const long * const *) {
|
||||
return long_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const int * const *) {
|
||||
return int_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const short * const *) {
|
||||
return short_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const char * const *) {
|
||||
return char_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const bool * const *) {
|
||||
return bool_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const double * const *) {
|
||||
return double_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const float * const *) {
|
||||
return float_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const void * const *) {
|
||||
return void_p_type_handle;
|
||||
}
|
||||
|
||||
|
||||
// The macro get_type_handle(type) is defined to make getting the type
|
||||
// handle associated with a particular type a bit cleaner.
|
||||
#define get_type_handle(type) _get_type_handle((const type *)0)
|
||||
|
||||
|
||||
// The following template function and its specializations can be used
|
||||
// to call init() on any unknown type. Handy for use within a
|
||||
// template class.
|
||||
|
||||
template<class T>
|
||||
INLINE void _do_init_type(const T *) {
|
||||
T::init_type();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const long *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const int *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const short *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const char *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const bool *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const double *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const float *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const long * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const int * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const short * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const char * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const bool * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const double * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const float * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const void * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
#define do_init_type(type) _do_init_type((const type *)0)
|
||||
|
||||
#include "register_type.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -38,6 +38,7 @@ public:
|
|||
TypedObject::init_type();
|
||||
ReferenceCount::init_type();
|
||||
register_type(_type_handle, "ThatThingie",
|
||||
TypedObject::get_class_type(),
|
||||
ReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
|
|
@ -16,11 +16,6 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_express.h"
|
||||
|
||||
#if defined(_DEBUG) && defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
// In general, we use the express_cat->info() syntax in this file
|
||||
// (instead of express_cat.info()), because much of this work is done at
|
||||
|
|
@ -226,215 +221,3 @@ none() {
|
|||
return _none;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_type
|
||||
// Description: This inline function is just a convenient way to call
|
||||
// TypeRegistry::register_type(), along with zero to four
|
||||
// record_derivation()s. If for some reason you have a
|
||||
// class that has more than four base classes (you're
|
||||
// insane!), then you will need to call Register() and
|
||||
// record_derivation() yourself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name) {
|
||||
TypeRegistry::ptr()->register_type(type_handle, name);
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
}
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
}
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
}
|
||||
}
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4) {
|
||||
if (TypeRegistry::ptr()->register_type(type_handle, name)) {
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent4);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_dynamic_type
|
||||
// Description: This is essentially similar to register_type(),
|
||||
// except that it doesn't store a reference to any
|
||||
// TypeHandle passed in and it therefore doesn't
|
||||
// complain if the type is registered more than once to
|
||||
// different TypeHandle reference.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name) {
|
||||
return TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name, TypeHandle parent1) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
return type_handle;
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
return type_handle;
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
return type_handle;
|
||||
}
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4) {
|
||||
TypeHandle type_handle =
|
||||
TypeRegistry::ptr()->register_dynamic_type(name);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent1);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent2);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent3);
|
||||
TypeRegistry::ptr()->record_derivation(type_handle, parent4);
|
||||
return type_handle;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast_get_typehandle
|
||||
// Description: Returns the TypeHandle associated with the type of
|
||||
// the parameter, if it can be determined. This is a
|
||||
// support function for _dcast, below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE TypeHandle
|
||||
_dcast_get_typehandle(WantType *) {
|
||||
TypeHandle handle = WantType::get_class_type();
|
||||
if (handle == TypeHandle::none()) {
|
||||
// This type handle is unregistered. Oops!
|
||||
WantType::init_type();
|
||||
handle = WantType::get_class_type();
|
||||
express_cat->warning()
|
||||
<< "Type " << handle << " was unregistered!\n";
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast
|
||||
// Description: The implementation of the DCAST macro, this checks
|
||||
// the actual type of the pointer before performing a
|
||||
// downcast operation. In NDEBUG mode, it simply
|
||||
// downcasts.
|
||||
//
|
||||
// This flavor of _dcast works on non-const pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE WantType *
|
||||
_dcast(WantType *, TypedObject *ptr) {
|
||||
#ifndef NDEBUG
|
||||
TypeHandle want_handle = _dcast_get_typehandle((WantType *)0);
|
||||
#if defined(_DEBUG) && defined(_WIN32)
|
||||
if ((ptr == (TypedObject *)NULL) || IsBadWritePtr(ptr,sizeof(TypedObject))) {
|
||||
#else
|
||||
if (ptr == (TypedObject *)NULL) {
|
||||
#endif
|
||||
express_cat->warning()
|
||||
<< "Attempt to cast NULL pointer to " << want_handle << "\n";
|
||||
return (WantType *)NULL;
|
||||
}
|
||||
if (!ptr->is_of_type(want_handle)) {
|
||||
express_cat->error()
|
||||
<< "Attempt to cast pointer from " << ptr->get_type()
|
||||
<< " to " << want_handle << "\n";
|
||||
if (ptr->get_type() == TypedObject::get_class_type()) {
|
||||
express_cat->error(false)
|
||||
<< "Perhaps pointer was inadvertently deleted?\n";
|
||||
}
|
||||
return (WantType *)NULL;
|
||||
}
|
||||
#endif
|
||||
return (WantType *)ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast
|
||||
// Description: The implementation of the DCAST macro, this checks
|
||||
// the actual type of the pointer before performing a
|
||||
// downcast operation. In NDEBUG mode, it simply
|
||||
// downcasts.
|
||||
//
|
||||
// This flavor of _dcast works on const pointers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE const WantType *
|
||||
_dcast(WantType *, const TypedObject *ptr) {
|
||||
#ifndef NDEBUG
|
||||
TypeHandle want_handle = _dcast_get_typehandle((WantType *)0);
|
||||
if (ptr == (const TypedObject *)NULL) {
|
||||
express_cat->warning()
|
||||
<< "Attempt to cast NULL pointer to " << want_handle << "\n";
|
||||
return (const WantType *)NULL;
|
||||
}
|
||||
if (!ptr->is_of_type(want_handle)) {
|
||||
express_cat->error()
|
||||
<< "Attempt to cast pointer from " << ptr->get_type()
|
||||
<< " to " << want_handle << "\n";
|
||||
if (ptr->get_type() == TypedObject::get_class_type()) {
|
||||
express_cat->error(false)
|
||||
<< "Perhaps pointer was inadvertently deleted?\n";
|
||||
}
|
||||
return (const WantType *)NULL;
|
||||
}
|
||||
#endif
|
||||
return (const WantType *)ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: _dcast_ref
|
||||
// Description: Similar to the above, with a pointer reference as the
|
||||
// first parameter. Just for fiddly compiler reasons;
|
||||
// the reference isn't used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class WantType>
|
||||
INLINE WantType *
|
||||
_dcast_ref(WantType *&, TypedObject *ptr) {
|
||||
return _dcast((WantType *)NULL, ptr);
|
||||
}
|
||||
|
||||
template<class WantType>
|
||||
INLINE const WantType *
|
||||
_dcast_ref(WantType *&, const TypedObject *ptr) {
|
||||
return _dcast((WantType *)NULL, ptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,687 +17,6 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "typeHandle.h"
|
||||
#include "typedObject.h"
|
||||
#include "indent.h"
|
||||
#include "config_express.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// In general, we use the express_cat->info() syntax in this file
|
||||
// (instead of express_cat.info()), because much of this work is done at
|
||||
// static init time, and we must use the arrow syntax to force
|
||||
// initialization of the express_cat category.
|
||||
|
||||
TypeRegistry *TypeRegistry::_global_pointer = NULL;
|
||||
|
||||
// This is initialized to zero by static initialization.
|
||||
TypeHandle TypeHandle::_none;
|
||||
|
||||
|
||||
TypeHandle long_type_handle;
|
||||
TypeHandle int_type_handle;
|
||||
TypeHandle short_type_handle;
|
||||
TypeHandle char_type_handle;
|
||||
TypeHandle bool_type_handle;
|
||||
TypeHandle double_type_handle;
|
||||
TypeHandle float_type_handle;
|
||||
|
||||
TypeHandle long_p_type_handle;
|
||||
TypeHandle int_p_type_handle;
|
||||
TypeHandle short_p_type_handle;
|
||||
TypeHandle char_p_type_handle;
|
||||
TypeHandle bool_p_type_handle;
|
||||
TypeHandle double_p_type_handle;
|
||||
TypeHandle float_p_type_handle;
|
||||
TypeHandle void_p_type_handle;
|
||||
|
||||
void init_system_type_handles() {
|
||||
static bool done = false;
|
||||
if (!done) {
|
||||
done = true;
|
||||
register_type(long_type_handle, "long");
|
||||
register_type(int_type_handle, "int");
|
||||
register_type(short_type_handle, "short");
|
||||
register_type(char_type_handle, "char");
|
||||
register_type(bool_type_handle, "bool");
|
||||
register_type(double_type_handle, "double");
|
||||
register_type(float_type_handle, "float");
|
||||
|
||||
register_type(int_p_type_handle, "int*");
|
||||
register_type(short_p_type_handle, "short*");
|
||||
register_type(char_p_type_handle, "char*");
|
||||
register_type(bool_p_type_handle, "bool*");
|
||||
register_type(double_p_type_handle, "double*");
|
||||
register_type(float_p_type_handle, "float*");
|
||||
register_type(void_p_type_handle, "void*");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::RegistryNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistry::RegistryNode::
|
||||
RegistryNode(TypeHandle handle, const string &name, TypeHandle &ref) :
|
||||
_handle(handle), _name(name), _ref(ref) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::register_type
|
||||
// Access: Public
|
||||
// Description: Creates a new Type of the given name and assigns a
|
||||
// unique value to the type_handle. All type names must
|
||||
// be unique. If the type name has already been used,
|
||||
// the supplied type_handle value must match the name's
|
||||
// assigned type_handle or an error is triggered.
|
||||
// Returns true if the name wasn't defined before, false
|
||||
// if it was.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypeRegistry::
|
||||
register_type(TypeHandle &type_handle, const string &name) {
|
||||
if (type_handle != TypeHandle::none()) {
|
||||
// Here's a type that was already registered. Just make sure
|
||||
// everything's still kosher.
|
||||
RegistryNode *rnode = look_up(type_handle, NULL);
|
||||
if (&type_handle == &rnode->_ref) {
|
||||
// No problem.
|
||||
nassertr(rnode->_name == name, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NameRegistry::iterator ri;
|
||||
ri = _name_registry.find(name);
|
||||
|
||||
if (ri == _name_registry.end()) {
|
||||
// The name was not already used; this is the first time this
|
||||
// class has been defined.
|
||||
|
||||
#ifdef NOTIFY_DEBUG
|
||||
// This code runs at static init time, so cannot use the
|
||||
// express_cat.is_spam() syntax.
|
||||
if (express_cat->is_spam()) {
|
||||
express_cat->spam() << "Registering type " << name << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
TypeHandle new_handle;
|
||||
new_handle._index = _handle_registry.size();
|
||||
|
||||
RegistryNode *rnode = new RegistryNode(new_handle, name, type_handle);
|
||||
_handle_registry.push_back(rnode);
|
||||
_name_registry[name] = rnode;
|
||||
|
||||
type_handle = new_handle;
|
||||
return true;
|
||||
}
|
||||
RegistryNode *rnode = (*ri).second;
|
||||
nassertr(rnode->_name == (*ri).first, false);
|
||||
nassertr(rnode->_handle._index >= 0 &&
|
||||
rnode->_handle._index < (int)_handle_registry.size(), false);
|
||||
nassertr(_handle_registry[rnode->_handle._index] == rnode, false);
|
||||
nassertr(rnode->_handle._index != 0, false);
|
||||
|
||||
// The name was previously used; make sure the type_handle matches.
|
||||
if (&type_handle == &rnode->_ref) {
|
||||
// Ok, this was just a repeated attempt to register the same type.
|
||||
|
||||
if (type_handle == rnode->_handle) {
|
||||
// No problem.
|
||||
return false;
|
||||
}
|
||||
// But wait--the type_handle has changed! We kept a reference to
|
||||
// the static _type_handle member in the class that was passed in
|
||||
// at the first call to register_type(), and we got the same
|
||||
// reference passed in this time, but now it's different! Bad
|
||||
// juju.
|
||||
express_cat->error()
|
||||
<< "Reregistering " << name << "\n";
|
||||
type_handle == rnode->_handle;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type_handle != rnode->_handle) {
|
||||
// Hmm, we seem to have a contradictory type registration!
|
||||
express_cat->warning()
|
||||
<< "Attempt to register type " << name << " more than once!\n";
|
||||
|
||||
// This is invalid, but we'll allow it anyway. It seems to happen
|
||||
// for some reason under GNU libc5 that we occasionally end up
|
||||
// with two legitimate copies of the same class object in
|
||||
// memory--each with its own static _type_handle member.
|
||||
|
||||
type_handle = rnode->_handle;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::register_dynamic_type
|
||||
// Access: Public
|
||||
// Description: Registers a new type on-the-fly, presumably at
|
||||
// runtime. A new TypeHandle is returned if the
|
||||
// typename was not seen before; otherwise the same
|
||||
// TypeHandle that was last used for this typename is
|
||||
// returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
register_dynamic_type(const string &name) {
|
||||
NameRegistry::iterator ri;
|
||||
ri = _name_registry.find(name);
|
||||
|
||||
if (ri == _name_registry.end()) {
|
||||
// The name was not already used; this is the first time this
|
||||
// class has been defined.
|
||||
|
||||
#ifdef NOTIFY_DEBUG
|
||||
// This code runs at static init time, so cannot use the
|
||||
// express_cat.is_spam() syntax.
|
||||
if (express_cat->is_spam()) {
|
||||
express_cat->spam() << "Registering type " << name << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// We must dynamically allocate a new handle so the RegistryNode
|
||||
// has something unique to point to. This doesn't really mean
|
||||
// anything, though.
|
||||
TypeHandle *new_handle = new TypeHandle;
|
||||
new_handle->_index = _handle_registry.size();
|
||||
|
||||
RegistryNode *rnode = new RegistryNode(*new_handle, name, *new_handle);
|
||||
_handle_registry.push_back(rnode);
|
||||
_name_registry[name] = rnode;
|
||||
|
||||
return *new_handle;
|
||||
}
|
||||
|
||||
// Return the TypeHandle previously obtained.
|
||||
RegistryNode *rnode = (*ri).second;
|
||||
return rnode->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::record_derivation
|
||||
// Access: Public
|
||||
// Description: Records that the type referenced by child inherits
|
||||
// directly from the type referenced by parent. In the
|
||||
// event of multiple inheritance, this should be called
|
||||
// once for each parent class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
record_derivation(TypeHandle child, TypeHandle parent) {
|
||||
RegistryNode *cnode = look_up(child, NULL);
|
||||
nassertv(cnode != (RegistryNode *)NULL);
|
||||
RegistryNode *pnode = look_up(parent, NULL);
|
||||
nassertv(pnode != (RegistryNode *)NULL);
|
||||
|
||||
// First, we'll just run through the list to make sure we hadn't
|
||||
// already made this connection.
|
||||
RegistryNode::Classes::iterator ni;
|
||||
ni = find(cnode->_parent_classes.begin(), cnode->_parent_classes.end(),
|
||||
pnode);
|
||||
|
||||
if (ni == cnode->_parent_classes.end()) {
|
||||
cnode->_parent_classes.push_back(pnode);
|
||||
pnode->_child_classes.push_back(cnode);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::record_alternate_name
|
||||
// Access: Public
|
||||
// Description: Indicates an alternate name for the same type. This
|
||||
// is particularly useful when a type has changed names,
|
||||
// since the type is stored in a Bam file by name;
|
||||
// setting the original name as the alternate will allow
|
||||
// the type to be correctly read from old Bam files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
record_alternate_name(TypeHandle type, const string &name) {
|
||||
RegistryNode *rnode = look_up(type, (TypedObject *)NULL);
|
||||
if (rnode != (RegistryNode *)NULL) {
|
||||
NameRegistry::iterator ri =
|
||||
_name_registry.insert(NameRegistry::value_type(name, rnode)).first;
|
||||
if ((*ri).second != rnode) {
|
||||
express_cat.warning()
|
||||
<< "Name " << name << " already assigned to TypeHandle "
|
||||
<< rnode->_name << "; cannot reassign to " << type << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::find_type
|
||||
// Access: Public
|
||||
// Description: Looks for a previously-registered type of the given
|
||||
// name. Returns its TypeHandle if it exists, or
|
||||
// TypeHandle::none() if there is no such type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
find_type(const string &name) const {
|
||||
NameRegistry::const_iterator ri;
|
||||
ri = _name_registry.find(name);
|
||||
if (ri == _name_registry.end()) {
|
||||
return TypeHandle::none();
|
||||
} else {
|
||||
return (*ri).second->_handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the indicated type.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string TypeRegistry::
|
||||
get_name(TypeHandle type, TypedObject *object) const {
|
||||
RegistryNode *rnode = look_up(type, object);
|
||||
nassertr(rnode != (RegistryNode *)NULL, "");
|
||||
return rnode->_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::is_derived_from
|
||||
// Access: Public
|
||||
// Description: Returns true if the first type is derived from the
|
||||
// second type, false otherwise.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypeRegistry::
|
||||
is_derived_from(TypeHandle child, TypeHandle parent,
|
||||
TypedObject *child_object) const {
|
||||
RegistryNode *rnode = look_up(child, child_object);
|
||||
nassertr(rnode != (RegistryNode *)NULL, false);
|
||||
return rnode->is_derived_from(parent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_num_root_classes
|
||||
// Access: Public
|
||||
// Description: Returns the number of root classes--that is, classes
|
||||
// that do not inherit from any other classes--known in
|
||||
// the system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TypeRegistry::
|
||||
get_num_root_classes() {
|
||||
freshen_root_classes();
|
||||
return _root_classes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_root_class
|
||||
// Access: Public
|
||||
// Description: Returns the nth root class in the system. See
|
||||
// get_num_root_classes().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_root_class(int n) {
|
||||
freshen_root_classes();
|
||||
nassertr(n >= 0 && n < get_num_root_classes(), TypeHandle::none());
|
||||
return _root_classes[n]->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_num_parent_classes
|
||||
// Access: Public
|
||||
// Description: Returns the number of parent classes that the
|
||||
// indicated type is known to have. This may then be
|
||||
// used to index into get_parent_class(). The result
|
||||
// will be 0 if this class does not inherit from any
|
||||
// other classes, 1 if normal, single inheritance is in
|
||||
// effect, or greater than one if multiple inheritance
|
||||
// is in effect.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TypeRegistry::
|
||||
get_num_parent_classes(TypeHandle child, TypedObject *child_object) const {
|
||||
RegistryNode *rnode = look_up(child, child_object);
|
||||
nassertr(rnode != (RegistryNode *)NULL, 0);
|
||||
return rnode->_parent_classes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_parent_class
|
||||
// Access: Public
|
||||
// Description: Returns the nth parent class of this type. The index
|
||||
// should be in the range 0 <= index <
|
||||
// get_num_parent_classes().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_parent_class(TypeHandle child, int index) const {
|
||||
RegistryNode *rnode = look_up(child, (TypedObject *)NULL);
|
||||
nassertr(rnode != (RegistryNode *)NULL, TypeHandle::none());
|
||||
nassertr(index >= 0 && index < (int)rnode->_parent_classes.size(),
|
||||
TypeHandle::none());
|
||||
return rnode->_parent_classes[index]->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_num_child_classes
|
||||
// Access: Public
|
||||
// Description: Returns the number of child classes that the
|
||||
// indicated type is known to have. This may then be
|
||||
// used to index into get_child_class().
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TypeRegistry::
|
||||
get_num_child_classes(TypeHandle child, TypedObject *child_object) const {
|
||||
RegistryNode *rnode = look_up(child, child_object);
|
||||
nassertr(rnode != (RegistryNode *)NULL, 0);
|
||||
return rnode->_child_classes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_child_class
|
||||
// Access: Public
|
||||
// Description: Returns the nth child class of this type. The index
|
||||
// should be in the range 0 <= index <
|
||||
// get_num_child_classes().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_child_class(TypeHandle child, int index) const {
|
||||
RegistryNode *rnode = look_up(child, (TypedObject *)NULL);
|
||||
nassertr(rnode != (RegistryNode *)NULL, TypeHandle::none());
|
||||
nassertr(index >= 0 && index < (int)rnode->_child_classes.size(),
|
||||
TypeHandle::none());
|
||||
return rnode->_child_classes[index]->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_parent_towards
|
||||
// Access: Public
|
||||
// Description: Returns the parent of the indicated child class that
|
||||
// is in a direct line of inheritance to the indicated
|
||||
// ancestor class. This is useful in the presence of
|
||||
// multiple inheritance to try to determine what
|
||||
// properties an unknown type may have.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_parent_towards(TypeHandle child, TypeHandle ancestor,
|
||||
TypedObject *child_object) const {
|
||||
if (child_object != (TypedObject *)NULL) {
|
||||
// First, guarantee that the ancestor type is defined.
|
||||
look_up(ancestor, child_object);
|
||||
}
|
||||
RegistryNode *rnode = look_up(child, child_object);
|
||||
nassertr(rnode != (RegistryNode *)NULL, TypeHandle::none());
|
||||
return rnode->get_parent_towards(ancestor);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::reregister_types
|
||||
// Access: Public, Static
|
||||
// Description: Walks through the TypeRegistry tree and makes sure
|
||||
// that each type that was previously registered is
|
||||
// *still* registered. This seems to get broken in
|
||||
// certain circumstances when compiled against libc5--it
|
||||
// is as if the static initializer stomps on the
|
||||
// _type_handle values of each class after they've been
|
||||
// registered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
reregister_types() {
|
||||
HandleRegistry::iterator ri;
|
||||
TypeRegistry *reg = ptr();
|
||||
for (ri = reg->_handle_registry.begin();
|
||||
ri != reg->_handle_registry.end();
|
||||
++ri) {
|
||||
RegistryNode *rnode = (*ri);
|
||||
if (rnode != NULL && rnode->_handle != rnode->_ref) {
|
||||
express_cat->warning()
|
||||
<< "Reregistering " << rnode->_name << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::write
|
||||
// Access: Public
|
||||
// Description: Makes an attempt to format the entire TypeRegistry in
|
||||
// a nice way that shows the derivation tree as
|
||||
// intelligently as possible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
write(ostream &out) const {
|
||||
// Recursively write out the tree, starting from each node that has
|
||||
// no parent.
|
||||
HandleRegistry::const_iterator hi;
|
||||
for (hi = _handle_registry.begin();
|
||||
hi != _handle_registry.end();
|
||||
++hi) {
|
||||
const RegistryNode *root = *hi;
|
||||
if (root != NULL && root->_parent_classes.empty()) {
|
||||
write_node(out, 2, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::ptr
|
||||
// Access: Public, Static
|
||||
// Description: Returns the pointer to the global TypeRegistry
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistry *TypeRegistry::
|
||||
ptr() {
|
||||
if (_global_pointer == NULL) {
|
||||
init_global_pointer();
|
||||
}
|
||||
return _global_pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistry::
|
||||
TypeRegistry() {
|
||||
// We'll start out our handle_registry with a default entry for the
|
||||
// TypeHandles whose index number is zero, and are therefore
|
||||
// (probably) uninitialized.
|
||||
_handle_registry.push_back(NULL);
|
||||
|
||||
_root_classes_fresh = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::init_global_pointer
|
||||
// Access: Private, Static
|
||||
// Description: Constructs the TypeRegistry object for the first
|
||||
// time. It is initially created on the local heap,
|
||||
// then as soon as shared memory becomes available, it
|
||||
// should be moved into shared memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
init_global_pointer() {
|
||||
_global_pointer = new TypeRegistry;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::freshen_root_classes
|
||||
// Access: Private
|
||||
// Description: Walks through the list of types registered, and adds
|
||||
// any type known to be a root (that is, that derives
|
||||
// from no other types) to the set of known root
|
||||
// classes. This must be done from time to time because
|
||||
// we don't record this information when we initially
|
||||
// record the types.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
freshen_root_classes() {
|
||||
if (!_root_classes_fresh) {
|
||||
_root_classes.clear();
|
||||
|
||||
HandleRegistry::iterator hi;
|
||||
for (hi = _handle_registry.begin();
|
||||
hi != _handle_registry.end();
|
||||
++hi) {
|
||||
RegistryNode *root = *hi;
|
||||
if (root != NULL && root->_parent_classes.empty()) {
|
||||
_root_classes.push_back(root);
|
||||
}
|
||||
}
|
||||
_root_classes_fresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::write_node
|
||||
// Access: Private
|
||||
// Description: Writes a single RegistryNode out, along with all of
|
||||
// its descendants.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
write_node(ostream &out, int indent_level, const RegistryNode *node) const {
|
||||
indent(out, indent_level) << node->_handle.get_index() << " " << node->_name;
|
||||
if (!node->_parent_classes.empty()) {
|
||||
out << " : " << node->_parent_classes[0]->_name;
|
||||
for (int pi = 1; pi < (int)node->_parent_classes.size(); pi++) {
|
||||
out << ", " << node->_parent_classes[pi]->_name;
|
||||
}
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
for (int i = 0; i < (int)node->_child_classes.size(); i++) {
|
||||
write_node(out, indent_level + 2, node->_child_classes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::look_up
|
||||
// Access: Private
|
||||
// Description: Returns the RegistryNode associated with the
|
||||
// indicated TypeHandle. If there is no associated
|
||||
// RegistryNode, reports an error condition and aborts.
|
||||
//
|
||||
// The associated TypedObject pointer is the pointer to
|
||||
// the object that owns the handle, if available. It is
|
||||
// only used in an error condition, if for some reason
|
||||
// the handle was uninitialized.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistry::RegistryNode *TypeRegistry::
|
||||
look_up(TypeHandle handle, TypedObject *object) const {
|
||||
if (handle._index == 0) {
|
||||
// The TypeHandle is unregistered. This is an error condition.
|
||||
|
||||
if (object != NULL) {
|
||||
// But we're lucky enough to have a TypedObject pointer handy!
|
||||
// Maybe we can use it to resolve the error.
|
||||
handle = object->force_init_type();
|
||||
if (handle._index == 0) {
|
||||
// Strange.
|
||||
express_cat->error()
|
||||
<< "Unable to force_init_type() on unregistered TypeHandle.\n";
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
if (handle == object->get_type()) {
|
||||
// Problem solved!
|
||||
express_cat->warning()
|
||||
<< "Type " << handle << " was unregistered!\n";
|
||||
} else {
|
||||
// No good; it looks like the TypeHandle belongs to a class
|
||||
// that defined get_type(), but didn't define
|
||||
// force_init_type().
|
||||
express_cat->error()
|
||||
<< "Attempt to reference unregistered TypeHandle. Type is of some\n"
|
||||
<< "class derived from " << handle << " that doesn't define a good\n"
|
||||
<< "force_init_type() method.\n";
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
|
||||
} else {
|
||||
// We don't have a TypedObject pointer, so there's nothing we
|
||||
// can do about it.
|
||||
express_cat->error()
|
||||
<< "Attempt to reference unregistered TypeHandle!\n"
|
||||
<< "Registered TypeHandles are:\n";
|
||||
write(express_cat->error(false));
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (handle._index < 0 ||
|
||||
handle._index >= (int)_handle_registry.size()) {
|
||||
express_cat->fatal()
|
||||
<< "Invalid TypeHandle index " << handle._index
|
||||
<< "! Is memory corrupt?\n";
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
|
||||
return _handle_registry[handle._index];
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::RegistryNode::is_derived_from
|
||||
// Access: Public
|
||||
// Description: Returns true if the current RegistryNode represents a
|
||||
// class of type TypeHandle, or any of its ancestors do.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypeRegistry::RegistryNode::
|
||||
is_derived_from(TypeHandle type) const {
|
||||
if (_handle == type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Classes::const_iterator ni;
|
||||
for (ni = _parent_classes.begin(); ni != _parent_classes.end(); ++ni) {
|
||||
if ((*ni)->is_derived_from(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::RegistryNode::get_parent_towards
|
||||
// Access: Public
|
||||
// Description: Returns the first derived class that is an descendant
|
||||
// of the indicated ancestor class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::RegistryNode::
|
||||
get_parent_towards(TypeHandle type) const {
|
||||
if (_handle == type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
Classes::const_iterator ni;
|
||||
for (ni = _parent_classes.begin(); ni != _parent_classes.end(); ++ni) {
|
||||
if ((*ni)->is_derived_from(type)) {
|
||||
return (*ni)->_handle;
|
||||
}
|
||||
}
|
||||
|
||||
return TypeHandle::none();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,15 +19,11 @@
|
|||
#ifndef TYPEHANDLE_H
|
||||
#define TYPEHANDLE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include <notify.h>
|
||||
#include "notify.h"
|
||||
|
||||
#include <string>
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
#include "pset.h"
|
||||
#include <stdlib.h>
|
||||
#include "config_express.h"
|
||||
|
||||
// The following illustrates the convention for declaring a type that
|
||||
// uses TypeHandle. In this example, ThisThingie inherits from
|
||||
|
|
@ -132,352 +128,11 @@ INLINE ostream &operator << (ostream &out, TypeHandle type) {
|
|||
return out << type.get_name();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TypeRegistry
|
||||
// Description : The TypeRegistry class maintains all the assigned
|
||||
// TypeHandles in a given system. There should be only
|
||||
// one TypeRegistry class during the lifetime of the
|
||||
// application. It will be created on the local heap
|
||||
// initially, and it should be migrated to shared memory
|
||||
// as soon as shared memory becomes available.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS TypeRegistry {
|
||||
protected:
|
||||
class RegistryNode {
|
||||
public:
|
||||
RegistryNode(TypeHandle handle, const string &name, TypeHandle &ref);
|
||||
bool is_derived_from(TypeHandle type) const;
|
||||
TypeHandle get_parent_towards(TypeHandle type) const;
|
||||
|
||||
TypeHandle _handle;
|
||||
string _name;
|
||||
TypeHandle &_ref;
|
||||
typedef pvector<RegistryNode *> Classes;
|
||||
Classes _parent_classes;
|
||||
Classes _child_classes;
|
||||
};
|
||||
|
||||
public:
|
||||
// User code shouldn't generally need to call
|
||||
// TypeRegistry::register_type() or record_derivation() directly;
|
||||
// instead, use the register_type convenience function, defined
|
||||
// below.
|
||||
bool register_type(TypeHandle &type_handle, const string &name);
|
||||
TypeHandle register_dynamic_type(const string &name);
|
||||
|
||||
void record_derivation(TypeHandle child, TypeHandle parent);
|
||||
void record_alternate_name(TypeHandle type, const string &name);
|
||||
|
||||
PUBLISHED:
|
||||
TypeHandle find_type(const string &name) const;
|
||||
|
||||
string get_name(TypeHandle type, TypedObject *object) const;
|
||||
bool is_derived_from(TypeHandle child, TypeHandle parent,
|
||||
TypedObject *child_object) const;
|
||||
|
||||
int get_num_root_classes();
|
||||
TypeHandle get_root_class(int n);
|
||||
|
||||
int get_num_parent_classes(TypeHandle child,
|
||||
TypedObject *child_object) const;
|
||||
TypeHandle get_parent_class(TypeHandle child, int index) const;
|
||||
|
||||
int get_num_child_classes(TypeHandle child,
|
||||
TypedObject *child_object) const;
|
||||
TypeHandle get_child_class(TypeHandle child, int index) const;
|
||||
|
||||
TypeHandle get_parent_towards(TypeHandle child, TypeHandle ancestor,
|
||||
TypedObject *child_object) const;
|
||||
|
||||
static void reregister_types();
|
||||
|
||||
void write(ostream &out) const;
|
||||
|
||||
// ptr() returns the pointer to the global TypeRegistry object.
|
||||
static TypeRegistry *ptr();
|
||||
|
||||
private:
|
||||
// The TypeRegistry class should never be constructed by user code.
|
||||
// There is only one in the universe, and it constructs itself!
|
||||
TypeRegistry();
|
||||
|
||||
static void init_global_pointer();
|
||||
|
||||
RegistryNode *look_up(TypeHandle type, TypedObject *object) const;
|
||||
|
||||
void freshen_root_classes();
|
||||
void write_node(ostream &out, int indent_level,
|
||||
const RegistryNode *node) const;
|
||||
|
||||
typedef pvector<RegistryNode *> HandleRegistry;
|
||||
HandleRegistry _handle_registry;
|
||||
|
||||
typedef pmap<string, RegistryNode *> NameRegistry;
|
||||
NameRegistry _name_registry;
|
||||
|
||||
typedef pvector<RegistryNode *> RootClasses;
|
||||
bool _root_classes_fresh;
|
||||
RootClasses _root_classes;
|
||||
|
||||
static TypeRegistry *_global_pointer;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_type
|
||||
// Description: This inline function is just a convenient way to call
|
||||
// TypeRegistry::register_type(), along with zero to four
|
||||
// record_derivation()s. If for some reason you have a
|
||||
// class that has more than four base classes (you're
|
||||
// insane!), then you will need to call Register() and
|
||||
// record_derivation() yourself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3);
|
||||
|
||||
INLINE void
|
||||
register_type(TypeHandle &type_handle, const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: register_dynamic_type
|
||||
// Description: This is essentially similar to register_type(),
|
||||
// except that it doesn't store a reference to any
|
||||
// TypeHandle passed in and it therefore doesn't
|
||||
// complain if the type is registered more than once to
|
||||
// different TypeHandle reference.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name, TypeHandle parent1);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3);
|
||||
|
||||
INLINE TypeHandle
|
||||
register_dynamic_type(const string &name,
|
||||
TypeHandle parent1, TypeHandle parent2,
|
||||
TypeHandle parent3, TypeHandle parent4);
|
||||
|
||||
|
||||
// A few system-wide TypeHandles are defined for some basic types.
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS long_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS int_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS short_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS char_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS bool_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS double_type_handle;
|
||||
extern TypeHandle EXPCL_PANDAEXPRESS float_type_handle;
|
||||
|
||||
extern TypeHandle long_p_type_handle;
|
||||
extern TypeHandle int_p_type_handle;
|
||||
extern TypeHandle short_p_type_handle;
|
||||
extern TypeHandle char_p_type_handle;
|
||||
extern TypeHandle bool_p_type_handle;
|
||||
extern TypeHandle double_p_type_handle;
|
||||
extern TypeHandle float_p_type_handle;
|
||||
extern TypeHandle void_p_type_handle;
|
||||
|
||||
void EXPCL_PANDAEXPRESS init_system_type_handles();
|
||||
|
||||
// The following template function and its specializations will return
|
||||
// a TypeHandle for any type in the world, from a pointer to that
|
||||
// type.
|
||||
|
||||
template<class T>
|
||||
INLINE TypeHandle _get_type_handle(const T *) {
|
||||
return T::get_class_type();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const long *) {
|
||||
return long_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const int *) {
|
||||
return int_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const short *) {
|
||||
return short_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const char *) {
|
||||
return char_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const bool *) {
|
||||
return bool_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const double *) {
|
||||
return double_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const float *) {
|
||||
return float_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const long * const *) {
|
||||
return long_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const int * const *) {
|
||||
return int_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const short * const *) {
|
||||
return short_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const char * const *) {
|
||||
return char_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const bool * const *) {
|
||||
return bool_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const double * const *) {
|
||||
return double_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const float * const *) {
|
||||
return float_p_type_handle;
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE TypeHandle _get_type_handle(const void * const *) {
|
||||
return void_p_type_handle;
|
||||
}
|
||||
|
||||
|
||||
// The macro get_type_handle(type) is defined to make getting the type
|
||||
// handle associated with a particular type a bit cleaner.
|
||||
#define get_type_handle(type) _get_type_handle((const type *)0)
|
||||
|
||||
|
||||
// The following template function and its specializations can be used
|
||||
// to call init() on any unknown type. Handy for use within a
|
||||
// template class.
|
||||
|
||||
template<class T>
|
||||
INLINE void _do_init_type(const T *) {
|
||||
T::init_type();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const long *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const int *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const short *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const char *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const bool *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const double *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const float *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const long * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const int * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const short * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const char * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const bool * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const double * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const float * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
template<>
|
||||
INLINE void _do_init_type(const void * const *) {
|
||||
init_system_type_handles();
|
||||
}
|
||||
|
||||
#define do_init_type(type) _do_init_type((const type *)0)
|
||||
// We must include typeRegistry at this point so we can call it from
|
||||
// our inline functions. This is a circular include that is
|
||||
// strategically placed to do no harm.
|
||||
/* okcircular */
|
||||
#include "typeRegistry.h"
|
||||
|
||||
#include "typeHandle.I"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
// Filename: typeRegistry.I
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef NDEBUG
|
||||
// This function is only inline if NDEBUG is defined. Otherwise, it
|
||||
// is non-inline and its definition appears in typeRegistry.cxx.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::look_up
|
||||
// Access: Private
|
||||
// Description: Returns the TypeRegistryNode associated with the
|
||||
// indicated TypeHandle.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeRegistry::TypeRegistryNode *TypeRegistry::
|
||||
look_up(TypeHandle handle, TypedObject *) const {
|
||||
return _handle_registry[handle._index];
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::freshen_derivations
|
||||
// Access: Private
|
||||
// Description: Rebuilds the derivation data structures after some
|
||||
// derivation relationship has been modified, so that
|
||||
// class relationships can quickly be determined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TypeRegistry::
|
||||
freshen_derivations() {
|
||||
if (!_derivations_fresh) {
|
||||
rebuild_derivations();
|
||||
_derivations_fresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::is_derived_from
|
||||
// Access: Public
|
||||
// Description: Returns true if the first type is derived from the
|
||||
// second type, false otherwise.
|
||||
//
|
||||
// The "child_object" pointer is an optional pointer to
|
||||
// the TypedObject class that owns the child TypeHandle.
|
||||
// It is only used in case the TypeHandle is
|
||||
// inadvertently undefined.
|
||||
//
|
||||
// This function definition follows the definitions for
|
||||
// look_up() and freshen_derivations() just to maximize
|
||||
// the chance the the compiler will be able to inline
|
||||
// the above functions. Yeah, a compiler shouldn't
|
||||
// care, but there's a big different between "shouldn't"
|
||||
// and "doesn't".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TypeRegistry::
|
||||
is_derived_from(TypeHandle child, TypeHandle base,
|
||||
TypedObject *child_object) {
|
||||
const TypeRegistryNode *child_node = look_up(child, child_object);
|
||||
const TypeRegistryNode *base_node = look_up(base, NULL);
|
||||
nassertr(child_node != (TypeRegistryNode *)NULL &&
|
||||
base_node != (TypeRegistryNode *)NULL, false);
|
||||
freshen_derivations();
|
||||
return TypeRegistryNode::is_derived_from(child_node, base_node);
|
||||
}
|
||||
|
|
@ -0,0 +1,608 @@
|
|||
// Filename: typeRegistry.cxx
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "typeRegistry.h"
|
||||
#include "typedObject.h"
|
||||
#include "indent.h"
|
||||
#include "config_express.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// In general, we use the express_cat->info() syntax in this file
|
||||
// (instead of express_cat.info()), because much of this work is done at
|
||||
// static init time, and we must use the arrow syntax to force
|
||||
// initialization of the express_cat category.
|
||||
|
||||
TypeRegistry *TypeRegistry::_global_pointer = NULL;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::register_type
|
||||
// Access: Public
|
||||
// Description: Creates a new Type of the given name and assigns a
|
||||
// unique value to the type_handle. All type names must
|
||||
// be unique. If the type name has already been used,
|
||||
// the supplied type_handle value must match the name's
|
||||
// assigned type_handle or an error is triggered.
|
||||
// Returns true if the name wasn't defined before, false
|
||||
// if it was.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypeRegistry::
|
||||
register_type(TypeHandle &type_handle, const string &name) {
|
||||
if (type_handle != TypeHandle::none()) {
|
||||
// Here's a type that was already registered. Just make sure
|
||||
// everything's still kosher.
|
||||
TypeRegistryNode *rnode = look_up(type_handle, NULL);
|
||||
if (&type_handle == &rnode->_ref) {
|
||||
// No problem.
|
||||
nassertr(rnode->_name == name, false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NameRegistry::iterator ri;
|
||||
ri = _name_registry.find(name);
|
||||
|
||||
if (ri == _name_registry.end()) {
|
||||
// The name was not already used; this is the first time this
|
||||
// class has been defined.
|
||||
|
||||
#ifdef NOTIFY_DEBUG
|
||||
// This code runs at static init time, so cannot use the
|
||||
// express_cat.is_spam() syntax.
|
||||
if (express_cat->is_spam()) {
|
||||
express_cat->spam() << "Registering type " << name << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
TypeHandle new_handle;
|
||||
new_handle._index = _handle_registry.size();
|
||||
|
||||
TypeRegistryNode *rnode = new TypeRegistryNode(new_handle, name, type_handle);
|
||||
_handle_registry.push_back(rnode);
|
||||
_name_registry[name] = rnode;
|
||||
_derivations_fresh = false;
|
||||
|
||||
type_handle = new_handle;
|
||||
return true;
|
||||
}
|
||||
TypeRegistryNode *rnode = (*ri).second;
|
||||
nassertr(rnode->_name == (*ri).first, false);
|
||||
nassertr(rnode->_handle._index >= 0 &&
|
||||
rnode->_handle._index < (int)_handle_registry.size(), false);
|
||||
nassertr(_handle_registry[rnode->_handle._index] == rnode, false);
|
||||
nassertr(rnode->_handle._index != 0, false);
|
||||
|
||||
// The name was previously used; make sure the type_handle matches.
|
||||
if (&type_handle == &rnode->_ref) {
|
||||
// Ok, this was just a repeated attempt to register the same type.
|
||||
|
||||
if (type_handle == rnode->_handle) {
|
||||
// No problem.
|
||||
return false;
|
||||
}
|
||||
// But wait--the type_handle has changed! We kept a reference to
|
||||
// the static _type_handle member in the class that was passed in
|
||||
// at the first call to register_type(), and we got the same
|
||||
// reference passed in this time, but now it's different! Bad
|
||||
// juju.
|
||||
express_cat->error()
|
||||
<< "Reregistering " << name << "\n";
|
||||
type_handle == rnode->_handle;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type_handle != rnode->_handle) {
|
||||
// Hmm, we seem to have a contradictory type registration!
|
||||
express_cat->warning()
|
||||
<< "Attempt to register type " << name << " more than once!\n";
|
||||
|
||||
// This is invalid, but we'll allow it anyway. It seems to happen
|
||||
// for some reason under GNU libc5 that we occasionally end up
|
||||
// with two legitimate copies of the same class object in
|
||||
// memory--each with its own static _type_handle member.
|
||||
|
||||
type_handle = rnode->_handle;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::register_dynamic_type
|
||||
// Access: Public
|
||||
// Description: Registers a new type on-the-fly, presumably at
|
||||
// runtime. A new TypeHandle is returned if the
|
||||
// typename was not seen before; otherwise the same
|
||||
// TypeHandle that was last used for this typename is
|
||||
// returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
register_dynamic_type(const string &name) {
|
||||
NameRegistry::iterator ri;
|
||||
ri = _name_registry.find(name);
|
||||
|
||||
if (ri == _name_registry.end()) {
|
||||
// The name was not already used; this is the first time this
|
||||
// class has been defined.
|
||||
|
||||
#ifdef NOTIFY_DEBUG
|
||||
// This code runs at static init time, so cannot use the
|
||||
// express_cat.is_spam() syntax.
|
||||
if (express_cat->is_spam()) {
|
||||
express_cat->spam() << "Registering type " << name << "\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
// We must dynamically allocate a new handle so the TypeRegistryNode
|
||||
// has something unique to point to. This doesn't really mean
|
||||
// anything, though.
|
||||
TypeHandle *new_handle = new TypeHandle;
|
||||
new_handle->_index = _handle_registry.size();
|
||||
|
||||
TypeRegistryNode *rnode = new TypeRegistryNode(*new_handle, name, *new_handle);
|
||||
_handle_registry.push_back(rnode);
|
||||
_name_registry[name] = rnode;
|
||||
_derivations_fresh = false;
|
||||
|
||||
return *new_handle;
|
||||
}
|
||||
|
||||
// Return the TypeHandle previously obtained.
|
||||
TypeRegistryNode *rnode = (*ri).second;
|
||||
return rnode->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::record_derivation
|
||||
// Access: Public
|
||||
// Description: Records that the type referenced by child inherits
|
||||
// directly from the type referenced by parent. In the
|
||||
// event of multiple inheritance, this should be called
|
||||
// once for each parent class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
record_derivation(TypeHandle child, TypeHandle parent) {
|
||||
TypeRegistryNode *cnode = look_up(child, NULL);
|
||||
nassertv(cnode != (TypeRegistryNode *)NULL);
|
||||
TypeRegistryNode *pnode = look_up(parent, NULL);
|
||||
nassertv(pnode != (TypeRegistryNode *)NULL);
|
||||
|
||||
// First, we'll just run through the list to make sure we hadn't
|
||||
// already made this connection.
|
||||
TypeRegistryNode::Classes::iterator ni;
|
||||
ni = find(cnode->_parent_classes.begin(), cnode->_parent_classes.end(),
|
||||
pnode);
|
||||
|
||||
if (ni == cnode->_parent_classes.end()) {
|
||||
cnode->_parent_classes.push_back(pnode);
|
||||
pnode->_child_classes.push_back(cnode);
|
||||
_derivations_fresh = false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::record_alternate_name
|
||||
// Access: Public
|
||||
// Description: Indicates an alternate name for the same type. This
|
||||
// is particularly useful when a type has changed names,
|
||||
// since the type is stored in a Bam file by name;
|
||||
// setting the original name as the alternate will allow
|
||||
// the type to be correctly read from old Bam files.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
record_alternate_name(TypeHandle type, const string &name) {
|
||||
TypeRegistryNode *rnode = look_up(type, (TypedObject *)NULL);
|
||||
if (rnode != (TypeRegistryNode *)NULL) {
|
||||
NameRegistry::iterator ri =
|
||||
_name_registry.insert(NameRegistry::value_type(name, rnode)).first;
|
||||
if ((*ri).second != rnode) {
|
||||
express_cat.warning()
|
||||
<< "Name " << name << " already assigned to TypeHandle "
|
||||
<< rnode->_name << "; cannot reassign to " << type << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::find_type
|
||||
// Access: Public
|
||||
// Description: Looks for a previously-registered type of the given
|
||||
// name. Returns its TypeHandle if it exists, or
|
||||
// TypeHandle::none() if there is no such type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
find_type(const string &name) const {
|
||||
NameRegistry::const_iterator ri;
|
||||
ri = _name_registry.find(name);
|
||||
if (ri == _name_registry.end()) {
|
||||
return TypeHandle::none();
|
||||
} else {
|
||||
return (*ri).second->_handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the indicated type.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string TypeRegistry::
|
||||
get_name(TypeHandle type, TypedObject *object) const {
|
||||
TypeRegistryNode *rnode = look_up(type, object);
|
||||
nassertr(rnode != (TypeRegistryNode *)NULL, "");
|
||||
return rnode->_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_num_root_classes
|
||||
// Access: Public
|
||||
// Description: Returns the number of root classes--that is, classes
|
||||
// that do not inherit from any other classes--known in
|
||||
// the system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TypeRegistry::
|
||||
get_num_root_classes() {
|
||||
freshen_derivations();
|
||||
return _root_classes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_root_class
|
||||
// Access: Public
|
||||
// Description: Returns the nth root class in the system. See
|
||||
// get_num_root_classes().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_root_class(int n) {
|
||||
freshen_derivations();
|
||||
nassertr(n >= 0 && n < get_num_root_classes(), TypeHandle::none());
|
||||
return _root_classes[n]->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_num_parent_classes
|
||||
// Access: Public
|
||||
// Description: Returns the number of parent classes that the
|
||||
// indicated type is known to have. This may then be
|
||||
// used to index into get_parent_class(). The result
|
||||
// will be 0 if this class does not inherit from any
|
||||
// other classes, 1 if normal, single inheritance is in
|
||||
// effect, or greater than one if multiple inheritance
|
||||
// is in effect.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TypeRegistry::
|
||||
get_num_parent_classes(TypeHandle child, TypedObject *child_object) const {
|
||||
TypeRegistryNode *rnode = look_up(child, child_object);
|
||||
nassertr(rnode != (TypeRegistryNode *)NULL, 0);
|
||||
return rnode->_parent_classes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_parent_class
|
||||
// Access: Public
|
||||
// Description: Returns the nth parent class of this type. The index
|
||||
// should be in the range 0 <= index <
|
||||
// get_num_parent_classes().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_parent_class(TypeHandle child, int index) const {
|
||||
TypeRegistryNode *rnode = look_up(child, (TypedObject *)NULL);
|
||||
nassertr(rnode != (TypeRegistryNode *)NULL, TypeHandle::none());
|
||||
nassertr(index >= 0 && index < (int)rnode->_parent_classes.size(),
|
||||
TypeHandle::none());
|
||||
return rnode->_parent_classes[index]->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_num_child_classes
|
||||
// Access: Public
|
||||
// Description: Returns the number of child classes that the
|
||||
// indicated type is known to have. This may then be
|
||||
// used to index into get_child_class().
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int TypeRegistry::
|
||||
get_num_child_classes(TypeHandle child, TypedObject *child_object) const {
|
||||
TypeRegistryNode *rnode = look_up(child, child_object);
|
||||
nassertr(rnode != (TypeRegistryNode *)NULL, 0);
|
||||
return rnode->_child_classes.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_child_class
|
||||
// Access: Public
|
||||
// Description: Returns the nth child class of this type. The index
|
||||
// should be in the range 0 <= index <
|
||||
// get_num_child_classes().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_child_class(TypeHandle child, int index) const {
|
||||
TypeRegistryNode *rnode = look_up(child, (TypedObject *)NULL);
|
||||
nassertr(rnode != (TypeRegistryNode *)NULL, TypeHandle::none());
|
||||
nassertr(index >= 0 && index < (int)rnode->_child_classes.size(),
|
||||
TypeHandle::none());
|
||||
return rnode->_child_classes[index]->_handle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::get_parent_towards
|
||||
// Access: Public
|
||||
// Description: Returns the parent of the indicated child class that
|
||||
// is in a direct line of inheritance to the indicated
|
||||
// ancestor class. This is useful in the presence of
|
||||
// multiple inheritance to try to determine what
|
||||
// properties an unknown type may have.
|
||||
//
|
||||
// The "object" pointer is an optional pointer to the
|
||||
// TypedObject class that owns this TypeHandle. It is
|
||||
// only used in case the TypeHandle is inadvertantly
|
||||
// undefined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistry::
|
||||
get_parent_towards(TypeHandle child, TypeHandle base,
|
||||
TypedObject *child_object) const {
|
||||
const TypeRegistryNode *child_node = look_up(child, child_object);
|
||||
const TypeRegistryNode *base_node = look_up(base, NULL);
|
||||
nassertr(child_node != (TypeRegistryNode *)NULL &&
|
||||
base_node != (TypeRegistryNode *)NULL, TypeHandle::none());
|
||||
return TypeRegistryNode::get_parent_towards(child_node, base_node);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::reregister_types
|
||||
// Access: Public, Static
|
||||
// Description: Walks through the TypeRegistry tree and makes sure
|
||||
// that each type that was previously registered is
|
||||
// *still* registered. This seems to get broken in
|
||||
// certain circumstances when compiled against libc5--it
|
||||
// is as if the static initializer stomps on the
|
||||
// _type_handle values of each class after they've been
|
||||
// registered.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
reregister_types() {
|
||||
HandleRegistry::iterator ri;
|
||||
TypeRegistry *reg = ptr();
|
||||
for (ri = reg->_handle_registry.begin();
|
||||
ri != reg->_handle_registry.end();
|
||||
++ri) {
|
||||
TypeRegistryNode *rnode = (*ri);
|
||||
if (rnode != NULL && rnode->_handle != rnode->_ref) {
|
||||
express_cat->warning()
|
||||
<< "Reregistering " << rnode->_name << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::write
|
||||
// Access: Public
|
||||
// Description: Makes an attempt to format the entire TypeRegistry in
|
||||
// a nice way that shows the derivation tree as
|
||||
// intelligently as possible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
write(ostream &out) const {
|
||||
// Recursively write out the tree, starting from each node that has
|
||||
// no parent.
|
||||
HandleRegistry::const_iterator hi;
|
||||
for (hi = _handle_registry.begin();
|
||||
hi != _handle_registry.end();
|
||||
++hi) {
|
||||
const TypeRegistryNode *root = *hi;
|
||||
if (root != NULL && root->_parent_classes.empty()) {
|
||||
write_node(out, 2, root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::ptr
|
||||
// Access: Public, Static
|
||||
// Description: Returns the pointer to the global TypeRegistry
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistry *TypeRegistry::
|
||||
ptr() {
|
||||
if (_global_pointer == NULL) {
|
||||
init_global_pointer();
|
||||
}
|
||||
return _global_pointer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistry::
|
||||
TypeRegistry() {
|
||||
// We'll start out our handle_registry with a default entry for the
|
||||
// TypeHandles whose index number is zero, and are therefore
|
||||
// (probably) uninitialized.
|
||||
_handle_registry.push_back(NULL);
|
||||
|
||||
_derivations_fresh = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::init_global_pointer
|
||||
// Access: Private, Static
|
||||
// Description: Constructs the TypeRegistry object for the first
|
||||
// time. It is initially created on the local heap,
|
||||
// then as soon as shared memory becomes available, it
|
||||
// should be moved into shared memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
init_global_pointer() {
|
||||
_global_pointer = new TypeRegistry;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::rebuild_derivations
|
||||
// Access: Private
|
||||
// Description: Rebuilds the derivation data structures after some
|
||||
// derivation relationship has been modified, so that
|
||||
// class relationships can quickly be determined.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
rebuild_derivations() {
|
||||
#ifdef NOTIFY_DEBUG
|
||||
express_cat->debug()
|
||||
<< "Rebuilding derivation tree.\n";
|
||||
#endif
|
||||
|
||||
// First, remove all of the old data from the last type
|
||||
// rebuild_derivations() was called.
|
||||
_root_classes.clear();
|
||||
|
||||
HandleRegistry::iterator hi;
|
||||
for (hi = _handle_registry.begin();
|
||||
hi != _handle_registry.end();
|
||||
++hi) {
|
||||
TypeRegistryNode *node = *hi;
|
||||
if (node != (TypeRegistryNode *)NULL) {
|
||||
node->clear_subtree();
|
||||
}
|
||||
}
|
||||
|
||||
// Start by getting the list of root classes: those classes which do
|
||||
// not derive from anything.
|
||||
for (hi = _handle_registry.begin();
|
||||
hi != _handle_registry.end();
|
||||
++hi) {
|
||||
TypeRegistryNode *node = *hi;
|
||||
if (node != NULL && node->_parent_classes.empty()) {
|
||||
_root_classes.push_back(node);
|
||||
|
||||
// Also, for each root class, define a subtree.
|
||||
node->define_subtree();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::write_node
|
||||
// Access: Private
|
||||
// Description: Writes a single TypeRegistryNode out, along with all of
|
||||
// its descendants.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistry::
|
||||
write_node(ostream &out, int indent_level, const TypeRegistryNode *node) const {
|
||||
indent(out, indent_level) << node->_handle.get_index() << " " << node->_name;
|
||||
if (!node->_parent_classes.empty()) {
|
||||
out << " : " << node->_parent_classes[0]->_name;
|
||||
for (int pi = 1; pi < (int)node->_parent_classes.size(); pi++) {
|
||||
out << ", " << node->_parent_classes[pi]->_name;
|
||||
}
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
for (int i = 0; i < (int)node->_child_classes.size(); i++) {
|
||||
write_node(out, indent_level + 2, node->_child_classes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// This function is only non-inline if NDEBUG is not defined.
|
||||
// Otherwise, it is inline and its definition appears in
|
||||
// typeRegistry.I.
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistry::look_up
|
||||
// Access: Private
|
||||
// Description: Returns the TypeRegistryNode associated with the
|
||||
// indicated TypeHandle. If there is no associated
|
||||
// TypeRegistryNode, reports an error condition and
|
||||
// returns NULL.
|
||||
//
|
||||
// The associated TypedObject pointer is the pointer to
|
||||
// the object that owns the handle, if available. It is
|
||||
// only used in an error condition, if for some reason
|
||||
// the handle was uninitialized.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistryNode *TypeRegistry::
|
||||
look_up(TypeHandle handle, TypedObject *object) const {
|
||||
if (handle._index == 0) {
|
||||
// The TypeHandle is unregistered. This is an error condition.
|
||||
|
||||
if (object != NULL) {
|
||||
// But we're lucky enough to have a TypedObject pointer handy!
|
||||
// Maybe we can use it to resolve the error.
|
||||
handle = object->force_init_type();
|
||||
if (handle._index == 0) {
|
||||
// Strange.
|
||||
express_cat->error()
|
||||
<< "Unable to force_init_type() on unregistered TypeHandle.\n";
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
if (handle == object->get_type()) {
|
||||
// Problem solved!
|
||||
express_cat->warning()
|
||||
<< "Type " << handle << " was unregistered!\n";
|
||||
} else {
|
||||
// No good; it looks like the TypeHandle belongs to a class
|
||||
// that defined get_type(), but didn't define
|
||||
// force_init_type().
|
||||
express_cat->error()
|
||||
<< "Attempt to reference unregistered TypeHandle. Type is of some\n"
|
||||
<< "class derived from " << handle << " that doesn't define a good\n"
|
||||
<< "force_init_type() method.\n";
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
|
||||
} else {
|
||||
// We don't have a TypedObject pointer, so there's nothing we
|
||||
// can do about it.
|
||||
express_cat->error()
|
||||
<< "Attempt to reference unregistered TypeHandle!\n"
|
||||
<< "Registered TypeHandles are:\n";
|
||||
write(express_cat->error(false));
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (handle._index < 0 ||
|
||||
handle._index >= (int)_handle_registry.size()) {
|
||||
express_cat->fatal()
|
||||
<< "Invalid TypeHandle index " << handle._index
|
||||
<< "! Is memory corrupt?\n";
|
||||
nassertr(false, NULL);
|
||||
}
|
||||
|
||||
return _handle_registry[handle._index];
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
// Filename: typeRegistry.h
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TYPEREGISTRY_H
|
||||
#define TYPEREGISTRY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typeHandle.h"
|
||||
#include "typeRegistryNode.h"
|
||||
|
||||
#include "notify.h"
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TypeRegistry
|
||||
// Description : The TypeRegistry class maintains all the assigned
|
||||
// TypeHandles in a given system. There should be only
|
||||
// one TypeRegistry class during the lifetime of the
|
||||
// application. It will be created on the local heap
|
||||
// initially, and it should be migrated to shared memory
|
||||
// as soon as shared memory becomes available.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS TypeRegistry {
|
||||
public:
|
||||
// User code shouldn't generally need to call
|
||||
// TypeRegistry::register_type() or record_derivation() directly;
|
||||
// instead, use the register_type convenience function, defined
|
||||
// below.
|
||||
bool register_type(TypeHandle &type_handle, const string &name);
|
||||
TypeHandle register_dynamic_type(const string &name);
|
||||
|
||||
void record_derivation(TypeHandle child, TypeHandle parent);
|
||||
void record_alternate_name(TypeHandle type, const string &name);
|
||||
|
||||
PUBLISHED:
|
||||
TypeHandle find_type(const string &name) const;
|
||||
|
||||
string get_name(TypeHandle type, TypedObject *object) const;
|
||||
INLINE bool is_derived_from(TypeHandle child, TypeHandle base,
|
||||
TypedObject *child_object);
|
||||
|
||||
int get_num_root_classes();
|
||||
TypeHandle get_root_class(int n);
|
||||
|
||||
int get_num_parent_classes(TypeHandle child,
|
||||
TypedObject *child_object) const;
|
||||
TypeHandle get_parent_class(TypeHandle child, int index) const;
|
||||
|
||||
int get_num_child_classes(TypeHandle child,
|
||||
TypedObject *child_object) const;
|
||||
TypeHandle get_child_class(TypeHandle child, int index) const;
|
||||
|
||||
TypeHandle get_parent_towards(TypeHandle child, TypeHandle base,
|
||||
TypedObject *child_object) const;
|
||||
|
||||
static void reregister_types();
|
||||
|
||||
void write(ostream &out) const;
|
||||
|
||||
// ptr() returns the pointer to the global TypeRegistry object.
|
||||
static TypeRegistry *ptr();
|
||||
|
||||
private:
|
||||
// The TypeRegistry class should never be constructed by user code.
|
||||
// There is only one in the universe, and it constructs itself!
|
||||
TypeRegistry();
|
||||
|
||||
static void init_global_pointer();
|
||||
|
||||
// In NDEBUG mode, this is an inline function; otherwise, it's
|
||||
// out-of-line.
|
||||
#ifdef NDEBUG
|
||||
INLINE TypeRegistryNode *look_up(TypeHandle type, TypedObject *object) const;
|
||||
#else
|
||||
TypeRegistryNode *look_up(TypeHandle type, TypedObject *object) const;
|
||||
#endif
|
||||
|
||||
INLINE void freshen_derivations();
|
||||
void rebuild_derivations();
|
||||
void write_node(ostream &out, int indent_level,
|
||||
const TypeRegistryNode *node) const;
|
||||
|
||||
typedef pvector<TypeRegistryNode *> HandleRegistry;
|
||||
HandleRegistry _handle_registry;
|
||||
|
||||
typedef pmap<string, TypeRegistryNode *> NameRegistry;
|
||||
NameRegistry _name_registry;
|
||||
|
||||
typedef pvector<TypeRegistryNode *> RootClasses;
|
||||
RootClasses _root_classes;
|
||||
|
||||
bool _derivations_fresh;
|
||||
|
||||
static TypeRegistry *_global_pointer;
|
||||
};
|
||||
|
||||
#include "typeRegistry.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
// Filename: typeRegistryNode.I
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Inherit::Default Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeRegistryNode::Inherit::
|
||||
Inherit() {
|
||||
_top = (TypeRegistryNode *)NULL;
|
||||
_mask = 0;
|
||||
_bits = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Inherit::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeRegistryNode::Inherit::
|
||||
Inherit(TypeRegistryNode *top, int bit_count,
|
||||
TypeRegistryNode::SubtreeMaskType bits) {
|
||||
nassertv(bit_count < (int)(sizeof(SubtreeMaskType) * 8));
|
||||
_top = top;
|
||||
|
||||
// Build a bitmask consisting of bit_count low-order bits.
|
||||
_mask = ((SubtreeMaskType)1 << bit_count) - 1;
|
||||
|
||||
// There shouldn't be anything but zeroes after bit_count bits.
|
||||
nassertv((bits & ~_mask) == 0);
|
||||
_bits = bits;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Inherit::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypeRegistryNode::Inherit::
|
||||
Inherit(const TypeRegistryNode::Inherit ©) :
|
||||
_top(copy._top),
|
||||
_mask(copy._mask),
|
||||
_bits(copy._bits)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Inherit::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void TypeRegistryNode::Inherit::
|
||||
operator = (const TypeRegistryNode::Inherit ©) {
|
||||
_top = copy._top;
|
||||
_mask = copy._mask;
|
||||
_bits = copy._bits;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Inherit::Ordering operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TypeRegistryNode::Inherit::
|
||||
operator < (const Inherit &other) const {
|
||||
return _top < other._top;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Inherit::is_derived_from
|
||||
// Access: Public
|
||||
// Description: Assuming the two Inherit objects share the same
|
||||
// subtree top, this returns true if the bitmasks
|
||||
// indicate that child inherits from base, or false
|
||||
// otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool TypeRegistryNode::Inherit::
|
||||
is_derived_from(const TypeRegistryNode::Inherit &child,
|
||||
const TypeRegistryNode::Inherit &base) {
|
||||
nassertr(child._top == base._top, false);
|
||||
|
||||
// Child derives from base if and only if its subtree mask contains
|
||||
// more bits (or the same number of bits), and the n low-order
|
||||
// subtree bits that are in common are identical.
|
||||
return ((child._mask & base._mask) == base._mask &&
|
||||
(child._bits & base._mask) == base._bits);
|
||||
}
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
// Filename: typeRegistryNode.cxx
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "typeRegistryNode.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// Define this to double-check all the inheritance derivations.
|
||||
//#define PARANOID_INHERITANCE
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistryNode::
|
||||
TypeRegistryNode(TypeHandle handle, const string &name, TypeHandle &ref) :
|
||||
_handle(handle), _name(name), _ref(ref)
|
||||
{
|
||||
clear_subtree();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::is_derived_from
|
||||
// Access: Public, Static
|
||||
// Description: Returns true if the child RegistryNode represents a
|
||||
// class that inherits directly or indirectly from the
|
||||
// class represented by the base RegistryNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypeRegistryNode::
|
||||
is_derived_from(const TypeRegistryNode *child, const TypeRegistryNode *base) {
|
||||
// This function is the basis for TypedObject::is_of_type(), which
|
||||
// gets used quite frequently within Panda, often in inner-loop
|
||||
// code. Therefore, we go through some pains to make this function
|
||||
// as efficient as possible.
|
||||
|
||||
// First, compare the subtree tops. If they are the same, then this
|
||||
// node and the base node are within the same single-inheritance
|
||||
// subtree, and we can use our bitmask trick to determine the
|
||||
// relationship with no additional work. (See r_build_subtrees()).
|
||||
|
||||
if (child->_inherit._top == base->_inherit._top) {
|
||||
nassertr(child->_inherit._top != (TypeRegistryNode *)NULL, false);
|
||||
|
||||
bool derives =
|
||||
Inherit::is_derived_from(child->_inherit, base->_inherit);
|
||||
|
||||
#ifdef PARANOID_INHERITANCE
|
||||
bool paranoid_derives = check_derived_from(child, base);
|
||||
if (derives != paranoid_derives) {
|
||||
express_cat.error()
|
||||
<< "Inheritance test for " << child->_name
|
||||
<< " from " << base->_name << " failed!\n"
|
||||
<< "Result: " << derives << " should have been: "
|
||||
<< paranoid_derives << "\n"
|
||||
<< "Classes are in the same single inheritance subtree, children of "
|
||||
<< child->_inherit._top->_name << "\n"
|
||||
<< hex
|
||||
<< child->_name << " has mask " << child->_inherit._mask
|
||||
<< " and bits " << child->_inherit._bits << "\n"
|
||||
<< base->_name << " has mask " << base->_inherit._mask
|
||||
<< " and bits " << base->_inherit._bits << "\n"
|
||||
<< dec;
|
||||
return paranoid_derives;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
cerr << "trivial: " << child->_name << " vs. " << base->_name
|
||||
<< " (" << child->_inherit._top->_name << ") = " << derives << "\n";
|
||||
*/
|
||||
|
||||
return derives;
|
||||
}
|
||||
|
||||
// The two nodes are not within the same single-inheritance subtree.
|
||||
// This complicates things a bit.
|
||||
|
||||
// First, we should check whether the subtree tops of the two nodes
|
||||
// inherit from each other.
|
||||
const TypeRegistryNode *child_top = child->_inherit._top;
|
||||
const TypeRegistryNode *base_top = base->_inherit._top;
|
||||
|
||||
bool derives = false;
|
||||
|
||||
// If child_top does not inherit from base_top, it follows that
|
||||
// child does not inherit from base.
|
||||
TopInheritance::const_iterator ti = child_top->find_top_inherit(base_top);
|
||||
|
||||
while (ti != child_top->_top_inheritance.end() &&
|
||||
(*ti)._top == base_top &&
|
||||
!derives) {
|
||||
// If child_top *does* inherit from base_top, then child may or
|
||||
// may not inherit from base. This depends on the exact path of
|
||||
// inheritance. Since there might be multiple paths from
|
||||
// child_top to base_top, we have to examine all of them.
|
||||
const Inherit &connection = (*ti);
|
||||
|
||||
// Here is one inheritance from child_top to base_top. If the
|
||||
// connecting node inherits from base, then child also inherits
|
||||
// from base. If the connecting node does not inherit from base,
|
||||
// we must keep looking.
|
||||
derives = Inherit::is_derived_from(connection, base->_inherit);
|
||||
|
||||
++ti;
|
||||
}
|
||||
|
||||
#ifdef PARANOID_INHERITANCE
|
||||
bool paranoid_derives = check_derived_from(child, base);
|
||||
if (derives != paranoid_derives) {
|
||||
express_cat.error()
|
||||
<< "Inheritance test for " << child->_name
|
||||
<< " from " << base->_name << " failed!\n"
|
||||
<< "Result: " << derives << " should have been: "
|
||||
<< paranoid_derives << "\n"
|
||||
<< child->_name << " is a descendent of "
|
||||
<< child_top->_name << "\n"
|
||||
<< base->_name << " is a descendent of "
|
||||
<< base_top->_name << "\n";
|
||||
return paranoid_derives;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
cerr << "complex: " << child->_name << " (" << child->_inherit._top->_name
|
||||
<< ") vs. " << base->_name << " (" << base->_inherit._top->_name
|
||||
<< ") = " << derives << "\n";
|
||||
*/
|
||||
return derives;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::get_parent_towards
|
||||
// Access: Public, Static
|
||||
// Description: Returns the first parent class of child that is a
|
||||
// descendant of the indicated base class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeHandle TypeRegistryNode::
|
||||
get_parent_towards(const TypeRegistryNode *child,
|
||||
const TypeRegistryNode *base) {
|
||||
if (child == base) {
|
||||
return child->_handle;
|
||||
}
|
||||
|
||||
Classes::const_iterator ni;
|
||||
for (ni = child->_parent_classes.begin();
|
||||
ni != child->_parent_classes.end(); ++ni) {
|
||||
if (is_derived_from((*ni), base)) {
|
||||
return (*ni)->_handle;
|
||||
}
|
||||
}
|
||||
|
||||
return TypeHandle::none();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::clear_subtree
|
||||
// Access: Public
|
||||
// Description: Removes any subtree definition previously set up via
|
||||
// define_subtree(), in preparation for rebuilding the
|
||||
// subtree data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistryNode::
|
||||
clear_subtree() {
|
||||
_inherit = Inherit();
|
||||
_top_inheritance.clear();
|
||||
_visit_count = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::define_subtree
|
||||
// Access: Public
|
||||
// Description: Indicates that this TypeRegistryNode is the top of a
|
||||
// subtree within the inheritance graph (typically, this
|
||||
// indicates a multiple-inheritance node). Builds all
|
||||
// the subtree_mask etc. flags for nodes at this level
|
||||
// and below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistryNode::
|
||||
define_subtree() {
|
||||
// cerr << "Building subtree for " << _name << ", top inheritance is:\n";
|
||||
|
||||
/*
|
||||
TopInheritance::const_iterator ti;
|
||||
for (ti = _top_inheritance.begin(); ti != _top_inheritance.end(); ++ti) {
|
||||
const Inherit &t = (*ti);
|
||||
cerr << " from " << t._top->_name << " via "
|
||||
<< hex << t._bits << " / " << t._mask << dec << "\n";
|
||||
}
|
||||
*/
|
||||
|
||||
r_build_subtrees(this, 0, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::r_build_subtrees
|
||||
// Access: Public
|
||||
// Description: Recursively builds up all the subtree cache
|
||||
// information for this node and the ones below. This
|
||||
// information is used to quickly determine class
|
||||
// inheritance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void TypeRegistryNode::
|
||||
r_build_subtrees(TypeRegistryNode *top, int bit_count,
|
||||
TypeRegistryNode::SubtreeMaskType bits) {
|
||||
// The idea with these bits is to optimize the common case of a
|
||||
// single-inheritance graph (that is, an inheritance tree), or a
|
||||
// single-inheritance subgraph of the full multiple-inheritance
|
||||
// graph (i.e. a subtree of the inheritance graph).
|
||||
|
||||
// When we have just single inheritance, we can define a unique
|
||||
// number for each node in the inheritance tree that allows us to
|
||||
// immediately determine the inheritance relationship between any
|
||||
// two nodes in the tree. We choose a number such that for a given
|
||||
// node whose number has n bits, each child node has m + n bits
|
||||
// where the low-order n bits are the same as the parent node's
|
||||
// bits, and the high-order m bits are unique among each sibling.
|
||||
// The node at the top of the tree has zero bits.
|
||||
|
||||
// That way, we can simply compare bitmasks to determine if class A
|
||||
// inherits from class B. If the low-order bits are the same, they
|
||||
// have some ancestry in common. The highest-order bit that still
|
||||
// matches corresponds to the lowest node in the tree that they have
|
||||
// in common; i.e. the node from which they both inherit.
|
||||
|
||||
// To put it more formally, let count(A) be the number of bits in
|
||||
// A's number, and count(B) be the number of bits in B's number. A
|
||||
// inherits from B if and only if count(B) <= count(A), and the
|
||||
// lower count(B) bits of A's number are the same as those in B's
|
||||
// number.
|
||||
|
||||
// This algorithm breaks down in the presence of multiple
|
||||
// inheritance, since we can't make up a single number for each node
|
||||
// any more. We still take advantage of the algorithm by
|
||||
// considering each single-inheritance subgraph separately.
|
||||
|
||||
// To handle multiple inheritance, we reset the numbers to zero
|
||||
// every time we come across a multiple-inheritance node (this
|
||||
// begins a new subtree). There are relatively few of these
|
||||
// "subtree top" nodes, and we record the explicit inheritance of
|
||||
// each one from all of its ancestor "subtree top" nodes within the
|
||||
// node itself.
|
||||
|
||||
if (top != this && _parent_classes.size() != 1) {
|
||||
nassertv(!_parent_classes.empty());
|
||||
|
||||
// This class multiply inherits; it therefore begins a new subtree.
|
||||
|
||||
// Copy in the inheritance relations from our parent subtree tops.
|
||||
_top_inheritance.insert(_top_inheritance.end(),
|
||||
top->_top_inheritance.begin(),
|
||||
top->_top_inheritance.end());
|
||||
_top_inheritance.push_back(Inherit(top, bit_count, bits));
|
||||
|
||||
_visit_count++;
|
||||
if (_visit_count == (int)_parent_classes.size()) {
|
||||
// This is the last time we'll visit this node, so continue the
|
||||
// recursion now.
|
||||
nassertv(_inherit._top == (TypeRegistryNode *)NULL);
|
||||
sort(_top_inheritance.begin(), _top_inheritance.end());
|
||||
define_subtree();
|
||||
}
|
||||
|
||||
} else {
|
||||
// This class singly inherits, so this had better be the only time
|
||||
// this function is called on it since clear_subtree().
|
||||
nassertv(_inherit._top == (TypeRegistryNode *)NULL);
|
||||
|
||||
nassertv(bit_count < (int)(sizeof(SubtreeMaskType) * 8));
|
||||
|
||||
_inherit = Inherit(top, bit_count, bits);
|
||||
|
||||
// Now, how many more bits do we need to encode each of our
|
||||
// children?
|
||||
int num_children = _child_classes.size();
|
||||
int more_bits = 0;
|
||||
int i = num_children - 1;
|
||||
while (i > 0) {
|
||||
more_bits++;
|
||||
i >>= 1;
|
||||
}
|
||||
|
||||
// We need at least one bit, even if there is only one child, so
|
||||
// we can differentiate parent from child.
|
||||
more_bits = max(more_bits, 1);
|
||||
|
||||
nassertv(more_bits < (int)(sizeof(SubtreeMaskType) * 8));
|
||||
|
||||
if (bit_count + more_bits > (int)(sizeof(SubtreeMaskType) * 8)) {
|
||||
// Too many bits; we need to start a new subtree right here.
|
||||
// This node becomes a subtree top node, even though it's not a
|
||||
// multiple-inheritance node.
|
||||
nassertv(top != this);
|
||||
_top_inheritance = top->_top_inheritance;
|
||||
_top_inheritance.push_back(_inherit);
|
||||
sort(_top_inheritance.begin(), _top_inheritance.end());
|
||||
_inherit = Inherit();
|
||||
define_subtree();
|
||||
|
||||
} else {
|
||||
// Still plenty of bits, so keep going.
|
||||
for (i = 0; i < num_children; i++) {
|
||||
TypeRegistryNode *child = _child_classes[i];
|
||||
SubtreeMaskType next_bits = ((SubtreeMaskType)i << bit_count);
|
||||
|
||||
child->r_build_subtrees(top, bit_count + more_bits,
|
||||
bits | next_bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::find_top_inherit
|
||||
// Access: Private, Static
|
||||
// Description: Finds the first element in the _top_inheritance array
|
||||
// that matches the indicated base node. If the base
|
||||
// node does not appear in the _top_inheritance array
|
||||
// (implying that this node does not inherit from the
|
||||
// base node), returns _top_inheritance.end().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypeRegistryNode::TopInheritance::const_iterator TypeRegistryNode::
|
||||
find_top_inherit(const TypeRegistryNode *base) const {
|
||||
TopInheritance::const_iterator ti;
|
||||
for (ti = _top_inheritance.begin(); ti != _top_inheritance.end(); ++ti) {
|
||||
if ((*ti)._top == base) {
|
||||
return ti;
|
||||
}
|
||||
}
|
||||
|
||||
return _top_inheritance.end();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TypeRegistryNode::check_derived_from
|
||||
// Access: Private, Static
|
||||
// Description: A recursive function to double-check the result of
|
||||
// is_derived_from(). This is the slow,
|
||||
// examine-the-whole-graph approach, as opposed to the
|
||||
// clever and optimal algorithm of is_derived_from();
|
||||
// it's intended to be used only for debugging said
|
||||
// clever algorithm.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool TypeRegistryNode::
|
||||
check_derived_from(const TypeRegistryNode *child,
|
||||
const TypeRegistryNode *base) {
|
||||
if (child == base) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Classes::const_iterator ni;
|
||||
for (ni = child->_parent_classes.begin();
|
||||
ni != child->_parent_classes.end();
|
||||
++ni) {
|
||||
if (check_derived_from(*ni, base)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
// Filename: typeRegistryNode.h
|
||||
// Created by: drose (06Aug01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TYPEREGISTRYNODE_H
|
||||
#define TYPEREGISTRYNODE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typeHandle.h"
|
||||
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : TypeRegistryNode
|
||||
// Description : This is a single entry in the TypeRegistry.
|
||||
// Normally, user code will never directly access this
|
||||
// class; this class is hidden within the TypeRegistry
|
||||
// accessors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS TypeRegistryNode {
|
||||
public:
|
||||
TypeRegistryNode(TypeHandle handle, const string &name, TypeHandle &ref);
|
||||
|
||||
static bool is_derived_from(const TypeRegistryNode *child,
|
||||
const TypeRegistryNode *base);
|
||||
|
||||
static TypeHandle get_parent_towards(const TypeRegistryNode *child,
|
||||
const TypeRegistryNode *base);
|
||||
|
||||
void clear_subtree();
|
||||
void define_subtree();
|
||||
|
||||
TypeHandle _handle;
|
||||
string _name;
|
||||
TypeHandle &_ref;
|
||||
typedef pvector<TypeRegistryNode *> Classes;
|
||||
Classes _parent_classes;
|
||||
Classes _child_classes;
|
||||
|
||||
private:
|
||||
typedef int SubtreeMaskType;
|
||||
|
||||
// This class defines the inheritance relationship of this node from
|
||||
// some ancestor denoted as a "subtree top" node. This is usually
|
||||
// the nearest ancestor that has multiple inheritance.
|
||||
class Inherit {
|
||||
public:
|
||||
INLINE Inherit();
|
||||
INLINE Inherit(TypeRegistryNode *top, int bit_count,
|
||||
SubtreeMaskType bits);
|
||||
INLINE Inherit(const Inherit ©);
|
||||
INLINE void operator = (const Inherit ©);
|
||||
|
||||
INLINE bool operator < (const Inherit &other) const;
|
||||
INLINE static bool is_derived_from(const Inherit &child, const Inherit &base);
|
||||
|
||||
TypeRegistryNode *_top;
|
||||
SubtreeMaskType _mask;
|
||||
SubtreeMaskType _bits;
|
||||
};
|
||||
typedef pvector<Inherit> TopInheritance;
|
||||
|
||||
void r_build_subtrees(TypeRegistryNode *top,
|
||||
int bit_count, SubtreeMaskType bits);
|
||||
|
||||
TopInheritance::const_iterator
|
||||
find_top_inherit(const TypeRegistryNode *base) const;
|
||||
|
||||
static bool check_derived_from(const TypeRegistryNode *child,
|
||||
const TypeRegistryNode *base);
|
||||
|
||||
Inherit _inherit;
|
||||
|
||||
// The _top_inheritance member is only filled for nodes that are
|
||||
// denoted as "subtree top" nodes. It represents the complete set
|
||||
// of subtree_top nodes that this node inherits from, directly or
|
||||
// indirectly.
|
||||
TopInheritance _top_inheritance;
|
||||
|
||||
// _visit_count is only used during r_build_subtree().
|
||||
int _visit_count;
|
||||
};
|
||||
|
||||
#include "typeRegistryNode.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -19,9 +19,10 @@
|
|||
#ifndef TYPEDOBJECT_H
|
||||
#define TYPEDOBJECT_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typeHandle.h"
|
||||
#include "register_type.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -70,63 +71,6 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
// The DCAST (downcast) macro is defined as a convenience for
|
||||
// downcasting from some TypedObject pointer (or a PointerTo). It's
|
||||
// just a normal C++-style downcast, except it first checks get_type()
|
||||
// to make sure the downcasting is safe. If you compile with NDEBUG,
|
||||
// this check is removed.
|
||||
|
||||
// DCAST will return NULL if the downcasting is unsafe. If you'd
|
||||
// rather it abort out of the function (ala nassertv/nassertr), then
|
||||
// see DCAST_INTO_V and DCAST_INTO_R, below.
|
||||
|
||||
template<class WantType>
|
||||
INLINE WantType *_dcast(WantType *, TypedObject *ptr);
|
||||
template<class WantType>
|
||||
INLINE const WantType *_dcast(WantType *, const TypedObject *ptr);
|
||||
|
||||
// Note: it is important that DCAST not repeat the pointer parameter,
|
||||
// since many users of DCAST may want to use the result of a function
|
||||
// as the pointer parameter, and it could be terribly confusing and
|
||||
// difficult to trace if the function was executed twice. This
|
||||
// happened!
|
||||
#define DCAST(want_type, pointer) _dcast((want_type*)0, pointer)
|
||||
|
||||
// DCAST_INTO_V and DCAST_INTO_R are similar in purpose to DCAST,
|
||||
// except they: (a) automatically assign a variable instead of
|
||||
// returning the downcasted pointer, and (b) they immediately return
|
||||
// out of the function if the downcasting fails. DCAST_INTO_V is for
|
||||
// use in a void function and returns nothing; DCAST_INTO_R is for use
|
||||
// in a non-void function and returns the indicated value.
|
||||
|
||||
// Both DCAST_INTO_V and DCAST_INTO_R accept as the first parameter a
|
||||
// variable of type (want_type *) or (const want_type *), instead of
|
||||
// the name of the type. This variable will be filled with the new
|
||||
// pointer.
|
||||
|
||||
|
||||
// _dcast_ref is used to implement DCAST_INTO_V and DCAST_INTO_R. Its
|
||||
// difference from _dcast is that it takes a reference to a pointer as
|
||||
// a first parameter. The main point of this is to shut up the
|
||||
// compiler about pointers used before their value is assigned.
|
||||
template<class WantType>
|
||||
INLINE WantType *_dcast_ref(WantType *&, TypedObject *ptr);
|
||||
template<class WantType>
|
||||
INLINE const WantType *_dcast_ref(WantType *&, const TypedObject *ptr);
|
||||
|
||||
|
||||
#define DCAST_INTO_V(to_pointer, from_pointer) \
|
||||
{ \
|
||||
(to_pointer) = _dcast_ref(to_pointer, from_pointer); \
|
||||
nassertv((void *)(to_pointer) != (void *)NULL); \
|
||||
}
|
||||
|
||||
#define DCAST_INTO_R(to_pointer, from_pointer, return_value) \
|
||||
{ \
|
||||
(to_pointer) = _dcast_ref(to_pointer, from_pointer); \
|
||||
nassertr((void *)(to_pointer) != (void *)NULL, return_value); \
|
||||
}
|
||||
|
||||
#include "typedObject.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,54 +22,55 @@
|
|||
#include "glGeomNodeContext.h"
|
||||
#include "config_glgsg.h"
|
||||
|
||||
#include <config_util.h>
|
||||
#include <directRenderTraverser.h>
|
||||
#include <cullTraverser.h>
|
||||
#include <displayRegion.h>
|
||||
#include <projectionNode.h>
|
||||
#include <camera.h>
|
||||
#include <renderBuffer.h>
|
||||
#include <geom.h>
|
||||
#include <geomIssuer.h>
|
||||
#include <graphicsWindow.h>
|
||||
#include <graphicsChannel.h>
|
||||
#include <projection.h>
|
||||
#include <get_rel_pos.h>
|
||||
#include <perspectiveProjection.h>
|
||||
#include <ambientLight.h>
|
||||
#include <directionalLight.h>
|
||||
#include <pointLight.h>
|
||||
#include <spotlight.h>
|
||||
#include <GL/glu.h>
|
||||
#include <projectionNode.h>
|
||||
#include <transformTransition.h>
|
||||
#include <colorMatrixTransition.h>
|
||||
#include <alphaTransformTransition.h>
|
||||
#include <colorTransition.h>
|
||||
#include <lightTransition.h>
|
||||
#include <textureTransition.h>
|
||||
#include <renderModeTransition.h>
|
||||
#include <materialTransition.h>
|
||||
#include <colorBlendTransition.h>
|
||||
#include <colorMaskTransition.h>
|
||||
#include <texMatrixTransition.h>
|
||||
#include <texGenTransition.h>
|
||||
#include <textureApplyTransition.h>
|
||||
#include <clipPlaneTransition.h>
|
||||
#include <transparencyTransition.h>
|
||||
#include <fogTransition.h>
|
||||
#include <linesmoothTransition.h>
|
||||
#include <depthTestTransition.h>
|
||||
#include <depthWriteTransition.h>
|
||||
#include <cullFaceTransition.h>
|
||||
#include <stencilTransition.h>
|
||||
#include <pointShapeTransition.h>
|
||||
#include <polygonOffsetTransition.h>
|
||||
#include <clockObject.h>
|
||||
#include <pStatTimer.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
#include "config_util.h"
|
||||
#include "directRenderTraverser.h"
|
||||
#include "cullTraverser.h"
|
||||
#include "displayRegion.h"
|
||||
#include "projectionNode.h"
|
||||
#include "camera.h"
|
||||
#include "renderBuffer.h"
|
||||
#include "geom.h"
|
||||
#include "geomIssuer.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "graphicsChannel.h"
|
||||
#include "projection.h"
|
||||
#include "get_rel_pos.h"
|
||||
#include "perspectiveProjection.h"
|
||||
#include "ambientLight.h"
|
||||
#include "directionalLight.h"
|
||||
#include "pointLight.h"
|
||||
#include "spotlight.h"
|
||||
#include "GL/glu.h"
|
||||
#include "projectionNode.h"
|
||||
#include "transformTransition.h"
|
||||
#include "colorMatrixTransition.h"
|
||||
#include "alphaTransformTransition.h"
|
||||
#include "colorTransition.h"
|
||||
#include "lightTransition.h"
|
||||
#include "textureTransition.h"
|
||||
#include "renderModeTransition.h"
|
||||
#include "materialTransition.h"
|
||||
#include "colorBlendTransition.h"
|
||||
#include "colorMaskTransition.h"
|
||||
#include "texMatrixTransition.h"
|
||||
#include "texGenTransition.h"
|
||||
#include "textureApplyTransition.h"
|
||||
#include "clipPlaneTransition.h"
|
||||
#include "transparencyTransition.h"
|
||||
#include "fogTransition.h"
|
||||
#include "linesmoothTransition.h"
|
||||
#include "depthTestTransition.h"
|
||||
#include "depthWriteTransition.h"
|
||||
#include "cullFaceTransition.h"
|
||||
#include "stencilTransition.h"
|
||||
#include "pointShapeTransition.h"
|
||||
#include "polygonOffsetTransition.h"
|
||||
#include "clockObject.h"
|
||||
#include "pStatTimer.h"
|
||||
#include "string_utils.h"
|
||||
#include "dcast.h"
|
||||
#include "pvector.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
#ifndef NODETRANSITION_H
|
||||
#define NODETRANSITION_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "graphHashGenerator.h"
|
||||
|
||||
#include <typedWritableReferenceCount.h>
|
||||
#include "pset.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
|
||||
class Node;
|
||||
class NodeTransitions;
|
||||
|
|
|
|||
|
|
@ -19,11 +19,12 @@
|
|||
#ifndef NODETRANSITIONS_H
|
||||
#define NODETRANSITIONS_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "nodeTransition.h"
|
||||
|
||||
#include <pointerTo.h>
|
||||
#include "pointerTo.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include "pmap.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA NullLevelState {
|
||||
public:
|
||||
INLINE_GRAPH NullLevelState() { }
|
||||
INLINE_GRAPH NullLevelState(const NullLevelState &) { }
|
||||
INLINE_GRAPH void operator = (const NullLevelState &) { }
|
||||
INLINE NullLevelState() { }
|
||||
INLINE NullLevelState(const NullLevelState &) { }
|
||||
INLINE void operator = (const NullLevelState &) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH NullTransitionWrapper::
|
||||
INLINE NullTransitionWrapper::
|
||||
NullTransitionWrapper() {
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ NullTransitionWrapper() {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH NullTransitionWrapper::
|
||||
INLINE NullTransitionWrapper::
|
||||
NullTransitionWrapper(const NullTransitionWrapper &) {
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ NullTransitionWrapper(const NullTransitionWrapper &) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
operator = (const NullTransitionWrapper &) {
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ operator = (const NullTransitionWrapper &) {
|
|||
// Access: Public, Static
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH NullTransitionWrapper NullTransitionWrapper::
|
||||
INLINE NullTransitionWrapper NullTransitionWrapper::
|
||||
init_from(const NullTransitionWrapper &) {
|
||||
return NullTransitionWrapper();
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ init_from(const NullTransitionWrapper &) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH bool NullTransitionWrapper::
|
||||
INLINE bool NullTransitionWrapper::
|
||||
is_identity() const {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ is_identity() const {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH int NullTransitionWrapper::
|
||||
INLINE int NullTransitionWrapper::
|
||||
compare_to(const NullTransitionWrapper &) const {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ compare_to(const NullTransitionWrapper &) const {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
make_identity() {
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ make_identity() {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
extract_from(const NodeRelation *) {
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ extract_from(const NodeRelation *) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
store_to(NodeRelation *) const {
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ store_to(NodeRelation *) const {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
compose_in_place(const NullTransitionWrapper &) {
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ compose_in_place(const NullTransitionWrapper &) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
invert_in_place() {
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ invert_in_place() {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
invert_compose_in_place(const NullTransitionWrapper &) {
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ invert_compose_in_place(const NullTransitionWrapper &) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH Node *NullTransitionWrapper::
|
||||
INLINE Node *NullTransitionWrapper::
|
||||
extract_from_cache(const NodeRelation *) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -146,7 +146,7 @@ extract_from_cache(const NodeRelation *) {
|
|||
// Description: Stores this transition into the arc's cache, and
|
||||
// updates the arc's top_subtree.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
store_to_cache(NodeRelation *, Node *) {
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ store_to_cache(NodeRelation *, Node *) {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH bool NullTransitionWrapper::
|
||||
INLINE bool NullTransitionWrapper::
|
||||
is_cache_verified(UpdateSeq) const {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -165,7 +165,7 @@ is_cache_verified(UpdateSeq) const {
|
|||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
set_computed_verified(UpdateSeq) {
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ set_computed_verified(UpdateSeq) {
|
|||
// that indicated by value, using the cache as a helper,
|
||||
// and stores the result in this wrapper.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
cached_compose(const NullTransitionWrapper &,
|
||||
const NullTransitionWrapper &,
|
||||
UpdateSeq) {
|
||||
|
|
@ -187,7 +187,7 @@ cached_compose(const NullTransitionWrapper &,
|
|||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
output(ostream &) const {
|
||||
}
|
||||
|
||||
|
|
@ -196,11 +196,11 @@ output(ostream &) const {
|
|||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_GRAPH void NullTransitionWrapper::
|
||||
INLINE void NullTransitionWrapper::
|
||||
write(ostream &, int) const {
|
||||
}
|
||||
|
||||
INLINE_GRAPH ostream &operator << (ostream &out, const NullTransitionWrapper &ntw) {
|
||||
INLINE ostream &operator << (ostream &out, const NullTransitionWrapper &ntw) {
|
||||
ntw.output(out);
|
||||
return out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,47 +46,51 @@ class NodeRelation;
|
|||
// wrt(), but it's useful for passing to df_traverse()
|
||||
// to perform a traversal without bothering to keep
|
||||
// track of state.
|
||||
|
||||
// It is important that these functions be honestly
|
||||
// flagged INLINE, instead of INLINE_GRAPH, so that they
|
||||
// honestly get flagged as inline functions, so they can
|
||||
// be optimized away by the compiler. They don't hide
|
||||
// anything that can't be exported anyway.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA NullTransitionWrapper {
|
||||
public:
|
||||
typedef NullTransitionWrapper TransitionWrapper;
|
||||
|
||||
INLINE_GRAPH NullTransitionWrapper();
|
||||
INLINE_GRAPH NullTransitionWrapper(const NullTransitionWrapper ©);
|
||||
INLINE_GRAPH void operator = (const NullTransitionWrapper ©);
|
||||
INLINE NullTransitionWrapper();
|
||||
INLINE NullTransitionWrapper(const NullTransitionWrapper ©);
|
||||
INLINE void operator = (const NullTransitionWrapper ©);
|
||||
|
||||
INLINE_GRAPH static NullTransitionWrapper
|
||||
INLINE static NullTransitionWrapper
|
||||
init_from(const NullTransitionWrapper &other);
|
||||
|
||||
INLINE_GRAPH bool is_identity() const;
|
||||
INLINE_GRAPH int compare_to(const NullTransitionWrapper &other) const;
|
||||
INLINE bool is_identity() const;
|
||||
INLINE int compare_to(const NullTransitionWrapper &other) const;
|
||||
|
||||
INLINE_GRAPH void make_identity();
|
||||
INLINE_GRAPH void extract_from(const NodeRelation *arc);
|
||||
INLINE_GRAPH void store_to(NodeRelation *arc) const;
|
||||
INLINE void make_identity();
|
||||
INLINE void extract_from(const NodeRelation *arc);
|
||||
INLINE void store_to(NodeRelation *arc) const;
|
||||
|
||||
INLINE_GRAPH void compose_in_place(const NullTransitionWrapper &other);
|
||||
INLINE_GRAPH void invert_in_place();
|
||||
INLINE_GRAPH void invert_compose_in_place(const NullTransitionWrapper &other);
|
||||
INLINE void compose_in_place(const NullTransitionWrapper &other);
|
||||
INLINE void invert_in_place();
|
||||
INLINE void invert_compose_in_place(const NullTransitionWrapper &other);
|
||||
|
||||
INLINE_GRAPH Node *extract_from_cache(const NodeRelation *arc);
|
||||
INLINE_GRAPH void store_to_cache(NodeRelation *arc, Node *top_subtree);
|
||||
INLINE_GRAPH bool is_cache_verified(UpdateSeq now) const;
|
||||
INLINE_GRAPH void set_computed_verified(UpdateSeq now);
|
||||
INLINE Node *extract_from_cache(const NodeRelation *arc);
|
||||
INLINE void store_to_cache(NodeRelation *arc, Node *top_subtree);
|
||||
INLINE bool is_cache_verified(UpdateSeq now) const;
|
||||
INLINE void set_computed_verified(UpdateSeq now);
|
||||
|
||||
INLINE_GRAPH void cached_compose(const NullTransitionWrapper &cache,
|
||||
INLINE void cached_compose(const NullTransitionWrapper &cache,
|
||||
const NullTransitionWrapper &value,
|
||||
UpdateSeq now);
|
||||
|
||||
INLINE_GRAPH void output(ostream &out) const;
|
||||
INLINE_GRAPH void write(ostream &out, int indent_level = 0) const;
|
||||
INLINE void output(ostream &out) const;
|
||||
INLINE void write(ostream &out, int indent_level = 0) const;
|
||||
};
|
||||
|
||||
INLINE_GRAPH ostream &operator << (ostream &out, const NullTransitionWrapper &ntw);
|
||||
INLINE ostream &operator << (ostream &out, const NullTransitionWrapper &ntw);
|
||||
|
||||
#ifndef DONT_INLINE_GRAPH
|
||||
#include "nullTransitionWrapper.I"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "boundingHexahedron.h"
|
||||
#include "boundingLine.h"
|
||||
#include "config_mathutil.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@
|
|||
#include "pnmFileType.h"
|
||||
#include "config_pnmimage.h"
|
||||
|
||||
#include <string_utils.h>
|
||||
#include <indent.h>
|
||||
#include "string_utils.h"
|
||||
#include "indent.h"
|
||||
#include "pset.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
|||
|
|
@ -134,13 +134,3 @@
|
|||
test_linestream.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_types
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] putil
|
||||
|
||||
#define SOURCES \
|
||||
test_types.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "bamReaderParam.h"
|
||||
#include "factory.h"
|
||||
#include "vector_ushort.h"
|
||||
#include "pset.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "graphicsStateGuardianBase.h"
|
||||
#include "indent.h"
|
||||
#include "dcast.h"
|
||||
|
||||
TypeHandle AlphaTransformTransition::_type_handle;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
#include "fogTransition.h"
|
||||
|
||||
#include <indent.h>
|
||||
#include "dcast.h"
|
||||
#include "indent.h"
|
||||
|
||||
TypeHandle FogTransition::_type_handle;
|
||||
|
||||
|
|
|
|||
|
|
@ -170,8 +170,8 @@ forward_arc(NodeRelation *arc, NullTransitionWrapper &,
|
|||
*/
|
||||
}
|
||||
|
||||
AllTransitionsWrapper attrib(_initial_state);
|
||||
attrib.compose_in_place(trans);
|
||||
AllTransitionsWrapper attrib;
|
||||
attrib.compose_from(_initial_state, trans);
|
||||
|
||||
_gsg->set_state(attrib.get_transitions(), true);
|
||||
gnode->draw(_gsg);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,9 @@
|
|||
#include "vrpnDialDevice.h"
|
||||
#include "config_vrpn.h"
|
||||
|
||||
#include <string_utils.h>
|
||||
#include <indent.h>
|
||||
#include "dcast.h"
|
||||
#include "string_utils.h"
|
||||
#include "indent.h"
|
||||
|
||||
TypeHandle VrpnClient::_type_handle;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue