Add iOSDevice and EAGLManager

This commit is contained in:
Benau 2019-07-13 13:44:03 +08:00
parent c7308b82b0
commit 8510ebfb27
20 changed files with 1516 additions and 196 deletions

View File

@ -47,6 +47,11 @@ if (IOS)
ADD_DEFINITIONS(-DMOBILE_STK)
ADD_DEFINITIONS(-DIOS_STK)
option(USE_GLES2 "Use OpenGL ES2 renderer" ON)
set(MACOSX_BUNDLE_ICON_FILE ${PROJECT_SOURCE_DIR}/data/supertuxkart.icns)
set(MACOSX_BUNDLE_BUNDLE_NAME "SuperTuxKart")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "org.supertuxkart.stk")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_VERSION ${IOS_BUILD_VERSION})
endif()
if((UNIX AND NOT APPLE) AND NOT SERVER_ONLY)
@ -485,7 +490,13 @@ else()
endif()
# Build the final executable
add_executable(supertuxkart ${STK_SOURCES} ${STK_RESOURCES} ${STK_HEADERS})
if (IOS)
file(GLOB IOS_ASSETS_FILES ${IOS_ASSETS})
set_source_files_properties(${IOS_ASSETS_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
add_executable(supertuxkart ${STK_SOURCES} ${STK_RESOURCES} ${STK_HEADERS} ${IOS_ASSETS_FILES})
else()
add_executable(supertuxkart ${STK_SOURCES} ${STK_RESOURCES} ${STK_HEADERS})
endif()
target_link_libraries(supertuxkart ${PTHREAD_LIBRARY})
endif()
@ -554,6 +565,8 @@ endif()
if(NOT SERVER_ONLY)
if(NOT USE_GLES2)
target_link_libraries(supertuxkart ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARIES})
elseif (IOS)
target_link_libraries(supertuxkart "-framework OpenGLES -framework UIKit -framework CoreMotion -framework Foundation -framework QuartzCore")
else()
target_link_libraries(supertuxkart GLESv2)
endif()

View File

@ -604,6 +604,20 @@ if(APPLE AND NOT IOS)
set_source_files_properties(source/Irrlicht/MacOSX/OSXClipboard.mm PROPERTIES LANGUAGE C)
endif()
if(IOS)
set(IRRLICHT_SOURCES
${IRRLICHT_SOURCES}
source/Irrlicht/CEAGLManager.mm
source/Irrlicht/CIrrDeviceiOS.mm)
set_source_files_properties(source/Irrlicht/CEAGLManager.mm PROPERTIES COMPILE_FLAGS "-x objective-c++ -O3 -fno-rtti")
set_source_files_properties(source/Irrlicht/CEAGLManager.mm PROPERTIES LANGUAGE C)
set_source_files_properties(source/Irrlicht/CIrrDeviceiOS.mm PROPERTIES COMPILE_FLAGS "-x objective-c++ -O3 -fno-rtti")
set_source_files_properties(source/Irrlicht/CIrrDeviceiOS.mm PROPERTIES LANGUAGE C)
endif()
add_library(stkirrlicht STATIC ${IRRLICHT_SOURCES})
target_link_libraries(stkirrlicht ${ZLIB_LIBRARY})

View File

@ -32,9 +32,9 @@ namespace irr
/** This device uses Apple's Cocoa API and works in Mac OSX 10.2 and above. */
EIDT_OSX,
//! A device native to the IPhone/IPod touch
//! A device native to the iOS
/** This device should be used with the OpenGL-ES driver. */
EIDT_IPHONE,
EIDT_IOS,
//! A device which uses Simple DirectMedia Layer
/** The SDL device works under all platforms supported by SDL but first must be compiled

View File

@ -0,0 +1,51 @@
// Copyright (C) 2013-2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __IRR_I_CONTEXT_MANAGER_H_INCLUDED__
#define __IRR_I_CONTEXT_MANAGER_H_INCLUDED__
#include "SExposedVideoData.h"
#include "SIrrCreationParameters.h"
namespace irr
{
namespace video
{
// For system specific window contexts (used for OpenGL)
class IContextManager : public virtual IReferenceCounted
{
public:
//! Initialize manager with device creation parameters and device window (passed as exposed video data)
virtual bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data) =0;
//! Terminate manager, any cleanup that is left over. Manager needs a new initialize to be usable again
virtual void terminate() =0;
//! Create surface based on current window set
virtual bool generateSurface() =0;
//! Destroy current surface
virtual void destroySurface() =0;
//! Create context based on current surface
virtual bool generateContext() =0;
//! Destroy current context
virtual void destroyContext() =0;
//! Get current context
virtual const SExposedVideoData& getContext() const =0;
//! Change render context, disable old and activate new defined by videoData
virtual bool activateContext(const SExposedVideoData& videoData) =0;
//! Swap buffers.
virtual bool swapBuffers() =0;
};
} // end namespace video
} // end namespace irr
#endif

View File

@ -24,7 +24,7 @@
//! _IRR_LINUX_PLATFORM_ for Linux (it is defined here if no other os is defined)
//! _IRR_SOLARIS_PLATFORM_ for Solaris
//! _IRR_OSX_PLATFORM_ for Apple systems running OSX
//! _IRR_IPHONE_PLATFORM_ for Apple devices running iOS
//! _IRR_IOS_PLATFORM_ for Apple devices running iOS
//! _IRR_ANDROID_PLATFORM_ for devices running Android
//! _IRR_POSIX_API_ for Posix compatible systems
//! Note: PLATFORM defines the OS specific layer, API can group several platforms
@ -66,14 +66,14 @@
// XBox only suppots the native Window stuff
#if defined(_XBOX)
#undef _IRR_WINDOWS_
#define _IRR_XBOX_PLATFORM_
#define _IRR_WINDOWS_API_
//#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_
#undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
//#define _IRR_COMPILE_WITH_SDL_DEVICE_
#undef _IRR_WINDOWS_
#define _IRR_XBOX_PLATFORM_
#define _IRR_WINDOWS_API_
//#define _IRR_COMPILE_WITH_WINDOWS_DEVICE_
#undef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
//#define _IRR_COMPILE_WITH_SDL_DEVICE_
#include <xtl.h>
#include <xtl.h>
#endif
#if defined(__APPLE__) || defined(MACOSX)
@ -83,8 +83,8 @@
#define _IRR_OSX_PLATFORM_ // we only support OSX on these systems
#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#define _IRR_IPHONE_PLATFORM_
#define _IRR_COMPILE_WITH_IPHONE_DEVICE_
#define _IRR_IOS_PLATFORM_
#define _IRR_COMPILE_WITH_IOS_DEVICE_
#define _IRR_COMPILE_WITH_OGLES2_
#else
#define _IRR_COMPILE_WITH_OSX_DEVICE_
@ -107,7 +107,7 @@
#define _IRR_COMPILE_ANDROID_ASSET_READER_
#endif
#if defined(_IRR_COMPILE_WITH_OGLES2_) && !defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if defined(_IRR_COMPILE_WITH_OGLES2_) && !defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#define _IRR_COMPILE_WITH_EGL_
#endif
@ -172,7 +172,7 @@ If not defined, Windows Multimedia library is used, which offers also broad supp
//! Define _IRR_COMPILE_WITH_OPENGL_ to compile the Irrlicht engine with OpenGL.
/** If you do not wish the engine to be compiled with OpenGL, comment this
define out. */
#if !defined(_IRR_IPHONE_PLATFORM_) && !defined(_IRR_ANDROID_PLATFORM_)
#if !defined(_IRR_IOS_PLATFORM_) && !defined(_IRR_ANDROID_PLATFORM_)
#define _IRR_COMPILE_WITH_OPENGL_
#endif
#ifdef NO_IRR_COMPILE_WITH_OPENGL_
@ -191,7 +191,7 @@ define out. */
#undef _IRR_COMPILE_WITH_OGLES2_
#endif
#ifndef IRR_OGLES2_SHADER_PATH
#ifdef _IRR_COMPILE_WITH_IPHONE_DEVICE_
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#define IRR_OGLES2_SHADER_PATH ""
#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
#define IRR_OGLES2_SHADER_PATH "media/Shaders/"
@ -211,7 +211,7 @@ define out. */
//! Define _IRR_OPENGL_USE_EXTPOINTER_ if the OpenGL renderer should use OpenGL extensions via function pointers.
/** On some systems there is no support for the dynamic extension of OpenGL
via function pointers such that this has to be undef'ed. */
via function pointers such that this has to be undef'ed. */
#ifdef _IRR_COMPILE_WITH_OPENGL_
#if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_)
#define _IRR_OPENGL_USE_EXTPOINTER_
@ -223,7 +223,7 @@ define out. */
architecture. You can simply uncomment the define and recompile.
*/
#ifdef _IRR_COMPILE_WITH_OGLES2_
#if !defined(_IRR_IPHONE_PLATFORM_)
#if !defined(_IRR_IOS_PLATFORM_)
#define _IRR_OGLES2_USE_EXTPOINTER_
#endif
#endif
@ -283,7 +283,7 @@ the engine will no longer read .jpeg images. */
//! Define _IRR_USE_NON_SYSTEM_JPEG_LIB_ to let irrlicht use the jpeglib which comes with irrlicht.
/** If this is commented out, Irrlicht will try to compile using the jpeg lib installed in the system.
This is only used when _IRR_COMPILE_WITH_LIBJPEG_ is defined. */
This is only used when _IRR_COMPILE_WITH_LIBJPEG_ is defined. */
//#define _IRR_USE_NON_SYSTEM_JPEG_LIB_
#ifdef NO_IRR_USE_NON_SYSTEM_JPEG_LIB_
#undef _IRR_USE_NON_SYSTEM_JPEG_LIB_
@ -299,7 +299,7 @@ the engine will no longer read .png images. */
//! Define _IRR_USE_NON_SYSTEM_LIBPNG_ to let irrlicht use the libpng which comes with irrlicht.
/** If this is commented out, Irrlicht will try to compile using the libpng installed in the system.
This is only used when _IRR_COMPILE_WITH_LIBPNG_ is defined. */
This is only used when _IRR_COMPILE_WITH_LIBPNG_ is defined. */
//#define _IRR_USE_NON_SYSTEM_LIB_PNG_
#ifdef NO_IRR_USE_NON_SYSTEM_LIB_PNG_
#undef _IRR_USE_NON_SYSTEM_LIB_PNG_
@ -327,7 +327,7 @@ B3D, MS3D or X meshes */
#ifdef NO_IRR_COMPILE_WITH_B3D_LOADER_
#undef _IRR_COMPILE_WITH_B3D_LOADER_
#endif
#endif // _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
#endif // _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
//! Define _IRR_COMPILE_WITH_BMP_LOADER_ if you want to load .bmp files
//! Disabling this loader will also disable the built-in font
@ -408,10 +408,10 @@ defined. */
precision will be lower but speed higher. currently X86 only
*/
#if !defined(_IRR_OSX_PLATFORM_) && !defined(_IRR_SOLARIS_PLATFORM_)
//#define IRRLICHT_FAST_MATH
#ifdef NO_IRRLICHT_FAST_MATH
#undef IRRLICHT_FAST_MATH
#endif
//#define IRRLICHT_FAST_MATH
#ifdef NO_IRRLICHT_FAST_MATH
#undef IRRLICHT_FAST_MATH
#endif
#endif
// Some cleanup and standard stuff
@ -462,7 +462,7 @@ precision will be lower but speed higher. currently X86 only
#endif
#ifndef _IRR_WINDOWS_API_
#undef _IRR_WCHAR_FILESYSTEM
#undef _IRR_WCHAR_FILESYSTEM
#endif
#if defined(__sparc__) || defined(__sun__)
@ -470,7 +470,7 @@ precision will be lower but speed higher. currently X86 only
#endif
#if defined(_IRR_SOLARIS_PLATFORM_)
#undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_
#undef _IRR_COMPILE_WITH_JOYSTICK_EVENTS_
#endif
//! Define __IRR_HAS_S64 if the irr::s64 type should be enable (needs long long, available on most platforms, but not part of ISO C++ 98)

View File

@ -17,7 +17,7 @@ namespace video
{
//! structure for holding data describing a driver and operating system specific data.
/** This data can be retrived by IVideoDriver::getExposedVideoData(). Use this with caution.
/** This data can be retrieved by IVideoDriver::getExposedVideoData(). Use this with caution.
This only should be used to make it possible to extend the engine easily without
modification of its source. Note that this structure does not contain any valid data, if
you are using the software or the null device.
@ -27,64 +27,87 @@ struct SExposedVideoData
SExposedVideoData() {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=0;}
explicit SExposedVideoData(void* Window) {OpenGLWin32.HDc=0; OpenGLWin32.HRc=0; OpenGLWin32.HWnd=Window;}
struct SD3D9
{
//! Pointer to the IDirect3D9 interface
IDirect3D9* D3D9;
//! Pointer to the IDirect3DDevice9 interface
IDirect3DDevice9* D3DDev9;
//! Window handle.
/** Get with for example HWND h = reinterpret_cast<HWND>(exposedData.D3D9.HWnd) */
void* HWnd;
};
struct SOpenGLWin32
{
//! Private GDI Device Context.
/** Get if for example with: HDC h = reinterpret_cast<HDC>(exposedData.OpenGLWin32.HDc) */
void* HDc;
//! Permanent Rendering Context.
/** Get if for example with: HGLRC h = reinterpret_cast<HGLRC>(exposedData.OpenGLWin32.HRc) */
void* HRc;
//! Window handle.
/** Get with for example with: HWND h = reinterpret_cast<HWND>(exposedData.OpenGLWin32.HWnd) */
void* HWnd;
};
struct SOpenGLLinux
{
// XWindow handles
void* X11Display;
void* X11Context;
unsigned long X11Window;
};
struct SOpenGLOSX
{
//! The NSOpenGLContext object.
void* Context;
//! The NSWindow object.
void* Window;
};
struct SOpenGLFB
{
//! The EGLNativeWindowType object.
void* Window;
};
struct SOpenGLiOS
{
//! The EAGLContext object.
void* Context;
//! The subview UIView object where the drawing happens.
void* View;
//! The UIViewController object.
void* ViewController;
//! The UIWindow object.
void* Window;
};
struct SOGLESAndroid
{
//! The ANativeWindow object.
void* Window;
};
union
{
struct
{
//! Pointer to the IDirect3D9 interface
IDirect3D9* D3D9;
//! Pointer to the IDirect3DDevice9 interface
IDirect3DDevice9* D3DDev9;
//! Window handle.
/** Get with for example HWND h = reinterpret_cast<HWND>(exposedData.D3D9.HWnd) */
void* HWnd;
} D3D9;
struct
{
//! Pointer to the IDirect3D8 interface
IDirect3D8* D3D8;
//! Pointer to the IDirect3DDevice8 interface
IDirect3DDevice8* D3DDev8;
//! Window handle.
/** Get with for example with: HWND h = reinterpret_cast<HWND>(exposedData.D3D8.HWnd) */
void* HWnd;
} D3D8;
struct
{
//! Private GDI Device Context.
/** Get if for example with: HDC h = reinterpret_cast<HDC>(exposedData.OpenGLWin32.HDc) */
void* HDc;
//! Permanent Rendering Context.
/** Get if for example with: HGLRC h = reinterpret_cast<HGLRC>(exposedData.OpenGLWin32.HRc) */
void* HRc;
//! Window handle.
/** Get with for example with: HWND h = reinterpret_cast<HWND>(exposedData.OpenGLWin32.HWnd) */
void* HWnd;
} OpenGLWin32;
struct
{
// XWindow handles
void* X11Display;
void* X11Context;
unsigned long X11Window;
} OpenGLLinux;
struct
{
//! The ANativeWindow object.
void* Window;
} OGLESAndroid;
SD3D9 D3D9;
SOpenGLWin32 OpenGLWin32;
SOpenGLLinux OpenGLLinux;
SOpenGLOSX OpenGLOSX;
SOpenGLFB OpenGLFB;
SOpenGLiOS OpenGLiOS;
SOGLESAndroid OGLESAndroid;
};
};

