Hi,

in calcultaeOffset fixed the condition of potentional crash when the text
glyphs are over couple of TextureGlyphQuadMap. Added support for:
LEFT,RIGHT,HOME,END,DELETE ... I might want to add support for
CTRL+LEFT/RIGHT to go to the beginning of the next/previous word and
buffering the input - that is what I have in my terminal like control, ...
of course if this is not beyond the features of the standard input. Let me
know

Nick

http://www.linkedin.com/in/tnick
Sent from Devlet, Ankara, Turkey
// -*-c++-*- osgWidget - Code by: Jeremy Moles (cubicool) 2007-2008

#include <osg/io_utils>
#include <osgWidget/WindowManager>
#include <osgWidget/Input>

namespace osgWidget {

Input::Input(const std::string& name, const std::string& label, unsigned int 
size):
Label        (name, label),
_xoff        (0.0f),
_yoff        (0.0f),
_index       (0),
_size        (0),
_cursorIndex (0),
_textLength      (0),
_maxSize     (size),
_cursor      (new Widget("cursor")) {
   _text->setAlignment(osgText::Text::LEFT_BOTTOM_BASE_LINE);
   _text->setKerningType(osgText::KERNING_NONE);

   // Make the cursor un-copyable.
   _cursor->setCanClone(false);
   _cursor->setDataVariance(osg::Object::DYNAMIC);
   _cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);

   setEventMask(
       // For showing/hiding the "cursor."
       EVENT_MASK_FOCUS |
       // For keypresses, obviously.
       EVENT_MASK_KEY |
       // For "click" focusing.
       EVENT_MOUSE_PUSH
   );

   _offsets.resize(size, 0.0f);

   _text->getText().resize(size, ' ');
   _text->update();
}

void Input::_calculateSize(const XYCoord& size) {
   // An Input cannot currently set it's own size RELIABLY until the osgText 
implementation
   // is dratiscally improved. I'm getting wildly crazy results. :(
   // point_type height = size.y() > _cursor->getHeight() ? size.y() : 
_cursor->getHeight();

#if 0
   point_type width  = size.x() + _cursor->getWidth();
   point_type height = _cursor->getHeight();

   if(width > getWidth()) setWidth(osg::round(width));

   if(height > getHeight()) setHeight(osg::round(height));
#endif
}

void Input::_calculateCursorOffsets() {
   // Determine the "offset"

        osg::Vec3 pos = _text->getPosition();

        osgText::Text::TextureGlyphQuadMap& tgqm = 
const_cast<osgText::Text::TextureGlyphQuadMap&>(_text->getTextureGlyphQuadMap());
        osgText::Text::TextureGlyphQuadMap::iterator tgqmi = tgqm.begin();

        std::vector<osg::Vec3>                          coords;
        std::vector<osgText::Font::Glyph*>      glyphs;
        for ( ; tgqmi != tgqm.end(); tgqmi++ )
        {
                const osgText::Text::GlyphQuads& gq = tgqmi->second;

                
coords.insert(coords.end(),gq.getTransformedCoords(0).begin(),gq.getTransformedCoords(0).end());
                for (unsigned int i=0; i<gq.getGlyphs().size(); ++i)
                {
                        glyphs.push_back(gq.getGlyphs().at(i));
                }
        }
        
        std::list<unsigned int> keys;
        for (unsigned int i=0; i<_text->getText().size(); ++i)
        {
                keys.push_back(_text->getText().at(i));
        }
        unsigned int idx=0;
        while (!keys.empty())
        {
                unsigned int key = keys.front();
                for (unsigned int i=0; i<glyphs.size(); ++i)
                {
                        osgText::Font::Glyph* g = glyphs.at(i);
                        if (g->getGlyphCode()==key)
                        {
                                osg::Vec3 lr = coords[2 + (i * 4)];
                                _offsets[idx++] = lr.x() - pos.x();

                                glyphs.erase(glyphs.begin()+i);
                                coords.erase(coords.begin()+i*4);
                                coords.erase(coords.begin()+i*4);
                                coords.erase(coords.begin()+i*4);
                                coords.erase(coords.begin()+i*4);
                                break;
                        }
                }
                keys.pop_front();
        }

        positioned();
}

