MacOS platform support.

This commit is contained in:
RexTimmy 2016-09-28 11:09:48 +10:00
parent 57dfeb829a
commit dd64004eaf
89 changed files with 1228 additions and 5098 deletions

View file

@ -183,8 +183,8 @@ endif()
set(SDL_LIBS "-lSDL2") set(SDL_LIBS "-lSDL2")
set(SDL_CFLAGS "") set(SDL_CFLAGS "")
# Emscripten toolchain has a nonempty default value for this, and the checks # Emscripten toolchain has a nonempty default value for this, and the checks
# in this file need to change that, so remember the original value, and # in this file need to change that, so remember the original value, and
# restore back to that afterwards. For check_function_exists() to work in # restore back to that afterwards. For check_function_exists() to work in
# Emscripten, this value must be at its default value. # Emscripten, this value must be at its default value.
set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
@ -212,7 +212,7 @@ include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include)
set(OPT_DEF_ASM TRUE) set(OPT_DEF_ASM TRUE)
if(EMSCRIPTEN) if(EMSCRIPTEN)
# Set up default values for the currently supported set of subsystems: # Set up default values for the currently supported set of subsystems:
# Emscripten/Javascript does not have assembly support, a dynamic library # Emscripten/Javascript does not have assembly support, a dynamic library
# loading architecture, low-level CPU inspection or multithreading. # loading architecture, low-level CPU inspection or multithreading.
set(OPT_DEF_ASM FALSE) set(OPT_DEF_ASM FALSE)
set(SDL_SHARED_ENABLED_BY_DEFAULT OFF) set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
@ -387,11 +387,14 @@ if(USE_GCC OR USE_CLANG)
list(APPEND EXTRA_CFLAGS "-Wshadow") list(APPEND EXTRA_CFLAGS "-Wshadow")
endif() endif()
set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined") # --no-undefined is unsupported with clang
check_c_compiler_flag("" HAVE_NO_UNDEFINED) if(NOT USE_CLANG)
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS}) set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
if(HAVE_NO_UNDEFINED) check_c_compiler_flag("" HAVE_NO_UNDEFINED)
list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined") set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
if(HAVE_NO_UNDEFINED)
list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
endif()
endif() endif()
endif() endif()
@ -836,7 +839,7 @@ elseif(UNIX AND NOT APPLE)
#include <linux/kd.h> #include <linux/kd.h>
#include <linux/keyboard.h> #include <linux/keyboard.h>
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct kbentry kbe; struct kbentry kbe;
kbe.kb_table = KG_CTRL; kbe.kb_table = KG_CTRL;

View file