View File

@ -0,0 +1,84 @@
// Copyright (C) 2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h
#ifndef __C_EAGL_MANAGER_H_INCLUDED__
#define __C_EAGL_MANAGER_H_INCLUDED__
#include "IrrCompileConfig.h"
#include "SIrrCreationParameters.h"
#include "SExposedVideoData.h"
#include "IContextManager.h"
namespace irr
{
namespace video
{
// EAGL manager.
class CEAGLManager : public IContextManager
{
public:
//! Constructor.
CEAGLManager();
//! Destructor.
virtual ~CEAGLManager();
// Initialize EAGL.
/* This method checks if a view has CAEAGLLayer and grabs it if it does, anyway surface and context
aren't create. */
bool initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data);
// Terminate EAGL.
/* Terminate EAGL context. This method break both existed surface and context. */
void terminate();
// Create EAGL surface.
/* This method configure CAEAGLLayer. */
bool generateSurface();
// Destroy EAGL surface.
/* This method reset CAEAGLLayer states. */
void destroySurface();
// Create EAGL context.
/* This method create and activate EAGL context. */
bool generateContext();
// Destroy EAGL context.
/* This method destroy EAGL context. */
void destroyContext();
const SExposedVideoData& getContext() const;
bool activateContext(const SExposedVideoData& videoData);
// Swap buffers.
bool swapBuffers();
private:
SIrrlichtCreationParameters Params;
SExposedVideoData Data;
bool Configured;
void* DataStorage;
struct SFrameBuffer
{
SFrameBuffer() : BufferID(0), ColorBuffer(0), DepthBuffer(0)
{
}
u32 BufferID;
u32 ColorBuffer;
u32 DepthBuffer;
};
SFrameBuffer FrameBuffer;
};
}
}
#endif

