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 
37 class KeyboardModel : public osg::Referenced
38 {
39 public:
40 
KeyboardModel()41         KeyboardModel() { createKeyboard(); }
42 
getScene()43         osg::Group* getScene() { return _scene.get(); }
44 
45         void keyChange(int key, int virtualKey, int value);
46 
47 protected:
48 
~KeyboardModel()49         ~KeyboardModel() {}
50 
51         osg::Switch* addKey(osg::Vec3& pos, int key,const std::string& text,float width, float height);
52 
53         void createKeyboard();
54 
55         typedef std::map<int, osg::ref_ptr<osg::Switch> > KeyModelMap;
56 
57         osg::ref_ptr<osg::Group>    _scene;
58         KeyModelMap                 _keyModelMap;
59         osg::ref_ptr<osgText::Text> _inputText;
60 
61 };
62 
keyChange(int key,int virtualKey,int value)63 void KeyboardModel::keyChange(int key, int virtualKey, int value)
64 {
65     osg::notify(osg::INFO) << "key value change, code="<<std::hex << key << "\t value="<< value << std::dec  << std::endl;
66 
67     // toggle the keys graphical representation on or off via osg::Swithc
68     KeyModelMap::iterator itr = _keyModelMap.find(virtualKey);
69     if (itr!=_keyModelMap.end())
70     {
71         itr->second->setSingleChildOn(value);
72     }
73 
74     if (value)
75     {
76         // when a key is pressed add the new data to the text field
77 
78         if (key>0 && key<256)
79         {
80             // just add ascii characters right now...
81             _inputText->getText().push_back(key);
82             _inputText->update();
83         }
84         else if (key==osgGA::GUIEventAdapter::KEY_Return)
85         {
86             _inputText->getText().push_back('\n');
87             _inputText->update();
88         }
89         else if (key==osgGA::GUIEventAdapter::KEY_BackSpace || key==osgGA::GUIEventAdapter::KEY_Delete)
90         {
91             if (!_inputText->getText().empty())
92             {
93                 _inputText->getText().pop_back();
94                 _inputText->update();
95             }
96         }
97 
98     }
99 
100 }
101 
addKey(osg::Vec3 & pos,int key,const std::string & text,float width,float height)102 osg::Switch* KeyboardModel::addKey(osg::Vec3& pos, int key,const std::string& text,float width, float height)
103 {
104 
105     osg::Geode* geodeUp = new osg::Geode;
106     {
107         osgText::Text* textUp = new osgText::Text;
108         textUp->setFont("fonts/arial.ttf");
109         textUp->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
110         textUp->setCharacterSize(height);
111         textUp->setPosition(pos);
112         textUp->setDrawMode(osgText::Text::TEXT/*|osgText::Text::BOUNDINGBOX*/);
113         textUp->setAlignment(osgText::Text::LEFT_CENTER);
114         textUp->setAxisAlignment(osgText::Text::XZ_PLANE);
115         textUp->setText(text);
116 
117         geodeUp->addDrawable(textUp);
118     }
119 
120     osg::Geode* geodeDown = new osg::Geode;
121     {
122         osgText::Text* textDown = new osgText::Text;
123         textDown->setFont("fonts/arial.ttf");
124         textDown->setColor(osg::Vec4(1.0f,0.0f,1.0f,1.0f));
125         textDown->setCharacterSize(height);
126         textDown->setPosition(pos);
127         textDown->setDrawMode(osgText::Text::TEXT/*||osgText::Text::BOUNDINGBOX*/);
128         textDown->setAlignment(osgText::Text::LEFT_CENTER);
129         textDown->setAxisAlignment(osgText::Text::XZ_PLANE);
130         textDown->setText(text);
131 
132         geodeDown->addDrawable(textDown);
133     }
134 
135     osg::Switch* model = new osg::Switch;
136     model->addChild(geodeUp,true);
137     model->addChild(geodeDown,false);
138 
139     _scene->addChild(model);
140 
141     _keyModelMap[key] = model;
142 
143     pos.x() += width;
144 
145     return model;
146 
147 }
148 
createKeyboard()149 void KeyboardModel::createKeyboard()
150 {
151     _scene = new osg::Group;
152 
153     osg::Vec3 origin(0.0f,0.0f,0.0f);
154     osg::Vec3 pos=origin;
155 
156     addKey(pos,osgGA::GUIEventAdapter::KEY_Control_L,"Ctrl",2.0f,0.5f);
157     addKey(pos,osgGA::GUIEventAdapter::KEY_Super_L,"Super",2.0f,0.5f);
158     addKey(pos,osgGA::GUIEventAdapter::KEY_Alt_L,"Alt",2.0f,0.5f);
159     addKey(pos,osgGA::GUIEventAdapter::KEY_Space,"Space",3.0f,1.0f);
160     addKey(pos,osgGA::GUIEventAdapter::KEY_Mode_switch,"Switch",2.0f,0.5f);
161     addKey(pos,osgGA::GUIEventAdapter::KEY_Super_R,"Super",2.0f,0.5f);
162     addKey(pos,osgGA::GUIEventAdapter::KEY_Menu,"Menu",2.0f,0.5f);
163     addKey(pos,osgGA::GUIEventAdapter::KEY_Control_R,"Ctrl",2.0f,0.5f);
164 
165     osg::Vec3 middle(pos.x()+1.0f,0.0f,0.0f);
166 
167     pos.x() = 0.0f;
168     pos.z() += 1.0f;
169 
170     addKey(pos,osgGA::GUIEventAdapter::KEY_Shift_L,"Shift",2.0f,0.5f);
171     addKey(pos,osgGA::GUIEventAdapter::KEY_Backslash,"\\",1.0f,1.0f);
172     addKey(pos,osgGA::GUIEventAdapter::KEY_Z,"Z",1.0f,1.0f);
173     addKey(pos,osgGA::GUIEventAdapter::KEY_X,"X",1.0f,1.0f);
174     addKey(pos,osgGA::GUIEventAdapter::KEY_C,"C",1.0f,1.0f);
175     addKey(pos,osgGA::GUIEventAdapter::KEY_V,"V",1.0f,1.0f);
176     addKey(pos,osgGA::GUIEventAdapter::KEY_B,"B",1.0f,1.0f);
177     addKey(pos,osgGA::GUIEventAdapter::KEY_N,"N",1.0f,1.0f);
178     addKey(pos,osgGA::GUIEventAdapter::KEY_M,"M",1.0f,1.0f);
179     addKey(pos,osgGA::GUIEventAdapter::KEY_Comma,",",1.0f,1.0f);
180     addKey(pos,osgGA::GUIEventAdapter::KEY_Period,".",1.0f,1.0f);
181     addKey(pos,osgGA::GUIEventAdapter::KEY_Slash,"/",1.0f,1.0f);
182     addKey(pos,osgGA::GUIEventAdapter::KEY_Shift_R,"Shift",2.0f,0.5f);
183 
184     pos.x() = 0.0f;
185     pos.z() += 1.0f;
186 
187     addKey(pos,osgGA::GUIEventAdapter::KEY_Caps_Lock,"Caps",2.0f,0.5f);
188     addKey(pos,osgGA::GUIEventAdapter::KEY_A,"A",1.0f,1.0f);
189     addKey(pos,osgGA::GUIEventAdapter::KEY_S,"S",1.0f,1.0f);
190     addKey(pos,osgGA::GUIEventAdapter::KEY_D,"D",1.0f,1.0f);
191     addKey(pos,osgGA::GUIEventAdapter::KEY_F,"F",1.0f,1.0f);
192     addKey(pos,osgGA::GUIEventAdapter::KEY_G,"G",1.0f,1.0f);
193     addKey(pos,osgGA::GUIEventAdapter::KEY_H,"H",1.0f,1.0f);
194     addKey(pos,osgGA::GUIEventAdapter::KEY_J,"J",1.0f,1.0f);
195     addKey(pos,osgGA::GUIEventAdapter::KEY_K,"K",1.0f,1.0f);
196     addKey(pos,osgGA::GUIEventAdapter::KEY_L,"L",1.0f,1.0f);
197     addKey(pos,osgGA::GUIEventAdapter::KEY_Semicolon,";",1.0f,1.0f);
198     addKey(pos,osgGA::GUIEventAdapter::KEY_Quote,"'",1.0f,1.0f);
199     addKey(pos,osgGA::GUIEventAdapter::KEY_Hash,"#",1.0f,1.0f);
200     addKey(pos,osgGA::GUIEventAdapter::KEY_Return,"Return",4.0f,0.5f);
201 
202     pos.x() = 0.0f;
203     pos.z() += 1.0f;
204 
205     addKey(pos,osgGA::GUIEventAdapter::KEY_Tab,"Tab",2.0f,0.5f);
206     addKey(pos,osgGA::GUIEventAdapter::KEY_Q,"Q",1.0f,1.0f);
207     addKey(pos,osgGA::GUIEventAdapter::KEY_W,"W",1.0f,1.0f);
208     addKey(pos,osgGA::GUIEventAdapter::KEY_E,"E",1.0f,1.0f);
209     addKey(pos,osgGA::GUIEventAdapter::KEY_R,"R",1.0f,1.0f);
210     addKey(pos,osgGA::GUIEventAdapter::KEY_T,"T",1.0f,1.0f);
211     addKey(pos,osgGA::GUIEventAdapter::KEY_Y,"Y",1.0f,1.0f);
212     addKey(pos,osgGA::GUIEventAdapter::KEY_U,"U",1.0f,1.0f);
213     addKey(pos,osgGA::GUIEventAdapter::KEY_I,"I",1.0f,1.0f);
214     addKey(pos,osgGA::GUIEventAdapter::KEY_O,"O",1.0f,1.0f);
215     addKey(pos,osgGA::GUIEventAdapter::KEY_P,"P",1.0f,1.0f);
216     addKey(pos,osgGA::GUIEventAdapter::KEY_Leftbracket,"[",1.0f,1.0f);
217     addKey(pos,osgGA::GUIEventAdapter::KEY_Rightbracket,"]",1.0f,1.0f);
218 
219     pos.x() = 0.0f;
220     pos.z() += 1.0f;
221 
222     addKey(pos,osgGA::GUIEventAdapter::KEY_Backquote,"`",1.0f,1.0f);
223     addKey(pos,osgGA::GUIEventAdapter::KEY_1,"1",1.0f,1.0f);
224     addKey(pos,osgGA::GUIEventAdapter::KEY_2,"2",1.0f,1.0f);
225     addKey(pos,osgGA::GUIEventAdapter::KEY_3,"3",1.0f,1.0f);
226     addKey(pos,osgGA::GUIEventAdapter::KEY_4,"4",1.0f,1.0f);
227     addKey(pos,osgGA::GUIEventAdapter::KEY_5,"5",1.0f,1.0f);
228     addKey(pos,osgGA::GUIEventAdapter::KEY_6,"6",1.0f,1.0f);
229     addKey(pos,osgGA::GUIEventAdapter::KEY_7,"7",1.0f,1.0f);
230     addKey(pos,osgGA::GUIEventAdapter::KEY_8,"8",1.0f,1.0f);
231     addKey(pos,osgGA::GUIEventAdapter::KEY_9,"9",1.0f,1.0f);
232     addKey(pos,osgGA::GUIEventAdapter::KEY_0,"0",1.0f,1.0f);
233     addKey(pos,osgGA::GUIEventAdapter::KEY_Minus,"-",1.0f,1.0f);
234     addKey(pos,osgGA::GUIEventAdapter::KEY_Equals,"=",1.0f,1.0f);
235     addKey(pos,osgGA::GUIEventAdapter::KEY_BackSpace,"Backspace",3.0f,0.5f);
236 
237     pos.x() = 0.0f;
238     pos.z() += 1.5f;
239 
240     float F_height = 0.5f;
241     addKey(pos,osgGA::GUIEventAdapter::KEY_Escape,"Esc",2.0f,F_height);
242     addKey(pos,osgGA::GUIEventAdapter::KEY_F1,"F1",1.0f,F_height);
243     addKey(pos,osgGA::GUIEventAdapter::KEY_F2,"F2",1.0f,F_height);
244     addKey(pos,osgGA::GUIEventAdapter::KEY_F3,"F3",1.0f,F_height);
245     addKey(pos,osgGA::GUIEventAdapter::KEY_F4,"F4",1.0f,F_height);
246     addKey(pos,osgGA::GUIEventAdapter::KEY_F5,"F5",1.0f,F_height);
247     addKey(pos,osgGA::GUIEventAdapter::KEY_F6,"F6",1.0f,F_height);
248     addKey(pos,osgGA::GUIEventAdapter::KEY_F7,"F7",1.0f,F_height);
249     addKey(pos,osgGA::GUIEventAdapter::KEY_F8,"F8",1.0f,F_height);
250     addKey(pos,osgGA::GUIEventAdapter::KEY_F9,"F9",1.0f,F_height);
251     addKey(pos,osgGA::GUIEventAdapter::KEY_F10,"F10",1.0f,F_height);
252     addKey(pos,osgGA::GUIEventAdapter::KEY_F11,"F11",1.0f,F_height);
253     addKey(pos,osgGA::GUIEventAdapter::KEY_F12,"F12",1.0f,F_height);
254 
255 
256 
257     float cursorMoveHeight=0.35f;
258 
259     pos = middle;
260     addKey(pos,osgGA::GUIEventAdapter::KEY_Left,"Left",1.0f,cursorMoveHeight);
261     osg::Vec3 down = pos;
262     addKey(pos,osgGA::GUIEventAdapter::KEY_Down,"Down",1.0f,cursorMoveHeight);
263     addKey(pos,osgGA::GUIEventAdapter::KEY_Right,"Right",1.0f,cursorMoveHeight);
264 
265     osg::Vec3 keypad = pos;
266     keypad.x()+=1.0f;
267 
268     pos = down;
269     pos.z() += 1.0f;
270 
271     addKey(pos,osgGA::GUIEventAdapter::KEY_Up,"Up",1.0f,cursorMoveHeight);
272 
273 
274     float homeHeight = 0.35f;
275     pos = middle;
276     pos.z() += 3.0;
277     addKey(pos,osgGA::GUIEventAdapter::KEY_Delete,"Delete",1.0f,homeHeight);
278     addKey(pos,osgGA::GUIEventAdapter::KEY_End,"End",1.0f,homeHeight);
279     addKey(pos,osgGA::GUIEventAdapter::KEY_Page_Down,"Page\nDown",1.0f,homeHeight);
280 
281     pos = middle;
282     pos.z() += 4.0;
283     addKey(pos,osgGA::GUIEventAdapter::KEY_Insert,"Insert",1.0f,homeHeight);
284     addKey(pos,osgGA::GUIEventAdapter::KEY_Home,"Home",1.0f,homeHeight);
285     addKey(pos,osgGA::GUIEventAdapter::KEY_Page_Up,"Page\nUp",1.0f,homeHeight);
286 
287     pos = middle;
288     pos.z() += 5.5;
289     addKey(pos,osgGA::GUIEventAdapter::KEY_Print,"PrtScrn\nSysRq",1.0f,homeHeight);
290     addKey(pos,osgGA::GUIEventAdapter::KEY_Scroll_Lock,"ScrLk",1.0f,homeHeight);
291     addKey(pos,osgGA::GUIEventAdapter::KEY_Pause,"Pause\nBreak",1.0f,homeHeight);
292 
293 
294 
295     pos = keypad;
296     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Insert,"0",2.0f,1.0f);
297     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Delete,".",1.0f,1.0f);
298     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Enter,"Enter",1.0f,homeHeight);
299 
300     pos = keypad;
301     pos.z() += 1.0f;
302     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_End,"1",1.0f,1.0f);
303     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Down,"2",1.0f,1.0f);
304     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Page_Down,"3",1.0f,1.0f);
305 
306     pos = keypad;
307     pos.z() += 2.0f;
308     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Left,"4",1.0f,1.0f);
309     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Begin,"5",1.0f,1.0f);
310     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Right,"6",1.0f,1.0f);
311     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Add,"+",1.0f,1.0f);
312 
313     pos = keypad;
314     pos.z() += 3.0f;
315     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Home,"7",1.0f,1.0f);
316     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Up,"8",1.0f,1.0f);
317     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Page_Up,"9",1.0f,1.0f);
318 
319     pos = keypad;
320     pos.z() += 4.0f;
321     addKey(pos,osgGA::GUIEventAdapter::KEY_Num_Lock,"Num\nLock",1.0f,0.3f);
322     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Divide,"/",1.0f,1.0f);
323     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Multiply,"*",1.0f,1.0f);
324     addKey(pos,osgGA::GUIEventAdapter::KEY_KP_Subtract,"-",1.0f,1.0f);
325 
326     float totalWidth = pos.x()-origin.x();
327     pos = origin;
328     pos.z() += -1.5f;
329 
330     osg::Geode* geodeInput = new osg::Geode;
331     {
332         _inputText = new osgText::Text;
333         _inputText->setFont("fonts/arial.ttf");
334         _inputText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
335         _inputText->setCharacterSize(1.0f);
336         _inputText->setMaximumWidth(totalWidth);
337         _inputText->setPosition(pos);
338         _inputText->setDrawMode(osgText::Text::TEXT/*||osgText::Text::BOUNDINGBOX*/);
339         _inputText->setAlignment(osgText::Text::BASE_LINE);
340         _inputText->setAxisAlignment(osgText::Text::XZ_PLANE);
341         _inputText->setDataVariance(osg::Object::DYNAMIC);
342         _inputText->setText("Press some keys...");
343 
344         geodeInput->addDrawable(_inputText.get());
345 
346         _scene->addChild(geodeInput);
347     }
348 
349 }
350 
351 
352 
353 
354 
355 
356 class KeyboardEventHandler : public osgGA::GUIEventHandler
357 {
358 public:
359 
KeyboardEventHandler(KeyboardModel * keyboardModel)360         KeyboardEventHandler(KeyboardModel* keyboardModel):
361             _keyboardModel(keyboardModel) {}
362 
handle(const osgGA::GUIEventAdapter & ea,osgGA::GUIActionAdapter &)363         virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
364         {
365 
366 #if 1
367 
368 //            osg::notify(osg::NOTICE)<<"Mouse "<<ea.getButtonMask()<<std::endl;
369 
370             #define PRINT(mask) osg::notify(osg::NOTICE)<<#mask<<" ="<<(ea.getModKeyMask() & mask)<<std::endl;
371             switch(ea.getEventType())
372             {
373                 case(osgGA::GUIEventAdapter::KEYDOWN):
374                 case(osgGA::GUIEventAdapter::KEYUP):
375                 {
376                     osg::notify(osg::NOTICE)<<std::endl;
377                     PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT);
378                     PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT);
379                     PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_ALT);
380                     PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_ALT);
381                     PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL);
382                     PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL);
383                     PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_META);
384                     PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_META);
385                     PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_SUPER);
386                     PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_SUPER);
387                     PRINT(osgGA::GUIEventAdapter::MODKEY_LEFT_HYPER);
388                     PRINT(osgGA::GUIEventAdapter::MODKEY_RIGHT_HYPER);
389                     PRINT(osgGA::GUIEventAdapter::MODKEY_NUM_LOCK);
390                     PRINT(osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK);
391                     break;
392                 }
393                 default:
394                     break;
395             }
396 #endif
397             switch(ea.getEventType())
398             {
399                 case(osgGA::GUIEventAdapter::KEYDOWN):
400                 {
401                     _keyboardModel->keyChange(ea.getKey(), ea.getUnmodifiedKey(),1);
402                     return true;
403                 }
404                 case(osgGA::GUIEventAdapter::KEYUP):
405                 {
406                     _keyboardModel->keyChange(ea.getKey(), ea.getUnmodifiedKey(),0);
407                     return true;
408                 }
409 
410                 default:
411                     return false;
412             }
413         }
414 
415         osg::ref_ptr<KeyboardModel> _keyboardModel;
416 
417 };
418 
main(int,char **)419 int main(int , char **)
420 {
421     osgViewer::Viewer viewer;
422 
423     osg::ref_ptr<KeyboardModel> keyboardModel = new KeyboardModel;
424 
425     viewer.addEventHandler(new osgViewer::StatsHandler);
426     viewer.addEventHandler(new osgViewer::WindowSizeHandler());
427     viewer.addEventHandler(new KeyboardEventHandler(keyboardModel.get()));
428     viewer.setSceneData( keyboardModel->getScene() );
429 
430     return viewer.run();
431 }
432