summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debian/changelog2
-rw-r--r--src/CMakeLists.txt10
-rw-r--r--src/app/app.cpp246
-rw-r--r--src/app/app.h1
-rw-r--r--src/app/system_linux.cpp79
-rw-r--r--src/app/system_linux.h71
-rw-r--r--src/app/system_other.cpp122
-rw-r--r--src/app/system_other.h114
-rw-r--r--src/app/system_windows.cpp98
-rw-r--r--src/app/system_windows.h95
-rw-r--r--src/common/logger.cpp82
-rw-r--r--src/common/logger.h131
-rw-r--r--src/common/misc.cpp124
-rw-r--r--src/common/misc.h3
-rw-r--r--src/common/profile.cpp45
-rw-r--r--src/common/profile.h28
-rw-r--r--src/graphics/core/color.h10
-rw-r--r--src/graphics/engine/engine.h6
-rw-r--r--src/graphics/engine/lightman.cpp100
-rw-r--r--src/graphics/engine/lightman.h21
-rw-r--r--src/graphics/engine/pyro.cpp9
-rw-r--r--src/graphics/opengl/gldevice.cpp25
-rw-r--r--src/graphics/opengl/gldevice.h14
-rw-r--r--src/object/object.cpp25
-rw-r--r--src/object/robotmain.cpp33
-rw-r--r--src/object/task/taskbuild.cpp17
-rw-r--r--src/object/task/taskshield.cpp13
-rw-r--r--src/script/script.cpp26
-rw-r--r--src/sound/oalsound/alsound.cpp11
-rw-r--r--src/sound/oalsound/channel.cpp2
-rw-r--r--src/ui/displayinfo.cpp7
-rw-r--r--src/ui/edit.cpp144
-rw-r--r--src/ui/edit.h34
-rw-r--r--src/ui/maindialog.cpp45
-rw-r--r--src/ui/maindialog.h6
-rw-r--r--src/ui/studio.cpp111
-rw-r--r--src/ui/studio.h5
-rw-r--r--test/envs/opengl/CMakeLists.txt11
-rw-r--r--test/unit/CMakeLists.txt215
-rw-r--r--test/unit/app/system_linux_test.cpp51
-rw-r--r--test/unit/graphics/core/device_mock.h107
-rw-r--r--test/unit/graphics/engine/engine_mock.h14
-rw-r--r--test/unit/graphics/engine/lightman_test.cpp146
-rw-r--r--test/unit/ui/CMakeLists.txt1
-rw-r--r--test/unit/ui/stubs/app_stub.cpp4
-rw-r--r--test/unit/ui/stubs/engine_stub.cpp17
46 files changed, 1590 insertions, 891 deletions
diff --git a/debian/changelog b/debian/changelog
index 1a0910e..75ca998 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-colobot (0.1.0~pre-alpha-git-dev~r3a594dc-1~OdyX0) UNRELEASED; urgency=low
+colobot (0.1.0~pre-alpha-git-dev~r1406464-1~OdyX0) UNRELEASED; urgency=low
* Initial release. (Closes: #695829)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e6b3acd..cc181f2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -55,11 +55,21 @@ if (${OPENAL_SOUND})
)
endif()
+# Platform-dependent implementation of system.h
+if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(SYSTEM_CPP_MODULE "system_windows.cpp")
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(SYSTEM_CPP_MODULE "system_linux.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}
common/event.cpp
common/image.cpp
common/iman.cpp
diff --git a/src/app/app.cpp b/src/app/app.cpp
index ae5ac88..cb1ac34 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -39,6 +39,7 @@
#include <stdlib.h>
#include <libintl.h>
#include <unistd.h>
+#include <getopt.h>
#ifdef OPENAL_SOUND
@@ -195,102 +196,131 @@ CEventQueue* CApplication::GetEventQueue()
CSoundInterface* CApplication::GetSound()
{
return m_sound;
+
+ for (int i = 0; i < PCNT_MAX; ++i)
+ {
+ DestroyTimeStamp(m_performanceCounters[i][0]);
+ DestroyTimeStamp(m_performanceCounters[i][1]);
+ }
}
ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
{
- bool waitDataDir = false;
- bool waitLogLevel = false;
- bool waitLanguage = false;
-
- for (int i = 1; i < argc; ++i)
+ enum OptionType
{
- std::string arg = argv[i];
-
- if (waitDataDir)
- {
- waitDataDir = false;
- m_dataPath = arg;
- GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str());
- continue;
- }
-
- if (waitLogLevel)
+ OPT_HELP = 1,
+ OPT_DEBUG,
+ OPT_DATADIR,
+ OPT_LOGLEVEL,
+ OPT_LANGUAGE,
+ OPT_VBO
+ };
+
+ option options[] =
+ {
+ { "help", no_argument, nullptr, OPT_HELP },
+ { "debug", no_argument, nullptr, OPT_DEBUG },
+ { "datadir", required_argument, nullptr, OPT_DATADIR },
+ { "loglevel", required_argument, nullptr, OPT_LOGLEVEL },
+ { "language", required_argument, nullptr, OPT_LANGUAGE },
+ { "vbo", required_argument, nullptr, OPT_VBO }
+ };
+
+ opterr = 0;
+
+ int c = 0;
+ int index = -1;
+ while ((c = getopt_long_only(argc, argv, "", options, &index)) != -1)
+ {
+ if (c == '?')
{
- waitLogLevel = false;
- if (arg == "trace")
- GetLogger()->SetLogLevel(LOG_TRACE);
- else if (arg == "debug")
- GetLogger()->SetLogLevel(LOG_DEBUG);
- else if (arg == "info")
- GetLogger()->SetLogLevel(LOG_INFO);
- else if (arg == "warn")
- GetLogger()->SetLogLevel(LOG_WARN);
- else if (arg == "error")
- GetLogger()->SetLogLevel(LOG_ERROR);
- else if (arg == "none")
- GetLogger()->SetLogLevel(LOG_NONE);
+ if (optopt == 0)
+ GetLogger()->Error("Invalid argument: %s\n", argv[optind-1]);
else
- return PARSE_ARGS_FAIL;
- continue;
- }
+ GetLogger()->Error("Expected argument for option: %s\n", argv[optind-1]);
- if (waitLanguage)
- {
- waitLanguage = false;
- if (arg == "en")
- m_language = LANGUAGE_ENGLISH;
- else if (arg == "de")
- m_language = LANGUAGE_GERMAN;
- else if (arg == "fr")
- m_language = LANGUAGE_FRENCH;
- else if (arg == "pl")
- m_language = LANGUAGE_POLISH;
- else
- return PARSE_ARGS_FAIL;
- continue;
+ m_exitCode = 1;
+ return PARSE_ARGS_FAIL;
}
- if (arg == "-debug")
- {
- SetDebugMode(true);
- }
- else if (arg == "-loglevel")
- {
- waitLogLevel = true;
- }
- else if (arg == "-datadir")
- {
- waitDataDir = true;
- }
- else if (arg == "-language")
- {
- waitLanguage = true;
- }
- else if (arg == "-help")
- {
- GetLogger()->Message("\n");
- GetLogger()->Message("Colobot %s (%s)\n",COLOBOT_CODENAME,COLOBOT_VERSION);
- GetLogger()->Message("\n");
- GetLogger()->Message("List of available options:\n");
- GetLogger()->Message(" -help this help\n");
- GetLogger()->Message(" -datadir path set custom data directory path\n");
- GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n");
- GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
- GetLogger()->Message(" -language lang set language (one of: en, de, fr, pl)\n");
- return PARSE_ARGS_HELP;
- }
- else
+ index = -1;
+
+ switch (c)
{
- m_exitCode = 1;
- return PARSE_ARGS_FAIL;
+ case OPT_HELP:
+ {
+ GetLogger()->Message("\n");
+ GetLogger()->Message("Colobot %s (%s)\n", COLOBOT_CODENAME, COLOBOT_VERSION);
+ GetLogger()->Message("\n");
+ GetLogger()->Message("List of available options:\n");
+ GetLogger()->Message(" -help this help\n");
+ GetLogger()->Message(" -debug enable debug mode (more info printed in logs)\n");
+ GetLogger()->Message(" -datadir path set custom data directory path\n");
+ GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n");
+ GetLogger()->Message(" -language lang set language (one of: en, de, fr, pl)\n");
+ GetLogger()->Message(" -vbo mode set OpenGL VBO mode (one of: auto, enable, disable)\n");
+ return PARSE_ARGS_HELP;
+ }
+ case OPT_DEBUG:
+ {
+ SetDebugMode(true);
+ break;
+ }
+ case OPT_DATADIR:
+ {
+ m_dataPath = optarg;
+ GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str());
+ break;
+ }
+ case OPT_LOGLEVEL:
+ {
+ LogLevel logLevel;
+ if (! CLogger::ParseLogLevel(optarg, logLevel))
+ {
+ GetLogger()->Error("Invalid log level: \"%s\"\n", optarg);
+ return PARSE_ARGS_FAIL;
+ }
+
+ GetLogger()->Message("[*****] Log level changed to %s\n", optarg);
+ GetLogger()->SetLogLevel(logLevel);
+ break;
+ }
+ case OPT_LANGUAGE:
+ {
+ Language language;
+ if (! ParseLanguage(optarg, language))
+ {
+ GetLogger()->Error("Invalid language: \"%s\"\n", optarg);
+ return PARSE_ARGS_FAIL;
+ }
+
+ GetLogger()->Info("Using language %s\n", optarg);
+ m_language = language;
+ break;
+ }
+ case OPT_VBO:
+ {
+ std::string vbo;
+ vbo = optarg;
+ if (vbo == "auto")
+ m_deviceConfig.vboMode = Gfx::VBO_MODE_AUTO;
+ else if (vbo == "enable")
+ m_deviceConfig.vboMode = Gfx::VBO_MODE_ENABLE;
+ else if (vbo == "disable")
+ m_deviceConfig.vboMode = Gfx::VBO_MODE_DISABLE;
+ else
+ {
+ GetLogger()->Error("Invalid vbo mode: \"%s\"\n", optarg);
+ return PARSE_ARGS_FAIL;
+ }
+
+ break;
+ }
+ default:
+ assert(false); // should never get here
}
}
- // Args not given?
- if (waitDataDir || waitLogLevel || waitLanguage)
- return PARSE_ARGS_FAIL;
-
return PARSE_ARGS_OK;
}
@@ -336,7 +366,7 @@ bool CApplication::Create()
} else {
m_sound->CacheAll(GetDataSubdirPath(DIR_SOUND));
}
-
+
if (GetProfile().GetLocalProfileString("Resources", "Music", path)) {
m_sound->AddMusicFiles(path);
} else {
@@ -376,20 +406,22 @@ bool CApplication::Create()
m_exitCode = 3;
return false;
}
-
+
// load settings from profile
int iValue;
- if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) ) {
- std::vector<Math::IntPoint> modes;
- GetVideoResolutionList(modes, true, true);
- if (static_cast<unsigned int>(iValue) < modes.size())
- m_deviceConfig.size = modes.at(iValue);
+ if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) )
+ {
+ std::vector<Math::IntPoint> modes;
+ GetVideoResolutionList(modes, true, true);
+ if (static_cast<unsigned int>(iValue) < modes.size())
+ m_deviceConfig.size = modes.at(iValue);
}
-
- if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) ) {
- m_deviceConfig.fullScreen = (iValue == 1);
+
+ if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) )
+ {
+ m_deviceConfig.fullScreen = (iValue == 1);
}
-
+
if (! CreateVideoSurface())
return false; // dialog is in function
@@ -409,7 +441,7 @@ bool CApplication::Create()
// Don't generate joystick events
SDL_JoystickEventState(SDL_IGNORE);
-
+
// The video is ready, we can create and initalize the graphics device
m_device = new Gfx::CGLDevice(m_deviceConfig);
if (! m_device->Create() )
@@ -1503,6 +1535,32 @@ char CApplication::GetLanguageChar()
return langChar;
}
+bool CApplication::ParseLanguage(const std::string& str, Language& language)
+{
+ if (str == "en")
+ {
+ language = LANGUAGE_ENGLISH;
+ return true;
+ }
+ else if (str == "de")
+ {
+ language = LANGUAGE_GERMAN;
+ return true;
+ }
+ else if (str == "fr")
+ {
+ language = LANGUAGE_FRENCH;
+ return true;
+ }
+ else if (str == "pl")
+ {
+ language = LANGUAGE_POLISH;
+ return true;
+ }
+
+ return false;
+}
+
void CApplication::SetLanguage(Language language)
{
m_language = language;
diff --git a/src/app/app.h b/src/app/app.h
index f3f5601..71a3527 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -327,6 +327,7 @@ public:
Language GetLanguage();
char GetLanguageChar();
void SetLanguage(Language language);
+ static bool ParseLanguage(const std::string& str, Language& language);
//@}
//! Management of sleep in main loop (lowers CPU usage)
diff --git a/src/app/system_linux.cpp b/src/app/system_linux.cpp
new file mode 100644
index 0000000..cd785f8
--- /dev/null
+++ b/src/app/system_linux.cpp
@@ -0,0 +1,79 @@
+// * 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/.
+
+#include "app/system_linux.h"
+
+#include <stdlib.h>
+
+
+SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ std::string options = "";
+ switch (type)
+ {
+ case SDT_INFO:
+ default:
+ options = "--info";
+ break;
+ case SDT_WARNING:
+ options = "--warning";
+ break;
+ case SDT_ERROR:
+ options = "--error";
+ break;
+ case SDT_YES_NO:
+ options = "--question --ok-label=\"Yes\" --cancel-label=\"No\"";
+ break;
+ case SDT_OK_CANCEL:
+ options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\"";
+ break;
+ }
+
+ std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\"";
+ int code = system(command.c_str());
+
+ SystemDialogResult result = SDR_OK;
+ switch (type)
+ {
+ case SDT_YES_NO:
+ result = code ? SDR_NO : SDR_YES;
+ break;
+ case SDT_OK_CANCEL:
+ result = code ? SDR_CANCEL : SDR_OK;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+void GetCurrentTimeStamp_Linux(SystemTimeStamp *stamp)
+{
+ clock_gettime(CLOCK_MONOTONIC_RAW, &stamp->clockTime);
+}
+
+long long GetTimeStampExactResolution_Linux()
+{
+ return 1ll;
+}
+
+long long TimeStampExactDiff_Linux(SystemTimeStamp *before, SystemTimeStamp *after)
+{
+ return (after->clockTime.tv_nsec - before->clockTime.tv_nsec) +
+ (after->clockTime.tv_sec - before->clockTime.tv_sec) * 1000000000ll;
+}
diff --git a/src/app/system_linux.h b/src/app/system_linux.h
index 69893de..bc07c31 100644
--- a/src/app/system_linux.h
+++ b/src/app/system_linux.h
@@ -20,20 +20,11 @@
* \brief Linux-specific implementation of system functions
*/
-/* NOTE: code is contained in this header;
- * there is no separate .cpp module for simplicity */
+#include "app/system.h"
#include <sys/time.h>
-#include <time.h>
-#include <stdlib.h>
-SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message);
-
-void GetCurrentTimeStamp_Linux(SystemTimeStamp *stamp);
-long long GetTimeStampExactResolution_Linux();
-long long TimeStampExactDiff_Linux(SystemTimeStamp *before, SystemTimeStamp *after);
-
struct SystemTimeStamp
{
timespec clockTime;
@@ -45,60 +36,8 @@ struct SystemTimeStamp
};
-SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message)
-{
- std::string options = "";
- switch (type)
- {
- case SDT_INFO:
- default:
- options = "--info";
- break;
- case SDT_WARNING:
- options = "--warning";
- break;
- case SDT_ERROR:
- options = "--error";
- break;
- case SDT_YES_NO:
- options = "--question --ok-label=\"Yes\" --cancel-label=\"No\"";
- break;
- case SDT_OK_CANCEL:
- options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\"";
- break;
- }
-
- std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\"";
- int code = system(command.c_str());
-
- SystemDialogResult result = SDR_OK;
- switch (type)
- {
- case SDT_YES_NO:
- result = code ? SDR_NO : SDR_YES;
- break;
- case SDT_OK_CANCEL:
- result = code ? SDR_CANCEL : SDR_OK;
- break;
- default:
- break;
- }
-
- return result;
-}
-
-void GetCurrentTimeStamp_Linux(SystemTimeStamp *stamp)
-{
- clock_gettime(CLOCK_MONOTONIC, &stamp->clockTime);
-}
-
-long long GetTimeStampExactResolution_Linux()
-{
- return 1ll;
-}
+SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message);
-long long TimeStampExactDiff_Linux(SystemTimeStamp *before, SystemTimeStamp *after)
-{
- return (after->clockTime.tv_nsec - before->clockTime.tv_nsec) +
- (after->clockTime.tv_sec - before->clockTime.tv_sec) * 1000000000ll;
-}
+void GetCurrentTimeStamp_Linux(SystemTimeStamp *stamp);
+long long GetTimeStampExactResolution_Linux();
+long long TimeStampExactDiff_Linux(SystemTimeStamp *before, SystemTimeStamp *after);
diff --git a/src/app/system_other.cpp b/src/app/system_other.cpp
new file mode 100644
index 0000000..006bf6d
--- /dev/null
+++ b/src/app/system_other.cpp
@@ -0,0 +1,122 @@
+// * 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/.
+
+#include "app/system_other.h"
+
+
+SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ switch (type)
+ {
+ case SDT_INFO:
+ std::cout << "INFO: ";
+ break;
+ case SDT_WARNING:
+ std::cout << "WARNING:";
+ break;
+ case SDT_ERROR:
+ std::cout << "ERROR: ";
+ break;
+ case SDT_YES_NO:
+ case SDT_OK_CANCEL:
+ std::cout << "QUESTION: ";
+ break;
+ }
+
+ std::cout << message << std::endl;
+
+ std::string line;
+
+ SystemDialogResult result = SDR_OK;
+
+ bool done = false;
+ while (!done)
+ {
+ switch (type)
+ {
+ case SDT_INFO:
+ case SDT_WARNING:
+ case SDT_ERROR:
+ std::cout << "Press ENTER to continue";
+ break;
+
+ case SDT_YES_NO:
+ std::cout << "Type 'Y' for Yes or 'N' for No";
+ break;
+
+ case SDT_OK_CANCEL:
+ std::cout << "Type 'O' for OK or 'C' for Cancel";
+ break;
+ }
+
+ std::getline(std::cin, line);
+
+ switch (type)
+ {
+ case SDT_INFO:
+ case SDT_WARNING:
+ case SDT_ERROR:
+ done = true;
+ break;
+
+ case SDT_YES_NO:
+ if (line == "Y" || line == "y")
+ {
+ result = SDR_YES;
+ done = true;
+ }
+ else if (line == "N" || line == "n")
+ {
+ result = SDR_NO;
+ done = true;
+ }
+ break;
+
+ case SDT_OK_CANCEL:
+ if (line == "O" || line == "o")
+ {
+ done = true;
+ result = SDR_OK;
+ }
+ else if (line == "C" || line == "c")
+ {
+ done = true;
+ result = SDR_CANCEL;
+ }
+ break;
+ }
+ }
+
+ return result;
+}
+
+
+
+void GetCurrentTimeStamp_Other(SystemTimeStamp *stamp)
+{
+ stamp->sdlTicks = SDL_GetTicks();
+}
+
+long long GetTimeStampExactResolution_Other()
+{
+ return 1000000ll;
+}
+
+long long TimeStampExactDiff_Other(SystemTimeStamp *before, SystemTimeStamp *after)
+{
+ return (after->sdlTicks - before->sdlTicks) * 1000000ll;
+}
diff --git a/src/app/system_other.h b/src/app/system_other.h
index eff0c8a..6fb4b86 100644
--- a/src/app/system_other.h
+++ b/src/app/system_other.h
@@ -20,20 +20,13 @@
* \brief Fallback code for other systems
*/
-/* NOTE: code is contained in this header;
- * there is no separate .cpp module for simplicity */
+#include "app/system.h"
#include <SDL/SDL.h>
#include <iostream>
-SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message);
-
-void GetCurrentTimeStamp_Other(SystemTimeStamp *stamp);
-long long GetTimeStampExactResolution_Other();
-long long TimeStampExactDiff_Other(SystemTimeStamp *before, SystemTimeStamp *after);
-
struct SystemTimeStamp
{
Uint32 sdlTicks;
@@ -45,105 +38,8 @@ struct SystemTimeStamp
};
-SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message)
-{
- switch (type)
- {
- case SDT_INFO:
- std::cout << "INFO: ";
- break;
- case SDT_WARNING:
- std::cout << "WARNING:";
- break;
- case SDT_ERROR:
- std::cout << "ERROR: ";
- break;
- case SDT_YES_NO:
- case SDT_OK_CANCEL:
- std::cout << "QUESTION: ";
- break;
- }
-
- std::cout << message << std::endl;
-
- std::string line;
-
- SystemDialogResult result = SDR_OK;
-
- bool done = false;
- while (!done)
- {
- switch (type)
- {
- case SDT_INFO:
- case SDT_WARNING:
- case SDT_ERROR:
- std::cout << "Press ENTER to continue";
- break;
-
- case SDT_YES_NO:
- std::cout << "Type 'Y' for Yes or 'N' for No";
- break;
-
- case SDT_OK_CANCEL:
- std::cout << "Type 'O' for OK or 'C' for Cancel";
- break;
- }
-
- std::getline(std::cin, line);
-
- switch (type)
- {
- case SDT_INFO:
- case SDT_WARNING:
- case SDT_ERROR:
- done = true;
- break;
-
- case SDT_YES_NO:
- if (line == "Y" || line == "y")
- {
- result = SDR_YES;
- done = true;
- }
- else if (line == "N" || line == "n")
- {
- result = SDR_NO;
- done = true;
- }
- break;
-
- case SDT_OK_CANCEL:
- if (line == "O" || line == "o")
- {
- done = true;
- result = SDR_OK;
- }
- else if (line == "C" || line == "c")
- {
- done = true;
- result = SDR_CANCEL;
- }
- break;
- }
- }
-
- return result;
-}
-
-
-
-void GetCurrentTimeStamp_Other(SystemTimeStamp *stamp)
-{
- stamp->sdlTicks = SDL_GetTicks();
-}
-
-long long GetTimeStampExactResolution_Other()
-{
- return 1000000ll;
-}
+SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message);
-long long TimeStampExactDiff_Other(SystemTimeStamp *before, SystemTimeStamp *after)
-{
- return (after->sdlTicks - before->sdlTicks) * 1000000ll;
-}
+void GetCurrentTimeStamp_Other(SystemTimeStamp *stamp);
+long long GetTimeStampExactResolution_Other();
+long long TimeStampExactDiff_Other(SystemTimeStamp *before, SystemTimeStamp *after);
diff --git a/src/app/system_windows.cpp b/src/app/system_windows.cpp
new file mode 100644
index 0000000..34fa57e
--- /dev/null
+++ b/src/app/system_windows.cpp
@@ -0,0 +1,98 @@
+// * 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/.
+
+#include "app/system_windows.h"
+
+
+// Convert a wide Unicode string to an UTF8 string
+std::string UTF8_Encode_Windows(const std::wstring &wstr)
+{
+ int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), NULL, 0, NULL, NULL);
+ std::string strTo(size_needed, 0);
+ WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), &strTo[0], size_needed, NULL, NULL);
+ return strTo;
+}
+
+// Convert an UTF8 string to a wide Unicode String
+std::wstring UTF8_Decode_Windows(const std::string &str)
+{
+ int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), NULL, 0);
+ std::wstring wstrTo(size_needed, 0);
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), &wstrTo[0], size_needed);
+ return wstrTo;
+}
+
+SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message)
+{
+ unsigned int windowsType = 0;
+ std::wstring windowsMessage = UTF8_Decode_Windows(message);
+ std::wstring windowsTitle = UTF8_Decode_Windows(title);
+
+ switch (type)
+ {
+ case SDT_INFO:
+ default:
+ windowsType = MB_ICONINFORMATION|MB_OK;
+ break;
+ case SDT_WARNING:
+ windowsType = MB_ICONWARNING|MB_OK;
+ break;
+ case SDT_ERROR:
+ windowsType = MB_ICONERROR|MB_OK;
+ break;
+ case SDT_YES_NO:
+ windowsType = MB_ICONQUESTION|MB_YESNO;
+ break;
+ case SDT_OK_CANCEL:
+ windowsType = MB_ICONWARNING|MB_OKCANCEL;
+ break;
+ }
+
+ switch (MessageBoxW(NULL, windowsMessage.c_str(), windowsTitle.c_str(), windowsType))
+ {
+ case IDOK:
+ return SDR_OK;
+ case IDCANCEL:
+ return SDR_CANCEL;
+ case IDYES:
+ return SDR_YES;
+ case IDNO:
+ return SDR_NO;
+ default:
+ break;
+ }
+
+ return SDR_OK;
+}
+
+
+void GetCurrentTimeStamp_Windows(SystemTimeStamp *stamp)
+{
+ GetSystemTimeAsFileTime(&stamp->fileTime);
+}
+
+long long GetTimeStampExactResolution_Windows()
+{
+ return 100ll;
+}
+
+long long TimeStampExactDiff_Windows(SystemTimeStamp *before, SystemTimeStamp *after)
+{
+ long long tH = (1ll << 32) * (after->fileTime.dwHighDateTime - before->fileTime.dwHighDateTime);
+ long long tL = after->fileTime.dwLowDateTime - before->fileTime.dwLowDateTime;
+ return (tH + tL) * 100ll;
+}
diff --git a/src/app/system_windows.h b/src/app/system_windows.h
index c9743e6..804d064 100644
--- a/src/app/system_windows.h
+++ b/src/app/system_windows.h
@@ -20,20 +20,11 @@
* \brief Windows-specific implementation of system functions
*/
-/* NOTE: code is contained in this header;
- * there is no separate .cpp module for simplicity */
+#include "app/system.h"
#include <windows.h>
-std::string UTF8_Encode_Windows(const std::wstring &wstr);
-std::wstring UTF8_Decode_Windows(const std::string &str);
-SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message);
-
-void GetCurrentTimeStamp_Windows(SystemTimeStamp *stamp);
-long long GetTimeStampExactResolution_Windows();
-long long TimeStampExactDiff_Windows(SystemTimeStamp *before, SystemTimeStamp *after);
-
struct SystemTimeStamp
{
FILETIME fileTime;
@@ -44,82 +35,10 @@ struct SystemTimeStamp
}
};
+std::string UTF8_Encode_Windows(const std::wstring &wstr);
+std::wstring UTF8_Decode_Windows(const std::string &str);
+SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message);
-// Convert a wide Unicode string to an UTF8 string
-std::string UTF8_Encode_Windows(const std::wstring &wstr)
-{
- int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), NULL, 0, NULL, NULL);
- std::string strTo(size_needed, 0);
- WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), &strTo[0], size_needed, NULL, NULL);
- return strTo;
-}
-
-// Convert an UTF8 string to a wide Unicode String
-std::wstring UTF8_Decode_Windows(const std::string &str)
-{
- int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), NULL, 0);
- std::wstring wstrTo(size_needed, 0);
- MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), &wstrTo[0], size_needed);
- return wstrTo;
-}
-
-SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message)
-{
- unsigned int windowsType = 0;
- std::wstring windowsMessage = UTF8_Decode_Windows(message);
- std::wstring windowsTitle = UTF8_Decode_Windows(title);
-
- switch (type)
- {
- case SDT_INFO:
- default:
- windowsType = MB_ICONINFORMATION|MB_OK;
- break;
- case SDT_WARNING:
- windowsType = MB_ICONWARNING|MB_OK;
- break;
- case SDT_ERROR:
- windowsType = MB_ICONERROR|MB_OK;
- break;
- case SDT_YES_NO:
- windowsType = MB_ICONQUESTION|MB_YESNO;
- break;
- case SDT_OK_CANCEL:
- windowsType = MB_ICONWARNING|MB_OKCANCEL;
- break;
- }
-
- switch (MessageBoxW(NULL, windowsMessage.c_str(), windowsTitle.c_str(), windowsType))
- {
- case IDOK:
- return SDR_OK;
- case IDCANCEL:
- return SDR_CANCEL;
- case IDYES:
- return SDR_YES;
- case IDNO:
- return SDR_NO;
- default:
- break;
- }
-
- return SDR_OK;
-}
-
-
-void GetCurrentTimeStamp_Windows(SystemTimeStamp *stamp)
-{
- GetSystemTimeAsFileTime(&stamp->fileTime);
-}
-
-long long GetTimeStampExactResolution_Windows()
-{
- return 100ll;
-}
-
-long long TimeStampExactDiff_Windows(SystemTimeStamp *before, SystemTimeStamp *after)
-{
- long long tH = (1ll << 32) * (after->fileTime.dwHighDateTime - before->fileTime.dwHighDateTime);
- long long tL = after->fileTime.dwLowDateTime - before->fileTime.dwLowDateTime;
- return (tH + tL) * 100ll;
-}
+void GetCurrentTimeStamp_Windows(SystemTimeStamp *stamp);
+long long GetTimeStampExactResolution_Windows();
+long long TimeStampExactDiff_Windows(SystemTimeStamp *before, SystemTimeStamp *after);
diff --git a/src/common/logger.cpp b/src/common/logger.cpp
index 3ec9746..8bc4cef 100644
--- a/src/common/logger.cpp
+++ b/src/common/logger.cpp
@@ -36,25 +36,37 @@ CLogger::~CLogger()
}
-void CLogger::Log(LogType type, const char *str, va_list args)
+void CLogger::Log(LogLevel type, const char* str, va_list args)
{
if (type < mLogLevel)
return;
- switch (type) {
- case LOG_TRACE: fprintf(IsOpened() ? mFile : stderr, "[TRACE]: "); break;
- case LOG_DEBUG: fprintf(IsOpened() ? mFile : stderr, "[DEBUG]: "); break;
- case LOG_WARN: fprintf(IsOpened() ? mFile : stderr, "[WARN]: "); break;
- case LOG_INFO: fprintf(IsOpened() ? mFile : stderr, "[INFO]: "); break;
- case LOG_ERROR: fprintf(IsOpened() ? mFile : stderr, "[ERROR]: "); break;
- default: break;
+ switch (type)
+ {
+ case LOG_TRACE:
+ fprintf(IsOpened() ? mFile : stderr, "[TRACE]: ");
+ break;
+ case LOG_DEBUG:
+ fprintf(IsOpened() ? mFile : stderr, "[DEBUG]: ");
+ break;
+ case LOG_WARN:
+ fprintf(IsOpened() ? mFile : stderr, "[WARN]: ");
+ break;
+ case LOG_INFO:
+ fprintf(IsOpened() ? mFile : stderr, "[INFO]: ");
+ break;
+ case LOG_ERROR:
+ fprintf(IsOpened() ? mFile : stderr, "[ERROR]: ");
+ break;
+ default:
+ break;
}
vfprintf(IsOpened() ? mFile : stderr, str, args);
}
-void CLogger::Trace(const char *str, ...)
+void CLogger::Trace(const char* str, ...)
{
va_list args;
va_start(args, str);
@@ -63,7 +75,7 @@ void CLogger::Trace(const char *str, ...)
}
-void CLogger::Debug(const char *str, ...)
+void CLogger::Debug(const char* str, ...)
{
va_list args;
va_start(args, str);
@@ -72,7 +84,7 @@ void CLogger::Debug(const char *str, ...)
}
-void CLogger::Info(const char *str, ...)
+void CLogger::Info(const char* str, ...)
{
va_list args;
va_start(args, str);
@@ -81,7 +93,7 @@ void CLogger::Info(const char *str, ...)
}
-void CLogger::Warn(const char *str, ...)
+void CLogger::Warn(const char* str, ...)
{
va_list args;
va_start(args, str);
@@ -90,7 +102,7 @@ void CLogger::Warn(const char *str, ...)
}
-void CLogger::Error(const char *str, ...)
+void CLogger::Error(const char* str, ...)
{
va_list args;
va_start(args, str);
@@ -99,7 +111,7 @@ void CLogger::Error(const char *str, ...)
}
-void CLogger::Message(const char *str, ...)
+void CLogger::Message(const char* str, ...)
{
va_list args;
va_start(args, str);
@@ -118,6 +130,7 @@ void CLogger::SetOutputFile(std::string filename)
void CLogger::Open()
{
mFile = fopen(mFilename.c_str(), "w");
+
if (mFile == NULL)
fprintf(stderr, "Could not create file %s\n", mFilename.c_str());
}
@@ -136,6 +149,45 @@ bool CLogger::IsOpened()
}
-void CLogger::SetLogLevel(LogType type) {
+void CLogger::SetLogLevel(LogLevel type)
+{
mLogLevel = type;
}
+
+
+bool CLogger::ParseLogLevel(const std::string& str, LogLevel& logLevel)
+{
+ if (str == "trace")
+ {
+ logLevel = LOG_TRACE;
+ return true;
+ }
+ else if (str == "debug")
+ {
+ logLevel = LOG_DEBUG;
+ return true;
+ }
+ else if (str == "info")
+ {
+ logLevel = LOG_INFO;
+ return true;
+ }
+ else if (str == "warn")
+ {
+ logLevel = LOG_WARN;
+ return true;
+ }
+ else if (str == "error")
+ {
+ logLevel = LOG_ERROR;
+ return true;
+ }
+ else if (str == "none")
+ {
+ logLevel = LOG_NONE;
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/src/common/logger.h b/src/common/logger.h
index 198e5e5..769f548 100644
--- a/src/common/logger.h
+++ b/src/common/logger.h
@@ -31,10 +31,10 @@
/**
* \public
- * \enum LogType common/logger.h
+ * \enum LogLevel common/logger.h
* \brief Enum representing log level
**/
-enum LogType
+enum LogLevel
{
LOG_TRACE = 1, /*!< lowest level, execution tracing */
LOG_DEBUG = 2, /*!< debugging messages */
@@ -53,65 +53,74 @@ enum LogType
*/
class CLogger : public CSingleton<CLogger>
{
- public:
- CLogger();
- ~CLogger();
-
- /** Write message to console or file
- * \param str - message to write
- * \param ... - additional arguments
- */
- void Message(const char *str, ...);
-
- /** Write message to console or file with LOG_TRACE level
- * \param str - message to write
- * \param ... - additional arguments
- */
- void Trace(const char *str, ...);
-
- /** Write message to console or file with LOG_DEBUG level
- * \param str - message to write
- * \param ... - additional arguments
- */
- void Debug(const char *str, ...);
-
- /** Write message to console or file with LOG_INFO level
- * \param str - message to write
- * \param ... - additional arguments
- */
- void Info(const char *str, ...);
-
- /** Write message to console or file with LOG_WARN level
- * \param str - message to write
- * \param ... - additional arguments
- */
- void Warn(const char *str, ...);
-
- /** Write message to console or file with LOG_ERROR level
- * \param str - message to write
- * \param ... - additional arguments
- */
- void Error(const char *str, ...);
-
- /** Set output file to write logs to
- * \param filename - output file to write to
- */
- void SetOutputFile(std::string filename);
-
- /** Set log level. Logs with level below will not be shown
- * \param level - minimum log level to write
- */
- void SetLogLevel(LogType level);
-
- private:
- std::string mFilename;
- FILE *mFile;
- LogType mLogLevel;
-
- void Open();
- void Close();
- bool IsOpened();
- void Log(LogType type, const char* str, va_list args);
+public:
+ CLogger();
+ ~CLogger();
+
+ /** Write message to console or file
+ * \param str - message to write
+ * \param ... - additional arguments
+ */
+ void Message(const char *str, ...);
+
+ /** Write message to console or file with LOG_TRACE level
+ * \param str - message to write
+ * \param ... - additional arguments
+ */
+ void Trace(const char *str, ...);
+
+ /** Write message to console or file with LOG_DEBUG level
+ * \param str - message to write
+ * \param ... - additional arguments
+ */
+ void Debug(const char *str, ...);
+
+ /** Write message to console or file with LOG_INFO level
+ * \param str - message to write
+ * \param ... - additional arguments
+ */
+ void Info(const char *str, ...);
+
+ /** Write message to console or file with LOG_WARN level
+ * \param str - message to write
+ * \param ... - additional arguments
+ */
+ void Warn(const char *str, ...);
+
+ /** Write message to console or file with LOG_ERROR level
+ * \param str - message to write
+ * \param ... - additional arguments
+ */
+ void Error(const char *str, ...);
+
+ /** Set output file to write logs to
+ * \param filename - output file to write to
+ */
+ void SetOutputFile(std::string filename);
+
+ /** Set log level. Logs with level below will not be shown
+ * \param level - minimum log level to write
+ */
+ void SetLogLevel(LogLevel level);
+
+ /** Parses string as a log level
+ * \param str string to parse
+ * \param logLevel result log level
+ *
+ * Valid values are "trace", "debug", "info", "warn", "error" and "none".
+ * On invalid value, returns \c false.
+ */
+ static bool ParseLogLevel(const std::string& str, LogLevel& logLevel);
+
+private:
+ std::string mFilename;
+ FILE *mFile;
+ LogLevel mLogLevel;
+
+ void Open();
+ void Close();
+ bool IsOpened();
+ void Log(LogLevel type, const char* str, va_list args);
};
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index 2bce3b8..b96abca 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -25,10 +25,6 @@
#include <time.h>
-static bool g_bUserDir = false;
-static char g_userDir[100] = "";
-
-
// Returns a non-accented letter.
char GetNoAccent(char letter)
@@ -234,72 +230,11 @@ void TimeToAscii(time_t time, char *buffer)
#endif*/
}
-
-// Makes a copy of a file.
-
-bool Xfer(char* src, char* dst)
-{
- FILE *fs, *fd;
- char *buffer;
- int len;
-
- fs = fopen(src, "rb");
- if ( fs == 0 )
- {
- return false;
- }
-
- fd = fopen(dst, "wb");
- if ( fd == 0 )
- {
- fclose(fs);
- return false;
- }
-
- buffer = static_cast<char*>(malloc(10000));
-
- while ( true )
- {
- len = fread(buffer, 1, 10000, fs);
- if ( len == 0 ) break;
- fwrite(buffer, 1, len, fd);
- }
-
- free(buffer);
- fclose(fs);
- fclose(fd);
- return true;
-}
-
-// Copy a file into the temporary folder.
-
-bool CopyFileToTemp(char* filename)
-{
- char src[100];
- char dst[100];
- char save[100];
-
- UserDir(src, filename, "textures");
-
- strcpy(save, g_userDir);
- strcpy(g_userDir, "temp");
- UserDir(dst, filename, "textures");
- strcpy(g_userDir, save);
-
- //_mkdir("temp");
- system("mkdir temp");
-
- if ( !Xfer(src, dst) ) return false;
-
- strcpy(filename, dst);
- return true;
-}
-
// Copy a list of numbered files into the temporary folder.
bool CopyFileListToTemp(char* filename, int* list, int total)
{
- char name[100];
+ /*char name[100];
char ext[10];
char file[100];
char save[100];
@@ -329,8 +264,8 @@ bool CopyFileListToTemp(char* filename, int* list, int total)
UserDir(file, filename, "textures");
strcpy(filename, file);
strcpy(g_userDir, save);
-
- return true;
+*/
+ return false;
}
@@ -342,56 +277,3 @@ void AddExt(char* filename, const char* ext)
strcat(filename, ext);
}
-
-// Specifies the user folder.
-
-void UserDir(bool bUser, const char* dir)
-{
- g_bUserDir = bUser;
- strcpy(g_userDir, dir);
-}
-
-// Replaces the string %user% by the user folder.
-// in: dir = "%user%toto.txt"
-// def = "abc\"
-// out: buffer = "abc\toto.txt"
-
-void UserDir(char* buffer, const char* dir, const char* def)
-{
- char ddir[100];
- const char* add;
-
- if ( strstr(dir, "\\") == 0 && def[0] != 0 )
- {
- sprintf(ddir, "%s\\%s", def, dir);
- }
- else
- {
- strcpy(ddir, dir);
- }
- dir = ddir;
-
- while ( *dir != 0 )
- {
- if ( dir[0] == '%' &&
- dir[1] == 'u' &&
- dir[2] == 's' &&
- dir[3] == 'e' &&
- dir[4] == 'r' &&
- dir[5] == '%' ) // %user% ?
- {
- if ( g_bUserDir ) add = g_userDir;
- else add = def;
-
- while ( *add != 0 )
- {
- *buffer++ = *add++;
- }
- dir += 6; // jumps to %user%
- continue;
- }
-
- *buffer++ = *dir++;
- }
- *buffer = 0;
-}
diff --git a/src/common/misc.h b/src/common/misc.h
index f210706..e2ddc44 100644
--- a/src/common/misc.h
+++ b/src/common/misc.h
@@ -29,8 +29,5 @@ extern char GetToLower(char letter);
extern void TimeToAscii(time_t time, char *buffer);
-extern bool CopyFileToTemp(char* filename);
extern bool CopyFileListToTemp(char* filename, int* list, int total);
extern void AddExt(char* filename, const char* ext);
-extern void UserDir(bool bUser, const char* dir);
-extern void UserDir(char* buffer, const char* dir, const char* def);
diff --git a/src/common/profile.cpp b/src/common/profile.cpp
index 18cc187..2d11217 100644
--- a/src/common/profile.cpp
+++ b/src/common/profile.cpp
@@ -182,3 +182,48 @@ std::vector< std::string > CProfile::GetLocalProfileSection(std::string section,
return ret_list;
}
+
+
+void CProfile::SetUserDir(std::string dir)
+{
+ m_userDirectory = dir;
+}
+
+
+std::string CProfile::GetUserBasedPath(std::string dir, std::string default_dir)
+{
+ std::string path = dir;
+ boost::replace_all(path, "\\", "/");
+ if (dir.find("/") == std::string::npos) {
+ path = default_dir + "/" + dir;
+ }
+
+ if (m_userDirectory.length() > 0) {
+ boost::replace_all(path, "%user%", m_userDirectory);
+ } else {
+ boost::replace_all(path, "%user%", default_dir);
+ }
+
+ 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 9bc6c37..bcd76c3 100644
--- a/src/common/profile.h
+++ b/src/common/profile.h
@@ -21,14 +21,20 @@
#pragma once
-
#include "common/singleton.h"
+// this is just to fix problem with undefined reference when compiling with c++11 support
+#define BOOST_NO_SCOPED_ENUMS
+
#include <boost/property_tree/ptree.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string/replace.hpp>
#include <string>
#include <vector>
+namespace fs = boost::filesystem;
+
/**
* \class CProfile
@@ -101,10 +107,30 @@ class CProfile : public CSingleton<CProfile>
* \return vector of values
*/
std::vector< std::string > GetLocalProfileSection(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 default_dir);
+
+ /** opy 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;
};
//! Global function to get profile instance
diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h
index 7cbd175..5d059e5 100644
--- a/src/graphics/core/color.h
+++ b/src/graphics/core/color.h
@@ -76,6 +76,16 @@ struct Color
{
return ! this->operator==(other);
}
+
+ inline Color operator*(float scale) const
+ {
+ Color c = *this;
+ c.r *= scale;
+ c.g *= scale;
+ c.b *= scale;
+ c.a *= scale;
+ return c;
+ }
};
/**
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 0647fbd..f9dfd45 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -729,7 +729,7 @@ public:
//@{
//! Management of game pause mode
void SetPause(bool pause);
- bool GetPause();
+ TEST_VIRTUAL bool GetPause();
//@}
//@{
@@ -1170,9 +1170,9 @@ public:
//! Returns the view matrix
const Math::Matrix& GetMatView();
//! Returns the camera center point
- Math::Vector GetEyePt();
+ TEST_VIRTUAL Math::Vector GetEyePt();
//! Returns the camera target point
- Math::Vector GetLookatPt();
+ TEST_VIRTUAL Math::Vector GetLookatPt();
//! Returns the horizontal direction angle of view
float GetEyeDirH();
//! Returns the vertical direction angle of view
diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp
index 4a8fd60..16c84ea 100644
--- a/src/graphics/engine/lightman.cpp
+++ b/src/graphics/engine/lightman.cpp
@@ -26,6 +26,7 @@
#include <cmath>
+#include <algorithm>
// Graphics module namespace
@@ -125,6 +126,7 @@ int CLightManager::CreateLight(LightPriority priority)
m_dynLights[index].light.type = LIGHT_DIRECTIONAL;
m_dynLights[index].light.diffuse = Color(0.5f, 0.5f, 0.5f);
+ m_dynLights[index].light.ambient = Color(0.0f, 0.0f, 0.0f);
m_dynLights[index].light.position = Math::Vector(-100.0f, 100.0f, -100.0f);
m_dynLights[index].light.direction = Math::Vector( 1.0f, -1.0f, 1.0f);
@@ -386,68 +388,35 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i)
m_lightMap[i] = -1;
- // High priority
- for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
- {
- if (! m_dynLights[i].used)
- continue;
- if (! m_dynLights[i].enabled)
- continue;
- if (Math::IsZero(m_dynLights[i].intensity.current))
- continue;
- if (m_dynLights[i].priority == LIGHT_PRI_LOW)
- continue;
-
- bool enabled = true;
- if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL)
- enabled = (m_dynLights[i].includeType == type);
-
- if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL)
- enabled = (m_dynLights[i].excludeType != type);
-
- if (enabled)
- {
- for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j)
- {
- if (m_lightMap[j] == -1)
- {
- m_lightMap[j] = i;
- break;
- }
- }
- }
- }
+ std::vector<DynamicLight> sortedLights = m_dynLights;
+ LightsComparator lightsComparator(m_engine->GetEyePt(), type);
+ std::sort(sortedLights.begin(), sortedLights.end(), lightsComparator);
- // Low priority
- for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ int lightMapIndex = 0;
+ for (int i = 0; i < static_cast<int>( sortedLights.size() ); i++)
{
- if (! m_dynLights[i].used)
+ if (! sortedLights[i].used)
continue;
- if (! m_dynLights[i].enabled)
+ if (! sortedLights[i].enabled)
continue;
- if (m_dynLights[i].intensity.current == 0.0f)
- continue;
- if (m_dynLights[i].priority == LIGHT_PRI_HIGH)
+ if (sortedLights[i].intensity.current == 0.0f)
continue;
bool enabled = true;
- if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL)
- enabled = (m_dynLights[i].includeType == type);
+ if (sortedLights[i].includeType != ENG_OBJTYPE_NULL)
+ enabled = (sortedLights[i].includeType == type);
- if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL)
- enabled = (m_dynLights[i].excludeType != type);
+ if (sortedLights[i].excludeType != ENG_OBJTYPE_NULL)
+ enabled = (sortedLights[i].excludeType != type);
if (enabled)
{
- for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j)
- {
- if (m_lightMap[j] == -1)
- {
- m_lightMap[j] = i;
- break;
- }
- }
+ m_lightMap[lightMapIndex] = i;
+ ++lightMapIndex;
}
+
+ if (lightMapIndex >= static_cast<int>( m_lightMap.size() ))
+ break;
}
for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i)
@@ -455,7 +424,8 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
int rank = m_lightMap[i];
if (rank != -1)
{
- m_device->SetLight(i, m_dynLights[rank].light);
+ sortedLights[rank].light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
+ m_device->SetLight(i, sortedLights[rank].light);
m_device->SetLightEnabled(i, true);
}
else
@@ -465,5 +435,33 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
}
}
+// -----------
+
+CLightManager::LightsComparator::LightsComparator(Math::Vector eyePos, EngineObjectType objectType)
+{
+ m_eyePos = eyePos;
+ m_objectType = objectType;
+}
+
+float CLightManager::LightsComparator::GetLightWeight(const DynamicLight& dynLight)
+{
+ bool enabled = true;
+ if (!dynLight.used || !dynLight.enabled || dynLight.intensity.current == 0.0f)
+ enabled = false;
+ else if (dynLight.includeType != ENG_OBJTYPE_NULL)
+ enabled = dynLight.includeType == m_objectType;
+ else if (dynLight.excludeType != ENG_OBJTYPE_NULL)
+ enabled = dynLight.excludeType != m_objectType;
+
+ return enabled ? ( (dynLight.light.position - m_eyePos).Length() * dynLight.priority ) : 10000.0f;
+}
+
+bool CLightManager::LightsComparator::operator()(const DynamicLight& left, const DynamicLight& right)
+{
+ float leftWeight = GetLightWeight(left);
+ float rightWeight = GetLightWeight(right);
+
+ return leftWeight < rightWeight;
+}
} // namespace Gfx
diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h
index 07dfe6a..ab66524 100644
--- a/src/graphics/engine/lightman.h
+++ b/src/graphics/engine/lightman.h
@@ -71,8 +71,8 @@ struct LightProgression
*/
enum LightPriority
{
- LIGHT_PRI_HIGH,
- LIGHT_PRI_LOW
+ LIGHT_PRI_HIGH = 1,
+ LIGHT_PRI_LOW = 2
};
/**
@@ -189,6 +189,21 @@ public:
void UpdateDeviceLights(EngineObjectType type);
protected:
+ class LightsComparator
+ {
+ public:
+ LightsComparator(Math::Vector eyePos, EngineObjectType objectType);
+
+ bool operator()(const DynamicLight& left, const DynamicLight& right);
+
+ private:
+ float GetLightWeight(const DynamicLight& dynLight);
+
+ Math::Vector m_eyePos;
+ EngineObjectType m_objectType;
+ };
+
+protected:
CEngine* m_engine;
CDevice* m_device;
@@ -196,7 +211,7 @@ protected:
float m_time;
//! List of dynamic lights
std::vector<DynamicLight> m_dynLights;
- //! Map of current light allotment: graphics light -> dynamic light
+ //! Map of current light allocation: graphics light -> dynamic light
std::vector<int> m_lightMap;
};
diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp
index 1d80fea..cab28b6 100644
--- a/src/graphics/engine/pyro.cpp
+++ b/src/graphics/engine/pyro.cpp
@@ -1318,12 +1318,9 @@ void CPyro::CreateLight(Math::Vector pos, float height)
Gfx::Light light;
light.type = LIGHT_SPOT;
- light.position.x = pos.x;
- light.position.y = pos.y+height;
- light.position.z = pos.z;
- light.direction.x = 0.0f;
- light.direction.y = -1.0f; // against the bottom
- light.direction.z = 0.0f;
+ light.ambient = Gfx::Color(0.0f, 0.0f, 0.0f);
+ light.position = Math::Vector(pos.x, pos.y+height, pos.z);
+ light.direction = Math::Vector(0.0f, -1.0f, 0.0f); // against the bottom
light.spotIntensity = 1.0f;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index 80fa9a1..beeb85e 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -51,6 +51,8 @@ void GLDeviceConfig::LoadDefault()
greenSize = 8;
alphaSize = 8;
depthSize = 24;
+
+ vboMode = VBO_MODE_AUTO;
}
@@ -99,11 +101,26 @@ bool CGLDevice::Create()
if (!m_multitextureAvailable)
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
- m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object");
- if (m_vboAvailable)
- GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n");
+ if (m_config.vboMode == VBO_MODE_ENABLE)
+ {
+ GetLogger()->Info("VBO enabled by override - using VBOs\n");
+ m_vboAvailable = true;
+ }
+ else if (m_config.vboMode == VBO_MODE_DISABLE)
+ {
+ GetLogger()->Info("VBO disabled by override - using display lists\n");
+ m_vboAvailable = false;
+ }
else
- GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n");
+ {
+ GetLogger()->Info("Auto-detecting VBO support\n");
+ m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object");
+
+ if (m_vboAvailable)
+ GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n");
+ else
+ GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n");
+ }
}
// This is mostly done in all modern hardware by default
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index 7137671..fe3f2a1 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -34,6 +34,17 @@
namespace Gfx {
/**
+ \enum VBOMode
+ \brief VBO autodetect/override
+ */
+enum VBOMode
+{
+ VBO_MODE_ENABLE, //! < override: enable
+ VBO_MODE_DISABLE, //! < override: disable
+ VBO_MODE_AUTO //! < autodetect
+};
+
+/**
\struct GLDeviceConfig
\brief Additional config with OpenGL-specific settings */
struct GLDeviceConfig : public DeviceConfig
@@ -52,6 +63,9 @@ struct GLDeviceConfig : public DeviceConfig
//! Force hardware acceleration (video mode set will fail on lack of hw accel)
bool hardwareAccel;
+ //! VBO override/autodetect
+ VBOMode vboMode;
+
//! Constructor calls LoadDefaults()
GLDeviceConfig();
diff --git a/src/object/object.cpp b/src/object/object.cpp
index 8f2a4cc..d6ac681 100644
--- a/src/object/object.cpp
+++ b/src/object/object.cpp
@@ -2248,15 +2248,10 @@ bool CObject::CreateShadowLight(float height, Gfx::Color color)
Gfx::Light light;
light.type = Gfx::LIGHT_SPOT;
- light.diffuse.r = color.r;
- light.diffuse.g = color.g;
- light.diffuse.b = color.b;
- light.position.x = pos.x;
- light.position.y = pos.y+height;
- light.position.z = pos.z;
- light.direction.x = 0.0f;
- light.direction.y = -1.0f; // against the bottom
- light.direction.z = 0.0f;
+ light.diffuse = color;
+ light.ambient = color * 0.1f;
+ light.position = Math::Vector(pos.x, pos.y+height, pos.z);
+ light.direction = Math::Vector(0.0f, -1.0f, 0.0f); // against the bottom
light.spotIntensity = 128;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
@@ -2291,15 +2286,9 @@ bool CObject::CreateEffectLight(float height, Gfx::Color color)
Gfx::Light light;
light.type = Gfx::LIGHT_SPOT;
- light.diffuse.r = color.r;
- light.diffuse.g = color.g;
- light.diffuse.b = color.b;
- light.position.x = 0.0f;
- light.position.y = 0.0f+height;
- light.position.z = 0.0f;
- light.direction.x = 0.0f;
- light.direction.y = -1.0f; // against the bottom
- light.direction.z = 0.0f;
+ light.diffuse = color;
+ light.position = Math::Vector(0.0f, height, 0.0f);
+ light.direction = Math::Vector(0.0f, -1.0f, 0.0f); // against the bottom
light.spotIntensity = 0.0f;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp
index 6efd853..2554ce4 100644
--- a/src/object/robotmain.cpp
+++ b/src/object/robotmain.cpp
@@ -661,7 +661,11 @@ CRobotMain::CRobotMain(CApplication* app)
m_showPos = false;
m_selectInsect = false;
m_showSoluce = false;
+ #ifdef NDEBUG
+ m_showAll = false;
+ #else
m_showAll = true; // for development
+ #endif
m_cheatRadar = false;
m_fixScene = false;
m_trainerPilot = false;
@@ -1142,6 +1146,7 @@ void CRobotMain::ChangePhase(Phase phase)
if (m_phase == PHASE_WIN)
{
+ m_sound->StopAll();
if (m_endingWinRank == -1)
{
ChangePhase(PHASE_TERM);
@@ -1181,20 +1186,20 @@ void CRobotMain::ChangePhase(Phase phase)
pe->SetGenericMode(true);
pe->SetFontType(Gfx::FONT_COLOBOT);
pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->ReadText("help/win.txt");
+ pe->SetHighlightCap(false);
+ pe->ReadText(std::string("help/win.txt"));
}
else
{
m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
}
+ StartMusic();
}
- m_sound->StopAll();
- StartMusic();
}
if (m_phase == PHASE_LOST)
{
+ m_sound->StopAll();
if (m_endingLostRank == -1)
{
ChangePhase(PHASE_TERM);
@@ -1211,9 +1216,9 @@ void CRobotMain::ChangePhase(Phase phase)
ddim.x = dim.x*2; ddim.y = dim.y*2;
m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
+
+ StartMusic();
}
- m_sound->StopAll();
- StartMusic();
}
if (m_phase == PHASE_LOADING)
@@ -3833,7 +3838,12 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
int rankObj = 0;
int rankGadget = 0;
CObject* sel = 0;
+
+ std::string oldLocale;
char *locale = setlocale(LC_NUMERIC, nullptr);
+ if (locale != nullptr)
+ oldLocale = locale;
+
setlocale(LC_NUMERIC, "C");
while (fgets(line, 500, file) != NULL)
@@ -4084,8 +4094,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
{
OpString(line, "image", name);
AddExt(name, ".png");
- if (strstr(name, "%user%") != 0)
- CopyFileToTemp(name);
+ if (strstr(name, "%user%") != 0) {
+ GetProfile().CopyFileToTemp(std::string(name));
+ }
m_terrain->AddMaterial(OpInt(line, "id", 0),
name,
@@ -4568,8 +4579,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
}
m_dialog->SetSceneRead("");
m_dialog->SetStackRead("");
-
- setlocale(LC_NUMERIC, locale);
+
+ setlocale(LC_NUMERIC, oldLocale.c_str());
}
//! Creates an object of decoration mobile or stationary
@@ -4917,6 +4928,7 @@ int CRobotMain::CreateLight(Math::Vector direction, Gfx::Color color)
Gfx::Light light;
light.type = Gfx::LIGHT_DIRECTIONAL;
light.diffuse = color;
+ light.ambient = color * 0.1f;
light.direction = direction;
int obj = m_lightMan->CreateLight(Gfx::LIGHT_PRI_HIGH);
m_lightMan->SetLight(obj, light);
@@ -4934,6 +4946,7 @@ int CRobotMain::CreateSpot(Math::Vector pos, Gfx::Color color)
Gfx::Light light;
light.type = Gfx::LIGHT_SPOT;
light.diffuse = color;
+ light.ambient = color * 0.1f;
light.position = pos;
light.direction = Math::Vector(0.0f, -1.0f, 0.0f);
light.spotIntensity = 1.0f;
diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp
index f209cd5..b9af475 100644
--- a/src/object/task/taskbuild.cpp
+++ b/src/object/task/taskbuild.cpp
@@ -114,7 +114,6 @@ bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle)
void CTaskBuild::CreateLight()
{
- Gfx::Light light;
Gfx::Color color;
Math::Vector center, pos, dir;
Math::Point c, p;
@@ -141,18 +140,12 @@ void CTaskBuild::CreateLight()
pos.y = center.y+40.0f;
dir = center-pos;
- memset(&light, 0, sizeof(light));
+ Gfx::Light light;
light.type = Gfx::LIGHT_SPOT;
- light.diffuse.r = 0.0f;
- light.diffuse.g = 0.0f;
- light.diffuse.b = 0.0f; // white (invisible)
- light.position.x = pos.x;
- light.position.y = pos.y;
- light.position.z = pos.z;
- light.direction.x = dir.x;
- light.direction.y = dir.y;
- light.direction.z = dir.z;
- //TODO Is this value correct
+ light.ambient = Gfx::Color(0.0f, 0.0f, 0.0f);
+ light.diffuse = Gfx::Color(0.0f, 0.0f, 0.0f); // invisible
+ light.position = pos;
+ light.direction = dir;
light.spotIntensity = 128;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp
index 4b2fccd..929dd5c 100644
--- a/src/object/task/taskshield.cpp
+++ b/src/object/task/taskshield.cpp
@@ -488,15 +488,10 @@ bool CTaskShield::CreateLight(Math::Vector pos)
memset(&light, 0, sizeof(light));
light.type = Gfx::LIGHT_SPOT;
- light.diffuse.r = 0.0f;
- light.diffuse.g = 1.0f;
- light.diffuse.b = 2.0f;
- light.position.x = pos.x;
- light.position.y = pos.y;
- light.position.z = pos.z;
- light.direction.x = 0.0f;
- light.direction.y = -1.0f; // against the bottom
- light.direction.z = 0.0f;
+ light.ambient = Gfx::Color(0.0f, 0.0f, 0.0f);
+ light.diffuse = Gfx::Color(0.0f, 1.0f, 2.0f);
+ light.position = pos;
+ light.direction = Math::Vector(0.0f, -1.0f, 0.0f); // against the bottom
light.spotIntensity = 128;
light.attenuation0 = 1.0f;
light.attenuation1 = 0.0f;
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 977070f..a62866d 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -948,10 +948,8 @@ bool CScript::rDirection(CBotVar* var, CBotVar* result, int& exception, void* us
}
-// Compilation of the instruction "produce(pos, angle, type, scriptName, power)".
-// or "produce(pos, angle, type, scriptName)"
-// or "produce(pos, angle, type)"
-// or "produce(type)"
+// Compilation of the instruction "produce(pos, angle, type[, scriptName[, power]])"
+// or "produce(type[, power])".
CBotTypResult CScript::cProduce(CBotVar* &var, void* user)
{
@@ -961,6 +959,10 @@ CBotTypResult CScript::cProduce(CBotVar* &var, void* user)
if ( var->GetType() <= CBotTypDouble ) {
var = var->GetNext();
+ if( var != 0 ) {
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ }
} else {
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
@@ -989,10 +991,8 @@ CBotTypResult CScript::cProduce(CBotVar* &var, void* user)
return CBotTypResult(CBotTypFloat);
}
-// Instruction "produce(pos, angle, type, scriptName, power)".
-// or "produce(pos, angle, type, scriptName)"
-// or "produce(pos, angle, type)"
-// or "produce(type)"
+// Instruction "produce(pos, angle, type[, scriptName[, power]])"
+// or "produce(type[, power])".
bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user)
{
@@ -1008,13 +1008,17 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
if ( var->GetType() <= CBotTypDouble ) {
type = static_cast<ObjectType>(var->GetValInt());
+ var = var->GetNext();
pos = me->GetPosition(0);
Math::Vector rotation = me->GetAngle(0) + me->GetInclinaison();
angle = rotation.y;
- power = -1.0f;
+ if( var != 0 )
+ power = var->GetValFloat();
+ else
+ power = -1.0f;
name = "";
} else {
@@ -2457,6 +2461,8 @@ bool CScript::rJet(CBotVar* var, CBotVar* result, int& exception, void* user)
float value;
value = var->GetValFloat();
+ if( value > 1.0f ) value = 1.0f;
+
physics->SetMotorSpeedY(value);
return true;
@@ -3894,7 +3900,7 @@ bool CScript::WriteScript(const char* filename)
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
edit->SetAutoIndent(m_engine->GetEditIndentMode());
edit->SetText(m_script);
- edit->WriteText(name.c_str());
+ edit->WriteText(name);
m_interface->DeleteControl(EVENT_EDIT9);
return true;
}
diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp
index 17a46fe..8c1cb81 100644
--- a/src/sound/oalsound/alsound.cpp
+++ b/src/sound/oalsound/alsound.cpp
@@ -136,7 +136,7 @@ void ALSound::SetMusicVolume(int volume)
{
mMusicVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f);
if (mCurrentMusic) {
- mCurrentMusic->SetVolume(mMusicVolume);
+ mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume);
}
}
@@ -318,7 +318,7 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc
Position(channel, pos);
// setting initial values
- mChannels[channel]->SetStartAmplitude(amplitude * mAudioVolume);
+ mChannels[channel]->SetStartAmplitude(amplitude);
mChannels[channel]->SetStartFrequency(frequency);
mChannels[channel]->SetChangeFrequency(1.0f);
mChannels[channel]->ResetOper();
@@ -434,7 +434,7 @@ bool ALSound::MuteAll(bool bMute)
volume = mAudioVolume;
for (auto channel : mChannels) {
- channel.second->SetVolume(volume);
+ channel.second->SetVolume(volume * mAudioVolume);
}
return true;
@@ -468,7 +468,6 @@ void ALSound::FrameMove(float delta)
// setting frequency
frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency() * it.second->GetInitFrequency();
it.second->AdjustFrequency(frequency);
- GetLogger()->Error("%f\n", frequency);
if (oper.totalTime <= oper.currentTime) {
if (oper.nextOper == SOPER_LOOP) {
@@ -509,7 +508,7 @@ bool ALSound::PlayMusic(int rank, bool bRepeat)
GetLogger()->Debug("Music loaded from cache\n");
mCurrentMusic->SetBuffer(music);
- mCurrentMusic->SetVolume(mMusicVolume);
+ mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume);
mCurrentMusic->SetLoop(bRepeat);
mCurrentMusic->Play();
return true;
@@ -534,7 +533,7 @@ bool ALSound::PlayMusic(int rank, bool bRepeat)
mMusicCache[rank] = buffer;
}
- mCurrentMusic->SetVolume(mMusicVolume);
+ mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume);
mCurrentMusic->SetLoop(bRepeat);
mCurrentMusic->Play();
diff --git a/src/sound/oalsound/channel.cpp b/src/sound/oalsound/channel.cpp
index 0faecd0..19394c6 100644
--- a/src/sound/oalsound/channel.cpp
+++ b/src/sound/oalsound/channel.cpp
@@ -94,7 +94,7 @@ bool Channel::AdjustFrequency(float freq)
if (!mReady || mBuffer == nullptr)
return false;
- return SetFrequency(mInitFrequency + freq);
+ return SetFrequency(mInitFrequency + fabs(freq));
}
diff --git a/src/ui/displayinfo.cpp b/src/ui/displayinfo.cpp
index a9e754f..974cd60 100644
--- a/src/ui/displayinfo.cpp
+++ b/src/ui/displayinfo.cpp
@@ -381,7 +381,7 @@ void CDisplayInfo::StartDisplayInfo(std::string filename, int index, bool bSoluc
edit->ReadText(filename.c_str());
edit->HyperHome(filename.c_str());
edit->SetEditCap(false); // just to see!
- edit->SetHiliteCap(false);
+ edit->SetHighlightCap(false);
edit->SetFocus(true);
ViewDisplayInfo();
@@ -455,6 +455,7 @@ void CDisplayInfo::StartDisplayInfo(std::string filename, int index, bool bSoluc
}
light.type = Gfx::LIGHT_DIRECTIONAL;
+ light.ambient = Gfx::Color(0.0f, 0.0f, 0.0f);
light.diffuse = Gfx::Color(1.0f, 0.1f, 0.1f);
light.direction = Math::Vector(1.0f, 0.0f, 1.0f);
@@ -670,7 +671,7 @@ void CDisplayInfo::ChangeIndexButton(int index)
{
filename = m_main->GetDisplayInfoName(m_index);
edit->ReadText(filename);
- edit->HyperHome(filename);
+ edit->HyperHome(std::string(filename));
SetPosition(m_main->GetDisplayInfoPosition(m_index));
}
@@ -784,7 +785,7 @@ void CDisplayInfo::UpdateIndexButton()
if ( edit != 0 )
{
//? edit->SetHiliteCap(m_index==SATCOM_LOADING);
- edit->SetHiliteCap(true);
+ edit->SetHighlightCap(true);
}
UpdateCopyButton();
diff --git a/src/ui/edit.cpp b/src/ui/edit.cpp
index c0b6446..e4bb3a3 100644
--- a/src/ui/edit.cpp
+++ b/src/ui/edit.cpp
@@ -560,7 +560,7 @@ bool CEdit::IsLinkPos(Math::Point pos)
if ( i == -1 ) return false;
if ( i >= m_len ) return false;
- if ( m_format.size() > i && ((m_format[i] & Gfx::FONT_MASK_HIGHLIGHT) == Gfx::FONT_HIGHLIGHT_LINK)) return true; // TODO
+ if ( m_format.size() > static_cast<unsigned int>(i) && ((m_format[i] & Gfx::FONT_MASK_HIGHLIGHT) == Gfx::FONT_HIGHLIGHT_LINK)) return true; // TODO
return false;
}
@@ -760,7 +760,7 @@ void CEdit::HyperFlush()
// Indicates which is the home page.
-void CEdit::HyperHome(const char *filename)
+void CEdit::HyperHome(std::string filename)
{
HyperFlush();
HyperAdd(filename, 0);
@@ -768,10 +768,10 @@ void CEdit::HyperHome(const char *filename)
// Performs a hyper jump through a link.
-void CEdit::HyperJump(const char *name, const char *marker)
+void CEdit::HyperJump(std::string name, std::string marker)
{
- char filename[100];
- char sMarker[100];
+ std::string filename;
+ std:: string sMarker;
int i, line, pos;
if ( m_historyCurrent >= 0 )
@@ -779,18 +779,16 @@ void CEdit::HyperJump(const char *name, const char *marker)
m_history[m_historyCurrent].firstLine = m_lineFirst;
}
- strcpy(sMarker, marker);
+ sMarker = marker;
//? sprintf(filename, "help\\%s.txt", name);
- if ( name[0] == '%' )
- {
- UserDir(filename, name, "");
- strcat(filename, ".txt");
- }
- else
- {
- sprintf(filename, "help\\%s.txt", name);
+
+ if ( name[0] == '%' ) {
+ filename = GetProfile().GetUserBasedPath(name, "") + ".txt";
+ } else {
+ filename = "/help/" + name + ".txt";
}
+
if ( ReadText(filename) )
{
Justif();
@@ -798,7 +796,7 @@ void CEdit::HyperJump(const char *name, const char *marker)
line = 0;
for ( i=0 ; i<m_markerTotal ; i++ )
{
- if ( strcmp(sMarker, m_marker[i].name) == 0 )
+ if (sMarker == m_marker[i].name)
{
pos = m_marker[i].pos;
for ( i=0 ; i<m_lineTotal ; i++ )
@@ -819,12 +817,12 @@ void CEdit::HyperJump(const char *name, const char *marker)
// Adds text to the history of visited.
-bool CEdit::HyperAdd(const char *filename, int firstLine)
+bool CEdit::HyperAdd(std::string filename, int firstLine)
{
if ( m_historyCurrent >= EDITHISTORYMAX-1 ) return false;
m_historyCurrent ++;
- strcpy(m_history[m_historyCurrent].filename, filename);
+ m_history[m_historyCurrent].filename = filename;
m_history[m_historyCurrent].firstLine = firstLine;
m_historyTotal = m_historyCurrent+1;
@@ -1136,16 +1134,14 @@ void CEdit::Draw()
// Draw an image part.
-void CEdit::DrawImage(Math::Point pos, const char *name, float width,
+void CEdit::DrawImage(Math::Point pos, std::string name, float width,
float offset, float height, int nbLine)
{
- Math::Point uv1, uv2, dim;
- float dp;
- char filename[100];
+ Math::Point uv1, uv2, dim;
+ float dp;
+ std::string filename;
-//? sprintf(filename, "diagram\\%s.png", name);
- UserDir(filename, name, "diagram");
- strcat(filename, ".png");
+ filename = GetProfile().GetUserBasedPath(name, "diagram") + ".png";
m_engine->SetTexture(filename);
m_engine->SetState(Gfx::ENG_RSTATE_NORMAL);
@@ -1389,77 +1385,58 @@ int CEdit::GetTextLength()
// Returns a name in a command.
// \x nom1 nom2 nom3;
-void GetNameParam(const char *cmd, int rank, char *buffer)
+std::string GetNameParam(std::string cmd, int rank)
{
- int i;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( *cmd != ' ' && *cmd != ';' )
- {
- cmd ++;
- }
- if ( *cmd != ';' ) cmd ++;
+ std::vector<std::string> results;
+ boost::split(results, cmd, boost::is_any_of(" ;"));
+
+ if (results.size() > static_cast<unsigned int>(rank)) {
+ return results.at(rank);
}
- while ( *cmd != ' ' && *cmd != ';' )
- {
- *buffer++ = *cmd++;
- }
- *buffer = 0;
+ return "";
}
// Returns a number of a command.
// \x nom n1 n2;
-int GetValueParam(const char *cmd, int rank)
+int GetValueParam(std::string cmd, int rank)
{
- int n, i;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( *cmd != ' ' && *cmd != ';' )
- {
- cmd ++;
- }
- if ( *cmd != ';' ) cmd ++;
+ std::vector<std::string> results;
+ boost::split(results, cmd, boost::is_any_of(" ;"));
+ int return_value = 0;
+
+ if (results.size() > static_cast<unsigned int>(rank)) {
+ return_value = atoi(results.at(rank).c_str());
}
- sscanf(cmd, "%d", &n);
- return n;
+ return return_value;
}
// Frees all images.
void CEdit::FreeImage()
{
- char filename[100];
- int i;
+ std::string filename;
- for ( i=0 ; i<m_imageTotal ; i++ )
- {
-//? sprintf(filename, "diagram\\%s.png", m_image[i].name);
- UserDir(filename, m_image[i].name, "diagram");
- strcat(filename, ".png");
+ for (int i = 0 ; i < m_imageTotal; i++ ) {
+ filename = GetProfile().GetUserBasedPath(m_image[i].name, "diagram") + ".png";
m_engine->DeleteTexture(filename);
}
}
// Reads the texture of an image.
-void CEdit::LoadImage(const char *name)
+void CEdit::LoadImage(std::string name)
{
- char filename[100];
-
-//? sprintf(filename, "diagram\\%s.png", name);
- UserDir(filename, name, "diagram");
- strcat(filename, ".png");
+ std::string filename;
+ filename = GetProfile().GetUserBasedPath(name, "diagram") + ".png";
m_engine->LoadTexture(filename);
}
// Read from a text file.
-bool CEdit::ReadText(const char *filename, int addSize)
+bool CEdit::ReadText(std::string filename, int addSize)
{
FILE *file = NULL;
char *buffer;
@@ -1471,7 +1448,16 @@ bool CEdit::ReadText(const char *filename, int addSize)
bool bInSoluce, bBOL;
if ( filename[0] == 0 ) return false;
- file = fopen(filename, "rb");
+ boost::replace_all(filename, "\\", "/");
+
+ /* This is ugly but doesn't require many changes in code. If file doesn't
+ exists it's posible filename is absolute not full path */
+ std::string path = filename;
+ if (!fs::exists(path)) {
+ path = CApplication::GetInstancePointer()->GetDataDirPath() + "/" + filename;
+ }
+
+ file = fopen(fs::path(path).make_preferred().string().c_str(), "rb");
if ( file == NULL ) return false;
fseek(file, 0, SEEK_END);
@@ -1605,8 +1591,8 @@ bool CEdit::ReadText(const char *filename, int addSize)
{
if ( iLink < EDITLINKMAX )
{
- GetNameParam(buffer+i+3, 0, m_link[iLink].name);
- GetNameParam(buffer+i+3, 1, m_link[iLink].marker);
+ m_link[iLink].name = GetNameParam(buffer+i+3, 0);
+ m_link[iLink].marker = GetNameParam(buffer+i+3, 1);
iLink ++;
}
font &= ~Gfx::FONT_MASK_HIGHLIGHT;
@@ -1622,7 +1608,7 @@ bool CEdit::ReadText(const char *filename, int addSize)
{
if ( m_markerTotal < EDITLINKMAX )
{
- GetNameParam(buffer+i+3, 0, m_marker[m_markerTotal].name);
+ m_marker[m_markerTotal].name = GetNameParam(buffer+i+3, 0);
m_marker[m_markerTotal].pos = j;
m_markerTotal ++;
}
@@ -1640,21 +1626,19 @@ bool CEdit::ReadText(const char *filename, int addSize)
{
if ( m_bSoluce || !bInSoluce )
{
-#if _DEMO
- strcpy(iName, "demo");
-#else
- GetNameParam(buffer+i+7, 0, iName);
-#endif
+
+ strcpy(iName, GetNameParam(buffer+i+7, 0).c_str());
+
//? iWidth = m_lineHeight*RetValueParam(buffer+i+7, 1);
iWidth = static_cast<float>(GetValueParam(buffer+i+7, 1));
iWidth *= m_engine->GetText()->GetHeight(Gfx::FONT_COLOBOT, Gfx::FONT_SIZE_SMALL);
iLines = GetValueParam(buffer+i+7, 2);
- LoadImage(iName);
+ LoadImage(std::string(iName));
// A part of image per line of text.
for ( iCount=0 ; iCount<iLines ; iCount++ )
{
- strcpy(m_image[iIndex].name, iName);
+ m_image[iIndex].name = iName;
m_image[iIndex].offset = static_cast<float>(iCount/iLines);
m_image[iIndex].height = 1.0f/iLines;
m_image[iIndex].width = iWidth*0.75f;
@@ -1888,7 +1872,7 @@ bool CEdit::ReadText(const char *filename, int addSize)
// Writes all the text in a file.
-bool CEdit::WriteText(const char *filename)
+bool CEdit::WriteText(std::string filename)
{
FILE* file;
char buffer[1000+20];
@@ -1896,7 +1880,7 @@ bool CEdit::WriteText(const char *filename)
float iDim;
if ( filename[0] == 0 ) return false;
- file = fopen(filename, "wb");
+ file = fopen(filename.c_str(), "wb");
if ( file == NULL ) return false;
if ( m_bAutoIndent )
@@ -1998,12 +1982,12 @@ bool CEdit::GetEditCap()
// Mode management "hilitable" (that's the franch).
-void CEdit::SetHiliteCap(bool bEnable)
+void CEdit::SetHighlightCap(bool bEnable)
{
m_bHilite = bEnable;
}
-bool CEdit::GetHiliteCap()
+bool CEdit::GetHighlightCap()
{
return m_bHilite;
}
diff --git a/src/ui/edit.h b/src/ui/edit.h
index 8f46445..1cfec80 100644
--- a/src/ui/edit.h
+++ b/src/ui/edit.h
@@ -35,7 +35,13 @@
#include "common/restext.h"
#include <set>
+#include <string>
+#include <cstdlib>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace fs = boost::filesystem;
namespace Ui {
@@ -84,7 +90,7 @@ enum OperUndo
struct ImageLine
{
//! name of the image (without diagram \)
- char name[40];
+ std::string name;
//! vertical offset (v texture)
float offset;
//! height of the part (dv texture)
@@ -96,15 +102,15 @@ struct ImageLine
struct HyperLink
{
//! text file name (without help \)
- char name[40];
+ std::string name;
//! name of the marker
- char marker[20];
+ std::string marker;
};
struct HyperMarker
{
//! name of the marker
- char name[20];
+ std::string name;
//! position in the text
int pos;
};
@@ -112,7 +118,7 @@ struct HyperMarker
struct HyperHistory
{
//! full file name text
- char filename[50];
+ std::string filename;
//! rank of the first displayed line
int firstLine;
};
@@ -140,8 +146,8 @@ public:
char* GetText();
int GetTextLength();
- bool ReadText(const char *filename, int addSize=0);
- bool WriteText(const char *filename);
+ bool ReadText(std::string filename, int addSize=0);
+ bool WriteText(std::string filename);
void SetMaxChar(int max);
int GetMaxChar();
@@ -149,8 +155,8 @@ public:
void SetEditCap(bool bMode);
bool GetEditCap();
- void SetHiliteCap(bool bEnable);
- bool GetHiliteCap();
+ void SetHighlightCap(bool bEnable);
+ bool GetHighlightCap();
void SetInsideScroll(bool bInside);
bool GetInsideScroll();
@@ -183,7 +189,7 @@ public:
bool Undo();
void HyperFlush();
- void HyperHome(const char *filename);
+ void HyperHome(std::string filename);
bool HyperTest(EventType event);
bool HyperGo(EventType event);
@@ -202,15 +208,15 @@ protected:
int MouseDetect(Math::Point mouse);
void MoveAdjust();
- void HyperJump(const char *name, const char *marker);
- bool HyperAdd(const char *filename, int firstLine);
+ void HyperJump(std::string name, std::string marker);
+ bool HyperAdd(std::string filename, int firstLine);
- void DrawImage(Math::Point pos, const char *name, float width, float offset, float height, int nbLine);
+ void DrawImage(Math::Point pos, std::string name, float width, float offset, float height, int nbLine);
void DrawBack(Math::Point pos, Math::Point dim);
void DrawPart(Math::Point pos, Math::Point dim, int icon);
void FreeImage();
- void LoadImage(const char *name);
+ void LoadImage(std::string name);
void Scroll(int pos, bool bAdjustCursor);
void Scroll();
void MoveChar(int move, bool bWord, bool bSelect);
diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp
index fede0b7..8b97f4e 100644
--- a/src/ui/maindialog.cpp
+++ b/src/ui/maindialog.cpp
@@ -745,6 +745,10 @@ pb->SetState(STATE_SHADOW);
m_phase == PHASE_USER ||
m_phase == PHASE_PROTO )
{
+ if (!m_sound->IsPlayingMusic()) {
+ m_sound->PlayMusic(11, true);
+ }
+
if ( m_phase == PHASE_TRAINER ) m_index = 0;
if ( m_phase == PHASE_DEFI ) m_index = 1;
if ( m_phase == PHASE_MISSION ) m_index = 2;
@@ -887,7 +891,7 @@ pb->SetState(STATE_SHADOW);
pe->SetState(STATE_SHADOW);
pe->SetMaxChar(500);
pe->SetEditCap(false); // just to see
- pe->SetHiliteCap(false);
+ pe->SetHighlightCap(false);
// Button displays the "soluce":
if ( m_phase != PHASE_TRAINER &&
@@ -1811,7 +1815,7 @@ pos.y -= 0.048f;
pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
pe->SetGenericMode(true);
pe->SetEditCap(false);
- pe->SetHiliteCap(false);
+ pe->SetHighlightCap(false);
pe->SetFontType(Gfx::FONT_COURIER);
pe->SetFontSize(8.0f);
pe->ReadText("help/authors.txt");
@@ -1823,7 +1827,7 @@ pos.y -= 0.048f;
pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT2);
pe->SetGenericMode(true);
pe->SetEditCap(false);
- pe->SetHiliteCap(false);
+ pe->SetHighlightCap(false);
pe->SetFontType(Gfx::FONT_COURIER);
pe->SetFontSize(6.5f);
pe->ReadText("help/licences.txt");
@@ -1843,7 +1847,7 @@ ddim.y = 150.0f/480.0f;
pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
pe->SetGenericMode(true);
pe->SetEditCap(false);
- pe->SetHiliteCap(false);
+ pe->SetHighlightCap(false);
pe->SetFontType(Gfx::FONT_COURIER);
pe->SetFontSize(8.0f);
pe->ReadText("help/authors.txt");
@@ -1876,7 +1880,7 @@ ddim.y = 150.0f/480.0f;
// TODO: #if !_DEMO
pos.x = 40.0f/640.0f;
- pos.y = 83.0f/480.0f;
+ pos.y = 65.0f/480.0f;
ddim.x = 246.0f/640.0f;
ddim.y = 16.0f/480.0f;
GetResource(RES_TEXT, RT_GENERIC_DEV1, name);
@@ -1884,14 +1888,14 @@ ddim.y = 150.0f/480.0f;
pl->SetFontType(Gfx::FONT_COURIER);
pl->SetFontSize(8.0f);
- pos.y = 13.0f/480.0f;
+ pos.y = 0.0f/480.0f;
GetResource(RES_TEXT, RT_GENERIC_DEV2, name);
pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
pl->SetFontType(Gfx::FONT_COURIER);
pl->SetFontSize(8.0f);
pos.x = 355.0f/640.0f;
- pos.y = 83.0f/480.0f;
+ pos.y = 65.0f/480.0f;
ddim.x = 246.0f/640.0f;
ddim.y = 16.0f/480.0f;
GetResource(RES_TEXT, RT_GENERIC_EDIT1, name);
@@ -1899,7 +1903,7 @@ ddim.y = 150.0f/480.0f;
pl->SetFontType(Gfx::FONT_COURIER);
pl->SetFontSize(8.0f);
- pos.y = 13.0f/480.0f;
+ pos.y = 0.0f/480.0f;
GetResource(RES_TEXT, RT_GENERIC_EDIT2, name);
pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL4, name);
pl->SetFontType(Gfx::FONT_COURIER);
@@ -3555,11 +3559,11 @@ void CMainDialog::SetUserDir(char *base, int rank)
if ( strcmp(base, "user") == 0 && rank >= 100 )
{
dir = m_userDir + "/" + m_userList.at(rank/100-1);
- UserDir(true, dir.c_str());
+ GetProfile().SetUserDir(dir);
}
else
{
- UserDir(false, "");
+ GetProfile().SetUserDir("");
}
}
@@ -4254,7 +4258,6 @@ bool CMainDialog::IsIOReadScene()
FILE* file;
std::string filename;
- //TODO: Change this to point user dir acocrding to operating system
filename = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + "000/data.sav";
file = fopen(filename.c_str(), "r");
if ( file == NULL ) return false;
@@ -4350,7 +4353,7 @@ void CMainDialog::IOReadList()
filename = m_savegameDir + "/" + m_main->GetGamerName() + "/save" + m_sceneName[0] + rankStream.str()+ "/data.sav";
// sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->GetGamerName(), m_sceneName[0], j);
- file = fopen(filename.c_str(), "r");
+ file = fopen(fs::path(filename).make_preferred().string().c_str(), "r");
if ( file == NULL ) break;
while ( fgets(line, 500, file) != NULL )
@@ -5042,8 +5045,8 @@ void CMainDialog::UpdateDisplayDevice()
CWindow* pw;
CList* pl;
char bufDevices[1000];
- char bufModes[5000];
- int i, j, totalDevices, selectDevices, totalModes, selectModes;
+ //char bufModes[5000];
+ int i, j;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
if ( pw == 0 ) return;
@@ -5051,7 +5054,7 @@ void CMainDialog::UpdateDisplayDevice()
if ( pl == 0 ) return;
pl->Flush();
- bufModes[0] = 0;
+ //bufModes[0] = 0;
/* TODO: remove device choice
m_engine->EnumDevices(bufDevices, 1000,
bufModes, 5000,
@@ -5066,10 +5069,10 @@ void CMainDialog::UpdateDisplayDevice()
while ( bufDevices[i++] != 0 );
}
- pl->SetSelect(selectDevices);
+ pl->SetSelect(0);
pl->ShowSelect(false);
- m_setupSelDevice = selectDevices;
+ m_setupSelDevice = 0;
}
// Updates the list of modes.
@@ -5106,8 +5109,8 @@ void CMainDialog::ChangeDisplay()
CWindow* pw;
CList* pl;
CCheck* pc;
- char* device;
- char* mode;
+ //char* device;
+ //char* mode;
bool bFull;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
@@ -5116,12 +5119,12 @@ void CMainDialog::ChangeDisplay()
pl = static_cast<CList*>(pw->SearchControl(EVENT_LIST1));
if ( pl == 0 ) return;
m_setupSelDevice = pl->GetSelect();
- device = pl->GetName(m_setupSelDevice);
+ //device = pl->GetName(m_setupSelDevice);
pl = static_cast<CList*>(pw->SearchControl(EVENT_LIST2));
if ( pl == 0 ) return;
m_setupSelMode = pl->GetSelect();
- mode = pl->GetName(m_setupSelMode);
+ //mode = pl->GetName(m_setupSelMode);
pc = static_cast<CCheck*>(pw->SearchControl(EVENT_INTERFACE_FULL));
if ( pc == 0 ) return;
diff --git a/src/ui/maindialog.h b/src/ui/maindialog.h
index be61299..a79b95e 100644
--- a/src/ui/maindialog.h
+++ b/src/ui/maindialog.h
@@ -23,6 +23,12 @@
#include "object/robotmain.h"
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace fs = boost::filesystem;
+
+
class CEventQueue;
class CSoundInterface;
diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp
index bf2ff33..da18d83 100644
--- a/src/ui/studio.cpp
+++ b/src/ui/studio.cpp
@@ -990,13 +990,13 @@ void CStudio::UpdateButtons()
{
edit->SetIcon(1); // red background
edit->SetEditCap(false); // just to see
- edit->SetHiliteCap(true);
+ edit->SetHighlightCap(true);
}
else
{
edit->SetIcon(0); // standard background
edit->SetEditCap(true);
- edit->SetHiliteCap(true);
+ edit->SetHighlightCap(true);
}
button = static_cast< CButton* >(pw->SearchControl(EVENT_STUDIO_COMPILE));
@@ -1477,8 +1477,7 @@ void CStudio::UpdateDialogPublic()
CCheck* pc;
CLabel* pl;
char name[100];
- char dir[MAX_FNAME];
- char text[MAX_FNAME+100];
+ //char text[MAX_FNAME+100];
pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9));
if ( pw == nullptr ) return;
@@ -1499,9 +1498,7 @@ void CStudio::UpdateDialogPublic()
if ( pl != 0 )
{
GetResource(RES_TEXT, RT_IO_LIST, name);
- SearchDirectory(dir, false);
- sprintf(text, name, dir);
- pl->SetName(text, false);
+ pl->SetName(SearchDirectory(false).c_str(), false);
}
}
@@ -1509,84 +1506,52 @@ void CStudio::UpdateDialogPublic()
void CStudio::UpdateDialogList()
{
- // TODO rewrite to multiplatform
- /*CWindow* pw;
- CList* pl;
- long hFile;
- struct _finddata_t fileBuffer;
- struct _finddata_t* listBuffer;
- bool bDo;
- char dir[MAX_FNAME];
- char temp[MAX_FNAME];
- int nbFilenames, i;
-
- pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9);
+ CWindow* pw;
+ CList* pl;
+ fs::path path;
+ int i = 0;
+ char time[100];
+ char temp[100];
+
+ pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9));
if ( pw == nullptr ) return;
- pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST);
- if ( pl == 0 ) return;
+ pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST));
+ if ( pl == nullptr ) return;
pl->Flush();
- nbFilenames = 0;
- listBuffer = (_finddata_t*)malloc(sizeof(_finddata_t)*1000);
-
- SearchDirectory(dir, false);
- strcat(dir, "*"); // list all
- hFile = _findfirst(dir, &fileBuffer);
- if ( hFile != -1 )
- {
- do
- {
- if ( (fileBuffer.attrib & _A_SUBDIR) == 0 )
- {
- listBuffer[nbFilenames++] = fileBuffer;
- }
- }
- while ( _findnext(hFile, &fileBuffer) == 0 && nbFilenames < 1000 );
- }
- do // sorts all names:
- {
- bDo = false;
- for ( i=0 ; i<nbFilenames-1 ; i++ )
- {
- if ( strcmp(listBuffer[i].name, listBuffer[i+1].name) > 0 )
- {
- fileBuffer = listBuffer[i]; // exchange i and i +1
- listBuffer[i] = listBuffer[i+1];
- listBuffer[i+1] = fileBuffer;
- bDo = true;
+ path = fs::path(SearchDirectory(false));
+ fs::directory_iterator end_iter;
+ if ( fs::exists(path) && fs::is_directory(path) ) {
+ for( fs::directory_iterator file(path); file != end_iter; file++) {
+ if (fs::is_regular_file(file->status()) ) {
+ TimeToAscii(fs::last_write_time(file->path()), time);
+ sprintf(temp, "%s\t%lu \t%s", file->path().filename().string().c_str(), fs::file_size(file->path()), time);
+
+ pl->SetName(i++, temp);
}
}
}
- while ( bDo );
-
- for ( i=0 ; i<nbFilenames ; i++ )
- {
- TimeToAscii(listBuffer[i].time_write, dir);
- sprintf(temp, "%s\t%d \t%s", listBuffer[i].name, listBuffer[i].size, dir);
- pl->SetName(i, temp);
- }
-
- free(listBuffer);*/
}
// Constructs the name of the folder or open/save.
// If the folder does not exist, it will be created.
-void CStudio::SearchDirectory(char *dir, bool bCreate)
+std::string CStudio::SearchDirectory(bool bCreate)
{
- if ( m_main->GetIOPublic() )
- {
- sprintf(dir, "%s\\", m_main->GetPublicDir());
+ char dir[MAX_FNAME];
+ if ( m_main->GetIOPublic() ) {
+ sprintf(dir, "%s/", m_main->GetPublicDir());
+ } else {
+ sprintf(dir, "%s/%s/Program/", m_main->GetSavegameDir(), m_main->GetGamerName());
}
- else
- {
- sprintf(dir, "%s\\%s\\Program\\", m_main->GetSavegameDir(), m_main->GetGamerName());
+
+ fs::path path = fs::path(dir);
+
+ if ( bCreate ) {
+ fs::create_directory(path);
}
- if ( bCreate )
- {// TODO
-// mkdir(dir,0777); // if does not exist yet!
- }
+ return path.make_preferred().string();
}
// Reads a new program.
@@ -1612,7 +1577,7 @@ bool CStudio::ReadProgram()
{
strcat(filename, ".txt");
}
- SearchDirectory(dir, true);
+ strcpy(dir, SearchDirectory(true).c_str());
strcat(dir, filename);
pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3));
@@ -1650,7 +1615,7 @@ bool CStudio::WriteProgram()
{
strcat(filename, ".txt");
}
- SearchDirectory(dir, true);
+ strcpy(dir, SearchDirectory(true).c_str());
strcat(dir, filename);
pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3));
@@ -1658,7 +1623,7 @@ bool CStudio::WriteProgram()
pe = static_cast< CEdit* >(pw->SearchControl(EVENT_STUDIO_EDIT));
if ( pe == nullptr ) return false;
- if ( !pe->WriteText(dir) ) return false;
+ if ( !pe->WriteText(std::string(dir)) ) return false;
m_script->SetFilename(filename);
return true;
diff --git a/src/ui/studio.h b/src/ui/studio.h
index 7c2f652..1c14124 100644
--- a/src/ui/studio.h
+++ b/src/ui/studio.h
@@ -22,6 +22,9 @@
#include "graphics/engine/camera.h"
+#include <boost/filesystem.hpp>
+
+namespace fs = boost::filesystem;
#include <string>
@@ -81,7 +84,7 @@ protected:
void UpdateDialogAction();
void UpdateDialogPublic();
void UpdateDialogList();
- void SearchDirectory(char* dir, bool bCreate);
+ std::string SearchDirectory(bool bCreate);
bool ReadProgram();
bool WriteProgram();
diff --git a/test/envs/opengl/CMakeLists.txt b/test/envs/opengl/CMakeLists.txt
index 3de5466..d6c3a37 100644
--- a/test/envs/opengl/CMakeLists.txt
+++ b/test/envs/opengl/CMakeLists.txt
@@ -2,6 +2,14 @@ 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 (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(SYSTEM_CPP_MODULE "system_windows.cpp")
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(SYSTEM_CPP_MODULE "system_linux.cpp")
+else()
+ set(SYSTEM_CPP_MODULE "system_other.cpp")
+endif()
set(TEXTURE_SOURCES
${SRC_DIR}/graphics/opengl/gldevice.cpp
@@ -17,6 +25,7 @@ ${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/image.cpp
${SRC_DIR}/common/stringutils.cpp
${SRC_DIR}/app/system.cpp
+${SRC_DIR}/app/${SYSTEM_CPP_MODULE}
model_test.cpp
)
@@ -25,6 +34,7 @@ ${SRC_DIR}/graphics/opengl/gldevice.cpp
${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/image.cpp
${SRC_DIR}/app/system.cpp
+${SRC_DIR}/app/${SYSTEM_CPP_MODULE}
transform_test.cpp
)
@@ -33,6 +43,7 @@ ${SRC_DIR}/graphics/opengl/gldevice.cpp
${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/image.cpp
${SRC_DIR}/app/system.cpp
+${SRC_DIR}/app/${SYSTEM_CPP_MODULE}
light_test.cpp
)
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index f6a1d75..34027b8 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -1,21 +1,222 @@
set(SRC_DIR ${colobot_SOURCE_DIR}/src)
-include_directories(
-${SRC_DIR}
-${GTEST_INCLUDE_DIR}
-math
-common
+# Additional libraries per platform
+if (${MXE}) # MXE requires special treatment
+ set(PLATFORM_LIBS ${MXE_LIBS})
+elseif (${PLATFORM_WINDOWS})
+ # because it isn't included in standard linking libraries
+ set(PLATFORM_LIBS "-lintl")
+elseif(${PLATFORM_LINUX})
+ # for clock_gettime
+ set(PLATFORM_LIBS "-lrt")
+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 (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(SYSTEM_CPP_MODULE "system_windows.cpp")
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "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}/common/event.cpp
+${SRC_DIR}/common/image.cpp
+${SRC_DIR}/common/iman.cpp
+${SRC_DIR}/common/logger.cpp
+${SRC_DIR}/common/misc.cpp
+${SRC_DIR}/common/profile.cpp
+${SRC_DIR}/common/restext.cpp
+${SRC_DIR}/common/stringutils.cpp
+${SRC_DIR}/graphics/core/color.cpp
+${SRC_DIR}/graphics/engine/camera.cpp
+${SRC_DIR}/graphics/engine/cloud.cpp
+${SRC_DIR}/graphics/engine/engine.cpp
+${SRC_DIR}/graphics/engine/lightman.cpp
+${SRC_DIR}/graphics/engine/lightning.cpp
+${SRC_DIR}/graphics/engine/modelfile.cpp
+${SRC_DIR}/graphics/engine/modelmanager.cpp
+${SRC_DIR}/graphics/engine/particle.cpp
+${SRC_DIR}/graphics/engine/planet.cpp
+${SRC_DIR}/graphics/engine/pyro.cpp
+${SRC_DIR}/graphics/engine/terrain.cpp
+${SRC_DIR}/graphics/engine/text.cpp
+${SRC_DIR}/graphics/engine/water.cpp
+${SRC_DIR}/graphics/opengl/gldevice.cpp
+${SRC_DIR}/object/auto/auto.cpp
+${SRC_DIR}/object/auto/autobase.cpp
+${SRC_DIR}/object/auto/autoconvert.cpp
+${SRC_DIR}/object/auto/autoderrick.cpp
+${SRC_DIR}/object/auto/autodestroyer.cpp
+${SRC_DIR}/object/auto/autoegg.cpp
+${SRC_DIR}/object/auto/autoenergy.cpp
+${SRC_DIR}/object/auto/autofactory.cpp
+${SRC_DIR}/object/auto/autoflag.cpp
+${SRC_DIR}/object/auto/autohuston.cpp
+${SRC_DIR}/object/auto/autoinfo.cpp
+${SRC_DIR}/object/auto/autojostle.cpp
+${SRC_DIR}/object/auto/autokid.cpp
+${SRC_DIR}/object/auto/autolabo.cpp
+${SRC_DIR}/object/auto/automush.cpp
+${SRC_DIR}/object/auto/autonest.cpp
+${SRC_DIR}/object/auto/autonuclear.cpp
+${SRC_DIR}/object/auto/autopara.cpp
+${SRC_DIR}/object/auto/autoportico.cpp
+${SRC_DIR}/object/auto/autoradar.cpp
+${SRC_DIR}/object/auto/autorepair.cpp
+${SRC_DIR}/object/auto/autoresearch.cpp
+${SRC_DIR}/object/auto/autoroot.cpp
+${SRC_DIR}/object/auto/autosafe.cpp
+${SRC_DIR}/object/auto/autostation.cpp
+${SRC_DIR}/object/auto/autotower.cpp
+${SRC_DIR}/object/brain.cpp
+${SRC_DIR}/object/mainmovie.cpp
+${SRC_DIR}/object/motion/motion.cpp
+${SRC_DIR}/object/motion/motionant.cpp
+${SRC_DIR}/object/motion/motionbee.cpp
+${SRC_DIR}/object/motion/motionhuman.cpp
+${SRC_DIR}/object/motion/motionmother.cpp
+${SRC_DIR}/object/motion/motionspider.cpp
+${SRC_DIR}/object/motion/motiontoto.cpp
+${SRC_DIR}/object/motion/motionvehicle.cpp
+${SRC_DIR}/object/motion/motionworm.cpp
+${SRC_DIR}/object/object.cpp
+${SRC_DIR}/object/robotmain.cpp
+${SRC_DIR}/object/task/task.cpp
+${SRC_DIR}/object/task/taskadvance.cpp
+${SRC_DIR}/object/task/taskbuild.cpp
+${SRC_DIR}/object/task/taskfire.cpp
+${SRC_DIR}/object/task/taskfireant.cpp
+${SRC_DIR}/object/task/taskflag.cpp
+${SRC_DIR}/object/task/taskgoto.cpp
+${SRC_DIR}/object/task/taskgungoal.cpp
+${SRC_DIR}/object/task/taskinfo.cpp
+${SRC_DIR}/object/task/taskmanager.cpp
+${SRC_DIR}/object/task/taskmanip.cpp
+${SRC_DIR}/object/task/taskpen.cpp
+${SRC_DIR}/object/task/taskrecover.cpp
+${SRC_DIR}/object/task/taskreset.cpp
+${SRC_DIR}/object/task/tasksearch.cpp
+${SRC_DIR}/object/task/taskshield.cpp
+${SRC_DIR}/object/task/taskspiderexplo.cpp
+${SRC_DIR}/object/task/tasktake.cpp
+${SRC_DIR}/object/task/taskterraform.cpp
+${SRC_DIR}/object/task/taskturn.cpp
+${SRC_DIR}/object/task/taskwait.cpp
+${SRC_DIR}/physics/physics.cpp
+${SRC_DIR}/script/cbottoken.cpp
+${SRC_DIR}/script/cmdtoken.cpp
+${SRC_DIR}/script/script.cpp
+${SRC_DIR}/ui/button.cpp
+${SRC_DIR}/ui/check.cpp
+${SRC_DIR}/ui/color.cpp
+${SRC_DIR}/ui/compass.cpp
+${SRC_DIR}/ui/control.cpp
+${SRC_DIR}/ui/displayinfo.cpp
+${SRC_DIR}/ui/displaytext.cpp
+${SRC_DIR}/ui/edit.cpp
+${SRC_DIR}/ui/editvalue.cpp
+${SRC_DIR}/ui/gauge.cpp
+${SRC_DIR}/ui/group.cpp
+${SRC_DIR}/ui/image.cpp
+${SRC_DIR}/ui/interface.cpp
+${SRC_DIR}/ui/key.cpp
+${SRC_DIR}/ui/label.cpp
+${SRC_DIR}/ui/list.cpp
+${SRC_DIR}/ui/maindialog.cpp
+${SRC_DIR}/ui/mainmap.cpp
+${SRC_DIR}/ui/mainshort.cpp
+${SRC_DIR}/ui/map.cpp
+${SRC_DIR}/ui/scroll.cpp
+${SRC_DIR}/ui/shortcut.cpp
+${SRC_DIR}/ui/slider.cpp
+${SRC_DIR}/ui/studio.cpp
+${SRC_DIR}/ui/target.cpp
+${SRC_DIR}/ui/window.cpp
)
+set(OPENAL_SOURCES "")
+
+if (${OPENAL_SOUND})
+ set(OPENAL_SOURCES
+ ${SRC_DIR}/sound/oalsound/alsound.cpp
+ ${SRC_DIR}/sound/oalsound/buffer.cpp
+ ${SRC_DIR}/sound/oalsound/channel.cpp
+ )
+endif()
+
+# Optional libraries
+set(OPTIONAL_LIBS "")
+
+if (${OPENAL_SOUND})
+ if (${PLATFORM_WINDOWS})
+ set(OPTIONAL_LIBS
+ OpenAL32
+ )
+ else()
+ set(OPTIONAL_LIBS
+ openal
+ )
+ endif()
+endif()
+
+
+# Platform-dependent tests
+if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ #TODO: set(PLATFORM_TESTS app/system_windows_test.cpp)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(PLATFORM_TESTS app/system_linux_test.cpp)
+else()
+ #TODO: set(PLATFORM_TESTS app/system_other_test.cpp)
+endif()
+
+# Tests
set(UT_SOURCES
main.cpp
+graphics/engine/lightman_test.cpp
math/geometry_test.cpp
math/matrix_test.cpp
math/vector_test.cpp
+${PLATFORM_TESTS}
+)
+
+include_directories(
+${CMAKE_CURRENT_BINARY_DIR}
+${SRC_DIR}
+${GTEST_INCLUDE_DIR}
+${GMOCK_INCLUDE_DIR}
+.
+common
+math
+)
+
+set(LIBS
+gtest
+gmock
+CBot
+${SDL_LIBRARY}
+${SDLIMAGE_LIBRARY}
+${SDLTTF_LIBRARY}
+${OPENGL_LIBRARY}
+${PNG_LIBRARIES}
+${GLEW_LIBRARY}
+${Boost_LIBRARIES}
+${OPTIONAL_LIBS}
+${PLATFORM_LIBS}
+${LIBSNDFILE_LIBRARY}
)
-add_executable(colobot_ut ${UT_SOURCES})
-target_link_libraries(colobot_ut gtest)
+add_executable(colobot_ut ${COLOBOT_SOURCES} ${UT_SOURCES} ${OPENAL_SOURCES})
+target_link_libraries(colobot_ut ${LIBS})
add_test(colobot_ut ./colobot_ut)
diff --git a/test/unit/app/system_linux_test.cpp b/test/unit/app/system_linux_test.cpp
new file mode 100644
index 0000000..fe89399
--- /dev/null
+++ b/test/unit/app/system_linux_test.cpp
@@ -0,0 +1,51 @@
+#include "app/system.h"
+#include "app/system_linux.h"
+
+#include <gtest/gtest.h>
+
+TEST(SystemLinuxTest, TimeStampDiff)
+{
+ const long long SEC = 1000000000;
+
+ SystemTimeStamp before, after;
+
+ before.clockTime.tv_sec = 1;
+ before.clockTime.tv_nsec = 100;
+
+ after.clockTime.tv_sec = 1;
+ after.clockTime.tv_nsec = 900;
+
+ long long tDiff = TimeStampExactDiff_Linux(&before, &after);
+ EXPECT_EQ( 800, tDiff);
+
+ tDiff = TimeStampExactDiff_Linux(&after, &before);
+ EXPECT_EQ(-800, tDiff);
+
+ // -------
+
+ before.clockTime.tv_sec = 2;
+ before.clockTime.tv_nsec = 200;
+
+ after.clockTime.tv_sec = 3;
+ after.clockTime.tv_nsec = 500;
+
+ tDiff = TimeStampExactDiff_Linux(&before, &after);
+ EXPECT_EQ( SEC + 300, tDiff);
+
+ tDiff = TimeStampExactDiff_Linux(&after, &before);
+ EXPECT_EQ(-SEC - 300, tDiff);
+
+ // -------
+
+ before.clockTime.tv_sec = 3;
+ before.clockTime.tv_nsec = 200;
+
+ after.clockTime.tv_sec = 4;
+ after.clockTime.tv_nsec = 100;
+
+ tDiff = TimeStampExactDiff_Linux(&before, &after);
+ EXPECT_EQ( SEC - 100, tDiff);
+
+ tDiff = TimeStampExactDiff_Linux(&after, &before);
+ EXPECT_EQ(-SEC + 100, tDiff);
+}
diff --git a/test/unit/graphics/core/device_mock.h b/test/unit/graphics/core/device_mock.h
new file mode 100644
index 0000000..80e214f
--- /dev/null
+++ b/test/unit/graphics/core/device_mock.h
@@ -0,0 +1,107 @@
+#pragma once
+
+#include "graphics/core/device.h"
+
+#include <gmock/gmock.h>
+
+class CDeviceMock : public Gfx::CDevice
+{
+public:
+ CDeviceMock() {}
+
+ MOCK_METHOD0(DebugHook, void());
+
+ MOCK_METHOD0(Create, bool());
+ MOCK_METHOD0(Destroy, void());
+
+ MOCK_METHOD0(BeginScene, void());
+ MOCK_METHOD0(EndScene, void());
+
+ MOCK_METHOD0(Clear, void());
+
+ MOCK_METHOD2(SetTransform, void(Gfx::TransformType type, const Math::Matrix &matrix));
+ MOCK_METHOD1(GetTransform, const Math::Matrix& (Gfx::TransformType type));
+ MOCK_METHOD2(MultiplyTransform, void(Gfx::TransformType type, const Math::Matrix &matrix));
+
+ MOCK_METHOD1(SetMaterial, void(const Gfx::Material &material));
+ MOCK_METHOD0(GetMaterial, const Gfx::Material&());
+
+ MOCK_METHOD0(GetMaxLightCount, int());
+
+ MOCK_METHOD2(SetLight, void(int index, const Gfx::Light &light));
+ MOCK_METHOD1(GetLight, const Gfx::Light&(int index));
+
+ MOCK_METHOD2(SetLightEnabled, void(int index, bool enabled));
+ MOCK_METHOD1(GetLightEnabled, bool(int index));
+
+ MOCK_METHOD2(CreateTexture, Gfx::Texture(CImage *image, const Gfx::TextureCreateParams &params));
+ MOCK_METHOD2(CreateTexture, Gfx::Texture(ImageData *data, const Gfx::TextureCreateParams &params));
+
+ MOCK_METHOD1(DestroyTexture, void(const Gfx::Texture &texture));
+ MOCK_METHOD0(DestroyAllTextures, void());
+
+ MOCK_METHOD0(GetMaxTextureStageCount, int());
+
+ MOCK_METHOD2(SetTexture, void(int index, const Gfx::Texture &texture));
+ MOCK_METHOD2(SetTexture, void(int index, unsigned int textureId));
+ MOCK_METHOD1(GetTexture, Gfx::Texture(int index));
+
+ MOCK_METHOD2(SetTextureEnabled, void(int index, bool enabled));
+ MOCK_METHOD1(GetTextureEnabled, bool(int index));
+
+ MOCK_METHOD2(SetTextureStageParams, void(int index, const Gfx::TextureStageParams &params));
+ MOCK_METHOD1(GetTextureStageParams, Gfx::TextureStageParams(int index));
+
+ MOCK_METHOD3(SetTextureStageWrap, void(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT));
+
+ MOCK_METHOD4(DrawPrimitive, void(Gfx::PrimitiveType type, const Gfx::Vertex *vertices, int vertexCount, Gfx::Color color));
+ MOCK_METHOD4(DrawPrimitive, void(Gfx::PrimitiveType type, const Gfx::VertexTex2 *vertices, int vertexCount, Gfx::Color color));
+ MOCK_METHOD3(DrawPrimitive, void(Gfx::PrimitiveType type, const Gfx::VertexCol *vertices, int vertexCount));
+
+ MOCK_METHOD3(CreateStaticBuffer, unsigned int(Gfx::PrimitiveType primitiveType, const Gfx::Vertex* vertices, int vertexCount));
+ MOCK_METHOD3(CreateStaticBuffer, unsigned int(Gfx::PrimitiveType primitiveType, const Gfx::VertexTex2* vertices, int vertexCount));
+ MOCK_METHOD3(CreateStaticBuffer, unsigned int(Gfx::PrimitiveType primitiveType, const Gfx::VertexCol* vertices, int vertexCount));
+
+ MOCK_METHOD4(UpdateStaticBuffer, void(unsigned int bufferId, Gfx::PrimitiveType primitiveType, const Gfx::Vertex* vertices, int vertexCount));
+ MOCK_METHOD4(UpdateStaticBuffer, void(unsigned int bufferId, Gfx::PrimitiveType primitiveType, const Gfx::VertexTex2* vertices, int vertexCount));
+ MOCK_METHOD4(UpdateStaticBuffer, void(unsigned int bufferId, Gfx::PrimitiveType primitiveType, const Gfx::VertexCol* vertices, int vertexCount));
+
+ MOCK_METHOD1(DrawStaticBuffer, void(unsigned int bufferId));
+
+ MOCK_METHOD1(DestroyStaticBuffer, void(unsigned int bufferId));
+
+ MOCK_METHOD2(ComputeSphereVisibility, int(const Math::Vector &center, float radius));
+
+ MOCK_METHOD2(SetRenderState, void(Gfx::RenderState state, bool enabled));
+ MOCK_METHOD1(GetRenderState, bool(Gfx::RenderState state));
+
+ MOCK_METHOD1(SetDepthTestFunc, void(Gfx::CompFunc func));
+ MOCK_METHOD0(GetDepthTestFunc, Gfx::CompFunc());
+
+ MOCK_METHOD1(SetDepthBias, void(float factor));
+ MOCK_METHOD0(GetDepthBias, float());
+
+ MOCK_METHOD2(SetAlphaTestFunc, void(Gfx::CompFunc func, float refValue));
+ MOCK_METHOD2(GetAlphaTestFunc, void(Gfx::CompFunc &func, float &refValue));
+
+ MOCK_METHOD2(SetBlendFunc, void(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend));
+ MOCK_METHOD2(GetBlendFunc, void(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend));
+
+ MOCK_METHOD1(SetClearColor, void(const Gfx::Color &color));
+ MOCK_METHOD0(GetClearColor, Gfx::Color());
+
+ MOCK_METHOD1(SetGlobalAmbient, void(const Gfx::Color &color));
+ MOCK_METHOD0(GetGlobalAmbient, Gfx::Color());
+
+ MOCK_METHOD5(SetFogParams, void(Gfx::FogMode mode, const Gfx::Color &color, float start, float end, float density));
+ MOCK_METHOD5(GetFogParams, void(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density));
+
+ MOCK_METHOD1(SetCullMode, void(Gfx::CullMode mode));
+ MOCK_METHOD0(GetCullMode, Gfx::CullMode());
+
+ MOCK_METHOD1(SetShadeModel, void(Gfx::ShadeModel model));
+ MOCK_METHOD0(GetShadeModel, Gfx::ShadeModel());
+
+ MOCK_METHOD1(SetFillMode, void(Gfx::FillMode mode));
+ MOCK_METHOD0(GetFillMode, Gfx::FillMode());
+};
diff --git a/test/unit/graphics/engine/engine_mock.h b/test/unit/graphics/engine/engine_mock.h
new file mode 100644
index 0000000..1a15eca
--- /dev/null
+++ b/test/unit/graphics/engine/engine_mock.h
@@ -0,0 +1,14 @@
+#include "graphics/engine/engine.h"
+
+#include <gmock/gmock.h>
+
+class CEngineMock : public Gfx::CEngine
+{
+public:
+ CEngineMock() : Gfx::CEngine(nullptr) {}
+
+ MOCK_METHOD0(GetPause, bool());
+
+ MOCK_METHOD0(GetEyePt, Math::Vector());
+ MOCK_METHOD0(GetLookatPt, Math::Vector());
+};
diff --git a/test/unit/graphics/engine/lightman_test.cpp b/test/unit/graphics/engine/lightman_test.cpp
new file mode 100644
index 0000000..c955f0a
--- /dev/null
+++ b/test/unit/graphics/engine/lightman_test.cpp
@@ -0,0 +1,146 @@
+#include "graphics/engine/lightman.h"
+
+#include "graphics/core/device_mock.h"
+#include "graphics/engine/engine_mock.h"
+
+#include <gtest/gtest.h>
+
+using namespace Gfx;
+
+using testing::_;
+using testing::Invoke;
+using testing::Return;
+
+class LightManagerUT : public testing::Test
+{
+protected:
+ LightManagerUT()
+ : lightManager(&engine)
+ {}
+
+ void PrepareLightTesting(int maxLights, Math::Vector eyePos);
+ void CheckLightSorting(EngineObjectType objectType, const std::vector<int>& expectedLights);
+ void CheckLight(int index, const Light& light);
+ void AddLight(int type, LightPriority priority, bool used, bool enabled,
+ Math::Vector pos, EngineObjectType includeType, EngineObjectType excludeType);
+
+
+ CLightManager lightManager;
+ CEngineMock engine;
+ CDeviceMock device;
+
+private:
+ std::vector<DynamicLight> dynamicLights;
+ std::vector<int> expectedLightTypes;
+ int maxLightsCount;
+};
+
+void LightManagerUT::PrepareLightTesting(int maxLights, Math::Vector eyePos)
+{
+ maxLightsCount = maxLights;
+
+ EXPECT_CALL(device, GetMaxLightCount()).WillOnce(Return(maxLights));
+ lightManager.SetDevice(&device);
+
+ ON_CALL(device, SetLight(_, _)).WillByDefault(Invoke(this, &LightManagerUT::CheckLight));
+
+ EXPECT_CALL(engine, GetEyePt()).WillRepeatedly(Return(eyePos));
+}
+
+void LightManagerUT::CheckLightSorting(EngineObjectType objectType, const std::vector<int>& expectedLights)
+{
+ expectedLightTypes = expectedLights;
+
+ EXPECT_CALL(device, SetLight(_, _)).Times(expectedLights.size());
+
+ for (int i = 0; i < static_cast<int>( expectedLights.size() ); ++i)
+ EXPECT_CALL(device, SetLightEnabled(i, true));
+
+ for (int i = expectedLights.size(); i < maxLightsCount; ++i)
+ EXPECT_CALL(device, SetLightEnabled(i, false));
+
+ lightManager.UpdateDeviceLights(objectType);
+}
+
+void LightManagerUT::CheckLight(int index, const Light& light)
+{
+ ASSERT_TRUE(index >= 0 && index < static_cast<int>( expectedLightTypes.size() ));
+ ASSERT_EQ(expectedLightTypes[index], light.type);
+}
+
+void LightManagerUT::AddLight(int type, LightPriority priority, bool used, bool enabled,
+ Math::Vector pos, EngineObjectType includeType, EngineObjectType excludeType)
+{
+ int rank = lightManager.CreateLight(priority);
+
+ Light light;
+ light.type = static_cast<LightType>(type);
+ light.position = pos;
+ lightManager.SetLight(rank, light);
+
+ lightManager.SetLightEnabled(rank, enabled);
+ lightManager.SetLightIncludeType(rank, includeType);
+ lightManager.SetLightExcludeType(rank, excludeType);
+
+ if (!used)
+ lightManager.DeleteLight(rank);
+}
+
+TEST_F(LightManagerUT, LightSorting_UnusedOrDisabledAreSkipped)
+{
+ const int lightCount = 10;
+ const Math::Vector eyePos(0.0f, 0.0f, 0.0f);
+ PrepareLightTesting(lightCount, eyePos);
+
+ AddLight(1, LIGHT_PRI_LOW, false, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(2, LIGHT_PRI_LOW, true, false, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(3, LIGHT_PRI_LOW, false, false, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+
+ std::vector<int> expectedLights;
+ CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
+}
+
+TEST_F(LightManagerUT, LightSorting_IncludeTypesAreIncluded)
+{
+ const int lightCount = 10;
+ const Math::Vector eyePos(0.0f, 0.0f, 0.0f);
+ PrepareLightTesting(lightCount, eyePos);
+
+ AddLight(1, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_TERRAIN, ENG_OBJTYPE_NULL);
+ AddLight(3, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_QUARTZ, ENG_OBJTYPE_NULL);
+
+ std::vector<int> expectedLights = { 1, 2 };
+ CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
+}
+
+TEST_F(LightManagerUT, LightSorting_ExcludeTypesAreExcluded)
+{
+ const int lightCount = 10;
+ const Math::Vector eyePos(0.0f, 0.0f, 0.0f);
+ PrepareLightTesting(lightCount, eyePos);
+
+ AddLight(1, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_TERRAIN);
+ AddLight(3, LIGHT_PRI_LOW, true, true, Math::Vector(0.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_QUARTZ);
+
+ std::vector<int> expectedLights = { 1, 3 };
+ CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
+}
+
+TEST_F(LightManagerUT, LightSorting_SortingAccordingToDistance)
+{
+ const int lightCount = 3;
+ const Math::Vector eyePos(0.0f, 0.0f, 0.0f);
+ PrepareLightTesting(lightCount, eyePos);
+
+ AddLight(1, LIGHT_PRI_HIGH, true, true, Math::Vector(10.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(2, LIGHT_PRI_LOW, true, true, Math::Vector(4.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(3, LIGHT_PRI_HIGH, true, true, Math::Vector(20.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(4, LIGHT_PRI_LOW, true, true, Math::Vector(11.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(5, LIGHT_PRI_LOW, true, true, Math::Vector(100.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+ AddLight(6, LIGHT_PRI_HIGH, true, true, Math::Vector(21.0f, 0.0f, 0.0f), ENG_OBJTYPE_NULL, ENG_OBJTYPE_NULL);
+
+ std::vector<int> expectedLights = { 2, 1, 3 };
+ CheckLightSorting(ENG_OBJTYPE_TERRAIN, expectedLights);
+}
diff --git a/test/unit/ui/CMakeLists.txt b/test/unit/ui/CMakeLists.txt
index 916a73b..f5945dc 100644
--- a/test/unit/ui/CMakeLists.txt
+++ b/test/unit/ui/CMakeLists.txt
@@ -11,6 +11,7 @@ add_executable(edit_test
${SRC_DIR}/common/event.cpp
${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/misc.cpp
+${SRC_DIR}/common/profile.cpp
${SRC_DIR}/common/iman.cpp
${SRC_DIR}/common/stringutils.cpp
${SRC_DIR}/graphics/engine/text.cpp
diff --git a/test/unit/ui/stubs/app_stub.cpp b/test/unit/ui/stubs/app_stub.cpp
index 094806f..3df7d42 100644
--- a/test/unit/ui/stubs/app_stub.cpp
+++ b/test/unit/ui/stubs/app_stub.cpp
@@ -36,3 +36,7 @@ CEventQueue* CApplication::GetEventQueue()
return nullptr;
}
+std::string CApplication::GetDataDirPath()
+{
+ return "";
+}
diff --git a/test/unit/ui/stubs/engine_stub.cpp b/test/unit/ui/stubs/engine_stub.cpp
index 40886da..0a2777c 100644
--- a/test/unit/ui/stubs/engine_stub.cpp
+++ b/test/unit/ui/stubs/engine_stub.cpp
@@ -77,11 +77,28 @@ int CEngine::GetEditIndentValue()
void CEngine::DeleteTexture(const std::string& /* texName */)
{
}
+
Texture CEngine::LoadTexture(const std::string& /* name */)
{
Texture texture;
return texture;
}
+Math::Vector CEngine::GetEyePt()
+{
+ return Math::Vector();
+}
+
+Math::Vector CEngine::GetLookatPt()
+{
+ return Math::Vector();
+}
+
+bool CEngine::GetPause()
+{
+ return false;
+}
+
+
} /* Gfx */