Nasal cppbindings: automatic conversion of vec2 to/from Nasal

This commit is contained in:
Thomas Geymayer 2012-12-17 00:26:02 +01:00
parent a1b7cb5330
commit fd39808ed8
9 changed files with 89 additions and 34 deletions

View File

@ -52,7 +52,7 @@ namespace canvas
_sys.lock()->gcRelease(_gc_key); _sys.lock()->gcRelease(_gc_key);
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------
void EventListener::call(const canvas::EventPtr& event) void EventListener::call(const canvas::EventPtr& event)
{ {
SystemAdapterPtr sys = _sys.lock(); SystemAdapterPtr sys = _sys.lock();

View File

@ -37,7 +37,7 @@ namespace canvas
void setFill(const std::string& fill); void setFill(const std::string& fill);
void setBackgroundColor(const std::string& fill); void setBackgroundColor(const std::string& fill);
osg::Vec2 handleHit(float x, float y); osg::Vec2 handleHit(const osg::Vec2f& pos);
virtual osg::BoundingBox computeBound() const; virtual osg::BoundingBox computeBound() const;
@ -79,13 +79,13 @@ namespace canvas
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
osg::Vec2 Text::TextOSG::handleHit(float x, float y) osg::Vec2 Text::TextOSG::handleHit(const osg::Vec2f& pos)
{ {
float line_height = _characterHeight + _lineSpacing; float line_height = _characterHeight + _lineSpacing;
// TODO check with align other than TOP // TODO check with align other than TOP
float first_line_y = -0.5 * _lineSpacing;//_offset.y() - _characterHeight; float first_line_y = -0.5 * _lineSpacing;//_offset.y() - _characterHeight;
size_t line = std::max<int>(0, (y - first_line_y) / line_height); size_t line = std::max<int>(0, (pos.y() - first_line_y) / line_height);
if( _textureGlyphQuadMap.empty() ) if( _textureGlyphQuadMap.empty() )
return osg::Vec2(-1, -1); return osg::Vec2(-1, -1);
@ -102,7 +102,7 @@ namespace canvas
const float character_width = getCharacterHeight() const float character_width = getCharacterHeight()
* getCharacterAspectRatio(); * getCharacterAspectRatio();
y = (line + 0.5) * line_height; float y = (line + 0.5) * line_height;
bool line_found = false; bool line_found = false;
for(size_t i = 0; i < line_numbers.size(); ++i) for(size_t i = 0; i < line_numbers.size(); ++i)
@ -132,20 +132,21 @@ namespace canvas
+ HIT_FRACTION * glyphs[i]->getHorizontalAdvance() + HIT_FRACTION * glyphs[i]->getHorizontalAdvance()
* character_width; * character_width;
if( x <= threshold ) if( pos.x() <= threshold )
{ {
osg::Vec2 hit(0, y);
if( i == 0 || line_numbers[i - 1] != line ) if( i == 0 || line_numbers[i - 1] != line )
// first character of line // first character of line
x = coords[i * 4].x(); hit.x() = coords[i * 4].x();
else if( coords[(i - 1) * 4].x() == coords[(i - 1) * 4 + 2].x() ) else if( coords[(i - 1) * 4].x() == coords[(i - 1) * 4 + 2].x() )
// If previous character width is zero set to begin of next character // If previous character width is zero set to begin of next character
// (Happens eg. with spaces) // (Happens eg. with spaces)
x = coords[i * 4].x(); hit.x() = coords[i * 4].x();
else else
// position at center between characters // position at center between characters
x = 0.5 * (coords[(i - 1) * 4 + 2].x() + coords[i * 4].x()); hit.x() = 0.5 * (coords[(i - 1) * 4 + 2].x() + coords[i * 4].x());
return osg::Vec2(x, y); return hit;
} }
} }
@ -266,26 +267,9 @@ namespace canvas
#endif #endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void Text::childChanged(SGPropertyNode* child) osg::Vec2 Text::getNearestCursor(const osg::Vec2& pos) const
{ {
if( child->getParent() != _node ) return _text->handleHit(pos);
return;
const std::string& name = child->getNameString();
if( name == "hit-y" )
handleHit
(
_node->getFloatValue("hit-x"),
_node->getFloatValue("hit-y")
);
}
//----------------------------------------------------------------------------
void Text::handleHit(float x, float y)
{
const osg::Vec2& pos = _text->handleHit(x, y);
_node->setFloatValue("cursor-x", pos.x());
_node->setFloatValue("cursor-y", pos.y());
} }
} // namespace canvas } // namespace canvas

View File

@ -43,15 +43,13 @@ namespace canvas
void setFont(const char* name); void setFont(const char* name);
void setAlignment(const char* align); void setAlignment(const char* align);
osg::Vec2 getNearestCursor(const osg::Vec2& pos) const;
protected: protected:
class TextOSG; class TextOSG;
osg::ref_ptr<TextOSG> _text; osg::ref_ptr<TextOSG> _text;
virtual void childChanged(SGPropertyNode * child);
void handleHit(float x, float y);
}; };
} // namespace canvas } // namespace canvas

View File

@ -18,6 +18,10 @@
#ifndef SGVec2_H #ifndef SGVec2_H
#define SGVec2_H #define SGVec2_H
#include "SGLimits.hxx"
#include "SGMathFwd.hxx"
#include "SGMisc.hxx"
#include <iosfwd> #include <iosfwd>
/// 2D Vector Class /// 2D Vector Class

View File