View File

@ -0,0 +1,263 @@
// Copyright (C) 2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in Irrlicht.h
#include "CEAGLManager.h"
#include "irrString.h"
#include "os.h"
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
namespace irr
{
namespace video
{
struct SEAGLManagerDataStorage
{
SEAGLManagerDataStorage() : Layer(0), Context(0)
{
}
CAEAGLLayer* Layer;
EAGLContext* Context;
};
CEAGLManager::CEAGLManager() : IContextManager(), Configured(false), DataStorage(0)
{
#ifdef _DEBUG
setDebugName("CEAGLManager");
#endif
DataStorage = new SEAGLManagerDataStorage();
}
CEAGLManager::~CEAGLManager()
{
destroyContext();
destroySurface();
terminate();
delete static_cast<SEAGLManagerDataStorage*>(DataStorage);
}
bool CEAGLManager::initialize(const SIrrlichtCreationParameters& params, const SExposedVideoData& data)
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
if (dataStorage->Layer != nil)
return true;
Params = params;
Data = data;
UIView* view = (__bridge UIView*)data.OpenGLiOS.View;
if (view == nil || ![[view layer] isKindOfClass:[CAEAGLLayer class]])
{
os::Printer::log("Could not get EAGL display.");
return false;
}
dataStorage->Layer = (CAEAGLLayer*)[view layer];
return true;
}
void CEAGLManager::terminate()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
[EAGLContext setCurrentContext:0];
destroySurface();
if (dataStorage->Layer != nil)
dataStorage->Layer = 0;
}
bool CEAGLManager::generateSurface()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
CAEAGLLayer* layer = dataStorage->Layer;
if (layer == nil)
return false;
if (Configured)
return true;
NSDictionary* attribs = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO],
kEAGLDrawablePropertyRetainedBacking,
(Params.Bits > 16) ? kEAGLColorFormatRGBA8 : kEAGLColorFormatRGB565,
kEAGLDrawablePropertyColorFormat,
nil];
[layer setOpaque:(Params.WithAlphaChannel) ? YES : NO];
[layer setDrawableProperties:attribs];
Configured = true;
return true;
}
void CEAGLManager::destroySurface()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
CAEAGLLayer* layer = dataStorage->Layer;
if (layer == nil)
return;
[layer setOpaque:NO];
[layer setDrawableProperties:nil];
Configured = false;
}
bool CEAGLManager::generateContext()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
if (dataStorage->Context != nil || !Configured)
return false;
EAGLRenderingAPI OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
switch (Params.DriverType)
{
case EDT_OGLES2:
OpenGLESVersion = kEAGLRenderingAPIOpenGLES2;
break;
default:
break;
}
dataStorage->Context = [[EAGLContext alloc] initWithAPI:OpenGLESVersion];
if (dataStorage->Context == nil)
{
os::Printer::log("Could not create EAGL context.", ELL_ERROR);
return false;
}
Data.OpenGLiOS.Context = (__bridge void*)dataStorage->Context;
os::Printer::log("EAGL context created with OpenGLESVersion: ", core::stringc(static_cast<int>(OpenGLESVersion)), ELL_DEBUG);
return true;
}
void CEAGLManager::destroyContext()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
[dataStorage->Context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:nil];
if (FrameBuffer.BufferID != 0)
{
glDeleteFramebuffersOES(1, &FrameBuffer.BufferID);
FrameBuffer.BufferID = 0;
}
if (FrameBuffer.ColorBuffer != 0)
{
glDeleteRenderbuffersOES(1, &FrameBuffer.ColorBuffer);
FrameBuffer.ColorBuffer = 0;
}
if (FrameBuffer.DepthBuffer != 0)
{
glDeleteRenderbuffersOES(1, &FrameBuffer.DepthBuffer);
FrameBuffer.DepthBuffer = 0;
}
[EAGLContext setCurrentContext:0];
if (dataStorage->Context != nil)
dataStorage->Context = 0;
Data.OpenGLiOS.Context = 0;
}
bool CEAGLManager::activateContext(const SExposedVideoData& videoData)
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
EAGLContext* context = dataStorage->Context;
bool status = false;
if (context != nil)
{
status = ([EAGLContext currentContext] == context || [EAGLContext setCurrentContext:context]);
}
if (status)
{
if (FrameBuffer.ColorBuffer == 0)
{
glGenRenderbuffersOES(1, &FrameBuffer.ColorBuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:dataStorage->Layer];
}
if (FrameBuffer.DepthBuffer == 0)
{
GLenum depth = (Params.ZBufferBits >= 24) ? GL_DEPTH_COMPONENT24_OES : GL_DEPTH_COMPONENT16_OES;
glGenRenderbuffersOES(1, &FrameBuffer.DepthBuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.DepthBuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, depth, Params.WindowSize.Width, Params.WindowSize.Height);
}
if (FrameBuffer.BufferID == 0)
{
glGenFramebuffersOES(1, &FrameBuffer.BufferID);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer.BufferID);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, FrameBuffer.DepthBuffer);
}
glBindFramebufferOES(GL_FRAMEBUFFER_OES, FrameBuffer.BufferID);
}
else
{
os::Printer::log("Could not make EGL context current.");
}
return status;
}
const SExposedVideoData& CEAGLManager::getContext() const
{
return Data;
}
bool CEAGLManager::swapBuffers()
{
SEAGLManagerDataStorage* dataStorage = static_cast<SEAGLManagerDataStorage*>(DataStorage);
EAGLContext* context = dataStorage->Context;
bool status = false;
if (context != nil && context == [EAGLContext currentContext])
{
glBindRenderbufferOES(GL_RENDERBUFFER_OES, FrameBuffer.ColorBuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
status = true;
}
return status;
}
}
}