@ -43,17 +43,6 @@ extern void createFontShutdown(void);
static HashTable<StringTableEntry,StringTableEntry> gSecureScript; 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 bool LinkConsoleFunctions;
extern "C" { extern "C" {
@ -78,10 +67,6 @@ extern "C" {
createFontInit(); createFontInit();
#endif #endif
#ifdef TORQUE_OS_MAC
torque_mac_engineinit(argc, argv);
#endif
// Initialize the subsystems. // Initialize the subsystems.
StandardMainLoop::init(); StandardMainLoop::init();
@ -113,11 +98,6 @@ extern "C" {
__try { __try {
#endif #endif
#ifdef TORQUE_OS_MAC
torque_mac_enginetick();
#endif
bool ret = StandardMainLoop::doMainLoop(); bool ret = StandardMainLoop::doMainLoop();
return ret; return ret;
@ -159,10 +139,6 @@ extern "C" {
createFontShutdown(); createFontShutdown();
#endif #endif
#ifdef TORQUE_OS_MAC
torque_mac_engineshutdown();
#endif
#if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE ) #if defined( TORQUE_MINIDUMP ) && defined( TORQUE_RELEASE )
} }

View file

@ -613,7 +613,7 @@ namespace _Private {
/// ///
#define FIELD( fieldName, exportName, numElements, doc ) \ #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 ) \ #define FIELD_AS( type, fieldName, exportName, numElements, doc ) \

View file

@ -60,6 +60,7 @@
** this software for any purpose. ** this software for any purpose.
*/ */
#include "platform/platform.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -68,7 +69,11 @@
#include "core/util/md5.h" #include "core/util/md5.h"
#if defined (TORQUE_OS_MAC) && defined(TORQUE_CPU_X64)
typedef unsigned int unsigned32;
#else
typedef unsigned long unsigned32; typedef unsigned long unsigned32;
#endif
typedef unsigned short unsigned16; typedef unsigned short unsigned16;
typedef unsigned char unsigned8; typedef unsigned char unsigned8;

View file

@ -533,7 +533,7 @@ void WaterPlane::setupVBIB( SceneRenderState *state )
1, // Top 1, // Top
-(S32)gridStride, // Right -(S32)gridStride, // Right
-1, // Bottom -1, // Bottom
gridStride, // Left (S32)gridStride, // Left
}; };
const U32 firstBorderVert = gridStride * gridSize + gridStride; const U32 firstBorderVert = gridStride * gridSize + gridStride;

View file

@ -232,3 +232,14 @@ DefineEngineStaticMethod( GFXCardProfilerAPI, queryProfile, S32, ( const char *n
{ {
return (S32)GFX->getCardProfiler()->queryProfile( name, (U32)defaultValue ); 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";
}

View file

@ -27,26 +27,9 @@
void GFXGLCardProfiler::init() void GFXGLCardProfiler::init()
{ {
mChipSet = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); mChipSet = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
mRendererString = "OpenGL";
// 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);
mCardDescription = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); mCardDescription = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
mVersionString = reinterpret_cast<const char*>(glGetString(GL_VERSION)); mVersionString = reinterpret_cast<const char*>(glGetString(GL_VERSION));
mVideoMemory = static_cast<GFXGLDevice*>(GFX)->getTotalVideoMemory(); mVideoMemory = static_cast<GFXGLDevice*>(GFX)->getTotalVideoMemory();
Parent::init(); Parent::init();
@ -85,7 +68,8 @@ void GFXGLCardProfiler::setupCardCapabilities()
setCapability("GL_ARB_copy_image", gglHasExtension(ARB_copy_image)); setCapability("GL_ARB_copy_image", gglHasExtension(ARB_copy_image));
// Check for vertex attrib binding // Check for vertex attrib binding
setCapability("GL_ARB_vertex_attrib_binding", gglHasExtension(ARB_vertex_attrib_binding)); setCapability("GL_ARB_vertex_attrib_binding", gglHasExtension(ARB_vertex_attrib_binding));
} }
bool GFXGLCardProfiler::_queryCardCap(const String& query, U32& foundResult) bool GFXGLCardProfiler::_queryCardCap(const String& query, U32& foundResult)

View file

@ -103,27 +103,6 @@ void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLs
Con::printf("AMDOPENGL: %s", message); 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() void GFXGLDevice::initGLState()
{ {
// We don't currently need to sync device state with a known good place because we are // We don't currently need to sync device state with a known good place because we are
@ -156,14 +135,11 @@ void GFXGLDevice::initGLState()
String vendorStr = (const char*)glGetString( GL_VENDOR ); String vendorStr = (const char*)glGetString( GL_VENDOR );
if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos) if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
mUseGlMap = false; mUseGlMap = false;
// Workaround for all Mac's, has a problem using glMap* with volatile buffers
if( vendorStr.find("INTEL", 0, String::NoCase | String::Left ) != String::NPos) #ifdef TORQUE_OS_MAC
{ mUseGlMap = false;
// @todo OPENGL INTEL - This is a workaround for a warning spam or even crashes with actual framebuffer code, remove when implemented TGL layer. #endif
__openglBindFramebuffer = glBindFramebuffer;
glBindFramebuffer = &_t3d_glBindFramebuffer;
}
#if TORQUE_DEBUG #if TORQUE_DEBUG
if( gglHasExtension(ARB_debug_output) ) if( gglHasExtension(ARB_debug_output) )

View file

@ -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);
}
}

View file

@ -32,6 +32,8 @@
#include "gfx/gfxStructs.h" #include "gfx/gfxStructs.h"
#include "console/console.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 class GFXGLShaderConstHandle : public GFXShaderConstHandle
{ {
@ -447,34 +449,62 @@ bool GFXGLShader::_init()
// If either shader was present and failed to compile, bail. // If either shader was present and failed to compile, bail.
if(!compiledVertexShader || !compiledPixelShader) if(!compiledVertexShader || !compiledPixelShader)
return false; 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! // Link it!
glLinkProgram( mProgram ); 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; GLint linkStatus;
glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus ); glGetProgramiv( mProgram, GL_LINK_STATUS, &linkStatus );
@ -486,23 +516,24 @@ bool GFXGLShader::_init()
FrameAllocatorMarker fam; FrameAllocatorMarker fam;
char* log = (char*)fam.alloc( logLength ); char* log = (char*)fam.alloc( logLength );
glGetProgramInfoLog( mProgram, logLength, NULL, log ); glGetProgramInfoLog( mProgram, logLength, NULL, log );
if ( linkStatus == GL_FALSE ) if ( linkStatus == GL_FALSE )
{ {
if ( smLogErrors ) if ( smLogErrors )
{ {
Con::errorf( "GFXGLShader::init - Error linking shader!" ); Con::errorf( "GFXGLShader::init - Error linking shader!" );
Con::errorf( "Program %s / %s: %s", 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 ) else if ( smLogWarnings )
{ {
Con::warnf( "Program %s / %s: %s", 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 we failed to link, bail.
if ( linkStatus == GL_FALSE ) if ( linkStatus == GL_FALSE )
return false; return false;

View file

@ -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. // 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!"); 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 else
{ {

View file

@ -118,11 +118,14 @@ inline void GFXGLWindowTarget::_setupAttachments()
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->getHandle(), 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->getHandle(), 0);
mBackBufferDepthTex.set(dstSize.x, dstSize.y, GFXFormatD24S8, &BackBufferDepthProfile, "backBuffer"); mBackBufferDepthTex.set(dstSize.x, dstSize.y, GFXFormatD24S8, &BackBufferDepthProfile, "backBuffer");
GFXGLTextureObject *depth = static_cast<GFXGLTextureObject*>(mBackBufferDepthTex.getPointer()); 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() void GFXGLWindowTarget::makeActive()
{ {
//make the rendering context active on this window
_makeContextCurrent();
if(mBackBufferFBO) if(mBackBufferFBO)
{ {
glBindFramebuffer( GL_FRAMEBUFFER, mBackBufferFBO); glBindFramebuffer( GL_FRAMEBUFFER, mBackBufferFBO);

View file

@ -64,6 +64,8 @@ private:
void _setupNewMode(); void _setupNewMode();
void _setupAttachments(); void _setupAttachments();
void _WindowPresent(); void _WindowPresent();
//set this windows context to be current
void _makeContextCurrent();
}; };
#endif #endif

View file

@ -155,12 +155,12 @@ void GFXGLDevice::enumerateVideoModes()
void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window ) void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
{ {
AssertFatal(window, "GFXGLDevice::init - no window specified, can't init device without a window!"); AssertFatal(window, "GFXGLDevice::init - no window specified, can't init device without a window!");
PlatformWindowSDL* x11Window = dynamic_cast<PlatformWindowSDL*>(window); PlatformWindowSDL* sdlWindow = dynamic_cast<PlatformWindowSDL*>(window);
AssertFatal(x11Window, "Window is not a valid PlatformWindowSDL object"); AssertFatal(sdlWindow, "Window is not a valid PlatformWindowSDL object");
// Create OpenGL context // Create OpenGL context
mContext = PlatformGL::CreateContextGL( x11Window ); mContext = PlatformGL::CreateContextGL( sdlWindow );
PlatformGL::MakeCurrentGL( x11Window, mContext ); PlatformGL::MakeCurrentGL( sdlWindow, mContext );
loadGLCore(); loadGLCore();
loadGLExtensions(0); loadGLExtensions(0);
@ -226,4 +226,9 @@ void GFXGLWindowTarget::_setupNewMode()
{ {
} }
void GFXGLWindowTarget::_makeContextCurrent()
{
PlatformGL::MakeCurrentGL(mWindow, mContext);
}
#endif #endif

View file

@ -363,3 +363,16 @@ void GFXGLWindowTarget::_teardownCurrentMode()
void GFXGLWindowTarget::_setupNewMode() 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.");
}
}

View file

@ -672,11 +672,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
} }
else 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: // set up the camera and viewport stuff:
F32 wwidth; F32 wwidth;
F32 wheight; F32 wheight;
@ -716,12 +711,6 @@ void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect)
} }
RectI tempRect = 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); _internalRender(tempRect, tempRect, frustum);
} }

View file

@ -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__)

View file

@ -125,16 +125,6 @@ typedef unsigned long U64;
# define TORQUE_CPU_X64 # define TORQUE_CPU_X64
# define TORQUE_LITTLE_ENDIAN # 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 #else
# error "GCC: Unsupported Target CPU" # error "GCC: Unsupported Target CPU"
#endif #endif

View file

@ -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

View file

@ -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

View file

@ -20,21 +20,29 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <sys/types.h> #import <sys/types.h>
#include <sys/sysctl.h> #import <sys/sysctl.h>
#include <mach/machine.h> #import <mach/machine.h>
#include <math.h> #import <math.h>
#include <CoreServices/CoreServices.h> #import <CoreServices/CoreServices.h>
#include "platformMac/platformMacCarb.h" #import "platform/platformAssert.h"
#include "platform/platformAssert.h" #import "console/console.h"
#include "console/console.h" #import "core/stringTable.h"
#include "core/stringTable.h" #import "platform/platformCPUCount.h"
// Gestalt has been deprecated // Gestalt has been deprecated
// we now have to use NSProcessInfo // 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). // 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; Platform::SystemInfo_struct Platform::SystemInfo;
#define BASE_MHZ_SPEED 0 #define BASE_MHZ_SPEED 0
//TODO update cpu list
void Processor::init() void Processor::init()
{ {
U32 procflags; U32 procflags;
int err, cpufam, cputype, cpusub; int err, cpufam, cputype, cpusub;
char buf[20]; char buf[255];
unsigned long lraw; U32 lraw;
unsigned long long llraw; U64 llraw;
Con::printf( "System & Processor Information:" ); Con::printf( "System & Processor Information:" );
@ -111,13 +119,13 @@ void Processor::init()
else else
Con::printf( " Mac OS Kernel version: %s", buf ); Con::printf( " Mac OS Kernel version: %s", buf );
err = _getSysCTLvalue<unsigned long long>("hw.memsize", &llraw); err = _getSysCTLvalue<U64>("hw.memsize", &llraw);
if (err) if (err)
Con::printf( " Unable to determine amount of physical RAM\n" ); Con::printf( " Unable to determine amount of physical RAM\n" );
else else
Con::printf( " Physical memory installed: %d MB", (llraw >> 20)); Con::printf( " Physical memory installed: %d MB", (llraw >> 20));
err = _getSysCTLvalue<unsigned long>("hw.usermem", &lraw); err = _getSysCTLvalue<U32>("hw.usermem", &lraw);
if (err) if (err)
Con::printf( " Unable to determine available user address space\n"); Con::printf( " Unable to determine available user address space\n");
else else
@ -132,17 +140,17 @@ void Processor::init()
cpufam = 0; cpufam = 0;
cputype = 0; cputype = 0;
cpusub = 0; cpusub = 0;
err = _getSysCTLvalue<unsigned long>("hw.cpufamily", &lraw); err = _getSysCTLvalue<U32>("hw.cpufamily", &lraw);
if (err) if (err)
Con::printf( " Unable to determine 'family' of CPU\n"); Con::printf( " Unable to determine 'family' of CPU\n");
else { else {
cpufam = (int) lraw; cpufam = (int) lraw;
err = _getSysCTLvalue<unsigned long>("hw.cputype", &lraw); err = _getSysCTLvalue<U32>("hw.cputype", &lraw);
if (err) if (err)
Con::printf( " Unable to determine CPU type\n"); Con::printf( " Unable to determine CPU type\n");
else { else {
cputype = (int) lraw; cputype = (int) lraw;
err = _getSysCTLvalue<unsigned long>("hw.cpusubtype", &lraw); err = _getSysCTLvalue<U32>("hw.cpusubtype", &lraw);
if (err) if (err)
Con::printf( " Unable to determine CPU subtype\n"); Con::printf( " Unable to determine CPU subtype\n");
else else
@ -154,7 +162,7 @@ void Processor::init()
// The Gestalt version was known to have issues with some Processor Upgrade cards // The Gestalt version was known to have issues with some Processor Upgrade cards
// but it is uncertain whether this version has similar issues. // 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) { if (err) {
llraw = BASE_MHZ_SPEED; llraw = BASE_MHZ_SPEED;
Con::printf( " Unable to determine CPU Frequency. Defaulting to %d MHz\n", llraw); 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 // Here's one that the original version of this routine couldn't do -- number
// of processors (cores) // of processors (cores)
U32 ncpu = 1; U32 ncpu = 1;
err = _getSysCTLvalue<unsigned long>("hw.ncpu", &lraw); err = _getSysCTLvalue<U32>("hw.ncpu", &lraw);
if (err) if (err)
Con::printf( " Unable to determine number of processor cores\n"); Con::printf( " Unable to determine number of processor cores\n");
else else
@ -184,29 +192,15 @@ void Processor::init()
// and the Optional Capability flags (further down) should be more than enough. // and the Optional Capability flags (further down) should be more than enough.
switch(cpufam) switch(cpufam)
{ {
case CPUFAMILY_POWERPC_G3: case CPUFAMILY_INTEL_YONAH:
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:
Platform::SystemInfo.processor.type = CPU_Intel_Core; Platform::SystemInfo.processor.type = CPU_Intel_Core;
if( ncpu == 2 ) if( ncpu == 2 )
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core Duo"); Platform::SystemInfo.processor.name = StringTable->insert("Intel Core Duo");
else else
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core"); Platform::SystemInfo.processor.name = StringTable->insert("Intel Core");
break; break;
#ifdef CPUFAMILY_INTEL_6_23 case CPUFAMILY_INTEL_PENRYN:
case CPUFAMILY_INTEL_6_23: case CPUFAMILY_INTEL_MEROM:
#endif
case CPUFAMILY_INTEL_6_15:
Platform::SystemInfo.processor.type = CPU_Intel_Core2; Platform::SystemInfo.processor.type = CPU_Intel_Core2;
if( ncpu == 4 ) if( ncpu == 4 )
Platform::SystemInfo.processor.name = StringTable->insert("Intel Core 2 Quad"); 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"); Platform::SystemInfo.processor.name = StringTable->insert("Intel Core 2 Duo");
break; break;
#ifdef CPUFAMILY_INTEL_6_26 case CPUFAMILY_INTEL_NEHALEM:
case CPUFAMILY_INTEL_6_26:
Platform::SystemInfo.processor.type = CPU_Intel_Core2; Platform::SystemInfo.processor.type = CPU_Intel_Core2;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel 'Nehalem' Core Processor" ); Platform::SystemInfo.processor.name = StringTable->insert( "Intel 'Nehalem' Core Processor" );
break; break;
#endif
default: default:
// explain why we can't get the processor type. // 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. // actually supported/implemented by the processor: 0 = no, 1 = yes, others are undefined.
procflags = 0; procflags = 0;
// Seriously this one should be an Assert() // 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; if ((err==0)&&(lraw==1)) procflags |= CPU_PROP_FPU;
// List of chip-specific features // 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; 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; 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; 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; 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; 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; 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; 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 // 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; 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; 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; if ((err==0)&&(lraw==1234)) procflags |= CPU_PROP_LE;
Platform::SystemInfo.processor.properties = procflags; Platform::SystemInfo.processor.properties = procflags;
@ -275,11 +266,27 @@ void Processor::init()
Con::printf( " SSE2 detected"); Con::printf( " SSE2 detected");
if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3) if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE3)
Con::printf( " SSE3 detected"); Con::printf( " SSE3 detected");
if (Platform::SystemInfo.processor.properties & CPU_PROP_ALTIVEC) if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_1)
Con::printf( " AltiVec detected"); Con::printf( " SSE4.1 detected");
if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE4_2)
Con::printf( " SSE4.2 detected");
Con::printf( "" ); Con::printf( "" );
// Trigger the signal // Trigger the signal
Platform::SystemInfoReady.trigger(); 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;
}
}

View file

@ -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 );
}

View file

@ -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);

View file

@ -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.
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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!");
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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
}

View file

@ -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;
}

View file

@ -20,49 +20,30 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <stdio.h> #import <Cocoa/Cocoa.h>
#include <stdlib.h> #import <stdio.h>
#include <errno.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> #import "core/fileio.h"
#include <sys/time.h> #import "core/util/tVector.h"
#import "core/stringTable.h"
#include <sys/types.h> #import "core/strings/stringFunctions.h"
#include <dirent.h> #import "console/console.h"
#include <unistd.h> #import "platform/profiler.h"
#include <sys/stat.h> #import "cinterface/cinterface.h";
#import "core/volume.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"
//TODO: file io still needs some work... //TODO: file io still needs some work...
#define MAX_MAC_PATH_LONG 2048 #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) bool dFileDelete(const char * name)
{ {
if(!name ) if(!name )
@ -78,12 +59,84 @@ bool dFileDelete(const char * name)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool dFileTouch(const char *path) bool dFileTouch(const char *path)
{ {
if (!path || !*path) if (!path || !*path)
return false; return false;
// set file at path's modification and access times to now. // set file at path's modification and access times to now.
return( utimes( path, NULL) == 0); // utimes returns 0 on success. 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 // Constructors & Destructor
@ -121,7 +174,7 @@ File::~File()
// Sets capability appropriate to the openMode. // Sets capability appropriate to the openMode.
// Returns the currentStatus of the file. // 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) if (dStrlen(filename) > MAX_MAC_PATH_LONG)
Con::warnf("File::open: Filename length is pretty long..."); Con::warnf("File::open: Filename length is pretty long...");
@ -150,7 +203,7 @@ File::Status File::open(const char *filename, const AccessMode openMode)
} }
// handle not created successfully // handle not created successfully
if (handle == NULL) if (handle == NULL)
return setStatus(); return setStatus();
// successfully created file, so set the file capabilities... // successfully created file, so set the file capabilities...
@ -177,7 +230,7 @@ File::Status File::open(const char *filename, const AccessMode openMode)
setPosition(0); setPosition(0);
// success! // success!
return currentStatus; return currentStatus;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -203,7 +256,7 @@ U32 File::getPosition() const
// //
// Returns the currentStatus of the file. // 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(Closed != currentStatus, "File::setPosition: file closed");
AssertFatal(handle != NULL, "File::setPosition: invalid file handle"); AssertFatal(handle != NULL, "File::setPosition: invalid file handle");
@ -232,11 +285,11 @@ File::Status File::setPosition(S32 position, bool absolutePos)
// ftell returns -1 on error. set error status // ftell returns -1 on error. set error status
if (0xffffffff == finalPos) if (0xffffffff == finalPos)
return setStatus(); return setStatus();
// success, at end of file // success, at end of file
else if (finalPos >= getSize()) else if (finalPos >= getSize())
return currentStatus = EOS; return currentStatus = EOS;
// success! // success!
else else
return currentStatus = Ok; return currentStatus = Ok;
@ -271,7 +324,7 @@ U32 File::getSize() const
// It is an error to flush a read-only file. // It is an error to flush a read-only file.
// Returns the currentStatus of the file. // Returns the currentStatus of the file.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
File::Status File::flush() File::FileStatus File::flush()
{ {
AssertFatal(Closed != currentStatus, "File::flush: file closed"); AssertFatal(Closed != currentStatus, "File::flush: file closed");
AssertFatal(handle != NULL, "File::flush: invalid file handle"); AssertFatal(handle != NULL, "File::flush: invalid file handle");
@ -288,7 +341,7 @@ File::Status File::flush()
// //
// Returns the currentStatus // Returns the currentStatus
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
File::Status File::close() File::FileStatus File::close()
{ {
// check if it's already closed... // check if it's already closed...
if (Closed == currentStatus) if (Closed == currentStatus)
@ -307,7 +360,7 @@ File::Status File::close()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Self-explanatory. // Self-explanatory.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
File::Status File::getStatus() const File::FileStatus File::getStatus() const
{ {
return currentStatus; return currentStatus;
} }
@ -315,7 +368,7 @@ File::Status File::getStatus() const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Sets and returns the currentStatus when an error has been encountered. // Sets and returns the currentStatus when an error has been encountered.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
File::Status File::setStatus() File::FileStatus File::setStatus()
{ {
switch (errno) switch (errno)
{ {
@ -336,7 +389,7 @@ File::Status File::setStatus()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Sets and returns the currentStatus to status. // Sets and returns the currentStatus to status.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
File::Status File::setStatus(File::Status status) File::FileStatus File::setStatus(File::FileStatus status)
{ {
return currentStatus = 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 // The number of bytes read is available in bytesRead if a non-Null pointer is
// provided. // 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(Closed != currentStatus, "File::read: file closed");
AssertFatal(handle != NULL, "File::read: invalid file handle"); AssertFatal(handle != NULL, "File::read: invalid file handle");
@ -368,7 +421,7 @@ File::Status File::read(U32 size, char *dst, U32 *bytesRead)
// if bytesRead is a valid pointer, send number of bytes read there. // if bytesRead is a valid pointer, send number of bytes read there.
if(bytesRead) if(bytesRead)
*bytesRead = nBytes; *bytesRead = nBytes;
// successfully read size bytes // successfully read size bytes
return currentStatus; return currentStatus;
} }
@ -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 // The number of bytes written is available in bytesWritten if a non-Null
// pointer is provided. // 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(Closed != currentStatus, "File::write: file closed");
AssertFatal(handle != NULL, "File::write: invalid file handle"); AssertFatal(handle != NULL, "File::write: invalid file handle");
@ -389,7 +442,7 @@ File::Status File::write(U32 size, const char *src, U32 *bytesWritten)
if ((Ok != currentStatus && EOS != currentStatus) || 0 == size) if ((Ok != currentStatus && EOS != currentStatus) || 0 == size)
return currentStatus; return currentStatus;
// write bytes to the stream // write bytes to the stream
U32 nBytes = fwrite(src, 1, size,(FILE*)handle); U32 nBytes = fwrite(src, 1, size,(FILE*)handle);
@ -435,7 +488,7 @@ bool Platform::getFileTimes(const char *path, FileTime *createTime, FileTime *mo
// So instead of creation time we return changed time, // So instead of creation time we return changed time,
// just like the Linux platform impl does. // just like the Linux platform impl does.
if (!path || !*path) if (!path || !*path)
return false; return false;
struct stat statData; struct stat statData;
@ -459,12 +512,12 @@ bool Platform::createPath(const char *file)
// if the path exists, we're done. // if the path exists, we're done.
struct stat statData; struct stat statData;
if( stat(file, &statData) == 0 ) if( stat(file, &statData) == 0 )
{ {
return true; // exists, rejoice. return true; // exists, rejoice.
} }
Con::warnf( "creating path %s", file ); Con::warnf( "creating path %s", file );
// get the parent path. // get the parent path.
// we're not using basename because it's not thread safe. // we're not using basename because it's not thread safe.
U32 len = dStrlen(file); U32 len = dStrlen(file);
@ -527,46 +580,17 @@ 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 // helper func for getWorkingDirectory
bool isMainDotCsPresent(NSString* dir) bool isMainDotCsPresent(NSString* dir)
{ {
return [[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:@"main.cs"]] == YES; return [[NSFileManager defaultManager] fileExistsAtPath:[dir stringByAppendingPathComponent:@"main.cs"]] == YES;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// Finds and sets the current working directory. /// Finds and sets the current working directory.
/// Torque tries to automatically detect whether you have placed the game files /// Torque tries to automatically detect whether you have placed the game files
/// inside or outside the application's bundle. It checks for the presence of /// inside or outside the application's bundle. It checks for the presence of
/// the file 'main.cs'. If it finds it, Torque will assume that the other game /// the file 'main.cs'. If it finds it, Torque will assume that the other game
/// files are there too. If Torque does not see 'main.cs' inside its bundle, it /// files are there too. If Torque does not see 'main.cs' inside its bundle, it
/// will assume the files are outside the bundle. /// will assume the files are outside the bundle.
@ -594,13 +618,14 @@ StringTableEntry Platform::getExecutablePath()
//first check the cwd for main.cs //first check the cwd for main.cs
static char buf[4096]; 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)) if (isMainDotCsPresent(currentDir))
{ {
cwd = buf; cwd = buf;
[pool release]; [pool release];
return cwd; [currentDir release];
return cwd;
} }
NSString* string = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"cs"]; NSString* string = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"cs"];
@ -612,6 +637,7 @@ StringTableEntry Platform::getExecutablePath()
cwd = dStrdup([string UTF8String]); cwd = dStrdup([string UTF8String]);
chdir(cwd); chdir(cwd);
[pool release]; [pool release];
[currentDir release];
} }
return cwd; return cwd;
@ -630,7 +656,7 @@ StringTableEntry Platform::getExecutableName()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool Platform::isFile(const char *path) bool Platform::isFile(const char *path)
{ {
if (!path || !*path) if (!path || !*path)
return false; return false;
// make sure we can stat the file // make sure we can stat the file
@ -652,7 +678,7 @@ bool Platform::isFile(const char *path)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool Platform::isDirectory(const char *path) bool Platform::isDirectory(const char *path)
{ {
if (!path || !*path) if (!path || !*path)
return false; return false;
// make sure we can stat the file // make sure we can stat the file
@ -670,7 +696,7 @@ bool Platform::isDirectory(const char *path)
S32 Platform::getFileSize(const char* pFilePath) S32 Platform::getFileSize(const char* pFilePath)
{ {
if (!pFilePath || !*pFilePath) if (!pFilePath || !*pFilePath)
return 0; return 0;
struct stat statData; struct stat statData;
@ -702,7 +728,7 @@ inline bool isGoodDirectory(dirent* entry)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool Platform::hasSubDirectory(const char *path) bool Platform::hasSubDirectory(const char *path)
{ {
DIR *dir; DIR *dir;
dirent *entry; dirent *entry;
@ -713,7 +739,7 @@ bool Platform::hasSubDirectory(const char *path)
while( (entry = readdir(dir)) ) while( (entry = readdir(dir)) )
{ {
if(isGoodDirectory(entry) ) if(isGoodDirectory(entry) )
{ {
closedir(dir); closedir(dir);
return true; // we have a subdirectory, that isnt on the exclude list. return true; // we have a subdirectory, that isnt on the exclude list.
@ -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. return false; // either this dir had no subdirectories, or they were all on the exclude list.
} }
bool Platform::fileDelete(const char * name) bool Platform::fileDelete(const char * name)
{
return dFileDelete(name);
}
//-----------------------------------------------------------------------------
bool recurseDumpDirectories(const char *basePath, const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
{ {
DIR *dir; return dFileDelete(name);
dirent *entry; }
U32 len = dStrlen(basePath) + dStrlen(path) + 2;
char pathbuf[len]; 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;
// construct the file path dsize_t trLen = basePath ? dStrlen(basePath) : 0;
dSprintf(pathbuf, len, "%s/%s", basePath, path); dsize_t subtrLen = subPath ? dStrlen(subPath) : 0;
pathbuf[len] = '\0'; char trail = trLen > 0 ? basePath[trLen - 1] : '\0';
char subTrail = subtrLen > 0 ? subPath[subtrLen - 1] : '\0';
// be sure it opens. if (trail == '/')
dir = opendir(pathbuf); {
if(!dir) 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; 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 (noBasePath)
if(!isGoodDirectory(entry)) {
continue; // We have a path and it's not an empty string or an excluded directory
if ( (subPath && (dStrncmp (subPath, "", 1) != 0)) )
// TODO: better unicode file name handling directoryVector.push_back(StringTable->insert(subPath));
// // Apple's file system stores unicode file names in decomposed form. }
// // ATSUI will not reliably draw out just the accent character by itself, else
// // so our text renderer has no chance of rendering decomposed form unicode. {
// // We have to convert the entry name to precomposed normalized form. if ( (subPath && (dStrncmp(subPath, "", 1) != 0)) )
// CFStringRef cfdname = CFStringCreateWithCString(NULL,entry->d_name,kCFStringEncodingUTF8); {
// CFMutableStringRef cfentryName = CFStringCreateMutableCopy(NULL,0,cfdname); char szPath[1024];
// CFStringNormalize(cfentryName,kCFStringNormalizationFormC); dMemset(szPath, 0, 1024);
// if (trail == '/')
// U32 entryNameLen = CFStringGetLength(cfentryName) * 4 + 1; {
// char entryName[entryNameLen]; if ((basePath[dStrlen(basePath) - 1]) != '/')
// CFStringGetCString(cfentryName, entryName, entryNameLen, kCFStringEncodingUTF8); dSprintf(szPath, 1024, "%s%s", basePath, &subPath[1]);
// entryName[entryNameLen-1] = NULL; // sometimes, CFStringGetCString() doesn't null terminate. else
// CFRelease(cfentryName); dSprintf(szPath, 1024, "%s%s", basePath, subPath);
// CFRelease(cfdname); }
else
// construct the new path string, we'll need this below. {
U32 newpathlen = dStrlen(path) + dStrlen(entry->d_name) + 2; if ((basePath[dStrlen(basePath) - 1]) != '/')
char newpath[newpathlen]; dSprintf(szPath, 1024, "%s%s", basePath, subPath);
if(dStrlen(path) > 0) // prevent extra slashes in the path else
dSprintf(newpath, newpathlen,"%s/%s",path,entry->d_name); dSprintf(szPath, 1024, "%s/%s", basePath, subPath);
else }
dStrncpy(newpath,entry->d_name, newpathlen);
newpath[newpathlen] = '\0'; directoryVector.push_back(StringTable->insert(szPath));
}
// we have a directory, add it to the list. else
if( noBasePath ) directoryVector.push_back(StringTable->insert(basePath));
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));
} }
// 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);
} }
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; return true;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool Platform::dumpDirectories(const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath) bool Platform::dumpDirectories(const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
{ {
PROFILE_START(dumpDirectories); bool retVal = recurseDumpDirectories(path, "", directoryVector, 0, depth, noBasePath);
clearExcludedDirectories();
int len = dStrlen(path); return retVal;
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;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -877,7 +958,7 @@ bool Platform::dumpPath(const char *path, Vector<Platform::FileInfo>& fileVector
dStrncpy(newpath,path,len); dStrncpy(newpath,path,len);
newpath[len] = '\0'; // null terminate newpath[len] = '\0'; // null terminate
if(newpath[len - 1] == '/') if(newpath[len - 1] == '/')
newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one
bool ret = recurseDumpPath( newpath, fileVector, depth); bool ret = recurseDumpPath( newpath, fileVector, depth);

View file

@ -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 // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
@ -20,55 +20,44 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <ApplicationServices/ApplicationServices.h> #import "platform/platformFont.h"
#include "platform/platformFont.h" #import <CoreText/CoreText.h>
//-----------------------------------------------------------------------------
class OSXFont : public PlatformFont
class MacCarbFont : public PlatformFont
{ {
private: private:
// Caches style, layout and colorspace data to speed up character drawing.
// TODO: style colors // Font reference.
ATSUStyle mStyle; CTFontRef mFontRef;
ATSUTextLayout mLayout;
// 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; 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: public:
MacCarbFont(); OSXFont();
virtual ~MacCarbFont(); virtual ~OSXFont();
/// Look up the requested font, cache style, layout, colorspace, and some metrics. /// 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. /// 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 UTF16 character) const;
virtual bool isValidChar( const UTF8 *str) 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. /// Get some vertical data on the font at large. Useful for drawing multiline text, and sizing text boxes.
virtual U32 getFontHeight() const; virtual U32 getFontHeight() const { return mHeight; }
virtual U32 getFontBaseLine() const; virtual U32 getFontBaseLine() const { return mBaseline; }
// Draw the character to a temporary bitmap, and fill the CharInfo with various text metrics. // 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; virtual PlatformFont::CharInfo &getCharInfo(const UTF8 *str) const;
}; };
inline U32 MacCarbFont::getFontHeight() const
{
return mHeight;
}
inline U32 MacCarbFont::getFontBaseLine() const
{
return mBaseline;
}

View 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;
}

View file

@ -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

View file

@ -20,175 +20,70 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <Cocoa/Cocoa.h> #import "app/mainLoop.h"
#include "app/mainLoop.h" #import "platform/platformInput.h"
#include "platform/platformInput.h" #import "console/console.h"
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
#include "console/console.h"
#include "platform/threads/thread.h"
// TODO: let the mainLoop's sleep time happen via rescheduling the timer every run-through. extern void InitWindowingSystem();
extern S32 sgTimeManagerProcessInterval;
@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() void Platform::init()
{ {
Con::printf("Initializing platform...");
// Set the platform variable for the scripts // Set the platform variable for the scripts
Con::setVariable( "$platform", "macos" ); Con::setVariable( "$platform", "MacOSX" );
Input::init(); Input::init();
//installRedBookDevices();
#ifndef TORQUE_DEDICATED
// if we're not dedicated do more initialization
InitWindowingSystem();
#endif
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void Platform::shutdown() 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

View file

@ -20,11 +20,10 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "platformMac/platformMacCarb.h" #import "platform/platform.h"
#include "platform/platform.h" #import "console/console.h"
#include "console/console.h" #import "math/mMath.h"
#include "math/mMath.h" #import "core/strings/stringFunctions.h"
#include "core/strings/stringFunctions.h"
extern void mInstallLibrary_C(); extern void mInstallLibrary_C();
extern void mInstallLibrary_Vec(); 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 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; properties |= CPU_PROP_C;
continue; continue;
} }
if (dStricmp(*argv, "VEC") == 0) {
properties |= CPU_PROP_ALTIVEC;
continue;
}
if( dStricmp( *argv, "SSE" ) == 0 ) if( dStricmp( *argv, "SSE" ) == 0 )
{ {
properties |= CPU_PROP_SSE; properties |= CPU_PROP_SSE;
continue; continue;
} }
Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", *argv); //Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", *argv);
} }
Math::init(properties); Math::init(properties);
} }
@ -99,15 +94,8 @@ void Math::init(U32 properties)
Con::printf("Math Init:"); Con::printf("Math Init:");
Con::printf(" Installing Standard C extensions"); Con::printf(" Installing Standard C extensions");
mInstallLibrary_C(); mInstallLibrary_C();
#if defined(__VEC__)
if (properties & CPU_PROP_ALTIVEC)
{
Con::printf(" Installing Altivec extensions");
mInstallLibrary_Vec();
}
#endif
#ifdef TORQUE_CPU_X86 #ifdef TORQUE_CPU_X86
if( properties & CPU_PROP_SSE ) if( properties & CPU_PROP_SSE )
{ {

View file

@ -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 // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
@ -20,10 +20,10 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "platform/platform.h" #import "platform/platform.h"
#include <stdlib.h> #import <stdlib.h>
#include <string.h> #import <string.h>
#include <mm_malloc.h> #import <mm_malloc.h>
//-------------------------------------- //--------------------------------------
void* dRealMalloc(dsize_t in_size) void* dRealMalloc(dsize_t in_size)
@ -51,20 +51,20 @@ void dFree_aligned(void* p)
void* dMemcpy(void *dst, const void *src, dsize_t size) void* dMemcpy(void *dst, const void *src, dsize_t size)
{ {
return memcpy(dst,src,size); return memcpy(dst,src,size);
} }
//-------------------------------------- //--------------------------------------
void* dMemmove(void *dst, const void *src, dsize_t size) void* dMemmove(void *dst, const void *src, dsize_t size)
{ {
return memmove(dst,src,size); return memmove(dst,src,size);
} }
//-------------------------------------- //--------------------------------------
void* dMemset(void *dst, int c, dsize_t size) void* dMemset(void *dst, int c, dsize_t size)
{ {
return memset(dst,c,size); return memset(dst,c,size);
} }
//-------------------------------------- //--------------------------------------
int dMemcmp(const void *ptr1, const void *ptr2, dsize_t len) int dMemcmp(const void *ptr1, const void *ptr2, dsize_t len)

View file

@ -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;
}

View 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);
}

View file

@ -20,25 +20,25 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "platform/platform.h" #import "platform/platform.h"
#include <stdlib.h> #import <stdlib.h>
#include <stdarg.h> #import <stdarg.h>
#include <string.h> #import <string.h>
#include <ctype.h> #import <ctype.h>
#include <stdio.h> #import <stdio.h>
#include "core/strings/stringFunctions.h" #import "core/strings/stringFunctions.h"
char *dStrnew(const char *src) char *dStrnew(const char *src)
{ {
char *buffer = new char[dStrlen(src) + 1]; char *buffer = new char[dStrlen(src) + 1];
dStrcpy(buffer, src); dStrcpy(buffer, src);
return buffer; return buffer;
} }
char* dStrstr(char *str1, char *str2) char* dStrstr(char *str1, char *str2)
{ {
return strstr(str1,str2); return strstr(str1,str2);
} }
int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...) int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...)
{ {
@ -47,15 +47,15 @@ int dSprintf(char *buffer, dsize_t /*bufferSize*/, const char *format, ...)
S32 len = vsprintf(buffer, format, args); S32 len = vsprintf(buffer, format, args);
va_end(args); va_end(args);
return (len); return (len);
} }
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); return (len);
} }
int dFflushStdout() int dFflushStdout()
{ {

View file

@ -20,10 +20,11 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <CoreServices/CoreServices.h> #import <CoreServices/CoreServices.h>
#include "platform/platformTimer.h" #import <mach/mach_time.h>
#include <time.h> #import "platform/platformTimer.h"
#include <unistd.h> #import <time.h>
#import <unistd.h>
//-------------------------------------- //--------------------------------------
@ -81,18 +82,17 @@ U32 Platform::getTime()
/// Storing milliseconds in a U32 overflows every 49.71 days /// Storing milliseconds in a U32 overflows every 49.71 days
U32 Platform::getRealMilliseconds() U32 Platform::getRealMilliseconds()
{ {
// Duration is a S32 value. const uint32_t oneMillion = 1000000;
// if negative, it is in microseconds. static mach_timebase_info_data_t s_timebase_info;
// if positive, it is in milliseconds.
Duration durTime = AbsoluteToDuration(UpTime()); if (s_timebase_info.denom == 0) {
U32 ret; (void) mach_timebase_info(&s_timebase_info);
if( durTime < 0 ) }
ret = durTime / -1000;
else // mach_absolute_time() returns billionth of seconds,
ret = durTime; // so divide by one million to get milliseconds
return (U32)((mach_absolute_time() * s_timebase_info.numer) / (oneMillion * s_timebase_info.denom));
return ret; }
}
U32 Platform::getVirtualMilliseconds() U32 Platform::getVirtualMilliseconds()
{ {

View file

@ -23,13 +23,8 @@
#ifndef _MACCARBVOLUME_H_ #ifndef _MACCARBVOLUME_H_
#define _MACCARBVOLUME_H_ #define _MACCARBVOLUME_H_
#ifndef _POSIXVOLUME_H_ #import "platformPOSIX/posixVolume.h"
#include "platformPOSIX/posixVolume.h" #import "core/util/tVector.h"
#endif
#ifndef _TVECTOR_H_
#include "core/util/tVector.h"
#endif
class MacFileSystem; class MacFileSystem;

View file

@ -20,16 +20,11 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <CoreServices/CoreServices.h> #import <CoreServices/CoreServices.h>
#import "platform/platform.h"
#include "platform/platform.h" #import "platformMac/macVolume.h"
#include "platformMac/macCarbVolume.h" #import "platform/platformVolume.h"
#include "platform/platformVolume.h" #import "console/console.h"
#include "console/console.h"
//#define DEBUG_SPEW
struct MacFileSystemChangeNotifier::Event struct MacFileSystemChangeNotifier::Event
{ {
@ -38,7 +33,6 @@ struct MacFileSystemChangeNotifier::Event
bool mHasChanged; bool mHasChanged;
}; };
static void fsNotifyCallback( static void fsNotifyCallback(
ConstFSEventStreamRef stream, ConstFSEventStreamRef stream,
void* callbackInfo, void* callbackInfo,

View file

@ -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>

View file

@ -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>

View file

@ -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);
}

View file

@ -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)
{
}

View file

@ -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_

View file

@ -11,12 +11,6 @@ namespace PlatformGL
void init() void init()
{ {
static bool inited = false;
if(inited)
return;
inited = true;
const U32 majorOGL = 3; const U32 majorOGL = 3;
const U32 minorOGL = 2; const U32 minorOGL = 2;
U32 debugFlag = 0; U32 debugFlag = 0;
@ -28,6 +22,9 @@ namespace PlatformGL
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minorOGL); 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_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag); SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, debugFlag);
#ifdef TORQUE_GL_SOFTWARE
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 0);
#endif
SDL_ClearError(); SDL_ClearError();
} }

View file

@ -245,11 +245,6 @@ void PostEffectManager::renderEffects( const SceneRenderState *state,
const PFXRenderTime effectTiming, const PFXRenderTime effectTiming,
const String &binName ) 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 // Check the global render effect state as
// well as the // well as the

View file

@ -61,7 +61,8 @@ SFXALDevice::SFXALDevice( SFXProvider *provider,
AssertFatal( mDevice != NULL && mContext != NULL, "Failed to create OpenAL device and/or context!" ); AssertFatal( mDevice != NULL && mContext != NULL, "Failed to create OpenAL device and/or context!" );
// Start the update thread. // Start the update thread.
#ifndef TORQUE_OS_LINUX // TODO AsyncPeriodicUpdateThread support for Linux/Mac
#ifdef TORQUE_OS_WIN
if( !Con::getBoolVariable( "$_forceAllMainThread" ) ) if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
{ {
SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread

View file

@ -0,0 +1 @@
/procedural/

View file

@ -31,8 +31,6 @@ in vec4 mieColor;
#define IN_mieColor mieColor #define IN_mieColor mieColor
in vec3 v3Direction; in vec3 v3Direction;
#define IN_v3Direction v3Direction #define IN_v3Direction v3Direction
in float zPosition;
#define IN_zPosition zPosition
in vec3 pos; in vec3 pos;
#define IN_pos pos #define IN_pos pos
@ -65,12 +63,6 @@ void main()
float fac = dot( normalize( pos ), sunDir ); float fac = dot( normalize( pos ), sunDir );
fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) ); fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) );
OUT_col = mix( color, nightSkyColor, nightInterpAndExposure.y ); 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.a = 1;

View file

@ -47,8 +47,6 @@ out vec4 mieColor;
#define OUT_mieColor mieColor #define OUT_mieColor mieColor
out vec3 v3Direction; out vec3 v3Direction;
#define OUT_v3Direction v3Direction #define OUT_v3Direction v3Direction
out float zPosition;
#define OUT_zPosition zPosition
out vec3 pos; out vec3 pos;
#define OUT_pos pos #define OUT_pos pos

View file

@ -47,8 +47,8 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
colorBuffer *= (1.0 - colorBuffer.a); colorBuffer *= (1.0 - colorBuffer.a);
} }
colorBuffer *= float4(lightBuffer.rgb, 1.0);
colorBuffer += float4(specular, specular, specular, 1.0); colorBuffer += float4(specular, specular, specular, 1.0);
colorBuffer *= float4(lightBuffer.rgb, 1.0);
return hdrEncode( float4(colorBuffer.rgb, 1.0) ); return hdrEncode( float4(colorBuffer.rgb, 1.0) );
} }

