diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 80fd1b50b7..73a246bfb4 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -43,6 +43,7 @@ #include "antialiasAttrib.h" #include "audioVolumeAttrib.h" #include "texProjectorEffect.h" +#include "scissorEffect.h" #include "texturePool.h" #include "planeNode.h" #include "lensNode.h" @@ -2796,6 +2797,113 @@ has_clip_plane_off(const NodePath &clip_plane) const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_scissor +// Access: Published +// Description: Sets up a scissor region on the nodes rendered at +// this level and below. The four coordinates are +// understood to define a rectangle in screen space. +// These numbers are relative to the current +// DisplayRegion, where (0,0) is the lower-left corner +// of the DisplayRegion, and (1,1) is the upper-right +// corner. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_scissor(float left, float right, float bottom, float top) { + set_effect(ScissorEffect::make_screen(LVecBase4f(left, right, bottom, top))); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_scissor +// Access: Published +// Description: Sets up a scissor region on the nodes rendered at +// this level and below. The two points are understood +// to be relative to this node. When these points are +// projected into screen space, they define the +// diagonally-opposite points that determine the scissor +// region. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_scissor(const LPoint3f &a, const LPoint3f &b) { + set_effect(ScissorEffect::make_node(a, b)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_scissor +// Access: Published +// Description: Sets up a scissor region on the nodes rendered at +// this level and below. The four points are understood +// to be relative to this node. When these points are +// projected into screen space, they define the +// bounding volume of the scissor region (the scissor +// region is the smallest onscreen rectangle that +// encloses all four points). +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_scissor(const LPoint3f &a, const LPoint3f &b, + const LPoint3f &c, const LPoint3f &d) { + set_effect(ScissorEffect::make_node(a, b, c, d)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_scissor +// Access: Published +// Description: Sets up a scissor region on the nodes rendered at +// this level and below. The two points are understood +// to be relative to the indicated other node. When +// these points are projected into screen space, they +// define the diagonally-opposite points that determine +// the scissor region. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_scissor(const NodePath &other, const LPoint3f &a, const LPoint3f &b) { + set_effect(ScissorEffect::make_node(a, b, other)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_scissor +// Access: Published +// Description: Sets up a scissor region on the nodes rendered at +// this level and below. The four points are understood +// to be relative to the indicated other node. When +// these points are projected into screen space, they +// define the bounding volume of the scissor region (the +// scissor region is the smallest onscreen rectangle +// that encloses all four points). +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_scissor(const NodePath &other, + const LPoint3f &a, const LPoint3f &b, + const LPoint3f &c, const LPoint3f &d) { + set_effect(ScissorEffect::make_node(a, b, c, d, other)); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::clear_scissor +// Access: Published +// Description: Removes the scissor region that was defined at this +// node level by a previous call to set_scissor(). +//////////////////////////////////////////////////////////////////// +void NodePath:: +clear_scissor() { + clear_effect(ScissorEffect::get_class_type()); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::has_scissor +// Access: Published +// Description: Returns true if a scissor region was defined at this +// node by a previous call to set_scissor(). This does +// not check for scissor regions inherited from a parent +// class. It also does not check for the presence of a +// low-level ScissorAttrib, which is different from the +// ScissorEffect added by set_scissor. +//////////////////////////////////////////////////////////////////// +bool NodePath:: +has_scissor() const { + return has_effect(ScissorEffect::get_class_type()); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_bin // Access: Published diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index b5e64ce783..4e529f2bd4 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -547,6 +547,18 @@ PUBLISHED: bool has_clip_plane_off() const; bool has_clip_plane_off(const NodePath &clip_plane) const; + void set_scissor(float left, float right, float bottom, float top); + void set_scissor(const LPoint3f &a, const LPoint3f &b); + void set_scissor(const LPoint3f &a, const LPoint3f &b, + const LPoint3f &c, const LPoint3f &d); + void set_scissor(const NodePath &other, + const LPoint3f &a, const LPoint3f &b); + void set_scissor(const NodePath &other, + const LPoint3f &a, const LPoint3f &b, + const LPoint3f &c, const LPoint3f &d); + void clear_scissor(); + bool has_scissor() const; + void set_bin(const string &bin_name, int draw_order, int priority = 0); void clear_bin(); bool has_bin() const; diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 6414298678..33c731f3dd 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -344,7 +344,16 @@ void PandaNode:: apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, GeomTransformer &transformer) { if ((attrib_types & SceneGraphReducer::TT_transform) != 0) { - xform(attribs._transform->get_mat()); + const LMatrix4f &mat = attribs._transform->get_mat(); + xform(mat); + + Thread *current_thread = Thread::get_current_thread(); + OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) { + CDStageWriter cdata(_cycler, pipeline_stage, current_thread); + cdata->_effects = cdata->_effects->xform(mat); + cdata->set_fancy_bit(FB_effects, !cdata->_effects->is_empty()); + } + CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler); } } diff --git a/panda/src/pgraph/scissorAttrib.cxx b/panda/src/pgraph/scissorAttrib.cxx index f0816bbc7d..09fc6a7400 100644 --- a/panda/src/pgraph/scissorAttrib.cxx +++ b/panda/src/pgraph/scissorAttrib.cxx @@ -103,6 +103,37 @@ compare_to_impl(const RenderAttrib *other) const { return _frame.compare_to(ta->_frame); } +//////////////////////////////////////////////////////////////////// +// Function: ScissorAttrib::compose_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived RenderAttrib +// types to specify how two consecutive RenderAttrib +// objects of the same type interact. +// +// This should return the result of applying the other +// RenderAttrib to a node in the scene graph below this +// RenderAttrib, which was already applied. In most +// cases, the result is the same as the other +// RenderAttrib (that is, a subsequent RenderAttrib +// completely replaces the preceding one). On the other +// hand, some kinds of RenderAttrib (for instance, +// ColorTransformAttrib) might combine in meaningful +// ways. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) ScissorAttrib:: +compose_impl(const RenderAttrib *other) const { + const ScissorAttrib *ta; + DCAST_INTO_R(ta, other, 0); + + LVecBase4f new_frame(max(ta->_frame[0], _frame[0]), + min(ta->_frame[1], _frame[1]), + max(ta->_frame[2], _frame[2]), + min(ta->_frame[3], _frame[3])); + + ScissorAttrib *attrib = new ScissorAttrib(new_frame); + return return_new(attrib); +} + //////////////////////////////////////////////////////////////////// // Function: ScissorAttrib::make_default_impl // Access: Protected, Virtual diff --git a/panda/src/pgraph/scissorAttrib.h b/panda/src/pgraph/scissorAttrib.h index 7bb7c84a8e..df550e722b 100644 --- a/panda/src/pgraph/scissorAttrib.h +++ b/panda/src/pgraph/scissorAttrib.h @@ -55,6 +55,7 @@ public: protected: virtual int compare_to_impl(const RenderAttrib *other) const; + virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const; virtual RenderAttrib *make_default_impl() const; private: diff --git a/panda/src/pgraph/scissorEffect.I b/panda/src/pgraph/scissorEffect.I index 81de70fbed..4f130173bd 100644 --- a/panda/src/pgraph/scissorEffect.I +++ b/panda/src/pgraph/scissorEffect.I @@ -63,7 +63,19 @@ get_num_points() const { INLINE const LPoint3f &ScissorEffect:: get_point(int n) const { nassertr(n >= 0 && n < (int)_points.size(), LPoint3f::zero()); - return _points[n]; + return _points[n]._p; +} + +//////////////////////////////////////////////////////////////////// +// Function: ScissorEffect::get_node +// Access: Published +// Description: Returns the node to which the nth point is relative, +// or empty NodePath to indicate the current node. +//////////////////////////////////////////////////////////////////// +INLINE NodePath ScissorEffect:: +get_node(int n) const { + nassertr(n >= 0 && n < (int)_points.size(), NodePath()); + return _points[n]._node; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/scissorEffect.cxx b/panda/src/pgraph/scissorEffect.cxx index 693e33da21..989905aa8e 100644 --- a/panda/src/pgraph/scissorEffect.cxx +++ b/panda/src/pgraph/scissorEffect.cxx @@ -33,7 +33,7 @@ TypeHandle ScissorEffect::_type_handle; //////////////////////////////////////////////////////////////////// ScissorEffect:: ScissorEffect(bool screen, const LVecBase4f &frame, - const LPoint3f *points, int num_points, bool clip) : + const PointDef *points, int num_points, bool clip) : _screen(screen), _frame(frame), _clip(clip) { _points.reserve(num_points); @@ -42,6 +42,21 @@ ScissorEffect(bool screen, const LVecBase4f &frame, } } +//////////////////////////////////////////////////////////////////// +// Function: ScissorEffect::Copy Constructor +// Access: Private +// Description: Use ScissorEffect::make() to construct a new +// ScissorEffect object. +//////////////////////////////////////////////////////////////////// +ScissorEffect:: +ScissorEffect(const ScissorEffect ©) : + _screen(copy._screen), + _frame(copy._frame), + _points(copy._points), + _clip(copy._clip) +{ +} + //////////////////////////////////////////////////////////////////// // Function: ScissorEffect::make_screen // Access: Published, Static @@ -55,20 +70,37 @@ make_screen(const LVecBase4f &frame, bool clip) { return return_new(effect); } +//////////////////////////////////////////////////////////////////// +// Function: ScissorEffect::make_node +// Access: Published, Static +// Description: Constructs a new node-relative ScissorEffect, with no +// points. This empty ScissorEffect does nothing. You +// must then call add_point a number of times to add the +// points you require. +//////////////////////////////////////////////////////////////////// +CPT(RenderEffect) ScissorEffect:: +make_node(bool clip) { + ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), NULL, 0, clip); + return return_new(effect); +} + //////////////////////////////////////////////////////////////////// // Function: ScissorEffect::make_node // Access: Published, Static // Description: Constructs a new node-relative ScissorEffect. The // two points are understood to be relative to the -// current node, and determine the diagonally opposite +// indicated node, or the current node if the NodePath +// is empty, and determine the diagonally opposite // corners of the scissor region. //////////////////////////////////////////////////////////////////// CPT(RenderEffect) ScissorEffect:: -make_node(const LPoint3f &a, const LPoint3f &b, bool clip) { - LPoint3f points[2]; - points[0] = a; - points[1] = b; - ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 2, clip); +make_node(const LPoint3f &a, const LPoint3f &b, const NodePath &node) { + PointDef points[2]; + points[0]._p = a; + points[0]._node = node; + points[1]._p = b; + points[1]._node = node; + ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 2, true); return return_new(effect); } @@ -77,30 +109,70 @@ make_node(const LPoint3f &a, const LPoint3f &b, bool clip) { // Access: Published, Static // Description: Constructs a new node-relative ScissorEffect. The // four points are understood to be relative to the -// current node, and determine four points surrounding -// the scissor region. +// indicated node, or the current node if the indicated +// NodePath is empty, and determine four points +// surrounding the scissor region. //////////////////////////////////////////////////////////////////// CPT(RenderEffect) ScissorEffect:: -make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, bool clip) { - LPoint3f points[4]; - points[0] = a; - points[1] = b; - points[2] = c; - points[3] = d; - ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 4, clip); +make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, const NodePath &node) { + PointDef points[4]; + points[0]._p = a; + points[0]._node = node; + points[1]._p = b; + points[1]._node = node; + points[2]._p = c; + points[2]._node = node; + points[3]._p = d; + points[3]._node = node; + ScissorEffect *effect = new ScissorEffect(false, LVecBase4f::zero(), points, 4, true); return return_new(effect); } //////////////////////////////////////////////////////////////////// -// Function: ScissorEffect::safe_to_transform -// Access: Public, Virtual -// Description: Returns true if it is generally safe to transform -// this particular kind of RenderEffect by calling the -// xform() method, false otherwise. +// Function: ScissorEffect::add_point +// Access: Published +// Description: Returns a new ScissorEffect with the indicated point +// added. It is only valid to call this on a "node" +// type ScissorEffect. The full set of points, +// projected into screen space, defines the bounding +// volume of the rectangular scissor region. +// +// Each point may be relative to a different node, if +// desired. //////////////////////////////////////////////////////////////////// -bool ScissorEffect:: -safe_to_transform() const { - return false; +CPT(RenderEffect) ScissorEffect:: +add_point(const LPoint3f &p, const NodePath &node) const { + nassertr(!is_screen(), this); + ScissorEffect *effect = new ScissorEffect(*this); + PointDef point; + point._p = p; + point._node = node; + effect->_points.push_back(point); + return return_new(effect); +} + +//////////////////////////////////////////////////////////////////// +// Function: ScissorEffect::xform +// Access: Public, Virtual +// Description: Returns a new RenderEffect transformed by the +// indicated matrix. +//////////////////////////////////////////////////////////////////// +CPT(RenderEffect) ScissorEffect:: +xform(const LMatrix4f &mat) const { + if (is_screen()) { + return this; + } + ScissorEffect *effect = new ScissorEffect(*this); + Points::iterator pi; + for (pi = effect->_points.begin(); + pi != effect->_points.end(); + ++pi) { + PointDef &point = (*pi); + if (point._node.is_empty()) { + point._p = point._p * mat; + } + } + return return_new(effect); } //////////////////////////////////////////////////////////////////// @@ -117,7 +189,12 @@ output(ostream &out) const { out << "node"; Points::const_iterator pi; for (pi = _points.begin(); pi != _points.end(); ++pi) { - out << " [" << (*pi) << "]"; + const PointDef &point = (*pi); + if (point._node.is_empty()) { + out << " (" << point._p << ")"; + } else { + out << " (" << point._node << ":" << point._p << ")"; + } } } if (!get_clip()) { @@ -162,8 +239,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data, CPT(RenderState) &node_state) const { LVecBase4f frame; const Lens *lens = trav->get_scene()->get_lens(); - CPT(TransformState) modelview_transform = data.get_modelview_transform(trav)->compose(node_transform); - if (modelview_transform->is_singular()) { + CPT(TransformState) modelview_transform = data.get_modelview_transform(trav); + CPT(TransformState) net_transform = modelview_transform->compose(node_transform); + if (net_transform->is_singular()) { // If we're under a singular transform, never mind. return; } @@ -172,15 +250,24 @@ cull_callback(CullTraverser *trav, CullTraverserData &data, frame = _frame; } else { const LMatrix4f &proj_mat = lens->get_projection_mat(); - LMatrix4f net_mat = modelview_transform->get_mat() * proj_mat; + LMatrix4f net_mat = net_transform->get_mat() * proj_mat; bool any_points = false; Points::const_iterator pi; for (pi = _points.begin(); pi != _points.end(); ++pi) { - const LPoint3f &p = (*pi); - LVecBase4f pv(p[0], p[1], p[2], 1.0f); - pv = pv * net_mat; + const PointDef &point = (*pi); + LVecBase4f pv(point._p[0], point._p[1], point._p[2], 1.0f); + if (point._node.is_empty()) { + // Relative to this node. + pv = pv * net_mat; + + } else { + // Relative to some other node. + LMatrix4f other_mat = point._node.get_net_transform()->get_mat() * proj_mat; + pv = pv * other_mat; + } + if (pv[3] == 0) { continue; } @@ -264,7 +351,11 @@ compare_to_impl(const RenderEffect *other) const { return compare; } for (size_t i = 0; i < _points.size(); ++i) { - compare = _points[i].compare_to(ta->_points[i]); + compare = _points[i]._p.compare_to(ta->_points[i]._p); + if (compare != 0) { + return compare; + } + compare = _points[i]._node.compare_to(ta->_points[i]._node); if (compare != 0) { return compare; } @@ -301,7 +392,7 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_uint16(_points.size()); Points::const_iterator pi; for (pi = _points.begin(); pi != _points.end(); ++pi) { - (*pi).write_datagram(dg); + (*pi)._p.write_datagram(dg); } } dg.add_bool(_clip); @@ -345,9 +436,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { int num_points = scan.get_uint16(); _points.reserve(num_points); for (int i = 0; i < num_points; ++i) { - LPoint3f p; - p.read_datagram(scan); - _points.push_back(p); + PointDef point; + point._p.read_datagram(scan); + _points.push_back(point); } } _clip = scan.get_bool(); diff --git a/panda/src/pgraph/scissorEffect.h b/panda/src/pgraph/scissorEffect.h index 7b6b53b61c..ac8c7a794b 100644 --- a/panda/src/pgraph/scissorEffect.h +++ b/panda/src/pgraph/scissorEffect.h @@ -31,24 +31,34 @@ //////////////////////////////////////////////////////////////////// class EXPCL_PANDA_PGRAPH ScissorEffect : public RenderEffect { private: + class PointDef { + public: + LPoint3f _p; + NodePath _node; + }; + ScissorEffect(bool screen, const LVecBase4f &frame, - const LPoint3f *points, int num_points, bool clip); + const PointDef *points, int num_points, bool clip); + ScissorEffect(const ScissorEffect ©); PUBLISHED: static CPT(RenderEffect) make_screen(const LVecBase4f &frame, bool clip = true); - static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, bool clip = true); - static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, bool clip = true); + static CPT(RenderEffect) make_node(bool clip = true); + static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, const NodePath &node = NodePath()); + static CPT(RenderEffect) make_node(const LPoint3f &a, const LPoint3f &b, const LPoint3f &c, const LPoint3f &d, const NodePath &node = NodePath()); + CPT(RenderEffect) add_point(const LPoint3f &point, const NodePath &node = NodePath()) const; INLINE bool is_screen() const; INLINE const LVecBase4f &get_frame() const; INLINE int get_num_points() const; INLINE const LPoint3f &get_point(int n) const; + INLINE NodePath get_node(int n) const; INLINE bool get_clip() const; public: - virtual bool safe_to_transform() const; + virtual CPT(RenderEffect) xform(const LMatrix4f &mat) const; virtual void output(ostream &out) const; virtual bool has_cull_callback() const; @@ -65,7 +75,7 @@ private: private: bool _screen; LVecBase4f _frame; - typedef pvector Points; + typedef pvector Points; Points _points; bool _clip; diff --git a/panda/src/pgui/pgVirtualFrame.I b/panda/src/pgui/pgVirtualFrame.I index b16b4c09b1..a8e7e14213 100644 --- a/panda/src/pgui/pgVirtualFrame.I +++ b/panda/src/pgui/pgVirtualFrame.I @@ -88,13 +88,11 @@ get_canvas_node() const { } //////////////////////////////////////////////////////////////////// -// Function: PGVirtualFrame::get_clip_plane_node +// Function: PGVirtualFrame::get_canvas_parent // Access: Published -// Description: Returns the special node that holds all of PlaneNodes -// that are used for applying the clip planes to the -// canvas_node. +// Description: Returns the parent node of the canvas_node. //////////////////////////////////////////////////////////////////// INLINE PandaNode *PGVirtualFrame:: -get_clip_plane_node() const { - return _clip_plane_node; +get_canvas_parent() const { + return _canvas_parent; } diff --git a/panda/src/pgui/pgVirtualFrame.cxx b/panda/src/pgui/pgVirtualFrame.cxx index 36335bedb4..143ab4d232 100644 --- a/panda/src/pgui/pgVirtualFrame.cxx +++ b/panda/src/pgui/pgVirtualFrame.cxx @@ -13,8 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "pgVirtualFrame.h" -#include "clipPlaneAttrib.h" -#include "planeNode.h" +#include "scissorEffect.h" #include "sceneGraphReducer.h" TypeHandle PGVirtualFrame::_type_handle; @@ -99,7 +98,7 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map, // Reassign the canvas_node to point to the new copy, if it's there. const PGVirtualFrame *from_frame = DCAST(PGVirtualFrame, from); PandaNode *from_canvas_node = from_frame->get_canvas_node(); - PandaNode *from_clip_plane_node = from_frame->get_clip_plane_node(); + PandaNode *from_canvas_parent = from_frame->get_canvas_parent(); InstanceMap::const_iterator ci; ci = inst_map.find(from_canvas_node); @@ -108,10 +107,10 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map, _canvas_node = DCAST(ModelNode, (*ci).second); } - ci = inst_map.find(from_clip_plane_node); + ci = inst_map.find(from_canvas_parent); if (ci != inst_map.end()) { - remove_child(_clip_plane_node); - _clip_plane_node = (*ci).second; + remove_child(_canvas_parent); + _canvas_parent = DCAST(ModelNode, (*ci).second); } // Reassign the clip planes according to the clip frame. @@ -163,33 +162,14 @@ set_clip_frame(const LVecBase4f &frame) { if (!_has_clip_frame || _clip_frame != frame) { _has_clip_frame = true; _clip_frame = frame; + + CPT(RenderEffect) scissor_effect = ScissorEffect::make_node + (LPoint3f(_clip_frame[0], _clip_frame[2], _clip_frame[2]), + LPoint3f(_clip_frame[1], _clip_frame[2], _clip_frame[2]), + LPoint3f(_clip_frame[1], _clip_frame[3], _clip_frame[3]), + LPoint3f(_clip_frame[0], _clip_frame[3], _clip_frame[3])); - const LVector3f r = LVector3f::right(); - const LVector3f u = LVector3f::up(); - - PT(PlaneNode) left_clip = - new PlaneNode("left_clip", Planef(r, r * _clip_frame[0])); - PT(PlaneNode) right_clip = - new PlaneNode("right_clip", Planef(-r, r * _clip_frame[1])); - - PT(PlaneNode) bottom_clip = - new PlaneNode("bottom_clip", Planef(u, u * _clip_frame[2])); - PT(PlaneNode) top_clip = - new PlaneNode("top_clip", Planef(-u, u * _clip_frame[3])); - - _clip_plane_node->remove_all_children(); - _clip_plane_node->add_child(left_clip); - _clip_plane_node->add_child(right_clip); - _clip_plane_node->add_child(bottom_clip); - _clip_plane_node->add_child(top_clip); - - CPT(ClipPlaneAttrib) plane_attrib = DCAST(ClipPlaneAttrib, ClipPlaneAttrib::make()); - plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(left_clip))); - plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(right_clip))); - plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(bottom_clip))); - plane_attrib = DCAST(ClipPlaneAttrib, plane_attrib->add_on_plane(NodePath::any_path(top_clip))); - - _canvas_node->set_attrib(plane_attrib); + _canvas_parent->set_effect(scissor_effect); clip_frame_changed(); } } @@ -205,7 +185,7 @@ clear_clip_frame() { if (_has_clip_frame) { _has_clip_frame = false; - _canvas_node->clear_attrib(ClipPlaneAttrib::get_class_type()); + _canvas_parent->clear_effect(ScissorEffect::get_class_type()); clip_frame_changed(); } } @@ -222,17 +202,16 @@ clip_frame_changed() { //////////////////////////////////////////////////////////////////// // Function: PGVirtualFrame::setup_child_nodes // Access: Private -// Description: Creates the special canvas_node and clip_plane_node +// Description: Creates the special canvas_node and canvas_parent // for this object. //////////////////////////////////////////////////////////////////// void PGVirtualFrame:: setup_child_nodes() { + _canvas_parent = new ModelNode("canvas_parent"); + _canvas_parent->set_preserve_transform(ModelNode::PT_local); + add_child(_canvas_parent); + _canvas_node = new ModelNode("canvas"); _canvas_node->set_preserve_transform(ModelNode::PT_local); - // We have to preserve the clip plane attribute. - _canvas_node->set_preserve_attributes(SceneGraphReducer::TT_other); - add_child(_canvas_node); - - _clip_plane_node = new PandaNode("clip_planes"); - add_child(_clip_plane_node); + _canvas_parent->add_child(_canvas_node); } diff --git a/panda/src/pgui/pgVirtualFrame.h b/panda/src/pgui/pgVirtualFrame.h index 844a5094c8..c04875f05f 100644 --- a/panda/src/pgui/pgVirtualFrame.h +++ b/panda/src/pgui/pgVirtualFrame.h @@ -29,19 +29,19 @@ class TransformState; // only see the portion of the canvas that is below the // window at any given time. // -// This works simply by automatically defining clipping -// planes to be applied to a special child node, called +// This works simply by automatically defining a scissor +// effect to be applied to a special child node, called // the canvas_node, of the PGVirtualFrame node. Every // object that is parented to the canvas_node will be -// clipped by the clip_frame. Also, you can modify the -// canvas_transform through convenience methods here, -// which actually modifies the transform on the +// clipped by the scissor effect. Also, you can modify +// the canvas_transform through convenience methods +// here, which actually modifies the transform on the // canvas_node. // // The net effect is that the virtual canvas is // arbitrarily large, and we can peek at it through the -// clip_frame, and scroll through different parts of it -// by modifying the canvas_transform. +// scissor region, and scroll through different parts of +// it by modifying the canvas_transform. // // See PGScrollFrame for a specialization of this class // that handles the traditional scrolling canvas, with @@ -71,7 +71,7 @@ PUBLISHED: INLINE const TransformState *get_canvas_transform() const; INLINE PandaNode *get_canvas_node() const; - INLINE PandaNode *get_clip_plane_node() const; + INLINE PandaNode *get_canvas_parent() const; protected: virtual void clip_frame_changed(); @@ -84,7 +84,7 @@ private: LVecBase4f _clip_frame; PT(ModelNode) _canvas_node; - PT(PandaNode) _clip_plane_node; + PT(ModelNode) _canvas_parent; public: static TypeHandle get_class_type() {