View File

@ -0,0 +1,98 @@
// Copyright (C) 2002-2008 Nikolaus Gebhardt
// Copyright (C) 2008 Redshift Software, Inc.
// Copyright (C) 2012-2015 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_IRR_DEVICE_IOS_H_INCLUDED__
#define __C_IRR_DEVICE_IOS_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "CIrrDeviceStub.h"
#include "IrrlichtDevice.h"
#include "IImagePresenter.h"
namespace irr
{
namespace video
{
class IContextManager;
}
class CIrrDeviceiOS : public CIrrDeviceStub, public video::IImagePresenter
{
public:
CIrrDeviceiOS(const SIrrlichtCreationParameters& params);
virtual ~CIrrDeviceiOS();
virtual bool run();
virtual void yield();
virtual void sleep(u32 timeMs, bool pauseTimer);
virtual void setWindowCaption(const wchar_t* text);
virtual void setWindowClass(const char* text) {}
virtual bool moveWindow(int x, int y) { return false; }
virtual bool isWindowActive() const;
virtual bool isWindowFocused() const;
virtual bool isWindowMinimized() const;
virtual bool present(video::IImage* surface, void * windowId = 0, core::rect<s32>* src = 0);
virtual void closeDevice();
virtual void setResizable(bool resize = false);
virtual void minimizeWindow();
virtual void maximizeWindow();
virtual void restoreWindow();
virtual bool getWindowPosition(int* x, int* y);
virtual bool activateAccelerometer(float updateInterval);
virtual bool deactivateAccelerometer();
virtual bool isAccelerometerActive();
virtual bool isAccelerometerAvailable();
virtual bool activateGyroscope(float updateInterval);
virtual bool deactivateGyroscope();
virtual bool isGyroscopeActive();
virtual bool isGyroscopeAvailable();
virtual bool activateDeviceMotion(float updateInterval) ;
virtual bool deactivateDeviceMotion() ;
virtual bool isDeviceMotionActive();
virtual bool isDeviceMotionAvailable();
virtual E_DEVICE_TYPE getType() const;
virtual u32 getScreenHeight() const { return 0; }
virtual u32 getOnScreenKeyboardHeight() const { return 0; }
virtual s32 getMovedHeight() const { return 0; }
virtual void toggleOnScreenKeyboard(bool show, s32 type = 0) {}
virtual void registerGetMovedHeightFunction(HeightFunc) {}
//! Returns true if system has touch device
virtual bool supportsTouchDevice() const { return true; }
//! Returns true if system has hardware keyboard attached
virtual bool hasHardwareKeyboard() const { return true; }
//! Returns true if system has native on screen keyboard
virtual bool hasOnScreenKeyboard() const { return false; }
private:
void createWindow();
void createViewAndDriver();
video::IContextManager* ContextManager;
void* DataStorage;
bool Close;
};
}
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
extern void irrlicht_main();
#endif
#endif
#endif

View File