View file

@ -21,13 +21,13 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0;
uniform sampler2D colorBufferTex; uniform sampler2D colorBufferTex;
out vec4 OUT_FragColor0; out vec4 OUT_FragColor0;
void main() void main()
{ {
OUT_FragColor0 = vec4(texture( colorBufferTex, uv0 ).rgb, 1.0); OUT_FragColor0 = vec4(texture( colorBufferTex, uv0 ).rgb, 1.0);
} }

View file

@ -33,4 +33,4 @@ void main()
{ {
float depth = prepassUncondition( prepassTex, uv0 ).w; float depth = prepassUncondition( prepassTex, uv0 ).w;
OUT_col = vec4( texture( depthViz, depth ).rgb, 1.0 ); OUT_col = vec4( texture( depthViz, depth ).rgb, 1.0 );
} }

View file

@ -21,14 +21,13 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
#include "../../../postFx/gl/postFX.glsl"
in vec2 uv0;
uniform sampler2D glowBuffer; uniform sampler2D glowBuffer;
out vec4 OUT_FragColor0; out vec4 OUT_FragColor0;
void main() void main()
{ {
OUT_FragColor0 = texture(glowBuffer, uv0); OUT_FragColor0 = texture(glowBuffer, uv0);
} }

View file

@ -21,7 +21,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0; in vec2 uv0;
uniform sampler2D lightPrePassTex; uniform sampler2D lightPrePassTex;
@ -29,7 +28,7 @@ uniform sampler2D lightPrePassTex;
out vec4 OUT_col; out vec4 OUT_col;
void main() void main()
{ {
vec4 lightColor = texture( lightPrePassTex, uv0 ); vec4 lightColor = texture( lightPrePassTex, uv0 );
OUT_col = vec4( lightColor.rgb, 1.0 ); OUT_col = vec4( lightColor.rgb, 1.0 );
} }

