1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
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 "CIrrDeviceStub.h"
6 #include "ISceneManager.h"
7 #include "IEventReceiver.h"
8 #include "IFileSystem.h"
9 #include "IGUIEnvironment.h"
10 #include "os.h"
11 #include "IrrCompileConfig.h"
12 #include "CTimer.h"
13 #include "CLogger.h"
14 #include "irrString.h"
15 #include "IRandomizer.h"
16 
17 namespace irr
18 {
19 //! constructor
CIrrDeviceStub(const SIrrlichtCreationParameters & params)20 CIrrDeviceStub::CIrrDeviceStub(const SIrrlichtCreationParameters& params)
21 : IrrlichtDevice(), VideoDriver(0), GUIEnvironment(0), SceneManager(0),
22 	Timer(0), CursorControl(0), UserReceiver(params.EventReceiver), Logger(0), Operator(0),
23 	Randomizer(0), FileSystem(0), InputReceivingSceneManager(0), CreationParams(params),
24 	Close(false), IsMousePressed(false)
25 {
26 	Timer = new CTimer(params.UsePerformanceTimer);
27 	if (os::Printer::Logger)
28 	{
29 		os::Printer::Logger->grab();
30 		Logger = (CLogger*)os::Printer::Logger;
31 		Logger->setReceiver(UserReceiver);
32 	}
33 	else
34 	{
35 		Logger = new CLogger(UserReceiver);
36 		os::Printer::Logger = Logger;
37 	}
38 	Logger->setLogLevel(CreationParams.LoggingLevel);
39 
40 	os::Printer::Logger = Logger;
41 	Randomizer = createDefaultRandomizer();
42 
43     // If the user supplies a file system, use it instead of creating a new one
44     if (params.FileSystem)
45     {
46         FileSystem = params.FileSystem;
47         FileSystem->grab();
48     }
49     else
50         FileSystem = io::createFileSystem();
51     core::stringc s = "..:: Antarctica Rendering Engine ";
52 	s.append("2.0 ::..");
53 	os::Printer::log(s.c_str(), ELL_INFORMATION);
54 
55 	checkVersion(params.SDK_version_do_not_use);
56 }
57 
58 
~CIrrDeviceStub()59 CIrrDeviceStub::~CIrrDeviceStub()
60 {
61 	FileSystem->drop();
62 
63 	if (GUIEnvironment)
64 		GUIEnvironment->drop();
65 
66 	if (VideoDriver)
67 		VideoDriver->drop();
68 
69 	if (SceneManager)
70 		SceneManager->drop();
71 
72 	if (InputReceivingSceneManager)
73 		InputReceivingSceneManager->drop();
74 
75 	if (CursorControl)
76 		CursorControl->drop();
77 
78 	if (Operator)
79 		Operator->drop();
80 
81 	if (Randomizer)
82 		Randomizer->drop();
83 
84 	CursorControl = 0;
85 
86 	if (Timer)
87 		Timer->drop();
88 
89 	if (Logger->drop())
90 		os::Printer::Logger = 0;
91 }
92 
93 
createGUIAndScene()94 void CIrrDeviceStub::createGUIAndScene()
95 {
96 	#ifdef _IRR_COMPILE_WITH_GUI_
97 	// create gui environment
98 	GUIEnvironment = gui::createGUIEnvironment(FileSystem, VideoDriver, Operator);
99 	#endif
100 
101 	// create Scene manager
102 	SceneManager = scene::createSceneManager(VideoDriver, FileSystem, CursorControl, GUIEnvironment);
103 
104 	setEventReceiver(UserReceiver);
105 }
106 
107 
108 //! returns the video driver
getVideoDriver()109 video::IVideoDriver* CIrrDeviceStub::getVideoDriver()
110 {
111 	return VideoDriver;
112 }
113 
114 
115 
116 //! return file system
getFileSystem()117 io::IFileSystem* CIrrDeviceStub::getFileSystem()
118 {
119 	return FileSystem;
120 }
121 
122 
123 
124 //! returns the gui environment
getGUIEnvironment()125 gui::IGUIEnvironment* CIrrDeviceStub::getGUIEnvironment()
126 {
127 	return GUIEnvironment;
128 }
129 
130 
131 
132 //! returns the scene manager
getSceneManager()133 scene::ISceneManager* CIrrDeviceStub::getSceneManager()
134 {
135 	return SceneManager;
136 }
137 
138 
139 //! \return Returns a pointer to the ITimer object. With it the
140 //! current Time can be received.
getTimer()141 ITimer* CIrrDeviceStub::getTimer()
142 {
143 	return Timer;
144 }
145 
146 
147 //! Returns the version of the engine.
getVersion() const148 const char* CIrrDeviceStub::getVersion() const
149 {
150 	return IRRLICHT_SDK_VERSION;
151 }
152 
153 //! \return Returns a pointer to the mouse cursor control interface.
getCursorControl()154 gui::ICursorControl* CIrrDeviceStub::getCursorControl()
155 {
156 	return CursorControl;
157 }
158 
159 
160 //! \return Returns a pointer to a list with all video modes supported
161 //! by the gfx adapter.
getVideoModeList()162 video::IVideoModeList* CIrrDeviceStub::getVideoModeList()
163 {
164 	return &VideoModeList;
165 }
166 
167 
168 //! checks version of sdk and prints warning if there might be a problem
checkVersion(const char * version)169 bool CIrrDeviceStub::checkVersion(const char* version)
170 {
171 	if (strcmp(getVersion(), version))
172 	{
173 		core::stringc w;
174 		w = "Warning: The library version of the Irrlicht Engine (";
175 		w += getVersion();
176 		w += ") does not match the version the application was compiled with (";
177 		w += version;
178 		w += "). This may cause problems.";
179 		os::Printer::log(w.c_str(), ELL_WARNING);
180 		_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
181 		return false;
182 	}
183 
184 	return true;
185 }
186 
187 
188 //! Compares to the last call of this function to return double and triple clicks.
checkSuccessiveClicks(s32 mouseX,s32 mouseY,EMOUSE_INPUT_EVENT inputEvent)189 u32 CIrrDeviceStub::checkSuccessiveClicks(s32 mouseX, s32 mouseY, EMOUSE_INPUT_EVENT inputEvent )
190 {
191 	const s32 MAX_MOUSEMOVE = 3;
192 
193 	irr::u32 clickTime = getTimer()->getRealTime();
194 
195 	if ( (clickTime-MouseMultiClicks.LastClickTime) < MouseMultiClicks.DoubleClickTime
196 		&& core::abs_(MouseMultiClicks.LastClick.X - mouseX ) <= MAX_MOUSEMOVE
197 		&& core::abs_(MouseMultiClicks.LastClick.Y - mouseY ) <= MAX_MOUSEMOVE
198 		&& MouseMultiClicks.CountSuccessiveClicks < 3
199 		&& MouseMultiClicks.LastMouseInputEvent == inputEvent
200 	   )
201 	{
202 		++MouseMultiClicks.CountSuccessiveClicks;
203 	}
204 	else
205 	{
206 		MouseMultiClicks.CountSuccessiveClicks = 1;
207 	}
208 
209 	MouseMultiClicks.LastMouseInputEvent = inputEvent;
210 	MouseMultiClicks.LastClickTime = clickTime;
211 	MouseMultiClicks.LastClick.X = mouseX;
212 	MouseMultiClicks.LastClick.Y = mouseY;
213 
214 	return MouseMultiClicks.CountSuccessiveClicks;
215 }
216 
217 
218 //! send the event to the right receiver
postEventFromUser(const SEvent & event)219 bool CIrrDeviceStub::postEventFromUser(const SEvent& event)
220 {
221 	bool absorbed = false;
222 
223 	if (UserReceiver)
224 		absorbed = UserReceiver->OnEvent(event);
225 
226 	if (!absorbed && GUIEnvironment)
227 		absorbed = GUIEnvironment->postEventFromUser(event);
228 
229 	scene::ISceneManager* inputReceiver = InputReceivingSceneManager;
230 	if (!inputReceiver)
231 		inputReceiver = SceneManager;
232 
233 	if (!absorbed && inputReceiver)
234 		absorbed = inputReceiver->postEventFromUser(event);
235 
236 	_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
237 	return absorbed;
238 }
239 
240 
241 //! Sets a new event receiver to receive events
setEventReceiver(IEventReceiver * receiver)242 void CIrrDeviceStub::setEventReceiver(IEventReceiver* receiver)
243 {
244 	UserReceiver = receiver;
245 	Logger->setReceiver(receiver);
246 	if (GUIEnvironment)
247 		GUIEnvironment->setUserEventReceiver(receiver);
248 }
249 
250 
251 //! Returns poinhter to the current event receiver. Returns 0 if there is none.
getEventReceiver()252 IEventReceiver* CIrrDeviceStub::getEventReceiver()
253 {
254 	return UserReceiver;
255 }
256 
257 
258 //! \return Returns a pointer to the logger.
getLogger()259 ILogger* CIrrDeviceStub::getLogger()
260 {
261 	return Logger;
262 }
263 
264 
265 //! Returns the operation system opertator object.
getOSOperator()266 IOSOperator* CIrrDeviceStub::getOSOperator()
267 {
268 	return Operator;
269 }
270 
271 
272 //! Provides access to the engine's currently set randomizer.
getRandomizer() const273 IRandomizer* CIrrDeviceStub::getRandomizer() const
274 {
275 	return Randomizer;
276 }
277 
278 //! Sets a new randomizer.
setRandomizer(IRandomizer * r)279 void CIrrDeviceStub::setRandomizer(IRandomizer* r)
280 {
281 	if (r!=Randomizer)
282 	{
283 		if (Randomizer)
284 			Randomizer->drop();
285 		Randomizer=r;
286 		if (Randomizer)
287 			Randomizer->grab();
288 	}
289 }
290 
291 namespace
292 {
293 	struct SDefaultRandomizer : public IRandomizer
294 	{
resetirr::__anonb4fdc4300111::SDefaultRandomizer295 		virtual void reset(s32 value=0x0f0f0f0f)
296 		{
297 			os::Randomizer::reset(value);
298 		}
299 
randirr::__anonb4fdc4300111::SDefaultRandomizer300 		virtual s32 rand() const
301 		{
302 			return os::Randomizer::rand();
303 		}
304 
frandirr::__anonb4fdc4300111::SDefaultRandomizer305 		virtual f32 frand() const
306 		{
307 			return os::Randomizer::frand();
308 		}
309 
randMaxirr::__anonb4fdc4300111::SDefaultRandomizer310 		virtual s32 randMax() const
311 		{
312 			return os::Randomizer::randMax();
313 		}
314 	};
315 }
316 
317 //! Creates a new default randomizer.
createDefaultRandomizer() const318 IRandomizer* CIrrDeviceStub::createDefaultRandomizer() const
319 {
320 	IRandomizer* r = new SDefaultRandomizer();
321 	if (r)
322 		r->reset();
323 	return r;
324 }
325 
326 
327 //! Sets the input receiving scene manager.
setInputReceivingSceneManager(scene::ISceneManager * sceneManager)328 void CIrrDeviceStub::setInputReceivingSceneManager(scene::ISceneManager* sceneManager)
329 {
330     if (sceneManager)
331         sceneManager->grab();
332 	if (InputReceivingSceneManager)
333 		InputReceivingSceneManager->drop();
334 
335 	InputReceivingSceneManager = sceneManager;
336 }
337 
338 
339 //! Checks if the window is running in fullscreen mode
isFullscreen() const340 bool CIrrDeviceStub::isFullscreen() const
341 {
342 	return CreationParams.Fullscreen;
343 }
344 
345 
346 //! returns color format
getColorFormat() const347 video::ECOLOR_FORMAT CIrrDeviceStub::getColorFormat() const
348 {
349 	return video::ECF_R5G6B5;
350 }
351 
352 //! No-op in this implementation
activateJoysticks(core::array<SJoystickInfo> & joystickInfo)353 bool CIrrDeviceStub::activateJoysticks(core::array<SJoystickInfo> & joystickInfo)
354 {
355 	return false;
356 }
357 
358 /*!
359 */
calculateGammaRamp(u16 * ramp,f32 gamma,f32 relativebrightness,f32 relativecontrast)360 void CIrrDeviceStub::calculateGammaRamp ( u16 *ramp, f32 gamma, f32 relativebrightness, f32 relativecontrast )
361 {
362 	s32 i;
363 	s32 value;
364 	s32 rbright = (s32) ( relativebrightness * (65535.f / 4 ) );
365 	f32 rcontrast = 1.f / (255.f - ( relativecontrast * 127.5f ) );
366 
367 	gamma = gamma > 0.f ? 1.0f / gamma : 0.f;
368 
369 	for ( i = 0; i < 256; ++i )
370 	{
371 		value = (s32)(pow( rcontrast * i, gamma)*65535.f + 0.5f );
372 		ramp[i] = (u16) core::s32_clamp ( value + rbright, 0, 65535 );
373 	}
374 
375 }
376 
calculateGammaFromRamp(f32 & gamma,const u16 * ramp)377 void CIrrDeviceStub::calculateGammaFromRamp ( f32 &gamma, const u16 *ramp )
378 {
379 	/* The following is adapted from a post by Garrett Bass on OpenGL
380 	Gamedev list, March 4, 2000.
381 	*/
382 	f32 sum = 0.0;
383 	s32 i, count = 0;
384 
385 	gamma = 1.0;
386 	for ( i = 1; i < 256; ++i ) {
387 		if ( (ramp[i] != 0) && (ramp[i] != 65535) ) {
388 			f32 B = (f32)i / 256.f;
389 			f32 A = ramp[i] / 65535.f;
390 			sum += (f32) ( logf(A) / logf(B) );
391 			count++;
392 		}
393 	}
394 	if ( count && sum ) {
395 		gamma = 1.0f / (sum / count);
396 	}
397 
398 }
399 
400 //! Set the current Gamma Value for the Display
setGammaRamp(f32 red,f32 green,f32 blue,f32 brightness,f32 contrast)401 bool CIrrDeviceStub::setGammaRamp( f32 red, f32 green, f32 blue, f32 brightness, f32 contrast )
402 {
403 	return false;
404 }
405 
406 //! Get the current Gamma Value for the Display
getGammaRamp(f32 & red,f32 & green,f32 & blue,f32 & brightness,f32 & contrast)407 bool CIrrDeviceStub::getGammaRamp( f32 &red, f32 &green, f32 &blue, f32 &brightness, f32 &contrast )
408 {
409 	return false;
410 }
411 
412 //! Set the maximal elapsed time between 2 clicks to generate doubleclicks for the mouse. It also affects tripleclick behavior.
setDoubleClickTime(u32 timeMs)413 void CIrrDeviceStub::setDoubleClickTime( u32 timeMs )
414 {
415 	MouseMultiClicks.DoubleClickTime = timeMs;
416 }
417 
418 //! Get the maximal elapsed time between 2 clicks to generate double- and tripleclicks for the mouse.
getDoubleClickTime() const419 u32 CIrrDeviceStub::getDoubleClickTime() const
420 {
421 	return MouseMultiClicks.DoubleClickTime;
422 }
423 
424 //! Remove all messages pending in the system message loop
clearSystemMessages()425 void CIrrDeviceStub::clearSystemMessages()
426 {
427 }
428 
simulateMouse(const SEvent & event,core::position2d<s32> & mouse_pos)429 void CIrrDeviceStub::simulateMouse(const SEvent& event, core::position2d<s32>& mouse_pos)
430 {
431 	if (!CursorControl) return;
432 	CursorControl->setPosition(mouse_pos);
433 
434 	SEvent irrevent;
435 	bool send_event = true;
436 
437 	switch (event.TouchInput.Event)
438 	{
439 	case ETIE_PRESSED_DOWN:
440 		irrevent.MouseInput.Event = EMIE_LMOUSE_PRESSED_DOWN;
441 		IsMousePressed = true;
442 		break;
443 	case ETIE_LEFT_UP:
444 		irrevent.MouseInput.Event = EMIE_LMOUSE_LEFT_UP;
445 		IsMousePressed = false;
446 		break;
447 	case ETIE_MOVED:
448 		irrevent.MouseInput.Event = EMIE_MOUSE_MOVED;
449 		break;
450 	default:
451 		send_event = false;
452 		break;
453 	}
454 
455 	if (send_event)
456 	{
457 		irrevent.MouseInput.Control = false;
458 		irrevent.MouseInput.Shift = false;
459 		irrevent.MouseInput.ButtonStates = IsMousePressed ? irr::EMBSM_LEFT : 0;
460 		irrevent.EventType = EET_MOUSE_INPUT_EVENT;
461 		irrevent.MouseInput.X = mouse_pos.X;
462 		irrevent.MouseInput.Y = mouse_pos.Y + getMovedHeight();
463 		postEventFromUser(irrevent);
464 	}
465 }
466 
467 } // end namespace irr
468 
469