@ -0,0 +1,799 @@
// Copyright (C) 2002-2008 Nikolaus Gebhardt
// Copyright (C) 2008 Redshift Software, Inc.
// Copyright (C) 2012 Patryk Nadrowski
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#import "CIrrDeviceiOS.h"
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "IFileSystem.h"
#include "CTimer.h"
#include "CEAGLManager.h"
#include "COGLES2Driver.h"
#import <UIKit/UIKit.h>
#import <CoreMotion/CoreMotion.h>
/* Important information */
// The application state events and following methods: IrrlichtDevice::isWindowActive, IrrlichtDevice::isWindowFocused
// and IrrlichtDevice::isWindowMinimized works out of box only if you'll use built-in CIrrDelegateiOS,
// so _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_ must be enabled in this case. If you need a custom UIApplicationDelegate you must
// handle all application events yourself.
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
namespace irr
{
class CIrrDeviceiOS;
}
/* CIrrDelegateiOS */
@interface CIrrDelegateiOS : NSObject<UIApplicationDelegate>
- (void)setDevice:(irr::CIrrDeviceiOS*)device;
- (bool)isActive;
- (bool)hasFocus;
@property (strong, nonatomic) UIWindow* window;
@end
@implementation CIrrDelegateiOS
{
irr::CIrrDeviceiOS* Device;
bool Active;
bool Focus;
}
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)options
{
Device = nil;
Active = true;
Focus = false;
[self performSelectorOnMainThread:@selector(runIrrlicht) withObject:nil waitUntilDone:NO];
return YES;
}
- (void)applicationWillTerminate:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_TERMINATE;
Device->postEventFromUser(ev);
Device->closeDevice();
}
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_MEMORY_WARNING;
Device->postEventFromUser(ev);
}
}
- (void)applicationWillResignActive:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_PAUSE;
Device->postEventFromUser(ev);
}
Focus = false;
}
- (void)applicationDidEnterBackground:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_DID_PAUSE;
Device->postEventFromUser(ev);
}
Active = false;
}
- (void)applicationWillEnterForeground:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_WILL_RESUME;
Device->postEventFromUser(ev);
}
Active = true;
}
- (void)applicationDidBecomeActive:(UIApplication*)application
{
if (Device != nil)
{
irr::SEvent ev;
ev.EventType = irr::EET_APPLICATION_EVENT;
ev.ApplicationEvent.EventType = irr::EAET_DID_RESUME;
Device->postEventFromUser(ev);
}
Focus = true;
}
- (void)runIrrlicht
{
irrlicht_main();
}
- (void)setDevice:(irr::CIrrDeviceiOS*)device
{
Device = device;
}
- (bool)isActive
{
return Active;
}
- (bool)hasFocus
{
return Focus;
}
@end
#endif
/* CIrrViewiOS */
@interface CIrrViewiOS : UIView
- (id)initWithFrame:(CGRect)frame forDevice:(irr::CIrrDeviceiOS*)device;
@end
@implementation CIrrViewiOS
{
irr::CIrrDeviceiOS* Device;
float Scale;
}
- (id)initWithFrame:(CGRect)frame forDevice:(irr::CIrrDeviceiOS*)device;
{
self = [super initWithFrame:frame];
if (self)
{
Device = device;
Scale = ([self respondsToSelector:@selector(setContentScaleFactor:)]) ? [[UIScreen mainScreen] scale] : 1.f;
}
return self;
}
- (BOOL)isMultipleTouchEnabled
{
return YES;
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_PRESSED_DOWN;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_MOVED;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_LEFT_UP;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event
{
irr::SEvent ev;
ev.EventType = irr::EET_TOUCH_INPUT_EVENT;
ev.TouchInput.Event = irr::ETIE_LEFT_UP;
for (UITouch* touch in touches)
{
ev.TouchInput.ID = (size_t)touch;
CGPoint touchPoint = [touch locationInView:self];
ev.TouchInput.X = touchPoint.x*Scale;
ev.TouchInput.Y = touchPoint.y*Scale;
Device->postEventFromUser(ev);
}
}
@end
/* CIrrViewEAGLiOS */
@interface CIrrViewEAGLiOS : CIrrViewiOS
@end
@implementation CIrrViewEAGLiOS
+ (Class)layerClass
{
return [CAEAGLLayer class];
}
@end
namespace irr
{
struct SIrrDeviceiOSDataStorage
{
SIrrDeviceiOSDataStorage() : Window(0), ViewController(0), View(0), MotionManager(0), ReferenceAttitude(0)
{
MotionManager = [[CMMotionManager alloc] init];
}
UIWindow* Window;
UIViewController* ViewController;
CIrrViewiOS* View;
CMMotionManager* MotionManager;
CMAttitude* ReferenceAttitude;
};
CIrrDeviceiOS::CIrrDeviceiOS(const SIrrlichtCreationParameters& params) : CIrrDeviceStub(params), ContextManager(0), DataStorage(0), Close(false)
{
#ifdef _DEBUG
setDebugName("CIrrDeviceiOS");
#endif
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
[delegate setDevice:this];
#endif
DataStorage = new SIrrDeviceiOSDataStorage();
FileSystem->changeWorkingDirectoryTo([[[NSBundle mainBundle] resourcePath] UTF8String]);
createWindow();
createViewAndDriver();
if (!VideoDriver)
return;
createGUIAndScene();
}
CIrrDeviceiOS::~CIrrDeviceiOS()
{
deactivateDeviceMotion();
deactivateGyroscope();
deactivateAccelerometer();
delete static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
[delegate setDevice:nil];
#endif
if (ContextManager)
ContextManager->drop();
}
bool CIrrDeviceiOS::run()
{
if (!Close)
{
const CFTimeInterval timeInSeconds = 0.000002;
s32 result = 0;
do
{
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeInSeconds, TRUE);
}
while (result == kCFRunLoopRunHandledSource);
os::Timer::tick();
//! Update events
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
//! Accelerometer
if (motionManager.isAccelerometerActive)
{
irr::SEvent ev;
ev.EventType = irr::EET_ACCELEROMETER_EVENT;
ev.AccelerometerEvent.X = motionManager.accelerometerData.acceleration.x;
ev.AccelerometerEvent.Y = motionManager.accelerometerData.acceleration.y;
ev.AccelerometerEvent.Z = motionManager.accelerometerData.acceleration.z;
postEventFromUser(ev);
}
//! Gyroscope
if (motionManager.isGyroActive)
{
irr::SEvent ev;
ev.EventType = irr::EET_GYROSCOPE_EVENT;
ev.GyroscopeEvent.X = motionManager.gyroData.rotationRate.x;
ev.GyroscopeEvent.Y = motionManager.gyroData.rotationRate.y;
ev.GyroscopeEvent.Z = motionManager.gyroData.rotationRate.z;
postEventFromUser(ev);
}
//! Device Motion
if (motionManager.isDeviceMotionActive)
{
CMAttitude* currentAttitude = motionManager.deviceMotion.attitude;
CMAttitude* referenceAttitude = dataStorage->ReferenceAttitude;
if (referenceAttitude != nil)
[currentAttitude multiplyByInverseOfAttitude: referenceAttitude];
else
referenceAttitude = motionManager.deviceMotion.attitude;
irr::SEvent ev;
ev.EventType = irr::EET_DEVICE_MOTION_EVENT;
ev.AccelerometerEvent.X = currentAttitude.roll;
ev.AccelerometerEvent.Y = currentAttitude.pitch;
ev.AccelerometerEvent.Z = currentAttitude.yaw;
postEventFromUser(ev);
}
}
return !Close;
}
void CIrrDeviceiOS::yield()
{
struct timespec ts = {0,0};
nanosleep(&ts, NULL);
}
void CIrrDeviceiOS::sleep(u32 timeMs, bool pauseTimer=false)
{
bool wasStopped = Timer ? Timer->isStopped() : true;
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);
if (pauseTimer && !wasStopped)
Timer->start();
}
void CIrrDeviceiOS::setWindowCaption(const wchar_t* text)
{
}
bool CIrrDeviceiOS::isWindowActive() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return [delegate isActive];
#else
return false;
#endif
}
bool CIrrDeviceiOS::isWindowFocused() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return [delegate hasFocus];
#else
return false;
#endif
}
bool CIrrDeviceiOS::isWindowMinimized() const
{
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
CIrrDelegateiOS* delegate = [UIApplication sharedApplication].delegate;
return ![delegate isActive];
#else
return false;
#endif
}
bool CIrrDeviceiOS::present(video::IImage* image, void * windowId, core::rect<s32>* src)
{
return false;
}
void CIrrDeviceiOS::closeDevice()
{
CFRunLoopStop(CFRunLoopGetMain());
Close = true;
}
void CIrrDeviceiOS::setResizable(bool resize)
{
}
void CIrrDeviceiOS::minimizeWindow()
{
}
void CIrrDeviceiOS::maximizeWindow()
{
}
void CIrrDeviceiOS::restoreWindow()
{
}
bool CIrrDeviceiOS::getWindowPosition(int* x, int* y)
{
*x = 0;
*y = 0;
return true;
}
bool CIrrDeviceiOS::activateAccelerometer(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isAccelerometerAvailable)
{
if (!motionManager.isAccelerometerActive)
{
motionManager.accelerometerUpdateInterval = updateInterval;
[motionManager startAccelerometerUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateAccelerometer()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isAccelerometerAvailable)
{
if (motionManager.isAccelerometerActive)
[motionManager stopAccelerometerUpdates];
status = true;
}
return status;
}
bool CIrrDeviceiOS::isAccelerometerActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isAccelerometerActive);
}
bool CIrrDeviceiOS::isAccelerometerAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isAccelerometerAvailable);
}
bool CIrrDeviceiOS::activateGyroscope(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isGyroAvailable)
{
if (!motionManager.isGyroActive)
{
motionManager.gyroUpdateInterval = updateInterval;
[motionManager startGyroUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateGyroscope()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isGyroAvailable)
{
if (motionManager.isGyroActive)
[motionManager stopGyroUpdates];
status = true;
}
return status;
}
bool CIrrDeviceiOS::isGyroscopeActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isGyroActive);
}
bool CIrrDeviceiOS::isGyroscopeAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isGyroAvailable);
}
bool CIrrDeviceiOS::activateDeviceMotion(float updateInterval)
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isDeviceMotionAvailable)
{
if (!motionManager.isDeviceMotionActive)
{
dataStorage->ReferenceAttitude = nil;
motionManager.deviceMotionUpdateInterval = updateInterval;
[motionManager startDeviceMotionUpdates];
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::deactivateDeviceMotion()
{
bool status = false;
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
CMMotionManager* motionManager = dataStorage->MotionManager;
if (motionManager.isDeviceMotionAvailable)
{
if (motionManager.isDeviceMotionActive)
{
[motionManager stopDeviceMotionUpdates];
dataStorage->ReferenceAttitude = nil;
}
status = true;
}
return status;
}
bool CIrrDeviceiOS::isDeviceMotionActive()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isDeviceMotionActive);
}
bool CIrrDeviceiOS::isDeviceMotionAvailable()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
return (dataStorage->MotionManager.isDeviceMotionAvailable);
}
E_DEVICE_TYPE CIrrDeviceiOS::getType() const
{
return EIDT_IOS;
}
void CIrrDeviceiOS::createWindow()
{
if (CreationParams.DriverType != video::EDT_NULL)
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
UIView* externalView = (__bridge UIView*)CreationParams.WindowId;
if (externalView == nil)
{
dataStorage->Window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
dataStorage->ViewController = [[UIViewController alloc] init];
dataStorage->Window.rootViewController = dataStorage->ViewController;
[dataStorage->Window makeKeyAndVisible];
}
else
{
dataStorage->Window = externalView.window;
UIResponder* currentResponder = externalView.nextResponder;
do
{
if ([currentResponder isKindOfClass:[UIViewController class]])
{
dataStorage->ViewController = (UIViewController*)currentResponder;
currentResponder = nil;
}
else if ([currentResponder isKindOfClass:[UIView class]])
{
currentResponder = currentResponder.nextResponder;
}
else
{
currentResponder = nil;
// Could not find view controller.
_IRR_DEBUG_BREAK_IF(true);
}
}
while (currentResponder != nil);
}
}
}
void CIrrDeviceiOS::createViewAndDriver()
{
SIrrDeviceiOSDataStorage* dataStorage = static_cast<SIrrDeviceiOSDataStorage*>(DataStorage);
video::SExposedVideoData data;
data.OpenGLiOS.Window = (__bridge void*)dataStorage->Window;
data.OpenGLiOS.ViewController = (__bridge void*)dataStorage->ViewController;
UIView* externalView = (__bridge UIView*)CreationParams.WindowId;
CGRect resolution = (externalView == nil) ? [[UIScreen mainScreen] bounds] : externalView.bounds;
switch (CreationParams.DriverType)
{
case video::EDT_OGLES2:
#ifdef _IRR_COMPILE_WITH_OGLES2_
{
CIrrViewEAGLiOS* view = [[CIrrViewEAGLiOS alloc] initWithFrame:resolution forDevice:this];
CreationParams.WindowSize = core::dimension2d<u32>(view.frame.size.width, view.frame.size.height);
dataStorage->View = view;
data.OpenGLiOS.View = (__bridge void*)view;
ContextManager = new irr::video::CEAGLManager();
ContextManager->initialize(CreationParams, data);
VideoDriver = new video::COGLES2Driver(CreationParams, FileSystem, this, ContextManager);
if (!VideoDriver)
os::Printer::log("Could not create OpenGL ES 2.x driver.", ELL_ERROR);
}
#else
os::Printer::log("No OpenGL ES 2.x support compiled in.", ELL_ERROR);
#endif
break;
case video::EDT_SOFTWARE:
case video::EDT_BURNINGSVIDEO:
case video::EDT_DIRECT3D9:
case video::EDT_OPENGL:
os::Printer::log("This driver is not available in iOS. Try OpenGL ES.", ELL_ERROR);
break;
case video::EDT_NULL:
VideoDriver = video::createNullDriver(FileSystem, CreationParams.WindowSize);
break;
default:
os::Printer::log("Unable to create video driver of unknown type.", ELL_ERROR);
break;
}
if (externalView == nil)
dataStorage->ViewController.view = dataStorage->View;
else
[externalView addSubview:dataStorage->View];
}
}
#ifdef _IRR_COMPILE_WITH_IOS_BUILTIN_MAIN_
int main(int argc, char** argv)
{
int result = UIApplicationMain(argc, argv, 0, NSStringFromClass([CIrrDelegateiOS class]));
return result;
}
#endif
#endif