View file

@ -21,7 +21,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0; in vec2 uv0;
uniform sampler2D lightPrePassTex; uniform sampler2D lightPrePassTex;
@ -29,7 +28,7 @@ uniform sampler2D lightPrePassTex;
out vec4 OUT_col; out vec4 OUT_col;
void main() void main()
{ {
float specular = texture( lightPrePassTex, uv0 ).a; float specular = texture( lightPrePassTex, uv0 ).a;
OUT_col = vec4( specular, specular, specular, 1.0 ); OUT_col = vec4( specular, specular, specular, 1.0 );
} }

View file

@ -20,14 +20,14 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0;
uniform sampler2D matinfoTex; uniform sampler2D matinfoTex;
out vec4 OUT_FragColor0; out vec4 OUT_FragColor0;
void main() void main()
{ {
float specular = texture( matinfoTex, uv0 ).a; float specular = texture( matinfoTex, uv0 ).a;
OUT_FragColor0 = vec4( specular, specular, specular, 1.0 ); OUT_FragColor0 = vec4( specular, specular, specular, 1.0 );
} }

View file

@ -52,8 +52,8 @@ void main()
colorBuffer *= (1.0 - colorBuffer.a); colorBuffer *= (1.0 - colorBuffer.a);
} }
colorBuffer *= vec4(lightBuffer.rgb, 1.0);
colorBuffer += vec4(specular, specular, specular, 1.0); colorBuffer += vec4(specular, specular, specular, 1.0);
colorBuffer *= vec4(lightBuffer.rgb, 1.0);
OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) ); OUT_col = hdrEncode( vec4(colorBuffer.rgb, 1.0) );
} }

