diff options
-rw-r--r-- | .gitignore | 1 | ||||
m--------- | data | 0 | ||||
-rw-r--r-- | desktop/CMakeLists.txt | 10 | ||||
-rw-r--r-- | po/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/app/app.cpp | 12 | ||||
-rw-r--r-- | src/app/app.h | 7 | ||||
-rw-r--r-- | src/app/main.cpp | 62 | ||||
-rw-r--r-- | src/common/misc.cpp | 38 | ||||
-rw-r--r-- | src/common/misc.h | 1 | ||||
-rw-r--r-- | src/common/profile.cpp | 49 | ||||
-rw-r--r-- | src/common/profile.h | 20 | ||||
-rw-r--r-- | src/common/resources/inputstreambuffer.cpp | 4 | ||||
-rw-r--r-- | src/common/resources/outputstreambuffer.cpp | 4 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.cpp | 25 | ||||
-rw-r--r-- | src/common/resources/resourcemanager.h | 2 | ||||
-rw-r--r-- | src/graphics/engine/engine.cpp | 5 | ||||
-rw-r--r-- | src/graphics/engine/modelfile.cpp | 38 | ||||
-rw-r--r-- | src/graphics/engine/terrain.cpp | 3 | ||||
-rw-r--r-- | src/graphics/opengl/gldevice.cpp | 156 | ||||
-rw-r--r-- | src/graphics/opengl/gldevice.h | 14 | ||||
-rw-r--r-- | src/object/level/parser.cpp | 6 | ||||
-rw-r--r-- | src/object/level/parser.h | 2 | ||||
-rw-r--r-- | src/object/level/parserparam.cpp | 2 | ||||
-rw-r--r-- | src/object/robotmain.cpp | 88 | ||||
-rw-r--r-- | src/ui/maindialog.cpp | 163 |
26 files changed, 392 insertions, 326 deletions
@@ -8,6 +8,7 @@ Makefile /CTestTestfile.cmake /CPackConfig.cmake /CPackSourceConfig.cmake +/src/libcolobotbase.a # Ignore the generated documentation /doc diff --git a/data b/data -Subproject f071d2403aab82830a3df2b89e32122b57cba17 +Subproject 2660c69a52411ca68a2cd6d61f6147f0efbfcc1 diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 87c8a4b..c63b80e 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -127,11 +127,11 @@ endif(PLATFORM_WINDOWS) ## # Packaging ## -set(CPACK_BUNDLE_NAME "Colobot") +set(CPACK_BUNDLE_NAME "Colobot: Gold Edition") 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_DESCRIPTION_SUMMARY "Colobot: Gold Edition") +set(CPACK_PACKAGE_VENDOR "Terranova Team") set(CPACK_PACKAGE_VERSION_MAJOR ${COLOBOT_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${COLOBOT_VERSION_MINOR}) @@ -142,10 +142,10 @@ if(PLATFORM_WINDOWS) # 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})\\\"") + set(CPACK_NSIS_DEFINES "SetOverwrite on\nBrandingText \\\"Colobot: Gold Edition (${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}") + set(CPACK_PACKAGE_EXECUTABLES "colobot" "Colobot: Gold Edition") # Branding ## Installation and uninstallation icons diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt index 78a63b7..def5473 100644 --- a/po/CMakeLists.txt +++ b/po/CMakeLists.txt @@ -7,7 +7,7 @@ find_program(XGETTEXT_CMD xgettext) add_custom_command(OUTPUT ${_potFile} COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/app/app.cpp --output=${_potFile} COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/common/restext.cpp --output=${_potFile} --join-existing --keyword=TR --no-location - COMMAND sed -i -E "s|^(\"POT-Creation-Date:).*$|\\1 DATE\\\\n\"|" ${_potFile} + COMMAND sed -i -e "s|^\\(\"POT-Creation-Date:\\).*$|\\1 DATE\\\\n\"|" ${_potFile} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Extract translatable messages to ${_potFile}" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 869f0cb..a8914e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -215,7 +215,7 @@ set(LIBS ${LIBSNDFILE_LIBRARY} ${OPTIONAL_LIBS} ${PLATFORM_LIBS} -${PHYSFS_LIBRARY} + ${PHYSFS_LIBRARY} ) set(COLOBOT_LIBS ${LIBS} PARENT_SCOPE) @@ -239,7 +239,7 @@ set(SYSTEM_INCLUDES ${LOCALENAME_INCLUDE_DIR} ${OPTIONAL_INCLUDE_DIRS} ${CLIPBOARD_INCLUDE_DIR} -${PHYSFS_INCLUDE_PATH} + ${PHYSFS_INCLUDE_PATH} ) set(COLOBOT_LOCAL_INCLUDES ${LOCAL_INCLUDES} PARENT_SCOPE) diff --git a/src/app/app.cpp b/src/app/app.cpp index 1b53a28..ea54cf1 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -113,6 +113,7 @@ CApplication::CApplication() m_exitCode = 0; m_active = false; m_debugModes = 0; + m_restart = false; m_windowTitle = "COLOBOT: Gold Edition"; @@ -675,6 +676,17 @@ void CApplication::Destroy() SDL_Quit(); } +void CApplication::Restart() +{ + m_restart = true; + m_eventQueue->AddEvent(Event(EVENT_SYS_QUIT)); +} + +bool CApplication::IsRestarting() +{ + return m_restart; +} + bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig) { static bool restore = false; diff --git a/src/app/app.h b/src/app/app.h index c73cb53..500cb2f 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -227,6 +227,11 @@ public: //! Cleans up before exit void Destroy(); + + //! Restart + void Restart(); + //! Should we restart after app quits? + bool IsRestarting(); //! Returns a list of possible video modes VideoQueryResult GetVideoResolutionList(std::vector<Math::IntPoint> &resolutions, @@ -413,6 +418,8 @@ protected: bool m_active; //! Bit array of active debug modes long m_debugModes; + //! If we are restarting the app + bool m_restart; //! Message to be displayed as error to the user std::string m_errorMessage; diff --git a/src/app/main.cpp b/src/app/main.cpp index e30a83d..88a7a73 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -86,42 +86,46 @@ int SDL_MAIN_FUNC(int argc, char *argv[]) InitializeRestext(); InitializeEventTypeTexts(); - CSystemUtils* systemUtils = CSystemUtils::Create(); // platform-specific utils - systemUtils->Init(); - logger.Info("Colobot starting\n"); - - CApplication* app = new CApplication(); // single instance of the application - - ParseArgsStatus status = app->ParseArguments(argc, argv); - if (status == PARSE_ARGS_FAIL) - { - systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); - return app->GetExitCode(); - } - else if (status == PARSE_ARGS_HELP) - { - return app->GetExitCode(); - } - + int code = 0; + while(true) { + CSystemUtils* systemUtils = CSystemUtils::Create(); // platform-specific utils + systemUtils->Init(); + + CApplication* app = new CApplication(); // single instance of the application + + ParseArgsStatus status = app->ParseArguments(argc, argv); + if (status == PARSE_ARGS_FAIL) + { + systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", "Invalid commandline arguments!\n"); + return app->GetExitCode(); + } + else if (status == PARSE_ARGS_HELP) + { + return app->GetExitCode(); + } - if (! app->Create()) - { - app->Destroy(); // ensure a clean exit - code = app->GetExitCode(); - if ( code != 0 && !app->GetErrorMessage().empty() ) + + if (! app->Create()) { - systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", app->GetErrorMessage()); + app->Destroy(); // ensure a clean exit + code = app->GetExitCode(); + if ( code != 0 && !app->GetErrorMessage().empty() ) + { + systemUtils->SystemDialog(SDT_ERROR, "COLOBOT - Fatal Error", app->GetErrorMessage()); + } + logger.Info("Didn't run main loop. Exiting with code %d\n", code); + return code; } - logger.Info("Didn't run main loop. Exiting with code %d\n", code); - return code; - } - code = app->Run(); + code = app->Run(); + bool restarting = app->IsRestarting(); - delete app; - delete systemUtils; + delete app; + delete systemUtils; + if(!restarting) break; + } logger.Info("Exiting with code %d\n", code); return code; diff --git a/src/common/misc.cpp b/src/common/misc.cpp index 1cbd3b1..4954fc0 100644 --- a/src/common/misc.cpp +++ b/src/common/misc.cpp @@ -232,44 +232,6 @@ void TimeToAsciiClean(time_t time, char *buffer) when.tm_hour, when.tm_min); } -// Copy a list of numbered files into the temporary folder. - -bool CopyFileListToTemp(char* filename, int* list, int total) -{ - /*char name[100]; - char ext[10]; - char file[100]; - char save[100]; - char* p; - int i; - - strcpy(name, filename); - p = strchr(name, '.'); - if ( p == 0 ) - { - strcpy(ext, ".tga"); - } - else - { - strcpy(ext, p); - *p = 0; - } - - for ( i=0 ; i<total ; i++ ) - { - sprintf(file, "%s%.3d%s", name, list[i], ext); // nameNNN.ext - CopyFileToTemp(file); - } - - strcpy(save, g_userDir); - strcpy(g_userDir, "temp"); - UserDir(file, filename, "textures"); - strcpy(filename, file); - strcpy(g_userDir, save); -*/ - return false; -} - // Adds an extension to file, if doesn't already one. diff --git a/src/common/misc.h b/src/common/misc.h index a079ba6..4b75ae3 100644 --- a/src/common/misc.h +++ b/src/common/misc.h @@ -33,6 +33,5 @@ extern char GetToLower(char letter); extern void TimeToAscii(time_t time, char *buffer); extern void TimeToAsciiClean(time_t time, char *buffer); -extern bool CopyFileListToTemp(char* filename, int* list, int total); extern void AddExt(char* filename, const char* ext); diff --git a/src/common/profile.cpp b/src/common/profile.cpp index 92fc1d6..75ab135 100644 --- a/src/common/profile.cpp +++ b/src/common/profile.cpp @@ -247,52 +247,3 @@ std::vector< std::string > CProfile::GetSection(std::string section, std::string return ret_list; } - -void CProfile::SetUserDir(std::string dir) -{ - m_userDirectory = dir; -} - - -std::string CProfile::GetUserBasedPath(std::string dir, std::string defaultDir) -{ - std::string path = dir; - boost::replace_all(path, "\\", "/"); - if (dir.find("/") == std::string::npos) - { - path = defaultDir + "/" + dir; - } - - if (m_userDirectory.length() > 0) - { - boost::replace_all(path, "%user%", m_userDirectory); - } - else - { - boost::replace_all(path, "%user%", defaultDir); - } - - return fs::path(path).make_preferred().string(); -} - - -bool CProfile::CopyFileToTemp(std::string filename) -{ - std::string src, dst; - std::string tmp_user_dir = m_userDirectory; - - src = GetUserBasedPath(filename, "textures"); - SetUserDir("temp"); - dst = GetUserBasedPath(filename, "textures"); - SetUserDir(tmp_user_dir); - - fs::create_directory(fs::path(dst).parent_path().make_preferred().string()); - fs::copy_file(src, dst, fs::copy_option::overwrite_if_exists); - if (fs::exists(dst)) - { - return true; - } - - return false; -} - diff --git a/src/common/profile.h b/src/common/profile.h index 444975c..d89c5d1 100644 --- a/src/common/profile.h +++ b/src/common/profile.h @@ -116,29 +116,9 @@ public: */ std::vector< std::string > GetSection(std::string section, std::string key); - /** Sets current user directory - * \param dir - */ - void SetUserDir(std::string dir); - - /** Returns path based on current user. Replaces %user% in path with current user dir or - * uses default_dir param if no user dir is specified - * \param dir - * \param default_dir - * \return path - */ - std::string GetUserBasedPath(std::string dir, std::string defaultDir); - - /** Copy a file into the temporary folder. - * \param filename - * \return true on success - */ - bool CopyFileToTemp(std::string filename); - private: boost::property_tree::ptree m_propertyTree; bool m_profileNeedSave; - std::string m_userDirectory; bool m_useCurrentDirectory; }; diff --git a/src/common/resources/inputstreambuffer.cpp b/src/common/resources/inputstreambuffer.cpp index 7059d60..9ac1fec 100644 --- a/src/common/resources/inputstreambuffer.cpp +++ b/src/common/resources/inputstreambuffer.cpp @@ -19,6 +19,8 @@ #include "common/resources/inputstreambuffer.h" +#include "common/resources/resourcemanager.h" + #include <stdexcept> #include <sstream> @@ -44,7 +46,7 @@ CInputStreamBuffer::~CInputStreamBuffer() void CInputStreamBuffer::open(const std::string &filename) { if (PHYSFS_isInit()) - m_file = PHYSFS_openRead(filename.c_str()); + m_file = PHYSFS_openRead(CResourceManager::CleanPath(filename).c_str()); } diff --git a/src/common/resources/outputstreambuffer.cpp b/src/common/resources/outputstreambuffer.cpp index f8b4100..157e17d 100644 --- a/src/common/resources/outputstreambuffer.cpp +++ b/src/common/resources/outputstreambuffer.cpp @@ -19,6 +19,8 @@ #include "common/resources/outputstreambuffer.h" +#include "common/resources/resourcemanager.h" + #include <stdexcept> #include <sstream> @@ -40,7 +42,7 @@ COutputStreamBuffer::~COutputStreamBuffer() void COutputStreamBuffer::open(const std::string &filename) { if (PHYSFS_isInit()) - m_file = PHYSFS_openWrite(filename.c_str()); + m_file = PHYSFS_openWrite(CResourceManager::CleanPath(filename).c_str()); } diff --git a/src/common/resources/resourcemanager.cpp b/src/common/resources/resourcemanager.cpp index 42f9634..475d71e 100644 --- a/src/common/resources/resourcemanager.cpp +++ b/src/common/resources/resourcemanager.cpp @@ -26,6 +26,7 @@ #include <physfs.h> #include <boost/filesystem.hpp> +#include <boost/regex.hpp> namespace fs = boost::filesystem; @@ -55,6 +56,11 @@ CResourceManager::~CResourceManager() } } +std::string CResourceManager::CleanPath(const std::string& path) +{ + return boost::regex_replace(path, boost::regex("(.*)/\\.\\./"), ""); +} + bool CResourceManager::AddLocation(const std::string &location, bool prepend) { @@ -121,7 +127,7 @@ SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename) return nullptr; } - PHYSFS_File *file = PHYSFS_openRead(filename.c_str()); + PHYSFS_File *file = PHYSFS_openRead(CleanPath(filename).c_str()); if (!file) { SDL_FreeRW(handler); @@ -141,32 +147,33 @@ SDL_RWops* CResourceManager::GetSDLFileHandler(const std::string &filename) CSNDFile* CResourceManager::GetSNDFileHandler(const std::string &filename) { - return new CSNDFile(filename); + return new CSNDFile(CleanPath(filename)); } bool CResourceManager::Exists(const std::string &filename) { - return PHYSFS_exists(filename.c_str()); + return PHYSFS_exists(CleanPath(filename).c_str()); } bool CResourceManager::DirectoryExists(const std::string& directory) { - return PHYSFS_exists(directory.c_str()) && PHYSFS_isDirectory(directory.c_str()); + return PHYSFS_exists(CleanPath(directory).c_str()) && PHYSFS_isDirectory(CleanPath(directory).c_str()); } bool CResourceManager::CreateDirectory(const std::string& directory) { - return PHYSFS_mkdir(directory.c_str()); + return PHYSFS_mkdir(CleanPath(directory).c_str()); } +//TODO: Don't use boost filesystem here bool CResourceManager::RemoveDirectory(const std::string& directory) { bool success = true; std::string writeDir = PHYSFS_getWriteDir(); try { - fs::remove_all(writeDir + "/" + directory); + fs::remove_all(writeDir + "/" + CleanPath(directory)); } catch (std::exception & e) { @@ -179,7 +186,7 @@ std::vector<std::string> CResourceManager::ListFiles(const std::string &director { std::vector<std::string> result; - char **files = PHYSFS_enumerateFiles(directory.c_str()); + char **files = PHYSFS_enumerateFiles(CleanPath(directory).c_str()); for (char **i = files; *i != nullptr; i++) { @@ -195,11 +202,11 @@ std::vector<std::string> CResourceManager::ListDirectories(const std::string &di { std::vector<std::string> result; - char **files = PHYSFS_enumerateFiles(directory.c_str()); + char **files = PHYSFS_enumerateFiles(CleanPath(directory).c_str()); for (char **i = files; *i != nullptr; i++) { - std::string path = directory + "/" + (*i); + std::string path = CleanPath(directory) + "/" + (*i); if (PHYSFS_isDirectory(path.c_str())) { result.push_back(*i); diff --git a/src/common/resources/resourcemanager.h b/src/common/resources/resourcemanager.h index 730cf3e..4d79e9b 100644 --- a/src/common/resources/resourcemanager.h +++ b/src/common/resources/resourcemanager.h @@ -30,6 +30,8 @@ class CResourceManager public: CResourceManager(const char *argv0); ~CResourceManager(); + + static std::string CleanPath(const std::string &path); static bool AddLocation(const std::string &location, bool prepend = true); static bool RemoveLocation(const std::string &location); diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index db702b7..ae6f238 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -295,6 +295,9 @@ bool CEngine::Create() void CEngine::Destroy() { m_text->Destroy(); + + delete m_pause; + m_pause = nullptr; delete m_lightMan; m_lightMan = nullptr; @@ -325,6 +328,8 @@ void CEngine::ResetAfterDeviceChanged() m_text->FlushCache(); FlushTextureCache(); + + LoadAllTextures(); } bool CEngine::ProcessEvent(const Event &event) diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp index 09c7bbd..c422f18 100644 --- a/src/graphics/engine/modelfile.cpp +++ b/src/graphics/engine/modelfile.cpp @@ -24,7 +24,9 @@ #include "common/logger.h" #include "common/stringutils.h" +#ifndef MODELFILE_NO_ENGINE #include "common/resources/inputstream.h" +#endif #include "graphics/engine/engine.h" @@ -436,13 +438,23 @@ bool CModelFile::ReadModel(const std::string& fileName) { m_triangles.clear(); + #ifndef MODELFILE_NO_ENGINE CInputStream stream; - stream.open(fileName.c_str()); + stream.open(fileName); if (!stream.is_open()) { GetLogger()->Error("Could not open file '%s'\n", fileName.c_str()); return false; } + #else + std::ifstream stream; + stream.open(fileName); + if (!stream.good()) + { + GetLogger()->Error("Could not open file '%s'\n", fileName.c_str()); + return false; + } + #endif return ReadModel(stream); } @@ -827,13 +839,23 @@ struct NewModelTriangle1 bool CModelFile::ReadTextModel(const std::string& fileName) { + #ifndef MODELFILE_NO_ENGINE CInputStream stream; - stream.open(fileName.c_str()); + stream.open(fileName); if (!stream.is_open()) { GetLogger()->Error("Could not open file '%s'\n", fileName.c_str()); return false; } + #else + std::ifstream stream; + stream.open(fileName); + if (!stream.good()) + { + GetLogger()->Error("Could not open file '%s'\n", fileName.c_str()); + return false; + } + #endif return ReadTextModel(stream); } @@ -1024,13 +1046,23 @@ bool CModelFile::WriteTextModel(std::ostream& stream) bool CModelFile::ReadBinaryModel(const std::string& fileName) { + #ifndef MODELFILE_NO_ENGINE CInputStream stream; - stream.open(fileName.c_str()); + stream.open(fileName); if (!stream.is_open()) { GetLogger()->Error("Could not open file '%s'\n", fileName.c_str()); return false; } + #else + std::ifstream stream; + stream.open(fileName); + if (!stream.good()) + { + GetLogger()->Error("Could not open file '%s'\n", fileName.c_str()); + return false; + } + #endif return ReadBinaryModel(stream); } diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index 21d7446..b58685b 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -123,7 +123,8 @@ bool CTerrain::InitTextures(const std::string& baseName, int* table, int dx, int m_useMaterials = false; m_texBaseName = baseName; - size_t pos = baseName.find('.'); + size_t pos = baseName.rfind('.'); + if(pos < baseName.find_last_of('/')) pos = std::string::npos; // If last . is not a part of filename (some directory, possibly . or ..) if (pos == std::string::npos) { diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 0ae6f88..a197b18 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -68,6 +68,7 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config) m_lastVboId = 0; m_multitextureAvailable = false; m_vboAvailable = false; + m_vertexBufferType = VBT_DISPLAY_LIST; } @@ -186,7 +187,7 @@ bool CGLDevice::Create() { GetLogger()->Info("Creating CDevice\n"); - static bool glewInited = false; + /*static*/ bool glewInited = false; if (!glewInited) { @@ -207,12 +208,12 @@ bool CGLDevice::Create() if (m_config.vboMode == VBO_MODE_ENABLE) { GetLogger()->Info("VBO enabled by override - using VBOs\n"); - m_vboAvailable = true; + SetVertexBufferType(VBT_VBO_CORE); } else if (m_config.vboMode == VBO_MODE_DISABLE) { GetLogger()->Info("VBO disabled by override - using display lists\n"); - m_vboAvailable = false; + SetVertexBufferType(VBT_DISPLAY_LIST); } else { @@ -223,18 +224,26 @@ bool CGLDevice::Create() int major = 0, minor = 0; sscanf(version, "%d.%d", &major, &minor); + + // detecting VBO ARB extension + bool vboARB = glewIsSupported("GL_ARB_vertex_buffer_object"); // VBO is core OpenGL feature since 1.5 // everything below 1.5 means no VBO support if(major > 1 || minor > 4) { GetLogger()->Info("OpenGL %d.%d, VBO supported\n", major, minor); - m_vboAvailable = true; + SetVertexBufferType(VBT_VBO_CORE); } - else + else if(vboARB) // VBO ARB extension available + { + GetLogger()->Info("OpenGL %d.%d with GL_ARB_vertex_buffer_object, VBO supported\n", major, minor); + SetVertexBufferType(VBT_VBO_ARB); + } + else // no VBO support { - GetLogger()->Info("OpenGL %d.%d, VBO not supported\n", major, minor); - m_vboAvailable = false; + GetLogger()->Info("OpenGL %d.%d without GL_ARB_vertex_buffer_object, VBO not supported\n", major, minor); + SetVertexBufferType(VBT_DISPLAY_LIST); } } } @@ -304,6 +313,13 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig) void CGLDevice::SetUseVbo(bool vboAvailable) { m_vboAvailable = vboAvailable; + m_vertexBufferType = vboAvailable ? VBT_VBO_CORE : VBT_DISPLAY_LIST; +} + +void CGLDevice::SetVertexBufferType(VertexBufferType type) +{ + m_vertexBufferType = type; + m_vboAvailable = (type != VBT_DISPLAY_LIST); } void CGLDevice::BeginScene() @@ -787,13 +803,13 @@ void CGLDevice::UpdateTextureParams(int index) glActiveTexture(GL_TEXTURE0 + index); if (params.wrapS == TEX_WRAP_CLAMP) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); else if (params.wrapS == TEX_WRAP_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); else assert(false); if (params.wrapT == TEX_WRAP_CLAMP) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); else if (params.wrapT == TEX_WRAP_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); else assert(false); @@ -926,13 +942,13 @@ void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wr glActiveTexture(GL_TEXTURE0 + index); if (wrapS == TEX_WRAP_CLAMP) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); else if (wrapS == TEX_WRAP_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); else assert(false); if (wrapT == TEX_WRAP_CLAMP) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); else if (wrapT == TEX_WRAP_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); else assert(false); @@ -1046,10 +1062,20 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve info.vertexCount = vertexCount; info.bufferId = 0; - glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glGenBuffersARB(1, &info.bufferId); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } m_vboObjects[id] = info; } @@ -1080,10 +1106,20 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve info.vertexCount = vertexCount; info.bufferId = 0; - glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glGenBuffersARB(1, &info.bufferId); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } m_vboObjects[id] = info; } @@ -1113,11 +1149,21 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve info.vertexType = VERTEX_TYPE_COL; info.vertexCount = vertexCount; info.bufferId = 0; - - glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + + if(m_vertexBufferType == VBT_VBO_CORE) + { + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glGenBuffersARB(1, &info.bufferId); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } m_vboObjects[id] = info; } @@ -1148,9 +1194,18 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv info.vertexType = VERTEX_TYPE_NORMAL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } } else { @@ -1175,9 +1230,18 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv info.vertexType = VERTEX_TYPE_TEX2; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } } else { @@ -1202,9 +1266,18 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv info.vertexType = VERTEX_TYPE_COL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); - glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + { + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId); + glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW_ARB); + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + } } else { @@ -1225,7 +1298,11 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) return; glEnable(GL_VERTEX_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId); + + if(m_vertexBufferType == VBT_VBO_CORE) + glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId); + else + glBindBufferARB(GL_ARRAY_BUFFER_ARB, (*it).second.bufferId); if ((*it).second.vertexType == VERTEX_TYPE_NORMAL) { @@ -1297,7 +1374,11 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glDisableClientState(GL_COLOR_ARRAY); } - glBindBuffer(GL_ARRAY_BUFFER, 0); + if(m_vertexBufferType == VBT_VBO_CORE) + glBindBuffer(GL_ARRAY_BUFFER, 0); + else + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + glDisable(GL_VERTEX_ARRAY); } else @@ -1314,7 +1395,10 @@ void CGLDevice::DestroyStaticBuffer(unsigned int bufferId) if (it == m_vboObjects.end()) return; - glDeleteBuffers(1, &(*it).second.bufferId); + if(m_vertexBufferType == VBT_VBO_CORE) + glDeleteBuffers(1, &(*it).second.bufferId); + else + glDeleteBuffersARB(1, &(*it).second.bufferId); m_vboObjects.erase(it); } diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 723b0f2..1174367 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -48,6 +48,17 @@ enum VBOMode }; /** + \enum VertexBufferType + \brief Specifies type of vertex buffer to use + */ +enum VertexBufferType +{ + VBT_DISPLAY_LIST, //! use display lists + VBT_VBO_CORE, //! use core OpenGL 1.5 VBOs + VBT_VBO_ARB //! use ARB extension VBOs +}; + +/** \struct GLDeviceConfig \brief Additional config with OpenGL-specific settings */ struct GLDeviceConfig : public DeviceConfig @@ -104,6 +115,7 @@ public: void ConfigChanged(const GLDeviceConfig &newConfig); void SetUseVbo(bool useVbo); + void SetVertexBufferType(VertexBufferType type); virtual void BeginScene() override; virtual void EndScene() override; @@ -235,6 +247,8 @@ private: bool m_multitextureAvailable; //! Whether to use VBOs or display lists bool m_vboAvailable; + //! Which vertex buffer type to use + VertexBufferType m_vertexBufferType; //! Map of saved VBO objects std::map<unsigned int, VboObjectInfo> m_vboObjects; //! Last ID of VBO object diff --git a/src/object/level/parser.cpp b/src/object/level/parser.cpp index ab3e6bc..3a0449a 100644 --- a/src/object/level/parser.cpp +++ b/src/object/level/parser.cpp @@ -22,6 +22,7 @@ #include "app/app.h" +#include "common/resources/resourcemanager.h" #include "common/resources/inputstream.h" #include "object/level/parserexceptions.h" @@ -115,6 +116,11 @@ std::string CLevelParser::BuildSceneName(std::string category, int chapter, int return outstream.str(); } +bool CLevelParser::Exists() +{ + return CResourceManager::Exists(m_filename); +} + void CLevelParser::Load() { CInputStream file; diff --git a/src/object/level/parser.h b/src/object/level/parser.h index 7e87e2d..ca2bf6f 100644 --- a/src/object/level/parser.h +++ b/src/object/level/parser.h @@ -46,6 +46,8 @@ public: //! Build level filename static std::string BuildSceneName(std::string category, int chapter, int rank, bool sceneFile = true); + //! Check if level file exists + bool Exists(); //! Load file void Load(); //! Save file diff --git a/src/object/level/parserparam.cpp b/src/object/level/parserparam.cpp index aa5a963..ee080b2 100644 --- a/src/object/level/parserparam.cpp +++ b/src/object/level/parserparam.cpp @@ -170,7 +170,7 @@ std::string CLevelParserParam::InjectLevelDir(std::string path, const std::strin boost::replace_all(newPath, "%lvl%", lvlDir); std::string chapDir = CLevelParser::BuildSceneName(CRobotMain::GetInstancePointer()->GetSceneName(), CRobotMain::GetInstancePointer()->GetSceneRank()/100, 0, false); boost::replace_all(newPath, "%chap%", chapDir); - if(newPath == path) + if(newPath == path && !path.empty()) { newPath = defaultDir + (!defaultDir.empty() ? "/" : "") + newPath; } diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index 1ad3c6d..adbe81d 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -3864,7 +3864,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "CacheAudio" && !resetObject && m_version >= 2) { - m_sound->CacheMusic(line->GetParam("filename")->AsPath("").c_str()); //TODO: don't make this relative to music/ + m_sound->CacheMusic(std::string("../")+line->GetParam("filename")->AsPath("music")); continue; } @@ -3882,7 +3882,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) m_audioChange[i].powermax = line->GetParam("powermax")->AsFloat(100); m_audioChange[i].tool = line->GetParam("tool")->AsToolType(TOOL_OTHER); m_audioChange[i].drive = line->GetParam("drive")->AsDriveType(DRIVE_OTHER); - strcpy(m_audioChange[i].music, line->GetParam("filename")->AsPath("").c_str()); //TODO: don't make this relative to music/ + strcpy(m_audioChange[i].music, (std::string("../")+line->GetParam("filename")->AsPath("music")).c_str()); m_audioChange[i].repeat = line->GetParam("repeat")->AsBool(true); m_audioChange[i].changed = false; m_sound->CacheMusic(m_audioChange[i].music); @@ -3906,14 +3906,26 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) } else { - m_audioTrack = line->GetParam("main")->AsPath("", ""); //TODO: don't make this relative to music/ - m_audioRepeat = line->GetParam("mainRepeat")->AsBool(true); + if(line->GetParam("main")->IsDefined()) { + m_audioTrack = std::string("../")+line->GetParam("main")->AsPath("music"); + m_audioRepeat = line->GetParam("mainRepeat")->AsBool(true); + } else { + m_audioTrack = ""; + } - m_satcomTrack = line->GetParam("satcom")->AsPath("", ""); //TODO: don't make this relative to music/ - m_satcomRepeat = line->GetParam("satcomRepeat")->AsBool(true); + if(line->GetParam("satcom")->IsDefined()) { + m_satcomTrack = std::string("../")+line->GetParam("satcom")->AsPath("music"); + m_satcomRepeat = line->GetParam("satcomRepeat")->AsBool(true); + } else { + m_satcomTrack = ""; + } - m_editorTrack = line->GetParam("editor")->AsPath("", ""); //TODO: don't make this relative to music/ - m_editorRepeat = line->GetParam("editorRepeat")->AsBool(true); + if(line->GetParam("editor")->IsDefined()) { + m_editorTrack = std::string("../")+line->GetParam("editor")->AsPath("music"); + m_editorRepeat = line->GetParam("editorRepeat")->AsBool(true); + } else { + m_editorTrack = ""; + } } if (m_audioTrack != "") m_sound->CacheMusic(m_audioTrack); if (m_satcomTrack != "") m_sound->CacheMusic(m_satcomTrack); @@ -3975,7 +3987,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "Background" && !resetObject) { - m_engine->SetBackground(line->GetParam("image")->AsPath("", "").c_str(), //TODO: don't make this relative to textures/ + std::string path = ""; + if(line->GetParam("image")->IsDefined()) + path = "../"+line->GetParam("image")->AsPath("textures"); + m_engine->SetBackground(path.c_str(), line->GetParam("up")->AsColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)), line->GetParam("down")->AsColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)), line->GetParam("cloudUp")->AsColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)), @@ -3996,17 +4011,17 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) line->GetParam("dim")->AsFloat(0.2f), line->GetParam("speed")->AsFloat(0.0f), line->GetParam("dir")->AsFloat(0.0f), - line->GetParam("image")->AsPath(""), //TODO: don't make this relative to textures/ + "../"+line->GetParam("image")->AsPath("textures"), Math::Point(uv1.x, uv1.z), Math::Point(uv2.x, uv2.z), - line->GetParam("image")->AsPath("").find("planet") != std::string::npos // TODO: add transparent op or modify textures + line->GetParam("image")->AsPath("textures").find("planet") != std::string::npos // TODO: add transparent op or modify textures ); continue; } if (line->GetCommand() == "ForegroundName" && !resetObject) { - m_engine->SetForegroundName(line->GetParam("image")->AsPath("")); //TODO: don't make this relative to textures/ + m_engine->SetForegroundName("../"+line->GetParam("image")->AsPath("textures")); continue; } @@ -4069,7 +4084,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) pos.z = pos.x; m_water->Create(line->GetParam("air")->AsWaterType(Gfx::WATER_TT), line->GetParam("water")->AsWaterType(Gfx::WATER_TT), - line->GetParam("image")->AsPath(""), //TODO: don't make this relative to textures/ + "../"+line->GetParam("image")->AsPath("textures"), line->GetParam("diffuse")->AsColor(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)), line->GetParam("ambient")->AsColor(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)), line->GetParam("level")->AsFloat(100.0f)*g_unit, @@ -4088,7 +4103,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "TerrainCloud" && !resetObject) { - m_cloud->Create(line->GetParam("image")->AsPath("", ""), //TODO: don't make this relative to textures/ + std::string path = ""; + if(line->GetParam("image")->IsDefined()) + path = "../"+line->GetParam("image")->AsPath("textures"); + m_cloud->Create(path, line->GetParam("diffuse")->AsColor(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)), line->GetParam("ambient")->AsColor(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)), line->GetParam("level")->AsFloat(500.0f)*g_unit); @@ -4105,7 +4123,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "TerrainInitTextures" && !resetObject) { - std::string name = line->GetParam("image")->AsPath(""); //TODO: don't make this relative to textures/ + std::string name = "../"+line->GetParam("image")->AsPath("textures"); if(name.find(".") == std::string::npos) name += ".png"; unsigned int dx = line->GetParam("dx")->AsInt(1); @@ -4136,11 +4154,6 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) } } - /*TODO: ??? - if (strstr(name, "%user%") != 0) - CopyFileListToTemp(name, tt, dx*dy); - */ - m_terrain->InitTextures(name.c_str(), tt, dx, dy); continue; } @@ -4153,15 +4166,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "TerrainMaterial" && !resetObject) { - std::string name = line->GetParam("image")->AsPath(""); //TODO: don't make this relative to textures/ + std::string name = line->GetParam("image")->AsPath("textures"); if(name.find(".") == std::string::npos) name += ".png"; - /*TODO: ??? - if (strstr(name, "%user%") != 0) - { - GetProfile().CopyFileToTemp(std::string(name)); - } - */ + name = "../"+name; m_terrain->AddMaterial(line->GetParam("id")->AsInt(0), name.c_str(), @@ -4229,7 +4237,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) CBrain* brain = m_controller->GetBrain(); if (brain != nullptr) { - std::string name = line->GetParam("script")->AsPath(""); //TODO: Don't make this relative to ai/ + std::string name = "../"+line->GetParam("script")->AsPath("ai"); if (!name.empty()) brain->SetScriptName(0, const_cast<char*>(name.c_str())); brain->SetScriptRun(0); @@ -4394,7 +4402,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) { std::string op = "script"+boost::lexical_cast<std::string>(i+1); // script1..script10 if(line->GetParam(op)->IsDefined()) { - brain->SetScriptName(i, const_cast<char*>(line->GetParam(op)->AsPath("").c_str())); //TODO: don't make this relative to ai/ + brain->SetScriptName(i, const_cast<char*>(("../"+line->GetParam(op)->AsPath("ai")).c_str())); } } @@ -4416,7 +4424,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) std::string op = "autoValue"+boost::lexical_cast<std::string>(i+1); // autoValue1..autoValue5 automat->SetValue(i, line->GetParam(op)->AsFloat(0.0f)); } - automat->SetString(const_cast<char*>(line->GetParam("autoString")->AsString("").c_str())); + automat->SetString(const_cast<char*>(line->GetParam("autoString")->AsPath("ai", "").c_str())); int i = line->GetParam("run")->AsInt(-1); if (i != -1) @@ -4539,7 +4547,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (m_mapImage) { Math::Vector offset; - strcpy(m_mapFilename, line->GetParam("filename")->AsPath("").c_str()); //TODO: don't make this relative to textures/ + strcpy(m_mapFilename, ("../"+line->GetParam("filename")->AsPath("textures")).c_str()); offset = line->GetParam("offset")->AsPoint(Math::Vector(0.0f, 0.0f, 0.0f)); m_map->SetFixParam(line->GetParam("zoom")->AsFloat(1.0f), offset.x, offset.z, @@ -4675,13 +4683,11 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (line->GetCommand() == "NewScript" && !resetObject) { - char name[200]; - strcpy(name, line->GetParam("name")->AsPath("").c_str()); //TODO: don't make this relative to ai/ - AddNewScriptName(line->GetParam("type")->AsObjectType(OBJECT_NULL), name); + AddNewScriptName(line->GetParam("type")->AsObjectType(OBJECT_NULL), const_cast<char*>(line->GetParam("name")->AsPath("ai").c_str())); continue; } - if(read[0] != 0) continue; // ignore errors when loading saevd game (TODO: don't report ones that are just not loaded when loading saved game) + if(read[0] != 0) continue; // ignore errors when loading saved game (TODO: don't report ones that are just not loaded when loading saved game) if(resetObject) continue; // ignore when reseting just objects (TODO: see above) throw CLevelParserException("Unknown command: '"+line->GetCommand()+"' in "+line->GetLevel()->GetFilename()+":"+boost::lexical_cast<std::string>(line->GetLineNumber())); @@ -5459,9 +5465,12 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank, ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; - + + std::string fnstr = filename; + boost::replace_all(fnstr, m_dialog->GetSavegameDir(), m_dialog->GetPHYSFSSavegameDir()); //TODO: Refactor to get physfs path here + //TODO: Refactor to std::string char fn[MAX_FNAME]; - strcpy(fn, filename); + strcpy(fn, fnstr.c_str()); char* ldir = SearchLastDir(fn); if (ldir == 0) return; @@ -5528,8 +5537,11 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank) ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return; + std::string fnstr = filename; + boost::replace_all(fnstr, m_dialog->GetSavegameDir(), m_dialog->GetPHYSFSSavegameDir()); //TODO: Refactor to get physfs path here + //TODO: Refactor to std::string char fn[MAX_FNAME]; - strcpy(fn, filename); + strcpy(fn, fnstr.c_str()); char* ldir = SearchLastDir(fn); if (ldir == 0) return; diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index fe40609..6c25902 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -322,6 +322,21 @@ void CMainDialog::ChangePhase(Phase phase) ddim.x = 0.09f; pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_USER); pb->SetState(STATE_SHADOW); + + try { + CLevelParser* level = new CLevelParser("levels/custom/config.txt"); + if(level->Exists()) { + level->Load(); + CLevelParserLine* line = level->Get("Button"); + if(line->GetParam("name")->IsDefined()) + pb->SetName(line->GetParam("name")->AsString()); + if(line->GetParam("tooltip")->IsDefined()) + pb->SetTooltip(line->GetParam("tooltip")->AsString()); + } + } + catch(CLevelParserException& e) { + CLogger::GetInstancePointer()->Error("Failed loading userlevel button name: %s\n", e.what()); + } } /*pos.x = 139.0f/640.0f; @@ -953,6 +968,9 @@ void CMainDialog::ChangePhase(Phase phase) pb->SetState(STATE_SHADOW); pb->SetState(STATE_CARD); pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPd || m_phase == PHASE_SETUPds)); + #if PLATFORM_WINDOWS + pb->SetState(STATE_ENABLE, !m_bSimulSetup); + #endif pos.x += ddim.x+0.01f; pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPg); @@ -1035,6 +1053,14 @@ void CMainDialog::ChangePhase(Phase phase) pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_FULL); pc->SetState(STATE_SHADOW); pc->SetState(STATE_CHECK, m_setupFull); + + #if !PLATFORM_LINUX + ddim.x = 0.9f; + ddim.y = 0.1f; + pos.x = 0.05f; + pos.y = 0.20f; + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, "The game will be restarted in order to apply changes. All unsaved progress will be lost."); + #endif ddim.x = dim.x*6; ddim.y = dim.y*1; @@ -1559,7 +1585,7 @@ void CMainDialog::ChangePhase(Phase phase) m_engine->SetOverColor(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f), Gfx::ENG_RSTATE_TCOLOR_BLACK); // TODO: color ok? m_engine->SetOverFront(true); - m_engine->SetBackground("interface/ppc.png", + m_engine->SetBackground("interface/intro1.png", Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), @@ -1578,7 +1604,7 @@ void CMainDialog::ChangePhase(Phase phase) m_engine->SetOverColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::ENG_RSTATE_TCOLOR_WHITE); // TODO: color ok? m_engine->SetOverFront(true); - m_engine->SetBackground("interface/colobot.png", + m_engine->SetBackground("interface/intro2.png", Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), @@ -1597,7 +1623,7 @@ void CMainDialog::ChangePhase(Phase phase) m_engine->SetOverColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::ENG_RSTATE_TCOLOR_WHITE); // TODO: color ok? m_engine->SetOverFront(true); - m_engine->SetBackground("interface/epsitec.png", + m_engine->SetBackground("interface/intro3.png", Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), @@ -1873,6 +1899,9 @@ bool CMainDialog::EventProcess(const Event &event) { StopDialog(); StartSuspend(); + #if PLATFORM_WINDOWS + if ( m_phaseSetup == PHASE_SETUPd ) m_phaseSetup = PHASE_SETUPg; + #endif if ( m_phaseSetup == PHASE_SETUPd ) ChangePhase(PHASE_SETUPds); if ( m_phaseSetup == PHASE_SETUPg ) ChangePhase(PHASE_SETUPgs); if ( m_phaseSetup == PHASE_SETUPp ) ChangePhase(PHASE_SETUPps); @@ -4136,6 +4165,8 @@ void CMainDialog::IOUpdateList() return; std::string filename = (m_saveList.at(sel) / "screen.png").make_preferred().string(); + boost::replace_all(filename, GetSavegameDir(), GetPHYSFSSavegameDir()); //TODO: Refactor everything to PHYSFS, see issue #334 + filename = "../"+filename; if ( m_phase == PHASE_WRITE || m_phase == PHASE_WRITEs ) { if ( sel < max-1 ) @@ -4378,17 +4409,11 @@ void CMainDialog::UpdateSceneChap(int &chap) CList* pl; std::string fileName; - char op[100]; - char op_i18n[100]; char line[500]; - char name[100]; - int i, j; + int j; bool bPassed; - memset(op, 0, 100); - memset(op_i18n, 0, 100); memset(line, 0, 500); - memset(name, 0, 100); pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == 0 ) return; @@ -4425,41 +4450,19 @@ void CMainDialog::UpdateSceneChap(int &chap) { for ( j=0 ; j<9 ; j++ ) { - BuildSceneName(fileName, m_sceneName, (j+1)*100); - CInputStream stream; - stream.open(fileName); - if (!stream.is_open()) break; - - BuildResumeName(name, m_sceneName, j+1); // default name - sprintf(op, "Title.E"); - sprintf(op_i18n, "Title.%c", m_app->GetLanguageChar()); - - while (stream.getline(line, 500)) - { - for ( i=0 ; i<500 ; i++ ) - { - if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space - if ( line[i] == '/' && line[i+1] == '/' ) - { - line[i] = 0; - break; - } - } - - if ( Cmd(line, op) ) - { - OpString(line, "text", name); - } - if ( Cmd(line, op_i18n) ) - { - OpString(line, "text", name); - break; - } + CLevelParser* level = new CLevelParser(m_sceneName, j+1, 0); + if(!level->Exists()) + break; + try { + level->Load(); + sprintf(line, "%d: %s", j+1, level->Get("Title")->GetParam("text")->AsString().c_str()); + } + catch(CLevelParserException& e) { + sprintf(line, "%s", (std::string("[ERROR]: ")+e.what()).c_str()); } - stream.close(); + delete level; bPassed = GetGamerInfoPassed((j+1)*100); - sprintf(line, "%d: %s", j+1, name); pl->SetItemName(j, line); pl->SetCheck(j, bPassed); pl->SetEnable(j, true); @@ -4491,17 +4494,11 @@ void CMainDialog::UpdateSceneList(int chap, int &sel) CWindow* pw; CList* pl; std::string fileName; - char op[100]; - char op_i18n[100]; char line[500]; - char name[100]; - int i, j; + int j; bool bPassed; - memset(op, 0, 100); - memset(op_i18n, 0, 100); memset(line, 0, 500); - memset(name, 0, 100); pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5)); if ( pw == 0 ) return; @@ -4512,68 +4509,45 @@ void CMainDialog::UpdateSceneList(int chap, int &sel) if(chap < 0) return; + bool readAll = true; for ( j=0 ; j<99 ; j++ ) { - BuildSceneName(fileName, m_sceneName, (chap+1)*100+(j+1)); - - CInputStream stream; - stream.open(fileName); - if (!stream.is_open()) break; - - BuildResumeName(name, m_sceneName, j+1); // default name - sprintf(op, "Title.E"); - sprintf(op_i18n, "Title.%c", m_app->GetLanguageChar()); - - while (stream.getline(line, 500)) - { - for ( i=0 ; i<500 ; i++ ) - { - if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space - if ( line[i] == '/' && line[i+1] == '/' ) - { - line[i] = 0; - break; - } - } - - if ( Cmd(line, op) ) - { - OpString(line, "text", name); - } - if ( Cmd(line, op_i18n) ) - { - OpString(line, "text", name); + CLevelParser* level = new CLevelParser(m_sceneName, chap+1, j+1); + if(!level->Exists()) { + readAll = true; + break; + } else { + if(!readAll) break; - } } - stream.close(); + try { + level->Load(); + sprintf(line, "%d: %s", j+1, level->Get("Title")->GetParam("text")->AsString().c_str()); + } + catch(CLevelParserException& e) { + sprintf(line, "%s", (std::string("[ERROR]: ")+e.what()).c_str()); + } + delete level; bPassed = GetGamerInfoPassed((chap+1)*100+(j+1)); - sprintf(line, "%d: %s", j+1, name); pl->SetItemName(j, line); pl->SetCheck(j, bPassed); pl->SetEnable(j, true); if ( m_phase == PHASE_MISSION && !m_main->GetShowAll() && !bPassed ) { - j ++; - break; + readAll = false; } } - /* TODO: ????? - BuildSceneName(fileName, m_sceneName, (chap+1)*100+(j+1)); - file = fopen(fileName.c_str(), "r"); - if ( file == NULL ) + if(readAll) { m_maxList = j; } else { m_maxList = j+1; // this is not the last! - fclose(file); - }*/ - m_maxList = j; + } if ( sel > j-1 ) sel = j-1; @@ -4716,7 +4690,13 @@ void CMainDialog::ChangeDisplay() bFull = pc->TestState(STATE_CHECK); m_setupFull = bFull; + SetupMemorize(); + #if !PLATFORM_LINUX + // Windows causes problems, so we'll restart the game + // Mac OS was not tested so let's restart just to be sure + m_app->Restart(); + #else std::vector<Math::IntPoint> modes; m_app->GetVideoResolutionList(modes, true, true); @@ -4724,6 +4704,7 @@ void CMainDialog::ChangeDisplay() config.size = modes[m_setupSelMode]; config.fullScreen = bFull; m_app->ChangeVideoConfig(config); + #endif } @@ -6269,7 +6250,7 @@ bool CMainDialog::WriteGamerInfo() for ( i=0 ; i<MAXSCENE ; i++ ) { - if ( m_sceneInfo[i].numTry == 0 ) continue; + if ( m_sceneInfo[i].numTry == 0 && !m_sceneInfo[i].bPassed ) continue; sprintf(line, "Chapter %d: Scene %d: numTry=%d passed=%d\n", i/100, i%100, m_sceneInfo[i].numTry, m_sceneInfo[i].bPassed); |