diff options
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CIrrDeviceConsole.cpp')
-rw-r--r-- | src/others/irrlicht-1.8.1/source/Irrlicht/CIrrDeviceConsole.cpp | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CIrrDeviceConsole.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CIrrDeviceConsole.cpp new file mode 100644 index 0000000..53892ee --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CIrrDeviceConsole.cpp | |||
@@ -0,0 +1,477 @@ | |||
1 | // Copyright (C) 2009-2012 Gaz Davidson | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "CIrrDeviceConsole.h" | ||
6 | |||
7 | #ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_ | ||
8 | |||
9 | #include "os.h" | ||
10 | #include "IGUISkin.h" | ||
11 | #include "IGUIEnvironment.h" | ||
12 | |||
13 | // to close the device on terminate signal | ||
14 | irr::CIrrDeviceConsole *DeviceToClose; | ||
15 | |||
16 | #ifdef _IRR_WINDOWS_NT_CONSOLE_ | ||
17 | // Callback for Windows | ||
18 | BOOL WINAPI ConsoleHandler(DWORD CEvent) | ||
19 | { | ||
20 | switch(CEvent) | ||
21 | { | ||
22 | case CTRL_C_EVENT: | ||
23 | irr::os::Printer::log("Closing console device", "CTRL+C"); | ||
24 | break; | ||
25 | case CTRL_BREAK_EVENT: | ||
26 | irr::os::Printer::log("Closing console device", "CTRL+Break"); | ||
27 | break; | ||
28 | case CTRL_CLOSE_EVENT: | ||
29 | irr::os::Printer::log("Closing console device", "User closed console"); | ||
30 | break; | ||
31 | case CTRL_LOGOFF_EVENT: | ||
32 | irr::os::Printer::log("Closing console device", "User is logging off"); | ||
33 | break; | ||
34 | case CTRL_SHUTDOWN_EVENT: | ||
35 | irr::os::Printer::log("Closing console device", "Computer shutting down"); | ||
36 | break; | ||
37 | } | ||
38 | DeviceToClose->closeDevice(); | ||
39 | return TRUE; | ||
40 | } | ||
41 | #elif defined(_IRR_POSIX_API_) | ||
42 | // sigterm handler | ||
43 | #include <signal.h> | ||
44 | |||
45 | void sighandler(int sig) | ||
46 | { | ||
47 | irr::core::stringc code = "Signal "; | ||
48 | code += sig; | ||
49 | code += " received"; | ||
50 | irr::os::Printer::log("Closing console device", code.c_str()); | ||
51 | |||
52 | DeviceToClose->closeDevice(); | ||
53 | } | ||
54 | #endif | ||
55 | |||
56 | namespace irr | ||
57 | { | ||
58 | |||
59 | const c8 ASCIIArtChars[] = " .,'~:;!+>=icopjtJY56SB8XDQKHNWM"; //MWNHKQDX8BS65YJtjpoci=+>!;:~',. "; | ||
60 | const u16 ASCIIArtCharsCount = 32; | ||
61 | |||
62 | //const c8 ASCIIArtChars[] = " \xb0\xb1\xf9\xb2\xdb"; | ||
63 | //const u16 ASCIIArtCharsCount = 5; | ||
64 | |||
65 | //! constructor | ||
66 | CIrrDeviceConsole::CIrrDeviceConsole(const SIrrlichtCreationParameters& params) | ||
67 | : CIrrDeviceStub(params), IsWindowFocused(true), ConsoleFont(0), OutFile(stdout) | ||
68 | { | ||
69 | DeviceToClose = this; | ||
70 | |||
71 | #ifdef _IRR_WINDOWS_NT_CONSOLE_ | ||
72 | MouseButtonStates = 0; | ||
73 | |||
74 | WindowsSTDIn = GetStdHandle(STD_INPUT_HANDLE); | ||
75 | WindowsSTDOut = GetStdHandle(STD_OUTPUT_HANDLE); | ||
76 | PCOORD Dimensions = 0; | ||
77 | |||
78 | if (CreationParams.Fullscreen) | ||
79 | { | ||
80 | // Some mingw versions lack this define, so avoid it in case it does not exist | ||
81 | #if (_WIN32_WINNT >= 0x0501) && defined(CONSOLE_FULLSCREEN_MODE) | ||
82 | if (SetConsoleDisplayMode(WindowsSTDOut, CONSOLE_FULLSCREEN_MODE, Dimensions)) | ||
83 | { | ||
84 | CreationParams.WindowSize.Width = Dimensions->X; | ||
85 | CreationParams.WindowSize.Width = Dimensions->Y; | ||
86 | } | ||
87 | #endif | ||
88 | } | ||
89 | else | ||
90 | { | ||
91 | COORD ConsoleSize; | ||
92 | ConsoleSize.X = CreationParams.WindowSize.Width; | ||
93 | ConsoleSize.X = CreationParams.WindowSize.Height; | ||
94 | SetConsoleScreenBufferSize(WindowsSTDOut, ConsoleSize); | ||
95 | } | ||
96 | |||
97 | // catch windows close/break signals | ||
98 | SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE); | ||
99 | |||
100 | #elif defined(_IRR_POSIX_API_) | ||
101 | // catch other signals | ||
102 | signal(SIGABRT, &sighandler); | ||
103 | signal(SIGTERM, &sighandler); | ||
104 | signal(SIGINT, &sighandler); | ||
105 | |||
106 | // set output stream | ||
107 | if (params.WindowId) | ||
108 | OutFile = (FILE*)(params.WindowId); | ||
109 | #endif | ||
110 | |||
111 | #ifdef _IRR_VT100_CONSOLE_ | ||
112 | // reset terminal | ||
113 | fprintf(OutFile, "%cc", 27); | ||
114 | // disable line wrapping | ||
115 | fprintf(OutFile, "%c[7l", 27); | ||
116 | #endif | ||
117 | |||
118 | switch (params.DriverType) | ||
119 | { | ||
120 | case video::EDT_SOFTWARE: | ||
121 | #ifdef _IRR_COMPILE_WITH_SOFTWARE_ | ||
122 | VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); | ||
123 | #else | ||
124 | os::Printer::log("Software driver was not compiled in.", ELL_ERROR); | ||
125 | #endif | ||
126 | break; | ||
127 | |||
128 | case video::EDT_BURNINGSVIDEO: | ||
129 | #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ | ||
130 | VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); | ||
131 | #else | ||
132 | os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR); | ||
133 | #endif | ||
134 | break; | ||
135 | |||
136 | case video::EDT_DIRECT3D8: | ||
137 | case video::EDT_DIRECT3D9: | ||
138 | case video::EDT_OPENGL: | ||
139 | os::Printer::log("The console device cannot use hardware drivers yet.", ELL_ERROR); | ||
140 | break; | ||
141 | case video::EDT_NULL: | ||
142 | VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize); | ||
143 | break; | ||
144 | default: | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | // set up output buffer | ||
149 | for (u32 y=0; y<CreationParams.WindowSize.Height; ++y) | ||
150 | { | ||
151 | core::stringc str; | ||
152 | str.reserve(CreationParams.WindowSize.Width); | ||
153 | for (u32 x=0; x<CreationParams.WindowSize.Width; ++x) | ||
154 | str += " "; | ||
155 | OutputBuffer.push_back(str); | ||
156 | } | ||
157 | |||
158 | |||
159 | #ifdef _IRR_WINDOWS_NT_CONSOLE_ | ||
160 | CursorControl = new CCursorControl(CreationParams.WindowSize); | ||
161 | #endif | ||
162 | |||
163 | if (VideoDriver) | ||
164 | { | ||
165 | createGUIAndScene(); | ||
166 | #ifdef _IRR_USE_CONSOLE_FONT_ | ||
167 | if (GUIEnvironment) | ||
168 | { | ||
169 | ConsoleFont = new gui::CGUIConsoleFont(this); | ||
170 | gui::IGUISkin *skin = GUIEnvironment->getSkin(); | ||
171 | if (skin) | ||
172 | { | ||
173 | for (u32 i=0; i < gui::EGDF_COUNT; ++i) | ||
174 | skin->setFont(ConsoleFont, gui::EGUI_DEFAULT_FONT(i)); | ||
175 | } | ||
176 | } | ||
177 | #endif | ||
178 | } | ||
179 | } | ||
180 | |||
181 | //! destructor | ||
182 | CIrrDeviceConsole::~CIrrDeviceConsole() | ||
183 | { | ||
184 | // GUI and scene are dropped in the stub | ||
185 | if (CursorControl) | ||
186 | { | ||
187 | CursorControl->drop(); | ||
188 | CursorControl = 0; | ||
189 | } | ||
190 | if (ConsoleFont) | ||
191 | { | ||
192 | ConsoleFont->drop(); | ||
193 | ConsoleFont = 0; | ||
194 | } | ||
195 | #ifdef _IRR_VT100_CONSOLE_ | ||
196 | // reset terminal | ||
197 | fprintf(OutFile, "%cc", 27); | ||
198 | #endif | ||
199 | } | ||
200 | |||
201 | //! runs the device. Returns false if device wants to be deleted | ||
202 | bool CIrrDeviceConsole::run() | ||
203 | { | ||
204 | // increment timer | ||
205 | os::Timer::tick(); | ||
206 | |||
207 | // process Windows console input | ||
208 | #ifdef _IRR_WINDOWS_NT_CONSOLE_ | ||
209 | |||
210 | INPUT_RECORD in; | ||
211 | DWORD oldMode; | ||
212 | DWORD count, waste; | ||
213 | |||
214 | // get old input mode | ||
215 | GetConsoleMode(WindowsSTDIn, &oldMode); | ||
216 | SetConsoleMode(WindowsSTDIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT); | ||
217 | |||
218 | GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); | ||
219 | |||
220 | // read keyboard and mouse input | ||
221 | while (count) | ||
222 | { | ||
223 | ReadConsoleInput(WindowsSTDIn, &in, 1, &waste ); | ||
224 | switch(in.EventType) | ||
225 | { | ||
226 | case KEY_EVENT: | ||
227 | { | ||
228 | SEvent e; | ||
229 | e.EventType = EET_KEY_INPUT_EVENT; | ||
230 | e.KeyInput.PressedDown = (in.Event.KeyEvent.bKeyDown == TRUE); | ||
231 | e.KeyInput.Control = (in.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0; | ||
232 | e.KeyInput.Shift = (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0; | ||
233 | e.KeyInput.Key = EKEY_CODE(in.Event.KeyEvent.wVirtualKeyCode); | ||
234 | e.KeyInput.Char = in.Event.KeyEvent.uChar.UnicodeChar; | ||
235 | postEventFromUser(e); | ||
236 | break; | ||
237 | } | ||
238 | case MOUSE_EVENT: | ||
239 | { | ||
240 | SEvent e; | ||
241 | e.EventType = EET_MOUSE_INPUT_EVENT; | ||
242 | e.MouseInput.X = in.Event.MouseEvent.dwMousePosition.X; | ||
243 | e.MouseInput.Y = in.Event.MouseEvent.dwMousePosition.Y; | ||
244 | e.MouseInput.Wheel = 0.f; | ||
245 | e.MouseInput.ButtonStates = | ||
246 | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) ? EMBSM_LEFT : 0 ) | | ||
247 | ( (in.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) ? EMBSM_RIGHT : 0 ) | | ||
248 | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) ? EMBSM_MIDDLE : 0 ) | | ||
249 | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_3RD_BUTTON_PRESSED) ? EMBSM_EXTRA1 : 0 ) | | ||
250 | ( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_4TH_BUTTON_PRESSED) ? EMBSM_EXTRA2 : 0 ); | ||
251 | |||
252 | if (in.Event.MouseEvent.dwEventFlags & MOUSE_MOVED) | ||
253 | { | ||
254 | CursorControl->setPosition(core::position2di(e.MouseInput.X, e.MouseInput.Y)); | ||
255 | |||
256 | // create mouse moved event | ||
257 | e.MouseInput.Event = EMIE_MOUSE_MOVED; | ||
258 | postEventFromUser(e); | ||
259 | } | ||
260 | |||
261 | if (in.Event.MouseEvent.dwEventFlags & MOUSE_WHEELED) | ||
262 | { | ||
263 | e.MouseInput.Event = EMIE_MOUSE_WHEEL; | ||
264 | e.MouseInput.Wheel = (in.Event.MouseEvent.dwButtonState & 0xFF000000) ? -1.0f : 1.0f; | ||
265 | postEventFromUser(e); | ||
266 | } | ||
267 | |||
268 | if ( (MouseButtonStates & EMBSM_LEFT) != (e.MouseInput.ButtonStates & EMBSM_LEFT) ) | ||
269 | { | ||
270 | e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_LEFT) ? EMIE_LMOUSE_PRESSED_DOWN : EMIE_LMOUSE_LEFT_UP; | ||
271 | postEventFromUser(e); | ||
272 | } | ||
273 | |||
274 | if ( (MouseButtonStates & EMBSM_RIGHT) != (e.MouseInput.ButtonStates & EMBSM_RIGHT) ) | ||
275 | { | ||
276 | e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_RIGHT) ? EMIE_RMOUSE_PRESSED_DOWN : EMIE_RMOUSE_LEFT_UP; | ||
277 | postEventFromUser(e); | ||
278 | } | ||
279 | |||
280 | if ( (MouseButtonStates & EMBSM_MIDDLE) != (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ) | ||
281 | { | ||
282 | e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ? EMIE_MMOUSE_PRESSED_DOWN : EMIE_MMOUSE_LEFT_UP; | ||
283 | postEventFromUser(e); | ||
284 | } | ||
285 | |||
286 | // save current button states | ||
287 | MouseButtonStates = e.MouseInput.ButtonStates; | ||
288 | |||
289 | break; | ||
290 | } | ||
291 | case WINDOW_BUFFER_SIZE_EVENT: | ||
292 | VideoDriver->OnResize( | ||
293 | core::dimension2d<u32>(in.Event.WindowBufferSizeEvent.dwSize.X, | ||
294 | in.Event.WindowBufferSizeEvent.dwSize.Y)); | ||
295 | break; | ||
296 | case FOCUS_EVENT: | ||
297 | IsWindowFocused = (in.Event.FocusEvent.bSetFocus == TRUE); | ||
298 | break; | ||
299 | default: | ||
300 | break; | ||
301 | } | ||
302 | GetNumberOfConsoleInputEvents(WindowsSTDIn, &count); | ||
303 | } | ||
304 | |||
305 | // set input mode | ||
306 | SetConsoleMode(WindowsSTDIn, oldMode); | ||
307 | #else | ||
308 | // todo: keyboard input from terminal in raw mode | ||
309 | #endif | ||
310 | |||
311 | return !Close; | ||
312 | } | ||
313 | |||
314 | //! Cause the device to temporarily pause execution and let other processes to run | ||
315 | // This should bring down processor usage without major performance loss for Irrlicht | ||
316 | void CIrrDeviceConsole::yield() | ||
317 | { | ||
318 | #ifdef _IRR_WINDOWS_API_ | ||
319 | Sleep(1); | ||
320 | #else | ||
321 | struct timespec ts = {0,0}; | ||
322 | nanosleep(&ts, NULL); | ||
323 | #endif | ||
324 | } | ||
325 | |||
326 | //! Pause execution and let other processes to run for a specified amount of time. | ||
327 | void CIrrDeviceConsole::sleep(u32 timeMs, bool pauseTimer) | ||
328 | { | ||
329 | const bool wasStopped = Timer ? Timer->isStopped() : true; | ||
330 | |||
331 | #ifdef _IRR_WINDOWS_API_ | ||
332 | Sleep(timeMs); | ||
333 | #else | ||
334 | struct timespec ts; | ||
335 | ts.tv_sec = (time_t) (timeMs / 1000); | ||
336 | ts.tv_nsec = (long) (timeMs % 1000) * 1000000; | ||
337 | |||
338 | if (pauseTimer && !wasStopped) | ||
339 | Timer->stop(); | ||
340 | |||
341 | nanosleep(&ts, NULL); | ||
342 | #endif | ||
343 | |||
344 | if (pauseTimer && !wasStopped) | ||
345 | Timer->start(); | ||
346 | } | ||
347 | |||
348 | //! sets the caption of the window | ||
349 | void CIrrDeviceConsole::setWindowCaption(const wchar_t* text) | ||
350 | { | ||
351 | #ifdef _IRR_WINDOWS_NT_CONSOLE_ | ||
352 | SetConsoleTitleW(text); | ||
353 | #endif | ||
354 | } | ||
355 | |||
356 | //! returns if window is active. if not, nothing need to be drawn | ||
357 | bool CIrrDeviceConsole::isWindowActive() const | ||
358 | { | ||
359 | // there is no window, but we always assume it is active | ||
360 | return true; | ||
361 | } | ||
362 | |||
363 | //! returns if window has focus | ||
364 | bool CIrrDeviceConsole::isWindowFocused() const | ||
365 | { | ||
366 | return IsWindowFocused; | ||
367 | } | ||
368 | |||
369 | //! returns if window is minimized | ||
370 | bool CIrrDeviceConsole::isWindowMinimized() const | ||
371 | { | ||
372 | return false; | ||
373 | } | ||
374 | |||
375 | //! presents a surface in the client area | ||
376 | bool CIrrDeviceConsole::present(video::IImage* surface, void* windowId, core::rect<s32>* src) | ||
377 | { | ||
378 | |||
379 | if (surface) | ||
380 | { | ||
381 | for (u32 y=0; y < surface->getDimension().Height; ++y) | ||
382 | { | ||
383 | for (u32 x=0; x< surface->getDimension().Width; ++x) | ||
384 | { | ||
385 | // get average pixel | ||
386 | u32 avg = surface->getPixel(x,y).getAverage() * (ASCIIArtCharsCount-1); | ||
387 | avg /= 255; | ||
388 | OutputBuffer[y] [x] = ASCIIArtChars[avg]; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | #ifdef _IRR_USE_CONSOLE_FONT_ | ||
393 | for (u32 i=0; i< Text.size(); ++i) | ||
394 | { | ||
395 | s32 y = Text[i].Pos.Y; | ||
396 | |||
397 | if ( y < (s32)OutputBuffer.size() && y > 0) | ||
398 | for (u32 c=0; c < Text[i].Text.size() && c + Text[i].Pos.X < OutputBuffer[y].size(); ++c) | ||
399 | //if (Text[i].Text[c] != ' ') | ||
400 | OutputBuffer[y] [c+Text[i].Pos.X] = Text[i].Text[c]; | ||
401 | } | ||
402 | Text.clear(); | ||
403 | #endif | ||
404 | |||
405 | // draw output | ||
406 | for (u32 y=0; y<OutputBuffer.size(); ++y) | ||
407 | { | ||
408 | setTextCursorPos(0,y); | ||
409 | fprintf(OutFile, "%s", OutputBuffer[y].c_str()); | ||
410 | } | ||
411 | return surface != 0; | ||
412 | } | ||
413 | |||
414 | //! notifies the device that it should close itself | ||
415 | void CIrrDeviceConsole::closeDevice() | ||
416 | { | ||
417 | // return false next time we run() | ||
418 | Close = true; | ||
419 | } | ||
420 | |||
421 | |||
422 | //! Sets if the window should be resizable in windowed mode. | ||
423 | void CIrrDeviceConsole::setResizable(bool resize) | ||
424 | { | ||
425 | // do nothing | ||
426 | } | ||
427 | |||
428 | |||
429 | //! Minimize the window. | ||
430 | void CIrrDeviceConsole::minimizeWindow() | ||
431 | { | ||
432 | // do nothing | ||
433 | } | ||
434 | |||
435 | |||
436 | //! Maximize window | ||
437 | void CIrrDeviceConsole::maximizeWindow() | ||
438 | { | ||
439 | // do nothing | ||
440 | } | ||
441 | |||
442 | |||
443 | //! Restore original window size | ||
444 | void CIrrDeviceConsole::restoreWindow() | ||
445 | { | ||
446 | // do nothing | ||
447 | } | ||
448 | |||
449 | |||
450 | void CIrrDeviceConsole::setTextCursorPos(s16 x, s16 y) | ||
451 | { | ||
452 | #ifdef _IRR_WINDOWS_NT_CONSOLE_ | ||
453 | // move WinNT cursor | ||
454 | COORD Position; | ||
455 | Position.X = x; | ||
456 | Position.Y = y; | ||
457 | SetConsoleCursorPosition(WindowsSTDOut, Position); | ||
458 | #elif defined(_IRR_VT100_CONSOLE_) | ||
459 | // send escape code | ||
460 | fprintf(OutFile, "%c[%d;%dH", 27, y, x); | ||
461 | #else | ||
462 | // not implemented | ||
463 | #endif | ||
464 | } | ||
465 | |||
466 | void CIrrDeviceConsole::addPostPresentText(s16 X, s16 Y, const wchar_t *text) | ||
467 | { | ||
468 | SPostPresentText p; | ||
469 | p.Text = text; | ||
470 | p.Pos.X = X; | ||
471 | p.Pos.Y = Y; | ||
472 | Text.push_back(p); | ||
473 | } | ||
474 | |||
475 | } // end namespace irr | ||
476 | |||
477 | #endif // _IRR_COMPILE_WITH_CONSOLE_DEVICE_ | ||