Retour
Version Originale

./aip/1.8aipmod/source/Irrlicht/CIrrDeviceConsole.cpp :


// Copyright (C) 2009-2011 Gaz Davidson

// This file is part of the "Irrlicht Engine".

// For conditions of distribution and use, see copyright notice in irrlicht.h


#include "CIrrDeviceConsole.h"

#ifdef _IRR_COMPILE_WITH_CONSOLE_DEVICE_

#include "os.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"

// to close the device on terminate signal

irr::CIrrDeviceConsole *DeviceToClose;

#ifdef _IRR_WINDOWS_NT_CONSOLE_
// Callback for Windows

BOOL WINAPI ConsoleHandler(DWORD CEvent)
{
    switch(CEvent)
    {
    case CTRL_C_EVENT:
		irr::os::Printer::log("Closing console device", "CTRL+C");
		break;
	case CTRL_BREAK_EVENT:
		irr::os::Printer::log("Closing console device", "CTRL+Break");
		break;
    case CTRL_CLOSE_EVENT:
		irr::os::Printer::log("Closing console device", "User closed console");
		break;
    case CTRL_LOGOFF_EVENT:
		irr::os::Printer::log("Closing console device", "User is logging off");
		break;
    case CTRL_SHUTDOWN_EVENT:
		irr::os::Printer::log("Closing console device", "Computer shutting down");
		break;
    }
	DeviceToClose->closeDevice();
    return TRUE;
}
#elif defined(_IRR_POSIX_API_)
// sigterm handler

#include <signal.h>

void sighandler(int sig)
{
	irr::core::stringc code = "Signal ";
	code += sig;
	code += " received";
	irr::os::Printer::log("Closing console device", code.c_str());

	DeviceToClose->closeDevice();
}
#endif

namespace irr
{

const c8 ASCIIArtChars[] = " .,'~:;!+>=icopjtJY56SB8XDQKHNWM"; //MWNHKQDX8BS65YJtjpoci=+>!;:~',. ";

const u16 ASCIIArtCharsCount = 32;

//const c8 ASCIIArtChars[] = " \xb0\xb1\xf9\xb2\xdb";

//const u16 ASCIIArtCharsCount = 5;


//! constructor

CIrrDeviceConsole::CIrrDeviceConsole(const SIrrlichtCreationParameters& params)
  : CIrrDeviceStub(params), IsWindowFocused(true), ConsoleFont(0), OutFile(stdout)
{
	DeviceToClose = this;

#ifdef _IRR_WINDOWS_NT_CONSOLE_
	MouseButtonStates = 0;

	WindowsSTDIn  = GetStdHandle(STD_INPUT_HANDLE);
	WindowsSTDOut = GetStdHandle(STD_OUTPUT_HANDLE);
	PCOORD Dimensions = 0;

	if (CreationParams.Fullscreen)
	{
		if (SetConsoleDisplayMode(WindowsSTDOut, CONSOLE_FULLSCREEN_MODE, Dimensions))
		{
			CreationParams.WindowSize.Width = Dimensions->X;
			CreationParams.WindowSize.Width = Dimensions->Y;
		}
	}
	else
	{
		COORD ConsoleSize;
		ConsoleSize.X = CreationParams.WindowSize.Width;
		ConsoleSize.X = CreationParams.WindowSize.Height;
		SetConsoleScreenBufferSize(WindowsSTDOut, ConsoleSize);
	}

	// catch windows close/break signals

	SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE);

#elif defined(_IRR_POSIX_API_)
	// catch other signals

	signal(SIGABRT, &sighandler);
	signal(SIGTERM, &sighandler);
	signal(SIGINT,  &sighandler);

	// set output stream

	if (params.WindowId)
		OutFile = (FILE*)(params.WindowId);
#endif

#ifdef _IRR_VT100_CONSOLE_
	// reset terminal

	fprintf(OutFile, "%cc", 27);
	// disable line wrapping