View file

@ -147,6 +147,17 @@ void main()
return; 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 // Sample/unpack the normal/z data
vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
vec3 normal = prepassSample.rgb; vec3 normal = prepassSample.rgb;
@ -258,6 +269,5 @@ void main()
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
} }
vec4 colorSample = texture( colorBuffer, uvScene ); OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
} }

View file

@ -89,6 +89,17 @@ void main()
return; 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 // Sample/unpack the normal/z data
vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene ); vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
vec3 normal = prepassSample.rgb; vec3 normal = prepassSample.rgb;
@ -195,6 +206,5 @@ void main()
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
} }
vec4 colorSample = texture( colorBuffer, uvScene ); OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
} }

View file

@ -202,6 +202,17 @@ void main()
return; 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 // Sample/unpack the normal/z data
vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 ); vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
vec3 normal = prepassSample.rgb; vec3 normal = prepassSample.rgb;
@ -312,6 +323,5 @@ void main()
lightColorOut = debugColor; lightColorOut = debugColor;
#endif #endif
vec4 colorSample = texture( colorBuffer, uv0 ); OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
} }

View file

@ -149,6 +149,16 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
{ {
return float4(0.0, 0.0, 0.0, 0.0); 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 // Sample/unpack the normal/z data
float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene ); float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene );
@ -263,6 +273,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
} }
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene ); return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
} }

