mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
MacOS platform support.
This commit is contained in:
parent
57dfeb829a
commit
dd64004eaf
|
|
@ -387,11 +387,14 @@ if(USE_GCC OR USE_CLANG)
|
|||
list(APPEND EXTRA_CFLAGS "-Wshadow")
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
|
||||
check_c_compiler_flag("" HAVE_NO_UNDEFINED)
|
||||
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
|
||||
if(HAVE_NO_UNDEFINED)
|
||||
list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
|
||||
# --no-undefined is unsupported with clang
|
||||
if(NOT USE_CLANG)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
|
||||
check_c_compiler_flag("" HAVE_NO_UNDEFINED)
|
||||
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
|
||||
if(HAVE_NO_UNDEFINED)
|
||||
list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -43,17 +43,6 @@ extern void createFontShutdown(void);
|
|||
|
||||
static HashTable<StringTableEntry,StringTableEntry> gSecureScript;
|
||||
|
||||
#ifdef TORQUE_OS_MAC
|
||||
|
||||
// ObjC hooks for shared library support
|
||||
// See: macMain.mm
|
||||
|
||||
void torque_mac_engineinit(S32 argc, const char **argv);
|
||||
void torque_mac_enginetick();
|
||||
void torque_mac_engineshutdown();
|
||||
|
||||
#endif
|
||||
|
||||
extern bool LinkConsoleFunctions;
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -78,10 +67,6 @@ extern "C" {
|
|||
createFontInit();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TORQUE_OS_MAC
|
||||
torque_mac_engineinit(argc, argv);
|
||||
#endif
|
||||
// Initialize the subsystems.
|
||||
StandardMainLoop::init();
|
||||
|
||||
|
|
@ -113,11 +98,6 @@ extern "C" {
|
|||
__try {
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TORQUE_OS_MAC
|
||||
torque_mac_enginetick();
|
||||
#endif
|
||||
|
||||
bool ret = StandardMainLoop::doMainLoop();
|
||||
return ret;
|
||||
|
||||
|
|
@ -159,10 +139,6 @@ extern "C" {
|
|||
createFontShutdown();
|
||||
#endif
|
||||
|
||||
#ifdef TORQUE_OS_MAC
|
||||
torque_mac_engineshutdown();
|
||||
#endif
|
||||
|
||||
#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE )
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -613,7 +613,7 @@ namespace _Private {
|
|||
|
||||
///
|
||||
#define FIELD( fieldName, exportName, numElements, doc ) \
|
||||
{ #exportName, doc, numElements, TYPE( ( ( ThisType* ) 16 )->fieldName ), FIELDOFFSET( fieldName ) }, // Artificial offset to avoid compiler warnings.
|
||||
{ #exportName, doc, numElements, TYPE( ( ( ThisType* ) 16 )->fieldName ), (U32)FIELDOFFSET( fieldName ) }, // Artificial offset to avoid compiler warnings.
|
||||
|
||||
///
|
||||
#define FIELD_AS( type, fieldName, exportName, numElements, doc ) \
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
** this software for any purpose.
|
||||
*/
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -68,7 +69,11 @@
|
|||
|
||||
#include "core/util/md5.h"
|
||||
|
||||
#if defined (TORQUE_OS_MAC) && defined(TORQUE_CPU_X64)
|
||||
typedef unsigned int unsigned32;
|
||||
#else
|
||||
typedef unsigned long unsigned32;
|
||||
#endif
|
||||
typedef unsigned short unsigned16;
|
||||
typedef unsigned char unsigned8;
|
||||
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ void WaterPlane::setupVBIB( SceneRenderState *state )
|
|||
1, // Top
|
||||
-(S32)gridStride, // Right
|
||||
-1, // Bottom
|
||||
gridStride, // Left
|
||||
(S32)gridStride, // Left
|
||||
};
|
||||
|
||||
const U32 firstBorderVert = gridStride * gridSize + gridStride;
|
||||
|
|
|
|||
|
|
@ -232,3 +232,14 @@ DefineEngineStaticMethod( GFXCardProfilerAPI, queryProfile, S32, ( const char *n
|
|||
{
|
||||
return (S32)GFX->getCardProfiler()->queryProfile( name, (U32)defaultValue );
|
||||
}
|
||||
|
||||
|
||||
DefineEngineStaticMethod( GFXCardProfilerAPI, getBestDepthFormat, String, (),,
|
||||
"Returns the card name." )
|
||||
{
|
||||
if (GFX->getCardProfiler()->queryProfile("GL::Workaround::intel_mac_depth", false))
|
||||
return "GFXFormatD16";
|
||||
else
|
||||
return "GFXFormatD24S8";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,26 +27,9 @@
|
|||
void GFXGLCardProfiler::init()
|
||||
{
|
||||
mChipSet = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||
|
||||
// get the major and minor parts of the GL version. These are defined to be
|
||||
// in the order "[major].[minor] [other]|[major].[minor].[release] [other] in the spec
|
||||
const char *versionStart = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
const char *versionEnd = versionStart;
|
||||
// get the text for the version "x.x.xxxx "
|
||||
for( S32 tok = 0; tok < 2; ++tok )
|
||||
{
|
||||
char *text = dStrdup( versionEnd );
|
||||
dStrtok(text, ". ");
|
||||
versionEnd += dStrlen( text ) + 1;
|
||||
dFree( text );
|
||||
}
|
||||
|
||||
mRendererString = "GL";
|
||||
mRendererString += String::SpanToString(versionStart, versionEnd - 1);
|
||||
|
||||
mRendererString = "OpenGL";
|
||||
mCardDescription = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
||||
mVersionString = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
|
||||
mVideoMemory = static_cast<GFXGLDevice*>(GFX)->getTotalVideoMemory();
|
||||
|
||||
Parent::init();
|
||||
|
|
@ -86,6 +69,7 @@ void GFXGLCardProfiler::setupCardCapabilities()
|
|||
|
||||
// Check for vertex attrib binding
|
||||
setCapability("GL_ARB_vertex_attrib_binding", gglHasExtension(ARB_vertex_attrib_binding));
|
||||
|
||||
}
|
||||
|
||||
bool GFXGLCardProfiler::_queryCardCap(const String& query, U32& foundResult)
|
||||
|
|
|
|||
|
|
@ -103,27 +103,6 @@ void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLs
|
|||
Con::printf("AMDOPENGL: %s", message);
|
||||
}
|
||||
|
||||
|
||||
// >>>> OPENGL INTEL WORKAROUND @todo OPENGL INTEL remove
|
||||
PFNGLBINDFRAMEBUFFERPROC __openglBindFramebuffer = NULL;
|
||||
|
||||
void STDCALL _t3d_glBindFramebuffer(GLenum target, GLuint framebuffer)
|
||||
{
|
||||
if( target == GL_FRAMEBUFFER )
|
||||
{
|
||||
if( GFXGL->getOpenglCache()->getCacheBinded( GL_DRAW_FRAMEBUFFER ) == framebuffer
|
||||
&& GFXGL->getOpenglCache()->getCacheBinded( GL_READ_FRAMEBUFFER ) == framebuffer )
|
||||
return;
|
||||
}
|
||||
else if( GFXGL->getOpenglCache()->getCacheBinded( target ) == framebuffer )
|
||||
return;
|
||||
|
||||
__openglBindFramebuffer(target, framebuffer);
|
||||
GFXGL->getOpenglCache()->setCacheBinded( target, framebuffer);
|
||||
}
|
||||
// <<<< OPENGL INTEL WORKAROUND
|
||||
|
||||
|
||||
void GFXGLDevice::initGLState()
|
||||
{
|
||||
// We don't currently need to sync device state with a known good place because we are
|
||||
|
|
@ -157,13 +136,10 @@ void GFXGLDevice::initGLState()
|
|||
if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
|
||||
mUseGlMap = false;
|
||||
|
||||
|
||||
if( vendorStr.find("INTEL", 0, String::NoCase | String::Left ) != String::NPos)
|
||||
{
|
||||
// @todo OPENGL INTEL - This is a workaround for a warning spam or even crashes with actual framebuffer code, remove when implemented TGL layer.
|
||||
__openglBindFramebuffer = glBindFramebuffer;
|
||||
glBindFramebuffer = &_t3d_glBindFramebuffer;
|
||||
}
|
||||
// Workaround for all Mac's, has a problem using glMap* with volatile buffers
|
||||
#ifdef TORQUE_OS_MAC
|
||||
mUseGlMap = false;
|
||||
#endif
|
||||
|
||||
#if TORQUE_DEBUG
|
||||
if( gglHasExtension(ARB_debug_output) )
|
||||
|
|
|
|||
|
|
@ -1,343 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Don't include Apple's GL header
|
||||
#define __gl_h_
|
||||
// Include our GL header before Apple headers.
|
||||
#include "gfx/gl/ggl/ggl.h"
|
||||
|
||||
#include "platform/tmm_off.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include "gfx/gl/gfxGLDevice.h"
|
||||
#include "platform/tmm_on.h"
|
||||
|
||||
#include "gfx/gl/gfxGLTextureTarget.h"
|
||||
#include "gfx/gl/gfxGLCardProfiler.h"
|
||||
#include "gfx/gl/gfxGLAppleFence.h"
|
||||
#include "gfx/gl/gfxGLWindowTarget.h"
|
||||
#include "platformMac/macGLUtils.h"
|
||||
#include "windowManager/mac/macWindow.h"
|
||||
|
||||
extern void loadGLCore();
|
||||
extern void loadGLExtensions(void* context);
|
||||
|
||||
static String _getRendererForDisplay(CGDirectDisplayID display)
|
||||
{
|
||||
Vector<NSOpenGLPixelFormatAttribute> attributes = _createStandardPixelFormatAttributesForDisplay(display);
|
||||
|
||||
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes.address()];
|
||||
AssertFatal(fmt, "_getRendererForDisplay - Unable to create a pixel format object");
|
||||
|
||||
NSOpenGLContext* ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
|
||||
AssertFatal(ctx, "_getRendererForDisplay - Unable to create an OpenGL context");
|
||||
|
||||
// Save the current context, just in case
|
||||
NSOpenGLContext* currCtx = [NSOpenGLContext currentContext];
|
||||
[ctx makeCurrentContext];
|
||||
|
||||
// CodeReview [ags 12/19/07] This is a hack. We should call loadGLCore somewhere else, before we reach here.
|
||||
// On Macs we can safely assume access to the OpenGL framework at anytime, perhaps this should go in main()?
|
||||
loadGLCore();
|
||||
|
||||
// get the renderer string
|
||||
String ret((const char*)glGetString(GL_RENDERER));
|
||||
|
||||
// Restore our old context, release the context and pixel format.
|
||||
[currCtx makeCurrentContext];
|
||||
[ctx release];
|
||||
[fmt release];
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _createInitialContextAndFormat(void* &ctx, void* &fmt)
|
||||
{
|
||||
AssertFatal(!fmt && !ctx, "_createInitialContextAndFormat - Already created initial context and format");
|
||||
|
||||
fmt = _createStandardPixelFormat();
|
||||
AssertFatal(fmt, "_createInitialContextAndFormat - Unable to create an OpenGL pixel format");
|
||||
|
||||
ctx = [[NSOpenGLContext alloc] initWithFormat: (NSOpenGLPixelFormat*)fmt shareContext: nil];
|
||||
AssertFatal(ctx, "_createInitialContextAndFormat - Unable to create an OpenGL context");
|
||||
}
|
||||
|
||||
static NSOpenGLContext* _createContextForWindow(PlatformWindow *window, void* &context, void* &pixelFormat)
|
||||
{
|
||||
NSOpenGLView* view = (NSOpenGLView*)window->getPlatformDrawable();
|
||||
AssertFatal([view isKindOfClass:[NSOpenGLView class]], avar("_createContextForWindow - Supplied a %s instead of a NSOpenGLView", [[view className] UTF8String]));
|
||||
|
||||
NSOpenGLContext* ctx = NULL;
|
||||
if(!context || !pixelFormat)
|
||||
{
|
||||
// Create the initial opengl context that the device and the first window will hold.
|
||||
_createInitialContextAndFormat(context, pixelFormat);
|
||||
ctx = (NSOpenGLContext*)context;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a context which shares its resources with the device's initial context
|
||||
ctx = [[NSOpenGLContext alloc] initWithFormat: (NSOpenGLPixelFormat*)pixelFormat shareContext: (NSOpenGLContext*)context];
|
||||
AssertFatal(ctx, "Unable to create a shared OpenGL context");
|
||||
}
|
||||
|
||||
[view setPixelFormat: (NSOpenGLPixelFormat*)pixelFormat];
|
||||
[view setOpenGLContext: ctx];
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
|
||||
{
|
||||
if(mInitialized)
|
||||
return;
|
||||
|
||||
NSOpenGLContext* ctx = _createContextForWindow(window, mContext, mPixelFormat);
|
||||
[ctx makeCurrentContext];
|
||||
|
||||
loadGLCore();
|
||||
loadGLExtensions(ctx);
|
||||
|
||||
initGLState();
|
||||
|
||||
mInitialized = true;
|
||||
deviceInited();
|
||||
}
|
||||
|
||||
void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
|
||||
{
|
||||
GFXAdapter *toAdd;
|
||||
|
||||
Vector<GFXVideoMode> videoModes;
|
||||
|
||||
CGDirectDisplayID display = CGMainDisplayID();
|
||||
|
||||
// Enumerate all available resolutions:
|
||||
NSArray* modeArray = (NSArray*)CGDisplayAvailableModes(display);
|
||||
|
||||
GFXVideoMode vmAdd;
|
||||
NSEnumerator* enumerator = [modeArray objectEnumerator];
|
||||
NSDictionary* mode;
|
||||
while((mode = [enumerator nextObject]))
|
||||
{
|
||||
vmAdd.resolution.x = [[mode valueForKey:@"Width"] intValue];
|
||||
vmAdd.resolution.y = [[mode valueForKey:@"Height"] intValue];
|
||||
vmAdd.bitDepth = [[mode valueForKey:@"BitsPerPixel"] intValue];
|
||||
vmAdd.refreshRate = [[mode valueForKey:@"RefreshRate"] intValue];
|
||||
|
||||
vmAdd.fullScreen = false;
|
||||
|
||||
// skip if mode claims to be 8bpp
|
||||
if( vmAdd.bitDepth == 8 )
|
||||
continue;
|
||||
|
||||
// Only add this resolution if it is not already in the list:
|
||||
bool alreadyInList = false;
|
||||
for(Vector<GFXVideoMode>::iterator i = videoModes.begin(); i != videoModes.end(); i++)
|
||||
{
|
||||
if(vmAdd == *i)
|
||||
{
|
||||
alreadyInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !alreadyInList )
|
||||
{
|
||||
videoModes.push_back( vmAdd );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get number of displays
|
||||
CGDisplayCount dispCnt;
|
||||
CGGetActiveDisplayList(0, NULL, &dispCnt);
|
||||
|
||||
// Take advantage of GNU-C
|
||||
CGDirectDisplayID displays[dispCnt];
|
||||
|
||||
CGGetActiveDisplayList(dispCnt, displays, &dispCnt);
|
||||
for(U32 i = 0; i < dispCnt; i++)
|
||||
{
|
||||
toAdd = new GFXAdapter();
|
||||
toAdd->mType = OpenGL;
|
||||
toAdd->mIndex = (U32)displays[i];
|
||||
toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance;
|
||||
String renderer = _getRendererForDisplay(displays[i]);
|
||||
AssertFatal(dStrlen(renderer.c_str()) < GFXAdapter::MaxAdapterNameLen, "GFXGLDevice::enumerateAdapter - renderer name too long, increae the size of GFXAdapter::MaxAdapterNameLen (or use String!)");
|
||||
dStrncpy(toAdd->mName, renderer.c_str(), GFXAdapter::MaxAdapterNameLen);
|
||||
adapterList.push_back(toAdd);
|
||||
|
||||
for (S32 j = videoModes.size() - 1 ; j >= 0 ; j--)
|
||||
toAdd->mAvailableModes.push_back(videoModes[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void GFXGLDevice::enumerateVideoModes()
|
||||
{
|
||||
mVideoModes.clear();
|
||||
|
||||
CGDirectDisplayID display = CGMainDisplayID();
|
||||
|
||||
// Enumerate all available resolutions:
|
||||
NSArray* modeArray = (NSArray*)CGDisplayAvailableModes(display);
|
||||
|
||||
GFXVideoMode toAdd;
|
||||
NSEnumerator* enumerator = [modeArray objectEnumerator];
|
||||
NSDictionary* mode;
|
||||
while((mode = [enumerator nextObject]))
|
||||
{
|
||||
toAdd.resolution.x = [[mode valueForKey:@"Width"] intValue];
|
||||
toAdd.resolution.y = [[mode valueForKey:@"Height"] intValue];
|
||||
toAdd.bitDepth = [[mode valueForKey:@"BitsPerPixel"] intValue];
|
||||
toAdd.refreshRate = [[mode valueForKey:@"RefreshRate"] intValue];
|
||||
|
||||
toAdd.fullScreen = false;
|
||||
|
||||
// skip if mode claims to be 8bpp
|
||||
if( toAdd.bitDepth == 8 )
|
||||
continue;
|
||||
|
||||
// Only add this resolution if it is not already in the list:
|
||||
bool alreadyInList = false;
|
||||
for(Vector<GFXVideoMode>::iterator i = mVideoModes.begin(); i != mVideoModes.end(); i++)
|
||||
{
|
||||
if(toAdd == *i)
|
||||
{
|
||||
alreadyInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !alreadyInList )
|
||||
{
|
||||
mVideoModes.push_back( toAdd );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GFXGLDevice::beginSceneInternal()
|
||||
{
|
||||
// Nothing to do here for GL.
|
||||
mCanCurrentlyRender = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
U32 GFXGLDevice::getTotalVideoMemory()
|
||||
{
|
||||
// Convert our adapterIndex (i.e. our CGDirectDisplayID) into an OpenGL display mask
|
||||
GLuint display = CGDisplayIDToOpenGLDisplayMask((CGDirectDisplayID)mAdapterIndex);
|
||||
CGLRendererInfoObj rend;
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
||||
GLint nrend;
|
||||
#else
|
||||
long int nrend;
|
||||
#endif
|
||||
CGLQueryRendererInfo(display, &rend, &nrend);
|
||||
if(!nrend)
|
||||
return 0;
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
||||
GLint vidMem;
|
||||
#else
|
||||
long int vidMem;
|
||||
#endif
|
||||
CGLDescribeRenderer(rend, 0, kCGLRPVideoMemory, &vidMem);
|
||||
CGLDestroyRendererInfo(rend);
|
||||
|
||||
// convert bytes to MB
|
||||
vidMem /= (1024 * 1024);
|
||||
|
||||
return vidMem;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
GFXWindowTarget *GFXGLDevice::allocWindowTarget(PlatformWindow *window)
|
||||
{
|
||||
void *ctx = NULL;
|
||||
|
||||
// Init if needed, or create a new context
|
||||
if(!mInitialized)
|
||||
init(window->getVideoMode(), window);
|
||||
else
|
||||
ctx = _createContextForWindow(window, mContext, mPixelFormat);
|
||||
|
||||
// Allocate the wintarget and create a new context.
|
||||
GFXGLWindowTarget *gwt = new GFXGLWindowTarget(window, this);
|
||||
gwt->mContext = ctx ? ctx : mContext;
|
||||
|
||||
// And return...
|
||||
return gwt;
|
||||
}
|
||||
|
||||
GFXFence* GFXGLDevice::_createPlatformSpecificFence()
|
||||
{
|
||||
if(!mCardProfiler->queryProfile("GL::APPLE::suppFence"))
|
||||
return NULL;
|
||||
|
||||
return new GFXGLAppleFence(this);
|
||||
}
|
||||
|
||||
void GFXGLWindowTarget::_WindowPresent()
|
||||
{
|
||||
GFX->updateStates();
|
||||
mFullscreenContext ? [(NSOpenGLContext*)mFullscreenContext flushBuffer] : [(NSOpenGLContext*)mContext flushBuffer];
|
||||
return true;
|
||||
}
|
||||
|
||||
void GFXGLWindowTarget::_teardownCurrentMode()
|
||||
{
|
||||
GFX->setActiveRenderTarget(this);
|
||||
static_cast<GFXGLDevice*>(mDevice)->zombify();
|
||||
if(mFullscreenContext)
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
[(NSOpenGLContext*)mFullscreenContext clearDrawable];
|
||||
}
|
||||
}
|
||||
|
||||
void GFXGLWindowTarget::_setupNewMode()
|
||||
{
|
||||
if(mWindow->getVideoMode().fullScreen && !mFullscreenContext)
|
||||
{
|
||||
// We have to create a fullscreen context.
|
||||
Vector<NSOpenGLPixelFormatAttribute> attributes = _beginPixelFormatAttributesForDisplay(static_cast<MacWindow*>(mWindow)->getDisplay());
|
||||
_addColorAlphaDepthStencilAttributes(attributes, 24, 8, 24, 8);
|
||||
_addFullscreenAttributes(attributes);
|
||||
_endAttributeList(attributes);
|
||||
|
||||
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes.address()];
|
||||
mFullscreenContext = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
|
||||
[fmt release];
|
||||
[(NSOpenGLContext*)mFullscreenContext setFullScreen];
|
||||
[(NSOpenGLContext*)mFullscreenContext makeCurrentContext];
|
||||
// Restore resources in new context
|
||||
static_cast<GFXGLDevice*>(mDevice)->resurrect();
|
||||
GFX->updateStates(true);
|
||||
}
|
||||
else if(!mWindow->getVideoMode().fullScreen && mFullscreenContext)
|
||||
{
|
||||
[(NSOpenGLContext*)mFullscreenContext release];
|
||||
mFullscreenContext = NULL;
|
||||
[(NSOpenGLContext*)mContext makeCurrentContext];
|
||||
GFX->clear(GFXClearTarget | GFXClearZBuffer | GFXClearStencil, ColorI(0, 0, 0), 1.0f, 0);
|
||||
static_cast<GFXGLDevice*>(mDevice)->resurrect();
|
||||
GFX->updateStates(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,8 @@
|
|||
#include "gfx/gfxStructs.h"
|
||||
#include "console/console.h"
|
||||
|
||||
#define CHECK_AARG(pos, name) static StringTableEntry attr_##name = StringTable->insert(#name); if (argName == attr_##name) { glBindAttribLocation(mProgram, pos, attr_##name); continue; }
|
||||
|
||||
|
||||
class GFXGLShaderConstHandle : public GFXShaderConstHandle
|
||||
{
|
||||
|
|
@ -448,33 +450,61 @@ bool GFXGLShader::_init()
|
|||
if(!compiledVertexShader || !compiledPixelShader)
|
||||
return false;
|
||||
|
||||
//bind vertex attributes
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Position, "vPosition");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Normal, "vNormal");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Color, "vColor");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Tangent, "vTangent");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TangentW, "vTangentW");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Binormal, "vBinormal");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord0, "vTexCoord0");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord1, "vTexCoord1");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord2, "vTexCoord2");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord3, "vTexCoord3");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord4, "vTexCoord4");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord5, "vTexCoord5");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord6, "vTexCoord6");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord7, "vTexCoord7");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord8, "vTexCoord8");
|
||||
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord9, "vTexCoord9");
|
||||
|
||||
//bind fragment out color
|
||||
glBindFragDataLocation(mProgram, 0, "OUT_col");
|
||||
glBindFragDataLocation(mProgram, 1, "OUT_col1");
|
||||
glBindFragDataLocation(mProgram, 2, "OUT_col2");
|
||||
glBindFragDataLocation(mProgram, 3, "OUT_col3");
|
||||
|
||||
// Link it!
|
||||
glLinkProgram( mProgram );
|
||||
|
||||
GLint activeAttribs = 0;
|
||||
glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs );
|
||||
|
||||
GLint maxLength;
|
||||
glGetProgramiv(mProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
|
||||
|
||||
FrameTemp<GLchar> tempData(maxLength+1);
|
||||
*tempData.address() = '\0';
|
||||
// Check atributes
|
||||
for (U32 i=0; i<activeAttribs; i++)
|
||||
{
|
||||
GLint size;
|
||||
GLenum type;
|
||||
|
||||
glGetActiveAttrib(mProgram, i, maxLength + 1, NULL, &size, &type, tempData.address());
|
||||
|
||||
StringTableEntry argName = StringTable->insert(tempData.address());
|
||||
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_Position, vPosition);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_Normal, vNormal);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_Color, vColor);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_Tangent, vTangent);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TangentW, vTangentW);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_Binormal, vBinormal);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord0, vTexCoord0);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord1, vTexCoord1);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord2, vTexCoord2);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord3, vTexCoord3);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord4, vTexCoord4);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord5, vTexCoord5);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord6, vTexCoord6);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord7, vTexCoord7);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord8, vTexCoord8);
|
||||
CHECK_AARG(Torque::GL_VertexAttrib_TexCoord9, vTexCoord9);
|
||||
}
|
||||
|
||||
//always have OUT_col
|
||||
glBindFragDataLocation(mProgram, 0, "OUT_col");
|
||||
// Check OUT_colN
|
||||
for(U32 i=1;i<4;i++)
|
||||
{
|
||||
char buffer[10];
|
||||
dSprintf(buffer, sizeof(buffer), "OUT_col%u",i);
|
||||
GLint location = glGetFragDataLocation(mProgram, buffer);
|
||||
if(location>0)
|
||||
glBindFragDataLocation(mProgram, i, buffer);
|
||||
|
||||
}
|
||||
|
||||
// Link it again!
|
||||
glLinkProgram( mProgram );
|
||||
|
||||
GLint linkStatus;
|
||||
glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus );
|
||||
|
||||
|
|
@ -493,16 +523,17 @@ bool GFXGLShader::_init()
|
|||
{
|
||||
Con::errorf( "GFXGLShader::init - Error linking shader!" );
|
||||
Con::errorf( "Program %s / %s: %s",
|
||||
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
|
||||
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
|
||||
}
|
||||
}
|
||||
else if ( smLogWarnings )
|
||||
{
|
||||
Con::warnf( "Program %s / %s: %s",
|
||||
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
|
||||
mVertexFile.getFullPath().c_str(), mPixelFile.getFullPath().c_str(), log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we failed to link, bail.
|
||||
if ( linkStatus == GL_FALSE )
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ void _GFXGLTextureTargetFBOImpl::applyState()
|
|||
{
|
||||
// Certain drivers have issues with depth only FBOs. That and the next two asserts assume we have a color target.
|
||||
AssertFatal(hasColor, "GFXGLTextureTarget::applyState() - Cannot set DepthStencil target without Color0 target!");
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthStecil->getBinding(), depthStecil->getHandle(), depthStecil->getMipLevel());
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, depthStecil->getBinding(), depthStecil->getHandle(), depthStecil->getMipLevel());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -118,11 +118,14 @@ inline void GFXGLWindowTarget::_setupAttachments()
|
|||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->getHandle(), 0);
|
||||
mBackBufferDepthTex.set(dstSize.x, dstSize.y, GFXFormatD24S8, &BackBufferDepthProfile, "backBuffer");
|
||||
GFXGLTextureObject *depth = static_cast<GFXGLTextureObject*>(mBackBufferDepthTex.getPointer());
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth->getHandle(), 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth->getHandle(), 0);
|
||||
}
|
||||
|
||||
void GFXGLWindowTarget::makeActive()
|
||||
{
|
||||
//make the rendering context active on this window
|
||||
_makeContextCurrent();
|
||||
|
||||
if(mBackBufferFBO)
|
||||
{
|
||||
glBindFramebuffer( GL_FRAMEBUFFER, mBackBufferFBO);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ private:
|
|||
void _setupNewMode();
|
||||
void _setupAttachments();
|
||||
void _WindowPresent();
|
||||
//set this windows context to be current
|
||||
void _makeContextCurrent();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -155,12 +155,12 @@ void GFXGLDevice::enumerateVideoModes()
|
|||
void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
|
||||
{
|
||||
AssertFatal(window, "GFXGLDevice::init - no window specified, can't init device without a window!");
|
||||
PlatformWindowSDL* x11Window = dynamic_cast<PlatformWindowSDL*>(window);
|
||||
AssertFatal(x11Window, "Window is not a valid PlatformWindowSDL object");
|
||||
PlatformWindowSDL* sdlWindow = dynamic_cast<PlatformWindowSDL*>(window);
|
||||
AssertFatal(sdlWindow, "Window is not a valid PlatformWindowSDL object");
|
||||
|
||||
// Create OpenGL context
|
||||
mContext = PlatformGL::CreateContextGL( x11Window );
|
||||
PlatformGL::MakeCurrentGL( x11Window, mContext );
|
||||
mContext = PlatformGL::CreateContextGL( sdlWindow );
|
||||
PlatformGL::MakeCurrentGL( sdlWindow, mContext );
|
||||
|
||||
loadGLCore();
|
||||
loadGLExtensions(0);
|
||||
|
|
@ -226,4 +226,9 @@ void GFXGLWindowTarget::_setupNewMode()
|
|||
{
|
||||
}
|
||||
|
||||
void GFXGLWindowTarget::_makeContextCurrent()
|
||||
{
|
||||
PlatformGL::MakeCurrentGL(mWindow, mContext);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -363,3 +363,16 @@ void GFXGLWindowTarget::_teardownCurrentMode()
|
|||
void GFXGLWindowTarget::_setupNewMode()
|
||||
{
|
||||
}
|
||||
|
||||
void GFXGLWindowTarget::_makeContextCurrent()
|
||||
{
|
||||
HWND hwnd = GETHWND(getWindow());
|
||||
HDC hdc = GetDC(hwnd);
|
||||
if (!wglMakeCurrent(hdc, (HGLRC)mContext))
|
||||
{
|
||||
//HRESULT if needed for debug
|
||||
//HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
AssertFatal(false, "GFXGLWindowTarget::_makeContextCurrent() - cannot make our context current.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -672,11 +672,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef TORQUE_OS_MAC
|
||||
Point2I screensize = getRoot()->getWindowSize();
|
||||
tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y);
|
||||
#endif
|
||||
|
||||
// set up the camera and viewport stuff:
|
||||
F32 wwidth;
|
||||
F32 wheight;
|
||||
|
|
@ -716,12 +711,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
|
|||
}
|
||||
|
||||
RectI tempRect = updateRect;
|
||||
|
||||
#ifdef TORQUE_OS_MAC
|
||||
Point2I screensize = getRoot()->getWindowSize();
|
||||
tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y);
|
||||
#endif
|
||||
|
||||
_internalRender(tempRect, tempRect, frustum);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This file is Mac specific.
|
||||
#if defined( __APPLE__ )
|
||||
|
||||
#include <vecLib/vecLib.h>
|
||||
#include "math/mMathFn.h"
|
||||
#include "console/console.h"
|
||||
#include "platform/profiler.h"
|
||||
|
||||
#if defined( __VEC__ )
|
||||
|
||||
// tests show BLAS to be about 4x slower than aligned altivec, 3x slower than unaligned altivec code below.
|
||||
|
||||
/// Altivec 4x4 Matrix multiplication.
|
||||
/// Most of our time is spent moving data in & out of the vector registers.
|
||||
/// Alignment of the matrix data to 16-byte boundaries is very important,
|
||||
/// because we get a much better speed gain if we can assume the data is aligned.
|
||||
void vec_MatrixF_x_MatrixF(const F32 *matA, const F32 *matB, F32 *result)
|
||||
{
|
||||
vector F32 A[4][1];
|
||||
vector F32 B[4][1];
|
||||
vector F32 C[4][1];
|
||||
|
||||
/// If the incoming pointers are not 16-byte aligned, we have to load & store the slow way.
|
||||
if((int)matA & 0xF || (int)matB & 0xF || (int)result & 0xF)
|
||||
{
|
||||
F32 *loader;
|
||||
loader = (F32*) &A;
|
||||
loader[0] = matA[0];
|
||||
loader[1] = matA[1];
|
||||
loader[2] = matA[2];
|
||||
loader[3] = matA[3];
|
||||
loader[4] = matA[4];
|
||||
loader[5] = matA[5];
|
||||
loader[6] = matA[6];
|
||||
loader[7] = matA[7];
|
||||
loader[8] = matA[8];
|
||||
loader[9] = matA[9];
|
||||
loader[10] = matA[10];
|
||||
loader[11] = matA[11];
|
||||
loader[12] = matA[12];
|
||||
loader[13] = matA[13];
|
||||
loader[14] = matA[14];
|
||||
loader[15] = matA[15];
|
||||
loader = (F32*) &B;
|
||||
loader[0] = matB[0];
|
||||
loader[1] = matB[1];
|
||||
loader[2] = matB[2];
|
||||
loader[3] = matB[3];
|
||||
loader[4] = matB[4];
|
||||
loader[5] = matB[5];
|
||||
loader[6] = matB[6];
|
||||
loader[7] = matB[7];
|
||||
loader[8] = matB[8];
|
||||
loader[9] = matB[9];
|
||||
loader[10] = matB[10];
|
||||
loader[11] = matB[11];
|
||||
loader[12] = matB[12];
|
||||
loader[13] = matB[13];
|
||||
loader[14] = matB[14];
|
||||
loader[15] = matB[15];
|
||||
|
||||
vMultMatMat_4x4( A, B, C);
|
||||
|
||||
loader = (F32*) &C;
|
||||
|
||||
result[0] = loader[0];
|
||||
result[1] = loader[1];
|
||||
result[2] = loader[2];
|
||||
result[3] = loader[3];
|
||||
result[4] = loader[4];
|
||||
result[5] = loader[5];
|
||||
result[6] = loader[6];
|
||||
result[7] = loader[7];
|
||||
result[8] = loader[8];
|
||||
result[9] = loader[9];
|
||||
result[10] = loader[10];
|
||||
result[11] = loader[11];
|
||||
result[12] = loader[12];
|
||||
result[13] = loader[13];
|
||||
result[14] = loader[14];
|
||||
result[15] = loader[15];
|
||||
}
|
||||
else
|
||||
{
|
||||
A[0][0] = vec_ld(0, matA);
|
||||
A[1][0] = vec_ld(16, matA);
|
||||
A[2][0] = vec_ld(32, matA);
|
||||
A[3][0] = vec_ld(48, matA);
|
||||
B[0][0] = vec_ld(0, matB);
|
||||
B[1][0] = vec_ld(16, matB);
|
||||
B[2][0] = vec_ld(32, matB);
|
||||
B[3][0] = vec_ld(48, matB);
|
||||
|
||||
vMultMatMat_4x4( A, B, C);
|
||||
|
||||
vec_st(C[0][0], 0, result);
|
||||
vec_st(C[1][0], 16, result);
|
||||
vec_st(C[2][0], 32, result);
|
||||
vec_st(C[3][0], 48, result);
|
||||
}
|
||||
}
|
||||
|
||||
void mInstallLibrary_Vec()
|
||||
{
|
||||
m_matF_x_matF = vec_MatrixF_x_MatrixF;
|
||||
}
|
||||
#else // defined(__VEC__)
|
||||
void mInstallLibrary_Vec()
|
||||
{
|
||||
Con::warnf("Cannot use altivec math, this build does not support altivec.");
|
||||
}
|
||||
#endif// defined(__VEC__)
|
||||
|
||||
#endif// defined(__APPLE__)
|
||||
|
|
@ -125,16 +125,6 @@ typedef unsigned long U64;
|
|||
# define TORQUE_CPU_X64
|
||||
# define TORQUE_LITTLE_ENDIAN
|
||||
|
||||
#elif defined(__ppc__)
|
||||
# define TORQUE_CPU_STRING "PowerPC"
|
||||
# define TORQUE_CPU_PPC
|
||||
# define TORQUE_BIG_ENDIAN
|
||||
|
||||
#elif defined(SN_TARGET_PS3)
|
||||
# define TORQUE_CPU_STRING "PowerPC"
|
||||
# define TORQUE_CPU_PPC
|
||||
# define TORQUE_BIG_ENDIAN
|
||||
|
||||
#else
|
||||
# error "GCC: Unsupported Target CPU"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// macApplication.h
|
||||
// T3D
|
||||
//
|
||||
// Created by admin account on 2/1/08.
|
||||
// Copyright 2008 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface macApplication : NSApplication
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "macApplication.h"
|
||||
#include "windowManager/mac/macWindow.h"
|
||||
#include "windowManager/mac/macView.h"
|
||||
#include "console/console.h"
|
||||
|
||||
@implementation macApplication
|
||||
|
||||
- (void)sendEvent:(NSEvent*)theEvent
|
||||
{
|
||||
if([theEvent type] == NSKeyUp)
|
||||
{
|
||||
if([theEvent modifierFlags] & NSCommandKeyMask)
|
||||
{
|
||||
// These will normally be blocked, but we wants them!
|
||||
[[self delegate] keyUp:theEvent];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MacWindow* window = [(GGMacView*)[self delegate] torqueWindow];
|
||||
if(window && window->isFullscreen())
|
||||
{
|
||||
switch([theEvent type])
|
||||
{
|
||||
case NSLeftMouseDown:
|
||||
[[self delegate] mouseDown:theEvent];
|
||||
return;
|
||||
case NSRightMouseDown:
|
||||
[[self delegate] rightMouseDown:theEvent];
|
||||
return;
|
||||
case NSLeftMouseUp:
|
||||
[[self delegate] mouseUp:theEvent];
|
||||
return;
|
||||
case NSRightMouseUp:
|
||||
[[self delegate] rightMouseUp:theEvent];
|
||||
return;
|
||||
case NSMouseMoved:
|
||||
[[self delegate] mouseMoved:theEvent];
|
||||
return;
|
||||
case NSLeftMouseDragged:
|
||||
[[self delegate] mouseDragged:theEvent];
|
||||
return;
|
||||
case NSRightMouseDragged:
|
||||
[[self delegate] rightMouseDragged:theEvent];
|
||||
return;
|
||||
case NSScrollWheel:
|
||||
[[self delegate] scrollWheel:theEvent];
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[super sendEvent:theEvent];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -20,21 +20,29 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <mach/machine.h>
|
||||
#include <math.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#import <sys/types.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <mach/machine.h>
|
||||
#import <math.h>
|
||||
#import <CoreServices/CoreServices.h>
|
||||
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
#include "platform/platformAssert.h"
|
||||
#include "console/console.h"
|
||||
#include "core/stringTable.h"
|
||||
#import "platform/platformAssert.h"
|
||||
#import "console/console.h"
|
||||
#import "core/stringTable.h"
|
||||
#import "platform/platformCPUCount.h"
|
||||
|
||||
// Gestalt has been deprecated
|
||||
// we now have to use NSProcessInfo
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//recently removed in Xcode 8 - most likely don't need these anymore
|
||||
#ifndef CPUFAMILY_INTEL_YONAH
|
||||
#define CPUFAMILY_INTEL_YONAH 0x73d67300
|
||||
#endif
|
||||
|
||||
#ifndef CPUFAMILY_INTEL_MEROM
|
||||
#define CPUFAMILY_INTEL_MEROM 0x426f69ef
|
||||
#endif
|
||||
|
||||
// Original code by Sean O'Brien (http://www.garagegames.com/community/forums/viewthread/81815).
|
||||
|
||||
|
|
@ -82,14 +90,14 @@ int _getSysCTLvalue(const char key[], T * dest) {
|
|||
Platform::SystemInfo_struct Platform::SystemInfo;
|
||||
|
||||
#define BASE_MHZ_SPEED 0
|
||||
|
||||
//TODO update cpu list
|
||||
void Processor::init()
|
||||
{
|
||||
U32 procflags;
|
||||
int err, cpufam, cputype, cpusub;
|
||||
char buf[20];
|
||||
unsigned long lraw;
|
||||
unsigned long long llraw;
|
||||
char buf[255];
|
||||
U32 lraw;
|
||||
U64 llraw;
|
||||
|
||||
Con::printf( "System & Processor Information:" );
|
||||
|
||||
|
|
@ -111,13 +119,13 @@ void Processor::init()
|
|||
else
|
||||
Con::printf( " Mac OS Kernel version: %s", buf );
|
||||
|
||||
err = _getSysCTLvalue<unsigned long long>("hw.memsize", &llraw);
|
||||
err = _getSysCTLvalue<U64>("hw.memsize", &llraw);
|
||||
if (err)
|
||||
Con::printf( " Unable to determine amount of physical RAM\n" );
|
||||
else
|
||||
Con::printf( " Physical memory installed: %d MB", (llraw >> 20));
|
||||
|
||||
err = _getSysCTLvalue<unsigned long>("hw.usermem", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.usermem", &lraw);
|
||||
if (err)
|
||||
Con::printf( " Unable to determine available user address space\n");
|
||||
else
|
||||
|
|
@ -132,17 +140,17 @@ void Processor::init()
|
|||
cpufam = 0;
|
||||
cputype = 0;
|
||||
cpusub = 0;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.cpufamily", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.cpufamily", &lraw);
|
||||
if (err)
|
||||
Con::printf( " Unable to determine 'family' of CPU\n");
|
||||
else {
|
||||
cpufam = (int) lraw;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.cputype", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.cputype", &lraw);
|
||||
if (err)
|
||||
Con::printf( " Unable to determine CPU type\n");
|
||||
else {
|
||||
cputype = (int) lraw;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.cpusubtype", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.cpusubtype", &lraw);
|
||||
if (err)
|
||||
Con::printf( " Unable to determine CPU subtype\n");
|
||||
else
|
||||
|
|
@ -154,7 +162,7 @@ void Processor::init()
|
|||
|
||||
// The Gestalt version was known to have issues with some Processor Upgrade cards
|
||||
// but it is uncertain whether this version has similar issues.
|
||||
err = _getSysCTLvalue<unsigned long long>("hw.cpufrequency", &llraw);
|
||||
err = _getSysCTLvalue<U64>("hw.cpufrequency", &llraw);
|
||||
if (err) {
|
||||
llraw = BASE_MHZ_SPEED;
|
||||
Con::printf( " Unable to determine CPU Frequency. Defaulting to %d MHz\n", llraw);
|
||||
|
|
@ -167,7 +175,7 @@ void Processor::init()
|
|||
// Here's one that the original version of this routine couldn't do -- number
|
||||
// of processors (cores)
|
||||
U32 ncpu = 1;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.ncpu", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.ncpu", &lraw);
|
||||
if (err)
|
||||
Con::printf( " Unable to determine number of processor cores\n");
|
||||
else
|
||||
|
|
@ -184,29 +192,15 @@ void Processor::init()
|
|||
// and the Optional Capability flags (further down) should be more than enough.
|
||||
switch(cpufam)
|
||||
{
|
||||
case CPUFAMILY_POWERPC_G3:
|
||||
Platform::SystemInfo.processor.type = CPU_PowerPC_G3;
|
||||
Platform::SystemInfo.processor.name = StringTable->insert("PowerPC G3");
|
||||
break;
|
||||
case CPUFAMILY_POWERPC_G4:
|
||||
Platform::SystemInfo.processor.type = CPU_PowerPC_G3;
|
||||
Platform::SystemInfo.processor.name = StringTable->insert("PowerPC G4");
|
||||
break;
|
||||
case CPUFAMILY_POWERPC_G5:
|
||||
Platform::SystemInfo.processor.type = CPU_PowerPC_G3;
|
||||
Platform::SystemInfo.processor.name = StringTable->insert("PowerPC G5");
|
||||
break;
|
||||
case CPUFAMILY_INTEL_6_14:
|
||||
case CPUFAMILY_INTEL_YONAH:
|
||||
Platform::SystemInfo.processor.type = CPU_Intel_Core;
|
||||
if( ncpu == 2 )
|
||||
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core Duo");
|
||||
else
|
||||
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core");
|
||||
break;
|
||||
#ifdef CPUFAMILY_INTEL_6_23
|
||||
case CPUFAMILY_INTEL_6_23:
|
||||
#endif
|
||||
case CPUFAMILY_INTEL_6_15:
|
||||
case CPUFAMILY_INTEL_PENRYN:
|
||||
case CPUFAMILY_INTEL_MEROM:
|
||||
Platform::SystemInfo.processor.type = CPU_Intel_Core2;
|
||||
if( ncpu == 4 )
|
||||
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core 2 Quad");
|
||||
|
|
@ -214,12 +208,10 @@ void Processor::init()
|
|||
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core 2 Duo");
|
||||
break;
|
||||
|
||||
#ifdef CPUFAMILY_INTEL_6_26
|
||||
case CPUFAMILY_INTEL_6_26:
|
||||
case CPUFAMILY_INTEL_NEHALEM:
|
||||
Platform::SystemInfo.processor.type = CPU_Intel_Core2;
|
||||
Platform::SystemInfo.processor.name = StringTable->insert( "Intel 'Nehalem' Core Processor" );
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
// explain why we can't get the processor type.
|
||||
|
|
@ -237,31 +229,30 @@ void Processor::init()
|
|||
// actually supported/implemented by the processor: 0 = no, 1 = yes, others are undefined.
|
||||
procflags = 0;
|
||||
// Seriously this one should be an Assert()
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.floatingpoint", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.floatingpoint", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_FPU;
|
||||
// List of chip-specific features
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.mmx", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.mmx", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_MMX;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.sse", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.sse", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_SSE;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.sse2", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.sse2", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_SSE2;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.sse3", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.sse3", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_SSE3;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.supplementalsse3", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.supplementalsse3", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_SSE3xt;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.sse4_1", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.sse4_1", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_SSE4_1;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.sse4_2", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.optional.sse4_2", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_SSE4_2;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.optional.altivec", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_ALTIVEC;
|
||||
|
||||
// Finally some architecture-wide settings
|
||||
err = _getSysCTLvalue<unsigned long>("hw.ncpu", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.ncpu", &lraw);
|
||||
if ((err==0)&&(lraw>1)) procflags |= CPU_PROP_MP;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.cpu64bit_capable", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.cpu64bit_capable", &lraw);
|
||||
if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_64bit;
|
||||
err = _getSysCTLvalue<unsigned long>("hw.byteorder", &lraw);
|
||||
err = _getSysCTLvalue<U32>("hw.byteorder", &lraw);
|
||||
if ((err==0)&&(lraw==1234)) procflags |= CPU_PROP_LE;
|
||||
|
||||
Platform::SystemInfo.processor.properties = procflags;
|
||||
|
|
@ -275,11 +266,27 @@ void Processor::init()
|
|||
Con::printf( " SSE2 detected");
|
||||
if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3)
|
||||
Con::printf( " SSE3 detected");
|
||||
if (Platform::SystemInfo.processor.properties & CPU_PROP_ALTIVEC)
|
||||
Con::printf( " AltiVec detected");
|
||||
if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_1)
|
||||
Con::printf( " SSE4.1 detected");
|
||||
if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_2)
|
||||
Con::printf( " SSE4.2 detected");
|
||||
|
||||
Con::printf( "" );
|
||||
|
||||
// Trigger the signal
|
||||
Platform::SystemInfoReady.trigger();
|
||||
}
|
||||
|
||||
namespace CPUInfo {
|
||||
EConfig CPUCount(U32 &logical, U32 &numCores, U32 &numPhysical) {
|
||||
// todo properly implement this
|
||||
logical = [[NSProcessInfo processInfo] activeProcessorCount];
|
||||
numCores = [[NSProcessInfo processInfo] activeProcessorCount];
|
||||
numPhysical = [[NSProcessInfo processInfo] processorCount];
|
||||
|
||||
// todo check for hyperthreading
|
||||
if (numCores > 1)
|
||||
return CONFIG_MultiCoreAndHTNotCapable;
|
||||
return CONFIG_SingleCoreAndHTNotCapable;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include "platform/async/asyncUpdate.h"
|
||||
|
||||
|
||||
AsyncUpdateThread::AsyncUpdateThread( String name, AsyncUpdateList* updateList )
|
||||
: Parent( 0, 0, false, false ),
|
||||
mUpdateList( updateList ),
|
||||
mName( name )
|
||||
{
|
||||
MPCreateEvent( ( MPEventID* ) &mUpdateEvent );
|
||||
}
|
||||
|
||||
AsyncUpdateThread::~AsyncUpdateThread()
|
||||
{
|
||||
MPDeleteEvent( *( ( MPEventID* ) &mUpdateEvent ) ) ;
|
||||
}
|
||||
|
||||
void AsyncUpdateThread::_waitForEventAndReset()
|
||||
{
|
||||
MPWaitForEvent( *( ( MPEventID* ) &mUpdateEvent ), NULL, kDurationForever );
|
||||
}
|
||||
|
||||
void AsyncUpdateThread::triggerUpdate()
|
||||
{
|
||||
MPSetEvent( *( ( MPEventID* ) &mUpdateEvent ), 1 );
|
||||
}
|
||||
|
||||
AsyncPeriodicUpdateThread::AsyncPeriodicUpdateThread
|
||||
( String name, AsyncUpdateList* updateList, U32 intervalMS )
|
||||
: Parent( name, updateList ),
|
||||
mIntervalMS( intervalMS )
|
||||
{
|
||||
}
|
||||
|
||||
AsyncPeriodicUpdateThread::~AsyncPeriodicUpdateThread()
|
||||
{
|
||||
}
|
||||
|
||||
void AsyncPeriodicUpdateThread::_waitForEventAndReset()
|
||||
{
|
||||
MPWaitForEvent( *( ( MPEventID* ) &mUpdateEvent ), NULL, kDurationMillisecond * mIntervalMS );
|
||||
}
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformMac/macCarbFont.h"
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
#include "math/mRect.h"
|
||||
#include "console/console.h"
|
||||
#include "core/strings/unicode.h"
|
||||
#include "core/stringTable.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// New Unicode capable font class.
|
||||
PlatformFont *createPlatformFont(const char *name, U32 size, U32 charset /* = TGE_ANSI_CHARSET */)
|
||||
{
|
||||
PlatformFont *retFont = new MacCarbFont;
|
||||
|
||||
if(retFont->create(name, size, charset))
|
||||
return retFont;
|
||||
|
||||
delete retFont;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
MacCarbFont::MacCarbFont()
|
||||
{
|
||||
mStyle = NULL;
|
||||
mLayout = NULL;
|
||||
mColorSpace = NULL;
|
||||
}
|
||||
|
||||
MacCarbFont::~MacCarbFont()
|
||||
{
|
||||
// apple docs say we should dispose the layout first.
|
||||
ATSUDisposeTextLayout(mLayout);
|
||||
ATSUDisposeStyle(mStyle);
|
||||
CGColorSpaceRelease(mColorSpace);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MacCarbFont::create( const char* name, U32 size, U32 charset)
|
||||
{
|
||||
String nameStr = name;
|
||||
nameStr = nameStr.trim();
|
||||
|
||||
// create and cache the style and layout.
|
||||
// based on apple sample code at http://developer.apple.com/qa/qa2001/qa1027.html
|
||||
|
||||
// note: charset is ignored on mac. -- we don't need it to get the right chars.
|
||||
// But do we need it to translate encodings? hmm...
|
||||
|
||||
CFStringRef cfsName;
|
||||
ATSUFontID atsuFontID;
|
||||
ATSFontRef atsFontRef;
|
||||
Fixed atsuSize;
|
||||
ATSURGBAlphaColor black;
|
||||
ATSFontMetrics fontMetrics;
|
||||
U32 scaledSize;
|
||||
|
||||
bool isBold = false;
|
||||
bool isItalic = false;
|
||||
|
||||
bool haveModifier;
|
||||
do
|
||||
{
|
||||
haveModifier = false;
|
||||
if( nameStr.compare( "Bold", 4, String::NoCase | String::Right ) == 0 )
|
||||
{
|
||||
isBold = true;
|
||||
nameStr = nameStr.substr( 0, nameStr.length() - 4 ).trim();
|
||||
haveModifier = true;
|
||||
}
|
||||
if( nameStr.compare( "Italic", 6, String::NoCase | String::Right ) == 0 )
|
||||
{
|
||||
isItalic = true;
|
||||
nameStr = nameStr.substr( 0, nameStr.length() - 6 ).trim();
|
||||
haveModifier = true;
|
||||
}
|
||||
}
|
||||
while( haveModifier );
|
||||
|
||||
// Look up the font. We need it in 2 differnt formats, for differnt Apple APIs.
|
||||
cfsName = CFStringCreateWithCString( kCFAllocatorDefault, nameStr.c_str(), kCFStringEncodingUTF8);
|
||||
if(!cfsName)
|
||||
Con::errorf("Error: could not make a cfstring out of \"%s\" ",nameStr.c_str());
|
||||
|
||||
atsFontRef = ATSFontFindFromName( cfsName, kATSOptionFlagsDefault);
|
||||
atsuFontID = FMGetFontFromATSFontRef( atsFontRef);
|
||||
|
||||
// make sure we found it. ATSFontFindFromName() appears to return 0 if it cant find anything. Apple docs contain no info on error returns.
|
||||
if( !atsFontRef || !atsuFontID )
|
||||
{
|
||||
Con::errorf("MacCarbFont::create - could not load font -%s-",name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adjust the size. win dpi = 96, mac dpi = 72. 72/96 = .75
|
||||
// Interestingly enough, 0.75 is not what makes things the right size.
|
||||
scaledSize = size - 2 - (int)((float)size * 0.1);
|
||||
mSize = scaledSize;
|
||||
|
||||
// Set up the size and color. We send these to ATSUSetAttributes().
|
||||
atsuSize = IntToFixed(scaledSize);
|
||||
black.red = black.green = black.blue = black.alpha = 1.0;
|
||||
|
||||
// Three parrallel arrays for setting up font, size, and color attributes.
|
||||
ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag, kATSURGBAlphaColorTag};
|
||||
ByteCount theSizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(ATSURGBAlphaColor) };
|
||||
ATSUAttributeValuePtr theValues[] = { &atsuFontID, &atsuSize, &black };
|
||||
|
||||
// create and configure the style object.
|
||||
ATSUCreateStyle(&mStyle);
|
||||
ATSUSetAttributes( mStyle, 3, theTags, theSizes, theValues );
|
||||
|
||||
if( isBold )
|
||||
{
|
||||
ATSUAttributeTag tag = kATSUQDBoldfaceTag;
|
||||
ByteCount size = sizeof( Boolean );
|
||||
Boolean value = true;
|
||||
ATSUAttributeValuePtr valuePtr = &value;
|
||||
ATSUSetAttributes( mStyle, 1, &tag, &size, &valuePtr );
|
||||
}
|
||||
|
||||
if( isItalic )
|
||||
{
|
||||
ATSUAttributeTag tag = kATSUQDItalicTag;
|
||||
ByteCount size = sizeof( Boolean );
|
||||
Boolean value = true;
|
||||
ATSUAttributeValuePtr valuePtr = &value;
|
||||
ATSUSetAttributes( mStyle, 1, &tag, &size, &valuePtr );
|
||||
}
|
||||
|
||||
// create the layout object,
|
||||
ATSUCreateTextLayout(&mLayout);
|
||||
// we'll bind the layout to a bitmap context when we actually draw.
|
||||
// ATSUSetTextPointerLocation() - will set the text buffer
|
||||
// ATSUSetLayoutControls() - will set the cg context.
|
||||
|
||||
// get font metrics, save our baseline and height
|
||||
ATSFontGetHorizontalMetrics(atsFontRef, kATSOptionFlagsDefault, &fontMetrics);
|
||||
mBaseline = scaledSize * fontMetrics.ascent;
|
||||
mHeight = scaledSize * ( fontMetrics.ascent - fontMetrics.descent + fontMetrics.leading ) + 1;
|
||||
|
||||
// cache our grey color space, so we dont have to re create it every time.
|
||||
mColorSpace = CGColorSpaceCreateDeviceGray();
|
||||
|
||||
// and finally cache the font's name. We use this to cheat some antialiasing options below.
|
||||
mName = StringTable->insert(name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool MacCarbFont::isValidChar(const UTF8 *str) const
|
||||
{
|
||||
// since only low order characters are invalid, and since those characters
|
||||
// are single codeunits in UTF8, we can safely cast here.
|
||||
return isValidChar((UTF16)*str);
|
||||
}
|
||||
|
||||
bool MacCarbFont::isValidChar( const UTF16 ch) const
|
||||
{
|
||||
// We cut out the ASCII control chars here. Only printable characters are valid.
|
||||
// 0x20 == 32 == space
|
||||
if( ch < 0x20 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PlatformFont::CharInfo& MacCarbFont::getCharInfo(const UTF8 *str) const
|
||||
{
|
||||
return getCharInfo(oneUTF32toUTF16(oneUTF8toUTF32(str,NULL)));
|
||||
}
|
||||
|
||||
PlatformFont::CharInfo& MacCarbFont::getCharInfo(const UTF16 ch) const
|
||||
{
|
||||
// We use some static data here to avoid re allocating the same variable in a loop.
|
||||
// this func is primarily called by GFont::loadCharInfo(),
|
||||
Rect imageRect;
|
||||
CGContextRef imageCtx;
|
||||
U32 bitmapDataSize;
|
||||
ATSUTextMeasurement tbefore, tafter, tascent, tdescent;
|
||||
OSStatus err;
|
||||
|
||||
// 16 bit character buffer for the ATUSI calls.
|
||||
// -- hey... could we cache this at the class level, set style and loc *once*,
|
||||
// then just write to this buffer and clear the layout cache, to speed up drawing?
|
||||
static UniChar chUniChar[1];
|
||||
chUniChar[0] = ch;
|
||||
|
||||
// Declare and clear out the CharInfo that will be returned.
|
||||
static PlatformFont::CharInfo c;
|
||||
dMemset(&c, 0, sizeof(c));
|
||||
|
||||
// prep values for GFont::addBitmap()
|
||||
c.bitmapIndex = 0;
|
||||
c.xOffset = 0;
|
||||
c.yOffset = 0;
|
||||
|
||||
// put the text in the layout.
|
||||
// we've hardcoded a string length of 1 here, but this could work for longer strings... (hint hint)
|
||||
// note: ATSUSetTextPointerLocation() also clears the previous cached layout information.
|
||||
ATSUSetTextPointerLocation( mLayout, chUniChar, 0, 1, 1);
|
||||
ATSUSetRunStyle( mLayout, mStyle, 0,1);
|
||||
|
||||
// get the typographic bounds. this tells us how characters are placed relative to other characters.
|
||||
ATSUGetUnjustifiedBounds( mLayout, 0, 1, &tbefore, &tafter, &tascent, &tdescent);
|
||||
c.xIncrement = FixedToInt(tafter);
|
||||
|
||||
// find out how big of a bitmap we'll need.
|
||||
// as a bonus, we also get the origin where we should draw, encoded in the Rect.
|
||||
ATSUMeasureTextImage( mLayout, 0, 1, 0, 0, &imageRect);
|
||||
U32 xFudge = 2;
|
||||
U32 yFudge = 1;
|
||||
c.width = imageRect.right - imageRect.left + xFudge; // add 2 because small fonts don't always have enough room
|
||||
c.height = imageRect.bottom - imageRect.top + yFudge;
|
||||
c.xOrigin = imageRect.left; // dist x0 -> center line
|
||||
c.yOrigin = -imageRect.top; // dist y0 -> base line
|
||||
|
||||
// kick out early if the character is undrawable
|
||||
if( c.width == xFudge || c.height == yFudge)
|
||||
return c;
|
||||
|
||||
// allocate a greyscale bitmap and clear it.
|
||||
bitmapDataSize = c.width * c.height;
|
||||
c.bitmapData = new U8[bitmapDataSize];
|
||||
dMemset(c.bitmapData,0x00,bitmapDataSize);
|
||||
|
||||
// get a graphics context on the bitmap
|
||||
imageCtx = CGBitmapContextCreate( c.bitmapData, c.width, c.height, 8, c.width, mColorSpace, kCGImageAlphaNone);
|
||||
if(!imageCtx) {
|
||||
Con::errorf("Error: failed to create a graphics context on the CharInfo bitmap! Drawing a blank block.");
|
||||
c.xIncrement = c.width;
|
||||
dMemset(c.bitmapData,0x0F,bitmapDataSize);
|
||||
return c;
|
||||
}
|
||||
|
||||
// Turn off antialiasing for monospaced console fonts. yes, this is cheating.
|
||||
if(mSize < 12 && ( dStrstr(mName,"Monaco")!=NULL || dStrstr(mName,"Courier")!=NULL ))
|
||||
CGContextSetShouldAntialias(imageCtx, false);
|
||||
|
||||
// Set up drawing options for the context.
|
||||
// Since we're not going straight to the screen, we need to adjust accordingly
|
||||
CGContextSetShouldSmoothFonts(imageCtx, false);
|
||||
CGContextSetRenderingIntent(imageCtx, kCGRenderingIntentAbsoluteColorimetric);
|
||||
CGContextSetInterpolationQuality( imageCtx, kCGInterpolationNone);
|
||||
CGContextSetGrayFillColor( imageCtx, 1.0, 1.0);
|
||||
CGContextSetTextDrawingMode( imageCtx, kCGTextFill);
|
||||
|
||||
// tell ATSUI to substitute fonts as needed for missing glyphs
|
||||
ATSUSetTransientFontMatching(mLayout, true);
|
||||
|
||||
// set up three parrallel arrays for setting up attributes.
|
||||
// this is how most options in ATSUI are set, by passing arrays of options.
|
||||
ATSUAttributeTag theTags[] = { kATSUCGContextTag };
|
||||
ByteCount theSizes[] = { sizeof(CGContextRef) };
|
||||
ATSUAttributeValuePtr theValues[] = { &imageCtx };
|
||||
|
||||
// bind the layout to the context.
|
||||
ATSUSetLayoutControls( mLayout, 1, theTags, theSizes, theValues );
|
||||
|
||||
// Draw the character!
|
||||
int yoff = c.height < 3 ? 1 : 0; // kludge for 1 pixel high characters, such as '-' and '_'
|
||||
int xoff = 1;
|
||||
err = ATSUDrawText( mLayout, 0, 1, IntToFixed(-imageRect.left + xoff), IntToFixed(imageRect.bottom + yoff ) );
|
||||
CGContextRelease(imageCtx);
|
||||
|
||||
if(err != noErr) {
|
||||
Con::errorf("Error: could not draw the character! Drawing a blank box.");
|
||||
dMemset(c.bitmapData,0x0F,bitmapDataSize);
|
||||
}
|
||||
|
||||
|
||||
#if TORQUE_DEBUG
|
||||
// Con::printf("Font Metrics: Rect = %2i %2i %2i %2i Char= %C, 0x%x Size= %i, Baseline= %i, Height= %i",imageRect.top, imageRect.bottom, imageRect.left, imageRect.right,ch,ch, mSize,mBaseline, mHeight);
|
||||
// Con::printf("Font Bounds: left= %2i right= %2i Char= %C, 0x%x Size= %i",FixedToInt(tbefore), FixedToInt(tafter), ch,ch, mSize);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void PlatformFont::enumeratePlatformFonts( Vector< StringTableEntry >& fonts, UTF16* fontFamily )
|
||||
{
|
||||
if( fontFamily )
|
||||
{
|
||||
// Determine the font ID from the family name.
|
||||
|
||||
ATSUFontID fontID;
|
||||
if( ATSUFindFontFromName(
|
||||
fontFamily,
|
||||
dStrlen( fontFamily ) * 2,
|
||||
kFontFamilyName,
|
||||
kFontMicrosoftPlatform,
|
||||
kFontNoScriptCode,
|
||||
kFontNoLanguageCode, &fontID ) != kATSUInvalidFontErr )
|
||||
{
|
||||
// Get the number of fonts in the family.
|
||||
|
||||
ItemCount numFonts;
|
||||
ATSUCountFontNames( fontID, &numFonts );
|
||||
|
||||
// Read out font names.
|
||||
|
||||
U32 bufferSize = 512;
|
||||
char* buffer = ( char* ) dMalloc( bufferSize );
|
||||
|
||||
for( U32 i = 0; i < numFonts; ++ i )
|
||||
{
|
||||
for( U32 n = 0; n < 2; ++ n )
|
||||
{
|
||||
ByteCount actualNameLength;
|
||||
FontNameCode fontNameCode;
|
||||
FontPlatformCode fontPlatformCode;
|
||||
FontScriptCode fontScriptCode;
|
||||
FontLanguageCode fontLanguageCode;
|
||||
|
||||
if( ATSUGetIndFontName(
|
||||
fontID,
|
||||
i,
|
||||
bufferSize - 2,
|
||||
buffer,
|
||||
&actualNameLength,
|
||||
&fontNameCode,
|
||||
&fontPlatformCode,
|
||||
&fontScriptCode,
|
||||
&fontLanguageCode ) == noErr )
|
||||
{
|
||||
*( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0';
|
||||
char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer );
|
||||
fonts.push_back( StringTable->insert( utf8 ) );
|
||||
delete [] utf8;
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate larger buffer.
|
||||
|
||||
bufferSize = actualNameLength + 2;
|
||||
buffer = ( char* ) dRealloc( buffer, bufferSize );
|
||||
}
|
||||
}
|
||||
|
||||
dFree( buffer );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the number of installed fonts.
|
||||
|
||||
ItemCount numFonts;
|
||||
ATSUFontCount( &numFonts );
|
||||
|
||||
// Get all the font IDs.
|
||||
|
||||
ATSUFontID* fontIDs = new ATSUFontID[ numFonts ];
|
||||
if( ATSUGetFontIDs( fontIDs, numFonts, &numFonts ) == noErr )
|
||||
{
|
||||
U32 bufferSize = 512;
|
||||
char* buffer = ( char* ) dMalloc( bufferSize );
|
||||
|
||||
// Read all family names.
|
||||
|
||||
for( U32 i = 0; i < numFonts; ++ i )
|
||||
{
|
||||
for( U32 n = 0; n < 2; ++ n )
|
||||
{
|
||||
ByteCount actualNameLength;
|
||||
ItemCount fontIndex;
|
||||
|
||||
OSStatus result = ATSUFindFontName(
|
||||
fontIDs[ i ],
|
||||
kFontFamilyName,
|
||||
kFontMicrosoftPlatform,
|
||||
kFontNoScriptCode,
|
||||
kFontNoLanguageCode,
|
||||
bufferSize - 2,
|
||||
buffer,
|
||||
&actualNameLength,
|
||||
&fontIndex );
|
||||
|
||||
if( result == kATSUNoFontNameErr )
|
||||
break;
|
||||
else if( result == noErr )
|
||||
{
|
||||
*( ( UTF16* ) &buffer[ actualNameLength ] ) = '\0';
|
||||
char* utf8 = convertUTF16toUTF8( ( UTF16* ) buffer );
|
||||
StringTableEntry name = StringTable->insert( utf8 );
|
||||
delete [] utf8;
|
||||
|
||||
// Avoid duplicates.
|
||||
|
||||
bool duplicate = false;
|
||||
for( U32 i = 0, num = fonts.size(); i < num; ++ i )
|
||||
if( fonts[ i ] == name )
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if( !duplicate )
|
||||
fonts.push_back( name );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Allocate larger buffer.
|
||||
|
||||
bufferSize = actualNameLength + 2;
|
||||
buffer = ( char* ) dRealloc( buffer, bufferSize );
|
||||
}
|
||||
}
|
||||
|
||||
dFree( buffer );
|
||||
}
|
||||
|
||||
delete [] fontIDs;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The following code snippet demonstrates how to get the elusive GlyphIDs,
|
||||
// which are needed when you want to do various complex and arcane things
|
||||
// with ATSUI and CoreGraphics.
|
||||
//
|
||||
// ATSUGlyphInfoArray glyphinfoArr;
|
||||
// ATSUGetGlyphInfo( mLayout, kATSUFromTextBeginning, kATSUToTextEnd,sizeof(ATSUGlyphInfoArray), &glyphinfoArr);
|
||||
// ATSUGlyphInfo glyphinfo = glyphinfoArr.glyphs[0];
|
||||
// Con::printf(" Glyphinfo: screenX= %i, idealX=%f, deltaY=%f", glyphinfo.screenX, glyphinfo.idealX, glyphinfo.deltaY);
|
||||
|
|
@ -1,500 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "platform/platformInput.h"
|
||||
#include "console/console.h"
|
||||
#include "core/strings/unicode.h"
|
||||
#include "core/util/tVector.h"
|
||||
|
||||
// Static class variables:
|
||||
InputManager* Input::smManager;
|
||||
bool Input::smActive;
|
||||
U8 Input::smModifierKeys;
|
||||
InputEvent Input::smInputEvent;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Keycode mapping.
|
||||
|
||||
struct KeyCode
|
||||
{
|
||||
U32 mKeyCode;
|
||||
UniChar mCharLower;
|
||||
UniChar mCharUpper;
|
||||
|
||||
KeyCode( U32 keyCode )
|
||||
: mKeyCode( keyCode ) {}
|
||||
};
|
||||
|
||||
static KeyCode sOSToKeyCode[] =
|
||||
{
|
||||
KEY_A, // 0x00
|
||||
KEY_S, // 0x01
|
||||
KEY_D, // 0x02
|
||||
KEY_F, // 0x03
|
||||
KEY_H, // 0x04
|
||||
KEY_G, // 0x05
|
||||
KEY_Z, // 0x06
|
||||
KEY_X, // 0x07
|
||||
KEY_C, // 0x08
|
||||
KEY_V, // 0x09
|
||||
0, // 0x0A
|
||||
KEY_B, // 0x0B
|
||||
KEY_Q, // 0x0C
|
||||
KEY_W, // 0x0D
|
||||
KEY_E, // 0x0E
|
||||
KEY_R, // 0x0F
|
||||
KEY_Y, // 0x10
|
||||
KEY_T, // 0x11
|
||||
KEY_1, // 0x12
|
||||
KEY_2, // 0x13
|
||||
KEY_3, // 0x14
|
||||
KEY_4, // 0x15
|
||||
KEY_6, // 0x16
|
||||
KEY_5, // 0x17
|
||||
KEY_EQUALS, // 0x18
|
||||
KEY_9, // 0x19
|
||||
KEY_7, // 0x1A
|
||||
KEY_MINUS, // 0x1B
|
||||
KEY_8, // 0x1C
|
||||
KEY_0, // 0x1D
|
||||
KEY_RBRACKET, // 0x1E
|
||||
KEY_O, // 0x1F
|
||||
KEY_U, // 0x20
|
||||
KEY_LBRACKET, // 0x21
|
||||
KEY_I, // 0x22
|
||||
KEY_P, // 0x23
|
||||
KEY_RETURN, // 0x24
|
||||
KEY_L, // 0x25
|
||||
KEY_J, // 0x26
|
||||
KEY_APOSTROPHE, // 0x27
|
||||
KEY_K, // 0x28
|
||||
KEY_SEMICOLON, // 0x29
|
||||
KEY_BACKSLASH, // 0x2A
|
||||
KEY_COMMA, // 0x2B
|
||||
KEY_SLASH, // 0x2C
|
||||
KEY_N, // 0x2D
|
||||
KEY_M, // 0x2E
|
||||
KEY_PERIOD, // 0x2F
|
||||
KEY_TAB, // 0x30
|
||||
KEY_SPACE, // 0x31
|
||||
KEY_TILDE, // 0x32
|
||||
KEY_BACKSPACE, // 0x33
|
||||
0, // 0x34
|
||||
KEY_ESCAPE, // 0x35
|
||||
KEY_RALT, // 0x36
|
||||
KEY_LALT, // 0x37
|
||||
KEY_LSHIFT, // 0x38
|
||||
KEY_CAPSLOCK, // 0x39
|
||||
KEY_MAC_LOPT, // 0x3A
|
||||
KEY_LCONTROL, // 0x3B
|
||||
KEY_RSHIFT, // 0x3C
|
||||
KEY_MAC_ROPT, // 0x3D
|
||||
KEY_RCONTROL, // 0x3E
|
||||
0, // 0x3F
|
||||
0, // 0x40
|
||||
KEY_DECIMAL, // 0x41
|
||||
0, // 0x42
|
||||
KEY_MULTIPLY, // 0x43
|
||||
0, // 0x44
|
||||
KEY_ADD, // 0x45
|
||||
0, // 0x46
|
||||
KEY_NUMLOCK, // 0x47
|
||||
0, // 0x48
|
||||
0, // 0x49
|
||||
0, // 0x4A
|
||||
KEY_DIVIDE, // 0x4B
|
||||
KEY_NUMPADENTER, // 0x4C
|
||||
0, // 0x4D
|
||||
KEY_SUBTRACT, // 0x4E
|
||||
0, // 0x4F
|
||||
0, // 0x50
|
||||
KEY_SEPARATOR, // 0x51
|
||||
KEY_NUMPAD0, // 0x52
|
||||
KEY_NUMPAD1, // 0x53
|
||||
KEY_NUMPAD2, // 0x54
|
||||
KEY_NUMPAD3, // 0x55
|
||||
KEY_NUMPAD4, // 0x56
|
||||
KEY_NUMPAD5, // 0x57
|
||||
KEY_NUMPAD6, // 0x58
|
||||
KEY_NUMPAD7, // 0x59
|
||||
0, // 0x5A
|
||||
KEY_NUMPAD8, // 0x5B
|
||||
KEY_NUMPAD9, // 0x5C
|
||||
0, // 0x5D
|
||||
0, // 0x5E
|
||||
0, // 0x5F
|
||||
KEY_F5, // 0x60
|
||||
KEY_F6, // 0x61
|
||||
KEY_F7, // 0x62
|
||||
KEY_F3, // 0x63
|
||||
KEY_F8, // 0x64
|
||||
KEY_F9, // 0x65
|
||||
0, // 0x66
|
||||
KEY_F11, // 0x67
|
||||
0, // 0x68
|
||||
KEY_F13, // 0x69
|
||||
KEY_F16, // 0x6A
|
||||
KEY_F14, // 0x6B
|
||||
0, // 0x6C
|
||||
KEY_F10, // 0x6D
|
||||
0, // 0x6E
|
||||
KEY_F12, // 0x6F
|
||||
0, // 0x70
|
||||
KEY_F15, // 0x71
|
||||
KEY_INSERT, // 0x72
|
||||
KEY_HOME, // 0x73
|
||||
KEY_PAGE_UP, // 0x74
|
||||
KEY_DELETE, // 0x75
|
||||
KEY_F4, // 0x76
|
||||
KEY_END, // 0x77
|
||||
KEY_F2, // 0x78
|
||||
KEY_PAGE_DOWN, // 0x79
|
||||
KEY_F1, // 0x7A
|
||||
KEY_LEFT, // 0x7B
|
||||
KEY_RIGHT, // 0x7C
|
||||
KEY_DOWN, // 0x7D
|
||||
KEY_UP, // 0x7E
|
||||
};
|
||||
|
||||
static Vector< U8 > sKeyCodeToOS( __FILE__, __LINE__ );
|
||||
|
||||
#define NSShiftKeyMask ( 1 << 17 )
|
||||
|
||||
static KeyboardLayoutRef sKeyLayout;
|
||||
static SInt32 sKeyLayoutKind = -1;
|
||||
static SInt32 sKeyLayoutID = -1;
|
||||
static SInt32 sLastKeyLayoutID = -1;
|
||||
|
||||
static void GetKeyboardLayout()
|
||||
{
|
||||
KLGetCurrentKeyboardLayout( &sKeyLayout );
|
||||
KLGetKeyboardLayoutProperty( sKeyLayout, kKLKind, ( const void** ) &sKeyLayoutKind );
|
||||
KLGetKeyboardLayoutProperty( sKeyLayout, kKLIdentifier, ( const void** ) &sKeyLayoutID );
|
||||
}
|
||||
|
||||
static bool KeyboardLayoutHasChanged()
|
||||
{
|
||||
GetKeyboardLayout();
|
||||
return ( sKeyLayoutID != sLastKeyLayoutID );
|
||||
}
|
||||
|
||||
static UniChar OSKeyCodeToUnicode( UInt16 osKeyCode, bool shift = false )
|
||||
{
|
||||
// Translate the key code.
|
||||
|
||||
UniChar uniChar = 0;
|
||||
if( sKeyLayoutKind == kKLKCHRKind )
|
||||
{
|
||||
// KCHR mapping.
|
||||
|
||||
void* KCHRData;
|
||||
KLGetKeyboardLayoutProperty( sKeyLayout, kKLKCHRData, ( const void** ) & KCHRData );
|
||||
|
||||
UInt16 key = ( osKeyCode & 0x7f );
|
||||
if( shift )
|
||||
key |= NSShiftKeyMask;
|
||||
|
||||
UInt32 keyTranslateState = 0;
|
||||
UInt32 charCode = KeyTranslate( KCHRData, key, &keyTranslateState );
|
||||
charCode &= 0xff;
|
||||
|
||||
if( keyTranslateState == 0 && charCode )
|
||||
uniChar = charCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// UCHR mapping.
|
||||
|
||||
UCKeyboardLayout* uchrData;
|
||||
KLGetKeyboardLayoutProperty( sKeyLayout, kKLuchrData, ( const void** ) &uchrData );
|
||||
|
||||
UInt32 deadKeyState;
|
||||
UniCharCount actualStringLength;
|
||||
UniChar unicodeString[ 4 ];
|
||||
UCKeyTranslate( uchrData,
|
||||
osKeyCode,
|
||||
kUCKeyActionDown,
|
||||
( shift ? 0x02 : 0 ), // Oh yeah... Apple docs are fun...
|
||||
LMGetKbdType(),
|
||||
0,
|
||||
&deadKeyState,
|
||||
sizeof( unicodeString ) / sizeof( unicodeString[ 0 ] ),
|
||||
&actualStringLength,
|
||||
unicodeString );
|
||||
|
||||
if( actualStringLength )
|
||||
uniChar = unicodeString[ 0 ]; // Well, Unicode is something else, but...
|
||||
}
|
||||
|
||||
return uniChar;
|
||||
}
|
||||
|
||||
static void InitKeyCodeMapping()
|
||||
{
|
||||
const U32 numOSKeyCodes = sizeof( sOSToKeyCode ) / sizeof( sOSToKeyCode[ 0 ] );
|
||||
GetKeyboardLayout();
|
||||
sLastKeyLayoutID = sKeyLayoutID;
|
||||
|
||||
U32 maxKeyCode = 0;
|
||||
for( U32 i = 0; i < numOSKeyCodes; ++ i )
|
||||
{
|
||||
sOSToKeyCode[ i ].mCharLower = OSKeyCodeToUnicode( i, false );
|
||||
sOSToKeyCode[ i ].mCharUpper = OSKeyCodeToUnicode( i, true );
|
||||
|
||||
if( sOSToKeyCode[ i ].mKeyCode > maxKeyCode )
|
||||
maxKeyCode = sOSToKeyCode[ i ].mKeyCode;
|
||||
}
|
||||
|
||||
if( !sKeyCodeToOS.size() )
|
||||
{
|
||||
sKeyCodeToOS.setSize( maxKeyCode + 1 );
|
||||
dMemset( sKeyCodeToOS.address(), 0, sKeyCodeToOS.size() );
|
||||
for( U32 i = 0; i < numOSKeyCodes; ++ i )
|
||||
sKeyCodeToOS[ sOSToKeyCode[ i ].mKeyCode ] = i;
|
||||
}
|
||||
}
|
||||
|
||||
U8 TranslateOSKeyCode(U8 macKeycode)
|
||||
{
|
||||
AssertWarn(macKeycode < sizeof(sOSToKeyCode) / sizeof(sOSToKeyCode[0]), avar("TranslateOSKeyCode - could not translate code %i", macKeycode));
|
||||
if(macKeycode >= sizeof(sOSToKeyCode) / sizeof(sOSToKeyCode[0]))
|
||||
return KEY_NULL;
|
||||
|
||||
return sOSToKeyCode[ macKeycode ].mKeyCode;
|
||||
}
|
||||
|
||||
U8 TranslateKeyCodeToOS( U8 keycode )
|
||||
{
|
||||
return sKeyCodeToOS[ keycode ];
|
||||
}
|
||||
|
||||
#pragma mark ---- Clipboard functions ----
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* Platform::getClipboard()
|
||||
{
|
||||
// mac clipboards can contain multiple items,
|
||||
// and each item can be in several differnt flavors,
|
||||
// such as unicode or plaintext or pdf, etc.
|
||||
// scan through the clipboard, and return the 1st piece of actual text.
|
||||
ScrapRef clip;
|
||||
char *retBuf = "";
|
||||
OSStatus err = noErr;
|
||||
char *dataBuf = "";
|
||||
|
||||
// get a local ref to the system clipboard
|
||||
GetScrapByName( kScrapClipboardScrap, kScrapGetNamedScrap, &clip );
|
||||
|
||||
|
||||
// First try to get unicode data, then try to get plain text data.
|
||||
Size dataSize = 0;
|
||||
bool plaintext = false;
|
||||
err = GetScrapFlavorSize(clip, kScrapFlavorTypeUnicode, &dataSize);
|
||||
if( err != noErr || dataSize <= 0)
|
||||
{
|
||||
Con::errorf("some error getting unicode clip");
|
||||
plaintext = true;
|
||||
err = GetScrapFlavorSize(clip, kScrapFlavorTypeText, &dataSize);
|
||||
}
|
||||
|
||||
// kick out if we don't have any data.
|
||||
if( err != noErr || dataSize <= 0)
|
||||
{
|
||||
Con::errorf("no data, kicking out. size = %i",dataSize);
|
||||
return "";
|
||||
}
|
||||
|
||||
if( err == noErr && dataSize > 0 )
|
||||
{
|
||||
// ok, we've got something! allocate a buffer and copy it in.
|
||||
char buf[dataSize+1];
|
||||
dMemset(buf, 0, dataSize+1);
|
||||
dataBuf = buf;
|
||||
// plain text needs no conversion.
|
||||
// unicode data needs to be converted to normalized utf-8 format.
|
||||
if(plaintext)
|
||||
{
|
||||
GetScrapFlavorData(clip, kScrapFlavorTypeText, &dataSize, &buf);
|
||||
retBuf = Con::getReturnBuffer(dataSize + 1);
|
||||
dMemcpy(retBuf,buf,dataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetScrapFlavorData(clip, kScrapFlavorTypeUnicode, &dataSize, &buf);
|
||||
|
||||
// normalize
|
||||
CFStringRef cfBuf = CFStringCreateWithBytes(NULL, (const UInt8*)buf, dataSize, kCFStringEncodingUnicode, false);
|
||||
CFMutableStringRef normBuf = CFStringCreateMutableCopy(NULL, 0, cfBuf);
|
||||
CFStringNormalize(normBuf, kCFStringNormalizationFormC);
|
||||
|
||||
// convert to utf-8
|
||||
U32 normBufLen = CFStringGetLength(normBuf);
|
||||
U32 retBufLen = CFStringGetMaximumSizeForEncoding(normBufLen,kCFStringEncodingUTF8) + 1; // +1 for the null terminator
|
||||
retBuf = Con::getReturnBuffer(retBufLen);
|
||||
CFStringGetCString( normBuf, retBuf, retBufLen, kCFStringEncodingUTF8);
|
||||
dataSize = retBufLen;
|
||||
}
|
||||
|
||||
// manually null terminate, just in case.
|
||||
retBuf[dataSize] = 0;
|
||||
}
|
||||
|
||||
// return the data, or the empty string if we did not find any data.
|
||||
return retBuf;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Platform::setClipboard(const char *text)
|
||||
{
|
||||
ScrapRef clip;
|
||||
U32 textSize;
|
||||
OSStatus err = noErr;
|
||||
|
||||
// make sure we have something to copy
|
||||
textSize = dStrlen(text);
|
||||
if(textSize == 0)
|
||||
return false;
|
||||
|
||||
// get a local ref to the system clipboard
|
||||
GetScrapByName( kScrapClipboardScrap, kScrapClearNamedScrap, &clip );
|
||||
|
||||
// put the data on the clipboard as text
|
||||
err = PutScrapFlavor( clip, kScrapFlavorTypeText, kScrapFlavorMaskNone, textSize, text);
|
||||
|
||||
// put the data on the clipboard as unicode
|
||||
const UTF16 *utf16Data = convertUTF8toUTF16(text);
|
||||
err |= PutScrapFlavor( clip, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
|
||||
dStrlen(utf16Data) * sizeof(UTF16), utf16Data);
|
||||
delete [] utf16Data;
|
||||
|
||||
// and see if we were successful.
|
||||
if( err == noErr )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Input::init()
|
||||
{
|
||||
smManager = NULL;
|
||||
smActive = false;
|
||||
|
||||
InitKeyCodeMapping();
|
||||
}
|
||||
|
||||
U16 Input::getKeyCode( U16 asciiCode )
|
||||
{
|
||||
if( KeyboardLayoutHasChanged() )
|
||||
InitKeyCodeMapping();
|
||||
|
||||
for( U32 i = 0; i < ( sizeof( sOSToKeyCode ) / sizeof( sOSToKeyCode[ 0 ] ) ); ++ i )
|
||||
if( sOSToKeyCode[ i ].mCharLower == asciiCode
|
||||
|| sOSToKeyCode[ i ].mCharUpper == asciiCode )
|
||||
return sOSToKeyCode[ i ].mKeyCode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U16 Input::getAscii( U16 keyCode, KEY_STATE keyState )
|
||||
{
|
||||
GetKeyboardLayout();
|
||||
return OSKeyCodeToUnicode( TranslateKeyCodeToOS( keyCode ), ( keyState == STATE_UPPER ? true : false ) );
|
||||
}
|
||||
|
||||
void Input::destroy()
|
||||
{
|
||||
}
|
||||
|
||||
bool Input::enable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Input::disable()
|
||||
{
|
||||
}
|
||||
|
||||
void Input::activate()
|
||||
{
|
||||
}
|
||||
|
||||
void Input::deactivate()
|
||||
{
|
||||
}
|
||||
|
||||
bool Input::isEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Input::isActive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Input::process()
|
||||
{
|
||||
}
|
||||
|
||||
InputManager* Input::getManager()
|
||||
{
|
||||
return smManager;
|
||||
}
|
||||
|
||||
ConsoleFunction( enableMouse, bool, 1, 1, "enableMouse()" )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ConsoleFunction( disableMouse, void, 1, 1, "disableMouse()" )
|
||||
{
|
||||
}
|
||||
|
||||
ConsoleFunction( echoInputState, void, 1, 1, "echoInputState()" )
|
||||
{
|
||||
}
|
||||
|
||||
ConsoleFunction( toggleInputState, void, 1, 1, "toggleInputState()" )
|
||||
{
|
||||
}
|
||||
|
||||
ConsoleFunction( isJoystickDetected, bool, 1, 1, "Always false on the MAC." )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ConsoleFunction( getJoystickAxes, const char*, 2, 2, "(handle instance)" )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
ConsoleFunction( deactivateKeyboard, void, 1, 1, "deactivateKeyboard();")
|
||||
{
|
||||
// these are only useful on the windows side. They deal with some vagaries of win32 DirectInput.
|
||||
}
|
||||
|
||||
ConsoleFunction( activateKeyboard, void, 1, 1, "activateKeyboard();")
|
||||
{
|
||||
// these are only useful on the windows side. They deal with some vagaries of win32 DirectInput.
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "platform/platform.h"
|
||||
#include "platform/threads/mutex.h"
|
||||
#include "platform/threads/thread.h"
|
||||
// TODO: examine & dump errno if pthread_* funcs fail. ( only in debug build )
|
||||
|
||||
class PlatformMutexData
|
||||
{
|
||||
public:
|
||||
pthread_mutex_t mMutex;
|
||||
bool locked;
|
||||
U32 lockedByThread;
|
||||
};
|
||||
|
||||
Mutex::Mutex(void)
|
||||
{
|
||||
int ok;
|
||||
mData = new PlatformMutexData;
|
||||
pthread_mutexattr_t attr;
|
||||
ok = pthread_mutexattr_init(&attr);
|
||||
ok = pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
ok = pthread_mutex_init(&(mData->mMutex),&attr);
|
||||
AssertFatal(ok == 0, "Mutex() failed: pthread_mutex_init() failed.");
|
||||
|
||||
mData->locked = false;
|
||||
mData->lockedByThread = 0;
|
||||
}
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
int ok;
|
||||
ok = pthread_mutex_destroy( &(mData->mMutex) );
|
||||
AssertFatal(ok == 0, "~Mutex() failed: pthread_mutex_destroy() failed.");
|
||||
|
||||
delete mData;
|
||||
}
|
||||
|
||||
bool Mutex::lock( bool block)
|
||||
{
|
||||
int ok;
|
||||
|
||||
if(block)
|
||||
{
|
||||
ok = pthread_mutex_lock( &(mData->mMutex) );
|
||||
AssertFatal( ok != EINVAL, "Mutex::lockMutex() failed: invalid mutex.");
|
||||
AssertFatal( ok != EDEADLK, "Mutex::lockMutex() failed: system detected a deadlock!");
|
||||
AssertFatal( ok == 0, "Mutex::lockMutex() failed: pthread_mutex_lock() failed -- unknown reason.");
|
||||
}
|
||||
else {
|
||||
ok = pthread_mutex_trylock( &(mData->mMutex) );
|
||||
// returns EBUSY if mutex was locked by another thread,
|
||||
// returns EINVAL if mutex was not a valid mutex pointer,
|
||||
// returns 0 if lock succeeded.
|
||||
AssertFatal( ok != EINVAL, "Mutex::lockMutex(non blocking) failed: invalid mutex.");
|
||||
if( ok != 0 )
|
||||
return false;
|
||||
|
||||
AssertFatal( ok == 0, "Mutex::lockMutex(non blocking) failed: pthread_mutex_trylock() failed -- unknown reason.");
|
||||
}
|
||||
|
||||
mData->locked = true;
|
||||
mData->lockedByThread = ThreadManager::getCurrentThreadId();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mutex::unlock()
|
||||
{
|
||||
int ok;
|
||||
ok = pthread_mutex_unlock( &(mData->mMutex) );
|
||||
AssertFatal( ok == 0, "Mutex::unlockMutex() failed: pthread_mutex_unlock() failed.");
|
||||
mData->locked = false;
|
||||
mData->lockedByThread = 0;
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
#include "platform/event.h"
|
||||
#include "core/util/journal/process.h"
|
||||
#include "console/console.h"
|
||||
|
||||
void Platform::postQuitMessage(const U32 in_quitVal)
|
||||
{
|
||||
Process::requestShutdown();
|
||||
}
|
||||
|
||||
void Platform::debugBreak()
|
||||
{
|
||||
DebugStr("\pDEBUG_BREAK!");
|
||||
}
|
||||
|
||||
void Platform::forceShutdown(S32 returnValue)
|
||||
{
|
||||
exit(returnValue);
|
||||
}
|
||||
|
||||
void Platform::restartInstance()
|
||||
{
|
||||
// execl() leaves open file descriptors open, that's the main reason it's not
|
||||
// used here. We want to start fresh.
|
||||
// get the path to the torque executable
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||
CFURLRef execURL = CFBundleCopyExecutableURL(mainBundle);
|
||||
CFStringRef execString = CFURLCopyFileSystemPath(execURL, kCFURLPOSIXPathStyle);
|
||||
|
||||
// append ampersand so that we can launch without blocking.
|
||||
// encase in quotes so that spaces in the path are accepted.
|
||||
CFMutableStringRef mut = CFStringCreateMutableCopy(NULL, 0, execString);
|
||||
CFStringInsert(mut, 0, CFSTR("\""));
|
||||
CFStringAppend(mut, CFSTR("\" & "));
|
||||
|
||||
U32 len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(mut), kCFStringEncodingUTF8);
|
||||
char *execCString = new char[len+1];
|
||||
CFStringGetCString(mut, execCString, len, kCFStringEncodingUTF8);
|
||||
execCString[len] = '\0';
|
||||
|
||||
Con::printf("---- %s -----",execCString);
|
||||
system(execCString);
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include "platform/platform.h"
|
||||
#include "platform/threads/semaphore.h"
|
||||
|
||||
class PlatformSemaphore
|
||||
{
|
||||
public:
|
||||
MPSemaphoreID mSemaphore;
|
||||
|
||||
PlatformSemaphore(S32 initialCount)
|
||||
{
|
||||
OSStatus err = MPCreateSemaphore(S32_MAX - 1, initialCount, &mSemaphore);
|
||||
AssertFatal(err == noErr, "Failed to allocate semaphore!");
|
||||
}
|
||||
|
||||
~PlatformSemaphore()
|
||||
{
|
||||
OSStatus err = MPDeleteSemaphore(mSemaphore);
|
||||
AssertFatal(err == noErr, "Failed to destroy semaphore!");
|
||||
}
|
||||
};
|
||||
|
||||
Semaphore::Semaphore(S32 initialCount)
|
||||
{
|
||||
mData = new PlatformSemaphore(initialCount);
|
||||
}
|
||||
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
AssertFatal(mData && mData->mSemaphore, "Semaphore::destroySemaphore: invalid semaphore");
|
||||
delete mData;
|
||||
}
|
||||
|
||||
bool Semaphore::acquire( bool block, S32 timeoutMS )
|
||||
{
|
||||
AssertFatal(mData && mData->mSemaphore, "Semaphore::acquireSemaphore: invalid semaphore");
|
||||
OSStatus err = MPWaitOnSemaphore(mData->mSemaphore, block ? ( timeoutMS == -1 ? kDurationForever : timeoutMS ) : kDurationImmediate);
|
||||
return(err == noErr);
|
||||
}
|
||||
|
||||
void Semaphore::release()
|
||||
{
|
||||
AssertFatal(mData && mData->mSemaphore, "Semaphore::releaseSemaphore: invalid semaphore");
|
||||
OSStatus err = MPSignalSemaphore(mData->mSemaphore);
|
||||
AssertFatal(err == noErr, "Failed to release semaphore!");
|
||||
}
|
||||
|
|
@ -1,159 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <pthread.h>
|
||||
#include "platform/threads/thread.h"
|
||||
#include "platform/threads/semaphore.h"
|
||||
#include "platform/threads/mutex.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
class PlatformThreadData
|
||||
{
|
||||
public:
|
||||
ThreadRunFunction mRunFunc;
|
||||
void* mRunArg;
|
||||
Thread* mThread;
|
||||
Semaphore mGateway; // default count is 1
|
||||
U32 mThreadID;
|
||||
bool mDead;
|
||||
};
|
||||
|
||||
ThreadManager::MainThreadId ThreadManager::smMainThreadId;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Function: ThreadRunHandler
|
||||
// Summary: Calls Thread::run() with the thread's specified run argument.
|
||||
// Neccesary because Thread::run() is provided as a non-threaded
|
||||
// way to execute the thread's run function. So we have to keep
|
||||
// track of the thread's lock here.
|
||||
static void *ThreadRunHandler(void * arg)
|
||||
{
|
||||
PlatformThreadData *mData = reinterpret_cast<PlatformThreadData*>(arg);
|
||||
Thread *thread = mData->mThread;
|
||||
|
||||
// mThreadID is filled in twice, once here and once in pthread_create().
|
||||
// We fill in mThreadID here as well as in pthread_create() because addThread()
|
||||
// can execute before pthread_create() returns and sets mThreadID.
|
||||
// The value from pthread_create() and pthread_self() are guaranteed to be equivalent (but not identical)
|
||||
mData->mThreadID = ThreadManager::getCurrentThreadId();
|
||||
|
||||
ThreadManager::addThread(thread);
|
||||
thread->run(mData->mRunArg);
|
||||
ThreadManager::removeThread(thread);
|
||||
|
||||
bool autoDelete = thread->autoDelete;
|
||||
|
||||
mData->mThreadID = 0;
|
||||
mData->mDead = true;
|
||||
mData->mGateway.release();
|
||||
|
||||
if( autoDelete )
|
||||
delete thread;
|
||||
|
||||
// return value for pthread lib's benefit
|
||||
return NULL;
|
||||
// the end of this function is where the created pthread will die.
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Thread::Thread(ThreadRunFunction func, void* arg, bool start_thread, bool autodelete)
|
||||
{
|
||||
AssertFatal( !start_thread, "Thread::Thread() - auto-starting threads from ctor has been disallowed since the run() method is virtual" );
|
||||
|
||||
mData = new PlatformThreadData;
|
||||
mData->mRunFunc = func;
|
||||
mData->mRunArg = arg;
|
||||
mData->mThread = this;
|
||||
mData->mThreadID = 0;
|
||||
mData->mDead = false;
|
||||
autoDelete = autodelete;
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
stop();
|
||||
if( isAlive() )
|
||||
join();
|
||||
|
||||
delete mData;
|
||||
}
|
||||
|
||||
void Thread::start( void* arg )
|
||||
{
|
||||
// cause start to block out other pthreads from using this Thread,
|
||||
// at least until ThreadRunHandler exits.
|
||||
mData->mGateway.acquire();
|
||||
|
||||
// reset the shouldStop flag, so we'll know when someone asks us to stop.
|
||||
shouldStop = false;
|
||||
|
||||
mData->mDead = false;
|
||||
|
||||
if( !mData->mRunArg )
|
||||
mData->mRunArg = arg;
|
||||
|
||||
pthread_create((pthread_t*)(&mData->mThreadID), NULL, ThreadRunHandler, mData);
|
||||
}
|
||||
|
||||
bool Thread::join()
|
||||
{
|
||||
// not using pthread_join here because pthread_join cannot deal
|
||||
// with multiple simultaneous calls.
|
||||
|
||||
mData->mGateway.acquire();
|
||||
AssertFatal( !isAlive(), "Thread::join() - thread not dead after join()" );
|
||||
mData->mGateway.release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Thread::run(void* arg)
|
||||
{
|
||||
if(mData->mRunFunc)
|
||||
mData->mRunFunc(arg);
|
||||
}
|
||||
|
||||
bool Thread::isAlive()
|
||||
{
|
||||
return ( !mData->mDead );
|
||||
}
|
||||
|
||||
U32 Thread::getId()
|
||||
{
|
||||
return mData->mThreadID;
|
||||
}
|
||||
|
||||
void Thread::_setName( const char* )
|
||||
{
|
||||
// Not supported. Wading through endless lists of Thread-1, Thread-2, Thread-3, ... trying to find
|
||||
// that one thread you are looking for is just so much fun.
|
||||
}
|
||||
|
||||
U32 ThreadManager::getCurrentThreadId()
|
||||
{
|
||||
return (U32)pthread_self();
|
||||
}
|
||||
|
||||
bool ThreadManager::compare(U32 threadId_1, U32 threadId_2)
|
||||
{
|
||||
return pthread_equal((_opaque_pthread_t*)threadId_1, (_opaque_pthread_t*)threadId_2);
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
|
||||
void Platform::outputDebugString( const char *string, ... )
|
||||
{
|
||||
#ifdef TORQUE_DEBUG
|
||||
char buffer[ 2048 ];
|
||||
|
||||
va_list args;
|
||||
va_start( args, string );
|
||||
|
||||
dVsprintf( buffer, sizeof( buffer ), string, args );
|
||||
va_end( args );
|
||||
|
||||
U32 length = strlen( buffer );
|
||||
if( length == ( sizeof( buffer ) - 1 ) )
|
||||
length --;
|
||||
|
||||
buffer[ length ] = '\n';
|
||||
buffer[ length + 1 ] = '\0';
|
||||
|
||||
fputs( buffer, stderr );
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark ---- Platform utility funcs ----
|
||||
//--------------------------------------
|
||||
// Web browser function:
|
||||
//--------------------------------------
|
||||
bool Platform::openWebBrowser( const char* webAddress )
|
||||
{
|
||||
OSStatus err;
|
||||
CFURLRef url = CFURLCreateWithBytes(NULL,(UInt8*)webAddress,dStrlen(webAddress),kCFStringEncodingASCII,NULL);
|
||||
err = LSOpenCFURLRef(url,NULL);
|
||||
CFRelease(url);
|
||||
|
||||
return(err==noErr);
|
||||
}
|
||||
|
||||
|
|
@ -1,623 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Get our GL header included before Apple's
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
// Don't include Apple's
|
||||
#define __gl_h_
|
||||
|
||||
#include "platform/tmm_off.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "platform/tmm_on.h"
|
||||
|
||||
#include "console/simBase.h"
|
||||
#include "platform/nativeDialogs/fileDialog.h"
|
||||
#include "platform/threads/mutex.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "math/mMath.h"
|
||||
#include "core/strings/unicode.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "platform/threads/thread.h"
|
||||
#include "platform/threads/semaphore.h"
|
||||
|
||||
class FileDialogOpaqueData
|
||||
{
|
||||
public:
|
||||
Semaphore *sem;
|
||||
FileDialogOpaqueData() { sem = new Semaphore(0); }
|
||||
~FileDialogOpaqueData() { delete sem; }
|
||||
};
|
||||
|
||||
class FileDialogFileExtList
|
||||
{
|
||||
public:
|
||||
Vector<UTF8*> list;
|
||||
UTF8* data;
|
||||
|
||||
FileDialogFileExtList(const char* exts) { data = dStrdup(exts); }
|
||||
~FileDialogFileExtList() { SAFE_DELETE(data); }
|
||||
};
|
||||
|
||||
class FileDialogFileTypeList
|
||||
{
|
||||
public:
|
||||
UTF8* filterData;
|
||||
Vector<UTF8*> names;
|
||||
Vector<FileDialogFileExtList*> exts;
|
||||
bool any;
|
||||
|
||||
FileDialogFileTypeList(const char* filter) { filterData = dStrdup(filter); any = false;}
|
||||
~FileDialogFileTypeList()
|
||||
{
|
||||
SAFE_DELETE(filterData);
|
||||
for(U32 i = 0; i < exts.size(); i++)
|
||||
delete exts[i];
|
||||
}
|
||||
};
|
||||
|
||||
#undef new
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PlatformFileDlgData Implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
FileDialogData::FileDialogData()
|
||||
{
|
||||
// Default Path
|
||||
//
|
||||
// Try to provide consistent experience by recalling the last file path
|
||||
// - else
|
||||
// Default to Working Directory if last path is not set or is invalid
|
||||
mDefaultPath = StringTable->insert( Con::getVariable("Tools::FileDialogs::LastFilePath") );
|
||||
if( mDefaultPath == StringTable->lookup("") || !Platform::isDirectory( mDefaultPath ) )
|
||||
mDefaultPath = Platform::getCurrentDirectory();
|
||||
|
||||
mDefaultFile = StringTable->insert("");
|
||||
mFilters = StringTable->insert("");
|
||||
mFile = StringTable->insert("");
|
||||
mTitle = StringTable->insert("");
|
||||
|
||||
mStyle = 0;
|
||||
|
||||
mOpaqueData = new FileDialogOpaqueData();
|
||||
|
||||
}
|
||||
FileDialogData::~FileDialogData()
|
||||
{
|
||||
delete mOpaqueData;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FileDialog Implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
IMPLEMENT_CONOBJECT(FileDialog);
|
||||
|
||||
FileDialog::FileDialog() : mData()
|
||||
{
|
||||
// Default to File Must Exist Open Dialog style
|
||||
mData.mStyle = FileDialogData::FDS_OPEN | FileDialogData::FDS_MUSTEXIST;
|
||||
mChangePath = false;
|
||||
}
|
||||
|
||||
FileDialog::~FileDialog()
|
||||
{
|
||||
}
|
||||
|
||||
void FileDialog::initPersistFields()
|
||||
{
|
||||
// why is this stuff buried in another class?
|
||||
addProtectedField("DefaultPath", TypeString, Offset(mData.mDefaultPath, FileDialog), &setDefaultPath, &defaultProtectedGetFn, "Default Path when Dialog is shown");
|
||||
addProtectedField("DefaultFile", TypeString, Offset(mData.mDefaultFile, FileDialog), &setDefaultFile, &defaultProtectedGetFn, "Default File when Dialog is shown");
|
||||
addProtectedField("FileName", TypeString, Offset(mData.mFile, FileDialog), &setFile, &defaultProtectedGetFn, "Default File when Dialog is shown");
|
||||
addProtectedField("Filters", TypeString, Offset(mData.mFilters, FileDialog), &setFilters, &defaultProtectedGetFn, "Default File when Dialog is shown");
|
||||
addField("Title", TypeString, Offset(mData.mTitle, FileDialog), "Default File when Dialog is shown");
|
||||
addProtectedField("ChangePath", TypeBool, Offset(mChangePath, FileDialog), &setChangePath, &getChangePath, "True/False whether to set the working directory to the directory returned by the dialog" );
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
|
||||
static FileDialogFileExtList* _MacCarbGetFileExtensionsFromString(const char* filter)
|
||||
{
|
||||
FileDialogFileExtList* list = new FileDialogFileExtList(filter);
|
||||
|
||||
char* token = list->data;
|
||||
char* place = list->data;
|
||||
|
||||
for( ; *place; place++)
|
||||
{
|
||||
if(*place != ';')
|
||||
continue;
|
||||
|
||||
*place = '\0';
|
||||
|
||||
list->list.push_back(token);
|
||||
|
||||
++place;
|
||||
token = place;
|
||||
}
|
||||
// last token
|
||||
list->list.push_back(token);
|
||||
|
||||
return list;
|
||||
|
||||
}
|
||||
|
||||
static FileDialogFileTypeList* _MacCarbGetFileTypesFromString(const char* filter)
|
||||
{
|
||||
FileDialogFileTypeList &list = *(new FileDialogFileTypeList(filter));
|
||||
|
||||
char* token = list.filterData;
|
||||
char* place = list.filterData;
|
||||
|
||||
// scan the filter list until we hit a null.
|
||||
// when we see the separator '|', replace it with a null, and save the token
|
||||
// format is description|extension|description|extension
|
||||
bool isDesc = true;
|
||||
for( ; *place; place++)
|
||||
{
|
||||
if(*place != '|')
|
||||
continue;
|
||||
|
||||
*place = '\0';
|
||||
|
||||
if(isDesc)
|
||||
list.names.push_back(token);
|
||||
else
|
||||
{
|
||||
// detect *.*
|
||||
if(dStrstr((const char*)token, "*.*"))
|
||||
list.any = true;
|
||||
|
||||
list.exts.push_back(_MacCarbGetFileExtensionsFromString(token));
|
||||
}
|
||||
|
||||
|
||||
isDesc = !isDesc;
|
||||
++place;
|
||||
token = place;
|
||||
}
|
||||
list.exts.push_back(_MacCarbGetFileExtensionsFromString(token));
|
||||
|
||||
return &list;
|
||||
}
|
||||
|
||||
static NSArray* _MacCocoaCreateAndRunSavePanel(FileDialogData &mData)
|
||||
{
|
||||
NSSavePanel* panel = [NSSavePanel savePanel];
|
||||
|
||||
// User freedom niceties
|
||||
[panel setCanCreateDirectories:YES];
|
||||
[panel setCanSelectHiddenExtension:YES];
|
||||
[panel setTreatsFilePackagesAsDirectories:YES];
|
||||
|
||||
NSString *initialFile = [[NSString stringWithUTF8String:mData.mDefaultFile] lastPathComponent];
|
||||
|
||||
// we only use mDefaultDir if mDefault path is not set.
|
||||
NSString *dir;
|
||||
if(dStrlen(mData.mDefaultPath) < 1)
|
||||
dir = [[NSString stringWithUTF8String:mData.mDefaultFile] stringByDeletingLastPathComponent];
|
||||
else
|
||||
dir = [NSString stringWithUTF8String: mData.mDefaultPath];
|
||||
[panel setDirectory:dir];
|
||||
|
||||
// todo: move file type handling to an accessory view.
|
||||
// parse file types
|
||||
FileDialogFileTypeList *fTypes = _MacCarbGetFileTypesFromString(mData.mFilters);
|
||||
|
||||
// fill an array with the possible file types
|
||||
NSMutableArray* types = [NSMutableArray arrayWithCapacity:10];
|
||||
for(U32 i = 0; i < fTypes->exts.size(); i++)
|
||||
{
|
||||
for(U32 j = 0; j < fTypes->exts[i]->list.size(); j++)
|
||||
{
|
||||
char* ext = fTypes->exts[i]->list[j];
|
||||
if(ext)
|
||||
{
|
||||
if(dStrlen(ext) == 0)
|
||||
continue;
|
||||
if(dStrncmp(ext, "*.*", 3) == 0)
|
||||
continue;
|
||||
if(dStrncmp(ext, "*.", 2) == 0)
|
||||
ext+=2;
|
||||
|
||||
[types addObject:[NSString stringWithUTF8String:ext]];
|
||||
}
|
||||
}
|
||||
}
|
||||
if([types count] > 0)
|
||||
[panel setAllowedFileTypes:types];
|
||||
|
||||
// if any file type was *.*, user may select any file type.
|
||||
[panel setAllowsOtherFileTypes:fTypes->any];
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Display the panel, enter a modal loop. This blocks.
|
||||
//---------------------------------------------------------------------------
|
||||
U32 button = [panel runModalForDirectory:dir file:initialFile];
|
||||
|
||||
// return the file name
|
||||
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10];
|
||||
if(button != NSFileHandlingPanelCancelButton)
|
||||
[array addObject:[panel filename]];
|
||||
|
||||
delete fTypes;
|
||||
|
||||
return array;
|
||||
|
||||
// TODO: paxorr: show as sheet
|
||||
// crashes when we try to display the window as a sheet. Not sure why.
|
||||
// the sheet is instantly dismissed, and crashes as it's dismissing itself.
|
||||
// here's the code snippet to get an nswindow from our carbon WindowRef
|
||||
//NSWindow *nsAppWindow = [[NSWindow alloc] initWithWindowRef:platState.appWindow];
|
||||
}
|
||||
|
||||
NSArray* _MacCocoaCreateAndRunOpenPanel(FileDialogData &mData)
|
||||
{
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
|
||||
// User freedom niceties
|
||||
[panel setCanCreateDirectories:YES];
|
||||
[panel setCanSelectHiddenExtension:YES];
|
||||
[panel setTreatsFilePackagesAsDirectories:YES];
|
||||
|
||||
[panel setAllowsMultipleSelection:(mData.mStyle & FileDialogData::FDS_MULTIPLEFILES)];
|
||||
|
||||
//
|
||||
bool chooseDir = (mData.mStyle & FileDialogData::FDS_BROWSEFOLDER);
|
||||
[panel setCanChooseFiles: !chooseDir ];
|
||||
[panel setCanChooseDirectories: chooseDir ];
|
||||
if(chooseDir)
|
||||
{
|
||||
[panel setPrompt:@"Choose"];
|
||||
[panel setTitle:@"Choose Folder"];
|
||||
}
|
||||
|
||||
NSString *initialFile = [[NSString stringWithUTF8String:mData.mDefaultFile] lastPathComponent];
|
||||
|
||||
// we only use mDefaultDir if mDefault path is not set.
|
||||
NSString *dir;
|
||||
if(dStrlen(mData.mDefaultPath) < 1)
|
||||
dir = [[NSString stringWithUTF8String:mData.mDefaultFile] stringByDeletingLastPathComponent];
|
||||
else
|
||||
dir = [NSString stringWithUTF8String: mData.mDefaultPath];
|
||||
[panel setDirectory:dir];
|
||||
|
||||
// todo: move file type handling to an accessory view.
|
||||
// parse file types
|
||||
FileDialogFileTypeList *fTypes = _MacCarbGetFileTypesFromString(mData.mFilters);
|
||||
|
||||
// fill an array with the possible file types
|
||||
NSMutableArray* types = [NSMutableArray arrayWithCapacity:10];
|
||||
for(U32 i = 0; i < fTypes->exts.size(); i++)
|
||||
{
|
||||
for(U32 j = 0; j < fTypes->exts[i]->list.size(); j++)
|
||||
{
|
||||
char* ext = fTypes->exts[i]->list[j];
|
||||
if(ext)
|
||||
{
|
||||
if(dStrncmp(ext, "*.", 2) == 0)
|
||||
ext+=2;
|
||||
|
||||
[types addObject:[NSString stringWithUTF8String:ext]];
|
||||
}
|
||||
}
|
||||
}
|
||||
if([types count] > 0)
|
||||
[panel setAllowedFileTypes:types];
|
||||
|
||||
// if any file type was *.*, user may select any file type.
|
||||
[panel setAllowsOtherFileTypes:fTypes->any];
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Display the panel, enter a modal loop. This blocks.
|
||||
//---------------------------------------------------------------------------
|
||||
U32 button = [panel runModalForDirectory:dir file:initialFile ];
|
||||
|
||||
// return the file name
|
||||
NSMutableArray *array = [NSMutableArray arrayWithCapacity:10];
|
||||
if(button != NSFileHandlingPanelCancelButton)
|
||||
[array addObject:[panel filename]];
|
||||
|
||||
delete fTypes;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
void MacCarbShowDialog(void* dialog)
|
||||
{
|
||||
FileDialog* d = static_cast<FileDialog*>(dialog);
|
||||
d->Execute();
|
||||
}
|
||||
//
|
||||
// Execute Method
|
||||
//
|
||||
bool FileDialog::Execute()
|
||||
{
|
||||
// if(! ThreadManager::isCurrentThread(platState.firstThreadId))
|
||||
// {
|
||||
// MacCarbSendTorqueEventToMain(kEventTorqueModalDialog,this);
|
||||
// mData.mOpaqueData->sem->acquire();
|
||||
// return;
|
||||
// }
|
||||
|
||||
NSArray* nsFileArray;
|
||||
if(mData.mStyle & FileDialogData::FDS_OPEN)
|
||||
nsFileArray = _MacCocoaCreateAndRunOpenPanel(mData);
|
||||
else if(mData.mStyle & FileDialogData::FDS_SAVE)
|
||||
nsFileArray = _MacCocoaCreateAndRunSavePanel(mData);
|
||||
else
|
||||
{
|
||||
Con::errorf("Bad File Dialog Setup.");
|
||||
mData.mOpaqueData->sem->release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if([nsFileArray count] == 0)
|
||||
return false;
|
||||
|
||||
if(! (mData.mStyle & FileDialogData::FDS_MULTIPLEFILES) && [nsFileArray count] >= 1)
|
||||
{
|
||||
const UTF8* f = [(NSString*)[nsFileArray objectAtIndex:0] UTF8String];
|
||||
mData.mFile = StringTable->insert(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(U32 i = 0; i < [nsFileArray count]; i++)
|
||||
{
|
||||
const UTF8* f = [(NSString*)[nsFileArray objectAtIndex:i] UTF8String];
|
||||
setDataField(StringTable->insert("files"), Con::getIntArg(i), StringTable->insert(f));
|
||||
}
|
||||
setDataField(StringTable->insert("fileCount"), NULL, Con::getIntArg([nsFileArray count]));
|
||||
}
|
||||
mData.mOpaqueData->sem->release();
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
ConsoleMethod( FileDialog, Execute, bool, 2, 2, "%fileDialog.Execute();" )
|
||||
{
|
||||
return object->Execute();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dialog Filters
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FileDialog::setFilters(void* obj, const char* index, const char* data)
|
||||
{
|
||||
// Will do validate on write at some point.
|
||||
if( !data )
|
||||
return true;
|
||||
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Default Path Property - String Validated on Write
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FileDialog::setDefaultPath(void* obj, const char* index, const char* data)
|
||||
{
|
||||
|
||||
if( !data )
|
||||
return true;
|
||||
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Default File Property - String Validated on Write
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FileDialog::setDefaultFile(void* obj, const char* index, const char* data)
|
||||
{
|
||||
if( !data )
|
||||
return true;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// ChangePath Property - Change working path on successful file selection
|
||||
//-----------------------------------------------------------------------------
|
||||
bool FileDialog::setChangePath(void* obj, const char* index, const char* data)
|
||||
{
|
||||
bool bChangePath = dAtob( data );
|
||||
|
||||
FileDialog *pDlg = static_cast<FileDialog*>( obj );
|
||||
|
||||
if( bChangePath )
|
||||
pDlg->mData.mStyle |= FileDialogData::FDS_CHANGEPATH;
|
||||
else
|
||||
pDlg->mData.mStyle &= ~FileDialogData::FDS_CHANGEPATH;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const char* FileDialog::getChangePath(void* obj, const char* data)
|
||||
{
|
||||
FileDialog *pDlg = static_cast<FileDialog*>( obj );
|
||||
if( pDlg->mData.mStyle & FileDialogData::FDS_CHANGEPATH )
|
||||
return StringTable->insert("true");
|
||||
else
|
||||
return StringTable->insert("false");
|
||||
}
|
||||
|
||||
bool FileDialog::setFile(void* obj, const char* index, const char* data)
|
||||
{
|
||||
return false;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OpenFileDialog Implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
OpenFileDialog::OpenFileDialog()
|
||||
{
|
||||
// Default File Must Exist
|
||||
mData.mStyle = FileDialogData::FDS_OPEN | FileDialogData::FDS_MUSTEXIST;
|
||||
}
|
||||
|
||||
OpenFileDialog::~OpenFileDialog()
|
||||
{
|
||||
mMustExist = true;
|
||||
mMultipleFiles = false;
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(OpenFileDialog);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Console Properties
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpenFileDialog::initPersistFields()
|
||||
{
|
||||
addProtectedField("MustExist", TypeBool, Offset(mMustExist, OpenFileDialog), &setMustExist, &getMustExist, "True/False whether the file returned must exist or not" );
|
||||
addProtectedField("MultipleFiles", TypeBool, Offset(mMultipleFiles, OpenFileDialog), &setMultipleFiles, &getMultipleFiles, "True/False whether multiple files may be selected and returned or not" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// File Must Exist - Boolean
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OpenFileDialog::setMustExist(void* obj, const char* index, const char* data)
|
||||
{
|
||||
bool bMustExist = dAtob( data );
|
||||
|
||||
OpenFileDialog *pDlg = static_cast<OpenFileDialog*>( obj );
|
||||
|
||||
if( bMustExist )
|
||||
pDlg->mData.mStyle |= FileDialogData::FDS_MUSTEXIST;
|
||||
else
|
||||
pDlg->mData.mStyle &= ~FileDialogData::FDS_MUSTEXIST;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const char* OpenFileDialog::getMustExist(void* obj, const char* data)
|
||||
{
|
||||
OpenFileDialog *pDlg = static_cast<OpenFileDialog*>( obj );
|
||||
if( pDlg->mData.mStyle & FileDialogData::FDS_MUSTEXIST )
|
||||
return StringTable->insert("true");
|
||||
else
|
||||
return StringTable->insert("false");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Can Select Multiple Files - Boolean
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OpenFileDialog::setMultipleFiles(void* obj, const char* index, const char* data)
|
||||
{
|
||||
bool bMustExist = dAtob( data );
|
||||
|
||||
OpenFileDialog *pDlg = static_cast<OpenFileDialog*>( obj );
|
||||
|
||||
if( bMustExist )
|
||||
pDlg->mData.mStyle |= FileDialogData::FDS_MULTIPLEFILES;
|
||||
else
|
||||
pDlg->mData.mStyle &= ~FileDialogData::FDS_MULTIPLEFILES;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const char* OpenFileDialog::getMultipleFiles(void* obj, const char* data)
|
||||
{
|
||||
OpenFileDialog *pDlg = static_cast<OpenFileDialog*>( obj );
|
||||
if( pDlg->mData.mStyle & FileDialogData::FDS_MULTIPLEFILES )
|
||||
return StringTable->insert("true");
|
||||
else
|
||||
return StringTable->insert("false");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SaveFileDialog Implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
SaveFileDialog::SaveFileDialog()
|
||||
{
|
||||
// Default File Must Exist
|
||||
mData.mStyle = FileDialogData::FDS_SAVE | FileDialogData::FDS_OVERWRITEPROMPT;
|
||||
mOverwritePrompt = true;
|
||||
}
|
||||
|
||||
SaveFileDialog::~SaveFileDialog()
|
||||
{
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(SaveFileDialog);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Console Properties
|
||||
//-----------------------------------------------------------------------------
|
||||
void SaveFileDialog::initPersistFields()
|
||||
{
|
||||
addProtectedField("OverwritePrompt", TypeBool, Offset(mOverwritePrompt, SaveFileDialog), &setOverwritePrompt, &getOverwritePrompt, "True/False whether the dialog should prompt before accepting an existing file name" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Prompt on Overwrite - Boolean
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SaveFileDialog::setOverwritePrompt(void* obj, const char* index, const char* data)
|
||||
{
|
||||
bool bOverwrite = dAtob( data );
|
||||
|
||||
SaveFileDialog *pDlg = static_cast<SaveFileDialog*>( obj );
|
||||
|
||||
if( bOverwrite )
|
||||
pDlg->mData.mStyle |= FileDialogData::FDS_OVERWRITEPROMPT;
|
||||
else
|
||||
pDlg->mData.mStyle &= ~FileDialogData::FDS_OVERWRITEPROMPT;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const char* SaveFileDialog::getOverwritePrompt(void* obj, const char* data)
|
||||
{
|
||||
SaveFileDialog *pDlg = static_cast<SaveFileDialog*>( obj );
|
||||
if( pDlg->mData.mStyle & FileDialogData::FDS_OVERWRITEPROMPT )
|
||||
return StringTable->insert("true");
|
||||
else
|
||||
return StringTable->insert("false");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// OpenFolderDialog Implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
OpenFolderDialog::OpenFolderDialog()
|
||||
{
|
||||
mData.mStyle = FileDialogData::FDS_OPEN | FileDialogData::FDS_OVERWRITEPROMPT | FileDialogData::FDS_BROWSEFOLDER;
|
||||
|
||||
mMustExistInDir = "";
|
||||
}
|
||||
|
||||
IMPLEMENT_CONOBJECT(OpenFolderDialog);
|
||||
|
||||
void OpenFolderDialog::initPersistFields()
|
||||
{
|
||||
addField("fileMustExist", TypeFilename, Offset(mMustExistInDir, OpenFolderDialog), "File that must in selected folder for it to be valid");
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
#include <unistd.h>
|
||||
#include "platform/platform.h"
|
||||
#include "console/console.h"
|
||||
#include "core/stringTable.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include "platform/threads/thread.h"
|
||||
|
||||
#pragma mark ---- Various Directories ----
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* Platform::getUserDataDirectory()
|
||||
{
|
||||
// application support directory is most in line with the current usages of this function.
|
||||
// this may change with later usage
|
||||
// perhaps the user data directory should be pref-controlled?
|
||||
NSString *nsDataDir = [@"~/Library/Application Support/" stringByStandardizingPath];
|
||||
return StringTable->insert([nsDataDir UTF8String]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* Platform::getUserHomeDirectory()
|
||||
{
|
||||
return StringTable->insert([[@"~/" stringByStandardizingPath] UTF8String]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
StringTableEntry osGetTemporaryDirectory()
|
||||
{
|
||||
NSString *tdir = NSTemporaryDirectory();
|
||||
const char *path = [tdir UTF8String];
|
||||
return StringTable->insert(path);
|
||||
}
|
||||
|
||||
#pragma mark ---- Administrator ----
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Platform::getUserIsAdministrator()
|
||||
{
|
||||
// if we can write to /Library, we're probably an admin
|
||||
// HACK: this is not really very good, because people can chmod Library.
|
||||
return (access("/Library", W_OK) == 0);
|
||||
}
|
||||
|
||||
#pragma mark ---- Cosmetic ----
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Platform::displaySplashWindow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Platform::closeSplashWindow()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma mark ---- File IO ----
|
||||
//-----------------------------------------------------------------------------
|
||||
bool dPathCopy(const char* source, const char* dest, bool nooverwrite)
|
||||
{
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSString *nsource = [[NSString stringWithUTF8String:source] stringByStandardizingPath];
|
||||
NSString *ndest = [[NSString stringWithUTF8String:dest] stringByStandardizingPath];
|
||||
NSString *ndestFolder = [ndest stringByDeletingLastPathComponent];
|
||||
|
||||
if(! [manager fileExistsAtPath:nsource])
|
||||
{
|
||||
Con::errorf("dPathCopy: no file exists at %s",source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( [manager fileExistsAtPath:ndest] )
|
||||
{
|
||||
if(nooverwrite)
|
||||
{
|
||||
Con::errorf("dPathCopy: file already exists at %s",dest);
|
||||
return false;
|
||||
}
|
||||
Con::warnf("Deleting files at path: %s", dest);
|
||||
bool deleted = [manager removeFileAtPath:ndest handler:nil];
|
||||
if(!deleted)
|
||||
{
|
||||
Con::errorf("Copy failed! Could not delete files at path: %s", dest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if([manager fileExistsAtPath:ndestFolder] == NO)
|
||||
{
|
||||
ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash
|
||||
Platform::createPath([ndestFolder UTF8String]);
|
||||
}
|
||||
|
||||
bool ret = [manager copyPath:nsource toPath:ndest handler:nil];
|
||||
|
||||
[pool release];
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool dFileRename(const char *source, const char *dest)
|
||||
{
|
||||
if(source == NULL || dest == NULL)
|
||||
return false;
|
||||
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
|
||||
NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)];
|
||||
NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)];
|
||||
|
||||
if(! [manager fileExistsAtPath:nsource])
|
||||
{
|
||||
Con::errorf("dFileRename: no file exists at %s",source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( [manager fileExistsAtPath:ndest] )
|
||||
{
|
||||
Con::warnf("dFileRename: Deleting files at path: %s", dest);
|
||||
}
|
||||
|
||||
bool ret = [manager movePath:nsource toPath:ndest handler:nil];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark ---- ShellExecute ----
|
||||
class ExecuteThread : public Thread
|
||||
{
|
||||
const char* zargs;
|
||||
const char* directory;
|
||||
const char* executable;
|
||||
public:
|
||||
ExecuteThread(const char *_executable, const char *_args /* = NULL */, const char *_directory /* = NULL */) : Thread(0, NULL, false, true)
|
||||
{
|
||||
zargs = dStrdup(_args);
|
||||
directory = dStrdup(_directory);
|
||||
executable = dStrdup(_executable);
|
||||
start();
|
||||
}
|
||||
|
||||
virtual void run(void* arg);
|
||||
};
|
||||
|
||||
static char* _unDoubleQuote(char* arg)
|
||||
{
|
||||
U32 len = dStrlen(arg);
|
||||
if(!len)
|
||||
return arg;
|
||||
|
||||
if(arg[0] == '"' && arg[len-1] == '"')
|
||||
{
|
||||
arg[len - 1] = '\0';
|
||||
return arg + 1;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
void ExecuteThread::run(void* arg)
|
||||
{
|
||||
// 2k should be enough. if it's not, bail.
|
||||
// char buf[2048];
|
||||
// U32 len = dSprintf(buf, sizeof(buf), "%s %s -workingDir %s", executable, args, directory);
|
||||
// if( len >= sizeof(buf))
|
||||
// {
|
||||
// Con::errorf("shellExecute(): the command was too long, and won't be run.");
|
||||
// return;
|
||||
// }
|
||||
// // calls sh with the string and blocks until the command returns.
|
||||
// system(buf);
|
||||
|
||||
// FIXME: there is absolutely no error checking in here.
|
||||
printf("creating nstask\n");
|
||||
NSTask *aTask = [[NSTask alloc] init];
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
|
||||
// scan the args list, breaking it up, space delimited, backslash escaped.
|
||||
U32 len = dStrlen(zargs);
|
||||
char args[len+1];
|
||||
dStrncpy(args, zargs, len+1);
|
||||
char *lastarg = args;
|
||||
bool escaping = false;
|
||||
for(int i = 0; i< len; i++)
|
||||
{
|
||||
char c = args[i];
|
||||
// a backslash escapes the next character
|
||||
if(escaping)
|
||||
continue;
|
||||
if(c == '\\')
|
||||
escaping = true;
|
||||
|
||||
if(c == ' ')
|
||||
{
|
||||
args[i] = '\0';
|
||||
if(*lastarg)
|
||||
[array addObject:[NSString stringWithUTF8String: _unDoubleQuote(lastarg)]];
|
||||
lastarg = args + i + 1;
|
||||
}
|
||||
}
|
||||
if(*lastarg)
|
||||
[array addObject:[NSString stringWithUTF8String: _unDoubleQuote(lastarg)]];
|
||||
|
||||
[aTask setArguments: array];
|
||||
|
||||
[aTask setCurrentDirectoryPath:[NSString stringWithUTF8String: this->directory]];
|
||||
[aTask setLaunchPath:[NSString stringWithUTF8String:executable]];
|
||||
[aTask launch];
|
||||
[aTask waitUntilExit];
|
||||
U32 ret = [aTask terminationStatus];
|
||||
Con::executef("onExecuteDone", Con::getIntArg(ret));
|
||||
printf("done nstask\n");
|
||||
}
|
||||
|
||||
ConsoleFunction(shellExecute, bool, 2, 4, "(executable, [args], [directory])")
|
||||
{
|
||||
ExecuteThread *et = new ExecuteThread(argv[1], argc > 2 ? argv[2] : NULL, argc > 3 ? argv[3] : NULL);
|
||||
TORQUE_UNUSED(et);
|
||||
return true; // Bug: BPNC error: need feedback on whether the command was sucessful
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/types.h"
|
||||
#include "platform/platformDlibrary.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
class MacDLibrary : public DLibrary
|
||||
{
|
||||
void* _handle;
|
||||
public:
|
||||
MacDLibrary();
|
||||
~MacDLibrary();
|
||||
bool open(const char* file);
|
||||
void close();
|
||||
void* bind(const char* name);
|
||||
};
|
||||
|
||||
MacDLibrary::MacDLibrary()
|
||||
{
|
||||
_handle = NULL;
|
||||
}
|
||||
|
||||
MacDLibrary::~MacDLibrary()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
bool MacDLibrary::open(const char* file)
|
||||
{
|
||||
Platform::getExecutablePath();
|
||||
_handle = dlopen(file, RTLD_LAZY | RTLD_LOCAL);
|
||||
return _handle != NULL;
|
||||
}
|
||||
|
||||
void* MacDLibrary::bind(const char* name)
|
||||
{
|
||||
return _handle ? dlsym(_handle, name) : NULL;
|
||||
}
|
||||
|
||||
void MacDLibrary::close()
|
||||
{
|
||||
if(_handle)
|
||||
dlclose(_handle);
|
||||
|
||||
_handle = NULL;
|
||||
}
|
||||
|
||||
DLibraryRef OsLoadLibrary(const char* file)
|
||||
{
|
||||
MacDLibrary* library = new MacDLibrary();
|
||||
if(!library->open(file))
|
||||
{
|
||||
delete library;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return library;
|
||||
}
|
||||
|
|
@ -20,49 +20,30 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <stdio.h>
|
||||
#import <stdlib.h>
|
||||
#import <errno.h>
|
||||
#import <utime.h>
|
||||
#import <sys/time.h>
|
||||
#import <sys/types.h>
|
||||
#import <dirent.h>
|
||||
#import <unistd.h>
|
||||
#import <sys/stat.h>
|
||||
|
||||
#include <utime.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// Get our GL header included before Apple's
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
// Don't include Apple's
|
||||
#define __gl_h_
|
||||
|
||||
#include "platform/tmm_off.h"
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "platform/tmm_on.h"
|
||||
|
||||
#include "core/fileio.h"
|
||||
#include "core/util/tVector.h"
|
||||
#include "core/stringTable.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#include "console/console.h"
|
||||
#include "platform/profiler.h"
|
||||
#include "cinterface/cinterface.h";
|
||||
|
||||
#include "core/volume.h"
|
||||
#import "core/fileio.h"
|
||||
#import "core/util/tVector.h"
|
||||
#import "core/stringTable.h"
|
||||
#import "core/strings/stringFunctions.h"
|
||||
#import "console/console.h"
|
||||
#import "platform/profiler.h"
|
||||
#import "cinterface/cinterface.h";
|
||||
#import "core/volume.h"
|
||||
|
||||
//TODO: file io still needs some work...
|
||||
|
||||
#define MAX_MAC_PATH_LONG 2048
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#if defined(TORQUE_OS_MAC)
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#else
|
||||
#include <CFBundle.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool dFileDelete(const char * name)
|
||||
{
|
||||
if(!name )
|
||||
|
|
@ -84,6 +65,78 @@ bool dFileTouch(const char *path)
|
|||
// set file at path's modification and access times to now.
|
||||
return( utimes( path, NULL) == 0); // utimes returns 0 on success.
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool dPathCopy(const char* source, const char* dest, bool nooverwrite)
|
||||
{
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSString *nsource = [[NSString stringWithUTF8String:source] stringByStandardizingPath];
|
||||
NSString *ndest = [[NSString stringWithUTF8String:dest] stringByStandardizingPath];
|
||||
NSString *ndestFolder = [ndest stringByDeletingLastPathComponent];
|
||||
|
||||
if(! [manager fileExistsAtPath:nsource])
|
||||
{
|
||||
Con::errorf("dPathCopy: no file exists at %s",source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( [manager fileExistsAtPath:ndest] )
|
||||
{
|
||||
if(nooverwrite)
|
||||
{
|
||||
Con::errorf("dPathCopy: file already exists at %s",dest);
|
||||
return false;
|
||||
}
|
||||
Con::warnf("Deleting files at path: %s", dest);
|
||||
bool deleted = [manager removeFileAtPath:ndest handler:nil];
|
||||
if(!deleted)
|
||||
{
|
||||
Con::errorf("Copy failed! Could not delete files at path: %s", dest);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if([manager fileExistsAtPath:ndestFolder] == NO)
|
||||
{
|
||||
ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash
|
||||
Platform::createPath([ndestFolder UTF8String]);
|
||||
}
|
||||
|
||||
bool ret = [manager copyPath:nsource toPath:ndest handler:nil];
|
||||
|
||||
[pool release];
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool dFileRename(const char *source, const char *dest)
|
||||
{
|
||||
if(source == NULL || dest == NULL)
|
||||
return false;
|
||||
|
||||
NSFileManager *manager = [NSFileManager defaultManager];
|
||||
|
||||
NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)];
|
||||
NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)];
|
||||
|
||||
if(! [manager fileExistsAtPath:nsource])
|
||||
{
|
||||
Con::errorf("dFileRename: no file exists at %s",source);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( [manager fileExistsAtPath:ndest] )
|
||||
{
|
||||
Con::warnf("dFileRename: Deleting files at path: %s", dest);
|
||||
}
|
||||
|
||||
bool ret = [manager movePath:nsource toPath:ndest handler:nil];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructors & Destructor
|
||||
|
|
@ -121,7 +174,7 @@ File::~File()
|
|||
// Sets capability appropriate to the openMode.
|
||||
// Returns the currentStatus of the file.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::open(const char *filename, const AccessMode openMode)
|
||||
File::FileStatus File::open(const char *filename, const AccessMode openMode)
|
||||
{
|
||||
if (dStrlen(filename) > MAX_MAC_PATH_LONG)
|
||||
Con::warnf("File::open: Filename length is pretty long...");
|
||||
|
|
@ -203,7 +256,7 @@ U32 File::getPosition() const
|
|||
//
|
||||
// Returns the currentStatus of the file.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::setPosition(S32 position, bool absolutePos)
|
||||
File::FileStatus File::setPosition(S32 position, bool absolutePos)
|
||||
{
|
||||
AssertFatal(Closed != currentStatus, "File::setPosition: file closed");
|
||||
AssertFatal(handle != NULL, "File::setPosition: invalid file handle");
|
||||
|
|
@ -271,7 +324,7 @@ U32 File::getSize() const
|
|||
// It is an error to flush a read-only file.
|
||||
// Returns the currentStatus of the file.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::flush()
|
||||
File::FileStatus File::flush()
|
||||
{
|
||||
AssertFatal(Closed != currentStatus, "File::flush: file closed");
|
||||
AssertFatal(handle != NULL, "File::flush: invalid file handle");
|
||||
|
|
@ -288,7 +341,7 @@ File::Status File::flush()
|
|||
//
|
||||
// Returns the currentStatus
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::close()
|
||||
File::FileStatus File::close()
|
||||
{
|
||||
// check if it's already closed...
|
||||
if (Closed == currentStatus)
|
||||
|
|
@ -307,7 +360,7 @@ File::Status File::close()
|
|||
//-----------------------------------------------------------------------------
|
||||
// Self-explanatory.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::getStatus() const
|
||||
File::FileStatus File::getStatus() const
|
||||
{
|
||||
return currentStatus;
|
||||
}
|
||||
|
|
@ -315,7 +368,7 @@ File::Status File::getStatus() const
|
|||
//-----------------------------------------------------------------------------
|
||||
// Sets and returns the currentStatus when an error has been encountered.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::setStatus()
|
||||
File::FileStatus File::setStatus()
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
|
|
@ -336,7 +389,7 @@ File::Status File::setStatus()
|
|||
//-----------------------------------------------------------------------------
|
||||
// Sets and returns the currentStatus to status.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::setStatus(File::Status status)
|
||||
File::FileStatus File::setStatus(File::FileStatus status)
|
||||
{
|
||||
return currentStatus = status;
|
||||
}
|
||||
|
|
@ -347,7 +400,7 @@ File::Status File::setStatus(File::Status status)
|
|||
// The number of bytes read is available in bytesRead if a non-Null pointer is
|
||||
// provided.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::read(U32 size, char *dst, U32 *bytesRead)
|
||||
File::FileStatus File::read(U32 size, char *dst, U32 *bytesRead)
|
||||
{
|
||||
AssertFatal(Closed != currentStatus, "File::read: file closed");
|
||||
AssertFatal(handle != NULL, "File::read: invalid file handle");
|
||||
|
|
@ -379,7 +432,7 @@ File::Status File::read(U32 size, char *dst, U32 *bytesRead)
|
|||
// The number of bytes written is available in bytesWritten if a non-Null
|
||||
// pointer is provided.
|
||||
//-----------------------------------------------------------------------------
|
||||
File::Status File::write(U32 size, const char *src, U32 *bytesWritten)
|
||||
File::FileStatus File::write(U32 size, const char *src, U32 *bytesWritten)
|
||||
{
|
||||
AssertFatal(Closed != currentStatus, "File::write: file closed");
|
||||
AssertFatal(handle != NULL, "File::write: invalid file handle");
|
||||
|
|
@ -527,35 +580,6 @@ bool Platform::setCurrentDirectory(StringTableEntry newDir)
|
|||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::openFolder(const char* path )
|
||||
{
|
||||
// TODO: users can still run applications by calling openfolder on an app bundle.
|
||||
// this may be a bad thing.
|
||||
if(!Platform::isDirectory(path))
|
||||
{
|
||||
Con::errorf(avar("Error: not a directory: %s",path));
|
||||
return;
|
||||
}
|
||||
|
||||
const char* arg = avar("open '%s'", path);
|
||||
U32 ret = system(arg);
|
||||
if(ret != 0)
|
||||
Con::printf(strerror(errno));
|
||||
}
|
||||
|
||||
void Platform::openFile(const char* path )
|
||||
{
|
||||
if( !Platform::isFile( path ) )
|
||||
{
|
||||
Con::errorf( avar( "Error: not a file: %s", path ) );
|
||||
return;
|
||||
}
|
||||
|
||||
const char* arg = avar( "open '%s'", path );
|
||||
U32 ret = system( arg );
|
||||
if( ret != 0 )
|
||||
Con::printf( strerror( errno ) );
|
||||
}
|
||||
|
||||
// helper func for getWorkingDirectory
|
||||
bool isMainDotCsPresent(NSString* dir)
|
||||
|
|
@ -594,12 +618,13 @@ StringTableEntry Platform::getExecutablePath()
|
|||
|
||||
//first check the cwd for main.cs
|
||||
static char buf[4096];
|
||||
NSString* currentDir = [[NSString alloc ] initWithCString:getcwd(buf,(4096 * sizeof(char))) ];
|
||||
NSString* currentDir = [[NSString alloc ] initWithUTF8String:getcwd(buf,(4096 * sizeof(char))) ];
|
||||
|
||||
if (isMainDotCsPresent(currentDir))
|
||||
{
|
||||
cwd = buf;
|
||||
[pool release];
|
||||
[currentDir release];
|
||||
return cwd;
|
||||
}
|
||||
|
||||
|
|
@ -612,6 +637,7 @@ StringTableEntry Platform::getExecutablePath()
|
|||
cwd = dStrdup([string UTF8String]);
|
||||
chdir(cwd);
|
||||
[pool release];
|
||||
[currentDir release];
|
||||
}
|
||||
|
||||
return cwd;
|
||||
|
|
@ -724,97 +750,152 @@ bool Platform::hasSubDirectory(const char *path)
|
|||
return false; // either this dir had no subdirectories, or they were all on the exclude list.
|
||||
}
|
||||
|
||||
bool Platform::fileDelete(const char * name)
|
||||
{
|
||||
return dFileDelete(name);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool recurseDumpDirectories(const char *basePath, const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
|
||||
bool Platform::fileDelete(const char * name)
|
||||
{
|
||||
DIR *dir;
|
||||
dirent *entry;
|
||||
U32 len = dStrlen(basePath) + dStrlen(path) + 2;
|
||||
char pathbuf[len];
|
||||
return dFileDelete(name);
|
||||
}
|
||||
|
||||
// construct the file path
|
||||
dSprintf(pathbuf, len, "%s/%s", basePath, path);
|
||||
pathbuf[len] = '\0';
|
||||
static bool recurseDumpDirectories(const char *basePath, const char *subPath, Vector<StringTableEntry> &directoryVector, S32 currentDepth, S32 recurseDepth, bool noBasePath)
|
||||
{
|
||||
char Path[1024];
|
||||
DIR *dip;
|
||||
struct dirent *d;
|
||||
|
||||
// be sure it opens.
|
||||
dir = opendir(pathbuf);
|
||||
if(!dir)
|
||||
dsize_t trLen = basePath ? dStrlen(basePath) : 0;
|
||||
dsize_t subtrLen = subPath ? dStrlen(subPath) : 0;
|
||||
char trail = trLen > 0 ? basePath[trLen - 1] : '\0';
|
||||
char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0';
|
||||
|
||||
if (trail == '/')
|
||||
{
|
||||
if (subPath && (dStrncmp(subPath, "", 1) != 0))
|
||||
{
|
||||
if (subTrail == '/')
|
||||
dSprintf(Path, 1024, "%s%s", basePath, subPath);
|
||||
else
|
||||
dSprintf(Path, 1024, "%s%s/", basePath, subPath);
|
||||
}
|
||||
else
|
||||
dSprintf(Path, 1024, "%s", basePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (subPath && (dStrncmp(subPath, "", 1) != 0))
|
||||
{
|
||||
if (subTrail == '/')
|
||||
dSprintf(Path, 1024, "%s%s", basePath, subPath);
|
||||
else
|
||||
dSprintf(Path, 1024, "%s%s/", basePath, subPath);
|
||||
}
|
||||
else
|
||||
dSprintf(Path, 1024, "%s/", basePath);
|
||||
}
|
||||
|
||||
dip = opendir(Path);
|
||||
if (dip == NULL)
|
||||
return false;
|
||||
|
||||
// look inside the current directory
|
||||
while( (entry = readdir(dir)) )
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// add path to our return list ( provided it is valid )
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (!Platform::isExcludedDirectory(subPath))
|
||||
{
|
||||
// we just want directories.
|
||||
if(!isGoodDirectory(entry))
|
||||
continue;
|
||||
|
||||
// TODO: better unicode file name handling
|
||||
// // Apple's file system stores unicode file names in decomposed form.
|
||||
// // ATSUI will not reliably draw out just the accent character by itself,
|
||||
// // so our text renderer has no chance of rendering decomposed form unicode.
|
||||
// // We have to convert the entry name to precomposed normalized form.
|
||||
// CFStringRef cfdname = CFStringCreateWithCString(NULL,entry->d_name,kCFStringEncodingUTF8);
|
||||
// CFMutableStringRef cfentryName = CFStringCreateMutableCopy(NULL,0,cfdname);
|
||||
// CFStringNormalize(cfentryName,kCFStringNormalizationFormC);
|
||||
//
|
||||
// U32 entryNameLen = CFStringGetLength(cfentryName) * 4 + 1;
|
||||
// char entryName[entryNameLen];
|
||||
// CFStringGetCString(cfentryName, entryName, entryNameLen, kCFStringEncodingUTF8);
|
||||
// entryName[entryNameLen-1] = NULL; // sometimes, CFStringGetCString() doesn't null terminate.
|
||||
// CFRelease(cfentryName);
|
||||
// CFRelease(cfdname);
|
||||
|
||||
// construct the new path string, we'll need this below.
|
||||
U32 newpathlen = dStrlen(path) + dStrlen(entry->d_name) + 2;
|
||||
char newpath[newpathlen];
|
||||
if(dStrlen(path) > 0) // prevent extra slashes in the path
|
||||
dSprintf(newpath, newpathlen,"%s/%s",path,entry->d_name);
|
||||
else
|
||||
dStrncpy(newpath,entry->d_name, newpathlen);
|
||||
newpath[newpathlen] = '\0';
|
||||
|
||||
// we have a directory, add it to the list.
|
||||
if( noBasePath )
|
||||
directoryVector.push_back(StringTable->insert(newpath));
|
||||
else {
|
||||
U32 fullpathlen = dStrlen(basePath) + dStrlen(newpath) + 2;
|
||||
char fullpath[fullpathlen];
|
||||
dSprintf(fullpath,fullpathlen,"%s/%s",basePath,newpath);
|
||||
fullpath[fullpathlen] = '\0';
|
||||
|
||||
directoryVector.push_back(StringTable->insert(fullpath));
|
||||
if (noBasePath)
|
||||
{
|
||||
// We have a path and it's not an empty string or an excluded directory
|
||||
if ( (subPath && (dStrncmp (subPath, "", 1) != 0)) )
|
||||
directoryVector.push_back(StringTable->insert(subPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) )
|
||||
{
|
||||
char szPath[1024];
|
||||
dMemset(szPath, 0, 1024);
|
||||
if (trail == '/')
|
||||
{
|
||||
if ((basePath[dStrlen(basePath) - 1]) != '/')
|
||||
dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]);
|
||||
else
|
||||
dSprintf(szPath, 1024, "%s%s", basePath, subPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((basePath[dStrlen(basePath) - 1]) != '/')
|
||||
dSprintf(szPath, 1024, "%s%s", basePath, subPath);
|
||||
else
|
||||
dSprintf(szPath, 1024, "%s/%s", basePath, subPath);
|
||||
}
|
||||
|
||||
// and recurse into it, unless we've run out of depth
|
||||
if( depth != 0) // passing a val of -1 as the recurse depth means go forever
|
||||
recurseDumpDirectories(basePath, newpath, directoryVector, depth-1, noBasePath);
|
||||
directoryVector.push_back(StringTable->insert(szPath));
|
||||
}
|
||||
else
|
||||
directoryVector.push_back(StringTable->insert(basePath));
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Iterate through and grab valid directories
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
while (d = readdir(dip))
|
||||
{
|
||||
bool isDir;
|
||||
isDir = false;
|
||||
if (d->d_type == DT_UNKNOWN)
|
||||
{
|
||||
char child [1024];
|
||||
if ((Path[dStrlen(Path) - 1] == '/'))
|
||||
dSprintf(child, 1024, "%s%s", Path, d->d_name);
|
||||
else
|
||||
dSprintf(child, 1024, "%s/%s", Path, d->d_name);
|
||||
isDir = Platform::isDirectory (child);
|
||||
}
|
||||
else if (d->d_type & DT_DIR)
|
||||
isDir = true;
|
||||
|
||||
if ( isDir )
|
||||
{
|
||||
if (dStrcmp(d->d_name, ".") == 0 ||
|
||||
dStrcmp(d->d_name, "..") == 0)
|
||||
continue;
|
||||
if (Platform::isExcludedDirectory(d->d_name))
|
||||
continue;
|
||||
if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) )
|
||||
{
|
||||
char child[1024];
|
||||
if ((subPath[dStrlen(subPath) - 1] == '/'))
|
||||
dSprintf(child, 1024, "%s%s", subPath, d->d_name);
|
||||
else
|
||||
dSprintf(child, 1024, "%s/%s", subPath, d->d_name);
|
||||
if (currentDepth < recurseDepth || recurseDepth == -1 )
|
||||
recurseDumpDirectories(basePath, child, directoryVector,
|
||||
currentDepth + 1, recurseDepth,
|
||||
noBasePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
char child[1024];
|
||||
if ( (basePath[dStrlen(basePath) - 1]) == '/')
|
||||
dStrcpy (child, d->d_name);
|
||||
else
|
||||
dSprintf(child, 1024, "/%s", d->d_name);
|
||||
if (currentDepth < recurseDepth || recurseDepth == -1)
|
||||
recurseDumpDirectories(basePath, child, directoryVector,
|
||||
currentDepth + 1, recurseDepth,
|
||||
noBasePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dip);
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Platform::dumpDirectories(const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
|
||||
{
|
||||
PROFILE_START(dumpDirectories);
|
||||
|
||||
int len = dStrlen(path);
|
||||
char newpath[len];
|
||||
|
||||
dStrncpy(newpath,path,len);
|
||||
newpath[len] = '\0';
|
||||
if(newpath[len - 1] == '/')
|
||||
newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one
|
||||
|
||||
bool ret = recurseDumpDirectories(newpath, "", directoryVector, depth, noBasePath);
|
||||
PROFILE_END();
|
||||
|
||||
return ret;
|
||||
bool retVal = recurseDumpDirectories(path, "", directoryVector, 0, depth, noBasePath);
|
||||
clearExcludedDirectories();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
|
|
@ -20,55 +20,44 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include "platform/platformFont.h"
|
||||
#import "platform/platformFont.h"
|
||||
#import <CoreText/CoreText.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class MacCarbFont : public PlatformFont
|
||||
class OSXFont : public PlatformFont
|
||||
{
|
||||
private:
|
||||
// Caches style, layout and colorspace data to speed up character drawing.
|
||||
// TODO: style colors
|
||||
ATSUStyle mStyle;
|
||||
ATSUTextLayout mLayout;
|
||||
|
||||
// Font reference.
|
||||
CTFontRef mFontRef;
|
||||
|
||||
// Distance from drawing point to typographic baseline.
|
||||
// Think of the drawing point as the upper left corner of a text box.
|
||||
// NOTE: 'baseline' is synonymous with 'ascent' in Torque.
|
||||
U32 mBaseline;
|
||||
|
||||
// Distance between lines.
|
||||
U32 mHeight;
|
||||
|
||||
// Glyph rendering color-space.
|
||||
CGColorSpaceRef mColorSpace;
|
||||
|
||||
// Cache the baseline and height for the getter methods below.
|
||||
U32 mHeight; // distance between lines
|
||||
U32 mBaseline; // distance from drawing point to typographic baseline,
|
||||
// think of the drawing point as the upper left corner of a text box.
|
||||
// note: 'baseline' is synonymous with 'ascent' in Torque.
|
||||
|
||||
// Cache the size and name requested in create()
|
||||
U32 mSize;
|
||||
StringTableEntry mName;
|
||||
|
||||
public:
|
||||
MacCarbFont();
|
||||
virtual ~MacCarbFont();
|
||||
OSXFont();
|
||||
virtual ~OSXFont();
|
||||
|
||||
/// Look up the requested font, cache style, layout, colorspace, and some metrics.
|
||||
virtual bool create( const char* name, U32 size, U32 charset = TGE_ANSI_CHARSET);
|
||||
virtual bool create( const char* name, dsize_t size, U32 charset = TGE_ANSI_CHARSET);
|
||||
|
||||
/// Determine if the character requested is a drawable character, or if it should be ignored.
|
||||
virtual bool isValidChar( const UTF16 ch) const;
|
||||
virtual bool isValidChar( const UTF8 *str) const;
|
||||
virtual bool isValidChar( const UTF16 character) const;
|
||||
virtual bool isValidChar( const UTF8* str) const;
|
||||
|
||||
/// Get some vertical data on the font at large. Useful for drawing multiline text, and sizing text boxes.
|
||||
virtual U32 getFontHeight() const;
|
||||
virtual U32 getFontBaseLine() const;
|
||||
virtual U32 getFontHeight() const { return mHeight; }
|
||||
virtual U32 getFontBaseLine() const { return mBaseline; }
|
||||
|
||||
// Draw the character to a temporary bitmap, and fill the CharInfo with various text metrics.
|
||||
virtual PlatformFont::CharInfo &getCharInfo(const UTF16 ch) const;
|
||||
virtual PlatformFont::CharInfo &getCharInfo(const UTF16 character) const;
|
||||
virtual PlatformFont::CharInfo &getCharInfo(const UTF8 *str) const;
|
||||
};
|
||||
|
||||
inline U32 MacCarbFont::getFontHeight() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
inline U32 MacCarbFont::getFontBaseLine() const
|
||||
{
|
||||
return mBaseline;
|
||||
}
|
||||
258
Engine/source/platformMac/macFont.mm
Normal file
258
Engine/source/platformMac/macFont.mm
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "platform/platform.h"
|
||||
#import "core/util/tVector.h"
|
||||
#import "math/mMathFn.h"
|
||||
#import "platformMac/macFont.h"
|
||||
#import "core/stringTable.h"
|
||||
#import "core/strings/unicode.h"
|
||||
#import "console/console.h"
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
PlatformFont* createPlatformFont( const char* name, dsize_t size, U32 charset )
|
||||
{
|
||||
PlatformFont* pFont = new OSXFont();
|
||||
|
||||
if ( pFont->create(name, size, charset) )
|
||||
return pFont;
|
||||
|
||||
delete pFont;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void PlatformFont::enumeratePlatformFonts( Vector<StringTableEntry>& fonts, UTF16 *fontFamily )
|
||||
{
|
||||
// Fetch available fonts.
|
||||
NSArray* availableFonts = [[NSFontManager sharedFontManager] availableFontNamesWithTraits:0];
|
||||
|
||||
// Enumerate font names.
|
||||
for (id fontName in availableFonts)
|
||||
{
|
||||
fonts.push_back( StringTable->insert( [fontName UTF8String] ) );
|
||||
}
|
||||
|
||||
// Release font name.
|
||||
[availableFonts release];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
OSXFont::OSXFont()
|
||||
{
|
||||
// Reset the rendering color-space.
|
||||
mColorSpace = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
OSXFont::~OSXFont()
|
||||
{
|
||||
// Destroy the rendering color-space.
|
||||
CGColorSpaceRelease( mColorSpace );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool OSXFont::create( const char* name, dsize_t size, U32 charset )
|
||||
{
|
||||
// Sanity!
|
||||
AssertFatal( name != NULL, "Cannot create a NULL font name." );
|
||||
|
||||
// Generate compatible font name.
|
||||
CFStringRef fontName = CFStringCreateWithCString( kCFAllocatorDefault, name, kCFStringEncodingUTF8 );
|
||||
|
||||
// Sanity!
|
||||
if ( !fontName )
|
||||
{
|
||||
Con::errorf("Could not handle font name of '%s'.", name );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use Windows as a baseline (96 DPI) and adjust accordingly.
|
||||
F32 scaledSize = size * (72.0f/96.0f);
|
||||
scaledSize = mRound(scaledSize);
|
||||
|
||||
// Create the font reference.
|
||||
mFontRef = CTFontCreateWithName( fontName, scaledSize, NULL );
|
||||
|
||||
// Sanity!
|
||||
if ( !mFontRef )
|
||||
{
|
||||
Con::errorf( "Could not generate a font reference to font name '%s' of size '%d'", name, size );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fetch font metrics.
|
||||
CGFloat ascent = CTFontGetAscent( mFontRef );
|
||||
CGFloat descent = CTFontGetDescent( mFontRef );
|
||||
|
||||
// Set baseline.
|
||||
mBaseline = (U32)mRound(ascent);
|
||||
|
||||
// Set height.
|
||||
mHeight = (U32)mRound( ascent + descent );
|
||||
|
||||
// Create a gray-scale color-space.
|
||||
mColorSpace = CGColorSpaceCreateDeviceGray();
|
||||
|
||||
// Return status.
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool OSXFont::isValidChar( const UTF8* str ) const
|
||||
{
|
||||
// since only low order characters are invalid, and since those characters
|
||||
// are single codeunits in UTF8, we can safely cast here.
|
||||
return isValidChar((UTF16)*str);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool OSXFont::isValidChar( const UTF16 character) const
|
||||
{
|
||||
// We cut out the ASCII control chars here. Only printable characters are valid.
|
||||
// 0x20 == 32 == space
|
||||
if( character < 0x20 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
PlatformFont::CharInfo& OSXFont::getCharInfo(const UTF8 *str) const
|
||||
{
|
||||
return getCharInfo( oneUTF32toUTF16(oneUTF8toUTF32(str,NULL)) );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
PlatformFont::CharInfo& OSXFont::getCharInfo(const UTF16 character) const
|
||||
{
|
||||
// Declare and clear out the CharInfo that will be returned.
|
||||
static PlatformFont::CharInfo characterInfo;
|
||||
dMemset(&characterInfo, 0, sizeof(characterInfo));
|
||||
|
||||
// prep values for GFont::addBitmap()
|
||||
characterInfo.bitmapIndex = 0;
|
||||
characterInfo.xOffset = 0;
|
||||
characterInfo.yOffset = 0;
|
||||
|
||||
CGGlyph characterGlyph;
|
||||
CGRect characterBounds;
|
||||
CGSize characterAdvances;
|
||||
UniChar unicodeCharacter = character;
|
||||
|
||||
// Fetch font glyphs.
|
||||
if ( !CTFontGetGlyphsForCharacters( mFontRef, &unicodeCharacter, &characterGlyph, (CFIndex)1) )
|
||||
{
|
||||
// Sanity!
|
||||
//AssertFatal( false, "Cannot create font glyph." );
|
||||
Con::warnf("Font glyph is messed up. Some characters may render incorrectly.");
|
||||
}
|
||||
|
||||
// Fetch glyph bounding box.
|
||||
CTFontGetBoundingRectsForGlyphs( mFontRef, kCTFontHorizontalOrientation, &characterGlyph, &characterBounds, (CFIndex)1 );
|
||||
|
||||
// Fetch glyph advances.
|
||||
CTFontGetAdvancesForGlyphs( mFontRef, kCTFontHorizontalOrientation, &characterGlyph, &characterAdvances, (CFIndex)1 );
|
||||
|
||||
// Set character metrics,
|
||||
characterInfo.xOrigin = (S32)mRound( characterBounds.origin.x );
|
||||
characterInfo.yOrigin = (S32)mRound( characterBounds.origin.y );
|
||||
characterInfo.width = (U32)mCeil( characterBounds.size.width ) + 2;
|
||||
characterInfo.height = (U32)mCeil( characterBounds.size.height ) + 2;
|
||||
characterInfo.xIncrement = (S32)mRound( characterAdvances.width );
|
||||
|
||||
// Finish if character is undrawable.
|
||||
if ( characterInfo.width == 0 && characterInfo.height == 0 )
|
||||
return characterInfo;
|
||||
|
||||
// Clamp character minimum width.
|
||||
if ( characterInfo.width == 0 )
|
||||
characterInfo.width = 2;
|
||||
|
||||
if ( characterInfo.height == 0 )
|
||||
characterInfo.height = 1;
|
||||
|
||||
|
||||
// Allocate a bitmap surface.
|
||||
const U32 bitmapSize = characterInfo.width * characterInfo.height;
|
||||
characterInfo.bitmapData = new U8[bitmapSize];
|
||||
dMemset(characterInfo.bitmapData, 0x00, bitmapSize);
|
||||
|
||||
// Create a bitmap context.
|
||||
CGContextRef bitmapContext = CGBitmapContextCreate( characterInfo.bitmapData, characterInfo.width, characterInfo.height, 8, characterInfo.width, mColorSpace, kCGImageAlphaNone );
|
||||
|
||||
// Sanity!
|
||||
AssertFatal( bitmapContext != NULL, "Cannot create font context." );
|
||||
|
||||
// Render font anti-aliased if font is arbitrarily small.
|
||||
CGContextSetShouldAntialias( bitmapContext, true);
|
||||
CGContextSetShouldSmoothFonts( bitmapContext, true);
|
||||
CGContextSetRenderingIntent( bitmapContext, kCGRenderingIntentAbsoluteColorimetric);
|
||||
CGContextSetInterpolationQuality( bitmapContext, kCGInterpolationNone);
|
||||
CGContextSetGrayFillColor( bitmapContext, 1.0, 1.0);
|
||||
CGContextSetTextDrawingMode( bitmapContext, kCGTextFill);
|
||||
|
||||
// Draw glyph.
|
||||
CGPoint renderOrigin;
|
||||
renderOrigin.x = -characterInfo.xOrigin;
|
||||
renderOrigin.y = -characterInfo.yOrigin;
|
||||
|
||||
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||
CTFontDrawGlyphs( mFontRef, &characterGlyph, &renderOrigin, 1, bitmapContext );
|
||||
#else
|
||||
CGFontRef cgFont = CTFontCopyGraphicsFont(mFontRef, NULL);
|
||||
CGContextSetFont(bitmapContext, cgFont);
|
||||
CGContextSetFontSize(bitmapContext, CTFontGetSize(mFontRef));
|
||||
CGContextShowGlyphsAtPositions(bitmapContext, &characterGlyph, &renderOrigin, 1);
|
||||
CFRelease(cgFont);
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
Con::printf("Width:%f, Height:%f, OriginX:%f, OriginY:%f",
|
||||
characterBounds.size.width,
|
||||
characterBounds.size.height,
|
||||
characterBounds.origin.x,
|
||||
characterBounds.origin.y );
|
||||
#endif
|
||||
|
||||
// Adjust the y origin for the glyph size.
|
||||
characterInfo.yOrigin += characterInfo.height;// + mHeight;
|
||||
|
||||
// Release the bitmap context.
|
||||
CGContextRelease( bitmapContext );
|
||||
|
||||
// Return character information.
|
||||
return characterInfo;
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MACGLUTILS_H_
|
||||
#define _MACGLUTILS_H_
|
||||
|
||||
static Vector<NSOpenGLPixelFormatAttribute> _beginPixelFormatAttributesForDisplay(CGDirectDisplayID display)
|
||||
{
|
||||
Vector<NSOpenGLPixelFormatAttribute> attributes;
|
||||
attributes.reserve(16); // Most attribute lists won't exceed this
|
||||
|
||||
attributes.push_back(NSOpenGLPFAScreenMask);
|
||||
attributes.push_back((NSOpenGLPixelFormatAttribute)CGDisplayIDToOpenGLDisplayMask(display));
|
||||
attributes.push_back(NSOpenGLPFANoRecovery);
|
||||
attributes.push_back(NSOpenGLPFADoubleBuffer);
|
||||
attributes.push_back(NSOpenGLPFAAccelerated);
|
||||
attributes.push_back(NSOpenGLPFAAuxBuffers);
|
||||
attributes.push_back((NSOpenGLPixelFormatAttribute)1);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
static void _addColorAlphaDepthStencilAttributes(Vector<NSOpenGLPixelFormatAttribute>& attributes, U32 color, U32 alpha, U32 depth, U32 stencil)
|
||||
{
|
||||
attributes.push_back(NSOpenGLPFAColorSize); attributes.push_back((NSOpenGLPixelFormatAttribute)color);
|
||||
attributes.push_back(NSOpenGLPFAAlphaSize); attributes.push_back((NSOpenGLPixelFormatAttribute)alpha);
|
||||
attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back((NSOpenGLPixelFormatAttribute)depth);
|
||||
attributes.push_back(NSOpenGLPFAStencilSize); attributes.push_back((NSOpenGLPixelFormatAttribute)stencil);
|
||||
}
|
||||
|
||||
static void _addFullscreenAttributes(Vector<NSOpenGLPixelFormatAttribute>& attributes)
|
||||
{
|
||||
attributes.push_back(NSOpenGLPFAFullScreen);
|
||||
}
|
||||
|
||||
static void _endAttributeList(Vector<NSOpenGLPixelFormatAttribute>& attributes)
|
||||
{
|
||||
attributes.push_back((NSOpenGLPixelFormatAttribute)0);
|
||||
}
|
||||
|
||||
static Vector<NSOpenGLPixelFormatAttribute> _createStandardPixelFormatAttributesForDisplay(CGDirectDisplayID display)
|
||||
{
|
||||
Vector<NSOpenGLPixelFormatAttribute> attributes = _beginPixelFormatAttributesForDisplay(display);
|
||||
_addColorAlphaDepthStencilAttributes(attributes, 24, 8, 24, 8);
|
||||
_endAttributeList(attributes);
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/// returns an opengl pixel format suitable for creating shared opengl contexts.
|
||||
static NSOpenGLPixelFormat* _createStandardPixelFormat()
|
||||
{
|
||||
Vector<NSOpenGLPixelFormatAttribute> attributes = _createStandardPixelFormatAttributesForDisplay(kCGDirectMainDisplay);
|
||||
|
||||
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes.address()];
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -20,175 +20,70 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include "app/mainLoop.h"
|
||||
#include "platform/platformInput.h"
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
#include <IOKit/ps/IOPSKeys.h>
|
||||
#include "console/console.h"
|
||||
#include "platform/threads/thread.h"
|
||||
#import "app/mainLoop.h"
|
||||
#import "platform/platformInput.h"
|
||||
#import "console/console.h"
|
||||
|
||||
// TODO: let the mainLoop's sleep time happen via rescheduling the timer every run-through.
|
||||
extern S32 sgTimeManagerProcessInterval;
|
||||
extern void InitWindowingSystem();
|
||||
|
||||
@interface MainLoopTimerHandler : NSObject
|
||||
{
|
||||
U32 argc;
|
||||
const char** argv;
|
||||
NSTimeInterval interval;
|
||||
}
|
||||
+(id)startTimerWithintervalMs:(U32)intervalMs argc:(U32)_argc argv:(const char**)_argv;
|
||||
-(void)firstFire:(NSTimer*)theTimer;
|
||||
-(void)fireTimer:(NSTimer*)theTimer;
|
||||
@end
|
||||
@implementation MainLoopTimerHandler
|
||||
-(void)firstFire:(NSTimer*)theTimer
|
||||
{
|
||||
StandardMainLoop::init();
|
||||
StandardMainLoop::handleCommandLine(argc, argv);
|
||||
[NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(fireTimer:) userInfo:nil repeats:YES];
|
||||
}
|
||||
-(void)fireTimer:(NSTimer*)theTimer
|
||||
{
|
||||
if(!StandardMainLoop::doMainLoop())
|
||||
{
|
||||
StandardMainLoop::shutdown();
|
||||
[theTimer invalidate];
|
||||
[NSApp setDelegate:nil];
|
||||
[NSApp terminate:self];
|
||||
}
|
||||
// if(!mainLoop || !mainLoop->mainLoop())
|
||||
// {
|
||||
// // stop the timer from firing again
|
||||
// if(mainLoop)
|
||||
// mainLoop->shutdown();
|
||||
//
|
||||
// [theTimer invalidate];
|
||||
// [NSApp setDelegate:nil];
|
||||
// [NSApp terminate:self];
|
||||
// }
|
||||
}
|
||||
+(id)startTimerWithintervalMs:(U32)intervalMs argc:(U32)_argc argv:(const char**)_argv
|
||||
{
|
||||
MainLoopTimerHandler* handler = [[[MainLoopTimerHandler alloc] init] autorelease];
|
||||
handler->argc = _argc;
|
||||
handler->argv = _argv;
|
||||
handler->interval = intervalMs / 1000.0; // interval in milliseconds
|
||||
[NSTimer scheduledTimerWithTimeInterval:handler->interval target:handler selector:@selector(firstFire:) userInfo:nil repeats:NO];
|
||||
return handler;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
#ifndef TORQUE_SHARED
|
||||
//-----------------------------------------------------------------------------
|
||||
// main() - the real one - this is the actual program entry point.
|
||||
//-----------------------------------------------------------------------------
|
||||
S32 main(S32 argc, const char **argv)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// get command line and text file args, filter them
|
||||
|
||||
// now, we prepare to hand off execution to torque & macosx.
|
||||
U32 appReturn = 0;
|
||||
printf("installing torque main loop timer\n");
|
||||
[MainLoopTimerHandler startTimerWithintervalMs:1 argc:argc argv:argv];
|
||||
printf("starting NSApplicationMain\n");
|
||||
appReturn = NSApplicationMain(argc, argv);
|
||||
printf("NSApplicationMain exited\n");
|
||||
|
||||
// shut down the engine
|
||||
|
||||
[pool release];
|
||||
|
||||
return appReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static NSApplication *app = NULL;
|
||||
static NSAutoreleasePool* pool = NULL;
|
||||
|
||||
void torque_mac_engineinit(S32 argc, const char **argv)
|
||||
{
|
||||
|
||||
if (!Platform::getWebDeployment())
|
||||
{
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
app = [NSApplication sharedApplication];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void torque_mac_enginetick()
|
||||
{
|
||||
|
||||
if (!Platform::getWebDeployment())
|
||||
{
|
||||
|
||||
NSEvent *e = [app nextEventMatchingMask: NSAnyEventMask
|
||||
untilDate: [NSDate distantPast]
|
||||
inMode: NSDefaultRunLoopMode
|
||||
dequeue: YES];
|
||||
if (e)
|
||||
[app sendEvent: e];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void torque_mac_engineshutdown()
|
||||
{
|
||||
if (!Platform::getWebDeployment())
|
||||
{
|
||||
[pool release];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// torque_macmain() - entry point for application using bundle
|
||||
//-----------------------------------------------------------------------------
|
||||
S32 torque_macmain(S32 argc, const char **argv)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// get command line and text file args, filter them
|
||||
|
||||
// now, we prepare to hand off execution to torque & macosx.
|
||||
U32 appReturn = 0;
|
||||
printf("installing torque main loop timer\n");
|
||||
[MainLoopTimerHandler startTimerWithintervalMs:1 argc:argc argv:argv];
|
||||
printf("starting NSApplicationMain\n");
|
||||
appReturn = NSApplicationMain(argc, argv);
|
||||
printf("NSApplicationMain exited\n");
|
||||
|
||||
// shut down the engine
|
||||
|
||||
[pool release];
|
||||
|
||||
return appReturn;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
|
||||
#pragma mark ---- Init funcs ----
|
||||
//------------------------------------------------------------------------------
|
||||
void Platform::init()
|
||||
{
|
||||
|
||||
Con::printf("Initializing platform...");
|
||||
|
||||
// Set the platform variable for the scripts
|
||||
Con::setVariable( "$platform", "macos" );
|
||||
Con::setVariable( "$platform", "MacOSX" );
|
||||
|
||||
Input::init();
|
||||
|
||||
//installRedBookDevices();
|
||||
|
||||
#ifndef TORQUE_DEDICATED
|
||||
// if we're not dedicated do more initialization
|
||||
InitWindowingSystem();
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void Platform::shutdown()
|
||||
{
|
||||
Input::destroy();
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool torque_engineinit(int argc, const char **argv);
|
||||
int torque_enginetick();
|
||||
S32 torque_getreturnstatus();
|
||||
bool torque_engineshutdown();
|
||||
|
||||
int torque_macmain(int argc, const char **argv)
|
||||
{
|
||||
if (!torque_engineinit(argc, argv))
|
||||
return 1;
|
||||
|
||||
while(torque_enginetick())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
torque_engineshutdown();
|
||||
|
||||
return torque_getreturnstatus();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extern S32 TorqueMain(S32 argc, const char **argv);
|
||||
|
||||
#if !defined(TORQUE_SHARED)
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
return TorqueMain(argc, argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -20,11 +20,10 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
#include "platform/platform.h"
|
||||
#include "console/console.h"
|
||||
#include "math/mMath.h"
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#import "platform/platform.h"
|
||||
#import "console/console.h"
|
||||
#import "math/mMath.h"
|
||||
#import "core/strings/stringFunctions.h"
|
||||
|
||||
extern void mInstallLibrary_C();
|
||||
extern void mInstallLibrary_Vec();
|
||||
|
|
@ -52,7 +51,7 @@ void Platform::setMathControlStateKnown()
|
|||
}
|
||||
|
||||
//--------------------------------------
|
||||
ConsoleFunction( MathInit, void, 1, 10, "(DETECT|C|VEC|SSE)")
|
||||
ConsoleFunction( MathInit, void, 1, 10, "(DETECT|C|SSE)")
|
||||
{
|
||||
U32 properties = CPU_PROP_C; // C entensions are always used
|
||||
|
||||
|
|
@ -71,16 +70,12 @@ ConsoleFunction( MathInit, void, 1, 10, "(DETECT|C|VEC|SSE)")
|
|||
properties |= CPU_PROP_C;
|
||||
continue;
|
||||
}
|
||||
if (dStricmp(*argv, "VEC") == 0) {
|
||||
properties |= CPU_PROP_ALTIVEC;
|
||||
continue;
|
||||
}
|
||||
if( dStricmp( *argv, "SSE" ) == 0 )
|
||||
{
|
||||
properties |= CPU_PROP_SSE;
|
||||
continue;
|
||||
}
|
||||
Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", *argv);
|
||||
//Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", *argv);
|
||||
}
|
||||
Math::init(properties);
|
||||
}
|
||||
|
|
@ -101,13 +96,6 @@ void Math::init(U32 properties)
|
|||
Con::printf(" Installing Standard C extensions");
|
||||
mInstallLibrary_C();
|
||||
|
||||
#if defined(__VEC__)
|
||||
if (properties & CPU_PROP_ALTIVEC)
|
||||
{
|
||||
Con::printf(" Installing Altivec extensions");
|
||||
mInstallLibrary_Vec();
|
||||
}
|
||||
#endif
|
||||
#ifdef TORQUE_CPU_X86
|
||||
if( properties & CPU_PROP_SSE )
|
||||
{
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
// Copyright (c) 2013 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
|
|
@ -20,10 +20,10 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mm_malloc.h>
|
||||
#import "platform/platform.h"
|
||||
#import <stdlib.h>
|
||||
#import <string.h>
|
||||
#import <mm_malloc.h>
|
||||
|
||||
//--------------------------------------
|
||||
void* dRealMalloc(dsize_t in_size)
|
||||
|
|
@ -1,180 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "platform/nativeDialogs/msgBox.h"
|
||||
#include "console/console.h"
|
||||
|
||||
void Platform::AlertOK(const char *windowTitle, const char *message)
|
||||
{
|
||||
Platform::messageBox(windowTitle, message, MBOk, MIInformation);
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
bool Platform::AlertOKCancel(const char *windowTitle, const char *message)
|
||||
{
|
||||
return ( Platform::messageBox(windowTitle, message, MBOkCancel, MIInformation) == MROk );
|
||||
}
|
||||
|
||||
//--------------------------------------
|
||||
bool Platform::AlertRetry(const char *windowTitle, const char *message)
|
||||
{
|
||||
return ( Platform::messageBox(windowTitle, message, MBRetryCancel, MIInformation) == MRRetry );
|
||||
}
|
||||
|
||||
namespace MsgBoxMac
|
||||
{
|
||||
struct _NSStringMap
|
||||
{
|
||||
S32 num;
|
||||
NSString* ok;
|
||||
NSString* cancel;
|
||||
NSString* third;
|
||||
};
|
||||
|
||||
static _NSStringMap sgButtonTextMap[] =
|
||||
{
|
||||
{ MBOk, @"OK", nil, nil },
|
||||
{ MBOkCancel, @"OK", @"Cancel", nil },
|
||||
{ MBRetryCancel, @"Retry", @"Cancel", nil },
|
||||
{ MBSaveDontSave, @"Yes", @"No", nil },
|
||||
{ MBSaveDontSaveCancel, @"Yes", @"No", @"Cancel" },
|
||||
{ -1, nil, nil, nil }
|
||||
};
|
||||
|
||||
struct _NSAlertResultMap
|
||||
{
|
||||
S32 num;
|
||||
S32 ok;
|
||||
S32 cancel;
|
||||
S32 third;
|
||||
};
|
||||
|
||||
static _NSAlertResultMap sgAlertResultMap[] =
|
||||
{
|
||||
{ MBOk, MROk, 0, 0 },
|
||||
{ MBOkCancel, MROk, MRCancel, 0 },
|
||||
{ MBRetryCancel, MRRetry, MRCancel, 0 },
|
||||
{ MBSaveDontSave, MROk, MRDontSave, 0 },
|
||||
{ MBSaveDontSaveCancel, MROk, MRDontSave, MRCancel },
|
||||
{ -1, nil, nil, nil }
|
||||
};
|
||||
} // end MsgBoxMac namespace
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
S32 Platform::messageBox(const UTF8 *title, const UTF8 *message, MBButtons buttons, MBIcons icon)
|
||||
{
|
||||
// TODO: put this on the main thread
|
||||
|
||||
// determine the button text
|
||||
NSString *okBtn = nil;
|
||||
NSString *cancelBtn = nil;
|
||||
NSString *thirdBtn = nil;
|
||||
U32 i;
|
||||
for(i = 0; MsgBoxMac::sgButtonTextMap[i].num != -1; i++)
|
||||
{
|
||||
if(MsgBoxMac::sgButtonTextMap[i].num != buttons)
|
||||
continue;
|
||||
|
||||
okBtn = MsgBoxMac::sgButtonTextMap[i].ok;
|
||||
cancelBtn = MsgBoxMac::sgButtonTextMap[i].cancel;
|
||||
thirdBtn = MsgBoxMac::sgButtonTextMap[i].third;
|
||||
break;
|
||||
}
|
||||
if(MsgBoxMac::sgButtonTextMap[i].num == -1)
|
||||
Con::errorf("Unknown message box button set requested. Mac Platform::messageBox() probably needs to be updated.");
|
||||
|
||||
// convert title and message to NSStrings
|
||||
NSString *nsTitle = [NSString stringWithUTF8String:title];
|
||||
NSString *nsMessage = [NSString stringWithUTF8String:message];
|
||||
// TODO: ensure that the cursor is the expected shape
|
||||
// show the alert
|
||||
S32 result = -2;
|
||||
|
||||
NSAlert *alert = [NSAlert alertWithMessageText:nsTitle
|
||||
defaultButton:okBtn
|
||||
alternateButton:thirdBtn
|
||||
otherButton:cancelBtn
|
||||
informativeTextWithFormat:nsMessage];
|
||||
|
||||
switch(icon)
|
||||
{
|
||||
// TODO:
|
||||
// Currently, NSAlert only provides two alert icon options.
|
||||
// NSWarningAlertStyle and NSInformationalAlertStyle are identical and
|
||||
// display the application icon, while NSCriticalAlertStyle displays
|
||||
// a shrunken app icon badge on a yellow-triangle-with-a-bang icon.
|
||||
// If custom icons were created, they could be used here with the
|
||||
// message [alert setIcon:foo]
|
||||
case MIWarning: // MIWarning = 0
|
||||
|
||||
case MIQuestion: // MIquestion = 3
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
break;
|
||||
|
||||
case MIInformation: // MIInformation = 1
|
||||
[alert setAlertStyle:NSInformationalAlertStyle];
|
||||
break;
|
||||
|
||||
case MIStop: // MIStop = 3
|
||||
[alert setAlertStyle:NSCriticalAlertStyle];
|
||||
break;
|
||||
|
||||
default:
|
||||
Con::errorf("Unknown message box icon requested. Mac Platform::messageBox() probably needs to be updated.");
|
||||
}
|
||||
|
||||
id appDelegate = [NSApp delegate];
|
||||
[NSApp setDelegate: nil];
|
||||
|
||||
U32 cursorDepth = 0;
|
||||
|
||||
while(!CGCursorIsVisible())
|
||||
{
|
||||
CGDisplayShowCursor(kCGDirectMainDisplay);
|
||||
cursorDepth++;
|
||||
}
|
||||
|
||||
CGAssociateMouseAndMouseCursorPosition(true);
|
||||
result = [alert runModal];
|
||||
|
||||
[NSApp setDelegate: appDelegate];
|
||||
|
||||
S32 ret = 0;
|
||||
for(U32 i = 0; MsgBoxMac::sgAlertResultMap[i].num != -1; i++)
|
||||
{
|
||||
if(MsgBoxMac::sgAlertResultMap[i].num != buttons)
|
||||
continue;
|
||||
|
||||
switch(result)
|
||||
{
|
||||
case NSAlertDefaultReturn:
|
||||
ret = MsgBoxMac::sgAlertResultMap[i].ok; break;
|
||||
case NSAlertOtherReturn:
|
||||
ret = MsgBoxMac::sgAlertResultMap[i].cancel; break;
|
||||
case NSAlertAlternateReturn:
|
||||
ret = MsgBoxMac::sgAlertResultMap[i].third; break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
153
Engine/source/platformMac/macPlatform.mm
Normal file
153
Engine/source/platformMac/macPlatform.mm
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <unistd.h>
|
||||
#import "platform/platform.h"
|
||||
#import "console/console.h"
|
||||
#import "core/stringTable.h"
|
||||
#import "core/util/str.h"
|
||||
#import "platform/platformInput.h"
|
||||
#import "platform/threads/thread.h"
|
||||
#import "core/util/journal/process.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Completely closes and restarts the simulation
|
||||
void Platform::restartInstance()
|
||||
{
|
||||
// Returns the NSBundle that corresponds to the directory where the current app executable is located.
|
||||
NSBundle* mainAppBundle = [NSBundle mainBundle];
|
||||
|
||||
// Returns the file URL of the receiver's executable file.
|
||||
// Not currently used, but left here for reference
|
||||
//NSURL* execURL = [mainAppBundle executableURL];
|
||||
|
||||
// Returns the full pathname of the receiver's executable file.
|
||||
NSString* execString = [mainAppBundle executablePath];
|
||||
|
||||
// Create a mutable string we can build into an executable command
|
||||
NSMutableString* mut = [[[NSMutableString alloc] init] autorelease];
|
||||
|
||||
// Base string is the executable path
|
||||
[mut appendString:execString];
|
||||
|
||||
// append ampersand so that we can launch without blocking.
|
||||
// encase in quotes so that spaces in the path are accepted.
|
||||
[mut insertString:@"\"" atIndex:0];
|
||||
[mut appendString:@"\" & "];
|
||||
[mut appendString:@"\\0"];
|
||||
|
||||
// Convert to a C string
|
||||
const char* execCString = [mut UTF8String];
|
||||
|
||||
// Echo the command before we run it
|
||||
Con::printf("---- %s -----", execCString);
|
||||
|
||||
// Run the restart command and hope for the best
|
||||
system(execCString);
|
||||
}
|
||||
|
||||
void Platform::postQuitMessage(const S32 in_quitVal)
|
||||
{
|
||||
Process::requestShutdown();
|
||||
}
|
||||
|
||||
void Platform::forceShutdown(S32 returnValue)
|
||||
{
|
||||
//exit(returnValue);
|
||||
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::debugBreak()
|
||||
{
|
||||
raise(SIGTRAP);
|
||||
}
|
||||
|
||||
#pragma mark ---- Various Directories ----
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* Platform::getUserDataDirectory()
|
||||
{
|
||||
// application support directory is most in line with the current usages of this function.
|
||||
// this may change with later usage
|
||||
// perhaps the user data directory should be pref-controlled?
|
||||
NSString *nsDataDir = [@"~/Library/Application Support/" stringByStandardizingPath];
|
||||
return StringTable->insert([nsDataDir UTF8String]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const char* Platform::getUserHomeDirectory()
|
||||
{
|
||||
return StringTable->insert([[@"~/" stringByStandardizingPath] UTF8String]);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
StringTableEntry osGetTemporaryDirectory()
|
||||
{
|
||||
NSString *tdir = NSTemporaryDirectory();
|
||||
const char *path = [tdir UTF8String];
|
||||
return StringTable->insert(path);
|
||||
}
|
||||
|
||||
#pragma mark ---- Platform utility funcs ----
|
||||
//-----------------------------------------------------------------------------
|
||||
void Platform::outputDebugString( const char *string, ... )
|
||||
{
|
||||
#ifdef TORQUE_DEBUG
|
||||
char buffer[ 2048 ];
|
||||
|
||||
va_list args;
|
||||
va_start( args, string );
|
||||
|
||||
dVsprintf( buffer, sizeof( buffer ), string, args );
|
||||
va_end( args );
|
||||
|
||||
U32 length = strlen( buffer );
|
||||
if( length == ( sizeof( buffer ) - 1 ) )
|
||||
length --;
|
||||
|
||||
buffer[ length ] = '\n';
|
||||
buffer[ length + 1 ] = '\0';
|
||||
|
||||
fputs( buffer, stderr );
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Platform::openWebBrowser( const char* webAddress )
|
||||
{
|
||||
OSStatus err;
|
||||
CFURLRef url = CFURLCreateWithBytes(NULL,(UInt8*)webAddress,dStrlen(webAddress),kCFStringEncodingASCII,NULL);
|
||||
err = LSOpenCFURLRef(url,NULL);
|
||||
CFRelease(url);
|
||||
|
||||
return(err==noErr);
|
||||
}
|
||||
|
||||
#pragma mark ---- Administrator ----
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Platform::getUserIsAdministrator()
|
||||
{
|
||||
// if we can write to /Library, we're probably an admin
|
||||
// HACK: this is not really very good, because people can chmod Library.
|
||||
return (access("/Library", W_OK) == 0);
|
||||
}
|
||||
|
|
@ -20,13 +20,13 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "core/strings/stringFunctions.h"
|
||||
#import "platform/platform.h"
|
||||
#import <stdlib.h>
|
||||
#import <stdarg.h>
|
||||
#import <string.h>
|
||||
#import <ctype.h>
|
||||
#import <stdio.h>
|
||||
#import "core/strings/stringFunctions.h"
|
||||
|
||||
char *dStrnew(const char *src)
|
||||
{
|
||||
|
|
@ -50,9 +50,9 @@ int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...)
|
|||
}
|
||||
|
||||
|
||||
int dVsprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, void *arglist)
|
||||
int dVsprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, va_list arglist)
|
||||
{
|
||||
S32 len = vsprintf(buffer, format, (char*)arglist);
|
||||
S32 len = vsprintf(buffer, format, arglist);
|
||||
|
||||
return (len);
|
||||
}
|
||||
|
|
@ -20,10 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include "platform/platformTimer.h"
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#import <CoreServices/CoreServices.h>
|
||||
#import <mach/mach_time.h>
|
||||
#import "platform/platformTimer.h"
|
||||
#import <time.h>
|
||||
#import <unistd.h>
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
|
|
@ -81,17 +82,16 @@ U32 Platform::getTime()
|
|||
/// Storing milliseconds in a U32 overflows every 49.71 days
|
||||
U32 Platform::getRealMilliseconds()
|
||||
{
|
||||
// Duration is a S32 value.
|
||||
// if negative, it is in microseconds.
|
||||
// if positive, it is in milliseconds.
|
||||
Duration durTime = AbsoluteToDuration(UpTime());
|
||||
U32 ret;
|
||||
if( durTime < 0 )
|
||||
ret = durTime / -1000;
|
||||
else
|
||||
ret = durTime;
|
||||
const uint32_t oneMillion = 1000000;
|
||||
static mach_timebase_info_data_t s_timebase_info;
|
||||
|
||||
return ret;
|
||||
if (s_timebase_info.denom == 0) {
|
||||
(void) mach_timebase_info(&s_timebase_info);
|
||||
}
|
||||
|
||||
// mach_absolute_time() returns billionth of seconds,
|
||||
// so divide by one million to get milliseconds
|
||||
return (U32)((mach_absolute_time() * s_timebase_info.numer) / (oneMillion * s_timebase_info.denom));
|
||||
}
|
||||
|
||||
U32 Platform::getVirtualMilliseconds()
|
||||
|
|
@ -23,13 +23,8 @@
|
|||
#ifndef _MACCARBVOLUME_H_
|
||||
#define _MACCARBVOLUME_H_
|
||||
|
||||
#ifndef _POSIXVOLUME_H_
|
||||
#include "platformPOSIX/posixVolume.h"
|
||||
#endif
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/util/tVector.h"
|
||||
#endif
|
||||
|
||||
#import "platformPOSIX/posixVolume.h"
|
||||
#import "core/util/tVector.h"
|
||||
|
||||
class MacFileSystem;
|
||||
|
||||
|
|
@ -20,16 +20,11 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platformMac/macCarbVolume.h"
|
||||
#include "platform/platformVolume.h"
|
||||
#include "console/console.h"
|
||||
|
||||
|
||||
//#define DEBUG_SPEW
|
||||
|
||||
#import <CoreServices/CoreServices.h>
|
||||
#import "platform/platform.h"
|
||||
#import "platformMac/macVolume.h"
|
||||
#import "platform/platformVolume.h"
|
||||
#import "console/console.h"
|
||||
|
||||
struct MacFileSystemChangeNotifier::Event
|
||||
{
|
||||
|
|
@ -38,7 +33,6 @@ struct MacFileSystemChangeNotifier::Event
|
|||
bool mHasChanged;
|
||||
};
|
||||
|
||||
|
||||
static void fsNotifyCallback(
|
||||
ConstFSEventStreamRef stream,
|
||||
void* callbackInfo,
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBClasses</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>ACTIONS</key>
|
||||
<dict>
|
||||
<key>toggleAutomaticLinkDetection</key>
|
||||
<string>id</string>
|
||||
<key>toggleAutomaticQuoteSubstitution</key>
|
||||
<string>id</string>
|
||||
<key>toggleGrammarChecking</key>
|
||||
<string>id</string>
|
||||
<key>toggleSmartInsertDelete</key>
|
||||
<string>id</string>
|
||||
</dict>
|
||||
<key>CLASS</key>
|
||||
<string>FirstResponder</string>
|
||||
<key>LANGUAGE</key>
|
||||
<string>ObjC</string>
|
||||
<key>SUPERCLASS</key>
|
||||
<string>NSObject</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>IBVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>629</string>
|
||||
<key>IBLastKnownRelativeProjectPath</key>
|
||||
<string>../../../../../GameExamples/T3D/buildFiles/Xcode/T3D.xcodeproj</string>
|
||||
<key>IBOldestOS</key>
|
||||
<integer>5</integer>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>29</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>9F33</string>
|
||||
<key>targetFramework</key>
|
||||
<string>IBCocoaFramework</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
|
|
@ -1,303 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
#include "platform/menus/menuBar.h"
|
||||
#include "platform/menus/popupMenu.h"
|
||||
#include "gui/core/guiCanvas.h"
|
||||
#include "windowManager/platformWindowMgr.h"
|
||||
#include "windowManager/platformWindow.h"
|
||||
|
||||
|
||||
class PlatformMenuBarData
|
||||
{
|
||||
public:
|
||||
PlatformMenuBarData() :
|
||||
mMenuEventHandlerRef(NULL),
|
||||
mCommandEventHandlerRef(NULL),
|
||||
mMenuOpenCount( 0 ),
|
||||
mLastCloseTime( 0 )
|
||||
{}
|
||||
|
||||
EventHandlerRef mMenuEventHandlerRef;
|
||||
EventHandlerRef mCommandEventHandlerRef;
|
||||
|
||||
/// More evil hacking for OSX. There seems to be no way to disable menu shortcuts and
|
||||
/// they are automatically routed within that Cocoa thing outside of our control. Also,
|
||||
/// there's no way of telling what triggered a command event and thus no way of knowing
|
||||
/// whether it was a keyboard shortcut. Sigh.
|
||||
///
|
||||
/// So what we do here is monitor the sequence of events leading to a command event. We
|
||||
/// capture the time the last open menu was closed and then, when we receive a command
|
||||
/// event (which are dished out after the menus are closed) and keyboard accelerators are
|
||||
/// disabled, we check whether we are a certain very short time away in the event stream
|
||||
/// from the menu close event. If so, we figure the event came from clicking in a menu.
|
||||
///
|
||||
/// Utterly evil and dirty but seems to do the trick.
|
||||
U32 mMenuOpenCount;
|
||||
EventTime mLastCloseTime;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark ---- menu event handler ----
|
||||
static OSStatus _OnMenuEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
|
||||
{
|
||||
PlatformMenuBarData* mbData = ( PlatformMenuBarData* ) userData;
|
||||
MenuRef menu;
|
||||
|
||||
GetEventParameter(theEvent, kEventParamDirectObject, typeMenuRef, NULL, sizeof(MenuRef), NULL, &menu);
|
||||
|
||||
// Count open/close for the sake of hotkey disabling.
|
||||
|
||||
UInt32 kind = GetEventKind( theEvent );
|
||||
if( kind == kEventMenuOpening )
|
||||
mbData->mMenuOpenCount ++;
|
||||
else
|
||||
{
|
||||
AssertWarn( mbData->mMenuOpenCount > 0, "Unbalanced menu open/close events in _OnMenuEvent" );
|
||||
if( mbData->mMenuOpenCount )
|
||||
mbData->mMenuOpenCount --;
|
||||
|
||||
// Initial menu closed. Capture time.
|
||||
|
||||
if( !mbData->mMenuOpenCount )
|
||||
mbData->mLastCloseTime = GetEventTime( theEvent );
|
||||
}
|
||||
|
||||
OSStatus err = eventNotHandledErr;
|
||||
PopupMenu *torqueMenu;
|
||||
if( CountMenuItems( menu ) > 0 )
|
||||
{
|
||||
// I don't know of a way to get the Torque PopupMenu object from a Carbon MenuRef
|
||||
// other than going through its first menu item
|
||||
err = GetMenuItemProperty(menu, 1, 'GG2d', 'ownr', sizeof(PopupMenu*), NULL, &torqueMenu);
|
||||
if( err == noErr && torqueMenu != NULL )
|
||||
{
|
||||
torqueMenu->onMenuSelect();
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark ---- menu command event handler ----
|
||||
static bool MacCarbHandleMenuCommand( void* hiCommand, PlatformMenuBarData* mbData )
|
||||
{
|
||||
HICommand *cmd = (HICommand*)hiCommand;
|
||||
|
||||
if(cmd->commandID != kHICommandTorque)
|
||||
return false;
|
||||
|
||||
MenuRef menu = cmd->menu.menuRef;
|
||||
MenuItemIndex item = cmd->menu.menuItemIndex;
|
||||
|
||||
// Run the command handler.
|
||||
|
||||
PopupMenu* torqueMenu;
|
||||
OSStatus err = GetMenuItemProperty(menu, item, 'GG2d', 'ownr', sizeof(PopupMenu*), NULL, &torqueMenu);
|
||||
AssertFatal(err == noErr, "Could not resolve the PopupMenu stored on a native menu item");
|
||||
|
||||
UInt32 command;
|
||||
err = GetMenuItemRefCon(menu, item, &command);
|
||||
AssertFatal(err == noErr, "Could not find the tag of a native menu item");
|
||||
|
||||
if(!torqueMenu->canHandleID(command))
|
||||
Con::errorf("menu claims it cannot handle that id. how odd.");
|
||||
|
||||
// un-highlight currently selected menu
|
||||
HiliteMenu( 0 );
|
||||
|
||||
return torqueMenu->handleSelect(command,NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark ---- Command Events ----
|
||||
|
||||
static OSStatus _OnCommandEvent(EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
|
||||
{
|
||||
PlatformMenuBarData* mbData = ( PlatformMenuBarData* ) userData;
|
||||
|
||||
HICommand commandStruct;
|
||||
|
||||
OSStatus result = eventNotHandledErr;
|
||||
|
||||
GetEventParameter(theEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &commandStruct);
|
||||
|
||||
// pass menu command events to a more specific handler.
|
||||
if(commandStruct.attributes & kHICommandFromMenu)
|
||||
{
|
||||
bool handleEvent = true;
|
||||
|
||||
// Do menu-close check hack.
|
||||
|
||||
PlatformWindow* window = PlatformWindowManager::get()->getFocusedWindow();
|
||||
if( !window || !window->getAcceleratorsEnabled() )
|
||||
{
|
||||
F32 deltaTime = mFabs( GetEventTime( theEvent ) - mbData->mLastCloseTime );
|
||||
if( deltaTime > 0.1f )
|
||||
handleEvent = false;
|
||||
}
|
||||
|
||||
if( handleEvent && MacCarbHandleMenuCommand(&commandStruct, mbData) )
|
||||
result = noErr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MenuBar Methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MenuBar::createPlatformPopupMenuData()
|
||||
{
|
||||
|
||||
mData = new PlatformMenuBarData;
|
||||
|
||||
}
|
||||
|
||||
void MenuBar::deletePlatformPopupMenuData()
|
||||
{
|
||||
|
||||
SAFE_DELETE(mData);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MenuBar::attachToCanvas(GuiCanvas *owner, S32 pos)
|
||||
{
|
||||
if(owner == NULL || isAttachedToCanvas())
|
||||
return;
|
||||
|
||||
mCanvas = owner;
|
||||
|
||||
|
||||
// Add the items
|
||||
for(S32 i = 0;i < size();++i)
|
||||
{
|
||||
PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(i));
|
||||
if(mnu == NULL)
|
||||
{
|
||||
Con::warnf("MenuBar::attachToMenuBar - Non-PopupMenu object in set");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(mnu->isAttachedToMenuBar())
|
||||
mnu->removeFromMenuBar();
|
||||
|
||||
mnu->attachToMenuBar(owner, pos + i, mnu->getBarTitle());
|
||||
}
|
||||
|
||||
// register as listener for menu opening events
|
||||
static EventTypeSpec menuEventTypes[ 2 ];
|
||||
|
||||
menuEventTypes[ 0 ].eventClass = kEventClassMenu;
|
||||
menuEventTypes[ 0 ].eventKind = kEventMenuOpening;
|
||||
menuEventTypes[ 1 ].eventClass = kEventClassMenu;
|
||||
menuEventTypes[ 1 ].eventKind = kEventMenuClosed;
|
||||
|
||||
EventHandlerUPP menuEventHandlerUPP;
|
||||
menuEventHandlerUPP = NewEventHandlerUPP(_OnMenuEvent);
|
||||
InstallEventHandler(GetApplicationEventTarget(), menuEventHandlerUPP, 2, menuEventTypes, mData, &mData->mMenuEventHandlerRef);
|
||||
|
||||
// register as listener for process command events
|
||||
static EventTypeSpec comEventTypes[1];
|
||||
comEventTypes[0].eventClass = kEventClassCommand;
|
||||
comEventTypes[0].eventKind = kEventCommandProcess;
|
||||
|
||||
EventHandlerUPP commandEventHandlerUPP;
|
||||
commandEventHandlerUPP = NewEventHandlerUPP(_OnCommandEvent);
|
||||
InstallEventHandler(GetApplicationEventTarget(), commandEventHandlerUPP, 1, comEventTypes, mData, &mData->mCommandEventHandlerRef);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MenuBar::removeFromCanvas()
|
||||
{
|
||||
if(mCanvas == NULL || ! isAttachedToCanvas())
|
||||
return;
|
||||
|
||||
if(mData->mCommandEventHandlerRef != NULL)
|
||||
RemoveEventHandler( mData->mCommandEventHandlerRef );
|
||||
mData->mCommandEventHandlerRef = NULL;
|
||||
|
||||
if(mData->mMenuEventHandlerRef != NULL)
|
||||
RemoveEventHandler( mData->mMenuEventHandlerRef );
|
||||
mData->mMenuEventHandlerRef = NULL;
|
||||
|
||||
// Add the items
|
||||
for(S32 i = 0;i < size();++i)
|
||||
{
|
||||
PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(i));
|
||||
if(mnu == NULL)
|
||||
{
|
||||
Con::warnf("MenuBar::removeFromMenuBar - Non-PopupMenu object in set");
|
||||
continue;
|
||||
}
|
||||
|
||||
mnu->removeFromMenuBar();
|
||||
}
|
||||
|
||||
mCanvas = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MenuBar::updateMenuBar(PopupMenu* menu)
|
||||
{
|
||||
if(! isAttachedToCanvas())
|
||||
return;
|
||||
|
||||
menu->removeFromMenuBar();
|
||||
SimSet::iterator itr = find(begin(), end(), menu);
|
||||
if(itr == end())
|
||||
return;
|
||||
|
||||
// Get the item currently at the position we want to add to
|
||||
S32 pos = itr - begin();
|
||||
S16 posID = 0;
|
||||
|
||||
PopupMenu *nextMenu = NULL;
|
||||
for(S32 i = pos + 1; i < size(); i++)
|
||||
{
|
||||
PopupMenu *testMenu = dynamic_cast<PopupMenu *>(at(i));
|
||||
if (testMenu && testMenu->isAttachedToMenuBar())
|
||||
{
|
||||
nextMenu = testMenu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nextMenu)
|
||||
posID = GetMenuID(nextMenu->mData->mMenu);
|
||||
|
||||
menu->attachToMenuBar(mCanvas, posID, menu->mBarTitle);
|
||||
}
|
||||
|
|
@ -1,439 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "platformMac/platformMacCarb.h"
|
||||
#include "platform/menus/popupmenu.h"
|
||||
#include "core/util/safeDelete.h"
|
||||
#include "gui/core/guiCanvas.h"
|
||||
|
||||
void PopupMenu::createPlatformPopupMenuData()
|
||||
{
|
||||
mData = new PlatformPopupMenuData;
|
||||
}
|
||||
|
||||
void PopupMenu::deletePlatformPopupMenuData()
|
||||
{
|
||||
SAFE_DELETE(mData);
|
||||
}
|
||||
|
||||
void PopupMenu::createPlatformMenu()
|
||||
{
|
||||
OSStatus err = CreateNewMenu( mData->tag, kMenuAttrAutoDisable,&(mData->mMenu));
|
||||
CFRetain(mData->mMenu);
|
||||
AssertFatal(err == noErr, "Could not create Carbon MenuRef");
|
||||
}
|
||||
|
||||
static int _getModifierMask(const char* accel)
|
||||
{
|
||||
int ret = 0;
|
||||
if(dStrstr(accel, "ctrl"))
|
||||
ret |= kMenuControlModifier;
|
||||
if(dStrstr(accel, "shift"))
|
||||
ret |= kMenuShiftModifier;
|
||||
if(dStrstr(accel, "alt"))
|
||||
ret |= kMenuOptionModifier;
|
||||
if(!(dStrstr(accel, "cmd") || dStrstr(accel, "command")))
|
||||
ret |= kMenuNoCommandModifier;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _assignCommandKeys(const char* accel, MenuRef menu, MenuItemIndex item)
|
||||
{
|
||||
if(!(accel && *accel))
|
||||
return;
|
||||
|
||||
// get the modifier keys
|
||||
String _accel = String::ToLower( accel );
|
||||
int mods = _getModifierMask(_accel);
|
||||
|
||||
// accel is space or dash delimted.
|
||||
// the modifier key is either the last token in accel, or the first char in accel.
|
||||
const char* key = dStrrchr(_accel, ' ');
|
||||
if(!key)
|
||||
key = dStrrchr(_accel, '-');
|
||||
if(!key)
|
||||
key = _accel;
|
||||
else
|
||||
key++;
|
||||
|
||||
if(dStrlen(key) <= 1)
|
||||
{
|
||||
char k = dToupper( key[0] );
|
||||
SetMenuItemCommandKey( menu, item, false, k );
|
||||
}
|
||||
else
|
||||
{
|
||||
SInt16 glyph = kMenuNullGlyph;
|
||||
|
||||
//*** A lot of these mappings came from a listing at http://developer.apple.com/releasenotes/Carbon/HIToolboxOlderNotes.html
|
||||
if(!dStricmp(key, "DELETE"))
|
||||
glyph = kMenuDeleteRightGlyph;
|
||||
|
||||
else if(!dStricmp(key, "HOME"))
|
||||
glyph = kMenuNorthwestArrowGlyph;
|
||||
|
||||
else if(!dStricmp(key, "END"))
|
||||
glyph = kMenuSoutheastArrowGlyph;
|
||||
|
||||
else if(!dStricmp(key, "BACKSPACE"))
|
||||
glyph = kMenuDeleteLeftGlyph;
|
||||
|
||||
else if(!dStricmp(key, "TAB"))
|
||||
glyph = kMenuTabRightGlyph;
|
||||
|
||||
else if(!dStricmp(key, "RETURN"))
|
||||
glyph = kMenuReturnGlyph;
|
||||
|
||||
else if(!dStricmp(key, "ENTER"))
|
||||
glyph = kMenuEnterGlyph;
|
||||
|
||||
else if(!dStricmp(key, "PG UP"))
|
||||
glyph = kMenuPageUpGlyph;
|
||||
|
||||
else if(!dStricmp(key, "PG DOWN"))
|
||||
glyph = kMenuPageDownGlyph;
|
||||
|
||||
else if(!dStricmp(key, "ESC"))
|
||||
glyph = kMenuEscapeGlyph;
|
||||
|
||||
else if(!dStricmp(key, "LEFT"))
|
||||
glyph = kMenuLeftArrowGlyph;
|
||||
|
||||
else if(!dStricmp(key, "RIGHT"))
|
||||
glyph = kMenuRightArrowGlyph;
|
||||
|
||||
else if(!dStricmp(key, "UP"))
|
||||
glyph = kMenuUpArrowGlyph;
|
||||
|
||||
else if(!dStricmp(key, "DOWN"))
|
||||
glyph = kMenuDownArrowGlyph;
|
||||
|
||||
else if(!dStricmp(key, "SPACE"))
|
||||
glyph = kMenuSpaceGlyph;
|
||||
|
||||
else if(!dStricmp(key, "F1"))
|
||||
glyph = kMenuF1Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F2"))
|
||||
glyph = kMenuF2Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F3"))
|
||||
glyph = kMenuF3Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F4"))
|
||||
glyph = kMenuF4Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F5"))
|
||||
glyph = kMenuF5Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F6"))
|
||||
glyph = kMenuF6Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F7"))
|
||||
glyph = kMenuF7Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F8"))
|
||||
glyph = kMenuF8Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F9"))
|
||||
glyph = kMenuF9Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F10"))
|
||||
glyph = kMenuF10Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F11"))
|
||||
glyph = kMenuF11Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F12"))
|
||||
glyph = kMenuF12Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F13"))
|
||||
glyph = kMenuF13Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F14"))
|
||||
glyph = kMenuF14Glyph;
|
||||
|
||||
else if(!dStricmp(key, "F15"))
|
||||
glyph = kMenuF15Glyph;
|
||||
|
||||
SetMenuItemKeyGlyph(menu, item, glyph);
|
||||
}
|
||||
|
||||
SetMenuItemModifiers(menu, item, mods);
|
||||
}
|
||||
|
||||
|
||||
S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accel)
|
||||
{
|
||||
MenuItemIndex item;
|
||||
CFStringRef cftitle;
|
||||
MenuItemAttributes attr = 0;
|
||||
|
||||
bool needRelease = false;
|
||||
if(title && *title)
|
||||
{
|
||||
cftitle = CFStringCreateWithCString(NULL,title,kCFStringEncodingUTF8);
|
||||
needRelease = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cftitle = CFSTR("-");
|
||||
attr = kMenuItemAttrSeparator;
|
||||
}
|
||||
|
||||
InsertMenuItemTextWithCFString(mData->mMenu, cftitle, pos, attr, kHICommandTorque + 1);
|
||||
if( needRelease )
|
||||
CFRelease( cftitle );
|
||||
|
||||
// ensure that we have the correct index for the new menu item
|
||||
MenuRef outref;
|
||||
GetIndMenuItemWithCommandID(mData->mMenu, kHICommandTorque+1, 1, &outref, &item);
|
||||
SetMenuItemCommandID(mData->mMenu, item, kHICommandTorque);
|
||||
|
||||
// save a ref to the PopupMenu that owns this item.
|
||||
PopupMenu* thisMenu = this;
|
||||
SetMenuItemProperty(mData->mMenu, item, 'GG2d', 'ownr', sizeof(PopupMenu*), &thisMenu);
|
||||
|
||||
// construct the accelerator keys
|
||||
_assignCommandKeys(accel, mData->mMenu, item);
|
||||
|
||||
S32 tag = PlatformPopupMenuData::getTag();
|
||||
SetMenuItemRefCon(mData->mMenu, item, tag);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu)
|
||||
{
|
||||
for(S32 i = 0;i < mSubmenus->size();i++)
|
||||
{
|
||||
if(submenu == (*mSubmenus)[i])
|
||||
{
|
||||
Con::errorf("PopupMenu::insertSubMenu - Attempting to add submenu twice");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
CFStringRef cftitle = CFStringCreateWithCString(NULL,title,kCFStringEncodingUTF8);
|
||||
InsertMenuItemTextWithCFString(mData->mMenu, cftitle, pos, 0, kHICommandTorque + 1);
|
||||
CFRelease( cftitle );
|
||||
|
||||
// ensure that we have the correct index for the new menu item
|
||||
MenuRef outref;
|
||||
MenuItemIndex item;
|
||||
GetIndMenuItemWithCommandID(mData->mMenu, kHICommandTorque+1, 1, &outref, &item);
|
||||
SetMenuItemCommandID(mData->mMenu, item, 0);
|
||||
|
||||
S32 tag = PlatformPopupMenuData::getTag();
|
||||
SetMenuItemRefCon( mData->mMenu, item, tag);
|
||||
|
||||
// store a pointer to the PopupMenu this item represents. See PopupMenu::removeItem()
|
||||
SetMenuItemProperty(mData->mMenu, item, 'GG2d', 'subm', sizeof(PopupMenu*), submenu);
|
||||
|
||||
SetMenuItemHierarchicalMenu( mData->mMenu, item, submenu->mData->mMenu);
|
||||
mSubmenus->addObject(submenu);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
void PopupMenu::removeItem(S32 itemPos)
|
||||
{
|
||||
PopupMenu* submenu;
|
||||
itemPos++; // adjust torque -> mac menu index
|
||||
|
||||
OSStatus err = GetMenuItemProperty(mData->mMenu, itemPos, 'GG2d', 'subm', sizeof(PopupMenu*),NULL,&submenu);
|
||||
if(err == noErr)
|
||||
mSubmenus->removeObject(submenu);
|
||||
|
||||
// deleting the item decrements the ref count on the mac submenu.
|
||||
DeleteMenuItem(mData->mMenu, itemPos);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PopupMenu::enableItem(S32 pos, bool enable)
|
||||
{
|
||||
pos++; // adjust torque -> mac menu index.
|
||||
if(enable)
|
||||
EnableMenuItem(mData->mMenu, pos);
|
||||
else
|
||||
DisableMenuItem(mData->mMenu, pos);
|
||||
}
|
||||
|
||||
void PopupMenu::checkItem(S32 pos, bool checked)
|
||||
{
|
||||
pos++;
|
||||
CheckMenuItem(mData->mMenu, pos, checked);
|
||||
}
|
||||
|
||||
void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos)
|
||||
{
|
||||
// uncheck items
|
||||
for(int i = firstPos; i <= lastPos; i++)
|
||||
checkItem( i, false);
|
||||
|
||||
// check the selected item
|
||||
checkItem( checkPos, true);
|
||||
}
|
||||
|
||||
bool PopupMenu::isItemChecked(S32 pos)
|
||||
{
|
||||
CharParameter mark;
|
||||
GetItemMark(mData->mMenu, pos, &mark);
|
||||
return (mark == checkMark);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// this method really isn't necessary for the mac implementation
|
||||
bool PopupMenu::canHandleID(U32 iD)
|
||||
{
|
||||
for(S32 i = 0;i < mSubmenus->size();i++)
|
||||
{
|
||||
PopupMenu *subM = dynamic_cast<PopupMenu *>((*mSubmenus)[i]);
|
||||
if(subM == NULL)
|
||||
continue;
|
||||
|
||||
if(subM->canHandleID(iD))
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt32 refcon;
|
||||
U32 nItems = CountMenuItems(mData->mMenu);
|
||||
for(int i = 1; i <= nItems; i++)
|
||||
{
|
||||
GetMenuItemRefCon(mData->mMenu, i, &refcon);
|
||||
if(refcon == iD)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */)
|
||||
{
|
||||
// [tom, 8/20/2006] Pass off to a sub menu if it's for them
|
||||
for(S32 i = 0;i < mSubmenus->size();i++)
|
||||
{
|
||||
PopupMenu *subM = dynamic_cast<PopupMenu *>((*mSubmenus)[i]);
|
||||
if(subM == NULL)
|
||||
continue;
|
||||
|
||||
if(subM->canHandleID(command))
|
||||
{
|
||||
return subM->handleSelect(command, text);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that this menu actually has an item with the specificed command / refcon.
|
||||
// this is not strictly necessary, we're just doing it here to keep the behavior
|
||||
// in line with the windows implementation.
|
||||
UInt32 refcon;
|
||||
U32 nItems = CountMenuItems(mData->mMenu);
|
||||
S32 pos = -1;
|
||||
for(int i = 1; i <= nItems; i++)
|
||||
{
|
||||
GetMenuItemRefCon(mData->mMenu, i, &refcon);
|
||||
if(refcon == command)
|
||||
pos = i;
|
||||
}
|
||||
if(pos == -1)
|
||||
{
|
||||
Con::errorf("PopupMenu::handleSelect - Could not find menu item position for ID %d ... this shouldn't happen!", command);
|
||||
return false;
|
||||
}
|
||||
|
||||
char textbuf[1024];
|
||||
if(!text)
|
||||
{
|
||||
CFStringRef cfstr;
|
||||
CopyMenuItemTextAsCFString(mData->mMenu, pos, &cfstr);
|
||||
CFStringGetCString(cfstr,textbuf,sizeof(textbuf) - 1,kCFStringEncodingUTF8);
|
||||
CFRelease( cfstr );
|
||||
text = textbuf;
|
||||
}
|
||||
|
||||
// [tom, 8/20/2006] Wasn't handled by a submenu, pass off to script
|
||||
return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(pos - 1), text ? text : ""));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PopupMenu::showPopup(GuiCanvas* canvas, S32 x /* = -1 */, S32 y /* = -1 */)
|
||||
{
|
||||
if(x < 0 || y < 0)
|
||||
{
|
||||
Point2I p = canvas->getCursorPos();
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
}
|
||||
|
||||
PopUpMenuSelect(mData->mMenu, y, x, 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void PopupMenu::attachToMenuBar(GuiCanvas* canvas, S32 pos, const char *title)
|
||||
{
|
||||
CFStringRef cftitle = CFStringCreateWithCString(NULL,title,kCFStringEncodingUTF8);
|
||||
SetMenuTitleWithCFString(mData->mMenu, cftitle);
|
||||
CFRelease( cftitle );
|
||||
InsertMenu(mData->mMenu, pos);
|
||||
|
||||
onAttachToMenuBar(canvas, pos, title);
|
||||
}
|
||||
|
||||
void PopupMenu::removeFromMenuBar()
|
||||
{
|
||||
DeleteMenu(mData->tag);
|
||||
|
||||
onRemoveFromMenuBar(mCanvas);
|
||||
}
|
||||
|
||||
U32 PopupMenu::getItemCount()
|
||||
{
|
||||
return CountMenuItems( mData->mMenu );
|
||||
}
|
||||
|
||||
bool PopupMenu::setItem(S32 pos, const char *title, const char *accelerator)
|
||||
{
|
||||
//TODO: update accelerator?
|
||||
|
||||
pos += 1; // Torque to mac index
|
||||
|
||||
CFStringRef cftitle = CFStringCreateWithCString( NULL, title, kCFStringEncodingUTF8 );
|
||||
SetMenuItemTextWithCFString( mData->mMenu, pos, cftitle );
|
||||
CFRelease( cftitle );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
S32 PopupMenu::getPosOnMenuBar()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) 2012 GarageGames, LLC
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _PLATFORMMACCARB_H_
|
||||
#define _PLATFORMMACCARB_H_
|
||||
|
||||
/// NOTE: Placing system headers before Torque's platform.h will work around the Torque-Redefines-New problems.
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include "platform/platform.h"
|
||||
#include "math/mMath.h"
|
||||
|
||||
#include "gfx/gl/tGL/tGL.h"
|
||||
#define __gl_h_
|
||||
#include <AGL/agl.h>
|
||||
|
||||
class MacCarbPlatState
|
||||
{
|
||||
public:
|
||||
GDHandle hDisplay;
|
||||
CGDirectDisplayID cgDisplay;
|
||||
|
||||
bool captureDisplay;
|
||||
bool fadeWindows;
|
||||
|
||||
WindowPtr appWindow;
|
||||
char appWindowTitle[256];
|
||||
WindowGroupRef torqueWindowGroup;
|
||||
|
||||
bool quit;
|
||||
|
||||
AGLContext ctx;
|
||||
bool ctxNeedsUpdate;
|
||||
|
||||
S32 desktopBitsPixel;
|
||||
S32 desktopWidth;
|
||||
S32 desktopHeight;
|
||||
U32 currentTime;
|
||||
bool isFullScreen;
|
||||
|
||||
U32 osVersion;
|
||||
|
||||
TSMDocumentID tsmDoc;
|
||||
bool tsmActive;
|
||||
|
||||
U32 firstThreadId;
|
||||
|
||||
void* alertSemaphore;
|
||||
S32 alertHit;
|
||||
DialogRef alertDlg;
|
||||
EventQueueRef mainEventQueue;
|
||||
|
||||
MRandomLCG platRandom;
|
||||
|
||||
bool mouseLocked;
|
||||
bool backgrounded;
|
||||
|
||||
U32 sleepTicks;
|
||||
|
||||
Point2I windowSize;
|
||||
|
||||
U32 appReturn;
|
||||
|
||||
U32 argc;
|
||||
char** argv;
|
||||
|
||||
U32 lastTimeTick;
|
||||
|
||||
MacCarbPlatState();
|
||||
};
|
||||
|
||||
/// Global singleton that encapsulates a lot of mac platform state & globals.
|
||||
extern MacCarbPlatState platState;
|
||||
|
||||
/// @name Misc Mac Plat Functions
|
||||
/// Functions that are used by multiple files in the mac plat, but too trivial
|
||||
/// to require their own header file.
|
||||
/// @{
|
||||
/// Fills gGLState with info about this gl renderer's capabilities.
|
||||
void getGLCapabilities(void);
|
||||
|
||||
/// Creates a new mac window, of a particular size, centered on the screen.
|
||||
/// If a fullScreen window is requested, then the window is created without
|
||||
/// decoration, in front of all other normal windows AND BEHIND asian text input methods.
|
||||
/// This path to a fullScreen window allows asian text input methods to work
|
||||
/// in full screen mode, because it avoids capturing the display.
|
||||
WindowPtr MacCarbCreateOpenGLWindow( GDHandle hDevice, U32 width, U32 height, bool fullScreen );
|
||||
|
||||
/// Asnychronously fade a window into existence, and set menu bar visibility.
|
||||
/// The fading can be turned off via the preference $pref::mac::fadeWindows.
|
||||
/// It also sends itself to the main thread if it is called on any other thread.
|
||||
void MacCarbFadeInWindow( WindowPtr window );
|
||||
|
||||
/// Asnychronously fade a window out of existence. The window will be destroyed
|
||||
/// when the fade is complete.
|
||||
/// The fading can be turned off via the preference $pref::mac::fadeWindows.
|
||||
/// It also sends itself to the main thread if it is called on any other thread.
|
||||
void MacCarbFadeAndReleaseWindow( WindowPtr window );
|
||||
|
||||
/// Translates a Mac keycode to a Torque keycode
|
||||
U8 TranslateOSKeyCode(U8 vcode);
|
||||
/// @}
|
||||
|
||||
/// @name Misc Mac Plat constants
|
||||
/// @{
|
||||
|
||||
/// earlier versions of OSX don't have these convinience macros, so manually stick them here.
|
||||
#ifndef IntToFixed
|
||||
#define IntToFixed(a) ((Fixed)(a) <<16)
|
||||
#define FixedToInt(a) ((short)(((Fixed)(a) + fixed1/2) >> 16))
|
||||
#endif
|
||||
|
||||
/// window level constants
|
||||
const U32 kTAlertWindowLevel = CGShieldingWindowLevel() - 1;
|
||||
const U32 kTUtilityWindowLevel = CGShieldingWindowLevel() - 2;
|
||||
const U32 kTFullscreenWindowLevel = CGShieldingWindowLevel() - 3;
|
||||
|
||||
/// mouse wheel sensitivity factor
|
||||
const S32 kTMouseWheelMagnificationFactor = 25;
|
||||
|
||||
/// Torque Menu Command ID
|
||||
const U32 kHICommandTorque = 'TORQ';
|
||||
|
||||
/// @}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Platform Menu Data
|
||||
//-----------------------------------------------------------------------------
|
||||
class PlatformPopupMenuData
|
||||
{
|
||||
public:
|
||||
// We assign each new menu item an arbitrary integer tag.
|
||||
static S32 getTag()
|
||||
{
|
||||
static S32 lastTag = 'TORQ';
|
||||
return ++lastTag;
|
||||
}
|
||||
|
||||
MenuRef mMenu;
|
||||
S32 tag;
|
||||
PlatformPopupMenuData()
|
||||
{
|
||||
mMenu = NULL;
|
||||
tag = getTag();
|
||||
}
|
||||
|
||||
~PlatformPopupMenuData()
|
||||
{
|
||||
if(mMenu)
|
||||
CFRelease(mMenu);
|
||||
mMenu = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_PLATFORMMACCARB_H_
|
||||
|
||||
Binary file not shown.
|
|
@ -11,12 +11,6 @@ namespace PlatformGL
|
|||
|
||||
void init()
|
||||
{
|
||||
static bool inited = false;
|
||||
|
||||
if(inited)
|
||||
return;
|
||||
|
||||
inited = true;
|
||||
const U32 majorOGL = 3;
|
||||
const U32 minorOGL = 2;
|
||||
U32 debugFlag = 0;
|
||||
|
|
@ -28,6 +22,9 @@ namespace PlatformGL
|
|||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minorOGL);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag);
|
||||
#ifdef TORQUE_GL_SOFTWARE
|
||||
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 0);
|
||||
#endif
|
||||
|
||||
SDL_ClearError();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,11 +245,6 @@ void PostEffectManager::renderEffects( const SceneRenderState *state,
|
|||
const PFXRenderTime effectTiming,
|
||||
const String &binName )
|
||||
{
|
||||
// MACHAX - The proper fix is to ensure that PostFX do not get rendered if
|
||||
// their shader failed to load.
|
||||
#ifdef TORQUE_OS_MAC
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Check the global render effect state as
|
||||
// well as the
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@ SFXALDevice::SFXALDevice( SFXProvider *provider,
|
|||
AssertFatal( mDevice != NULL && mContext != NULL, "Failed to create OpenAL device and/or context!" );
|
||||
|
||||
// Start the update thread.
|
||||
#ifndef TORQUE_OS_LINUX
|
||||
// TODO AsyncPeriodicUpdateThread support for Linux/Mac
|
||||
#ifdef TORQUE_OS_WIN
|
||||
if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
|
||||
{
|
||||
SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread
|
||||
|
|
|
|||
Binary file not shown.
1
Templates/Empty/game/shaders/.gitignore
vendored
Normal file
1
Templates/Empty/game/shaders/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/procedural/
|
||||
|
|
@ -31,8 +31,6 @@ in vec4 mieColor;
|
|||
#define IN_mieColor mieColor
|
||||
in vec3 v3Direction;
|
||||
#define IN_v3Direction v3Direction
|
||||
in float zPosition;
|
||||
#define IN_zPosition zPosition
|
||||
in vec3 pos;
|
||||
#define IN_pos pos
|
||||
|
||||
|
|
@ -66,12 +64,6 @@ void main()
|
|||
fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) );
|
||||
OUT_col = mix( color, nightSkyColor, nightInterpAndExposure.y );
|
||||
|
||||
// Clip based on the camera-relative
|
||||
// z position of the vertex, passed through
|
||||
// from the vertex position.
|
||||
if(zPosition < 0.0)
|
||||
discard;
|
||||
|
||||
OUT_col.a = 1;
|
||||
|
||||
OUT_col = clamp(OUT_col, 0.0, 1.0);
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ out vec4 mieColor;
|
|||
#define OUT_mieColor mieColor
|
||||
out vec3 v3Direction;
|
||||
#define OUT_v3Direction v3Direction
|
||||
out float zPosition;
|
||||
#define OUT_zPosition zPosition
|
||||
out vec3 pos;
|
||||
#define OUT_pos pos
|
||||
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
|||
colorBuffer *= (1.0 - colorBuffer.a);
|
||||
}
|
||||
|
||||
colorBuffer *= float4(lightBuffer.rgb, 1.0);
|
||||
colorBuffer += float4(specular, specular, specular, 1.0);
|
||||
colorBuffer *= float4(lightBuffer.rgb, 1.0);
|
||||
|
||||
return hdrEncode( float4(colorBuffer.rgb, 1.0) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D colorBufferTex;
|
||||
|
||||
out vec4 OUT_FragColor0;
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "../../../postFx/gl/postFX.glsl"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D glowBuffer;
|
||||
|
||||
out vec4 OUT_FragColor0;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D lightPrePassTex;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D lightPrePassTex;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D matinfoTex;
|
||||
|
||||
out vec4 OUT_FragColor0;
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ void main()
|
|||
colorBuffer *= (1.0 - colorBuffer.a);
|
||||
}
|
||||
|
||||
colorBuffer *= vec4(lightBuffer.rgb, 1.0);
|
||||
colorBuffer += vec4(specular, specular, specular, 1.0);
|
||||
colorBuffer *= vec4(lightBuffer.rgb, 1.0);
|
||||
|
||||
OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,17 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uvScene );
|
||||
vec3 subsurface = vec3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = vec3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = vec3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
|
||||
vec3 normal = prepassSample.rgb;
|
||||
|
|
@ -258,6 +269,5 @@ void main()
|
|||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uvScene );
|
||||
OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,17 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uvScene );
|
||||
vec3 subsurface = vec3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = vec3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = vec3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
|
||||
vec3 normal = prepassSample.rgb;
|
||||
|
|
@ -195,6 +206,5 @@ void main()
|
|||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uvScene );
|
||||
OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,17 @@ void main()
|
|||
return;
|
||||
}
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uv0 );
|
||||
vec3 subsurface = vec3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = vec3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = vec3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
|
||||
vec3 normal = prepassSample.rgb;
|
||||
|
|
@ -312,6 +323,5 @@ void main()
|
|||
lightColorOut = debugColor;
|
||||
#endif
|
||||
|
||||
vec4 colorSample = texture( colorBuffer, uv0 );
|
||||
OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,16 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
|||
{
|
||||
return float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
||||
float3 subsurface = float3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene );
|
||||
|
|
@ -263,6 +273,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
|||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
}
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
||||
return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,17 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
|||
return float4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
||||
float3 subsurface = float3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
|
||||
// Sample/unpack the normal/z data
|
||||
float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene );
|
||||
float3 normal = prepassSample.rgb;
|
||||
|
|
@ -194,6 +205,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
|
|||
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
|
||||
}
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
|
||||
return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,16 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
|
|||
return float4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
|
||||
float3 subsurface = float3(0.0,0.0,0.0);
|
||||
if (getFlag( matInfo.r, 1 ))
|
||||
{
|
||||
subsurface = colorSample.rgb;
|
||||
if (colorSample.r>colorSample.g)
|
||||
subsurface = float3(0.772549, 0.337255, 0.262745);
|
||||
else
|
||||
subsurface = float3(0.337255, 0.772549, 0.262745);
|
||||
}
|
||||
// Sample/unpack the normal/z data
|
||||
float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, IN.uv0 );
|
||||
float3 normal = prepassSample.rgb;
|
||||
|
|
@ -314,6 +324,5 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
|
|||
lightColorOut = debugColor;
|
||||
#endif
|
||||
|
||||
float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
|
||||
return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,5 +43,5 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
|
|||
fogData.y,
|
||||
fogData.z );
|
||||
|
||||
return hdrEncode( float4( fogColor.rgb, 1.0 - saturate( factor ) ) );
|
||||
return hdrEncode( float4( toLinear(fogColor.rgb), 1.0 - saturate( factor ) ) );
|
||||
}
|
||||
|
|
@ -48,5 +48,5 @@ void main()
|
|||
fogData.y,
|
||||
fogData.z );
|
||||
|
||||
OUT_col = hdrEncode( vec4( fogColor.rgb, 1.0 - saturate( factor ) ) );
|
||||
OUT_col = hdrEncode( vec4( toLinear(fogColor.rgb), 1.0 - saturate( factor ) ) );
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>torqueDemo</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.garagegames.${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>GG3d</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>mainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>macApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -31,8 +31,6 @@ in vec4 mieColor;
|
|||
#define IN_mieColor mieColor
|
||||
in vec3 v3Direction;
|
||||
#define IN_v3Direction v3Direction
|
||||
in float zPosition;
|
||||
#define IN_zPosition zPosition
|
||||
in vec3 pos;
|
||||
#define IN_pos pos
|
||||
|
||||
|
|
@ -66,12 +64,6 @@ void main()
|
|||
fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) );
|
||||
OUT_col = mix( color, nightSkyColor, nightInterpAndExposure.y );
|
||||
|
||||
// Clip based on the camera-relative
|
||||
// z position of the vertex, passed through
|
||||
// from the vertex position.
|
||||
if(zPosition < 0.0)
|
||||
discard;
|
||||
|
||||
OUT_col.a = 1;
|
||||
|
||||
OUT_col = clamp(OUT_col, 0.0, 1.0);
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ out vec4 mieColor;
|
|||
#define OUT_mieColor mieColor
|
||||
out vec3 v3Direction;
|
||||
#define OUT_v3Direction v3Direction
|
||||
out float zPosition;
|
||||
#define OUT_zPosition zPosition
|
||||
out vec3 pos;
|
||||
#define OUT_pos pos
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D colorBufferTex;
|
||||
|
||||
out vec4 OUT_FragColor0;
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
#include "../../../postFx/gl/postFX.glsl"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D glowBuffer;
|
||||
|
||||
out vec4 OUT_FragColor0;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D lightPrePassTex;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D lightPrePassTex;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
// IN THE SOFTWARE.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "../../../gl/hlslCompat.glsl"
|
||||
#include "shadergen:/autogenConditioners.h"
|
||||
|
||||
in vec2 uv0;
|
||||
uniform sampler2D matinfoTex;
|
||||
|
||||
out vec4 OUT_FragColor0;
|
||||
|
|
|
|||
|
|
@ -7,20 +7,14 @@
|
|||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>torqueDemo</string>
|
||||
<string>torque</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.garagegames.${EXECUTABLE_NAME}</string>
|
||||
<string>com.torque3d.${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>GG3d</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>mainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>macApplication</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -64,11 +64,16 @@ macro(addPath dir)
|
|||
if(${ARGC} GREATER 1 AND "${ARGV1}" STREQUAL "REC")
|
||||
set(glob_config GLOB_RECURSE)
|
||||
endif()
|
||||
set(mac_files "")
|
||||
if(APPLE)
|
||||
set(mac_files ${dir}/*.mm ${dir}/*.m)
|
||||
endif()
|
||||
file(${glob_config} tmp_files
|
||||
${dir}/*.cpp
|
||||
${dir}/*.c
|
||||
${dir}/*.cc
|
||||
${dir}/*.h
|
||||
${mac_files}
|
||||
#${dir}/*.asm
|
||||
)
|
||||
foreach(entry ${BLACKLIST})
|
||||
|
|
@ -167,6 +172,13 @@ macro(_process_libs)
|
|||
endif()
|
||||
endmacro()
|
||||
|
||||
# apple frameworks
|
||||
macro(addFramework framework)
|
||||
if (APPLE)
|
||||
addLib("-framework ${framework}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
###############################################################################
|
||||
### Include Handling
|
||||
###############################################################################
|
||||
|
|
@ -298,7 +310,13 @@ macro(finishExecutable)
|
|||
set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_EXECUTABLES}")
|
||||
endif()
|
||||
|
||||
add_executable("${PROJECT_NAME}" WIN32 ${${PROJECT_NAME}_files})
|
||||
if (APPLE)
|
||||
set(ICON_FILE "${projectSrcDir}/torque.icns")
|
||||
set_source_files_properties(${ICON_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
add_executable("${PROJECT_NAME}" MACOSX_BUNDLE ${ICON_FILE} ${${PROJECT_NAME}_files})
|
||||
else()
|
||||
add_executable("${PROJECT_NAME}" WIN32 ${${PROJECT_NAME}_files})
|
||||
endif()
|
||||
addInclude("${firstDir}")
|
||||
|
||||
_postTargetProcess()
|
||||
|
|
@ -387,13 +405,20 @@ else()
|
|||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${projectOutDir}")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${projectOutDir}")
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${projectOutDir}")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${projectOutDir}")
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}")
|
||||
endif()
|
||||
|
||||
# fix the debug/release subfolders on windows
|
||||
if(MSVC)
|
||||
SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY" "${projectOutDir}")
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ addPath("${libDir}/epoxy/src")
|
|||
if (WIN32)
|
||||
addPath("${libDir}/epoxy/src/wgl")
|
||||
addDef(BUILD_WGL)
|
||||
else()
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
addPath("${libDir}/epoxy/src/glx")
|
||||
addDef(BUILD_GLX)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ mark_as_advanced(TORQUE_EXPERIMENTAL_EC)
|
|||
###############################################################################
|
||||
# options
|
||||
###############################################################################
|
||||
if(NOT MSVC) # handle single-configuration generator
|
||||
if(NOT MSVC AND NOT APPLE) # handle single-configuration generator
|
||||
set(TORQUE_BUILD_TYPE "Debug" CACHE STRING "Select one of Debug, Release and RelWithDebInfo")
|
||||
set_property(CACHE TORQUE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo")
|
||||
|
||||
|
|
@ -157,7 +157,7 @@ if(WIN32)
|
|||
endif()
|
||||
|
||||
# build types
|
||||
if(NOT MSVC) # handle single-configuration generator
|
||||
if(NOT MSVC AND NOT APPLE) # handle single-configuration generator
|
||||
set(CMAKE_BUILD_TYPE ${TORQUE_BUILD_TYPE})
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(TORQUE_DEBUG TRUE)
|
||||
|
|
@ -324,15 +324,17 @@ endif()
|
|||
# OpenAL
|
||||
if(TORQUE_SFX_OPENAL AND NOT TORQUE_DEDICATED)
|
||||
addPath("${srcDir}/sfx/openal")
|
||||
#addPath("${srcDir}/sfx/openal/mac")
|
||||
if(WIN32)
|
||||
addPath("${srcDir}/sfx/openal/win32")
|
||||
addInclude("${libDir}/openal/win32")
|
||||
addPath("${srcDir}/sfx/openal/win32")
|
||||
addInclude("${libDir}/openal/win32")
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
addPath("${srcDir}/sfx/openal/linux")
|
||||
endif()
|
||||
if(APPLE)
|
||||
addPath("${srcDir}/sfx/openal/mac")
|
||||
addFramework("OpenAL")
|
||||
endif()
|
||||
if(UNIX)
|
||||
addPath("${srcDir}/sfx/openal/linux")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
# Vorbis
|
||||
|
|
@ -388,7 +390,7 @@ if(TORQUE_SDL)
|
|||
addPathRec("${srcDir}/gfx/gl/sdl")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
#set(CMAKE_SIZEOF_VOID_P 4) #force 32 bit
|
||||
set(ENV{CFLAGS} "${CXX_FLAG32} -g -O3")
|
||||
if("${TORQUE_ADDITIONAL_LINKER_FLAGS}" STREQUAL "")
|
||||
|
|
@ -408,22 +410,33 @@ if(TORQUE_SDL)
|
|||
# Add other flags to the compiler
|
||||
add_definitions(${GTK3_CFLAGS_OTHER})
|
||||
|
||||
set(BLACKLIST "nfd_win.cpp" )
|
||||
set(BLACKLIST "nfd_win.cpp" "nfd_cocoa.m" )
|
||||
addLib(nativeFileDialogs)
|
||||
|
||||
set(BLACKLIST "" )
|
||||
target_link_libraries(nativeFileDialogs ${GTK3_LIBRARIES})
|
||||
elseif(APPLE)
|
||||
set(BLACKLIST "nfd_gtk.c" "nfd_win.cpp" )
|
||||
addLib(nativeFileDialogs)
|
||||
set(BLACKLIST "" )
|
||||
else()
|
||||
set(BLACKLIST "nfd_gtk.c" )
|
||||
set(BLACKLIST "nfd_gtk.c" "nfd_cocoa.m" )
|
||||
addLib(nativeFileDialogs)
|
||||
set(BLACKLIST "" )
|
||||
set(BLACKLIST "" )
|
||||
addLib(comctl32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#override and hide SDL2 cache variables
|
||||
set(SDL_SHARED ON CACHE INTERNAL "" FORCE)
|
||||
set(SDL_STATIC OFF CACHE INTERNAL "" FORCE)
|
||||
#set apple to sue sdl static lib, other platforms use dynamic
|
||||
if(APPLE)
|
||||
set(SDL_SHARED OFF CACHE BOOL "Build a shared version of the library" FORCE)
|
||||
set(SDL_STATIC ON CACHE BOOL "Build a static version of the library" FORCE)
|
||||
else()
|
||||
set(SDL_SHARED ON CACHE BOOL "Build a shared version of the library" FORCE)
|
||||
set(SDL_STATIC OFF CACHE BOOL "Build a static version of the library" FORCE)
|
||||
endif()
|
||||
add_subdirectory( ${libDir}/sdl ${CMAKE_CURRENT_BINARY_DIR}/sdl2)
|
||||
link_directories( ${libDir}/sdl ${CMAKE_CURRENT_BINARY_DIR}/sdl2)
|
||||
endif()
|
||||
|
||||
if(TORQUE_DEDICATED)
|
||||
|
|
@ -451,7 +464,9 @@ if(WIN32)
|
|||
addPath("${srcDir}/platformWin32/nativeDialogs")
|
||||
set(BLACKLIST "" )
|
||||
addPath("${srcDir}/platformWin32/menus")
|
||||
addPath("${srcDir}/platformWin32/threads")
|
||||
if(NOT TORQUE_SDL)
|
||||
addPath("${srcDir}/platformWin32/threads")
|
||||
endif()
|
||||
addPath("${srcDir}/platformWin32/videoInfo")
|
||||
addPath("${srcDir}/platformWin32/minidump")
|
||||
addPath("${srcDir}/windowManager/win32")
|
||||
|
|
@ -469,46 +484,10 @@ endif()
|
|||
|
||||
if(APPLE)
|
||||
addPath("${srcDir}/platformMac")
|
||||
addPath("${srcDir}/platformMac/menus")
|
||||
addPath("${srcDir}/platformPOSIX")
|
||||
addPath("${srcDir}/windowManager/mac")
|
||||
addPath("${srcDir}/gfx/gl")
|
||||
addPath("${srcDir}/gfx/gl/ggl")
|
||||
addPath("${srcDir}/gfx/gl/ggl/mac")
|
||||
addPath("${srcDir}/gfx/gl/ggl/generated")
|
||||
addPath("${srcDir}/shaderGen/GLSL")
|
||||
addPath("${srcDir}/terrain/glsl")
|
||||
addPath("${srcDir}/forest/glsl")
|
||||
endif()
|
||||
|
||||
if(XBOX360)
|
||||
addPath("${srcDir}/platformXbox")
|
||||
addPath("${srcDir}/platformXbox/threads")
|
||||
addPath("${srcDir}/windowManager/360")
|
||||
addPath("${srcDir}/gfx/D3D9")
|
||||
addPath("${srcDir}/gfx/D3D9/360")
|
||||
addPath("${srcDir}/shaderGen/HLSL")
|
||||
addPath("${srcDir}/shaderGen/360")
|
||||
addPath("${srcDir}/ts/arch/360")
|
||||
addPath("${srcDir}/terrain/hlsl")
|
||||
addPath("${srcDir}/forest/hlsl")
|
||||
endif()
|
||||
|
||||
if(PS3)
|
||||
addPath("${srcDir}/platformPS3")
|
||||
addPath("${srcDir}/platformPS3/threads")
|
||||
addPath("${srcDir}/windowManager/ps3")
|
||||
addPath("${srcDir}/gfx/gl")
|
||||
addPath("${srcDir}/gfx/gl/ggl")
|
||||
addPath("${srcDir}/gfx/gl/ggl/ps3")
|
||||
addPath("${srcDir}/gfx/gl/ggl/generated")
|
||||
addPath("${srcDir}/shaderGen/GLSL")
|
||||
addPath("${srcDir}/ts/arch/ps3")
|
||||
addPath("${srcDir}/terrain/glsl")
|
||||
addPath("${srcDir}/forest/glsl")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
# linux_dedicated
|
||||
if(TORQUE_DEDICATED)
|
||||
addPath("${srcDir}/windowManager/dedicated")
|
||||
|
|
@ -529,7 +508,6 @@ if(UNIX)
|
|||
addPath("${srcDir}/platformX86UNIX/nativeDialogs")
|
||||
endif()
|
||||
# linux
|
||||
addPath("${srcDir}/platformX86UNIX/threads")
|
||||
addPath("${srcDir}/platformPOSIX")
|
||||
endif()
|
||||
|
||||
|
|
@ -563,9 +541,24 @@ message(STATUS "writing ${projectSrcDir}/torqueConfig.h")
|
|||
CONFIGURE_FILE("${cmakeDir}/torqueConfig.h.in" "${projectSrcDir}/torqueConfig.h")
|
||||
|
||||
# configure the relevant files only once
|
||||
if(NOT EXISTS "${projectSrcDir}/torque.ico")
|
||||
CONFIGURE_FILE("${cmakeDir}/torque.ico" "${projectSrcDir}/torque.ico" COPYONLY)
|
||||
|
||||
if(APPLE)
|
||||
#icon
|
||||
if(NOT EXISTS "${projectSrcDir}/torque.icns")
|
||||
CONFIGURE_FILE("${cmakeDir}/torque.icns" "${projectSrcDir}/torque.icns" COPYONLY)
|
||||
endif()
|
||||
#plist
|
||||
if(NOT EXISTS "${projectSrcDir}/Info.plist")
|
||||
CONFIGURE_FILE("${cmakeDir}/Info.plist.in" "${projectSrcDir}/Info.plist" COPYONLY)
|
||||
endif()
|
||||
#target properties for mac
|
||||
set_target_properties("${PROJECT_NAME}" PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${projectSrcDir}/Info.plist")
|
||||
else()
|
||||
if(NOT EXISTS "${projectSrcDir}/torque.ico")
|
||||
CONFIGURE_FILE("${cmakeDir}/torque.ico" "${projectSrcDir}/torque.ico" COPYONLY)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${projectOutDir}/${PROJECT_NAME}.torsion")
|
||||
CONFIGURE_FILE("${cmakeDir}/template.torsion.in" "${projectOutDir}/${PROJECT_NAME}.torsion")
|
||||
endif()
|
||||
|
|
@ -620,18 +613,26 @@ if(WIN32)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
# copy pasted from T3D build system, some might not be needed
|
||||
set(TORQUE_EXTERNAL_LIBS "dl Xxf86vm Xext X11 Xft stdc++ pthread GL" CACHE STRING "external libs to link against")
|
||||
mark_as_advanced(TORQUE_EXTERNAL_LIBS)
|
||||
|
||||
string(REPLACE " " ";" TORQUE_EXTERNAL_LIBS_LIST ${TORQUE_EXTERNAL_LIBS})
|
||||
addLib( "${TORQUE_EXTERNAL_LIBS_LIST}" )
|
||||
if (APPLE)
|
||||
addFramework("Cocoa")
|
||||
addFramework("OpenGL")
|
||||
#These are needed by sdl2 static lib
|
||||
addFramework("CoreAudio")
|
||||
addFramework("AudioUnit")
|
||||
addFramework("ForceFeedback")
|
||||
addFramework("IOKit")
|
||||
addFramework("CoreVideo")
|
||||
#grrr damn you sdl!
|
||||
addFramework("Carbon")
|
||||
addLib("iconv")
|
||||
#set a few arch defaults
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "OSX Architecture" FORCE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "OSX Deployment target" FORCE)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
# copy pasted from T3D build system, some might not be needed
|
||||
set(TORQUE_EXTERNAL_LIBS "rt dl Xxf86vm Xext X11 Xft stdc++ pthread GL" CACHE STRING "external libs to link against")
|
||||
set(TORQUE_EXTERNAL_LIBS "dl Xxf86vm Xext X11 Xft stdc++ pthread GL" CACHE STRING "external libs to link against")
|
||||
mark_as_advanced(TORQUE_EXTERNAL_LIBS)
|
||||
|
||||
string(REPLACE " " ";" TORQUE_EXTERNAL_LIBS_LIST ${TORQUE_EXTERNAL_LIBS})
|
||||
|
|
@ -661,7 +662,7 @@ addDef(PCRE_STATIC)
|
|||
addDef(_CRT_SECURE_NO_WARNINGS)
|
||||
addDef(_CRT_SECURE_NO_DEPRECATE)
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
addDef(LINUX)
|
||||
endif()
|
||||
|
||||
|
|
@ -705,7 +706,7 @@ if(TORQUE_OPENGL)
|
|||
addInclude("${libDir}/epoxy/src")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
if(UNIX AND NOT APPLE)
|
||||
addInclude("/usr/include/freetype2/freetype")
|
||||
addInclude("/usr/include/freetype2")
|
||||
endif()
|
||||
|
|
@ -715,11 +716,6 @@ if(WIN32)
|
|||
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES $ENV{DXSDK_DIR}/Include)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
addInclude("/usr/include/freetype2/freetype")
|
||||
addInclude("/usr/include/freetype2")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Match projectGenerator naming for executables
|
||||
set(OUTPUT_CONFIG DEBUG MINSIZEREL RELWITHDEBINFO)
|
||||
|
|
|
|||
Loading…
Reference in a new issue