	fprintf(OutFile, "%c[7l", 27);
#endif

	switch (params.DriverType)
	{
	case video::EDT_SOFTWARE:
		#ifdef _IRR_COMPILE_WITH_SOFTWARE_
		VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this);
		#else
		os::Printer::log("Software driver was not compiled in.", ELL_ERROR);
		#endif
		break;

	case video::EDT_BURNINGSVIDEO:
		#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
		VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this);
		#else
		os::Printer::log("Burning's Video driver was not compiled in.", ELL_ERROR);
		#endif
		break;

	case video::EDT_DIRECT3D8:
	case video::EDT_DIRECT3D9:
	case video::EDT_OPENGL:
		os::Printer::log("The console device cannot use hardware drivers yet.", ELL_ERROR);
		break;
	case video::EDT_NULL:
		VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
		break;
	default:
		break;
	}

	// set up output buffer

	for (u32 y=0; y<CreationParams.WindowSize.Height; ++y)
	{
		core::stringc str;
		str.reserve(CreationParams.WindowSize.Width);
		for (u32 x=0; x<CreationParams.WindowSize.Width; ++x)
			str += " ";
		OutputBuffer.push_back(str);
	}


#ifdef _IRR_WINDOWS_NT_CONSOLE_
	CursorControl = new CCursorControl(CreationParams.WindowSize);
#endif

	if (VideoDriver)
	{
		createGUIAndScene();
#ifdef _IRR_USE_CONSOLE_FONT_
		if (GUIEnvironment)
		{
			ConsoleFont = new gui::CGUIConsoleFont(this);
			gui::IGUISkin *skin = GUIEnvironment->getSkin();
			if (skin)
			{
				for (u32 i=0; i < gui::EGDF_COUNT; ++i)
					skin->setFont(ConsoleFont, gui::EGUI_DEFAULT_FONT(i));
			}
		}
#endif
	}
}

//! destructor

CIrrDeviceConsole::~CIrrDeviceConsole()
{
	// GUI and scene are dropped in the stub

	if (CursorControl)
	{
		CursorControl->drop();
		CursorControl = 0;
	}
	if (ConsoleFont)
	{
		ConsoleFont->drop();
		ConsoleFont = 0;
	}
#ifdef _IRR_VT100_CONSOLE_
	// reset terminal

	fprintf(OutFile, "%cc", 27);
#endif
}

//! runs the device. Returns false if device wants to be deleted