View file

@ -87,6 +87,17 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
return float4(0.0, 0.0, 0.0, 0.0); 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 // Sample/unpack the normal/z data
float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene ); float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene );
float3 normal = prepassSample.rgb; float3 normal = prepassSample.rgb;
@ -194,6 +205,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
addToResult = ( 1.0 - shadowed ) * abs(lightMapParams); addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
} }
float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene ); return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
} }

View file

@ -202,6 +202,16 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
return float4(1.0, 1.0, 1.0, 0.0); 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 // Sample/unpack the normal/z data
float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, IN.uv0 ); float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, IN.uv0 );
float3 normal = prepassSample.rgb; float3 normal = prepassSample.rgb;
@ -314,6 +324,5 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
lightColorOut = debugColor; lightColorOut = debugColor;
#endif #endif
float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 ); return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
} }

View file

@ -43,5 +43,5 @@ float4 main( PFXVertToPix IN ) : TORQUE_TARGET0
fogData.y, fogData.y,
fogData.z ); fogData.z );
return hdrEncode( float4( fogColor.rgb, 1.0 - saturate( factor ) ) ); return hdrEncode( float4( toLinear(fogColor.rgb), 1.0 - saturate( factor ) ) );
} }

View file

@ -48,5 +48,5 @@ void main()
fogData.y, fogData.y,
fogData.z ); fogData.z );
OUT_col = hdrEncode( vec4( fogColor.rgb, 1.0 - saturate( factor ) ) ); OUT_col = hdrEncode( vec4( toLinear(fogColor.rgb), 1.0 - saturate( factor ) ) );
} }

View file

@ -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>

View file

@ -31,8 +31,6 @@ in vec4 mieColor;
#define IN_mieColor mieColor #define IN_mieColor mieColor
in vec3 v3Direction; in vec3 v3Direction;
#define IN_v3Direction v3Direction #define IN_v3Direction v3Direction
in float zPosition;
#define IN_zPosition zPosition
in vec3 pos; in vec3 pos;
#define IN_pos pos #define IN_pos pos
@ -65,12 +63,6 @@ void main()
float fac = dot( normalize( pos ), sunDir ); float fac = dot( normalize( pos ), sunDir );
fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) ); fac = max( nightInterpAndExposure.y, pow( clamp( fac, 0.0, 1.0 ), 2 ) );
OUT_col = mix( color, nightSkyColor, nightInterpAndExposure.y ); 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.a = 1;

View file

@ -47,8 +47,6 @@ out vec4 mieColor;
#define OUT_mieColor mieColor #define OUT_mieColor mieColor
out vec3 v3Direction; out vec3 v3Direction;
#define OUT_v3Direction v3Direction #define OUT_v3Direction v3Direction
out float zPosition;
#define OUT_zPosition zPosition
out vec3 pos; out vec3 pos;
#define OUT_pos pos #define OUT_pos pos

View file

@ -21,13 +21,13 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0;
uniform sampler2D colorBufferTex; uniform sampler2D colorBufferTex;
out vec4 OUT_FragColor0; out vec4 OUT_FragColor0;
void main() void main()
{ {
OUT_FragColor0 = vec4(texture( colorBufferTex, uv0 ).rgb, 1.0); OUT_FragColor0 = vec4(texture( colorBufferTex, uv0 ).rgb, 1.0);
} }

View file

@ -33,4 +33,4 @@ void main()
{ {
float depth = prepassUncondition( prepassTex, uv0 ).w; float depth = prepassUncondition( prepassTex, uv0 ).w;
OUT_col = vec4( texture( depthViz, depth ).rgb, 1.0 ); OUT_col = vec4( texture( depthViz, depth ).rgb, 1.0 );
} }

View file

@ -21,14 +21,13 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
#include "../../../postFx/gl/postFX.glsl"
in vec2 uv0;
uniform sampler2D glowBuffer; uniform sampler2D glowBuffer;
out vec4 OUT_FragColor0; out vec4 OUT_FragColor0;
void main() void main()
{ {
OUT_FragColor0 = texture(glowBuffer, uv0); OUT_FragColor0 = texture(glowBuffer, uv0);
} }

View file

@ -21,7 +21,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0; in vec2 uv0;
uniform sampler2D lightPrePassTex; uniform sampler2D lightPrePassTex;
@ -29,7 +28,7 @@ uniform sampler2D lightPrePassTex;
out vec4 OUT_col; out vec4 OUT_col;
void main() void main()
{ {
vec4 lightColor = texture( lightPrePassTex, uv0 ); vec4 lightColor = texture( lightPrePassTex, uv0 );
OUT_col = vec4( lightColor.rgb, 1.0 ); OUT_col = vec4( lightColor.rgb, 1.0 );
} }

View file

@ -21,7 +21,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0; in vec2 uv0;
uniform sampler2D lightPrePassTex; uniform sampler2D lightPrePassTex;
@ -29,7 +28,7 @@ uniform sampler2D lightPrePassTex;
out vec4 OUT_col; out vec4 OUT_col;
void main() void main()
{ {
float specular = texture( lightPrePassTex, uv0 ).a; float specular = texture( lightPrePassTex, uv0 ).a;
OUT_col = vec4( specular, specular, specular, 1.0 ); OUT_col = vec4( specular, specular, specular, 1.0 );
} }

View file

@ -20,14 +20,14 @@
// IN THE SOFTWARE. // IN THE SOFTWARE.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../../../gl/hlslCompat.glsl" #include "../../../gl/hlslCompat.glsl"
#include "shadergen:/autogenConditioners.h"
in vec2 uv0;
uniform sampler2D matinfoTex; uniform sampler2D matinfoTex;
out vec4 OUT_FragColor0; out vec4 OUT_FragColor0;
void main() void main()
{ {
float specular = texture( matinfoTex, uv0 ).a; float specular = texture( matinfoTex, uv0 ).a;
OUT_FragColor0 = vec4( specular, specular, specular, 1.0 ); OUT_FragColor0 = vec4( specular, specular, specular, 1.0 );
} }

View file

@ -7,20 +7,14 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string> <string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>torqueDemo</string> <string>torque</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.garagegames.${EXECUTABLE_NAME}</string> <string>com.torque3d.${EXECUTABLE_NAME}</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleSignature</key>
<string>GG3d</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>NSMainNibFile</key>
<string>mainMenu</string>
<key>NSPrincipalClass</key>
<string>macApplication</string>
</dict> </dict>
</plist> </plist>

View file

