root/OpenSceneGraph/trunk/examples/osgkeyboard/osgkeyboard.cpp @ 8079

Revision 8079, 15.2 kB (checked in by robert, 6 years ago)

From Melchior Franz, "The GUIEventAdapter header file had KeySymbols? for the super and
hyper keys defined already, but these modifiers were missing in
GUIEventAdapter::ModKeyMask?, and the EventQueue? ingored them as well.

The attached diff/archive adds the missing parts for Super/Hyper
modifier key support.

I'm aware that this might not be supported on all systems/keyboards
out of the box, but decided to submit it anyway because:

- developers are aware of differences between input devices

(Some mice have scroll wheels, others don't. Some have five or
more buttons, some have only one. Some keyboards don't have
numpads, some have AltGr?, some don't etc.)

- even if someone relies on Hyper/Super in distributed software,

this is easy to fix and doesn't create lock-in conditions

- while the names Hyper/Super may only be common on X11, they are

just symbol names and not OS-specific

- even though some systems might not offer these additional modifiers

by default, it's likely that all of them have at least 8 modifier
levels internally, so it should only be a matter of OS configuration
to make them work

- having super/hyper available is useful to offer a user ways

to define local key definitions that are safe from collisions with
predefined "official" key assignments"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgkeyboard.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osgViewer/Viewer>
20#include <osgViewer/ViewerEventHandlers>
21#include <osg/io_utils>
22
23#include <osg/MatrixTransform>
24#include <osg/Geode>
25#include <osg/Group>
26#include <osg/Switch>
27#include <osg/Notify>
28#include <osg/Geometry>
29
30#include <osgText/Text>
31
32#include <osgDB/Registry>
33#include <osgDB/ReadFile>
34#include <osgDB/WriteFile>
35
36
37class KeyboardModel : public osg::Referenced
38{
39public:
40
41        KeyboardModel() { createKeyboard(); }
42       
43        osg::Group* getScene() { return _scene.get(); }
44       
45        void keyChange(int key,int value);
46       
47protected:
48       
49        ~KeyboardModel() {}
50
51        osg::Switch* addKey(osg::Vec3& pos, int key,const std::string& text,float width, float height);
52        osg::Switch* addKey(int key,osg::Switch* sw);
53
54        void createKeyboard();
55
56        typedef std::map<int, osg::ref_ptr<osg::Switch> > KeyModelMap;
57       
58        osg::ref_ptr<osg::Group>    _scene;
59        KeyModelMap                 _keyModelMap;
60        osg::ref_ptr<osgText::Text> _inputText;
61
62};
63
64void KeyboardModel::keyChange(int key,int value)
65{
66    osg::notify(osg::INFO) << "key value change, code="<<std::hex << key << "\t value="<< value << std::dec  << std::endl;
67
68    // toggle the keys graphical representation on or off via osg::Swithc
69    KeyModelMap::iterator itr = _keyModelMap.find(key);
70    if (itr!=_keyModelMap.end())
71    {
72        itr->second->setSingleChildOn(value);
73    }
74   
75    if (value)
76    {
77        // when a key is pressed add the new data to the text field
78       
79        if (key>0 && key<256)
80        {
81            // just add ascii characters right now...
82            _inputText->getText().push_back(key);
83            _inputText->update();
84        }
85        else if (key==osgGA::GUIEventAdapter::KEY_Return)
86        {
87            _inputText->getText().push_back('\n');
88            _inputText->update();
89        }
90        else if (key==osgGA::GUIEventAdapter::KEY_BackSpace || key==osgGA::GUIEventAdapter::KEY_Delete)
91        {
92            if (!_inputText->getText().empty())
93            {
94                _inputText->getText().pop_back();
95                _inputText->update();
96            }
97        }
98       
99    }
100   
101}
102
103osg::Switch* KeyboardModel::addKey(osg::Vec3& pos, int key,const std::string& text,float width, float height)
104{
105
106    osg::Geode* geodeUp = new osg::Geode;
107    {
108        osgText::Text* textUp = new osgText::Text;
109        textUp->setFont("fonts/arial.ttf");
110        textUp->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
111        textUp->setCharacterSize(height);
112        textUp->setPosition(pos);
113        textUp->setDrawMode(osgText::Text::TEXT/*|osgText::Text::BOUNDINGBOX*/);
114        textUp->setAlignment(osgText::Text::LEFT_CENTER);
115        textUp->setAxisAlignment(osgText::Text::XZ_PLANE);
116        textUp->setText(text);
117       
118        geodeUp->addDrawable(textUp);
119    }
120   
121    osg::Geode* geodeDown = new osg::Geode;
122    {
123        osgText::Text* textDown = new osgText::Text;
124        textDown->setFont("fonts/arial.ttf");
125        textDown->setColor(osg::Vec4(1.0f,0.0f,1.0f,1.0f));
126        textDown->setCharacterSize(height);
127        textDown->setPosition(pos);
128        textDown->setDrawMode(osgText::Text::TEXT/*||osgText::Text::BOUNDINGBOX*/);
129        textDown->setAlignment(osgText::Text::LEFT_CENTER);
130        textDown->setAxisAlignment(osgText::Text::XZ_PLANE);
131        textDown->setText(text);
132       
133        geodeDown->addDrawable(textDown);
134    }
135
136    osg::Switch* model = new osg::Switch;
137    model->addChild(geodeUp,true);
138    model->addChild(geodeDown,false);
139   
140    _scene->addChild(model);
141
142    _keyModelMap[key] = model;
143   
144    pos.x() += width;
145   
146    return model;
147   
148}
149
150osg::Switch* KeyboardModel::addKey(int key,osg::Switch* sw)
151{
152    _keyModelMap[key] = sw;
153    return sw;
154}
155
156void KeyboardModel::createKeyboard()
157{
158    _scene = new osg::Group;
159   
160    osg::Vec3 origin(0.0f,0.0f,0.0f);
161    osg::Vec3 pos=origin;
162   
163    addKey(pos,osgGA::GUIEventAdapter::KEY_Control_L,"Ctrl",2.0f,0.5f);
164    addKey(pos,osgGA::GUIEventAdapter::KEY_Super_L,"Super",2.0f,0.5f);
165    addKey(pos,osgGA::GUIEventAdapter::KEY_Alt_L,"Alt",2.0f,0.5f);
166    addKey(pos,osgGA::GUIEventAdapter::KEY_Space,"Space",3.0f,1.0f);
167    addKey(pos,osgGA::GUIEventAdapter::KEY_Mode_switch,"Switch",2.0f,0.5f);
168    addKey(pos,osgGA::GUIEventAdapter::KEY_Super_R,"Super",2.0f,0.5f);
169    addKey(pos,osgGA::GUIEventAdapter::KEY_Menu,"Menu",2.0f,0.5f);
170    addKey(pos,osgGA::GUIEventAdapter::KEY_Control_R,"Ctrl",2.0f,0.5f);
171
172    osg::Vec3 middle(pos.x()+1.0f,0.0f,0.0f);
173   
174    pos.x() = 0.0f;
175    pos.z() += 1.0f;
176
177    addKey(pos,osgGA::GUIEventAdapter::KEY_Shift_L,"Shift",2.0f,0.5f);
178    addKey(pos,'\\',"\\",1.0f,1.0f);
179    addKey('Z',addKey(pos,'z',"Z",1.0f,1.0f));
180    addKey('X',addKey(pos,'x',"X",1.0f,1.0f));
181    addKey('C',addKey(pos,'c',"C",1.0f,1.0f));
182    addKey('V',addKey(pos,'v',"V",1.0f,1.0f));
183    addKey('B',addKey(pos,'b',"B",1.0f,1.0f));
184    addKey('N',addKey(pos,'n',"N",1.0f,1.0f));
185    addKey('M',addKey(pos,'m',"M",1.0f,1.0f));
186    addKey('<',addKey(pos,',',",",1.0f,1.0f));
187    addKey('>',addKey(pos,'.',".",1.0f,1.0f));
188    addKey('?',addKey(pos,'/',"/",1.0f,1.0f));
189    addKey(pos,osgGA::GUIEventAdapter::KEY_Shift_R,"Shift",2.0f,0.5f);
190
191    pos.x() = 0.0f;
192    pos.z() += 1.0f;
193   
194    addKey(pos,osgGA::GUIEventAdapter::KEY_Caps_Lock,"Caps",2.0f,0.5f);
195    addKey('A',addKey(pos,'a',"A",1.0f,1.0f));
196    addKey('S',addKey(pos,'s',"S",1.0f,1.0f));
197    addKey('D',addKey(pos,'d',"D",1.0f,1.0f));
198    addKey('F',addKey(pos,'f',"F",1.0f,1.0f));
199    addKey('G',addKey(pos,'g',"G",1.0f,1.0f));
200    addKey('H',addKey(pos,'h',"H",1.0f,1.0f));
201    addKey('J',addKey(pos,'j',"J",1.0f,1.0f));
202    addKey('K',addKey(pos,'k',"K",1.0f,1.0f));
203    addKey('L',addKey(pos,'l',"L",1.0f,1.0f));
204    addKey(':',addKey(pos,';',";",1.0f,1.0f));
205    addKey('@',addKey(pos,'\'',"'",1.0f,1.0f));
206    addKey('~',addKey(pos,'#',"#",1.0f,1.0f));
207    addKey(pos,osgGA::GUIEventAdapter::KEY_Return,"Return",4.0f,0.5f);
208
209    pos.x() = 0.0f;
210    pos.z() += 1.0f;
211   
212    addKey(pos,osgGA::GUIEventAdapter::KEY_Tab,"Tab",2.0f,0.5f);
213    addKey('Q',addKey(pos,'q',"Q",1.0f,1.0f));
214    addKey('W',addKey(pos,'w',"W",1.0f,1.0f));
215    addKey('E',addKey(pos,'e',"E",1.0f,1.0f));
216    addKey('R',addKey(pos,'r',"R",1.0f,1.0f));
217    addKey('T',addKey(pos,'t',"T",1.0f,1.0f));
218    addKey('Y',addKey(pos,'y',"Y",1.0f,1.0f));
219    addKey('U',addKey(pos,'u',"U",1.0f,1.0f));
220    addKey('I',addKey(pos,'i',"I",1.0f,1.0f));
221    addKey('O',addKey(pos,'o',"O",1.0f,1.0f));
222    addKey('P',addKey(pos,'p',"P",1.0f,1.0f));
223    addKey('{',addKey(pos,'[',"[",1.0f,1.0f));
224    addKey('}',addKey(pos,']',"]",1.0f,1.0f));
225
226    pos.x() = 0.0f;
227    pos.z() += 1.0f;
228   
229    addKey(pos,'`',"`",1.0f,1.0f);
230    addKey(pos,'1',"1",1.0f,1.0f);
231    addKey(pos,'2',"2",1.0f,1.0f);
232    addKey(pos,'3',"3",1.0f,1.0f);
233    addKey(pos,'4',"4",1.0f,1.0f);
234    addKey(pos,'5',"5",1.0f,1.0f);
235    addKey(pos,'6',"6",1.0f,1.0f);
236    addKey(pos,'7',"7",1.0f,1.0f);
237    addKey(pos,'8',"8",1.0f,1.0f);
238    addKey(pos,'9',"9",1.0f,1.0f);
239    addKey(pos,'0',"0",1.0f,1.0f);
240    addKey(pos,'-',"-",1.0f,1.0f);
241    addKey(pos,'=',"=",1.0f,1.0f);
242    addKey(pos,osgGA::GUIEventAdapter::KEY_BackSpace,"Backspace",3.0f,0.5f);
243
244    pos.x() = 0.0f;
245    pos.z() += 1.5f;
246   
247    float F_height = 0.5f;
248    addKey(pos,osgGA::GUIEventAdapter::KEY_Escape,"Esc",2.0f,F_height);
249    addKey(pos,osgGA::GUIEventAdapter::KEY_F1,"F1",1.0f,F_height);
250    addKey(pos,osgGA::GUIEventAdapter::KEY_F2,"F2",1.0f,F_height);
251    addKey(pos,osgGA::GUIEventAdapter::KEY_F3,"F3",1.0f,F_height);
252    addKey(pos,osgGA::GUIEventAdapter::KEY_F4,"F4",1.0f,F_height);
253    addKey(pos,osgGA::GUIEventAdapter::KEY_F5,"F5",1.0f,F_height);
254    addKey(pos,osgGA::GUIEventAdapter::KEY_F6,"F6",1.0f,F_height);
255    addKey(pos,osgGA::GUIEventAdapter::KEY_F7,"F7",1.0f,F_height);
256    addKey(pos,osgGA::GUIEventAdapter::KEY_F8,"F8",1.0f,F_height);
257    addKey(pos,osgGA::GUIEventAdapter::KEY_F9,"F9",1.0f,F_height);
258    addKey(pos,osgGA::GUIEventAdapter::KEY_F10,"F10",1.0f,F_height);
259    addKey(pos,osgGA::GUIEventAdapter::KEY_F11,"F11",1.0f,F_height);
260    addKey(pos,osgGA::GUIEventAdapter::KEY_F12,"F12",1.0f,F_height);
261
262
263   
264    float cursorMoveHeight=0.35f;
265
266    pos = middle;   
267    addKey(pos,osgGA::GUIEventAdapter::KEY_Left,"Left",1.0f,cursorMoveHeight);
268    osg::Vec3 down = pos;
269    addKey(pos,osgGA::GUIEventAdapter::KEY_Down,"Down",1.0f,cursorMoveHeight);
270    addKey(pos,osgGA::GUIEventAdapter::KEY_Right,"Right",1.0f,cursorMoveHeight);
271   
272    osg::Vec3 keypad = pos;
273    keypad.x()+=1.0f;
274
275    pos = down;
276    pos.z() += 1.0f;
277   
278    addKey(pos,osgGA::GUIEventAdapter::KEY_Up,"Up",1.0f,cursorMoveHeight);
279   
280
281    float homeHeight = 0.35f;
282    pos = middle;
283    pos.z() += 3.0;   
284    addKey(pos,osgGA::GUIEventAdapter::KEY_Delete,"Delete",1.0f,homeHeight);
285    addKey(pos,osgGA::GUIEventAdapter::KEY_End,"End",1.0f,homeHeight);
286    addKey(pos,osgGA::GUIEventAdapter::KEY_Page_Down,"Page\nDown",1.0f,homeHeight);
287   
288    pos = middle;
289    pos.z() += 4.0;   
290    addKey(pos,osgGA::GUIEventAdapter::KEY_Insert,"Insert",1.0f,homeHeight);
291    addKey(pos,osgGA::GUIEventAdapter::KEY_Home,"Home",1.0f,homeHeight);
292    addKey(pos,osgGA::GUIEventAdapter::KEY_Page_Up,"Page\nUp",1.0f,homeHeight);
293
294    pos = middle;
295    pos.z() += 5.5;   
296    addKey(pos,osgGA::GUIEventAdapter::KEY_Print,"PrtScrn\nSysRq",1.0f,homeHeight);
297    addKey(pos,osgGA::GUIEventAdapter::KEY_Scroll_Lock,"ScrLk",1.0f,homeHeight);
298    addKey(pos,osgGA::GUIEventAdapter::KEY_Pause,"Pause\nBreak",1.0f,homeHeight);
299   
300   
301
302    pos = keypad;
303    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Insert,"0",2.0f,1.0f);
304    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Delete,".",1.0f,1.0f);
305    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Enter,"Enter",1.0f,homeHeight);
306   
307    pos = keypad;
308    pos.z() += 1.0f;
309    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_End,"1",1.0f,1.0f);
310    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Down,"2",1.0f,1.0f);
311    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Page_Down,"3",1.0f,1.0f);
312
313    pos = keypad;
314    pos.z() += 2.0f;
315    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Left,"4",1.0f,1.0f);
316    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Begin,"5",1.0f,1.0f);
317    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Right,"6",1.0f,1.0f);
318    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Add,"+",1.0f,1.0f);
319
320    pos = keypad;
321    pos.z() += 3.0f;
322    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Home,"7",1.0f,1.0f);
323    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Up,"8",1.0f,1.0f);
324    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Page_Up,"9",1.0f,1.0f);
325
326    pos = keypad;
327    pos.z() += 4.0f;
328    addKey(pos,osgGA::GUIEventAdapter::KEY_Num_Lock,"Num\nLock",1.0f,0.3f);
329    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Divide,"/",1.0f,1.0f);
330    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Multiply,"*",1.0f,1.0f);
331    addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Subtract,"-",1.0f,1.0f);
332   
333    float totalWidth = pos.x()-origin.x();
334    pos = origin;
335    pos.z() += -1.5f;
336
337    osg::Geode* geodeInput = new osg::Geode;
338    {
339        _inputText = new osgText::Text;
340        _inputText->setFont("fonts/arial.ttf");
341        _inputText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
342        _inputText->setCharacterSize(1.0f);
343        _inputText->setMaximumWidth(totalWidth);
344        _inputText->setPosition(pos);
345        _inputText->setDrawMode(osgText::Text::TEXT/*||osgText::Text::BOUNDINGBOX*/);
346        _inputText->setAlignment(osgText::Text::BASE_LINE);
347        _inputText->setAxisAlignment(osgText::Text::XZ_PLANE);
348        _inputText->setDataVariance(osg::Object::DYNAMIC);
349        _inputText->setText("Press some keys...");
350       
351        geodeInput->addDrawable(_inputText.get());
352       
353        _scene->addChild(geodeInput);
354    }
355
356}
357
358
359
360
361
362
363class KeyboardEventHandler : public osgGA::GUIEventHandler
364{
365public:
366   
367        KeyboardEventHandler(KeyboardModel* keyboardModel):
368            _keyboardModel(keyboardModel) {}
369   
370        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
371        {
372
373#if 1
374
375//            osg::notify(osg::NOTICE)<<"Mouse "<<ea.getButtonMask()<<std::endl;
376
377            #define PRINT(mask) osg::notify(osg::NOTICE)<<#mask<<" ="<<(ea.getModKeyMask() & mask)<<std::endl;
378            switch(ea.getEventType())
379            {
380                case(osgGA::GUIEventAdapter::KEYDOWN):
381                case(osgGA::GUIEventAdapter::KEYUP):
382                {
383                    osg::notify(osg::NOTICE)<<std::endl;
384                    PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT);
385                    PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT);
386                    PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_ALT);
387                    PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_ALT);
388                    PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL);
389                    PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL);
390                    PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_META);
391                    PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_META);
392                    PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_SUPER);
393                    PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_SUPER);
394                    PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_HYPER);
395                    PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_HYPER);
396                    PRINT(osgGA::GUIEventAdapter::MODKEY_NUM_LOCK);
397                    PRINT(osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK);
398                    break;
399                }
400                default:
401                    break;
402            }
403#endif
404            switch(ea.getEventType())
405            {
406                case(osgGA::GUIEventAdapter::KEYDOWN):
407                {
408                    _keyboardModel->keyChange(ea.getKey(),1);
409                    return true;
410                }
411                case(osgGA::GUIEventAdapter::KEYUP):
412                {
413                    _keyboardModel->keyChange(ea.getKey(),0);
414                    return true;
415                }
416
417                default:
418                    return false;
419            }
420        }
421       
422        osg::ref_ptr<KeyboardModel> _keyboardModel;
423       
424};
425
426int main(int , char **)
427{
428    osgViewer::Viewer viewer;
429
430    osg::ref_ptr<KeyboardModel> keyboardModel = new KeyboardModel;
431
432    viewer.addEventHandler(new osgViewer::StatsHandler);
433    viewer.addEventHandler(new osgViewer::WindowSizeHandler());
434    viewer.addEventHandler(new KeyboardEventHandler(keyboardModel.get()));
435    viewer.setSceneData( keyboardModel->getScene() );
436
437    return viewer.run();
438}
Note: See TracBrowser for help on using the browser.