diff --git a/AI/BattleAI/CMakeLists.txt b/AI/BattleAI/CMakeLists.txt index eaf7983e6..978587320 100644 --- a/AI/BattleAI/CMakeLists.txt +++ b/AI/BattleAI/CMakeLists.txt @@ -1,7 +1,7 @@ project(battleAI) cmake_minimum_required(VERSION 2.6) -include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) +include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) set(battleAI_SRCS BattleAI.cpp @@ -11,5 +11,7 @@ set(battleAI_SRCS add_library(BattleAI SHARED ${battleAI_SRCS}) target_link_libraries(BattleAI vcmi) -install(TARGETS BattleAI DESTINATION ${AI_LIB_DIR}) +if (NOT APPLE) # Already inside vcmiclient bundle + install(TARGETS BattleAI DESTINATION ${AI_LIB_DIR}) +endif() diff --git a/AI/EmptyAI/CMakeLists.txt b/AI/EmptyAI/CMakeLists.txt index 4630de447..c7a40ec70 100644 --- a/AI/EmptyAI/CMakeLists.txt +++ b/AI/EmptyAI/CMakeLists.txt @@ -1,7 +1,7 @@ project(emptyAI) cmake_minimum_required(VERSION 2.6) -include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) +include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) set(emptyAI_SRCS CEmptyAI.cpp @@ -11,4 +11,6 @@ set(emptyAI_SRCS add_library(EmptyAI SHARED ${emptyAI_SRCS}) target_link_libraries(EmptyAI vcmi) -install(TARGETS EmptyAI DESTINATION ${AI_LIB_DIR}) +if (NOT APPLE) # Already inside vcmiclient bundle + install(TARGETS EmptyAI DESTINATION ${AI_LIB_DIR}) +endif() diff --git a/AI/StupidAI/CMakeLists.txt b/AI/StupidAI/CMakeLists.txt index d3e9c53e7..9320fceb9 100644 --- a/AI/StupidAI/CMakeLists.txt +++ b/AI/StupidAI/CMakeLists.txt @@ -1,7 +1,7 @@ project(stupidAI) cmake_minimum_required(VERSION 2.6) -include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) +include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib) set(stupidAI_SRCS StupidAI.cpp @@ -11,5 +11,7 @@ set(stupidAI_SRCS add_library(StupidAI SHARED ${stupidAI_SRCS}) target_link_libraries(StupidAI vcmi) -install(TARGETS StupidAI DESTINATION ${AI_LIB_DIR}) +if (NOT APPLE) # Already inside vcmiclient bundle + install(TARGETS StupidAI DESTINATION ${AI_LIB_DIR}) +endif() diff --git a/AI/VCAI/CMakeLists.txt b/AI/VCAI/CMakeLists.txt index ad5f9d0e3..2a45dca06 100644 --- a/AI/VCAI/CMakeLists.txt +++ b/AI/VCAI/CMakeLists.txt @@ -1,7 +1,7 @@ project(VCAI) cmake_minimum_required(VERSION 2.6) -include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib ${CMAKE_HOME_DIRECTORY}/AI/FuzzyLite) +include_directories(${Boost_INCLUDE_DIRS} ${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_HOME_DIRECTORY}/lib ${CMAKE_HOME_DIRECTORY}/AI/FuzzyLite) set(VCAI_SRCS main.cpp @@ -12,4 +12,6 @@ set(VCAI_SRCS add_library(VCAI SHARED ${VCAI_SRCS}) target_link_libraries(VCAI FuzzyLite_lib vcmi) -install(TARGETS VCAI DESTINATION ${AI_LIB_DIR}) +if (NOT APPLE) # Already inside vcmiclient bundle + install(TARGETS VCAI DESTINATION ${AI_LIB_DIR}) +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index c0c021e9e..54afff106 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,25 @@ option(DISABLE_ERM "Disable compilation of ERM scripting module" ON) # Building section # ############################################ +if (APPLE) + # Default location for thirdparty libs + set(CMAKE_INCLUDE_PATH "../include") + set(CMAKE_LIBRARY_PATH "../lib") + set(CMAKE_FRAMEWORK_PATH "../Frameworks") + set(BOOST_ROOT "../") + + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin") + + set(CMAKE_XCODE_ATTRIBUTE_CONFIGURATION_BUILD_DIR "${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)") + set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks") + + # Build with clang ang libc++ + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") +endif() + find_package(Boost 1.46.0 COMPONENTS program_options filesystem system thread REQUIRED) find_package(SDL REQUIRED) find_package(SDL_image REQUIRED) @@ -47,6 +66,13 @@ if(WIN32) # on Win everything goes into H3 root directory set(BIN_DIR "" CACHE STRING "Where to install binaries") set(LIB_DIR "" CACHE STRING "Where to install main library") set(DATA_DIR "" CACHE STRING "Where to install data files") +elseif(APPLE) + # includes lib path which determines where to install shared libraries (either /lib or /lib64) + include(GNUInstallDirs) + + set(BIN_DIR "." CACHE STRING "Where to install binaries") + set(LIB_DIR "." CACHE STRING "Where to install main library") + set(DATA_DIR "../h3" CACHE STRING "Where to install data files") else() # includes lib path which determines where to install shared libraries (either /lib or /lib64) include(GNUInstallDirs) @@ -79,17 +105,21 @@ endif() # Installation section # ####################################### -# copy whole directory but .svn control files and user-specific settings.json -install(DIRECTORY config DESTINATION ${DATA_DIR} PATTERN ".svn" EXCLUDE PATTERN "settings.json" EXCLUDE) -# copy vcmi mod along with all its content -install(DIRECTORY Mods/vcmi DESTINATION ${DATA_DIR}/Mods PATTERN ".svn" EXCLUDE) -# copy only fs.json for WoG -install(FILES Mods/WoG/filesystem.json DESTINATION ${DATA_DIR}/Mods/WoG) +# For apple this files will be already inside vcmiclient bundle +if (NOT APPLE) + # copy whole directory but .svn control files and user-specific settings.json + install(DIRECTORY config DESTINATION ${DATA_DIR} PATTERN ".svn" EXCLUDE PATTERN "settings.json" EXCLUDE) + # copy vcmi mod along with all its content + install(DIRECTORY Mods/vcmi DESTINATION ${DATA_DIR}/Mods PATTERN ".svn" EXCLUDE) + # copy only fs.json for WoG + install(FILES Mods/WoG/filesystem.json DESTINATION ${DATA_DIR}/Mods/WoG) +endif() if(WIN32) #TODO: install any additional dll's. This version (may be broken) will copy all dll's including H3 ones #FILE(GLOB dll_files "${CMAKE_BINARY_DIR}/*.dll") #INSTALL(FILES ${dll_files} DESTINATION ${BIN_DIR}) +elseif(APPLE) else() #install icons and desktop file on Linux install(FILES "${CMAKE_SOURCE_DIR}/client/icons/vcmiclient.64x64.png" DESTINATION share/icons/hicolor/64x64/apps RENAME vcmiclient.png) @@ -118,6 +148,8 @@ set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) if(WIN32) set(CPACK_GENERATOR ZIP) # just use zip? CPack has some GUI install as well +elseif(APPLE) + set(CPACK_GENERATOR DragNDrop) else() set(CPACK_GENERATOR TGZ) endif() diff --git a/client/BattleInterface/CBattleInterface.h b/client/BattleInterface/CBattleInterface.h index 81b13921d..cb0683dec 100644 --- a/client/BattleInterface/CBattleInterface.h +++ b/client/BattleInterface/CBattleInterface.h @@ -5,6 +5,7 @@ #include "../../lib/ConstTransitivePtr.h" //may be reundant #include "../CAnimation.h" #include "../../lib/GameConstants.h" +#include "CBattleAnimations.h" /* * CBattleInterface.h, part of VCMI engine diff --git a/client/CMT.cpp b/client/CMT.cpp index 9ee079f4c..ef017fa98 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -177,11 +177,20 @@ static void prog_help(const po::options_description &opts) #ifdef _WIN32 int _tmain(int argc, _TCHAR* argv[]) +#elif defined(__APPLE__) +int SDL_main(int argc, char *argv[]) #else int main(int argc, char** argv) #endif { - tlog0 << "Starting... " << std::endl; +#ifdef __APPLE__ + // Correct working dir executable folder (not bundle folder) so we can use executable relative pathes + std::string executablePath = argv[0]; + std::string workDir = executablePath.substr(0, executablePath.rfind('/')); + chdir(workDir.c_str()); +#endif + + tlog0 << "Starting... " << std::endl; po::options_description opts("Allowed options"); opts.add_options() ("help,h", "display help and exit") diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 7e67f59a7..a389728b3 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -42,11 +42,45 @@ set(client_SRCS NetPacksClient.cpp ) -IF(UNIX) - add_executable(vcmiclient ${client_SRCS}) -ELSEIF(WIN32) +if(WIN32) add_executable(vcmiclient WIN32 ${client_SRCS}) -ENDIF() +elseif(APPLE) + # When building for OS X we need add SDLMain.m to source files + add_executable(vcmiclient MACOSX_BUNDLE ${client_SRCS} SDLMain.m ${CMAKE_CURRENT_SOURCE_DIR}/vcmi.icns) + + # Because server and AI libs would be copies to bundle they need to be built before client + add_dependencies(vcmiclient vcmiserver VCAI EmptyAI StupidAI BattleAI) + + # Copy icon file + set(MACOSX_BUNDLE_ICON_FILE vcmi.icns) + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/vcmi.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + # Copy server executable, libs and game data to bundle + set(BUNDLE_PATH ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/vcmiclient.app/Contents) + set(MakeVCMIBundle + # Copy all needed binaries + mkdir -p ${BUNDLE_PATH}/MacOS/AI && + cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/vcmiserver ${BUNDLE_PATH}/MacOS/vcmiserver && + cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libvcmi.dylib ${BUNDLE_PATH}/MacOS/libvcmi.dylib && + cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libVCAI.dylib ${BUNDLE_PATH}/MacOS/AI/libVCAI.dylib && + cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libStupidAI.dylib ${BUNDLE_PATH}/MacOS/AI/libStupidAI.dylib && + cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libEmptyAI.dylib ${BUNDLE_PATH}/MacOS/AI/libEmptyAI.dylib && + cp ${CMAKE_HOME_DIRECTORY}/bin/$(CONFIGURATION)/libBattleAI.dylib ${BUNDLE_PATH}/MacOS/AI/libBattleAI.dylib && + + # Copy frameworks + cp -r ${CMAKE_HOME_DIRECTORY}/${CMAKE_FRAMEWORK_PATH} ${BUNDLE_PATH}/Frameworks && + + # Copy vcmi data + mkdir -p ${BUNDLE_PATH}/Data && + mkdir -p ${BUNDLE_PATH}/Data/Mods && + mkdir -p ${BUNDLE_PATH}/Data/Mods/WoG && + cp -r ${CMAKE_HOME_DIRECTORY}/config ${BUNDLE_PATH}/Data/config && + cp -r ${CMAKE_HOME_DIRECTORY}/Mods/vcmi ${BUNDLE_PATH}/Data/Mods/vcmi && + cp ${CMAKE_HOME_DIRECTORY}/Mods/WoG/filesystem.json ${BUNDLE_PATH}/Data/Mods/WoG/filesystem.json) + add_custom_command(TARGET vcmiclient POST_BUILD COMMAND ${MakeVCMIBundle}) +else() + add_executable(vcmiclient ${client_SRCS}) +endif() target_link_libraries(vcmiclient vcmi ${Boost_LIBRARIES} ${SDL_LIBRARY} ${SDLIMAGE_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLTTF_LIBRARY} ${ZLIB_LIBRARIES} ${FFMPEG_LIBRARIES} ${RT_LIB} ${DL_LIB}) diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 6a4c2f9e6..ab383030e 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -5,6 +5,7 @@ #include "FunctionList.h" #include "../lib/CGameInterface.h" #include "UIFramework/CIntObject.h" +#include "CGameState.h" #ifdef __GNUC__ #define sprintf_s snprintf diff --git a/client/CVideoHandler.cpp b/client/CVideoHandler.cpp index 1291f48fd..7ec031536 100644 --- a/client/CVideoHandler.cpp +++ b/client/CVideoHandler.cpp @@ -837,12 +837,27 @@ bool CVideoPlayer::open(std::string fname, bool loop, bool useOverlay) { PixelFormat screenFormat = PIX_FMT_NONE; - switch(screen->format->BytesPerPixel) + if (screen->format->Bshift < screen->format->Rshift) { - case 2: screenFormat = PIX_FMT_RGB565; break; - case 3: screenFormat = PIX_FMT_RGB24; break; - case 4: screenFormat = PIX_FMT_RGB32; break; - default: return false; + // this a BGR surface + switch (screen->format->BytesPerPixel) + { + case 2: screenFormat = PIX_FMT_BGR565; break; + case 3: screenFormat = PIX_FMT_BGR24; break; + case 4: screenFormat = PIX_FMT_BGR32; break; + default: return false; + } + } + else + { + // this a RGB surface + switch (screen->format->BytesPerPixel) + { + case 2: screenFormat = PIX_FMT_RGB565; break; + case 3: screenFormat = PIX_FMT_RGB24; break; + case 4: screenFormat = PIX_FMT_RGB32; break; + default: return false; + } } sws = sws_getContext(codecContext->width, codecContext->height, diff --git a/client/SDLMain.h b/client/SDLMain.h new file mode 100644 index 000000000..c56d90cbe --- /dev/null +++ b/client/SDLMain.h @@ -0,0 +1,16 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#ifndef _SDLMain_h_ +#define _SDLMain_h_ + +#import + +@interface SDLMain : NSObject +@end + +#endif /* _SDLMain_h_ */ diff --git a/client/SDLMain.m b/client/SDLMain.m new file mode 100644 index 000000000..b065a2009 --- /dev/null +++ b/client/SDLMain.m @@ -0,0 +1,383 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#include "SDL.h" +#include "SDLMain.h" +#include /* for MAXPATHLEN */ +#include + +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ +@interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; +@end + +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + const NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ +@interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; +@end +#endif + +@interface SDLApplication : NSApplication +@end + +@implementation SDLApplication +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} +@end + +/* The main class of the application, the application's delegate */ +@implementation SDLMain + +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { + chdir(parentdir); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } +} + +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } + [ aMenu sizeToFit ]; +} + +#else + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [SDLApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif + + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} +@end + + +@implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + +@end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } + +#if SDL_USE_NIB_FILE + [SDLApplication poseAsClass:[NSApplication class]]; + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; +} + diff --git a/client/icons/generate_icns.py b/client/icons/generate_icns.py new file mode 100644 index 000000000..25d351afb --- /dev/null +++ b/client/icons/generate_icns.py @@ -0,0 +1,18 @@ +from PIL import Image +import os, sys, shutil + +img = Image.open(sys.argv[1]) +if img.size != (1024,1024): + print "Input image must be 1024x1024. Provided image is %dx%d" % img.size + +os.mkdir("vcmi.iconset") +for i in [16, 32, 128, 256, 512]: + resized = img.resize((i, i), Image.ANTIALIAS) + resized.save("vcmi.iconset/icon_%dx%d.png" % (i, i)) + + resized2x = img.resize((2*i, 2*i), Image.ANTIALIAS) + resized2x.save("vcmi.iconset/icon_%dx%d@2x.png" % (i, i)) + +os.system("iconutil -c icns vcmi.iconset") +shutil.rmtree("vcmi.iconset") + diff --git a/client/mapHandler.h b/client/mapHandler.h index aa0bf2e55..58ec27e02 100644 --- a/client/mapHandler.h +++ b/client/mapHandler.h @@ -2,6 +2,7 @@ #include "../lib/int3.h" +#include "SDL.h" /* * mapHandler.h, part of VCMI engine @@ -21,7 +22,7 @@ class CGObjectInstance; class CDefHandler; struct TerrainTile; struct SDL_Surface; -struct SDL_Rect; +//struct SDL_Rect; class CDefEssential; struct TerrainTile2 diff --git a/client/vcmi.icns b/client/vcmi.icns new file mode 100644 index 000000000..4fdfe983d Binary files /dev/null and b/client/vcmi.icns differ diff --git a/cmake_modules/FindFFMPEG_swscale.cmake b/cmake_modules/FindFFMPEG_swscale.cmake index 6cd23ef30..2d0991f92 100644 --- a/cmake_modules/FindFFMPEG_swscale.cmake +++ b/cmake_modules/FindFFMPEG_swscale.cmake @@ -68,5 +68,9 @@ ENDIF( FFMPEG_CONFIG ) ENDIF( FFMPEG_INCLUDE_DIR ) +IF (APPLE) + SET(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} "-framework VideoDecodeAcceleration -framework CoreVideo -lbz2") +ENDIF() + INCLUDE (FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFMPEG DEFAULT_MESSAGE FFMPEG_INCLUDE_DIR FFMPEG_LIBRARIES) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cab87d50f..9d481d560 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -2,7 +2,7 @@ project(libvcmi) cmake_minimum_required(VERSION 2.6) include_directories(${CMAKE_HOME_DIRECTORY} ${CMAKE_CURRENT_SOURCE_DIRECTORY} ${CMAKE_HOME_DIRECTORY}/lib) -include_directories(${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) +include_directories(${Boost_INCLUDE_DIRS} ${SDL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) set(lib_SRCS Filesystem/CBinaryReader.cpp @@ -70,6 +70,9 @@ set(lib_HEADERS ) add_library(vcmi SHARED ${lib_SRCS} ${lib_HEADERS}) +set_target_properties(vcmi PROPERTIES XCODE_ATTRIBUTE_LD_DYLIB_INSTALL_NAME "@executable_path/libvcmi.dylib") target_link_libraries(vcmi ${Boost_LIBRARIES} ${SDL_LIBRARY} ${ZLIB_LIBRARIES}) -install(TARGETS vcmi DESTINATION ${LIB_DIR}) +if (NOT APPLE) # Already inside vcmiclient bundle + install(TARGETS vcmi DESTINATION ${LIB_DIR}) +endif() diff --git a/lib/CThreadHelper.cpp b/lib/CThreadHelper.cpp index f3b624469..c250f1b9f 100644 --- a/lib/CThreadHelper.cpp +++ b/lib/CThreadHelper.cpp @@ -3,7 +3,7 @@ #ifdef _WIN32 #include -#else +#elif !defined(__APPLE__) #include #endif /* @@ -80,7 +80,7 @@ void setThreadName(const std::string &name) //not supported #endif -#else - prctl(PR_SET_NAME, name.c_str(), 0, 0, 0); +#elif defined(__linux__) + prctl(PR_SET_NAME, name.c_str(), 0, 0, 0); #endif } diff --git a/lib/GameConstants.h b/lib/GameConstants.h index b36fe2df9..8758fa218 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -19,15 +19,22 @@ namespace GameConstants * BIN_DIR is where the vcmiclient/vcmiserver binaries reside * LIB_DIR is where the AI libraries reside (linux only) */ - #ifdef _WIN32 + #if defined(_WIN32) const std::string DATA_DIR = "."; const std::string BIN_DIR = "."; const std::string LIB_DIR = "."; const std::string SERVER_NAME = "VCMI_server.exe"; const std::string LIB_EXT = "dll"; const std::string PATH_SEPARATOR = "\\"; - #else - #ifndef M_DATA_DIR + #elif defined(__APPLE__) + const std::string DATA_DIR = "../Data"; + const std::string BIN_DIR = "."; + const std::string LIB_DIR = "."; + const std::string SERVER_NAME = "./vcmiserver"; + const std::string LIB_EXT = "dylib"; + const std::string PATH_SEPARATOR = "/"; + #else + #ifndef M_DATA_DIR #error M_DATA_DIR undefined. #else const std::string DATA_DIR = M_DATA_DIR; diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index f15a00185..0aae925fc 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -10,13 +10,15 @@ set(server_SRCS NetPacksServer.cpp ) -IF(UNIX) - add_executable(vcmiserver ${server_SRCS}) -ELSEIF(WIN32) +if(WIN32) add_executable(vcmiserver WIN32 ${server_SRCS}) -ENDIF() +else() + add_executable(vcmiserver ${server_SRCS}) +endif() target_link_libraries(vcmiserver vcmi ${Boost_LIBRARIES} ${RT_LIB} ${DL_LIB}) -install(TARGETS vcmiserver DESTINATION ${BIN_DIR}) +if (NOT APPLE) # Already inside vcmiclient bundle + install(TARGETS vcmiserver DESTINATION ${BIN_DIR}) +endif()