View File

@ -8,6 +8,7 @@
#include "COGLES2Driver.h"
// needed here also because of the create methods' parameters
#include "CNullDriver.h"
#include "IContextManager.h"
#ifdef _IRR_COMPILE_WITH_OGLES2_
@ -22,7 +23,7 @@
#include "os.h"
#include "IrrlichtDevice.h"
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else
@ -40,14 +41,28 @@ namespace video
bool useCoreContext = true;
//! constructor and init code
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
COGLES2Driver::COGLES2Driver(const SIrrlichtCreationParameters& params,
const SExposedVideoData& data, io::IFileSystem* io
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
, CIrrDeviceIPhone* device
io::IFileSystem* io, IrrlichtDevice* device, IContextManager* context)
: CNullDriver(io, params.WindowSize), COGLES2ExtensionHandler(),
BridgeCalls(0), CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
Transformation3DChanged(true), AntiAlias(params.AntiAlias),
RenderTargetTexture(0), CurrentRendertargetSize(0, 0),
ColorFormat(ECF_R8G8B8), Params(params)
{
m_eagl_context = context;
m_eagl_context->grab();
m_eagl_context->generateSurface();
m_eagl_context->generateContext();
ExposedData = m_eagl_context->getContext();
m_eagl_context->activateContext(ExposedData);
m_device = device;
genericDriverInit(params.WindowSize, params.Stencilbuffer);
}
#else
, IrrlichtDevice* device
#endif
)
COGLES2Driver::COGLES2Driver(const SIrrlichtCreationParameters& params,
const SExposedVideoData& data, io::IFileSystem* io,
IrrlichtDevice* device)
: CNullDriver(io, params.WindowSize), COGLES2ExtensionHandler(),
BridgeCalls(0), CurrentRenderMode(ERM_NONE), ResetRenderStates(true),
Transformation3DChanged(true), AntiAlias(params.AntiAlias),
@ -55,10 +70,6 @@ namespace video
#if defined(_IRR_COMPILE_WITH_EGL_)
, EglContext(0)
, EglContextExternal(false)
#elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
, ViewFramebuffer(0)
, ViewRenderbuffer(0)
, ViewDepthRenderbuffer(0)
#endif
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
, HDc(0)
@ -94,57 +105,25 @@ namespace video
egl_params.window = ((struct android_app *)(params.PrivateData))->window;
egl_params.display = NULL;
#endif
EglContext->init(egl_params);
useCoreContext = !EglContext->isLegacyDevice();
genericDriverInit(params.WindowSize, params.Stencilbuffer);
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
int width = 0;
int height = 0;
EglContext->getSurfaceDimensions(&width, &height);
CNullDriver::ScreenSize = core::dimension2d<u32>(width, height);
CNullDriver::ScreenSize = core::dimension2d<u32>(width, height);
#endif
#elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
Device = device;
glGenFramebuffers(1, &ViewFramebuffer);
glGenRenderbuffers(1, &ViewRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, ViewRenderbuffer);
ExposedData.OGLESIPhone.AppDelegate = Device;
Device->displayInitialize(&ExposedData.OGLESIPhone.Context, &ExposedData.OGLESIPhone.View);
GLint backingWidth;
GLint backingHeight;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &backingHeight);
glGenRenderbuffers(1, &ViewDepthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, ViewDepthRenderbuffer);
GLenum depthComponent = GL_DEPTH_COMPONENT16;
if(params.ZBufferBits >= 24)
depthComponent = GL_DEPTH_COMPONENT24_OES;
glRenderbufferStorage(GL_RENDERBUFFER, depthComponent, backingWidth, backingHeight);
glBindFramebuffer(GL_FRAMEBUFFER, ViewFramebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ViewRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ViewDepthRenderbuffer);
core::dimension2d<u32> WindowSize(backingWidth, backingHeight);
CNullDriver::ScreenSize = WindowSize;
CNullDriver::ViewPort = core::rect<s32>(core::position2d<s32>(0,0), core::dimension2di(WindowSize));
genericDriverInit(WindowSize, params.Stencilbuffer);
#endif
m_device = device;
}
#endif
#ifdef _IRR_COMPILE_WITH_WAYLAND_DEVICE_
COGLES2Driver::COGLES2Driver(const SIrrlichtCreationParameters& params,
io::IFileSystem* io, CIrrDeviceWayland* device)
@ -182,23 +161,13 @@ namespace video
ReleaseDC((ExposedData.OpenGLWin32.HWnd, HDc);
#endif
#endif
#elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
if (0 != ViewFramebuffer)
{
glDeleteFramebuffers(1,&ViewFramebuffer);
ViewFramebuffer = 0;
}
if (0 != ViewRenderbuffer)
{
glDeleteRenderbuffers(1,&ViewRenderbuffer);
ViewRenderbuffer = 0;
}
if (0 != ViewDepthRenderbuffer)
{
glDeleteRenderbuffers(1,&ViewDepthRenderbuffer);
ViewDepthRenderbuffer = 0;
}
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
m_eagl_context->destroyContext();
m_eagl_context->destroySurface();
m_eagl_context->terminate();
m_eagl_context->drop();
#endif
}
@ -514,10 +483,8 @@ namespace video
os::Printer::log("Could not swap buffers for OpenGL-ES2 driver.");
return false;
}
#elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
glFlush();
glBindRenderbuffer(GL_RENDERBUFFER, ViewRenderbuffer);
Device->displayEnd();
#elif defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
m_eagl_context->swapBuffers();
#endif
return true;
@ -529,6 +496,9 @@ namespace video
const SExposedVideoData& videoData, core::rect<s32>* sourceRect)
{
CNullDriver::beginScene(backBuffer, zBuffer, color);
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
m_eagl_context->activateContext(videoData);
#endif
GLbitfield mask = 0;
@ -2909,7 +2879,7 @@ namespace irr
namespace video
{
#if !defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) && (defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_COMPILE_WITH_SDL_DEVICE_) || defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_))
#if !defined(_IRR_COMPILE_WITH_IOS_DEVICE_) && (defined(_IRR_COMPILE_WITH_X11_DEVICE_) || defined(_IRR_COMPILE_WITH_SDL_DEVICE_) || defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) || defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_))
IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
video::SExposedVideoData& data, io::IFileSystem* io, IrrlichtDevice* device)
{
@ -2952,21 +2922,5 @@ namespace video
}
#endif // _IRR_COMPILE_WITH_OSX_DEVICE_
// -----------------------------------
// IPHONE VERSION
// -----------------------------------
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params,
video::SExposedVideoData& data, io::IFileSystem* io,
CIrrDeviceIPhone* device)
{
#ifdef _IRR_COMPILE_WITH_OGLES2_
return new COGLES2Driver(params, data, io, device);
#else
return 0;
#endif // _IRR_COMPILE_WITH_OGLES2_
}
#endif // _IRR_COMPILE_WITH_IPHONE_DEVICE_
} // end namespace
} // end namespace

