From 4d59f04134274aeec855cb23864772554f25928b Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 1 Aug 2008 22:48:42 +0000 Subject: [PATCH] scissor MouseWatcherRegions too --- panda/src/pgraph/renderState.I | 19 ++++++++++++++ panda/src/pgraph/renderState.cxx | 22 ++++++++++++++++ panda/src/pgraph/renderState.h | 39 ++++++++++++++++------------- panda/src/pgui/pgItem.cxx | 43 +++++++++++++++++++++++--------- panda/src/pgui/pgItem.h | 4 ++- 5 files changed, 97 insertions(+), 30 deletions(-) diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index 79347e3ab0..b100855f2b 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -366,6 +366,25 @@ get_clip_plane() const { return _clip_plane; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::get_scissor +// Access: Published +// Description: This function is provided as an optimization, to +// speed up the render-time checking for the existance +// of a ScissorAttrib on this state. It returns a +// pointer to the ScissorAttrib, if there is one, or +// NULL if there is not. +//////////////////////////////////////////////////////////////////// +INLINE const ScissorAttrib *RenderState:: +get_scissor() const { + if ((_flags & F_checked_scissor) == 0) { + // We pretend this function is const, even though it transparently + // modifies the internal scissor cache. + ((RenderState *)this)->determine_scissor(); + } + return _scissor; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::get_shader // Access: Published diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index a89908e786..5304e498b8 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -18,6 +18,7 @@ #include "cullBinManager.h" #include "fogAttrib.h" #include "clipPlaneAttrib.h" +#include "scissorAttrib.h" #include "transparencyAttrib.h" #include "colorAttrib.h" #include "colorScaleAttrib.h" @@ -1972,6 +1973,27 @@ determine_clip_plane() { _flags |= F_checked_clip_plane; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::determine_scissor +// Access: Private +// Description: This is the private implementation of get_scissor(). +//////////////////////////////////////////////////////////////////// +void RenderState:: +determine_scissor() { + MutexHolder holder(_lock); + if ((_flags & F_checked_scissor) != 0) { + // Someone else checked it first. + return; + } + + const RenderAttrib *attrib = get_attrib(ScissorAttrib::get_class_type()); + _scissor = (const ScissorAttrib *)NULL; + if (attrib != (const RenderAttrib *)NULL) { + _scissor = DCAST(ScissorAttrib, attrib); + } + _flags |= F_checked_scissor; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::determine_shader // Access: Private diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 664430a1bb..37fbd26156 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -42,6 +42,7 @@ class ColorScaleAttrib; class TextureAttrib; class TexGenAttrib; class ClipPlaneAttrib; +class ScissorAttrib; class ShaderAttrib; class FactoryParams; class AudioVolumeAttrib; @@ -147,6 +148,7 @@ PUBLISHED: INLINE const TexMatrixAttrib *get_tex_matrix() const; INLINE const RenderModeAttrib *get_render_mode() const; INLINE const ClipPlaneAttrib *get_clip_plane() const; + INLINE const ScissorAttrib *get_scissor() const; INLINE const ShaderAttrib *get_shader() const; INLINE const AudioVolumeAttrib *get_audio_volume() const; @@ -201,6 +203,7 @@ private: void determine_tex_matrix(); void determine_render_mode(); void determine_clip_plane(); + void determine_scissor(); void determine_shader(); void determine_cull_callback(); void determine_audio_volume(); @@ -315,28 +318,30 @@ private: const TexMatrixAttrib *_tex_matrix; const RenderModeAttrib *_render_mode; const ClipPlaneAttrib *_clip_plane; + const ScissorAttrib *_scissor; const ShaderAttrib *_shader; const AudioVolumeAttrib *_audio_volume; enum Flags { - F_checked_bin_index = 0x0001, - F_checked_fog = 0x0002, - F_checked_bin = 0x0004, - F_checked_transparency = 0x0008, - F_checked_color = 0x0010, - F_checked_color_scale = 0x0020, - F_checked_texture = 0x0040, - F_checked_tex_gen = 0x0080, - F_checked_tex_matrix = 0x0100, - F_checked_render_mode = 0x0200, - F_checked_clip_plane = 0x0400, - F_checked_shader = 0x0800, - F_checked_cull_callback = 0x1000, - F_checked_audio_volume = 0x2000, - F_has_cull_callback = 0x4000, - F_is_destructing = 0x8000, + F_checked_bin_index = 0x000001, + F_checked_fog = 0x000002, + F_checked_bin = 0x000004, + F_checked_transparency = 0x000008, + F_checked_color = 0x000010, + F_checked_color_scale = 0x000020, + F_checked_texture = 0x000040, + F_checked_tex_gen = 0x000080, + F_checked_tex_matrix = 0x000100, + F_checked_render_mode = 0x000200, + F_checked_clip_plane = 0x000400, + F_checked_shader = 0x000800, + F_checked_cull_callback = 0x001000, + F_checked_audio_volume = 0x002000, + F_has_cull_callback = 0x004000, + F_is_destructing = 0x008000, + F_checked_scissor = 0x010000, }; - unsigned short _flags; + unsigned int _flags; // This mutex protects _flags, and all of the above computed values. Mutex _lock; diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index d8f95dcf7b..9e68a60f53 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -26,6 +26,7 @@ #include "cullTraverserData.h" #include "cullBinManager.h" #include "clipPlaneAttrib.h" +#include "scissorAttrib.h" #include "dcast.h" #include "boundingSphere.h" #include "boundingBox.h" @@ -252,7 +253,8 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { // which only provides one. sort = (bin_sort << 16) | ((sort + 0x8000) & 0xffff); - if (activate_region(transform, sort, data._state->get_clip_plane())) { + if (activate_region(transform, sort, data._state->get_clip_plane(), + data._state->get_scissor())) { pg_trav->_top->add_region(get_region()); } } @@ -379,7 +381,8 @@ xform(const LMatrix4f &mat) { //////////////////////////////////////////////////////////////////// bool PGItem:: activate_region(const LMatrix4f &transform, int sort, - const ClipPlaneAttrib *cpa) { + const ClipPlaneAttrib *cpa, + const ScissorAttrib *sa) { // Transform all four vertices, and get the new bounding box. This // way the region works (mostly) even if has been rotated. LPoint3f ll(_frame[0], 0.0f, _frame[2]); @@ -391,8 +394,10 @@ activate_region(const LMatrix4f &transform, int sort, ul = ul * transform; ur = ur * transform; + LVecBase4f frame; if (cpa != (ClipPlaneAttrib *)NULL && cpa->get_num_on_planes() != 0) { - // Apply the clip plane(s) now that we are here in world space. + // Apply the clip plane(s) and/or scissor region now that we are + // here in world space. pvector points; points.reserve(4); @@ -406,13 +411,13 @@ activate_region(const LMatrix4f &transform, int sort, NodePath plane_path = cpa->get_on_plane(i); Planef plane = DCAST(PlaneNode, plane_path.node())->get_plane(); plane.xform(plane_path.get_net_transform()->get_mat()); - + // We ignore the y coordinate, assuming the frame is still in // the X-Z plane after being transformed. Not sure if we really // need to support general 3-D transforms on 2-D objects. clip_frame(points, plane); } - + if (points.empty()) { // Turns out it's completely clipped after all. return false; @@ -420,7 +425,7 @@ activate_region(const LMatrix4f &transform, int sort, pvector::iterator pi; pi = points.begin(); - LVecBase4f frame((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]); + frame.set((*pi)[0], (*pi)[0], (*pi)[1], (*pi)[1]); ++pi; while (pi != points.end()) { frame[0] = min(frame[0], (*pi)[0]); @@ -429,15 +434,29 @@ activate_region(const LMatrix4f &transform, int sort, frame[3] = max(frame[3], (*pi)[1]); ++pi; } - _region->set_frame(frame); - } else { // Since there are no clip planes involved, just set the frame. - _region->set_frame(min(min(ll[0], lr[0]), min(ul[0], ur[0])), - max(max(ll[0], lr[0]), max(ul[0], ur[0])), - min(min(ll[2], lr[2]), min(ul[2], ur[2])), - max(max(ll[2], lr[2]), max(ul[2], ur[2]))); + frame.set(min(min(ll[0], lr[0]), min(ul[0], ur[0])), + max(max(ll[0], lr[0]), max(ul[0], ur[0])), + min(min(ll[2], lr[2]), min(ul[2], ur[2])), + max(max(ll[2], lr[2]), max(ul[2], ur[2]))); } + + if (sa != (ScissorAttrib *)NULL) { + // Also restrict it to within the scissor region. + const LVecBase4f &sf = sa->get_frame(); + // Expand sf from 0..1 to -1..1. + frame.set(max(frame[0], sf[0] * 2.0f - 1.0f), + min(frame[1], sf[1] * 2.0f - 1.0f), + max(frame[2], sf[2] * 2.0f - 1.0f), + min(frame[3], sf[3] * 2.0f - 1.0f)); + if (frame[1] <= frame[0] || frame[3] <= frame[2]) { + // Completely outside the scissor region. + return false; + } + } + + _region->set_frame(frame); _region->set_sort(sort); _region->set_active(true); diff --git a/panda/src/pgui/pgItem.h b/panda/src/pgui/pgItem.h index 57636bff5f..7119b3881a 100644 --- a/panda/src/pgui/pgItem.h +++ b/panda/src/pgui/pgItem.h @@ -34,6 +34,7 @@ class PGTop; class MouseWatcherParameter; class AudioSound; class ClipPlaneAttrib; +class ScissorAttrib; //////////////////////////////////////////////////////////////////// // Class : PGItem @@ -70,7 +71,8 @@ protected: public: virtual void xform(const LMatrix4f &mat); bool activate_region(const LMatrix4f &transform, int sort, - const ClipPlaneAttrib *cpa); + const ClipPlaneAttrib *cpa, + const ScissorAttrib *sa); INLINE PGMouseWatcherRegion *get_region() const; virtual void enter_region(const MouseWatcherParameter ¶m);