1 // Copyright (C) 2005-2006 Etienne Petitjean
2 // Copyright (C) 2007-2012 Christian Stehno
3 // This file is part of the "Irrlicht Engine".
4 // For conditions of distribution and use, see copyright notice in Irrlicht.h
5 
6 #ifndef __C_IRR_DEVICE_MACOSX_H_INCLUDED__
7 #define __C_IRR_DEVICE_MACOSX_H_INCLUDED__
8 
9 #include "IrrCompileConfig.h"
10 
11 #ifdef _IRR_COMPILE_WITH_OSX_DEVICE_
12 
13 #include "../CIrrDeviceStub.h"
14 #include "IrrlichtDevice.h"
15 #include "../IImagePresenter.h"
16 #include "IGUIEnvironment.h"
17 #include "ICursorControl.h"
18 
19 #define GL_SILENCE_DEPRECATION
20 #include <OpenGL/OpenGL.h>
21 #include <map>
22 
23 #ifndef __OBJC__
24 class NSWindow;
25 class NSOpenGLContext;
26 class NSBitmapImageRep;
27 #endif
28 
29 namespace irr
30 {
31 	class CIrrDeviceMacOSX : public CIrrDeviceStub, video::IImagePresenter
32 	{
33 	public:
34 
35 		//! constructor
36 		CIrrDeviceMacOSX(const SIrrlichtCreationParameters& params);
37 
38 		//! destructor
39 		virtual ~CIrrDeviceMacOSX();
40 
41 		//! runs the device. Returns false if device wants to be deleted
42 		virtual bool run();
43 
44 		//! Cause the device to temporarily pause execution and let other processes to run
45 		// This should bring down processor usage without major performance loss for Irrlicht
46 		virtual void yield();
47 
48 		//! Pause execution and let other processes to run for a specified amount of time.
49 		virtual void sleep(u32 timeMs, bool pauseTimer);
50 
51 		//! sets the caption of the window
52 		virtual void setWindowCaption(const wchar_t* text);
53 
54 		//! sets the class of the window
setWindowClass(const char * text)55 		virtual void setWindowClass(const char* text) {}
56 
57 		//! returns if window is active. if not, nothing need to be drawn
58 		virtual bool isWindowActive() const;
59 
60 		//! Checks if the Irrlicht window has focus
61 		virtual bool isWindowFocused() const;
62 
63 		//! Checks if the Irrlicht window is minimized
64 		virtual bool isWindowMinimized() const;
65 
66 		//! presents a surface in the client area
67 		virtual bool present(video::IImage* surface, void* windowId=0, core::rect<s32>* src=0 );
68 
69 		//! notifies the device that it should close itself
70 		virtual void closeDevice();
71 
72 		//! Sets if the window should be resizable in windowed mode.
73 		virtual void setResizable(bool resize);
74 
75 		//! Returns true if the window is resizable, false if not
76 		virtual bool isResizable() const;
77 
78 		//! Minimizes the window if possible
79 		virtual void minimizeWindow();
80 
81 		//! Maximizes the window if possible.
82 		virtual void maximizeWindow();
83 
84 		//! Restore the window to normal size if possible.
85 		virtual void restoreWindow();
86 
87 		//! Move window to requested position
88 		virtual bool moveWindow(int x, int y);
89 
90 		//! Get current window position.
91 		virtual bool getWindowPosition(int* x, int* y);
92 
93 		//! Activate any joysticks, and generate events for them.
94 		virtual bool activateJoysticks(core::array<SJoystickInfo> & joystickInfo);
95 
96 		//! \return Returns a pointer to a list with all video modes
97 		//! supported by the gfx adapter.
98 		virtual video::IVideoModeList* getVideoModeList();
99 
100 		//! Get the device type
getType()101 		virtual E_DEVICE_TYPE getType() const
102 		{
103 				return EIDT_OSX;
104 		}
105 
106 		void flush();
107 		void setMouseLocation(int x, int y);
108 		void setResize(int width, int height);
109 		void setCursorVisible(bool visible);
110 
111 	private:
112 
113 		//! create the driver
114 		void createDriver();
115 
116 		//! Implementation of the macos x cursor control
117 		class CCursorControl : public gui::ICursorControl
118 		{
119 		public:
120 
CCursorControl(const core::dimension2d<u32> & wsize,CIrrDeviceMacOSX * device)121 			CCursorControl(const core::dimension2d<u32>& wsize, CIrrDeviceMacOSX *device)
122 				: WindowSize(wsize), IsVisible(true), InvWindowSize(0.0f, 0.0f), Device(device), UseReferenceRect(false)
123 			{
124 				CursorPos.X = CursorPos.Y = 0;
125 				if (WindowSize.Width!=0)
126 					InvWindowSize.Width = 1.0f / WindowSize.Width;
127 				if (WindowSize.Height!=0)
128 					InvWindowSize.Height = 1.0f / WindowSize.Height;
129 			}
130 
131 			//! Changes the visible state of the mouse cursor.
setVisible(bool visible)132 			virtual void setVisible(bool visible)
133 			{
134 				IsVisible = visible;
135 				Device->setCursorVisible(visible);
136 			}
137 
138 			//! Returns if the cursor is currently visible.
isVisible()139 			virtual bool isVisible() const
140 			{
141 				return IsVisible;
142 			}
143 
144 			//! Sets the new position of the cursor.
setPosition(const core::position2d<f32> & pos)145 			virtual void setPosition(const core::position2d<f32> &pos)
146 			{
147 				setPosition(pos.X, pos.Y);
148 			}
149 
150 			//! Sets the new position of the cursor.
setPosition(f32 x,f32 y)151 			virtual void setPosition(f32 x, f32 y)
152 			{
153 				setPosition((s32)(x*WindowSize.Width), (s32)(y*WindowSize.Height));
154 			}
155 
156 			//! Sets the new position of the cursor.
setPosition(const core::position2d<s32> & pos)157 			virtual void setPosition(const core::position2d<s32> &pos)
158 			{
159 				if (CursorPos.X != pos.X || CursorPos.Y != pos.Y)
160 					setPosition(pos.X, pos.Y);
161 			}
162 
163 			//! Sets the new position of the cursor.
setPosition(s32 x,s32 y)164 			virtual void setPosition(s32 x, s32 y)
165 			{
166 				if (UseReferenceRect)
167 				{
168 					Device->setMouseLocation(ReferenceRect.UpperLeftCorner.X + x, ReferenceRect.UpperLeftCorner.Y + y);
169 				}
170 				else
171 				{
172 					Device->setMouseLocation(x,y);
173 				}
174 			}
175 
176 			//! Returns the current position of the mouse cursor.
getPosition()177 			virtual const core::position2d<s32>& getPosition()
178 			{
179 				return CursorPos;
180 			}
181 
182 			//! Returns the current position of the mouse cursor.
getRelativePosition()183 			virtual core::position2d<f32> getRelativePosition()
184 			{
185 				if (!UseReferenceRect)
186 				{
187 					return core::position2d<f32>(CursorPos.X * InvWindowSize.Width,
188 						CursorPos.Y * InvWindowSize.Height);
189 				}
190 
191 				return core::position2d<f32>(CursorPos.X / (f32)ReferenceRect.getWidth(),
192 						CursorPos.Y / (f32)ReferenceRect.getHeight());
193 			}
194 
195 			//! Sets an absolute reference rect for calculating the cursor position.
196 			virtual void setReferenceRect(core::rect<s32>* rect=0)
197 			{
198 				if (rect)
199 				{
200 					ReferenceRect = *rect;
201 					UseReferenceRect = true;
202 
203 					// prevent division through zero and uneven sizes
204 
205 					if (!ReferenceRect.getHeight() || ReferenceRect.getHeight()%2)
206 						ReferenceRect.LowerRightCorner.Y += 1;
207 
208 					if (!ReferenceRect.getWidth() || ReferenceRect.getWidth()%2)
209 						ReferenceRect.LowerRightCorner.X += 1;
210 				}
211 				else
212 					UseReferenceRect = false;
213 			}
214 
215 			//! Updates the internal cursor position
updateInternalCursorPosition(int x,int y)216 			void updateInternalCursorPosition(int x,int y)
217 			{
218 				CursorPos.X = x;
219 				CursorPos.Y = y;
220 			}
221 
222 		private:
223 
224 			core::position2d<s32> CursorPos;
225 			core::dimension2d<s32> WindowSize;
226 			core::dimension2d<float> InvWindowSize;
227 			core::rect<s32> ReferenceRect;
228 			CIrrDeviceMacOSX *Device;
229 			bool IsVisible;
230 			bool UseReferenceRect;
231 		};
232 
233 		bool createWindow();
234 		void initKeycodes();
235 		void storeMouseLocation();
236 		void postMouseEvent(void *event, irr::SEvent &ievent);
237 		void postKeyEvent(void *event, irr::SEvent &ievent, bool pressed);
238 		void charToKeys(void* str, irr::u32& character, irr::u32& key_code);
239 		void pollJoysticks();
240 
241 		NSWindow *Window;
242 		CGLContextObj CGLContext;
243 		NSOpenGLContext *OGLContext;
244 		NSBitmapImageRep *SoftwareDriverTarget;
245 		std::map<int,int> KeyCodes;
246 		int DeviceWidth;
247 		int DeviceHeight;
248 		int ScreenWidth;
249 		int ScreenHeight;
250 		u32 MouseButtonStates;
251         u32 SoftwareRendererType;
252         bool IsFullscreen;
253 		bool IsActive;
254 		bool IsShiftDown;
255 		bool IsControlDown;
256 		bool IsResizable;
257 	};
258 
259 
260 } // end namespace irr
261 
262 #endif // _IRR_COMPILE_WITH_OSX_DEVICE_
263 #endif // __C_IRR_DEVICE_MACOSX_H_INCLUDED__
264 
265