diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index d3e12c25a2..e2c15004f8 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -978,9 +978,13 @@ setup_scene(const NodePath &camera, GraphicsStateGuardian *gsg) { // We will need both the camera transform (the net transform to the // camera from the scene) and the world transform (the camera // transform inverse, or the net transform to the scene from the - // camera). - CPT(TransformState) camera_transform = camera.get_transform(scene_root); - CPT(TransformState) world_transform = scene_root.get_transform(camera); + // camera). These are actually defined from the parent of the + // scene_root, because the scene_root's own transform is immediately + // applied to these during rendering. (Normally, the parent of the + // scene_root is the empty NodePath, although it need not be.) + NodePath scene_parent = scene_root.get_parent(); + CPT(TransformState) camera_transform = camera.get_transform(scene_parent); + CPT(TransformState) world_transform = scene_parent.get_transform(camera); // The render transform is the same as the world transform, except // it is converted into the GSG's internal coordinate system. This diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index c70be6466f..b0b99046c4 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -590,10 +590,10 @@ void GraphicsStateGuardian:: issue_color_scale(const ColorScaleAttrib *attrib) { _current_color_scale = attrib->get_scale(); - if (_current_color_scale == LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)) { - _color_transform_enabled &= ~CT_scale; - } else { + if (attrib->has_scale()) { _color_transform_enabled |= CT_scale; + } else { + _color_transform_enabled &= ~CT_scale; } _scene_graph_color_stale = _has_scene_graph_color; diff --git a/panda/src/pgraph/camera.I b/panda/src/pgraph/camera.I index e651f24a3a..7ddf39b70d 100644 --- a/panda/src/pgraph/camera.I +++ b/panda/src/pgraph/camera.I @@ -118,7 +118,7 @@ get_camera_mask() const { //////////////////////////////////////////////////////////////////// // Function: Camera::set_cull_center -// Access: Public +// Access: Published // Description: Specifies the point from which the culling operations // are performed. Normally, this is the same as the // camera, and that is the default if this is not @@ -133,7 +133,7 @@ set_cull_center(const NodePath &cull_center) { //////////////////////////////////////////////////////////////////// // Function: Camera::get_cull_center -// Access: Public +// Access: Published // Description: Returns the point from which the culling operations // will be performed, if it was set by // set_cull_center(), or the empty NodePath otherwise. @@ -142,3 +142,50 @@ INLINE const NodePath &Camera:: get_cull_center() const { return _cull_center; } + +//////////////////////////////////////////////////////////////////// +// Function: Camera::set_initial_state +// Access: Published +// Description: Sets the initial state which is applied to all nodes +// in the scene, as if it were set at the top of the +// scene graph. +//////////////////////////////////////////////////////////////////// +INLINE void Camera:: +set_initial_state(const RenderState *state) { + _initial_state = state; +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::get_initial_state +// Access: Published +// Description: Returns the initial state as set by a previous call +// to set_initial_state(). +//////////////////////////////////////////////////////////////////// +INLINE CPT(RenderState) Camera:: +get_initial_state() const { + return _initial_state; +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::set_tag_state_key +// Access: Published +// Description: Sets the tag key which, when encountered as a tag on +// nodes in the scene graph, causes this Camera to apply +// an arbitrary state transition based on the value of +// the tag (as specified to set_tag_state()). +//////////////////////////////////////////////////////////////////// +INLINE void Camera:: +set_tag_state_key(const string &tag_state_key) { + _tag_state_key = tag_state_key; +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::get_tag_state_key +// Access: Published +// Description: Returns the tag key as set by a previous call to +// set_tag_state_key(). +//////////////////////////////////////////////////////////////////// +INLINE const string &Camera:: +get_tag_state_key() const { + return _tag_state_key; +} diff --git a/panda/src/pgraph/camera.cxx b/panda/src/pgraph/camera.cxx index d7ea8989c7..0ff7aadedd 100644 --- a/panda/src/pgraph/camera.cxx +++ b/panda/src/pgraph/camera.cxx @@ -32,7 +32,8 @@ Camera:: Camera(const string &name) : LensNode(name), _active(true), - _camera_mask(DrawMask::all_on()) + _camera_mask(DrawMask::all_on()), + _initial_state(RenderState::make_empty()) { } @@ -46,7 +47,10 @@ Camera(const Camera ©) : LensNode(copy), _active(copy._active), _scene(copy._scene), - _camera_mask(copy._camera_mask) + _camera_mask(copy._camera_mask), + _initial_state(copy._initial_state), + _tag_state_key(copy._tag_state_key), + _tag_states(copy._tag_states) { } @@ -104,6 +108,69 @@ safe_to_transform() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: Camera::set_tag_state +// Access: Published +// Description: Associates a particular state transition with the +// indicated tag value. When a node is encountered +// during traversal with the tag key specified by +// set_tag_state_key(), if the value of that tag matches +// tag_state, then the indicated state is applied to +// this node--but only when it is rendered by this +// camera. +// +// This can be used to apply special effects to nodes +// when they are rendered by certain cameras. It is +// particularly useful for multipass rendering, in which +// specialty cameras might be needed to render the scene +// with a particular set of effects. +//////////////////////////////////////////////////////////////////// +void Camera:: +set_tag_state(const string &tag_state, const RenderState *state) { + _tag_states[tag_state] = state; +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::clear_tag_state +// Access: Published +// Description: Removes the association established by a previous +// call to set_tag_state(). +//////////////////////////////////////////////////////////////////// +void Camera:: +clear_tag_state(const string &tag_state) { + _tag_states.erase(tag_state); +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::has_tag_state +// Access: Published +// Description: Returns true if set_tag_state() has previously been +// called with the indicated tag state, false otherwise. +//////////////////////////////////////////////////////////////////// +bool Camera:: +has_tag_state(const string &tag_state) const { + TagStates::const_iterator tsi; + tsi = _tag_states.find(tag_state); + return (tsi != _tag_states.end()); +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::get_tag_state +// Access: Published +// Description: Returns the state associated with the indicated tag +// state by a previous call to set_tag_state(), or the +// empty state if nothing has been associated. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) Camera:: +get_tag_state(const string &tag_state) const { + TagStates::const_iterator tsi; + tsi = _tag_states.find(tag_state); + if (tsi != _tag_states.end()) { + return (*tsi).second; + } + return RenderState::make_empty(); +} + //////////////////////////////////////////////////////////////////// // Function: Camera::add_display_region // Access: Private diff --git a/panda/src/pgraph/camera.h b/panda/src/pgraph/camera.h index 2e5543b663..239288d14d 100644 --- a/panda/src/pgraph/camera.h +++ b/panda/src/pgraph/camera.h @@ -24,6 +24,9 @@ #include "lensNode.h" #include "nodePath.h" #include "drawMask.h" +#include "renderState.h" +#include "pointerTo.h" +#include "pmap.h" class DisplayRegion; @@ -62,6 +65,17 @@ PUBLISHED: INLINE void set_cull_center(const NodePath &cull_center); INLINE const NodePath &get_cull_center() const; + INLINE void set_initial_state(const RenderState *state); + INLINE CPT(RenderState) get_initial_state() const; + + INLINE void set_tag_state_key(const string &tag_state_key); + INLINE const string &get_tag_state_key() const; + + void set_tag_state(const string &tag_state, const RenderState *state); + void clear_tag_state(const string &tag_state); + bool has_tag_state(const string &tag_state) const; + CPT(RenderState) get_tag_state(const string &tag_state) const; + private: void add_display_region(DisplayRegion *display_region); void remove_display_region(DisplayRegion *display_region); @@ -75,6 +89,12 @@ private: typedef pvector DisplayRegions; DisplayRegions _display_regions; + CPT(RenderState) _initial_state; + string _tag_state_key; + + typedef pmap TagStates; + TagStates _tag_states; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); diff --git a/panda/src/pgraph/colorScaleAttrib.I b/panda/src/pgraph/colorScaleAttrib.I index b7017aee3a..cec71a9f6a 100644 --- a/panda/src/pgraph/colorScaleAttrib.I +++ b/panda/src/pgraph/colorScaleAttrib.I @@ -19,14 +19,55 @@ //////////////////////////////////////////////////////////////////// // Function: ColorScaleAttrib::Constructor -// Access: Private +// Access: Protected // Description: Use ColorScaleAttrib::make() to construct a new // ColorScaleAttrib object. //////////////////////////////////////////////////////////////////// INLINE ColorScaleAttrib:: -ColorScaleAttrib(const LVecBase4f &scale) : +ColorScaleAttrib(bool off, const LVecBase4f &scale) : + _off(off), _scale(scale) { + _has_scale = !_scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::Copy Constructor +// Access: Protected +// Description: Use ColorScaleAttrib::make() to construct a new +// ColorScaleAttrib object. +//////////////////////////////////////////////////////////////////// +INLINE ColorScaleAttrib:: +ColorScaleAttrib(const ColorScaleAttrib ©) : + _off(copy._off), + _has_scale(copy._has_scale), + _scale(copy._scale) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::is_off +// Access: Published +// Description: Returns true if the ColorScaleAttrib will ignore any +// color scales inherited from above, false otherwise. +// This is not the same thing as !has_scale(); a +// ColorScaleAttrib may have the "off" flag set and also +// have another scale specified. +//////////////////////////////////////////////////////////////////// +INLINE bool ColorScaleAttrib:: +is_off() const { + return _off; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::has_scale +// Access: Published +// Description: Returns true if the ColorScaleAttrib has a +// non-identity scale, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool ColorScaleAttrib:: +has_scale() const { + return _has_scale; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/colorScaleAttrib.cxx b/panda/src/pgraph/colorScaleAttrib.cxx index a23a86f118..ab6dde81ec 100644 --- a/panda/src/pgraph/colorScaleAttrib.cxx +++ b/panda/src/pgraph/colorScaleAttrib.cxx @@ -34,7 +34,36 @@ TypeHandle ColorScaleAttrib::_type_handle; //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ColorScaleAttrib:: make(const LVecBase4f &scale) { - ColorScaleAttrib *attrib = new ColorScaleAttrib(scale); + ColorScaleAttrib *attrib = new ColorScaleAttrib(false, scale); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::make_off +// Access: Published, Static +// Description: Constructs a new ColorScaleAttrib object that ignores +// any ColorScaleAttrib inherited from above. You may +// also specify an additional color scale to apply to +// geometry below (using set_scale()). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ColorScaleAttrib:: +make_off() { + ColorScaleAttrib *attrib = + new ColorScaleAttrib(true, LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::set_scale +// Access: Published +// Description: Returns a new ColorScaleAttrib, just like this one, but +// with the scale changed to the indicated value. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ColorScaleAttrib:: +set_scale(const LVecBase4f &scale) const { + ColorScaleAttrib *attrib = new ColorScaleAttrib(*this); + attrib->_scale = scale; + attrib->_has_scale = !scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); return return_new(attrib); } @@ -59,7 +88,13 @@ issue(GraphicsStateGuardianBase *gsg) const { //////////////////////////////////////////////////////////////////// void ColorScaleAttrib:: output(ostream &out) const { - out << get_type() << ":(" << get_scale() << ")"; + out << get_type() << ":"; + if (is_off()) { + out << "off"; + } + if (has_scale()) { + out << "(" << get_scale() << ")"; + } } //////////////////////////////////////////////////////////////////// @@ -81,6 +116,11 @@ int ColorScaleAttrib:: compare_to_impl(const RenderAttrib *other) const { const ColorScaleAttrib *ta; DCAST_INTO_R(ta, other, 0); + + if (is_off() != ta->is_off()) { + return (int)is_off() - (int)ta->is_off(); + } + return _scale.compare_to(ta->_scale); } @@ -105,12 +145,17 @@ CPT(RenderAttrib) ColorScaleAttrib:: compose_impl(const RenderAttrib *other) const { const ColorScaleAttrib *ta; DCAST_INTO_R(ta, other, 0); + + if (ta->is_off()) { + return ta; + } + LVecBase4f new_scale(ta->_scale[0] * _scale[0], ta->_scale[1] * _scale[1], ta->_scale[2] * _scale[2], ta->_scale[3] * _scale[3]); - - ColorScaleAttrib *attrib = new ColorScaleAttrib(new_scale); + + ColorScaleAttrib *attrib = new ColorScaleAttrib(is_off(), new_scale); return return_new(attrib); } @@ -125,14 +170,17 @@ compose_impl(const RenderAttrib *other) const { //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) ColorScaleAttrib:: invert_compose_impl(const RenderAttrib *other) const { + if (is_off()) { + return other; + } const ColorScaleAttrib *ta; DCAST_INTO_R(ta, other, 0); - LVecBase4f new_scale(ta->_scale[0] / _scale[0], - ta->_scale[1] / _scale[1], - ta->_scale[2] / _scale[2], - ta->_scale[3] / _scale[3]); + LVecBase4f new_scale(_scale[0] == 0.0f ? 1.0f : ta->_scale[0] / _scale[0], + _scale[1] == 0.0f ? 1.0f : ta->_scale[1] / _scale[1], + _scale[2] == 0.0f ? 1.0f : ta->_scale[2] / _scale[2], + _scale[3] == 0.0f ? 1.0f : ta->_scale[3] / _scale[3]); - ColorScaleAttrib *attrib = new ColorScaleAttrib(new_scale); + ColorScaleAttrib *attrib = new ColorScaleAttrib(false, new_scale); return return_new(attrib); } @@ -149,7 +197,7 @@ invert_compose_impl(const RenderAttrib *other) const { //////////////////////////////////////////////////////////////////// RenderAttrib *ColorScaleAttrib:: make_default_impl() const { - return new ColorScaleAttrib(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); + return new ColorScaleAttrib(false, LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); } //////////////////////////////////////////////////////////////////// @@ -173,6 +221,10 @@ void ColorScaleAttrib:: write_datagram(BamWriter *manager, Datagram &dg) { RenderAttrib::write_datagram(manager, dg); + // We cheat, and modify the bam stream without upping the bam + // version. We can do this since we know that no existing bam files + // have a ColorScaleAttrib in them. + dg.add_bool(_off); _scale.write_datagram(dg); } @@ -186,7 +238,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { //////////////////////////////////////////////////////////////////// TypedWritable *ColorScaleAttrib:: make_from_bam(const FactoryParams ¶ms) { - ColorScaleAttrib *attrib = new ColorScaleAttrib(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); + ColorScaleAttrib *attrib = new ColorScaleAttrib(false, LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); DatagramIterator scan; BamReader *manager; @@ -207,5 +259,7 @@ void ColorScaleAttrib:: fillin(DatagramIterator &scan, BamReader *manager) { RenderAttrib::fillin(scan, manager); + _off = scan.get_bool(); _scale.read_datagram(scan); + _has_scale = !_scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); } diff --git a/panda/src/pgraph/colorScaleAttrib.h b/panda/src/pgraph/colorScaleAttrib.h index a697f7c851..d450ebcf86 100644 --- a/panda/src/pgraph/colorScaleAttrib.h +++ b/panda/src/pgraph/colorScaleAttrib.h @@ -32,13 +32,18 @@ class FactoryParams; // vertices. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA ColorScaleAttrib : public RenderAttrib { -private: - INLINE ColorScaleAttrib(const LVecBase4f &scale); +protected: + INLINE ColorScaleAttrib(bool off, const LVecBase4f &scale); + INLINE ColorScaleAttrib(const ColorScaleAttrib ©); PUBLISHED: static CPT(RenderAttrib) make(const LVecBase4f &scale); + static CPT(RenderAttrib) make_off(); + INLINE bool is_off() const; + INLINE bool has_scale() const; INLINE const LVecBase4f &get_scale() const; + CPT(RenderAttrib) set_scale(const LVecBase4f &scale) const; public: virtual void issue(GraphicsStateGuardianBase *gsg) const; @@ -51,6 +56,8 @@ protected: virtual RenderAttrib *make_default_impl() const; private: + bool _off; + bool _has_scale; LVecBase4f _scale; public: diff --git a/panda/src/pgraph/cullTraverser.I b/panda/src/pgraph/cullTraverser.I index c1b0a757bd..cfd44a4370 100644 --- a/panda/src/pgraph/cullTraverser.I +++ b/panda/src/pgraph/cullTraverser.I @@ -27,6 +27,10 @@ INLINE void CullTraverser:: set_scene(SceneSetup *scene_setup) { _scene_setup = scene_setup; + const Camera *camera = scene_setup->get_camera_node(); + _tag_state_key = camera->get_tag_state_key(); + _has_tag_state_key = !_tag_state_key.empty(); + _initial_state = camera->get_initial_state(); } //////////////////////////////////////////////////////////////////// @@ -39,6 +43,28 @@ get_scene() const { return _scene_setup; } +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::has_tag_state_key +// Access: Public +// Description: Returns true if a nonempty tag state key has been +// specified for the scene's camera, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool CullTraverser:: +has_tag_state_key() const { + return _has_tag_state_key; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverser::get_tag_state_key +// Access: Public +// Description: Returns the tag state key that has been specified for +// the scene's camera, if any. +//////////////////////////////////////////////////////////////////// +INLINE const string &CullTraverser:: +get_tag_state_key() const { + return _tag_state_key; +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverser::get_camera_transform // Access: Public diff --git a/panda/src/pgraph/cullTraverser.cxx b/panda/src/pgraph/cullTraverser.cxx index ecd7c4404f..6835318125 100644 --- a/panda/src/pgraph/cullTraverser.cxx +++ b/panda/src/pgraph/cullTraverser.cxx @@ -49,6 +49,7 @@ TypeHandle CullTraverser::_type_handle; CullTraverser:: CullTraverser() { _camera_mask = DrawMask::all_on(); + _has_tag_state_key = false; _initial_state = RenderState::make_empty(); _depth_offset_decals = false; _cull_handler = (CullHandler *)NULL; @@ -64,6 +65,8 @@ CullTraverser:: CullTraverser(const CullTraverser ©) : _scene_setup(copy._scene_setup), _camera_mask(copy._camera_mask), + _has_tag_state_key(copy._has_tag_state_key), + _tag_state_key(copy._tag_state_key), _initial_state(copy._initial_state), _depth_offset_decals(copy._depth_offset_decals), _view_frustum(copy._view_frustum), @@ -148,8 +151,11 @@ traverse(CullTraverserData &data) { // being "fancy", and skip this processing for non-fancy nodes. if (data.is_in_view(_camera_mask)) { + if (pgraph_cat.is_spam()) { + pgraph_cat.spam() << "\n" << data._node_path << "\n"; + } + PandaNode *node = data.node(); - pgraph_cat.spam() << "\n" << data._node_path << "\n"; const RenderEffects *node_effects = node->get_effects(); if (node_effects->has_show_bounds()) { diff --git a/panda/src/pgraph/cullTraverser.h b/panda/src/pgraph/cullTraverser.h index bcabc0757b..19add50513 100644 --- a/panda/src/pgraph/cullTraverser.h +++ b/panda/src/pgraph/cullTraverser.h @@ -27,6 +27,7 @@ #include "transformState.h" #include "geometricBoundingVolume.h" #include "pointerTo.h" +#include "camera.h" #include "drawMask.h" #include "typedObject.h" #include "pStatCollector.h" @@ -53,6 +54,8 @@ public: INLINE void set_scene(SceneSetup *scene_setup); INLINE SceneSetup *get_scene() const; + INLINE bool has_tag_state_key() const; + INLINE const string &get_tag_state_key() const; INLINE void set_camera_mask(const DrawMask &camera_mask); INLINE const DrawMask &get_camera_mask() const; @@ -99,6 +102,8 @@ private: PT(SceneSetup) _scene_setup; DrawMask _camera_mask; + bool _has_tag_state_key; + string _tag_state_key; CPT(RenderState) _initial_state; bool _depth_offset_decals; PT(GeometricBoundingVolume) _view_frustum; diff --git a/panda/src/pgraph/cullTraverserData.I b/panda/src/pgraph/cullTraverserData.I index 289a01baf2..1bd6529006 100644 --- a/panda/src/pgraph/cullTraverserData.I +++ b/panda/src/pgraph/cullTraverserData.I @@ -136,16 +136,3 @@ is_in_view(const DrawMask &camera_mask) { return is_in_view_impl(); } -//////////////////////////////////////////////////////////////////// -// Function: CullTraverserData::apply_transform_and_state -// Access: Public -// Description: Applies the transform and state from the current -// node onto the current data. This also evaluates -// billboards, etc. -//////////////////////////////////////////////////////////////////// -INLINE void CullTraverserData:: -apply_transform_and_state(CullTraverser *trav) { - apply_transform_and_state(trav, node()->get_transform(), - node()->get_state(), node()->get_effects()); -} - diff --git a/panda/src/pgraph/cullTraverserData.cxx b/panda/src/pgraph/cullTraverserData.cxx index 48ad43562e..a2e9c50cec 100644 --- a/panda/src/pgraph/cullTraverserData.cxx +++ b/panda/src/pgraph/cullTraverserData.cxx @@ -27,6 +27,33 @@ #include "compassEffect.h" #include "polylightEffect.h" #include "renderState.h" + + +//////////////////////////////////////////////////////////////////// +// Function: CullTraverserData::apply_transform_and_state +// Access: Public +// Description: Applies the transform and state from the current +// node onto the current data. This also evaluates +// billboards, etc. +//////////////////////////////////////////////////////////////////// +void CullTraverserData:: +apply_transform_and_state(CullTraverser *trav) { + PandaNode *node = _node_path.node(); + CPT(RenderState) node_state = node->get_state(); + + if (trav->has_tag_state_key() && node->has_tag(trav->get_tag_state_key())) { + // Here's a node that has been tagged with the special key for our + // current camera. This indicates some special state transition + // for this node, which is unique to this camera. + const Camera *camera = trav->get_scene()->get_camera_node(); + string tag_state = node->get_tag(trav->get_tag_state_key()); + node_state = node_state->compose(camera->get_tag_state(tag_state)); + } + + apply_transform_and_state(trav, node->get_transform(), + node_state, node->get_effects()); +} + //////////////////////////////////////////////////////////////////// // Function: CullTraverserData::apply_specific_transform // Access: Public diff --git a/panda/src/pgraph/cullTraverserData.h b/panda/src/pgraph/cullTraverserData.h index 32f318bb89..08c717c4a8 100644 --- a/panda/src/pgraph/cullTraverserData.h +++ b/panda/src/pgraph/cullTraverserData.h @@ -62,7 +62,7 @@ public: INLINE PandaNode *node() const; INLINE bool is_in_view(const DrawMask &camera_mask); - INLINE void apply_transform_and_state(CullTraverser *trav); + void apply_transform_and_state(CullTraverser *trav); void apply_transform_and_state(CullTraverser *trav, CPT(TransformState) node_transform, CPT(RenderState) node_state, diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index a72d019699..4235b183cd 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -357,11 +357,13 @@ has_parent() const { // Access: Published // Description: Returns the NodePath to the parent of the referenced // node: that is, this NodePath, shortened by one node. +// The parent of a singleton NodePath is defined to be +// the empty NodePath. //////////////////////////////////////////////////////////////////// INLINE NodePath NodePath:: get_parent() const { if (!has_parent()) { - return NodePath::fail(); + return NodePath(); } NodePath parent; parent._head = _head->get_next(); diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 5e8be69fc0..2805eaaad6 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -1956,28 +1956,73 @@ clear_color_scale() { void NodePath:: set_color_scale(const LVecBase4f &scale, int priority) { nassertv_always(!is_empty()); - node()->set_attrib(ColorScaleAttrib::make(scale), priority); + + const RenderAttrib *attrib = + node()->get_attrib(ColorScaleAttrib::get_class_type()); + if (attrib != (const RenderAttrib *)NULL) { + priority = max(priority, + node()->get_state()->get_override(ColorScaleAttrib::get_class_type())); + const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib); + + // Modify the existing ColorScaleAttrib to add the indicated + // colorScale. + node()->set_attrib(csa->set_scale(scale), priority); + + } else { + // Create a new ColorScaleAttrib for this node. + node()->set_attrib(ColorScaleAttrib::make(scale), priority); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_color_scale_off +// Access: Published +// Description: Disables any color scale attribute inherited from +// above. This is not the same thing as +// clear_color_scale(), which undoes any previous +// set_color_scale() operation on this node; rather, +// this actively disables any set_color_scale() that +// might be inherited from a parent node. This also +// disables set_alpha_scale() at the same time. +// +// It is legal to specify a new color scale on the same +// node with a subsequent call to set_color_scale() or +// set_alpha_scale(); this new scale will apply to lower +// geometry. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_color_scale_off(int priority) { + nassertv_always(!is_empty()); + node()->set_attrib(ColorScaleAttrib::make_off(), priority); } //////////////////////////////////////////////////////////////////// // Function: NodePath::set_alpha_scale // Access: Published // Description: Sets the alpha scale component of the transform -// without affecting the color scale. Note that any -// priority specified will also apply to the color +// without (much) affecting the color scale. Note that +// any priority specified will also apply to the color // scale. //////////////////////////////////////////////////////////////////// void NodePath:: set_alpha_scale(float scale, int priority) { nassertv_always(!is_empty()); + const RenderAttrib *attrib = node()->get_attrib(ColorScaleAttrib::get_class_type()); if (attrib != (const RenderAttrib *)NULL) { + priority = max(priority, + node()->get_state()->get_override(ColorScaleAttrib::get_class_type())); const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib); + + // Modify the existing ColorScaleAttrib to add the indicated + // colorScale. const LVecBase4f &sc = csa->get_scale(); - set_color_scale(sc[0], sc[1], sc[2], scale, priority); + node()->set_attrib(csa->set_scale(LVecBase4f(sc[0], sc[1], sc[2], scale)), priority); + } else { - set_color_scale(1.0f, 1.0f, 1.0f, scale, priority); + // Create a new ColorScaleAttrib for this node. + node()->set_attrib(ColorScaleAttrib::make(LVecBase4f(1.0f, 1.0f, 1.0f, scale)), priority); } } @@ -1985,21 +2030,29 @@ set_alpha_scale(float scale, int priority) { // Function: NodePath::set_all_color_scale // Access: Published // Description: Scales all the color components of the object by the -// same amount, darkening the object, without affecting -// alpha. Note that any priority specified will also -// apply to the alpha scale. +// same amount, darkening the object, without (much) +// affecting alpha. Note that any priority specified +// will also apply to the alpha scale. //////////////////////////////////////////////////////////////////// void NodePath:: set_all_color_scale(float scale, int priority) { nassertv_always(!is_empty()); + const RenderAttrib *attrib = node()->get_attrib(ColorScaleAttrib::get_class_type()); if (attrib != (const RenderAttrib *)NULL) { + priority = max(priority, + node()->get_state()->get_override(ColorScaleAttrib::get_class_type())); const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib); + + // Modify the existing ColorScaleAttrib to add the indicated + // colorScale. const LVecBase4f &sc = csa->get_scale(); - set_color_scale(scale, scale, scale, sc[3], priority); + node()->set_attrib(csa->set_scale(LVecBase4f(scale, scale, scale, sc[3])), priority); + } else { - set_color_scale(scale, scale, scale, 1.0f, priority); + // Create a new ColorScaleAttrib for this node. + node()->set_attrib(ColorScaleAttrib::make(LVecBase4f(scale, scale, scale, 1.0f)), priority); } } @@ -2007,8 +2060,10 @@ set_all_color_scale(float scale, int priority) { // Function: NodePath::get_color_scale // Access: Published // Description: Returns the complete color scale vector that has been -// applied to the bottom node, or all 1's (identity) if -// no scale has been applied. +// applied to this node via a previous call to +// set_color_scale() and/or set_alpha_scale(), or all +// 1's (identity) if no scale has been applied to this +// particular node. //////////////////////////////////////////////////////////////////// const LVecBase4f &NodePath:: get_color_scale() const { diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index aa303044cb..ae71695f1a 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -474,6 +474,8 @@ PUBLISHED: int priority = 0); INLINE void set_color_scale(float sx, float sy, float sz, float sa, int priority = 0); + void set_color_scale_off(int priority = 0); + void set_alpha_scale(float scale, int priority = 0); void set_all_color_scale(float scale, int priority = 0); INLINE void set_sr(float sr);