Canvas: basic support for rectangular clipping (like CSS clip property)
This commit is contained in:
parent
4dfe36cdc1
commit
fd27e7bd43
@ -335,6 +335,18 @@ namespace canvas
|
||||
_texture.setViewSize(_view_width, _view_height);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int Canvas::getViewWidth() const
|
||||
{
|
||||
return _view_width;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int Canvas::getViewHeight() const
|
||||
{
|
||||
return _view_height;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool Canvas::handleMouseEvent(const MouseEventPtr& event)
|
||||
{
|
||||
|
@ -114,6 +114,9 @@ namespace canvas
|
||||
void setViewWidth(int w);
|
||||
void setViewHeight(int h);
|
||||
|
||||
int getViewWidth() const;
|
||||
int getViewHeight() const;
|
||||
|
||||
bool handleMouseEvent(const MouseEventPtr& event);
|
||||
|
||||
virtual void childAdded( SGPropertyNode * parent,
|
||||
|
@ -24,9 +24,13 @@
|
||||
|
||||
#include <osg/Drawable>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Scissor>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@ -303,6 +307,71 @@ namespace canvas
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setClip(const std::string& clip)
|
||||
{
|
||||
if( clip.empty() || clip == "auto" )
|
||||
{
|
||||
getOrCreateStateSet()->removeAttribute(osg::StateAttribute::SCISSOR);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO generalize CSS property parsing
|
||||
const std::string RECT("rect(");
|
||||
if( !boost::ends_with(clip, ")")
|
||||
|| !boost::starts_with(clip, RECT) )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
|
||||
return;
|
||||
}
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
const boost::char_separator<char> del(", \t\npx");
|
||||
|
||||
tokenizer tokens(clip.begin() + RECT.size(), clip.end() - 1, del);
|
||||
int comp = 0;
|
||||
int values[4];
|
||||
for( tokenizer::const_iterator tok = tokens.begin();
|
||||
tok != tokens.end() && comp < 4;
|
||||
++tok, ++comp )
|
||||
{
|
||||
values[comp] = boost::lexical_cast<int>(*tok);
|
||||
}
|
||||
|
||||
if( comp < 4 )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
|
||||
return;
|
||||
}
|
||||
|
||||
float scale_x = 1,
|
||||
scale_y = 1;
|
||||
|
||||
CanvasPtr canvas = _canvas.lock();
|
||||
if( canvas )
|
||||
{
|
||||
// The scissor rectangle isn't affected by any transformation, so we need
|
||||
// to convert to image/canvas coordinates on our selves.
|
||||
scale_x = canvas->getSizeX()
|
||||
/ static_cast<float>(canvas->getViewWidth());
|
||||
scale_y = canvas->getSizeY()
|
||||
/ static_cast<float>(canvas->getViewHeight());
|
||||
}
|
||||
|
||||
osg::Scissor* scissor = new osg::Scissor();
|
||||
// <top>, <right>, <bottom>, <left>
|
||||
scissor->x() = scale_x * values[3];
|
||||
scissor->y() = scale_y * values[0];
|
||||
scissor->width() = scale_x * (values[1] - values[3]);
|
||||
scissor->height() = scale_y * (values[2] - values[0]);
|
||||
|
||||
if( canvas )
|
||||
// Canvas has y axis upside down
|
||||
scissor->y() = canvas->getSizeY() - scissor->y() - scissor->height();
|
||||
|
||||
getOrCreateStateSet()->setAttributeAndModes(scissor);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setBoundingBox(const osg::BoundingBox& bb)
|
||||
{
|
||||
@ -347,6 +416,8 @@ namespace canvas
|
||||
SG_DEBUG,
|
||||
"New canvas element " << node->getPath()
|
||||
);
|
||||
|
||||
addStyle("clip", &Element::setClip, this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -360,6 +431,13 @@ namespace canvas
|
||||
_transform->addChild(geode);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
osg::StateSet* Element::getOrCreateStateSet()
|
||||
{
|
||||
return _drawable ? _drawable->getOrCreateStateSet()
|
||||
: _transform->getOrCreateStateSet();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void Element::setupStyle()
|
||||
{
|
||||
|
@ -92,6 +92,14 @@ namespace canvas
|
||||
|
||||
virtual bool setStyle(const SGPropertyNode* child);
|
||||
|
||||
/**
|
||||
* Set clipping shape
|
||||
*
|
||||
* @note Only "rect(<top>, <right>, <bottom>, <left>)" is supported
|
||||
* @see http://www.w3.org/TR/CSS21/visufx.html#propdef-clip
|
||||
*/
|
||||
void setClip(const std::string& clip);
|
||||
|
||||
/**
|
||||
* Write the given bounding box to the property tree
|
||||
*/
|
||||
@ -182,6 +190,11 @@ namespace canvas
|
||||
|
||||
void setDrawable(osg::Drawable* drawable);
|
||||
|
||||
/**
|
||||
* Get stateset of drawable if available or use transform otherwise
|
||||
*/
|
||||
osg::StateSet* getOrCreateStateSet();
|
||||
|
||||
void setupStyle();
|
||||
|
||||
private:
|
||||
|
@ -137,6 +137,10 @@ namespace canvas
|
||||
//----------------------------------------------------------------------------
|
||||
bool Group::setStyle(const SGPropertyNode* style)
|
||||
{
|
||||
// Don't propagate styles directly applicable to this group
|
||||
if( Element::setStyle(style) )
|
||||
return true;
|
||||
|
||||
if( style->getParent() != _node
|
||||
&& _style.find(style->getNameString()) != _style.end() )
|
||||
return false;
|
||||
@ -192,8 +196,12 @@ namespace canvas
|
||||
return;
|
||||
}
|
||||
|
||||
_style[ child->getNameString() ] = child;
|
||||
setStyle(child);
|
||||
if( !Element::setStyle(child) )
|
||||
{
|
||||
// Only add style if not applicable to group itself
|
||||
_style[ child->getNameString() ] = child;
|
||||
setStyle(child);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user