Canvas: basic support for rectangular clipping (like CSS clip property)
This commit is contained in:
@@ -335,6 +335,18 @@ namespace canvas
|
|||||||
_texture.setViewSize(_view_width, _view_height);
|
_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)
|
bool Canvas::handleMouseEvent(const MouseEventPtr& event)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -114,6 +114,9 @@ namespace canvas
|
|||||||
void setViewWidth(int w);
|
void setViewWidth(int w);
|
||||||
void setViewHeight(int h);
|
void setViewHeight(int h);
|
||||||
|
|
||||||
|
int getViewWidth() const;
|
||||||
|
int getViewHeight() const;
|
||||||
|
|
||||||
bool handleMouseEvent(const MouseEventPtr& event);
|
bool handleMouseEvent(const MouseEventPtr& event);
|
||||||
|
|
||||||
virtual void childAdded( SGPropertyNode * parent,
|
virtual void childAdded( SGPropertyNode * parent,
|
||||||
|
|||||||
@@ -24,9 +24,13 @@
|
|||||||
|
|
||||||
#include <osg/Drawable>
|
#include <osg/Drawable>
|
||||||
#include <osg/Geode>
|
#include <osg/Geode>
|
||||||
|
#include <osg/Scissor>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/tokenizer.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@@ -303,6 +307,71 @@ namespace canvas
|
|||||||
return true;
|
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)
|
void Element::setBoundingBox(const osg::BoundingBox& bb)
|
||||||
{
|
{
|
||||||
@@ -347,6 +416,8 @@ namespace canvas
|
|||||||
SG_DEBUG,
|
SG_DEBUG,
|
||||||
"New canvas element " << node->getPath()
|
"New canvas element " << node->getPath()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
addStyle("clip", &Element::setClip, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@@ -360,6 +431,13 @@ namespace canvas
|
|||||||
_transform->addChild(geode);
|
_transform->addChild(geode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
osg::StateSet* Element::getOrCreateStateSet()
|
||||||
|
{
|
||||||
|
return _drawable ? _drawable->getOrCreateStateSet()
|
||||||
|
: _transform->getOrCreateStateSet();
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void Element::setupStyle()
|
void Element::setupStyle()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,6 +92,14 @@ namespace canvas
|
|||||||
|
|
||||||
virtual bool setStyle(const SGPropertyNode* child);
|
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
|
* Write the given bounding box to the property tree
|
||||||
*/
|
*/
|
||||||
@@ -182,6 +190,11 @@ namespace canvas
|
|||||||
|
|
||||||
void setDrawable(osg::Drawable* drawable);
|
void setDrawable(osg::Drawable* drawable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get stateset of drawable if available or use transform otherwise
|
||||||
|
*/
|
||||||
|
osg::StateSet* getOrCreateStateSet();
|
||||||
|
|
||||||
void setupStyle();
|
void setupStyle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -137,6 +137,10 @@ namespace canvas
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool Group::setStyle(const SGPropertyNode* style)
|
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
|
if( style->getParent() != _node
|
||||||
&& _style.find(style->getNameString()) != _style.end() )
|
&& _style.find(style->getNameString()) != _style.end() )
|
||||||
return false;
|
return false;
|
||||||
@@ -192,8 +196,12 @@ namespace canvas
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_style[ child->getNameString() ] = child;
|
if( !Element::setStyle(child) )
|
||||||
setStyle(child);
|
{
|
||||||
|
// Only add style if not applicable to group itself
|
||||||
|
_style[ child->getNameString() ] = child;
|
||||||
|
setStyle(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user