From bf0c0227ecefa491937a982cff6ab9cf60460ada Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 30 Oct 2013 09:06:06 +0100 Subject: [PATCH 01/20] Fix tab-vs-space in CMake configuration file --- desktop/CMakeLists.txt | 198 ++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index b2115639..72417578 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -1,104 +1,104 @@ cmake_minimum_required(VERSION 2.8) if(NOT PLATFORM_WINDOWS) - # Install Desktop Entry file - set(COLOBOT_DESKTOP_FILE colobot.desktop) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE} - COMMAND ./create_desktop_file.sh > ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Build ${COLOBOT_DESKTOP_FILE}" - ) - add_custom_target(desktopfile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}) - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE} - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/ - ) - - # Install Icon - set(COLOBOT_ICON_FILE colobot.svg) - install( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/ - ) - - # Render SVG icon in various sizes - find_program(RSVG_CONVERT rsvg-convert) - if(RSVG_CONVERT) - foreach(PNGSIZE "48" "32" "16") - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}) - add_custom_target(resize_icon_${PNGSIZE} ALL - COMMAND ${RSVG_CONVERT} -w ${PNGSIZE} -h ${PNGSIZE} ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} - > ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png - ) - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${PNGSIZE}x${PNGSIZE}/apps/ - ) - endforeach() - endif() - - # Create manpage from pod-formatted file - find_program(POD2MAN pod2man) - if(POD2MAN) - set(COLOBOT_MANPAGE_SECTION 6) - - macro(podman) - cmake_parse_arguments(PM "" "PODFILE;LOCALE;" "" ${ARGN}) - if(PM_LOCALE) - # This copes with the fact that english has no "/LANG" in the paths and filenames. - set(SLASHLOCALE /${PM_LOCALE}) - endif() - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}) - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE} - COMMAND ${POD2MAN} ARGS --section=${COLOBOT_MANPAGE_SECTION} - --center="Colobot" --stderr --utf8 - --release="${COLOBOT_VERSION_FULL}" - ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE} - ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} - COMMENT "Create ${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} manpage" - ) - add_custom_target(man${PM_LOCALE} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}) - - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man${SLASHLOCALE}/man${COLOBOT_MANPAGE_SECTION}/ ) - - add_dependencies(man man${PM_LOCALE}) - endmacro() - - # Create the english manpage - podman(PODFILE colobot.pod) - - endif() - - # Translate translatable material - find_program(PO4A po4a) - - if(PO4A) - add_custom_target(desktop_po4a - COMMAND ${PO4A} po4a.cfg - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - add_dependencies(desktopfile desktop_po4a) - - if(POD2MAN) - add_custom_target(man_po4a - COMMAND ${PO4A} po4a.cfg - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - add_dependencies(man man_po4a) - file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po) - string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO}) - foreach(LOCALE ${LINGUAS}) - podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE}) - add_dependencies(man${PM_LOCALE} man_po4a) - endforeach() - endif() - endif() - + # Install Desktop Entry file + set(COLOBOT_DESKTOP_FILE colobot.desktop) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE} + COMMAND ./create_desktop_file.sh > ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + COMMENT "Build ${COLOBOT_DESKTOP_FILE}" + ) + add_custom_target(desktopfile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE} + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/ + ) + + # Install Icon + set(COLOBOT_ICON_FILE colobot.svg) + install( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/ + ) + + # Render SVG icon in various sizes + find_program(RSVG_CONVERT rsvg-convert) + if(RSVG_CONVERT) + foreach(PNGSIZE "48" "32" "16") + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}) + add_custom_target(resize_icon_${PNGSIZE} ALL + COMMAND ${RSVG_CONVERT} -w ${PNGSIZE} -h ${PNGSIZE} ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} + > ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png + ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${PNGSIZE}x${PNGSIZE}/apps/ + ) + endforeach() + endif() + + # Create manpage from pod-formatted file + find_program(POD2MAN pod2man) + if(POD2MAN) + set(COLOBOT_MANPAGE_SECTION 6) + + macro(podman) + cmake_parse_arguments(PM "" "PODFILE;LOCALE;" "" ${ARGN}) + if(PM_LOCALE) + # This copes with the fact that english has no "/LANG" in the paths and filenames. + set(SLASHLOCALE /${PM_LOCALE}) + endif() + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE} + COMMAND ${POD2MAN} ARGS --section=${COLOBOT_MANPAGE_SECTION} + --center="Colobot" --stderr --utf8 + --release="${COLOBOT_VERSION_FULL}" + ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE} + ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} + COMMENT "Create ${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} manpage" + ) + add_custom_target(man${PM_LOCALE} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}) + + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man${SLASHLOCALE}/man${COLOBOT_MANPAGE_SECTION}/ ) + + add_dependencies(man man${PM_LOCALE}) + endmacro() + + # Create the english manpage + podman(PODFILE colobot.pod) + + endif() + + # Translate translatable material + find_program(PO4A po4a) + + if(PO4A) + add_custom_target(desktop_po4a + COMMAND ${PO4A} po4a.cfg + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + add_dependencies(desktopfile desktop_po4a) + + if(POD2MAN) + add_custom_target(man_po4a + COMMAND ${PO4A} po4a.cfg + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + add_dependencies(man man_po4a) + file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po) + string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO}) + foreach(LOCALE ${LINGUAS}) + podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE}) + add_dependencies(man${PM_LOCALE} man_po4a) + endforeach() + endif() + endif() + else() # if(NOT PLATFORM_WINDOWS) - set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0") - configure_file(colobot.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/colobot.rc) + set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0") + configure_file(colobot.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/colobot.rc) endif() From d8762fdd8dcfcf9ac62704547c669be15e9c74bc Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 30 Oct 2013 16:38:58 +0100 Subject: [PATCH 02/20] Reorder desktop/CMakeLists.txt for more platform-specific clarity --- desktop/CMakeLists.txt | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 72417578..f7aa5f1b 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) -if(NOT PLATFORM_WINDOWS) +if(PLATFORM_LINUX) # Install Desktop Entry file set(COLOBOT_DESKTOP_FILE colobot.desktop) add_custom_command( @@ -38,12 +38,22 @@ if(NOT PLATFORM_WINDOWS) endforeach() endif() + # Translate translatable material + find_program(PO4A po4a) + if(PO4A) + add_custom_target(desktop_po4a + COMMAND ${PO4A} po4a.cfg + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + add_dependencies(desktopfile desktop_po4a) + endif() + # Create manpage from pod-formatted file find_program(POD2MAN pod2man) if(POD2MAN) set(COLOBOT_MANPAGE_SECTION 6) - macro(podman) + macro(podman) cmake_parse_arguments(PM "" "PODFILE;LOCALE;" "" ${ARGN}) if(PM_LOCALE) # This copes with the fact that english has no "/LANG" in the paths and filenames. @@ -71,19 +81,8 @@ if(NOT PLATFORM_WINDOWS) # Create the english manpage podman(PODFILE colobot.pod) - endif() - - # Translate translatable material - find_program(PO4A po4a) - - if(PO4A) - add_custom_target(desktop_po4a - COMMAND ${PO4A} po4a.cfg - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - add_dependencies(desktopfile desktop_po4a) - - if(POD2MAN) + if(PO4A) + # Translate the manpage to other languages add_custom_target(man_po4a COMMAND ${PO4A} po4a.cfg WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -97,8 +96,9 @@ if(NOT PLATFORM_WINDOWS) endforeach() endif() endif() +endif(PLATFORM_LINUX) -else() # if(NOT PLATFORM_WINDOWS) +if(PLATFORM_WINDOWS) set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0") configure_file(colobot.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/colobot.rc) -endif() +endif(PLATFORM_WINDOWS) From 96383279321d0e467f18e570f6c84915010dea8f Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 30 Oct 2013 17:05:29 +0100 Subject: [PATCH 03/20] Drop redundant custom_target for po4a --- desktop/CMakeLists.txt | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index f7aa5f1b..be886e50 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -83,16 +83,12 @@ if(PLATFORM_LINUX) if(PO4A) # Translate the manpage to other languages - add_custom_target(man_po4a - COMMAND ${PO4A} po4a.cfg - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - add_dependencies(man man_po4a) + add_dependencies(man desktop_po4a) file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po) string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO}) foreach(LOCALE ${LINGUAS}) podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE}) - add_dependencies(man${PM_LOCALE} man_po4a) + add_dependencies(man${PM_LOCALE} desktop_po4a) endforeach() endif() endif() From 11dd911faf9763382431162985b8363a39ffe481 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 30 Oct 2013 17:08:12 +0100 Subject: [PATCH 04/20] Under MacOSX, generate an Info.plist --- desktop/CMakeLists.txt | 7 +++++++ desktop/Info.plist.cmake | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 desktop/Info.plist.cmake diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index be886e50..3bf1011b 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -94,6 +94,13 @@ if(PLATFORM_LINUX) endif() endif(PLATFORM_LINUX) +if(PLATFORM_MACOSX) + configure_file(Info.plist.cmake ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Info.plist + DESTINATION ${CMAKE_INSTALL_PREFIX}/Contents/ + ) +endif(PLATFORM_MACOSX) + if(PLATFORM_WINDOWS) set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0") configure_file(colobot.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/colobot.rc) diff --git a/desktop/Info.plist.cmake b/desktop/Info.plist.cmake new file mode 100644 index 00000000..21149090 --- /dev/null +++ b/desktop/Info.plist.cmake @@ -0,0 +1,27 @@ + + + + + CFBundleInfoDictionaryVersion + 6.0 + CFBundleDevelopmentRegion + English + + CFBundleDisplayName + Colobot + CFBundleExecutable + colobot + CFBundleIconFile + Colobot + CFBundleIdentifier + info.colobot.colobot + CFBundleName + Colobot + CFBundlePackageType + APPL + CFBundleSignature + cbot + CFBundleVersion + @COLOBOT_VERSION_FULL@ + + From 68d9a72357016206db6578e0137b3e8227865fbd Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 30 Oct 2013 17:18:53 +0100 Subject: [PATCH 05/20] Generate an icns icon on Mac OSX --- desktop/CMakeLists.txt | 57 +++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 3bf1011b..6dc3d1cb 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -1,5 +1,45 @@ cmake_minimum_required(VERSION 2.8) +set(COLOBOT_ICON_FILE colobot.svg) + +# Render SVG icon in various sizes +find_program(RSVG_CONVERT rsvg-convert) +if(RSVG_CONVERT AND (PLATFORM_LINUX OR PLATFORM_MACOSX)) + add_custom_target(png-icons ALL) + foreach(PNGSIZE 512 256 128 48 32 16) + add_custom_command( + OUTPUT ${PNGSIZE}/colobot.png + COMMAND mkdir -p ${PNGSIZE} + COMMAND ${RSVG_CONVERT} -w ${PNGSIZE} -h ${PNGSIZE} ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} > ${PNGSIZE}/colobot.png + ) + add_custom_target(png-icon-${PNGSIZE} ALL DEPENDS ${PNGSIZE}/colobot.png) + add_dependencies(png-icons png-icon-${PNGSIZE}) + + if(PLATFORM_LINUX) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${PNGSIZE}x${PNGSIZE}/apps/ + ) + endif() + # Prepare the ICNS icon generation + list(APPEND ICNS_SRCS "${PNGSIZE}/colobot.png") + endforeach() + + # Pack icon for Mac OS + find_program(PNG2ICNS png2icns) + if(PNG2ICNS AND PLATFORM_MACOSX) + add_custom_command(OUTPUT Colobot.icns + COMMAND ${PNG2ICNS} Colobot.icns ${ICNS_SRCS} + DEPENDS png-icons + ) + add_custom_target(icns-icon ALL DEPENDS Colobot.icns) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Colobot.icns + DESTINATION ${CMAKE_INSTALL_PREFIX}/Contents/Resources/ + ) + endif() + +endif() + if(PLATFORM_LINUX) # Install Desktop Entry file set(COLOBOT_DESKTOP_FILE colobot.desktop) @@ -16,28 +56,11 @@ if(PLATFORM_LINUX) ) # Install Icon - set(COLOBOT_ICON_FILE colobot.svg) install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/ ) - # Render SVG icon in various sizes - find_program(RSVG_CONVERT rsvg-convert) - if(RSVG_CONVERT) - foreach(PNGSIZE "48" "32" "16") - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}) - add_custom_target(resize_icon_${PNGSIZE} ALL - COMMAND ${RSVG_CONVERT} -w ${PNGSIZE} -h ${PNGSIZE} ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE} - > ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png - ) - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${PNGSIZE}x${PNGSIZE}/apps/ - ) - endforeach() - endif() - # Translate translatable material find_program(PO4A po4a) if(PO4A) From 8f7f56f1eae2998b9431e07a3ed0ea7765eb19ba Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 30 Oct 2013 17:27:05 +0100 Subject: [PATCH 06/20] On Mac OS X, write colobot.ini and savegames to Application Support directories --- src/CMakeLists.txt | 3 ++ src/app/system.cpp | 4 +++ src/app/system_macosx.cpp | 60 +++++++++++++++++++++++++++++++++++++++ src/app/system_macosx.h | 36 +++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 src/app/system_macosx.cpp create mode 100644 src/app/system_macosx.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2fab853d..9a6dba11 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,9 @@ if(PLATFORM_WINDOWS) set(SYSTEM_CPP_MODULE "system_windows.cpp") elseif(PLATFORM_LINUX) set(SYSTEM_CPP_MODULE "system_linux.cpp") +elseif(PLATFORM_MACOSX) + set(SYSTEM_CPP_MODULE "system_macosx.cpp") + set(SYSTEM_CPP_MODULE ${SYSTEM_CPP_MODULE} "app/system_other.cpp") else() set(SYSTEM_CPP_MODULE "system_other.cpp") endif() diff --git a/src/app/system.cpp b/src/app/system.cpp index 2eb68ba0..ce694690 100644 --- a/src/app/system.cpp +++ b/src/app/system.cpp @@ -25,6 +25,8 @@ #include "app/system_windows.h" #elif defined(PLATFORM_LINUX) #include "app/system_linux.h" +#elif defined(PLATFORM_MACOSX) + #include "app/system_macosx.h" #else #include "app/system_other.h" #endif @@ -48,6 +50,8 @@ CSystemUtils* CSystemUtils::Create() m_instance = new CSystemUtilsWindows(); #elif defined(PLATFORM_LINUX) m_instance = new CSystemUtilsLinux(); +#elif defined(PLATFORM_MACOSX) + m_instance = new CSystemUtilsMacOSX(); #else m_instance = new CSystemUtilsOther(); #endif diff --git a/src/app/system_macosx.cpp b/src/app/system_macosx.cpp new file mode 100644 index 00000000..8e9608cd --- /dev/null +++ b/src/app/system_macosx.cpp @@ -0,0 +1,60 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2013, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +#include "app/system_macosx.h" + +#include "common/logger.h" + +#include + +#include + +#include + +void CSystemUtilsMacOSX::Init() +{ + // These functions are a deprecated way to get the 'Application Support' folder, but they do work, in plain C++ + FSRef ref; + OSType folderType = kApplicationSupportFolderType; + char path[PATH_MAX]; + FSFindFolder( kUserDomain, folderType, kCreateFolder, &ref ); + FSRefMakePath( &ref, reinterpret_cast(&path), PATH_MAX ); + + m_ASPath = path; + m_ASPath.append("/colobot/"); + + // Make sure the directory exists + boost::filesystem::create_directories(m_ASPath.c_str()); +} + +std::string CSystemUtilsMacOSX::GetProfileFileLocation() +{ + std::string profileFile = m_ASPath + "/colobot.ini"; + + GetLogger()->Trace("Profile file is %s\n", profileFile.c_str()); + return profileFile; +} + +std::string CSystemUtilsMacOSX::GetSavegameDirectoryLocation() +{ + std::string savegameDir = m_ASPath + "/savegame"; + boost::filesystem::create_directories(savegameDir.c_str()); + GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str()); + + return savegameDir; +} + diff --git a/src/app/system_macosx.h b/src/app/system_macosx.h new file mode 100644 index 00000000..a5c11502 --- /dev/null +++ b/src/app/system_macosx.h @@ -0,0 +1,36 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +/** + * \file app/system_macosx.h + * \brief MacOSX-specific implementation of system functions + */ + +#include "app/system.h" +#include "app/system_other.h" + +class CSystemUtilsMacOSX : public CSystemUtilsOther +{ +public: + virtual void Init() override; + + virtual std::string GetProfileFileLocation() override; + virtual std::string GetSavegameDirectoryLocation() override; +private: + std::string m_ASPath; +}; + From 17ad3e5a906c59e8d108b75a6d51cc7528dfa44d Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Thu, 31 Oct 2013 10:08:32 +0100 Subject: [PATCH 07/20] Abstract the definition of DataPath to CSystemUtils --- src/app/app.cpp | 2 +- src/app/system.cpp | 5 +++++ src/app/system.h | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index e2405b81..404c6156 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -147,7 +147,7 @@ CApplication::CApplication() m_mouseButtonsState = 0; m_trackedKeys = 0; - m_dataPath = COLOBOT_DEFAULT_DATADIR; + m_dataPath = GetSystemUtils()->GetDataPath(); m_langPath = COLOBOT_I18N_DIR; m_texPackPath = ""; diff --git a/src/app/system.cpp b/src/app/system.cpp index ce694690..90b7d205 100644 --- a/src/app/system.cpp +++ b/src/app/system.cpp @@ -192,6 +192,11 @@ float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *afte return result; } +std::string CSystemUtils::GetDataPath() +{ + return std::string(COLOBOT_DEFAULT_DATADIR); +} + std::string CSystemUtils::GetProfileFileLocation() { return std::string("colobot.ini"); diff --git a/src/app/system.h b/src/app/system.h index d22a5194..c357bff8 100644 --- a/src/app/system.h +++ b/src/app/system.h @@ -130,6 +130,9 @@ public: /** The difference is \a after - \a before. */ virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) = 0; + //! Returns the data path (containing textures, levels, helpfiles, etc) + virtual std::string GetDataPath(); + //! Returns the profile (colobot.ini) file location virtual std::string GetProfileFileLocation(); From e78d2cce18b50ed86933d05ac5bccdf4ef13d6e3 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Thu, 31 Oct 2013 10:35:43 +0100 Subject: [PATCH 08/20] On MacOSX, define the DataPath as being the Resources path in the bundle --- src/app/system_macosx.cpp | 53 +++++++++++++++++++++++++++++++++++++++ src/app/system_macosx.h | 1 + 2 files changed, 54 insertions(+) diff --git a/src/app/system_macosx.cpp b/src/app/system_macosx.cpp index 8e9608cd..d452fe60 100644 --- a/src/app/system_macosx.cpp +++ b/src/app/system_macosx.cpp @@ -21,10 +21,47 @@ #include +// MacOS-specific headers +#include #include #include +inline std::string CFStringRefToStdString(CFStringRef str) { + + std::string stdstr; + + char *fullPath; + CFStringEncoding encodingMethod = CFStringGetSystemEncoding(); + + // 1st try for English system + fullPath = const_cast(CFStringGetCStringPtr(str, encodingMethod)); + if( fullPath == NULL ) + { + // 2nd try for Japanese system + encodingMethod = kCFStringEncodingUTF8; + fullPath = const_cast(CFStringGetCStringPtr(str, encodingMethod)); + } + + // for safer operation. + if( fullPath == NULL ) + { + CFIndex length = CFStringGetLength(str); + fullPath = static_cast(malloc( length + 1 )); + + // TODO: Check boolean result of that conversion + CFStringGetCString(str, fullPath, length, kCFStringEncodingUTF8 ); + + stdstr = fullPath; + + free( fullPath ); + } + else + stdstr = fullPath; + + return stdstr; +} + void CSystemUtilsMacOSX::Init() { // These functions are a deprecated way to get the 'Application Support' folder, but they do work, in plain C++ @@ -41,6 +78,22 @@ void CSystemUtilsMacOSX::Init() boost::filesystem::create_directories(m_ASPath.c_str()); } +std::string CSystemUtilsMacOSX::GetDataPath() +{ + std::string dataPath; + // Get the Resources bundle URL + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFURLRef resourcesURL = CFBundleCopyBundleURL(mainBundle); + CFStringRef str = CFURLCopyFileSystemPath( resourcesURL, kCFURLPOSIXPathStyle ); + CFRelease(resourcesURL); + + dataPath = CFStringRefToStdString(str); + dataPath += "/Contents/Resources"; + GetLogger()->Trace("dataPath is %s\n", dataPath.c_str()); + + return dataPath; +} + std::string CSystemUtilsMacOSX::GetProfileFileLocation() { std::string profileFile = m_ASPath + "/colobot.ini"; diff --git a/src/app/system_macosx.h b/src/app/system_macosx.h index a5c11502..c2b9a412 100644 --- a/src/app/system_macosx.h +++ b/src/app/system_macosx.h @@ -28,6 +28,7 @@ class CSystemUtilsMacOSX : public CSystemUtilsOther public: virtual void Init() override; + virtual std::string GetDataPath() override; virtual std::string GetProfileFileLocation() override; virtual std::string GetSavegameDirectoryLocation() override; private: From 93727a3fdf543d5699f676772e32311fe8383254 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Thu, 31 Oct 2013 11:10:45 +0100 Subject: [PATCH 09/20] On MacOSX, don't cache the Data, Sound and Music paths As users can potentially move the bundle around, it doesn't make sense to cache these (It would probably make sense to drop this caching on all architectures, but it's only on MacOSX where it hurts most) --- src/app/app.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/app/app.cpp b/src/app/app.cpp index 404c6156..56931489 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -423,7 +423,10 @@ bool CApplication::Create() return false; } +#if !defined(PLATFORM_MACOSX) + // On Mac OSX, the bundle can potentially change place, it doesn't make sense to cache it to the configuration file GetProfile().SetLocalProfileString("Resources", "Data", m_dataPath); +#endif SetLanguage(m_language); @@ -437,12 +440,16 @@ bool CApplication::Create() m_sound->Create(true); +#if !defined(PLATFORM_MACOSX) + // On Mac OSX, the bundle can potentially change place, it doesn't make sense to cache it to the configuration file + // Cache sound files if (defaultValues) { GetProfile().SetLocalProfileString("Resources", "Sound", GetDataSubdirPath(DIR_SOUND)); GetProfile().SetLocalProfileString("Resources", "Music", GetDataSubdirPath(DIR_MUSIC)); } +#endif if (!m_customDataPath && GetProfile().GetLocalProfileString("Resources", "Sound", path)) { From b32f87bac7cde826db2502422b0696c0d08f0822 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Thu, 31 Oct 2013 11:29:52 +0100 Subject: [PATCH 10/20] Abstract the definition of LangPath to CSystemUtils --- src/app/app.cpp | 2 +- src/app/system.cpp | 7 ++++++- src/app/system.h | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/app.cpp b/src/app/app.cpp index 56931489..ce973351 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -148,7 +148,7 @@ CApplication::CApplication() m_trackedKeys = 0; m_dataPath = GetSystemUtils()->GetDataPath(); - m_langPath = COLOBOT_I18N_DIR; + m_langPath = GetSystemUtils()->GetLangPath(); m_texPackPath = ""; m_runSceneName = ""; diff --git a/src/app/system.cpp b/src/app/system.cpp index 90b7d205..eaa9e4c9 100644 --- a/src/app/system.cpp +++ b/src/app/system.cpp @@ -194,7 +194,12 @@ float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *afte std::string CSystemUtils::GetDataPath() { - return std::string(COLOBOT_DEFAULT_DATADIR); + return COLOBOT_DEFAULT_DATADIR; +} + +std::string CSystemUtils::GetLangPath() +{ + return COLOBOT_I18N_DIR; } std::string CSystemUtils::GetProfileFileLocation() diff --git a/src/app/system.h b/src/app/system.h index c357bff8..c2125fe5 100644 --- a/src/app/system.h +++ b/src/app/system.h @@ -133,6 +133,9 @@ public: //! Returns the data path (containing textures, levels, helpfiles, etc) virtual std::string GetDataPath(); + //! Returns the translations path + virtual std::string GetLangPath(); + //! Returns the profile (colobot.ini) file location virtual std::string GetProfileFileLocation(); From aeefdbd1bed4d0670b1e860e900eebb9d70b3543 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Fri, 8 Nov 2013 10:41:50 +0100 Subject: [PATCH 11/20] On MacOSX, define the LangPath as being i18n in the Resources path of the bundle --- src/app/system_macosx.cpp | 19 +++++++++++-------- src/app/system_macosx.h | 2 ++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/app/system_macosx.cpp b/src/app/system_macosx.cpp index d452fe60..68f5c79f 100644 --- a/src/app/system_macosx.cpp +++ b/src/app/system_macosx.cpp @@ -76,22 +76,25 @@ void CSystemUtilsMacOSX::Init() // Make sure the directory exists boost::filesystem::create_directories(m_ASPath.c_str()); -} -std::string CSystemUtilsMacOSX::GetDataPath() -{ - std::string dataPath; // Get the Resources bundle URL CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef resourcesURL = CFBundleCopyBundleURL(mainBundle); CFStringRef str = CFURLCopyFileSystemPath( resourcesURL, kCFURLPOSIXPathStyle ); CFRelease(resourcesURL); - dataPath = CFStringRefToStdString(str); - dataPath += "/Contents/Resources"; - GetLogger()->Trace("dataPath is %s\n", dataPath.c_str()); + m_dataPath = CFStringRefToStdString(str); + m_dataPath += "/Contents/Resources"; +} - return dataPath; +std::string CSystemUtilsMacOSX::GetDataPath() +{ + return m_dataPath; +} + +std::string CSystemUtilsMacOSX::GetLangPath() +{ + return m_dataPath + "/i18n"; } std::string CSystemUtilsMacOSX::GetProfileFileLocation() diff --git a/src/app/system_macosx.h b/src/app/system_macosx.h index c2b9a412..b6a044bc 100644 --- a/src/app/system_macosx.h +++ b/src/app/system_macosx.h @@ -29,9 +29,11 @@ public: virtual void Init() override; virtual std::string GetDataPath() override; + virtual std::string GetLangPath() override; virtual std::string GetProfileFileLocation() override; virtual std::string GetSavegameDirectoryLocation() override; private: std::string m_ASPath; + std::string m_dataPath; }; From ffdba25411e544efd04b51c54f8b23cdd518b554 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Thu, 31 Oct 2013 11:56:32 +0100 Subject: [PATCH 12/20] Add MacOSX bundle-specific installation paths --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43b4a8fe..9af0aefc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,6 +309,12 @@ if(PLATFORM_WINDOWS) set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory") set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory") endif() +elseif(PLATFORM_MACOSX) + set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/Contents/MacOS CACHE PATH "Colobot binary directory") + set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/Contents/libs CACHE PATH "Colobot libraries directory") + set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/Contents/Resources CACHE PATH "Colobot shared data directory") + set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/Contents/Resources/i18n CACHE PATH "Colobot translations directory") + set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/Contents/Resources/doc CACHE PATH "Colobot documentation directory") else() set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/games CACHE PATH "Colobot binary directory") set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib/colobot CACHE PATH "Colobot libraries directory") From bea84f0af4edd58e665ae510b843189c0b8c50df Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Fri, 8 Nov 2013 10:04:26 +0100 Subject: [PATCH 13/20] Don't set rpath if libCBot is compiled statically --- src/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9a6dba11..958f86cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -240,5 +240,6 @@ add_executable(colobot ${SOURCES}) target_link_libraries(colobot ${LIBS}) install(TARGETS colobot RUNTIME DESTINATION ${COLOBOT_INSTALL_BIN_DIR}) -set_target_properties(colobot PROPERTIES INSTALL_RPATH ${COLOBOT_INSTALL_LIB_DIR}) - +if(NOT CBOT_STATIC) + set_target_properties(colobot PROPERTIES INSTALL_RPATH ${COLOBOT_INSTALL_LIB_DIR}) +endif() From 6b3e6694e35eb2fe94d9b7500ea00bcacbbee6e1 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Fri, 8 Nov 2013 10:06:06 +0100 Subject: [PATCH 14/20] On MacOSX, install files to Bundle-specific directories --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9af0aefc..1ca364ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,11 +310,11 @@ if(PLATFORM_WINDOWS) set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory") endif() elseif(PLATFORM_MACOSX) - set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/Contents/MacOS CACHE PATH "Colobot binary directory") - set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/Contents/libs CACHE PATH "Colobot libraries directory") - set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/Contents/Resources CACHE PATH "Colobot shared data directory") - set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/Contents/Resources/i18n CACHE PATH "Colobot translations directory") - set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/Contents/Resources/doc CACHE PATH "Colobot documentation directory") + set(COLOBOT_INSTALL_BIN_DIR ../MacOS CACHE STRING "Colobot binary directory") + set(COLOBOT_INSTALL_LIB_DIR ../MacOS CACHE STRING "Colobot libraries directory") + set(COLOBOT_INSTALL_DATA_DIR . CACHE STRING "Colobot shared data directory") + set(COLOBOT_INSTALL_I18N_DIR i18n CACHE SRING "Colobot translations directory") + set(COLOBOT_INSTALL_DOC_DIR doc CACHE STRING "Colobot documentation directory") else() set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/games CACHE PATH "Colobot binary directory") set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib/colobot CACHE PATH "Colobot libraries directory") From fda831d991708af79a8719d404662f97e497e095 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Fri, 8 Nov 2013 16:52:42 +0100 Subject: [PATCH 15/20] Add MacOSX Bundle and Windows NSIS installer - Add two images from screenshots or existing data textures to brand the NSIS installer --- desktop/CMakeLists.txt | 62 ++++++++++++++++++++++++++++++---- desktop/colobot_nsis.bmp | Bin 0 -> 9744 bytes desktop/colobot_nsis_left.bmp | Bin 0 -> 103048 bytes 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 desktop/colobot_nsis.bmp create mode 100644 desktop/colobot_nsis_left.bmp diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 6dc3d1cb..9fa0c5e5 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -33,9 +33,6 @@ if(RSVG_CONVERT AND (PLATFORM_LINUX OR PLATFORM_MACOSX)) DEPENDS png-icons ) add_custom_target(icns-icon ALL DEPENDS Colobot.icns) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Colobot.icns - DESTINATION ${CMAKE_INSTALL_PREFIX}/Contents/Resources/ - ) endif() endif() @@ -119,12 +116,65 @@ endif(PLATFORM_LINUX) if(PLATFORM_MACOSX) configure_file(Info.plist.cmake ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Info.plist - DESTINATION ${CMAKE_INSTALL_PREFIX}/Contents/ - ) endif(PLATFORM_MACOSX) if(PLATFORM_WINDOWS) set(COLOBOT_VERSION_4COMMAS "${COLOBOT_VERSION_MAJOR},${COLOBOT_VERSION_MINOR},${COLOBOT_VERSION_REVISION},0") configure_file(colobot.rc.cmake ${CMAKE_CURRENT_BINARY_DIR}/colobot.rc) endif(PLATFORM_WINDOWS) + + +## +# Packaging +## +set(CPACK_BUNDLE_NAME "Colobot") +set(CPACK_PACKAGE_FILE_NAME "colobot-${COLOBOT_VERSION_FULL}") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../README.md") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Colobot - Colonize with Bots") +set(CPACK_PACKAGE_VENDOR "Polish Portal of Colobot") + +set(CPACK_PACKAGE_VERSION_MAJOR ${COLOBOT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${COLOBOT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${COLOBOT_VERSION_REVISION}) + +if(PLATFORM_WINDOWS) + set(CPACK_STRIP_FILES TRUE) + + # Don't version the install directory, and allow overwriting + set(CPACK_PACKAGE_INSTALL_DIRECTORY "Colobot") + set(CPACK_NSIS_DEFINES "SetOverwrite on\nBrandingText \\\"Colobot ${COLOBOT_VERSION_CODENAME} (${COLOBOT_VERSION_FULL})\\\"") + # Install the executable directly in Program Files/Colobot/ + set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") + set(CPACK_PACKAGE_EXECUTABLES "colobot" "Colobot ${COLOBOT_VERSION_CODENAME}") + + # Branding + ## Installation and uninstallation icons + set(CPACK_NSIS_MUI_ICON ${CMAKE_CURRENT_SOURCE_DIR}/colobot.ico) + set(CPACK_NSIS_MUI_UNIICON ${CMAKE_CURRENT_SOURCE_DIR}/colobot.ico) + ## Header and Left banner images + set(CPACK_PACKAGE_ICON "") + set(CPACK_NSIS_INSTALLER_ICON_CODE "!define MUI_HEADERIMAGE_BITMAP \\\"${CMAKE_CURRENT_SOURCE_DIR}/colobot_nsis.bmp\\\" + !define MUI_WELCOMEFINISHPAGE_BITMAP \\\"${CMAKE_CURRENT_SOURCE_DIR}/colobot_nsis_left.bmp\\\"") + + ## Allow to directly run Colobot at the end of the installation + set(CPACK_NSIS_MUI_FINISHPAGE_RUN "colobot.exe") + + ## TODO: Find a way to have no license prompt. Until that, display the GPL-3 + set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE.txt) + +elseif(PLATFORM_MACOSX) + set(CPACK_GENERATOR "Bundle") + set(CPACK_BUNDLE_ICON ${CMAKE_CURRENT_BINARY_DIR}/Colobot.icns) + set(CPACK_PACKAGE_ICON ${CMAKE_CURRENT_BINARY_DIR}/Colobot.icns) + set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) + + set(CPACK_BINARY_DRAGNDROP ON) + + install(CODE " + include(BundleUtilities) + message(STATUS \"fixup_bundle(\${CMAKE_INSTALL_PREFIX}/${COLOBOT_INSTALL_BIN_DIR}/colobot/\") + fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${COLOBOT_INSTALL_BIN_DIR}/colobot\" \"\" \"\") + ") +endif() + +include(CPack) diff --git a/desktop/colobot_nsis.bmp b/desktop/colobot_nsis.bmp new file mode 100644 index 0000000000000000000000000000000000000000..529a0cf7b12becd699a6997a0229b51745417a1c GIT binary patch literal 9744 zcmZ9R!HeWbdd0((L8^5v82h$m8tA@<6R#Y<84g$ zp|&RlDX2X8Wbmo?;7OP$S_%0N^q$Qes>te#G4ww$1|>+TgAelWeW9%BaVWpcjH*oO z>3uI=d=dGVfBT1j;;jAo?>l$KyMH78g7`fb+u#4|kDdFYKL}xeczF8KIUerIFT)GZ zyd}PLzx(gsx#mAt&Od(S2Esji8KH-Uh zaBt`no)`%Cjy~aufp8z_6P_3dH_#_MF%Zt(gXbP3_waKM9{PkQ2Esk2Pk3S=+%x)w zCkDd3rcZccAlw`JgeL~Vy`xWfVj$cH`h+J2!VUBZPYikw3Xp+g00-}hfpCxM6P_3d z_l!Q_iGgsh=@Xt92=|6Q;faB8@8}br7zp=)KH-T$?+4x!!#Cd$ybgax{3G%2#5bHD zWfPvTG`^uvcw!*jJNkqt2Eu)yPk3U``+@g_bC0;kN8IBh?(z}$NuThBiROO? z_aDFgt&L&MU=M)k9U*+Y@)Q->q2*cAMO7T%#BuDavaG7g>k*ecmAufa`o527S)OKD z+I3mZ`z-64lj(FinM^OwlPt=btk2H*f0`y~n&o`poFnbhjBnB5OQCVLk}H+f>e%1J z@8i4M^?twJgDuO8C{MejOS>k`ep7;oLm%ylGN90NOx8eim3(WIM+0-Yv5FS4kJBHdwc_s(VEB3{R9Q0;{)&+@7-bZc2( z#$w0oGw}#1<=U=Mn#R^N9avy$XaDJRsb<%nv?mi|Y?ifYc9OQ~dDb+|?yPBee9_MO ztPs`3m>$6rus$LqCD*%$ulO$B#{vefA}h)=;$t}}w6uvMao)CF({jmu8+mXY|%jx7~3Safx*`zy9`l9JlL_~^7 zTUu0E)Mqn*2o@nkq3I7js;#PHe@_}A%=kJzjf$L9+L5Ay5tY(PZk65?Xl-EVfQ^(s zaMw;q;L-F5X-%fHx}HoXDZ+0__xbsG!3_flvSy%}0V(3S7gyhbL&!)v_V>5zQC`F8 zsbol4vp20n{~tGD1Km#8zCFmyUfZmnO@BN^@{{R_o=+y{Kb)O6>Aaes&u0CiTKGlP zFZvWvf(0Z!Ojn@O;HELWDu08%?r#seKRrzo_|W*ZgQsRESQ<~Xk0A?Pi`2$Uw%xSe zZ=V|)96}ypFN-S6s=BVdf9tESt4hG&ORy}3%A(#HWAX?a_olCSy&io6T!6}z%g|B{ zHw^+E;ZNk&+QSHnP&5W}z1i*s3q)pJ)5QYDX7z1NI5=jQv(b}_k} zO7)l16X4YVTW;%m4qbKSuR*mSiK z-7eErX~vaVUy1=GpC)HXio(>|B+1L(xq83ZUqTYNrawns)5UDE*w&l6T0j_-K^J^2 z=JGBHY%bvo5`z%V7J{X*Sgw%0?0#L3!aqGVe~?Fz$wCuRFc?_Ldz>sw6IoEA=d0JNVr-9>(tzhb=RIfNNo0+&K#zB+EI z{dRLCRDf$IN3+Rv17XlbV>m7r9nR7*6>;+&?lVXGoZWP08k2YFsJ!OK_4ZCU=TCYoku;lkM-*yo0=Ck4`@v~Q^XN7ftpo2#^sYBITgsdQcWyO4gGDqc?(r9%~&{u*@ z0*q9W#57|JrsNx?Nkujs!S(8up-NJWV&@<-i>mkgeRP!-`_1iUznCtz*adEXD|IdP z5L-It#+P6zhtbnHe8H7Ge>AYM=7TQyvPwte(bR?NX{N9&jUcy=61Qu2Nh-Q5jmTaO zYc0)tPeD@V(T)Kr+drvi49LlJK^kexua}FZ!4fb|Ok1FO9lZdCTn2$vm8lEHKH_V2 z75HM5K(>^hMjn1m_z0=s|5qFcERj*DeC<%ZXV~~WYGzvuYddS_3-pCg2-h|4Rn-e) zORNYOQ07k!kR~F?deE0@9P;Sb@mS|j-=ChASLlm!yCj>a3fm$_D(`WO-7d+Du0R>H zqy{7Qg{73fzNz4g5xGVD)7kZ8lFVlFjhV!k+CBoD_q6!YC@*Q#c z^?EF$g=@Y-T(Sw>QN@g>^cP37 z=@g@|G^&{R2-R$XnnGQu(o5!LP9ce*WltI@zv8&Q(|8=~)zXS+c`AjF=W5&>t1`a^ z7t5Wiem-B#0jEr6A(1#GVnbq{KQ#zUW-*)o{BqJVZJSL}ZB3WO~sd#iG&bCgCwnHgb`#AP*wBt`?5ifGN+V>O`>X?dKJ$8#l-bsD&O z>Ie$8J$$8UzFK+jt9b-pSQz!Hp%OB*j|4I&vILA$49j2K;uF_?sY2EGGG<64Yaw%r zfXws-V@4P5#j4g*2E=Qi^6>mVKA0WR2>3NV}kLBz5r#JTuhhqb^@rk{<;=p z8jgUHxEQEG?_o@06p~jUOvub9zQ@f^JoR79Q;o-4J?cGTI+>WO)?qXXl@79I-ldWFR724$OoW9>2Us_nhe8^W*YLAn z&a0KTMFs;hW>voKBZ{m-aP3 zsx(w85kA>LC>$WD&Z2&x)QR^+HWjS)|61x_SsBkAiR@O2w+QCc>0TC6YXv--mMb!M~REX2XbtFzSDl zFPDHIJEm`fDn9Z1HiQgYNQK+%}n@9)k+$Af?U#ISb)Wc*fi*ctilw?nXMs7pf)Z>WI#;Ve98oAY<41w9j!R5 zC>%}V!BZu9L}nU;tANZLpKTLW_oGoT9)J1+JL#s^76sWxVcx@RW#!I#Af572HZjDN z!P52#9k#{T(*f6L69M05K23TRtHu_oBw4U!gqh+kg%BoG<9I~hkR@cQC-yvs;h&z5 zH(M=5yR6sRs#;N0lhgfhS810MSDj0}guxza7HTT#ARA1s?Rd6pWCl313 zU<`DLwxBReq^@^t%SX0-4-2Bx)A4lVV^a&4WY69+4R2tDRWUy9DSp&c-f%!3n|0dL zam_;($NP&HQyk3blJL2*RBwEl;7wXmmtwB*Xyc4cIXD})Cm`&XzZ%bHFWU04eIJ;; zVXJ_7M+G3;vRWar7n!`ET`+jrg0?+F%VQwxa3Xdyq07djsxR3+C;}*{%bdanr08PB zE&r0SDv|5j3JU6+a5_uFMza<0O@&PFcWV_`VbP$|Md{g#i;D|c1dDs=tBF72OXpbD z@nRBSg~?HNFLHP`$v;&J$>{tke==NVtH*+6z8dx?KKnJNGEjz3q^c+cJ?`)KclZYR z!$Wvt7pei)#aTy2wXNwKt~$2w&QY_=Dw$d>0bLxL6~!3XRD{V|*_r+bmbnDB8p<#7 zc>ej}#P$lOsvlLS>7$etdypA4>5B>REIB)q-&2R}O!XfD5?y{7&x@MTI2JiZl_)cJ z0F}UrFpbGDAWO-f;ppSLnz=~EI{eEEX{8k<*}b@ID$i_B_#y5$Y5}agRja~{hEC_Qx|;w>A@%LtZ^-} zcnG{;i8f@$?+)6(MC@l5$=L<o;C7mOKJJy{YP@yvw{^laOR2dU&$KiXAJa zLn4va3RuUIeeekg8~*thI+4!GBj(-(Ous&`ZlVkmHar9Ut7TDpHVO>FT(Ra0hwqMW z0Lqd!RE6RzR5^x;69meXLLHVytMCyFS7UpkW~0gKuNQyCiK&(jNvM}fqrZGwwStdErk7;bm+0QV-#o4%JVd7!g;FB!POkC3Av5ir|V$<%$OO6zP z8S8fa6V8^F&X^nIJR&PBIrz0hnUcK3kEu&)Fn}SEoK&EgVdB+&>;+56_Uj?bglYuF znYk2$5+ni#zuGzgB>OvR*~Lp*8Wml};#fk}ewq=co3at$m%0@E@|EZ8Nmv#^1u|nw zZ|pH9QWvxF#pw<|E9{5QGTmZbp^qxi1#?Tyk6P7{c9lk4#@dh0K=mR4R*nU751eWh z!?Ryn{<&%pf%68G6ktM!lzKDzo4#xNZM$XAVJo5dA2ukVlQj2Uz-v+HMlQ z%vaZY_<|1Z6M2}@I5AxoM$#BpRVta1?%z=8dpHx6YvZGrCM(5|3rekjd*G&;{imfLVR7(|`*5 zvIS9=at<-|-9aLCdS2|zoExW4&YoO6dBPTPkIB4`Z*FgHInn$2JvVBT7RYonIt@*O zaa^KFV22cPCTn3ln!fORtE^04RQP-QSpomT)BfK-T_T{%CnigI}(+e32UDZL>Vo81Vi_`O*X$ zaX$Zp&i{zh(4&i^?@OrCP3DV@ z|9kLrj^xYkoqM|cKJqzUZawE{zQVDf&+;gF`*h|NEa$Q1t!YnP?x?RcpL@E}^1@}s zzS+GFIl8Auj~Cm+7oJBpcJW#y3cu4=q=q`L`1hLaxzvn1!{XbFp6hJ!MaDjxBlkM` zTR&^g=wtB}spIIizT6!19XvX-r_Valt66ULb@}1dapd+_^L=KW%YWZxm-xM(uaJ}f zvU{^B>Kf*_zTEIi-*)vJoxNP?Xq>gKFlG~bzd660Xg<;G_46}-zBA>}9_MFqri+Z_ z(e!;jE!f`2_CvOkiq#ApzeIZ`pJ=iDyK6^2d4w9?|Ei1dFG9C~sD0d|W%F^3jiy+9 zJ$u_P$MLhsdHs%(Fm^?1uU&EJ`wg$L)baDm`>~f=n$A=0<#^gWESC8k3zu5cT6^8% zE9GcgnWekS)L4ipl{%35YRZ-Qf~ngw^3T6-w8a~aMF|#eO_E=f1nUJ%4-?J@5N@-^zR`>WMwo&xhZdS%%c;rM>@ ziH1i1@=$BA(f?}Qt95#mCmK%R*!gdY@GD+d;Y3PbRUvKAE%t4rm0IXUT{NjpC8PGL z(}m>R)4Ja0U^Z4Wm|eE)1EpKZSt!wU#kN%P`H2c(_m=xvl)%zQ~iLH`>R=W`~ex) zIR&2ud|hmv?~*ascgr--wMDSG$-g47BDg0!C;38VFf*s^SomBd4u3W7bCRTf7X`0| zBle6l)#N`H@5`KvmA4ILQPLN>t5*(XDi$7%%x$}vTd;CCJ11G*vMqHnHOYQpYiVA=jHOZ>wl|EOo=m>XjVtOQ+Xd>^@OH1o*A?^%spTepk#hf}!u`m! z{Z0JV`zM$9hq5EN_7sjMQ@wIQ@2A4DThdUdJ~EVrgHg|a_Ak{!%#&1}t9 z_g?Jr`fi>m6kP;!)uUP5?&9TUccpPsy?r#*e44`Y=82ob7kdWazqe*Dc3;XK$8q+h zwxtF$Bf0$;-L`_DnB6 zF--U22v(=>2FtSH#Gou!`YfUYVR1#^rjyL#{pRQHXO}xb}*YvmH3pR zsZ(KHa}yUjL@as^wfb?Rip?~NF`?>ge+82C%OtrXgmaq%DKHzvIe#I`&#jr&Nmvy0 z*=La)f`=M_r#ct)`mf%yKhv&xK5$-MZDJ6<#^8x3bW4HAV zXJ20TWIxMLwih0X@p5;>7x?4n%6&wS4#(pDz>sWc3^WFMQ@>x=zh>>4nq_+;t)bnK zJ>eChP56%^H#-+w5n2&so+DZmJsOhvdUR?}l8zcJEf(OjCyQ~kNxGxC@g|m4h$0`D zTsLt~v$E8#tOSI7jw(nxl|2Yqc0l{5_$bAXtW0g!h2p+33;83DF1Ii&hWD)yEgZ zsil}6RehHy$#0YPeq&&drN}+uz2Uu~qv5kLkQ6=IEI&`)WBE&$*RYn{3X79-&vnyt#=k5_ z_F>RIM3v&P>2WrPc=YUZRC^NtWO(Maa14n&rXaQuC0B}nQzl^zEtBq;h%(9K0i*ay zM6teCG{|02n<6s{P^1=xA}zUCG#F*kWa)4#9K-#%#r0Tx8&R(N>dOhl9IqcF)lbq( zqMQRsyHD4lNvf9bT*Gy5Or|7PBA=Dj=r-FaO0i-!9r zKQIZ!%Ccp@=B#1(OkUqOVJ&oK2cn0c)D&;U=Qr8qJ`@H zS_n#;KPFa}xVf`F&Qd3z97+L0E%mYbD3*gNSa)Kr*w|3M`sCbM{3IG8AKV;S5k`bT z>kGZOv9qxwQD10W(92TP^4$D%y!d)%Zjt-!FGmsfUvjx+Xp3$JJ@t|x31#vh*AA_| zXq%^A9}%j1B7MoBOwF>3xsK$__?Y+@Xl_iDpPndKkyk9rLKT`4s}I*l>LXl-`n(z3 zXGRP;Qgao_2H7%Ui)&MaWp{L9+r+jHW3g~U$cHkT(r{9aK zEu^>^THF-g6?r2zu`Q6C*tR}$OE`u?l0KIv4Y6XwV)UGO+G)YCWoQtdoG7jYziBn*DG}4zHMsGfQSoWvyh()76?fknX;J4(bT~XL83pHn# z*qGQDC^Z`YY3Fag|L*r+>H0D-Pk!gC>_$j9FF zDq7H&$$nJyo~};a68>r8r(L&q*2n&EGp&0J)rKKR+C|B78F<3pZwL3kTk;pt6WSui zT@Z4blgS_^J4z`1aUC(E^f1^Pf>H3JB_Q z$FB29nyI3DF*LbH9XCT<%RzqyG`UywsI6C$M6oQ6L*8@oTEmej`ufqIiK`Hq{h2w* zF(BxPpn#D_yd=G#DMF6~#gmE`#k%i)Yi86Z_EO?|5N*c4Yw$#FuSOdZtt0jlotm^e z{Cezz#C7Sr(n)ldCDLUnf4VevDq%=2Ezo4q8W&~fUen>|%ry+1p|k8W#y}NbGP>8| zcr1ecDQMF6UM`xiqTdMp(CIlzT-(WXBr96Rg+M3r?v04tH~!&9)uc@idCvO{e{A?; z^Vb4j3;soDY`D?a>s_VAv&!4&?e*>ix4MaAV*fB-``OrYG-gb^{%q*O=&JPd-Op$5 z%J|dqOiwnRX-=0WPsMk{wnx{)y6uQ_ndto)wFc#49L-kB(M($=)+K8;iH+idNy~j z%plujsJwGZ+mz-h%jDe*v zJEgZzs*C?--ojF}&Cy?+oA_GwgoP_pccoS(FXSHYf2sfF{(Jf>dmqllGxU=OND?g9 zqgXTxvZ2pn$mLcZZjo>}=50HQlRNU7@e*X|S{Oxog5+oXB>H%x`+N!SU3M7+u_4be z$^h!$j?W?dzkotJCAn2LN99D#^~sX0!dKTL#a_&PyK-w8Nq*h)VCllrziY1R{JZ8m zCQ1u@(!z-+Ca-MUn|&_xc5dyOzhCqJ;95-OnuojTB}Zt@{3_7tHqn&K7X z3>k7SCg1-Irj{1r^=8#{Kw*zeKN6!JQJ9tUKl-yNtTW42a3nP?gW~-LJcB4^9yuy0 zU?mlq@En@>K=rE)b)D~i>zT>VRO5g0gVoPezaBoH z3$DDD*9zBkt@*3ow{k1ft(iq&IX+dIDoy)QH1ceZ*|F!Uj?JNdxmgZO9J z6?`l6F|Ji#$i0wxEBB|K7czIH;@M5P74Vd8nU&dt3sFrhF9=66)G~y~ zLN@f6THdymX=rjyZZ`z=lKk7{7p83WKI*BOQ8nXHOjpmSo=OifgML5$lS5AEgT{qacZvgHn9I`PG8*O7nQJ+N4la1@(F!so$O09orox z&)v~2VG<_e7eLERjZw!bhVE9Z$8krm9HSp)dBIyX^Ap(g+hx}`eq1@=xmXsOIb6OC zXQaCzwE`-7i6gz|%*eCMveSn{>_ zAHVe~a=uq*zcTy%X8&}%Oz}@?p6;*FI1p0FSAcGvrXVCns#S>aKY+t_bu%BcIu{i-#i=iw`@u8&92N<_CDGFU;BRzl5h63 zAsb@6VcXlM{;ViDi5>Qme2yR}r7_ePiFIvQx-Ygbb_``-6n$aAhy8cf-#O*ZnmcQ5 zt+}i68)HB9eCoM`|Jt!m(Rr6V7qNuPSZc;z@+=tpW2!k;M!e~n7b{nTrKDA>9GYJ-<&t+npsBzXTryFdvhPHdc6PdLGm7lqt(j!e0nte%&-ww z9b2;T`^w?Zp2=e;kNt*}TI=%?^1tIk;y8vJBehG`m_ta{xd4`nQEs#gr&!4J-mz;@ z?gi%?!I$TyMv9&tj;o!M9vSYJ!m0h9fQZuIxZ(B-Wf#jXm3;#gl_WJ*Ga+5uRhvfX zstwi7udPP8wzg_&)zoWi=T}u%)JzDKEI_#d1w%`#3&y5P(i5aqq^s_!O;_D8)+s`? zWU&@uOTs@Md*4`9?~T~Ykmp4y$6Xxh7v8Sht1$dz$|q9>z05bSE05#; z^jjj!LVudRxa!`iFEzg0_)_D4nf2f1{L7sGW$wSu`p3rWXFfmW)|%N1kM->9Mx0so zR?o3jJvrJn`qbD)41O*>7GyKXV1nS-)qU5FAARtnz&+P5m_Os%8P`s|P_ww=-U;_k zcyhwpirXp{SM*oiCM8`vf9f}9R?eE#SUHn4uLaEzC{le6s~g7NrlsVzlG`Sr=#ZaE z82h`Y_MWMrX=(M|k{_2W=9(32t73=r@8juzn*PMp zf3E#??XRnTUA4CAw%UG{sp+X*Gp?U;{miPFl`|(bg6WKFYeN;G2@57rl|m83`X``( zSbx>ywU5`Xty){Lw&Y%DkL<`fJvKBUG@)i}_1Nl?>Iv6YTw6u0f9xBaLZ7FeaX)lv zh|YuDC3S-W;>|I{aDyfpLWnJ>?HdB(42 zJT>*D886NF{nQ&u9+`3`;g=quQ)tO2^K=yOFG<%mqidX}m4 zYpNGk?4t`D3Rq;fs4C>OaxHt+^vIpjQ7Q z(?`mNaqMaOOmeD7tIa}vwCV*Vp$S#Bl{5ZS|5p85(}%pn-Vwy85y`fPyn|)*W!lbD zYRZtYgrt}!ap=SrPLZuC+}9_S*Uua&6PBtui4sC@#;Bumh& zSc0fIT)x@AA+j^NBPzYR?5E%ru+Ne6Fs?M>_t%Khu6_oIH1wEk6-KP~OcV@}OWDhe zNAt7-!{*2)PTKT!=4ag%|-78Xu~PcmUn9ziYSaxfMd?`Vb{2OuHmTjm?P*p z;Iy6(oil=Oh7!w|Puw^*42D$V&!IZep$y5A9G{r_($tq~pPH~_>_zWhUw33FeBsiF ztKUp|AyNOUY|9vqyepK&WIZzUBYu-)7%jrfw69gWf1KS`V`3;Zq)Jk4(JGB~>X>>s zF6DeJWN)}AFY`HUu`IVh?g4afYU=0RYs`!fnG7^1In_ITd_ygPeZ zwRLMq8cLe=@sq_^tWGO2st&mz{>ju7Lu^>)j>uA~P&3y3GRAedR48YRA4^xy6s)1PU{y_eB{}k9?j~K0h->Rbq_-ZlkB+EoYbb zw!*HcJ{A(C?i`LrU(V35(xDO~MUJ^uM@2H1rw+Mp;qnpBkmV5RXJPK%84u;V)j;|?F?_@zG)XOOiQ;b>Dd`gC|AYFpoHhK%D5 zuR+8RPLZdwP=)2INv+ecGQ;DZKcldPX>y?p*az2T%k!egOesa?H%s6VY0*oh^>ZV0 z{EFMEm@jH!q@hn-D@t69wU&$>DR1=uasJg)k-H4?&w%xuxX)NCf1Bb{t19XF z#KU<9(R(#q_DKzSs+vfGtx6@T)X3W5$7P%{>bnS<__ z$vDG|e=S;EPgXsJcuh^BRM00ZTS zL~@KQe?PVwobE%ma|1|{rL@jVemvpF757%%TlHgMc%$g``6*5Q_vYgY%hl3yt>>nZ zcRdwE`4sPB`}E58?kzui{LY#eEk#~CgM9~Ymsd$|pz4ksOe7&YrKb8*ozik0d;U~> zBG=OST*flud9>`iQ!aU^uf@)s9zIUO- zV)gy3dCXdztEtYIQt`n%E@PYt*`=7TwC5Fmo7=CB3pM+d)PB!}via!E8bBWmu7`^C zlH!oWTP2fkrAmk%QG4GweNhN<9=A|6VjtdHE63ND_)F`XeRoyDKUTHXzt%k7cM^BJ zfF>>_bj?ImMoWquNs)P7e{cTRifX2?R-ZjBkzMRst{vjcfMd8Nr>emPM0TzyT&&%y9E z^sp}|d3bswj_Pv9{ngE<9^D+Rag*o62av3lLyqEF$k~hDqmeRIl=?Jkkt|e`B&kac zRZ>%;O5033TQIK7nnGF!r;#Krd3-%dj;}w6>4MVmTs^N#P>ae{X46X z{&7)=EkKYGN*rfVo*e3QKFNaP;@YBWUtnCQ$^SdhVo`Ra=#X@Hie{~47eJFss8o)l zwI`n=ol*rkAD64AQ+i5~86wF#QHIpWk~U6u+8Q(*=||u8+*Mu*B_5#W$O_k= zo5Z4_rBYNq>NMxkn*CzUh8C~oQ*E?qa-=$4 z1xvwMmXy}x`8zJp zx4Z)1!ZNnfJENlNm!dt=c}F}V*=S3Tx-=v;Vsi=SX>6ft)tV2e5|x(R5kZRMVYSUZ z-W}nhX!}kO#u_C)=*#q_6seuzSunhU-8V?yL|x|dGgBI8?ET4FdC|l2k7TB7&CqyG z7fYczZc6u@Esbp1(9fwqJT4TeNcue!YdBZcYCcJH*t4p&6wn&bap zJE~q3j_kR35t<}JQbh5x49j(zL9Z6v?Ns)&^1CYUth}!B^u%YY4@^5D4BZ@=^Dw$V zZ-_7_Y{F0_Ec#U4sXAy86icB-bCrpAwCe98IEPoCER`xv+lum(V>A9dOvz98!ZwY? z6VHyrJk_6lKJ8iFAN-nA&P#l_0X9l@~F2Tu4kn9Hi6MtDc&mY_IZDdydc?m9}# zs%Tq$vWzL?#Gj7VsXLZji7T^5?u*_Q-zMiteICYzjdN~CkC~%zmU#X5PkZI&r#o)` z-%8_KVm)hA1uXAtWSYlsd%{Tx1)c=O7*Xi1|6>;Bz28YOjY2*C| zM0d|rGj2Fbv=u{AXj@O&J_&d2J1m7GmWgjs+*C z`I1fF-@Ww6T}M_NS-NY*EC2Zy|9R1m_T0W=#ktPovwqpwT<=z1b08k18V^o;u=>E{ zldx6(vuJbyBj2nk1Neoyt8&97qnOv~*-TGIO)#xwA_)E!ovs@$J14wo|A(uxQv4?g?^?cOsJw3n|ZD!$k(JyIZTCeku}t|WIa(QS*aF_@iQbB z;VHM{ZLQl`4Ce?#i=$tcG~sHuDdb5nI;sR01vUrqOr*%U=(!l5P07-c>`2aQo7*<8 z1y2oZsc5NKSkcmiUr<&g4M%!BK1~Nt*72XLdj@J0w%|yXN|Cf)s0^d8mO0XQ%gOP; zv}Y$Xb7Uz+1d`tn>nDEsr1tHV{-H)ZN0Y@lVmDRSxbiEALWWrJ;UfG(9zTN{*5q%+b32%qi(W|%5lj9tt^~DC zMgfIGqc(d8(#VY@KQh#~%#0TsLXTIt?g~!%lw2NE7|NOBI;K^?NX0_pS}qpAjGt0Y92FssmCdDJs@??2(Ph>NE!U^0tDv`hL zeOs5*B%UyfV^lWIk>P0UBhfK)^k(Q-wDfaZHR4>dWNi#n;po~Q{haK@;zw@*<(OXw zTE7vL$mC+`Iv(r08j(9$SroFV7R{vWWp17&uwr+?J@H`So?~%DUg)paYX-b-u&Vqu z=oFqK32zWNmpIpXHjcZ{qfLR6mNnC+<;eL&6c*HsEKU7PwAN_D<#ye5ol&1k%{ux5 zj=aCe#o;r@Y4I9sF8}HNCKqyJZjf%({He@ zVc`xZ&ufS!1UsSu2X^iu_0vV0o zgA$aS(c(22CY$6CYq_ako~8P+lg+XQuJ}Qbu+`V5fuPpVqIm%7e82h5DK}bb z&n}nsnZ(pSeo&SJ+#U5o|IvZYjn+Z z4wg%8S!eEv`KBvQu%&MJ3P+>IJVMO9N1ZKej-x`ZVb+tmM%ltrws%?=&i+m|TkQPf z{o~C!!Wn1{HskX`S#3$p1l&Q1d;GO<{6ZP;JTYoK?g4S+nCD}c@Eqm}5L}%G$L!o> z1vuWb=H+$eEw8E`(OPT9@4?T<@H8&uM+jGdvFvE3HEOWk#WA1fjtHArStE;{@_9k2_ z)qBQCZn6CHlZ97OS9zIhJ~O$Zt+sb{W_9LbPe&SWE66Fw+t&OZdQ^_yz=^t^;5BV~ zBb!4N`0PPG%X8ZZec=ckJ5trzb~(DXJL0hnupnriHXQ z)>f!Z_2xQu@d3^^;TRFS=O*u&bj@6o9(VLxOuvP>$mBR!M@ z$JGApNcY@SJD!1@7LKpUQ)u~Ap=;WXMSDWWq7`lWxjD2Mt+-bFK9w~weB48+A?l|p zv^8pJr(jLt0FDK<(RwwyR8_!9wu42Y7zTOAW1r(u8ICz-*a6#=4pFmaNnmsM?#%G2 zx9?ul*0tcT8dZP8a-S`E@}BS731}0cT~y+04a`k$!xNf*$O%XncyAO7a=l|fDE35Hz^Wp9!-s*gf+lv_UK^IU8%o(oseb}q)x zqj;7YpVjp1`?h6NvG%tMxz96I!Yza%IksBYwQNqJ6R|_I8M(aGl{4~tWcz||way&1 ziY4~GWQ^OGd1g%Kxj#v@306JQJ%o6%7xl-J%F{;@9jS_iFSabk@1F1*sEStn)=c;A z_3w_-HOuQ-d^;YoI{J}T>MPbt*l9=3JD`?LSHZXkmvT3K2uJR+S>9^lAp1Q@f| zHDk6CWeK9p3Q-*SG4qgO&EfV^oVuGi)_lXDSaxHRMN}SdD^$*hcvxAEJ)3>-O*MO> z@N!vb2$mNQHp41A(sNRHPYa^RHndrA4~?BqgCp|BJdSumeS4;>|6kUvS$K5JteUp^ zy}=`ivkCrUR~5Mz?VYo+1$c_Q^LCDsd?JR^RSwCABwIsqC+~4na@9|2D$79Gwsng+ zYO5q1mQJQ)vvkP0#@q~%ry*+1O^tMKQ;y+Q^!prz;^rpLMJrn7;{8js)B86*HqZD^V zl9p0sdy=I8a};5sl%sU3u0oOC!qCefHrq7a`x-q?W#+3BaTkT(a-v~VcnC3uSs=4L zUSp_8uFkfn@YEGN+u}T)U+g|EW`KQovsHVlPu}`q?7C~shYP|IT zxwFe=a1A54U}b-Q|9wMQz7J;(o;f!sm0t72y8ix`)~#Lhu`lUKg5_*HXDZgORpI~ z9(goc-TTCSYccPob?>zCsRDc=27U!z@~J0y)8lvo*llZeMO|tPFEYhus63a2-9^@N ztwDxv(#yjx|5#8@o1^6Q=#8`cN7P zQ0B@0IY}o|AYv9_+}BpiOra&!*u~oJHo?j<=6p=-wPU z7p++~l%;RBlqf#Z7rwQIzs$UZ`(7@27u4P}bM2b7&|UoE0Zsh4V$b*6n^ z9ZTg`V)z+i#i#A>Mchvr;e_Hp;oA~R9t+=P?B&{aPrApW^YcTvkVR-ShJvokDz;9z;1K#rJ`ImlW)u-&cY+ zOb&IA;C+6~zj;?qOow-`qJe3L|Mu$bp%2A(d3CZg^)>;l%XMK#7;0fQW z;T`uQ=V88c4%ht3lLN?sDq5Oh)eBZ$>_(f_Ib#^(u{Q=EEx&PWdg>3q8Agv9d&{Xz z^Yot@+`Tg5d8-~z+7BIxrDwiS(-2|iY%Edj(cOCo4aj~AC>nCbmSLX8sEv4okweUB z+oAUw#T8F%yO*^cB6(xRyPC))b#=)LehCx==YTlJEa`j?KQz&_yuR z?J#t&C)}7H$=+n0<>5_uM!DSIV{5XIsKy0}1vW?UlpgsKLwbK%_M8;&GufJ}S=pX!#k1OLR}N&jSFJ1QK~?zVbR+(`?f&kHHs(uc z??tYk^M5XQyb;f7f!7RG91HFa&$}r-_2K%K$RexO(2rGGjm_#1k=)Q*9w93f*e&i@ zmMvvk_Yv8E<;x;ky2C9Pmpq)lNBS&e2upN$nEEb)ax~+x$j}yCT%@i>jZ#ZF-}atl zKh}J)cNyn>tVd$BXI_Qc6OQA`!cp|#B3kEQ)uE0g)EH)aSZq=l8uc*lmM7^Ac$G%Z z0(vZy-Bs&uyzS4(ENj7W(wu9)-9Mwcq9IBP)S?tQu4JICu<#=riy7C^wHN6S%r-_g zMmLh6t8_=Y!}!M%nSf$Oe#XG71g`X6un9imLA zB!uUsq$g|+v_{Sej^40x zPSWaCu=HVUl6t|mxr=vi%XKC@(GsU;s7Max(*6Hs-G5)Wcxt-#MbF}r1r?ivF_#*J zk1*mG8E%Yhg3g4aDvjUd(j3;Y7=j$;lb;Zb?Ucf)oiW&}Sf{E=6{eq@qi3ERMXPyQ za#Z!j#~OpXBj|HP#)BR*T!X^fpCY}Pa=c&rXk1d2(EU_Gj@E)u5gzzHl-- zuWe1+bM6$&kTcX`Yi{jI0o8&|f$T$mzES#2N znB@;ugVu&&K<3 z{j|Le*Y!ep&wKasuobJtn<+tZ=#DQ6{K?;o`>;Bzjn>C z2pK}R!j0NvAwQlMQY5+MV$~eWC$|wA+hvuVu-uKR!q`R>Ly>yaad1Qrq+MLZ9Cl{R zA!XUQ(TEO5*{rUQt@G9+3DkpY<8ygfddqUWzBQCvon@?U&y4i+rQ*`AZcn{Gn@Y6# zsm0+PWzW?N;^|BJyPU71C4JHR{PaM2AeUa#4~FEpi`Fc0fRwBv49T&DEX`aQf-;oF zsKEm6qEybqSZo9MsU15Ul_44L!o7mZN&KJG*l;uIGed{t)sD%Ybe~F($L=bN!h515 zIDq$Q%k_Z_Gw@^@*O?=6KVmhm8lbNknvp^(&{ur=qhdHilWza->Y6Mz5hgS6#yl-W03ONs3 zh#B5HGJ^Ncw^;2irQaRx@tJ1=Jzu{f*o3#;ZVvr+`T*Vsu-|i`W-fYt``3`;%j-Vq zYzdPSqHS0*7P3Ks9V1$()@Zx5SrP$@_^!Ar&U|tS?U;oe&3q26srXK8vjH3#uNj@~ z){0CCNfNz`wUU-*#MoBy;R1fNS{4kIfuU!si&;j9_mgy_@V-9u@}T7rsc36YS0pbY zcSLX5%8NOl#gTi7MOW7IH;Md(-3wEC0tcq$@Z|dOzAfRm@g9N!^iF(SUk!$9*F4dG z<8AwJ{hH5xbF!8V@Rm>?ES+johUx>sI~t3yU}>aV=z*^khn?87uq0K?kH0PycgA*r zBQjho%dy(*LXHHpKN$w5}&Z}?Bv$apZtBelJ!f^4;S3CuD^Hf znqRHEr*Vx3zhMSNQ547+&nFq7JZ-cg#1dm3jpfwavS_zhGq)i}wOkWpx^2$OxV~NwgWu;wUQGWhMro-lgL z(%aH=@J_>Rxc`Z2qGfO7m4@tvO8vbtIF|1V9>nkFDsW%;$-36STfqTu06mX2Rp0m? zt}Wn-;XSk7@oWn3jPJ5EMQyRZR9*`x#=qenwm#SvL z9V}IuSZfpdQk>%OLUwAGjgslpA~D7yBwgHWg89@8`DHd`wC=5QvJ9Eq>MZXP>&sT) ziZ$K>9Ku~FxU#_O)p#FObWYNTwKqn~Q+?>YKxUMwuDB?_G(PU#$6w6U?Zvwz{6XS_#Ll>`L;hTgX9m`tIFooiv567Ps++Jw-^H%zZmaByZnC)*7u{pdKv<>fdmp35t zt&MY11Kk7NgJ^%VD8-A2&A;_+4(r|H=o5;448NI#Wq%3}`B7-nO>a;CaLj(s#qz^l z!pCA`7)tFyV26@Zf-+9UZ4|B>W3b|IOf*Y-MW?jG*h zmYvJqGF)wycdX#OKX`LjdN4N#hQmGl96(NU{TzL6z$H8%=sfPf>%kSVJ+a>gjzfL> zalOCS`nC6qpnBZ%sdsZ=Jr!g{WW!NO2?MuXD^<01TcadP?sjwrUr@zdGF=+o5#JGC z51OyXp%zi2Q+qc(E)z?3v2&(3qCG_FEYuz1pxGCuHpyI>gC$%}kBt(6w~DO7bNrLI z2L~*DFVuG?=b-m?uzOA$-}%~syCZN1q{VO!uECZk(Km?JQ{VDW` z?|2!1C!h4r21!P3URB_}J3OY-2T1ur#s)eC}gWVQIT)n+t@ zv*6mZaF!>hA*Y*NrWD(SBkvuNJ8`^cCRVfz^$e*cqn$W_7{n{uyoz`<+Ls>cS+kHF zc_oW?0Bi#{vP70h_dch)34XU9yMGkiBSh${=|0ps00eHpzI znLXtlh})G5eg}%5LVLV6%_q<;#&rZfg>D-NK8DQaP2YNWEb7GAE%Yau3bp7c>@b)e zj#FF0LzbxD<65M~^J6j!Tok9Yi7^uiS9d7S#>kO6R=JhspCm*0FdcsOz9`>ZF}P=!>W(BmAk z*#SnR$LK)XEbEn_ED>LbH4!-yUr(PArIPawsQZIXSi3C4T8T5AhZF0CBKNc-t~F=9 zl^s4gjzTt9Dpa3D8ugJDIq8`a6*fwn4ElsZ!4PY0j4q8o?E5nmwI5Hl9{@$_Qq_3L zv$huZdP9Lqk?)9I4MpPqo@g`f^yVG&bCX+p{_>{Bu>FnlmKDBZ<;JluRBjBN4;~5c z=sMg*yWC}I3_eguvesJ24~($f_&KVP$|Nhph`cT91#RWNQ@G;{BuH&%{7mN#jO~CH zY1Pyu^eEbMtMZBz$pr)%Qy8tK&jh4s`-oJ?6LAF)*YVWuwLgVDDsrY`Eumhyw`s(C z2|YH)Jp*_{*(&rOj(9R-7t|)vFTNTadqQ}^0{+oT#P5rEul%_EBI#c?df<5Jy;GRU%BX6GWL_{XA@K)EgAQsqMgED zYtU2jE`ilqFm2lsoVW1qWW~a{E#++uAsiVaFFlYemhc-9B_uXeEy_fq3y4vVoTDn_ zx{N>T1xP@&>6x*_~ z44Hr(uhr|}sHL<>Z_369_YgxYX$hMc-7{Yxm0fYD3x(qw@GcQP#g6@YX6Z(&)epOsZODvq&^oX9 zW-5StLqV?E;kj6Oj8_HGPjhfuPw=-j7h%_f9zHJ^Z%z-*MZQf-K8n^g?+O^|?#Qlg zt5~=v*x53aIUAqY_Ij)VeK`DnMooIdGl>bQ>oV76&Y(_0f@h7qEH0$NT9X$UkrbK1 z+sTq0uuOV7jq}(CE!bLO$R9S!v$!297?LCTv7Tz%9OE$xJ>f^oZ-n-6HAj|d4cwf1d}H2c{v@l17z|2e!tZV+)}@z^`@ z+=QOc`8X|kF7B`2hC9XE)5jv$eEXW4R^xYU$@CkD!7*6!MxGNXJV*5V+ij)s{0U2` zC#fA0f;=YC8C1C*tvRZa7F!0*fuFU`PHZJ!5OxjAmwjxHiyzcAI{9t1b+L4KNUj4< zNskcUCW`h$PoNgiI^iS z*T*&mk9$6b-)qM2wvI&~tUgiqobLs2T#Tq2$L|yNqSeA4$kkcCSv+{t`S9F@tCItG zUpvnkvKZYXH4hTt!ki9o>|i^W{FH*KPi^r~;-T0f&?J{z!pu)tZ>#o+!=2Yp>pu1)#$`NYM2)y?DVbaA8ogM1hB8_6t=?aH-mc#h8IOAsPu1NqsWI@@ zltFM@GPb(v7#OaWn7luGF1|O|`R&!oA^d9a>nW;-cF48|k3!Cp#1X24BzIt`TA(r{ znTHU;>Ekp@p>@#bo#|X3e+X>W!(xOgh>2Z;^_i{-@P|7@e?3$Rx(TjJod{K~X)(1p zVhP4XOR?}R(MQW3!yEFB;R+?68CBxj5`4RC7{4Z1Ja*o~K3wlY+d75cP$L>YhTm}X zW)kTQ!jFE9F%>ZZbt5}608!3C9V91K3x^$3MYKh=OIk5`Qemt$^n)x(=P{Sz*bdnX z*ske85wgisuNa@WsHYtjapH1M;tBf;Dqwo zW$4|(8+4zaGFZ-c)C{3*@^O8;MCsMZZK>O)F0SqI&6J3u^jK5WRT!v#NRs@-{$O() zXS`i1yh#M{R_v3JWLAbmPIt`$Nh*jos}Y(c$=NBiUFwjEJB0bCyTmWbI4N3M#5v%0 zqEYS-^+aDFqceKXchLue0_SkJGx~arQCo;gdv(3U6=+MmI_rWOVK3~_WM(U|4xFJ( z?pfqGaY)D4P5T`>+zg#tmaYdaJv=RkBveoBCvBQf2dGT|q; z7h0;u z@F_a}5OjuhpdMx)w?x*9=14%}C$qOh+(yoTQsgJC{f+n{|8oCzo*v)s@Q%)BQJW^; zqQHv43jAtQRRcbV17u}o7tq-D_zz+a;s2H>>7DAFm7SG61n))vbqFyUp0IOP27V3G zpiaeMFT%aE4E#w#32}^s)bq(aWh={d9U&`w;Mw97w#GSSR1+Vnm7SVX;&$Sb-Gjvem_6We%XieQ%d}>d~lMD|@gA!V2~HxhArXhvM54rF;M{bx1vdA@<94 zSYNSzcuCc&i62Vtu&4{;LIzxfCY7qo$sOz9`&mxwQX$AXu`Q&YkF66Hy~?r)IX3+v zBgih%oN$Hq$d#(%6*781o(1yZknw|_@pUjnn+%>@GYI-e{WgB1C=bU$ONPfnJ?X1x zl^DaBB^Q5=pHNWevzW&S0nZK#rB2A2wML}K(!!Ckus&QP&8>7TEEhXxOocsXXv5SE z3il>d`Td|mHWnW;<2?N*LyVcVWXLs6b1TW8Xj9Z6d?3_^zAh+`eKfqM0e9X7hHuqnHeD(k3bZr`?V&diSM@oB4$)(`JdB>HAnvpee?6rUmG(CBnbcdUsd~fbO7~L!GSsp-w-1ny5;+F-EAD zA~&u>vZ6d;K~0b=8LJYh)Q4c(6ENqLReNkp#dbXyBVQd?CM0UxCz*=&RB1+WoU7}A zps*xAu|CWH;mWe!MIz4$$2e(1hl}vUxJ}UyJFm;I2g$?Fy8_u{Hj!nNpqJAtXWW}b2+_p&I{G$_GXtc5<2OtG z29iHOVU*N*s&=TmXA`Ho{9<>f!&t+!Ko6<&^;7l=dNL(@;Fv`R1hr6Y`tRtGbVYrZ?Mg2JG{mb+yP}|`1TBur zkoSV(x2+)fMrTF3JToubkqsaZWN!y`#Tfh$%Hf2G8ET)}LK3!M$qa-o3+A}k66&M< zvSw5i3UZKBsO7;EXbn6f~$pGEz@Tex+%WdocE$=;6*= zv$Ha=WoYuCtW_#nR8psehoN#xRfc)o8<=Tq(P@hv){$dSwq$4MsqcgTL!4#HZ5i&N zhTpU9U!wk0i?CrRk$2ZD5BG#$Pt48C!&9f{@iQ|gGg~-X`7$VxBXfp_ke&S?ikJZp zN6&=#!7(gf8e{eb-+|-Y9)A#1KY%|v)L9DuM?$1l3hhvF!b`?Z;ZtgfWlEWRsY0VH zv0!`?*D^$Cp(G%5%$V3T))G$En%Dw4l&*|T=>D;lb(D^2E!{RYOfM|3rSjc zd@n*I*&9ESxF!=64H|}g7J7RoAsm$=zww~xfgET>a*Q|z4jECk*6?^xUTL}%wyBDf znn8~op6+TxHVE}~kto=Jo7yq$*A&JQ@+9-N93%I$i3i2^DOK(VN1&994uuJil10@e z-zeisnGwYzDP9p%v|nUECN_ehgGIZ1)O3s?Pci#YUwjpF$1fc)vVi2}o~>9_u{Xd2UHXrXurE*EMM=mPL1F zIzh1)9KS0Z+hEnSIM#&3Og+R3g&U&+6aIa`{ohg+mI_MO+!rbdLARzk%D7Ts!9*ONU~--b_heX z)R?`%di7peYOb(oEP;Jvon_$-;I}b)ByoPpxvq2kM>*eRb4<_61i_G{FS812G#uG4 zj$@VjsqK*)mBUZYVUCAmUUI1G!T24qXW_+=n;_n>^~E-uwsXm=E$7d2NS|r;Mf=6J z+@qYOLt^z3vE%T9m`5t~Cv5kzH^;P_g(H2Yw1O;pSobu_VPS~;ff|JMf+4P}*!n~6 z0!86>bD$%?tpGb(X%1i z%lW@NvI6?!-N?`@+8&2Na8Ke`*HM(SN^(hghJ|*mzLB1hO5_vOdZ9+u;w;pMEmP%2 zKBs8Eux2Wby0iQl2$n%%%!la*nGs`M>I@brZ4LFA&@JdJq2J>&JulQH_sHyo>_mB( z<{Cmsi1HhC9gP*LLE0@_G^9rjN)7>j$SAbGgbW#Z@xLL`Dr%G8rtw#$m?Asg6>PPK zrFATvv5faGNG~gT_I4-sB#w5{8y@LALW+25twt&X7KRAH zyqH-HYfV+?Ct`Ev)Dm*0&2ldM9>$sT{2<1bhDIH7A~(mDbq+sE?Ylb%;K!tnpb|F#($1ddviY&;oNl+P5i=;@7RHH^}$zT|L)0Q8E7PY3ZJyE9WiJC+# zfO^;>rtO_V+k_OUDA672t_syHIL@^UG3BDvRCCNwxfEBK$P8N3UTWPRX<}_g4cm6f z4}~p%Xb%d^sp+0jmuKu zW6eD!%XKY&(y}qcC;MXA*GT1Av@ELyVVT2E+OPDBSp0a${6jGl=4 zV+>}W6TeGUgJp;#I<6E9GuW_@l3o{RQhch58TTMXEESwEt>47GORtvAN@Fgv7F`$Q z)c-+wa?P53f1*H%4T!&Dzhc8sSSy~Vg`5w|$V<4&8Y^Jmc%nC2%iIzmyP&}p z(YDCS=;jz0vc&g-<5B4GXy;j!4?&U)D@ZYqqgu4_jgD1QjpIRz5s~^}e*+^hqX-$3 z+(Gf0q9PngsTG4PMoNm-DVowFr9}!wev+U4N$ruSnTIvCwSg_fg4GAo^NH=k1}zI# z+ax9Pn{U;flEbrZgrM-{lQjak>s03P3d&(dDf;csUGbi%DK^Cz)u>-pjT*-bNA^OXZW24iFOftZBW+V7irnL%B z;V701YAn*u1u>oCr_hB8*_#aQ;C~~oz|sF9AEpMWI$MKeMy2r|1-v9aJHH@DuOOC2 z(4!AsvsE}AUg>aWJhH;3*yE_taJ2P!wsWFdG}Jg3_jI@^{t)lP*d{T?vGy%h9?s<2Zonif~EQ4hzyGu9up5Dh>_c!40cp;zM^d~yw0#&}D6g*8lP#zmB^j(c-Su#smIMwBK~bX?v3w@zlnD$(mPrdQ{}0O6rK?c zJwlD?P84{?v{IxVHO8>7jGmDcOTckF{G;Kgl*mDgvQPy=M?#nML`|5YDlM9fPq>ro zu&i?$Yp^F1+lcOTC>fyKdqC?|-^U2T>z5LP#eyvr3LmAXtT>-Ve|67!uwVJj6r-`^ zLu7~}M{SmzTGEsqpWO|QI4eYoR3po1j&CMD!W*gF94iVq-kkpaSNrZ966-~=?7IM8hhdSOa_BYjutEg zEiY)Ih>|m(oC}I*!z~YOlHM4$n>WdpxJR9;W@gEPGe?aygJEfAPwdXftsn@FLXt5? zwFphZqW7Teg&IHVJcq(qeHKGYjiN_H8K}{41WU=m`_RY3D+&CjQ#fO%K#?4I*P7It zwU=Viq7_RaQ_kaBvM%RhjMQ+=2IM)HQ|j|ndD82LIwF3E1*;ufIgHbTB`PE%!_5qJ zj@3(p<)&9gvTVu1aZens81bqRz8S~J9+J{56>_j^bM)cJ!_k$Iwg@QN9EBt(S{&m? z&MDkf+`^LOX&5 zOTP~ZVjrRl-X(>&Yh^Ixhx^YY2ZR+fi#8T4L&MEIw4Ry4o*HSXaG7q!2m}>V%hVx` znCFpRis~3I3OU$Gid&-O*h7-EYb##UvY9thjYs3hz>#)r^mrML)M5H=_D?{e=mE#Q zj1zEm3fYvUM%Cl?1h2d3^?H(Ifd-|JT451lPyy%ju1?FUtgPAaQx($x(Sq^s@N=KQ85S)O2Ndx%m)U9j(hD9Ctzi7qs>!h| zy~EO%sL`fInzUZ#=SqzBDh0Nrg_x4#o}j%RGh>S zp{Q}D2^6V9{!&b?BV#)-bSQ%14rr0~Op20wNMt#+WOw|L$RlKEQQYEiBuP*-97TZi=uKAid_eA9(kP_Y;4UbKPr)P5iOLQe3BvW_k*>f@QN?> z!k$pp+AiqX!!)Tm{M;1ThhP*bB-O4FlVQu7M6pmJ_G@}xd0!XL*fM;xwuRt%&;sM< zc*N&sxtg&%zAv)RMUiSW#Zb)Sm>@?}RE=(qRHW+huMuVXV9|jzDXJO^IWi^)AK0i4 zdG~}WZ-e+e6E$eV^m<}zXgMfFYK0jfpDVBk3`hVB<)5GIA5m3w>RhXY=#4W)h;tW@I_1yWS9r`=Tsr(|6hwg{G~>z3`2D@#alf zHJ+JoIGQ1PDa1cslLE(7keMUO-RWNOjO3_y579dwqD`Yvk9>NC^22>Ta^D^9cEm5d z4^w%T_Q=jIa@QZGz{t7#k33Az^Cqc17;+nqlbZF3X-sXzzm>=6d=iwkxIQBarx;hL zMBel7ob8>=btKcGSCkkHU-d@(5&YU64CNmlGE$79s&TJG8Hv^8m`_rA%*d1+=cPJ@ z<74U7;K(?wdSpKrW1Dh3(Df`>@_u>g<&#g%lX33h^>`3D%57ogn8&Tj5cK4naBHz>P}DO`D>)-~79C13N*@GC zT>a?U726AnEZ~Sz$nj2OK`akPRg28P$q`u(I9_AhHu#~(48`V%*M~65h*i5evd=r8 zqvR)u7r47c;_Objx1Ld!Po$ux$c{{?4y~_nv&ra`Y=N~cZo))JQC+G!-GX#%hV+wU z&%Mi*nC6|Cx+N*{9!uW2h5I0cB0mpzGCCv2fnAT!?20{%=hP@iLy~$lio8?fw|Gu+ zl&r_%$o!GYv#eSv=5b_uX0_xy%5j!hws3?ss8v&sjJ2diN{9{;H)x@p$9k}aTFA=~ zXjLXyPijvx*n&iaxurxdl{Iv2n-o>&*e+EFJ9qeTZElJ4svgn4^9|V!atic?`OybK zuh^V@Bk^#U{?Kq#lEy=Vp-piw-gTyWWVAk(I0rpmjw8v!uG1+{?8IAel9p8)|2UfC zk+{^}j=A!@3QUmz>u2bhcG)7#vF1~AC~C_bW9@lWgj=#GE8T~Da=EO-s3iO6ci=4O zCsnvn7&6nQzoGi5M%uIFWz2N4{#-L6G_JWV`M{zm+`>keYS|CNzNJJTLD}b`NUOFu zBKNlSXw=B-)D}nd_uw~Xh}0?iM&ljJa94!3Wn6kBG1T4AbQ45`m3A%J84h42VGTrki@UuxHLYHgTf;lE?Mxe{Z{(P^086vTbC7W# z>O6@U2`y5M{6yJ;e^@vpj(EvObZBvONP;4wwW=|nqjmR*SUUCCneMNg5BTdy#zzML84LgHS`p z^hQi{k2%-_K1q=DxIKDt@OvkT%EFHsBk#SGoEsT8DW2+V&b}TevAwihK>wx5IUL`e{)j^oQ2H z{?36p&U*HRAU2~n2mLwBImTz-a3~s%&|@)pGt zUl)q{dkV>U(2_q1dMwZW|E--{b6w?`=R5caNkiu@7hE_XSYLr?oH?{(Nq>+oCu=kOlZ+Tw_7;uW|0!!oa%*A$=fd@o@Qw$!)$E79{OIbyxZ z=x?Mj{)M&!Bj!Wo>Bd!*v8vYm$X=Z?>38fK#+Zawp|{9dt=N} zUZkTjw_zI+YAc*VlN?duIyB>RP&~^Roo}b1Rhwd1w>+dde!TE8JmhZ|f4lg}(kIm6 z(#MPBh!%>%@pDERv`Da!V^aKj!x5gbP;Bdiw&}N5`0P{{Q+0JDAp-uC*0_eYjd!Cc zvn<>6N{pqKLZy5Ih)J_OmlW}a0olG8+Ix5#_OINA)3gK3`T*oPi=&7*7~cOp+X_MXHf{bUT@P z_E2xSj#6ub^o*nkjw|9A^;~JBrAIE64ZeXIO@>>=9POEk^p>*i_&a1TuxRG@v}k7h zRI`qP7BhOq*dJOUs6MKY7L8U#ej-9+gaYf($`wUX7M;0b)gk9PJvNpNHJT$S;+NTb zj;#GLp0HSvZZCVR;m9b>RytCw9A(oh$?=`mH$rpCBM7z}VW%BMY)gV>n6V@O?hSoI zc6dt|p4ZN7pAl_I@k zC^A@nvLKG4`MEgWi}%6ar@Hlhs1>pn?eaGw$yP^d@#&}!qV>CQWZOjQ5zj$_qB;J? zdbEeMRR^uhp(*k~F<<43Wm%-&kPhJsVZ-!>)?zuAh2S)@+tFzN8X!+LI*3&-EV^!4V8W(dApDh{D<* zS&}4rT17GI)s>?uVobM+BDFc5dVA%6M4PmI6?s9Ex<+Jih@aqD_>xvF@ON6m7Kp%9 zYOQ0EF4t3qqKhRilN%M!tyy!wfTv}c4brO7&!XO2=G|8i9#f6t zh-ZSRM(XirlQ{Bfb=A<3u01VRBSpl5Tey(4Gip<`^@<{5iVMH-)_EWB768+P3rM-`^i=!W`(baX9bQVNlgw3T8qB` zxd|K>$PtQMB1LdKJ%d6;{tbR{<(1WcJo8qNB*p)(@)n4)4g4w9s+l=3|DMG0XVT-l z$lrblij1SC2rA^(u}dWtib0HANQON%S(quJ=Zov5yVR(r*pk*ShR`2kG<+iS9rpe) zJ7OD-DWZQE^%jf)#@pESY%|Ym{vEXMzKP#!f3w(iwPs~I9Z9bF7>fK{9Pc}U0;`5K zt9+LnPyYno(RxgZYyl@nw%y|Ca>W_d1{;pHX{(WT{jPFrv`5Hp7)^1uS&IEirCK7L z3sfGXgl)H@sD9UuGWCjkLmeVVWPvxt$O2MCf%*_pK=C@(BR-2F*kbGvYto1DTh*20 zWjyKZ(sN7=BLAi>hbA=-jvz_zxJZgKD5SU&EX5I;q+L^&WcVv`L=PcG(u-r(sxt?t zT@N`Te^i?e{ZF(nj!_H_!I8S7t?E5p?6WBm8Q)-Dq_M5NBA3lxThjlv6fsX9$=0zy z@Yy9i-{sNOux(L1j5qg_BklSPw5nYgkfa(-(fmxZ;VOg;hI)tad$#BYzEn6qy-Ik0M4JrY)KS707wBB1Mjn(^6P5TMW5v za^%*mPt%S$Dx1C!nKm>Ck}AxylOx)=M)5lGa9FN5GAh3Vg1G;M zrg(}XJs}JF7{f;4(?Ha;FNtFPJN8kSB5am5J=Ijqke-ngZ;R-Mvg1(V87T34OL#Zf z6gVC>N5vWIvFDh|GeIuds%6vij^ya<=kujMFUzuN*Q;dslc0!LQ#k(W%=>4_@y8qk zKG5TxI3h>P8e8PrNdr?Uk?IUJk|Mnv^kti--c&-1mvsjmpD%znqDskZXvHjyFYq_9 zo|&SQ2{n$;Ha4}eckVD4lA`p8=hf1#@5Iq8$2c;N1joNZl$k{V#nsh9k(&Ic(Bu2! z_{)hL!>*gG2a)C!_4p z&FE}W;;0_wwCzIBV=P1+>oi6i%411xQlgfw>yvRAc_QZ3B5`(UacjmDY17u@I7gD? zJH`16K*=sGdXgT^@z3D+^^>zFsYg)+N7f4Yk99+O$8nA|52qUY9NZMi@mxmVc{4Q=_N}c$M?kXy)*xE=9heL;@N49i^BV# z)q*RIofebh2jDo2(9oe2nI6)$X06qm^v#o>qS$Z*ZBT!a)*lq@3Db&Ak6zKOiW;>j zYiE}8n^Q{*d~au}vFC_)3?c7fVeZ3xe8`dXIxS*3qIKa2tA-vQOEuEMS7(FdE32u- z_s-xAp5S=;>}mAQusxg{*mf(hX_o%#gzegTG{wh2k}MmJh}PuzT|Pado~}Oz$KEqmlHe$2W=IxbsA7s( zRt7}tbso(({DdO0HOnR1Jc?Ogs1)N3S+whxVr|6%#c1t*esObpYbH6iie$WItx$#S zzM)9hv|EnjS}fV)fa6N&F*!a4ii|g`$sl)>RlkhiZh09aaam)W!KfeVk!oxsOv~}z z;3yK}0V0^%noEq18X(6`MdrwDVaLq7^|w$p?0o66dREv9dr5Pw0g@v9Bx8v^B4Z2I zqAvaLx!0GskC9=^F-a=UBt`zFV^QSgrpYDzT@SdPI~tX^xMs^)~VCGFNvqzP`IC5F7v5Y6IxqzJh)1sMmbNseP7&$^eeC{^h9BL(Q4>;~c4j#D= z-vSnTOp+JoFE2DC9k&&^#S!-GqPmRK7#ta`3rA2y#C{qSk@YAOCr48x$5-&Q$NM1p zkLa`cXaYxiMrxA&@m=(Tnw8WfW?0rbu15_f*A;sfJLH*UZi?Clk(}hzI}p!^FmohD zDiL{&-n7E_%y%z*xbpnc){H5p9{0#Uwq6p76i1PS9#fHTfFx~O?P&6pQe+wDGsY3^ z6!4G1am89x2Kh7yvb-fdzQqW0<{!{v_G55-4;=b&g zY1erA2t5sdDLo>4+=1iUdJlW@qaquI%xs`I`ajpH8Eujxr_?1ma(rS?gf%;33?(9x z(4sRkyA|T_!rEwKRFpWqr5MxuN3a}lJc0KviX@1lc7U29IaZQMlf5^oM%H3n*aF#e zWc`{o!_cDi_?E2N98Z%ZpKwL5_Seq*PHm4ZN7{7i@ohX$+h~pNwwFKDTIPrJkQid%NPBxZ`7M*%}BG4kxlc0OD=zOXT>Bv_iHSwff5cVmw9jY*O1kLa1{^cYb)^eEc~#b1UVpOPlY@~@#rMj5yCWQm7;M{6uS$G%lw8^`FkVR6;;fT?21<;%P4G5K6v(ZWQn0e z((4Osd@m^O#<7yjth^=p?!xa;I9i2z1jo=KX;zN3?963? z9X$KOB697*4m^it2EQj#BTd-#RHMh|Gjc{p;3 zLy;}Vr=>_n>{sx+K`$e|xL1bt>U*HXtjo|lnj?B-vY@T!XQzIO_8zE_*4y&Zvh3SB zv{hpZuq9Q_!Lr%zqdIitI;2RN*VC$lBI_+Ipg6rvPZ;zzr^iSRIHre0Yi`6EW}~bPD379WZ^F-4elB+8 z=kil>!n5I;NqF}XSPHXOQr<}L;6HzI_zWl-lbFf=Jw5P z&#*AlsU?}lwBac0o==j;8hb0x!C1+_7>c#YW=rAb;J^4j&O^)^OGy`j0HNZR{Qk4@W8joGDk6ZJ&YxaljIPnOJ_ zw*9YNoUtD7JE;sZ>erd|WTbfodgK^pK8IO#$lTkWu`;w*{OR%!qWm1zYu!$vd(#*A4Owk0%a1GJ9a=bYMo><M&863 zN1Ti{#X}Y!>1>iU?%>#y#4qk*d|75bj@KLoz<6yvz7pAE<@jB2{OYPQkQMVILvd`B z2#VlWDgFR&rl@)ZPqG9p)|IJ4w5XxLb{5`gESb9Fe|kd_t&zp?_}4)bdi+*^*E=i3WNjrBfFaTL!{{VZ(Te)yS7Xw6=O9d`_i z9%a9@Tq|#q9&OjbvC^b2rO1UTl!=-g*mvp@G@%8v{MW@lAt(CN($`LW?c}3DlA|hK zh6brg=8i8*jkal6vKTU^kR9JL_mC-7!9jJP2y zQ53b{iIF5~m%wx6=fn^MH(6^Qmdb3vF`0VmoM>x?1YH_WX+;h=D*p+Fv~acY%2TGl zMBQJW>0QzMD9Pd*}&r~PmB#~{fqS)d0I+tGvjz3sx%ef^M za)f^bIcD9AC1eS^=I>!bjd~VH6oVj+VFl8vnRoO3T~qU$)8`LufZ+s+y=|u-49jjv zhShILk5=RMF|wtX%vN3NG9tHnw%JZ zB!2Z%Z9yfoEF{6wEdijpbR8NYN0NNx^pmF_IsFLeO{=J>r-pPhL~) zTO=8=TaJ#__$(wdUN?~j{n^l@y=24Dnv^O{lGa|BDqB|`mn827$)hKao<4f|p3{6z zOV4Tr#c?$*;h#7{b&p$rqGyf|EIxpx=agfEV#H}$Ie#Y!{erMySugz|BMfZVt=RaL zpC!fP4 zW{rYn)W)ewSR8E*EmX^QpF}y$@&`QY#5VxxTG2lcHjQWct;Qw1-T(OF(&CF?d7KoB z20?Hk%W?L(D#NBC)w&3Z_+2Pbq%R~vzJLBV%k)yP1k9Ic_mBlAxzd}raI;7DKT5kM``6AMphR4ktJ5mo0%h)Aqi!25$F-iM2~ z8G_|!Xf^#T>J_#%QCxXlHqE#~t2W2S!ScB5nEH#daMwJ`SLVOD@Ho7n{Uf~yEE;ud z*I3wg1BReDHP3dzwb8TppFecI_`+1<7_}r>$$eRlg&}FCRUZb$Wl#dg-doDnJ%Z)L z{C7Z+@0fW)%1w%x^0(UbD?=K^Pm*RBV?HutjBFw zTY=)`Q(d6y$eTf^TYWc;kQkmkV+Yo zT&PHLG)caF6>sV_MZW6^#ra~5(uHC$6vz1o=FKuWZp`pnuE1*4mV=SBewq)zM7eZ$ zesjdy8%R##I0D^9k&%0gBiXC$%F)}fy{GYz)Z&n%m!0{b{gP1zab`!3^p{8QR=AV+ ze`L5F>gJ3VB+0so-es%j81cI>QFBpynCmQvDD;QC2jDmV;QSsH`$PN0ufQ|jIJPmf zHhppW%JiN&_x15vdyFGS6x^I%A1Rlc$dL?b*+Z6YVPq@gm*L1(AKSFz3g^?dn{S+z z=eSbZG3~sTv}|hjArKtl|9)z?)XcR7IJPAD%T=$Fq3V1;N8P#9pCLurGbrv2g5o%L zmrF#KPmkSz8cE_J&YShg7Z!O`s1G_SEi(g->r*Tn<|vZsB_q;QMN*A-R3!O{W0G^- z+qz7O!F5me+JK%Yno|8VRV=gJeLwz-qCfQ=NP>zRT&qy`CHifq8(LPWtC0Opvk(yQH!E~U< zmfIK9qinj`vOT2EA$@3`SwlqHX!JIb=$7i{){#GL+t8#`d0Zr+MX_T&<+y5mR_tMW zM%r}R@*EkOo#W)i>5F6m8sK#^4iBh@a)r!XE1|;!)>X?zkEJcqTrNp3H7)p(>>FO1E-k?|+l4F+p*AG2Z`jvTx zgX;;7m1XiXxqhk8ydy`G#M7vIkm<|ak*6hfyZr$uR)yN~X^JOn(+n|^p za=>LbmT^7P8?eaSuHy*nM!jV50ot;x85}{_IVl+3wg~ z^sZ85*6*xCesaBIR!33Mg?^ERk-6A%&Pk)|Q%@`~Z#Bv7nX5XF%zLiJ^_k*2`%#mK zzades*^bhG{N>DzAjz6tC7BdM zv1s{JjK<$(rnBY&UL1@vz>4e3ABi zzltqe5qxvn9FL%ezaKTz{UFJ*f0hL-MUtwdZ70WVu2t#p{(xU4JD_MSwmvmDGQ*OO zupWaUvIu*7AB`lDwqbd4ISyKKbpIKB?X)p-8AwB$)#}AdguiOWBqb3r8pt zXLqsXsCI4U;^=XnereI|QB>stlAPN&%eua)-U{mmNqR@w^)}X}2j$e~8rM|W<=hy< z+_G{^En=E2AYcJr5hLO+f($u!$He-pIH!ZNch8bz_=x7X;0hv1GOe2=?=nNEQ9d#1 z(3PL>pY?bV6vgp=^bAx*PO*NtIgK6TKN|I(_DVZd zHdoVa)A`0?)zYICNiBU@jt5(g^c!(>(P%i5nLK478L>qi8Qqc}+GtT6XIhRyQZ*Vz za&kO8zuzQ9&n-_yk26%{wdrdnDQf0u`v*@cveQQ@k<&4b#jBRBkfTO%y=mQ^Q>r7$ zb|0xlTW$U3D$Y^8;vD)0s~Zwb23_MJy{t)Z*2Ci5h6-NUx*(F|GO=&wk_k zwCk4R3^}^}vt?QJ$oz+e=Luq>NDrDNb&081(pQCLn?TSSYE!z@cM~|anQ9kfNNuZ- z?e0n(wfb6eM2Wx06!t2PAc;adFFbR3``Bpi$@vlL%8qThH*+L8s8NOUuO50e^*Hk# z)Mv&yMx>$ML~*-t1jB|RXkr_#Gf#L;(2NW-I7(fiuv8DH+NkoX{zlim1IYo$rhN`Ab-hIvj#MZ2={)D??9thSv)4koEbd7l6e4oQ^}E9V@xJD#p%NF;vwfj_{3IQGY^sDyb8#$NL}Pe zW>tyg$Te9ss;(?yYwDD>%lOOKZbwCyYi~JbiwJX{^o%(*M}KZl@1H$6_Y1tI@Z{X> z2^?MLq-W-S@Vvy#{<$M_2XMd1F|+}Yie2K`NRaA*`uv%SG*^A=?USJ? zw)Syr=D;kD#XXA_iE+=SN0MFx!Z<$T@JM!@R=scbAnw8~aJ&+KWqU3@agrWo)2w&V zFS_7(yK+oL`re8ow&z&mO0S*U2Q{9W#8D)-Do0$m=$W8D8;<-|$Be&7-;b8DLe9#J z`awf%5=ZW9dwL(3?}x`piq_)+L@DSoIWoIZOG%@~&?EdKJtH`-Y2+P97WJBAwgY=w z6=^l$jH8tTc1@1*&DC31lH0Hy=CC~5EMfB{d#;*nSjs$yQyH&)ZnTr+NQx|LF%6pXkIr@YxrW|q_Muje ztY33nN?-hh0Ch(i=IElqVAh&1$$bvw;P9i&jywHHlBO@p3!N!>)_{wsxIt%(Nc4w(2tD@p^9yF4AM^-A|fh9IeP|*^@bvD#mr#w{;v* zE31S`jUd*6Rn5_w?fe&^pwtoXj_sE;qn+oD91kGxzMJ`C>}`7*Eq$}ek@PFQwX{`H zPL7IP${;^Q-mN9YJ!gvKXidgA36dO8RL;}nj{M6t=>71#W3NZDSeaccW|T~w6pm>d zo~Gt(_hV`#$&Mqhs_c{gQHtcWC^6@-W$KYV2M1u)iY(fn^vHN?RxL+)IkV)q=9t`g z)~LTI@8-HIiq_VnIfg|Sj%`07qBZL>sLhbNHLy92(cj8pvX$6stPy$JcVB19W0F}< zQI;JZkgW(R+KStzM@>a^)1+mV4M$x&zZJ*)8`cJ|)%yyc$M|g>@>6#NpWqkQN0LD~ z?ntn#TEtzjrWAwImg}_YvD61eQME$%*oQMBe&F zS~Qnlk&`(VhUESQIfg3JZ{i7rFUV1ZcHl@gwk7X6?*W+x$FTZT1*chpqgWP_{5FY| zE%g_$z5$C^b4zBo&tg^Sjzl zliJLqbDH=03v;XlIoDC-5+ioQQJGE~VK`ro|0VQT{s!mV>>-GfOTC)BCR5x5xrQS& zNhP*xWdDU^^@T~0u_sG16zMoRDRLh?Zu`A`u7jpEBDB+Xvqj61Tj$+u_{q-Mninl6Qj_#6dc94X zVr9d*mLm1&x+SitDZA>?(Hgz}6Kom`N%Cg#j~tP~o)uVPXtHCYWAg?8~ zRp(TGl4q6_Jymvj6B<1ZBkIYvhul$#8Zloi8XVa=G0fddWRCDxIL~NpRDMJXgD71oa&8BbSYJ5uPHf`$H3~=iuySRcvVv0m zb}*OUV~W}^x91qSuJg1(U5_`Z?``M8rdV_u~j?Dj9 z8hY(~PqO_+^H3u=Zgd=>%((h!S<3raNRdu3uIn@>hV(Yvt2J3zrXGE_8p3fjuD4GC zCuRhZdksl?naU(pj*#FOJN9B@)G#caQ9SMh`--)sqwx%xgD>>FR z4Zn++Pd#oFHRkmuE9F0;q`RuK!FRG`l1EkGPII*IAQ|nJYIBo)lOsK5_Ry8HC9_ac zr35>Nuav*Uc_&5A)oq}>_~v}G);t|&d?i#RG?7<1k=}-ng7c7v$xq)&E_tqeqV|g` z+^g~bn^am+8;?_n^0;KJ--Iv*5yjg@b39POPGIb4A#-hrd{F`$_I#wb#e&=p$`b$7rK zgsd6U%DYBVO>{A*A-%dRt+s8Id>)dXQtNaCdQ4{NwT4sgyg9~aP+Zd;=bde0ES{W6 z4dygyk|eErz){ypH7d4nsp#>F?v|A%FOn+kr}U3ShdIZ+6xHb%q{wTuFS9DGK5H_R zN0OD>gt@e7OtG*17=x$rf~CcGo7RmisBmn~cF2)u>pRZ--EwTkm4+HC$5%&{{kDtvudza{@=6AJ3JeU`H62#*t$Gd5%`2ELk2GqZ>WaEjX5^>BKS4eQ?IDT^B2q z8bPtS0{P4ErURCdTRw{sk$YxwbrU&qUst;Q#ol-1xPkGSc&3FJ3M0M=94%UWlQ0q zzc0ZNGqwB6tuxp*yI7jxn zSBl^m{?YX~UM0V6NoAhRb)?gN7we)OjZ4W9_kw%rj+Hzy<(Zd~*T!kfv8qw_TiSGD zDM%(o^}}ji;W#{cp;(R|`o_6*9E+FKIZ}_zey{O;UQt?xoM+y{c+H62#_XgOx)Q&f z&+j&OcdX-zB&@lmhzR1=+SFxHBc9G|`(e%T z{`IN7^pAbX<7g@k@*EXF5{LY=G2Re?Fjzl^&wJaaAk z+O0})oJdkVuC!(pYq6!6cAbh$9ndT1b=A2%vo)Vrb5`JJ`;IHLO5)SX#OGv=-v`OH zLt7Xpow|>!&a2mS5=YakpJrUo(sRj?oU9?uj>GWvDVBf_SwWe?sMcQ>zJYSA!HLg#wHk;hAj%QVuz5lqfyuu`z?b)^M zrq1n!HzYqjSC1+BlbRNYEM+rm7q!s z2{JuL?xW*KiXV)wRg&I5|5{UNvZw?MF;APkiX4coHEP+0@@}E#SeN$A@+n#tK9fu< z7su||ykUKe>dJd1rBQF`0Yi_;k>9A0Yp2M89)qKNWaStcd9iB{*wEGP&QWpNcVfWt z+UWM^){tXo=@U4jEr=YMo13IR`TQlH2ILZTco5H6q9%URV**PN0SqF*idT#iZ0zBc*{@5Q>xzaYKXTJy1& z+^44Chn6aqPLU*c03#z<%<_OJ9-V&}Z@cRBSQHuU&kaY{?~-LMQEyj9|0@_e=3tG~ zsBQdBxvJv9e7(U@SMT}IBE6>ch`pO(jc0kyxxRAYxbh$=U+Fuz2D`qEJ`s9I)N$gz z#$Vz5xS!moIl`vR5hP{V>hr4<#S$8{7JH6H(4 zju{-GN0X$Nyd7#Bp+7ncp3T(rpXnd-P0f|2Ip$}LIg>e(Ft3v>x2#WX@T{Y>6en^t zOYv*-pV#o7VZ}Vvc2(C`J(YD|mn~fa-iW}r{qwDW{Dp;KnVOqY1ggKFq~Er{ zIy~h!>%yztGwb;7Pqrr`dhx0II7^-}%NDMP_kb}&SBWd;v%+n$Msm&e=r8`_KLD!9 B=EVR2 literal 0 HcmV?d00001 From 642034eda9cd0071a32974ce8cd9b333a95a8d74 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Tue, 12 Nov 2013 11:32:41 +0100 Subject: [PATCH 16/20] Update the MXE install README to document the creation of the installer --- INSTALL-MXE.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/INSTALL-MXE.md b/INSTALL-MXE.md index f12ed888..47b6bcc8 100644 --- a/INSTALL-MXE.md +++ b/INSTALL-MXE.md @@ -58,12 +58,18 @@ To cross-compile Colobot using MXE: 4. Now `cd` to directory with colobot sources. To cross-compile a CMake project, you have to specify a CMake toolchain file. MXE has such file in MXE's directory: `usr/i686-pc-mingw32/share/cmake/mxe-conf.cmake` - Toolchain file is specified thus:`cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/mxe-conf.cmake .` + Toolchain file is specified that way: `cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/mxe-conf.cmake .` CMake files in Colobot should detect that MXE is being used and they will modify flags, paths, etc. as required. You should not run into any problems. *Note:* you may also want to use a separate out-of-source build directory for MXE. -5. `make` should now compile the game with the resulting exe in `bin/colobot.exe`. +5. `make` should now compile the game with the resulting executable as `colobot.exe`. The exe is linked against all libraries *statically*, so there are no dependencies on external DLLs. However, the resulting binary will be huge with all these libraries, so you might want to do: `strip bin/colobot.exe`. + +6. If you want to create a Colobot installer, you need to additionally build 'nsis' + in MXE. Then you can create the NSIS installer that way: + `PATH=/path/to/mxe/binaries/:$PATH make package` This will create a versionned + colobot-$version.exe installer that will install Colobot in system directories, + add a shortcut in the start menu and setup an uninstaller. From ba8dcc887f3ece99c7ee48cc0b5400ddd180b415 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 13 Nov 2013 14:04:11 +0100 Subject: [PATCH 17/20] Add an INSTALL file for MacOSX --- INSTALL-MacOSX.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 INSTALL-MacOSX.md diff --git a/INSTALL-MacOSX.md b/INSTALL-MacOSX.md new file mode 100644 index 00000000..862fda47 --- /dev/null +++ b/INSTALL-MacOSX.md @@ -0,0 +1,60 @@ +# Compile and install instructions on MacOSX + +To compile Colobot on MacOS X, you need to first get all tools, all +building dependencies (including the recompilation of some of them), and +finally compile colobot. + +* Install git from [git-osx-installer on Google Code](https://code.google.com/p/git-osx-installer/) +* Install Xcode through the Mac AppStore +* Accept the Xcode license + + xcodebuild -license + +* Download and install Apple's Command Line Developer Tools from within Xcode (Preferences, Download, Components) +* Download and install [Mac Ports](http://www.macports.org/install.php#requirements) +* Install GCC 4.8 through MacPorts + + sudo port install gcc48 + +* Install all colobot build depends + + sudo port install cmake libsdl libsdl_image libsdl_ttf boost libsndfile glew libicns librsvg + + > [po4a](http://po4a.alioth.debian.org/) should also be installed for the translation of levels, but the [MacPorts' Portfiles have not been accepted yet](http://trac.macports.org/ticket/41227). + +* Rebuild libtiff locally + + This is needed because of the following error: + + > libtiff.5.dylib (for architecture x86_64) because larger updated load + > commands do not fit (the program must be relinked, and you may need to + > use -headerpad or -headerpad_max_install_names) + + MacPorts changed the default linker flag, a simple local rebuild suffices: + + sudo port -ns upgrade --force tiff + +* Rebuild boost with the same gcc that we want to use + + This is needed because boost is compiled against Mac's system libstdc++ + which is older than the one used by gcc-4.8 + + sudo port -ns upgrade --force boost configure.compiler=macports-gcc-4.8 + +* Build colobot with gcc-4.8 + + mkdir -p build + cd build + CC=/opt/local/bin/gcc-mp-4.8 CXX=/opt/local/bin/g++-mp-4.8 cmake .. + make + +* Build a Colobot drag-n-drop package + + make package + +* Open the package + + open colobot-*.dmg + +* Once opened, drag the Colobot application and drop it in the + Application directory. Then just launch it as any other application. From d7af8204cec4ea91ed50d42b2db491b68416a750 Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 13 Nov 2013 17:41:33 +0100 Subject: [PATCH 18/20] On MacOSX, assume we do have CFLocaleCopyCurrent to detect the actual locale by hard-coding the fact in config.h.cmake This circumvents the fact that we are using localename.c directly instead of relying on the autotools-generated config.h --- src/common/config.h.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/config.h.cmake b/src/common/config.h.cmake index 2f403fa5..63cd93b9 100644 --- a/src/common/config.h.cmake +++ b/src/common/config.h.cmake @@ -6,6 +6,11 @@ #cmakedefine PLATFORM_MACOSX @PLATFORM_MACOSX@ #cmakedefine PLATFORM_OTHER @PLATFORM_OTHER@ +#ifdef PLATFORM_MACOSX +// Assume we have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework +#define HAVE_CFLOCALECOPYCURRENT 1 +#endif + #cmakedefine GLEW_STATIC #cmakedefine OPENAL_SOUND From 4e2ac61ee6c4d95c4846bce2ca29022083876347 Mon Sep 17 00:00:00 2001 From: Didier Raboud Date: Thu, 14 Nov 2013 14:49:25 +0100 Subject: [PATCH 19/20] Enable OpenAL in CI build --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 038e4c23..1abfb514 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,11 @@ language: cpp compiler: - gcc - clang -script: mkdir build; cd build; cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DOPENAL_SOUND=0 -DTESTS=1 && make all doc test && DESTDIR=. make install +script: mkdir build; cd build; cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DOPENAL_SOUND=1 -DTESTS=1 && make all doc test && DESTDIR=. make install before_install: - git submodule update --init --recursive - sudo add-apt-repository ppa:mapnik/boost -y - sudo apt-get update -qq - - sudo apt-get install -qq --no-install-recommends libgl1-mesa-dev libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev libpng12-dev libglew-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev google-mock libgtest-dev doxygen graphviz po4a librsvg2-bin libsndfile-dev + - sudo apt-get install -qq --no-install-recommends libgl1-mesa-dev libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev libpng12-dev libglew-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev google-mock libgtest-dev doxygen graphviz po4a librsvg2-bin libsndfile-dev libopenal-dev notifications: email: false From 89e2855f9577a629d1ca67e87de588815829864e Mon Sep 17 00:00:00 2001 From: Didier 'OdyX' Raboud Date: Wed, 20 Nov 2013 10:39:06 +0100 Subject: [PATCH 20/20] Consolidate SYSTEM_CPP_MODULE in the main CMakeLists.txt --- CMakeLists.txt | 12 ++++++++++++ src/CMakeLists.txt | 13 +------------ test/envs/opengl/CMakeLists.txt | 13 ++++--------- test/unit/CMakeLists.txt | 10 +--------- test/unit/ui/CMakeLists.txt | 5 +---- 5 files changed, 19 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ca364ea..7ee21cfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,12 +45,18 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Windows") set(PLATFORM_LINUX 0) set(PLATFORM_MACOSX 0) set(PLATFORM_OTHER 0) + + # Platform-dependent implementation of system.h + set(SYSTEM_CPP_MODULE "system_windows.cpp") elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") message(STATUS "Build for Linux system") set(PLATFORM_WINDOWS 0) set(PLATFORM_LINUX 1) set(PLATFORM_MACOSX 0) set(PLATFORM_OTHER 0) + + # Platform-dependent implementation of system.h + set(SYSTEM_CPP_MODULE "system_linux.cpp") elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") message(STATUS "Build for Mac OSX system") set(PLATFORM_WINDOWS 0) @@ -58,6 +64,9 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") set(PLATFORM_MACOSX 1) set(PLATFORM_OTHER 0) + # Platform-dependent implementation of system.h + set(SYSTEM_CPP_MODULE "system_macosx.cpp") + set(USE_SDL_MAIN 1) # fixes SDL_main else() message(STATUS "Build for other system") @@ -65,6 +74,9 @@ else() set(PLATFORM_LINUX 0) set(PLATFORM_MACOSX 0) set(PLATFORM_OTHER 1) + + # Platform-dependent implementation of system.h + set(SYSTEM_CPP_MODULE "system_other.cpp") endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 958f86cc..ef59973c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,24 +56,13 @@ if(PLATFORM_WINDOWS) set(RES_FILES "../desktop/colobot.rc") endif() -# Platform-dependent implementation of system.h -if(PLATFORM_WINDOWS) - set(SYSTEM_CPP_MODULE "system_windows.cpp") -elseif(PLATFORM_LINUX) - set(SYSTEM_CPP_MODULE "system_linux.cpp") -elseif(PLATFORM_MACOSX) - set(SYSTEM_CPP_MODULE "system_macosx.cpp") - set(SYSTEM_CPP_MODULE ${SYSTEM_CPP_MODULE} "app/system_other.cpp") -else() - set(SYSTEM_CPP_MODULE "system_other.cpp") -endif() - # Source files set(SOURCES app/app.cpp app/main.cpp app/system.cpp app/${SYSTEM_CPP_MODULE} +app/system_other.cpp common/event.cpp common/image.cpp common/iman.cpp diff --git a/test/envs/opengl/CMakeLists.txt b/test/envs/opengl/CMakeLists.txt index 28553185..a78962c5 100644 --- a/test/envs/opengl/CMakeLists.txt +++ b/test/envs/opengl/CMakeLists.txt @@ -2,15 +2,6 @@ set(SRC_DIR ${colobot_SOURCE_DIR}/src) configure_file(${SRC_DIR}/common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h) -# Platform-dependent implementation of system.h -if(PLATFORM_WINDOWS) - set(SYSTEM_CPP_MODULE "system_windows.cpp") -elseif(PLATFORM_LINUX) - set(SYSTEM_CPP_MODULE "system_linux.cpp") -else() - set(SYSTEM_CPP_MODULE "system_other.cpp") -endif() - set(TEXTURE_SOURCES ${SRC_DIR}/graphics/core/color.cpp ${SRC_DIR}/graphics/opengl/gldevice.cpp @@ -28,6 +19,7 @@ ${SRC_DIR}/common/image.cpp ${SRC_DIR}/common/stringutils.cpp ${SRC_DIR}/app/system.cpp ${SRC_DIR}/app/${SYSTEM_CPP_MODULE} +${SRC_DIR}/app/system_other.cpp model_test.cpp ) @@ -38,6 +30,7 @@ ${SRC_DIR}/common/logger.cpp ${SRC_DIR}/common/image.cpp ${SRC_DIR}/app/system.cpp ${SRC_DIR}/app/${SYSTEM_CPP_MODULE} +${SRC_DIR}/app/system_other.cpp transform_test.cpp ) @@ -48,6 +41,7 @@ ${SRC_DIR}/common/logger.cpp ${SRC_DIR}/common/image.cpp ${SRC_DIR}/app/system.cpp ${SRC_DIR}/app/${SYSTEM_CPP_MODULE} +${SRC_DIR}/app/system_other.cpp light_test.cpp ) @@ -68,6 +62,7 @@ ${SDLIMAGE_LIBRARY} ${OPENGL_LIBRARY} ${GLEW_LIBRARY} ${PNG_LIBRARIES} +${Boost_LIBRARIES} ) add_executable(texture_test ${TEXTURE_SOURCES}) diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 1f5e1bc3..38bffda8 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -18,20 +18,12 @@ endif() # Configure file configure_file(${SRC_DIR}/common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h) -# Platform-dependent implementation of system.h -if(PLATFORM_WINDOWS) - set(SYSTEM_CPP_MODULE "system_windows.cpp") -elseif(PLATFORM_LINUX) - set(SYSTEM_CPP_MODULE "system_linux.cpp") -else() - set(SYSTEM_CPP_MODULE "system_other.cpp") -endif() - # Code sources set(COLOBOT_SOURCES ${SRC_DIR}/app/app.cpp ${SRC_DIR}/app/system.cpp ${SRC_DIR}/app/${SYSTEM_CPP_MODULE} +${SRC_DIR}/app/system_other.cpp ${SRC_DIR}/common/event.cpp ${SRC_DIR}/common/image.cpp ${SRC_DIR}/common/iman.cpp diff --git a/test/unit/ui/CMakeLists.txt b/test/unit/ui/CMakeLists.txt index 97dd6818..80869676 100644 --- a/test/unit/ui/CMakeLists.txt +++ b/test/unit/ui/CMakeLists.txt @@ -10,21 +10,18 @@ ${CLIPBOARD_INCLUDE_DIR} # Platform-dependent implementation of CSystemUtils if(PLATFORM_WINDOWS) - set(SYSTEM_CPP_MODULE "system_windows.cpp") elseif(PLATFORM_LINUX) - set(SYSTEM_CPP_MODULE "system_linux.cpp") set(ADDITIONAL_LIB "-lX11") elseif(PLATFORM_MACOSX) - set(SYSTEM_CPP_MODULE "system_other.cpp") set(ADDITIONAL_LIB "${X11_X11_LIB}") else() - set(SYSTEM_CPP_MODULE "system_other.cpp") set(ADDITIONAL_LIB "-lX11") endif() add_executable(edit_test ${SRC_DIR}/app/system.cpp ${SRC_DIR}/app/${SYSTEM_CPP_MODULE} +${SRC_DIR}/app/system_other.cpp ${SRC_DIR}/common/event.cpp ${SRC_DIR}/common/logger.cpp ${SRC_DIR}/common/misc.cpp