View File

@ -12,8 +12,8 @@
#if defined(_IRR_COMPILE_WITH_OSX_DEVICE_)
#include "MacOSX/CIrrDeviceMacOSX.h"
#elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#include "iOS/CIrrDeviceiOS.h"
#elif defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include "CIrrDeviceiOS.h"
#elif _IRR_COMPILE_WITH_WAYLAND_DEVICE_
#include "CIrrDeviceWayland.h"
#endif
@ -22,7 +22,7 @@
#ifdef _IRR_COMPILE_WITH_OGLES2_
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_)
@ -52,7 +52,7 @@ namespace video
class COGLES2Renderer2D;
class COGLES2NormalMapRenderer;
class COGLES2ParallaxMapRenderer;
class IContextManager;
class COGLES2Driver : public CNullDriver, public IMaterialRendererServices, public COGLES2ExtensionHandler
{
friend class COGLES2CallBridge;
@ -75,10 +75,9 @@ namespace video
io::IFileSystem* io, CIrrDeviceMacOSX *device);
#endif
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
COGLES2Driver(const SIrrlichtCreationParameters& params,
const SExposedVideoData& data,
io::IFileSystem* io, CIrrDeviceIPhone* device);
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
COGLES2Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io,
IrrlichtDevice* device, IContextManager* context);
#endif
//! destructor
@ -381,7 +380,7 @@ namespace video
//! Get bridge calls.
COGLES2CallBridge* getBridgeCalls() const;
#if defined(_IRR_COMPILE_WITH_EGL_)
ContextManagerEGL* getEGLContext() {return EglContext;}
#endif
@ -473,11 +472,8 @@ namespace video
ContextManagerEGL* EglContext;
bool EglContextExternal;
#endif
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
CIrrDeviceIPhone* Device;
GLuint ViewFramebuffer;
GLuint ViewRenderbuffer;
GLuint ViewDepthRenderbuffer;
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
IContextManager* m_eagl_context;
#endif
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
HDC HDc;

