*** empty log message ***

This commit is contained in:
David Rose 2001-04-14 02:14:24 +00:00
parent b1f323a992
commit 259683160c
22 changed files with 576 additions and 217 deletions

View File

@ -738,7 +738,7 @@ void event_C(CPT_Event) {
void event_N(CPT_Event) {
nout << "Reducing scene graph.\n";
SceneGraphReducer gr(RenderRelation::get_class_type());
gr.apply_transitions(root);
gr.apply_transitions(first_arc);
int num_reduced = gr.flatten(root, true);
nout << "Removed " << num_reduced << " arcs.\n";
}
@ -1120,8 +1120,8 @@ int framework_main(int argc, char *argv[]) {
first_arc = new RenderRelation(render, root, 100);
if (files.empty() && framework.GetBool("have-omnitriangle", true)) {
// The user did not specify an file. Create some default
// geometry.
// The user did not specify a model file to load. Create some
// default geometry.
PTA_Vertexf coords;
PTA_TexCoordf uvs;

View File

@ -10,9 +10,9 @@
// attaches it.
////////////////////////////////////////////////////////////////////
INLINE NodeRelation::
NodeRelation(Node *parent, Node *to, int sort, TypeHandle type) :
NodeRelation(Node *parent, Node *to, int sort, TypeHandle graph_type) :
_parent(parent), _child(to), _sort(sort),
_type(type), _num_transitions(0)
_graph_type(graph_type), _num_transitions(0)
{
_top_subtree = NULL;
_attached = false;
@ -29,8 +29,8 @@ NodeRelation(Node *parent, Node *to, int sort, TypeHandle type) :
// general, attempt to create an unattached arc.
////////////////////////////////////////////////////////////////////
INLINE NodeRelation::
NodeRelation(TypeHandle type) :
_type(type)
NodeRelation(TypeHandle graph_type) :
_graph_type(graph_type)
{
_parent = NULL;
_child = NULL;
@ -49,14 +49,13 @@ NodeRelation(TypeHandle type) :
// unattached arc.
////////////////////////////////////////////////////////////////////
INLINE NodeRelation::
NodeRelation(void)
{
NodeRelation(void) {
_parent = NULL;
_child = NULL;
_sort = 0;
_top_subtree = NULL;
_attached = false;
_type = get_class_type();
_graph_type = get_class_type();
_num_transitions = 0;
}
@ -124,6 +123,20 @@ get_sort() const {
return _sort;
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::get_graph_type
// Access: Public
// Description: Returns the type of graph this arc represents. This
// is normally the same value as get_type(), i.e. the
// class type of the arc, but it may be set to any type.
// A node may simultaneously have many arcs of different
// types.
////////////////////////////////////////////////////////////////////
INLINE TypeHandle NodeRelation::
get_graph_type() const {
return _graph_type;
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::change_parent
// Access: Public
@ -189,6 +202,20 @@ set_sort(int sort) {
attach();
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::set_graph_type
// Access: Public
// Description: Changes the graph type of the arc. This moves the
// arc into a totally different graph; it may now be
// detected only by a special traversal.
////////////////////////////////////////////////////////////////////
INLINE void NodeRelation::
set_graph_type(TypeHandle graph_type) {
PT(NodeRelation) hold_arc = detach();
_graph_type = graph_type;
attach();
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::set_transition
// Access: Public
@ -390,6 +417,31 @@ get_factory() {
return *_factory;
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::get_class_type
// Access: Public, Static
// Description: Returns the TypeHandle associated with this type.
////////////////////////////////////////////////////////////////////
INLINE TypeHandle NodeRelation::
get_class_type() {
return _type_handle;
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::get_stashed_type
// Access: Public, Static
// Description: Returns a special TypeHandle that, by convention,
// arcs that wish to remove themselves from normal
// consideration during any traversal (including
// rendering and collision traversals), as well as
// removing themselves from the bounding volumes of
// their parents, should set their graph_type to.
////////////////////////////////////////////////////////////////////
INLINE TypeHandle NodeRelation::
get_stashed_type() {
return _stashed_type_handle;
}
////////////////////////////////////////////////////////////////////
// Function: get_transition_into
// Description: This external template function is handy for

View File

@ -12,6 +12,7 @@
#include <algorithm>
TypeHandle NodeRelation::_type_handle;
TypeHandle NodeRelation::_stashed_type_handle;
Factory<NodeRelation> *NodeRelation::_factory = NULL;
@ -507,8 +508,8 @@ attach() {
_attached = true;
DownRelationPointers &parent_list = _parent->_children[_type];
UpRelationPointers &child_list = _child->_parents[_type];
DownRelationPointers &parent_list = _parent->_children[_graph_type];
UpRelationPointers &child_list = _child->_parents[_graph_type];
bool inserted_one = internal_insert_arc(parent_list, this);
bool inserted_two = internal_insert_arc(child_list, this);
@ -516,7 +517,7 @@ attach() {
// Blow out the cache and increment the current update sequence.
_net_transitions.clear();
_last_update = ++last_graph_update(_type);
_last_update = ++last_graph_update(_graph_type);
// If we have just added a new parent arc to a node that previously
// had exactly one parent, we also need to set the update sequence
@ -557,8 +558,8 @@ detach() {
force_bound_stale();
DownRelationPointers &parent_list = _parent->_children[_type];
UpRelationPointers &child_list = _child->_parents[_type];
DownRelationPointers &parent_list = _parent->_children[_graph_type];
UpRelationPointers &child_list = _child->_parents[_graph_type];
bool removed_one = internal_remove_arc(parent_list, this);
bool removed_two = internal_remove_arc(child_list, this);
@ -570,7 +571,7 @@ detach() {
// Blow out the cache and increment the current update sequence.
_net_transitions.clear();
_last_update = ++last_graph_update(_type);
_last_update = ++last_graph_update(_graph_type);
// If we have just removed a parent arc from a node, leaving exactly
// one parent, we also need to set the update sequence
@ -580,6 +581,16 @@ detach() {
child_list[0]->_last_update = _last_update;
}
// If we have completely emptied the parent or child lists, remove
// the entry for this graph type from the node, as a small render
// optimization.
if (parent_list.empty()) {
_parent->_children.erase(_graph_type);
}
if (child_list.empty()) {
_child->_parents.erase(_graph_type);
}
return result;
}
@ -601,7 +612,7 @@ detach_below() {
force_bound_stale();
bool removed = internal_remove_arc(_child->_parents[_type], this);
bool removed = internal_remove_arc(_child->_parents[_graph_type], this);
nassertr(removed, result);
@ -609,7 +620,7 @@ detach_below() {
// Blow out the cache and increment the current update sequence.
_net_transitions.clear();
_last_update = ++last_graph_update(_type);
_last_update = ++last_graph_update(_graph_type);
return result;
}
@ -631,7 +642,7 @@ changed_transition(TypeHandle trans_type) {
if (_net_transitions != (NodeTransitionCache *)NULL) {
_net_transitions->clear_transition(trans_type);
}
_last_update = ++last_graph_update(get_type());
_last_update = ++last_graph_update(_graph_type);
}
////////////////////////////////////////////////////////////////////
@ -648,7 +659,7 @@ propagate_stale_bound() {
nassertv(node != (Node*)NULL);
UpRelations::const_iterator uri;
uri = node->_parents.find(get_type());
uri = node->_parents.find(_graph_type);
if (uri != node->_parents.end()) {
const UpRelationPointers &urp = (*uri).second;
@ -681,7 +692,7 @@ recompute_bound() {
child_volumes.push_back(&node->get_bound());
DownRelations::const_iterator dri;
dri = node->_children.find(get_type());
dri = node->_children.find(_graph_type);
if (dri != node->_children.end()) {
const DownRelationPointers &drp = (*dri).second;
@ -717,7 +728,7 @@ void NodeRelation::
write_datagram(BamWriter *manager, Datagram &me)
{
//Write out the "dynamic" type
manager->write_handle(me, _type);
manager->write_handle(me, _graph_type);
//We should always be attached if we are trying to write out
nassertv(_attached);
@ -769,7 +780,7 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager)
// We must explicitly add the arc to its child node, but not to
// its parent node.
UpRelationPointers &child_list = _child->_parents[_type];
UpRelationPointers &child_list = _child->_parents[_graph_type];
bool inserted = internal_insert_arc(child_list, this);
nassertr(inserted, _num_transitions + 2);
_attached = true;
@ -785,8 +796,9 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager)
//at old code
if (plist[i] == TypedWriteable::Null)
{
graph_cat->warning() << get_type().get_name()
<< "Ignoring null Transition" << endl;
graph_cat->warning()
<< get_type().get_name()
<< ": Ignoring null Transition" << endl;
}
else
{
@ -829,7 +841,7 @@ make_NodeRelation(const FactoryParams &params)
void NodeRelation::
fillin(DatagramIterator& scan, BamReader* manager)
{
_type = manager->read_handle(scan);
_graph_type = manager->read_handle(scan);
//Read in my parent
manager->read_pointer(scan, this);
//Read in my child
@ -855,3 +867,46 @@ register_with_read_factory(void)
{
BamReader::get_factory()->register_factory(get_class_type(), make_NodeRelation);
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::init_type
// Access: Public, Static
// Description: Initializes the TypeHandles associated with this
// class.
////////////////////////////////////////////////////////////////////
void NodeRelation::
init_type() {
TypedWriteableReferenceCount::init_type();
BoundedObject::init_type();
register_type(_type_handle, "NodeRelation",
TypedWriteableReferenceCount::get_class_type(),
BoundedObject::get_class_type());
register_type(_stashed_type_handle, "StashedNodeRelation",
get_class_type());
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::get_type
// Access: Public, Virtual
// Description: Returns the particular type represented by this
// instance of the class.
////////////////////////////////////////////////////////////////////
TypeHandle NodeRelation::
get_type() const {
return get_class_type();
}
////////////////////////////////////////////////////////////////////
// Function: NodeRelation::force_init_type
// Access: Public, Virtual
// Description: Called by the TypeHandle system when it is detected
// that init_type() was not called for some reason.
// This is only called in an error situation, and it
// attempts to remedy the problem so we can recover and
// continue.
////////////////////////////////////////////////////////////////////
TypeHandle NodeRelation::
force_init_type() {
init_type();
return get_class_type();
}

View File

@ -47,13 +47,13 @@ extern EXPCL_PANDA UpdateSeq &last_graph_update(TypeHandle graph_type);
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA NodeRelation : public TypedWriteableReferenceCount, public BoundedObject {
public:
INLINE NodeRelation(Node *from, Node *to, int sort, TypeHandle type);
INLINE NodeRelation(Node *from, Node *to, int sort, TypeHandle graph_type);
protected:
// Normally, this should only be used from derived classes for
// passing to the factory. Don't attempt to create an unattached
// arc directly.
INLINE NodeRelation(TypeHandle type);
INLINE NodeRelation(TypeHandle graph_type);
//make_NodeRelation needs to have a construct that takes nothing
//since it creates the object before it has any information
@ -80,12 +80,14 @@ PUBLISHED:
INLINE Node *get_parent() const;
INLINE Node *get_child() const;
INLINE int get_sort() const;
INLINE TypeHandle get_graph_type() const;
INLINE void change_parent(Node *parent);
INLINE void change_parent(Node *parent, int sort);
INLINE void change_child(Node *child);
INLINE void change_parent_and_child(Node *parent, Node *child);
INLINE void set_sort(int sort);
INLINE void set_graph_type(TypeHandle graph_type);
INLINE PT(NodeTransition) set_transition(TypeHandle handle,
NodeTransition *trans);
@ -141,7 +143,7 @@ private:
Node *_parent;
PT_Node _child;
int _sort;
TypeHandle _type;
TypeHandle _graph_type;
bool _attached;
private:
@ -193,24 +195,18 @@ protected:
virtual void propagate_stale_bound();
virtual void recompute_bound();
PUBLISHED:
INLINE static TypeHandle get_class_type();
INLINE static TypeHandle get_stashed_type();
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWriteableReferenceCount::init_type();
BoundedObject::init_type();
register_type(_type_handle, "NodeRelation",
TypedWriteableReferenceCount::get_class_type(),
BoundedObject::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static void init_type();
virtual TypeHandle get_type() const;
virtual TypeHandle force_init_type();
private:
static TypeHandle _type_handle;
static TypeHandle _stashed_type_handle;
friend INLINE void remove_arc(NodeRelation *arc);
friend class Node;

View File

@ -39,3 +39,13 @@ INLINE void RenderRelation::
register_with_factory() {
get_factory().register_factory(get_class_type(), make_arc);
}
////////////////////////////////////////////////////////////////////
// Function: RenderRelation::get_class_type
// Access: Public, Static
// Description: Returns the TypeHandle associated with this type.
////////////////////////////////////////////////////////////////////
INLINE TypeHandle RenderRelation::
get_class_type() {
return _type_handle;
}

View File

@ -98,3 +98,43 @@ register_with_read_factory(void)
{
BamReader::get_factory()->register_factory(get_class_type(), make_RenderRelation);
}
////////////////////////////////////////////////////////////////////
// Function: RenderRelation::init_type
// Access: Public, Static
// Description: Initializes the TypeHandles associated with this
// class.
////////////////////////////////////////////////////////////////////
void RenderRelation::
init_type() {
NodeRelation::init_type();
register_type(_type_handle, "RenderRelation",
NodeRelation::get_class_type());
}
////////////////////////////////////////////////////////////////////
// Function: RenderRelation::get_type
// Access: Public, Virtual
// Description: Returns the particular type represented by this
// instance of the class.
////////////////////////////////////////////////////////////////////
TypeHandle RenderRelation::
get_type() const {
return get_class_type();
}
////////////////////////////////////////////////////////////////////
// Function: RenderRelation::force_init_type
// Access: Public, Virtual
// Description: Called by the TypeHandle system when it is detected
// that init_type() was not called for some reason.
// This is only called in an error situation, and it
// attempts to remedy the problem so we can recover and
// continue.
////////////////////////////////////////////////////////////////////
TypeHandle RenderRelation::
force_init_type() {
init_type();
return get_class_type();
}

View File

@ -43,20 +43,12 @@ public:
static TypedWriteable *make_RenderRelation(const FactoryParams &params);
PUBLISHED:
static TypeHandle get_class_type() {
return _type_handle;
}
INLINE static TypeHandle get_class_type();
public:
static void init_type() {
NodeRelation::init_type();
register_type(_type_handle, "RenderRelation",
NodeRelation::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static void init_type();
virtual TypeHandle get_type() const;
virtual TypeHandle force_init_type();
private:
static TypeHandle _type_handle;

View File

@ -44,6 +44,17 @@ operator = (const FindApproxLevelEntry &copy) {
}
////////////////////////////////////////////////////////////////////
// Function: FindApproxLevelEntry::next_is_stashed
// Access: Public
// Description: Returns true if the next node matched by this entry
// must be a stashed node, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool FindApproxLevelEntry::
next_is_stashed() const {
return _approx_path.matches_stashed(_i);
}
////////////////////////////////////////////////////////////////////
// Function: FindApproxLevelEntry::is_solution
// Access: Public

View File

@ -30,6 +30,61 @@ output(ostream &out) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: FindApproxLevelEntry::consider_node
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void FindApproxLevelEntry::
consider_node(NodePathCollection &result, FindApproxLevel &next_level,
int max_matches, TypeHandle graph_type) const {
nassertv(_i < _approx_path.get_num_components());
if (_approx_path.is_component_match_many(_i)) {
// Match any number, zero or more, levels of nodes. This is the
// tricky case that requires this whole nutty breadth-first thing.
// This means we must reconsider our own entry with the next path
// entry, before we consider the next entry--this supports
// matching zero levels of nodes.
FindApproxLevelEntry reconsider(*this);
++reconsider._i;
if (reconsider.is_solution()) {
// Does this now represent a solution?
result.add_path(reconsider._node_path);
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
return;
}
} else {
reconsider.consider_node(result, next_level, max_matches, graph_type);
}
}
Node *bottom_node = _node_path.node();
nassertv(bottom_node != (Node *)NULL);
TypeHandle next_graph_type = graph_type;
if (next_is_stashed()) {
next_graph_type = NodeRelation::get_stashed_type();
}
DownRelations::const_iterator dri;
dri = bottom_node->_children.find(next_graph_type);
if (dri != bottom_node->_children.end()) {
const DownRelationPointers &drp = (*dri).second;
DownRelationPointers::const_iterator drpi;
for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
NodeRelation *arc = (*drpi);
consider_next_step(result, arc, next_level, max_matches, graph_type);
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
return;
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: FindApproxLevelEntry::consider_next_step
// Access: Public
@ -40,47 +95,28 @@ output(ostream &out) const {
// whatever additional entries are appropriate and
// stores them in next_level.
//
// If a complete solution is found, returns the solution
// node; otherwise, returns NULL.
// If a complete solution is found, stores it in result.
////////////////////////////////////////////////////////////////////
void FindApproxLevelEntry::
consider_next_step(NodePathCollection &result,
NodeRelation *arc, FindApproxLevel &next_level,
int max_matches) const {
int max_matches, TypeHandle graph_type) const {
nassertv(_i < _approx_path.get_num_components());
FindApproxLevelEntry next(*this);
bool eb = next._node_path.extend_by(arc);
nassertv(eb);
Node *child = arc->get_child();
if (_approx_path.is_component_match_many(_i)) {
// Match any number, zero or more, levels of nodes. This is the
// tricky case that requires this whole nutty breadth-first thing.
// This means we must reconsider our own entry with the next
// path entry, before we consider the next entry.
FindApproxLevelEntry reconsider(*this);
++reconsider._i;
if (reconsider.is_solution()) {
// Does this now represent a solution?
bool eb = reconsider._node_path.extend_by(arc);
nassertv(eb);
result.add_path(reconsider._node_path);
} else {
reconsider.consider_next_step(result, arc, next_level, max_matches);
}
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
return;
}
// And now we just add the next entry without incrementing its
// path entry.
next_level.add_entry(next);
} else {
if (_approx_path.matches_component(_i, child)) {
if (_approx_path.matches_component(_i, arc)) {
// That matched, and it consumes one path entry.
++next._i;
next_level.add_entry(next);

View File

@ -32,9 +32,13 @@ public:
INLINE FindApproxLevelEntry(const FindApproxLevelEntry &copy);
INLINE void operator = (const FindApproxLevelEntry &copy);
INLINE bool next_is_stashed() const;
void consider_node(NodePathCollection &result, FindApproxLevel &next_level,
int max_matches, TypeHandle graph_type) const;
void consider_next_step(NodePathCollection &result,
NodeRelation *arc, FindApproxLevel &next_level,
int max_matches) const;
int max_matches, TypeHandle graph_type) const;
INLINE bool is_solution() const;
void output(ostream &out) const;

View File

@ -20,10 +20,11 @@ FindApproxPath() {
// exactly.
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_name(const string &name) {
add_match_name(const string &name, int flags) {
Component comp;
comp._type = CT_match_name;
comp._name = name;
comp._flags = flags;
_path.push_back(comp);
}
@ -35,10 +36,11 @@ add_match_name(const string &name) {
// characters accepted.
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_name_glob(const string &name) {
add_match_name_glob(const string &name, int flags) {
Component comp;
comp._type = CT_match_name_glob;
comp._name = name;
comp._flags = flags;
_path.push_back(comp);
}
@ -49,10 +51,11 @@ add_match_name_glob(const string &name) {
// exactly, with no derived types matching.
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_exact_type(TypeHandle type) {
add_match_exact_type(TypeHandle type, int flags) {
Component comp;
comp._type = CT_match_exact_type;
comp._type_handle = type;
comp._flags = flags;
_path.push_back(comp);
}
@ -63,10 +66,11 @@ add_match_exact_type(TypeHandle type) {
// or be a base class of the node's type.
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_inexact_type(TypeHandle type) {
add_match_inexact_type(TypeHandle type, int flags) {
Component comp;
comp._type = CT_match_inexact_type;
comp._type_handle = type;
comp._flags = flags;
_path.push_back(comp);
}
@ -77,9 +81,10 @@ add_match_inexact_type(TypeHandle type) {
// chain of many nodes).
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_one() {
add_match_one(int flags) {
Component comp;
comp._type = CT_match_one;
comp._flags = flags;
_path.push_back(comp);
}
@ -90,9 +95,10 @@ add_match_one() {
// more consecutive nodes.
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_many() {
add_match_many(int flags) {
Component comp;
comp._type = CT_match_many;
comp._flags = flags;
_path.push_back(comp);
}
@ -103,10 +109,11 @@ add_match_many() {
// exactly, by pointer.
////////////////////////////////////////////////////////////////////
INLINE void FindApproxPath::
add_match_pointer(Node *pointer) {
add_match_pointer(Node *pointer, int flags) {
Component comp;
comp._type = CT_match_pointer;
comp._pointer = pointer;
comp._flags = flags;
_path.push_back(comp);
}
@ -139,9 +146,24 @@ is_component_match_many(int index) const {
// the indicated node, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool FindApproxPath::
matches_component(int index, Node *node) const {
matches_component(int index, NodeRelation *arc) const {
nassertr(index >= 0 && index < (int)_path.size(), false);
return (_path[index].matches(node));
return (_path[index].matches(arc));
}
////////////////////////////////////////////////////////////////////
// Function: FindApproxPath::matches_stashed
// Access: Public
// Description: Returns true if the nth component of the path matches
// a stashed node only, false otherwise.
////////////////////////////////////////////////////////////////////
INLINE bool FindApproxPath::
matches_stashed(int index) const {
if (index >= 0 && index < (int)_path.size()) {
return ((_path[index]._flags & CF_stashed) != 0);
} else {
return false;
}
}
////////////////////////////////////////////////////////////////////

View File

@ -9,6 +9,7 @@
#include <globPattern.h>
#include <node.h>
#include <namedNode.h>
#include <nodeRelation.h>
////////////////////////////////////////////////////////////////////
@ -18,7 +19,8 @@
// component, false otherwise.
////////////////////////////////////////////////////////////////////
bool FindApproxPath::Component::
matches(Node *node) const {
matches(NodeRelation *arc) const {
Node *node = arc->get_child();
string node_name;
switch (_type) {
@ -113,12 +115,22 @@ add_string(const string &str_path) {
// the string component was in some way invalid.
////////////////////////////////////////////////////////////////////
bool FindApproxPath::
add_component(const string &str_component) {
add_component(string str_component) {
int flags = 0;
if (str_component.size() >= 2 && str_component.substr(0, 2) == "@@") {
flags |= CF_stashed;
str_component = str_component.substr(2);
}
if (str_component == "*") {
add_match_one();
add_match_one(flags);
} else if (str_component == "**") {
add_match_many();
if ((flags & CF_stashed) != 0) {
sgmanip_cat.warning()
<< "@@** is ambiguous; use @@*/** or **/@@* instead.\n";
}
add_match_many(flags);
} else if (!str_component.empty() && str_component[0] == '-') {
string type_name = str_component.substr(1);
@ -130,7 +142,7 @@ add_component(const string &str_component) {
return false;
} else {
add_match_exact_type(handle);
add_match_exact_type(handle, flags);
}
} else if (!str_component.empty() && str_component[0] == '+') {
@ -143,11 +155,11 @@ add_component(const string &str_component) {
return false;
} else {
add_match_inexact_type(handle);
add_match_inexact_type(handle, flags);
}
} else {
add_match_name_glob(str_component);
add_match_name_glob(str_component, flags);
}
return true;

View File

@ -14,6 +14,7 @@
#include <vector>
class Node;
class NodeRelation;
////////////////////////////////////////////////////////////////////
// Class : FindApproxPath
@ -27,19 +28,20 @@ public:
INLINE FindApproxPath();
bool add_string(const string &str_path);
bool add_component(const string &str_component);
bool add_component(string str_component);
INLINE void add_match_name(const string &name);
INLINE void add_match_name_glob(const string &glob);
INLINE void add_match_exact_type(TypeHandle type);
INLINE void add_match_inexact_type(TypeHandle type);
INLINE void add_match_one();
INLINE void add_match_many();
INLINE void add_match_pointer(Node *pointer);
INLINE void add_match_name(const string &name, int flags);
INLINE void add_match_name_glob(const string &glob, int flags);
INLINE void add_match_exact_type(TypeHandle type, int flags);
INLINE void add_match_inexact_type(TypeHandle type, int flags);
INLINE void add_match_one(int flags);
INLINE void add_match_many(int flags);
INLINE void add_match_pointer(Node *pointer, int flags);
INLINE int get_num_components() const;
INLINE bool is_component_match_many(int index) const;
INLINE bool matches_component(int index, Node *node) const;
INLINE bool matches_component(int index, NodeRelation *arc) const;
INLINE bool matches_stashed(int index) const;
void output(ostream &out) const;
INLINE void output_component(ostream &out, int index) const;
@ -58,16 +60,20 @@ private:
CT_match_many,
CT_match_pointer
};
enum ComponentFlags {
CF_stashed = 0x001,
};
class Component {
public:
bool matches(Node *node) const;
bool matches(NodeRelation *arc) const;
void output(ostream &out) const;
ComponentType _type;
string _name;
TypeHandle _type_handle;
Node *_pointer;
int _flags;
};
typedef vector<Component> Path;

View File

@ -98,6 +98,7 @@ INLINE NodePath::
NodePath(const ArcChain &chain, TypeHandle graph_type) :
NodePathBase(chain, graph_type)
{
reset_top_node();
nassertv(verify_connectivity());
}
@ -262,6 +263,18 @@ get_num_nodes() const {
return get_num_arcs() + 1;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_top_node
// Access: Public
// Description: Returns the top node of the path, or NULL if the path
// is empty.
////////////////////////////////////////////////////////////////////
INLINE Node *NodePath::
get_top_node() {
reset_top_node();
return _top_node;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::node
// Access: Public
@ -1409,6 +1422,13 @@ show() {
// Access: Public
// Description: Puts a PruneTransition on this bottom arc so that the
// geometry at this level and below will be invisible.
//
// However, it will remain part of the scene graph, and
// will still be counted in its parent's bounding
// volume; furthermore, traversals like the collision
// traversal will still visit the node.
//
// See stash() for a more thorough way to hide the node.
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
hide() {
@ -1439,3 +1459,61 @@ INLINE void NodePath::
hide_collision_solids() {
find_all_matches("**/+CollisionNode").hide();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::is_hidden
// Access: Public
// Description: Returns true if some arc above this bottom node has
// been set to 'hide', false if it should be visible.
////////////////////////////////////////////////////////////////////
INLINE bool NodePath::
is_hidden() const {
return !get_hidden_ancestor().is_empty();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::stash
// Access: Public
// Description: A more thorough version of hide(), this effectively
// removes the bottom node from the scene graph--it does
// not appear in any traversals, rendering or otherwise,
// and cannot be located again via NodePath::find().
// The node is also removed from its parents' bounding
// volume.
//
// However, the node is still associated with its
// parent, and will be removed if the parent is removed,
// and it can be revealed again by a future call to
// unstash().
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
stash() {
nassertv(has_arcs());
nassertv(_head != (ArcComponent *)NULL);
_head->_arc->set_graph_type(NodeRelation::get_stashed_type());
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::unstash
// Access: Public
// Description: Reveals a node that was previously hidden via stash().
////////////////////////////////////////////////////////////////////
INLINE void NodePath::
unstash() {
nassertv(has_arcs());
nassertv(_head != (ArcComponent *)NULL);
_head->_arc->set_graph_type(_head->_arc->get_type());
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::is_stashed
// Access: Public
// Description: Returns true if some arc above this bottom node has
// been set to 'stash', false if it should be visible.
////////////////////////////////////////////////////////////////////
INLINE bool NodePath::
is_stashed() const {
return !get_stashed_ancestor().is_empty();
}

View File

@ -122,8 +122,6 @@ bool NodePath::
extend_by(NodeRelation *arc) {
nassertr(verify_connectivity(), false);
nassertr(arc != (NodeRelation *)NULL, false);
// Make sure the graph types are consistent.
nassertr(arc->get_type() == _graph_type, false);
if (is_empty()) {
nassertr(_head == (ArcComponent *)NULL, false);
@ -212,8 +210,8 @@ extend_down_to(Node *dnode) {
nassertr(verify_connectivity(), false);
NodePathCollection col;
FindApproxPath approx_path;
approx_path.add_match_many();
approx_path.add_match_pointer(dnode);
approx_path.add_match_many(0);
approx_path.add_match_pointer(dnode, 0);
find_matches(col, approx_path, -1);
if (col.is_empty()) {
@ -352,8 +350,8 @@ find_all_paths_down_to(Node *dnode) const {
nassertr(verify_connectivity(), col);
nassertr(dnode != (Node *)NULL, col);
FindApproxPath approx_path;
approx_path.add_match_many();
approx_path.add_match_pointer(dnode);
approx_path.add_match_many(0);
approx_path.add_match_pointer(dnode, 0);
find_matches(col, approx_path, -1);
return col;
}
@ -485,30 +483,6 @@ get_arc(int index) const {
return comp->_arc;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_top_node
// Access: Public
// Description: Returns the top node of the path, or NULL if the path
// is empty. This requires iterating through the path.
////////////////////////////////////////////////////////////////////
Node *NodePath::
get_top_node() const {
if (_head == (ArcComponent *)NULL) {
// A singleton or empty list.
return _top_node;
}
ArcComponent *comp = _head;
while (comp->_next != (ArcComponent *)NULL) {
comp = comp->_next;
}
// This assertion should not fail unless there is a logic error in
// the above.
nassertr(comp != (ArcComponent *)NULL, NULL);
return comp->_arc->get_parent();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::share_with
// Access: Public
@ -604,12 +578,6 @@ verify_connectivity() const {
return false;
}
// We also want to verify that all of the arcs are of the proper
// type.
if (comp->_arc->get_type() != _graph_type) {
return false;
}
comp = comp->_next;
while (comp != (const ArcComponent *)NULL) {
Node *next_parent = comp->_arc->get_parent();
@ -620,15 +588,21 @@ verify_connectivity() const {
if (next_child != parent) {
return false;
}
if (comp->_arc->get_type() != _graph_type) {
return false;
}
parent = next_parent;
child = next_child;
comp = comp->_next;
}
// We cannot insist that _top_node be correct, since it might have
// wandered, particularly if our parent path has changed without our
// knowledge.
/*
if (parent != _top_node) {
return false;
}
*/
return true;
}
@ -666,15 +640,6 @@ amputate_badness() {
return false;
}
// We also want to verify that all of the arcs are of the proper
// type.
if (comp->_arc->get_type() != _graph_type) {
// Eek! The bottom arc is broken!
_top_node = child;
_head = (ArcComponent *)NULL;
return false;
}
ArcComponent *prev = comp;
comp = comp->_next;
while (comp != (const ArcComponent *)NULL) {
@ -682,14 +647,12 @@ amputate_badness() {
Node *next_child = comp->_arc->get_child();
if (next_parent == (Node *)NULL || next_child == (Node *)NULL) {
prev->_next = (ArcComponent *)NULL;
_top_node = parent;
return false;
}
if (next_child != parent) {
prev->_next = (ArcComponent *)NULL;
return false;
}
if (comp->_arc->get_type() != _graph_type) {
prev->_next = (ArcComponent *)NULL;
_top_node = parent;
return false;
}
@ -714,6 +677,14 @@ amputate_badness() {
////////////////////////////////////////////////////////////////////
bool NodePath::
repair_connectivity(const NodePath &top) {
// If the only problem is the top node, we can fix that first.
reset_top_node();
if (verify_connectivity()) {
return true;
}
nassertr(top.verify_connectivity(), false);
NodePath new_path(*this);
new_path.amputate_badness();
if (new_path.is_empty()) {
@ -731,6 +702,7 @@ repair_connectivity(const NodePath &top) {
}
(*this) = full_path;
return true;
}
@ -767,6 +739,7 @@ reparent_to(const NodePath &other, int sort) {
// update our own path, as well as all paths that share the same
// head pointer (i.e. all paths derived from this one).
_head->_next = other._head;
_top_node = other._top_node;
}
////////////////////////////////////////////////////////////////////
@ -832,6 +805,7 @@ instance_to(const NodePath &other, int sort) const {
NodePath instance(*this);
instance._head = new ArcComponent(darc, other._head);
instance._top_node = other._top_node;
return instance;
}
@ -874,6 +848,7 @@ copy_to(const NodePath &other, int sort) const {
NodePath instance(*this);
instance._head = new ArcComponent(darc, other._head);
instance._top_node = other._top_node;
return instance;
}
@ -1080,7 +1055,7 @@ int NodePath::
flatten_medium() {
nassertr(!is_empty(), 0);
SceneGraphReducer gr(_graph_type);
gr.apply_transitions(node());
gr.apply_transitions(arc());
int num_removed = gr.flatten(node(), false);
if (sgmanip_cat.is_debug()) {
@ -1112,7 +1087,7 @@ int NodePath::
flatten_strong() {
nassertr(!is_empty(), 0);
SceneGraphReducer gr(_graph_type);
gr.apply_transitions(node());
gr.apply_transitions(arc());
int num_removed = gr.flatten(node(), true);
if (sgmanip_cat.is_debug()) {
@ -2312,17 +2287,6 @@ get_transparency() const {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::is_hidden
// Access: Public
// Description: Returns true if some arc above this bottom node has
// been set to 'hide', false if it should be visible.
////////////////////////////////////////////////////////////////////
bool NodePath::
is_hidden() const {
return !get_hidden_ancestor().is_empty();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_hidden_ancestor
// Access: Public
@ -2351,6 +2315,33 @@ get_hidden_ancestor() const {
return next.get_hidden_ancestor();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::get_stashed_ancestor
// Access: Public
// Description: Returns a NodePath indicating the lowest arc above
// this node which has been set to 'stash'. Calling
// unstash() on the NodePath returned by this function
// should make the node visible again (unless there is
// another arc further up that also has been 'stashed'.
//
// This function returns an empty NodePath if no
// ancestors have been 'stashed'.
////////////////////////////////////////////////////////////////////
NodePath NodePath::
get_stashed_ancestor() const {
if (!has_arcs()) {
return NodePath();
}
nassertr(_head != (ArcComponent *)NULL, NodePath());
if (_head->_arc->get_graph_type() != _graph_type) {
return *this;
}
NodePath next(*this);
next.shorten();
return next.get_stashed_ancestor();
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::prepare_scene
// Access: Public
@ -2450,6 +2441,27 @@ write_bounds(ostream &out) const {
get_bounds()->write(out);
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::reset_top_node
// Access: Private
// Description: Recomputes the _top_node member to accurately reflect
// the top node of the chain.
////////////////////////////////////////////////////////////////////
void NodePath::
reset_top_node() {
if (_head != (ArcComponent *)NULL) {
ArcComponent *comp = _head;
while (comp->_next != (ArcComponent *)NULL) {
comp = comp->_next;
}
// This assertion should not fail unless there is a logic error in
// the above.
nassertv(comp != (ArcComponent *)NULL);
_top_node = comp->_arc->get_parent();
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::r_compare_to
// Access: Private, Static
@ -2513,8 +2525,9 @@ r_as_string(const ArcComponent *comp, string &result, int skip_nodes) const {
// Here's the end of the chain.
if (skip_nodes == 0) {
// Skip no nodes; return the full name.
result = format_node_name(comp->_arc->get_parent()) + "/" +
format_node_name(comp->_arc->get_child());
result = format_node_name(comp->_arc->get_parent());
result += format_arc_name(comp->_arc);
result += format_node_name(comp->_arc->get_child());
} else if (skip_nodes == 1) {
// Skip the first node.
@ -2530,14 +2543,13 @@ r_as_string(const ArcComponent *comp, string &result, int skip_nodes) const {
// This is not the first node, so format a slash between the
// previous node and this node.
if (comp->_arc->get_child() == (Node *)NULL ||
comp->_arc->get_parent() == comp->_next->_arc->get_child()) {
result += "/";
} else {
if (!(comp->_arc->get_child() == (Node *)NULL ||
comp->_arc->get_parent() == comp->_next->_arc->get_child())) {
// Unless the path is broken here. In this case, insert a
// visual indication of the break.
result += "/.../" + format_node_name(comp->_arc->get_parent()) + "/";
result += "/.../" + format_node_name(comp->_arc->get_parent());
}
result += format_arc_name(comp->_arc);
result += format_node_name(comp->_arc->get_child());
}
}
@ -2615,6 +2627,28 @@ format_node_name(Node *dnode) const {
return name;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::format_arc_name
// Access: Private
// Description: Formats the "name" for the arc in as_string().
// Normally, this is simply "/", but for certain arcs
// (as for stashed nodes, for instance), it might
// contain other characters.
////////////////////////////////////////////////////////////////////
string NodePath::
format_arc_name(NodeRelation *arc) const {
string result = "/";
if (arc->get_graph_type() == NodeRelation::get_stashed_type()) {
result += "@@";
} else if (arc->get_graph_type() != _graph_type) {
result += "@@(" + arc->get_graph_type().get_name() + ")";
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: NodePath::find_matches
// Access: Private
@ -2685,33 +2719,18 @@ r_find_matches(NodePathCollection &result,
FindApproxLevel::Vec::const_iterator li;
for (li = level._v.begin(); li != level._v.end(); ++li) {
const FindApproxLevelEntry &entry = (*li);
if (entry.is_solution()) {
// Does this entry already represent a solution?
result.add_path(entry._node_path);
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
return;
}
} else {
Node *bottom_node = entry._node_path.node();
nassertv(bottom_node != (Node *)NULL);
entry.consider_node(result, next_level, max_matches, _graph_type);
}
DownRelations::const_iterator dri;
dri = bottom_node->_children.find(_graph_type);
if (dri != bottom_node->_children.end()) {
const DownRelationPointers &drp = (*dri).second;
DownRelationPointers::const_iterator drpi;
for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
NodeRelation *arc = (*drpi);
entry.consider_next_step(result, arc, next_level, max_matches);
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
return;
}
}
}
}
}
// Now recurse on the next level.
r_find_matches(result, next_level, max_matches, num_levels_remaining);

View File

@ -154,7 +154,7 @@ PUBLISHED:
int get_num_arcs() const;
NodeRelation *get_arc(int index) const;
Node *get_top_node() const;
INLINE Node *get_top_node();
INLINE Node *node() const;
INLINE NodeRelation *arc() const;
@ -442,9 +442,14 @@ PUBLISHED:
INLINE void hide();
INLINE void show_collision_solids();
INLINE void hide_collision_solids();
bool is_hidden() const;
INLINE bool is_hidden() const;
NodePath get_hidden_ancestor() const;
INLINE void stash();
INLINE void unstash();
INLINE bool is_stashed() const;
NodePath get_stashed_ancestor() const;
void prepare_scene(GraphicsStateGuardianBase *gsg);
void show_bounds();
@ -466,6 +471,7 @@ public:
};
private:
void reset_top_node();
static int r_compare_to(const ArcComponent *a, const ArcComponent *v);
bool r_extend_by(const ArcComponent *other);
int r_as_string(const ArcComponent *comp, string &result,
@ -475,6 +481,7 @@ private:
void r_get_net_transitions(const ArcComponent *comp,
AllTransitionsWrapper &trans) const;
string format_node_name(Node *dnode) const;
string format_arc_name(NodeRelation *arc) const;
void find_matches(NodePathCollection &result,
const string &approx_path_str,

View File

@ -32,8 +32,14 @@ protected:
// Most of the interesting part of NodePathBase is inherited from
// ArcChain. This gives us a sharable linked list of arcs.
// The _top_node pointer is only used when the NodePath is a
// singleton. If there is at least one arc, this is ignored.
// We also add an explicit pointer to the top node in the chain,
// mainly to allow us to define a NodePath containing a single node,
// even if the chain of arcs is empty.
// If the chain is nonempty, this might still be useful (int that it
// keeps a reference count to the top node), but this is problematic
// since it will not automatically update if our parent is changed
// without our knowledge.
PT_Node _top_node;
TypeHandle _graph_type;

View File

@ -348,6 +348,30 @@ hide() {
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::stash
// Access: Published
// Description: Stashes all NodePaths in the collection.
////////////////////////////////////////////////////////////////////
void NodePathCollection::
stash() {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).stash();
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::unstash
// Access: Published
// Description: Unstashes all NodePaths in the collection.
////////////////////////////////////////////////////////////////////
void NodePathCollection::
unstash() {
for (int i = 0; i < get_num_paths(); i++) {
get_path(i).unstash();
}
}
////////////////////////////////////////////////////////////////////
// Function: NodePathCollection::output
// Access: Published

View File

@ -54,6 +54,8 @@ PUBLISHED:
void show();
void hide();
void stash();
void unstash();
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;

View File

@ -89,7 +89,7 @@ SceneGraphReducer(TypeHandle graph_type) :
// operations impossible.
////////////////////////////////////////////////////////////////////
void SceneGraphReducer::
apply_transitions(Node *root, int transition_types) {
apply_transitions(NodeRelation *arc, int transition_types) {
AccumulatedTransitions trans;
if ((transition_types & TT_transform) != 0) {
trans._transform = new TransformTransition;
@ -101,20 +101,7 @@ apply_transitions(Node *root, int transition_types) {
trans._texture_matrix = new TexMatrixTransition;
}
DownRelations::const_iterator dri;
dri = root->_children.find(_graph_type);
if (dri != root->_children.end()) {
// We must make a temporary copy of the DownRelationPointers,
// because we'll be modifying this list as we go.
DownRelationPointers drp = (*dri).second;
DownRelationPointers::const_iterator drpi;
for (drpi = drp.begin(); drpi != drp.end(); ++drpi) {
NodeRelation *child_arc = (*drpi);
r_apply_transitions(child_arc, transition_types, trans, false);
}
}
r_apply_transitions(arc, transition_types, trans, false);
}
////////////////////////////////////////////////////////////////////

View File

@ -36,7 +36,7 @@ public:
TT_texture_matrix = 0x004,
};
void apply_transitions(Node *root, int transition_types = ~0);
void apply_transitions(NodeRelation *arc, int transition_types = ~0);
protected:
class AccumulatedTransitions {

View File

@ -510,7 +510,7 @@ do_rebuild() {
if (flatten_text) {
SceneGraphReducer gr(RenderRelation::get_class_type());
gr.apply_transitions(_root);
gr.apply_transitions(_root_arc);
gr.flatten(_root, true);
}
}