361 lines
13 KiB
Plaintext
361 lines
13 KiB
Plaintext
// Filename: nodeTransitionCacheEntry.I
|
|
// Created by: drose (20Mar00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "config_graph.h"
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry::
|
|
NodeTransitionCacheEntry(NodeTransition *trans) : _trans(trans) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::Copy Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry::
|
|
NodeTransitionCacheEntry(const NodeTransitionCacheEntry ©) :
|
|
_trans(copy._trans),
|
|
_computed(copy._computed),
|
|
_verified(copy._verified)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::Copy Assignment Operator
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH void NodeTransitionCacheEntry::
|
|
operator = (const NodeTransitionCacheEntry ©) {
|
|
_trans = copy._trans;
|
|
_computed = copy._computed;
|
|
_verified = copy._verified;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::is_identity
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH bool NodeTransitionCacheEntry::
|
|
is_identity() const {
|
|
return (_trans == (NodeTransition *)NULL);
|
|
// || _trans->is_identity();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::compare_to
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH int NodeTransitionCacheEntry::
|
|
compare_to(const NodeTransitionCacheEntry &other) const {
|
|
bool this_ident = is_identity();
|
|
bool other_ident = other.is_identity();
|
|
if (this_ident && other_ident) {
|
|
return 0;
|
|
}
|
|
if (this_ident) {
|
|
return -1;
|
|
}
|
|
if (other_ident) {
|
|
return 1;
|
|
}
|
|
|
|
// This should be guaranteed by the above logic.
|
|
nassertr(_trans != (NodeTransition *)NULL &&
|
|
other._trans != (NodeTransition *)NULL, false);
|
|
|
|
return _trans->compare_to(*other._trans);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::generate_hash
|
|
// Access: Public
|
|
// Description: Adds the transition to the indicated hash generator.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH void NodeTransitionCacheEntry::
|
|
generate_hash(GraphHashGenerator &hashgen) const {
|
|
if (_trans != (NodeTransition *)NULL) {
|
|
_trans->generate_hash(hashgen);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::clear
|
|
// Access: Public
|
|
// Description: Reinitializes the cache entry to its original state.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH void NodeTransitionCacheEntry::
|
|
clear() {
|
|
_trans.clear();
|
|
_computed.clear();
|
|
_verified.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::set_trans
|
|
// Access: Public
|
|
// Description: Changes the transition associated with the cache
|
|
// entry without changing the associated time stamps.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH void NodeTransitionCacheEntry::
|
|
set_trans(NodeTransition *trans) {
|
|
_trans = trans;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::clear_trans
|
|
// Access: Public
|
|
// Description: Removes the transitoin associated with the cache
|
|
// entry without changing the associated time stamps.
|
|
// This is of limited usefulness.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH void NodeTransitionCacheEntry::
|
|
clear_trans() {
|
|
_trans.clear();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::has_trans
|
|
// Access: Public
|
|
// Description: Returns true if the cache entry has an associated
|
|
// NodeTransition, false if it doesn't (and the
|
|
// transition should be assumed to be identity).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH bool NodeTransitionCacheEntry::
|
|
has_trans() const {
|
|
return _trans != (NodeTransition *)NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::get_trans
|
|
// Access: Public
|
|
// Description: Returns the NodeTransition associated with the cache
|
|
// entry, or NULL if there is no associated
|
|
// NodeTransition (in which case it should be assumed to
|
|
// be identity).
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransition *NodeTransitionCacheEntry::
|
|
get_trans() const {
|
|
return _trans;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::is_cache_verified
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH bool NodeTransitionCacheEntry::
|
|
is_cache_verified(UpdateSeq as_of) const {
|
|
if (wrt_cat.is_spam()) {
|
|
wrt_cat.spam()
|
|
<< "NodeTransitionCacheEntry::is_cache_verified(" << as_of
|
|
<< "), _verified = " << _verified << ", result = "
|
|
<< (as_of <= _verified) << "\n";
|
|
}
|
|
return as_of <= _verified;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::is_freshly_computed
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH bool NodeTransitionCacheEntry::
|
|
is_freshly_computed(UpdateSeq changed) const {
|
|
return changed < _computed;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::set_computed_verified
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH void NodeTransitionCacheEntry::
|
|
set_computed_verified(UpdateSeq now) {
|
|
_computed = now;
|
|
_verified = now;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::Typecast Operator
|
|
// Access: Public
|
|
// Description: This typecast operator allows the cache entry to be
|
|
// directly assigned to a NodeTransition pointer. It's
|
|
// primarily useful for using the code in
|
|
// setTransitionHelpers.h interchangeably between
|
|
// NodeTransitions and NodeTransitionCaches.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry::
|
|
operator const PT(NodeTransition) &() const {
|
|
return _trans;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::get_computed
|
|
// Access: Public
|
|
// Description: Returns the timestamp at which this cache entry was
|
|
// computed.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH UpdateSeq NodeTransitionCacheEntry::
|
|
get_computed() const {
|
|
return _computed;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::get_verified
|
|
// Access: Public
|
|
// Description: Returns the last timestamp at which this cache entry
|
|
// was verified; i.e. when the graph was last walked up
|
|
// to the root to ensure the cache entry is still valid.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH UpdateSeq NodeTransitionCacheEntry::
|
|
get_verified() const {
|
|
return _verified;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::invert
|
|
// Access: Public, Static
|
|
// Description: Returns a new cache entry that represents the inverse
|
|
// of a.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry NodeTransitionCacheEntry::
|
|
invert(const NodeTransitionCacheEntry &a) {
|
|
if (a.is_identity()) {
|
|
return a;
|
|
}
|
|
return NodeTransitionCacheEntry(a._trans->invert());
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::compose
|
|
// Access: Public, Static
|
|
// Description: Returns a new cache entry that represents the
|
|
// composition of a and b.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry NodeTransitionCacheEntry::
|
|
compose(const NodeTransitionCacheEntry &a,
|
|
const NodeTransitionCacheEntry &b) {
|
|
if (a.is_identity()) {
|
|
return b;
|
|
}
|
|
if (b.is_identity()) {
|
|
return a;
|
|
}
|
|
return NodeTransitionCacheEntry(a._trans->compose(b._trans));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::invert_compose
|
|
// Access: Public, Static
|
|
// Description: Returns a new cache entry that represents the
|
|
// composition of invert(a) and b.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry NodeTransitionCacheEntry::
|
|
invert_compose(const NodeTransitionCacheEntry &a,
|
|
const NodeTransitionCacheEntry &b) {
|
|
if (a.is_identity()) {
|
|
return b;
|
|
}
|
|
if (b.is_identity()) {
|
|
return NodeTransitionCacheEntry(a._trans->invert());
|
|
}
|
|
if (a._trans->compare_to(*b._trans) == 0) {
|
|
return NodeTransitionCacheEntry();
|
|
}
|
|
|
|
PT(NodeTransition) inv = a._trans->invert();
|
|
if (inv == (NodeTransition *)NULL) {
|
|
return b;
|
|
}
|
|
|
|
// We don't care about priority for this operation.
|
|
|
|
// This is broken! We don't have the right the change the priority
|
|
// on this node. For now, leave this out, since we aren't using
|
|
// priority on any transitions for which we're computing wrt() at
|
|
// the moment. Fix me soon.
|
|
// inv->set_priority(b._trans->get_priority());
|
|
|
|
return NodeTransitionCacheEntry(inv->compose(b._trans));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: NodeTransitionCacheEntry::cached_compose
|
|
// Access: Public, Static
|
|
// Description: Sets this cache entry to the result of compose(a, b),
|
|
// as computed using the cache value as a hint. Mark
|
|
// the result as computed at time 'now'.
|
|
////////////////////////////////////////////////////////////////////
|
|
INLINE_GRAPH NodeTransitionCacheEntry NodeTransitionCacheEntry::
|
|
cached_compose(const NodeTransitionCacheEntry &a,
|
|
const NodeTransitionCacheEntry &cache,
|
|
const NodeTransitionCacheEntry &b,
|
|
UpdateSeq now) {
|
|
if (wrt_cat.is_spam()) {
|
|
wrt_cat.spam()
|
|
<< "Composing:\n"
|
|
<< " a) " << a << " = " << a._computed << "\n"
|
|
<< " cache) " << cache << " = " << cache._computed << "\n"
|
|
<< " b) " << b << " = " << b._computed << "\n";
|
|
}
|
|
|
|
if (cache._computed == UpdateSeq::initial() ||
|
|
(a._computed == UpdateSeq::initial() &&
|
|
b._computed == UpdateSeq::initial()) ||
|
|
cache._computed < a._computed) {
|
|
|
|
// If the cache value has not yet been computed, or if the values
|
|
// in a and b are both empty, or if the cache is older than the
|
|
// source value (a), discard the cache and compute the composition
|
|
// directly.
|
|
NodeTransitionCacheEntry result = compose(a, b);
|
|
result.set_computed_verified(now);
|
|
|
|
if (wrt_cat.is_spam()) {
|
|
wrt_cat.spam() << "computed result is " << result << "\n";
|
|
}
|
|
|
|
return result;
|
|
|
|
} else {
|
|
// Otherwise, the cache value is recent and we can simply use it
|
|
// directly.
|
|
NodeTransitionCacheEntry result = cache;
|
|
result._verified = now;
|
|
|
|
if (wrt_cat.is_spam()) {
|
|
wrt_cat.spam() << "cached result is " << result << "\n";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
INLINE_GRAPH ostream &operator << (ostream &out, const NodeTransitionCacheEntry &e) {
|
|
e.output(out);
|
|
return out;
|
|
}
|