~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to examples/19.MouseAndJoystick/main.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** Example 019 Mouse and Joystick
 
2
 
 
3
This tutorial builds on example 04.Movement which showed how to
 
4
handle keyboard events in Irrlicht.  Here we'll handle mouse events
 
5
and joystick events, if you have a joystick connected and a device
 
6
that supports joysticks.  These are currently Windows, Linux and SDL
 
7
devices.
 
8
*/
 
9
 
 
10
#ifdef _MSC_VER
 
11
// We'll define this to stop MSVC complaining about sprintf().
 
12
#define _CRT_SECURE_NO_WARNINGS
 
13
#pragma comment(lib, "Irrlicht.lib")
 
14
#endif
 
15
 
 
16
#include <irrlicht.h>
 
17
#include "driverChoice.h"
 
18
 
 
19
using namespace irr;
 
20
 
 
21
/*
 
22
Just as we did in example 04.Movement, we'll store the latest state of the
 
23
mouse and the first joystick, updating them as we receive events.
 
24
*/
 
25
class MyEventReceiver : public IEventReceiver
 
26
{
 
27
public:
 
28
        // We'll create a struct to record info on the mouse state
 
29
        struct SMouseState
 
30
        {
 
31
                core::position2di Position;
 
32
                bool LeftButtonDown;
 
33
                SMouseState() : LeftButtonDown(false) { }
 
34
        } MouseState;
 
35
 
 
36
        // This is the one method that we have to implement
 
37
        virtual bool OnEvent(const SEvent& event)
 
38
        {
 
39
                // Remember the mouse state
 
40
                if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
 
41
                {
 
42
                        switch(event.MouseInput.Event)
 
43
                        {
 
44
                        case EMIE_LMOUSE_PRESSED_DOWN:
 
45
                                MouseState.LeftButtonDown = true;
 
46
                                break;
 
47
 
 
48
                        case EMIE_LMOUSE_LEFT_UP:
 
49
                                MouseState.LeftButtonDown = false;
 
50
                                break;
 
51
 
 
52
                        case EMIE_MOUSE_MOVED:
 
53
                                MouseState.Position.X = event.MouseInput.X;
 
54
                                MouseState.Position.Y = event.MouseInput.Y;
 
55
                                break;
 
56
 
 
57
                        default:
 
58
                                // We won't use the wheel
 
59
                                break;
 
60
                        }
 
61
                }
 
62
 
 
63
                // The state of each connected joystick is sent to us
 
64
                // once every run() of the Irrlicht device.  Store the
 
65
                // state of the first joystick, ignoring other joysticks.
 
66
                // This is currently only supported on Windows and Linux.
 
67
                if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT
 
68
                        && event.JoystickEvent.Joystick == 0)
 
69
                {
 
70
                        JoystickState = event.JoystickEvent;
 
71
                }
 
72
 
 
73
                return false;
 
74
        }
 
75
 
 
76
        const SEvent::SJoystickEvent & GetJoystickState(void) const
 
77
        {
 
78
                return JoystickState;
 
79
        }
 
80
 
 
81
        const SMouseState & GetMouseState(void) const
 
82
        {
 
83
                return MouseState;
 
84
        }
 
85
 
 
86
 
 
87
        MyEventReceiver()
 
88
        {
 
89
        }
 
90
 
 
91
private:
 
92
        SEvent::SJoystickEvent JoystickState;
 
93
};
 
94
 
 
95
 
 
96
/*
 
97
The event receiver for keeping the pressed keys is ready, the actual responses
 
98
will be made inside the render loop, right before drawing the scene. So lets
 
99
just create an irr::IrrlichtDevice and the scene node we want to move. We also
 
100
create some other additional scene nodes, to show that there are also some
 
101
different possibilities to move and animate scene nodes.
 
102
*/
 
103
int main()
 
