mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 01:44:06 -04:00
pgraph find
This commit is contained in:
parent
fc26653ada
commit
adfa89b233
@ -314,8 +314,6 @@ class ShowBase:
|
||||
per application.
|
||||
"""
|
||||
|
||||
print 'setup mouse'
|
||||
|
||||
# We create both a MouseAndKeyboard object and a MouseWatcher object
|
||||
# for the window. The MouseAndKeyboard generates mouse events and
|
||||
# mouse button/keyboard events; the MouseWatcher passes them through
|
||||
@ -341,7 +339,12 @@ class ShowBase:
|
||||
self.drive = self.dataUnused.attachNewNode(DriveInterface('drive'))
|
||||
self.mouse2cam = self.dataUnused.attachNewNode(Transform2SG('mouse2cam'))
|
||||
self.mouse2cam.node().setNode(self.camera.node())
|
||||
self.useDrive()
|
||||
|
||||
# The default is trackball mode, which is more convenient for
|
||||
# ad-hoc development in Python using ShowBase. Applications
|
||||
# can expclitly call base.useDrive() if they prefer a drive
|
||||
# interface.
|
||||
self.useTrackball()
|
||||
|
||||
# A ButtonThrower to generate events from the mouse and
|
||||
# keyboard buttons as they are pressed.
|
||||
@ -386,8 +389,7 @@ class ShowBase:
|
||||
# one.
|
||||
for i in range(chanConfig.getNumGroups()):
|
||||
camera = self.camera.attachNewNode(chanConfig.getGroupNode(i))
|
||||
#cam = camera.find('**/+Camera')
|
||||
cam = camera.getChild(0)
|
||||
cam = camera.find('**/+Camera')
|
||||
lens = cam.node().getLens()
|
||||
|
||||
# Enforce our expected aspect ratio, overriding whatever
|
||||
|
@ -244,6 +244,7 @@ reconnect() {
|
||||
int num_parents = get_num_parents();
|
||||
_data_connections.clear();
|
||||
// Look for each input among one of the parents.
|
||||
int num_datanode_parents = 0;
|
||||
|
||||
Wires::const_iterator wi;
|
||||
for (wi = _input_wires.begin(); wi != _input_wires.end(); ++wi) {
|
||||
@ -255,6 +256,7 @@ reconnect() {
|
||||
PandaNode *parent_node = get_parent(i);
|
||||
if (parent_node->is_of_type(qpDataNode::get_class_type())) {
|
||||
qpDataNode *data_node = DCAST(qpDataNode, parent_node);
|
||||
num_datanode_parents++;
|
||||
Wires::const_iterator pi;
|
||||
pi = data_node->_output_wires.find(name);
|
||||
if (pi != data_node->_output_wires.end()) {
|
||||
@ -282,7 +284,8 @@ reconnect() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_data_connections.empty() && get_num_inputs() != 0 && num_parents != 0) {
|
||||
if (_data_connections.empty() && get_num_inputs() != 0 &&
|
||||
num_datanode_parents != 0) {
|
||||
dgraph_cat.warning()
|
||||
<< "No data connected to " << *this << "\n";
|
||||
}
|
||||
|
@ -27,6 +27,9 @@
|
||||
depthTestAttrib.h depthTestAttrib.I \
|
||||
depthWriteAttrib.h depthWriteAttrib.I \
|
||||
drawCullHandler.h drawCullHandler.I \
|
||||
qpfindApproxLevel.I qpfindApproxLevel.h \
|
||||
qpfindApproxLevelEntry.I qpfindApproxLevelEntry.h \
|
||||
qpfindApproxPath.I qpfindApproxPath.h \
|
||||
qpgeomNode.h qpgeomNode.I \
|
||||
qplensNode.h qplensNode.I \
|
||||
qplodNode.h qplodNode.I \
|
||||
@ -67,6 +70,9 @@
|
||||
depthTestAttrib.cxx \
|
||||
depthWriteAttrib.cxx \
|
||||
drawCullHandler.cxx \
|
||||
qpfindApproxLevel.cxx \
|
||||
qpfindApproxLevelEntry.cxx \
|
||||
qpfindApproxPath.cxx \
|
||||
qpgeomNode.cxx \
|
||||
qplensNode.cxx \
|
||||
qplodNode.cxx \
|
||||
@ -129,6 +135,11 @@
|
||||
transformState.h transformState.I \
|
||||
transparencyAttrib.h transparencyAttrib.I
|
||||
|
||||
// No need to install these.
|
||||
// qpfindApproxLevel.I qpfindApproxLevel.h \
|
||||
// qpfindApproxLevelEntry.I qpfindApproxLevelEntry.h \
|
||||
// qpfindApproxPath.I qpfindApproxPath.h \
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
@ -1380,7 +1380,7 @@ fix_path_lengths(const CData *cdata) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNode::
|
||||
r_list_descendants(ostream &out, int indent_level) const {
|
||||
write(out, indent_level);
|
||||
indent(out, indent_level) << *this << "\n";
|
||||
|
||||
CDReader cdata(_cycler);
|
||||
Down::const_iterator di;
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include "depthTestAttrib.cxx"
|
||||
#include "depthWriteAttrib.cxx"
|
||||
#include "drawCullHandler.cxx"
|
||||
#include "qpfindApproxPath.cxx"
|
||||
#include "qpfindApproxLevel.cxx"
|
||||
#include "qpfindApproxLevelEntry.cxx"
|
||||
#include "qpgeomNode.cxx"
|
||||
#include "qplensNode.cxx"
|
||||
#include "qplodNode.cxx"
|
||||
|
29
panda/src/pgraph/qpfindApproxLevel.I
Normal file
29
panda/src/pgraph/qpfindApproxLevel.I
Normal file
@ -0,0 +1,29 @@
|
||||
// Filename: qpfindApproxLevel.I
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: qpFindApproxLevel::add_entry
|
||||
// Access: Public
|
||||
// Description: Adds a new entry to the level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxLevel::
|
||||
add_entry(const qpFindApproxLevelEntry &entry) {
|
||||
_v.push_back(entry);
|
||||
}
|
||||
|
34
panda/src/pgraph/qpfindApproxLevel.cxx
Normal file
34
panda/src/pgraph/qpfindApproxLevel.cxx
Normal file
@ -0,0 +1,34 @@
|
||||
// Filename: qpfindApproxLevel.cxx
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "qpfindApproxLevel.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevel::write
|
||||
// Access: Public
|
||||
// Description: Shows the entire contents of the level, one entry per
|
||||
// line. For debugging only.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpFindApproxLevel::
|
||||
write(ostream &out) const {
|
||||
Vec::const_iterator vi;
|
||||
for (vi = _v.begin(); vi != _v.end(); ++vi) {
|
||||
(*vi).output(out);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
46
panda/src/pgraph/qpfindApproxLevel.h
Normal file
46
panda/src/pgraph/qpfindApproxLevel.h
Normal file
@ -0,0 +1,46 @@
|
||||
// Filename: qpfindApproxLevel.h
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 qpFINDAPPROXLEVEL_H
|
||||
#define qpFINDAPPROXLEVEL_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "qpfindApproxLevelEntry.h"
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpFindApproxLevel
|
||||
// Description : This class is local to this package only; it doesn't
|
||||
// get exported. It maintains the list of nodes
|
||||
// find_approx() considers for each level of the scene
|
||||
// graph it visits, in its breadth-first search.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class qpFindApproxLevel {
|
||||
public:
|
||||
INLINE void add_entry(const qpFindApproxLevelEntry &entry);
|
||||
|
||||
void write(ostream &out) const;
|
||||
|
||||
typedef pvector<qpFindApproxLevelEntry> Vec;
|
||||
Vec _v;
|
||||
};
|
||||
|
||||
#include "qpfindApproxLevel.I"
|
||||
|
||||
#endif
|
80
panda/src/pgraph/qpfindApproxLevelEntry.I
Normal file
80
panda/src/pgraph/qpfindApproxLevelEntry.I
Normal file
@ -0,0 +1,80 @@
|
||||
// Filename: qpfindApproxLevelEntry.I
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: qpFindApproxLevelEntry::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpFindApproxLevelEntry::
|
||||
qpFindApproxLevelEntry(const qpNodePath &node_path, qpFindApproxPath &approx_path) :
|
||||
_node_path(node_path),
|
||||
_approx_path(approx_path)
|
||||
{
|
||||
_i = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::Copy Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpFindApproxLevelEntry::
|
||||
qpFindApproxLevelEntry(const qpFindApproxLevelEntry ©) :
|
||||
_node_path(copy._node_path),
|
||||
_i(copy._i),
|
||||
_approx_path(copy._approx_path)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::Copy Assignment Operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxLevelEntry::
|
||||
operator = (const qpFindApproxLevelEntry ©) {
|
||||
_node_path = copy._node_path;
|
||||
_i = copy._i;
|
||||
nassertv(&_approx_path == ©._approx_path);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::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 qpFindApproxLevelEntry::
|
||||
next_is_stashed() const {
|
||||
return _approx_path.matches_stashed(_i);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::is_solution
|
||||
// Access: Public
|
||||
// Description: Returns true if this entry represents a solution to
|
||||
// the search; i.e. all the components of the path have
|
||||
// been successfully matched.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpFindApproxLevelEntry::
|
||||
is_solution() const {
|
||||
return (_i >= _approx_path.get_num_components());
|
||||
}
|
149
panda/src/pgraph/qpfindApproxLevelEntry.cxx
Normal file
149
panda/src/pgraph/qpfindApproxLevelEntry.cxx
Normal file
@ -0,0 +1,149 @@
|
||||
// Filename: qpfindApproxLevelEntry.cxx
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "qpfindApproxLevelEntry.h"
|
||||
#include "qpnodePathCollection.h"
|
||||
#include "pandaNode.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::output
|
||||
// Access: Public
|
||||
// Description: Formats the entry for meaningful output. For
|
||||
// debugging only.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpFindApproxLevelEntry::
|
||||
output(ostream &out) const {
|
||||
out << "(" << _node_path << "):";
|
||||
if (is_solution()) {
|
||||
out << " solution!";
|
||||
} else {
|
||||
out << "(";
|
||||
_approx_path.output_component(out, _i);
|
||||
out << ")," << _i;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::consider_node
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpFindApproxLevelEntry::
|
||||
consider_node(qpNodePathCollection &result, qpFindApproxLevel &next_level,
|
||||
int max_matches) 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.
|
||||
qpFindApproxLevelEntry 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);
|
||||
}
|
||||
}
|
||||
|
||||
PandaNode *this_node = _node_path.node();
|
||||
nassertv(this_node != (PandaNode *)NULL);
|
||||
|
||||
bool stashed_only = next_is_stashed();
|
||||
|
||||
if (!stashed_only) {
|
||||
// Check the normal list of children.
|
||||
int num_children = this_node->get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
PandaNode *child_node = this_node->get_child(i);
|
||||
|
||||
consider_next_step(result, child_node, next_level, max_matches);
|
||||
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_approx_path.return_stashed() || stashed_only) {
|
||||
// Also check the stashed list.
|
||||
int num_stashed = this_node->get_num_stashed();
|
||||
for (int i = 0; i < num_stashed; i++) {
|
||||
PandaNode *stashed_node = this_node->get_stashed(i);
|
||||
|
||||
consider_next_step(result, stashed_node, next_level, max_matches);
|
||||
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxLevelEntry::consider_next_step
|
||||
// Access: Public
|
||||
// Description: Compares the indicated child node (which is assumed
|
||||
// to be a child of _node_path) with the next component
|
||||
// of the path. If it matches, generates whatever
|
||||
// additional entries are appropriate and stores them in
|
||||
// next_level.
|
||||
//
|
||||
// If a complete solution is found, stores it in result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpFindApproxLevelEntry::
|
||||
consider_next_step(qpNodePathCollection &result, PandaNode *child_node,
|
||||
qpFindApproxLevel &next_level, int max_matches) const {
|
||||
if (!_approx_path.return_hidden() &&
|
||||
child_node->get_draw_mask().is_zero()) {
|
||||
// If the approx path does not allow us to return hidden nodes,
|
||||
// and this node has indeed been completely hidden, then stop
|
||||
// here.
|
||||
return;
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
// And now we just add the next entry without incrementing its
|
||||
// path entry.
|
||||
|
||||
qpFindApproxLevelEntry next(*this);
|
||||
next._node_path = qpNodePath(_node_path, child_node);
|
||||
next_level.add_entry(next);
|
||||
|
||||
} else {
|
||||
if (_approx_path.matches_component(_i, child_node)) {
|
||||
// That matched, and it consumes one path entry.
|
||||
qpFindApproxLevelEntry next(*this);
|
||||
++next._i;
|
||||
next._node_path = qpNodePath(_node_path, child_node);
|
||||
next_level.add_entry(next);
|
||||
}
|
||||
}
|
||||
}
|
75
panda/src/pgraph/qpfindApproxLevelEntry.h
Normal file
75
panda/src/pgraph/qpfindApproxLevelEntry.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Filename: qpfindApproxLevelEntry.h
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 qpFINDAPPROXLEVELENTRY_H
|
||||
#define qpFINDAPPROXLEVELENTRY_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "qpfindApproxPath.h"
|
||||
#include "qpnodePath.h"
|
||||
|
||||
class qpFindApproxLevel;
|
||||
class qpNodePathCollection;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpFindApproxLevelEntry
|
||||
// Description : This class is local to this package only; it doesn't
|
||||
// get exported. It represents a single node under
|
||||
// consideration for matching at a single point in the
|
||||
// breadth-first search.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class qpFindApproxLevelEntry {
|
||||
public:
|
||||
INLINE qpFindApproxLevelEntry(const qpNodePath &node_path,
|
||||
qpFindApproxPath &approx_path);
|
||||
INLINE qpFindApproxLevelEntry(const qpFindApproxLevelEntry ©);
|
||||
INLINE void operator = (const qpFindApproxLevelEntry ©);
|
||||
|
||||
INLINE bool next_is_stashed() const;
|
||||
|
||||
void consider_node(qpNodePathCollection &result, qpFindApproxLevel &next_level,
|
||||
int max_matches) const;
|
||||
void consider_next_step(qpNodePathCollection &result,
|
||||
PandaNode *child_node, qpFindApproxLevel &next_level,
|
||||
int max_matches) const;
|
||||
INLINE bool is_solution() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
// _node_path represents the most recent node that we have
|
||||
// previously accepted as being a partial solution.
|
||||
qpNodePath _node_path;
|
||||
|
||||
// _i represents the next component in the approx_path that must be
|
||||
// matched against all of the children of _node_path, above. If _i
|
||||
// refers to the end of the approx_path, then _node_path is a
|
||||
// solution.
|
||||
int _i;
|
||||
qpFindApproxPath &_approx_path;
|
||||
};
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const qpFindApproxLevelEntry &entry) {
|
||||
entry.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "qpfindApproxLevelEntry.I"
|
||||
|
||||
#endif
|
216
panda/src/pgraph/qpfindApproxPath.I
Normal file
216
panda/src/pgraph/qpfindApproxPath.I
Normal file
@ -0,0 +1,216 @@
|
||||
// Filename: qpfindApproxPath.I
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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: qpFindApproxPath::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpFindApproxPath::
|
||||
qpFindApproxPath() {
|
||||
_return_hidden = true;
|
||||
_return_stashed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_name
|
||||
// Access: Public
|
||||
// Description: Adds a component that must match the name of a node
|
||||
// exactly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_name_glob
|
||||
// Access: Public
|
||||
// Description: Adds a component that must match the name of a node
|
||||
// using standard shell globbing rules, with wildcard
|
||||
// characters accepted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_exact_type
|
||||
// Access: Public
|
||||
// Description: Adds a component that must match the type of a node
|
||||
// exactly, with no derived types matching.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_inexact_type
|
||||
// Access: Public
|
||||
// Description: Adds a component that must match the type of a node
|
||||
// or be a base class of the node's type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_one
|
||||
// Access: Public
|
||||
// Description: Adds a component that will match any node (but not a
|
||||
// chain of many nodes).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
add_match_one(int flags) {
|
||||
Component comp;
|
||||
comp._type = CT_match_one;
|
||||
comp._flags = flags;
|
||||
_path.push_back(comp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_many
|
||||
// Access: Public
|
||||
// Description: Adds a component that will match a chain of zero or
|
||||
// more consecutive nodes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
add_match_many(int flags) {
|
||||
Component comp;
|
||||
comp._type = CT_match_many;
|
||||
comp._flags = flags;
|
||||
_path.push_back(comp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_match_pointer
|
||||
// Access: Public
|
||||
// Description: Adds a component that must match a particular node
|
||||
// exactly, by pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
add_match_pointer(PandaNode *pointer, int flags) {
|
||||
Component comp;
|
||||
comp._type = CT_match_pointer;
|
||||
comp._pointer = pointer;
|
||||
comp._flags = flags;
|
||||
_path.push_back(comp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::get_num_components
|
||||
// Access: Public
|
||||
// Description: Returns the number of components in the path.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int qpFindApproxPath::
|
||||
get_num_components() const {
|
||||
return _path.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::is_component_match_many
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth component is of type
|
||||
// match_many, which will require special handling.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpFindApproxPath::
|
||||
is_component_match_many(int index) const {
|
||||
nassertr(index >= 0 && index < (int)_path.size(), false);
|
||||
return (_path[index]._type == CT_match_many);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::matches_component
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth component of the path matches
|
||||
// the indicated node, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpFindApproxPath::
|
||||
matches_component(int index, PandaNode *node) const {
|
||||
nassertr(index >= 0 && index < (int)_path.size(), false);
|
||||
return (_path[index].matches(node));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::matches_stashed
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth component of the path matches
|
||||
// a stashed node only, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpFindApproxPath::
|
||||
matches_stashed(int index) const {
|
||||
if (index >= 0 && index < (int)_path.size()) {
|
||||
return ((_path[index]._flags & CF_stashed) != 0);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::return_hidden
|
||||
// Access: Public
|
||||
// Description: Returns true if this path allows returning of hidden
|
||||
// nodes, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpFindApproxPath::
|
||||
return_hidden() const {
|
||||
return _return_hidden;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::return_stashed
|
||||
// Access: Public
|
||||
// Description: Returns true if this path allows returning of stashed
|
||||
// nodes, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool qpFindApproxPath::
|
||||
return_stashed() const {
|
||||
return _return_stashed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::output_component
|
||||
// Access: Public
|
||||
// Description: Formats the nth component of the path to the
|
||||
// indicated output stream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void qpFindApproxPath::
|
||||
output_component(ostream &out, int index) const {
|
||||
nassertv(index >= 0 && index < (int)_path.size());
|
||||
out << _path[index];
|
||||
}
|
306
panda/src/pgraph/qpfindApproxPath.cxx
Normal file
306
panda/src/pgraph/qpfindApproxPath.cxx
Normal file
@ -0,0 +1,306 @@
|
||||
// Filename: qpfindApproxPath.cxx
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "qpfindApproxPath.h"
|
||||
#include "config_pgraph.h"
|
||||
|
||||
#include "globPattern.h"
|
||||
#include "pandaNode.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::Component::matches
|
||||
// Access: Public
|
||||
// Description: Returns true if the indicated node matches this
|
||||
// component, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpFindApproxPath::Component::
|
||||
matches(PandaNode *node) const {
|
||||
string node_name;
|
||||
|
||||
switch (_type) {
|
||||
case CT_match_name:
|
||||
// Match the node's name exactly.
|
||||
return (_name == node->get_name());
|
||||
|
||||
case CT_match_name_glob:
|
||||
// Match the node's name according to filename globbing rules.
|
||||
{
|
||||
GlobPattern pattern(_name);
|
||||
return (pattern.matches(node->get_name()));
|
||||
}
|
||||
|
||||
case CT_match_exact_type:
|
||||
// Match the node's type exactly.
|
||||
return (node->is_exact_type(_type_handle));
|
||||
|
||||
case CT_match_inexact_type:
|
||||
// Match the node's type inexactly: it's a match if the node
|
||||
// is the type, or is derived from the type.
|
||||
return (node->is_of_type(_type_handle));
|
||||
|
||||
case CT_match_one:
|
||||
case CT_match_many:
|
||||
// Match any node.
|
||||
return true;
|
||||
|
||||
case CT_match_pointer:
|
||||
// Match only this one particular node.
|
||||
return (_pointer == node);
|
||||
}
|
||||
|
||||
pgraph_cat.error()
|
||||
<< "Invalid component in qpFindApproxPath\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::Component::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpFindApproxPath::Component::
|
||||
output(ostream &out) const {
|
||||
out << _type;
|
||||
if (_type == CT_match_name || _type == CT_match_name_glob) {
|
||||
out << " \"" << _name << "\"";
|
||||
|
||||
} else if (_type == CT_match_exact_type || _type == CT_match_inexact_type) {
|
||||
out << " " << _type_handle;
|
||||
|
||||
} else if (_type == CT_match_pointer) {
|
||||
out << " (" << *_pointer << ")";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_string
|
||||
// Access: Public
|
||||
// Description: Adds a sequence of components separated by slashes,
|
||||
// followed optionally by a semicolon and a sequence of
|
||||
// control flags, to the path sequence. Returns true if
|
||||
// successful, false if the string contained an error.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpFindApproxPath::
|
||||
add_string(const string &str_path) {
|
||||
size_t start = 0;
|
||||
size_t slash = str_path.find('/');
|
||||
while (slash != string::npos) {
|
||||
if (!add_component(str_path.substr(start, slash - start))) {
|
||||
return false;
|
||||
}
|
||||
start = slash + 1;
|
||||
slash = str_path.find('/', start);
|
||||
}
|
||||
|
||||
size_t semicolon = str_path.rfind(';');
|
||||
|
||||
// We want to find the *last* semicolon at start or later, if there
|
||||
// happens to be more than one. rfind will find the rightmost
|
||||
// semicolon in the entire string; if this is less than start, there
|
||||
// is no semicolon right of start.
|
||||
if (semicolon < start) {
|
||||
semicolon = string::npos;
|
||||
}
|
||||
|
||||
if (!add_component(str_path.substr(start, semicolon - start))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (semicolon != string::npos) {
|
||||
return add_flags(str_path.substr(semicolon + 1));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_flags
|
||||
// Access: Public
|
||||
// Description: Adds a sequence of control flags. This will be a
|
||||
// sequence of letters preceded by either '+' or '-',
|
||||
// with no intervening punctuation. Returns true if
|
||||
// successful, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpFindApproxPath::
|
||||
add_flags(const string &str_flags) {
|
||||
string::const_iterator pi = str_flags.begin();
|
||||
while (pi != str_flags.end()) {
|
||||
bool on;
|
||||
switch (*pi) {
|
||||
case '+':
|
||||
on = true;
|
||||
break;
|
||||
case '-':
|
||||
on = false;
|
||||
break;
|
||||
default:
|
||||
pgraph_cat.error()
|
||||
<< "Invalid control flag string: " << str_flags << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
++pi;
|
||||
if (pi == str_flags.end()) {
|
||||
pgraph_cat.error()
|
||||
<< "Invalid control flag string: " << str_flags << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (*pi) {
|
||||
case 'h':
|
||||
_return_hidden = on;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
_return_stashed = on;
|
||||
break;
|
||||
|
||||
default:
|
||||
pgraph_cat.error()
|
||||
<< "Invalid control flag string: " << str_flags << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
++pi;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::add_component
|
||||
// Access: Public
|
||||
// Description: Adds a single component to the path sequence, defined
|
||||
// by a string as might appear between slashes in the
|
||||
// path string. Returns true if successful, false if
|
||||
// the string component was in some way invalid.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool qpFindApproxPath::
|
||||
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(flags);
|
||||
|
||||
} else if (str_component == "**") {
|
||||
if ((flags & CF_stashed) != 0) {
|
||||
pgraph_cat.error()
|
||||
<< "@@** is undefined; use @@*/** or **/@@* instead.\n";
|
||||
return false;
|
||||
}
|
||||
add_match_many(flags);
|
||||
|
||||
} else if (!str_component.empty() && str_component[0] == '-') {
|
||||
string type_name = str_component.substr(1);
|
||||
|
||||
// *** for now, as a quick hack, if a type exists with the "qp"
|
||||
// prefix on the named type, we search for that type instead.
|
||||
TypeHandle handle = TypeRegistry::ptr()->find_type("qp" + type_name);
|
||||
if (handle == TypeHandle::none()) {
|
||||
handle = TypeRegistry::ptr()->find_type(type_name);
|
||||
}
|
||||
|
||||
if (handle == TypeHandle::none()) {
|
||||
pgraph_cat.error()
|
||||
<< "Invalid type name: " + type_name;
|
||||
return false;
|
||||
|
||||
} else {
|
||||
add_match_exact_type(handle, flags);
|
||||
}
|
||||
|
||||
} else if (!str_component.empty() && str_component[0] == '+') {
|
||||
string type_name = str_component.substr(1);
|
||||
|
||||
// *** for now, as a quick hack, if a type exists with the "qp"
|
||||
// prefix on the named type, we search for that type instead.
|
||||
TypeHandle handle = TypeRegistry::ptr()->find_type("qp" + type_name);
|
||||
if (handle == TypeHandle::none()) {
|
||||
handle = TypeRegistry::ptr()->find_type(type_name);
|
||||
}
|
||||
|
||||
if (handle == TypeHandle::none()) {
|
||||
pgraph_cat.error()
|
||||
<< "Invalid type name: " + type_name;
|
||||
return false;
|
||||
|
||||
} else {
|
||||
add_match_inexact_type(handle, flags);
|
||||
}
|
||||
|
||||
} else {
|
||||
add_match_name_glob(str_component, flags);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpFindApproxPath::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpFindApproxPath::
|
||||
output(ostream &out) const {
|
||||
out << "(";
|
||||
if (!_path.empty()) {
|
||||
Path::const_iterator pi = _path.begin();
|
||||
out << *pi;
|
||||
++pi;
|
||||
while (pi != _path.end()) {
|
||||
out << " / " << *pi;
|
||||
++pi;
|
||||
}
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
||||
ostream &
|
||||
operator << (ostream &out, qpFindApproxPath::ComponentType type) {
|
||||
switch (type) {
|
||||
case qpFindApproxPath::CT_match_name:
|
||||
return out << "match_name";
|
||||
|
||||
case qpFindApproxPath::CT_match_name_glob:
|
||||
return out << "match_name_glob";
|
||||
|
||||
case qpFindApproxPath::CT_match_exact_type:
|
||||
return out << "match_exact_type";
|
||||
|
||||
case qpFindApproxPath::CT_match_inexact_type:
|
||||
return out << "match_inexact_type";
|
||||
|
||||
case qpFindApproxPath::CT_match_one:
|
||||
return out << "match_one";
|
||||
|
||||
case qpFindApproxPath::CT_match_many:
|
||||
return out << "match_many";
|
||||
|
||||
case qpFindApproxPath::CT_match_pointer:
|
||||
return out << "match_pointer";
|
||||
};
|
||||
|
||||
return out << "**invalid**";
|
||||
};
|
||||
|
119
panda/src/pgraph/qpfindApproxPath.h
Normal file
119
panda/src/pgraph/qpfindApproxPath.h
Normal file
@ -0,0 +1,119 @@
|
||||
// Filename: qpqpFindApproxPath.h
|
||||
// Created by: drose (13Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 qpFINDAPPROXPATH_H
|
||||
#define qpFINDAPPROXPATH_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "pvector.h"
|
||||
|
||||
class PandaNode;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : qpFindApproxPath
|
||||
// Description : This class is local to this package only; it doesn't
|
||||
// get exported. It chops a string path, as supplied to
|
||||
// find_up() or find_down(), and breaks it up into its
|
||||
// component pieces.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class qpFindApproxPath {
|
||||
public:
|
||||
INLINE qpFindApproxPath();
|
||||
|
||||
bool add_string(const string &str_path);
|
||||
bool add_flags(const string &str_flags);
|
||||
bool add_component(string str_component);
|
||||
|
||||
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(PandaNode *pointer, int flags);
|
||||
|
||||
INLINE int get_num_components() const;
|
||||
INLINE bool is_component_match_many(int index) const;
|
||||
INLINE bool matches_component(int index, PandaNode *node) const;
|
||||
INLINE bool matches_stashed(int index) const;
|
||||
|
||||
INLINE bool return_hidden() const;
|
||||
INLINE bool return_stashed() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
INLINE void output_component(ostream &out, int index) const;
|
||||
|
||||
#ifndef WIN32_VC
|
||||
// Visual C++ won't let us define the ostream operator functions for
|
||||
// these guys if they're private--even though we declare them friends.
|
||||
private:
|
||||
#endif
|
||||
enum ComponentType {
|
||||
CT_match_name,
|
||||
CT_match_name_glob,
|
||||
CT_match_exact_type,
|
||||
CT_match_inexact_type,
|
||||
CT_match_one,
|
||||
CT_match_many,
|
||||
CT_match_pointer
|
||||
};
|
||||
enum ComponentFlags {
|
||||
CF_stashed = 0x001,
|
||||
};
|
||||
|
||||
class Component {
|
||||
public:
|
||||
bool matches(PandaNode *node) const;
|
||||
void output(ostream &out) const;
|
||||
|
||||
ComponentType _type;
|
||||
string _name;
|
||||
TypeHandle _type_handle;
|
||||
PandaNode *_pointer;
|
||||
int _flags;
|
||||
};
|
||||
|
||||
typedef pvector<Component> Path;
|
||||
Path _path;
|
||||
|
||||
bool _return_hidden;
|
||||
bool _return_stashed;
|
||||
|
||||
friend ostream &operator << (ostream &, qpFindApproxPath::ComponentType);
|
||||
friend INLINE ostream &operator << (ostream &, const qpFindApproxPath::Component &);
|
||||
};
|
||||
|
||||
ostream &
|
||||
operator << (ostream &out, qpFindApproxPath::ComponentType type);
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const qpFindApproxPath::Component &component) {
|
||||
component.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const qpFindApproxPath &path) {
|
||||
path.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "qpfindApproxPath.I"
|
||||
|
||||
#endif
|
@ -50,10 +50,12 @@ qpNodePath(const string &top_node_name) :
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::Constructor
|
||||
// Access: Published
|
||||
// Description: This constructs an empty qpNodePath with a single node.
|
||||
//
|
||||
// If the Node pointer is NULL, this quietly creates an
|
||||
// empty qpNodePath.
|
||||
// Description: This constructs a NodePath for the indicated node.
|
||||
// If the node does not have any parents, this creates a
|
||||
// single NodePath; otherwise, it automatically finds
|
||||
// the path from the node to the root. If the node has
|
||||
// multiple paths to the root, one path is chosen
|
||||
// arbitrarily and a warning message is printed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpNodePath::
|
||||
qpNodePath(PandaNode *top_node) :
|
||||
@ -64,6 +66,28 @@ qpNodePath(PandaNode *top_node) :
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs a NodePath with the indicated parent
|
||||
// NodePath and child node; the child node must be a
|
||||
|
||||
// stashed or unstashed child of the parent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE qpNodePath::
|
||||
qpNodePath(const qpNodePath &parent, PandaNode *child) :
|
||||
_error_type(ET_fail)
|
||||
{
|
||||
nassertv(!parent.is_empty());
|
||||
nassertv(child != (PandaNode *)NULL);
|
||||
_head = PandaNode::get_component(parent._head, child);
|
||||
nassertv(_head != (qpNodePathComponent *)NULL);
|
||||
|
||||
if (_head != (qpNodePathComponent *)NULL) {
|
||||
_error_type = ET_ok;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::Copy Constructor
|
||||
// Access: Published
|
||||
|
@ -18,10 +18,10 @@
|
||||
|
||||
#include "qpnodePath.h"
|
||||
#include "qpnodePathCollection.h"
|
||||
#include "node.h"
|
||||
#include "namedNode.h"
|
||||
#include "qpfindApproxPath.h"
|
||||
#include "qpfindApproxLevelEntry.h"
|
||||
#include "qpfindApproxLevel.h"
|
||||
#include "config_pgraph.h"
|
||||
#include "plist.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "cullBinAttrib.h"
|
||||
#include "textureAttrib.h"
|
||||
@ -32,7 +32,11 @@
|
||||
#include "materialPool.h"
|
||||
#include "look_at.h"
|
||||
#include "compose_matrix.h"
|
||||
#include "plist.h"
|
||||
|
||||
// stack seems to overflow on Intel C++ at 7000. If we need more than
|
||||
// 7000, need to increase stack size.
|
||||
int qpNodePath::_max_search_depth = 7000;
|
||||
TypeHandle qpNodePath::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -124,6 +128,65 @@ get_children() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qoNodePath::find
|
||||
// Access: Published
|
||||
// Description: Searches for a node below the referenced node that
|
||||
// matches the indicated string. Returns the shortest
|
||||
// match found, if any, or an empty NodePath if no match
|
||||
// can be found.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpNodePath qpNodePath::
|
||||
find(const string &path) const {
|
||||
nassertr(!is_empty(), fail());
|
||||
|
||||
qpNodePathCollection col;
|
||||
find_matches(col, path, 1);
|
||||
|
||||
if (col.is_empty()) {
|
||||
return qpNodePath::not_found();
|
||||
}
|
||||
|
||||
return col.get_path(0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::find_all_matches
|
||||
// Access: Published
|
||||
// Description: Returns the complete set of all NodePaths that begin
|
||||
// with this NodePath and can be extended by
|
||||
// path. The shortest paths will be listed
|
||||
// first.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpNodePathCollection qpNodePath::
|
||||
find_all_matches(const string &path) const {
|
||||
qpNodePathCollection col;
|
||||
nassertr(!is_empty(), col);
|
||||
nassertr(verify_complete(), col);
|
||||
find_matches(col, path, -1);
|
||||
return col;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::find_all_paths_to
|
||||
// Access: Published
|
||||
// Description: Returns the set of all NodePaths that extend from
|
||||
// this NodePath down to the indicated node. The
|
||||
// shortest paths will be listed first.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
qpNodePathCollection qpNodePath::
|
||||
find_all_paths_to(PandaNode *node) const {
|
||||
qpNodePathCollection col;
|
||||
nassertr(!is_empty(), col);
|
||||
nassertr(verify_complete(), col);
|
||||
nassertr(node != (PandaNode *)NULL, col);
|
||||
qpFindApproxPath approx_path;
|
||||
approx_path.add_match_many(0);
|
||||
approx_path.add_match_pointer(node, 0);
|
||||
find_matches(col, approx_path, -1);
|
||||
return col;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::reparent_to
|
||||
// Access: Published
|
||||
@ -258,9 +321,11 @@ attach_new_node(PandaNode *node, int sort) const {
|
||||
void qpNodePath::
|
||||
remove_node() {
|
||||
nassertv(_error_type != ET_not_found);
|
||||
if (is_empty()) {
|
||||
// If we have no arcs (maybe we were already removed), quietly do
|
||||
// nothing except to ensure the qpNodePath is clear.
|
||||
if (is_empty() || is_singleton()) {
|
||||
// If we have no parents, remove_node() is just a do-nothing
|
||||
// operation; if we have no nodes, maybe we were already removed.
|
||||
// In either case, quietly do nothing except to ensure the
|
||||
// qpNodePath is clear.
|
||||
(*this) = qpNodePath::removed();
|
||||
return;
|
||||
}
|
||||
@ -2303,7 +2368,101 @@ r_output(ostream &out, qpNodePathComponent *comp) const {
|
||||
if (node->has_name()) {
|
||||
out << node->get_name();
|
||||
} else {
|
||||
out << "+" << node->get_type();
|
||||
out << "-" << node->get_type();
|
||||
}
|
||||
// out << "[" << comp->get_length() << "]";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::find_matches
|
||||
// Access: Private
|
||||
// Description: Finds up to max_matches matches against the given
|
||||
// path string from this node and deeper. The
|
||||
// max_matches count indicates the maximum number of
|
||||
// matches to return, or -1 not to limit the number
|
||||
// returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpNodePath::
|
||||
find_matches(qpNodePathCollection &result, const string &path,
|
||||
int max_matches) const {
|
||||
if (is_empty()) {
|
||||
pgraph_cat.warning()
|
||||
<< "Attempt to extend an empty qpNodePath by '" << path
|
||||
<< "'.\n";
|
||||
return;
|
||||
}
|
||||
qpFindApproxPath approx_path;
|
||||
if (approx_path.add_string(path)) {
|
||||
find_matches(result, approx_path, max_matches);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::find_matches
|
||||
// Access: Private
|
||||
// Description: Finds up to max_matches matches against the given
|
||||
// approx_path from this node and deeper. The
|
||||
// max_matches count indicates the maximum number of
|
||||
// matches to return, or -1 not to limit the number
|
||||
// returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpNodePath::
|
||||
find_matches(qpNodePathCollection &result, qpFindApproxPath &approx_path,
|
||||
int max_matches) const {
|
||||
if (is_empty()) {
|
||||
pgraph_cat.warning()
|
||||
<< "Attempt to extend an empty qpNodePath by: " << approx_path << ".\n";
|
||||
return;
|
||||
}
|
||||
qpFindApproxLevelEntry start(*this, approx_path);
|
||||
qpFindApproxLevel level;
|
||||
level.add_entry(start);
|
||||
r_find_matches(result, level, max_matches, _max_search_depth);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: qpNodePath::r_find_matches
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of find_matches.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void qpNodePath::
|
||||
r_find_matches(qpNodePathCollection &result,
|
||||
const qpFindApproxLevel &level,
|
||||
int max_matches, int num_levels_remaining) const {
|
||||
// Go on to the next level. If we exceeded the requested maximum
|
||||
// depth, stop.
|
||||
if (num_levels_remaining <= 0) {
|
||||
return;
|
||||
}
|
||||
num_levels_remaining--;
|
||||
|
||||
qpFindApproxLevel next_level;
|
||||
bool okflag = true;
|
||||
|
||||
// For each node in the current level, build up the set of possible
|
||||
// matches in the next level.
|
||||
qpFindApproxLevel::Vec::const_iterator li;
|
||||
for (li = level._v.begin(); li != level._v.end() && okflag; ++li) {
|
||||
const qpFindApproxLevelEntry &entry = (*li);
|
||||
|
||||
if (entry.is_solution()) {
|
||||
// Does this entry already represent a solution?
|
||||
result.add_path(entry._node_path);
|
||||
} else {
|
||||
entry.consider_node(result, next_level, max_matches);
|
||||
}
|
||||
|
||||
if (max_matches > 0 && result.get_num_paths() >= max_matches) {
|
||||
// Really, we just want to return here. But returning from
|
||||
// within the conditional within the for loop seems to sometimes
|
||||
// cause a compiler fault in GCC. We'll use a semaphore
|
||||
// variable instead.
|
||||
okflag = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now recurse on the next level.
|
||||
if (okflag) {
|
||||
r_find_matches(result, next_level, max_matches, num_levels_remaining);
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,85 @@
|
||||
#include "typedObject.h"
|
||||
|
||||
class qpNodePathCollection;
|
||||
class qpFindApproxLevel;
|
||||
class qpFindApproxPath;
|
||||
class Texture;
|
||||
class Material;
|
||||
class Fog;
|
||||
|
||||
//
|
||||
// A NodePath is the fundamental unit of high-level interaction with
|
||||
// the scene graph. It encapsulates the complete path down to a node
|
||||
// from some other node, usually the root of the scene graph. This is
|
||||
// used to resolve ambiguities associated with instancing.
|
||||
//
|
||||
// NodePath also contains a number of handy high-level methods for
|
||||
// common scene-graph manipulations, such as reparenting, and common
|
||||
// state changes, such as repositioning.
|
||||
//
|
||||
// There are also a number of NodePath methods for finding nodes deep
|
||||
// within the tree by name or by type. These take a path string,
|
||||
// which at its simplest consists of a series of node names separated
|
||||
// by slashes, like a directory pathname.
|
||||
//
|
||||
// Each component of the path string may optionally consist of one of
|
||||
// the following special names, instead of a node name:
|
||||
//
|
||||
// * -- matches exactly one node, with any name.
|
||||
// ** -- matches any sequence of zero or more nodes.
|
||||
// +typename -- matches any node that is or derives from the given type.
|
||||
// -typename -- matches any node that is the given type exactly.
|
||||
//
|
||||
// Furthermore, a node name may itself contain standard filename
|
||||
// globbing characters, like *, ?, and [a-z], that will be accepted as
|
||||
// a partial match. (In fact, the '*' special name may be seen as
|
||||
// just a special case of this.) The globbing characters may not be
|
||||
// used with the typename matches.
|
||||
//
|
||||
// The special characters "@@", appearing at the beginning of a node
|
||||
// name, indicate a stashed node. Normally, stashed nodes are not
|
||||
// returned by a find (but see the special flags, below), but a
|
||||
// stashed node may be found if it is explicitly named with its
|
||||
// leading @@ characters. By extension, "@@*" may be used to identify
|
||||
// any stashed node.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// "room//graph" will look for a node named "graph", which is a child
|
||||
// of an unnamed node, which is a child of a node named "room", which
|
||||
// is a child of the starting path.
|
||||
//
|
||||
// "**/red*" will look for any node anywhere in the tree (below the
|
||||
// starting path) with a name that begins with "red".
|
||||
//
|
||||
// "**/+PartBundleNode/**/head" will look for a node named "head",
|
||||
// somewhere below a PartBundleNode anywhere in the tree.
|
||||
//
|
||||
//
|
||||
// The search is always potentially ambiguous, even if the special
|
||||
// wildcard operators are not used, because there may be multiple
|
||||
// nodes in the tree with the same name. In general, in the case of
|
||||
// an ambiguity, the shortest path is preferred; when a method (such
|
||||
// as extend_by) must choose only only one of several possible paths,
|
||||
// it will choose the shortest available; on the other hand, when a
|
||||
// method (such as find_all_matches) is to return all of the matching
|
||||
// paths, it will sort them so that the shortest paths appear first in
|
||||
// the output.
|
||||
//
|
||||
//
|
||||
// Special flags. The entire string may optionally be followed by the
|
||||
// ";" character, followed by one or more of the following special
|
||||
// control flags, with no intervening spaces or punctuation:
|
||||
//
|
||||
// -h Do not return hidden nodes.
|
||||
// +h Do return hidden nodes.
|
||||
// -s Do not return stashed nodes unless explicitly referenced with @@.
|
||||
// +s Return stashed nodes even without any explicit @@ characters.
|
||||
//
|
||||
// The default flags are +h-s.
|
||||
//
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : NodePath
|
||||
// Description : NodePath is the fundamental system for disambiguating
|
||||
@ -71,6 +146,7 @@ PUBLISHED:
|
||||
INLINE qpNodePath(const string &top_node_name);
|
||||
INLINE qpNodePath(PandaNode *top_node);
|
||||
INLINE qpNodePath(const qpNodePath ©);
|
||||
INLINE qpNodePath(const qpNodePath &parent, PandaNode *child_node);
|
||||
INLINE void operator = (const qpNodePath ©);
|
||||
|
||||
INLINE static qpNodePath not_found();
|
||||
@ -98,12 +174,9 @@ PUBLISHED:
|
||||
INLINE bool has_parent() const;
|
||||
INLINE qpNodePath get_parent() const;
|
||||
|
||||
/*
|
||||
INLINE qpNodePath find(const string &path) const;
|
||||
|
||||
qpNodePathCollection
|
||||
find_all_matches(const string &path) const;
|
||||
*/
|
||||
qpNodePath find(const string &path) const;
|
||||
qpNodePathCollection find_all_matches(const string &path) const;
|
||||
qpNodePathCollection find_all_paths_to(PandaNode *node) const;
|
||||
|
||||
// Methods that actually move nodes around in the scene graph. The
|
||||
// optional "sort" parameter can be used to force a particular
|
||||
@ -405,8 +478,19 @@ private:
|
||||
CPT(TransformState) r_get_partial_transform(qpNodePathComponent *comp, int n) const;
|
||||
void r_output(ostream &out, qpNodePathComponent *comp) const;
|
||||
|
||||
void find_matches(qpNodePathCollection &result,
|
||||
const string &approx_path_str,
|
||||
int max_matches) const;
|
||||
void find_matches(qpNodePathCollection &result,
|
||||
qpFindApproxPath &approx_path,
|
||||
int max_matches) const;
|
||||
void r_find_matches(qpNodePathCollection &result,
|
||||
const qpFindApproxLevel &level,
|
||||
int max_matches, int num_levels_remaining) const;
|
||||
|
||||
PT(qpNodePathComponent) _head;
|
||||
ErrorType _error_type;
|
||||
static int _max_search_depth;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user