@ -5,6 +5,7 @@ set(HEADERS
NasalHash.hxx NasalHash.hxx
from_nasal_detail.hxx from_nasal_detail.hxx
from_nasal.hxx from_nasal.hxx
nasal_traits.hxx
to_nasal.hxx to_nasal.hxx
) )

View File

@ -1,3 +1,5 @@
#include <simgear/math/SGVec2.hxx>
#include "Ghost.hxx" #include "Ghost.hxx"
#include "NasalHash.hxx" #include "NasalHash.hxx"
@ -73,8 +75,15 @@ int main(int argc, char* argv[])
VERIFY( naNumValue(r).num == 4.2f ); VERIFY( naNumValue(r).num == 4.2f );
VERIFY( from_nasal<float>(c, r) == 4.2f ); VERIFY( from_nasal<float>(c, r) == 4.2f );
std::vector<int> vec; float test_data[3] = {0, 4, 2};
r = to_nasal(c, test_data);
SGVec2f vec(0,2);
r = to_nasal(c, vec); r = to_nasal(c, vec);
VERIFY( from_nasal<SGVec2f>(c, r) == vec );
std::vector<int> std_vec;
r = to_nasal(c, std_vec);
r = to_nasal(c, "string"); r = to_nasal(c, "string");
try try
@ -177,6 +186,9 @@ int main(int argc, char* argv[])
VERIFY( cc.getArg<std::string>(0) == "test-arg" ); VERIFY( cc.getArg<std::string>(0) == "test-arg" );
VERIFY( cc.getArg<std::string>(1) == "" ); VERIFY( cc.getArg<std::string>(1) == "" );
naRef args_vec = nasal::to_nasal(c, args);
VERIFY( naIsVector(args_vec) );
// TODO actually do something with the ghosts... // TODO actually do something with the ghosts...
naFreeContext(c); naFreeContext(c);

View File

@ -20,6 +20,8 @@
#ifndef SG_FROM_NASAL_DETAIL_HXX_ #ifndef SG_FROM_NASAL_DETAIL_HXX_
#define SG_FROM_NASAL_DETAIL_HXX_ #define SG_FROM_NASAL_DETAIL_HXX_
#include "nasal_traits.hxx"
#include <simgear/nasal/nasal.h> #include <simgear/nasal/nasal.h>
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
@ -112,6 +114,20 @@ namespace nasal
return vec; return vec;
} }
/**
* Convert a Nasal vector of 2 elements to a 2d vector
*/
template<class Vec2>
typename boost::enable_if<is_vec2<Vec2>, Vec2>::type
from_nasal_helper(naContext c, naRef ref, Vec2*)
{
std::vector<double> vec =
from_nasal_helper(c, ref, static_cast<std::vector<double>*>(0));
if( vec.size() != 2 )
throw bad_nasal_cast("Expected vector with two elements");
return Vec2(vec[0], vec[1]);
}
} // namespace nasal } // namespace nasal
#endif /* SG_FROM_NASAL_DETAIL_HXX_ */ #endif /* SG_FROM_NASAL_DETAIL_HXX_ */

View File

@ -29,6 +29,12 @@ namespace nasal
return ret; return ret;
} }
//----------------------------------------------------------------------------
naRef to_nasal(naContext c, const char* str)
{
return to_nasal(c, std::string(str));
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
naRef to_nasal(naContext c, naCFunction func) naRef to_nasal(naContext c, naCFunction func)
{ {

View File

@ -20,6 +20,8 @@
#ifndef SG_TO_NASAL_HXX_ #ifndef SG_TO_NASAL_HXX_
#define SG_TO_NASAL_HXX_ #define SG_TO_NASAL_HXX_
#include "nasal_traits.hxx"
#include <simgear/nasal/nasal.h> #include <simgear/nasal/nasal.h>
#include <boost/utility/enable_if.hpp> #include <boost/utility/enable_if.hpp>
@ -37,6 +39,12 @@ namespace nasal
*/ */
naRef to_nasal(naContext c, const std::string& str); naRef to_nasal(naContext c, const std::string& str);
/**
* Convert C-string to Nasal string
*/
// We need this to prevent the array overload of to_nasal being called
naRef to_nasal(naContext c, const char* str);
/** /**
* Convert function pointer to Nasal function * Convert function pointer to Nasal function
*/ */
@ -62,6 +70,19 @@ namespace nasal
return naNum(num); return naNum(num);
} }
/**
* Convert a fixed size array to a Nasal vector
*/
template<class T, size_t N>
naRef to_nasal(naContext c, const T(&array)[N])
{
naRef ret = naNewVector(c);
naVec_setsize(c, ret, N);
for(size_t i = 0; i < N; ++i)
naVec_set(ret, i, to_nasal(c, array[i]));
return ret;
}
/** /**
* Convert std::vector to Nasal vector * Convert std::vector to Nasal vector
*/ */
@ -83,6 +104,19 @@ namespace nasal
return ret; return ret;
} }
/**
* Convert a 2d vector to Nasal vector with 2 elements
*/
template<class Vec2>
typename boost::enable_if<is_vec2<Vec2>, naRef>::type
to_nasal(naContext c, const Vec2& vec)
{
// We take just double because in Nasal every number is represented as
// double
double nasal_vec[2] = {vec[0], vec[1]};
return to_nasal(c, nasal_vec);
}
} // namespace nasal } // namespace nasal
#endif /* SG_TO_NASAL_HXX_ */ #endif /* SG_TO_NASAL_HXX_ */