104
{
 
105
        // ask user for driver
 
106
        video::E_DRIVER_TYPE driverType=driverChoiceConsole();
 
107
        if (driverType==video::EDT_COUNT)
 
108
                return 1;
 
109
 
 
110
        // create device
 
111
        MyEventReceiver receiver;
 
112
 
 
113
        IrrlichtDevice* device = createDevice(driverType,
 
114
                        core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver);
 
115
 
 
116
        if (device == 0)
 
117
                return 1; // could not create selected driver.
 
118
 
 
119
 
 
120
        core::array<SJoystickInfo> joystickInfo;
 
121
        if(device->activateJoysticks(joystickInfo))
 
122
        {
 
123
                std::cout << "Joystick support is enabled and " << joystickInfo.size() << " joystick(s) are present." << std::endl;
 
124
 
 
125
                for(u32 joystick = 0; joystick < joystickInfo.size(); ++joystick)
 
126
                {
 
127
                        std::cout << "Joystick " << joystick << ":" << std::endl;
 
128
                        std::cout << "\tName: '" << joystickInfo[joystick].Name.c_str() << "'" << std::endl;
 
129
                        std::cout << "\tAxes: " << joystickInfo[joystick].Axes << std::endl;
 
130
                        std::cout << "\tButtons: " << joystickInfo[joystick].Buttons << std::endl;
 
131
 
 
132
                        std::cout << "\tHat is: ";
 
133
 
 
134
                        switch(joystickInfo[joystick].PovHat)
 
135
                        {
 
136
                        case SJoystickInfo::POV_HAT_PRESENT:
 
137
                                std::cout << "present" << std::endl;
 
138
                                break;
 
139
 
 
140
                        case SJoystickInfo::POV_HAT_ABSENT:
 
141
                                std::cout << "absent" << std::endl;
 
142
                                break;
 
143
 
 
144
                        case SJoystickInfo::POV_HAT_UNKNOWN:
 
145
                        default:
 
146
                                std::cout << "unknown" << std::endl;
 
147
                                break;
 
148
                        }
 
149
                }
 
150
        }
 
151
        else
 
152
        {
 
153
                std::cout << "Joystick support is not enabled." << std::endl;
 
154
        }
 
155
 
 
156
        core::stringw tmp = L"Irrlicht Joystick Example (";
 
157
        tmp += joystickInfo.size();
 
158
        tmp += " joysticks)";
 
159
        device->setWindowCaption(tmp.c_str());
 
160
 
 
161
        video::IVideoDriver* driver = device->getVideoDriver();
 
162
        scene::ISceneManager* smgr = device->getSceneManager();
 
163
 
 
164
        /*
 
165
        We'll create an arrow mesh and move it around either with the joystick axis/hat,
 
166
        or make it follow the mouse pointer. */
 
167
        scene::ISceneNode * node = smgr->addMeshSceneNode(
 
168
                smgr->addArrowMesh( "Arrow",
 
169
                                video::SColor(255, 255, 0, 0),
 
170
                                video::SColor(255, 0, 255, 0),
 
171
                                16,16,
 
172
                                2.f, 1.3f,
 
173
                                0.1f, 0.6f
 
174
                                )
 
175
                );
 
176
        node->setMaterialFlag(video::EMF_LIGHTING, false);
 
177
 
 
178
        scene::ICameraSceneNode * camera = smgr->addCameraSceneNode();
 
179
        camera->setPosition(core::vector3df(0, 0, -10));
 
180
 
 
181
        // As in example 04, we'll use framerate independent movement.
 
182
        u32 then = device->getTimer()->getTime();
 
183
        const f32 MOVEMENT_SPEED = 5.f;
 
184
 
 
185
        while(device->run())
 
186
        {
 
187
                // Work out a frame delta time.
 
188
                const u32 now = device->getTimer()->getTime();
 
189
                const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
 
190
                then = now;
 
191
 
 
192
                bool movedWithJoystick = false;
 
193
                core::vector3df nodePosition = node->getPosition();
 
194
 
 
195
                if(joystickInfo.size() > 0)
 
196
                {
 
197
                        f32 moveHorizontal = 0.f; // Range is -1.f for full left to +1.f for full right
 
198
                        f32 moveVertical = 0.f; // -1.f for full down to +1.f for full up.
 
199
 
 
200
                        const SEvent::SJoystickEvent & joystickData = receiver.GetJoystickState();
 
201
 
 
202
                        // We receive the full analog range of the axes, and so have to implement our
 
203
                        // own dead zone.  This is an empirical value, since some joysticks have more
 
204
                        // jitter or creep around the center point than others.  We'll use 5% of the
 
205
                        // range as the dead zone, but generally you would want to give the user the
 
206
                        // option to change this.
 
207
                        const f32 DEAD_ZONE = 0.05f;
 
208
 
 
209
                        moveHorizontal =
 
210
                                (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_X] / 32767.f;
 
211
                        if(fabs(moveHorizontal) < DEAD_ZONE)
 
212
                                moveHorizontal = 0.f;
 
213
 
 
214
                        moveVertical =
 
215
                                (f32)joystickData.Axis[SEvent::SJoystickEvent::AXIS_Y] / -32767.f;
 
216
                        if(fabs(moveVertical) < DEAD_ZONE)
 
217
                                moveVertical = 0.f;
 
218
 
 
219
                        // POV hat info is only currently supported on Windows, but the value is
 
220
                        // guaranteed to be 65535 if it's not supported, so we can check its range.
 
221
                        const u16 povDegrees = joystickData.POV / 100;
 
222
                        if(povDegrees < 360)
 
223
                        {
 
224
                                if(povDegrees > 0 && povDegrees < 180)
 
225
                                        moveHorizontal = 1.f;
 
226
                                else if(povDegrees > 180)
 
227
                                        moveHorizontal = -1.f;
 
228
 
 
229
                                if(povDegrees > 90 && povDegrees < 270)
 
230
                                        moveVertical = -1.f;
 
231
                                else if(povDegrees > 270 || povDegrees < 90)
 
232
                                        moveVertical = +1.f;
 
233
                        }
 
234
 
 
235
                        if(!core::equals(moveHorizontal, 0.f) || !core::equals(moveVertical, 0.f))
 
236
                        {
 
237
                                nodePosition.X += MOVEMENT_SPEED * frameDeltaTime * moveHorizontal;
 
238
                                nodePosition.Y += MOVEMENT_SPEED * frameDeltaTime * moveVertical;
 
239
                                movedWithJoystick = true;
 
240
                        }
 
241
                }
 
242
 
 
243
                // If the arrow node isn't being moved with the joystick, then have it follow the mouse cursor.
 
244
                if(!movedWithJoystick)
 
245
                {
 
246
                        // Create a ray through the mouse cursor.
 
247
                        core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
 
248
                                receiver.GetMouseState().Position, camera);
 
249
 
 
250
                        // And intersect the ray with a plane around the node facing towards the camera.
 
251
                        core::plane3df plane(nodePosition, core::vector3df(0, 0, -1));
 
252
                        core::vector3df mousePosition;
 
253
                        if(plane.getIntersectionWithLine(ray.start, ray.getVector(), mousePosition))
 
254
                        {
 
255
                                // We now have a mouse position in 3d space; move towards it.
 
256
                                core::vector3df toMousePosition(mousePosition - nodePosition);
 
257
                                const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime;
 
258
 
 
259
                                if(toMousePosition.getLength() <= availableMovement)
 
260
                                        nodePosition = mousePosition; // Jump to the final position
 
261
                                else
 
262
                                        nodePosition += toMousePosition.normalize() * availableMovement; // Move towards it
 
263
                        }
 
264
                }
 
265
 
 
266
                node->setPosition(nodePosition);
 
267
 
 
268
                // Turn lighting on and off depending on whether the left mouse button is down.
 
269
                node->setMaterialFlag(video::EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown);
 
270
 
 
271
                driver->beginScene(true, true, video::SColor(255,113,113,133));
 
272
                smgr->drawAll(); // draw the 3d scene
 
273
                driver->endScene();
 
274
        }
 
275
 
 
276
        /*
 
277
        In the end, delete the Irrlicht device.
 
278
        */
 
279
        device->drop();
 
280
 
 
281
        return 0;
 
282
}
 
283
 
 
284
/*
 
285
**/