bool Input::focus(const WindowManager*) {
   _cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);

   return true;
}

bool Input::unfocus(const WindowManager*) {
   _cursor->setColor(0.0f, 0.0f, 0.0f, 0.0f);

   return true;
}

void Input::parented(Window* parent) {
   Label::parented(parent);

   _cursor->setSize(2.0f, _text->getCharacterHeight());

   if(_cursorIndex) parent->getGeode()->setDrawable(_cursorIndex, 
_cursor.get());

   else _cursorIndex = parent->addDrawableAndGetIndex(_cursor.get());
}

void Input::positioned() {
   point_type ln = static_cast<point_type>(_text->getLineCount());

   ln = ln == 0.0f ? 1.0f : ln;

   // point_type th = (_text->getCharacterHeight() * ln) + 
(_text->getLineSpacing() * (ln - 1.0f));

   point_type x = getX() + _xoff;
   point_type y = getY() + _yoff;

   // XYCoord size = getTextSize();

   _text->setPosition(osg::Vec3(x, y, _calculateZ(LAYER_MIDDLE)));

   point_type xoffset = _index > 0 ? _offsets[_index - 1] : 0.0f;

   _cursor->setOrigin(x + xoffset + 1.0f, y + 1.0f);
   _cursor->setZ(_calculateZ(LAYER_MIDDLE));
}

bool Input::keyUp(int key, int mask, const WindowManager*) {
   return false;
}

bool Input::keyDown(int key, int mask, const WindowManager*) {
   osgText::String& s = _text->getText();

   switch (key)
   {
        case osgGA::GUIEventAdapter::KEY_Left:
                if (_index>0)
                {
                        --_index;
                }
                break;
        case osgGA::GUIEventAdapter::KEY_Right:
                if (_index<_textLength)
                {
                        ++_index;
                }
                break;
        case osgGA::GUIEventAdapter::KEY_Home:
                _index = 0;
                break;
        case osgGA::GUIEventAdapter::KEY_End:
                _index = _textLength;
                break;
        case osgGA::GUIEventAdapter::KEY_Delete:
                if (_index < s.size()-1)
                {
                        for (unsigned int i=_index; i < s.size()-1; ++i)
                        {
                                s[i] = s[i+1];
                        }

                        _text->update();

                        _calculateCursorOffsets();

                        --_textLength;
                }
                break;
        case osgGA::GUIEventAdapter::KEY_BackSpace:
           if(_index >= 1) {

                   _index--;
                        if (_index< s.size()-1)
                        {
                                for (unsigned int i=_index; i < s.size()-1; ++i)
                                {
                                        s[i] = s[i+1];
                                }
                        }
                        else
                        {
                                s[s.size()-1] = ' ';
                        }

           _text->update();

           _calculateCursorOffsets();

                   --_textLength;
       }
           break;
   default:
           if(key > 255 || _index >= _maxSize) return false;

       s[_index] = key;

       _text->update();

       _calculateCursorOffsets();

       _index++;

           ++_textLength;
   }

   // _text->update();

   _calculateSize(getTextSize());

   getParent()->resize();

   return false;
}

void Input::setCursor(Widget*) {
}

unsigned int Input::calculateBestYOffset(const std::string& s)
{

   const osgText::FontResolution fr(static_cast<unsigned 
int>(_text->getCharacterHeight()),
                                    static_cast<unsigned 
int>(_text->getCharacterHeight()));

   osgText::String utf(s);

   unsigned int descent = 0;

   for(osgText::String::iterator i = utf.begin(); i != utf.end(); i++) {
       osgText::Font*        font  = 
const_cast<osgText::Font*>(_text->getFont());
       osgText::Font::Glyph* glyph = font->getGlyph(fr, *i);
       unsigned int          d     = 
abs((int)glyph->getHorizontalBearing().y());

       if(d > descent) descent = d;
   }

   return descent;
}

}

Attachment: Input
Description: Binary data

_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to