bool CIrrDeviceConsole::run()
{
	// increment timer

	os::Timer::tick();

	// process Windows console input

#ifdef _IRR_WINDOWS_NT_CONSOLE_

	INPUT_RECORD in;
	DWORD        oldMode;
	DWORD        count, waste;

	// get old input mode

	GetConsoleMode(WindowsSTDIn, &oldMode);
	SetConsoleMode(WindowsSTDIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);

	GetNumberOfConsoleInputEvents(WindowsSTDIn, &count);

	// read keyboard and mouse input

	while (count)
	{
		ReadConsoleInput(WindowsSTDIn, &in, 1, &waste );
		switch(in.EventType)
		{
		case KEY_EVENT:
		{
			SEvent e;
			e.EventType            = EET_KEY_INPUT_EVENT;
			e.KeyInput.PressedDown = (in.Event.KeyEvent.bKeyDown == TRUE);
			e.KeyInput.Control     = (in.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0;
			e.KeyInput.Shift       = (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) != 0;
			e.KeyInput.Key         = EKEY_CODE(in.Event.KeyEvent.wVirtualKeyCode);
			e.KeyInput.Char        = in.Event.KeyEvent.uChar.UnicodeChar;
			postEventFromUser(e);
			break;
		}
		case MOUSE_EVENT:
		{
			SEvent e;
			e.EventType        = EET_MOUSE_INPUT_EVENT;
			e.MouseInput.X     = in.Event.MouseEvent.dwMousePosition.X;
			e.MouseInput.Y     = in.Event.MouseEvent.dwMousePosition.Y;
			e.MouseInput.Wheel = 0.f;
			e.MouseInput.ButtonStates =
				( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) ? EMBSM_LEFT   : 0 ) |
				( (in.Event.MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED)     ? EMBSM_RIGHT  : 0 ) |
				( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) ? EMBSM_MIDDLE : 0 ) |
				( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_3RD_BUTTON_PRESSED) ? EMBSM_EXTRA1 : 0 ) |
				( (in.Event.MouseEvent.dwButtonState & FROM_LEFT_4TH_BUTTON_PRESSED) ? EMBSM_EXTRA2 : 0 );

			if (in.Event.MouseEvent.dwEventFlags & MOUSE_MOVED)
			{
				CursorControl->setPosition(core::position2di(e.MouseInput.X, e.MouseInput.Y));

				// create mouse moved event

				e.MouseInput.Event = EMIE_MOUSE_MOVED;
				postEventFromUser(e);
			}

			if (in.Event.MouseEvent.dwEventFlags & MOUSE_WHEELED)
			{
				e.MouseInput.Event = EMIE_MOUSE_WHEEL;
				e.MouseInput.Wheel = (in.Event.MouseEvent.dwButtonState & 0xFF000000) ? -1.0f : 1.0f;
				postEventFromUser(e);
			}

			if ( (MouseButtonStates & EMBSM_LEFT) != (e.MouseInput.ButtonStates & EMBSM_LEFT) )
			{
				e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_LEFT) ? EMIE_LMOUSE_PRESSED_DOWN : EMIE_LMOUSE_LEFT_UP;
				postEventFromUser(e);
			}

			if ( (MouseButtonStates & EMBSM_RIGHT) != (e.MouseInput.ButtonStates & EMBSM_RIGHT) )
			{
				e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_RIGHT) ? EMIE_RMOUSE_PRESSED_DOWN : EMIE_RMOUSE_LEFT_UP;
				postEventFromUser(e);
			}

			if ( (MouseButtonStates & EMBSM_MIDDLE) != (e.MouseInput.ButtonStates & EMBSM_MIDDLE) )
			{
				e.MouseInput.Event = (e.MouseInput.ButtonStates & EMBSM_MIDDLE) ? EMIE_MMOUSE_PRESSED_DOWN : EMIE_MMOUSE_LEFT_UP;
				postEventFromUser(e);
			}

			// save current button states

			MouseButtonStates = e.MouseInput.ButtonStates;

			break;
		}
		case WINDOW_BUFFER_SIZE_EVENT:
			VideoDriver->OnResize(
				core::dimension2d<u32>(in.Event.WindowBufferSizeEvent.dwSize.X,
				                       in.Event.WindowBufferSizeEvent.dwSize.Y));
			break;
		case FOCUS_EVENT:
			IsWindowFocused = (in.Event.FocusEvent.bSetFocus == TRUE);
			break;
		default:
			break;
		}
		GetNumberOfConsoleInputEvents(WindowsSTDIn, &count);
	}

	// set input mode

	SetConsoleMode(WindowsSTDIn, oldMode);
#else
	// todo: keyboard input from terminal in raw mode

#endif

	return !Close;
}

//! Cause the device to temporarily pause execution and let other processes to run

// This should bring down processor usage without major performance loss for Irrlicht

void CIrrDeviceConsole::yield()
{
#ifdef _IRR_WINDOWS_API_
	Sleep(1);
#else
	struct timespec ts = {0,0};
	nanosleep(&ts, NULL);
#endif
}

//! Pause execution and let other processes to run for a specified amount of time.

void CIrrDeviceConsole::sleep(u32 timeMs, bool pauseTimer)
{
	const bool wasStopped = Timer ? Timer->isStopped() : true;

#ifdef _IRR_WINDOWS_API_
	Sleep(timeMs);
#else
	struct timespec ts;
	ts.tv_sec = (time_t) (timeMs / 1000);
	ts.tv_nsec = (long) (timeMs % 1000) * 1000000;

	if (pauseTimer && !wasStopped)
		Timer->stop();

	nanosleep(&ts, NULL);
#endif

	if (pauseTimer && !wasStopped)
		Timer->start();
}

