aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/examples/24.CursorControl/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/examples/24.CursorControl/main.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/examples/24.CursorControl/main.cpp563
1 files changed, 563 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/examples/24.CursorControl/main.cpp b/src/others/irrlicht-1.8.1/examples/24.CursorControl/main.cpp
new file mode 100644
index 0000000..ff7c16f
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/examples/24.CursorControl/main.cpp
@@ -0,0 +1,563 @@
1/** Example 024 CursorControl
2
3Show how to modify cursors and offer some useful tool-functions for creating cursors.
4It can also be used for experiments with the mouse in general.
5*/
6
7#include <irrlicht.h>
8#include "driverChoice.h"
9
10using namespace irr;
11using namespace core;
12using namespace scene;
13using namespace video;
14using namespace io;
15using namespace gui;
16
17#ifdef _IRR_WINDOWS_
18#pragma comment(lib, "Irrlicht.lib")
19#endif
20
21const int DELAY_TIME = 3000;
22
23enum ETimerAction
24{
25 ETA_MOUSE_VISIBLE,
26 ETA_MOUSE_INVISIBLE,
27};
28
29/*
30 Structure to allow delayed execution of some actions.
31*/
32struct TimerAction
33{
34 u32 TargetTime;
35 ETimerAction Action;
36};
37
38/*
39*/
40struct SAppContext
41{
42 SAppContext()
43 : Device(0), InfoStatic(0), EventBox(0), CursorBox(0), SpriteBox(0)
44 , ButtonSetVisible(0), ButtonSetInvisible(0), ButtonSimulateBadFps(0)
45 , ButtonChangeIcon(0)
46 , SimulateBadFps(false)
47 {
48 }
49
50 void update()
51 {
52 if (!Device)
53 return;
54 u32 timeNow = Device->getTimer()->getTime();
55 for ( u32 i=0; i < TimerActions.size(); ++i )
56 {
57 if ( timeNow >= TimerActions[i].TargetTime )
58 {
59 runTimerAction(TimerActions[i]);
60 TimerActions.erase(i);
61 }
62 else
63 {
64 ++i;
65 }
66 }
67 }
68
69 void runTimerAction(const TimerAction& action)
70 {
71 if (ETA_MOUSE_VISIBLE == action.Action)
72 {
73 Device->getCursorControl()->setVisible(true);
74 ButtonSetVisible->setEnabled(true);
75 }
76 else if ( ETA_MOUSE_INVISIBLE == action.Action)
77 {
78 Device->getCursorControl()->setVisible(false);
79 ButtonSetInvisible->setEnabled(true);
80 }
81 }
82
83 /*
84 Add another icon which the user can click and select as cursor later on.
85 */
86 void addIcon(const stringw& name, const SCursorSprite &sprite, bool addCursor=true)
87 {
88 // Sprites are just icons - not yet cursors. They can be displayed by Irrlicht sprite functions and be used to create cursors.
89 SpriteBox->addItem(name.c_str(), sprite.SpriteId);
90 Sprites.push_back(sprite);
91
92 // create the cursor together with the icon?
93 if ( addCursor )
94 {
95 /* Here we create a hardware cursor from a sprite */
96 Device->getCursorControl()->addIcon(sprite);
97
98 // ... and add it to the cursors selection listbox to the other system cursors.
99 CursorBox->addItem(name.c_str());
100 }
101 }
102
103 IrrlichtDevice * Device;
104 gui::IGUIStaticText * InfoStatic;
105 gui::IGUIListBox * EventBox;
106 gui::IGUIListBox * CursorBox;
107 gui::IGUIListBox * SpriteBox;
108 gui::IGUIButton * ButtonSetVisible;
109 gui::IGUIButton * ButtonSetInvisible;
110 gui::IGUIButton * ButtonSimulateBadFps;
111 gui::IGUIButton * ButtonChangeIcon;
112 array<TimerAction> TimerActions;
113 bool SimulateBadFps;
114 array<SCursorSprite> Sprites;
115};
116
117/*
118 Helper function to print mouse event names into a stringw
119*/
120void PrintMouseEventName(const SEvent& event, stringw &result)
121{
122 switch ( event.MouseInput.Event )
123 {
124 case EMIE_LMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_LMOUSE_PRESSED_DOWN"); break;
125 case EMIE_RMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_RMOUSE_PRESSED_DOWN"); break;
126 case EMIE_MMOUSE_PRESSED_DOWN: result += stringw(L"EMIE_MMOUSE_PRESSED_DOWN"); break;
127 case EMIE_LMOUSE_LEFT_UP: result += stringw(L"EMIE_LMOUSE_LEFT_UP"); break;
128 case EMIE_RMOUSE_LEFT_UP: result += stringw(L"EMIE_RMOUSE_LEFT_UP"); break;
129 case EMIE_MMOUSE_LEFT_UP: result += stringw(L"EMIE_MMOUSE_LEFT_UP"); break;
130 case EMIE_MOUSE_MOVED: result += stringw(L"EMIE_MOUSE_MOVED"); break;
131 case EMIE_MOUSE_WHEEL: result += stringw(L"EMIE_MOUSE_WHEEL"); break;
132 case EMIE_LMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_LMOUSE_DOUBLE_CLICK"); break;
133 case EMIE_RMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_RMOUSE_DOUBLE_CLICK"); break;
134 case EMIE_MMOUSE_DOUBLE_CLICK: result += stringw(L"EMIE_MMOUSE_DOUBLE_CLICK"); break;
135 case EMIE_LMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_LMOUSE_TRIPLE_CLICK"); break;
136 case EMIE_RMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_RMOUSE_TRIPLE_CLICK"); break;
137 case EMIE_MMOUSE_TRIPLE_CLICK: result += stringw(L"EMIE_MMOUSE_TRIPLE_CLICK"); break;
138 default:
139 break;
140 }
141}
142
143/*
144 Helper function to print all the state information which get from a mouse-event into a stringw
145*/
146void PrintMouseState(const SEvent& event, stringw &result)
147{
148 result += stringw(L"X: ");
149 result += stringw(event.MouseInput.X);
150 result += stringw(L"\n");
151
152 result += stringw(L"Y: ");
153 result += stringw(event.MouseInput.Y);
154 result += stringw(L"\n");
155
156
157 result += stringw(L"Wheel: ");
158 result += stringw(event.MouseInput.Wheel);
159 result += stringw(L"\n");
160
161 result += stringw(L"Shift: ");
162 if ( event.MouseInput.Shift )
163 result += stringw(L"true\n");
164 else
165 result += stringw(L"false\n");
166
167 result += stringw(L"Control: ");
168 if ( event.MouseInput.Control )
169 result += stringw(L"true\n");
170 else
171 result += stringw(L"false\n");
172
173 result += stringw(L"ButtonStates: ");
174 result += stringw(event.MouseInput.ButtonStates);
175 result += stringw(L"\n");
176
177 result += stringw(L"isLeftPressed: ");
178 if ( event.MouseInput.isLeftPressed() )
179 result += stringw(L"true\n");
180 else
181 result += stringw(L"false\n");
182
183 result += stringw(L"isRightPressed: ");
184 if ( event.MouseInput.isRightPressed() )
185 result += stringw(L"true\n");
186 else
187 result += stringw(L"false\n");
188
189 result += stringw(L"isMiddlePressed: ");
190 if ( event.MouseInput.isMiddlePressed() )
191 result += stringw(L"true\n");
192 else
193 result += stringw(L"false\n");
194
195 result += stringw(L"Event: ");
196
197 PrintMouseEventName(event, result);
198
199 result += stringw(L"\n");
200}
201
202/*
203 A typical event receiver.
204*/
205class MyEventReceiver : public IEventReceiver
206{
207public:
208 MyEventReceiver(SAppContext & context) : Context(context) { }
209
210 virtual bool OnEvent(const SEvent& event)
211 {
212 if (event.EventType == EET_GUI_EVENT )
213 {
214 switch ( event.GUIEvent.EventType )
215 {
216 case EGET_BUTTON_CLICKED:
217 {
218 u32 timeNow = Context.Device->getTimer()->getTime();
219 TimerAction action;
220 action.TargetTime = timeNow + DELAY_TIME;
221 if ( event.GUIEvent.Caller == Context.ButtonSetVisible )
222 {
223 action.Action = ETA_MOUSE_VISIBLE;
224 Context.TimerActions.push_back(action);
225 Context.ButtonSetVisible->setEnabled(false);
226 }
227 else if ( event.GUIEvent.Caller == Context.ButtonSetInvisible )
228 {
229 action.Action = ETA_MOUSE_INVISIBLE;
230 Context.TimerActions.push_back(action);
231 Context.ButtonSetInvisible->setEnabled(false);
232 }
233 else if ( event.GUIEvent.Caller == Context.ButtonSimulateBadFps )
234 {
235 Context.SimulateBadFps = Context.ButtonSimulateBadFps->isPressed();
236 }
237 else if ( event.GUIEvent.Caller == Context.ButtonChangeIcon )
238 {
239 /*
240 Replace an existing cursor icon by another icon.
241 The user has to select both - the icon which should be replaced and the icon which will replace it.
242 */
243 s32 selectedCursor = Context.CursorBox->getSelected();
244 s32 selectedSprite = Context.SpriteBox->getSelected();
245 if ( selectedCursor >= 0 && selectedSprite >= 0 )
246 {
247 /*
248 This does replace the icon.
249 */
250 Context.Device->getCursorControl()->changeIcon((ECURSOR_ICON)selectedCursor, Context.Sprites[selectedSprite] );
251
252 /*
253 Do also show the new icon.
254 */
255 Context.Device->getCursorControl()->setActiveIcon( ECURSOR_ICON(selectedCursor) );
256 }
257 }
258 }
259 break;
260 case EGET_LISTBOX_CHANGED:
261 case EGET_LISTBOX_SELECTED_AGAIN:
262 {
263 if ( event.GUIEvent.Caller == Context.CursorBox )
264 {
265 /*
266 Find out which cursor the user selected
267 */
268 s32 selected = Context.CursorBox->getSelected();
269 if ( selected >= 0 )
270 {
271 /*
272 Here we set the new cursor icon which will now be used within our window.
273 */
274 Context.Device->getCursorControl()->setActiveIcon( ECURSOR_ICON(selected) );
275 }
276 }
277 }
278 break;
279 default:
280 break;
281 }
282 }
283
284 if (event.EventType == EET_MOUSE_INPUT_EVENT)
285 {
286 stringw infoText;
287 PrintMouseState(event, infoText);
288 Context.InfoStatic->setText(infoText.c_str());
289 if ( event.MouseInput.Event != EMIE_MOUSE_MOVED && event.MouseInput.Event != EMIE_MOUSE_WHEEL ) // no spam
290 {
291 infoText = L"";
292 PrintMouseEventName(event, infoText);
293 Context.EventBox->insertItem(0, infoText.c_str(), -1);
294 }
295 }
296
297 return false;
298 }
299
300private:
301 SAppContext & Context;
302};
303
304/*
305 Use several imagefiles as animation frames for a sprite which can be used as cursor icon.
306 The images in those files all need to have the same size.
307 Return sprite index on success or -1 on failure
308*/
309s32 AddAnimatedIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideoDriver* driver, const array< io::path >& files, u32 frameTime )
310{
311 if ( !spriteBank || !driver || !files.size() )
312 return -1;
313
314 video::ITexture * tex = driver->getTexture( files[0] );
315 if ( tex )
316 {
317 array< rect<s32> >& spritePositions = spriteBank->getPositions();
318 u32 idxRect = spritePositions.size();
319 spritePositions.push_back( rect<s32>(0,0, tex->getSize().Width, tex->getSize().Height) );
320
321 SGUISprite sprite;
322 sprite.frameTime = frameTime;
323
324 array< SGUISprite >& sprites = spriteBank->getSprites();
325 u32 startIdx = spriteBank->getTextureCount();
326 for ( u32 f=0; f < files.size(); ++f )
327 {
328 tex = driver->getTexture( files[f] );
329 if ( tex )
330 {
331 spriteBank->addTexture( driver->getTexture(files[f]) );
332 gui::SGUISpriteFrame frame;
333 frame.rectNumber = idxRect;
334 frame.textureNumber = startIdx+f;
335 sprite.Frames.push_back( frame );
336 }
337 }
338
339 sprites.push_back( sprite );
340 return sprites.size()-1;
341 }
342
343 return -1;
344}
345
346/*
347 Use several images within one imagefile as animation frames for a sprite which can be used as cursor icon
348 The sizes of the icons within that file all need to have the same size
349 Return sprite index on success or -1 on failure
350*/
351s32 AddAnimatedIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideoDriver* driver, const io::path& file, const array< rect<s32> >& rects, u32 frameTime )
352{
353 if ( !spriteBank || !driver || !rects.size() )
354 return -1;
355
356 video::ITexture * tex = driver->getTexture( file );
357 if ( tex )
358 {
359 array< rect<s32> >& spritePositions = spriteBank->getPositions();
360 u32 idxRect = spritePositions.size();
361 u32 idxTex = spriteBank->getTextureCount();
362 spriteBank->addTexture( tex );
363
364 SGUISprite sprite;
365 sprite.frameTime = frameTime;
366
367 array< SGUISprite >& sprites = spriteBank->getSprites();
368 for ( u32 i=0; i < rects.size(); ++i )
369 {
370 spritePositions.push_back( rects[i] );
371
372 gui::SGUISpriteFrame frame;
373 frame.rectNumber = idxRect+i;
374 frame.textureNumber = idxTex;
375 sprite.Frames.push_back( frame );
376 }
377
378 sprites.push_back( sprite );
379 return sprites.size()-1;
380 }
381
382 return -1;
383}
384
385/*
386 Create a non-animated icon from the given file and position and put it into the spritebank.
387 We can use this icon later on in a cursor.
388*/
389s32 AddIconToSpriteBank( gui::IGUISpriteBank * spriteBank, video::IVideoDriver* driver, const io::path& file, const core::rect<s32>& rect )
390{
391 if ( !spriteBank || !driver )
392 return -1;
393
394 video::ITexture * tex = driver->getTexture( file );
395 if ( tex )
396 {
397 core::array< core::rect<irr::s32> >& spritePositions = spriteBank->getPositions();
398 spritePositions.push_back( rect );
399 array< SGUISprite >& sprites = spriteBank->getSprites();
400 spriteBank->addTexture( tex );
401
402 gui::SGUISpriteFrame frame;
403 frame.rectNumber = spritePositions.size()-1;
404 frame.textureNumber = spriteBank->getTextureCount()-1;
405
406 SGUISprite sprite;
407 sprite.frameTime = 0;
408 sprite.Frames.push_back( frame );
409
410 sprites.push_back( sprite );
411
412 return sprites.size()-1;
413 }
414
415 return -1;
416}
417
418int main()
419{
420 video::E_DRIVER_TYPE driverType = driverChoiceConsole();
421 if (driverType==video::EDT_COUNT)
422 return 1;
423
424 IrrlichtDevice * device = createDevice(driverType, dimension2d<u32>(640, 480));
425 if (device == 0)
426 return 1; // could not create selected driver.
427
428 // It's sometimes of interest to know how the mouse behaves after a resize
429 device->setResizable(true);
430
431 device->setWindowCaption(L"Cursor control - Irrlicht engine tutorial");
432 video::IVideoDriver* driver = device->getVideoDriver();
433 IGUIEnvironment* env = device->getGUIEnvironment();
434
435 gui::IGUISpriteBank * SpriteBankIcons;
436
437 SAppContext context;
438 context.Device = device;
439
440 rect< s32 > rectInfoStatic(10,10, 200, 200);
441 env->addStaticText (L"Cursor state information", rectInfoStatic, true, true);
442 rectInfoStatic.UpperLeftCorner += dimension2di(0, 15);
443 context.InfoStatic = env->addStaticText (L"", rectInfoStatic, true, true);
444 rect< s32 > rectEventBox(10,210, 200, 400);
445 env->addStaticText (L"click events (new on top)", rectEventBox, true, true);
446 rectEventBox.UpperLeftCorner += dimension2di(0, 15);
447 context.EventBox = env->addListBox(rectEventBox);
448 rect< s32 > rectCursorBox(210,10, 400, 250);
449 env->addStaticText (L"cursors, click to set the active one", rectCursorBox, true, true);
450 rectCursorBox.UpperLeftCorner += dimension2di(0, 15);
451 context.CursorBox = env->addListBox(rectCursorBox);
452 rect< s32 > rectSpriteBox(210,260, 400, 400);
453 env->addStaticText (L"sprites", rectSpriteBox, true, true);
454 rectSpriteBox.UpperLeftCorner += dimension2di(0, 15);
455 context.SpriteBox = env->addListBox(rectSpriteBox);
456
457 context.ButtonSetVisible = env->addButton( rect<s32>( 410, 20, 560, 40 ), 0, -1, L"set visible (delayed)" );
458 context.ButtonSetInvisible = env->addButton( rect<s32>( 410, 50, 560, 70 ), 0, -1, L"set invisible (delayed)" );
459 context.ButtonSimulateBadFps = env->addButton( rect<s32>( 410, 80, 560, 100 ), 0, -1, L"simulate bad FPS" );
460 context.ButtonSimulateBadFps->setIsPushButton(true);
461 context.ButtonChangeIcon = env->addButton( rect<s32>( 410, 140, 560, 160 ), 0, -1, L"replace cursor icon\n(cursor+sprite must be selected)" );
462
463 // set the names for all the system cursors
464 for ( int i=0; i < (int)gui::ECI_COUNT; ++i )
465 {
466 context.CursorBox->addItem(stringw( GUICursorIconNames[i] ).c_str());
467 }
468
469 /*
470 Create sprites which then can be used as cursor icons.
471 */
472 SpriteBankIcons = env->addEmptySpriteBank(io::path("cursor_icons"));
473 context.SpriteBox->setSpriteBank(SpriteBankIcons);
474
475 // create one animated icon from several files
476 array< io::path > files;
477 files.push_back( io::path("../../media/icon_crosshairs16x16bw1.png") );
478 files.push_back( io::path("../../media/icon_crosshairs16x16bw2.png") );
479 files.push_back( io::path("../../media/icon_crosshairs16x16bw3.png") );
480 files.push_back( io::path("../../media/icon_crosshairs16x16bw3.png") );
481 files.push_back( io::path("../../media/icon_crosshairs16x16bw2.png") );
482 SCursorSprite spriteBw; // the sprite + some additional information needed for cursors
483 spriteBw.SpriteId = AddAnimatedIconToSpriteBank( SpriteBankIcons, driver, files, 200 );
484 spriteBw.SpriteBank = SpriteBankIcons;
485 spriteBw.HotSpot = position2d<s32>(7,7);
486 context.addIcon(L"crosshair_bw", spriteBw);
487
488 // create one animated icon from one file
489 array< rect<s32> > iconRects;
490 iconRects.push_back( rect<s32>(0,0, 16, 16) );
491 iconRects.push_back( rect<s32>(16,0, 32, 16) );
492 iconRects.push_back( rect<s32>(0,16, 16, 32) );
493 iconRects.push_back( rect<s32>(0,16, 16, 32) );
494 iconRects.push_back( rect<s32>(16,0, 32, 16) );
495 SCursorSprite spriteCol; // the sprite + some additional information needed for cursors
496 spriteCol.SpriteId = AddAnimatedIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), iconRects, 200 );
497 spriteCol.HotSpot = position2d<s32>(7,7);
498 spriteCol.SpriteBank = SpriteBankIcons;
499 context.addIcon(L"crosshair_colored", spriteCol);
500
501 // Create some non-animated icons
502 rect<s32> rectIcon;
503 SCursorSprite spriteNonAnimated(SpriteBankIcons, 0, position2d<s32>(7,7));
504
505 rectIcon = rect<s32>(0,0, 16, 16);
506 spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), rectIcon );
507 context.addIcon(L"crosshair_col1", spriteNonAnimated, false);
508
509 rectIcon = rect<s32>(16,0, 32, 16);
510 spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), rectIcon );
511 context.addIcon(L"crosshair_col2", spriteNonAnimated, false);
512
513 rectIcon = rect<s32>(0,16, 16, 32);
514 spriteNonAnimated.SpriteId = AddIconToSpriteBank( SpriteBankIcons, driver, io::path("../../media/icon_crosshairs16x16col.png"), rectIcon );
515 context.addIcon(L"crosshair_col3", spriteNonAnimated, false);
516
517
518 MyEventReceiver receiver(context);
519 device->setEventReceiver(&receiver);
520
521 while(device->run() && driver)
522 {
523 // if (device->isWindowActive())
524 {
525 u32 realTimeNow = device->getTimer()->getRealTime();
526
527 context.update();
528
529 driver->beginScene(true, true, SColor(0,200,200,200));
530
531 env->drawAll();
532
533 // draw custom sprite with Irrlicht functions for comparison. It should usually look the same as the cursors.
534 if ( context.SpriteBox )
535 {
536 s32 selectedSprite = context.SpriteBox->getSelected();
537 if ( selectedSprite >= 0 && context.Sprites[selectedSprite].SpriteId >= 0 )
538 {
539 SpriteBankIcons->draw2DSprite(u32(context.Sprites[selectedSprite].SpriteId), position2di(580, 140), 0, video::SColor(255, 255, 255, 255), 0, realTimeNow);
540 }
541 }
542
543 driver->endScene();
544 }
545
546 // By simulating bad fps we can find out if hardware-support for cursors works or not. If it works the cursor will move as usual,while it otherwise will just update with 2 fps now.
547 if ( context.SimulateBadFps )
548 {
549 device->sleep(500); // 2 fps
550 }
551 else
552 {
553 device->sleep(10);
554 }
555 }
556
557 device->drop();
558
559 return 0;
560}
561
562/*
563**/