@ -64,11 +64,16 @@ macro(addPath dir)
if(${ARGC} GREATER 1 AND "${ARGV1}" STREQUAL "REC") if(${ARGC} GREATER 1 AND "${ARGV1}" STREQUAL "REC")
set(glob_config GLOB_RECURSE) set(glob_config GLOB_RECURSE)
endif() endif()
set(mac_files "")
if(APPLE)
set(mac_files ${dir}/*.mm ${dir}/*.m)
endif()
file(${glob_config} tmp_files file(${glob_config} tmp_files
${dir}/*.cpp ${dir}/*.cpp
${dir}/*.c ${dir}/*.c
${dir}/*.cc ${dir}/*.cc
${dir}/*.h ${dir}/*.h
${mac_files}
#${dir}/*.asm #${dir}/*.asm
) )
foreach(entry ${BLACKLIST}) foreach(entry ${BLACKLIST})
@ -167,6 +172,13 @@ macro(_process_libs)
endif() endif()
endmacro() endmacro()
# apple frameworks
macro(addFramework framework)
if (APPLE)
addLib("-framework ${framework}")
endif()
endmacro()
############################################################################### ###############################################################################
### Include Handling ### Include Handling
############################################################################### ###############################################################################
@ -298,7 +310,13 @@ macro(finishExecutable)
set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_EXECUTABLES}") set_source_files_properties(${${PROJECT_NAME}_files} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS_EXECUTABLES}")
endif() 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}") addInclude("${firstDir}")
_postTargetProcess() _postTargetProcess()
@ -352,7 +370,7 @@ if(WIN32)
set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "${TORQUE_CXX_FLAGS_COMMON_DEFAULT} /arch:SSE2") set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "${TORQUE_CXX_FLAGS_COMMON_DEFAULT} /arch:SSE2")
endif() endif()
set(TORQUE_CXX_FLAGS_COMMON ${TORQUE_CXX_FLAGS_COMMON_DEFAULT} CACHE TYPE STRING) set(TORQUE_CXX_FLAGS_COMMON ${TORQUE_CXX_FLAGS_COMMON_DEFAULT} CACHE TYPE STRING)
mark_as_advanced(TORQUE_CXX_FLAGS_COMMON) mark_as_advanced(TORQUE_CXX_FLAGS_COMMON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORQUE_CXX_FLAGS_COMMON}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORQUE_CXX_FLAGS_COMMON}")
@ -387,13 +405,20 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}")
endif() endif()
if(UNIX) if(UNIX AND NOT APPLE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${projectOutDir}") SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${projectOutDir}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${projectOutDir}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${projectOutDir}")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}") SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${projectOutDir}")
endif() 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 # fix the debug/release subfolders on windows
if(MSVC) if(MSVC)
SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY" "${projectOutDir}") SET("CMAKE_RUNTIME_OUTPUT_DIRECTORY" "${projectOutDir}")

View file

@ -28,9 +28,9 @@ addPath("${libDir}/epoxy/src")
if (WIN32) if (WIN32)
addPath("${libDir}/epoxy/src/wgl") addPath("${libDir}/epoxy/src/wgl")
addDef(BUILD_WGL) addDef(BUILD_WGL)
else() elseif(UNIX AND NOT APPLE)
addPath("${libDir}/epoxy/src/glx") addPath("${libDir}/epoxy/src/glx")
addDef(BUILD_GLX) addDef(BUILD_GLX)
endif() endif()
addInclude("${libDir}/epoxy/include") addInclude("${libDir}/epoxy/include")

View file

@ -27,7 +27,7 @@ if(UNIX)
set(CXX_FLAG32 "") set(CXX_FLAG32 "")
endif() endif()
#set(CXX_FLAG32 "-m32") #uncomment for build x32 on OSx64 #set(CXX_FLAG32 "-m32") #uncomment for build x32 on OSx64
# default compiler flags # default compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAG32} -Wundef -msse -pipe -Wfatal-errors ${TORQUE_ADDITIONAL_LINKER_FLAGS} -Wl,-rpath,'$$ORIGIN'") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_FLAG32} -Wundef -msse -pipe -Wfatal-errors ${TORQUE_ADDITIONAL_LINKER_FLAGS} -Wl,-rpath,'$$ORIGIN'")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CXX_FLAG32} -Wundef -msse -pipe -Wfatal-errors ${TORQUE_ADDITIONAL_LINKER_FLAGS} -Wl,-rpath,'$$ORIGIN'") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CXX_FLAG32} -Wundef -msse -pipe -Wfatal-errors ${TORQUE_ADDITIONAL_LINKER_FLAGS} -Wl,-rpath,'$$ORIGIN'")
@ -35,7 +35,7 @@ if(UNIX)
# for asm files # for asm files
SET (CMAKE_ASM_NASM_OBJECT_FORMAT "elf") SET (CMAKE_ASM_NASM_OBJECT_FORMAT "elf")
ENABLE_LANGUAGE (ASM_NASM) ENABLE_LANGUAGE (ASM_NASM)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif() endif()
@ -94,10 +94,10 @@ mark_as_advanced(TORQUE_EXPERIMENTAL_EC)
############################################################################### ###############################################################################
# options # 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(TORQUE_BUILD_TYPE "Debug" CACHE STRING "Select one of Debug, Release and RelWithDebInfo")
set_property(CACHE TORQUE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo") set_property(CACHE TORQUE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo")
set(TORQUE_ADDITIONAL_LINKER_FLAGS "" CACHE STRING "Additional linker flags") set(TORQUE_ADDITIONAL_LINKER_FLAGS "" CACHE STRING "Additional linker flags")
mark_as_advanced(TORQUE_ADDITIONAL_LINKER_FLAGS) mark_as_advanced(TORQUE_ADDITIONAL_LINKER_FLAGS)
endif() endif()
@ -157,7 +157,7 @@ if(WIN32)
endif() endif()
# build types # 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}) set(CMAKE_BUILD_TYPE ${TORQUE_BUILD_TYPE})
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(TORQUE_DEBUG TRUE) set(TORQUE_DEBUG TRUE)
@ -200,7 +200,7 @@ addPath("${srcDir}/math/util")
addPath("${srcDir}/math/test") addPath("${srcDir}/math/test")
addPath("${srcDir}/platform") addPath("${srcDir}/platform")
if(NOT TORQUE_SDL) if(NOT TORQUE_SDL)
set(BLACKLIST "fileDialog.cpp" ) set(BLACKLIST "fileDialog.cpp" )
endif() endif()
addPath("${srcDir}/platform/nativeDialogs") addPath("${srcDir}/platform/nativeDialogs")
@ -258,7 +258,7 @@ addPath("${srcDir}/physics")
addPath("${srcDir}/gui/3d") addPath("${srcDir}/gui/3d")
addPath("${srcDir}/postFx") addPath("${srcDir}/postFx")
if(NOT TORQUE_EXPERIMENTAL_EC) if(NOT TORQUE_EXPERIMENTAL_EC)
set(BLACKLIST "entity.cpp;entity.h" ) set(BLACKLIST "entity.cpp;entity.h" )
endif() endif()
addPath("${srcDir}/T3D") addPath("${srcDir}/T3D")
@ -324,15 +324,17 @@ endif()
# OpenAL # OpenAL
if(TORQUE_SFX_OPENAL AND NOT TORQUE_DEDICATED) if(TORQUE_SFX_OPENAL AND NOT TORQUE_DEDICATED)
addPath("${srcDir}/sfx/openal") addPath("${srcDir}/sfx/openal")
#addPath("${srcDir}/sfx/openal/mac")
if(WIN32) if(WIN32)
addPath("${srcDir}/sfx/openal/win32") addPath("${srcDir}/sfx/openal/win32")
addInclude("${libDir}/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() endif()
if(UNIX)
addPath("${srcDir}/sfx/openal/linux")
endif()
endif() endif()
# Vorbis # Vorbis
@ -348,7 +350,7 @@ if(TORQUE_THEORA)
addPath("${srcDir}/core/ogg") addPath("${srcDir}/core/ogg")
addPath("${srcDir}/gfx/video") addPath("${srcDir}/gfx/video")
addPath("${srcDir}/gui/theora") addPath("${srcDir}/gui/theora")
addDef(TORQUE_OGGTHEORA) addDef(TORQUE_OGGTHEORA)
addDef(TORQUE_OGGVORIBS) addDef(TORQUE_OGGVORIBS)
addInclude(${libDir}/libtheora/include) addInclude(${libDir}/libtheora/include)
@ -361,7 +363,7 @@ if(TORQUE_TOOLS)
addPath("${srcDir}/environment/editors") addPath("${srcDir}/environment/editors")
addPath("${srcDir}/forest/editor") addPath("${srcDir}/forest/editor")
addPath("${srcDir}/gui/editor") addPath("${srcDir}/gui/editor")
if(NOT TORQUE_EXPERIMENTAL_EC) if(NOT TORQUE_EXPERIMENTAL_EC)
set(BLACKLIST "entityGroup.cpp;entityGroup.h;mountingGroup.cpp;mountingGroup.h;componentGroup.cpp;componentGroup.h" ) set(BLACKLIST "entityGroup.cpp;entityGroup.h;mountingGroup.cpp;mountingGroup.h;componentGroup.cpp;componentGroup.h" )
endif() endif()
addPath("${srcDir}/gui/editor/inspector") addPath("${srcDir}/gui/editor/inspector")
@ -372,7 +374,7 @@ if(TORQUE_HIFI)
addPath("${srcDir}/T3D/gameBase/hifi") addPath("${srcDir}/T3D/gameBase/hifi")
addDef(TORQUE_HIFI_NET) addDef(TORQUE_HIFI_NET)
endif() endif()
if(TORQUE_EXTENDED_MOVE) if(TORQUE_EXTENDED_MOVE)
addPath("${srcDir}/T3D/gameBase/extended") addPath("${srcDir}/T3D/gameBase/extended")
addDef(TORQUE_EXTENDED_MOVE) addDef(TORQUE_EXTENDED_MOVE)
@ -383,12 +385,12 @@ endif()
if(TORQUE_SDL) if(TORQUE_SDL)
addPathRec("${srcDir}/windowManager/sdl") addPathRec("${srcDir}/windowManager/sdl")
addPathRec("${srcDir}/platformSDL") addPathRec("${srcDir}/platformSDL")
if(TORQUE_OPENGL) if(TORQUE_OPENGL)
addPathRec("${srcDir}/gfx/gl/sdl") addPathRec("${srcDir}/gfx/gl/sdl")
endif() endif()
if(UNIX) if(UNIX AND NOT APPLE)
#set(CMAKE_SIZEOF_VOID_P 4) #force 32 bit #set(CMAKE_SIZEOF_VOID_P 4) #force 32 bit
set(ENV{CFLAGS} "${CXX_FLAG32} -g -O3") set(ENV{CFLAGS} "${CXX_FLAG32} -g -O3")
if("${TORQUE_ADDITIONAL_LINKER_FLAGS}" STREQUAL "") if("${TORQUE_ADDITIONAL_LINKER_FLAGS}" STREQUAL "")
@ -408,22 +410,33 @@ if(TORQUE_SDL)
# Add other flags to the compiler # Add other flags to the compiler
add_definitions(${GTK3_CFLAGS_OTHER}) add_definitions(${GTK3_CFLAGS_OTHER})
set(BLACKLIST "nfd_win.cpp" ) set(BLACKLIST "nfd_win.cpp" "nfd_cocoa.m" )
addLib(nativeFileDialogs) addLib(nativeFileDialogs)
set(BLACKLIST "" ) set(BLACKLIST "" )
target_link_libraries(nativeFileDialogs ${GTK3_LIBRARIES}) target_link_libraries(nativeFileDialogs ${GTK3_LIBRARIES})
elseif(APPLE)
set(BLACKLIST "nfd_gtk.c" "nfd_win.cpp" )
addLib(nativeFileDialogs)
set(BLACKLIST "" )
else() else()
set(BLACKLIST "nfd_gtk.c" ) set(BLACKLIST "nfd_gtk.c" "nfd_cocoa.m" )
addLib(nativeFileDialogs) addLib(nativeFileDialogs)
set(BLACKLIST "" ) set(BLACKLIST "" )
addLib(comctl32) addLib(comctl32)
endif() endif()
#override and hide SDL2 cache variables #override and hide SDL2 cache variables
set(SDL_SHARED ON CACHE INTERNAL "" FORCE) #set apple to sue sdl static lib, other platforms use dynamic
set(SDL_STATIC OFF CACHE INTERNAL "" FORCE) 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) add_subdirectory( ${libDir}/sdl ${CMAKE_CURRENT_BINARY_DIR}/sdl2)
link_directories( ${libDir}/sdl ${CMAKE_CURRENT_BINARY_DIR}/sdl2)
endif() endif()
if(TORQUE_DEDICATED) if(TORQUE_DEDICATED)
@ -445,13 +458,15 @@ endforeach()
############################################################################### ###############################################################################
if(WIN32) if(WIN32)
addPath("${srcDir}/platformWin32") addPath("${srcDir}/platformWin32")
if(TORQUE_SDL) if(TORQUE_SDL)
set(BLACKLIST "fileDialog.cpp" ) set(BLACKLIST "fileDialog.cpp" )
endif() endif()
addPath("${srcDir}/platformWin32/nativeDialogs") addPath("${srcDir}/platformWin32/nativeDialogs")
set(BLACKLIST "" ) set(BLACKLIST "" )
addPath("${srcDir}/platformWin32/menus") addPath("${srcDir}/platformWin32/menus")
addPath("${srcDir}/platformWin32/threads") if(NOT TORQUE_SDL)
addPath("${srcDir}/platformWin32/threads")
endif()
addPath("${srcDir}/platformWin32/videoInfo") addPath("${srcDir}/platformWin32/videoInfo")
addPath("${srcDir}/platformWin32/minidump") addPath("${srcDir}/platformWin32/minidump")
addPath("${srcDir}/windowManager/win32") addPath("${srcDir}/windowManager/win32")
@ -460,7 +475,7 @@ if(WIN32)
endif() endif()
addPath("${srcDir}/gfx/D3D9") addPath("${srcDir}/gfx/D3D9")
addPath("${srcDir}/gfx/D3D9/pc") addPath("${srcDir}/gfx/D3D9/pc")
addPath("${srcDir}/shaderGen/HLSL") addPath("${srcDir}/shaderGen/HLSL")
addPath("${srcDir}/terrain/hlsl") addPath("${srcDir}/terrain/hlsl")
addPath("${srcDir}/forest/hlsl") addPath("${srcDir}/forest/hlsl")
# add windows rc file for the icon # add windows rc file for the icon
@ -469,50 +484,14 @@ endif()
if(APPLE) if(APPLE)
addPath("${srcDir}/platformMac") addPath("${srcDir}/platformMac")
addPath("${srcDir}/platformMac/menus")
addPath("${srcDir}/platformPOSIX") 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() endif()
if(XBOX360) if(UNIX AND NOT APPLE)
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)
# linux_dedicated # linux_dedicated
if(TORQUE_DEDICATED) if(TORQUE_DEDICATED)
addPath("${srcDir}/windowManager/dedicated") addPath("${srcDir}/windowManager/dedicated")
# ${srcDir}/platformX86UNIX/*.client.* files are not needed # ${srcDir}/platformX86UNIX/*.client.* files are not needed
# @todo: move to separate file # @todo: move to separate file
file( GLOB tmp_files file( GLOB tmp_files
${srcDir}/platformX86UNIX/*.cpp ${srcDir}/platformX86UNIX/*.cpp
@ -527,9 +506,8 @@ if(UNIX)
else() else()
addPath("${srcDir}/platformX86UNIX") addPath("${srcDir}/platformX86UNIX")
addPath("${srcDir}/platformX86UNIX/nativeDialogs") addPath("${srcDir}/platformX86UNIX/nativeDialogs")
endif() endif()
# linux # linux
addPath("${srcDir}/platformX86UNIX/threads")
addPath("${srcDir}/platformPOSIX") addPath("${srcDir}/platformPOSIX")
endif() endif()
@ -537,12 +515,12 @@ if( TORQUE_OPENGL )
addPath("${srcDir}/shaderGen/GLSL") addPath("${srcDir}/shaderGen/GLSL")
if( TORQUE_OPENGL AND NOT TORQUE_DEDICATED ) if( TORQUE_OPENGL AND NOT TORQUE_DEDICATED )
addPath("${srcDir}/gfx/gl") addPath("${srcDir}/gfx/gl")
addPath("${srcDir}/gfx/gl/tGL") addPath("${srcDir}/gfx/gl/tGL")
addPath("${srcDir}/shaderGen/GLSL") addPath("${srcDir}/shaderGen/GLSL")
addPath("${srcDir}/terrain/glsl") addPath("${srcDir}/terrain/glsl")
addPath("${srcDir}/forest/glsl") addPath("${srcDir}/forest/glsl")
endif() endif()
if(WIN32 AND NOT TORQUE_SDL) if(WIN32 AND NOT TORQUE_SDL)
addPath("${srcDir}/gfx/gl/win32") addPath("${srcDir}/gfx/gl/win32")
endif() endif()
@ -563,9 +541,24 @@ message(STATUS "writing ${projectSrcDir}/torqueConfig.h")
CONFIGURE_FILE("${cmakeDir}/torqueConfig.h.in" "${projectSrcDir}/torqueConfig.h") CONFIGURE_FILE("${cmakeDir}/torqueConfig.h.in" "${projectSrcDir}/torqueConfig.h")
# configure the relevant files only once # 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() endif()
if(NOT EXISTS "${projectOutDir}/${PROJECT_NAME}.torsion") if(NOT EXISTS "${projectOutDir}/${PROJECT_NAME}.torsion")
CONFIGURE_FILE("${cmakeDir}/template.torsion.in" "${projectOutDir}/${PROJECT_NAME}.torsion") CONFIGURE_FILE("${cmakeDir}/template.torsion.in" "${projectOutDir}/${PROJECT_NAME}.torsion")
endif() endif()
@ -607,11 +600,11 @@ if(WIN32)
set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against") set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against")
mark_as_advanced(TORQUE_EXTERNAL_LIBS) mark_as_advanced(TORQUE_EXTERNAL_LIBS)
addLib("${TORQUE_EXTERNAL_LIBS}") addLib("${TORQUE_EXTERNAL_LIBS}")
if(TORQUE_OPENGL) if(TORQUE_OPENGL)
addLib(OpenGL32.lib) addLib(OpenGL32.lib)
endif() endif()
# JTH: DXSDK is compiled with older runtime, and MSVC 2015+ is when __vsnprintf is undefined. # JTH: DXSDK is compiled with older runtime, and MSVC 2015+ is when __vsnprintf is undefined.
# This is a workaround by linking with the older legacy library functions. # This is a workaround by linking with the older legacy library functions.
# See this for more info: http://stackoverflow.com/a/34230122 # See this for more info: http://stackoverflow.com/a/34230122
@ -620,20 +613,28 @@ if(WIN32)
endif() endif()
endif() endif()
if(UNIX) 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 AND NOT APPLE)
# copy pasted from T3D build system, some might not be needed # 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") 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) mark_as_advanced(TORQUE_EXTERNAL_LIBS)
string(REPLACE " " ";" TORQUE_EXTERNAL_LIBS_LIST ${TORQUE_EXTERNAL_LIBS})
addLib( "${TORQUE_EXTERNAL_LIBS_LIST}" )
endif()
if(UNIX)
# 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")
mark_as_advanced(TORQUE_EXTERNAL_LIBS)
string(REPLACE " " ";" TORQUE_EXTERNAL_LIBS_LIST ${TORQUE_EXTERNAL_LIBS}) string(REPLACE " " ";" TORQUE_EXTERNAL_LIBS_LIST ${TORQUE_EXTERNAL_LIBS})
addLib( "${TORQUE_EXTERNAL_LIBS_LIST}" ) addLib( "${TORQUE_EXTERNAL_LIBS_LIST}" )
endif() endif()
@ -661,8 +662,8 @@ addDef(PCRE_STATIC)
addDef(_CRT_SECURE_NO_WARNINGS) addDef(_CRT_SECURE_NO_WARNINGS)
addDef(_CRT_SECURE_NO_DEPRECATE) addDef(_CRT_SECURE_NO_DEPRECATE)
if(UNIX) if(UNIX AND NOT APPLE)
addDef(LINUX) addDef(LINUX)
endif() endif()
if(TORQUE_OPENGL) if(TORQUE_OPENGL)
@ -705,7 +706,7 @@ if(TORQUE_OPENGL)
addInclude("${libDir}/epoxy/src") addInclude("${libDir}/epoxy/src")
endif() endif()
if(UNIX) if(UNIX AND NOT APPLE)
addInclude("/usr/include/freetype2/freetype") addInclude("/usr/include/freetype2/freetype")
addInclude("/usr/include/freetype2") addInclude("/usr/include/freetype2")
endif() endif()
@ -715,11 +716,6 @@ if(WIN32)
set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES $ENV{DXSDK_DIR}/Include) set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY INCLUDE_DIRECTORIES $ENV{DXSDK_DIR}/Include)
endif() endif()
if(UNIX)
addInclude("/usr/include/freetype2/freetype")
addInclude("/usr/include/freetype2")
endif()
if(MSVC) if(MSVC)
# Match projectGenerator naming for executables # Match projectGenerator naming for executables
set(OUTPUT_CONFIG DEBUG MINSIZEREL RELWITHDEBINFO) set(OUTPUT_CONFIG DEBUG MINSIZEREL RELWITHDEBINFO)
@ -738,16 +734,16 @@ endif()
if(TORQUE_TEMPLATE) if(TORQUE_TEMPLATE)
message("Prepare Template(${TORQUE_TEMPLATE}) install...") message("Prepare Template(${TORQUE_TEMPLATE}) install...")
file(GLOB_RECURSE INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/*") file(GLOB_RECURSE INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/*")
IF( NOT TORQUE_EXPERIMENTAL_EC) IF( NOT TORQUE_EXPERIMENTAL_EC)
list(REMOVE_ITEM INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/art/art.module.taml") list(REMOVE_ITEM INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/art/art.module.taml")
list(REMOVE_ITEM INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/art/shapes/actors/Soldier/soldier.asset.taml") list(REMOVE_ITEM INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/art/shapes/actors/Soldier/soldier.asset.taml")
list(REMOVE_ITEM INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/scripts.module.taml") list(REMOVE_ITEM INSTALL_FILES_AND_DIRS "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/scripts.module.taml")
foreach(ITEM ${INSTALL_FILES_AND_DIRS}) foreach(ITEM ${INSTALL_FILES_AND_DIRS})
get_filename_component( dir ${ITEM} DIRECTORY ) get_filename_component( dir ${ITEM} DIRECTORY )
get_filename_component( fileName ${ITEM} NAME ) get_filename_component( fileName ${ITEM} NAME )
if( ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/components if( ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/components
OR ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/components/game OR ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/components/game
OR ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/components/input OR ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/components/input
OR ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/gameObjects OR ${dir} STREQUAL ${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/game/scripts/server/gameObjects
@ -758,13 +754,13 @@ if(TORQUE_TEMPLATE)
ENDIF() ENDIF()
endforeach() endforeach()
ENDIF() ENDIF()
foreach(ITEM ${INSTALL_FILES_AND_DIRS}) foreach(ITEM ${INSTALL_FILES_AND_DIRS})
get_filename_component( dir ${ITEM} DIRECTORY ) get_filename_component( dir ${ITEM} DIRECTORY )
STRING(REGEX REPLACE "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/" "${TORQUE_APP_DIR}/" INSTALL_DIR ${dir}) STRING(REGEX REPLACE "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/" "${TORQUE_APP_DIR}/" INSTALL_DIR ${dir})
install( FILES ${ITEM} DESTINATION ${INSTALL_DIR} ) install( FILES ${ITEM} DESTINATION ${INSTALL_DIR} )
endforeach() endforeach()
if(WIN32) if(WIN32)
INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/cleanShaders.bat" DESTINATION "${TORQUE_APP_DIR}") INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/cleanShaders.bat" DESTINATION "${TORQUE_APP_DIR}")
INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/DeleteCachedDTSs.bat" DESTINATION "${TORQUE_APP_DIR}") INSTALL(FILES "${CMAKE_SOURCE_DIR}/Templates/${TORQUE_TEMPLATE}/DeleteCachedDTSs.bat" DESTINATION "${TORQUE_APP_DIR}")