//! sets the caption of the window

void CIrrDeviceConsole::setWindowCaption(const wchar_t* text)
{
#ifdef _IRR_WINDOWS_NT_CONSOLE_
	SetConsoleTitleW(text);
#endif
}

//! returns if window is active. if not, nothing need to be drawn

bool CIrrDeviceConsole::isWindowActive() const
{
	// there is no window, but we always assume it is active

	return true;
}

//! returns if window has focus

bool CIrrDeviceConsole::isWindowFocused() const
{
	return IsWindowFocused;
}

//! returns if window is minimized

bool CIrrDeviceConsole::isWindowMinimized() const
{
	return false;
}

//! presents a surface in the client area

bool CIrrDeviceConsole::present(video::IImage* surface, void* windowId, core::rect<s32>* src)
{

	if (surface)
	{
		for (u32 y=0; y < surface->getDimension().Height; ++y)
		{
			for (u32 x=0; x< surface->getDimension().Width; ++x)
			{
				// get average pixel

				u32 avg = surface->getPixel(x,y).getAverage() * (ASCIIArtCharsCount-1);
				avg /= 255;
				OutputBuffer[y] [x] = ASCIIArtChars[avg];
			}
		}
	}
#ifdef _IRR_USE_CONSOLE_FONT_
	for (u32 i=0; i< Text.size(); ++i)
	{
		s32 y = Text[i].Pos.Y;

		if ( y < (s32)OutputBuffer.size() && y > 0)
			for (u32 c=0; c < Text[i].Text.size() && c + Text[i].Pos.X < OutputBuffer[y].size(); ++c)
				//if (Text[i].Text[c] != ' ')

				OutputBuffer[y] [c+Text[i].Pos.X] = Text[i].Text[c];
	}
	Text.clear();
#endif

	// draw output

	for (u32 y=0; y<OutputBuffer.size(); ++y)
	{
		setTextCursorPos(0,y);
		fprintf(OutFile, "%s", OutputBuffer[y].c_str());
	}
	return surface != 0;
}

//! notifies the device that it should close itself

void CIrrDeviceConsole::closeDevice()
{
	// return false next time we run()

	Close = true;
}


//! Sets if the window should be resizable in windowed mode.

void CIrrDeviceConsole::setResizable(bool resize)
{
	// do nothing

}


//! Minimize the window.

void CIrrDeviceConsole::minimizeWindow()
{
	// do nothing

}


//! Maximize window

void CIrrDeviceConsole::maximizeWindow()
{
	// do nothing

}


//! Restore original window size

void CIrrDeviceConsole::restoreWindow()
{
	// do nothing

}


void CIrrDeviceConsole::setTextCursorPos(s16 x, s16 y)
{
#ifdef _IRR_WINDOWS_NT_CONSOLE_
	// move WinNT cursor

	COORD Position;
    Position.X = x;
    Position.Y = y;
    SetConsoleCursorPosition(WindowsSTDOut, Position);
#elif defined(_IRR_VT100_CONSOLE_)
	// send escape code

	fprintf(OutFile, "%c[%d;%dH", 27, y, x);
#else
	// not implemented

#endif
}

void CIrrDeviceConsole::addPostPresentText(s16 X, s16 Y, const wchar_t *text)
{
	SPostPresentText p;
	p.Text = text;
	p.Pos.X = X;
	p.Pos.Y = Y;
	Text.push_back(p);
}

} // end namespace irr


#endif // _IRR_COMPILE_WITH_CONSOLE_DEVICE_

Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
881 membres
1426 sujets
11116 messages
Dernier membre inscrit: Bidule
14 invités en ligne
Aucun membre connecté
RSS Feed