View File

@ -10,7 +10,7 @@
#include "IrrCompileConfig.h"
#ifdef _IRR_COMPILE_WITH_OGLES2_
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else

View File

@ -12,7 +12,7 @@
#ifdef _IRR_COMPILE_WITH_OGLES2_
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else

View File

@ -20,7 +20,7 @@
#include "irrString.h"
#if !defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if !defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <EGL/egl.h>
@ -248,7 +248,7 @@ void COGLES2Texture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
break;
}
// Hack for iPhone SDK, which requires a different InternalFormat
#ifdef _IRR_IPHONE_PLATFORM_
#ifdef _IRR_IOS_PLATFORM_
if (InternalFormat==GL_BGRA)
InternalFormat=GL_RGBA;
#endif

View File

@ -12,7 +12,7 @@
#ifdef _IRR_COMPILE_WITH_OGLES2_
#if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_)
#if defined(_IRR_COMPILE_WITH_IOS_DEVICE_)
#include <OpenGLES/ES2/gl.h>
#else
#include <GLES2/gl2.h>

View File

@ -34,6 +34,10 @@
#include "CIrrDeviceSDL.h"
#endif
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
#include "CIrrDeviceiOS.h"
#endif
#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_
#include "CIrrDeviceAndroid.h"
#include <android/log.h>
@ -116,6 +120,11 @@ namespace irr
SIrrlichtCreationParameters creation_params = params;
overrideDeviceType(creation_params.DeviceType);
#ifdef _IRR_COMPILE_WITH_IOS_DEVICE_
if (creation_params.DeviceType == EIDT_IOS || (!dev && creation_params.DeviceType == EIDT_BEST))
dev = new CIrrDeviceiOS(creation_params);
#endif
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
if (creation_params.DeviceType == EIDT_WIN32 || (!dev && creation_params.DeviceType == EIDT_BEST))
dev = new CIrrDeviceWin32(creation_params);

View File

@ -32,7 +32,19 @@ extern "C" {
}
#include <cinttypes>
#if defined(USE_GLES2)
# define __gl2_h_
#if defined(__APPLE__)
# include <OpenGLES/ES3/gl.h>
# include <OpenGLES/ES3/glext.h>
# include <OpenGLES/ES2/glext.h>
#else
# include <GLES3/gl3.h>
# include <GLES3/gl3ext.h>
# include <GLES2/gl2ext.h>
#endif
# define glVertexAttribDivisorARB glVertexAttribDivisor
#elif defined(__APPLE__)
# include <OpenGL/gl.h>
# include <OpenGL/gl3.h>
# define OGL32CTX
@ -45,12 +57,6 @@ extern "C" {
# ifndef GL_TEXTURE_SWIZZLE_RGBA
# define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
# endif
#elif defined(USE_GLES2)
# define __gl2_h_
# include <GLES3/gl3.h>
# include <GLES3/gl3ext.h>
# include <GLES2/gl2ext.h>
# define glVertexAttribDivisorARB glVertexAttribDivisor
#elif defined(WIN32)
# define WIN32_LEAN_AND_MEAN
# include <windows.h>

View File

@ -40,8 +40,10 @@
#endif
#if defined(USE_GLES2)
#ifndef __APPLE__
#include <EGL/egl.h>
#include <EGL/eglext.h>
#endif
#ifdef ARB_DEBUG_OUTPUT
#define GL_DEBUG_SEVERITY_HIGH_ARB GL_DEBUG_SEVERITY_HIGH_KHR
@ -158,10 +160,12 @@ debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei le
#endif
#ifdef USE_GLES2
#ifndef IOS_STK
GL_APICALL void(*GL_APIENTRY glDebugMessageControl)(GLenum source, GLenum type,
GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
GL_APICALL void(*GL_APIENTRY glDebugMessageInsert)(GLenum source, GLenum type,
GLuint id, GLenum severity, GLsizei length, const char *message);
#endif
#define GL_DEBUG_SOURCE_APPLICATION 0x824A
#define GL_DEBUG_TYPE_MARKER 0x8268
@ -203,6 +207,7 @@ void initGL()
#ifndef ANDROID
if (SP::sp_apitrace && hasGLExtension("GL_KHR_debug"))
{
#ifndef IOS_STK
#ifdef USE_GLES2
glDebugMessageControl = (void(GL_APIENTRY*)(GLenum, GLenum, GLenum, GLsizei,
const GLuint*, GLboolean))eglGetProcAddress("glDebugMessageControlKHR");
@ -211,6 +216,7 @@ void initGL()
assert(glDebugMessageControl && glDebugMessageInsert);
#endif
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
#endif
}
else
{
@ -222,6 +228,7 @@ void initGL()
ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
{
#ifndef ANDROID
#ifndef IOS_STK
if (SP::sp_apitrace)
{
std::string msg = timer.getName();
@ -229,6 +236,7 @@ ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
GL_DEBUG_SEVERITY_NOTIFICATION, -1, msg.c_str());
}
#endif
#endif
if (!UserConfigParams::m_profiler_enabled) return;
if (profiler.isFrozen()) return;
@ -245,6 +253,7 @@ ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t)
ScopedGPUTimer::~ScopedGPUTimer()
{
#ifndef ANDROID
#ifndef IOS_STK
if (SP::sp_apitrace)
{
std::string msg = timer.getName();
@ -252,6 +261,7 @@ ScopedGPUTimer::~ScopedGPUTimer()
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 100,
GL_DEBUG_SEVERITY_NOTIFICATION, -1, msg.c_str());
}
#endif
#endif
if (!UserConfigParams::m_profiler_enabled) return;
if (profiler.isFrozen()) return;

View File

@ -39,7 +39,7 @@ namespace Online
{
#if defined(_WIN32)
ShellExecuteA(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
#elif defined(__APPLE__)
#elif defined(__APPLE__) && !defined(IOS_STK)
std::string command = std::string("open ").append(url);
if (system(command.c_str()))
{
@ -76,4 +76,4 @@ namespace Online
Log::error("OpenURL", "Not implemented for this platform!");
#endif
}
}
}