summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2013-06-24 21:37:15 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2013-06-24 21:37:15 +0200
commit7c2e955e1552a9c4e412ea2c936be61fc78ba010 (patch)
treeee506dfbec54f998d10c385bde3a1c3fa04e66b2
parente218dcfdf2c58f8841e7ebd220527d08e870a6d5 (diff)
parentb376486fd74fa02b0297ceef6d0f977b32358e5e (diff)
downloadcolobot-7c2e955e1552a9c4e412ea2c936be61fc78ba010.tar.gz
colobot-7c2e955e1552a9c4e412ea2c936be61fc78ba010.tar.bz2
colobot-7c2e955e1552a9c4e412ea2c936be61fc78ba010.zip
Colobot Gold 0.1.0-alpha
-rw-r--r--.gitignore27
-rw-r--r--.travis.yml2
-rw-r--r--CMakeLists.txt129
-rw-r--r--INSTALL-MXE.md (renamed from INSTALL-MXE.txt)14
-rw-r--r--INSTALL.md (renamed from INSTALL.txt)27
-rw-r--r--README.md59
-rw-r--r--bin/.gitignore6
-rw-r--r--bin/README.txt1
-rw-r--r--cmake/FindGettext.cmake218
m---------data0
-rw-r--r--desktop/.gitignore7
-rw-r--r--desktop/CMakeLists.txt99
-rw-r--r--desktop/colobot.desktop.in (renamed from src/desktop/colobot.desktop.in)1
-rw-r--r--desktop/colobot.ini (renamed from src/desktop/colobot.ini)1
-rw-r--r--desktop/colobot.pod (renamed from src/desktop/colobot.pod)1
-rw-r--r--desktop/colobot.svg (renamed from src/desktop/colobot.svg)1
-rwxr-xr-xdesktop/create_desktop_file.sh (renamed from src/desktop/create_desktop_file.sh)8
-rw-r--r--desktop/po/colobot-desktop.pot (renamed from src/desktop/po/colobot-desktop.pot)1
-rw-r--r--desktop/po/fr.po (renamed from src/desktop/po/fr.po)0
-rw-r--r--desktop/po4a.cfg (renamed from src/desktop/po4a.cfg)1
-rw-r--r--lib/clipboard/.gitignore1
-rw-r--r--lib/clipboard/CMakeLists.txt17
-rw-r--r--lib/clipboard/COPYING.README72
-rw-r--r--lib/clipboard/include/clipboard/clipboard.h55
-rw-r--r--lib/clipboard/include/clipboard/types.h100
-rw-r--r--lib/clipboard/include/clipboard/utf.h115
-rw-r--r--lib/clipboard/include/clipboard/wzglobal.h614
-rw-r--r--lib/clipboard/readme.txt1
-rw-r--r--lib/clipboard/src/clipboardWin32.c160
-rw-r--r--lib/clipboard/src/clipboardX11.c293
-rw-r--r--lib/clipboard/src/utf.c530
-rw-r--r--lib/localename/CMakeLists.txt3
-rw-r--r--lib/localename/README.txt41
-rw-r--r--lib/localename/localename.c2864
-rw-r--r--lib/localename/localename.h95
-rw-r--r--po/.gitignore1
-rw-r--r--po/CMakeLists.txt (renamed from src/po/CMakeLists.txt)6
-rw-r--r--po/colobot.pot (renamed from src/po/colobot.pot)1
-rw-r--r--po/de.po (renamed from src/po/de.po)1
-rw-r--r--po/fr.po (renamed from src/po/fr.po)1
-rw-r--r--po/pl.po (renamed from src/po/pl.po)1
-rw-r--r--src/CBot/.gitignore1
-rw-r--r--src/CBot/CBot.cpp65
-rw-r--r--src/CBot/CBot.h76
-rw-r--r--src/CBot/CBotAddExpr.cpp3
-rw-r--r--src/CBot/CBotClass.cpp40
-rw-r--r--src/CBot/CBotCompExpr.cpp2
-rw-r--r--src/CBot/CBotDll.h46
-rw-r--r--src/CBot/CBotFunction.cpp43
-rw-r--r--src/CBot/CBotIf.cpp4
-rw-r--r--src/CBot/CBotProgram.cpp48
-rw-r--r--src/CBot/CBotStack.cpp56
-rw-r--r--src/CBot/CBotString.cpp11
-rw-r--r--src/CBot/CBotToken.cpp8
-rw-r--r--src/CBot/CBotToken.h1
-rw-r--r--src/CBot/CBotTwoOpExpr.cpp15
-rw-r--r--src/CBot/CBotVar.cpp35
-rw-r--r--src/CBot/CBotWhile.cpp207
-rw-r--r--src/CBot/CMakeLists.txt3
-rw-r--r--src/CBot/ClassFILE.cpp6
-rw-r--r--src/CBot/StringFunctions.cpp7
-rw-r--r--src/CBot/idees.txt1
-rw-r--r--src/CBot/resource.h2
-rw-r--r--src/CMakeLists.txt34
-rw-r--r--src/app/README.txt1
-rw-r--r--src/app/app.cpp580
-rw-r--r--src/app/app.h111
-rw-r--r--src/app/main.cpp5
-rw-r--r--src/app/system.cpp9
-rw-r--r--src/app/system.h5
-rw-r--r--src/app/system_linux.cpp31
-rw-r--r--src/app/system_linux.h5
-rw-r--r--src/app/system_other.cpp1
-rw-r--r--src/app/system_other.h1
-rw-r--r--src/app/system_windows.cpp27
-rw-r--r--src/app/system_windows.h5
-rw-r--r--src/common/.gitignore2
-rw-r--r--src/common/README.txt1
-rw-r--r--src/common/config.h.cmake1
-rw-r--r--src/common/event.cpp536
-rw-r--r--src/common/event.h48
-rw-r--r--src/common/global.h5
-rw-r--r--src/common/image.cpp33
-rw-r--r--src/common/image.h4
-rw-r--r--src/common/iman.cpp1
-rw-r--r--src/common/iman.h1
-rw-r--r--src/common/ioutils.h1
-rw-r--r--src/common/key.h1
-rw-r--r--src/common/logger.cpp32
-rw-r--r--src/common/logger.h10
-rw-r--r--src/common/misc.h1
-rw-r--r--src/common/profile.cpp82
-rw-r--r--src/common/profile.h183
-rw-r--r--src/common/restext.cpp17
-rw-r--r--src/common/restext.h5
-rw-r--r--src/common/singleton.h1
-rw-r--r--src/common/stringutils.cpp1
-rw-r--r--src/common/stringutils.h1
-rw-r--r--src/desktop/.gitignore1
-rw-r--r--src/desktop/CMakeLists.txt97
-rw-r--r--src/graphics/README.txt1
-rw-r--r--src/graphics/core/README.txt3
-rw-r--r--src/graphics/core/color.cpp1
-rw-r--r--src/graphics/core/color.h9
-rw-r--r--src/graphics/core/device.h6
-rw-r--r--src/graphics/core/light.h1
-rw-r--r--src/graphics/core/material.h1
-rw-r--r--src/graphics/core/texture.h6
-rw-r--r--src/graphics/core/vertex.h1
-rw-r--r--src/graphics/d3d/README.txt1
-rw-r--r--src/graphics/engine/README.txt1
-rw-r--r--src/graphics/engine/camera.cpp1
-rw-r--r--src/graphics/engine/camera.h4
-rw-r--r--src/graphics/engine/cloud.cpp1
-rw-r--r--src/graphics/engine/cloud.h1
-rw-r--r--src/graphics/engine/engine.cpp228
-rw-r--r--src/graphics/engine/engine.h67
-rw-r--r--src/graphics/engine/lightman.cpp77
-rw-r--r--src/graphics/engine/lightman.h14
-rw-r--r--src/graphics/engine/lightning.cpp1
-rw-r--r--src/graphics/engine/lightning.h1
-rw-r--r--src/graphics/engine/modelfile.cpp80
-rw-r--r--src/graphics/engine/modelfile.h5
-rw-r--r--src/graphics/engine/modelmanager.cpp18
-rw-r--r--src/graphics/engine/modelmanager.h11
-rw-r--r--src/graphics/engine/particle.cpp7
-rw-r--r--src/graphics/engine/particle.h1
-rw-r--r--src/graphics/engine/planet.cpp1
-rw-r--r--src/graphics/engine/planet.h1
-rw-r--r--src/graphics/engine/pyro.cpp32
-rw-r--r--src/graphics/engine/pyro.h1
-rw-r--r--src/graphics/engine/terrain.cpp1
-rw-r--r--src/graphics/engine/terrain.h1
-rw-r--r--src/graphics/engine/test/CMakeLists.txt27
-rw-r--r--src/graphics/engine/text.cpp123
-rw-r--r--src/graphics/engine/text.h32
-rw-r--r--src/graphics/engine/water.cpp1
-rw-r--r--src/graphics/engine/water.h1
-rw-r--r--src/graphics/opengl/README.txt1
-rw-r--r--src/graphics/opengl/gldevice.cpp131
-rw-r--r--src/graphics/opengl/gldevice.h4
-rw-r--r--src/math/README.txt1
-rw-r--r--src/math/all.h1
-rw-r--r--src/math/const.h1
-rw-r--r--src/math/func.h7
-rw-r--r--src/math/geometry.h1
-rw-r--r--src/math/intpoint.h1
-rw-r--r--src/math/matrix.h17
-rw-r--r--src/math/point.h16
-rw-r--r--src/math/vector.h19
-rw-r--r--src/object/README.txt1
-rw-r--r--src/object/auto/auto.cpp6
-rw-r--r--src/object/auto/auto.h6
-rw-r--r--src/object/auto/autobase.cpp3
-rw-r--r--src/object/auto/autoderrick.cpp1
-rw-r--r--src/object/auto/autodestroyer.cpp191
-rw-r--r--src/object/auto/autodestroyer.h4
-rw-r--r--src/object/auto/autoenergy.cpp1
-rw-r--r--src/object/auto/autofactory.cpp106
-rw-r--r--src/object/auto/autofactory.h8
-rw-r--r--src/object/auto/autoflag.cpp1
-rw-r--r--src/object/auto/autoinfo.cpp5
-rw-r--r--src/object/auto/autojostle.cpp6
-rw-r--r--src/object/auto/autojostle.h4
-rw-r--r--src/object/auto/autokid.cpp1
-rw-r--r--src/object/auto/autolabo.cpp98
-rw-r--r--src/object/auto/autolabo.h3
-rw-r--r--src/object/auto/automush.cpp1
-rw-r--r--src/object/auto/autonest.cpp1
-rw-r--r--src/object/auto/autonuclear.cpp1
-rw-r--r--src/object/auto/autopara.cpp1
-rw-r--r--src/object/auto/autoradar.cpp1
-rw-r--r--src/object/auto/autorepair.cpp13
-rw-r--r--src/object/auto/autorepair.h1
-rw-r--r--src/object/auto/autoresearch.cpp176
-rw-r--r--src/object/auto/autoresearch.h4
-rw-r--r--src/object/auto/autoroot.cpp1
-rw-r--r--src/object/auto/autosafe.cpp4
-rw-r--r--src/object/auto/autostation.cpp11
-rw-r--r--src/object/auto/autotower.cpp3
-rw-r--r--src/object/brain.cpp43
-rw-r--r--src/object/brain.h3
-rw-r--r--src/object/mainmovie.cpp1
-rw-r--r--src/object/motion/motionant.cpp5
-rw-r--r--src/object/motion/motionbee.cpp5
-rw-r--r--src/object/motion/motiondummy.cpp85
-rw-r--r--src/object/motion/motiondummy.h34
-rw-r--r--src/object/motion/motionhuman.cpp15
-rw-r--r--src/object/motion/motionmother.cpp3
-rw-r--r--src/object/motion/motionspider.cpp5
-rw-r--r--src/object/motion/motiontoto.cpp3
-rw-r--r--src/object/motion/motionvehicle.cpp6
-rw-r--r--src/object/motion/motionworm.cpp5
-rw-r--r--src/object/object.cpp28
-rw-r--r--src/object/object.h1
-rw-r--r--src/object/objman.cpp389
-rw-r--r--src/object/objman.h53
-rw-r--r--src/object/robotmain.cpp756
-rw-r--r--src/object/robotmain.h50
-rw-r--r--src/object/task/task.cpp1
-rw-r--r--src/object/task/task.h4
-rw-r--r--src/object/task/taskadvance.cpp1
-rw-r--r--src/object/task/taskbuild.cpp2
-rw-r--r--src/object/task/taskgoto.cpp24
-rw-r--r--src/object/task/taskmanager.cpp1
-rw-r--r--src/object/task/tasksearch.cpp8
-rw-r--r--src/object/task/taskshield.cpp2
-rw-r--r--src/object/task/tasktake.cpp1
-rw-r--r--src/object/task/taskturn.cpp1
-rw-r--r--src/object/task/taskwait.cpp1
-rw-r--r--src/physics/README.txt1
-rw-r--r--src/physics/physics.cpp7
-rw-r--r--src/physics/physics.h1
-rw-r--r--src/script/cbottoken.cpp40
-rw-r--r--src/script/cbottoken.h1
-rw-r--r--src/script/cmdtoken.cpp3
-rw-r--r--src/script/dd.cpp1
-rw-r--r--src/script/script.cpp1149
-rw-r--r--src/script/script.h39
-rw-r--r--src/sound/README.txt1
-rw-r--r--src/sound/oalsound/alsound.cpp517
-rw-r--r--src/sound/oalsound/alsound.h142
-rw-r--r--src/sound/oalsound/buffer.cpp69
-rw-r--r--src/sound/oalsound/buffer.h48
-rw-r--r--src/sound/oalsound/channel.cpp328
-rw-r--r--src/sound/oalsound/channel.h142
-rw-r--r--src/sound/oalsound/check.h1
-rw-r--r--src/sound/sound.cpp191
-rw-r--r--src/sound/sound.h110
-rw-r--r--src/tools/CMakeLists.txt1
-rw-r--r--src/tools/README.txt1
-rw-r--r--src/tools/convert_model.cpp1
-rw-r--r--src/ui/README.txt1
-rw-r--r--src/ui/button.cpp1
-rw-r--r--src/ui/button.h1
-rw-r--r--src/ui/check.cpp1
-rw-r--r--src/ui/color.cpp1
-rw-r--r--src/ui/color.h1
-rw-r--r--src/ui/compass.cpp1
-rw-r--r--src/ui/compass.h1
-rw-r--r--src/ui/control.cpp17
-rw-r--r--src/ui/control.h1
-rw-r--r--src/ui/displayinfo.cpp11
-rw-r--r--src/ui/displayinfo.h1
-rw-r--r--src/ui/displaytext.cpp1
-rw-r--r--src/ui/edit.cpp294
-rw-r--r--src/ui/edit.h5
-rw-r--r--src/ui/editvalue.cpp1
-rw-r--r--src/ui/editvalue.h1
-rw-r--r--src/ui/gauge.cpp1
-rw-r--r--src/ui/gauge.h23
-rw-r--r--src/ui/group.cpp1
-rw-r--r--src/ui/group.h1
-rw-r--r--src/ui/image.cpp1
-rw-r--r--src/ui/image.h1
-rw-r--r--src/ui/interface.cpp33
-rw-r--r--src/ui/interface.h83
-rw-r--r--src/ui/key.cpp1
-rw-r--r--src/ui/label.cpp4
-rw-r--r--src/ui/label.h13
-rw-r--r--src/ui/list.cpp195
-rw-r--r--src/ui/list.h10
-rw-r--r--src/ui/maindialog.cpp447
-rw-r--r--src/ui/maindialog.h4
-rw-r--r--src/ui/mainmap.cpp17
-rw-r--r--src/ui/mainmap.h62
-rw-r--r--src/ui/mainshort.h47
-rw-r--r--src/ui/map.cpp45
-rw-r--r--src/ui/map.h143
-rw-r--r--src/ui/scroll.cpp1
-rw-r--r--src/ui/scroll.h65
-rw-r--r--src/ui/shortcut.cpp3
-rw-r--r--src/ui/shortcut.h21
-rw-r--r--src/ui/slider.cpp1
-rw-r--r--src/ui/slider.h69
-rw-r--r--src/ui/studio.cpp37
-rw-r--r--src/ui/target.cpp1
-rw-r--r--src/ui/target.h19
-rw-r--r--src/ui/window.cpp8
-rw-r--r--src/ui/window.h3
-rw-r--r--test/envs/opengl/CMakeLists.txt8
-rw-r--r--test/unit/CMakeLists.txt28
-rw-r--r--test/unit/app/app_test.cpp3
-rw-r--r--test/unit/graphics/core/device_mock.h1
-rw-r--r--test/unit/graphics/engine/modelfile_test.cpp (renamed from src/graphics/engine/test/modelfile_test.cpp)65
-rw-r--r--test/unit/main.cpp6
-rw-r--r--test/unit/math/func_test.cpp39
-rw-r--r--test/unit/math/geometry_test.cpp18
-rw-r--r--test/unit/math/matrix_test.cpp18
-rw-r--r--test/unit/math/vector_test.cpp18
-rw-r--r--test/unit/ui/CMakeLists.txt12
-rw-r--r--test/unit/ui/edit_test.cpp7
-rw-r--r--test/unit/ui/stubs/app_stub.cpp6
-rw-r--r--test/unit/ui/stubs/robotmain_stub.cpp2
-rwxr-xr-xtools/fix-eof-eol.sh17
-rwxr-xr-xtools/git-grep-braces.sh4
296 files changed, 12532 insertions, 3517 deletions
diff --git a/.gitignore b/.gitignore
index 0e9774c..122663d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,3 @@
-# Ignore the documentation folder
-/doc
-
-# Ignore local data
-/colobot.ini
-/savegame
-
# Ignore the CMake build files
CMakeFiles
CMakeCache.txt
@@ -13,9 +6,21 @@ Makefile
/install_manifest.txt
/Testing
/CTestTestfile.cmake
-/src/CBot/tests/CBot_console/bin/
+
+# Ignore the generated documentation
+/doc
+/Doxyfile
+
+# Ignore targets
+/colobot
+
+# Ignore local data
+/colobot.ini
+/savegame
+
+# Standard build directory
+/build
+
+# Ignore KDevelop files
.kdev4
*.kdev4
-*.flv
-*.mp4
-
diff --git a/.travis.yml b/.travis.yml
index af27ea3..038e4c2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: cpp
compiler:
- gcc
- clang
-script: mkdir build; cd build; cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON && make all doc test && DESTDIR=. make install
+script: mkdir build; cd build; cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DOPENAL_SOUND=0 -DTESTS=1 && make all doc test && DESTDIR=. make install
before_install:
- git submodule update --init --recursive
- sudo add-apt-repository ppa:mapnik/boost -y
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38458bc..4a22138 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,8 +15,10 @@ set(COLOBOT_VERSION_MAJOR 0)
set(COLOBOT_VERSION_MINOR 1)
set(COLOBOT_VERSION_REVISION 0)
-# Comment out when releasing
-set(COLOBOT_VERSION_UNRELEASED "~pre-alpha")
+# Used on official releases
+set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha")
+# Used on unreleased, development builds
+#set(COLOBOT_VERSION_UNRELEASED "+alpha")
# Append git characteristics to version
if(DEFINED COLOBOT_VERSION_UNRELEASED AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
@@ -30,21 +32,20 @@ if(DEFINED COLOBOT_VERSION_UNRELEASED AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(COLOBOT_VERSION_UNRELEASED "${COLOBOT_VERSION_UNRELEASED}-git-${GIT_BRANCH}~r${GIT_REVISION}")
endif()
-set(COLOBOT_VERSION_FULL "${COLOBOT_VERSION_MAJOR}.${COLOBOT_VERSION_MINOR}.${COLOBOT_VERSION_REVISION}${COLOBOT_VERSION_UNRELEASED}")
+set(COLOBOT_VERSION_FULL "${COLOBOT_VERSION_MAJOR}.${COLOBOT_VERSION_MINOR}.${COLOBOT_VERSION_REVISION}${COLOBOT_VERSION_UNRELEASED}${COLOBOT_VERSION_RELEASE_CODENAME}")
message(STATUS "Building Colobot \"${COLOBOT_VERSION_CODENAME}\" (${COLOBOT_VERSION_FULL})")
-# Include cmake directory with some additional scripts
-set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${colobot_SOURCE_DIR}/cmake")
##
# Build options
##
-# Global build type
-if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE debug)
-endif()
+# Build targets should be placed in the root build directory
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+
+# Include cmake directory with some additional scripts
+set(CMAKE_MODULE_PATH "${colobot_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
# Compiler detection
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
@@ -83,8 +84,14 @@ set(COLOBOT_CXX_FLAGS_DEBUG "-g -O0")
# Asserts can be enabled/disabled regardless of build type
option(ASSERTS "Enable assert()s" ON)
+# Development build can be enabled/disabled regardless of build type
+option(DEV_BUILD "Enable development build (enables some debugging tools, local setting paths, etc.)" OFF)
+
# Building tests can be enabled/disabled
-option(TESTS "Enable tests" ON)
+option(TESTS "Build tests" OFF)
+
+# Building tool programs can be enabled/disabled
+option(TOOLS "Build tool programs" OFF)
# CBot can also be a static library
option(CBOT_STATIC "Build CBot as static libary" OFF)
@@ -95,8 +102,26 @@ option(DESKTOP "Generate desktop files, manpages, etc" ON)
# Doxygen docs are optional for installation
option(INSTALL_DOCS "Install Doxygen-generated documentation" OFF)
-# Build openal sound support
-option(OPENAL_SOUND "Build openal sound support" OFF)
+# Build OpenAL sound support
+option(OPENAL_SOUND "Build OpenAL sound support" ON)
+
+# Change to false in case static boost libraries are not available
+option(BOOST_STATIC "Link with static boost libraries" OFF)
+
+# This is useful on Windows, if linking against standard GLEW dll fails
+option(GLEW_STATIC "Link statically with GLEW" OFF)
+
+
+# Default build type if not given is debug
+if(NOT DEFINED CMAKE_BUILD_TYPE)
+ message(STATUS "Build type not specified - assuming debug")
+ set(CMAKE_BUILD_TYPE debug)
+endif()
+
+# Warn about development build
+if(DEV_BUILD)
+ message("Building with development extensions")
+endif()
##
@@ -110,21 +135,18 @@ find_package(SDL_ttf 2.0 REQUIRED)
find_package(PNG 1.2 REQUIRED)
find_package(Gettext REQUIRED)
-set(Boost_USE_STATIC_LIBS ON)
-set(Boost_USE_MULTITHREADED ON)
-set(Boost_USE_STATIC_RUNTIME OFF)
+set(Boost_USE_STATIC_LIBS ${BOOST_STATIC})
+set(Boost_USE_MULTITHREADED ON)
+set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_ADDITIONALVERSION "1.51" "1.51.0")
find_package(Boost COMPONENTS system filesystem regex REQUIRED)
-# This is useful on Windows, if linking against standard GLEW dll fails
-option(GLEW_STATIC "Link statically with GLEW" OFF)
-
find_package(GLEW REQUIRED)
-if (${OPENAL_SOUND})
+if (OPENAL_SOUND)
find_package(OpenAL REQUIRED)
- include("${colobot_SOURCE_DIR}/cmake/FindLibSndFile.cmake")
+ find_package(LibSndFile REQUIRED)
endif()
@@ -132,11 +154,11 @@ endif()
# Platform detection and some related checks
##
-if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+if("${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
set(PLATFORM_WINDOWS 1)
set(PLATFORM_LINUX 0)
set(PLATFORM_OTHER 0)
-elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(PLATFORM_WINDOWS 0)
set(PLATFORM_LINUX 1)
set(PLATFORM_OTHER 0)
@@ -146,11 +168,11 @@ else()
set(PLATFORM_OTHER 1)
endif()
-if(NOT ${ASSERTS})
+if(NOT ASSERTS)
add_definitions(-DNDEBUG)
endif()
-if(${TESTS})
+if(TESTS)
add_definitions(-DTESTS -DTEST_VIRTUAL=virtual)
else()
add_definitions(-DTEST_VIRTUAL=)
@@ -172,9 +194,9 @@ include("${colobot_SOURCE_DIR}/cmake/msys.cmake")
##
# Summary of detected things
##
-if (${PLATFORM_WINDOWS})
+if (PLATFORM_WINDOWS)
message(STATUS "Build for Windows system")
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
message(STATUS "Build for Linux system")
else()
message(STATUS "Build for other system")
@@ -182,6 +204,20 @@ endif()
##
+# Clipboard support
+##
+set(CLIPBOARD_INCLUDE_DIR ${colobot_SOURCE_DIR}/lib/clipboard/include)
+add_subdirectory(lib/clipboard)
+
+
+##
+# Localename
+##
+set(LOCALENAME_INCLUDE_DIR ${colobot_SOURCE_DIR}/lib/localename)
+add_subdirectory(lib/localename)
+
+
+##
# Doxygen docs
##
@@ -200,7 +236,7 @@ endif()
# Targets
##
-if(${TESTS})
+if(TESTS)
# Google Test library
find_path(GTEST_SRC_DIR NAMES src/gtest.cc src/gtest-all.cc PATHS /usr/src PATH_SUFFIXES gtest)
find_path(GTEST_INCLUDE_DIR gtest/gtest.h PATHS /usr/include)
@@ -212,7 +248,7 @@ if(${TESTS})
set(GTEST_INCLUDE_DIR ${colobot_SOURCE_DIR}/lib/gtest/include)
endif()
- add_subdirectory(${GTEST_SRC_DIR} bin/gtest)
+ add_subdirectory(${GTEST_SRC_DIR} lib/gtest)
# Google Mock library
find_path(GMOCK_SRC_DIR NAMES src/gmock.cc src/gmock-all.cc PATHS /usr/src PATH_SUFFIXES gmock)
@@ -227,23 +263,32 @@ if(${TESTS})
message(STATUS "Using bundled gmock library")
set(GMOCK_SRC_DIR ${colobot_SOURCE_DIR}/lib/gmock)
set(GMOCK_INCLUDE_DIR ${colobot_SOURCE_DIR}/lib/gmock/include)
- add_subdirectory(${GMOCK_SRC_DIR} bin/gmock)
+ add_subdirectory(${GMOCK_SRC_DIR} lib/gmock)
endif()
# Tests targets
enable_testing()
- add_subdirectory(test bin/test)
+ add_subdirectory(test)
endif()
# Installation paths defined before compiling sources
-if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
- set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
- set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
- set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory")
- set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot translations directory")
- set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
+if(PLATFORM_WINDOWS)
+ if(MXE)
+ # We need to use STRING because PATH doesn't accept relative paths
+ set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory")
+ set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory")
+ set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory")
+ set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory")
+ set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory")
+ else()
+ set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory")
+ set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory")
+ set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory")
+ set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory")
+ set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory")
+ endif()
else()
set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/games CACHE PATH "Colobot binary directory")
set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib/colobot CACHE PATH "Colobot libraries directory")
@@ -253,7 +298,17 @@ else()
endif()
# Subdirectory with sources
-add_subdirectory(src bin)
+add_subdirectory(src)
+
+add_subdirectory(po)
+
+if(DESKTOP)
+ if(PLATFORM_WINDOWS)
+ message("Desktop files ignored on Windows")
+ else()
+ add_subdirectory(desktop)
+ endif()
+endif()
##
diff --git a/INSTALL-MXE.txt b/INSTALL-MXE.md
index 120a60e..f12ed88 100644
--- a/INSTALL-MXE.txt
+++ b/INSTALL-MXE.md
@@ -29,6 +29,7 @@ To cross-compile Colobot using MXE:
* check-requirements
* expat
* flac
+ * flac
* freetype
* gcc
* gcc-gmp
@@ -39,24 +40,21 @@ To cross-compile Colobot using MXE:
* jpeg
* libiconv
* libpng
+ * libsndfile
* libtool
* mingwrt
+ * ogg
+ * openal
* portaudio
* sdl
* sdl_image
* sdl_ttf
* tiff
+ * vorbis
* w32api
* xz
* zlib
- For optional audio support you'll need also:
- * openal
- * libsndfile
- * ogg
- * vorbis
- * flac
-
4. Now `cd` to directory with colobot sources. To cross-compile a CMake project,
you have to specify a CMake toolchain file. MXE has such file in MXE's directory:
`usr/i686-pc-mingw32/share/cmake/mxe-conf.cmake`
@@ -68,4 +66,4 @@ To cross-compile Colobot using MXE:
5. `make` should now compile the game with the resulting exe in `bin/colobot.exe`.
The exe is linked against all libraries *statically*, so there are no dependencies
on external DLLs. However, the resulting binary will be huge with all these libraries,
- so you might want to do:`strip bin/colobot.exe`.
+ so you might want to do: `strip bin/colobot.exe`.
diff --git a/INSTALL.txt b/INSTALL.md
index cb9943f..b7d356a 100644
--- a/INSTALL.txt
+++ b/INSTALL.md
@@ -6,8 +6,9 @@ Colobot source files can be downloaded from Github repository (https://github.co
the repository as a ZIP archive, or, clone the repository using git or a GUI frontent for git.
Make sure that once you download/clone the repository, you have the neeeded data files in `data/` subdirectory.These files
-are provided as git submodule, hosted at a separate Github repository (https://github.com/colobot/colobot-data). If you
-don't have them, download the repository and unpack its content into `data/`.
+are provided as git submodule, hosted at a separate Github repository (https://github.com/colobot/colobot-data).
+If you don't have them, you can either download the repository manually and unpack its content into `data/` or,
+if you're working with git cloned repository, `git submodule update --init` will download the data submodule repository.
## Compiling on Windows
@@ -24,18 +25,19 @@ When installing, select **all** possible packages in the installer.
Next, download the development package available at Colobot site (http://colobot.info/) and unpack the files
from the archive to MinGW directory. This should provide a working environment, including CMake and
-all necessary packages.
+all necessary packages. However, make sure you get the right package. There are slight changes between GCC 4.6 and 4.7,
+especially with boost library which will result in build failure or error in runtime.
To compile Colobot, `cd` to directory with sources and run:
- $ cmake -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release -DOPENAL_SOUND=1 .
+ $ cmake -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release .
and then:
$ make
Everything should compile just fine. If you see any errors, it most likely means missing libraries or invalid installation.
Warnings may occur, but are mostly harmless.
-You'll get the binary in `bin/colobot.exe`, which you can run directly, pointing it to the data directory:
- $ bin/colobot.exe -datadir ./data
+You'll get the binary `colobot.exe`, which you can run directly, pointing it to the data directory:
+ $ colobot.exe -datadir ./data
You can also install Colobot in your system using
$ make install
@@ -49,7 +51,7 @@ See also "Hints and notes" below on some useful advice.
MXE (http://mxe.cc/) is a very good cross-compiling framework, complete with a suite of libraries
that make it extremely easy to port applications to Win32. It runs on pretty much any *nix flavor and generates generic,
-statically linked Win32 binaries. More information is available in INSTALL-MXE.txt file.
+statically linked Win32 binaries. More information is available in INSTALL-MXE.md file.
## Compiling on Linux
@@ -65,15 +67,13 @@ be different for different distros:
* GLEW >= 1.8.0
* libpng >= 1.2
* gettext >= 0.18
-
-For optional sound support (`-DOPENAL_SOUND`):
* libsndfile >= 1.0.25
* libvorbis >= 1.3.2
* libogg >= 1.3.0
- * OpenAL (OpenAL-Soft) >= 1.13 (optional)
+ * OpenAL (OpenAL-Soft) >= 1.13
Instructions for compiling are universal:
- $ cmake -DCMAKE_BUILD_TYPE=Release -DOPENAL_SOUND=1 .
+ $ cmake -DCMAKE_BUILD_TYPE=Release .
$ make
Everything should compile just fine. If you see any errors, it most likely means missing libraries. Warnings may occur,
@@ -107,8 +107,9 @@ This way, you can keep clean the directory with your source files. Example of us
$ make
-If you want to submit debug reports, please use Debug builds (`-DCMAKE_BUILD_TYPE=Debug`) and run the game in debug mode and with
-logging on higher level (commandline arguments: `-debug -loglevel debug`). Also, `-help` will give full list of available arguments.
+If you want to submit debug reports, please use special Debug and Dev builds (`-DDEV_BUILD=1 -DCMAKE_BUILD_TYPE=Debug`)
+and run the game in debug mode and with logging on higher level (commandline arguments: `-loglevel debug`).
+Also, `-help` will give full list of available arguments.
If you encounter any problems, you can get help at our forum or IRC channels.
diff --git a/README.md b/README.md
index 3e35172..21f7158 100644
--- a/README.md
+++ b/README.md
@@ -4,40 +4,32 @@ Welcome to the Colobot project code repository
This is official repository for the open-source Colobot project developed by Polish Portal of Colobot (PPC; in Polish: Polski Portal Colobota) with the official site at: http://colobot.info/.
-The source code contained here was released by Epsitec -- the original creator of the game -- on open source (GPLv3) license. The code was given and the rights granted specifically to PPC community in March 2012. Since then, we have been modifying the code and working on our goals, which are briefly summed up below.
+The source code contained here was released by Epsitec -- the original creator of the game -- on open source (GPLv3) license. The code was given and the rights granted specifically to PPC community in March 2012. Since then, we have been developing the game further.
-More information for developers (in English) can be found on the [developer wiki](https://colobot.info/wiki/Dev:Main_Page). However, the freshest source of information is our IRC channels, see below.
+More information for developers (in English) can be found on the [developer wiki](https://colobot.info/wiki/Dev:Main_Page) or [our forum](http://colobot.info/forum/). However, the freshest source of information is our IRC channels (see below).
-This repository contains only the source code of the project. The game requires also data files which are now provided as git submodule and are hosted in separate repository (https://github.com/colobot/colobot-data).
+This repository contains only the source code of the project. The game requires also data files which are now provided as git submodule and are hosted in [separate repository](https://github.com/colobot/colobot-data).
## Status
-Our main goals can be summed up in three milestones:
+The original version of the game, as released to us by Epsitec, is available as download at [our download site](http://colobot.info/files/) along with original source code and related data files. However, we will not develop this version further, as we focused our efforts on new versions of the game. The original version is also known as Colobot Classic.
-### Milestone 1 - Colobot Classic
+We are now working on refreshed and updated version of original game, codename Colobot Gold and this is the version currently hosted in this repository. The goal is to rewrite the game engine to be multi-platform, refresh the graphics, include some enhancements and refactor the code to make the game easier to modify.
-This is the original version of the game, as released to us by Epsitec with only minor changes and bugfixes. It is available as a tag named colobot-original in the repository. This version will not be developed further. The compiled version and data packs needed to run the game (split by language version) can also be found at http://colobot.info/files/.
+The project at this point is in alpha stage - the game is mostly playable, both on Windows and Linux, and most major bugs have been corrected. However, there is still a lot of work to be done. We are now working steadily towards subsequent beta releases, correcting other bugs and introducing enhancements and new features. There is a lot of work ahead and we will gladly accept any and all help.
-### Milestone 2 - Colobot Gold
-
-This is a version of the game that is currently being developed in this repository. It is based on the original code, but refreshed and rewritten using SDL and OpenGL libraries, thus making it multiplatform.
-
-Currently (March 2013), we have rewritten all of the original code and we are in the process of testing and fixing issues that are still present in the game. The master branch contains the current snapshot code which should always compile and run with the latest data pack. The dev branch is used for general development.
-
-### Milestone 3 - Colobot 2
-
-This will be a new installment in the Colobot series. We have many ideas for the new game and we are still discussing them. Generally, the development of this version will begin only after finishing Colobot Gold (it will be probably hosted in another repository, forked off the Colobot Gold code).
+In the future, we will begin development on a new installment in the Colobot series, codename Colobot 2. We have many ideas for the new game and we are still discussing them. Generally, the development of this version will begin only after finishing Colobot Gold (it will be probably hosted in another repository, forked off the Colobot Gold code).
## Compiling and running the game
-For these instructions see INSTALL.txt file.
+For these instructions see INSTALL.md file.
## Contact
-If you want to help in the project, please contact us on our IRC channels or the forum on our website: http://colobot.info/forum (Polish only).
+If you want to help in the project, please contact us on our IRC channels or [our forum](http://colobot.info/forum/) (Polish, though there is an English board as well).
### IRC channels
@@ -45,43 +37,40 @@ If you want to help in the project, please contact us on our IRC channels or the
* [#colobot on Freenode](irc://freenode.net#colobot) in English;
-# PL
+# Polski
Witamy w repozytorium projektu Colobot
To jest oficjalne repozytorium z kodem projektu open-source Colobot rozwijanego przez Polski Portal Colobota (PPC; po angielsku: Polish Portal of Colobot) z oficjalnÄ… stronÄ…: http://colobot.info/.
-Kod źródłowy zawarty tutaj został wydany przez Epsitec -- oryginalnego twórcę gry -- na otwartej licencji (GPLv3). Kod został wydany i prawa nadane specjalnie dla społeczności PPC w marcu 2012. Od tamtej pory, zajmujemy się modyfikowaniem kodu i pracowaniem nad naszymi celami, które są krótko podsumowane poniżej.
+Kod źródłowy zawarty tutaj został wydany przez Epsitec -- oryginalnego twórcę gry -- na otwartej licencji (GPLv3). Kod został wydany i prawa nadane specjalnie dla społeczności PPC w marcu 2012. Od tamtej pory, zajmowaliśmy się dalszym rozwojem gry.
-Więcej informacji dla developerów projektu (po angielsku) można znaleźć na [wiki dla developerów](http://colobot.info/wiki/Dev:Main_Page). Jednak źródłem najświeższych informacji jest nasz kanał IRC #colobot na pirc.pl.
+Więcej informacji dla developerów projektu (po angielsku) można znaleźć na [wiki dla developerów](http://colobot.info/wiki/Dev:Main_Page) lub [naszym forum](http://colobot.info/forum/). Jednak źródłem najświeższych informacji są nasze kanały IRC (patrz niżej).
-To repozytorium zawiera jedynie kod źródłowy projektu. Gra wymaga jeszcze plików danych, które są teraz udostępniane jako submoduł gita i hostowane w osobnym repozytorium ((https://github.com/colobot/colobot-data).
+To repozytorium zawiera jedynie kod źródłowy projektu. Gra wymaga jeszcze plików danych, które są teraz udostępniane jako submoduł gita i hostowane w [osobnym repozytorium]((https://github.com/colobot/colobot-data).
## Status
-Nasze główne cele można podsumować w trzech cel, które chcemy osiągnąć:
-
-### Cel 1 - Colobot Classic
+Oryginalna wersja gry, jaka została udostępniona nam przez Epsitec, jest dostępna do ściągnięcia na [naszej stronie](http://colobot.info/files/) wraz z oryginalnym kodem źródłowym i związanymi z nią plikami danych. Jednakże nie będziemy zajmować się dalszym rozwojem tej wersji, ponieważ skupiamy nasze wysiłki na tworzenie nowych wersji gry. Oryginalna wersja jest też znana jako Colobot Classic.
-To jest oryginalna wersja gry, dokładnie taka, jaką otrzymaliśmy od Epsiteca z jedynie niewielkimi zmianami i poprawkami. Jest dostępna jako tag nazwany colobot-original w repozytorium. Ta wersja nie będzie dalej rozwijana. Skompilowaną wersję wraz z potrzebnymi paczkami danych (podzielone wg wersji językowej) można pobrać z http://colobot.info/files.
+Obecnie pracujemy nad odświeżoną i uaktualnioną wersją oryginalnej gry, którą nazywamy Colobot Gold i jest to wersja obecnie dostępna w tym repozytorium. Celem tego projektu jest przepisanie silnika gry na wersję wieloplatformową, odświeżenie grafiki, dodanie pewnych usprawnień i zrefaktorowanie kodu tak, by dało się łatwiej modyfikować grę.
-### Cel 2 - Colobot Gold
+W tym momencie, gra jest w stadium alpha - gra jest w większości grywalna, pod Windowsem i Linuksem i większość poważnych bugów została poprawiona. Jednakże, jest nadal sporo pracy do zrobienia. Teraz systematycznie pracujemy do kolejnych wydań w fazie beta, poprawiając pozostałe bugi i wprowadzając usprawnienia i nowe funkcje. Jest sporo pracy przed nami i chętnie przyjmiemy pomoc w jakielkolwiek formie.
-Jest to wersja gry, którą obecnie rozwijamy w tym repozytorium. Jest oparta na oryginalnym kodzie, ale odświeżonym i przepisanym z wykorzystaniem bibliotek SDL i OpenGL, czyniąc ją wieloplatformową.
-
-Obecnie (marzec 2013), przepisaliśmy cały oryginalny kod i jesteśmy teraz w trakcie testowania i poprawiania błędów nadal obecnych w grze. Gałąź master zawiera obecny snapshot kodu, który powinien zawsze dać się skompilować i uruchomić z aktualną paczką danych. Gałąź dev jest wykorzystywana do ogólnego rozwoju.
-
-### Krok 3 - Colobot 2
-
-To będzie nowa część z cyklu gier Colobot. Mamy wiele pomysłów na nową grę i nadal dyskutujemy nad nimi. Ogólnie, rozwój tej wersji zacznie się po skończeniu wersji Colobot Gold (prawdopodobnie będzie hostowane w osobnym repozytorium, sforkowanym z kodu Colobot Gold).
+W przyszłości, planujemy rozpocząć prace nad nową częścią z serii Colobot, pod nazwą Colobot 2.Mamy wiele pomysłów na nową grę i nadal dyskutujemy nad nimi. Ogólnie, rozwój tej wersji zacznie się po skończeniu wersji Colobot Gold (prawdopodobnie będzie hostowane w osobnym repozytorium, sforkowanym z kodu Colobot Gold).
## Kompilacja i uruchomienie gry
-Instrukcje te znajdujÄ… siÄ™ w pliku INSTALL.txt (po angielsku).
+Instrukcje te znajdujÄ… siÄ™ w pliku INSTALL.md (po angielsku).
## Kontakt
-Jeżeli chcesz pomóc w projekcie, prosimy o kontakt na naszym kanale IRC: #colobot na pirc.pl (po polsku i angielsku) albo na forum na naszej stronie: http://colobot.info/forum (jedynie polski).
+Jeżeli chcesz pomóc w projekcie, prosimy o kontakt na naszych kanałach IRC lub [naszym forum](http://colobot.info/forum/).
+
+### Kanały IRC
+
+* [#colobot on pirc.pl](irc://pirc.pl#colobot) polski;
+* [#colobot on Freenode](irc://freenode.net#colobot) angielski;
diff --git a/bin/.gitignore b/bin/.gitignore
deleted file mode 100644
index 96ec5ae..0000000
--- a/bin/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-# Ignore everything
-*
-
-# But not these files...
-!.gitignore
-!README.txt
diff --git a/bin/README.txt b/bin/README.txt
deleted file mode 100644
index c63a6ee..0000000
--- a/bin/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-Target directory for binary objects: colobot.exe and CBot/libCBot.dll
diff --git a/cmake/FindGettext.cmake b/cmake/FindGettext.cmake
new file mode 100644
index 0000000..ca1150e
--- /dev/null
+++ b/cmake/FindGettext.cmake
@@ -0,0 +1,218 @@
+##
+# Patched version of original CMake module
+# Added variable GETTEXT_INSTALL_PREFIX to optionally override installation path of resulting translations
+##
+
+# - Find GNU gettext tools
+# This module looks for the GNU gettext tools. This module defines the
+# following values:
+# GETTEXT_MSGMERGE_EXECUTABLE: the full path to the msgmerge tool.
+# GETTEXT_MSGFMT_EXECUTABLE: the full path to the msgfmt tool.
+# GETTEXT_FOUND: True if gettext has been found.
+# GETTEXT_VERSION_STRING: the version of gettext found (since CMake 2.8.8)
+#
+# Additionally it provides the following macros:
+# GETTEXT_CREATE_TRANSLATIONS ( outputFile [ALL] file1 ... fileN )
+# This will create a target "translations" which will convert the
+# given input po files into the binary output mo file. If the
+# ALL option is used, the translations will also be created when
+# building the default target.
+# GETTEXT_PROCESS_POT( <potfile> [ALL] [INSTALL_DESTINATION <destdir>] LANGUAGES <lang1> <lang2> ... )
+# Process the given pot file to mo files.
+# If INSTALL_DESTINATION is given then automatically install rules will be created,
+# the language subdirectory will be taken into account (by default use share/locale/).
+# If ALL is specified, the pot file is processed when building the all traget.
+# It creates a custom target "potfile".
+# GETTEXT_PROCESS_PO_FILES( <lang> [ALL] [INSTALL_DESTINATION <dir>] PO_FILES <po1> <po2> ... )
+# Process the given po files to mo files for the given language.
+# If INSTALL_DESTINATION is given then automatically install rules will be created,
+# the language subdirectory will be taken into account (by default use share/locale/).
+# If ALL is specified, the po files are processed when building the all traget.
+# It creates a custom target "pofiles".
+
+#=============================================================================
+# Copyright 2007-2009 Kitware, Inc.
+# Copyright 2007 Alexander Neundorf <neundorf@kde.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+find_program(GETTEXT_MSGMERGE_EXECUTABLE msgmerge)
+
+find_program(GETTEXT_MSGFMT_EXECUTABLE msgfmt)
+
+if(GETTEXT_MSGMERGE_EXECUTABLE)
+ execute_process(COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --version
+ OUTPUT_VARIABLE gettext_version
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (gettext_version MATCHES "^msgmerge \\(.*\\) [0-9]")
+ string(REGEX REPLACE "^msgmerge \\([^\\)]*\\) ([0-9\\.]+[^ \n]*).*" "\\1" GETTEXT_VERSION_STRING "${gettext_version}")
+ endif()
+ unset(gettext_version)
+endif()
+
+set(GETTEXT_INSTALL_PREFIX share/locale)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Gettext
+ REQUIRED_VARS GETTEXT_MSGMERGE_EXECUTABLE GETTEXT_MSGFMT_EXECUTABLE
+ VERSION_VAR GETTEXT_VERSION_STRING)
+
+include(CMakeParseArguments)
+
+function(_GETTEXT_GET_UNIQUE_TARGET_NAME _name _unique_name)
+ set(propertyName "_GETTEXT_UNIQUE_COUNTER_${_name}")
+ get_property(currentCounter GLOBAL PROPERTY "${propertyName}")
+ if(NOT currentCounter)
+ set(currentCounter 1)
+ endif()
+ set(${_unique_name} "${_name}_${currentCounter}" PARENT_SCOPE)
+ math(EXPR currentCounter "${currentCounter} + 1")
+ set_property(GLOBAL PROPERTY ${propertyName} ${currentCounter} )
+endfunction()
+
+macro(GETTEXT_CREATE_TRANSLATIONS _potFile _firstPoFileArg)
+ # make it a real variable, so we can modify it here
+ set(_firstPoFile "${_firstPoFileArg}")
+
+ set(_gmoFiles)
+ get_filename_component(_potName ${_potFile} NAME)
+ string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _potBasename ${_potName})
+ get_filename_component(_absPotFile ${_potFile} ABSOLUTE)
+
+ set(_addToAll)
+ if(${_firstPoFile} STREQUAL "ALL")
+ set(_addToAll "ALL")
+ set(_firstPoFile)
+ endif()
+
+ foreach (_currentPoFile ${_firstPoFile} ${ARGN})
+ get_filename_component(_absFile ${_currentPoFile} ABSOLUTE)
+ get_filename_component(_abs_PATH ${_absFile} PATH)
+ get_filename_component(_lang ${_absFile} NAME_WE)
+ set(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo)
+
+ add_custom_command(
+ OUTPUT ${_gmoFile}
+ COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_absFile} ${_absPotFile}
+ COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_absFile}
+ DEPENDS ${_absPotFile} ${_absFile}
+ )
+
+ install(FILES ${_gmoFile} DESTINATION ${GETTEXT_INSTALL_PREFIX}/${_lang}/LC_MESSAGES RENAME ${_potBasename}.mo)
+ set(_gmoFiles ${_gmoFiles} ${_gmoFile})
+
+ endforeach ()
+
+ if(NOT TARGET translations)
+ add_custom_target(translations)
+ endif()
+
+ _GETTEXT_GET_UNIQUE_TARGET_NAME(translations uniqueTargetName)
+
+ add_custom_target(${uniqueTargetName} ${_addToAll} DEPENDS ${_gmoFiles})
+
+ add_dependencies(translations ${uniqueTargetName})
+
+endmacro()
+
+
+function(GETTEXT_PROCESS_POT_FILE _potFile)
+ set(_gmoFiles)
+ set(_options ALL)
+ set(_oneValueArgs INSTALL_DESTINATION)
+ set(_multiValueArgs LANGUAGES)
+
+ CMAKE_PARSE_ARGUMENTS(_parsedArguments "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
+
+ get_filename_component(_potName ${_potFile} NAME)
+ string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _potBasename ${_potName})
+ get_filename_component(_absPotFile ${_potFile} ABSOLUTE)
+
+ foreach (_lang ${_parsedArguments_LANGUAGES})
+ set(_poFile "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.po")
+ set(_gmoFile "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo")
+
+ add_custom_command(
+ OUTPUT "${_poFile}"
+ COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_poFile} ${_absPotFile}
+ DEPENDS ${_absPotFile}
+ )
+
+ add_custom_command(
+ OUTPUT "${_gmoFile}"
+ COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_poFile}
+ DEPENDS ${_absPotFile} ${_poFile}
+ )
+
+ if(_parsedArguments_INSTALL_DESTINATION)
+ install(FILES ${_gmoFile} DESTINATION ${_parsedArguments_INSTALL_DESTINATION}/${_lang}/LC_MESSAGES RENAME ${_potBasename}.mo)
+ endif()
+ list(APPEND _gmoFiles ${_gmoFile})
+ endforeach ()
+
+ if(NOT TARGET potfiles)
+ add_custom_target(potfiles)
+ endif()
+
+ _GETTEXT_GET_UNIQUE_TARGET_NAME( potfiles uniqueTargetName)
+
+ if(_parsedArguments_ALL)
+ add_custom_target(${uniqueTargetName} ALL DEPENDS ${_gmoFiles})
+ else()
+ add_custom_target(${uniqueTargetName} DEPENDS ${_gmoFiles})
+ endif()
+
+ add_dependencies(potfiles ${uniqueTargetName})
+
+endfunction()
+
+
+function(GETTEXT_PROCESS_PO_FILES _lang)
+ set(_options ALL)
+ set(_oneValueArgs INSTALL_DESTINATION)
+ set(_multiValueArgs PO_FILES)
+ set(_gmoFiles)
+
+ CMAKE_PARSE_ARGUMENTS(_parsedArguments "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
+
+ foreach(_current_PO_FILE ${_parsedArguments_PO_FILES})
+ get_filename_component(_name ${_current_PO_FILE} NAME)
+ string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _basename ${_name})
+ set(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.gmo)
+ add_custom_command(OUTPUT ${_gmoFile}
+ COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_current_PO_FILE}
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ DEPENDS ${_current_PO_FILE}
+ )
+
+ if(_parsedArguments_INSTALL_DESTINATION)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.gmo DESTINATION ${_parsedArguments_INSTALL_DESTINATION}/${_lang}/LC_MESSAGES/ RENAME ${_basename}.mo)
+ endif()
+ list(APPEND _gmoFiles ${_gmoFile})
+ endforeach()
+
+
+ if(NOT TARGET pofiles)
+ add_custom_target(pofiles)
+ endif()
+
+ _GETTEXT_GET_UNIQUE_TARGET_NAME( pofiles uniqueTargetName)
+
+ if(_parsedArguments_ALL)
+ add_custom_target(${uniqueTargetName} ALL DEPENDS ${_gmoFiles})
+ else()
+ add_custom_target(${uniqueTargetName} DEPENDS ${_gmoFiles})
+ endif()
+
+ add_dependencies(pofiles ${uniqueTargetName})
+
+endfunction()
diff --git a/data b/data
-Subproject 827236ef15f105613f083bf3aeb1629b13ba2f5
+Subproject 2d7172438e8db1fa6d73d1c5f314489f8c936c1
diff --git a/desktop/.gitignore b/desktop/.gitignore
new file mode 100644
index 0000000..e6649e0
--- /dev/null
+++ b/desktop/.gitignore
@@ -0,0 +1,7 @@
+lang/
+fr/
+16/
+32/
+48/
+colobot.6
+colobot.desktop
diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt
new file mode 100644
index 0000000..6d2ece0
--- /dev/null
+++ b/desktop/CMakeLists.txt
@@ -0,0 +1,99 @@
+cmake_minimum_required(VERSION 2.8)
+
+# Install Desktop Entry file
+set(COLOBOT_DESKTOP_FILE colobot.desktop)
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}
+ COMMAND ./create_desktop_file.sh > ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ COMMENT "Build ${COLOBOT_DESKTOP_FILE}"
+ )
+add_custom_target(desktopfile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE})
+install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/
+ )
+
+# Install Icon
+set(COLOBOT_ICON_FILE colobot.svg)
+install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/
+ )
+
+# Render SVG icon in various sizes
+find_program(RSVG_CONVERT rsvg-convert)
+if(RSVG_CONVERT)
+ foreach(PNGSIZE "48" "32" "16")
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE})
+ add_custom_target(resize_icon_${PNGSIZE} ALL
+ COMMAND ${RSVG_CONVERT} -w ${PNGSIZE} -h ${PNGSIZE} ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE}
+ > ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png
+ )
+ install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${PNGSIZE}x${PNGSIZE}/apps/
+ )
+ endforeach()
+endif()
+
+# Create manpage from pod-formatted file
+find_program(POD2MAN pod2man)
+if(POD2MAN)
+ set(COLOBOT_MANPAGE_SECTION 6)
+
+ macro(podman)
+ cmake_parse_arguments(PM "" "PODFILE;LOCALE;" "" ${ARGN})
+ if(PM_LOCALE)
+ # This copes with the fact that english has no "/LANG" in the paths and filenames.
+ set(SLASHLOCALE /${PM_LOCALE})
+ endif()
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE})
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE}
+ COMMAND ${POD2MAN} ARGS --section=${COLOBOT_MANPAGE_SECTION}
+ --center="Colobot" --stderr --utf8
+ --release="${COLOBOT_VERSION_FULL}"
+ ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE}
+ ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}
+ COMMENT "Create ${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} manpage"
+ )
+ add_custom_target(man${PM_LOCALE} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION})
+
+ install(
+ FILES ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man${SLASHLOCALE}/man${COLOBOT_MANPAGE_SECTION}/ )
+
+ add_dependencies(man man${PM_LOCALE})
+ endmacro()
+
+ # Create the english manpage
+ podman(PODFILE colobot.pod)
+
+endif()
+
+# Translate translatable material
+find_program(PO4A po4a)
+
+if(PO4A)
+ add_custom_target(desktop_po4a
+ COMMAND ${PO4A} po4a.cfg
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+ add_dependencies(desktopfile desktop_po4a)
+
+ if(POD2MAN)
+ add_custom_target(man_po4a
+ COMMAND ${PO4A} po4a.cfg
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+ add_dependencies(man man_po4a)
+ file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po)
+ string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO})
+ foreach(LOCALE ${LINGUAS})
+ podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE})
+ add_dependencies(man${PM_LOCALE} man_po4a)
+ endforeach()
+ endif()
+endif()
+
diff --git a/src/desktop/colobot.desktop.in b/desktop/colobot.desktop.in
index 9b09803..9b48d87 100644
--- a/src/desktop/colobot.desktop.in
+++ b/desktop/colobot.desktop.in
@@ -4,3 +4,4 @@ Type=Application
Exec=colobot
Icon=colobot
Categories=Education;Robotics;Game;AdventureGame;StrategyGame;
+
diff --git a/src/desktop/colobot.ini b/desktop/colobot.ini
index 136e008..27193df 100644
--- a/src/desktop/colobot.ini
+++ b/desktop/colobot.ini
@@ -1,3 +1,4 @@
Name="Colobot"
GenericName="Game to learn programming"
Comment="Colonize with bots"
+
diff --git a/src/desktop/colobot.pod b/desktop/colobot.pod
index ae67e72..6a25f70 100644
--- a/src/desktop/colobot.pod
+++ b/desktop/colobot.pod
@@ -45,3 +45,4 @@ Set language. Note that you can also fill the B<LANG> environment variable.
=head1 AUTHOR
This manpage was written by Didier Raboud <S<odyx@debian.org>>.
+
diff --git a/src/desktop/colobot.svg b/desktop/colobot.svg
index 85a0545..ef5949f 100644
--- a/src/desktop/colobot.svg
+++ b/desktop/colobot.svg
@@ -236,3 +236,4 @@
</g>
</g>
</svg>
+
diff --git a/src/desktop/create_desktop_file.sh b/desktop/create_desktop_file.sh
index e0f120b..8f3d15b 100755
--- a/src/desktop/create_desktop_file.sh
+++ b/desktop/create_desktop_file.sh
@@ -11,8 +11,8 @@ cat colobot.desktop.in
linguas=$([ ! -d lang ] || ( cd lang ; ls));
for type in Name GenericName Comment; do
- egrep "^$type=" $fname | sed -e "s/^$type=\"\(.*\)\"$/$type=\1/g"
- for l in $linguas; do
- egrep "^$type=" lang/$l/$fname | sed -e "s/^$type=\"\(.*\)\"$/$type[$l]=\1/g"
- done
+ egrep "^$type=" $fname | sed -e "s/^$type=\"\(.*\)\"$/$type=\1/g"
+ for l in $linguas; do
+ egrep "^$type=" lang/$l/$fname | sed -e "s/^$type=\"\(.*\)\"$/$type[$l]=\1/g"
+ done
done
diff --git a/src/desktop/po/colobot-desktop.pot b/desktop/po/colobot-desktop.pot
index 94eb85a..ac6bbd2 100644
--- a/src/desktop/po/colobot-desktop.pot
+++ b/desktop/po/colobot-desktop.pot
@@ -132,3 +132,4 @@ msgstr ""
#: colobot.pod:47
msgid "This manpage was written by Didier Raboud <S<odyx@debian.org>>."
msgstr ""
+
diff --git a/src/desktop/po/fr.po b/desktop/po/fr.po
index 40fa9e1..40fa9e1 100644
--- a/src/desktop/po/fr.po
+++ b/desktop/po/fr.po
diff --git a/src/desktop/po4a.cfg b/desktop/po4a.cfg
index c251959..881929d 100644
--- a/src/desktop/po4a.cfg
+++ b/desktop/po4a.cfg
@@ -2,3 +2,4 @@
[type:ini] colobot.ini $lang:lang/$lang/colobot.ini
[type:pod] colobot.pod $lang:lang/$lang/colobot.pod
+
diff --git a/lib/clipboard/.gitignore b/lib/clipboard/.gitignore
new file mode 100644
index 0000000..ffbe18e
--- /dev/null
+++ b/lib/clipboard/.gitignore
@@ -0,0 +1 @@
+libclipboard.a
diff --git a/lib/clipboard/CMakeLists.txt b/lib/clipboard/CMakeLists.txt
new file mode 100644
index 0000000..a189ec4
--- /dev/null
+++ b/lib/clipboard/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8)
+
+include_directories(. include/clipboard)
+
+add_definitions(-DLIB_COMPILE=1)
+
+
+if(PLATFORM_WINDOWS)
+ set(CLIPBOARD_SRC src/clipboardWin32.c)
+elseif(PLATFORM_LINUX)
+ set(CLIPBOARD_SRC src/clipboardX11.c)
+else()
+ set(CLIPBOARD_SRC src/clipboardX11.c)
+endif()
+
+include_directories(${SDL_INCLUDE_DIR})
+add_library(clipboard STATIC src/utf.c ${CLIPBOARD_SRC})
diff --git a/lib/clipboard/COPYING.README b/lib/clipboard/COPYING.README
new file mode 100644
index 0000000..2f8aad8
--- /dev/null
+++ b/lib/clipboard/COPYING.README
@@ -0,0 +1,72 @@
+Warzone 2100 Source & Data
+--------------------------
+
+This document replaces the file "readme.txt" as present in the Warzone 2100 GPL
+ release of December 6th 2004.
+
+1) These source and data files are provided as is with no guarantees:
+ - No assistance or support will be offered or given.
+ - Everything you will require to make a build of the game should be here. If
+ it isn't, you'll have to improvise.
+ - None of us here at Pivotal Games are in a position to be able to offer any
+ help with making this work.
+
+2) Everything included (source code and data), as well as the not included
+ videos and music, is released under the terms of the GNU General Public
+ License, version 2 or (at your option) any later version.
+ Please be sure to read the entirety of this license, but the summary is that
+ you're free to do what you want with the source subject to making the full
+ source code freely available in the event of the distribution of new
+ binaries.
+
+3) Following exception to the GPL is granted:
+ ------
+ Linking Warzone 2100 statically or dynamically with other modules is making
+ a combined work based on Warzone 2100. Thus, the terms and conditions of
+ the GNU General Public License cover the whole combination.
+
+ In addition, as a special exception, the copyright holders of Warzone 2100
+ give you permission to combine Warzone 2100 with code included in the
+ standard release of libraries that are accessible, redistributable and
+ linkable free of charge. You may copy and distribute such a system
+ following the terms of the GNU GPL for Warzone 2100 and the licenses of the
+ other code concerned.
+
+ Note that people who make modified versions of Warzone 2100 are not
+ obligated to grant this special exception for their modified versions; it
+ is their choice whether to do so. The GNU General Public License gives
+ permission to release a modified version without this exception; this
+ exception also makes it possible to release a modified version which
+ carries forward this exception.
+ ------
+
+4) Permission is granted to use the name "Warzone 2100", the logos, stories,
+ texts and related materials.
+
+5) Permission is granted to copy and distribute unaltered copies and/or images
+ of the original game discs in any medium, provided that they are distributed
+ free of charge and retain their original copyright and trademark notices.
+
+Finally, the primary motivation for this release is for entertainment and
+ educational purposes. On the subject of the latter, don't be surprised to see
+ some pretty gnarly old-school C code in here; the game was a classic, but large
+ areas of the code aren't pretty; OO design and C++ evangelists beware! We
+ haven't spent any time cleaning the code or making it pretty - what you see is
+ what you're getting, warts n' all.
+
+Thank you to Jonathan Kemp of Eidos Europe for permitting the release. Thanks to
+ Martin Severn for allowing to use his soundtrack. Thanks to Jason Walker for
+ helping to facilitate the release of the movies and sound tracks, as well as
+ clarifying the meaning of this license. Thanks also to Frank Lamboy for
+ assistance with the release and for campaigning along with many many others
+ over the years for the source to be made available.
+The correspondence, online petitions and persistence made this possible. We were
+ constantly amazed at the community support for Warzone even after all this
+ time; it's nice to be able to give something back, assuming you can get it to
+ compile... ;-)
+
+Original - 6th December 2004
+Alex M - ex Pumpkin Studios (Eidos)
+
+Amended - 10th June 2008
+Jason W - Eidos
diff --git a/lib/clipboard/include/clipboard/clipboard.h b/lib/clipboard/include/clipboard/clipboard.h
new file mode 100644
index 0000000..dcee2ea
--- /dev/null
+++ b/lib/clipboard/include/clipboard/clipboard.h
@@ -0,0 +1,55 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 2008 Freddie Witherden
+ Copyright (C) 2008-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CLIPBOARD_H_
+#define CLIPBOARD_H_
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * Returns a copy of the text in the systems clipboard. Should the clipboard be
+ * empty, or populated with non-textual data NULL is returned. The character set
+ * of the returned is guaranteed to be UTF-8.
+ *
+ * It remains the responsibility of the caller to free() the string when
+ * finished with it.
+ *
+ * @return The textual contents of the clipboard (if any), otherwise NULL.
+ */
+char *widgetGetClipboardText(void);
+
+/**
+ * Attempts to set the contents of the systems clipboard to text. The character
+ * set of text must be UTF-8.
+ *
+ * @param text The UTF-8 text to set the clipboard to.
+ * @return True if the contents were successfully set, false otherwise.
+ */
+bool widgetSetClipboardText(const char *text);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*CLIPBOARD_H_*/
diff --git a/lib/clipboard/include/clipboard/types.h b/lib/clipboard/include/clipboard/types.h
new file mode 100644
index 0000000..ff7ca68
--- /dev/null
+++ b/lib/clipboard/include/clipboard/types.h
@@ -0,0 +1,100 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 1999-2004 Eidos Interactive
+ Copyright (C) 2005-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/*! \file
+ * \brief Simple type definitions.
+ */
+
+#ifndef __INCLUDED_LIB_FRAMEWORK_TYPES_H__
+#define __INCLUDED_LIB_FRAMEWORK_TYPES_H__
+
+#include "wzglobal.h"
+
+#ifdef HAVE_INTTYPES_H // defined WZ_C99
+/* Compilers that have support for C99 have all values below defined in stdint.h */
+# include <inttypes.h>
+#else
+// Defines C99 types for C99 incompatible compilers (e.g. MSVC)
+#include <SDL_stdinc.h>
+#ifndef WZ_CC_MINGW
+# define INT8_MIN (-128)
+# define INT16_MIN (-32767-1)
+# define INT32_MIN (-2147483647-1)
+# define INT8_MAX (127)
+# define INT16_MAX (32767)
+# define INT32_MAX (2147483647)
+# define UINT8_MAX (255)
+# define UINT16_MAX (65535)
+# define UINT32_MAX (4294967295U)
+#endif
+#ifdef WZ_CC_MSVC
+# define PRIu32 "u"
+# define PRIu64 "I64u"
+typedef SSIZE_T ssize_t;
+#endif
+#endif // WZ_C99
+
+#include <limits.h>
+#include <ctype.h>
+
+/* Basic numeric types */
+typedef uint8_t UBYTE;
+typedef int8_t SBYTE;
+typedef uint16_t UWORD;
+typedef int16_t SWORD;
+typedef uint32_t UDWORD;
+typedef int32_t SDWORD;
+
+/* Numeric size defines */
+#define UBYTE_MAX UINT8_MAX
+#define SBYTE_MIN INT8_MIN
+#define SBYTE_MAX INT8_MAX
+#define UWORD_MAX UINT16_MAX
+#define SWORD_MIN INT16_MIN
+#define SWORD_MAX INT16_MAX
+#define UDWORD_MAX UINT32_MAX
+#define SDWORD_MIN INT32_MIN
+#define SDWORD_MAX INT32_MAX
+
+// If we are C99 compatible, the "bool" macro will be defined in <stdbool.h> (as _Bool)
+// C++ comes with an integrated bool type
+#if defined(WZ_CXX98)
+#elif defined(WZ_C99)
+# include <stdbool.h>
+#else
+// Pretend we are C99 compatible (well, for the bool type then)
+# ifndef bool
+# define bool BOOL
+# endif
+# ifndef true
+# define true (1)
+# endif
+# ifndef false
+# define false (0)
+# endif
+# ifndef __bool_true_false_are_defined
+# define __bool_true_false_are_defined (1)
+# endif
+#endif /* WZ_C99 */
+
+#if !defined(WZ_OS_WIN)
+typedef int BOOL;
+#endif // WZ_OS_WIN
+
+#endif // __INCLUDED_LIB_FRAMEWORK_TYPES_H__
diff --git a/lib/clipboard/include/clipboard/utf.h b/lib/clipboard/include/clipboard/utf.h
new file mode 100644
index 0000000..eadc3b3
--- /dev/null
+++ b/lib/clipboard/include/clipboard/utf.h
@@ -0,0 +1,115 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 2007 Giel van Schijndel
+ Copyright (C) 2007-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ $Revision: 9336 $
+ $Id: utf.h 9336 2010-01-18 19:10:17Z cypr $
+ $HeadURL: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk/lib/framework/utf.h $
+*/
+
+#ifndef __INCLUDE_LIB_FRAMEWORK_UTF8_H__
+#define __INCLUDE_LIB_FRAMEWORK_UTF8_H__
+
+/* Allow frame header files to be singly included */
+#define FRAME_LIB_INCLUDE
+
+#include "types.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+/** Used to store a UTF-32 character in
+ */
+typedef uint32_t utf_32_char;
+
+/** Used to store a UTF-16 character in (this is <em>not</em> necessarily a
+ * full Unicode codepoint)
+ */
+typedef uint16_t utf_16_char;
+
+/** Decodes a single Unicode character from the given UTF-16 string.
+ *
+ * \param utf16_char Points to a character string that should contain at
+ * least one valid UTF-16 character sequence.
+ * \param[out] next_char Will be modified to point to the first character
+ * following the UTF-16 character sequence.
+ *
+ * \return The Unicode character encoded as UTF-32 with native endianness.
+ */
+utf_32_char UTF16DecodeChar(const utf_16_char *utf16_char, const utf_16_char **next_char);
+
+/** Decodes a single Unicode character from the given UTF-8 string.
+ *
+ * \param utf8_char Points to a character string that should contain at
+ * least one valid UTF-8 character sequence.
+ * \param[out] next_char Will be modified to point to the first character
+ * following the UTF-8 character sequence.
+ *
+ * \return The Unicode character encoded as UTF-32 with native endianness.
+ */
+utf_32_char UTF8DecodeChar(const char *utf8_char, const char **next_char);
+
+/** Determines the amount of unicode codepoints in a UTF-8 encoded string
+ * \param utf8_string the UTF-8 encoded string to count
+ * \return the amount of codepoints found in the UTF-8 string
+ */
+size_t UTF8CharacterCount(const char *utf8_string);
+
+size_t UTF16CharacterCount(const uint16_t *utf16);
+
+/** Encodes a UTF-16 encoded unicode string to a UTF-8 encoded string
+ * \param unicode_string the UTF-16 encoded unicode string to encode into UTF-8
+ * \param[out] nbytes the number of bytes allocated, may be NULL
+ * \return a UTF-8 encoded unicode nul terminated string (use free() to deallocate it)
+ */
+char *UTF16toUTF8(const utf_16_char *unicode_string, size_t *nbytes);
+
+/** Decodes a UTF-8 encoded string to a UTF-16 encoded string (native endianess)
+ * \param utf8_string a UTF-8 encoded nul terminated string
+ * \param[out] nbytes the number of bytes allocated, may be NULL
+ * \return a UTF-16 encoded unicode nul terminated string (use free() to deallocate it)
+ */
+utf_16_char *UTF8toUTF16(const char *utf8_string, size_t *nbytes);
+
+char *UTF8CharacterAtOffset(const char *utf8_string, size_t index);
+utf_16_char *UTF16CharacterAtOffset(const utf_16_char *utf16_string, size_t index);
+
+/** Encodes a UTF-32 string to a UTF-8 encoded string
+ * \param unicode_string the UTF-32 string to encode into UTF-8
+ * \param[out] nbytes the number of bytes allocated, may be NULL
+ * \return a UTF-8 encoded unicode nul terminated string (use free() to deallocate it)
+ */
+char *UTF32toUTF8(const utf_32_char *unicode_string, size_t *nbytes);
+
+/** Decodes a UTF-8 encoded string to a UTF-32 string
+ * \param utf8_string a UTF-8 encoded nul terminated string
+ * \param[out] nbytes the number of bytes allocated, may be NULL
+ * \return a UTF-32 nul terminated string (use free() to deallocate it)
+ */
+utf_32_char *UTF8toUTF32(const char *utf8_string, size_t *nbytes);
+
+/** Returns number of characters, not including terminating nul. */
+size_t utf32len(const utf_32_char *unicode_string);
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#endif // __INCLUDE_LIB_FRAMEWORK_UTF8_H__
diff --git a/lib/clipboard/include/clipboard/wzglobal.h b/lib/clipboard/include/clipboard/wzglobal.h
new file mode 100644
index 0000000..113223e
--- /dev/null
+++ b/lib/clipboard/include/clipboard/wzglobal.h
@@ -0,0 +1,614 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 1992-2007 Trolltech ASA.
+ Copyright (C) 2005-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+/*! \file wzglobal.h
+ * \brief Platform detection, workarounds and compat fixes
+ *
+ * OS and CC detection code shamelessly stolen from Qt4 (Qt/qglobal.h) by Dennis.
+ * This has been stripped down, feel free to add checks as you need them.
+ */
+
+#ifndef WZGLOBAL_H
+#define WZGLOBAL_H
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+#if defined(HAVE_CONFIG_H)
+# undef _XOPEN_SOURCE
+# include "config.h"
+#elif defined(__MACOSX__)
+# include "config-macosx.h"
+#endif
+
+
+/* ---- Platform detection ---- */
+
+
+/*
+ The operating system, must be one of: (WZ_OS_x)
+
+ DARWIN - Darwin OS (synonym for WZ_OS_MAC)
+ OS2 - OS/2
+ OS2EMX - XFree86 on OS/2 (not PM)
+ WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP)
+ CYGWIN - Cygwin
+ SOLARIS - Sun Solaris
+ HPUX - HP-UX
+ ULTRIX - DEC Ultrix
+ LINUX - Linux
+ FREEBSD - FreeBSD
+ GNU_kFREEBSD - GNU/kFreeBSD
+ NETBSD - NetBSD
+ OPENBSD - OpenBSD
+ BSDI - BSD/OS
+ IRIX - SGI Irix
+ OSF - HP Tru64 UNIX
+ SCO - SCO OpenServer 5
+ UNIXWARE - UnixWare 7, Open UNIX 8
+ AIX - AIX
+ HURD - GNU Hurd
+ DGUX - DG/UX
+ RELIANT - Reliant UNIX
+ DYNIX - DYNIX/ptx
+ QNX - QNX
+ QNX6 - QNX RTP 6.1
+ LYNX - LynxOS
+ BSD4 - Any BSD 4.4 system
+ UNIX - Any UNIX BSD/SYSV system
+*/
+
+#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
+# define WZ_OS_DARWIN
+# define WZ_OS_BSD4
+# ifdef __LP64__
+# define WZ_OS_DARWIN64
+# else
+# define WZ_OS_DARWIN32
+# endif
+#elif defined(__CYGWIN__)
+# define WZ_OS_CYGWIN
+#elif defined(__OS2__)
+# if defined(__EMX__)
+# define WZ_OS_OS2EMX
+# else
+# define WZ_OS_OS2
+# endif
+#elif !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
+# define WZ_OS_WIN32
+# define WZ_OS_WIN64
+#elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
+# define WZ_OS_WIN32
+#elif defined(__MWERKS__) && defined(__INTEL__)
+# define WZ_OS_WIN32
+#elif defined(__sun) || defined(sun)
+# define WZ_OS_SOLARIS
+#elif defined(hpux) || defined(__hpux)
+# define WZ_OS_HPUX
+#elif defined(__ultrix) || defined(ultrix)
+# define WZ_OS_ULTRIX
+#elif defined(sinix)
+# define WZ_OS_RELIANT
+#elif defined(__linux__) || defined(__linux)
+# define WZ_OS_LINUX
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
+# define WZ_OS_FREEBSD
+# define WZ_OS_BSD4
+#elif defined(__FreeBSD_kernel__) && !defined(__FreeBSD__)
+ /* We're running a non-FreeBSD system with a FreeBSD kernel. Find out what C
+ * library we're using to detect the system we're running on. */
+# include <stdlib.h>
+# if defined(__GLIBC__)
+ /* We're running GNU/kFreeBSD */
+# define WZ_OS_GNU_kFREEBSD
+# endif
+#elif defined(__NetBSD__)
+# define WZ_OS_NETBSD
+# define WZ_OS_BSD4
+#elif defined(__OpenBSD__)
+# define WZ_OS_OPENBSD
+# define WZ_OS_BSD4
+#elif defined(__bsdi__)
+# define WZ_OS_BSDI
+# define WZ_OS_BSD4
+#elif defined(__sgi)
+# define WZ_OS_IRIX
+#elif defined(__osf__)
+# define WZ_OS_OSF
+#elif defined(_AIX)
+# define WZ_OS_AIX
+#elif defined(__Lynx__)
+# define WZ_OS_LYNX
+#elif defined(__GNU__)
+# define WZ_OS_HURD
+#elif defined(__DGUX__)
+# define WZ_OS_DGUX
+#elif defined(__QNXNTO__)
+# define WZ_OS_QNX6
+#elif defined(__QNX__)
+# define WZ_OS_QNX
+#elif defined(_SEQUENT_)
+# define WZ_OS_DYNIX
+#elif defined(_SCO_DS) /* SCO OpenServer 5 + GCC */
+# define WZ_OS_SCO
+#elif defined(__USLC__) /* all SCO platforms + UDK or OUDK */
+# define WZ_OS_UNIXWARE
+#elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */
+# define WZ_OS_UNIXWARE
+#elif defined(__INTEGRITY)
+# define WZ_OS_INTEGRITY
+#elif defined(__MAKEDEPEND__)
+#else
+# error "Warzone has not been tested on this OS. Please contact warzone-dev@gna.org"
+#endif /* WZ_OS_x */
+
+#if defined(WZ_OS_WIN32) || defined(WZ_OS_WIN64)
+# define WZ_OS_WIN
+#endif /* WZ_OS_WIN32 */
+
+#if defined(WZ_OS_DARWIN)
+# define WZ_OS_MAC /* WZ_OS_MAC is mostly for compatibility, but also more clear */
+# define WZ_OS_MACX /* WZ_OS_MACX is only for compatibility.*/
+# if defined(WZ_OS_DARWIN64)
+# define WZ_OS_MAC64
+# elif defined(WZ_OS_DARWIN32)
+# define WZ_OS_MAC32
+# endif
+#endif /* WZ_OS_DARWIN */
+
+#if defined(WZ_OS_MSDOS) || defined(WZ_OS_OS2) || defined(WZ_OS_WIN)
+# undef WZ_OS_UNIX
+#elif !defined(WZ_OS_UNIX)
+# define WZ_OS_UNIX
+#endif /* WZ_OS_* */
+
+
+/*
+ The compiler, must be one of: (WZ_CC_x)
+
+ MSVC - Microsoft Visual C/C++, Intel C++ for Windows
+ GNU - GNU C++
+ CLANG - Clang LLVM
+ INTEL - Intel C++ for Linux, Intel C++ for Windows
+ TINYC - Fabrice Bellard's Tiny C Compiler
+
+ Should be sorted most to least authoritative.
+*/
+
+#if defined(_MSC_VER)
+# define WZ_CC_MSVC
+/* All ISO C89 compliant compilers _should_ define the macro __STDC__, MSVC
+ * however is known _not_ to do this, so work around that here. */
+# if !defined(__STDC__)
+# define __STDC__ 1
+# endif
+/* Visual C++.Net issues for _MSC_VER >= 1300 */
+# if _MSC_VER >= 1300
+# define WZ_CC_MSVC_NET
+# endif
+/* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */
+# if defined(__INTEL_COMPILER)
+# define WZ_CC_INTEL
+# endif
+/* x64 does not support mmx intrinsics on windows */
+# if (defined(ZS_OS_WIN64) && defined(_M_X64))
+# undef ZS_HAVE_SSE
+# undef ZS_HAVE_SSE2
+# undef ZS_HAVE_MMX
+# undef ZS_HAVE_3DNOW
+# endif
+
+#elif defined(__GNUC__)
+# define WZ_CC_GNU
+# if defined(__MINGW32__)
+# define WZ_CC_MINGW
+# endif
+# if defined(__INTEL_COMPILER)
+/* Intel C++ also masquerades as GCC 3.2.0 */
+# define WZ_CC_INTEL
+# endif
+
+# if defined(__llvm__)
+# define WZ_CC_LLVM
+# endif
+# if defined(__clang__)
+# define WZ_CC_CLANG
+# endif
+/* Clang may not always masquerade as gcc */
+#elif defined(__clang__)
+# define WZ_CC_CLANG
+# define WZ_CC_LLVM
+
+#elif defined(__TINYC__)
+# define WZ_CC_TINYC
+
+#else
+# error "Warzone has not been tested on this compiler. Please contact warzone-dev@gna.org"
+#endif /* WZ_CC_x */
+
+
+/*
+ The window system, must be one of: (WZ_WS_x)
+
+ MACX - Mac OS X
+ WIN32 - Windows
+ X11 - X Window System
+ QNX - QNX
+*/
+
+#if defined(_WIN32_X11_)
+# define WZ_WS_X11
+
+#elif defined(WZ_OS_WIN32)
+# define WZ_WS_WIN32
+# if defined(WZ_OS_WIN64)
+# define WZ_WS_WIN64
+# endif
+
+#elif defined(WZ_OS_MAC)
+# define WZ_WS_MAC
+# define WZ_WS_MACX
+# if defined(WZ_OS_MAC64)
+# define WZ_WS_MAC64
+# elif defined(WZ_OS_MAC32)
+# define WZ_WS_MAC32
+# endif
+
+#elif defined(WZ_OS_QNX)
+# define WZ_WS_QNX
+
+#elif defined(WZ_OS_UNIX)
+# define WZ_WS_X11
+
+#else
+# error "Warzone has not been tested on this window system. Please contact warzone-dev@gna.org"
+#endif /* WZ_WS_x */
+
+#if defined(WZ_WS_WIN16) || defined(WZ_WS_WIN32)
+# define WZ_WS_WIN
+#endif
+
+
+/*
+ The supported C standard, must be one of: (WZ_Cxx)
+
+ 99 - ISO/IEC 9899:1999 / C99
+*/
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+# define WZ_C99
+#endif /* WZ_Cxx */
+
+/*
+ The supported C++ standard, must be one of: (WZ_CXXxx)
+
+ 98 - ISO/IEC 14882:1998 / C++98
+*/
+#if defined(__cplusplus)
+# define WZ_CXX98
+#endif /* WZ_CXXxx */
+
+
+/*
+ Convenience macros to test the versions of gcc.
+ Copied from glibc's features.h.
+*/
+#if defined(WZ_CC_GNU) && defined __GNUC__ && defined __GNUC_MINOR__
+# define WZ_CC_GNU_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define WZ_CC_GNU_PREREQ(maj, min) 0
+#endif
+
+
+/*
+ Convenience macros to test the versions of icc.
+*/
+#if defined(WZ_CC_INTEL) && defined __ICC
+# define WZ_CC_INTEL_PREREQ(maj, min) \
+ ((__ICC) >= ((maj) * 100) + (min))
+#else
+# define WZ_CC_INTEL_PREREQ(maj, min) 0
+#endif
+
+
+
+
+/* ---- Declaration attributes ---- */
+
+
+/*!
+ * \def WZ_DECL_DEPRECATED
+ *
+ * The WZ_DECL_DEPRECATED macro can be used to trigger compile-time warnings
+ * with newer compilers when deprecated functions are used.
+ *
+ * For non-inline functions, the macro gets inserted at front of the
+ * function declaration, right before the return type:
+ *
+ * \code
+ * WZ_DECL_DEPRECATED void deprecatedFunctionA();
+ * WZ_DECL_DEPRECATED int deprecatedFunctionB() const;
+ * \endcode
+ *
+ * For functions which are implemented inline,
+ * the WZ_DECL_DEPRECATED macro is inserted at the front, right before the return
+ * type, but after "static", "inline" or "virtual":
+ *
+ * \code
+ * WZ_DECL_DEPRECATED void deprecatedInlineFunctionA() { .. }
+ * virtual WZ_DECL_DEPRECATED int deprecatedInlineFunctionB() { .. }
+ * static WZ_DECL_DEPRECATED bool deprecatedInlineFunctionC() { .. }
+ * inline WZ_DECL_DEPRECATED bool deprecatedInlineFunctionD() { .. }
+ * \endcode
+ *
+ * You can also mark whole structs or classes as deprecated, by inserting the
+ * WZ_DECL_DEPRECATED macro after the struct/class keyword, but before the
+ * name of the struct/class:
+ *
+ * \code
+ * class WZ_DECL_DEPRECATED DeprecatedClass { };
+ * struct WZ_DECL_DEPRECATED DeprecatedStruct { };
+ * \endcode
+ *
+ * \note
+ * Description copied from KDE4, code copied from Qt4.
+ *
+ */
+#if WZ_CC_GNU_PREREQ(3,2) || WZ_CC_INTEL_PREREQ(10,0)
+# define WZ_DECL_DEPRECATED __attribute__((__deprecated__))
+#elif defined(WZ_CC_MSVC) && defined(WZ_CC_MSVC_NET)
+# define WZ_DECL_DEPRECATED __declspec(deprecated)
+#else
+# define WZ_DECL_DEPRECATED
+#endif
+
+
+/*! \def WZ_DECL_FORMAT
+ * GCC: "The format attribute specifies that a function takes printf, scanf, strftime or strfmon
+ * style arguments which should be type-checked against a format string."
+ */
+#if WZ_CC_GNU_PREREQ(2,5) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_FORMAT(archetype, string_index, first_to_check) \
+ __attribute__((__format__(archetype, string_index, first_to_check)))
+#else
+# define WZ_DECL_FORMAT(archetype, string_index, first_to_check)
+#endif
+
+
+/*!
+ * \def WZ_DECL_NORETURN
+ * "A few standard library functions, such as abort and exit, cannot return. GCC knows this
+ * automatically. Some programs define their own functions that never return.
+ * You can declare them noreturn to tell the compiler this fact."
+ */
+#if WZ_CC_GNU_PREREQ(2,5) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_NORETURN __attribute__((__noreturn__))
+#elif defined(WZ_CC_MSVC)
+# define WZ_DECL_NORETURN __declspec(noreturn)
+#else
+# define WZ_DECL_NORETURN
+#endif
+
+
+/*!
+ * \def WZ_DECL_CONST
+ * GCC: "Many functions do not examine any values except their arguments, and have no effects
+ * except the return value. Basically this is just slightly more strict class than
+ * the pure attribute below, since function is not allowed to read global memory."
+ */
+#if WZ_CC_GNU_PREREQ(2,5) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_CONST __attribute__((__const__,__warn_unused_result__))
+#else
+# define WZ_DECL_CONST
+#endif
+
+
+/*!
+ * \def WZ_DECL_PURE
+ * GCC: "Many functions have no effects except the return value and their return value depends
+ * only on the parameters and/or global variables. Such a function can be subject to
+ * common subexpression elimination and loop optimization just as an arithmetic operator
+ * would be."
+ */
+#if WZ_CC_GNU_PREREQ(2,96) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_PURE __attribute__((__pure__))
+#else
+# define WZ_DECL_PURE
+#endif
+
+
+/*!
+ * \def WZ_DECL_UNUSED
+ * GCC: "This attribute, attached to a function, means that the function is meant to be possibly
+ * unused. GCC will not produce a warning for this function."
+ */
+#if WZ_CC_GNU_PREREQ(3,2) || WZ_CC_INTEL_PREREQ(10,0)
+# define WZ_DECL_UNUSED __attribute__((__unused__))
+#else
+# define WZ_DECL_UNUSED
+#endif
+
+
+/*!
+ * \def WZ_DECL_WARN_UNUSED_RESULT
+ * GCC: "The warn_unused_result attribute causes a warning to be emitted if a caller of the
+ * function with this attribute does not use its return value. This is useful for
+ * functions where not checking the result is either a security problem or always a bug,
+ * such as realloc."
+ */
+#if defined(WZ_CC_GNU) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
+#else
+# define WZ_DECL_WARN_UNUSED_RESULT
+#endif
+
+
+/*! \def WZ_DECL_MAY_ALIAS
+ * GCC: "Accesses to objects with types with this attribute are not subjected to type-based alias
+ * analysis, but are instead assumed to be able to alias any other type of objects,
+ * just like the char type. See -fstrict-aliasing for more information on aliasing issues."
+ */
+#if WZ_CC_GNU_PREREQ(3,3) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_MAY_ALIAS __attribute__((__may_alias__))
+#else
+# define WZ_DECL_MAY_ALIAS
+#endif
+
+
+/*!
+ * \def WZ_DECL_RESTRICT
+ * Apply the "restrict" keyword found in the C99 revision of the standard.
+ * The compiler may assume that the memory referenced by a "restrict" pointer is not aliased
+ * by any other pointer. Thus this forms the opposite of WZ_DECL_MAY_ALIAS.
+ */
+#if defined(WZ_C99) && WZ_CC_GNU_PREREQ(4,1) && !defined(WZ_CC_INTEL)
+# define WZ_DECL_RESTRICT restrict
+#elif defined(WZ_CC_MSVC) && defined(WZ_CC_MSVC_NET)
+# define WZ_DECL_RESTRICT __restrict
+#else
+# define WZ_DECL_RESTRICT
+#endif
+
+
+/*! \def WZ_DECL_THREAD
+ * Declares a variable to be local to the running thread, and not shared between threads.
+ */
+#if defined(WZ_CC_GNU) || defined(WZ_CC_INTEL)
+# define WZ_DECL_THREAD __thread
+#elif defined(WZ_CC_MSVC)
+# define WZ_DECL_THREAD __declspec(thread)
+#else
+# error "Thread local storage attribute required"
+#endif
+
+
+/*! \def WZ_ASSERT_STATIC_STRING
+ * Asserts that the given string is statically allocated.
+ */
+#if defined(__cplusplus)
+# include <typeinfo>
+# define WZ_ASSERT_STATIC_STRING(_var) assert(typeid(_var) == typeid(char[sizeof(_var)]))
+#elif defined(WZ_CC_GNU) || defined(WZ_CC_INTEL)
+# define WZ_ASSERT_STATIC_STRING(_var) STATIC_ASSERT(__builtin_types_compatible_p(typeof(_var), char[]))
+#else
+# define WZ_ASSERT_STATIC_STRING(_var) (void)(_var)
+#endif
+
+/*! \def WZ_ASSERT_ARRAY
+ * Asserts that the given variable is a (statically sized) array, not just a pointer.
+ */
+#if defined(__cplusplus)
+# define WZ_ASSERT_ARRAY_EXPR(a) 0
+#elif defined(WZ_CC_GNU) || defined(WZ_CC_INTEL)
+/* &a[0] degrades to a pointer: a different type from an array */
+# define WZ_ASSERT_ARRAY_EXPR(a) STATIC_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])))
+#else
+# define WZ_ASSERT_ARRAY_EXPR(a) 0
+#endif
+#define WZ_ASSERT_ARRAY(a) (void)WZ_ASSERT_ARRAY_EXPR(a)
+
+
+/* ---- Platform specific setup ---- */
+
+
+#if defined(WZ_OS_WIN)
+# if defined(WZ_CC_MINGW)
+# include <unistd.h>
+# include <sys/param.h>
+# include <w32api.h>
+# define _WIN32_IE IE5
+// Required for alloca
+# include <malloc.h>
+
+# elif defined(WZ_CC_MSVC)
+# if defined(_DEBUG)
+# define DEBUG
+# define _CRTDBG_MAP_ALLOC
+# include <stdlib.h>
+# include <crtdbg.h>
+# endif /* _DEBUG */
+# endif /* WZ_CC_* */
+
+# define WIN32_LEAN_AND_MEAN
+# define WIN32_EXTRA_LEAN
+# undef NOMINMAX
+# define NOMINMAX 1 // disable the min / max macros
+# include <windows.h>
+
+# if defined(WZ_CC_MSVC)
+// notify people we are disabling these warning messages.
+# pragma message (" *** Warnings 4018,4100,4127,4204,4244,4267,4389 have been squelched. ***")
+# pragma warning (disable : 4018) // Shut up: '>' : signed/unsigned mismatch
+# pragma warning (disable : 4100) // Shut up: unreferenced formal parameter (FIXME)
+# pragma warning (disable : 4127) // Shut up: conditional expression is constant (eg. "while(0)")
+# pragma warning (disable : 4204) // Shut up: non-constant aggregate initializer
+# pragma warning (disable : 4244) // Shut up: conversion from 'float' to 'int', possible loss of data
+# pragma warning (disable : 4267) // Shut up: conversion from 'size_t' to 'type', possible loss of data
+# pragma warning (disable : 4389) // Shut up: '==' : signed/unsigned mismatch
+
+# define strcasecmp _stricmp
+# define strncasecmp _strnicmp
+# define inline __inline
+# define alloca _alloca
+# define fileno _fileno
+
+# define isnan _isnan
+# define isfinite _finite
+
+# define PATH_MAX MAX_PATH
+# endif /* WZ_CC_MSVC */
+
+/* Make sure that PATH_MAX is large enough to use as the size for return
+ * buffers for Windows API calls
+ */
+# if (PATH_MAX < MAX_PATH)
+# undef PATH_MAX
+# define PATH_MAX MAX_PATH
+# endif
+
+#elif defined(WZ_OS_UNIX)
+# include <unistd.h>
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# endif
+#endif /* WZ_OS_* */
+
+// Define PATH_MAX for systems that don't have it, like Hurd
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+
+#if !defined(WZ_C99) && !defined(va_copy)
+/**
+ * Implements the interface of the C99 macro va_copy such that we can use it on
+ * non-C99 systems as well.
+ *
+ * This implementation assumes that va_list is just a pointer to the stack
+ * frame of the variadic function. This is by far the most common setup, though
+ * it might not always work.
+ */
+# define va_copy(dest, src) (void)((dest) = (src))
+#endif // !WZ_C99 && !va_copy
+
+#endif /* WZGLOBAL_H */
diff --git a/lib/clipboard/readme.txt b/lib/clipboard/readme.txt
new file mode 100644
index 0000000..196c127
--- /dev/null
+++ b/lib/clipboard/readme.txt
@@ -0,0 +1 @@
+Source code in this directory was taken from Warzone2100 source. Please read COPING.README for licence or visit https://github.com/cybersphinx/wzgraphicsmods for more information.
diff --git a/lib/clipboard/src/clipboardWin32.c b/lib/clipboard/src/clipboardWin32.c
new file mode 100644
index 0000000..be48906
--- /dev/null
+++ b/lib/clipboard/src/clipboardWin32.c
@@ -0,0 +1,160 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 2008 Freddie Witherden
+ Copyright (C) 2008-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "utf.h"
+// Defines most macros and types from <stdbool.h> and <stdint.h>
+#include "types.h"
+
+char *widgetGetClipboardText()
+{
+ uint16_t *clipboardText;
+ char *ourText = NULL;
+
+ // If there is any text on the clipboard, open it
+ if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
+ {
+ // Get any text on the clipboard
+ HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
+
+ // If the handle is valid, fetch the text
+ if (hClipboardData)
+ {
+ // Get the text
+ clipboardText = GlobalLock(hClipboardData);
+
+ // So long as we got something
+ if (clipboardText)
+ {
+ int i, j;
+
+ // Convert it to UTF-8 (from UTF-16)
+ ourText = UTF16toUTF8(clipboardText, NULL);
+
+ // Unlock the text
+ GlobalUnlock(hClipboardData);
+
+ // Strip any '\r' from the text
+ for (i = j = 0; ourText[i]; i++)
+ {
+ if (ourText[i] != '\r')
+ {
+ ourText[j++] = ourText[i];
+ }
+ }
+
+ // NUL terminate
+ ourText[j] = '\0';
+ }
+ }
+
+ // Close the clipboard
+ CloseClipboard();
+ }
+
+ return ourText;
+}
+
+bool widgetSetClipboardText(const char *text)
+{
+ bool ret = false;
+
+ // Copy of text with \n => \r\n
+ char *newText;
+
+ // UTF-16 version of newText
+ uint16_t *utf16NewText;
+
+ // Number of bytes utf16NewText is in size
+ size_t nbytes;
+
+ int count, i, j;
+
+ // Get the number of '\n' characters in the text
+ for (i = count = 0; text[i]; i++)
+ {
+ if (text[i] == '\n')
+ {
+ count++;
+ }
+ }
+
+ // Allocate enough space for the \r\n string
+ newText = malloc(strlen(text) + count + 1);
+
+ // Copy the string, converting \n to \r\n
+ for (i = j = 0; text[i]; i++, j++)
+ {
+ // If the character is a newline prepend a \r
+ if (text[i] == '\n')
+ {
+ newText[j++] = '\r';
+ }
+
+ // Copy the character (\n or otherwise)
+ newText[j] = text[i];
+ }
+
+ // NUL terminate
+ newText[j] = '\0';
+
+ // Convert to UTF-16
+ utf16NewText = UTF8toUTF16(newText, &nbytes);
+
+ // Open the clipboard
+ if (OpenClipboard(NULL))
+ {
+ HGLOBAL hGlobal;
+ uint16_t *clipboardText;
+
+ // Empty it (which also transfers ownership of it to ourself)
+ EmptyClipboard();
+
+ // Allocate global space for the text
+ hGlobal = GlobalAlloc(GMEM_MOVEABLE, nbytes);
+
+ // Lock the newly allocated memory
+ clipboardText = GlobalLock(hGlobal);
+
+ // Copy the text
+ memcpy(clipboardText, utf16NewText, nbytes);
+
+ // Unlock the memory (must come before CloseClipboard())
+ GlobalUnlock(hGlobal);
+
+ // Place the handle on the clipboard
+ if (SetClipboardData(CF_UNICODETEXT, hGlobal))
+ {
+ // We were successful
+ ret = true;
+ }
+
+ // Close the clipboard
+ CloseClipboard();
+ }
+
+ // Release the malloc-ed strings
+ free(newText);
+ free(utf16NewText);
+
+ return ret;
+}
diff --git a/lib/clipboard/src/clipboardX11.c b/lib/clipboard/src/clipboardX11.c
new file mode 100644
index 0000000..0653250
--- /dev/null
+++ b/lib/clipboard/src/clipboardX11.c
@@ -0,0 +1,293 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 2008 Freddie Witherden
+ Copyright (C) 2008-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ * Something wicked this way comes...
+ * Documentation/reference:
+ * http://svr-www.eng.cam.ac.uk/~er258/code/dist/x_clipboard/paste.cc
+ */
+
+#include <stdbool.h>
+#include <assert.h>
+
+#include <SDL_syswm.h>
+#include <SDL.h>
+
+static SDL_SysWMinfo info;
+
+// Atoms
+static Atom XA_CLIPBOARD;
+static Atom XA_COMPOUND_TEXT;
+static Atom XA_UTF8_STRING;
+static Atom XA_TARGETS;
+
+/**
+ * Filters through SDL_Events searching for clipboard requests from the X
+ * server.
+ *
+ * @param evt The event to filter.
+ */
+static int widgetClipboardFilterX11(const SDL_Event *evt)
+{
+ // We are only interested in window manager events
+ if (evt->type == SDL_SYSWMEVENT)
+ {
+ XEvent xevent = evt->syswm.msg->event.xevent;
+
+ // See if the event is a selection/clipboard request
+ if (xevent.type == SelectionRequest)
+ {
+ // Get the request in question
+ XSelectionRequestEvent *request = &xevent.xselectionrequest;
+
+ // Generate a reply to the selection request
+ XSelectionEvent reply;
+
+ reply.type = SelectionNotify;
+ reply.serial = xevent.xany.send_event;
+ reply.send_event = True;
+ reply.display = info.info.x11.display;
+ reply.requestor = request->requestor;
+ reply.selection = request->selection;
+ reply.property = request->property;
+ reply.target = None;
+ reply.time = request->time;
+
+ // They want to know what we can provide/offer
+ if (request->target == XA_TARGETS)
+ {
+ Atom possibleTargets[] =
+ {
+ XA_STRING,
+ XA_UTF8_STRING,
+ XA_COMPOUND_TEXT
+ };
+
+ XChangeProperty(info.info.x11.display, request->requestor,
+ request->property, XA_ATOM, 32, PropModeReplace,
+ (unsigned char *) possibleTargets, 3);
+ }
+ // They want a string (all we can provide)
+ else if (request->target == XA_STRING
+ || request->target == XA_UTF8_STRING
+ || request->target == XA_COMPOUND_TEXT)
+ {
+ int len;
+ char *xdata = XFetchBytes(info.info.x11.display, &len);
+
+ XChangeProperty(info.info.x11.display, request->requestor,
+ request->property, request->target, 8,
+ PropModeReplace, (unsigned char *) xdata,
+ len);
+ XFree(xdata);
+ }
+ else
+ {
+ // Did not have what they wanted, so no property set
+ reply.property = None;
+ }
+
+ // Dispatch the event
+ XSendEvent(request->display, request->requestor, 0, NoEventMask,
+ (XEvent *) &reply);
+ XSync(info.info.x11.display, False);
+ }
+ }
+
+ return 1;
+}
+
+static void widgetInitialiseClipboardX11()
+{
+ static bool initialised = false;
+
+ if (!initialised)
+ {
+ // Get the window manager information
+ SDL_GetWMInfo(&info);
+
+ // Ensure we're running under X11
+ assert(info.subsystem == SDL_SYSWM_X11);
+
+ // Register the event filter
+ SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
+ SDL_SetEventFilter(widgetClipboardFilterX11);
+
+ // Lock the connection to the X server
+ info.info.x11.lock_func();
+
+ // Get the clipboard atom (it is not defined by default)
+ XA_CLIPBOARD = XInternAtom(info.info.x11.display, "CLIPBOARD", True);
+
+ // Get the compound text type atom
+ XA_COMPOUND_TEXT = XInternAtom(info.info.x11.display, "COMPOUND_TEXT",
+ True);
+
+ // UTF-8 string atom
+ XA_UTF8_STRING = XInternAtom(info.info.x11.display, "UTF8_STRING",
+ True);
+
+ // TARGETS atom
+ XA_TARGETS = XInternAtom(info.info.x11.display, "TARGETS", True);
+
+ // Unlock the connection
+ info.info.x11.unlock_func();
+
+ // We are initialised
+ initialised = true;
+ }
+}
+
+char *widgetGetClipboardText()
+{
+ char *text = NULL;
+ unsigned char *data = NULL;
+ Atom type;
+ int format, result;
+ unsigned long len, bytesLeft, dummy;
+ Window selectionOwner;
+
+ // Make sure we are initialised
+ widgetInitialiseClipboardX11();
+
+ // Lock the connection
+ info.info.x11.lock_func();
+
+ // Get the owner of the clipboard selection
+ selectionOwner = XGetSelectionOwner(info.info.x11.display, XA_CLIPBOARD);
+
+ // If there is a selection (and therefore owner) fetch it
+ if (selectionOwner != None)
+ {
+ SDL_Event event;
+ bool response = false;
+
+ /*
+ * Ask the window whom current owns the clipboard to convert it to an
+ * XA_UTF8_STRING and place it into the XA_CLIPBOARD property of our
+ * window.
+ */
+ XConvertSelection(info.info.x11.display, XA_CLIPBOARD, XA_UTF8_STRING,
+ XA_CLIPBOARD, info.info.x11.window, CurrentTime);
+ XFlush(info.info.x11.display);
+
+ /*
+ * We now need to wait for a response from the window that owns the
+ * clipboard.
+ */
+
+ // Unlock the connection so that the SDL event loop may function
+ info.info.x11.unlock_func();
+
+ while (!response)
+ {
+ // Wait for an event
+ SDL_WaitEvent(&event);
+
+ // If the event is a window manager event
+ if (event.type == SDL_SYSWMEVENT)
+ {
+ XEvent xevent = event.syswm.msg->event.xevent;
+
+ // See if it is a response to our request
+ if (xevent.type == SelectionNotify
+ && xevent.xselection.requestor == info.info.x11.window)
+ {
+ response = true;
+ }
+ }
+ }
+
+ // Lock the connection once again
+ info.info.x11.lock_func();
+
+ // See how much data is there
+ XGetWindowProperty(info.info.x11.display, info.info.x11.window,
+ XA_CLIPBOARD, 0, 0, False, AnyPropertyType, &type,
+ &format, &len, &bytesLeft, &data);
+
+ // If any 0-length data was returned, free it
+ if (data)
+ {
+ XFree(data);
+ data = NULL;
+ }
+
+ // If there is any data
+ if (bytesLeft)
+ {
+ // Fetch the data
+ result = XGetWindowProperty(info.info.x11.display,
+ info.info.x11.window, XA_CLIPBOARD, 0,
+ bytesLeft, False, AnyPropertyType,
+ &type, &format, &len, &dummy, &data);
+
+ // If we got some data, duplicate it
+ if (result == Success)
+ {
+ text = strdup((char *) data);
+ XFree(data);
+ }
+ }
+
+ // Delete the property now that we are finished with it
+ XDeleteProperty(info.info.x11.display, info.info.x11.window,
+ XA_CLIPBOARD);
+ }
+
+ // Unlock the connection
+ info.info.x11.unlock_func();
+
+ return text;
+}
+
+bool widgetSetClipboardText(const char *text)
+{
+ Window selectionOwner;
+
+ // Make sure we are initialised
+ widgetInitialiseClipboardX11();
+
+ // Lock the connection
+ info.info.x11.lock_func();
+
+ // Copy the text into the root windows cut buffer (for Xterm compatibility)
+ XStoreBytes(info.info.x11.display, text, strlen(text) + 1);
+
+ // Set ourself as the owner of the CLIPBOARD atom
+ XSetSelectionOwner(info.info.x11.display, XA_CLIPBOARD,
+ info.info.x11.window, CurrentTime);
+
+ // Check if we acquired ownership or not
+ selectionOwner = XGetSelectionOwner(info.info.x11.display, XA_CLIPBOARD);
+
+ // We got ownership
+ if (selectionOwner == info.info.x11.window)
+ {
+ info.info.x11.unlock_func();
+ return true;
+ }
+ // We did not get ownership
+ else
+ {
+ info.info.x11.unlock_func();
+ return false;
+ }
+}
diff --git a/lib/clipboard/src/utf.c b/lib/clipboard/src/utf.c
new file mode 100644
index 0000000..2313bb6
--- /dev/null
+++ b/lib/clipboard/src/utf.c
@@ -0,0 +1,530 @@
+/*
+ This file is part of Warzone 2100.
+ Copyright (C) 2007 Giel van Schijndel
+ Copyright (C) 2007-2009 Warzone Resurrection Project
+
+ Warzone 2100 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 2 of the License, or
+ (at your option) any later version.
+
+ Warzone 2100 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 Warzone 2100; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ $Revision: 9101 $
+ $Id: utf.c 9101 2010-01-10 13:11:55Z zarelsl $
+ $HeadURL: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk/lib/framework/utf.c $
+*/
+
+/** \file
+ * Functions to convert between different Unicode Transformation Formats (UTF for short)
+ */
+
+#include "utf.h"
+#include <assert.h>
+#include <stdlib.h>
+
+#if defined(LIB_COMPILE)
+# define ASSERT(expr, ...) (assert(expr))
+# define debug(part, ...) ((void)0)
+#else
+# include "debug.h"
+#endif
+
+// Assert that non-starting octets are of the form 10xxxxxx
+#define ASSERT_NON_START_OCTET(octet) \
+ assert((octet & 0xC0) == 0x80 && "invalid non-start UTF-8 octet")
+
+// Assert that starting octets are either of the form 0xxxxxxx (ASCII) or 11xxxxxx
+#define ASSERT_START_OCTECT(octet) \
+ assert((octet & 0x80) == 0x00 || (octet & 0xC0) == 0xC0 || !"invalid starting UTF-8 octet")
+
+// Assert that hexadect (16bit sequence) 1 of UTF-16 surrogate pair sequences are of the form 110110XXXXXXXXXX
+#define ASSERT_START_HEXADECT(hexadect) \
+ assert(((hexadect) & 0xD800) == 0xD800 && "invalid first UTF-16 hexadect")
+
+// Assert that hexadect (16bit sequence) 2 of UTF-16 surrogate pair sequences are of the form 110111XXXXXXXXXX
+#define ASSERT_FINAL_HEXADECT(hexadect) \
+ assert(((hexadect) & 0xDC00) == 0xDC00 && "invalid first UTF-16 hexadect")
+
+utf_32_char UTF8DecodeChar(const char *utf8_char, const char **next_char)
+{
+ utf_32_char decoded = '\0';
+ *next_char = utf8_char;
+
+ ASSERT_START_OCTECT(*utf8_char);
+
+ // first octect: 0xxxxxxx: 7 bit (ASCII)
+ if ((*utf8_char & 0x80) == 0x00)
+ {
+ // 1 byte long encoding
+ decoded = *((*next_char)++);
+ }
+ // first octect: 110xxxxx: 11 bit
+ else if ((*utf8_char & 0xe0) == 0xc0)
+ {
+ // 2 byte long encoding
+ ASSERT_NON_START_OCTET(utf8_char[1]);
+
+ decoded = (*((*next_char)++) & 0x1f) << 6;
+ decoded |= (*((*next_char)++) & 0x3f) << 0;
+ }
+ // first octect: 1110xxxx: 16 bit
+ else if ((*utf8_char & 0xf0) == 0xe0)
+ {
+ // 3 byte long encoding
+ ASSERT_NON_START_OCTET(utf8_char[1]);
+ ASSERT_NON_START_OCTET(utf8_char[2]);
+
+ decoded = (*((*next_char)++) & 0x0f) << 12;
+ decoded |= (*((*next_char)++) & 0x3f) << 6;
+ decoded |= (*((*next_char)++) & 0x3f) << 0;
+ }
+ // first octect: 11110xxx: 21 bit
+ else if ((*utf8_char & 0xf8) == 0xf0)
+ {
+ // 4 byte long encoding
+ ASSERT_NON_START_OCTET(utf8_char[1]);
+ ASSERT_NON_START_OCTET(utf8_char[2]);
+ ASSERT_NON_START_OCTET(utf8_char[3]);
+
+ decoded = (*((*next_char)++) & 0x07) << 18;
+ decoded |= (*((*next_char)++) & 0x3f) << 12;
+ decoded |= (*((*next_char)++) & 0x3f) << 6;
+ decoded |= (*((*next_char)++) & 0x3f) << 0;
+ }
+ else
+ {
+ // apparently this character uses more than 21 bit
+ // this decoder is not developed to cope with those
+ // characters so error out
+ ASSERT(!"out-of-range UTF-8 character", "this UTF-8 character is too large (> 21bits) for this UTF-8 decoder and too large to be a valid Unicode codepoint");
+ }
+
+ return decoded;
+}
+
+size_t UTF8CharacterCount(const char *utf8_string)
+{
+ size_t length = 0;
+
+ while (*utf8_string != '\0')
+ {
+ UTF8DecodeChar(utf8_string, &utf8_string);
+
+ ++length;
+ }
+
+ return length;
+}
+
+size_t UTF16CharacterCount(const uint16_t *utf16)
+{
+ size_t length = 0;
+
+ while (*utf16)
+ {
+ UTF16DecodeChar(utf16, &utf16);
+
+ ++length;
+ }
+
+ return length;
+}
+
+static size_t unicode_utf8_char_length(const utf_32_char unicode_char)
+{
+ // an ASCII character, which uses 7 bit at most, which is one byte in UTF-8
+ if (unicode_char < 0x00000080)
+ return 1; // stores 7 bits
+ else if (unicode_char < 0x00000800)
+ return 2; // stores 11 bits
+ else if (unicode_char < 0x00010000)
+ return 3; // stores 16 bits
+ /* This encoder can deal with < 0x00200000, but Unicode only ranges
+ * from 0x0 to 0x10FFFF. Thus we don't accept anything else.
+ */
+ else if (unicode_char < 0x00110000)
+ return 4; // stores 21 bits
+
+ /* Apparently this character lies outside the 0x0 - 0x10FFFF
+ * Unicode range, so don't accept it.
+ */
+ ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint is too large (%u > 0x10FFFF) to be a valid Unicode codepoint", (unsigned int)unicode_char);
+
+ // Dummy value to prevent warnings about missing return from function
+ return 0;
+}
+
+char *UTF8CharacterAtOffset(const char *utf8_string, size_t index)
+{
+ while (*utf8_string != '\0'
+ && index != 0)
+ {
+ // Move to the next character
+ UTF8DecodeChar(utf8_string, &utf8_string);
+
+ --index;
+ }
+
+ if (*utf8_string == '\0')
+ return NULL;
+
+ return (char*)utf8_string;
+}
+
+/** Encodes a single Unicode character to a UTF-8 encoded string.
+ *
+ * \param unicode_char A UTF-32 encoded Unicode codepoint that will be encoded
+ * into UTF-8. This should be a valid Unicode codepoint
+ * (i.e. ranging from 0x0 to 0x10FFFF inclusive).
+ * \param out_char Points to the position in a buffer where the UTF-8
+ * encoded character can be stored.
+ *
+ * \return A pointer pointing to the first byte <em>after</em> the encoded
+ * UTF-8 sequence. This can be used as the \c out_char parameter for a
+ * next invocation of encode_utf8_char().
+ */
+static char *encode_utf8_char(const utf_32_char unicode_char, char *out_char)
+{
+ char *next_char = out_char;
+
+ // 7 bits
+ if (unicode_char < 0x00000080)
+ {
+ *(next_char++) = unicode_char;
+ }
+ // 11 bits
+ else if (unicode_char < 0x00000800)
+ {
+ // 0xc0 provides the counting bits: 110
+ // then append the 5 most significant bits
+ *(next_char++) = 0xc0 | (unicode_char >> 6);
+ // Put the next 6 bits in a byte of their own
+ *(next_char++) = 0x80 | (unicode_char & 0x3f);
+ }
+ // 16 bits
+ else if (unicode_char < 0x00010000)
+ {
+ // 0xe0 provides the counting bits: 1110
+ // then append the 4 most significant bits
+ *(next_char++) = 0xe0 | (unicode_char >> 12);
+ // Put the next 12 bits in two bytes of their own
+ *(next_char++) = 0x80 | ((unicode_char >> 6) & 0x3f);
+ *(next_char++) = 0x80 | (unicode_char & 0x3f);
+ }
+ // 21 bits
+ /* This encoder can deal with < 0x00200000, but Unicode only ranges
+ * from 0x0 to 0x10FFFF. Thus we don't accept anything else.
+ */
+ else if (unicode_char < 0x00110000)
+ {
+ // 0xf0 provides the counting bits: 11110
+ // then append the 3 most significant bits
+ *(next_char++) = 0xf0 | (unicode_char >> 18);
+ // Put the next 18 bits in three bytes of their own
+ *(next_char++) = 0x80 | ((unicode_char >> 12) & 0x3f);
+ *(next_char++) = 0x80 | ((unicode_char >> 6) & 0x3f);
+ *(next_char++) = 0x80 | (unicode_char & 0x3f);
+ }
+ else
+ {
+ /* Apparently this character lies outside the 0x0 - 0x10FFFF
+ * Unicode range, so don't accept it.
+ */
+ ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint is too large (%u > 0x10FFFF) to be a valid Unicode codepoint", (unsigned int)unicode_char);
+ }
+
+ return next_char;
+}
+
+utf_32_char UTF16DecodeChar(const utf_16_char *utf16_char, const utf_16_char **next_char)
+{
+ utf_32_char decoded;
+ *next_char = utf16_char;
+
+ // Are we dealing with a surrogate pair
+ if (*utf16_char >= 0xD800
+ && *utf16_char <= 0xDFFF)
+ {
+ ASSERT_START_HEXADECT(utf16_char[0]);
+ ASSERT_FINAL_HEXADECT(utf16_char[1]);
+
+ decoded = (*((*next_char)++) & 0x3ff) << 10;
+ decoded |= *((*next_char)++) & 0x3ff;
+
+ decoded += 0x10000;
+ }
+ // Not a surrogate pair, so it's a valid Unicode codepoint right away
+ else
+ {
+ decoded = *((*next_char)++);
+ }
+
+ return decoded;
+}
+
+/** Encodes a single Unicode character to a UTF-16 encoded string.
+ *
+ * \param unicode_char A UTF-32 encoded Unicode codepoint that will be encoded
+ * into UTF-16. This should be a valid Unicode codepoint
+ * (i.e. ranging from 0x0 to 0x10FFFF inclusive).
+ * \param out_char Points to the position in a buffer where the UTF-16
+ * encoded character can be stored.
+ *
+ * \return A pointer pointing to the first byte <em>after</em> the encoded
+ * UTF-16 sequence. This can be used as the \c out_char parameter for a
+ * next invocation of encode_utf16_char().
+ */
+static utf_16_char *encode_utf16_char(const utf_32_char unicode_char, utf_16_char *out_char)
+{
+ utf_16_char *next_char = out_char;
+
+ // 16 bits
+ if (unicode_char < 0x10000)
+ {
+ *(next_char++) = unicode_char;
+ }
+ else if (unicode_char < 0x110000)
+ {
+ const utf_16_char v = unicode_char - 0x10000;
+
+ *(next_char++) = 0xD800 | (v >> 10);
+ *(next_char++) = 0xDC00 | (v & 0x3ff);
+
+ ASSERT_START_HEXADECT(out_char[0]);
+ ASSERT_FINAL_HEXADECT(out_char[1]);
+ }
+ else
+ {
+ /* Apparently this character lies outside the 0x0 - 0x10FFFF
+ * Unicode range, and UTF-16 cannot cope with that, so error
+ * out.
+ */
+ ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint is too large (%u > 0x10FFFF) to be a valid Unicode codepoint", (unsigned int)unicode_char);
+ }
+
+ return next_char;
+}
+
+static size_t utf16_utf8_buffer_length(const utf_16_char* unicode_string)
+{
+ const utf_16_char* curChar = unicode_string;
+
+ // Determine length of string (in octets) when encoded in UTF-8
+ size_t length = 0;
+
+ while (*curChar)
+ {
+ length += unicode_utf8_char_length(UTF16DecodeChar(curChar, &curChar));
+ }
+
+ return length;
+}
+
+char *UTF16toUTF8(const utf_16_char *unicode_string, size_t *nbytes)
+{
+ const utf_16_char* curChar;
+
+ const size_t utf8_length = utf16_utf8_buffer_length(unicode_string);
+
+ // Allocate memory to hold the UTF-8 encoded string (plus a terminating nul char)
+ char* utf8_string = malloc(utf8_length + 1);
+ char* curOutPos = utf8_string;
+
+ if (utf8_string == NULL)
+ {
+ debug(LOG_ERROR, "Out of memory");
+ return NULL;
+ }
+
+ curChar = unicode_string;
+ while (*curChar)
+ {
+ curOutPos = encode_utf8_char(UTF16DecodeChar(curChar, &curChar), curOutPos);
+ }
+
+ // Terminate the string with a nul character
+ utf8_string[utf8_length] = '\0';
+
+ // Set the number of bytes allocated
+ if (nbytes)
+ {
+ *nbytes = utf8_length + 1;
+ }
+
+ return utf8_string;
+}
+
+static size_t utf8_as_utf16_buf_size(const char* utf8_string)
+{
+ const char* curChar = utf8_string;
+
+ size_t length = 0;
+ while (*curChar != '\0')
+ {
+ const utf_32_char unicode_char = UTF8DecodeChar(curChar, &curChar);
+
+ if (unicode_char < 0x10000)
+ {
+ length += 1;
+ }
+ else if (unicode_char < 0x110000)
+ {
+ length += 2;
+ }
+ else
+ {
+ /* Apparently this character lies outside the 0x0 - 0x10FFFF
+ * Unicode range, and UTF-16 cannot cope with that, so error
+ * out.
+ */
+ ASSERT(!"out-of-range Unicode codepoint", "This Unicode codepoint too large (%u > 0x10FFFF) for the UTF-16 encoding", (unsigned int)unicode_char);
+ }
+ }
+
+ return length;
+}
+
+utf_16_char *UTF8toUTF16(const char* utf8_string, size_t *nbytes)
+{
+ const char* curChar = utf8_string;
+ const size_t unicode_length = utf8_as_utf16_buf_size(utf8_string);
+
+ // Allocate memory to hold the UTF-16 encoded string (plus a terminating nul)
+ utf_16_char* unicode_string = malloc(sizeof(utf_16_char) * (unicode_length + 1));
+ utf_16_char* curOutPos = unicode_string;
+
+ if (unicode_string == NULL)
+ {
+ debug(LOG_ERROR, "Out of memory");
+ return NULL;
+ }
+
+ while (*curChar != '\0')
+ {
+ curOutPos = encode_utf16_char(UTF8DecodeChar(curChar, &curChar), curOutPos);
+ }
+
+ // Terminate the string with a nul
+ unicode_string[unicode_length] = '\0';
+
+ // Set the number of bytes allocated
+ if (nbytes)
+ {
+ *nbytes = sizeof(utf_16_char) * (unicode_length + 1);
+ }
+
+ return unicode_string;
+}
+
+utf_16_char *UTF16CharacterAtOffset(const utf_16_char *utf16_string, size_t index)
+{
+ while (*utf16_string != '\0'
+ && index != 0)
+ {
+ // Move to the next character
+ UTF16DecodeChar(utf16_string, &utf16_string);
+
+ --index;
+ }
+
+ if (*utf16_string == '\0')
+ return NULL;
+
+ return (utf_16_char*)utf16_string;
+}
+
+
+static size_t utf32_utf8_buffer_length(const utf_32_char* unicode_string)
+{
+ const utf_32_char* curChar;
+
+ // Determine length of string (in octets) when encoded in UTF-8
+ size_t length = 0;
+ for (curChar = unicode_string; *curChar != '\0'; ++curChar)
+ {
+ length += unicode_utf8_char_length(*curChar);
+ }
+
+ return length;
+}
+
+char *UTF32toUTF8(const utf_32_char *unicode_string, size_t *nbytes)
+{
+ const utf_32_char* curChar;
+
+ const size_t utf8_length = utf32_utf8_buffer_length(unicode_string);
+
+ // Allocate memory to hold the UTF-8 encoded string (plus a terminating nul char)
+ char* utf8_string = malloc(utf8_length + 1);
+ char* curOutPos = utf8_string;
+
+ if (utf8_string == NULL)
+ {
+ debug(LOG_ERROR, "Out of memory");
+ return NULL;
+ }
+
+ for (curChar = unicode_string; *curChar != 0; ++curChar)
+ {
+ curOutPos = encode_utf8_char(*curChar, curOutPos);
+ }
+
+ // Terminate the string with a nul character
+ utf8_string[utf8_length] = '\0';
+
+ // Set the number of bytes allocated
+ if (nbytes)
+ {
+ *nbytes = utf8_length + 1;
+ }
+
+ return utf8_string;
+}
+
+utf_32_char *UTF8toUTF32(const char *utf8_string, size_t *nbytes)
+{
+ const char* curChar = utf8_string;
+ const size_t unicode_length = UTF8CharacterCount(utf8_string);
+
+ // Allocate memory to hold the UTF-32 encoded string (plus a terminating nul)
+ utf_32_char* unicode_string = malloc(sizeof(utf_32_char) * (unicode_length + 1));
+ utf_32_char* curOutPos = unicode_string;
+
+ if (unicode_string == NULL)
+ {
+ debug(LOG_ERROR, "Out of memory");
+ return NULL;
+ }
+
+ while (*curChar != '\0')
+ {
+ *(curOutPos++) = UTF8DecodeChar(curChar, &curChar);
+ }
+
+ // Terminate the string with a nul
+ unicode_string[unicode_length] = '\0';
+
+ // Set the number of bytes allocated
+ if (nbytes)
+ {
+ *nbytes = sizeof(utf_32_char) * (unicode_length + 1);
+ }
+
+ return unicode_string;
+}
+
+size_t utf32len(const utf_32_char *unicode_string)
+{
+ size_t ret = 0;
+ while (*unicode_string++)
+ ++ret;
+ return ret;
+}
diff --git a/lib/localename/CMakeLists.txt b/lib/localename/CMakeLists.txt
new file mode 100644
index 0000000..c54648f
--- /dev/null
+++ b/lib/localename/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+
+add_library(localename STATIC localename.c) \ No newline at end of file
diff --git a/lib/localename/README.txt b/lib/localename/README.txt
new file mode 100644
index 0000000..9831651
--- /dev/null
+++ b/lib/localename/README.txt
@@ -0,0 +1,41 @@
+Part of gnulib library (http://www.gnu.org/software/gnulib/)
+
+Original source with added patch to also include LANGUAGE environment variable.
+
+Orignal module description below
+
+================================
+
+Description:
+Return current locale's name, according to glibc naming conventions.
+
+Files:
+lib/localename.h
+lib/localename.c
+m4/localename.m4
+m4/intlmacosx.m4
+m4/lcmessage.m4
+
+Depends-on:
+strdup
+lock
+
+configure.ac:
+gl_LOCALENAME
+
+Makefile.am:
+lib_SOURCES += localename.c
+
+Include:
+"localename.h"
+
+Link:
+@INTL_MACOSX_LIBS@
+$(LTLIBTHREAD) when linking with libtool, $(LIBTHREAD) otherwise
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible
+
diff --git a/lib/localename/localename.c b/lib/localename/localename.c
new file mode 100644
index 0000000..18eea6b
--- /dev/null
+++ b/lib/localename/localename.c
@@ -0,0 +1,2864 @@
+/* Determine name of the currently selected locale.
+ Copyright (C) 1995-2013 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
+/* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */
+/* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */
+
+//#include <config.h>
+
+/* Specification. */
+#ifdef IN_LIBINTL
+# include "gettextP.h"
+#else
+# include "localename.h"
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+
+#if HAVE_USELOCALE
+/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
+# if defined __APPLE__ && defined __MACH__
+# include <xlocale.h>
+# endif
+# include <langinfo.h>
+# if !defined IN_LIBINTL
+# include "glthread/lock.h"
+# endif
+#endif
+
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFString.h>
+# if HAVE_CFLOCALECOPYCURRENT
+# include <CoreFoundation/CFLocale.h>
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFPreferences.h>
+# endif
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# define WINDOWS_NATIVE
+#endif
+
+#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* List of language codes, sorted by value:
+ 0x01 LANG_ARABIC
+ 0x02 LANG_BULGARIAN
+ 0x03 LANG_CATALAN
+ 0x04 LANG_CHINESE
+ 0x05 LANG_CZECH
+ 0x06 LANG_DANISH
+ 0x07 LANG_GERMAN
+ 0x08 LANG_GREEK
+ 0x09 LANG_ENGLISH
+ 0x0a LANG_SPANISH
+ 0x0b LANG_FINNISH
+ 0x0c LANG_FRENCH
+ 0x0d LANG_HEBREW
+ 0x0e LANG_HUNGARIAN
+ 0x0f LANG_ICELANDIC
+ 0x10 LANG_ITALIAN
+ 0x11 LANG_JAPANESE
+ 0x12 LANG_KOREAN
+ 0x13 LANG_DUTCH
+ 0x14 LANG_NORWEGIAN
+ 0x15 LANG_POLISH
+ 0x16 LANG_PORTUGUESE
+ 0x17 LANG_ROMANSH
+ 0x18 LANG_ROMANIAN
+ 0x19 LANG_RUSSIAN
+ 0x1a LANG_CROATIAN == LANG_SERBIAN
+ 0x1b LANG_SLOVAK
+ 0x1c LANG_ALBANIAN
+ 0x1d LANG_SWEDISH
+ 0x1e LANG_THAI
+ 0x1f LANG_TURKISH
+ 0x20 LANG_URDU
+ 0x21 LANG_INDONESIAN
+ 0x22 LANG_UKRAINIAN
+ 0x23 LANG_BELARUSIAN
+ 0x24 LANG_SLOVENIAN
+ 0x25 LANG_ESTONIAN
+ 0x26 LANG_LATVIAN
+ 0x27 LANG_LITHUANIAN
+ 0x28 LANG_TAJIK
+ 0x29 LANG_FARSI
+ 0x2a LANG_VIETNAMESE
+ 0x2b LANG_ARMENIAN
+ 0x2c LANG_AZERI
+ 0x2d LANG_BASQUE
+ 0x2e LANG_SORBIAN
+ 0x2f LANG_MACEDONIAN
+ 0x30 LANG_SUTU
+ 0x31 LANG_TSONGA
+ 0x32 LANG_TSWANA
+ 0x33 LANG_VENDA
+ 0x34 LANG_XHOSA
+ 0x35 LANG_ZULU
+ 0x36 LANG_AFRIKAANS
+ 0x37 LANG_GEORGIAN
+ 0x38 LANG_FAEROESE
+ 0x39 LANG_HINDI
+ 0x3a LANG_MALTESE
+ 0x3b LANG_SAMI
+ 0x3c LANG_GAELIC
+ 0x3d LANG_YIDDISH
+ 0x3e LANG_MALAY
+ 0x3f LANG_KAZAK
+ 0x40 LANG_KYRGYZ
+ 0x41 LANG_SWAHILI
+ 0x42 LANG_TURKMEN
+ 0x43 LANG_UZBEK
+ 0x44 LANG_TATAR
+ 0x45 LANG_BENGALI
+ 0x46 LANG_PUNJABI
+ 0x47 LANG_GUJARATI
+ 0x48 LANG_ORIYA
+ 0x49 LANG_TAMIL
+ 0x4a LANG_TELUGU
+ 0x4b LANG_KANNADA
+ 0x4c LANG_MALAYALAM
+ 0x4d LANG_ASSAMESE
+ 0x4e LANG_MARATHI
+ 0x4f LANG_SANSKRIT
+ 0x50 LANG_MONGOLIAN
+ 0x51 LANG_TIBETAN
+ 0x52 LANG_WELSH
+ 0x53 LANG_CAMBODIAN
+ 0x54 LANG_LAO
+ 0x55 LANG_BURMESE
+ 0x56 LANG_GALICIAN
+ 0x57 LANG_KONKANI
+ 0x58 LANG_MANIPURI
+ 0x59 LANG_SINDHI
+ 0x5a LANG_SYRIAC
+ 0x5b LANG_SINHALESE
+ 0x5c LANG_CHEROKEE
+ 0x5d LANG_INUKTITUT
+ 0x5e LANG_AMHARIC
+ 0x5f LANG_TAMAZIGHT
+ 0x60 LANG_KASHMIRI
+ 0x61 LANG_NEPALI
+ 0x62 LANG_FRISIAN
+ 0x63 LANG_PASHTO
+ 0x64 LANG_TAGALOG
+ 0x65 LANG_DIVEHI
+ 0x66 LANG_EDO
+ 0x67 LANG_FULFULDE
+ 0x68 LANG_HAUSA
+ 0x69 LANG_IBIBIO
+ 0x6a LANG_YORUBA
+ 0x6d LANG_BASHKIR
+ 0x6e LANG_LUXEMBOURGISH
+ 0x6f LANG_GREENLANDIC
+ 0x70 LANG_IGBO
+ 0x71 LANG_KANURI
+ 0x72 LANG_OROMO
+ 0x73 LANG_TIGRINYA
+ 0x74 LANG_GUARANI
+ 0x75 LANG_HAWAIIAN
+ 0x76 LANG_LATIN
+ 0x77 LANG_SOMALI
+ 0x78 LANG_YI
+ 0x79 LANG_PAPIAMENTU
+ 0x7a LANG_MAPUDUNGUN
+ 0x7c LANG_MOHAWK
+ 0x7e LANG_BRETON
+ 0x82 LANG_OCCITAN
+ 0x83 LANG_CORSICAN
+ 0x84 LANG_ALSATIAN
+ 0x85 LANG_YAKUT
+ 0x86 LANG_KICHE
+ 0x87 LANG_KINYARWANDA
+ 0x88 LANG_WOLOF
+ 0x8c LANG_DARI
+ 0x91 LANG_SCOTTISH_GAELIC
+*/
+/* Mingw headers don't have latest language and sublanguage codes. */
+# ifndef LANG_AFRIKAANS
+# define LANG_AFRIKAANS 0x36
+# endif
+# ifndef LANG_ALBANIAN
+# define LANG_ALBANIAN 0x1c
+# endif
+# ifndef LANG_ALSATIAN
+# define LANG_ALSATIAN 0x84
+# endif
+# ifndef LANG_AMHARIC
+# define LANG_AMHARIC 0x5e
+# endif
+# ifndef LANG_ARABIC
+# define LANG_ARABIC 0x01
+# endif
+# ifndef LANG_ARMENIAN
+# define LANG_ARMENIAN 0x2b
+# endif
+# ifndef LANG_ASSAMESE
+# define LANG_ASSAMESE 0x4d
+# endif
+# ifndef LANG_AZERI
+# define LANG_AZERI 0x2c
+# endif
+# ifndef LANG_BASHKIR
+# define LANG_BASHKIR 0x6d
+# endif
+# ifndef LANG_BASQUE
+# define LANG_BASQUE 0x2d
+# endif
+# ifndef LANG_BELARUSIAN
+# define LANG_BELARUSIAN 0x23
+# endif
+# ifndef LANG_BENGALI
+# define LANG_BENGALI 0x45
+# endif
+# ifndef LANG_BRETON
+# define LANG_BRETON 0x7e
+# endif
+# ifndef LANG_BURMESE
+# define LANG_BURMESE 0x55
+# endif
+# ifndef LANG_CAMBODIAN
+# define LANG_CAMBODIAN 0x53
+# endif
+# ifndef LANG_CATALAN
+# define LANG_CATALAN 0x03
+# endif
+# ifndef LANG_CHEROKEE
+# define LANG_CHEROKEE 0x5c
+# endif
+# ifndef LANG_CORSICAN
+# define LANG_CORSICAN 0x83
+# endif
+# ifndef LANG_DARI
+# define LANG_DARI 0x8c
+# endif
+# ifndef LANG_DIVEHI
+# define LANG_DIVEHI 0x65
+# endif
+# ifndef LANG_EDO
+# define LANG_EDO 0x66
+# endif
+# ifndef LANG_ESTONIAN
+# define LANG_ESTONIAN 0x25
+# endif
+# ifndef LANG_FAEROESE
+# define LANG_FAEROESE 0x38
+# endif
+# ifndef LANG_FARSI
+# define LANG_FARSI 0x29
+# endif
+# ifndef LANG_FRISIAN
+# define LANG_FRISIAN 0x62
+# endif
+# ifndef LANG_FULFULDE
+# define LANG_FULFULDE 0x67
+# endif
+# ifndef LANG_GAELIC
+# define LANG_GAELIC 0x3c
+# endif
+# ifndef LANG_GALICIAN
+# define LANG_GALICIAN 0x56
+# endif
+# ifndef LANG_GEORGIAN
+# define LANG_GEORGIAN 0x37
+# endif
+# ifndef LANG_GREENLANDIC
+# define LANG_GREENLANDIC 0x6f
+# endif
+# ifndef LANG_GUARANI
+# define LANG_GUARANI 0x74
+# endif
+# ifndef LANG_GUJARATI
+# define LANG_GUJARATI 0x47
+# endif
+# ifndef LANG_HAUSA
+# define LANG_HAUSA 0x68
+# endif
+# ifndef LANG_HAWAIIAN
+# define LANG_HAWAIIAN 0x75
+# endif
+# ifndef LANG_HEBREW
+# define LANG_HEBREW 0x0d
+# endif
+# ifndef LANG_HINDI
+# define LANG_HINDI 0x39
+# endif
+# ifndef LANG_IBIBIO
+# define LANG_IBIBIO 0x69
+# endif
+# ifndef LANG_IGBO
+# define LANG_IGBO 0x70
+# endif
+# ifndef LANG_INDONESIAN
+# define LANG_INDONESIAN 0x21
+# endif
+# ifndef LANG_INUKTITUT
+# define LANG_INUKTITUT 0x5d
+# endif
+# ifndef LANG_KANNADA
+# define LANG_KANNADA 0x4b
+# endif
+# ifndef LANG_KANURI
+# define LANG_KANURI 0x71
+# endif
+# ifndef LANG_KASHMIRI
+# define LANG_KASHMIRI 0x60
+# endif
+# ifndef LANG_KAZAK
+# define LANG_KAZAK 0x3f
+# endif
+# ifndef LANG_KICHE
+# define LANG_KICHE 0x86
+# endif
+# ifndef LANG_KINYARWANDA
+# define LANG_KINYARWANDA 0x87
+# endif
+# ifndef LANG_KONKANI
+# define LANG_KONKANI 0x57
+# endif
+# ifndef LANG_KYRGYZ
+# define LANG_KYRGYZ 0x40
+# endif
+# ifndef LANG_LAO
+# define LANG_LAO 0x54
+# endif
+# ifndef LANG_LATIN
+# define LANG_LATIN 0x76
+# endif
+# ifndef LANG_LATVIAN
+# define LANG_LATVIAN 0x26
+# endif
+# ifndef LANG_LITHUANIAN
+# define LANG_LITHUANIAN 0x27
+# endif
+# ifndef LANG_LUXEMBOURGISH
+# define LANG_LUXEMBOURGISH 0x6e
+# endif
+# ifndef LANG_MACEDONIAN
+# define LANG_MACEDONIAN 0x2f
+# endif
+# ifndef LANG_MALAY
+# define LANG_MALAY 0x3e
+# endif
+# ifndef LANG_MALAYALAM
+# define LANG_MALAYALAM 0x4c
+# endif
+# ifndef LANG_MALTESE
+# define LANG_MALTESE 0x3a
+# endif
+# ifndef LANG_MANIPURI
+# define LANG_MANIPURI 0x58
+# endif
+# ifndef LANG_MAORI
+# define LANG_MAORI 0x81
+# endif
+# ifndef LANG_MAPUDUNGUN
+# define LANG_MAPUDUNGUN 0x7a
+# endif
+# ifndef LANG_MARATHI
+# define LANG_MARATHI 0x4e
+# endif
+# ifndef LANG_MOHAWK
+# define LANG_MOHAWK 0x7c
+# endif
+# ifndef LANG_MONGOLIAN
+# define LANG_MONGOLIAN 0x50
+# endif
+# ifndef LANG_NEPALI
+# define LANG_NEPALI 0x61
+# endif
+# ifndef LANG_OCCITAN
+# define LANG_OCCITAN 0x82
+# endif
+# ifndef LANG_ORIYA
+# define LANG_ORIYA 0x48
+# endif
+# ifndef LANG_OROMO
+# define LANG_OROMO 0x72
+# endif
+# ifndef LANG_PAPIAMENTU
+# define LANG_PAPIAMENTU 0x79
+# endif
+# ifndef LANG_PASHTO
+# define LANG_PASHTO 0x63
+# endif
+# ifndef LANG_PUNJABI
+# define LANG_PUNJABI 0x46
+# endif
+# ifndef LANG_QUECHUA
+# define LANG_QUECHUA 0x6b
+# endif
+# ifndef LANG_ROMANSH
+# define LANG_ROMANSH 0x17
+# endif
+# ifndef LANG_SAMI
+# define LANG_SAMI 0x3b
+# endif
+# ifndef LANG_SANSKRIT
+# define LANG_SANSKRIT 0x4f
+# endif
+# ifndef LANG_SCOTTISH_GAELIC
+# define LANG_SCOTTISH_GAELIC 0x91
+# endif
+# ifndef LANG_SERBIAN
+# define LANG_SERBIAN 0x1a
+# endif
+# ifndef LANG_SINDHI
+# define LANG_SINDHI 0x59
+# endif
+# ifndef LANG_SINHALESE
+# define LANG_SINHALESE 0x5b
+# endif
+# ifndef LANG_SLOVAK
+# define LANG_SLOVAK 0x1b
+# endif
+# ifndef LANG_SOMALI
+# define LANG_SOMALI 0x77
+# endif
+# ifndef LANG_SORBIAN
+# define LANG_SORBIAN 0x2e
+# endif
+# ifndef LANG_SOTHO
+# define LANG_SOTHO 0x6c
+# endif
+# ifndef LANG_SUTU
+# define LANG_SUTU 0x30
+# endif
+# ifndef LANG_SWAHILI
+# define LANG_SWAHILI 0x41
+# endif
+# ifndef LANG_SYRIAC
+# define LANG_SYRIAC 0x5a
+# endif
+# ifndef LANG_TAGALOG
+# define LANG_TAGALOG 0x64
+# endif
+# ifndef LANG_TAJIK
+# define LANG_TAJIK 0x28
+# endif
+# ifndef LANG_TAMAZIGHT
+# define LANG_TAMAZIGHT 0x5f
+# endif
+# ifndef LANG_TAMIL
+# define LANG_TAMIL 0x49
+# endif
+# ifndef LANG_TATAR
+# define LANG_TATAR 0x44
+# endif
+# ifndef LANG_TELUGU
+# define LANG_TELUGU 0x4a
+# endif
+# ifndef LANG_THAI
+# define LANG_THAI 0x1e
+# endif
+# ifndef LANG_TIBETAN
+# define LANG_TIBETAN 0x51
+# endif
+# ifndef LANG_TIGRINYA
+# define LANG_TIGRINYA 0x73
+# endif
+# ifndef LANG_TSONGA
+# define LANG_TSONGA 0x31
+# endif
+# ifndef LANG_TSWANA
+# define LANG_TSWANA 0x32
+# endif
+# ifndef LANG_TURKMEN
+# define LANG_TURKMEN 0x42
+# endif
+# ifndef LANG_UIGHUR
+# define LANG_UIGHUR 0x80
+# endif
+# ifndef LANG_UKRAINIAN
+# define LANG_UKRAINIAN 0x22
+# endif
+# ifndef LANG_URDU
+# define LANG_URDU 0x20
+# endif
+# ifndef LANG_UZBEK
+# define LANG_UZBEK 0x43
+# endif
+# ifndef LANG_VENDA
+# define LANG_VENDA 0x33
+# endif
+# ifndef LANG_VIETNAMESE
+# define LANG_VIETNAMESE 0x2a
+# endif
+# ifndef LANG_WELSH
+# define LANG_WELSH 0x52
+# endif
+# ifndef LANG_WOLOF
+# define LANG_WOLOF 0x88
+# endif
+# ifndef LANG_XHOSA
+# define LANG_XHOSA 0x34
+# endif
+# ifndef LANG_YAKUT
+# define LANG_YAKUT 0x85
+# endif
+# ifndef LANG_YI
+# define LANG_YI 0x78
+# endif
+# ifndef LANG_YIDDISH
+# define LANG_YIDDISH 0x3d
+# endif
+# ifndef LANG_YORUBA
+# define LANG_YORUBA 0x6a
+# endif
+# ifndef LANG_ZULU
+# define LANG_ZULU 0x35
+# endif
+# ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
+# define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_ALBANIAN_ALBANIA
+# define SUBLANG_ALBANIAN_ALBANIA 0x01
+# endif
+# ifndef SUBLANG_ALSATIAN_FRANCE
+# define SUBLANG_ALSATIAN_FRANCE 0x01
+# endif
+# ifndef SUBLANG_AMHARIC_ETHIOPIA
+# define SUBLANG_AMHARIC_ETHIOPIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
+# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_IRAQ
+# define SUBLANG_ARABIC_IRAQ 0x02
+# endif
+# ifndef SUBLANG_ARABIC_EGYPT
+# define SUBLANG_ARABIC_EGYPT 0x03
+# endif
+# ifndef SUBLANG_ARABIC_LIBYA
+# define SUBLANG_ARABIC_LIBYA 0x04
+# endif
+# ifndef SUBLANG_ARABIC_ALGERIA
+# define SUBLANG_ARABIC_ALGERIA 0x05
+# endif
+# ifndef SUBLANG_ARABIC_MOROCCO
+# define SUBLANG_ARABIC_MOROCCO 0x06
+# endif
+# ifndef SUBLANG_ARABIC_TUNISIA
+# define SUBLANG_ARABIC_TUNISIA 0x07
+# endif
+# ifndef SUBLANG_ARABIC_OMAN
+# define SUBLANG_ARABIC_OMAN 0x08
+# endif
+# ifndef SUBLANG_ARABIC_YEMEN
+# define SUBLANG_ARABIC_YEMEN 0x09
+# endif
+# ifndef SUBLANG_ARABIC_SYRIA
+# define SUBLANG_ARABIC_SYRIA 0x0a
+# endif
+# ifndef SUBLANG_ARABIC_JORDAN
+# define SUBLANG_ARABIC_JORDAN 0x0b
+# endif
+# ifndef SUBLANG_ARABIC_LEBANON
+# define SUBLANG_ARABIC_LEBANON 0x0c
+# endif
+# ifndef SUBLANG_ARABIC_KUWAIT
+# define SUBLANG_ARABIC_KUWAIT 0x0d
+# endif
+# ifndef SUBLANG_ARABIC_UAE
+# define SUBLANG_ARABIC_UAE 0x0e
+# endif
+# ifndef SUBLANG_ARABIC_BAHRAIN
+# define SUBLANG_ARABIC_BAHRAIN 0x0f
+# endif
+# ifndef SUBLANG_ARABIC_QATAR
+# define SUBLANG_ARABIC_QATAR 0x10
+# endif
+# ifndef SUBLANG_ARMENIAN_ARMENIA
+# define SUBLANG_ARMENIAN_ARMENIA 0x01
+# endif
+# ifndef SUBLANG_ASSAMESE_INDIA
+# define SUBLANG_ASSAMESE_INDIA 0x01
+# endif
+# ifndef SUBLANG_AZERI_LATIN
+# define SUBLANG_AZERI_LATIN 0x01
+# endif
+# ifndef SUBLANG_AZERI_CYRILLIC
+# define SUBLANG_AZERI_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_BASHKIR_RUSSIA
+# define SUBLANG_BASHKIR_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_BASQUE_BASQUE
+# define SUBLANG_BASQUE_BASQUE 0x01
+# endif
+# ifndef SUBLANG_BELARUSIAN_BELARUS
+# define SUBLANG_BELARUSIAN_BELARUS 0x01
+# endif
+# ifndef SUBLANG_BENGALI_INDIA
+# define SUBLANG_BENGALI_INDIA 0x01
+# endif
+# ifndef SUBLANG_BENGALI_BANGLADESH
+# define SUBLANG_BENGALI_BANGLADESH 0x02
+# endif
+# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
+# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
+# endif
+# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
+# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
+# endif
+# ifndef SUBLANG_BRETON_FRANCE
+# define SUBLANG_BRETON_FRANCE 0x01
+# endif
+# ifndef SUBLANG_BULGARIAN_BULGARIA
+# define SUBLANG_BULGARIAN_BULGARIA 0x01
+# endif
+# ifndef SUBLANG_CAMBODIAN_CAMBODIA
+# define SUBLANG_CAMBODIAN_CAMBODIA 0x01
+# endif
+# ifndef SUBLANG_CATALAN_SPAIN
+# define SUBLANG_CATALAN_SPAIN 0x01
+# endif
+# ifndef SUBLANG_CORSICAN_FRANCE
+# define SUBLANG_CORSICAN_FRANCE 0x01
+# endif
+# ifndef SUBLANG_CROATIAN_CROATIA
+# define SUBLANG_CROATIAN_CROATIA 0x01
+# endif
+# ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
+# define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
+# endif
+# ifndef SUBLANG_CHINESE_MACAU
+# define SUBLANG_CHINESE_MACAU 0x05
+# endif
+# ifndef SUBLANG_CZECH_CZECH_REPUBLIC
+# define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
+# endif
+# ifndef SUBLANG_DANISH_DENMARK
+# define SUBLANG_DANISH_DENMARK 0x01
+# endif
+# ifndef SUBLANG_DARI_AFGHANISTAN
+# define SUBLANG_DARI_AFGHANISTAN 0x01
+# endif
+# ifndef SUBLANG_DIVEHI_MALDIVES
+# define SUBLANG_DIVEHI_MALDIVES 0x01
+# endif
+# ifndef SUBLANG_DUTCH_SURINAM
+# define SUBLANG_DUTCH_SURINAM 0x03
+# endif
+# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
+# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
+# endif
+# ifndef SUBLANG_ENGLISH_JAMAICA
+# define SUBLANG_ENGLISH_JAMAICA 0x08
+# endif
+# ifndef SUBLANG_ENGLISH_CARIBBEAN
+# define SUBLANG_ENGLISH_CARIBBEAN 0x09
+# endif
+# ifndef SUBLANG_ENGLISH_BELIZE
+# define SUBLANG_ENGLISH_BELIZE 0x0a
+# endif
+# ifndef SUBLANG_ENGLISH_TRINIDAD
+# define SUBLANG_ENGLISH_TRINIDAD 0x0b
+# endif
+# ifndef SUBLANG_ENGLISH_ZIMBABWE
+# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
+# endif
+# ifndef SUBLANG_ENGLISH_PHILIPPINES
+# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
+# endif
+# ifndef SUBLANG_ENGLISH_INDONESIA
+# define SUBLANG_ENGLISH_INDONESIA 0x0e
+# endif
+# ifndef SUBLANG_ENGLISH_HONGKONG
+# define SUBLANG_ENGLISH_HONGKONG 0x0f
+# endif
+# ifndef SUBLANG_ENGLISH_INDIA
+# define SUBLANG_ENGLISH_INDIA 0x10
+# endif
+# ifndef SUBLANG_ENGLISH_MALAYSIA
+# define SUBLANG_ENGLISH_MALAYSIA 0x11
+# endif
+# ifndef SUBLANG_ENGLISH_SINGAPORE
+# define SUBLANG_ENGLISH_SINGAPORE 0x12
+# endif
+# ifndef SUBLANG_ESTONIAN_ESTONIA
+# define SUBLANG_ESTONIAN_ESTONIA 0x01
+# endif
+# ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
+# define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
+# endif
+# ifndef SUBLANG_FARSI_IRAN
+# define SUBLANG_FARSI_IRAN 0x01
+# endif
+# ifndef SUBLANG_FINNISH_FINLAND
+# define SUBLANG_FINNISH_FINLAND 0x01
+# endif
+# ifndef SUBLANG_FRENCH_LUXEMBOURG
+# define SUBLANG_FRENCH_LUXEMBOURG 0x05
+# endif
+# ifndef SUBLANG_FRENCH_MONACO
+# define SUBLANG_FRENCH_MONACO 0x06
+# endif
+# ifndef SUBLANG_FRENCH_WESTINDIES
+# define SUBLANG_FRENCH_WESTINDIES 0x07
+# endif
+# ifndef SUBLANG_FRENCH_REUNION
+# define SUBLANG_FRENCH_REUNION 0x08
+# endif
+# ifndef SUBLANG_FRENCH_CONGO
+# define SUBLANG_FRENCH_CONGO 0x09
+# endif
+# ifndef SUBLANG_FRENCH_SENEGAL
+# define SUBLANG_FRENCH_SENEGAL 0x0a
+# endif
+# ifndef SUBLANG_FRENCH_CAMEROON
+# define SUBLANG_FRENCH_CAMEROON 0x0b
+# endif
+# ifndef SUBLANG_FRENCH_COTEDIVOIRE
+# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
+# endif
+# ifndef SUBLANG_FRENCH_MALI
+# define SUBLANG_FRENCH_MALI 0x0d
+# endif
+# ifndef SUBLANG_FRENCH_MOROCCO
+# define SUBLANG_FRENCH_MOROCCO 0x0e
+# endif
+# ifndef SUBLANG_FRENCH_HAITI
+# define SUBLANG_FRENCH_HAITI 0x0f
+# endif
+# ifndef SUBLANG_FRISIAN_NETHERLANDS
+# define SUBLANG_FRISIAN_NETHERLANDS 0x01
+# endif
+# ifndef SUBLANG_GALICIAN_SPAIN
+# define SUBLANG_GALICIAN_SPAIN 0x01
+# endif
+# ifndef SUBLANG_GEORGIAN_GEORGIA
+# define SUBLANG_GEORGIAN_GEORGIA 0x01
+# endif
+# ifndef SUBLANG_GERMAN_LUXEMBOURG
+# define SUBLANG_GERMAN_LUXEMBOURG 0x04
+# endif
+# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
+# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
+# endif
+# ifndef SUBLANG_GREEK_GREECE
+# define SUBLANG_GREEK_GREECE 0x01
+# endif
+# ifndef SUBLANG_GREENLANDIC_GREENLAND
+# define SUBLANG_GREENLANDIC_GREENLAND 0x01
+# endif
+# ifndef SUBLANG_GUJARATI_INDIA
+# define SUBLANG_GUJARATI_INDIA 0x01
+# endif
+# ifndef SUBLANG_HAUSA_NIGERIA_LATIN
+# define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
+# endif
+# ifndef SUBLANG_HEBREW_ISRAEL
+# define SUBLANG_HEBREW_ISRAEL 0x01
+# endif
+# ifndef SUBLANG_HINDI_INDIA
+# define SUBLANG_HINDI_INDIA 0x01
+# endif
+# ifndef SUBLANG_HUNGARIAN_HUNGARY
+# define SUBLANG_HUNGARIAN_HUNGARY 0x01
+# endif
+# ifndef SUBLANG_ICELANDIC_ICELAND
+# define SUBLANG_ICELANDIC_ICELAND 0x01
+# endif
+# ifndef SUBLANG_IGBO_NIGERIA
+# define SUBLANG_IGBO_NIGERIA 0x01
+# endif
+# ifndef SUBLANG_INDONESIAN_INDONESIA
+# define SUBLANG_INDONESIAN_INDONESIA 0x01
+# endif
+# ifndef SUBLANG_INUKTITUT_CANADA
+# define SUBLANG_INUKTITUT_CANADA 0x01
+# endif
+# undef SUBLANG_INUKTITUT_CANADA_LATIN
+# define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
+# undef SUBLANG_IRISH_IRELAND
+# define SUBLANG_IRISH_IRELAND 0x02
+# ifndef SUBLANG_JAPANESE_JAPAN
+# define SUBLANG_JAPANESE_JAPAN 0x01
+# endif
+# ifndef SUBLANG_KANNADA_INDIA
+# define SUBLANG_KANNADA_INDIA 0x01
+# endif
+# ifndef SUBLANG_KASHMIRI_INDIA
+# define SUBLANG_KASHMIRI_INDIA 0x02
+# endif
+# ifndef SUBLANG_KAZAK_KAZAKHSTAN
+# define SUBLANG_KAZAK_KAZAKHSTAN 0x01
+# endif
+# ifndef SUBLANG_KICHE_GUATEMALA
+# define SUBLANG_KICHE_GUATEMALA 0x01
+# endif
+# ifndef SUBLANG_KINYARWANDA_RWANDA
+# define SUBLANG_KINYARWANDA_RWANDA 0x01
+# endif
+# ifndef SUBLANG_KONKANI_INDIA
+# define SUBLANG_KONKANI_INDIA 0x01
+# endif
+# ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
+# define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
+# endif
+# ifndef SUBLANG_LAO_LAOS
+# define SUBLANG_LAO_LAOS 0x01
+# endif
+# ifndef SUBLANG_LATVIAN_LATVIA
+# define SUBLANG_LATVIAN_LATVIA 0x01
+# endif
+# ifndef SUBLANG_LITHUANIAN_LITHUANIA
+# define SUBLANG_LITHUANIAN_LITHUANIA 0x01
+# endif
+# undef SUBLANG_LOWER_SORBIAN_GERMANY
+# define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
+# ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
+# define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
+# endif
+# ifndef SUBLANG_MACEDONIAN_MACEDONIA
+# define SUBLANG_MACEDONIAN_MACEDONIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_MALAYSIA
+# define SUBLANG_MALAY_MALAYSIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
+# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
+# endif
+# ifndef SUBLANG_MALAYALAM_INDIA
+# define SUBLANG_MALAYALAM_INDIA 0x01
+# endif
+# ifndef SUBLANG_MALTESE_MALTA
+# define SUBLANG_MALTESE_MALTA 0x01
+# endif
+# ifndef SUBLANG_MAORI_NEW_ZEALAND
+# define SUBLANG_MAORI_NEW_ZEALAND 0x01
+# endif
+# ifndef SUBLANG_MAPUDUNGUN_CHILE
+# define SUBLANG_MAPUDUNGUN_CHILE 0x01
+# endif
+# ifndef SUBLANG_MARATHI_INDIA
+# define SUBLANG_MARATHI_INDIA 0x01
+# endif
+# ifndef SUBLANG_MOHAWK_CANADA
+# define SUBLANG_MOHAWK_CANADA 0x01
+# endif
+# ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
+# define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
+# endif
+# ifndef SUBLANG_MONGOLIAN_PRC
+# define SUBLANG_MONGOLIAN_PRC 0x02
+# endif
+# ifndef SUBLANG_NEPALI_NEPAL
+# define SUBLANG_NEPALI_NEPAL 0x01
+# endif
+# ifndef SUBLANG_NEPALI_INDIA
+# define SUBLANG_NEPALI_INDIA 0x02
+# endif
+# ifndef SUBLANG_OCCITAN_FRANCE
+# define SUBLANG_OCCITAN_FRANCE 0x01
+# endif
+# ifndef SUBLANG_ORIYA_INDIA
+# define SUBLANG_ORIYA_INDIA 0x01
+# endif
+# ifndef SUBLANG_PASHTO_AFGHANISTAN
+# define SUBLANG_PASHTO_AFGHANISTAN 0x01
+# endif
+# ifndef SUBLANG_POLISH_POLAND
+# define SUBLANG_POLISH_POLAND 0x01
+# endif
+# ifndef SUBLANG_PUNJABI_INDIA
+# define SUBLANG_PUNJABI_INDIA 0x01
+# endif
+# ifndef SUBLANG_PUNJABI_PAKISTAN
+# define SUBLANG_PUNJABI_PAKISTAN 0x02
+# endif
+# ifndef SUBLANG_QUECHUA_BOLIVIA
+# define SUBLANG_QUECHUA_BOLIVIA 0x01
+# endif
+# ifndef SUBLANG_QUECHUA_ECUADOR
+# define SUBLANG_QUECHUA_ECUADOR 0x02
+# endif
+# ifndef SUBLANG_QUECHUA_PERU
+# define SUBLANG_QUECHUA_PERU 0x03
+# endif
+# ifndef SUBLANG_ROMANIAN_ROMANIA
+# define SUBLANG_ROMANIAN_ROMANIA 0x01
+# endif
+# ifndef SUBLANG_ROMANIAN_MOLDOVA
+# define SUBLANG_ROMANIAN_MOLDOVA 0x02
+# endif
+# ifndef SUBLANG_ROMANSH_SWITZERLAND
+# define SUBLANG_ROMANSH_SWITZERLAND 0x01
+# endif
+# ifndef SUBLANG_RUSSIAN_RUSSIA
+# define SUBLANG_RUSSIAN_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_RUSSIAN_MOLDAVIA
+# define SUBLANG_RUSSIAN_MOLDAVIA 0x02
+# endif
+# ifndef SUBLANG_SAMI_NORTHERN_NORWAY
+# define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
+# endif
+# ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
+# define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
+# endif
+# ifndef SUBLANG_SAMI_NORTHERN_FINLAND
+# define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
+# endif
+# ifndef SUBLANG_SAMI_LULE_NORWAY
+# define SUBLANG_SAMI_LULE_NORWAY 0x04
+# endif
+# ifndef SUBLANG_SAMI_LULE_SWEDEN
+# define SUBLANG_SAMI_LULE_SWEDEN 0x05
+# endif
+# ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
+# define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
+# endif
+# ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
+# define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
+# endif
+# undef SUBLANG_SAMI_SKOLT_FINLAND
+# define SUBLANG_SAMI_SKOLT_FINLAND 0x08
+# undef SUBLANG_SAMI_INARI_FINLAND
+# define SUBLANG_SAMI_INARI_FINLAND 0x09
+# ifndef SUBLANG_SANSKRIT_INDIA
+# define SUBLANG_SANSKRIT_INDIA 0x01
+# endif
+# ifndef SUBLANG_SERBIAN_LATIN
+# define SUBLANG_SERBIAN_LATIN 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_CYRILLIC
+# define SUBLANG_SERBIAN_CYRILLIC 0x03
+# endif
+# ifndef SUBLANG_SINDHI_INDIA
+# define SUBLANG_SINDHI_INDIA 0x01
+# endif
+# undef SUBLANG_SINDHI_PAKISTAN
+# define SUBLANG_SINDHI_PAKISTAN 0x02
+# ifndef SUBLANG_SINDHI_AFGHANISTAN
+# define SUBLANG_SINDHI_AFGHANISTAN 0x02
+# endif
+# ifndef SUBLANG_SINHALESE_SRI_LANKA
+# define SUBLANG_SINHALESE_SRI_LANKA 0x01
+# endif
+# ifndef SUBLANG_SLOVAK_SLOVAKIA
+# define SUBLANG_SLOVAK_SLOVAKIA 0x01
+# endif
+# ifndef SUBLANG_SLOVENIAN_SLOVENIA
+# define SUBLANG_SLOVENIAN_SLOVENIA 0x01
+# endif
+# ifndef SUBLANG_SOTHO_SOUTH_AFRICA
+# define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_SPANISH_GUATEMALA
+# define SUBLANG_SPANISH_GUATEMALA 0x04
+# endif
+# ifndef SUBLANG_SPANISH_COSTA_RICA
+# define SUBLANG_SPANISH_COSTA_RICA 0x05
+# endif
+# ifndef SUBLANG_SPANISH_PANAMA
+# define SUBLANG_SPANISH_PANAMA 0x06
+# endif
+# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
+# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
+# endif
+# ifndef SUBLANG_SPANISH_VENEZUELA
+# define SUBLANG_SPANISH_VENEZUELA 0x08
+# endif
+# ifndef SUBLANG_SPANISH_COLOMBIA
+# define SUBLANG_SPANISH_COLOMBIA 0x09
+# endif
+# ifndef SUBLANG_SPANISH_PERU
+# define SUBLANG_SPANISH_PERU 0x0a
+# endif
+# ifndef SUBLANG_SPANISH_ARGENTINA
+# define SUBLANG_SPANISH_ARGENTINA 0x0b
+# endif
+# ifndef SUBLANG_SPANISH_ECUADOR
+# define SUBLANG_SPANISH_ECUADOR 0x0c
+# endif
+# ifndef SUBLANG_SPANISH_CHILE
+# define SUBLANG_SPANISH_CHILE 0x0d
+# endif
+# ifndef SUBLANG_SPANISH_URUGUAY
+# define SUBLANG_SPANISH_URUGUAY 0x0e
+# endif
+# ifndef SUBLANG_SPANISH_PARAGUAY
+# define SUBLANG_SPANISH_PARAGUAY 0x0f
+# endif
+# ifndef SUBLANG_SPANISH_BOLIVIA
+# define SUBLANG_SPANISH_BOLIVIA 0x10
+# endif
+# ifndef SUBLANG_SPANISH_EL_SALVADOR
+# define SUBLANG_SPANISH_EL_SALVADOR 0x11
+# endif
+# ifndef SUBLANG_SPANISH_HONDURAS
+# define SUBLANG_SPANISH_HONDURAS 0x12
+# endif
+# ifndef SUBLANG_SPANISH_NICARAGUA
+# define SUBLANG_SPANISH_NICARAGUA 0x13
+# endif
+# ifndef SUBLANG_SPANISH_PUERTO_RICO
+# define SUBLANG_SPANISH_PUERTO_RICO 0x14
+# endif
+# ifndef SUBLANG_SPANISH_US
+# define SUBLANG_SPANISH_US 0x15
+# endif
+# ifndef SUBLANG_SWAHILI_KENYA
+# define SUBLANG_SWAHILI_KENYA 0x01
+# endif
+# ifndef SUBLANG_SWEDISH_SWEDEN
+# define SUBLANG_SWEDISH_SWEDEN 0x01
+# endif
+# ifndef SUBLANG_SWEDISH_FINLAND
+# define SUBLANG_SWEDISH_FINLAND 0x02
+# endif
+# ifndef SUBLANG_SYRIAC_SYRIA
+# define SUBLANG_SYRIAC_SYRIA 0x01
+# endif
+# ifndef SUBLANG_TAGALOG_PHILIPPINES
+# define SUBLANG_TAGALOG_PHILIPPINES 0x01
+# endif
+# ifndef SUBLANG_TAJIK_TAJIKISTAN
+# define SUBLANG_TAJIK_TAJIKISTAN 0x01
+# endif
+# ifndef SUBLANG_TAMAZIGHT_ARABIC
+# define SUBLANG_TAMAZIGHT_ARABIC 0x01
+# endif
+# ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
+# define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
+# endif
+# ifndef SUBLANG_TAMIL_INDIA
+# define SUBLANG_TAMIL_INDIA 0x01
+# endif
+# ifndef SUBLANG_TATAR_RUSSIA
+# define SUBLANG_TATAR_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_TELUGU_INDIA
+# define SUBLANG_TELUGU_INDIA 0x01
+# endif
+# ifndef SUBLANG_THAI_THAILAND
+# define SUBLANG_THAI_THAILAND 0x01
+# endif
+# ifndef SUBLANG_TIBETAN_PRC
+# define SUBLANG_TIBETAN_PRC 0x01
+# endif
+# undef SUBLANG_TIBETAN_BHUTAN
+# define SUBLANG_TIBETAN_BHUTAN 0x02
+# ifndef SUBLANG_TIGRINYA_ETHIOPIA
+# define SUBLANG_TIGRINYA_ETHIOPIA 0x01
+# endif
+# ifndef SUBLANG_TIGRINYA_ERITREA
+# define SUBLANG_TIGRINYA_ERITREA 0x02
+# endif
+# ifndef SUBLANG_TSWANA_SOUTH_AFRICA
+# define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_TURKISH_TURKEY
+# define SUBLANG_TURKISH_TURKEY 0x01
+# endif
+# ifndef SUBLANG_TURKMEN_TURKMENISTAN
+# define SUBLANG_TURKMEN_TURKMENISTAN 0x01
+# endif
+# ifndef SUBLANG_UIGHUR_PRC
+# define SUBLANG_UIGHUR_PRC 0x01
+# endif
+# ifndef SUBLANG_UKRAINIAN_UKRAINE
+# define SUBLANG_UKRAINIAN_UKRAINE 0x01
+# endif
+# ifndef SUBLANG_UPPER_SORBIAN_GERMANY
+# define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
+# endif
+# ifndef SUBLANG_URDU_PAKISTAN
+# define SUBLANG_URDU_PAKISTAN 0x01
+# endif
+# ifndef SUBLANG_URDU_INDIA
+# define SUBLANG_URDU_INDIA 0x02
+# endif
+# ifndef SUBLANG_UZBEK_LATIN
+# define SUBLANG_UZBEK_LATIN 0x01
+# endif
+# ifndef SUBLANG_UZBEK_CYRILLIC
+# define SUBLANG_UZBEK_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_VIETNAMESE_VIETNAM
+# define SUBLANG_VIETNAMESE_VIETNAM 0x01
+# endif
+# ifndef SUBLANG_WELSH_UNITED_KINGDOM
+# define SUBLANG_WELSH_UNITED_KINGDOM 0x01
+# endif
+# ifndef SUBLANG_WOLOF_SENEGAL
+# define SUBLANG_WOLOF_SENEGAL 0x01
+# endif
+# ifndef SUBLANG_XHOSA_SOUTH_AFRICA
+# define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_YAKUT_RUSSIA
+# define SUBLANG_YAKUT_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_YI_PRC
+# define SUBLANG_YI_PRC 0x01
+# endif
+# ifndef SUBLANG_YORUBA_NIGERIA
+# define SUBLANG_YORUBA_NIGERIA 0x01
+# endif
+# ifndef SUBLANG_ZULU_SOUTH_AFRICA
+# define SUBLANG_ZULU_SOUTH_AFRICA 0x01
+# endif
+/* GetLocaleInfoA operations. */
+# ifndef LOCALE_SNAME
+# define LOCALE_SNAME 0x5c
+# endif
+#endif
+
+
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+/* Mac OS X 10.2 or newer */
+
+/* Canonicalize a Mac OS X locale name to a Unix locale name.
+ NAME is a sufficiently large buffer.
+ On input, it contains the Mac OS X locale name.
+ On output, it contains the Unix locale name. */
+# if !defined IN_LIBINTL
+static
+# endif
+void
+gl_locale_name_canonicalize (char *name)
+{
+ /* This conversion is based on a posting by
+ Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
+ http://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
+
+ /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
+ ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
+ Therefore we do it ourselves, using a table based on the results of the
+ Mac OS X 10.3.8 function
+ CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
+ typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
+ legacy_entry;
+ static const legacy_entry legacy_table[] = {
+ { "Afrikaans", "af" },
+ { "Albanian", "sq" },
+ { "Amharic", "am" },
+ { "Arabic", "ar" },
+ { "Armenian", "hy" },
+ { "Assamese", "as" },
+ { "Aymara", "ay" },
+ { "Azerbaijani", "az" },
+ { "Basque", "eu" },
+ { "Belarusian", "be" },
+ { "Belorussian", "be" },
+ { "Bengali", "bn" },
+ { "Brazilian Portugese", "pt_BR" },
+ { "Brazilian Portuguese", "pt_BR" },
+ { "Breton", "br" },
+ { "Bulgarian", "bg" },
+ { "Burmese", "my" },
+ { "Byelorussian", "be" },
+ { "Catalan", "ca" },
+ { "Chewa", "ny" },
+ { "Chichewa", "ny" },
+ { "Chinese", "zh" },
+ { "Chinese, Simplified", "zh_CN" },
+ { "Chinese, Traditional", "zh_TW" },
+ { "Chinese, Tradtional", "zh_TW" },
+ { "Croatian", "hr" },
+ { "Czech", "cs" },
+ { "Danish", "da" },
+ { "Dutch", "nl" },
+ { "Dzongkha", "dz" },
+ { "English", "en" },
+ { "Esperanto", "eo" },
+ { "Estonian", "et" },
+ { "Faroese", "fo" },
+ { "Farsi", "fa" },
+ { "Finnish", "fi" },
+ { "Flemish", "nl_BE" },
+ { "French", "fr" },
+ { "Galician", "gl" },
+ { "Gallegan", "gl" },
+ { "Georgian", "ka" },
+ { "German", "de" },
+ { "Greek", "el" },
+ { "Greenlandic", "kl" },
+ { "Guarani", "gn" },
+ { "Gujarati", "gu" },
+ { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
+ { "Hebrew", "he" },
+ { "Hindi", "hi" },
+ { "Hungarian", "hu" },
+ { "Icelandic", "is" },
+ { "Indonesian", "id" },
+ { "Inuktitut", "iu" },
+ { "Irish", "ga" },
+ { "Italian", "it" },
+ { "Japanese", "ja" },
+ { "Javanese", "jv" },
+ { "Kalaallisut", "kl" },
+ { "Kannada", "kn" },
+ { "Kashmiri", "ks" },
+ { "Kazakh", "kk" },
+ { "Khmer", "km" },
+ { "Kinyarwanda", "rw" },
+ { "Kirghiz", "ky" },
+ { "Korean", "ko" },
+ { "Kurdish", "ku" },
+ { "Latin", "la" },
+ { "Latvian", "lv" },
+ { "Lithuanian", "lt" },
+ { "Macedonian", "mk" },
+ { "Malagasy", "mg" },
+ { "Malay", "ms" },
+ { "Malayalam", "ml" },
+ { "Maltese", "mt" },
+ { "Manx", "gv" },
+ { "Marathi", "mr" },
+ { "Moldavian", "mo" },
+ { "Mongolian", "mn" },
+ { "Nepali", "ne" },
+ { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
+ { "Nyanja", "ny" },
+ { "Nynorsk", "nn" },
+ { "Oriya", "or" },
+ { "Oromo", "om" },
+ { "Panjabi", "pa" },
+ { "Pashto", "ps" },
+ { "Persian", "fa" },
+ { "Polish", "pl" },
+ { "Portuguese", "pt" },
+ { "Portuguese, Brazilian", "pt_BR" },
+ { "Punjabi", "pa" },
+ { "Pushto", "ps" },
+ { "Quechua", "qu" },
+ { "Romanian", "ro" },
+ { "Ruanda", "rw" },
+ { "Rundi", "rn" },
+ { "Russian", "ru" },
+ { "Sami", "se_NO" }, /* Not just "se". */
+ { "Sanskrit", "sa" },
+ { "Scottish", "gd" },
+ { "Serbian", "sr" },
+ { "Simplified Chinese", "zh_CN" },
+ { "Sindhi", "sd" },
+ { "Sinhalese", "si" },
+ { "Slovak", "sk" },
+ { "Slovenian", "sl" },
+ { "Somali", "so" },
+ { "Spanish", "es" },
+ { "Sundanese", "su" },
+ { "Swahili", "sw" },
+ { "Swedish", "sv" },
+ { "Tagalog", "tl" },
+ { "Tajik", "tg" },
+ { "Tajiki", "tg" },
+ { "Tamil", "ta" },
+ { "Tatar", "tt" },
+ { "Telugu", "te" },
+ { "Thai", "th" },
+ { "Tibetan", "bo" },
+ { "Tigrinya", "ti" },
+ { "Tongan", "to" },
+ { "Traditional Chinese", "zh_TW" },
+ { "Turkish", "tr" },
+ { "Turkmen", "tk" },
+ { "Uighur", "ug" },
+ { "Ukrainian", "uk" },
+ { "Urdu", "ur" },
+ { "Uzbek", "uz" },
+ { "Vietnamese", "vi" },
+ { "Welsh", "cy" },
+ { "Yiddish", "yi" }
+ };
+
+ /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
+ to Unix (ISO 639 and ISO 3166) names. */
+ typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
+ langtag_entry;
+ static const langtag_entry langtag_table[] = {
+ /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
+ The default script for az on Unix is Latin. */
+ { "az-Latn", "az" },
+ /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
+ { "ga-dots", "ga" },
+ /* Mac OS X has "kk-Cyrl". Does not yet exist on Unix. */
+ /* Mac OS X has "mn-Cyrl", "mn-Mong".
+ The default script for mn on Unix is Cyrillic. */
+ { "mn-Cyrl", "mn" },
+ /* Mac OS X has "ms-Arab", "ms-Latn".
+ The default script for ms on Unix is Latin. */
+ { "ms-Latn", "ms" },
+ /* Mac OS X has "tg-Cyrl".
+ The default script for tg on Unix is Cyrillic. */
+ { "tg-Cyrl", "tg" },
+ /* Mac OS X has "tk-Cyrl". Does not yet exist on Unix. */
+ /* Mac OS X has "tt-Cyrl".
+ The default script for tt on Unix is Cyrillic. */
+ { "tt-Cyrl", "tt" },
+ /* Mac OS X has "zh-Hans", "zh-Hant".
+ Country codes are used to distinguish these on Unix. */
+ { "zh-Hans", "zh_CN" },
+ { "zh-Hant", "zh_TW" }
+ };
+
+ /* Convert script names (ISO 15924) to Unix conventions.
+ See http://www.unicode.org/iso15924/iso15924-codes.html */
+ typedef struct { const char script[4+1]; const char unixy[9+1]; }
+ script_entry;
+ static const script_entry script_table[] = {
+ { "Arab", "arabic" },
+ { "Cyrl", "cyrillic" },
+ { "Mong", "mongolian" }
+ };
+
+ /* Step 1: Convert using legacy_table. */
+ if (name[0] >= 'A' && name[0] <= 'Z')
+ {
+ unsigned int i1, i2;
+ i1 = 0;
+ i2 = sizeof (legacy_table) / sizeof (legacy_entry);
+ while (i2 - i1 > 1)
+ {
+ /* At this point we know that if name occurs in legacy_table,
+ its index must be >= i1 and < i2. */
+ unsigned int i = (i1 + i2) >> 1;
+ const legacy_entry *p = &legacy_table[i];
+ if (strcmp (name, p->legacy) < 0)
+ i2 = i;
+ else
+ i1 = i;
+ }
+ if (strcmp (name, legacy_table[i1].legacy) == 0)
+ {
+ strcpy (name, legacy_table[i1].unixy);
+ return;
+ }
+ }
+
+ /* Step 2: Convert using langtag_table and script_table. */
+ if (strlen (name) == 7 && name[2] == '-')
+ {
+ unsigned int i1, i2;
+ i1 = 0;
+ i2 = sizeof (langtag_table) / sizeof (langtag_entry);
+ while (i2 - i1 > 1)
+ {
+ /* At this point we know that if name occurs in langtag_table,
+ its index must be >= i1 and < i2. */
+ unsigned int i = (i1 + i2) >> 1;
+ const langtag_entry *p = &langtag_table[i];
+ if (strcmp (name, p->langtag) < 0)
+ i2 = i;
+ else
+ i1 = i;
+ }
+ if (strcmp (name, langtag_table[i1].langtag) == 0)
+ {
+ strcpy (name, langtag_table[i1].unixy);
+ return;
+ }
+
+ i1 = 0;
+ i2 = sizeof (script_table) / sizeof (script_entry);
+ while (i2 - i1 > 1)
+ {
+ /* At this point we know that if (name + 3) occurs in script_table,
+ its index must be >= i1 and < i2. */
+ unsigned int i = (i1 + i2) >> 1;
+ const script_entry *p = &script_table[i];
+ if (strcmp (name + 3, p->script) < 0)
+ i2 = i;
+ else
+ i1 = i;
+ }
+ if (strcmp (name + 3, script_table[i1].script) == 0)
+ {
+ name[2] = '@';
+ strcpy (name + 3, script_table[i1].unixy);
+ return;
+ }
+ }
+
+ /* Step 3: Convert new-style dash to Unix underscore. */
+ {
+ char *p;
+ for (p = name; *p != '\0'; p++)
+ if (*p == '-')
+ *p = '_';
+ }
+}
+
+#endif
+
+
+#if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
+
+/* Canonicalize a Windows native locale name to a Unix locale name.
+ NAME is a sufficiently large buffer.
+ On input, it contains the Windows locale name.
+ On output, it contains the Unix locale name. */
+# if !defined IN_LIBINTL
+static
+# endif
+void
+gl_locale_name_canonicalize (char *name)
+{
+ /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
+ "zh-Hant". */
+ char *p;
+
+ for (p = name; *p != '\0'; p++)
+ if (*p == '-')
+ {
+ *p = '_';
+ p++;
+ for (; *p != '\0'; p++)
+ {
+ if (*p >= 'a' && *p <= 'z')
+ *p += 'A' - 'a';
+ if (*p == '-')
+ {
+ *p = '\0';
+ return;
+ }
+ }
+ return;
+ }
+}
+
+# if !defined IN_LIBINTL
+static
+# endif
+const char *
+gl_locale_name_from_win32_LANGID (LANGID langid)
+{
+ /* Activate the new code only when the GETTEXT_MUI environment variable is
+ set, for the time being, since the new code is not well tested. */
+ if (getenv ("GETTEXT_MUI") != NULL)
+ {
+ static char namebuf[256];
+
+ /* Query the system's notion of locale name.
+ On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
+ But we don't need to support systems that are so old. */
+ if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
+ namebuf, sizeof (namebuf) - 1))
+ {
+ /* Convert it to a Unix locale name. */
+ gl_locale_name_canonicalize (namebuf);
+ return namebuf;
+ }
+ }
+ /* Internet Explorer has an LCID to RFC3066 name mapping stored in
+ HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
+ since IE's i18n subsystem is known to be inconsistent with the native
+ Windows base (e.g. they have different character conversion facilities
+ that produce different results). */
+ /* Use our own table. */
+ {
+ int primary, sub;
+
+ /* Split into language and territory part. */
+ primary = PRIMARYLANGID (langid);
+ sub = SUBLANGID (langid);
+
+ /* Dispatch on language.
+ See also http://www.unicode.org/unicode/onlinedat/languages.html .
+ For details about languages, see http://www.ethnologue.com/ . */
+ switch (primary)
+ {
+ case LANG_AFRIKAANS:
+ switch (sub)
+ {
+ case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA";
+ }
+ return "af";
+ case LANG_ALBANIAN:
+ switch (sub)
+ {
+ case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL";
+ }
+ return "sq";
+ case LANG_ALSATIAN:
+ switch (sub)
+ {
+ case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR";
+ }
+ return "gsw";
+ case LANG_AMHARIC:
+ switch (sub)
+ {
+ case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET";
+ }
+ return "am";
+ case LANG_ARABIC:
+ switch (sub)
+ {
+ case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
+ case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
+ case SUBLANG_ARABIC_EGYPT: return "ar_EG";
+ case SUBLANG_ARABIC_LIBYA: return "ar_LY";
+ case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
+ case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
+ case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
+ case SUBLANG_ARABIC_OMAN: return "ar_OM";
+ case SUBLANG_ARABIC_YEMEN: return "ar_YE";
+ case SUBLANG_ARABIC_SYRIA: return "ar_SY";
+ case SUBLANG_ARABIC_JORDAN: return "ar_JO";
+ case SUBLANG_ARABIC_LEBANON: return "ar_LB";
+ case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
+ case SUBLANG_ARABIC_UAE: return "ar_AE";
+ case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
+ case SUBLANG_ARABIC_QATAR: return "ar_QA";
+ }
+ return "ar";
+ case LANG_ARMENIAN:
+ switch (sub)
+ {
+ case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM";
+ }
+ return "hy";
+ case LANG_ASSAMESE:
+ switch (sub)
+ {
+ case SUBLANG_ASSAMESE_INDIA: return "as_IN";
+ }
+ return "as";
+ case LANG_AZERI:
+ switch (sub)
+ {
+ /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
+ case 0x1e: return "az@latin";
+ case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
+ case 0x1d: return "az@cyrillic";
+ case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
+ }
+ return "az";
+ case LANG_BASHKIR:
+ switch (sub)
+ {
+ case SUBLANG_BASHKIR_RUSSIA: return "ba_RU";
+ }
+ return "ba";
+ case LANG_BASQUE:
+ switch (sub)
+ {
+ case SUBLANG_BASQUE_BASQUE: return "eu_ES";
+ }
+ return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
+ case LANG_BELARUSIAN:
+ switch (sub)
+ {
+ case SUBLANG_BELARUSIAN_BELARUS: return "be_BY";
+ }
+ return "be";
+ case LANG_BENGALI:
+ switch (sub)
+ {
+ case SUBLANG_BENGALI_INDIA: return "bn_IN";
+ case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
+ }
+ return "bn";
+ case LANG_BRETON:
+ switch (sub)
+ {
+ case SUBLANG_BRETON_FRANCE: return "br_FR";
+ }
+ return "br";
+ case LANG_BULGARIAN:
+ switch (sub)
+ {
+ case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG";
+ }
+ return "bg";
+ case LANG_BURMESE:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "my_MM";
+ }
+ return "my";
+ case LANG_CAMBODIAN:
+ switch (sub)
+ {
+ case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH";
+ }
+ return "km";
+ case LANG_CATALAN:
+ switch (sub)
+ {
+ case SUBLANG_CATALAN_SPAIN: return "ca_ES";
+ }
+ return "ca";
+ case LANG_CHEROKEE:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "chr_US";
+ }
+ return "chr";
+ case LANG_CHINESE:
+ switch (sub)
+ {
+ case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW";
+ case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN";
+ case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */
+ case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */
+ case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */
+ }
+ return "zh";
+ case LANG_CORSICAN:
+ switch (sub)
+ {
+ case SUBLANG_CORSICAN_FRANCE: return "co_FR";
+ }
+ return "co";
+ case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
+ * What used to be called Serbo-Croatian
+ * should really now be two separate
+ * languages because of political reasons.
+ * (Says tml, who knows nothing about Serbian
+ * or Croatian.)
+ * (I can feel those flames coming already.)
+ */
+ switch (sub)
+ {
+ /* Croatian */
+ case 0x00: return "hr";
+ case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
+ case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
+ /* Serbian */
+ case 0x1f: return "sr";
+ case 0x1c: return "sr"; /* latin */
+ case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */
+ case 0x09: return "sr_RS"; /* latin */
+ case 0x0b: return "sr_ME"; /* latin */
+ case 0x06: return "sr_BA"; /* latin */
+ case 0x1b: return "sr@cyrillic";
+ case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
+ case 0x0a: return "sr_RS@cyrillic";
+ case 0x0c: return "sr_ME@cyrillic";
+ case 0x07: return "sr_BA@cyrillic";
+ /* Bosnian */
+ case 0x1e: return "bs";
+ case 0x1a: return "bs"; /* latin */
+ case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */
+ case 0x19: return "bs@cyrillic";
+ case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
+ }
+ return "hr";
+ case LANG_CZECH:
+ switch (sub)
+ {
+ case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ";
+ }
+ return "cs";
+ case LANG_DANISH:
+ switch (sub)
+ {
+ case SUBLANG_DANISH_DENMARK: return "da_DK";
+ }
+ return "da";
+ case LANG_DARI:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_DARI_AFGHANISTAN: return "prs_AF";
+ }
+ return "prs";
+ case LANG_DIVEHI:
+ switch (sub)
+ {
+ case SUBLANG_DIVEHI_MALDIVES: return "dv_MV";
+ }
+ return "dv";
+ case LANG_DUTCH:
+ switch (sub)
+ {
+ case SUBLANG_DUTCH: return "nl_NL";
+ case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
+ case SUBLANG_DUTCH_SURINAM: return "nl_SR";
+ }
+ return "nl";
+ case LANG_EDO:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "bin_NG";
+ }
+ return "bin";
+ case LANG_ENGLISH:
+ switch (sub)
+ {
+ /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
+ * English was the language spoken in England.
+ * Oh well.
+ */
+ case SUBLANG_ENGLISH_US: return "en_US";
+ case SUBLANG_ENGLISH_UK: return "en_GB";
+ case SUBLANG_ENGLISH_AUS: return "en_AU";
+ case SUBLANG_ENGLISH_CAN: return "en_CA";
+ case SUBLANG_ENGLISH_NZ: return "en_NZ";
+ case SUBLANG_ENGLISH_EIRE: return "en_IE";
+ case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
+ case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
+ case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
+ case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
+ case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
+ case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
+ case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
+ case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
+ case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
+ case SUBLANG_ENGLISH_INDIA: return "en_IN";
+ case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
+ case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
+ }
+ return "en";
+ case LANG_ESTONIAN:
+ switch (sub)
+ {
+ case SUBLANG_ESTONIAN_ESTONIA: return "et_EE";
+ }
+ return "et";
+ case LANG_FAEROESE:
+ switch (sub)
+ {
+ case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO";
+ }
+ return "fo";
+ case LANG_FARSI:
+ switch (sub)
+ {
+ case SUBLANG_FARSI_IRAN: return "fa_IR";
+ }
+ return "fa";
+ case LANG_FINNISH:
+ switch (sub)
+ {
+ case SUBLANG_FINNISH_FINLAND: return "fi_FI";
+ }
+ return "fi";
+ case LANG_FRENCH:
+ switch (sub)
+ {
+ case SUBLANG_FRENCH: return "fr_FR";
+ case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
+ case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
+ case SUBLANG_FRENCH_SWISS: return "fr_CH";
+ case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
+ case SUBLANG_FRENCH_MONACO: return "fr_MC";
+ case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
+ case SUBLANG_FRENCH_REUNION: return "fr_RE";
+ case SUBLANG_FRENCH_CONGO: return "fr_CG";
+ case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
+ case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
+ case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
+ case SUBLANG_FRENCH_MALI: return "fr_ML";
+ case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
+ case SUBLANG_FRENCH_HAITI: return "fr_HT";
+ }
+ return "fr";
+ case LANG_FRISIAN:
+ switch (sub)
+ {
+ case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL";
+ }
+ return "fy";
+ case LANG_FULFULDE:
+ /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ff_NG";
+ }
+ return "ff";
+ case LANG_GAELIC:
+ switch (sub)
+ {
+ case 0x01: /* SCOTTISH */
+ /* old, superseded by LANG_SCOTTISH_GAELIC */
+ return "gd_GB";
+ case SUBLANG_IRISH_IRELAND: return "ga_IE";
+ }
+ return "ga";
+ case LANG_GALICIAN:
+ switch (sub)
+ {
+ case SUBLANG_GALICIAN_SPAIN: return "gl_ES";
+ }
+ return "gl";
+ case LANG_GEORGIAN:
+ switch (sub)
+ {
+ case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE";
+ }
+ return "ka";
+ case LANG_GERMAN:
+ switch (sub)
+ {
+ case SUBLANG_GERMAN: return "de_DE";
+ case SUBLANG_GERMAN_SWISS: return "de_CH";
+ case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
+ case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
+ case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
+ }
+ return "de";
+ case LANG_GREEK:
+ switch (sub)
+ {
+ case SUBLANG_GREEK_GREECE: return "el_GR";
+ }
+ return "el";
+ case LANG_GREENLANDIC:
+ switch (sub)
+ {
+ case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL";
+ }
+ return "kl";
+ case LANG_GUARANI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "gn_PY";
+ }
+ return "gn";
+ case LANG_GUJARATI:
+ switch (sub)
+ {
+ case SUBLANG_GUJARATI_INDIA: return "gu_IN";
+ }
+ return "gu";
+ case LANG_HAUSA:
+ switch (sub)
+ {
+ case 0x1f: return "ha";
+ case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG";
+ }
+ return "ha";
+ case LANG_HAWAIIAN:
+ /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
+ or Hawaii Creole English ("cpe_US", 600000 speakers)? */
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "cpe_US";
+ }
+ return "cpe";
+ case LANG_HEBREW:
+ switch (sub)
+ {
+ case SUBLANG_HEBREW_ISRAEL: return "he_IL";
+ }
+ return "he";
+ case LANG_HINDI:
+ switch (sub)
+ {
+ case SUBLANG_HINDI_INDIA: return "hi_IN";
+ }
+ return "hi";
+ case LANG_HUNGARIAN:
+ switch (sub)
+ {
+ case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU";
+ }
+ return "hu";
+ case LANG_IBIBIO:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "nic_NG";
+ }
+ return "nic";
+ case LANG_ICELANDIC:
+ switch (sub)
+ {
+ case SUBLANG_ICELANDIC_ICELAND: return "is_IS";
+ }
+ return "is";
+ case LANG_IGBO:
+ switch (sub)
+ {
+ case SUBLANG_IGBO_NIGERIA: return "ig_NG";
+ }
+ return "ig";
+ case LANG_INDONESIAN:
+ switch (sub)
+ {
+ case SUBLANG_INDONESIAN_INDONESIA: return "id_ID";
+ }
+ return "id";
+ case LANG_INUKTITUT:
+ switch (sub)
+ {
+ case 0x1e: return "iu"; /* syllabic */
+ case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */
+ case 0x1f: return "iu@latin";
+ case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin";
+ }
+ return "iu";
+ case LANG_ITALIAN:
+ switch (sub)
+ {
+ case SUBLANG_ITALIAN: return "it_IT";
+ case SUBLANG_ITALIAN_SWISS: return "it_CH";
+ }
+ return "it";
+ case LANG_JAPANESE:
+ switch (sub)
+ {
+ case SUBLANG_JAPANESE_JAPAN: return "ja_JP";
+ }
+ return "ja";
+ case LANG_KANNADA:
+ switch (sub)
+ {
+ case SUBLANG_KANNADA_INDIA: return "kn_IN";
+ }
+ return "kn";
+ case LANG_KANURI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "kr_NG";
+ }
+ return "kr";
+ case LANG_KASHMIRI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ks_PK";
+ case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
+ }
+ return "ks";
+ case LANG_KAZAK:
+ switch (sub)
+ {
+ case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ";
+ }
+ return "kk";
+ case LANG_KICHE:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_KICHE_GUATEMALA: return "qut_GT";
+ }
+ return "qut";
+ case LANG_KINYARWANDA:
+ switch (sub)
+ {
+ case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW";
+ }
+ return "rw";
+ case LANG_KONKANI:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_KONKANI_INDIA: return "kok_IN";
+ }
+ return "kok";
+ case LANG_KOREAN:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ko_KR";
+ }
+ return "ko";
+ case LANG_KYRGYZ:
+ switch (sub)
+ {
+ case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG";
+ }
+ return "ky";
+ case LANG_LAO:
+ switch (sub)
+ {
+ case SUBLANG_LAO_LAOS: return "lo_LA";
+ }
+ return "lo";
+ case LANG_LATIN:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "la_VA";
+ }
+ return "la";
+ case LANG_LATVIAN:
+ switch (sub)
+ {
+ case SUBLANG_LATVIAN_LATVIA: return "lv_LV";
+ }
+ return "lv";
+ case LANG_LITHUANIAN:
+ switch (sub)
+ {
+ case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT";
+ }
+ return "lt";
+ case LANG_LUXEMBOURGISH:
+ switch (sub)
+ {
+ case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU";
+ }
+ return "lb";
+ case LANG_MACEDONIAN:
+ switch (sub)
+ {
+ case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK";
+ }
+ return "mk";
+ case LANG_MALAY:
+ switch (sub)
+ {
+ case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
+ case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
+ }
+ return "ms";
+ case LANG_MALAYALAM:
+ switch (sub)
+ {
+ case SUBLANG_MALAYALAM_INDIA: return "ml_IN";
+ }
+ return "ml";
+ case LANG_MALTESE:
+ switch (sub)
+ {
+ case SUBLANG_MALTESE_MALTA: return "mt_MT";
+ }
+ return "mt";
+ case LANG_MANIPURI:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "mni_IN";
+ }
+ return "mni";
+ case LANG_MAORI:
+ switch (sub)
+ {
+ case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ";
+ }
+ return "mi";
+ case LANG_MAPUDUNGUN:
+ switch (sub)
+ {
+ case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL";
+ }
+ return "arn";
+ case LANG_MARATHI:
+ switch (sub)
+ {
+ case SUBLANG_MARATHI_INDIA: return "mr_IN";
+ }
+ return "mr";
+ case LANG_MOHAWK:
+ switch (sub)
+ {
+ case SUBLANG_MOHAWK_CANADA: return "moh_CA";
+ }
+ return "moh";
+ case LANG_MONGOLIAN:
+ switch (sub)
+ {
+ case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN";
+ case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN";
+ }
+ return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
+ case LANG_NEPALI:
+ switch (sub)
+ {
+ case SUBLANG_NEPALI_NEPAL: return "ne_NP";
+ case SUBLANG_NEPALI_INDIA: return "ne_IN";
+ }
+ return "ne";
+ case LANG_NORWEGIAN:
+ switch (sub)
+ {
+ case 0x1f: return "nb";
+ case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
+ case 0x1e: return "nn";
+ case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
+ }
+ return "no";
+ case LANG_OCCITAN:
+ switch (sub)
+ {
+ case SUBLANG_OCCITAN_FRANCE: return "oc_FR";
+ }
+ return "oc";
+ case LANG_ORIYA:
+ switch (sub)
+ {
+ case SUBLANG_ORIYA_INDIA: return "or_IN";
+ }
+ return "or";
+ case LANG_OROMO:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "om_ET";
+ }
+ return "om";
+ case LANG_PAPIAMENTU:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "pap_AN";
+ }
+ return "pap";
+ case LANG_PASHTO:
+ switch (sub)
+ {
+ case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF";
+ }
+ return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
+ case LANG_POLISH:
+ switch (sub)
+ {
+ case SUBLANG_POLISH_POLAND: return "pl_PL";
+ }
+ return "pl";
+ case LANG_PORTUGUESE:
+ switch (sub)
+ {
+ /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
+ Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
+ case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
+ case SUBLANG_PORTUGUESE: return "pt_PT";
+ }
+ return "pt";
+ case LANG_PUNJABI:
+ switch (sub)
+ {
+ case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
+ case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
+ }
+ return "pa";
+ case LANG_QUECHUA:
+ /* Note: Microsoft uses the non-ISO language code "quz". */
+ switch (sub)
+ {
+ case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
+ case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
+ case SUBLANG_QUECHUA_PERU: return "qu_PE";
+ }
+ return "qu";
+ case LANG_ROMANIAN:
+ switch (sub)
+ {
+ case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
+ case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
+ }
+ return "ro";
+ case LANG_ROMANSH:
+ switch (sub)
+ {
+ case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH";
+ }
+ return "rm";
+ case LANG_RUSSIAN:
+ switch (sub)
+ {
+ case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
+ case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
+ }
+ return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
+ case LANG_SAMI:
+ switch (sub)
+ {
+ /* Northern Sami */
+ case 0x00: return "se";
+ case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO";
+ case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE";
+ case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI";
+ /* Lule Sami */
+ case 0x1f: return "smj";
+ case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO";
+ case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE";
+ /* Southern Sami */
+ case 0x1e: return "sma";
+ case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO";
+ case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE";
+ /* Skolt Sami */
+ case 0x1d: return "sms";
+ case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI";
+ /* Inari Sami */
+ case 0x1c: return "smn";
+ case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI";
+ }
+ return "se"; /* or "smi"? */
+ case LANG_SANSKRIT:
+ switch (sub)
+ {
+ case SUBLANG_SANSKRIT_INDIA: return "sa_IN";
+ }
+ return "sa";
+ case LANG_SCOTTISH_GAELIC:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "gd_GB";
+ }
+ return "gd";
+ case LANG_SINDHI:
+ switch (sub)
+ {
+ case SUBLANG_SINDHI_INDIA: return "sd_IN";
+ case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
+ /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
+ }
+ return "sd";
+ case LANG_SINHALESE:
+ switch (sub)
+ {
+ case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK";
+ }
+ return "si";
+ case LANG_SLOVAK:
+ switch (sub)
+ {
+ case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK";
+ }
+ return "sk";
+ case LANG_SLOVENIAN:
+ switch (sub)
+ {
+ case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI";
+ }
+ return "sl";
+ case LANG_SOMALI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "so_SO";
+ }
+ return "so";
+ case LANG_SORBIAN:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ /* Upper Sorbian */
+ case 0x00: return "hsb";
+ case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE";
+ /* Lower Sorbian */
+ case 0x1f: return "dsb";
+ case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE";
+ }
+ return "wen";
+ case LANG_SOTHO:
+ /* <http://www.microsoft.com/globaldev/reference/lcid-all.mspx> calls
+ it "Sepedi"; according to
+ <http://www.ethnologue.com/show_language.asp?code=nso>
+ <http://www.ethnologue.com/show_language.asp?code=sot>
+ it's the same as Northern Sotho. */
+ switch (sub)
+ {
+ case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA";
+ }
+ return "nso";
+ case LANG_SPANISH:
+ switch (sub)
+ {
+ case SUBLANG_SPANISH: return "es_ES";
+ case SUBLANG_SPANISH_MEXICAN: return "es_MX";
+ case SUBLANG_SPANISH_MODERN:
+ return "es_ES@modern"; /* not seen on Unix */
+ case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
+ case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
+ case SUBLANG_SPANISH_PANAMA: return "es_PA";
+ case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
+ case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
+ case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
+ case SUBLANG_SPANISH_PERU: return "es_PE";
+ case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
+ case SUBLANG_SPANISH_ECUADOR: return "es_EC";
+ case SUBLANG_SPANISH_CHILE: return "es_CL";
+ case SUBLANG_SPANISH_URUGUAY: return "es_UY";
+ case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
+ case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
+ case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
+ case SUBLANG_SPANISH_HONDURAS: return "es_HN";
+ case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
+ case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
+ case SUBLANG_SPANISH_US: return "es_US";
+ }
+ return "es";
+ case LANG_SUTU:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
+ }
+ return "bnt";
+ case LANG_SWAHILI:
+ switch (sub)
+ {
+ case SUBLANG_SWAHILI_KENYA: return "sw_KE";
+ }
+ return "sw";
+ case LANG_SWEDISH:
+ switch (sub)
+ {
+ case SUBLANG_SWEDISH_SWEDEN: return "sv_SE";
+ case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
+ }
+ return "sv";
+ case LANG_SYRIAC:
+ switch (sub)
+ {
+ case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */
+ }
+ return "syr";
+ case LANG_TAGALOG:
+ switch (sub)
+ {
+ case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */
+ }
+ return "tl"; /* or "fil"? */
+ case LANG_TAJIK:
+ switch (sub)
+ {
+ case 0x1f: return "tg";
+ case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ";
+ }
+ return "tg";
+ case LANG_TAMAZIGHT:
+ /* Note: Microsoft uses the non-ISO language code "tmz". */
+ switch (sub)
+ {
+ /* FIXME: Adjust this when Tamazight locales appear on Unix. */
+ case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
+ case 0x1f: return "ber@latin";
+ case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
+ }
+ return "ber";
+ case LANG_TAMIL:
+ switch (sub)
+ {
+ case SUBLANG_TAMIL_INDIA: return "ta_IN";
+ }
+ return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
+ case LANG_TATAR:
+ switch (sub)
+ {
+ case SUBLANG_TATAR_RUSSIA: return "tt_RU";
+ }
+ return "tt";
+ case LANG_TELUGU:
+ switch (sub)
+ {
+ case SUBLANG_TELUGU_INDIA: return "te_IN";
+ }
+ return "te";
+ case LANG_THAI:
+ switch (sub)
+ {
+ case SUBLANG_THAI_THAILAND: return "th_TH";
+ }
+ return "th";
+ case LANG_TIBETAN:
+ switch (sub)
+ {
+ case SUBLANG_TIBETAN_PRC:
+ /* Most Tibetans would not like "bo_CN". But Tibet does not yet
+ have a country code of its own. */
+ return "bo";
+ case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
+ }
+ return "bo";
+ case LANG_TIGRINYA:
+ switch (sub)
+ {
+ case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
+ case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
+ }
+ return "ti";
+ case LANG_TSONGA:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ts_ZA";
+ }
+ return "ts";
+ case LANG_TSWANA:
+ /* Spoken in South Africa, Botswana. */
+ switch (sub)
+ {
+ case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA";
+ }
+ return "tn";
+ case LANG_TURKISH:
+ switch (sub)
+ {
+ case SUBLANG_TURKISH_TURKEY: return "tr_TR";
+ }
+ return "tr";
+ case LANG_TURKMEN:
+ switch (sub)
+ {
+ case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM";
+ }
+ return "tk";
+ case LANG_UIGHUR:
+ switch (sub)
+ {
+ case SUBLANG_UIGHUR_PRC: return "ug_CN";
+ }
+ return "ug";
+ case LANG_UKRAINIAN:
+ switch (sub)
+ {
+ case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA";
+ }
+ return "uk";
+ case LANG_URDU:
+ switch (sub)
+ {
+ case SUBLANG_URDU_PAKISTAN: return "ur_PK";
+ case SUBLANG_URDU_INDIA: return "ur_IN";
+ }
+ return "ur";
+ case LANG_UZBEK:
+ switch (sub)
+ {
+ case 0x1f: return "uz";
+ case SUBLANG_UZBEK_LATIN: return "uz_UZ";
+ case 0x1e: return "uz@cyrillic";
+ case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
+ }
+ return "uz";
+ case LANG_VENDA:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ve_ZA";
+ }
+ return "ve";
+ case LANG_VIETNAMESE:
+ switch (sub)
+ {
+ case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN";
+ }
+ return "vi";
+ case LANG_WELSH:
+ switch (sub)
+ {
+ case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB";
+ }
+ return "cy";
+ case LANG_WOLOF:
+ switch (sub)
+ {
+ case SUBLANG_WOLOF_SENEGAL: return "wo_SN";
+ }
+ return "wo";
+ case LANG_XHOSA:
+ switch (sub)
+ {
+ case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA";
+ }
+ return "xh";
+ case LANG_YAKUT:
+ switch (sub)
+ {
+ case SUBLANG_YAKUT_RUSSIA: return "sah_RU";
+ }
+ return "sah";
+ case LANG_YI:
+ switch (sub)
+ {
+ case SUBLANG_YI_PRC: return "ii_CN";
+ }
+ return "ii";
+ case LANG_YIDDISH:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "yi_IL";
+ }
+ return "yi";
+ case LANG_YORUBA:
+ switch (sub)
+ {
+ case SUBLANG_YORUBA_NIGERIA: return "yo_NG";
+ }
+ return "yo";
+ case LANG_ZULU:
+ switch (sub)
+ {
+ case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA";
+ }
+ return "zu";
+ default: return "C";
+ }
+ }
+}
+
+# if !defined IN_LIBINTL
+static
+# endif
+const char *
+gl_locale_name_from_win32_LCID (LCID lcid)
+{
+ LANGID langid;
+
+ /* Strip off the sorting rules, keep only the language part. */
+ langid = LANGIDFROMLCID (lcid);
+
+ return gl_locale_name_from_win32_LANGID (langid);
+}
+
+#endif
+
+
+#if HAVE_USELOCALE /* glibc or Mac OS X */
+
+/* Simple hash set of strings. We don't want to drag in lots of hash table
+ code here. */
+
+# define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
+
+/* A hash function for NUL-terminated char* strings using
+ the method described by Bruno Haible.
+ See http://www.haible.de/bruno/hashfunc.html. */
+static size_t
+string_hash (const void *x)
+{
+ const char *s = (const char *) x;
+ size_t h = 0;
+
+ for (; *s; s++)
+ h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
+
+ return h;
+}
+
+/* A hash table of fixed size. Multiple threads can access it read-only
+ simultaneously, but only one thread can insert into it at the same time. */
+
+/* A node in a hash bucket collision list. */
+struct hash_node
+ {
+ struct hash_node * volatile next;
+ char contents[100]; /* has variable size */
+ };
+
+# define HASH_TABLE_SIZE 257
+static struct hash_node * volatile struniq_hash_table[HASH_TABLE_SIZE]
+ /* = { NULL, ..., NULL } */;
+
+/* This lock protects the struniq_hash_table against multiple simultaneous
+ insertions. */
+gl_lock_define_initialized(static, struniq_lock)
+
+/* Store a copy of the given string in a string pool with indefinite extent.
+ Return a pointer to this copy. */
+static const char *
+struniq (const char *string)
+{
+ size_t hashcode = string_hash (string);
+ size_t slot = hashcode % HASH_TABLE_SIZE;
+ size_t size;
+ struct hash_node *new_node;
+ struct hash_node *p;
+ for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
+ if (strcmp (p->contents, string) == 0)
+ return p->contents;
+ size = strlen (string) + 1;
+ new_node =
+ (struct hash_node *)
+ malloc (offsetof (struct hash_node, contents[0]) + size);
+ if (new_node == NULL)
+ /* Out of memory. Return a statically allocated string. */
+ return "C";
+ memcpy (new_node->contents, string, size);
+ /* Lock while inserting new_node. */
+ gl_lock_lock (struniq_lock);
+ /* Check whether another thread already added the string while we were
+ waiting on the lock. */
+ for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
+ if (strcmp (p->contents, string) == 0)
+ {
+ free (new_node);
+ new_node = p;
+ goto done;
+ }
+ /* Really insert new_node into the hash table. Fill new_node entirely first,
+ because other threads may be iterating over the linked list. */
+ new_node->next = struniq_hash_table[slot];
+ struniq_hash_table[slot] = new_node;
+ done:
+ /* Unlock after new_node is inserted. */
+ gl_lock_unlock (struniq_lock);
+ return new_node->contents;
+}
+
+#endif
+
+
+#if defined IN_LIBINTL || HAVE_USELOCALE
+
+/* Like gl_locale_name_thread, except that the result is not in storage of
+ indefinite extent. */
+# if !defined IN_LIBINTL
+static
+# endif
+const char *
+gl_locale_name_thread_unsafe (int category, const char *categoryname)
+{
+# if HAVE_USELOCALE
+ {
+ locale_t thread_locale = uselocale (NULL);
+ if (thread_locale != LC_GLOBAL_LOCALE)
+ {
+# if __GLIBC__ >= 2 && !defined __UCLIBC__
+ /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
+ glibc < 2.12.
+ See <http://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
+ const char *name =
+ nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
+ if (name[0] == '\0')
+ /* Fallback code for glibc < 2.4, which did not implement
+ nl_langinfo (_NL_LOCALE_NAME (category)). */
+ name = thread_locale->__names[category];
+ return name;
+# elif defined __FreeBSD__ || (defined __APPLE__ && defined __MACH__)
+ /* FreeBSD, Mac OS X */
+ int mask;
+
+ switch (category)
+ {
+ case LC_CTYPE:
+ mask = LC_CTYPE_MASK;
+ break;
+ case LC_NUMERIC:
+ mask = LC_NUMERIC_MASK;
+ break;
+ case LC_TIME:
+ mask = LC_TIME_MASK;
+ break;
+ case LC_COLLATE:
+ mask = LC_COLLATE_MASK;
+ break;
+ case LC_MONETARY:
+ mask = LC_MONETARY_MASK;
+ break;
+ case LC_MESSAGES:
+ mask = LC_MESSAGES_MASK;
+ break;
+ default: /* We shouldn't get here. */
+ return "";
+ }
+ return querylocale (mask, thread_locale);
+# endif
+ }
+ }
+# endif
+ return NULL;
+}
+
+#endif
+
+const char *
+gl_locale_name_thread (int category, const char *categoryname)
+{
+#if HAVE_USELOCALE
+ const char *name = gl_locale_name_thread_unsafe (category, categoryname);
+ if (name != NULL)
+ return struniq (name);
+#endif
+ return NULL;
+}
+
+/* XPG3 defines the result of 'setlocale (category, NULL)' as:
+ "Directs 'setlocale()' to query 'category' and return the current
+ setting of 'local'."
+ However it does not specify the exact format. Neither do SUSV2 and
+ ISO C 99. So we can use this feature only on selected systems (e.g.
+ those using GNU C Library). */
+#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
+# define HAVE_LOCALE_NULL
+#endif
+
+const char *
+gl_locale_name_posix (int category, const char *categoryname)
+{
+ /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
+ On some systems this can be done by the 'setlocale' function itself. */
+#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
+ return setlocale (category, NULL);
+#else
+ /* On other systems we ignore what setlocale reports and instead look at the
+ environment variables directly. This is necessary
+ 1. on systems which have a facility for customizing the default locale
+ (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
+ function ignores this default locale (Mac OS X, Cygwin), in two cases:
+ a. when the user missed to use the setlocale() override from libintl
+ (for example by not including <libintl.h>),
+ b. when setlocale supports only the "C" locale, such as on Cygwin
+ 1.5.x. In this case even the override from libintl cannot help.
+ 2. on all systems where setlocale supports only the "C" locale. */
+ /* Strictly speaking, it is a POSIX violation to look at the environment
+ variables regardless whether setlocale has been called or not. POSIX
+ says:
+ "For C-language programs, the POSIX locale shall be the
+ default locale when the setlocale() function is not called."
+ But we assume that all programs that use internationalized APIs call
+ setlocale (LC_ALL, ""). */
+ return gl_locale_name_environ (category, categoryname);
+#endif
+}
+
+const char *
+gl_locale_name_environ (int category, const char *categoryname)
+{
+ const char *retval;
+
+ /* Setting of LC_ALL overrides all other. */
+ retval = getenv ("LC_ALL");
+ if (retval != NULL && retval[0] != '\0')
+ return retval;
+ /* Next comes the name of the desired category. */
+ retval = getenv (categoryname);
+ if (retval != NULL && retval[0] != '\0')
+ return retval;
+
+ /* LANGUAGE has higher priority than LANG */
+ retval = getenv("LANGUAGE");
+ if (retval != NULL && retval[0] != '\0')
+ return retval;
+
+ /* Last possibility is the LANG environment variable. */
+ retval = getenv ("LANG");
+ if (retval != NULL && retval[0] != '\0')
+ {
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+ /* Mac OS X 10.2 or newer.
+ Ignore invalid LANG value set by the Terminal application. */
+ if (strcmp (retval, "UTF-8") != 0)
+#endif
+#if defined __CYGWIN__
+ /* Cygwin.
+ Ignore dummy LANG value set by ~/.profile. */
+ if (strcmp (retval, "C.UTF-8") != 0)
+#endif
+ return retval;
+ }
+
+ return NULL;
+}
+
+const char *
+gl_locale_name_default (void)
+{
+ /* POSIX:2001 says:
+ "All implementations shall define a locale as the default locale, to be
+ invoked when no environment variables are set, or set to the empty
+ string. This default locale can be the POSIX locale or any other
+ implementation-defined locale. Some implementations may provide
+ facilities for local installation administrators to set the default
+ locale, customizing it for each location. POSIX:2001 does not require
+ such a facility.
+
+ The systems with such a facility are Mac OS X and Windows: They provide a
+ GUI that allows the user to choose a locale.
+ - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
+ Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
+ 'Terminal' application (but sometimes to an incorrect value "UTF-8").
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ "C" locale.
+ - On native Windows, by default, none of LC_* or LANG are set.
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ locale chosen by the user.
+ - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ "C" locale.
+ - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
+ ~/.profile is executed.
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ "C.UTF-8" locale, which operates in the same way as the "C" locale.
+ */
+
+#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
+
+ /* The system does not have a way of setting the locale, other than the
+ POSIX specified environment variables. We use C as default locale. */
+ return "C";
+
+#else
+
+ /* Return an XPG style locale name language[_territory][@modifier].
+ Don't even bother determining the codeset; it's not useful in this
+ context, because message catalogs are not specific to a single
+ codeset. */
+
+# if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+ /* Mac OS X 10.2 or newer */
+ {
+ /* Cache the locale name, since CoreFoundation calls are expensive. */
+ static const char *cached_localename;
+
+ if (cached_localename == NULL)
+ {
+ char namebuf[256];
+# if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.3 or newer */
+ CFLocaleRef locale = CFLocaleCopyCurrent ();
+ CFStringRef name = CFLocaleGetIdentifier (locale);
+
+ if (CFStringGetCString (name, namebuf, sizeof (namebuf),
+ kCFStringEncodingASCII))
+ {
+ gl_locale_name_canonicalize (namebuf);
+ cached_localename = strdup (namebuf);
+ }
+ CFRelease (locale);
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.2 or newer */
+ CFTypeRef value =
+ CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
+ kCFPreferencesCurrentApplication);
+ if (value != NULL
+ && CFGetTypeID (value) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)value,
+ namebuf, sizeof (namebuf),
+ kCFStringEncodingASCII))
+ {
+ gl_locale_name_canonicalize (namebuf);
+ cached_localename = strdup (namebuf);
+ }
+# endif
+ if (cached_localename == NULL)
+ cached_localename = "C";
+ }
+ return cached_localename;
+ }
+
+# endif
+
+# if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
+ {
+ LCID lcid;
+
+ /* Use native Windows API locale ID. */
+ lcid = GetThreadLocale ();
+
+ return gl_locale_name_from_win32_LCID (lcid);
+ }
+# endif
+#endif
+}
+
+/* Determine the current locale's name, and canonicalize it into XPG syntax
+ language[_territory][.codeset][@modifier]
+ The codeset part in the result is not reliable; the locale_charset()
+ should be used for codeset information instead.
+ The result must not be freed; it is statically allocated. */
+
+const char *
+gl_locale_name (int category, const char *categoryname)
+{
+ const char *retval;
+
+ retval = gl_locale_name_thread (category, categoryname);
+ if (retval != NULL)
+ return retval;
+
+ retval = gl_locale_name_posix (category, categoryname);
+ if (retval != NULL)
+ return retval;
+
+ return gl_locale_name_default ();
+}
diff --git a/lib/localename/localename.h b/lib/localename/localename.h
new file mode 100644
index 0000000..a76dbc5
--- /dev/null
+++ b/lib/localename/localename.h
@@ -0,0 +1,95 @@
+/* Determine name of the currently selected locale.
+ Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _GL_LOCALENAME_H
+#define _GL_LOCALENAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Determine the current locale's name.
+ It considers both the POSIX notion of locale name (see functions
+ gl_locale_name_thread and gl_locale_name_posix) and the system notion
+ of locale name (see function gl_locale_name_default).
+ CATEGORY is a locale category abbreviation, as defined in <locale.h>,
+ but not LC_ALL. E.g. LC_MESSAGES.
+ CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES".
+ Return the locale category's name, canonicalized into XPG syntax
+ language[_territory][.codeset][@modifier]
+ The codeset part in the result is not reliable; the locale_charset()
+ should be used for codeset information instead.
+ The result must not be freed; it is statically allocated. */
+extern const char * gl_locale_name (int category, const char *categoryname);
+
+/* Determine the current per-thread locale's name, as specified by uselocale()
+ calls.
+ CATEGORY is a locale category abbreviation, as defined in <locale.h>,
+ but not LC_ALL. E.g. LC_MESSAGES.
+ CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES".
+ Return the locale category's name, canonicalized into XPG syntax
+ language[_territory][.codeset][@modifier]
+ or NULL if no locale has been specified for the current thread.
+ The codeset part in the result is not reliable; the locale_charset()
+ should be used for codeset information instead.
+ The result must not be freed; it is statically allocated. */
+extern const char * gl_locale_name_thread (int category, const char *categoryname);
+
+/* Determine the thread-independent current locale's name, as specified by
+ setlocale() calls or by environment variables.
+ CATEGORY is a locale category abbreviation, as defined in <locale.h>,
+ but not LC_ALL. E.g. LC_MESSAGES.
+ CATEGORYNAME is the name of CATEGORY as a string, e.g. "LC_MESSAGES".
+ Return the locale category's name, canonicalized into XPG syntax
+ language[_territory][.codeset][@modifier]
+ or NULL if no locale has been specified to setlocale() or by environment
+ variables.
+ The codeset part in the result is not reliable; the locale_charset()
+ should be used for codeset information instead.
+ The result must not be freed; it is statically allocated. */
+extern const char * gl_locale_name_posix (int category, const char *categoryname);
+
+/* Determine the default locale's name, as specified by environment
+ variables.
+ Return the locale category's name, or NULL if no locale has been specified
+ by environment variables.
+ The result must not be freed; it is statically allocated. */
+extern const char * gl_locale_name_environ (int category, const char *categoryname);
+
+/* Determine the default locale's name. This is the current locale's name,
+ if not specified by uselocale() calls, by setlocale() calls, or by
+ environment variables. This locale name is usually determined by systems
+ settings that the user can manipulate through a GUI.
+
+ Quoting POSIX:2001:
+ "All implementations shall define a locale as the default locale,
+ to be invoked when no environment variables are set, or set to the
+ empty string. This default locale can be the C locale or any other
+ implementation-defined locale. Some implementations may provide
+ facilities for local installation administrators to set the default
+ locale, customizing it for each location. IEEE Std 1003.1-2001 does
+ not require such a facility."
+
+ The result must not be freed; it is statically allocated. */
+extern const char * gl_locale_name_default (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_LOCALENAME_H */
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000..becd153
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1 @@
+*.gmo
diff --git a/src/po/CMakeLists.txt b/po/CMakeLists.txt
index df667dd..2bd7461 100644
--- a/src/po/CMakeLists.txt
+++ b/po/CMakeLists.txt
@@ -5,8 +5,8 @@ set(_potFile colobot.pot)
find_program(XGETTEXT_CMD xgettext)
add_custom_command(OUTPUT ${_potFile}
- COMMAND ${XGETTEXT_CMD} ../app/app.cpp --output=${_potFile}
- COMMAND ${XGETTEXT_CMD} ../common/restext.cpp --output=${_potFile} --join-existing --extract-all --no-location
+ COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/app/app.cpp --output=${_potFile}
+ COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/common/restext.cpp --output=${_potFile} --join-existing --extract-all --no-location
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Extract translatable messages to ${_potFile}"
@@ -15,4 +15,6 @@ add_custom_command(OUTPUT ${_potFile}
add_custom_target(update-pot DEPENDS ${_potFile})
file(GLOB _poFiles *.po)
+set(GETTEXT_INSTALL_PREFIX ${COLOBOT_INSTALL_I18N_DIR})
gettext_create_translations(${_potFile} ALL ${_poFiles})
+
diff --git a/src/po/colobot.pot b/po/colobot.pot
index e1f9dc7..8ce386f 100644
--- a/src/po/colobot.pot
+++ b/po/colobot.pot
@@ -1816,3 +1816,4 @@ msgstr ""
msgid "%1"
msgstr ""
+
diff --git a/src/po/de.po b/po/de.po
index 2992cb1..d0943ab 100644
--- a/src/po/de.po
+++ b/po/de.po
@@ -2053,3 +2053,4 @@ msgstr "www.epsitec.com"
#~ msgid "Zoom"
#~ msgstr "Zoom"
+
diff --git a/src/po/fr.po b/po/fr.po
index 662fb93..343458d 100644
--- a/src/po/fr.po
+++ b/po/fr.po
@@ -2055,3 +2055,4 @@ msgstr "www.epsitec.com"
#~ msgid "Zoom"
#~ msgstr "Zoom"
+
diff --git a/src/po/pl.po b/po/pl.po
index 9bab529..4cbfe60 100644
--- a/src/po/pl.po
+++ b/po/pl.po
@@ -2063,3 +2063,4 @@ msgstr "www.epsitec.com"
#~ msgid "Zoom"
#~ msgstr "Powiększenie"
+
diff --git a/src/CBot/.gitignore b/src/CBot/.gitignore
new file mode 100644
index 0000000..4c80252
--- /dev/null
+++ b/src/CBot/.gitignore
@@ -0,0 +1 @@
+libCBot.so
diff --git a/src/CBot/CBot.cpp b/src/CBot/CBot.cpp
index ed6831d..513b803 100644
--- a/src/CBot/CBot.cpp
+++ b/src/CBot/CBot.cpp
@@ -186,7 +186,7 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
{
type = pp->GetType();
// these instructions accept only lable
- if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, ID_REPEAT, 0))
+ if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, 0))
{
pStack->SetError(TX_LABEL, pp->GetStart());
return NULL;
@@ -205,9 +205,6 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
case ID_DO:
return CBotDo::Compile(p, pStack);
- case ID_REPEAT:
- return CBotRepeat::Compile(p, pStack);
-
case ID_BREAK:
case ID_CONTINUE:
return CBotBreak::Compile(p, pStack);
@@ -513,7 +510,7 @@ CBotInstr* CBotLeftExprVar::Compile(CBotToken* &p, CBotCStack* pStack)
return inst;
}
-// creates a variable and assigns the result to the stack
+// creates a variable and assigns the result to the stack
bool CBotLeftExprVar::Execute(CBotStack* &pj)
{
CBotVar* var1;
@@ -1076,7 +1073,7 @@ bool CBotInt::Execute(CBotStack* &pj)
if (pile->IfStep()) return false;
- if ( m_next2b &&
+ if ( m_next2b &&
!m_next2b->Execute(pile)) return false; // other(s) definition(s)
return pj->Return(pile); // forward below
@@ -1561,8 +1558,8 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
int OpType = p->GetType();
if ( pStack->IsOk() &&
- IsOfTypeList(p, ID_ASS, ID_ASSADD, ID_ASSSUB, ID_ASSMUL, ID_ASSDIV, ID_ASSMODULO,
- ID_ASSAND, ID_ASSXOR, ID_ASSOR,
+ IsOfTypeList(p, ID_ASS, ID_ASSADD, ID_ASSSUB, ID_ASSMUL, ID_ASSDIV, ID_ASSMODULO,
+ ID_ASSAND, ID_ASSXOR, ID_ASSOR,
ID_ASSSL , ID_ASSSR, ID_ASSASR, 0 ))
{
if (inst->m_leftop == NULL)
@@ -1658,7 +1655,7 @@ bool CBotExpression::Execute(CBotStack* &pj)
CBotStack* pile = pj->AddStack(this);
// CBotToken* pToken = m_leftop->GetToken();
-
+
CBotVar* pVar = NULL;
CBotStack* pile1 = pile;
@@ -1714,13 +1711,13 @@ bool CBotExpression::Execute(CBotStack* &pj)
pile2->SetVar(result);
break;
case ID_ASSDIV:
- if (IsInit &&
+ if (IsInit &&
result->Div(pile1->GetVar(), pile2->GetVar()))
pile2->SetError(TX_DIVZERO, &m_token);
pile2->SetVar(result);
break;
case ID_ASSMODULO:
- if (IsInit &&
+ if (IsInit &&
result->Modulo(pile1->GetVar(), pile2->GetVar()))
pile2->SetError(TX_DIVZERO, &m_token);
pile2->SetVar(result);
@@ -1779,7 +1776,7 @@ void CBotExpression::RestoreState(CBotStack* &pj, bool bMain)
if ( pile1->GetState()==0)
{
- m_leftop->RestoreStateVar(pile, true);
+ m_leftop->RestoreStateVar(pile, true);
return;
}
@@ -1972,7 +1969,7 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
}
// is it a number or DefineNum?
- if (p->GetType() == TokenTypNum ||
+ if (p->GetType() == TokenTypNum ||
p->GetType() == TokenTypDef )
{
CBotInstr* inst = CBotExprNum::Compile(p, pStk);
@@ -2069,7 +2066,7 @@ bool CBotPostIncExpr::Execute(CBotStack* &pj)
pile1->SetState(1);
pile1->SetCopyVar(var1); // places the result (before incrementation);
- CBotStack* pile3 = pile2->AddStack(this);
+ CBotStack* pile3 = pile2->AddStack(this);
if (pile3->IfStep()) return false;
if (var1->GetInit() == IS_NAN)
@@ -2324,7 +2321,7 @@ bool CBotIndexExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prev
pVar->Maj(pile->GetPUser(), true);
- if ( m_next3 != NULL &&
+ if ( m_next3 != NULL &&
!m_next3->ExecuteVar(pVar, pile, prevToken, bStep, bExtend) ) return false;
// does not release the stack
@@ -2343,7 +2340,7 @@ void CBotIndexExpr::RestoreStateVar(CBotStack* &pile, bool bMain)
return;
}
- if (m_next3)
+ if (m_next3)
m_next3->RestoreStateVar(pile, bMain);
}
@@ -2431,7 +2428,7 @@ bool CBotFieldExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prev
// request the update of the element, if applicable
pVar->Maj(pile->GetPUser(), true);
- if ( m_next3 != NULL &&
+ if ( m_next3 != NULL &&
!m_next3->ExecuteVar(pVar, pile, &m_token, bStep, bExtend) ) return false;
// does not release the stack
@@ -2445,7 +2442,7 @@ void CBotFieldExpr::RestoreStateVar(CBotStack* &pj, bool bMain)
pj = pj->RestoreStack(this);
if (pj == NULL) return;
- if (m_next3 != NULL)
+ if (m_next3 != NULL)
m_next3->RestoreStateVar(pj, bMain);
}
@@ -2659,7 +2656,7 @@ bool CBotLeftExpr::ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevT
if (bStep && m_next3 == NULL && pile->IfStep()) return false;
- if ( m_next3 != NULL &&
+ if ( m_next3 != NULL &&
!m_next3->ExecuteVar(pVar, pile, &m_token, bStep, true) ) return false;
return true;
@@ -2670,7 +2667,7 @@ void CBotLeftExpr::RestoreStateVar(CBotStack* &pile, bool bMain)
pile = pile->RestoreStack(this);
if (pile == NULL) return;
- if (m_next3 != NULL)
+ if (m_next3 != NULL)
m_next3->RestoreStateVar(pile, bMain);
}
@@ -3098,7 +3095,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken* &p, CBotCStack* pStack, int privat)
{
if (var->GetType() == CBotTypArrayPointer)
{
- if (IsOfType( p, ID_OPBRK )) // check if there is an aindex
+ if (IsOfType( p, ID_OPBRK )) // check if there is an aindex
{
CBotIndexExpr* i = new CBotIndexExpr();
i->m_expr = CBotExpression::Compile(p, pStk); // compile the formula
@@ -3415,7 +3412,7 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
{
CBotClass* pClass = var->GetClass(); // pointer to the class
inst->m_ClassName = pClass->GetName(); // name of the class
- CBotTypResult r = pClass->CompileMethode(inst->m_NomMethod, var, ppVars,
+ CBotTypResult r = pClass->CompileMethode(inst->m_NomMethod, var, ppVars,
pStack, inst->m_MethodeIdent);
delete pStack->TokenStack(); // release parameters on the stack
inst->m_typRes = r;
@@ -3507,8 +3504,8 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
}
CBotVar* pRes = pResult;
- if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
- pThis, ppVars,
+ if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
+ pThis, ppVars,
pResult, pile2, GetToken())) return false;
if (pRes != pResult) delete pRes;
@@ -3558,7 +3555,7 @@ void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
// CBotVar* pRes = pResult;
- pClass->RestoreMethode(m_MethodeIdent, m_NomMethod,
+ pClass->RestoreMethode(m_MethodeIdent, m_NomMethod,
pThis, ppVars, pile2);
}
@@ -3612,8 +3609,8 @@ bool CBotInstrMethode::Execute(CBotStack* &pj)
}
CBotVar* pRes = pResult;
- if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
- pThis, ppVars,
+ if ( !pClass->ExecuteMethode(m_MethodeIdent, m_NomMethod,
+ pThis, ppVars,
pResult, pile2, GetToken())) return false; // interupted
// set the new value of this in place of the old variable
@@ -3628,7 +3625,7 @@ bool CBotInstrMethode::Execute(CBotStack* &pj)
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// compile an instruction "new"
+// compile an instruction "new"
CBotNew::CBotNew()
{
@@ -3773,8 +3770,8 @@ bool CBotNew::Execute(CBotStack* &pj)
// create a variable for the result
CBotVar* pResult = NULL; // constructos still void
- if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
- pThis, ppVars,
+ if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
+ pThis, ppVars,
pResult, pile2, GetToken())) return false; // interrupt
pThis->ConstructorSet(); // indicates that the constructor has been called
@@ -3860,13 +3857,13 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
if (max >= CBotTypBoolean)
{
- if ( (op == ID_EQ || op == ID_NE) &&
+ if ( (op == ID_EQ || op == ID_NE) &&
(t1 == CBotTypPointer && t2 == CBotTypNullPointer)) return true;
- if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
+ if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
(t2 == CBotTypPointer && t1 == CBotTypNullPointer)) return true;
- if ( (op == ID_EQ || op == ID_NE) &&
+ if ( (op == ID_EQ || op == ID_NE) &&
(t1 == CBotTypArrayPointer && t2 == CBotTypNullPointer)) return true;
- if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
+ if ( (op == ID_EQ || op == ID_NE || op == ID_ASS) &&
(t2 == CBotTypArrayPointer && t1 == CBotTypNullPointer)) return true;
if (t2 != t1) return false;
if (t1 == CBotTypArrayPointer) return type1.Compare(type2);
diff --git a/src/CBot/CBot.h b/src/CBot/CBot.h
index 8886308..8313252 100644
--- a/src/CBot/CBot.h
+++ b/src/CBot/CBot.h
@@ -57,7 +57,6 @@ class CBotExprVar; // a variable name as
class CBotWhile; // while (...) {...};
class CBotIf; // if (...) {...} else {...}
class CBotDefParam; // paramerer list of a function
-class CBotRepeat; // repeat (nb) {...}
@@ -70,7 +69,7 @@ class CBotRepeat; // repeat (nb) {...}
// to use for routine CBotProgram :: Execute (CBotStack)
-/**\class CBotStack
+/**\class CBotStack
* \brief Management of the execution stack.
* \brief Actually the only thing it can do is to create an instance of a stack
* \brief to use for routine CBotProgram :: Execute(CBotStack)*/
@@ -211,14 +210,14 @@ public:
// in case of eventual break
bool IfContinue(int state, const char* name);
// or "continue"
-
+
bool IsOk();
bool SetState(int n, int lim = -10); // select a state
int GetState(); // in what state am I?
bool IncState(int lim = -10); // passes to the next state
bool IfStep(); // do step by step
- bool Execute();
+ bool Execute();
void SetVar( CBotVar* var );
void SetCopyVar( CBotVar* var );
@@ -260,7 +259,7 @@ private:
CBotStack* m_prev;
friend class CBotInstArray;
-#ifdef _DEBUG
+#ifdef _DEBUG
int m_index;
#endif
int m_state;
@@ -361,7 +360,7 @@ public:
CBotCStack* TokenStack(CBotToken* pToken = NULL, bool bBlock = false);
CBotInstr* Return(CBotInstr* p, CBotCStack* pParent); // transmits the result upper
CBotFunction* ReturnFunc(CBotFunction* p, CBotCStack* pParent); // transmits the result upper
-
+
void SetVar( CBotVar* var );
void SetCopyVar( CBotVar* var );
CBotVar* GetVar();
@@ -481,7 +480,7 @@ class CBotWhile : public CBotInstr
private:
CBotInstr* m_Condition; // condition
CBotInstr* m_Block; // instructions
- CBotString m_label; // a label if there is
+ CBotString m_label; // a label if there is
public:
CBotWhile();
@@ -492,38 +491,12 @@ public:
void RestoreState(CBotStack* &pj, bool bMain);
};
-class CBotRepeat : public CBotInstr
-{
-private:
- /// Number of iterations
- CBotInstr* m_NbIter;
-
- /// Instructions
- CBotInstr* m_Block;
-
- /// Label
- CBotString m_label; // a label if there is
-
-public:
- CBotRepeat();
- ~CBotRepeat();
-
- /// Static method used for compilation
- static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
-
- /// Execute
- bool Execute(CBotStack* &pj);
-
- /// Restore state
- void RestoreState(CBotStack* &pj, bool bMain);
-};
-
class CBotDo : public CBotInstr
{
private:
CBotInstr* m_Block; // instruction
CBotInstr* m_Condition; // conditions
- CBotString m_label; // a label if there is
+ CBotString m_label; // a label if there is
public:
CBotDo();
@@ -541,7 +514,7 @@ private:
CBotInstr* m_Test; // test condition
CBotInstr* m_Incr; // instruction for increment
CBotInstr* m_Block; // instructions
- CBotString m_label; // a label if there is
+ CBotString m_label; // a label if there is
public:
CBotFor();
@@ -555,7 +528,7 @@ public:
class CBotBreak : public CBotInstr
{
private:
- CBotString m_label; // a label if there is
+ CBotString m_label; // a label if there is
public:
CBotBreak();
@@ -569,7 +542,7 @@ public:
class CBotReturn : public CBotInstr
{
private:
- CBotInstr* m_Instr; // paramter of return
+ CBotInstr* m_Instr; // paramter of return
public:
CBotReturn();
@@ -584,7 +557,7 @@ public:
class CBotSwitch : public CBotInstr
{
private:
- CBotInstr* m_Value; // value to seek
+ CBotInstr* m_Value; // value to seek
CBotInstr* m_Block; // instructions
public:
@@ -731,7 +704,7 @@ public:
};
-// definition of a assignment list for a table
+// definition of a assignment list for a table
// int [ ] a [ ] = ( ( 1, 2, 3 ) , ( 3, 2, 1 ) ) ;
class CBotListArray : public CBotInstr
@@ -1442,12 +1415,12 @@ public:
void IncrementUse(); // a reference to incrementation
void DecrementUse(); // a reference to decrementation
- CBotVarClass*
+ CBotVarClass*
GetPointer();
void SetItemList(CBotVar* pVar);
void SetIdent(long n);
-
+
static CBotVarClass* Find(long id);
@@ -1516,7 +1489,7 @@ public:
void SetPointer(CBotVar* p);
CBotVarClass*
GetPointer();
-
+
void Copy(CBotVar* pSrc, bool bName=true);
CBotVar* GetItem(int n, bool bGrow=false); // makes an element according to its numeric index
// enlarged the table if necessary if bExtend
@@ -1571,14 +1544,14 @@ private:
CBotCall* m_next;
public:
- CBotCall(const char* name,
- bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+ CBotCall(const char* name,
+ bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
~CBotCall();
static
- bool AddFunction(const char* name,
- bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+ bool AddFunction(const char* name,
+ bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
static
@@ -1599,7 +1572,7 @@ public:
CBotString GetName();
CBotCall* Next();
-
+
static void SetPUser(void* pUser);
static void Free();
};
@@ -1618,13 +1591,13 @@ private:
long m_nFuncIdent;
public:
- CBotCallMethode(const char* name,
- bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+ CBotCallMethode(const char* name,
+ bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar));
~CBotCallMethode();
CBotTypResult
- CompileCall(const char* name, CBotVar* pThis,
+ CompileCall(const char* name, CBotVar* pThis,
CBotVar** ppVars, CBotCStack* pStack,
long& nIdent);
@@ -1633,7 +1606,7 @@ public:
CBotString GetName();
CBotCallMethode* Next();
void AddNext(CBotCallMethode* p);
-
+
};
// a list of parameters
@@ -1730,4 +1703,3 @@ public:
bool GetPosition(int& start, int& stop, CBotGet modestart, CBotGet modestop);
};
-
diff --git a/src/CBot/CBotAddExpr.cpp b/src/CBot/CBotAddExpr.cpp
index 231f008..ec007ae 100644
--- a/src/CBot/CBotAddExpr.cpp
+++ b/src/CBot/CBotAddExpr.cpp
@@ -84,7 +84,7 @@ CBotInstr* CBotAddExpr::Compile(CBotToken* &p, CBotStack* pStack)
return pStack->Return(NULL, pStk);
}
- // if we are not dealing with an operation + or -
+ // if we are not dealing with an operation + or -
// goes to that requested, the operand (left) found
// place the object "addition"
return pStack->Return(left, pStk);
@@ -141,4 +141,3 @@ bool CBotAddExpr::Execute(CBotStack* &pStack)
return pStack->Return(pStk1); // transmits the result
}
-
diff --git a/src/CBot/CBotClass.cpp b/src/CBot/CBotClass.cpp
index a1c3fd4..12765ba 100644
--- a/src/CBot/CBotClass.cpp
+++ b/src/CBot/CBotClass.cpp
@@ -54,7 +54,7 @@ CBotClass::CBotClass(const char* name, CBotClass* pPapa, bool bIntrinsic)
CBotClass::~CBotClass()
{
- // removes the list of class
+ // removes the list of class
if ( m_ExPrev ) m_ExPrev->m_ExNext = m_ExNext;
else m_ExClass = m_ExNext;
@@ -106,7 +106,7 @@ bool CBotClass::Lock(CBotProgram* p)
m_ProgInLock[0] = p;
return true;
}
- if ( p == m_ProgInLock[0] )
+ if ( p == m_ProgInLock[0] )
{
m_cptOne++;
m_cptLock--; // has already been counted
@@ -156,14 +156,14 @@ void CBotClass::FreeLock(CBotProgram* p)
while ( pClass != NULL )
{
- if ( p == pClass->m_ProgInLock[0] )
+ if ( p == pClass->m_ProgInLock[0] )
{
pClass->m_cptLock -= pClass->m_cptOne;
pClass->m_cptOne = 0;
}
for ( int j = 1; j < 5 ; j++ )
- if ( p == pClass->m_ProgInLock[j] )
+ if ( p == pClass->m_ProgInLock[j] )
pClass->m_cptLock--;
pClass = pClass->m_ExNext;
@@ -291,8 +291,8 @@ CBotClass* CBotClass::Find(const char* name)
return NULL;
}
-bool CBotClass::AddFunction(const char* name,
- bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+bool CBotClass::AddFunction(const char* name,
+ bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar))
{
// stores pointers to the two functions
@@ -313,7 +313,7 @@ bool CBotClass::AddFunction(const char* name,
}
p = new CBotCallMethode(name, rExec, rCompile);
-
+
if (m_pCalls == NULL) m_pCalls = p;
else m_pCalls->AddNext(p); // added to the list
@@ -329,8 +329,8 @@ bool CBotClass::AddUpdateFunc( void rMaj ( CBotVar* pThis, void* pUser ) )
// compiles a method associated with an instance of class
// the method can be declared by the user or AddFunction
-CBotTypResult CBotClass::CompileMethode(const char* name,
- CBotVar* pThis, CBotVar** ppParams,
+CBotTypResult CBotClass::CompileMethode(const char* name,
+ CBotVar* pThis, CBotVar** ppParams,
CBotCStack* pStack, long& nIdent)
{
nIdent = 0; // forget the previous one if necessary
@@ -350,8 +350,8 @@ CBotTypResult CBotClass::CompileMethode(const char* name,
// executes a method
-bool CBotClass::ExecuteMethode(long& nIdent, const char* name,
- CBotVar* pThis, CBotVar** ppParams,
+bool CBotClass::ExecuteMethode(long& nIdent, const char* name,
+ CBotVar* pThis, CBotVar** ppParams,
CBotVar* &pResult, CBotStack* &pStack,
CBotToken* pToken)
{
@@ -437,7 +437,7 @@ bool CBotClass::RestoreStaticState(FILE* pf)
if (!ReadString( pf, VarName )) return false;
if ( pClass != NULL ) pVar = pClass->GetItem(VarName);
- if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable
+ if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable
if ( pVar != NULL ) pVar->Copy(pv);
delete pv;
@@ -514,7 +514,7 @@ CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass*
delete inst; // is not type CBotInt
p = vartoken; // returns to the variable name
- // compiles declaration an array
+ // compiles declaration an array
inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type ));
@@ -595,7 +595,7 @@ CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass*
goto error;
}
// if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer());
- if ( !bIntrinsic )
+ if ( !bIntrinsic )
{
// does not use the result on the stack, to impose the class
CBotVar* pvar = CBotVar::Create("", pClass);
@@ -608,7 +608,7 @@ CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass*
{
// creates the object on the "job" (\TODO "tas")
// with a pointer to the object
- if ( !bIntrinsic )
+ if ( !bIntrinsic )
{
CBotVar* pvar = CBotVar::Create("", pClass);
var->SetPointer( pvar ); // variable already declared instance pointer
@@ -617,14 +617,14 @@ CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass*
var->SetInit(2); // marks the pointer as init
}
suite:
- if (IsOfType(p, ID_COMMA)) // several chained definitions
+ if (IsOfType(p, ID_COMMA)) // several chained definitions
{
if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compiles the following
{
return pStack->Return(inst, pStk);
}
}
-
+
if (IsOfType(p, ID_SEP)) // complete instruction
{
return pStack->Return(inst, pStk);
@@ -684,7 +684,7 @@ bool CBotClassInst::Execute(CBotStack* &pj)
{
// evaluates the expression for the assignment
if (!m_expr->Execute(pile)) return false;
-
+
if ( bIntrincic )
{
CBotVar* pv = pile->GetVar();
@@ -750,8 +750,8 @@ bool CBotClassInst::Execute(CBotStack* &pj)
// creates a variable for the result
CBotVar* pResult = NULL; // constructor still void
- if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
- pThis, ppVars,
+ if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
+ pThis, ppVars,
pResult, pile2, GetToken())) return false; // interrupt
pThis->SetInit(true);
diff --git a/src/CBot/CBotCompExpr.cpp b/src/CBot/CBotCompExpr.cpp
index 2daf53f..c9a977c 100644
--- a/src/CBot/CBotCompExpr.cpp
+++ b/src/CBot/CBotCompExpr.cpp
@@ -83,7 +83,7 @@ CBotInstr* CBotCompExpr::Compile(CBotToken* &p, CBotCStack* pStack)
}
-// perform the operation
+// perform the operation
bool CBotCompExpr::Execute(CBotStack* &pStack)
{
diff --git a/src/CBot/CBotDll.h b/src/CBot/CBotDll.h
index b401528..8858559 100644
--- a/src/CBot/CBotDll.h
+++ b/src/CBot/CBotDll.h
@@ -93,22 +93,22 @@ public:
CBotTypResult(int type);
// for simple types (CBotTypInt à CBotTypString)
-
+
CBotTypResult(int type, const char* name);
// for pointer types and intrinsic classes
-
+
CBotTypResult(int type, CBotClass* pClass);
// for the instance of a class
-
+
CBotTypResult(int type, CBotTypResult elem);
// for arrays of variables
-
+
CBotTypResult(const CBotTypResult& typ);
// for assignments
-
+
CBotTypResult();
// for default
-
+
~CBotTypResult();
int GetType(int mode = 0) const;
@@ -147,7 +147,7 @@ private:
CBotClass* m_pClass; // for the derivatives of class
int m_limite; // limits of tables
friend class CBotVarClass;
- friend class CBotVarPointer;
+ friend class CBotVarPointer;
};
/*
@@ -246,7 +246,7 @@ private:
////////////////////////////////////////////////////////////////////////
-//
+//
// as part of MFC CString not used here.
//
// ( all functions are not implemented yet )
@@ -451,12 +451,12 @@ public:
static
void SetTimer(int n);
- // defines the number of steps (parts of instructions) to done
+ // defines the number of steps (parts of instructions) to done
// in Run() before rendering hand "false" \TODO avant de rendre la main "false"
static
- bool AddFunction(const char* name,
- bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+ bool AddFunction(const char* name,
+ bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser));
// call this to add externally (**)
// a new function used by the program CBoT
@@ -472,8 +472,8 @@ public:
// restores the state of execution from file
// the compiled program must obviously be the same
- bool GetPosition(const char* name, int& start, int& stop,
- CBotGet modestart = GetPosExtern,
+ bool GetPosition(const char* name, int& start, int& stop,
+ CBotGet modestart = GetPosExtern,
CBotGet modestop = GetPosBloc);
// gives the position of a routine in the original text
// the user can select the item to find from the beginning to the end
@@ -513,7 +513,7 @@ int cMean(CBotVar* &pVar, CBotString& ClassName)
while ( pVar != NULL )
{
- if ( pVar->GetType() > CBotTypDouble ) return 6002; // this is not a number
+ if ( pVar->GetType() > CBotTypDouble ) return 6002; // this is not a number
pVar = pVar -> GetNext();
}
@@ -623,7 +623,7 @@ virtual ~CBotVar( ); // destructor
void SetName(const char* name); // changes the name of the variable
int GetType(int mode = 0); // returns the base type (int) of the variable
- // TODO check it
+ // TODO check it
////////////////////////////////////////////////////////////////////////////////////////
CBotTypResult GetTypResult(int mode = 0); // returns the complete type of the variable
@@ -654,7 +654,7 @@ virtual ~CBotVar( ); // destructor
CBotVar* GetItemRef(int nIdent); // idem à partir du n° ref
// TODO ditto from ref no.
virtual
- CBotVar* GetItem(int row, bool bGrow = false);
+ CBotVar* GetItem(int row, bool bGrow = false);
virtual
CBotVar* GetItemList(); // lists the elements
@@ -802,8 +802,8 @@ public:
~CBotClass( ); // destructor
- bool AddFunction(const char* name,
- bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+ bool AddFunction(const char* name,
+ bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar));
// this call allows to add as external (**)
// new method used by the objects of this class
@@ -841,7 +841,7 @@ public:
CBotVar* GetItem(const char* name); // one of the variables according to its name
CBotVar* GetItemRef(int nIdent);
- CBotTypResult CompileMethode(const char* name, CBotVar* pThis, CBotVar** ppParams,
+ CBotTypResult CompileMethode(const char* name, CBotVar* pThis, CBotVar** ppParams,
CBotCStack* pStack, long& nIdent);
bool ExecuteMethode(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppParams, CBotVar* &pResult, CBotStack* &pStack, CBotToken* pToken);
@@ -854,7 +854,7 @@ public:
CBotClass* Compile1(CBotToken* &p, CBotCStack* pStack);
bool CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond);
-
+
bool IsIntrinsic();
void Purge();
static
@@ -917,7 +917,7 @@ private:
int m_start; // position in the original text (program)
int m_end; // the same for the end of the token
-
+
/**
* \brief Check whether given parameter is a keyword
*/
@@ -979,11 +979,11 @@ public:
CBotToken* GetPrev();
/**
- * \brief transforms the entire program
+ * \brief transforms the entire program
*/
static
CBotToken* CompileTokens(const char* p, int& error);
-
+
/**
* \brief releases the list
*/
diff --git a/src/CBot/CBotFunction.cpp b/src/CBot/CBotFunction.cpp
index 28db24e..862554e 100644
--- a/src/CBot/CBotFunction.cpp
+++ b/src/CBot/CBotFunction.cpp
@@ -28,7 +28,7 @@ CBotFunction::CBotFunction()
m_Param = NULL; // empty parameter list
m_Block = NULL; // the instruction block
m_next = NULL; // functions can be chained
- m_bPublic = false; // function not public
+ m_bPublic = false; // function not public
m_bExtern = false; // function not extern
m_nextpublic = NULL;
m_prevpublic = NULL;
@@ -159,9 +159,9 @@ CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile)
if ( pClass != NULL)
{
p = p->GetNext();
- return ArrayType(p, pile,
- pClass->IsIntrinsic() ?
- CBotTypResult( CBotTypIntrinsic, pClass ) :
+ return ArrayType(p, pile,
+ pClass->IsIntrinsic() ?
+ CBotTypResult( CBotTypIntrinsic, pClass ) :
CBotTypResult( CBotTypPointer, pClass ) );
}
}
@@ -261,7 +261,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
}
}
- // and compiles the following instruction block
+ // and compiles the following instruction block
func->m_openblk = p;
func->m_Block = CBotBlock::Compile(p, pStk, false);
func->m_closeblk = p->GetPrev();
@@ -288,7 +288,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
{
CBotFunction* func = new CBotFunction();
func->m_nFuncIdent = CBotVar::NextUniqNum();
-
+
CBotCStack* pStk = pStack->TokenStack(p, true);
while (true)
@@ -334,7 +334,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
func->m_Param = CBotDefParam::Compile( p, pStk );
if (pStk->IsOk())
{
- // looks if the function exists elsewhere
+ // looks if the function exists elsewhere
if (( pClass != NULL || !pStack->CheckCall(pp, func->m_Param)) &&
( pClass == NULL || !pClass->CheckCall(pp, func->m_Param)) )
{
@@ -350,7 +350,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
if (type == ID_CLBLK) level--;
}
while (level > 0 && p != NULL);
-
+
return pStack->ReturnFunc(func, pStk);
}
pStk->SetError(TX_OPENBLK, p);
@@ -528,7 +528,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const char* name, CB
pv = pv->GetNext();
pw = ppVars[i++];
}
- if ( pw != NULL )
+ if ( pw != NULL )
{
if ( pFunc != NULL ) continue;
if ( TypeOrError.Eq(TX_LOWPARAM) ) TypeOrError.SetType(TX_NUMPARAM);
@@ -583,7 +583,7 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const char* name, CB
pv = pv->GetNext();
pw = ppVars[i++];
}
- if ( pw != NULL )
+ if ( pw != NULL )
{
if ( pFunc != NULL ) continue;
if ( TypeOrError.Eq(TX_LOWPARAM) ) TypeOrError.SetType(TX_NUMPARAM);
@@ -630,7 +630,7 @@ int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar** ppVars, CBotS
{
CBotTypResult type;
CBotFunction* pt = NULL;
-
+
pt = FindLocalOrPublic(nIdent, name, ppVars, type);
if ( pt != NULL )
@@ -754,7 +754,7 @@ void CBotFunction::RestoreCall(long& nIdent, const char* name, CBotVar** ppVars,
-// makes call of a method
+// makes call of a method
// note: this is already on the stack, the pointer pThis is just to simplify
int CBotFunction::DoCall(long& nIdent, const char* name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
@@ -951,7 +951,7 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
if (IsOfType(p, ID_OPENPAR))
{
CBotDefParam* list = NULL;
-
+
while (!IsOfType(p, ID_CLOSEPAR))
{
CBotDefParam* param = new CBotDefParam();
@@ -1090,7 +1090,7 @@ CBotDefParam* CBotDefParam::GetNext()
CBotString CBotDefParam::GetParamString()
{
CBotString param;
-
+
param = m_typename;
param += ' ';
@@ -1136,7 +1136,7 @@ CBotInstr* CBotReturn::Compile(CBotToken* &p, CBotCStack* pStack)
if ( pStack->IsOk() )
{
CBotTypResult retType = pStack->GetTypResult(2);
- if (TypeCompatible(retType, type, ID_ASS))
+ if (TypeCompatible(retType, type, ID_ASS))
{
if ( IsOfType( p, ID_SEP ) )
return inst;
@@ -1202,7 +1202,7 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
int i = 0;
- CBotToken* pp = p;
+ CBotToken* pp = p;
p = p->GetNext();
pStack->SetStartError(p->GetStart());
@@ -1367,7 +1367,7 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
pStack->SetError(TX_NOPUBLIC, p);
return NULL;
}
-
+
if ( !IsOfType(p, ID_CLASS) ) return NULL;
CBotString name = p->GetString();
@@ -1443,7 +1443,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
return false;
}
- while (pStack->IsOk())
+ while (pStack->IsOk())
{
CBotToken* pp = p;
IsOfType(p, ID_NOT); // skips ~ eventual (destructor)
@@ -1484,7 +1484,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
if ( !bSecond )
{
p = pBase;
- CBotFunction* f =
+ CBotFunction* f =
CBotFunction::Compile1(p, pStack, this);
if ( f == NULL ) return false;
@@ -1497,7 +1497,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
// return a method precompiled in pass 1
CBotFunction* pf = m_pMethod;
CBotFunction* prev = NULL;
- while ( pf != NULL )
+ while ( pf != NULL )
{
if (pf->GetName() == pp->GetString()) break;
prev = pf;
@@ -1541,7 +1541,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
// compiles a method
p = pBase;
- CBotFunction* f =
+ CBotFunction* f =
CBotFunction::Compile(p, pile, NULL/*, false*/);
if ( f != NULL )
@@ -1646,3 +1646,4 @@ CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
pStack->SetError(TX_ENDOF, p);
return NULL;
}
+
diff --git a/src/CBot/CBotIf.cpp b/src/CBot/CBotIf.cpp
index a5d2693..bc58af1 100644
--- a/src/CBot/CBotIf.cpp
+++ b/src/CBot/CBotIf.cpp
@@ -109,7 +109,7 @@ bool CBotIf :: Execute(CBotStack* &pj)
// passes into the second state
if (!pile->SetState(1)) return false; // ready for further
}
-
+
// second state, evaluates the associated instructions
// the result of the condition is on the stack
@@ -143,7 +143,7 @@ void CBotIf :: RestoreState(CBotStack* &pj, bool bMain)
m_Condition->RestoreState(pile, bMain); // interrupted here!
return;
}
-
+
// second state, evaluates the associated instructions
// the result of the condition is on the stack
diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp
index f4987a7..1944f92 100644
--- a/src/CBot/CBotProgram.cpp
+++ b/src/CBot/CBotProgram.cpp
@@ -97,7 +97,7 @@ bool CBotProgram::Compile( const char* program, CBotStringArray& ListFonctions,
{
if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking
- if ( p->GetType() == ID_CLASS ||
+ if ( p->GetType() == ID_CLASS ||
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
{
CBotClass* nxt = CBotClass::Compile1(p, pStack);
@@ -113,7 +113,7 @@ bool CBotProgram::Compile( const char* program, CBotStringArray& ListFonctions,
}
if ( !pStack->IsOk() )
{
- m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
+ m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
delete m_Prog;
m_Prog = NULL;
delete pBaseToken;
@@ -129,7 +129,7 @@ bool CBotProgram::Compile( const char* program, CBotStringArray& ListFonctions,
{
if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking
- if ( p->GetType() == ID_CLASS ||
+ if ( p->GetType() == ID_CLASS ||
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
{
m_bCompileClass = true;
@@ -150,7 +150,7 @@ bool CBotProgram::Compile( const char* program, CBotStringArray& ListFonctions,
if ( !pStack->IsOk() )
{
- m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
+ m_ErrorCode = pStack->GetError(m_ErrorStart, m_ErrorEnd);
delete m_Prog;
m_Prog = NULL;
}
@@ -228,7 +228,7 @@ bool CBotProgram::Run(void* pUser, int timer)
#if STACKRUN
// resumes execution on the top of the stack
ok = m_pStack->Execute();
- if ( ok )
+ if ( ok )
{
#ifdef _DEBUG
CBotVar* ppVar[3];
@@ -354,8 +354,8 @@ CBotFunction* CBotProgram::GetFunctions()
return m_Prog;
}
-bool CBotProgram::AddFunction(const char* name,
- bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+bool CBotProgram::AddFunction(const char* name,
+ bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
{
// stores pointers to the two functions
@@ -369,7 +369,7 @@ bool WriteWord(FILE* pf, unsigned short w)
lg = fwrite(&w, sizeof( unsigned short ), 1, pf );
- return (lg == 1);
+ return (lg == 1);
}
bool ReadWord(FILE* pf, unsigned short& w)
@@ -387,7 +387,7 @@ bool WriteFloat(FILE* pf, float w)
lg = fwrite(&w, sizeof( float ), 1, pf );
- return (lg == 1);
+ return (lg == 1);
}
bool ReadFloat(FILE* pf, float& w)
@@ -405,7 +405,7 @@ bool WriteLong(FILE* pf, long w)
lg = fwrite(&w, sizeof( long ), 1, pf );
- return (lg == 1);
+ return (lg == 1);
}
bool ReadLong(FILE* pf, long& w)
@@ -425,7 +425,7 @@ bool WriteString(FILE* pf, CBotString s)
if (!WriteWord(pf, lg1)) return false;
lg2 = fwrite(s, 1, lg1, pf );
- return (lg1 == lg2);
+ return (lg1 == lg2);
}
bool ReadString(FILE* pf, CBotString& s)
@@ -510,7 +510,7 @@ bool CBotProgram::SaveState(FILE* pf)
if (!WriteString( pf, m_pRun->GetName() )) return false;
if (!m_pStack->SaveState(pf)) return false;
}
- else
+ else
{
if (!WriteWord( pf, 0)) return false;
}
@@ -560,9 +560,9 @@ int CBotProgram::GetVersion()
//////////////////////////////////////////////////////////////////////////////////////////////////////
CBotCall* CBotCall::m_ListCalls = NULL;
-
-CBotCall::CBotCall(const char* name,
- bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+
+CBotCall::CBotCall(const char* name,
+ bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
{
m_name = name;
@@ -583,8 +583,8 @@ void CBotCall::Free()
delete CBotCall::m_ListCalls;
}
-bool CBotCall::AddFunction(const char* name,
- bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
+bool CBotCall::AddFunction(const char* name,
+ bool rExec (CBotVar* pVar, CBotVar* pResult, int& Exception, void* pUser),
CBotTypResult rCompile (CBotVar* &pVar, void* pUser))
{
CBotCall* p = m_ListCalls;
@@ -608,7 +608,7 @@ bool CBotCall::AddFunction(const char* name,
}
pp = new CBotCall(name, rExec, rCompile);
-
+
if (p) p->m_next = pp;
else m_ListCalls = pp;
@@ -658,7 +658,7 @@ CBotTypResult CBotCall::CompileCall(CBotToken* &p, CBotVar** ppVar, CBotCStack*
CBotVar* pVar2 = pVar;
CBotTypResult r = pt->m_rComp(pVar2, m_pUser);
int ret = r.GetType();
-
+
// if a class is returned, it is actually a pointer
if ( ret == CBotTypClass ) r.SetType( ret = CBotTypPointer );
@@ -859,8 +859,8 @@ bool CBotCall::Run(CBotStack* pStack)
///////////////////////////////////////////////////////////////////////////////////////
-CBotCallMethode::CBotCallMethode(const char* name,
- bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
+CBotCallMethode::CBotCallMethode(const char* name,
+ bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception),
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar))
{
m_name = name;
@@ -879,7 +879,7 @@ CBotCallMethode::~CBotCallMethode()
// is acceptable by a call procedure name
// and given parameters
-CBotTypResult CBotCallMethode::CompileCall(const char* name, CBotVar* pThis,
+CBotTypResult CBotCallMethode::CompileCall(const char* name, CBotVar* pThis,
CBotVar** ppVar, CBotCStack* pStack,
long& nIdent)
{
@@ -1008,7 +1008,7 @@ bool rSizeOf( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
while ( pVar != NULL )
{
- i++;
+ i++;
pVar = pVar->GetNext();
}
@@ -1107,7 +1107,7 @@ void CBotProgram::Init()
void CBotProgram::Free()
{
- CBotToken::Free() ;
+ CBotToken::Free() ;
CBotCall ::Free() ;
CBotClass::Free() ;
}
diff --git a/src/CBot/CBotStack.cpp b/src/CBot/CBotStack.cpp
index 67f2000..086442d 100644
--- a/src/CBot/CBotStack.cpp
+++ b/src/CBot/CBotStack.cpp
@@ -63,7 +63,7 @@ CBotStack* CBotStack::FirstStack()
pp->m_bOver = true;
pp ++;
}
-#ifdef _DEBUG
+#ifdef _DEBUG
int n = 1;
pp = p;
for ( i = 0 ; i< MAXSTACK+10 ; i++ )
@@ -120,7 +120,7 @@ void CBotStack::Delete()
m_index = n;
#endif
- if ( p == NULL )
+ if ( p == NULL )
free( this );
}
@@ -128,7 +128,7 @@ void CBotStack::Delete()
// routine improved
CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
{
- if (m_next != NULL)
+ if (m_next != NULL)
{
return m_next; // included in an existing stack
}
@@ -160,7 +160,7 @@ CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
{
- if (m_next != NULL)
+ if (m_next != NULL)
{
if ( m_next == EOX )
{
@@ -177,7 +177,7 @@ CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
CBotStack* CBotStack::AddStack2(bool bBlock)
{
- if (m_next2 != NULL)
+ if (m_next2 != NULL)
{
m_next2->m_prog = m_prog; // special avoids RestoreStack2
return m_next2; // included in an existing stack
@@ -251,8 +251,8 @@ CBotStack::CBotStack(CBotStack* ppapa)
if (ppapa == NULL) m_timer = m_initimer; // sets the timer at the beginning
m_listVar = NULL;
- m_bDontDelete = false;
-
+ m_bDontDelete = false;
+
m_var = NULL;
m_prog = NULL;
m_instr = NULL;
@@ -275,7 +275,7 @@ CBotStack::~CBotStack()
// \TODO routine has/to optimize
CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
{
- if (m_next != NULL)
+ if (m_next != NULL)
{
return m_next; // included in an existing stack
}
@@ -290,7 +290,7 @@ CBotStack* CBotStack::AddStack(CBotInstr* instr, bool bBlock)
CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
{
- if (m_next != NULL)
+ if (m_next != NULL)
{
if ( m_next == EOX )
{
@@ -311,7 +311,7 @@ CBotStack* CBotStack::AddStackEOX(CBotCall* instr, bool bBlock)
CBotStack* CBotStack::AddStack2(bool bBlock)
{
- if (m_next2 != NULL)
+ if (m_next2 != NULL)
{
m_next2->m_prog = m_prog; // special avoids RestoreStack2
return m_next2; // included in an existing stack
@@ -362,7 +362,7 @@ void CBotStack::Reset(void* pUser)
CBotStack* CBotStack::RestoreStack(CBotInstr* instr)
{
- if (m_next != NULL)
+ if (m_next != NULL)
{
m_next->m_instr = instr; // reset (if recovery after )
m_next->m_prog = m_prog;
@@ -480,7 +480,7 @@ CBotVar* CBotStack::FindVar(CBotToken* &pToken, bool bUpdate, bool bModif)
{
if (pp->GetName() == name)
{
- if ( bUpdate )
+ if ( bUpdate )
pp->Maj(m_pUser, false);
return pp;
@@ -521,7 +521,7 @@ CBotVar* CBotStack::FindVar(long ident, bool bUpdate, bool bModif)
{
if (pp->GetUniqNum() == ident)
{
- if ( bUpdate )
+ if ( bUpdate )
pp->Maj(m_pUser, false);
return pp;
@@ -552,7 +552,7 @@ CBotVar* CBotStack::CopyVar(CBotToken& Token, bool bUpdate)
return pCopy;
}
-
+
bool CBotStack::SetState(int n, int limite)
{
m_state = n;
@@ -609,7 +609,7 @@ bool CBotStack::Execute()
while (p != NULL)
{
if ( p->m_next2 != NULL ) break;
- if ( p->m_call != NULL )
+ if ( p->m_call != NULL )
{
instr = p->m_call;
pile = p->m_prev ;
@@ -684,7 +684,7 @@ void CBotStack::AddVar(CBotVar* pVar)
while (p != NULL && p->m_bBlock == 0) p = p->m_prev;
if ( p == NULL ) return;
-
+
/// p->m_bDontDelete = bDontDelete;
CBotVar** pp = &p->m_listVar;
@@ -787,7 +787,7 @@ void CBotStack::GetRunPos(const char* &FunctionName, int &start, int &end)
{
if ( p->m_instr != NULL ) instr = p->m_instr;
if ( p->m_bFunc == 1 ) funct = p->m_instr;
- if ( p->m_next->m_prog != prog ) break ;
+ if ( p->m_next->m_prog != prog ) break ;
if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ;
else p = p->m_next;
@@ -818,7 +818,7 @@ CBotVar* CBotStack::GetStackVars(const char* &FunctionName, int level)
while (p->m_next != NULL)
{
- if ( p->m_next->m_prog != prog ) break ;
+ if ( p->m_next->m_prog != prog ) break ;
if (p->m_next2 && p->m_next2->m_state != 0) p = p->m_next2 ;
else p = p->m_next;
@@ -848,7 +848,7 @@ CBotVar* CBotStack::GetStackVars(const char* &FunctionName, int level)
CBotToken* t = pp->m_instr->GetToken();
FunctionName = t->GetString();
-
+
return p->m_listVar;
}
@@ -872,8 +872,8 @@ bool CBotStack::SaveState(FILE* pf)
if (!WriteWord(pf, m_state)) return false; // in what state?
if (!WriteWord(pf, 0)) return false; // by compatibility m_bDontDelete
if (!WriteWord(pf, m_step)) return false; // in what state?
-
-
+
+
if (!SaveVar(pf, m_var)) return false; // current result
if (!SaveVar(pf, m_listVar)) return false; // local variables
@@ -921,7 +921,7 @@ bool CBotStack::RestoreState(FILE* pf, CBotStack* &pStack)
bool CBotVar::Save0State(FILE* pf)
-{
+{
if (!WriteWord(pf, 100+m_mPrivate))return false; // private variable?
if (!WriteWord(pf, m_bStatic))return false; // static variable?
if (!WriteWord(pf, m_type.GetType()))return false; // saves the type (always non-zero)
@@ -930,11 +930,11 @@ bool CBotVar::Save0State(FILE* pf)
}
bool CBotVarInt::Save0State(FILE* pf)
-{
+{
if ( !m_defnum.IsEmpty() )
{
if(!WriteWord(pf, 200 )) return false; // special marker
- if(!WriteString(pf, m_defnum)) return false; // name of the value
+ if(!WriteString(pf, m_defnum)) return false; // name of the value
}
return CBotVar::Save0State(pf);
@@ -1051,7 +1051,7 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar)
if ( p != NULL )
{
delete pNew;
- pNew = p; // resume known element
+ pNew = p; // resume known element
}
}
}
@@ -1167,7 +1167,7 @@ CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
-{
+{
if ( pfils == this ) return inst;
if (m_var != NULL) delete m_var; // value replaced?
@@ -1185,7 +1185,7 @@ CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
}
CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
-{
+{
if (m_var != NULL) delete m_var; // value replaced?
m_var = pfils->m_var; // result transmitted
pfils->m_var = NULL; // not to destroy the variable
@@ -1292,7 +1292,7 @@ bool CBotCStack::IsOk()
return (m_error == 0);
}
-
+
void CBotCStack::SetStartError( int pos )
{
if ( m_error != 0) return; // does not change existing error
diff --git a/src/CBot/CBotString.cpp b/src/CBot/CBotString.cpp
index b1b5fc4..2929977 100644
--- a/src/CBot/CBotString.cpp
+++ b/src/CBot/CBotString.cpp
@@ -54,7 +54,6 @@ const std::map<EID,const char *> CBotString::s_keywordString =
{ID_STATIC, "static"},
{ID_PROTECTED, "protected"},
{ID_PRIVATE, "private"},
- {ID_REPEAT, "repeat"},
{ID_DEBUGDD, "STARTDEBUGDD"},
{ID_INT, "int"},
{ID_FLOAT, "float"},
@@ -162,7 +161,7 @@ CBotString::CBotString(const CBotString& srcString)
int CBotString::GetLength()
{
if (m_ptr == NULL) return 0;
- return strlen( m_ptr );
+ return strlen( m_ptr );
}
@@ -337,7 +336,7 @@ const CBotString& CBotString::operator=(const CBotString& stringSrc)
delete[] m_ptr;
m_ptr = nullptr;
- m_lg = stringSrc.m_lg;
+ m_lg = stringSrc.m_lg;
if (m_lg > 0)
{
@@ -374,7 +373,7 @@ const CBotString& CBotString::operator=(const char ch)
{
delete[] m_ptr;
- m_lg = 1;
+ m_lg = 1;
m_ptr = new char[2];
m_ptr[0] = ch;
@@ -390,7 +389,7 @@ const CBotString& CBotString::operator=(const char* pString)
if (pString != nullptr)
{
- m_lg = strlen(pString);
+ m_lg = strlen(pString);
if (m_lg != 0)
{
@@ -521,7 +520,7 @@ int CBotString::Compare(const char * lpsz) const
char* p = m_ptr;
if (lpsz == NULL) lpsz = emptyString;
if (m_ptr == NULL) p = emptyString;
- return strcmp(p, lpsz); // wcscmp
+ return strcmp(p, lpsz); // wcscmp
}
const char * CBotString::MapIdToString(EID id)
diff --git a/src/CBot/CBotToken.cpp b/src/CBot/CBotToken.cpp
index f03ca91..48033a3 100644
--- a/src/CBot/CBotToken.cpp
+++ b/src/CBot/CBotToken.cpp
@@ -248,17 +248,15 @@ CBotToken* CBotToken::NextToken(char* &program, int& error, bool first)
{
while (c != 0 && !CharInList(c, nch))
{
- mot += c;
- c = *(program++); // next character
if ( c == '\\' )
{
c = *(program++); // next character
if ( c == 'n' ) c = '\n';
if ( c == 'r' ) c = '\r';
if ( c == 't' ) c = '\t';
- mot += c;
- c = *(program++); // next character
}
+ mot += c;
+ c = *(program++);
}
if ( c == '\"' )
{
@@ -474,7 +472,7 @@ void CBotToken::LoadKeyWords()
{
CBotString s;
int i, n = 0;
-
+
i = TokenKeyWord; //start with keywords of the language
while (s.LoadString(i))
{
diff --git a/src/CBot/CBotToken.h b/src/CBot/CBotToken.h
index 6f11bb2..a423375 100644
--- a/src/CBot/CBotToken.h
+++ b/src/CBot/CBotToken.h
@@ -36,3 +36,4 @@
extern bool IsOfType(CBotToken* &p, int type1, int type2 = -1);
extern bool IsOfTypeList(CBotToken* &p, int type1, ...);
+
diff --git a/src/CBot/CBotTwoOpExpr.cpp b/src/CBot/CBotTwoOpExpr.cpp
index dfaed9f..6a0d636 100644
--- a/src/CBot/CBotTwoOpExpr.cpp
+++ b/src/CBot/CBotTwoOpExpr.cpp
@@ -63,10 +63,10 @@ CBotLogicExpr::~CBotLogicExpr()
// acceptable type, operand
// zero ends level \TODO précéance
-static int ListOp[] =
+static int ListOp[] =
{
BOOLEEN, ID_LOGIC, 0,
- BOOLEEN, ID_TXT_OR,
+ BOOLEEN, ID_TXT_OR,
BOOLEEN, ID_LOG_OR, 0,
BOOLEEN, ID_TXT_AND,
BOOLEEN, ID_LOG_AND, 0,
@@ -76,7 +76,7 @@ static int ListOp[] =
BOOLEEN|ENTIER|FLOTANT
|CHAINE
|POINTER
- |INSTANCE,ID_EQ,
+ |INSTANCE,ID_EQ,
BOOLEEN|ENTIER|FLOTANT
|CHAINE
|POINTER
@@ -90,8 +90,8 @@ static int ListOp[] =
ENTIER, ID_ASR, 0,
ENTIER|FLOTANT|CHAINE, ID_ADD,
ENTIER|FLOTANT, ID_SUB, 0,
- ENTIER|FLOTANT, ID_MUL,
- ENTIER|FLOTANT, ID_DIV,
+ ENTIER|FLOTANT, ID_MUL,
+ ENTIER|FLOTANT, ID_DIV,
ENTIER|FLOTANT, ID_MODULO, 0,
ENTIER|FLOTANT, ID_POWER, 0,
0,
@@ -194,7 +194,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera
if ( NULL != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp )) )
// expression (...) right
{
- // there is an second operand acceptable
+ // there is an second operand acceptable
type2 = pStk->GetTypResult(); // what kind of results?
@@ -327,7 +327,7 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack)
}
- // requires a little more stack to avoid touching the result
+ // requires a little more stack to avoid touching the result
// of which is left on the stack, precisely
CBotStack* pStk2 = pStk1->AddStack(); // adds an item to the stack
@@ -566,3 +566,4 @@ void t(bool t)
t ? 0 : "test";
}
#endif
+
diff --git a/src/CBot/CBotVar.cpp b/src/CBot/CBotVar.cpp
index 7b0ce7b..ad3708d 100644
--- a/src/CBot/CBotVar.cpp
+++ b/src/CBot/CBotVar.cpp
@@ -134,8 +134,8 @@ void CBotVarClass::InitCBotVarClass( const CBotToken* name, CBotTypResult& type
m_LimExpr = NULL;
m_pVar = NULL;
m_type = type;
- if ( type.Eq(CBotTypArrayPointer) ) m_type.SetType( CBotTypArrayBody );
- else if ( !type.Eq(CBotTypArrayBody) ) m_type.SetType( CBotTypClass );
+ if ( type.Eq(CBotTypArrayPointer) ) m_type.SetType( CBotTypArrayBody );
+ else if ( !type.Eq(CBotTypArrayBody) ) m_type.SetType( CBotTypClass );
// officel type for this object
m_pClass = NULL;
@@ -394,7 +394,7 @@ CBotVar* CBotVar::Create( const char* n, CBotTypResult type)
CBotVarClass* instance = new CBotVarClass(&name, type);
CBotVarArray* array = new CBotVarArray(&name, type);
array->SetPointer( instance );
-
+
CBotVar* pv = array;
while (type.Eq(CBotTypArrayBody))
{
@@ -414,14 +414,14 @@ CBotVar* CBotVar::Create( const char* name, int type, CBotClass* pClass)
{
CBotToken token( name, "" );
CBotVar* pVar = Create( &token, type );
-
+
if ( type == CBotTypPointer && pClass == NULL ) // pointer "null" ?
return pVar;
if ( type == CBotTypClass || type == CBotTypPointer ||
type == CBotTypIntrinsic )
{
- if (pClass == NULL)
+ if (pClass == NULL)
{
delete pVar;
return NULL;
@@ -443,9 +443,9 @@ CBotTypResult CBotVar::GetTypResult(int mode)
{
CBotTypResult r = m_type;
- if ( mode == 1 && m_type.Eq(CBotTypClass) )
+ if ( mode == 1 && m_type.Eq(CBotTypClass) )
r.SetType(CBotTypPointer);
- if ( mode == 2 && m_type.Eq(CBotTypClass) )
+ if ( mode == 2 && m_type.Eq(CBotTypClass) )
r.SetType(CBotTypIntrinsic);
return r;
@@ -453,9 +453,9 @@ CBotTypResult CBotVar::GetTypResult(int mode)
int CBotVar::GetType(int mode)
{
- if ( mode == 1 && m_type.Eq(CBotTypClass) )
+ if ( mode == 1 && m_type.Eq(CBotTypClass) )
return CBotTypPointer;
- if ( mode == 2 && m_type.Eq(CBotTypClass) )
+ if ( mode == 2 && m_type.Eq(CBotTypClass) )
return CBotTypIntrinsic;
return m_type.GetType();
}
@@ -620,7 +620,7 @@ void CBotVar::SetVal(CBotVar* var)
ASM_TRAP();
}
- m_binit = var->m_binit; // copie l'état nan s'il y a
+ m_binit = var->m_binit; // copie l'état nan s'il y a
}
void CBotVar::SetStatic(bool bStatic)
@@ -1293,7 +1293,7 @@ void CBotVarBoolean::XOr(CBotVar* left, CBotVar* right)
void CBotVarBoolean::Not()
{
- m_val = m_val ? false : true ;
+ m_val = m_val ? false : true ;
}
bool CBotVarBoolean::Eq(CBotVar* left, CBotVar* right)
@@ -1468,7 +1468,7 @@ void CBotVarClass::SetClass(CBotClass* pClass)//, int &nIdent)
CBotInstr* p = pv->m_LimExpr; // the different formulas
if ( p != NULL )
{
- CBotStack* pile = CBotStack::FirstStack(); // an independent stack
+ CBotStack* pile = CBotStack::FirstStack(); // an independent stack
int n = 0;
int max[100];
@@ -1524,7 +1524,7 @@ CBotClass* CBotVarClass::GetClass()
void CBotVarClass::Maj(void* pUser, bool bContinu)
{
-/* if (!bContinu && m_pMyThis != NULL)
+/* if (!bContinu && m_pMyThis != NULL)
m_pMyThis->Maj(pUser, true);*/
// an update routine exist?
@@ -1671,7 +1671,7 @@ void CBotVarClass::IncrementUse()
void CBotVarClass::DecrementUse()
{
m_CptUse--;
- if ( m_CptUse == 0 )
+ if ( m_CptUse == 0 )
{
// if there is one, call the destructor
// but only if a constructor had been called.
@@ -2025,7 +2025,7 @@ bool CBotVarPointer::Save1State(FILE* pf)
if (!WriteLong(pf, GetIdent())) return false; // the unique reference
- // also saves the proceedings copies
+ // also saves the proceedings copies
return SaveVar(pf, GetPointer());
}
@@ -2082,7 +2082,7 @@ bool CBotVarPointer::Ne(CBotVar* left, CBotVar* right)
///////////////////////////////////////////////////////
-// management of results types
+// management of results types
CBotTypResult::CBotTypResult(int type)
@@ -2164,7 +2164,7 @@ int CBotTypResult::GetType(int mode) const
if ( m_pClass == NULL ) ASM_TRAP();
-
+
if ( m_type == CBotTypArrayPointer )
if ( m_pNext == NULL ) ASM_TRAP();
#endif
@@ -2245,4 +2245,3 @@ CBotTypResult&
return *this;
}
-
diff --git a/src/CBot/CBotWhile.cpp b/src/CBot/CBotWhile.cpp
index dfd69bf..73bcab9 100644
--- a/src/CBot/CBotWhile.cpp
+++ b/src/CBot/CBotWhile.cpp
@@ -112,16 +112,16 @@ bool CBotWhile :: Execute(CBotStack* &pj)
// the condition is true, pass in the second mode
if (!pile->SetState(1)) return false; // ready for further
-
+
case 1:
// evaluates the associated statement block
- if ( m_Block != NULL &&
+ if ( m_Block != NULL &&
!m_Block->Execute(pile) )
{
if (pile->IfContinue(0, m_label)) continue; // if continued, will return to test
return pj->BreakReturn(pile, m_label); // sends the results and releases the stack
}
-
+
// terminates if there is an error
if ( !pile->IsOk() )
{
@@ -130,7 +130,7 @@ bool CBotWhile :: Execute(CBotStack* &pj)
// returns to the test again
if (!pile->SetState(0, 0)) return false;
- continue;
+ continue;
}
}
@@ -140,163 +140,20 @@ void CBotWhile :: RestoreState(CBotStack* &pj, bool bMain)
CBotStack* pile = pj->RestoreStack(this); // adds an item to the stack
if ( pile == NULL ) return;
- switch( pile->GetState() )
+ switch( pile->GetState() )
{ // there are two possible states (depending on recovery)
case 0:
// evaluates the condition
- m_Condition->RestoreState(pile, bMain);
+ m_Condition->RestoreState(pile, bMain);
return;
-
+
case 1:
// evaluates the associated statement block
if ( m_Block != NULL ) m_Block->RestoreState(pile, bMain);
return;
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////
-// compiles instruction "repeat"
-
-CBotRepeat::CBotRepeat()
-{
- m_NbIter =
- m_Block = NULL; // NULL so that delete is not possible further
- name = "CBotRepeat"; // debug
-}
-
-CBotRepeat::~CBotRepeat()
-{
- delete m_NbIter; // frees the condition
- delete m_Block; // frees the instruction block
-}
-
-CBotInstr* CBotRepeat::Compile(CBotToken* &p, CBotCStack* pStack)
-{
- CBotRepeat* inst = new CBotRepeat(); // creates the object
- CBotToken* pp = p; // preserves at the ^ token (starting position)
-
- if ( IsOfType( p, TokenTypVar ) &&
- IsOfType( p, ID_DOTS ) )
- {
- inst->m_label = pp->GetString(); // register the name of label
- }
-
- inst->SetToken(p);
- if (!IsOfType(p, ID_REPEAT)) return NULL; // should never happen
-
- CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
-
- if ( IsOfType(p, ID_OPENPAR ) )
- {
- CBotToken* ppp = p; // preserves the ^ token (starting position)
- if ( NULL != (inst->m_NbIter = CBotExpression::Compile( p, pStk )) )
- {
- if ( pStk->GetType() < CBotTypLong )
- {
- if ( IsOfType(p, ID_CLOSEPAR ) )
- {
-
- IncLvl(inst->m_label);
- inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk, true );
- DecLvl();
-
- if ( pStk->IsOk() )
- {
- // the statement block is ok (it may be empty!
-
- return pStack->Return(inst, pStk); // return an object to the application
- }
- }
- pStack->SetError(TX_CLOSEPAR, p->GetStart());
- }
- pStk->SetStartError(ppp->GetStart());
- pStk->SetError( TX_BADTYPE, p->GetStart() );
- }
- pStack->SetError(TX_ENDOF, p);
- }
- pStack->SetError(TX_OPENPAR, p->GetStart()); // missing parenthesis
-
- delete inst; // error, frees up
- return pStack->Return(NULL, pStk); // no object, the error is on the stack
-}
-
-// execution of intruction "repeat"
-
-bool CBotRepeat :: Execute(CBotStack* &pj)
-{
- CBotStack* pile = pj->AddStack(this); // adds an item to the stack
- // or find in case of recovery
-// if ( pile == EOX ) return true;
-
- if ( pile->IfStep() ) return false;
-
- while( true ) switch( pile->GetState() ) // executes the loop
- { // there are two possible states (depending on recovery)
- case 0:
- // evaluates the number of iterations
- if ( !m_NbIter->Execute(pile) ) return false; // interrupted here ?
-
- // the result of the condition is on the stack
-
- // terminates if an error or if the condition is false
- int n;
- if ( !pile->IsOk() || ( n = pile->GetVal() ) < 1 )
- {
- return pj->Return(pile); // sends the results and releases the stack
- }
-
- // puts the number of iterations +1 to the "state"
-
- if (!pile->SetState(n+1)) return false; // ready for further
- continue; // continue as a result
-
- case 1:
- // normal end of the loop
- return pj->Return(pile); // sends the results and releases the stack
-
- default:
- // evaluates the associated statement block
- if ( m_Block != NULL &&
- !m_Block->Execute(pile) )
- {
- if (pile->IfContinue(pile->GetState()-1, m_label)) continue; // if continued, will return to test
- return pj->BreakReturn(pile, m_label); // sends the results and releases the stack
- }
-
- // terminates if there is an error
- if ( !pile->IsOk() )
- {
- return pj->Return(pile); // sends the results and releases the stack
- }
-
- // returns to the test again
- if (!pile->SetState(pile->GetState()-1, 0)) return false;
- continue;
}
}
-void CBotRepeat :: RestoreState(CBotStack* &pj, bool bMain)
-{
- if ( !bMain ) return;
- CBotStack* pile = pj->RestoreStack(this); // adds an item to the stack
- if ( pile == NULL ) return;
-
- switch( pile->GetState() )
- { // there are two possible states (depending on recovery)
- case 0:
- // evaluates the condition
- m_NbIter->RestoreState(pile, bMain);
- return;
-
- case 1:
- // evaluates the associated statement block
- if ( m_Block != NULL ) m_Block->RestoreState(pile, bMain);
- return;
- }
-}
///////////////////////////////////////////////////////////////////////////
@@ -374,13 +231,13 @@ bool CBotDo :: Execute(CBotStack* &pj)
{ // there are two possible states (depending on recovery)
case 0:
// evaluates the associated statement block
- if ( m_Block != NULL &&
+ if ( m_Block != NULL &&
!m_Block->Execute(pile) )
{
if (pile->IfContinue(1, m_label)) continue; // if continued, will return to test
return pj->BreakReturn(pile, m_label); // sends the results and releases the stack
}
-
+
// terminates if there is an error
if ( !pile->IsOk() )
{
@@ -388,7 +245,7 @@ bool CBotDo :: Execute(CBotStack* &pj)
}
if (!pile->SetState(1)) return false; // ready for further
-
+
case 1:
// evaluates the condition
if ( !m_Condition->Execute(pile) ) return false; // interrupted here ?
@@ -403,7 +260,7 @@ bool CBotDo :: Execute(CBotStack* &pj)
// returns to instruction block to start
if (!pile->SetState(0, 0)) return false;
- continue;
+ continue;
}
}
@@ -420,7 +277,7 @@ void CBotDo :: RestoreState(CBotStack* &pj, bool bMain)
// restores the assosiated statement's block
if ( m_Block != NULL ) m_Block->RestoreState(pile, bMain);
return;
-
+
case 1:
// restores the condition
m_Condition->RestoreState(pile, bMain);
@@ -445,9 +302,9 @@ CBotFor::CBotFor()
CBotFor::~CBotFor()
{
- delete m_Init;
- delete m_Test;
- delete m_Incr;
+ delete m_Init;
+ delete m_Test;
+ delete m_Incr;
delete m_Block; // frees the instruction block
}
@@ -529,7 +386,7 @@ bool CBotFor :: Execute(CBotStack* &pj)
if ( m_Init != NULL &&
!m_Init->Execute(pile) ) return false; // interrupted here ?
if (!pile->SetState(1)) return false; // ready for further
-
+
case 1:
// evaluates the condition
if ( m_Test != NULL ) // no strings attached? -> True!
@@ -547,10 +404,10 @@ bool CBotFor :: Execute(CBotStack* &pj)
// la condition est vrai, passe à la suite
if (!pile->SetState(2)) return false; // ready for further
-
+
case 2:
// evaluates the associated statement block
- if ( m_Block != NULL &&
+ if ( m_Block != NULL &&
!m_Block->Execute(pile) )
{
if (pile->IfContinue(3, m_label)) continue; // if continued, going on to incrementation
@@ -572,7 +429,7 @@ bool CBotFor :: Execute(CBotStack* &pj)
// returns to the test again
if (!pile->SetState(1, 0)) return false; // returns to the test
- continue;
+ continue;
}
}
@@ -589,7 +446,7 @@ void CBotFor :: RestoreState(CBotStack* &pj, bool bMain)
// initialize
if ( m_Init != NULL ) m_Init->RestoreState(pile, true); // interrupted here !
return;
-
+
case 1:
if ( m_Init != NULL ) m_Init->RestoreState(pile, false); // variables definitions
@@ -686,7 +543,7 @@ void CBotListExpression::RestoreState(CBotStack* &pj, bool bMain)
{
CBotStack* pile = pj;
int state = 0x7000;
-
+
if ( bMain )
{
pile = pj->RestoreStack();
@@ -758,7 +615,7 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
CBotInstr* i = CBotCase::Compile( p, pStk2 );
if (i == NULL)
{
- delete inst;
+ delete inst;
return pStack->Return(NULL, pStk2);
}
delete pStk2;
@@ -766,7 +623,7 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
else inst->m_Block->AddNext(i);
continue;
}
-
+
if ( inst->m_Block == NULL )
{
pStk->SetError(TX_NOCASE, p->GetStart());
@@ -790,7 +647,7 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
}
}
DecLvl();
-
+
if ( inst->m_Block == NULL )
{
pStk->SetError(TX_NOCASE, p->GetStart());
@@ -817,7 +674,7 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
bool CBotSwitch :: Execute(CBotStack* &pj)
{
- CBotStack* pile1 = pj->AddStack(this); // adds an item to the stack
+ CBotStack* pile1 = pj->AddStack(this); // adds an item to the stack
// if ( pile1 == EOX ) return true;
CBotInstr* p = m_Block; // first expression
@@ -866,7 +723,7 @@ void CBotSwitch :: RestoreState(CBotStack* &pj, bool bMain)
{
if ( !bMain ) return;
- CBotStack* pile1 = pj->RestoreStack(this); // adds an item to the stack
+ CBotStack* pile1 = pj->RestoreStack(this); // adds an item to the stack
if ( pile1 == NULL ) return;
CBotInstr* p = m_Block; // first expression
@@ -1055,7 +912,7 @@ CBotTry::~CBotTry()
delete m_ListCatch; // frees the list
delete m_Block; // frees the instruction block
delete m_FinalInst;
-}
+}
CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack)
{
@@ -1069,7 +926,7 @@ CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack)
inst->m_Block = CBotBlock::CompileBlkOrInst( p, pStk );
CBotCatch** pn = &inst->m_ListCatch;
-
+
while (pStk->IsOk() && p->GetType() == ID_CATCH)
{
CBotCatch* i = CBotCatch::Compile(p, pStk);
@@ -1154,7 +1011,7 @@ bool CBotTry :: Execute(CBotStack* &pj)
if ( !pc->Execute(pile2) ) return false; // performs the operation
if ( m_FinalInst == NULL )
return pj->Return(pile2); // ends the try
-
+
pile1->SetState(-2); // passes final
break;
}
@@ -1162,13 +1019,13 @@ bool CBotTry :: Execute(CBotStack* &pj)
}
pc = pc->m_next;
}
- if ( m_FinalInst != NULL &&
+ if ( m_FinalInst != NULL &&
pile1->GetState() > 0 && val != 0 ) pile1->SetState(-1);// if stop then made the final
if (pile1->GetState() <= -1)
{
// pile0->SetState(1);
-
+
if (!m_FinalInst->Execute(pile2) && pile2->IsOk()) return false;
if (!pile2->IsOk()) return pj->Return(pile2); // keep this exception
pile2->SetError(pile1->GetState()==-1 ? val : 0); // gives the initial error
@@ -1319,7 +1176,7 @@ bool CBotCatch :: TestCatch(CBotStack* &pile, int val)
var->SetValInt( pile->GetVal() == val );
pile->SetVar(var); // calls on the stack
}
-
+
return true;
}
diff --git a/src/CBot/CMakeLists.txt b/src/CBot/CMakeLists.txt
index fecd18e..8bb8a5c 100644
--- a/src/CBot/CMakeLists.txt
+++ b/src/CBot/CMakeLists.txt
@@ -12,7 +12,7 @@ CBotVar.cpp
CBotWhile.cpp
)
-if(${CBOT_STATIC})
+if(CBOT_STATIC)
add_library(CBot STATIC ${SOURCES})
else()
add_library(CBot SHARED ${SOURCES})
@@ -21,3 +21,4 @@ else()
ARCHIVE DESTINATION ${COLOBOT_INSTALL_LIB_DIR}
RUNTIME DESTINATION ${COLOBOT_INSTALL_BIN_DIR})
endif()
+
diff --git a/src/CBot/ClassFILE.cpp b/src/CBot/ClassFILE.cpp
index b0f7977..6906bd4 100644
--- a/src/CBot/ClassFILE.cpp
+++ b/src/CBot/ClassFILE.cpp
@@ -58,7 +58,7 @@ void PrepareFilename(CBotString &filename) //DD!
// gets the filename as a parameter
// execution
-bool rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+bool rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
{
CBotString mode;
@@ -239,7 +239,7 @@ CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
return CBotTypResult(CBotTypBoolean); //DR
}
-
+
// FILE :: close method
// execution
@@ -291,7 +291,7 @@ bool rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
if ( pVar->GetInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
FILE* pFile= (FILE*)pVar->GetValInt();
-
+
int res = fputs(param+CBotString("\n"), pFile);
// on error throws an exception
diff --git a/src/CBot/StringFunctions.cpp b/src/CBot/StringFunctions.cpp
index d24c942..abdcc18 100644
--- a/src/CBot/StringFunctions.cpp
+++ b/src/CBot/StringFunctions.cpp
@@ -184,10 +184,10 @@ bool rStrMid( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
if ( pVar->GetNext() != NULL )
{
pVar = pVar->GetNext();
-
+
// which must be a number
if ( pVar->GetType() > CBotTypDouble ) { ex = TX_BADNUM ; return true; }
-
+
// retrieves this number
int l = pVar->GetValInt();
@@ -231,7 +231,7 @@ CBotTypResult cStrStrIntInt( CBotVar* &pVar, void* pUser )
// third parameter optional
if ( pVar->GetNext() != NULL )
{
-
+
pVar = pVar->GetNext();
// which must be a number
if ( pVar->GetType() > CBotTypDouble )
@@ -434,3 +434,4 @@ void InitStringFunctions()
CBotProgram::AddFunction("strupper", rStrUpper, cStrStr );
CBotProgram::AddFunction("strlower", rStrLower, cStrStr );
}
+
diff --git a/src/CBot/idees.txt b/src/CBot/idees.txt
index 3966ee1..3f335da 100644
--- a/src/CBot/idees.txt
+++ b/src/CBot/idees.txt
@@ -39,3 +39,4 @@ the object being created with CBotVar :: Create (name, pClasse)
not destroy the object when there imédiatement pointers
but marked as virtually destroyed
+
diff --git a/src/CBot/resource.h b/src/CBot/resource.h
index ed14240..9c7e82e 100644
--- a/src/CBot/resource.h
+++ b/src/CBot/resource.h
@@ -47,7 +47,6 @@ enum EID
ID_STATIC,
ID_PROTECTED,
ID_PRIVATE,
- ID_REPEAT,
ID_DEBUGDD,
ID_INT,
ID_FLOAT,
@@ -177,3 +176,4 @@ enum EID
#define TX_ERRWRITE 6015
#define TX_MAX 6016
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index de60ef3..40373a3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,12 +8,8 @@ set(CMAKE_CXX_FLAGS_DEBUG ${COLOBOT_CXX_FLAGS_DEBUG})
add_subdirectory(CBot)
-add_subdirectory(tools)
-
-add_subdirectory(po)
-
-if(${DESKTOP})
- add_subdirectory(desktop)
+if(TOOLS)
+ add_subdirectory(tools)
endif()
@@ -21,20 +17,20 @@ endif()
set(OPTIONAL_LIBS "")
set(OPTIONAL_INCLUDES "")
-if (${OPENAL_SOUND})
+if(OPENAL_SOUND)
set(OPTIONAL_LIBS ${OPENAL_LIBRARY})
set(OPTIONAL_INCLUDES ${OPENAL_INCLUDE_DIR})
endif()
# Additional libraries per platform
-if (${MXE}) # MXE requires special treatment
- set(PLATFORM_LIBS ${MXE_LIBS})
-elseif (${PLATFORM_WINDOWS})
+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})
+elseif(PLATFORM_LINUX)
# for clock_gettime
- set(PLATFORM_LIBS "-lrt")
+ set(PLATFORM_LIBS "-lrt -lX11")
endif()
@@ -43,7 +39,7 @@ configure_file(common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h
set(OPENAL_SRC "")
-if (${OPENAL_SOUND})
+if(OPENAL_SOUND)
set(OPENAL_SRC
sound/oalsound/alsound.cpp
sound/oalsound/buffer.cpp
@@ -52,9 +48,9 @@ if (${OPENAL_SOUND})
endif()
# Platform-dependent implementation of system.h
-if (${PLATFORM_WINDOWS})
+if(PLATFORM_WINDOWS)
set(SYSTEM_CPP_MODULE "system_windows.cpp")
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
set(SYSTEM_CPP_MODULE "system_linux.cpp")
else()
set(SYSTEM_CPP_MODULE "system_other.cpp")
@@ -120,6 +116,7 @@ object/mainmovie.cpp
object/motion/motion.cpp
object/motion/motionant.cpp
object/motion/motionbee.cpp
+object/motion/motiondummy.cpp
object/motion/motionhuman.cpp
object/motion/motionmother.cpp
object/motion/motionspider.cpp
@@ -128,6 +125,7 @@ object/motion/motionvehicle.cpp
object/motion/motionworm.cpp
object/object.cpp
object/robotmain.cpp
+object/objman.cpp
object/task/task.cpp
object/task/taskadvance.cpp
object/task/taskbuild.cpp
@@ -153,6 +151,7 @@ physics/physics.cpp
script/cbottoken.cpp
script/cmdtoken.cpp
script/script.cpp
+sound/sound.cpp
ui/button.cpp
ui/check.cpp
ui/color.cpp
@@ -185,6 +184,8 @@ ${OPENAL_SRC}
set(LIBS
CBot
+clipboard
+localename
${SDL_LIBRARY}
${SDLIMAGE_LIBRARY}
${SDLTTF_LIBRARY}
@@ -214,7 +215,9 @@ ${PNG_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
${Boost_INCLUDE_DIRS}
${LIBSNDFILE_INCLUDE_DIR}
+${LOCALENAME_INCLUDE_DIR}
${OPTIONAL_INCLUDE_DIRS}
+${CLIPBOARD_INCLUDE_DIR}
)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/CBot)
@@ -225,3 +228,4 @@ target_link_libraries(colobot ${LIBS})
install(TARGETS colobot RUNTIME DESTINATION ${COLOBOT_INSTALL_BIN_DIR})
set_target_properties(colobot PROPERTIES INSTALL_RPATH ${COLOBOT_INSTALL_LIB_DIR})
+
diff --git a/src/app/README.txt b/src/app/README.txt
index 92be8a6..57a2785 100644
--- a/src/app/README.txt
+++ b/src/app/README.txt
@@ -2,3 +2,4 @@
* \dir src/app
* Main class of the application and system functions
*/
+
diff --git a/src/app/app.cpp b/src/app/app.cpp
index 59a04f4..f98e0fc 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -25,13 +25,19 @@
#include "common/iman.h"
#include "common/image.h"
#include "common/key.h"
+#include "common/stringutils.h"
#include "graphics/engine/modelmanager.h"
#include "graphics/opengl/gldevice.h"
#include "object/robotmain.h"
+#ifdef OPENAL_SOUND
+ #include "sound/oalsound/alsound.h"
+#endif
+
#include <boost/filesystem.hpp>
+#include <boost/tokenizer.hpp>
#include <SDL.h>
#include <SDL_image.h>
@@ -40,11 +46,7 @@
#include <libintl.h>
#include <unistd.h>
#include <getopt.h>
-
-
-#ifdef OPENAL_SOUND
- #include "sound/oalsound/alsound.h"
-#endif
+#include <localename.h>
template<> CApplication* CSingleton<CApplication>::m_instance = nullptr;
@@ -95,6 +97,7 @@ CApplication::CApplication()
{
m_private = new ApplicationPrivate();
m_iMan = new CInstanceManager();
+ m_objMan = new CObjectManager();
m_eventQueue = new CEventQueue();
m_profile = new CProfile();
@@ -106,7 +109,7 @@ CApplication::CApplication()
m_exitCode = 0;
m_active = false;
- m_debugMode = false;
+ m_debugModes = 0;
m_windowTitle = "COLOBOT";
@@ -145,23 +148,29 @@ CApplication::CApplication()
m_dataPath = COLOBOT_DEFAULT_DATADIR;
m_langPath = COLOBOT_I18N_DIR;
+ m_texPackPath = "";
+
+ m_runSceneName = "";
+ m_runSceneRank = 0;
m_language = LANGUAGE_ENV;
m_lowCPU = true;
+ m_protoMode = false;
+
for (int i = 0; i < DIR_MAX; ++i)
- m_dataDirs[i] = nullptr;
+ m_standardDataDirs[i] = nullptr;
- m_dataDirs[DIR_AI] = "ai";
- m_dataDirs[DIR_FONT] = "fonts";
- m_dataDirs[DIR_HELP] = "help";
- m_dataDirs[DIR_ICON] = "icons";
- m_dataDirs[DIR_LEVEL] = "levels";
- m_dataDirs[DIR_MODEL] = "models";
- m_dataDirs[DIR_MUSIC] = "music";
- m_dataDirs[DIR_SOUND] = "sounds";
- m_dataDirs[DIR_TEXTURE] = "textures";
+ m_standardDataDirs[DIR_AI] = "ai";
+ m_standardDataDirs[DIR_FONT] = "fonts";
+ m_standardDataDirs[DIR_HELP] = "help";
+ m_standardDataDirs[DIR_ICON] = "icons";
+ m_standardDataDirs[DIR_LEVEL] = "levels";
+ m_standardDataDirs[DIR_MODEL] = "models";
+ m_standardDataDirs[DIR_MUSIC] = "music";
+ m_standardDataDirs[DIR_SOUND] = "sounds";
+ m_standardDataDirs[DIR_TEXTURE] = "textures";
}
CApplication::~CApplication()
@@ -169,6 +178,9 @@ CApplication::~CApplication()
delete m_private;
m_private = nullptr;
+ delete m_objMan;
+ m_objMan = nullptr;
+
delete m_eventQueue;
m_eventQueue = nullptr;
@@ -211,22 +223,29 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
{
OPT_HELP = 1,
OPT_DEBUG,
- OPT_DATADIR,
+ OPT_RUNSCENE,
OPT_LOGLEVEL,
OPT_LANGUAGE,
+ OPT_DATADIR,
OPT_LANGDIR,
- OPT_VBO
+ OPT_TEXPACK,
+ OPT_VBO,
+ OPT_PROTO
};
option options[] =
{
{ "help", no_argument, nullptr, OPT_HELP },
- { "debug", no_argument, nullptr, OPT_DEBUG },
- { "datadir", required_argument, nullptr, OPT_DATADIR },
+ { "debug", required_argument, nullptr, OPT_DEBUG },
+ { "runscene", required_argument, nullptr, OPT_RUNSCENE },
{ "loglevel", required_argument, nullptr, OPT_LOGLEVEL },
{ "language", required_argument, nullptr, OPT_LANGUAGE },
+ { "datadir", required_argument, nullptr, OPT_DATADIR },
{ "langdir", required_argument, nullptr, OPT_LANGDIR },
- { "vbo", required_argument, nullptr, OPT_VBO }
+ { "texpack", required_argument, nullptr, OPT_TEXPACK },
+ { "vbo", required_argument, nullptr, OPT_VBO },
+ { "proto", no_argument, nullptr, OPT_PROTO },
+ { nullptr, 0, nullptr, 0}
};
opterr = 0;
@@ -256,24 +275,44 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
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(" -langdir path set custom language directory path\n");
- GetLogger()->Message(" -vbo mode set OpenGL VBO mode (one of: auto, enable, disable)\n");
+ GetLogger()->Message(" -help this help\n");
+ GetLogger()->Message(" -debug modes enable debug modes (more info printed in logs; see code for reference of modes)\n");
+ GetLogger()->Message(" -runscene sceneNNN run given scene on start\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(" -datadir path set custom data directory path\n");
+ GetLogger()->Message(" -langdir path set custom language directory path\n");
+ GetLogger()->Message(" -texpack path set path to custom texture pack\n");
+ GetLogger()->Message(" -vbo mode set OpenGL VBO mode (one of: auto, enable, disable)\n");
+ GetLogger()->Message(" -proto show prototype levels\n");
return PARSE_ARGS_HELP;
}
case OPT_DEBUG:
{
- SetDebugMode(true);
+ if (optarg == nullptr)
+ {
+ m_debugModes = DEBUG_ALL;
+ GetLogger()->Info("All debug modes active\n");
+ }
+ else
+ {
+ int debugModes;
+ if (! ParseDebugModes(optarg, debugModes))
+ {
+ return PARSE_ARGS_FAIL;
+ }
+
+ m_debugModes = debugModes;
+ GetLogger()->Info("Active debug modes: %s\n", optarg);
+ }
break;
}
- case OPT_DATADIR:
+ case OPT_RUNSCENE:
{
- m_dataPath = optarg;
- GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str());
+ std::string file = optarg;
+ m_runSceneName = file.substr(0, file.size()-3);
+ m_runSceneRank = StrUtils::FromString<int>(file.substr(file.size()-3, 3));
+ GetLogger()->Info("Running scene '%s%d' on start\n", m_runSceneName.c_str(), m_runSceneRank);
break;
}
case OPT_LOGLEVEL:
@@ -281,7 +320,7 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
LogLevel logLevel;
if (! CLogger::ParseLogLevel(optarg, logLevel))
{
- GetLogger()->Error("Invalid log level: \"%s\"\n", optarg);
+ GetLogger()->Error("Invalid log level: '%s'\n", optarg);
return PARSE_ARGS_FAIL;
}
@@ -294,7 +333,7 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
Language language;
if (! ParseLanguage(optarg, language))
{
- GetLogger()->Error("Invalid language: \"%s\"\n", optarg);
+ GetLogger()->Error("Invalid language: '%s'\n", optarg);
return PARSE_ARGS_FAIL;
}
@@ -302,12 +341,24 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
m_language = language;
break;
}
+ case OPT_DATADIR:
+ {
+ m_dataPath = optarg;
+ GetLogger()->Info("Using custom data dir: '%s'\n", m_dataPath.c_str());
+ break;
+ }
case OPT_LANGDIR:
{
m_langPath = optarg;
GetLogger()->Info("Using custom language dir: '%s'\n", m_langPath.c_str());
break;
}
+ case OPT_TEXPACK:
+ {
+ m_texPackPath = optarg;
+ GetLogger()->Info("Using texturepack: '%s'\n", m_texPackPath.c_str());
+ break;
+ }
case OPT_VBO:
{
std::string vbo;
@@ -320,12 +371,17 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
m_deviceConfig.vboMode = Gfx::VBO_MODE_DISABLE;
else
{
- GetLogger()->Error("Invalid vbo mode: \"%s\"\n", optarg);
+ GetLogger()->Error("Invalid vbo mode: '%s'\n", optarg);
return PARSE_ARGS_FAIL;
}
break;
}
+ case OPT_PROTO:
+ {
+ m_protoMode = true;
+ break;
+ }
default:
assert(false); // should never get here
}
@@ -336,8 +392,22 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[])
bool CApplication::Create()
{
+ std::string path;
+ bool defaultValues = false;
+
GetLogger()->Info("Creating CApplication\n");
+ if (!GetProfile().InitCurrentDirectory())
+ {
+ GetLogger()->Warn("Config not found. Default values will be used!\n");
+ defaultValues = true;
+ }
+ else
+ {
+ if (GetProfile().GetLocalProfileString("Resources", "Data", path))
+ m_dataPath = path;
+ }
+
boost::filesystem::path dataPath(m_dataPath);
if (! (boost::filesystem::exists(dataPath) && boost::filesystem::is_directory(dataPath)) )
{
@@ -349,41 +419,47 @@ bool CApplication::Create()
return false;
}
+ GetProfile().SetLocalProfileString("Resources", "Data", m_dataPath);
+
SetLanguage(m_language);
//Create the sound instance.
- if (!GetProfile().InitCurrentDirectory())
+ #ifdef OPENAL_SOUND
+ m_sound = static_cast<CSoundInterface *>(new ALSound());
+ #else
+ GetLogger()->Info("No sound support.\n");
+ m_sound = new CSoundInterface();
+ #endif
+
+ m_sound->Create(true);
+
+ // Cache sound files
+ if (defaultValues)
{
- GetLogger()->Warn("Config not found. Default values will be used!\n");
- m_sound = new CSoundInterface();
+ GetProfile().SetLocalProfileString("Resources", "Sound", GetDataSubdirPath(DIR_SOUND));
+ GetProfile().SetLocalProfileString("Resources", "Music", GetDataSubdirPath(DIR_MUSIC));
+ }
+
+ if (GetProfile().GetLocalProfileString("Resources", "Sound", path))
+ {
+ m_sound->CacheAll(path);
}
else
{
- std::string path;
- if (GetProfile().GetLocalProfileString("Resources", "Data", path))
- m_dataPath = path;
-
- #ifdef OPENAL_SOUND
- m_sound = static_cast<CSoundInterface *>(new ALSound());
- #else
- GetLogger()->Info("No sound support.\n");
- m_sound = new CSoundInterface();
- #endif
-
- m_sound->Create(true);
- if (GetProfile().GetLocalProfileString("Resources", "Sound", path)) {
- m_sound->CacheAll(path);
- } else {
- m_sound->CacheAll(GetDataSubdirPath(DIR_SOUND));
- }
+ m_sound->CacheAll(GetDataSubdirPath(DIR_SOUND));
+ }
- if (GetProfile().GetLocalProfileString("Resources", "Music", path)) {
- m_sound->AddMusicFiles(path);
- } else {
- m_sound->AddMusicFiles(GetDataSubdirPath(DIR_MUSIC));
- }
+ if (GetProfile().GetLocalProfileString("Resources", "Music", path))
+ {
+ m_sound->AddMusicFiles(path);
+ }
+ else
+ {
+ m_sound->AddMusicFiles(GetDataSubdirPath(DIR_MUSIC));
}
+ GetLogger()->Info("CApplication created successfully\n");
+
std::string standardInfoMessage =
"\nPlease see the console output or log file\n"
"to get more information on the source of error";
@@ -448,6 +524,7 @@ bool CApplication::Create()
// Enable translating key codes of key press events to unicode chars
SDL_EnableUNICODE(1);
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
// Don't generate joystick events
SDL_JoystickEventState(SDL_IGNORE);
@@ -477,11 +554,14 @@ bool CApplication::Create()
m_modelManager = new Gfx::CModelManager(m_engine);
// Create the robot application.
- m_robotMain = new CRobotMain(this);
+ m_robotMain = new CRobotMain(this, !defaultValues);
- m_robotMain->ChangePhase(PHASE_WELCOME1);
+ if (defaultValues) m_robotMain->CreateIni();
- GetLogger()->Info("CApplication created successfully\n");
+ if (! m_runSceneName.empty())
+ m_robotMain->LoadSceneOnStart(m_runSceneName, m_runSceneRank);
+ else
+ m_robotMain->ChangePhase(PHASE_WELCOME1);
return true;
}
@@ -605,7 +685,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig)
if (! CreateVideoSurface())
{
// Fatal error, so post the quit event
- m_eventQueue->AddEvent(Event(EVENT_QUIT));
+ m_eventQueue->AddEvent(Event(EVENT_SYS_QUIT));
return false;
}
@@ -634,7 +714,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig)
// Fatal error, so post the quit event
- m_eventQueue->AddEvent(Event(EVENT_QUIT));
+ m_eventQueue->AddEvent(Event(EVENT_SYS_QUIT));
return false;
}
}
@@ -818,31 +898,15 @@ int CApplication::Run()
Event event = ProcessSystemEvent();
- if (event.type == EVENT_QUIT)
+ if (event.type == EVENT_SYS_QUIT)
goto end; // exit the loop
if (event.type != EVENT_NULL)
- {
- bool passOn = ProcessEvent(event);
-
- if (m_engine != nullptr && passOn)
- passOn = m_engine->ProcessEvent(event);
-
- if (passOn)
- m_eventQueue->AddEvent(event);
- }
+ m_eventQueue->AddEvent(event);
Event virtualEvent = CreateVirtualEvent(event);
if (virtualEvent.type != EVENT_NULL)
- {
- bool passOn = ProcessEvent(virtualEvent);
-
- if (m_engine != nullptr && passOn)
- passOn = m_engine->ProcessEvent(virtualEvent);
-
- if (passOn)
- m_eventQueue->AddEvent(virtualEvent);
- }
+ m_eventQueue->AddEvent(virtualEvent);
}
}
@@ -853,19 +917,11 @@ int CApplication::Run()
Event event = ProcessSystemEvent();
- if (event.type == EVENT_QUIT)
+ if (event.type == EVENT_SYS_QUIT)
goto end; // exit the loop
if (event.type != EVENT_NULL)
- {
- bool passOn = ProcessEvent(event);
-
- if (m_engine != nullptr && passOn)
- passOn = m_engine->ProcessEvent(event);
-
- if (passOn)
- m_eventQueue->AddEvent(event);
- }
+ m_eventQueue->AddEvent(event);
}
// Enter game update & frame rendering only if active
@@ -874,22 +930,17 @@ int CApplication::Run()
Event event;
while (m_eventQueue->GetEvent(event))
{
- if (event.type == EVENT_QUIT)
+ if (event.type == EVENT_SYS_QUIT || event.type == EVENT_QUIT)
goto end; // exit both loops
- bool passOn = true;
-
- // Skip system events (they have been processed earlier)
- if (! event.systemEvent)
- {
- passOn = ProcessEvent(event);
+ LogEvent(event);
- if (passOn && m_engine != nullptr)
- passOn = m_engine->ProcessEvent(event);
- }
+ bool passOn = true;
+ if (m_engine != nullptr)
+ passOn = m_engine->ProcessEvent(event);
if (passOn && m_robotMain != nullptr)
- m_robotMain->EventProcess(event);
+ m_robotMain->ProcessEvent(event);
}
StopPerformanceCounter(PCNT_EVENT_PROCESSING);
@@ -900,6 +951,8 @@ int CApplication::Run()
event = CreateUpdateEvent();
if (event.type != EVENT_NULL && m_robotMain != nullptr)
{
+ LogEvent(event);
+
StartPerformanceCounter(PCNT_UPDATE_ENGINE);
m_engine->FrameUpdate();
StopPerformanceCounter(PCNT_UPDATE_ENGINE);
@@ -907,7 +960,7 @@ int CApplication::Run()
m_sound->FrameMove(m_relTime);
StartPerformanceCounter(PCNT_UPDATE_GAME);
- m_robotMain->EventProcess(event);
+ m_robotMain->ProcessEvent(event);
StopPerformanceCounter(PCNT_UPDATE_GAME);
}
@@ -938,12 +991,12 @@ end:
return m_exitCode;
}
-int CApplication::GetExitCode()
+int CApplication::GetExitCode() const
{
return m_exitCode;
}
-const std::string& CApplication::GetErrorMessage()
+const std::string& CApplication::GetErrorMessage() const
{
return m_errorMessage;
}
@@ -953,11 +1006,10 @@ const std::string& CApplication::GetErrorMessage()
Event CApplication::ProcessSystemEvent()
{
Event event;
- event.systemEvent = true;
if (m_private->currentEvent.type == SDL_QUIT)
{
- event.type = EVENT_QUIT;
+ event.type = EVENT_SYS_QUIT;
}
else if (m_private->currentEvent.type == SDL_VIDEORESIZE)
{
@@ -1103,76 +1155,74 @@ Event CApplication::ProcessSystemEvent()
return event;
}
-/**
- * Processes incoming events. It is the first function called after an event is captured.
- * Event is modified, updating its tracked keys state and mouse position to current values.
- * Function returns \c true if the event is to be passed on to other processing functions
- * or \c false if not. */
-bool CApplication::ProcessEvent(const Event &event)
+void CApplication::LogEvent(const Event &event)
{
CLogger *l = GetLogger();
- // Print the events in debug mode to test the code
- if (m_debugMode)
+ auto PrintEventDetails = [&]()
{
- switch (event.type)
- {
- case EVENT_KEY_DOWN:
- case EVENT_KEY_UP:
- l->Trace("EVENT_KEY_%s:\n", (event.type == EVENT_KEY_DOWN) ? "DOWN" : "UP");
- l->Trace(" virt = %s\n", (event.key.virt) ? "true" : "false");
- l->Trace(" key = %d\n", event.key.key);
- l->Trace(" unicode = 0x%04x\n", event.key.unicode);
- break;
- case EVENT_MOUSE_MOVE:
- l->Trace("EVENT_MOUSE_MOVE:\n");
- break;
- case EVENT_MOUSE_BUTTON_DOWN:
- case EVENT_MOUSE_BUTTON_UP:
- l->Trace("EVENT_MOUSE_BUTTON_%s:\n", (event.type == EVENT_MOUSE_BUTTON_DOWN) ? "DOWN" : "UP");
- l->Trace(" button = %d\n", event.mouseButton.button);
- break;
- case EVENT_MOUSE_WHEEL:
- l->Trace("EVENT_MOUSE_WHEEL:\n");
- l->Trace(" dir = %s\n", (event.mouseWheel.dir == WHEEL_DOWN) ? "WHEEL_DOWN" : "WHEEL_UP");
- break;
- case EVENT_JOY_AXIS:
- l->Trace("EVENT_JOY_AXIS:\n");
- l->Trace(" axis = %d\n", event.joyAxis.axis);
- l->Trace(" value = %d\n", event.joyAxis.value);
- break;
- case EVENT_JOY_BUTTON_DOWN:
- case EVENT_JOY_BUTTON_UP:
- l->Trace("EVENT_JOY_BUTTON_%s:\n", (event.type == EVENT_JOY_BUTTON_DOWN) ? "DOWN" : "UP");
- l->Trace(" button = %d\n", event.joyButton.button);
- break;
- case EVENT_ACTIVE:
- l->Trace("EVENT_ACTIVE:\n");
- l->Trace(" flags = 0x%x\n", event.active.flags);
- l->Trace(" gain = %s\n", event.active.gain ? "true" : "false");
- break;
- default:
- l->Trace("Event type = %d:\n", static_cast<int>(event.type));
- break;
- }
-
- l->Trace(" systemEvent = %s\n", event.systemEvent ? "true" : "false");
l->Trace(" rTime = %f\n", event.rTime);
l->Trace(" kmodState = %04x\n", event.kmodState);
l->Trace(" trackedKeysState = %04x\n", event.trackedKeysState);
l->Trace(" mousePos = %f, %f\n", event.mousePos.x, event.mousePos.y);
l->Trace(" mouseButtonsState = %02x\n", event.mouseButtonsState);
- }
+ l->Trace(" customParam = %d\n", event.customParam);
+ };
- // By default, pass on all events
- return true;
+ // Print the events in debug mode to test the code
+ if (IsDebugModeActive(DEBUG_SYS_EVENTS) || IsDebugModeActive(DEBUG_APP_EVENTS))
+ {
+ std::string eventType = ParseEventType(event.type);
+
+ if (IsDebugModeActive(DEBUG_SYS_EVENTS) && event.type <= EVENT_SYS_MAX)
+ {
+ l->Trace("System event %s:\n", eventType.c_str());
+ switch (event.type)
+ {
+ case EVENT_KEY_DOWN:
+ case EVENT_KEY_UP:
+ l->Trace(" virt = %s\n", (event.key.virt) ? "true" : "false");
+ l->Trace(" key = %d\n", event.key.key);
+ l->Trace(" unicode = 0x%04x\n", event.key.unicode);
+ break;
+ case EVENT_MOUSE_BUTTON_DOWN:
+ case EVENT_MOUSE_BUTTON_UP:
+ l->Trace(" button = %d\n", event.mouseButton.button);
+ break;
+ case EVENT_MOUSE_WHEEL:
+ l->Trace(" dir = %s\n", (event.mouseWheel.dir == WHEEL_DOWN) ? "WHEEL_DOWN" : "WHEEL_UP");
+ break;
+ case EVENT_JOY_AXIS:
+ l->Trace(" axis = %d\n", event.joyAxis.axis);
+ l->Trace(" value = %d\n", event.joyAxis.value);
+ break;
+ case EVENT_JOY_BUTTON_DOWN:
+ case EVENT_JOY_BUTTON_UP:
+ l->Trace(" button = %d\n", event.joyButton.button);
+ break;
+ case EVENT_ACTIVE:
+ l->Trace(" flags = 0x%x\n", event.active.flags);
+ l->Trace(" gain = %s\n", event.active.gain ? "true" : "false");
+ break;
+ default:
+ break;
+ }
+
+ PrintEventDetails();
+ }
+
+ if (IsDebugModeActive(DEBUG_APP_EVENTS) && event.type > EVENT_SYS_MAX)
+ {
+ l->Trace("App event %s:\n", eventType.c_str());
+ PrintEventDetails();
+ }
+ }
}
Event CApplication::CreateVirtualEvent(const Event& sourceEvent)
{
Event virtualEvent;
- virtualEvent.systemEvent = true;
if ((sourceEvent.type == EVENT_KEY_DOWN) || (sourceEvent.type == EVENT_KEY_UP))
{
@@ -1228,16 +1278,27 @@ void CApplication::SuspendSimulation()
void CApplication::ResumeSimulation()
{
m_simulationSuspended = false;
+ InternalResumeSimulation();
+ GetLogger()->Info("Resume simulation\n");
+}
+
+void CApplication::ResetTimeAfterLoading()
+{
+ InternalResumeSimulation();
+
+ GetLogger()->Trace("Resume simulation on loading\n");
+}
+
+void CApplication::InternalResumeSimulation()
+{
GetSystemUtils()->GetCurrentTimeStamp(m_baseTimeStamp);
GetSystemUtils()->CopyTimeStamp(m_curTimeStamp, m_baseTimeStamp);
m_realAbsTimeBase = m_realAbsTime;
m_absTimeBase = m_exactAbsTime;
-
- GetLogger()->Info("Resume simulation\n");
}
-bool CApplication::GetSimulationSuspended()
+bool CApplication::GetSimulationSuspended() const
{
return m_simulationSuspended;
}
@@ -1269,7 +1330,7 @@ Event CApplication::CreateUpdateEvent()
{
GetLogger()->Error("Fatal error: got negative system counter difference!\n");
GetLogger()->Error("This should never happen. Please report this error.\n");
- m_eventQueue->AddEvent(Event(EVENT_QUIT));
+ m_eventQueue->AddEvent(Event(EVENT_SYS_QUIT));
return Event(EVENT_NULL);
}
else
@@ -1285,7 +1346,6 @@ Event CApplication::CreateUpdateEvent()
}
Event frameEvent(EVENT_FRAME);
- frameEvent.systemEvent = true;
frameEvent.trackedKeysState = m_trackedKeys;
frameEvent.kmodState = m_kmodState;
frameEvent.mousePos = m_mousePos;
@@ -1295,48 +1355,48 @@ Event CApplication::CreateUpdateEvent()
return frameEvent;
}
-float CApplication::GetSimulationSpeed()
+float CApplication::GetSimulationSpeed() const
{
return m_simulationSpeed;
}
-float CApplication::GetAbsTime()
+float CApplication::GetAbsTime() const
{
return m_absTime;
}
-long long CApplication::GetExactAbsTime()
+long long CApplication::GetExactAbsTime() const
{
return m_exactAbsTime;
}
-long long CApplication::GetRealAbsTime()
+long long CApplication::GetRealAbsTime() const
{
return m_realAbsTime;
}
-float CApplication::GetRelTime()
+float CApplication::GetRelTime() const
{
return m_relTime;
}
-long long CApplication::GetExactRelTime()
+long long CApplication::GetExactRelTime() const
{
return m_exactRelTime;
}
-long long CApplication::GetRealRelTime()
+long long CApplication::GetRealRelTime() const
{
return m_realRelTime;
}
-Gfx::GLDeviceConfig CApplication::GetVideoConfig()
+Gfx::GLDeviceConfig CApplication::GetVideoConfig() const
{
return m_deviceConfig;
}
VideoQueryResult CApplication::GetVideoResolutionList(std::vector<Math::IntPoint> &resolutions,
- bool fullScreen, bool resizeable)
+ bool fullScreen, bool resizeable) const
{
resolutions.clear();
@@ -1378,39 +1438,80 @@ VideoQueryResult CApplication::GetVideoResolutionList(std::vector<Math::IntPoint
return VIDEO_QUERY_OK;
}
-void CApplication::SetDebugMode(bool mode)
+void CApplication::SetDebugModeActive(DebugMode mode, bool active)
+{
+ if (active)
+ m_debugModes |= mode;
+ else
+ m_debugModes &= (~mode);
+}
+
+bool CApplication::IsDebugModeActive(DebugMode mode) const
{
- m_debugMode = mode;
+ return (m_debugModes & mode) != 0;
}
-bool CApplication::GetDebugMode()
+bool CApplication::ParseDebugModes(const std::string& str, int& debugModes)
{
- return m_debugMode;
+ debugModes = 0;
+
+ boost::char_separator<char> sep(",");
+ boost::tokenizer<boost::char_separator<char>> tokens(str, sep);
+ for (const auto& modeToken : tokens)
+ {
+ if (modeToken == "sys_events")
+ {
+ debugModes |= DEBUG_SYS_EVENTS;
+ }
+ else if (modeToken == "app_events")
+ {
+ debugModes |= DEBUG_APP_EVENTS;
+ }
+ else if (modeToken == "events")
+ {
+ debugModes |= DEBUG_EVENTS;
+ }
+ else if (modeToken == "models")
+ {
+ debugModes |= DEBUG_MODELS;
+ }
+ else if (modeToken == "all")
+ {
+ debugModes = DEBUG_ALL;
+ }
+ else
+ {
+ GetLogger()->Error("Invalid debug mode: '%s'\n", modeToken.c_str());
+ return false;
+ }
+ }
+
+ return true;
}
-int CApplication::GetKmods()
+int CApplication::GetKmods() const
{
return m_kmodState;
}
-bool CApplication::GetKmodState(int kmod)
+bool CApplication::GetKmodState(int kmod) const
{
return (m_kmodState & kmod) != 0;
}
-bool CApplication::GetTrackedKeyState(TrackedKey key)
+bool CApplication::GetTrackedKeyState(TrackedKey key) const
{
return (m_trackedKeys & key) != 0;
}
-bool CApplication::GetMouseButtonState(int index)
+bool CApplication::GetMouseButtonState(int index) const
{
return (m_mouseButtonsState & (1<<index)) != 0;
}
void CApplication::ResetKeyStates()
{
- GetLogger()->Info("Reset key states\n");
+ GetLogger()->Trace("Reset key states\n");
m_trackedKeys = 0;
m_kmodState = 0;
m_robotMain->ResetKeyStates();
@@ -1421,7 +1522,7 @@ void CApplication::SetGrabInput(bool grab)
SDL_WM_GrabInput(grab ? SDL_GRAB_ON : SDL_GRAB_OFF);
}
-bool CApplication::GetGrabInput()
+bool CApplication::GetGrabInput() const
{
int result = SDL_WM_GrabInput(SDL_GRAB_QUERY);
return result == SDL_GRAB_ON;
@@ -1436,12 +1537,12 @@ void CApplication::SetMouseMode(MouseMode mode)
SDL_ShowCursor(SDL_DISABLE);
}
-MouseMode CApplication::GetMouseMode()
+MouseMode CApplication::GetMouseMode() const
{
return m_mouseMode;
}
-Math::Point CApplication::GetMousePos()
+Math::Point CApplication::GetMousePos() const
{
return m_mousePos;
}
@@ -1454,7 +1555,7 @@ void CApplication::MoveMouse(Math::Point pos)
SDL_WarpMouse(windowPos.x, windowPos.y);
}
-std::vector<JoystickDevice> CApplication::GetJoystickList()
+std::vector<JoystickDevice> CApplication::GetJoystickList() const
{
std::vector<JoystickDevice> result;
@@ -1471,7 +1572,7 @@ std::vector<JoystickDevice> CApplication::GetJoystickList()
return result;
}
-JoystickDevice CApplication::GetJoystick()
+JoystickDevice CApplication::GetJoystick() const
{
return m_joystick;
}
@@ -1493,36 +1594,37 @@ void CApplication::SetJoystickEnabled(bool enable)
}
}
-bool CApplication::GetJoystickEnabled()
+bool CApplication::GetJoystickEnabled() const
{
return m_joystickEnabled;
}
-std::string CApplication::GetDataDirPath()
+std::string CApplication::GetDataDirPath() const
{
return m_dataPath;
}
-std::string CApplication::GetDataSubdirPath(DataDir stdDir)
+std::string CApplication::GetDataSubdirPath(DataDir stdDir) const
{
int index = static_cast<int>(stdDir);
assert(index >= 0 && index < DIR_MAX);
std::stringstream str;
str << m_dataPath;
str << "/";
- str << m_dataDirs[index];
+ str << m_standardDataDirs[index];
return str.str();
}
-std::string CApplication::GetDataFilePath(DataDir stdDir, const std::string& subpath)
+std::string CApplication::GetDataFilePath(DataDir stdDir, const std::string& subpath) const
{
int index = static_cast<int>(stdDir);
assert(index >= 0 && index < DIR_MAX);
std::stringstream str;
str << m_dataPath;
str << "/";
- str << m_dataDirs[index];
- if (stdDir == DIR_HELP) {
+ str << m_standardDataDirs[index];
+ if (stdDir == DIR_HELP)
+ {
str << "/";
str << GetLanguageChar();
}
@@ -1531,12 +1633,31 @@ std::string CApplication::GetDataFilePath(DataDir stdDir, const std::string& sub
return str.str();
}
-Language CApplication::GetLanguage()
+std::string CApplication::GetTexPackFilePath(const std::string& textureName) const
+{
+ std::stringstream str;
+
+ if (! m_texPackPath.empty())
+ {
+ str << m_texPackPath;
+ str << "/";
+ str << textureName;
+ if (! boost::filesystem::exists(str.str()))
+ {
+ GetLogger()->Trace("Texture '%s' not in texpack\n", textureName.c_str());
+ str.str("");
+ }
+ }
+
+ return str.str();
+}
+
+Language CApplication::GetLanguage() const
{
return m_language;
}
-char CApplication::GetLanguageChar()
+char CApplication::GetLanguageChar() const
{
char langChar = 'E';
switch (m_language)
@@ -1621,33 +1742,38 @@ void CApplication::SetLanguage(Language language)
if (locale.empty())
{
- char *envLang = getenv("LANGUAGE");
- if (envLang == NULL)
- {
- envLang = getenv("LANG");
- }
+ const char* envLang = gl_locale_name(LC_MESSAGES, "LC_MESSAGES");
if (envLang == NULL)
{
- GetLogger()->Error("Failed to get language from environment, setting default language");
+ GetLogger()->Error("Failed to get language from environment, setting default language\n");
m_language = LANGUAGE_ENGLISH;
}
- else if (strncmp(envLang,"en",2) == 0)
- {
- m_language = LANGUAGE_ENGLISH;
- }
- else if (strncmp(envLang,"de",2) == 0)
- {
- m_language = LANGUAGE_GERMAN;
- }
- else if (strncmp(envLang,"fr",2) == 0)
- {
- m_language = LANGUAGE_FRENCH;
- }
- else if (strncmp(envLang,"pl",2) == 0)
+ else
{
- m_language = LANGUAGE_POLISH;
+ GetLogger()->Trace("gl_locale_name: '%s'\n", envLang);
+
+ if (strncmp(envLang,"en",2) == 0)
+ {
+ m_language = LANGUAGE_ENGLISH;
+ }
+ else if (strncmp(envLang,"de",2) == 0)
+ {
+ m_language = LANGUAGE_GERMAN;
+ }
+ else if (strncmp(envLang,"fr",2) == 0)
+ {
+ m_language = LANGUAGE_FRENCH;
+ }
+ else if (strncmp(envLang,"pl",2) == 0)
+ {
+ m_language = LANGUAGE_POLISH;
+ }
+ else
+ {
+ GetLogger()->Warn("Enviromnent locale ('%s') is not supported, setting default language\n", envLang);
+ m_language = LANGUAGE_ENGLISH;
+ }
}
- GetLogger()->Trace("SetLanguage: Inherit LANGUAGE=%s from environment\n", envLang);
}
else
{
@@ -1657,6 +1783,7 @@ void CApplication::SetLanguage(Language language)
putenv(S_LANGUAGE);
GetLogger()->Trace("SetLanguage: Set LANGUAGE=%s in environment\n", locale.c_str());
}
+
setlocale(LC_ALL, "");
bindtextdomain("colobot", m_langPath.c_str());
@@ -1671,7 +1798,7 @@ void CApplication::SetLowCPU(bool low)
m_lowCPU = low;
}
-bool CApplication::GetLowCPU()
+bool CApplication::GetLowCPU() const
{
return m_lowCPU;
}
@@ -1686,7 +1813,7 @@ void CApplication::StopPerformanceCounter(PerformanceCounter counter)
GetSystemUtils()->GetCurrentTimeStamp(m_performanceCounters[counter][1]);
}
-float CApplication::GetPerformanceCounterData(PerformanceCounter counter)
+float CApplication::GetPerformanceCounterData(PerformanceCounter counter) const
{
return m_performanceCountersData[counter];
}
@@ -1715,3 +1842,8 @@ void CApplication::UpdatePerformanceCountersData()
}
}
+bool CApplication::GetProtoMode() const
+{
+ return m_protoMode;
+}
+
diff --git a/src/app/app.h b/src/app/app.h
index dcc90e0..269fa9b 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -31,6 +31,8 @@
#include "graphics/engine/engine.h"
#include "graphics/opengl/gldevice.h"
+#include "object/objman.h"
+
#include <string>
#include <vector>
@@ -141,6 +143,15 @@ enum PerformanceCounter
PCNT_MAX
};
+enum DebugMode
+{
+ DEBUG_SYS_EVENTS = 1 << 0,
+ DEBUG_APP_EVENTS = 1 << 1,
+ DEBUG_EVENTS = DEBUG_SYS_EVENTS | DEBUG_APP_EVENTS,
+ DEBUG_MODELS = 1 << 2,
+ DEBUG_ALL = DEBUG_SYS_EVENTS | DEBUG_APP_EVENTS | DEBUG_MODELS
+};
+
struct ApplicationPrivate;
/**
@@ -207,20 +218,20 @@ public:
//! Main event loop
int Run();
//! Returns the code to be returned at main() exit
- int GetExitCode();
+ int GetExitCode() const;
//! Returns the message of error (set to something if exit code is not 0)
- const std::string& GetErrorMessage();
+ const std::string& GetErrorMessage() const;
//! Cleans up before exit
void Destroy();
//! Returns a list of possible video modes
VideoQueryResult GetVideoResolutionList(std::vector<Math::IntPoint> &resolutions,
- bool fullScreen, bool resizeable);
+ bool fullScreen, bool resizeable) const;
//! Returns the current video mode
- Gfx::GLDeviceConfig GetVideoConfig();
+ Gfx::GLDeviceConfig GetVideoConfig() const;
//! Change the video mode to given mode
bool ChangeVideoConfig(const Gfx::GLDeviceConfig &newConfig);
@@ -230,35 +241,38 @@ public:
//! Resumes animation
void ResumeSimulation();
//! Returns whether simulation is suspended
- bool GetSimulationSuspended();
+ bool GetSimulationSuspended() const;
+
+ //! Resets time counters to account for time spent loading game
+ void ResetTimeAfterLoading();
//@{
//! Management of simulation speed
void SetSimulationSpeed(float speed);
- float GetSimulationSpeed();
+ float GetSimulationSpeed() const;
//@}
//! Returns the absolute time counter [seconds]
- float GetAbsTime();
+ float GetAbsTime() const;
//! Returns the exact absolute time counter [nanoseconds]
- long long GetExactAbsTime();
+ long long GetExactAbsTime() const;
//! Returns the exact absolute time counter disregarding speed setting [nanoseconds]
- long long GetRealAbsTime();
+ long long GetRealAbsTime() const;
//! Returns the relative time since last update [seconds]
- float GetRelTime();
+ float GetRelTime() const;
//! Returns the exact realative time since last update [nanoseconds]
- long long GetExactRelTime();
+ long long GetExactRelTime() const;
//! Returns the exact relative time since last update disregarding speed setting [nanoseconds]
- long long GetRealRelTime();
+ long long GetRealRelTime() const;
//! Returns a list of available joystick devices
- std::vector<JoystickDevice> GetJoystickList();
+ std::vector<JoystickDevice> GetJoystickList() const;
//! Returns info about the current joystick
- JoystickDevice GetJoystick();
+ JoystickDevice GetJoystick() const;
//! Change the current joystick device
bool ChangeJoystick(const JoystickDevice &newJoystick);
@@ -266,7 +280,7 @@ public:
//! Management of joystick enable state
//@{
void SetJoystickEnabled(bool enable);
- bool GetJoystickEnabled();
+ bool GetJoystickEnabled() const;
//@}
//! Polls the state of joystick axes and buttons
@@ -276,15 +290,15 @@ public:
void UpdateMouse();
//! Returns the current key modifiers
- int GetKmods();
+ int GetKmods() const;
//! Returns whether the given kmod is active
- bool GetKmodState(int kmod);
+ bool GetKmodState(int kmod) const;
//! Returns whether the tracked key is pressed
- bool GetTrackedKeyState(TrackedKey key);
+ bool GetTrackedKeyState(TrackedKey key) const;
//! Returns whether the mouse button is pressed
- bool GetMouseButtonState(int index);
+ bool GetMouseButtonState(int index) const;
//! Resets tracked key states and modifiers
void ResetKeyStates();
@@ -292,40 +306,44 @@ public:
//! Management of the grab mode for input (keyboard & mouse)
//@{
void SetGrabInput(bool grab);
- bool GetGrabInput();
+ bool GetGrabInput() const;
//@}
//! Management of mouse mode
//@{
void SetMouseMode(MouseMode mode);
- MouseMode GetMouseMode();
+ MouseMode GetMouseMode() const;
//@}
//! Returns the position of mouse cursor (in interface coords)
- Math::Point GetMousePos();
+ Math::Point GetMousePos() const;
//! Moves (warps) the mouse cursor to the specified position (in interface coords)
void MoveMouse(Math::Point pos);
- //! Management of debug mode (prints more info in logger)
+ //! Management of debug modes (printing more info in logger)
//@{
- void SetDebugMode(bool mode);
- bool GetDebugMode();
+ void SetDebugModeActive(DebugMode mode, bool active);
+ bool IsDebugModeActive(DebugMode mode) const;
+ static bool ParseDebugModes(const std::string& str, int& debugModes);
//@}
//! Returns the full path to data directory
- std::string GetDataDirPath();
+ std::string GetDataDirPath() const;
//! Returns the full path to a standard dir in data directory
- std::string GetDataSubdirPath(DataDir stdDir);
+ std::string GetDataSubdirPath(DataDir stdDir) const;
//! Returns the full path to a file in data directory given standard dir and subpath
- std::string GetDataFilePath(DataDir stdDir, const std::string &subpath);
+ std::string GetDataFilePath(DataDir stdDir, const std::string &subpath) const;
+
+ //! Returns the full path to a file in texture pack directory
+ std::string GetTexPackFilePath(const std::string& textureName) const;
//! Management of language
//@{
- Language GetLanguage();
- char GetLanguageChar();
+ Language GetLanguage() const;
+ char GetLanguageChar() const;
void SetLanguage(Language language);
static bool ParseLanguage(const std::string& str, Language& language);
//@}
@@ -333,16 +351,18 @@ public:
//! Management of sleep in main loop (lowers CPU usage)
//@{
void SetLowCPU(bool low);
- bool GetLowCPU();
+ bool GetLowCPU() const;
//@}
//! Management of performance counters
//@{
void StartPerformanceCounter(PerformanceCounter counter);
void StopPerformanceCounter(PerformanceCounter counter);
- float GetPerformanceCounterData(PerformanceCounter counter);
+ float GetPerformanceCounterData(PerformanceCounter counter) const;
//@}
+ bool GetProtoMode() const;
+
protected:
//! Creates the window's SDL_Surface
bool CreateVideoSurface();
@@ -353,8 +373,8 @@ protected:
Event CreateVirtualEvent(const Event& sourceEvent);
//! Prepares a simulation update event
TEST_VIRTUAL Event CreateUpdateEvent();
- //! Handles some incoming events
- bool ProcessEvent(const Event& event);
+ //! Logs debug data for event
+ void LogEvent(const Event& event);
//! Renders the image in window
void Render();
@@ -363,6 +383,9 @@ protected:
//! Closes the joystick device
void CloseJoystick();
+ //! Internal procedure to reset time counters
+ void InternalResumeSimulation();
+
//! Resets all performance counters to zero
void ResetPerformanceCounters();
//! Updates performance counters from gathered timer data
@@ -374,6 +397,8 @@ protected:
//! Instance manager
// TODO: to be removed
CInstanceManager* m_iMan;
+ //! Object manager
+ CObjectManager* m_objMan;
//! Global event queue
CEventQueue* m_eventQueue;
//! Graphics engine
@@ -393,8 +418,8 @@ protected:
int m_exitCode;
//! Whether application window is active
bool m_active;
- //! Whether debug mode is enabled
- bool m_debugMode;
+ //! Bit array of active debug modes
+ long m_debugModes;
//! Message to be displayed as error to the user
std::string m_errorMessage;
@@ -458,12 +483,24 @@ protected:
//! Path to directory with language files
std::string m_langPath;
- const char* m_dataDirs[DIR_MAX];
+ //! Path to directory with user texture pack
+ std::string m_texPackPath;
+
+ //@{
+ //! Scene to run on startup
+ std::string m_runSceneName;
+ int m_runSceneRank;
+ //@}
+
+ const char* m_standardDataDirs[DIR_MAX];
//! Application language
Language m_language;
//! Low cpu mode
bool m_lowCPU;
+
+ //! Show prototype levels
+ bool m_protoMode;
};
diff --git a/src/app/main.cpp b/src/app/main.cpp
index edb5828..5c0afd3 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -78,7 +78,9 @@ int SDL_MAIN_FUNC(int argc, char *argv[])
{
CLogger logger; // single istance of logger
- InitializeRestext(); // init static translation strings
+ // Initialize static string arrays
+ InitializeRestext();
+ InitializeEventTypeTexts();
CSystemUtils* systemUtils = CSystemUtils::Create(); // platform-specific utils
systemUtils->Init();
@@ -122,3 +124,4 @@ int SDL_MAIN_FUNC(int argc, char *argv[])
}
} // extern "C"
+
diff --git a/src/app/system.cpp b/src/app/system.cpp
index 743ed96..2eb68ba 100644
--- a/src/app/system.cpp
+++ b/src/app/system.cpp
@@ -188,12 +188,13 @@ float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *afte
return result;
}
-std::string CSystemUtils::profileFileLocation()
+std::string CSystemUtils::GetProfileFileLocation()
{
- return std::string("colobot.ini");
+ return std::string("colobot.ini");
}
-std::string CSystemUtils::savegameDirectoryLocation()
+std::string CSystemUtils::GetSavegameDirectoryLocation()
{
- return std::string("savegame");
+ return std::string("savegame");
}
+
diff --git a/src/app/system.h b/src/app/system.h
index 6ae05d6..d22a519 100644
--- a/src/app/system.h
+++ b/src/app/system.h
@@ -131,10 +131,10 @@ public:
virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) = 0;
//! Returns the profile (colobot.ini) file location
- virtual std::string profileFileLocation();
+ virtual std::string GetProfileFileLocation();
//! Returns the savegame directory location
- virtual std::string savegameDirectoryLocation();
+ virtual std::string GetSavegameDirectoryLocation();
};
//! Global function to get CSystemUtils instance
@@ -142,3 +142,4 @@ inline CSystemUtils* GetSystemUtils()
{
return CSystemUtils::GetInstancePointer();
}
+
diff --git a/src/app/system_linux.cpp b/src/app/system_linux.cpp
index 01dd850..492af7d 100644
--- a/src/app/system_linux.cpp
+++ b/src/app/system_linux.cpp
@@ -95,9 +95,9 @@ long long CSystemUtilsLinux::TimeStampExactDiff(SystemTimeStamp *before, SystemT
(after->clockTime.tv_sec - before->clockTime.tv_sec) * 1000000000ll;
}
-std::string CSystemUtilsLinux::profileFileLocation()
+std::string CSystemUtilsLinux::GetProfileFileLocation()
{
- std::string m_profileFile;
+ std::string profileFile;
// Determine profileFile according to XDG Base Directory Specification
char* envXDG_CONFIG_HOME = getenv("XDG_CONFIG_HOME");
@@ -106,25 +106,25 @@ std::string CSystemUtilsLinux::profileFileLocation()
char *envHOME = getenv("HOME");
if (envHOME == NULL)
{
- m_profileFile = "colobot.ini";
+ profileFile = "colobot.ini";
}
else
{
- m_profileFile = std::string(envHOME) + "/.config/colobot.ini";
+ profileFile = std::string(envHOME) + "/.config/colobot.ini";
}
}
else
{
- m_profileFile = std::string(envXDG_CONFIG_HOME) + "/colobot.ini";
+ profileFile = std::string(envXDG_CONFIG_HOME) + "/colobot.ini";
}
- GetLogger()->Trace("Profile configuration is %s\n", m_profileFile.c_str());
+ GetLogger()->Trace("Profile configuration is %s\n", profileFile.c_str());
- return m_profileFile;
+ return profileFile;
}
-std::string CSystemUtilsLinux::savegameDirectoryLocation()
+std::string CSystemUtilsLinux::GetSavegameDirectoryLocation()
{
- std::string m_savegameDir;
+ std::string savegameDir;
// Determine savegame dir according to XDG Base Directory Specification
char *envXDG_DATA_HOME = getenv("XDG_CONFIG_DATA");
@@ -133,18 +133,19 @@ std::string CSystemUtilsLinux::savegameDirectoryLocation()
char *envHOME = getenv("HOME");
if (envHOME == NULL)
{
- m_savegameDir = "/tmp/colobot-savegame";
+ savegameDir = "/tmp/colobot-savegame";
}
else
- {
- m_savegameDir = std::string(envHOME) + "/.local/share/colobot";
+ {
+ savegameDir = std::string(envHOME) + "/.local/share/colobot";
}
}
else
{
- m_savegameDir = std::string(envXDG_DATA_HOME) + "/colobot";
+ savegameDir = std::string(envXDG_DATA_HOME) + "/colobot";
}
- GetLogger()->Trace("Saved game files are going to %s\n", m_savegameDir.c_str());
+ GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
- return m_savegameDir;
+ return savegameDir;
}
+
diff --git a/src/app/system_linux.h b/src/app/system_linux.h
index a9a5a52..212d840 100644
--- a/src/app/system_linux.h
+++ b/src/app/system_linux.h
@@ -46,9 +46,10 @@ public:
virtual long long GetTimeStampExactResolution() override;
virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override;
- virtual std::string profileFileLocation() override;
- virtual std::string savegameDirectoryLocation() override;
+ virtual std::string GetProfileFileLocation() override;
+ virtual std::string GetSavegameDirectoryLocation() override;
private:
bool m_zenityAvailable;
};
+
diff --git a/src/app/system_other.cpp b/src/app/system_other.cpp
index 9fc1f95..da81a6d 100644
--- a/src/app/system_other.cpp
+++ b/src/app/system_other.cpp
@@ -37,3 +37,4 @@ long long int CSystemUtilsOther::TimeStampExactDiff(SystemTimeStamp* before, Sys
{
return (after->sdlTicks - before->sdlTicks) * 1000000ll;
}
+
diff --git a/src/app/system_other.h b/src/app/system_other.h
index bf16c80..b10a326 100644
--- a/src/app/system_other.h
+++ b/src/app/system_other.h
@@ -46,3 +46,4 @@ public:
virtual long long GetTimeStampExactResolution() override;
virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override;
};
+
diff --git a/src/app/system_windows.cpp b/src/app/system_windows.cpp
index 870683f..f48d4e0 100644
--- a/src/app/system_windows.cpp
+++ b/src/app/system_windows.cpp
@@ -111,38 +111,39 @@ std::wstring CSystemUtilsWindows::UTF8_Decode(const std::string& str)
}
-std::string CSystemUtilsWindows::profileFileLocation()
+std::string CSystemUtilsWindows::GetProfileFileLocation()
{
- std::string m_profileFile;
+ std::string profileFile;
char* envUSERPROFILE = getenv("USERPROFILE");
if (envUSERPROFILE == NULL)
{
- m_profileFile = "colobot.ini";
+ profileFile = "colobot.ini";
}
else
{
- m_profileFile = std::string(envUSERPROFILE) + "\\colobot\\colobot.ini";
+ profileFile = std::string(envUSERPROFILE) + "\\colobot\\colobot.ini";
}
- GetLogger()->Trace("Profile configuration is %s\n", m_profileFile.c_str());
+ GetLogger()->Trace("Profile configuration is %s\n", profileFile.c_str());
- return m_profileFile;
+ return profileFile;
}
-std::string CSystemUtilsWindows::savegameDirectoryLocation()
+std::string CSystemUtilsWindows::GetSavegameDirectoryLocation()
{
- std::string m_savegameDir;
+ std::string savegameDir;
char* envUSERPROFILE = getenv("USERPROFILE");
if (envUSERPROFILE == NULL)
{
- m_savegameDir = "savegame";
+ savegameDir = "savegame";
}
else
{
- m_savegameDir = std::string(envUSERPROFILE) + "\\colobot\\savegame";
+ savegameDir = std::string(envUSERPROFILE) + "\\colobot\\savegame";
}
- GetLogger()->Trace("Saved game files are going to %s\n", m_savegameDir.c_str());
+ GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str());
+
+ return savegameDir;
+}
- return m_savegameDir;
-} \ No newline at end of file
diff --git a/src/app/system_windows.h b/src/app/system_windows.h
index 88e7507..fbc71a1 100644
--- a/src/app/system_windows.h
+++ b/src/app/system_windows.h
@@ -44,8 +44,8 @@ public:
virtual long long GetTimeStampExactResolution() override;
virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override;
- virtual std::string profileFileLocation() override;
- virtual std::string savegameDirectoryLocation() override;
+ virtual std::string GetProfileFileLocation() override;
+ virtual std::string GetSavegameDirectoryLocation() override;
private:
std::string UTF8_Encode(const std::wstring &wstr);
@@ -54,3 +54,4 @@ private:
protected:
long long m_counterFrequency;
};
+
diff --git a/src/common/.gitignore b/src/common/.gitignore
new file mode 100644
index 0000000..a13f82d
--- /dev/null
+++ b/src/common/.gitignore
@@ -0,0 +1,2 @@
+# CMake config header
+config.h
diff --git a/src/common/README.txt b/src/common/README.txt
index 25c9fbf..1fc21f1 100644
--- a/src/common/README.txt
+++ b/src/common/README.txt
@@ -2,3 +2,4 @@
* \dir src/common
* \brief Structs and utils shared throughout the application
*/
+
diff --git a/src/common/config.h.cmake b/src/common/config.h.cmake
index d5a03b4..76b37b5 100644
--- a/src/common/config.h.cmake
+++ b/src/common/config.h.cmake
@@ -23,3 +23,4 @@
#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@"
#define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@"
+
diff --git a/src/common/event.cpp b/src/common/event.cpp
index ff3fbc7..7acac77 100644
--- a/src/common/event.cpp
+++ b/src/common/event.cpp
@@ -19,15 +19,541 @@
#include "common/logger.h"
-static EventType g_uniqueEventType = EVENT_USER;
+namespace
+{
+static EventType UNIQUE_EVENT_TYPE = EVENT_USER;
+const char* EVENT_TYPE_TEXT[EVENT_STD_MAX];
+}
+EventType GetUniqueEventType()
+{
+ int i = static_cast<int>(UNIQUE_EVENT_TYPE+1);
+ UNIQUE_EVENT_TYPE = static_cast<EventType>(i);
+ return UNIQUE_EVENT_TYPE;
+}
+void InitializeEventTypeTexts()
+{
+ for (int i = 0; i < EVENT_STD_MAX; ++i)
+ EVENT_TYPE_TEXT[i] = "";
-EventType GetUniqueEventType()
+ EVENT_TYPE_TEXT[EVENT_NULL] = "EVENT_NULL";
+
+ EVENT_TYPE_TEXT[EVENT_QUIT] = "EVENT_QUIT";
+
+ EVENT_TYPE_TEXT[EVENT_FRAME] = "EVENT_FRAME";
+
+ EVENT_TYPE_TEXT[EVENT_MOUSE_BUTTON_DOWN] = "EVENT_MOUSE_BUTTON_DOWN";
+ EVENT_TYPE_TEXT[EVENT_MOUSE_BUTTON_UP] = "EVENT_MOUSE_BUTTON_UP";
+ EVENT_TYPE_TEXT[EVENT_MOUSE_WHEEL] = "EVENT_MOUSE_WHEEL";
+ EVENT_TYPE_TEXT[EVENT_MOUSE_MOVE] = "EVENT_MOUSE_MOVE";
+ EVENT_TYPE_TEXT[EVENT_KEY_DOWN] = "EVENT_KEY_DOWN";
+ EVENT_TYPE_TEXT[EVENT_KEY_UP] = "EVENT_KEY_UP";
+
+ EVENT_TYPE_TEXT[EVENT_ACTIVE] = "EVENT_ACTIVE";
+
+ EVENT_TYPE_TEXT[EVENT_JOY_AXIS] = "EVENT_JOY_AXIS";
+ EVENT_TYPE_TEXT[EVENT_JOY_BUTTON_DOWN] = "EVENT_JOY_BUTTON_DOWN";
+ EVENT_TYPE_TEXT[EVENT_JOY_BUTTON_UP] = "EVENT_JOY_BUTTON_UP";
+
+
+ EVENT_TYPE_TEXT[EVENT_UPDINTERFACE] = "EVENT_UPDINTERFACE";
+ EVENT_TYPE_TEXT[EVENT_WIN] = "EVENT_WIN";
+ EVENT_TYPE_TEXT[EVENT_LOST] = "EVENT_LOST";
+
+ EVENT_TYPE_TEXT[EVENT_FOCUS] = "EVENT_FOCUS";
+
+ EVENT_TYPE_TEXT[EVENT_BUTTON_OK] = "EVENT_BUTTON_OK";
+ EVENT_TYPE_TEXT[EVENT_BUTTON_CANCEL] = "EVENT_BUTTON_CANCEL";
+ EVENT_TYPE_TEXT[EVENT_BUTTON_NEXT] = "EVENT_BUTTON_NEXT";
+ EVENT_TYPE_TEXT[EVENT_BUTTON_PREV] = "EVENT_BUTTON_PREV";
+ EVENT_TYPE_TEXT[EVENT_BUTTON_QUIT] = "EVENT_BUTTON_QUIT";
+
+ EVENT_TYPE_TEXT[EVENT_BUTTON0] = "EVENT_BUTTON0";
+ EVENT_TYPE_TEXT[EVENT_BUTTON1] = "EVENT_BUTTON1";
+ EVENT_TYPE_TEXT[EVENT_BUTTON2] = "EVENT_BUTTON2";
+ EVENT_TYPE_TEXT[EVENT_BUTTON3] = "EVENT_BUTTON3";
+ EVENT_TYPE_TEXT[EVENT_BUTTON4] = "EVENT_BUTTON4";
+ EVENT_TYPE_TEXT[EVENT_BUTTON5] = "EVENT_BUTTON5";
+ EVENT_TYPE_TEXT[EVENT_BUTTON6] = "EVENT_BUTTON6";
+ EVENT_TYPE_TEXT[EVENT_BUTTON7] = "EVENT_BUTTON7";
+ EVENT_TYPE_TEXT[EVENT_BUTTON8] = "EVENT_BUTTON8";
+ EVENT_TYPE_TEXT[EVENT_BUTTON9] = "EVENT_BUTTON9";
+ EVENT_TYPE_TEXT[EVENT_BUTTON10] = "EVENT_BUTTON10";
+ EVENT_TYPE_TEXT[EVENT_BUTTON11] = "EVENT_BUTTON11";
+ EVENT_TYPE_TEXT[EVENT_BUTTON12] = "EVENT_BUTTON12";
+ EVENT_TYPE_TEXT[EVENT_BUTTON13] = "EVENT_BUTTON13";
+ EVENT_TYPE_TEXT[EVENT_BUTTON14] = "EVENT_BUTTON14";
+ EVENT_TYPE_TEXT[EVENT_BUTTON15] = "EVENT_BUTTON15";
+ EVENT_TYPE_TEXT[EVENT_BUTTON16] = "EVENT_BUTTON16";
+ EVENT_TYPE_TEXT[EVENT_BUTTON17] = "EVENT_BUTTON17";
+ EVENT_TYPE_TEXT[EVENT_BUTTON18] = "EVENT_BUTTON18";
+ EVENT_TYPE_TEXT[EVENT_BUTTON19] = "EVENT_BUTTON19";
+
+ EVENT_TYPE_TEXT[EVENT_EDIT0] = "EVENT_EDIT0";
+ EVENT_TYPE_TEXT[EVENT_EDIT1] = "EVENT_EDIT1";
+ EVENT_TYPE_TEXT[EVENT_EDIT2] = "EVENT_EDIT2";
+ EVENT_TYPE_TEXT[EVENT_EDIT3] = "EVENT_EDIT3";
+ EVENT_TYPE_TEXT[EVENT_EDIT4] = "EVENT_EDIT4";
+ EVENT_TYPE_TEXT[EVENT_EDIT5] = "EVENT_EDIT5";
+ EVENT_TYPE_TEXT[EVENT_EDIT6] = "EVENT_EDIT6";
+ EVENT_TYPE_TEXT[EVENT_EDIT7] = "EVENT_EDIT7";
+ EVENT_TYPE_TEXT[EVENT_EDIT8] = "EVENT_EDIT8";
+ EVENT_TYPE_TEXT[EVENT_EDIT9] = "EVENT_EDIT9";
+
+ EVENT_TYPE_TEXT[EVENT_WINDOW0] = "EVENT_WINDOW0";
+ EVENT_TYPE_TEXT[EVENT_WINDOW1] = "EVENT_WINDOW1";
+ EVENT_TYPE_TEXT[EVENT_WINDOW2] = "EVENT_WINDOW2";
+ EVENT_TYPE_TEXT[EVENT_WINDOW3] = "EVENT_WINDOW3";
+ EVENT_TYPE_TEXT[EVENT_WINDOW4] = "EVENT_WINDOW4";
+ EVENT_TYPE_TEXT[EVENT_WINDOW5] = "EVENT_WINDOW5";
+ EVENT_TYPE_TEXT[EVENT_WINDOW6] = "EVENT_WINDOW6";
+ EVENT_TYPE_TEXT[EVENT_WINDOW7] = "EVENT_WINDOW7";
+ EVENT_TYPE_TEXT[EVENT_WINDOW8] = "EVENT_WINDOW8";
+ EVENT_TYPE_TEXT[EVENT_WINDOW9] = "EVENT_WINDOW9";
+
+ EVENT_TYPE_TEXT[EVENT_LABEL0] = "EVENT_LABEL0";
+ EVENT_TYPE_TEXT[EVENT_LABEL1] = "EVENT_LABEL1";
+ EVENT_TYPE_TEXT[EVENT_LABEL2] = "EVENT_LABEL2";
+ EVENT_TYPE_TEXT[EVENT_LABEL3] = "EVENT_LABEL3";
+ EVENT_TYPE_TEXT[EVENT_LABEL4] = "EVENT_LABEL4";
+ EVENT_TYPE_TEXT[EVENT_LABEL5] = "EVENT_LABEL5";
+ EVENT_TYPE_TEXT[EVENT_LABEL6] = "EVENT_LABEL6";
+ EVENT_TYPE_TEXT[EVENT_LABEL7] = "EVENT_LABEL7";
+ EVENT_TYPE_TEXT[EVENT_LABEL8] = "EVENT_LABEL8";
+ EVENT_TYPE_TEXT[EVENT_LABEL9] = "EVENT_LABEL9";
+ EVENT_TYPE_TEXT[EVENT_LABEL10] = "EVENT_LABEL10";
+ EVENT_TYPE_TEXT[EVENT_LABEL11] = "EVENT_LABEL11";
+ EVENT_TYPE_TEXT[EVENT_LABEL12] = "EVENT_LABEL12";
+ EVENT_TYPE_TEXT[EVENT_LABEL13] = "EVENT_LABEL13";
+ EVENT_TYPE_TEXT[EVENT_LABEL14] = "EVENT_LABEL14";
+ EVENT_TYPE_TEXT[EVENT_LABEL15] = "EVENT_LABEL15";
+ EVENT_TYPE_TEXT[EVENT_LABEL16] = "EVENT_LABEL16";
+ EVENT_TYPE_TEXT[EVENT_LABEL17] = "EVENT_LABEL17";
+ EVENT_TYPE_TEXT[EVENT_LABEL18] = "EVENT_LABEL18";
+ EVENT_TYPE_TEXT[EVENT_LABEL19] = "EVENT_LABEL19";
+
+ EVENT_TYPE_TEXT[EVENT_LIST0] = "EVENT_LIST0";
+ EVENT_TYPE_TEXT[EVENT_LIST1] = "EVENT_LIST1";
+ EVENT_TYPE_TEXT[EVENT_LIST2] = "EVENT_LIST2";
+ EVENT_TYPE_TEXT[EVENT_LIST3] = "EVENT_LIST3";
+ EVENT_TYPE_TEXT[EVENT_LIST4] = "EVENT_LIST4";
+ EVENT_TYPE_TEXT[EVENT_LIST5] = "EVENT_LIST5";
+ EVENT_TYPE_TEXT[EVENT_LIST6] = "EVENT_LIST6";
+ EVENT_TYPE_TEXT[EVENT_LIST7] = "EVENT_LIST7";
+ EVENT_TYPE_TEXT[EVENT_LIST8] = "EVENT_LIST8";
+ EVENT_TYPE_TEXT[EVENT_LIST9] = "EVENT_LIST9";
+
+ EVENT_TYPE_TEXT[EVENT_TOOLTIP] = "EVENT_TOOLTIP";
+
+ EVENT_TYPE_TEXT[EVENT_DIALOG_OK] = "EVENT_DIALOG_OK";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_CANCEL] = "EVENT_DIALOG_CANCEL";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_LABEL] = "EVENT_DIALOG_LABEL";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_LABEL1] = "EVENT_DIALOG_LABEL1";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_LABEL2] = "EVENT_DIALOG_LABEL2";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_LABEL3] = "EVENT_DIALOG_LABEL3";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_LIST] = "EVENT_DIALOG_LIST";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_EDIT] = "EVENT_DIALOG_EDIT";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_CHECK1] = "EVENT_DIALOG_CHECK1";
+ EVENT_TYPE_TEXT[EVENT_DIALOG_CHECK2] = "EVENT_DIALOG_CHECK2";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_TRAINER] = "EVENT_INTERFACE_TRAINER";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_DEFI] = "EVENT_INTERFACE_DEFI";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_MISSION] = "EVENT_INTERFACE_MISSION";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_FREE] = "EVENT_INTERFACE_FREE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PROTO] = "EVENT_INTERFACE_PROTO";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NAME] = "EVENT_INTERFACE_NAME";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUP] = "EVENT_INTERFACE_SETUP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_QUIT] = "EVENT_INTERFACE_QUIT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_BACK] = "EVENT_INTERFACE_BACK";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_AGAIN] = "EVENT_INTERFACE_AGAIN";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_WRITE] = "EVENT_INTERFACE_WRITE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_READ] = "EVENT_INTERFACE_READ";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_ABORT] = "EVENT_INTERFACE_ABORT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_USER] = "EVENT_INTERFACE_USER";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_TEEN] = "EVENT_INTERFACE_TEEN";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_CHAP] = "EVENT_INTERFACE_CHAP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_LIST] = "EVENT_INTERFACE_LIST";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_RESUME] = "EVENT_INTERFACE_RESUME";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PLAY] = "EVENT_INTERFACE_PLAY";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPd] = "EVENT_INTERFACE_SETUPd";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPg] = "EVENT_INTERFACE_SETUPg";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPp] = "EVENT_INTERFACE_SETUPp";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPc] = "EVENT_INTERFACE_SETUPc";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SETUPs] = "EVENT_INTERFACE_SETUPs";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_DEVICE] = "EVENT_INTERFACE_DEVICE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_RESOL] = "EVENT_INTERFACE_RESOL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_FULL] = "EVENT_INTERFACE_FULL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_APPLY] = "EVENT_INTERFACE_APPLY";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_TOTO] = "EVENT_INTERFACE_TOTO";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SHADOW] = "EVENT_INTERFACE_SHADOW";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_DIRTY] = "EVENT_INTERFACE_DIRTY";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_LENS] = "EVENT_INTERFACE_LENS";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SKY] = "EVENT_INTERFACE_SKY";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PLANET] = "EVENT_INTERFACE_PLANET";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_LIGHT] = "EVENT_INTERFACE_LIGHT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PARTI] = "EVENT_INTERFACE_PARTI";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_CLIP] = "EVENT_INTERFACE_CLIP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_DETAIL] = "EVENT_INTERFACE_DETAIL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_TEXTURE] = "EVENT_INTERFACE_TEXTURE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_RAIN] = "EVENT_INTERFACE_RAIN";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINT] = "EVENT_INTERFACE_GLINT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_TOOLTIP] = "EVENT_INTERFACE_TOOLTIP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_MOVIES] = "EVENT_INTERFACE_MOVIES";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NICERST] = "EVENT_INTERFACE_NICERST";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SCROLL] = "EVENT_INTERFACE_SCROLL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_INVERTX] = "EVENT_INTERFACE_INVERTX";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_INVERTY] = "EVENT_INTERFACE_INVERTY";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_EFFECT] = "EVENT_INTERFACE_EFFECT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_MOUSE] = "EVENT_INTERFACE_MOUSE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GROUND] = "EVENT_INTERFACE_GROUND";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GADGET] = "EVENT_INTERFACE_GADGET";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_FOG] = "EVENT_INTERFACE_FOG";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_HIMSELF] = "EVENT_INTERFACE_HIMSELF";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_EDITMODE]= "EVENT_INTERFACE_EDITMODE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_EDITVALUE]= "EVENT_INTERFACE_EDITVALUE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SOLUCE4] = "EVENT_INTERFACE_SOLUCE4";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KINFO1] = "EVENT_INTERFACE_KINFO1";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KINFO2] = "EVENT_INTERFACE_KINFO2";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KGROUP] = "EVENT_INTERFACE_KGROUP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KSCROLL] = "EVENT_INTERFACE_KSCROLL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KDEF] = "EVENT_INTERFACE_KDEF";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KLEFT] = "EVENT_INTERFACE_KLEFT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KRIGHT] = "EVENT_INTERFACE_KRIGHT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KUP] = "EVENT_INTERFACE_KUP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KDOWN] = "EVENT_INTERFACE_KDOWN";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KGUP] = "EVENT_INTERFACE_KGUP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KGDOWN] = "EVENT_INTERFACE_KGDOWN";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KCAMERA] = "EVENT_INTERFACE_KCAMERA";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KDESEL] = "EVENT_INTERFACE_KDESEL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KACTION] = "EVENT_INTERFACE_KACTION";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KNEAR] = "EVENT_INTERFACE_KNEAR";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KAWAY] = "EVENT_INTERFACE_KAWAY";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KNEXT] = "EVENT_INTERFACE_KNEXT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KHUMAN] = "EVENT_INTERFACE_KHUMAN";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KQUIT] = "EVENT_INTERFACE_KQUIT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KHELP] = "EVENT_INTERFACE_KHELP";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KPROG] = "EVENT_INTERFACE_KPROG";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KCBOT] = "EVENT_INTERFACE_KCBOT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KVISIT] = "EVENT_INTERFACE_KVISIT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KSPEED10]= "EVENT_INTERFACE_KSPEED10";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KSPEED15]= "EVENT_INTERFACE_KSPEED15";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KSPEED20]= "EVENT_INTERFACE_KSPEED20";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_KSPEED30]= "EVENT_INTERFACE_KSPEED30";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_VOLSOUND]= "EVENT_INTERFACE_VOLSOUND";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_VOLMUSIC]= "EVENT_INTERFACE_VOLMUSIC";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SOUND3D] = "EVENT_INTERFACE_SOUND3D";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_MIN] = "EVENT_INTERFACE_MIN";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NORM] = "EVENT_INTERFACE_NORM";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_MAX] = "EVENT_INTERFACE_MAX";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SILENT] = "EVENT_INTERFACE_SILENT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NOISY] = "EVENT_INTERFACE_NOISY";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK]= "EVENT_INTERFACE_JOYSTICK";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_SOLUCE] = "EVENT_INTERFACE_SOLUCE";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTl] = "EVENT_INTERFACE_GLINTl";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTr] = "EVENT_INTERFACE_GLINTr";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTu] = "EVENT_INTERFACE_GLINTu";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTb] = "EVENT_INTERFACE_GLINTb";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NEDIT] = "EVENT_INTERFACE_NEDIT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NLIST] = "EVENT_INTERFACE_NLIST";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NOK] = "EVENT_INTERFACE_NOK";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NCANCEL] = "EVENT_INTERFACE_NCANCEL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NDELETE] = "EVENT_INTERFACE_NDELETE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_NLABEL] = "EVENT_INTERFACE_NLABEL";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IOWRITE] = "EVENT_INTERFACE_IOWRITE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IOREAD] = "EVENT_INTERFACE_IOREAD";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IOLIST] = "EVENT_INTERFACE_IOLIST";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IONAME] = "EVENT_INTERFACE_IONAME";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IOLABEL] = "EVENT_INTERFACE_IOLABEL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IOIMAGE] = "EVENT_INTERFACE_IOIMAGE";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_IODELETE]= "EVENT_INTERFACE_IODELETE";
+
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PERSO] = "EVENT_INTERFACE_PERSO";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_POK] = "EVENT_INTERFACE_POK";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCANCEL] = "EVENT_INTERFACE_PCANCEL";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PDEF] = "EVENT_INTERFACE_PDEF";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PHEAD] = "EVENT_INTERFACE_PHEAD";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PBODY] = "EVENT_INTERFACE_PBODY";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PLROT] = "EVENT_INTERFACE_PLROT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PRROT] = "EVENT_INTERFACE_PRROT";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC0a] = "EVENT_INTERFACE_PC0a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC1a] = "EVENT_INTERFACE_PC1a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC2a] = "EVENT_INTERFACE_PC2a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC3a] = "EVENT_INTERFACE_PC3a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC4a] = "EVENT_INTERFACE_PC4a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC5a] = "EVENT_INTERFACE_PC5a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC6a] = "EVENT_INTERFACE_PC6a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC7a] = "EVENT_INTERFACE_PC7a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC8a] = "EVENT_INTERFACE_PC8a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC9a] = "EVENT_INTERFACE_PC9a";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCRa] = "EVENT_INTERFACE_PCRa";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCGa] = "EVENT_INTERFACE_PCGa";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCBa] = "EVENT_INTERFACE_PCBa";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC0b] = "EVENT_INTERFACE_PC0b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC1b] = "EVENT_INTERFACE_PC1b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC2b] = "EVENT_INTERFACE_PC2b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC3b] = "EVENT_INTERFACE_PC3b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC4b] = "EVENT_INTERFACE_PC4b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC5b] = "EVENT_INTERFACE_PC5b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC6b] = "EVENT_INTERFACE_PC6b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC7b] = "EVENT_INTERFACE_PC7b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC8b] = "EVENT_INTERFACE_PC8b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PC9b] = "EVENT_INTERFACE_PC9b";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCRb] = "EVENT_INTERFACE_PCRb";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCGb] = "EVENT_INTERFACE_PCGb";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PCBb] = "EVENT_INTERFACE_PCBb";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PFACE1] = "EVENT_INTERFACE_PFACE1";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PFACE2] = "EVENT_INTERFACE_PFACE2";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PFACE3] = "EVENT_INTERFACE_PFACE3";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PFACE4] = "EVENT_INTERFACE_PFACE4";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS0] = "EVENT_INTERFACE_PGLASS0";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS1] = "EVENT_INTERFACE_PGLASS1";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS2] = "EVENT_INTERFACE_PGLASS2";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS3] = "EVENT_INTERFACE_PGLASS3";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS4] = "EVENT_INTERFACE_PGLASS4";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS5] = "EVENT_INTERFACE_PGLASS5";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS6] = "EVENT_INTERFACE_PGLASS6";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS7] = "EVENT_INTERFACE_PGLASS7";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS8] = "EVENT_INTERFACE_PGLASS8";
+ EVENT_TYPE_TEXT[EVENT_INTERFACE_PGLASS9] = "EVENT_INTERFACE_PGLASS9";
+
+ EVENT_TYPE_TEXT[EVENT_DT_GROUP0] = "EVENT_DT_GROUP0";
+ EVENT_TYPE_TEXT[EVENT_DT_GROUP1] = "EVENT_DT_GROUP1";
+ EVENT_TYPE_TEXT[EVENT_DT_GROUP2] = "EVENT_DT_GROUP2";
+ EVENT_TYPE_TEXT[EVENT_DT_GROUP3] = "EVENT_DT_GROUP3";
+ EVENT_TYPE_TEXT[EVENT_DT_GROUP4] = "EVENT_DT_GROUP4";
+ EVENT_TYPE_TEXT[EVENT_DT_LABEL0] = "EVENT_DT_LABEL0";
+ EVENT_TYPE_TEXT[EVENT_DT_LABEL1] = "EVENT_DT_LABEL1";
+ EVENT_TYPE_TEXT[EVENT_DT_LABEL2] = "EVENT_DT_LABEL2";
+ EVENT_TYPE_TEXT[EVENT_DT_LABEL3] = "EVENT_DT_LABEL3";
+ EVENT_TYPE_TEXT[EVENT_DT_LABEL4] = "EVENT_DT_LABEL4";
+ EVENT_TYPE_TEXT[EVENT_DT_VISIT0] = "EVENT_DT_VISIT0";
+ EVENT_TYPE_TEXT[EVENT_DT_VISIT1] = "EVENT_DT_VISIT1";
+ EVENT_TYPE_TEXT[EVENT_DT_VISIT2] = "EVENT_DT_VISIT2";
+ EVENT_TYPE_TEXT[EVENT_DT_VISIT3] = "EVENT_DT_VISIT3";
+ EVENT_TYPE_TEXT[EVENT_DT_VISIT4] = "EVENT_DT_VISIT4";
+ EVENT_TYPE_TEXT[EVENT_DT_END] = "EVENT_DT_END";
+
+ EVENT_TYPE_TEXT[EVENT_CMD] = "EVENT_CMD";
+ EVENT_TYPE_TEXT[EVENT_SPEED] = "EVENT_SPEED";
+
+ EVENT_TYPE_TEXT[EVENT_HYPER_PREV] = "EVENT_HYPER_PREV";
+ EVENT_TYPE_TEXT[EVENT_HYPER_NEXT] = "EVENT_HYPER_NEXT";
+ EVENT_TYPE_TEXT[EVENT_HYPER_HOME] = "EVENT_HYPER_HOME";
+ EVENT_TYPE_TEXT[EVENT_HYPER_COPY] = "EVENT_HYPER_COPY";
+ EVENT_TYPE_TEXT[EVENT_HYPER_SIZE1] = "EVENT_HYPER_SIZE1";
+ EVENT_TYPE_TEXT[EVENT_HYPER_SIZE2] = "EVENT_HYPER_SIZE2";
+ EVENT_TYPE_TEXT[EVENT_HYPER_SIZE3] = "EVENT_HYPER_SIZE3";
+ EVENT_TYPE_TEXT[EVENT_HYPER_SIZE4] = "EVENT_HYPER_SIZE4";
+ EVENT_TYPE_TEXT[EVENT_HYPER_SIZE5] = "EVENT_HYPER_SIZE5";
+
+ EVENT_TYPE_TEXT[EVENT_SATCOM_HUSTON] = "EVENT_SATCOM_HUSTON";
+ EVENT_TYPE_TEXT[EVENT_SATCOM_SAT] = "EVENT_SATCOM_SAT";
+ EVENT_TYPE_TEXT[EVENT_SATCOM_LOADING] = "EVENT_SATCOM_LOADING";
+ EVENT_TYPE_TEXT[EVENT_SATCOM_OBJECT] = "EVENT_SATCOM_OBJECT";
+ EVENT_TYPE_TEXT[EVENT_SATCOM_PROG] = "EVENT_SATCOM_PROG";
+ EVENT_TYPE_TEXT[EVENT_SATCOM_SOLUCE] = "EVENT_SATCOM_SOLUCE";
+
+ EVENT_TYPE_TEXT[EVENT_OBJECT_DESELECT] = "EVENT_OBJECT_DESELECT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_LEFT] = "EVENT_OBJECT_LEFT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RIGHT] = "EVENT_OBJECT_RIGHT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_UP] = "EVENT_OBJECT_UP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_DOWN] = "EVENT_OBJECT_DOWN";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GASUP] = "EVENT_OBJECT_GASUP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GASDOWN] = "EVENT_OBJECT_GASDOWN";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_HTAKE] = "EVENT_OBJECT_HTAKE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MTAKE] = "EVENT_OBJECT_MTAKE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MFRONT] = "EVENT_OBJECT_MFRONT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MBACK] = "EVENT_OBJECT_MBACK";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MPOWER] = "EVENT_OBJECT_MPOWER";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BHELP] = "EVENT_OBJECT_BHELP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BTAKEOFF] = "EVENT_OBJECT_BTAKEOFF";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BDESTROY] = "EVENT_OBJECT_BDESTROY";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BDERRICK] = "EVENT_OBJECT_BDERRICK";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BSTATION] = "EVENT_OBJECT_BSTATION";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BFACTORY] = "EVENT_OBJECT_BFACTORY";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BCONVERT] = "EVENT_OBJECT_BCONVERT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BTOWER] = "EVENT_OBJECT_BTOWER";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BREPAIR] = "EVENT_OBJECT_BREPAIR";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BRESEARCH] = "EVENT_OBJECT_BRESEARCH";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BRADAR] = "EVENT_OBJECT_BRADAR";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BENERGY] = "EVENT_OBJECT_BENERGY";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BLABO] = "EVENT_OBJECT_BLABO";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BNUCLEAR] = "EVENT_OBJECT_BNUCLEAR";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BPARA] = "EVENT_OBJECT_BPARA";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BINFO] = "EVENT_OBJECT_BINFO";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BDESTROYER] = "EVENT_OBJECT_BDESTROYER";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GFLAT] = "EVENT_OBJECT_GFLAT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FCREATE] = "EVENT_OBJECT_FCREATE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FDELETE] = "EVENT_OBJECT_FDELETE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FCOLORb] = "EVENT_OBJECT_FCOLORb";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FCOLORr] = "EVENT_OBJECT_FCOLORr";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FCOLORg] = "EVENT_OBJECT_FCOLORg";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FCOLORy] = "EVENT_OBJECT_FCOLORy";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FCOLORv] = "EVENT_OBJECT_FCOLORv";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYwa] = "EVENT_OBJECT_FACTORYwa";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYta] = "EVENT_OBJECT_FACTORYta";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYfa] = "EVENT_OBJECT_FACTORYfa";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYia] = "EVENT_OBJECT_FACTORYia";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYwc] = "EVENT_OBJECT_FACTORYwc";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYtc] = "EVENT_OBJECT_FACTORYtc";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYfc] = "EVENT_OBJECT_FACTORYfc";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYic] = "EVENT_OBJECT_FACTORYic";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYwi] = "EVENT_OBJECT_FACTORYwi";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYti] = "EVENT_OBJECT_FACTORYti";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYfi] = "EVENT_OBJECT_FACTORYfi";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYii] = "EVENT_OBJECT_FACTORYii";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYws] = "EVENT_OBJECT_FACTORYws";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYts] = "EVENT_OBJECT_FACTORYts";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYfs] = "EVENT_OBJECT_FACTORYfs";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYis] = "EVENT_OBJECT_FACTORYis";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrt] = "EVENT_OBJECT_FACTORYrt";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrc] = "EVENT_OBJECT_FACTORYrc";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrr] = "EVENT_OBJECT_FACTORYrr";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrs] = "EVENT_OBJECT_FACTORYrs";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYsa] = "EVENT_OBJECT_FACTORYsa";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SEARCH] = "EVENT_OBJECT_SEARCH";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_TERRAFORM] = "EVENT_OBJECT_TERRAFORM";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FIRE] = "EVENT_OBJECT_FIRE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_FIREANT] = "EVENT_OBJECT_FIREANT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SPIDEREXPLO]= "EVENT_OBJECT_SPIDEREXPLO";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RECOVER] = "EVENT_OBJECT_RECOVER";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_BEGSHIELD] = "EVENT_OBJECT_BEGSHIELD";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_ENDSHIELD] = "EVENT_OBJECT_ENDSHIELD";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RTANK] = "EVENT_OBJECT_RTANK";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RFLY] = "EVENT_OBJECT_RFLY";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RTHUMP] = "EVENT_OBJECT_RTHUMP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RCANON] = "EVENT_OBJECT_RCANON";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RTOWER] = "EVENT_OBJECT_RTOWER";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RPHAZER] = "EVENT_OBJECT_RPHAZER";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RSHIELD] = "EVENT_OBJECT_RSHIELD";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RATOMIC] = "EVENT_OBJECT_RATOMIC";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RiPAW] = "EVENT_OBJECT_RiPAW";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RiGUN] = "EVENT_OBJECT_RiGUN";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_RESET] = "EVENT_OBJECT_RESET";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_DIMSHIELD] = "EVENT_OBJECT_DIMSHIELD";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_TARGET] = "EVENT_OBJECT_TARGET";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PROGLIST] = "EVENT_OBJECT_PROGLIST";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PROGRUN] = "EVENT_OBJECT_PROGRUN";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PROGEDIT] = "EVENT_OBJECT_PROGEDIT";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PROGSTART] = "EVENT_OBJECT_PROGSTART";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PROGSTOP] = "EVENT_OBJECT_PROGSTOP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_INFOOK] = "EVENT_OBJECT_INFOOK";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_DELETE] = "EVENT_OBJECT_DELETE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GENERGY] = "EVENT_OBJECT_GENERGY";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GSHIELD] = "EVENT_OBJECT_GSHIELD";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GRANGE] = "EVENT_OBJECT_GRANGE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_COMPASS] = "EVENT_OBJECT_COMPASS";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MAP] = "EVENT_OBJECT_MAP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MAPZOOM] = "EVENT_OBJECT_MAPZOOM";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GPROGRESS] = "EVENT_OBJECT_GPROGRESS";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GRADAR] = "EVENT_OBJECT_GRADAR";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_GINFO] = "EVENT_OBJECT_GINFO";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_TYPE] = "EVENT_OBJECT_TYPE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CROSSHAIR] = "EVENT_OBJECT_CROSSHAIR";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CORNERul] = "EVENT_OBJECT_CORNERul";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CORNERur] = "EVENT_OBJECT_CORNERur";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CORNERdl] = "EVENT_OBJECT_CORNERdl";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CORNERdr] = "EVENT_OBJECT_CORNERdr";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MAPi] = "EVENT_OBJECT_MAPi";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MAPg] = "EVENT_OBJECT_MAPg";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CAMERA] = "EVENT_OBJECT_CAMERA";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_HELP] = "EVENT_OBJECT_HELP";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SOLUCE] = "EVENT_OBJECT_SOLUCE";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CAMERAleft] = "EVENT_OBJECT_CAMERAleft";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CAMERAright]= "EVENT_OBJECT_CAMERAright";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CAMERAnear] = "EVENT_OBJECT_CAMERAnear";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_CAMERAaway] = "EVENT_OBJECT_CAMERAaway";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT00] = "EVENT_OBJECT_SHORTCUT00";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT01] = "EVENT_OBJECT_SHORTCUT01";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT02] = "EVENT_OBJECT_SHORTCUT02";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT03] = "EVENT_OBJECT_SHORTCUT03";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT04] = "EVENT_OBJECT_SHORTCUT04";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT05] = "EVENT_OBJECT_SHORTCUT05";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT06] = "EVENT_OBJECT_SHORTCUT06";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT07] = "EVENT_OBJECT_SHORTCUT07";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT08] = "EVENT_OBJECT_SHORTCUT08";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT09] = "EVENT_OBJECT_SHORTCUT09";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT10] = "EVENT_OBJECT_SHORTCUT10";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT11] = "EVENT_OBJECT_SHORTCUT11";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT12] = "EVENT_OBJECT_SHORTCUT12";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT13] = "EVENT_OBJECT_SHORTCUT13";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT14] = "EVENT_OBJECT_SHORTCUT14";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT15] = "EVENT_OBJECT_SHORTCUT15";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT16] = "EVENT_OBJECT_SHORTCUT16";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT17] = "EVENT_OBJECT_SHORTCUT17";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT18] = "EVENT_OBJECT_SHORTCUT18";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_SHORTCUT19] = "EVENT_OBJECT_SHORTCUT19";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_MOVIELOCK] = "EVENT_OBJECT_MOVIELOCK";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_EDITLOCK] = "EVENT_OBJECT_EDITLOCK";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_LIMIT] = "EVENT_OBJECT_LIMIT";
+
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN0] = "EVENT_OBJECT_PEN0";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN1] = "EVENT_OBJECT_PEN1";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN2] = "EVENT_OBJECT_PEN2";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN3] = "EVENT_OBJECT_PEN3";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN4] = "EVENT_OBJECT_PEN4";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN5] = "EVENT_OBJECT_PEN5";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN6] = "EVENT_OBJECT_PEN6";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN7] = "EVENT_OBJECT_PEN7";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_PEN8] = "EVENT_OBJECT_PEN8";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_REC] = "EVENT_OBJECT_REC";
+ EVENT_TYPE_TEXT[EVENT_OBJECT_STOP] = "EVENT_OBJECT_STOP";
+
+ EVENT_TYPE_TEXT[EVENT_STUDIO_OK] = "EVENT_STUDIO_OK";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_CANCEL] = "EVENT_STUDIO_CANCEL";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_EDIT] = "EVENT_STUDIO_EDIT";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_LIST] = "EVENT_STUDIO_LIST";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_NEW] = "EVENT_STUDIO_NEW";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_OPEN] = "EVENT_STUDIO_OPEN";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_SAVE] = "EVENT_STUDIO_SAVE";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_UNDO] = "EVENT_STUDIO_UNDO";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_CUT] = "EVENT_STUDIO_CUT";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_COPY] = "EVENT_STUDIO_COPY";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_PASTE] = "EVENT_STUDIO_PASTE";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_SIZE] = "EVENT_STUDIO_SIZE";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_TOOL] = "EVENT_STUDIO_TOOL";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_HELP] = "EVENT_STUDIO_HELP";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_COMPILE] = "EVENT_STUDIO_COMPILE";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_RUN] = "EVENT_STUDIO_RUN";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_REALTIME] = "EVENT_STUDIO_REALTIME";
+ EVENT_TYPE_TEXT[EVENT_STUDIO_STEP] = "EVENT_STUDIO_STEP";
+}
+
+std::string ParseEventType(EventType eventType)
{
- int i = static_cast<int>(g_uniqueEventType+1);
- g_uniqueEventType = static_cast<EventType>(i);
- return g_uniqueEventType;
+ auto Other = [&](const char* name)
+ {
+ std::stringstream str;
+ str << name << "(" << static_cast<int>(eventType) << ")";
+ return str.str();
+ };
+
+ if (eventType < EVENT_STD_MAX)
+ {
+ const char* stdEvent = EVENT_TYPE_TEXT[eventType];
+ if (stdEvent[0] == 0)
+ return Other("STD_UNDEFINED");
+
+ return stdEvent;
+ }
+
+ if (eventType >= EVENT_USER)
+ return Other("USER_EVENT");
+
+ return Other("UNDEFINED");
}
diff --git a/src/common/event.h b/src/common/event.h
index 153b732..9405660 100644
--- a/src/common/event.h
+++ b/src/common/event.h
@@ -40,8 +40,10 @@ enum EventType
//! Invalid event / no event
EVENT_NULL = 0,
- //! Event sent on user or system quit request
- EVENT_QUIT = 1,
+ // System events (originating in CApplication)
+
+ //! Event sent on system quit request
+ EVENT_SYS_QUIT = 1,
//! Frame update event
EVENT_FRAME = 2,
@@ -69,10 +71,15 @@ enum EventType
//! Event sent after releasing a joystick button
EVENT_JOY_BUTTON_UP = 14,
+ //!< Maximum value of system events
+ EVENT_SYS_MAX,
+
/* Events sent/received in game and user interface */
- EVENT_UPDINTERFACE = 20,
+ //! Event sent on user quit request
+ EVENT_QUIT = 20,
+ EVENT_UPDINTERFACE = 21,
EVENT_WIN = 30,
EVENT_LOST = 31,
@@ -396,6 +403,7 @@ enum EventType
EVENT_OBJECT_MPOWER = 1024,
EVENT_OBJECT_BHELP = 1040,
EVENT_OBJECT_BTAKEOFF = 1041,
+ EVENT_OBJECT_BDESTROY = 1042,
EVENT_OBJECT_BDERRICK = 1050,
EVENT_OBJECT_BSTATION = 1051,
EVENT_OBJECT_BFACTORY = 1052,
@@ -547,7 +555,8 @@ enum EventType
EVENT_STUDIO_REALTIME = 2052,
EVENT_STUDIO_STEP = 2053,
- EVENT_STD_MAX, //! < maximum value of standard events
+ //! Maximum value of standard events
+ EVENT_STD_MAX,
EVENT_USER = 10000,
EVENT_FORCE_LONG = 0x7fffffff
@@ -668,8 +677,8 @@ struct ActiveEventData
* \struct Event
* \brief Event sent by system, interface or game
*
- * Event is described by its type (EventType) and the union
- * \a data contains additional data about the event.
+ * Event is described by its type (EventType) and anonymous union that
+ * contains additional data about the event.
* Different members of the union are filled with different event types.
* With some events, nothing is filled (it's zeroed out).
* The union contains roughly the same information as SDL_Event struct
@@ -680,9 +689,6 @@ struct Event
//! Type of event
EventType type;
- //! If true, the event was produced by system in CApplication; else, it has come from game engine
- bool systemEvent;
-
//! Relative time since last EVENT_FRAME
//! Scope: only EVENT_FRAME events
// TODO: gradually replace the usage of this with new CApplication's time functions
@@ -729,22 +735,25 @@ struct Event
ActiveEventData active;
};
- Event(EventType type = EVENT_NULL)
- {
- this->type = type;
-
- systemEvent = false;
- rTime = 0.0f;
- mouseButtonsState = 0;
- trackedKeysState = 0;
- customParam = 0;
- }
+ explicit Event(EventType _type = EVENT_NULL)
+ : type(_type)
+ , rTime(0.0f)
+ , kmodState(0)
+ , trackedKeysState(0)
+ , mouseButtonsState(0)
+ , customParam(0)
+ {}
};
//! Returns an unique event type (above the standard IDs)
EventType GetUniqueEventType();
+//! Initializes static array with event type strings
+void InitializeEventTypeTexts();
+
+//! Parses event type to string
+std::string ParseEventType(EventType eventType);
/**
* \class CEventQueue
@@ -778,3 +787,4 @@ protected:
int m_tail;
int m_total;
};
+
diff --git a/src/common/global.h b/src/common/global.h
index 7a5fdfd..a322057 100644
--- a/src/common/global.h
+++ b/src/common/global.h
@@ -55,6 +55,8 @@ enum Error
ERR_BUILD_BASE = 129, //! < too close to the rocket
ERR_BUILD_NARROW = 130, //! < buildings too close
ERR_BUILD_MOTOR = 131, //! < built: not possible in movement
+ ERR_BUILD_DISABLED = 132, //! < built: can not produce this object in this mission
+ ERR_BUILD_RESEARCH = 133, //! < built: can not produce not researched object
ERR_SEARCH_FLY = 140, //! < not possible in flight
ERR_SEARCH_VEH = 141, //! < inappropriate vehicle
ERR_SEARCH_MOTOR = 142, //! < impossible in movement
@@ -104,6 +106,8 @@ enum Error
ERR_INFO_NULL = 390, //! < no information terminal
ERR_VEH_VIRUS = 400, //! < vehicle infected by a virus
ERR_BAT_VIRUS = 401, //! < building infected by a virus
+ ERR_DESTROY_NOTFOUND = 410, //! < not found anything to destroy
+ ERR_WRONG_OBJ = 420, //! < inappropriate vehicle
ERR_VEH_POWER = 500, //! < no battery
ERR_VEH_ENERGY = 501, //! < more energy
ERR_FLAG_FLY = 510, //! < impossible in flight
@@ -293,3 +297,4 @@ extern int g_build; // constructible buildings
extern int g_researchDone; // research done
extern long g_researchEnable; // research available
extern float g_unit; // conversion factor
+
diff --git a/src/common/image.cpp b/src/common/image.cpp
index db14797..a9587ef 100644
--- a/src/common/image.cpp
+++ b/src/common/image.cpp
@@ -17,6 +17,8 @@
#include "common/image.h"
+#include "math/func.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -108,7 +110,8 @@ bool PNGSaveSurface(const char *filename, SDL_Surface *surf)
return false;
}
- if (setjmp(png_jmpbuf(png_ptr))) {
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp);
return false;
@@ -200,6 +203,33 @@ void CImage::Fill(Gfx::IntColor color)
}
/**
+ * Image must be valid.
+ *
+ * The dimensions are increased to nearest even power of two values.
+ * If image is already in power-of-two format, nothing is done.
+ */
+void CImage::PadToNearestPowerOfTwo()
+{
+ assert(m_data != nullptr);
+
+ if (Math::IsPowerOfTwo(m_data->surface->w) && Math::IsPowerOfTwo(m_data->surface->h))
+ return;
+
+ int w = Math::NextPowerOfTwo(m_data->surface->w);
+ int h = Math::NextPowerOfTwo(m_data->surface->h);
+
+ m_data->surface->flags &= (~SDL_SRCALPHA);
+ SDL_Surface* resizedSurface = SDL_CreateRGBSurface(0, w, h, 32, 0x00ff0000, 0x0000ff00,
+ 0x000000ff, 0xff000000);
+ assert(resizedSurface != NULL);
+ SDL_BlitSurface(m_data->surface, NULL, resizedSurface, NULL);
+
+ SDL_FreeSurface(m_data->surface);
+
+ m_data->surface = resizedSurface;
+}
+
+/**
* Image must be valid and pixel coords in valid range.
*
* \param pixel pixel coords (range x: 0..width-1 y: 0..height-1)
@@ -367,3 +397,4 @@ bool CImage::SavePNG(const std::string& fileName)
return true;
}
+
diff --git a/src/common/image.h b/src/common/image.h
index d9da75b..44aedf1 100644
--- a/src/common/image.h
+++ b/src/common/image.h
@@ -94,6 +94,9 @@ public:
//! Returns the precise color at given pixel
Gfx::IntColor GetPixelInt(Math::IntPoint pixel);
+ //! Pads the image to nearest power of 2 dimensions
+ void PadToNearestPowerOfTwo();
+
//! Loads an image from the specified file
bool Load(const std::string &fileName);
@@ -109,3 +112,4 @@ private:
//! Image data
ImageData* m_data;
};
+
diff --git a/src/common/iman.cpp b/src/common/iman.cpp
index e1400fd..88fbb9b 100644
--- a/src/common/iman.cpp
+++ b/src/common/iman.cpp
@@ -111,3 +111,4 @@ void CInstanceManager::Compress(ManagedClassType classType)
}
m_table[classType].usedCount = j;
}
+
diff --git a/src/common/iman.h b/src/common/iman.h
index faabd0c..bfa2204 100644
--- a/src/common/iman.h
+++ b/src/common/iman.h
@@ -93,4 +93,3 @@ protected:
ManagedClassInstances m_table[CLASS_MAX];
};
-
diff --git a/src/common/ioutils.h b/src/common/ioutils.h
index 9a94617..823b720 100644
--- a/src/common/ioutils.h
+++ b/src/common/ioutils.h
@@ -146,3 +146,4 @@ std::string ReadBinaryString(std::istream &istr)
}
}; // namespace IOUtils
+
diff --git a/src/common/key.h b/src/common/key.h
index 84ee618..82b3fbd 100644
--- a/src/common/key.h
+++ b/src/common/key.h
@@ -61,3 +61,4 @@ enum VirtualKmod
//! Special value for invalid key bindings
const unsigned int KEY_INVALID = SDLK_LAST + 1000;
+
diff --git a/src/common/logger.cpp b/src/common/logger.cpp
index 8bc4cef..a02854d 100644
--- a/src/common/logger.cpp
+++ b/src/common/logger.cpp
@@ -25,8 +25,8 @@ template<> CLogger* CSingleton<CLogger>::m_instance = nullptr;
CLogger::CLogger()
{
- mFile = NULL;
- mLogLevel = LOG_INFO;
+ m_file = NULL;
+ m_logLevel = LOG_INFO;
}
@@ -38,31 +38,31 @@ CLogger::~CLogger()
void CLogger::Log(LogLevel type, const char* str, va_list args)
{
- if (type < mLogLevel)
+ if (type < m_logLevel)
return;
switch (type)
{
case LOG_TRACE:
- fprintf(IsOpened() ? mFile : stderr, "[TRACE]: ");
+ fprintf(IsOpened() ? m_file : stderr, "[TRACE]: ");
break;
case LOG_DEBUG:
- fprintf(IsOpened() ? mFile : stderr, "[DEBUG]: ");
+ fprintf(IsOpened() ? m_file : stderr, "[DEBUG]: ");
break;
case LOG_WARN:
- fprintf(IsOpened() ? mFile : stderr, "[WARN]: ");
+ fprintf(IsOpened() ? m_file : stderr, "[WARN]: ");
break;
case LOG_INFO:
- fprintf(IsOpened() ? mFile : stderr, "[INFO]: ");
+ fprintf(IsOpened() ? m_file : stderr, "[INFO]: ");
break;
case LOG_ERROR:
- fprintf(IsOpened() ? mFile : stderr, "[ERROR]: ");
+ fprintf(IsOpened() ? m_file : stderr, "[ERROR]: ");
break;
default:
break;
}
- vfprintf(IsOpened() ? mFile : stderr, str, args);
+ vfprintf(IsOpened() ? m_file : stderr, str, args);
}
@@ -122,36 +122,36 @@ void CLogger::Message(const char* str, ...)
void CLogger::SetOutputFile(std::string filename)
{
- mFilename = filename;
+ m_filename = filename;
Open();
}
void CLogger::Open()
{
- mFile = fopen(mFilename.c_str(), "w");
+ m_file = fopen(m_filename.c_str(), "w");
- if (mFile == NULL)
- fprintf(stderr, "Could not create file %s\n", mFilename.c_str());
+ if (m_file == NULL)
+ fprintf(stderr, "Could not create file %s\n", m_filename.c_str());
}
void CLogger::Close()
{
if (IsOpened())
- fclose(mFile);
+ fclose(m_file);
}
bool CLogger::IsOpened()
{
- return mFile != NULL;
+ return m_file != NULL;
}
void CLogger::SetLogLevel(LogLevel type)
{
- mLogLevel = type;
+ m_logLevel = type;
}
diff --git a/src/common/logger.h b/src/common/logger.h
index 769f548..1a5f3b9 100644
--- a/src/common/logger.h
+++ b/src/common/logger.h
@@ -113,9 +113,9 @@ public:
static bool ParseLogLevel(const std::string& str, LogLevel& logLevel);
private:
- std::string mFilename;
- FILE *mFile;
- LogLevel mLogLevel;
+ std::string m_filename;
+ FILE *m_file;
+ LogLevel m_logLevel;
void Open();
void Close();
@@ -125,6 +125,8 @@ private:
//! Global function to get Logger instance
-inline CLogger* GetLogger() {
+inline CLogger* GetLogger()
+{
return CLogger::GetInstancePointer();
}
+
diff --git a/src/common/misc.h b/src/common/misc.h
index e2ddc44..bcebf76 100644
--- a/src/common/misc.h
+++ b/src/common/misc.h
@@ -31,3 +31,4 @@ extern void TimeToAscii(time_t time, char *buffer);
extern bool CopyFileListToTemp(char* filename, int* list, int total);
extern void AddExt(char* filename, const char* ext);
+
diff --git a/src/common/profile.cpp b/src/common/profile.cpp
index 654648d..77c70c3 100644
--- a/src/common/profile.cpp
+++ b/src/common/profile.cpp
@@ -39,17 +39,7 @@ CProfile::CProfile() :
CProfile::~CProfile()
{
- if (m_profileNeedSave)
- {
- try
- {
- bp::ini_parser::write_ini(GetSystemUtils()->profileFileLocation(), m_propertyTree);
- }
- catch (std::exception & e)
- {
- GetLogger()->Info("Error on storing profile: %s\n", e.what());
- }
- }
+ SaveCurrentDirectory();
}
@@ -57,17 +47,40 @@ bool CProfile::InitCurrentDirectory()
{
try
{
- bp::ini_parser::read_ini(GetSystemUtils()->profileFileLocation(), m_propertyTree);
+ #if DEV_BUILD
+ bp::ini_parser::read_ini("colobot.ini", m_propertyTree);
+ #else
+ bp::ini_parser::read_ini(GetSystemUtils()->GetProfileFileLocation(), m_propertyTree);
+ #endif
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
}
-
+bool CProfile::SaveCurrentDirectory()
+{
+ if (m_profileNeedSave)
+ {
+ try
+ {
+ #if DEV_BUILD
+ bp::ini_parser::write_ini("colobot.ini", m_propertyTree);
+ #else
+ bp::ini_parser::write_ini(GetSystemUtils()->GetProfileFileLocation(), m_propertyTree);
+ #endif
+ }
+ catch (std::exception & e)
+ {
+ GetLogger()->Error("Error on storing profile: %s\n", e.what());
+ return false;
+ }
+ }
+ return true;
+}
bool CProfile::SetLocalProfileString(std::string section, std::string key, std::string value)
{
@@ -78,7 +91,7 @@ bool CProfile::SetLocalProfileString(std::string section, std::string key, std::
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
@@ -93,7 +106,7 @@ bool CProfile::GetLocalProfileString(std::string section, std::string key, std::
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
@@ -109,7 +122,7 @@ bool CProfile::SetLocalProfileInt(std::string section, std::string key, int valu
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
@@ -124,7 +137,7 @@ bool CProfile::GetLocalProfileInt(std::string section, std::string key, int &val
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
@@ -140,7 +153,7 @@ bool CProfile::SetLocalProfileFloat(std::string section, std::string key, float
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
@@ -155,7 +168,7 @@ bool CProfile::GetLocalProfileFloat(std::string section, std::string key, float
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
return false;
}
return true;
@@ -179,7 +192,7 @@ std::vector< std::string > CProfile::GetLocalProfileSection(std::string section,
}
catch (std::exception & e)
{
- GetLogger()->Info("Error on parsing profile: %s\n", e.what());
+ GetLogger()->Error("Error on parsing profile: %s\n", e.what());
}
return ret_list;
@@ -196,34 +209,39 @@ 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) {
+ if (dir.find("/") == std::string::npos)
+ {
path = default_dir + "/" + dir;
}
-
- if (m_userDirectory.length() > 0) {
+
+ if (m_userDirectory.length() > 0)
+ {
boost::replace_all(path, "%user%", m_userDirectory);
- } else {
+ }
+ 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;
+ if (fs::exists(dst))
+ {
+ return true;
}
return false;
diff --git a/src/common/profile.h b/src/common/profile.h
index 7f99d81..f084ece 100644
--- a/src/common/profile.h
+++ b/src/common/profile.h
@@ -41,96 +41,103 @@ namespace fs = boost::filesystem;
*/
class CProfile : public CSingleton<CProfile>
{
- public:
- CProfile();
- ~CProfile();
-
- /** Loads colobot.ini from current directory
- * \return return true on success
- */
- bool InitCurrentDirectory();
-
- /** Sets string value in section under specified key
- * \param section
- * \param key
- * \param value
- * \return return true on success
- */
- bool SetLocalProfileString(std::string section, std::string key, std::string value);
-
- /** Gets string value in section under specified key
- * \param section
- * \param key
- * \param buffer
- * \return return true on success
- */
- bool GetLocalProfileString(std::string section, std::string key, std::string& buffer);
-
- /** Sets int value in section under specified key
- * \param section
- * \param key
- * \param value
- * \return return true on success
- */
- bool SetLocalProfileInt(std::string section, std::string key, int value);
-
- /** Gets int value in section under specified key
- * \param section
- * \param key
- * \param value
- * \return return true on success
- */
- bool GetLocalProfileInt(std::string section, std::string key, int &value);
-
- /** Sets float value in section under specified key
- * \param section
- * \param key
- * \param value
- * \return return true on success
- */
- bool SetLocalProfileFloat(std::string section, std::string key, float value);
-
- /** Gets float value in section under specified key
- * \param section
- * \param key
- * \param value
- * \return return true on success
- */
- bool GetLocalProfileFloat(std::string section, std::string key, float &value);
-
- /** Gets all values in section under specified key
- * \param section
- * \param key
- * \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;
+public:
+ CProfile();
+ virtual ~CProfile();
+
+ /** Loads colobot.ini from current directory
+ * \return return true on success
+ */
+ bool InitCurrentDirectory();
+
+ /** Saves colobot.ini to current directory
+ * \return return true on success
+ */
+ bool SaveCurrentDirectory();
+
+ /** Sets string value in section under specified key
+ * \param section
+ * \param key
+ * \param value
+ * \return return true on success
+ */
+ bool SetLocalProfileString(std::string section, std::string key, std::string value);
+
+ /** Gets string value in section under specified key
+ * \param section
+ * \param key
+ * \param buffer
+ * \return return true on success
+ */
+ bool GetLocalProfileString(std::string section, std::string key, std::string& buffer);
+
+ /** Sets int value in section under specified key
+ * \param section
+ * \param key
+ * \param value
+ * \return return true on success
+ */
+ bool SetLocalProfileInt(std::string section, std::string key, int value);
+
+ /** Gets int value in section under specified key
+ * \param section
+ * \param key
+ * \param value
+ * \return return true on success
+ */
+ bool GetLocalProfileInt(std::string section, std::string key, int &value);
+
+ /** Sets float value in section under specified key
+ * \param section
+ * \param key
+ * \param value
+ * \return return true on success
+ */
+ bool SetLocalProfileFloat(std::string section, std::string key, float value);
+
+ /** Gets float value in section under specified key
+ * \param section
+ * \param key
+ * \param value
+ * \return return true on success
+ */
+ bool GetLocalProfileFloat(std::string section, std::string key, float &value);
+
+ /** Gets all values in section under specified key
+ * \param section
+ * \param key
+ * \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
-inline CProfile & GetProfile() {
+inline CProfile & GetProfile()
+{
return *CProfile::GetInstancePointer();
}
+
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 729a883..d61fa63 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -295,6 +295,7 @@ void InitializeRestext()
stringsEvent[EVENT_OBJECT_MPOWER] = "..power cell";
stringsEvent[EVENT_OBJECT_BHELP] = "Instructions for the mission (\\key help;)";
stringsEvent[EVENT_OBJECT_BTAKEOFF] = "Take off to finish the mission";
+ stringsEvent[EVENT_OBJECT_BDESTROY] = "Destroy";
stringsEvent[EVENT_OBJECT_BDERRICK] = "Build a derrick";
stringsEvent[EVENT_OBJECT_BSTATION] = "Build a power station";
stringsEvent[EVENT_OBJECT_BFACTORY] = "Build a bot factory";
@@ -539,6 +540,7 @@ void InitializeRestext()
+ stringsErr[ERR_GENERIC] = "Internal error - tell the developers";
stringsErr[ERR_CMD] = "Unknown command";
stringsErr[ERR_MANIP_VEH] = "Inappropriate bot";
stringsErr[ERR_MANIP_FLY] = "Impossible when flying";
@@ -563,6 +565,8 @@ void InitializeRestext()
stringsErr[ERR_BUILD_NARROW] = "Too close to a building";
stringsErr[ERR_BUILD_MOTOR] = "Impossible when moving";
stringsErr[ERR_SEARCH_FLY] = "Impossible when flying";
+ stringsErr[ERR_BUILD_DISABLED] = "Can not produce this object in this mission";
+ stringsErr[ERR_BUILD_RESEARCH] = "Can not produce not researched object";
stringsErr[ERR_SEARCH_VEH] = "Inappropriate bot";
stringsErr[ERR_SEARCH_MOTOR] = "Impossible when moving";
stringsErr[ERR_TERRA_VEH] = "Inappropriate bot";
@@ -620,6 +624,8 @@ void InitializeRestext()
stringsErr[ERR_FLAG_CREATE] = "Too many flags of this color (maximum 5)";
stringsErr[ERR_FLAG_PROXY] = "Too close to an existing flag";
stringsErr[ERR_FLAG_DELETE] = "No flag nearby";
+ stringsErr[ERR_DESTROY_NOTFOUND]= "Not found anything to destroy";
+ stringsErr[ERR_WRONG_OBJ] = "Inappropriate object";
stringsErr[ERR_MISSION_NOTERM] = "The mission is not accomplished yet (press \\key help; for more details)";
stringsErr[ERR_DELETEMOBILE] = "Bot destroyed";
stringsErr[ERR_DELETEBUILDING] = "Building destroyed";
@@ -729,9 +735,9 @@ void InitializeRestext()
static char g_gamerName[100];
-void SetGlobalGamerName(char *name)
+void SetGlobalGamerName(std::string name)
{
- strcpy(g_gamerName, name);
+ strcpy(g_gamerName, name.c_str());
}
@@ -842,10 +848,8 @@ static const char* GetResourceBase(ResType type, int num)
case RES_EVENT:
if (num >= EVENT_STD_MAX)
- {
- GetLogger()->Trace("GetResource event num out of range: %d\n", num); // TODO: fix later
- return "";
- }
+ return ""; // can be safely ignored (user events)
+
str = stringsEvent[num];
break;
@@ -914,3 +918,4 @@ bool GetResource(ResType type, int num, char* text)
PutKeyName(text, tmpl);
return true;
}
+
diff --git a/src/common/restext.h b/src/common/restext.h
index 8199f9f..e4659e2 100644
--- a/src/common/restext.h
+++ b/src/common/restext.h
@@ -24,6 +24,8 @@
#include "common/global.h"
+#include <string>
+
/**
* \enum ResType
@@ -153,6 +155,7 @@ enum ResTextType
void InitializeRestext();
-void SetGlobalGamerName(char *name);
+void SetGlobalGamerName(std::string name);
bool SearchKey(const char *cmd, InputSlot& slot);
bool GetResource(ResType type, int num, char* text);
+
diff --git a/src/common/singleton.h b/src/common/singleton.h
index 25e1648..841759d 100644
--- a/src/common/singleton.h
+++ b/src/common/singleton.h
@@ -74,3 +74,4 @@ private:
CSingleton& operator=(const CSingleton<T> &);
CSingleton(const CSingleton<T> &);
};
+
diff --git a/src/common/stringutils.cpp b/src/common/stringutils.cpp
index db486f0..953abba 100644
--- a/src/common/stringutils.cpp
+++ b/src/common/stringutils.cpp
@@ -142,3 +142,4 @@ size_t StrUtils::Utf8StringLength(const std::string &str)
}
return result;
}
+
diff --git a/src/common/stringutils.h b/src/common/stringutils.h
index 064351d..c60bfb0 100644
--- a/src/common/stringutils.h
+++ b/src/common/stringutils.h
@@ -78,3 +78,4 @@ int Utf8CharSizeAt(const std::string &str, unsigned int pos);
size_t Utf8StringLength(const std::string &str);
}; // namespace StrUtil
+
diff --git a/src/desktop/.gitignore b/src/desktop/.gitignore
deleted file mode 100644
index bade6f3..0000000
--- a/src/desktop/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-lang/
diff --git a/src/desktop/CMakeLists.txt b/src/desktop/CMakeLists.txt
deleted file mode 100644
index 9a00dd4..0000000
--- a/src/desktop/CMakeLists.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-# Install Desktop Entry file
-set(COLOBOT_DESKTOP_FILE colobot.desktop)
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}
- COMMAND ./create_desktop_file.sh > ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}
- WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
- COMMENT "Build ${COLOBOT_DESKTOP_FILE}"
- )
-add_custom_target(desktopfile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE})
-install(
- FILES ${CMAKE_CURRENT_BINARY_DIR}/${COLOBOT_DESKTOP_FILE}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications/
- )
-
-# Install Icon
-set(COLOBOT_ICON_FILE colobot.svg)
-install(
- FILES ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/
- )
-
-# Render SVG icon in various sizes
-find_program(RSVG_CONVERT rsvg-convert)
-if(RSVG_CONVERT)
- foreach(PNGSIZE "48" "32" "16")
- file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE})
- add_custom_target(resize_icon_${PNGSIZE} ALL
- COMMAND ${RSVG_CONVERT} -w ${PNGSIZE} -h ${PNGSIZE} ${CMAKE_CURRENT_SOURCE_DIR}/${COLOBOT_ICON_FILE}
- > ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png
- )
- install(
- FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGSIZE}/colobot.png
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${PNGSIZE}x${PNGSIZE}/apps/
- )
- endforeach()
-endif()
-
-# Create manpage from pod-formatted file
-find_program(POD2MAN pod2man)
-if(POD2MAN AND (NOT MSYS))
- set(COLOBOT_MANPAGE_SECTION 6)
-
- macro(podman)
- cmake_parse_arguments(PM "" "PODFILE;LOCALE;" "" ${ARGN})
- if(PM_LOCALE)
- # This copes with the fact that english has no "/LANG" in the paths and filenames.
- set(SLASHLOCALE /${PM_LOCALE})
- endif()
- file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE})
- add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE}
- COMMAND ${POD2MAN} ARGS --section=${COLOBOT_MANPAGE_SECTION}
- --center="Colobot" --stderr --utf8
- --release="${COLOBOT_VERSION_FULL}"
- ${CMAKE_CURRENT_SOURCE_DIR}/${PM_PODFILE}
- ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}
- COMMENT "Create ${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION} manpage"
- )
- add_custom_target(man${PM_LOCALE} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION})
-
- install(
- FILES ${CMAKE_CURRENT_BINARY_DIR}${SLASHLOCALE}/colobot.${COLOBOT_MANPAGE_SECTION}
- DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man${SLASHLOCALE}/man${COLOBOT_MANPAGE_SECTION}/ )
-
- add_dependencies(man man${PM_LOCALE})
- endmacro()
-
- # Create the english manpage
- podman(PODFILE colobot.pod)
-
-endif()
-
-# Translate translatable material
-find_program(PO4A po4a)
-
-if(PO4A)
- add_custom_target(desktop_po4a
- COMMAND ${PO4A} po4a.cfg
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- )
- add_dependencies(desktopfile desktop_po4a)
-
- if(POD2MAN)
- add_custom_target(man_po4a
- COMMAND ${PO4A} po4a.cfg
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
- )
- add_dependencies(man man_po4a)
- file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po)
- string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO})
- foreach(LOCALE ${LINGUAS})
- podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE})
- endforeach()
- endif()
-endif()
diff --git a/src/graphics/README.txt b/src/graphics/README.txt
index 1cb91ba..f9ec2ae 100644
--- a/src/graphics/README.txt
+++ b/src/graphics/README.txt
@@ -10,3 +10,4 @@
* This namespace was created to avoid clashing with old code, but now it still serves,
* defining a border between pure graphics engine and other parts of application.
*/
+
diff --git a/src/graphics/core/README.txt b/src/graphics/core/README.txt
index ca3768c..056441d 100644
--- a/src/graphics/core/README.txt
+++ b/src/graphics/core/README.txt
@@ -4,4 +4,5 @@
*
* Core types, enums, structs and CDevice abstract class that define
* the abstract graphics device used in graphics engine
- */ \ No newline at end of file
+ */
+
diff --git a/src/graphics/core/color.cpp b/src/graphics/core/color.cpp
index 1f9d7a5..f0b74f8 100644
--- a/src/graphics/core/color.cpp
+++ b/src/graphics/core/color.cpp
@@ -106,3 +106,4 @@ Color HSV2RGB(ColorHSV color)
} // namespace Gfx
+
diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h
index 5d059e5..87a50f4 100644
--- a/src/graphics/core/color.h
+++ b/src/graphics/core/color.h
@@ -139,10 +139,10 @@ struct ColorHSV
//! Returns a string "(h, s, v)"
inline std::string ToString() const
{
- std::stringstream s;
- s.precision(3);
- s << "(" << h << ", " << s << ", " << v << ")";
- return s.str();
+ std::stringstream str;
+ str.precision(3);
+ str << "(" << h << ", " << s << ", " << v << ")";
+ return str.str();
}
};
@@ -154,3 +154,4 @@ Color HSV2RGB(ColorHSV color);
} // namespace Gfx
+
diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
index 41d7796..4c1189c 100644
--- a/src/graphics/core/device.h
+++ b/src/graphics/core/device.h
@@ -72,7 +72,7 @@ struct DeviceConfig
size = Math::IntPoint(800, 600);
bpp = 32;
fullScreen = false;
- resizeable = false;
+ resizeable = true;
doubleBuf = true;
noFrame = false;
}
@@ -240,6 +240,9 @@ public:
//! Provides a hook to debug graphics code (implementation-specific)
virtual void DebugHook() = 0;
+ //! Displays light positions to aid in debuggings
+ virtual void DebugLights() = 0;
+
//! Initializes the device, setting the initial state
virtual bool Create() = 0;
//! Destroys the device, releasing every acquired resource
@@ -401,3 +404,4 @@ public:
} // namespace Gfx
+
diff --git a/src/graphics/core/light.h b/src/graphics/core/light.h
index 28733c1..923d0e9 100644
--- a/src/graphics/core/light.h
+++ b/src/graphics/core/light.h
@@ -98,3 +98,4 @@ struct Light
} // namespace Gfx
+
diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h
index 07782d5..e0bfaff 100644
--- a/src/graphics/core/material.h
+++ b/src/graphics/core/material.h
@@ -60,3 +60,4 @@ struct Material
} // namespace Gfx
+
diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h
index 49b29f8..0702428 100644
--- a/src/graphics/core/texture.h
+++ b/src/graphics/core/texture.h
@@ -136,6 +136,8 @@ struct TextureCreateParams
TexMinFilter minFilter;
//! Magnification filter
TexMagFilter magFilter;
+ //! Pad the image to nearest power of 2 dimensions
+ bool padToNearestPowerOfTwo;
//! Constructor; calls LoadDefault()
TextureCreateParams()
@@ -146,6 +148,7 @@ struct TextureCreateParams
{
format = TEX_IMG_RGB;
mipmap = false;
+ padToNearestPowerOfTwo = false;
minFilter = TEX_MIN_FILTER_NEAREST;
magFilter = TEX_MAG_FILTER_NEAREST;
@@ -212,6 +215,8 @@ struct Texture
unsigned int id;
//! Size of texture
Math::IntPoint size;
+ //! Original size of texture (as loaded from image)
+ Math::IntPoint originalSize;
//! Whether the texture has alpha channel
bool alpha;
@@ -264,3 +269,4 @@ struct Texture
} // namespace Gfx
+
diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h
index 66e1503..c3a657a 100644
--- a/src/graphics/core/vertex.h
+++ b/src/graphics/core/vertex.h
@@ -140,3 +140,4 @@ struct VertexTex2
} // namespace Gfx
+
diff --git a/src/graphics/d3d/README.txt b/src/graphics/d3d/README.txt
index 0fe7db6..4f96f27 100644
--- a/src/graphics/d3d/README.txt
+++ b/src/graphics/d3d/README.txt
@@ -1 +1,2 @@
Possible future DirectX implementation of graphics engine
+
diff --git a/src/graphics/engine/README.txt b/src/graphics/engine/README.txt
index 05d2d76..fbf45fd 100644
--- a/src/graphics/engine/README.txt
+++ b/src/graphics/engine/README.txt
@@ -7,3 +7,4 @@
*
* Graphics operations are done on abstract interface from src/graphics/core
*/
+
diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp
index f65a59a..f0c379c 100644
--- a/src/graphics/engine/camera.cpp
+++ b/src/graphics/engine/camera.cpp
@@ -1676,3 +1676,4 @@ Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
}
+
diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h
index 0ffc2c2..6d94dad 100644
--- a/src/graphics/engine/camera.h
+++ b/src/graphics/engine/camera.h
@@ -128,8 +128,7 @@ enum CameraOverEffect
... */
class CCamera {
-
- public:
+public:
CCamera();
~CCamera();
@@ -391,3 +390,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp
index d9ebf5a..74083af 100644
--- a/src/graphics/engine/cloud.cpp
+++ b/src/graphics/engine/cloud.cpp
@@ -270,3 +270,4 @@ bool CCloud::GetEnabled()
} // namespace Gfx
+
diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h
index 8f644f0..8e820c7 100644
--- a/src/graphics/engine/cloud.h
+++ b/src/graphics/engine/cloud.h
@@ -140,3 +140,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index e2ef569..669ea42 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -42,6 +42,8 @@
#include "ui/interface.h"
+#include <iomanip>
+
template<> Gfx::CEngine* CSingleton<Gfx::CEngine>::m_instance = nullptr;
// Graphics module namespace
@@ -94,7 +96,6 @@ CEngine::CEngine(CApplication *app)
m_backgroundCloudUp = Color();
m_backgroundCloudDown = Color();
m_backgroundFull = false;
- m_backgroundScale = Math::Point(1.0f, 1.0f);
m_overFront = true;
m_overColor = Color();
m_overMode = ENG_RSTATE_TCOLOR_BLACK;
@@ -127,6 +128,9 @@ CEngine::CEngine(CApplication *app)
m_interfaceMode = false;
+ m_debugLights = false;
+ m_debugDumpLights = false;
+
m_mice[ENG_MOUSE_NORM] = EngineMouse( 0, 1, 32, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 1.0f, 1.0f));
m_mice[ENG_MOUSE_WAIT] = EngineMouse( 2, 3, 33, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 8.0f, 12.0f));
m_mice[ENG_MOUSE_HAND] = EngineMouse( 4, 5, 34, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 7.0f, 2.0f));
@@ -237,7 +241,6 @@ void CEngine::SetTerrain(CTerrain* terrain)
m_terrain = terrain;
}
-
bool CEngine::Create()
{
m_size = m_app->GetVideoConfig().size;
@@ -317,7 +320,7 @@ void CEngine::ResetAfterDeviceChanged()
m_text->FlushCache();
- // TODO reload textures, reset device state, etc.
+ FlushTextureCache();
}
bool CEngine::ProcessEvent(const Event &event)
@@ -325,7 +328,22 @@ bool CEngine::ProcessEvent(const Event &event)
if (event.type == EVENT_KEY_DOWN)
{
if (event.key.key == KEY(F12))
+ {
m_showStats = !m_showStats;
+ return false;
+ }
+
+ if (event.key.key == KEY(F11))
+ {
+ m_debugLights = !m_debugLights;
+ return false;
+ }
+
+ if (event.key.key == KEY(F10))
+ {
+ m_debugDumpLights = true;
+ return false;
+ }
}
// By default, pass on all events
@@ -591,6 +609,27 @@ void CEngine::CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank)
assert(destBaseObjRank >= 0 && destBaseObjRank < static_cast<int>( m_baseObjects.size() ));
m_baseObjects[destBaseObjRank] = m_baseObjects[sourceBaseObjRank];
+
+ EngineBaseObject& p1 = m_baseObjects[destBaseObjRank];
+
+ if (! p1.used)
+ return;
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
+ {
+ EngineBaseObjLODTier& p3 = p2.next[l3];
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
+ {
+ EngineBaseObjDataTier& p4 = p3.next[l4];
+ p4.staticBufferId = 0;
+ }
+ }
+ }
}
void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector<VertexTex2>& vertices,
@@ -677,6 +716,82 @@ void CEngine::AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buff
p1.totalTriangles += p4.vertices.size() - 2;
}
+void CEngine::DebugObject(int objRank)
+{
+ assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
+
+ CLogger* l = GetLogger();
+
+ l->Debug("Debug object: %d\n", objRank);
+ if (! m_objects[objRank].used)
+ {
+ l->Debug(" not used\n");
+ return;
+ }
+
+ l->Debug(" baseObjRank = %d\n", m_objects[objRank].baseObjRank);
+ l->Debug(" visible = %s\n", m_objects[objRank].visible ? "true" : "false");
+ l->Debug(" drawWorld = %s\n", m_objects[objRank].drawWorld ? "true" : "false");
+ l->Debug(" drawFront = %s\n", m_objects[objRank].drawFront ? "true" : "false");
+ l->Debug(" type = %d\n", m_objects[objRank].type);
+ l->Debug(" distance = %f\n", m_objects[objRank].distance);
+ l->Debug(" shadowRank = %d\n", m_objects[objRank].shadowRank);
+ l->Debug(" transparency = %f\n", m_objects[objRank].transparency);
+
+ l->Debug(" baseObj:\n");
+ int baseObjRank = m_objects[objRank].baseObjRank;
+ if (baseObjRank == -1)
+ {
+ l->Debug(" null\n");
+ return;
+ }
+
+ assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
+
+ EngineBaseObject& p1 = m_baseObjects[baseObjRank];
+ if (!p1.used)
+ {
+ l->Debug(" not used\n");
+ return;
+ }
+
+ std::string vecStr;
+
+ vecStr = p1.bboxMin.ToString();
+ l->Debug(" bboxMin: %s\n", vecStr.c_str());
+ vecStr = p1.bboxMax.ToString();
+ l->Debug(" bboxMax: %s\n", vecStr.c_str());
+ l->Debug(" totalTriangles: %d\n", p1.totalTriangles);
+ l->Debug(" radius: %f\n", p1.radius);
+
+ for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
+ {
+ EngineBaseObjTexTier& p2 = p1.next[l2];
+ l->Debug(" l2:\n");
+
+ l->Debug(" tex1: %s (id: %u)\n", p2.tex1Name.c_str(), p2.tex1.id);
+ l->Debug(" tex2: %s (id: %u)\n", p2.tex2Name.c_str(), p2.tex2.id);
+
+ for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
+ {
+ EngineBaseObjLODTier& p3 = p2.next[l3];
+
+ l->Debug(" l3:\n");
+ l->Debug(" lodLevel: %d\n", p3.lodLevel);
+
+ for (int l4 = 0; l4 < static_cast<int>( p3.next.size() ); l4++)
+ {
+ EngineBaseObjDataTier& p4 = p3.next[l4];
+
+ l->Debug(" l4:\n");
+ l->Debug(" type: %d\n", p4.type);
+ l->Debug(" state: %d\n", p4.state);
+ l->Debug(" staticBufferId: %u\n", p4.staticBufferId);
+ l->Debug(" updateStaticBuffer: %s\n", p4.updateStaticBuffer ? "true" : "false");
+ }
+ }
+ }
+}
int CEngine::CreateObject()
{
@@ -965,13 +1080,19 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name)
for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
- EngineBaseObjTexTier& p2 = p1.next[l2];
-
- if (p2.tex2Name == tex2Name)
+ if (p1.next[l2].tex2Name == tex2Name)
continue; // already new
- EngineBaseObjTexTier& newP2 = AddLevel2(p1, p2.tex1Name, tex2Name);
- newP2.next.swap(p2.next);
+ std::string tex1Name = p1.next[l2].tex1Name;
+ EngineBaseObjTexTier& newP2 = AddLevel2(p1, tex1Name, tex2Name);
+ newP2.next.insert(newP2.next.end(), p1.next[l2].next.begin(), p1.next[l2].next.end());
+ p1.next[l2].next.clear();
+
+ if (!newP2.tex1.Valid())
+ newP2.tex1 = LoadTexture(newP2.tex1Name);
+
+ if (!newP2.tex2.Valid())
+ newP2.tex2 = LoadTexture(newP2.tex2Name);
}
}
@@ -2098,25 +2219,44 @@ Texture CEngine::CreateTexture(const std::string& texName, const TextureCreatePa
return Texture(); // invalid texture
Texture tex;
+ CImage img;
if (image == nullptr)
{
- CImage img;
- if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ bool loadedFromTexPack = false;
+
+ std::string texPackName = m_app->GetTexPackFilePath(texName);
+ if (! texPackName.empty())
{
- std::string error = img.GetError();
- GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
- m_texBlacklist.insert(texName);
- return Texture(); // invalid texture
+ if (img.Load(texPackName))
+ {
+ loadedFromTexPack = true;
+ }
+ else
+ {
+ std::string error = img.GetError();
+ GetLogger()->Error("Couldn't load texture '%s' from texpack: %s, blacklisting the texpack path\n",
+ texName.c_str(), error.c_str());
+ m_texBlacklist.insert(texPackName);
+ }
}
- tex = m_device->CreateTexture(&img, params);
- }
- else
- {
- tex = m_device->CreateTexture(image, params);
+ if (!loadedFromTexPack)
+ {
+ if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ {
+ std::string error = img.GetError();
+ GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
+ m_texBlacklist.insert(texName);
+ return Texture(); // invalid texture
+ }
+ }
+
+ image = &img;
}
+ tex = m_device->CreateTexture(image, params);
+
if (! tex.Valid())
{
GetLogger()->Error("Couldn't load texture '%s', blacklisting\n", texName.c_str());
@@ -2150,8 +2290,7 @@ Texture CEngine::LoadTexture(const std::string& name, const TextureCreateParams&
if (it != m_texNameMap.end())
return (*it).second;
- Texture tex = CreateTexture(name, params);
- return tex;
+ return CreateTexture(name, params);
}
bool CEngine::LoadAllTextures()
@@ -2167,7 +2306,11 @@ bool CEngine::LoadAllTextures()
LoadTexture("map.png");
if (! m_backgroundName.empty())
- m_backgroundTex = LoadTexture(m_backgroundName);
+ {
+ TextureCreateParams params = m_defaultTexParams;
+ params.padToNearestPowerOfTwo = true;
+ m_backgroundTex = LoadTexture(m_backgroundName, params);
+ }
else
m_backgroundTex.SetInvalid();
@@ -2405,6 +2548,13 @@ void CEngine::DeleteTexture(const Texture& tex)
m_texNameMap.erase(it);
}
+void CEngine::FlushTextureCache()
+{
+ m_texNameMap.clear();
+ m_revTexNameMap.clear();
+ m_texBlacklist.clear();
+}
+
bool CEngine::SetTexture(const std::string& name, int stage)
{
auto it = m_texNameMap.find(name);
@@ -2588,8 +2738,7 @@ float CEngine::GetFogStart(int rank)
}
void CEngine::SetBackground(const std::string& name, Color up, Color down,
- Color cloudUp, Color cloudDown,
- bool full, Math::Point scale)
+ Color cloudUp, Color cloudDown, bool full)
{
if (m_backgroundTex.Valid())
{
@@ -2603,15 +2752,17 @@ void CEngine::SetBackground(const std::string& name, Color up, Color down,
m_backgroundCloudUp = cloudUp;
m_backgroundCloudDown = cloudDown;
m_backgroundFull = full;
- m_backgroundScale = scale;
if (! m_backgroundName.empty())
- m_backgroundTex = LoadTexture(m_backgroundName);
+ {
+ TextureCreateParams params = m_defaultTexParams;
+ params.padToNearestPowerOfTwo = true;
+ m_backgroundTex = LoadTexture(m_backgroundName, params);
+ }
}
void CEngine::GetBackground(std::string& name, Color& up, Color& down,
- Color& cloudUp, Color& cloudDown,
- bool &full, Math::Point& scale)
+ Color& cloudUp, Color& cloudDown, bool &full)
{
name = m_backgroundName;
up = m_backgroundColorUp;
@@ -2619,7 +2770,6 @@ void CEngine::GetBackground(std::string& name, Color& up, Color& down,
cloudUp = m_backgroundCloudUp;
cloudDown = m_backgroundCloudDown;
full = m_backgroundFull;
- scale = m_backgroundScale;
}
void CEngine::SetForegroundName(const std::string& name)
@@ -3161,6 +3311,15 @@ void CEngine::Draw3DScene()
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN);
+ if (m_debugLights)
+ m_device->DebugLights();
+
+ if (m_debugDumpLights)
+ {
+ m_debugDumpLights = false;
+ m_lightMan->DebugDumpLights();
+ }
+
if (m_waterMode)
{
m_app->StartPerformanceCounter(PCNT_RENDER_WATER);
@@ -3630,7 +3789,7 @@ void CEngine::DrawShadow()
float lastIntensity = -1.0f;
for (int i = 0; i < static_cast<int>( m_shadows.size() ); i++)
{
- if (m_shadows[i].hide)
+ if (m_shadows[i].hide || !m_shadows[i].used)
continue;
Math::Vector pos = m_shadows[i].pos; // pos = center of the shadow on the ground
@@ -3879,8 +4038,12 @@ void CEngine::DrawBackgroundImage()
v2 = v1+h;
}
- u2 *= m_backgroundScale.x;
- v2 *= m_backgroundScale.y;
+ Math::Point backgroundScale;
+ backgroundScale.x = static_cast<float>(m_backgroundTex.originalSize.x) / static_cast<float>(m_backgroundTex.size.x);
+ backgroundScale.y = static_cast<float>(m_backgroundTex.originalSize.y) / static_cast<float>(m_backgroundTex.size.y);
+
+ u2 *= backgroundScale.x;
+ v2 *= backgroundScale.y;
SetTexture(m_backgroundTex);
SetState(ENG_RSTATE_OPAQUE_TEXTURE | ENG_RSTATE_WRAP);
@@ -4279,3 +4442,4 @@ void CEngine::DrawStats()
} // namespace Gfx
+
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index f9dfd45..5ecde8f 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -118,7 +118,7 @@ enum EngineRenderState
//! Mode for rendering text
ENG_RSTATE_TEXT = (1<<18),
//! Only opaque texture, no blending, etc.
- ENG_RSTATE_OPAQUE_TEXTURE = (1<<19),
+ ENG_RSTATE_OPAQUE_TEXTURE = (1<<19),
//! Only opaque color, no texture, blending, etc.
ENG_RSTATE_OPAQUE_COLOR = (1<<20)
};
@@ -171,7 +171,7 @@ enum EngineObjectType
//! Fixed object
ENG_OBJTYPE_FIX = 2,
//! Moving object
- ENG_OBJTYPE_VEHICULE = 3,
+ ENG_OBJTYPE_VEHICLE = 3,
//! Part of a moving object
ENG_OBJTYPE_DESCENDANT = 4,
//! Fixed object type quartz
@@ -194,10 +194,15 @@ struct EngineBaseObjDataTier
unsigned int staticBufferId;
bool updateStaticBuffer;
- inline EngineBaseObjDataTier(EngineTriangleType type = ENG_TRIANGLE_TYPE_TRIANGLES,
- const Material& material = Material(),
- int state = ENG_RSTATE_NORMAL)
- : type(type), material(material), state(state), staticBufferId(0), updateStaticBuffer(false) {}
+ inline EngineBaseObjDataTier(EngineTriangleType _type = ENG_TRIANGLE_TYPE_TRIANGLES,
+ const Material& _material = Material(),
+ int _state = ENG_RSTATE_NORMAL)
+ : type(_type)
+ , material(_material)
+ , state(_state)
+ , staticBufferId(0)
+ , updateStaticBuffer(false)
+ {}
};
/**
@@ -209,8 +214,9 @@ struct EngineBaseObjLODTier
LODLevel lodLevel;
std::vector<EngineBaseObjDataTier> next;
- inline EngineBaseObjLODTier(LODLevel lodLevel = LOD_Constant)
- : lodLevel(lodLevel) {}
+ inline EngineBaseObjLODTier(LODLevel _lodLevel = LOD_Constant)
+ : lodLevel(_lodLevel)
+ {}
};
/**
@@ -225,8 +231,10 @@ struct EngineBaseObjTexTier
Texture tex2;
std::vector<EngineBaseObjLODTier> next;
- inline EngineBaseObjTexTier(const std::string& tex1Name = "", const std::string& tex2Name = "")
- : tex1Name(tex1Name), tex2Name(tex2Name) {}
+ inline EngineBaseObjTexTier(const std::string& _tex1Name = "", const std::string& _tex2Name = "")
+ : tex1Name(_tex1Name)
+ , tex2Name(_tex2Name)
+ {}
};
/**
@@ -556,18 +564,17 @@ struct EngineMouse
//! Hot point
Math::Point hotPoint;
- inline EngineMouse(int icon1 = -1, int icon2 = -1, int iconShadow = -1,
- EngineRenderState mode1 = ENG_RSTATE_NORMAL,
- EngineRenderState mode2 = ENG_RSTATE_NORMAL,
- Math::Point hotPoint = Math::Point())
- {
- this->icon1 = icon1;
- this->icon2 = icon2;
- this->iconShadow = iconShadow;
- this->mode1 = mode1;
- this->mode2 = mode2;
- this->hotPoint = hotPoint;
- }
+ inline EngineMouse(int _icon1 = -1, int _icon2 = -1, int _iconShadow = -1,
+ EngineRenderState _mode1 = ENG_RSTATE_NORMAL,
+ EngineRenderState _mode2 = ENG_RSTATE_NORMAL,
+ Math::Point _hotPoint = Math::Point())
+ : icon1(_icon1)
+ , icon2(_icon2)
+ , iconShadow(_iconShadow)
+ , mode1(_mode1)
+ , mode2(_mode2)
+ , hotPoint(_hotPoint)
+ {}
};
@@ -726,6 +733,7 @@ public:
//! Writes a screenshot containing the current frame
bool WriteScreenShot(const std::string& fileName, int width, int height);
+
//@{
//! Management of game pause mode
void SetPause(bool pause);
@@ -799,6 +807,9 @@ public:
// Objects
+ //! Print debug info about an object
+ void DebugObject(int rank);
+
//! Creates a new object and returns its rank
int CreateObject();
//! Deletes all objects, shadows and ground spots
@@ -957,6 +968,9 @@ public:
//! Deletes the given texture, unloading it and removing from cache
void DeleteTexture(const Texture& tex);
+ //! Empties the texture cache
+ void FlushTextureCache();
+
//! Defines of the distance field of vision
void SetTerrainVision(float vision);
@@ -1050,10 +1064,10 @@ public:
//! Management of the background image to use
void SetBackground(const std::string& name, Color up = Color(), Color down = Color(),
Color cloudUp = Color(), Color cloudDown = Color(),
- bool full = false, Math::Point scale = Math::Point(1.0f, 1.0f));
+ bool full = false);
void GetBackground(std::string& name, Color& up, Color& down,
Color& cloudUp, Color& cloudDown,
- bool& full, Math::Point& scale);
+ bool& full);
//@}
//! Specifies the name of foreground texture
@@ -1346,7 +1360,6 @@ protected:
bool m_firstGroundSpot;
int m_secondTexNum;
bool m_backgroundFull;
- Math::Point m_backgroundScale;
std::string m_backgroundName;
Texture m_backgroundTex;
Color m_backgroundColorUp;
@@ -1424,7 +1437,11 @@ protected:
//! True when drawing 2D UI
bool m_interfaceMode;
+
+ bool m_debugLights;
+ bool m_debugDumpLights;
};
} // namespace Gfx
+
diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp
index 16c84ea..8694c7a 100644
--- a/src/graphics/engine/lightman.cpp
+++ b/src/graphics/engine/lightman.cpp
@@ -71,6 +71,7 @@ void LightProgression::SetTarget(float value)
DynamicLight::DynamicLight()
{
+ rank = 0;
used = enabled = false;
priority = LIGHT_PRI_LOW;
includeType = excludeType = ENG_OBJTYPE_NULL;
@@ -98,6 +99,61 @@ void CLightManager::SetDevice(CDevice* device)
m_lightMap = std::vector<int>(m_device->GetMaxLightCount(), -1);
}
+void CLightManager::DebugDumpLights()
+{
+ CLogger* l = GetLogger();
+
+ l->Debug("Dynamic lights:\n");
+
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); ++i)
+ {
+ const DynamicLight& dynLight = m_dynLights[i];
+ if (!dynLight.used)
+ continue;
+
+ int deviceLight = -1;
+ for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j)
+ {
+ if (m_lightMap[j] == i)
+ {
+ deviceLight = j;
+ break;
+ }
+ }
+
+ l->Debug(" light %d\n", i);
+ l->Debug(" enabled = %s\n", dynLight.enabled ? "true" : "false");
+ l->Debug(" priority = %d\n", dynLight.priority);
+ l->Debug(" device light = %d\n", deviceLight);
+ l->Debug(" light:\n");
+
+ const Light& light = dynLight.light;
+ std::string str;
+
+ l->Debug(" type = %d\n", light.type);
+ str = light.ambient.ToString();
+ l->Debug(" ambient = %s\n", str.c_str());
+ str = light.diffuse.ToString();
+ l->Debug(" diffuse = %s\n", str.c_str());
+ str = light.specular.ToString();
+ l->Debug(" specular = %s\n", str.c_str());
+ str = light.position.ToString();
+ l->Debug(" position = %s\n", str.c_str());
+ str = light.direction.ToString();
+ l->Debug(" direction = %s\n", str.c_str());
+ l->Debug(" attenuation0 = %f\n", light.attenuation0);
+ l->Debug(" attenuation1 = %f\n", light.attenuation1);
+ l->Debug(" attenuation2 = %f\n", light.attenuation2);
+ l->Debug(" spotAngle = %f\n", light.spotAngle);
+ l->Debug(" spotIntensity = %f\n", light.spotIntensity);
+
+ l->Debug(" intensity: %f\n", dynLight.intensity.current);
+ l->Debug(" color: %f %f %f\n", dynLight.colorRed.current, dynLight.colorGreen.current, dynLight.colorBlue.current);
+ l->Debug(" includeType: %d\n", dynLight.includeType);
+ l->Debug(" excludeType: %d\n", dynLight.excludeType);
+ }
+}
+
void CLightManager::FlushLights()
{
m_dynLights.clear();
@@ -117,6 +173,7 @@ int CLightManager::CreateLight(LightPriority priority)
m_dynLights.push_back(DynamicLight());
m_dynLights[index] = DynamicLight();
+ m_dynLights[index].rank = index;
m_dynLights[index].used = true;
m_dynLights[index].enabled = true;
m_dynLights[index].priority = priority;
@@ -179,6 +236,15 @@ bool CLightManager::SetLightEnabled(int lightRank, bool enabled)
return true;
}
+bool CLightManager::SetLightPriority(int lightRank, LightPriority priority)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].priority = priority;
+ return true;
+}
+
bool CLightManager::SetLightIncludeType(int lightRank, EngineObjectType type)
{
if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
@@ -411,7 +477,7 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
if (enabled)
{
- m_lightMap[lightMapIndex] = i;
+ m_lightMap[lightMapIndex] = sortedLights[i].rank;
++lightMapIndex;
}
@@ -424,8 +490,9 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type)
int rank = m_lightMap[i];
if (rank != -1)
{
- sortedLights[rank].light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
- m_device->SetLight(i, sortedLights[rank].light);
+ Light light = m_dynLights[rank].light;
+ light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
+ m_device->SetLight(i, light);
m_device->SetLightEnabled(i, true);
}
else
@@ -445,6 +512,9 @@ CLightManager::LightsComparator::LightsComparator(Math::Vector eyePos, EngineObj
float CLightManager::LightsComparator::GetLightWeight(const DynamicLight& dynLight)
{
+ if (dynLight.priority == LIGHT_PRI_HIGHEST)
+ return -1.0f;
+
bool enabled = true;
if (!dynLight.used || !dynLight.enabled || dynLight.intensity.current == 0.0f)
enabled = false;
@@ -465,3 +535,4 @@ bool CLightManager::LightsComparator::operator()(const DynamicLight& left, const
}
} // namespace Gfx
+
diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h
index ab66524..a2f6044 100644
--- a/src/graphics/engine/lightman.h
+++ b/src/graphics/engine/lightman.h
@@ -71,8 +71,9 @@ struct LightProgression
*/
enum LightPriority
{
- LIGHT_PRI_HIGH = 1,
- LIGHT_PRI_LOW = 2
+ LIGHT_PRI_HIGHEST = 0, //!< always highest weight (always picked)
+ LIGHT_PRI_HIGH = 1, //!< high weight
+ LIGHT_PRI_LOW = 2 //!< low weight
};
/**
@@ -84,6 +85,9 @@ enum LightPriority
*/
struct DynamicLight
{
+ //! Rank (index)
+ int rank;
+
//! Whether the light is used
bool used;
//! Whether the light is turned on
@@ -136,6 +140,9 @@ public:
//! Sets the device to be used
void SetDevice(CDevice* device);
+ //! Prints debug info
+ void DebugDumpLights();
+
//! Clears and disables all lights
void FlushLights();
//! Creates a new dynamic light and returns its index (lightRank)
@@ -148,6 +155,8 @@ public:
bool GetLight(int lightRank, Light &light);
//! Enables/disables the given dynamic light
bool SetLightEnabled(int lightRank, bool enable);
+ //! Changes the light priority
+ bool SetLightPriority(int lightRank, LightPriority priority);
//! Sets what objects are included in given dynamic light
bool SetLightIncludeType(int lightRank, EngineObjectType type);
@@ -216,3 +225,4 @@ protected:
};
}; // namespace Gfx
+
diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp
index 5fdae51..4395eec 100644
--- a/src/graphics/engine/lightning.cpp
+++ b/src/graphics/engine/lightning.cpp
@@ -418,3 +418,4 @@ CObject* CLightning::SearchObject(Math::Vector pos)
} // namespace Gfx
+
diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h
index 7809a6c..1b1d339 100644
--- a/src/graphics/engine/lightning.h
+++ b/src/graphics/engine/lightning.h
@@ -107,3 +107,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp
index f6d7a7b..99496aa 100644
--- a/src/graphics/engine/modelfile.cpp
+++ b/src/graphics/engine/modelfile.cpp
@@ -310,6 +310,7 @@ bool ReadLineString(std::istream& stream, const std::string& prefix, std::string
CModelFile::CModelFile()
+ : m_printDebugInfo(false)
{
}
@@ -615,23 +616,26 @@ bool CModelFile::ReadModel(std::istream& stream)
if (m_triangles[i].tex1Name == "plant.png")
m_triangles[i].state |= ENG_RSTATE_ALPHA;
- GetLogger()->Trace("ModelTriangle %d\n", i+1);
- std::string s1 = m_triangles[i].p1.ToString();
- GetLogger()->Trace(" p1: %s\n", s1.c_str());
- std::string s2 = m_triangles[i].p2.ToString();
- GetLogger()->Trace(" p2: %s\n", s2.c_str());
- std::string s3 = m_triangles[i].p3.ToString();
- GetLogger()->Trace(" p3: %s\n", s3.c_str());
-
- std::string d = m_triangles[i].material.diffuse.ToString();
- std::string a = m_triangles[i].material.ambient.ToString();
- std::string s = m_triangles[i].material.specular.ToString();
- GetLogger()->Trace(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str());
-
- GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(),
- m_triangles[i].variableTex2 ? "(variable)" : m_triangles[i].tex2Name.c_str());
- GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel);
- GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ if (m_printDebugInfo)
+ {
+ GetLogger()->Trace("ModelTriangle %d\n", i+1);
+ std::string s1 = m_triangles[i].p1.ToString();
+ GetLogger()->Trace(" p1: %s\n", s1.c_str());
+ std::string s2 = m_triangles[i].p2.ToString();
+ GetLogger()->Trace(" p2: %s\n", s2.c_str());
+ std::string s3 = m_triangles[i].p3.ToString();
+ GetLogger()->Trace(" p3: %s\n", s3.c_str());
+
+ std::string d = m_triangles[i].material.diffuse.ToString();
+ std::string a = m_triangles[i].material.ambient.ToString();
+ std::string s = m_triangles[i].material.specular.ToString();
+ GetLogger()->Trace(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str());
+
+ GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(),
+ m_triangles[i].variableTex2 ? "(variable)" : m_triangles[i].tex2Name.c_str());
+ GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel);
+ GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ }
}
return true;
@@ -1093,24 +1097,27 @@ bool CModelFile::ReadBinaryModel(std::istream& stream)
return false;
}
- for (int i = 0; i < static_cast<int>( m_triangles.size() ); ++i)
+ if (m_printDebugInfo)
{
- GetLogger()->Trace("ModelTriangle %d\n", i+1);
- std::string s1 = m_triangles[i].p1.ToString();
- GetLogger()->Trace(" p1: %s\n", s1.c_str());
- std::string s2 = m_triangles[i].p2.ToString();
- GetLogger()->Trace(" p2: %s\n", s2.c_str());
- std::string s3 = m_triangles[i].p3.ToString();
- GetLogger()->Trace(" p3: %s\n", s3.c_str());
-
- std::string d = m_triangles[i].material.diffuse.ToString();
- std::string a = m_triangles[i].material.ambient.ToString();
- std::string s = m_triangles[i].material.specular.ToString();
- GetLogger()->Trace(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str());
-
- GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(), m_triangles[i].tex2Name.c_str());
- GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel);
- GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); ++i)
+ {
+ GetLogger()->Trace("ModelTriangle %d\n", i+1);
+ std::string s1 = m_triangles[i].p1.ToString();
+ GetLogger()->Trace(" p1: %s\n", s1.c_str());
+ std::string s2 = m_triangles[i].p2.ToString();
+ GetLogger()->Trace(" p2: %s\n", s2.c_str());
+ std::string s3 = m_triangles[i].p3.ToString();
+ GetLogger()->Trace(" p3: %s\n", s3.c_str());
+
+ std::string d = m_triangles[i].material.diffuse.ToString();
+ std::string a = m_triangles[i].material.ambient.ToString();
+ std::string s = m_triangles[i].material.specular.ToString();
+ GetLogger()->Trace(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str());
+
+ GetLogger()->Trace(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(), m_triangles[i].tex2Name.c_str());
+ GetLogger()->Trace(" lod level: %d\n", m_triangles[i].lodLevel);
+ GetLogger()->Trace(" state: %ld\n", m_triangles[i].state);
+ }
}
return true;
@@ -1197,5 +1204,10 @@ int CModelFile::GetTriangleCount()
return m_triangles.size();
}
+void CModelFile::SetPrintDebugInfo(bool printDebugInfo)
+{
+ m_printDebugInfo = printDebugInfo;
+}
} // namespace Gfx
+
diff --git a/src/graphics/engine/modelfile.h b/src/graphics/engine/modelfile.h
index 3a702cb..3b4019b 100644
--- a/src/graphics/engine/modelfile.h
+++ b/src/graphics/engine/modelfile.h
@@ -137,6 +137,9 @@ public:
//! Returns the triangle vector
const std::vector<ModelTriangle>& GetTriangles();
+ //! Controls printing of debug information
+ void SetPrintDebugInfo(bool printDebugInfo);
+
protected:
//@{
//! @deprecated min, max conversions
@@ -147,6 +150,8 @@ protected:
protected:
//! Model triangles
std::vector<ModelTriangle> m_triangles;
+ bool m_printDebugInfo;
};
}; // namespace Gfx
+
diff --git a/src/graphics/engine/modelmanager.cpp b/src/graphics/engine/modelmanager.cpp
index c23b79d..abc8c6c 100644
--- a/src/graphics/engine/modelmanager.cpp
+++ b/src/graphics/engine/modelmanager.cpp
@@ -23,10 +23,13 @@ CModelManager::~CModelManager()
bool CModelManager::LoadModel(const std::string& fileName, bool mirrored)
{
- GetLogger()->Info("Loading model '%s'\n", fileName.c_str());
+ GetLogger()->Debug("Loading model '%s'\n", fileName.c_str());
CModelFile modelFile;
+ if (CApplication::GetInstance().IsDebugModeActive(DEBUG_MODELS))
+ modelFile.SetPrintDebugInfo(true);
+
std::string filePath = CApplication::GetInstance().GetDataFilePath(DIR_MODEL, fileName);
if (!modelFile.ReadModel(filePath))
@@ -111,6 +114,8 @@ bool CModelManager::AddModelCopy(const std::string& fileName, bool mirrored, int
m_engine->CopyBaseObject((*it).second.baseObjRank, copyBaseObjRank);
m_engine->SetObjectBaseRank(objRank, copyBaseObjRank);
+ m_copiesBaseRanks.push_back(copyBaseObjRank);
+
return true;
}
@@ -128,6 +133,16 @@ int CModelManager::GetModelBaseObjRank(const std::string& fileName, bool mirrore
return (*it).second.baseObjRank;
}
+void CModelManager::DeleteAllModelCopies()
+{
+ for (int baseObjRank : m_copiesBaseRanks)
+ {
+ m_engine->DeleteBaseObject(baseObjRank);
+ }
+
+ m_copiesBaseRanks.clear();
+}
+
void CModelManager::UnloadModel(const std::string& fileName, bool mirrored)
{
auto it = m_models.find(FileInfo(fileName, mirrored));
@@ -189,3 +204,4 @@ float CModelManager::GetHeight(std::vector<ModelTriangle>& triangles, Math::Vect
}
+
diff --git a/src/graphics/engine/modelmanager.h b/src/graphics/engine/modelmanager.h
index 601d636..9d50b97 100644
--- a/src/graphics/engine/modelmanager.h
+++ b/src/graphics/engine/modelmanager.h
@@ -53,6 +53,9 @@ public:
//! Returns the rank of base engine object of given loaded model
int GetModelBaseObjRank(const std::string& fileName, bool mirrored);
+ //! Deletes all copied objects
+ void DeleteAllModelCopies();
+
//! Unloads the given model
void UnloadModel(const std::string& fileName, bool mirrored);
//! Unloads all models
@@ -76,8 +79,10 @@ private:
std::string fileName;
bool mirrored;
- inline FileInfo(const std::string& fileName, bool mirrored)
- : fileName(fileName), mirrored(mirrored) {}
+ inline FileInfo(const std::string& _fileName, bool _mirrored)
+ : fileName(_fileName)
+ , mirrored(_mirrored)
+ {}
inline bool operator<(const FileInfo& other) const
{
@@ -91,7 +96,9 @@ private:
}
};
std::map<FileInfo, ModelInfo> m_models;
+ std::vector<int> m_copiesBaseRanks;
CEngine* m_engine;
};
} // namespace Gfx
+
diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp
index d15ee3b..abee2e2 100644
--- a/src/graphics/engine/particle.cpp
+++ b/src/graphics/engine/particle.cpp
@@ -3553,9 +3553,9 @@ void CParticle::DrawParticle(int sheet)
{
m_engine->SetTexture("text.png");
m_engine->SetState(ENG_RSTATE_TTEXTURE_WHITE);
- Math::Matrix mat;
- mat.LoadIdentity();
- m_device->SetTransform(TRANSFORM_WORLD, mat);
+ Math::Matrix matrix;
+ matrix.LoadIdentity();
+ m_device->SetTransform(TRANSFORM_WORLD, matrix);
for (int i = 0; i < m_wheelTraceTotal; i++)
DrawParticleWheel(i);
@@ -3917,3 +3917,4 @@ bool CParticle::WriteWheelTrace(const char *filename, int width, int height,
}
} // namespace Gfx
+
diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h
index 708a04d..7fb24a1 100644
--- a/src/graphics/engine/particle.h
+++ b/src/graphics/engine/particle.h
@@ -395,3 +395,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp
index 49bcb4c..0c96f63 100644
--- a/src/graphics/engine/planet.cpp
+++ b/src/graphics/engine/planet.cpp
@@ -185,3 +185,4 @@ int CPlanet::GetMode()
} // namespace Gfx
+
diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h
index 3762e1d..58d3aeb 100644
--- a/src/graphics/engine/planet.h
+++ b/src/graphics/engine/planet.h
@@ -118,3 +118,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp
index cab28b6..7c51829 100644
--- a/src/graphics/engine/pyro.cpp
+++ b/src/graphics/engine/pyro.cpp
@@ -89,13 +89,15 @@ bool CPyro::Create(PyroType type, CObject* obj, float force)
DisplayError(type, obj); // displays eventual messages
- int i = 0;
- // Copies all spheres of the object.
- for (; i < 50; i++)
{
- if ( !obj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
+ int i = 0;
+ // Copies all spheres of the object.
+ for (; i < 50; i++)
+ {
+ if ( !obj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
+ }
+ m_crashSphereUsed = i;
}
- m_crashSphereUsed = i;
// Calculates the size of the effect.
if ( oType == OBJECT_ANT ||
@@ -1554,8 +1556,15 @@ void CPyro::ExploStart()
for (int i = 0; i < OBJECTMAXPART; i++)
{
int objRank = m_object->GetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+ if (objRank == -1) continue;
+
+ // TODO: refactor later to material change
+ int oldBaseObjRank = m_engine->GetObjectBaseRank(objRank);
+ int newBaseObjRank = m_engine->CreateBaseObject();
+ m_engine->CopyBaseObject(oldBaseObjRank, newBaseObjRank);
+ m_engine->SetObjectBaseRank(objRank, newBaseObjRank);
+
+ m_engine->ChangeSecondTexture(objRank, "dirty04.png");
Math::Vector pos = m_object->GetPosition(i);
@@ -1616,6 +1625,13 @@ void CPyro::BurnStart()
{
int objRank = m_object->GetObjectRank(i);
if (objRank == -1) continue;
+
+ // TODO: refactor later to material change
+ int oldBaseObjRank = m_engine->GetObjectBaseRank(objRank);
+ int newBaseObjRank = m_engine->CreateBaseObject();
+ m_engine->CopyBaseObject(oldBaseObjRank, newBaseObjRank);
+ m_engine->SetObjectBaseRank(objRank, newBaseObjRank);
+
m_engine->ChangeSecondTexture(objRank, "dirty04.png");
}
m_engine->LoadTexture("dirty04.png");
@@ -2382,6 +2398,7 @@ void CPyro::LightOperFrame(float rTime)
{
if ( m_progress < m_lightOper[i].progress )
{
+ assert(i > 0); // TODO: if assert fails, fix the code
float progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
float intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
@@ -2399,3 +2416,4 @@ void CPyro::LightOperFrame(float rTime)
} // namespace Gfx
+
diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h
index 9548a07..98b9a1b 100644
--- a/src/graphics/engine/pyro.h
+++ b/src/graphics/engine/pyro.h
@@ -219,3 +219,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp
index c2a7855..4fe3057 100644
--- a/src/graphics/engine/terrain.cpp
+++ b/src/graphics/engine/terrain.cpp
@@ -1801,3 +1801,4 @@ float CTerrain::GetFlyingLimit(Math::Vector pos, bool noLimit)
} // namespace Gfx
+
diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h
index 1fa8dec..e2317c4 100644
--- a/src/graphics/engine/terrain.h
+++ b/src/graphics/engine/terrain.h
@@ -418,3 +418,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/test/CMakeLists.txt b/src/graphics/engine/test/CMakeLists.txt
deleted file mode 100644
index afaa86a..0000000
--- a/src/graphics/engine/test/CMakeLists.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-
-if(NOT CMAKE_BUILD_TYPE)
- set(CMAKE_BUILD_TYPE debug)
-endif(NOT CMAKE_BUILD_TYPE)
-set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
-
-set(MODELFILE_TEST_SOURCES
-modelfile_test.cpp
-../modelfile.cpp
-../../../common/logger.cpp
-../../../common/stringutils.cpp
-)
-
-add_definitions(-DMODELFILE_NO_ENGINE)
-
-include_directories(
-.
-../../..
-${GTEST_INCLUDE_DIR}
-)
-
-add_executable(modelfile_test ${MODELFILE_TEST_SOURCES})
-
-target_link_libraries(modelfile_test gtest)
-
-add_test(modelfile_test modelfile_test)
diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp
index 308c813..610bfcf 100644
--- a/src/graphics/engine/text.cpp
+++ b/src/graphics/engine/text.cpp
@@ -56,6 +56,7 @@ CText::CText(CEngine* engine)
m_engine = engine;
m_defaultSize = 12.0f;
+ m_tabSize = 4;
m_lastFontType = FONT_COLOBOT;
m_lastFontSize = 0;
@@ -148,6 +149,16 @@ void CText::FlushCache()
m_lastCachedFont = nullptr;
}
+int CText::GetTabSize()
+{
+ return m_tabSize;
+}
+
+void CText::SetTabSize(int tabSize)
+{
+ m_tabSize = tabSize;
+}
+
void CText::DrawText(const std::string &text, std::vector<FontMetaChar>::iterator format,
std::vector<FontMetaChar>::iterator end,
float size, Math::Point pos, float width, TextAlign align,
@@ -309,11 +320,16 @@ float CText::GetStringWidth(const std::string &text,
return width;
}
-float CText::GetStringWidth(const std::string &text, FontType font, float size)
+float CText::GetStringWidth(std::string text, FontType font, float size)
{
assert(font != FONT_BUTTON);
- // TODO: special chars?
+ // Skip special chars
+ for (char& c : text)
+ {
+ if (c < 32)
+ c = ':';
+ }
CachedFont* cf = GetOrOpenFont(font, size);
assert(cf != nullptr);
@@ -328,8 +344,16 @@ float CText::GetCharWidth(UTF8Char ch, FontType font, float size, float offset)
// TODO: if (font == FONT_BUTTON)
if (font == FONT_BUTTON) return 0.0f;
- // TODO: special chars?
- // TODO: tab sizing
+ int width = 1;
+ if (ch.c1 < 32)
+ {
+ if (ch.c1 == '\t')
+ width = m_tabSize;
+
+ // TODO: tab sizing at intervals?
+
+ ch.c1 = ':';
+ }
CachedFont* cf = GetOrOpenFont(font, size);
assert(cf != nullptr);
@@ -341,7 +365,7 @@ float CText::GetCharWidth(UTF8Char ch, FontType font, float size, float offset)
else
tex = CreateCharTexture(ch, cf);
- return tex.charSize.x;
+ return tex.charSize.x * width;
}
@@ -505,6 +529,63 @@ int CText::Detect(const std::string &text, FontType font, float size, float offs
return index;
}
+UTF8Char CText::TranslateSpecialChar(int specialChar)
+{
+ UTF8Char ch;
+
+ switch (specialChar)
+ {
+ case CHAR_TAB:
+ ch.c1 = ':';
+ ch.c2 = 0;
+ ch.c3 = 0;
+ break;
+
+ case CHAR_NEWLINE:
+ // Unicode: U+21B2
+ ch.c1 = 0xE2;
+ ch.c2 = 0x86;
+ ch.c3 = 0xB2;
+ break;
+
+ case CHAR_DOT:
+ // Unicode: U+23C5
+ ch.c1 = 0xE2;
+ ch.c2 = 0x8F;
+ ch.c3 = 0x85;
+ break;
+
+ case CHAR_SQUARE:
+ // Unicode: U+25FD
+ ch.c1 = 0xE2;
+ ch.c2 = 0x97;
+ ch.c3 = 0xBD;
+ break;
+
+ case CHAR_SKIP_RIGHT:
+ // Unicode: U+25B6
+ ch.c1 = 0xE2;
+ ch.c2 = 0x96;
+ ch.c3 = 0xB6;
+ break;
+
+ case CHAR_SKIP_LEFT:
+ // Unicode: U+25C0
+ ch.c1 = 0xE2;
+ ch.c2 = 0x97;
+ ch.c3 = 0x80;
+ break;
+
+ default:
+ ch.c1 = '?';
+ ch.c2 = 0;
+ ch.c3 = 0;
+ break;
+ }
+
+ return ch;
+}
+
void CText::DrawString(const std::string &text, std::vector<FontMetaChar>::iterator format,
std::vector<FontMetaChar>::iterator end,
float size, Math::Point pos, float width, int eol, Color color)
@@ -532,7 +613,11 @@ void CText::DrawString(const std::string &text, std::vector<FontMetaChar>::itera
float cw = GetCharWidth(ch, font, size, offset);
if (offset + cw > width) // exceeds the maximum width?
{
- // TODO: special end-of-line char
+ ch = TranslateSpecialChar(CHAR_SKIP_RIGHT);
+ cw = GetCharWidth(ch, font, size, offset);
+ pos.x = start + width - cw;
+ color = Color(1.0f, 0.0f, 0.0f);
+ DrawCharAndAdjustPos(ch, font, size, pos, color);
break;
}
@@ -550,7 +635,13 @@ void CText::DrawString(const std::string &text, std::vector<FontMetaChar>::itera
fmtIndex++;
}
- // TODO: eol
+ if (eol != 0)
+ {
+ FontType font = FONT_COLOBOT;
+ UTF8Char ch = TranslateSpecialChar(eol);
+ color = Color(1.0f, 0.0f, 0.0f);
+ DrawCharAndAdjustPos(ch, font, size, pos, color);
+ }
}
void CText::StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars)
@@ -675,23 +766,18 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, Math::P
// TODO: if (font == FONT_BUTTON)
if (font == FONT_BUTTON) return;
- // TODO: special chars?
-
CachedFont* cf = GetOrOpenFont(font, size);
if (cf == nullptr)
return;
int width = 1;
- if (ch.c1 > 0 && ch.c1 < 32) { // FIXME add support for chars with code 9 10 23
- if (ch.c1 == '\t') {
- ch.c1 = ':';
- width = 4;
- } else {
- ch.c1 = ' ';
- }
- ch.c2 = 0;
- ch.c3 = 0;
+ if (ch.c1 > 0 && ch.c1 < 32)
+ {
+ if (ch.c1 == '\t')
+ width = m_tabSize;
+
+ ch = TranslateSpecialChar(ch.c1);
}
auto it = cf->cache.find(ch);
@@ -827,3 +913,4 @@ CharTexture CText::CreateCharTexture(UTF8Char ch, CachedFont* font)
} // namespace Gfx
+
diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h
index 6bcc59b..3abb8b7 100644
--- a/src/graphics/engine/text.h
+++ b/src/graphics/engine/text.h
@@ -206,6 +206,20 @@ struct MultisizeFont
};
/**
+ * \enum SpecialChar
+ * \brief Special codes for certain characters
+ */
+enum SpecialChar
+{
+ CHAR_TAB = '\t', //! Tab character - :
+ CHAR_NEWLINE = '\n', //! Newline character - arrow pointing down and left
+ CHAR_DOT = 1, //! Single dot in the middle
+ CHAR_SQUARE = 2, //! Square
+ CHAR_SKIP_RIGHT = 5, //! Filled triangle pointing right
+ CHAR_SKIP_LEFT = 6 //! Filled triangle pointing left
+};
+
+/**
* \class CText
* \brief Text rendering engine
*
@@ -240,6 +254,12 @@ public:
//! Flushes cached textures
void FlushCache();
+ //@{
+ //! Tab size management
+ void SetTabSize(int tabSize);
+ int GetTabSize();
+ //@}
+
//! Draws text (multi-format)
void DrawText(const std::string &text, std::vector<FontMetaChar>::iterator format,
std::vector<FontMetaChar>::iterator end,
@@ -268,11 +288,11 @@ public:
float GetHeight(FontType font, float size);
//! Returns width of string (multi-format)
- TEST_VIRTUAL float GetStringWidth(const std::string &text,
- std::vector<FontMetaChar>::iterator format,
- std::vector<FontMetaChar>::iterator end, float size);
+ TEST_VIRTUAL float GetStringWidth(const std::string& text,
+ std::vector<FontMetaChar>::iterator format,
+ std::vector<FontMetaChar>::iterator end, float size);
//! Returns width of string (single font)
- TEST_VIRTUAL float GetStringWidth(const std::string &text, FontType font, float size);
+ TEST_VIRTUAL float GetStringWidth(std::string text, FontType font, float size);
//! Returns width of single character
TEST_VIRTUAL float GetCharWidth(UTF8Char ch, FontType font, float size, float offset);
@@ -290,6 +310,8 @@ public:
//! Returns the most suitable position to a given offset (one font)
int Detect(const std::string &text, FontType font, float size, float offset);
+ UTF8Char TranslateSpecialChar(int specialChar);
+
protected:
CachedFont* GetOrOpenFont(FontType type, float size);
CharTexture CreateCharTexture(UTF8Char ch, CachedFont* font);
@@ -309,6 +331,7 @@ protected:
std::string m_error;
float m_defaultSize;
+ int m_tabSize;
std::map<FontType, MultisizeFont*> m_fonts;
@@ -319,3 +342,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp
index d90652b..d1f8d29 100644
--- a/src/graphics/engine/water.cpp
+++ b/src/graphics/engine/water.cpp
@@ -628,3 +628,4 @@ void CWater::AdjustEye(Math::Vector &eye)
} // namespace Gfx
+
diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h
index bb113e0..5e9f4b2 100644
--- a/src/graphics/engine/water.h
+++ b/src/graphics/engine/water.h
@@ -204,3 +204,4 @@ protected:
} // namespace Gfx
+
diff --git a/src/graphics/opengl/README.txt b/src/graphics/opengl/README.txt
index c62166b..1a6bedd 100644
--- a/src/graphics/opengl/README.txt
+++ b/src/graphics/opengl/README.txt
@@ -5,3 +5,4 @@
* Contains the concrete implementation using OpenGL of abstract CDevice class
* from src/graphics/core
*/
+
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index df64e34..bbabdd6 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -79,6 +79,106 @@ void CGLDevice::DebugHook()
glColor3i(0, 0, 0);
}
+void CGLDevice::DebugLights()
+{
+ Gfx::ColorHSV color(0.0, 1.0, 1.0);
+
+ glLineWidth(3.0f);
+ glDisable(GL_LIGHTING);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_BLEND);
+
+ Math::Matrix saveWorldMat = m_worldMat;
+ m_worldMat.LoadIdentity();
+ UpdateModelviewMatrix();
+
+ for (int i = 0; i < static_cast<int>( m_lights.size() ); ++i)
+ {
+ color.h = static_cast<float>(i) / static_cast<float>(m_lights.size());
+ if (m_lightsEnabled[i])
+ {
+ const Light& l = m_lights[i];
+ if (l.type == LIGHT_DIRECTIONAL)
+ {
+ Gfx::VertexCol v[2];
+ v[0].coord = -Math::Normalize(l.direction) * 100.0f + Math::Vector(0.0f, 0.0f, 1.0f) * i;
+ v[0].color = HSV2RGB(color);
+ v[1].coord = Math::Normalize(l.direction) * 100.0f + Math::Vector(0.0f, 0.0f, 1.0f) * i;
+ v[1].color = HSV2RGB(color);
+ while (v[0].coord.y < 60.0f && v[0].coord.y < 60.0f)
+ {
+ v[0].coord.y += 10.0f;
+ v[1].coord.y += 10.0f;
+ }
+ DrawPrimitive(PRIMITIVE_LINES, v, 2);
+
+ v[0].coord = v[1].coord + Math::Normalize(v[0].coord - v[1].coord) * 50.0f;
+
+ glLineWidth(10.0f);
+ DrawPrimitive(PRIMITIVE_LINES, v, 2);
+ glLineWidth(3.0f);
+ }
+ else if (l.type == LIGHT_POINT)
+ {
+ Gfx::VertexCol v[8];
+ for (int i = 0; i < 8; ++i)
+ v[i].color = HSV2RGB(color);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector( 1.0f, -1.0f, -1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, 1.0f, -1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector(-1.0f, 1.0f, -1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector( 1.0f, -1.0f, 1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, 1.0f, 1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector(-1.0f, 1.0f, 1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, -1.0f, -1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector( 1.0f, -1.0f, 1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector( 1.0f, 1.0f, -1.0f) * 4.0f;
+ v[5].coord = l.position + Math::Vector( 1.0f, 1.0f, 1.0f) * 4.0f;
+ v[6].coord = l.position + Math::Vector(-1.0f, 1.0f, -1.0f) * 4.0f;
+ v[7].coord = l.position + Math::Vector(-1.0f, 1.0f, 1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINES, v, 8);
+ }
+ else if (l.type == LIGHT_SPOT)
+ {
+ Gfx::VertexCol v[5];
+ for (int i = 0; i < 5; ++i)
+ v[i].color = HSV2RGB(color);
+
+ v[0].coord = l.position + Math::Vector(-1.0f, 0.0f, -1.0f) * 4.0f;
+ v[1].coord = l.position + Math::Vector( 1.0f, 0.0f, -1.0f) * 4.0f;
+ v[2].coord = l.position + Math::Vector( 1.0f, 0.0f, 1.0f) * 4.0f;
+ v[3].coord = l.position + Math::Vector(-1.0f, 0.0f, 1.0f) * 4.0f;
+ v[4].coord = l.position + Math::Vector(-1.0f, 0.0f, -1.0f) * 4.0f;
+ DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5);
+
+ v[0].coord = l.position;
+ v[1].coord = l.position + Math::Normalize(l.direction) * 100.0f;
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(3.0, 0xFF);
+ DrawPrimitive(PRIMITIVE_LINES, v, 2);
+ glDisable(GL_LINE_STIPPLE);
+ }
+ }
+ }
+
+ glLineWidth(1.0f);
+ glEnable(GL_LIGHTING);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_BLEND);
+ m_worldMat = saveWorldMat;
+ UpdateModelviewMatrix();
+}
+
bool CGLDevice::Create()
{
GetLogger()->Info("Creating CDevice\n");
@@ -417,13 +517,21 @@ bool CGLDevice::GetLightEnabled(int index)
Texture CGLDevice::CreateTexture(CImage *image, const TextureCreateParams &params)
{
ImageData *data = image->GetData();
- if (data == NULL)
+ if (data == nullptr)
{
GetLogger()->Error("Invalid texture data\n");
return Texture(); // invalid texture
}
- return CreateTexture(data, params);
+ Math::IntPoint originalSize = image->GetSize();
+
+ if (params.padToNearestPowerOfTwo)
+ image->PadToNearestPowerOfTwo();
+
+ Texture tex = CreateTexture(data, params);
+ tex.originalSize = originalSize;
+
+ return tex;
}
Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &params)
@@ -433,6 +541,11 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
result.size.x = data->surface->w;
result.size.y = data->surface->h;
+ if (!Math::IsPowerOfTwo(result.size.x) || !Math::IsPowerOfTwo(result.size.y))
+ GetLogger()->Warn("Creating non-power-of-2 texture (%dx%d)!\n", result.size.x, result.size.y);
+
+ result.originalSize = result.size;
+
// Use & enable 1st texture stage
if (m_multitextureAvailable)
glActiveTexture(GL_TEXTURE0);
@@ -640,7 +753,7 @@ void CGLDevice::SetTexture(int index, const Texture &texture)
glBindTexture(GL_TEXTURE_2D, texture.id);
// Params need to be updated for the new bound texture
- SetTextureStageParams(index, m_textureStageParams[index]);
+ UpdateTextureParams(index);
}
void CGLDevice::SetTexture(int index, unsigned int textureId)
@@ -661,7 +774,7 @@ void CGLDevice::SetTexture(int index, unsigned int textureId)
glBindTexture(GL_TEXTURE_2D, textureId);
// Params need to be updated for the new bound texture
- SetTextureStageParams(index, m_textureStageParams[index]);
+ UpdateTextureParams(index);
}
/**
@@ -714,6 +827,13 @@ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams &param
// Remember the settings
m_textureStageParams[index] = params;
+ UpdateTextureParams(index);
+}
+
+void CGLDevice::UpdateTextureParams(int index)
+{
+ assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
+
if (!m_multitextureAvailable && index != 0)
return;
@@ -721,6 +841,8 @@ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams &param
if (! m_currentTextures[index].Valid())
return;
+ const TextureStageParams &params = m_textureStageParams[index];
+
if (m_multitextureAvailable)
glActiveTexture(GL_TEXTURE0 + index);
@@ -1667,3 +1789,4 @@ FillMode CGLDevice::GetFillMode()
} // namespace Gfx
+
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index fe3f2a1..c648161 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -93,6 +93,7 @@ public:
virtual ~CGLDevice();
virtual void DebugHook();
+ virtual void DebugLights();
virtual bool Create();
virtual void Destroy();
@@ -192,6 +193,8 @@ private:
void UpdateModelviewMatrix();
//! Updates position for given light based on transformation matrices
void UpdateLightPosition(int index);
+ //! Updates the texture params for given texture stage
+ void UpdateTextureParams(int index);
private:
//! Current config
@@ -255,3 +258,4 @@ private:
} // namespace Gfx
+
diff --git a/src/math/README.txt b/src/math/README.txt
index 26069aa..fcc204f 100644
--- a/src/math/README.txt
+++ b/src/math/README.txt
@@ -10,3 +10,4 @@
* This namespace was created to avoid clashing with old code, but now it still serves,
* defining a border between math and non-math-related code.
*/
+
diff --git a/src/math/all.h b/src/math/all.h
index 10c17a9..7d716c8 100644
--- a/src/math/all.h
+++ b/src/math/all.h
@@ -28,3 +28,4 @@
#include "math/vector.h"
#include "math/matrix.h"
#include "math/geometry.h"
+
diff --git a/src/math/const.h b/src/math/const.h
index 8318b7a..fee635e 100644
--- a/src/math/const.h
+++ b/src/math/const.h
@@ -53,3 +53,4 @@ const float LOG_2 = log(2.0f);
} // namespace Math
+
diff --git a/src/math/func.h b/src/math/func.h
index 413b5d9..98111c5 100644
--- a/src/math/func.h
+++ b/src/math/func.h
@@ -128,6 +128,12 @@ inline float Rand()
return static_cast<float>(rand()) / static_cast<float>(RAND_MAX);
}
+//! Returns whether \a x is an even power of 2
+inline bool IsPowerOfTwo(unsigned int x)
+{
+ return x && !(x & (x - 1));
+}
+
//! Returns the next nearest power of two to \a x
inline int NextPowerOfTwo(int x)
{
@@ -257,3 +263,4 @@ inline float Bounce(float progress, float middle = 0.3f, float bounce = 0.4f)
} // namespace Math
+
diff --git a/src/math/geometry.h b/src/math/geometry.h
index 23c149c..9dcb447 100644
--- a/src/math/geometry.h
+++ b/src/math/geometry.h
@@ -643,3 +643,4 @@ inline Math::Vector RotateView(Math::Vector center, float angleH, float angleV,
} // namespace Math
+
diff --git a/src/math/intpoint.h b/src/math/intpoint.h
index 010b0fb..872e614 100644
--- a/src/math/intpoint.h
+++ b/src/math/intpoint.h
@@ -59,3 +59,4 @@ struct IntPoint
} // namespace Math
+
diff --git a/src/math/matrix.h b/src/math/matrix.h
index e0cf492..f139517 100644
--- a/src/math/matrix.h
+++ b/src/math/matrix.h
@@ -73,10 +73,10 @@ struct Matrix
//! Creates the matrix from 1D array
/** \a m matrix values in column-major order */
- inline explicit Matrix(const float (&m)[16])
+ inline explicit Matrix(const float (&_m)[16])
{
for (int i = 0; i < 16; ++i)
- this->m[i] = m[i];
+ m[i] = _m[i];
}
//! Creates the matrix from 2D array
@@ -84,21 +84,21 @@ struct Matrix
* The array's first index is row, second is column.
* \param m array with values
*/
- inline explicit Matrix(const float (&m)[4][4])
+ inline explicit Matrix(const float (&_m)[4][4])
{
for (int c = 0; c < 4; ++c)
{
for (int r = 0; r < 4; ++r)
{
- this->m[4*c+r] = m[r][c];
+ m[4*c+r] = _m[r][c];
}
}
}
//! Sets value in given row and col
/**
- * \param row row (0 to 3)
- * \param col column (0 to 3)
+ * \param row row (1 to 4)
+ * \param col column (1 to 4)
* \param value value
*/
inline void Set(int row, int col, float value)
@@ -108,8 +108,8 @@ struct Matrix
//! Returns the value in given row and col
/**
- * \param row row (0 to 3)
- * \param col column (0 to 3)
+ * \param row row (1 to 4)
+ * \param col column (1 to 4)
* \returns value
*/
inline float Get(int row, int col)
@@ -462,3 +462,4 @@ inline Math::Vector MatrixVectorMultiply(const Math::Matrix &m, const Math::Vect
} // namespace Math
+
diff --git a/src/math/point.h b/src/math/point.h
index 456fe1e..edb902b 100644
--- a/src/math/point.h
+++ b/src/math/point.h
@@ -52,16 +52,15 @@ struct Point
//! Constructs a zero point: (0,0)
inline Point()
- {
- LoadZero();
- }
+ : x(0.0f)
+ , y(0.0f)
+ {}
//! Constructs a point from given coords: (x,y)
- inline explicit Point(float x, float y)
- {
- this->x = x;
- this->y = y;
- }
+ inline explicit Point(float _x, float _y)
+ : x(_x)
+ , y(_y)
+ {}
//! Sets the zero point: (0,0)
inline void LoadZero()
@@ -191,3 +190,4 @@ inline float Distance(const Point &a, const Point &b)
} // namespace Math
+
diff --git a/src/math/vector.h b/src/math/vector.h
index 73e8e44..6827785 100644
--- a/src/math/vector.h
+++ b/src/math/vector.h
@@ -57,17 +57,17 @@ struct Vector
//! Creates a zero vector (0, 0, 0)
inline Vector()
- {
- LoadZero();
- }
+ : x(0.0f)
+ , y(0.0f)
+ , z(0.0f)
+ {}
//! Creates a vector from given values
- inline explicit Vector(float x, float y, float z)
- {
- this->x = x;
- this->y = y;
- this->z = z;
- }
+ inline explicit Vector(float _x, float _y, float _z)
+ : x(_x)
+ , y(_y)
+ , z(_z)
+ {}
//! Loads the zero vector (0, 0, 0)
inline void LoadZero()
@@ -281,3 +281,4 @@ inline Vector Clamp(const Vector &vec, const Vector &min, const Vector &max)
} // namespace Math
+
diff --git a/src/object/README.txt b/src/object/README.txt
index fe946db..4e21620 100644
--- a/src/object/README.txt
+++ b/src/object/README.txt
@@ -5,3 +5,4 @@
* Contains the main class of game engine - CRobotMain and the various in-game objects:
* CObject and related auto, motion and task subclasses.
*/
+
diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp
index 3d88012..8dc1d94 100644
--- a/src/object/auto/auto.cpp
+++ b/src/object/auto/auto.cpp
@@ -107,6 +107,12 @@ void CAuto::Start(int param)
{
}
+// Starts an action
+
+Error CAuto::StartAction(int param)
+{
+ return ERR_GENERIC;
+}
// Gete a type.
diff --git a/src/object/auto/auto.h b/src/object/auto/auto.h
index 53ccdf9..4a430ce 100644
--- a/src/object/auto/auto.h
+++ b/src/object/auto/auto.h
@@ -31,7 +31,7 @@ namespace Ui {
class CDisplayText;
class CInterface;
class CWindow;
-} /* Ui */
+} /* Ui */
namespace Gfx {
@@ -44,7 +44,7 @@ class CCloud;
class CCamera;
class CPlanet;
class CLightning;
-} /* Gfx */
+} /* Gfx */
class CAuto
@@ -61,6 +61,8 @@ public:
virtual Error IsEnded();
virtual bool Abort();
+ virtual Error StartAction(int param);
+
virtual bool SetType(ObjectType type);
virtual bool SetValue(int rank, float value);
virtual bool SetString(char *string);
diff --git a/src/object/auto/autobase.cpp b/src/object/auto/autobase.cpp
index cb7f04c..d0bd87b 100644
--- a/src/object/auto/autobase.cpp
+++ b/src/object/auto/autobase.cpp
@@ -1412,9 +1412,8 @@ void CAutoBase::BeginTransit()
m_engine->SetDeepView(2000.0f); // we see very far
m_engine->ApplyChange();
- Math::Point scale;
bool full;
- m_engine->GetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, full, scale);
+ m_engine->GetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, full);
m_engine->DeleteTexture(m_bgName);
m_engine->SetBackground(m_bgBack, Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
diff --git a/src/object/auto/autoderrick.cpp b/src/object/auto/autoderrick.cpp
index 260edcb..b613406 100644
--- a/src/object/auto/autoderrick.cpp
+++ b/src/object/auto/autoderrick.cpp
@@ -589,4 +589,3 @@ Error CAutoDerrick::GetError()
return ERR_OK;
}
-
diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp
index b62a45a..fdaebc0 100644
--- a/src/object/auto/autodestroyer.cpp
+++ b/src/object/auto/autodestroyer.cpp
@@ -24,6 +24,7 @@
#include "ui/interface.h"
#include "ui/window.h"
+#include "ui/displaytext.h"
#include <stdio.h>
#include <string.h>
@@ -68,18 +69,65 @@ void CAutoDestroyer::Init()
}
+// Starts an action
+Error CAutoDestroyer::StartAction(int param)
+{
+ CObject* scrap;
+
+ if ( m_object->GetVirusMode() ) // contaminated by a virus?
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ scrap = SearchPlastic();
+ if ( scrap == nullptr )
+ return ERR_DESTROY_NOTFOUND;
+ else
+ {
+ if ( m_phase == ADEP_WAIT )
+ {
+ scrap->SetLock(true); // usable waste
+//? scrap->SetTruck(m_object); // usable waste
+
+ m_sound->Play(SOUND_PSHHH2, m_object->GetPosition(0), 1.0f, 1.0f);
+
+ m_phase = ADEP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_bExplo = false;
+ }
+ else
+ return ERR_GENERIC;
+ }
+ return ERR_OK;
+}
+
// Management of an event.
bool CAutoDestroyer::EventProcess(const Event &event)
{
- CObject* scrap;
- Gfx::CPyro* pyro;
+ CObject* scrap;
+ Gfx::CPyro* pyro;
Math::Vector pos, speed;
Math::Point dim;
+ Ui::CWindow* pw;
CAuto::EventProcess(event);
if ( m_engine->GetPause() ) return true;
+
+ if (m_main->GetSelect() == m_object)
+ {
+ if ( event.type == EVENT_OBJECT_BDESTROY )
+ {
+ Error err = StartAction(0);
+ if ( err != ERR_OK )
+ m_displayText->DisplayError(err, m_object);
+
+ return false;
+ }
+ }
+
if ( event.type != EVENT_FRAME ) return true;
m_progress += event.rTime*m_speed;
@@ -94,61 +142,21 @@ bool CAutoDestroyer::EventProcess(const Event &event)
return true;
}
+ pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( m_phase == ADEP_WAIT )
{
if ( m_progress >= 1.0f )
{
- scrap = SearchPlastic();
- if ( scrap == 0 )
- {
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- else
+ m_phase = ADEP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ if (m_main->GetSelect() == m_object)
{
- scrap->SetLock(true); // usable waste
-//? scrap->SetTruck(m_object); // usable waste
-
- if ( SearchVehicle() )
- {
- if ( m_progress < 20.0f ) {
- m_phase = ADEP_WAIT; // still waiting ...
- //m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- } else {
- if ( m_object->GetLock() ) { // If still building...
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- } else {
- m_sound->Play(SOUND_PSHHH2, m_object->GetPosition(0), 1.0f, 1.0f);
-
- m_phase = ADEP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_bExplo = false;
- }
- }
- }
- else
- {
- if ( m_object->GetLock() ) { // If still building...
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- } else {
- m_sound->Play(SOUND_PSHHH2, m_object->GetPosition(0), 1.0f, 1.0f);
-
- m_phase = ADEP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_bExplo = false;
- }
- }
+ scrap = SearchPlastic();
+ if ( pw != 0 ) EnableInterface(pw, EVENT_OBJECT_BDESTROY, (scrap != 0));
}
}
- }
+ } else if ( pw != 0 ) EnableInterface(pw, EVENT_OBJECT_BDESTROY, false);
if ( m_phase == ADEP_DOWN )
{
@@ -224,6 +232,7 @@ bool CAutoDestroyer::CreateInterface(bool bSelect)
Ui::CWindow* pw;
Math::Point pos, ddim;
float ox, oy, sx, sy;
+ CObject* scrap;
CAuto::CreateInterface(bSelect);
@@ -243,6 +252,15 @@ bool CAutoDestroyer::CreateInterface(bool bSelect)
ddim.y = 66.0f/480.0f;
pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
+ pos.x = ox+sx*8.00f;
+ pos.y = oy+sy*0.25f;
+ ddim.x = (33.0f/640.0f)*1.5f;
+ ddim.y = (33.0f/480.0f)*1.5f;
+ pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_BDESTROY);
+
+ scrap = SearchPlastic();
+ EnableInterface(pw, EVENT_OBJECT_BDESTROY, (scrap != 0));
+
return true;
}
@@ -323,68 +341,6 @@ CObject* CAutoDestroyer::SearchPlastic()
return nullptr;
}
-// Seeks if one vehicle is too close.
-
-bool CAutoDestroyer::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->GetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = static_cast< CObject* >(m_iMan->SearchInstance(CLASS_OBJECT, i));
- if ( pObj == nullptr ) break;
-
- type = pObj->GetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 20.0f ) return true;
- }
-
- return false;
-}
-
-
// Returns an error due the state of the automation.
Error CAutoDestroyer::GetError()
@@ -440,4 +396,15 @@ bool CAutoDestroyer::Read(char *line)
return true;
}
+// Changes the state of a button interface.
+
+void CAutoDestroyer::EnableInterface(Ui::CWindow *pw, EventType event, bool bState)
+{
+ Ui::CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(Ui::STATE_ENABLE, bState);
+}
diff --git a/src/object/auto/autodestroyer.h b/src/object/auto/autodestroyer.h
index 26981c3..ef3d5ae 100644
--- a/src/object/auto/autodestroyer.h
+++ b/src/object/auto/autodestroyer.h
@@ -46,6 +46,8 @@ public:
bool EventProcess(const Event &event);
Error GetError();
+ Error StartAction(int param);
+
bool CreateInterface(bool bSelect);
bool Write(char *line);
@@ -53,7 +55,7 @@ public:
protected:
CObject* SearchPlastic();
- bool SearchVehicle();
+ void EnableInterface(Ui::CWindow *pw, EventType event, bool bState);
protected:
AutoDestroyerPhase m_phase;
diff --git a/src/object/auto/autoenergy.cpp b/src/object/auto/autoenergy.cpp
index a0b4d85..6a8672b 100644
--- a/src/object/auto/autoenergy.cpp
+++ b/src/object/auto/autoenergy.cpp
@@ -649,3 +649,4 @@ bool CAutoEnergy::Read(char *line)
return true;
}
+
diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp
index 82877c6..a648656 100644
--- a/src/object/auto/autofactory.cpp
+++ b/src/object/auto/autofactory.cpp
@@ -24,6 +24,7 @@
#include "math/geometry.h"
#include "object/robotmain.h"
+#include "object/brain.h"
#include "physics/physics.h"
@@ -103,21 +104,74 @@ void CAutoFactory::Init()
m_fretPos = m_object->GetPosition(0);
+ m_program = nullptr;
+
CAuto::Init();
}
+// Starts an action
+
+Error CAutoFactory::StartAction(int param)
+{
+ CObject* fret;
+ ObjectType type = static_cast<ObjectType>(param);
+
+ if ( type != OBJECT_NULL )
+ {
+ if ( m_phase != AFP_WAIT )
+ {
+ return ERR_OK;
+ }
+
+ m_type = type;
+
+ fret = SearchFret(); // transform metal?
+ if ( fret == 0 )
+ {
+ return ERR_FACTORY_NULL;
+ }
+ if ( NearestVehicle() )
+ {
+ return ERR_FACTORY_NEAR;
+ }
+
+ SetBusy(true);
+ InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f);
+ UpdateInterface();
+
+ fret->SetLock(true); // usable metal
+ SoundManip(3.0f, 1.0f, 0.5f);
+
+ m_phase = AFP_CLOSE_S;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ return ERR_OK;
+ }
+ return ERR_GENERIC;
+}
+
+
+// Sets program for created robot
+
+void CAutoFactory::SetProgram(const char* program)
+{
+ m_program = new char[strlen(program)+1];
+ strcpy(m_program, program);
+}
+
+
// Management of an event.
bool CAutoFactory::EventProcess(const Event &event)
{
+ ObjectType type;
CObject* fret;
CObject* vehicle;
Math::Matrix* mat;
CPhysics* physics;
Math::Vector pos, speed;
Math::Point dim;
- ObjectType type;
float zoom, angle, prog;
int i;
@@ -155,39 +209,12 @@ bool CAutoFactory::EventProcess(const Event &event)
if ( event.type == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs;
if ( event.type == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa;
- if ( type != OBJECT_NULL )
- {
- m_type = type;
+ Error err = StartAction(type);
+ if( err != ERR_OK && err != ERR_GENERIC )
+ m_displayText->DisplayError(err, m_object);
- if ( m_phase != AFP_WAIT )
- {
- return false;
- }
-
- fret = SearchFret(); // transform metal?
- if ( fret == 0 )
- {
- m_displayText->DisplayError(ERR_FACTORY_NULL, m_object);
- return false;
- }
- if ( NearestVehicle() )
- {
- m_displayText->DisplayError(ERR_FACTORY_NEAR, m_object);
- return false;
- }
-
- SetBusy(true);
- InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f);
- UpdateInterface();
-
- fret->SetLock(true); // usable metal
- SoundManip(3.0f, 1.0f, 0.5f);
-
- m_phase = AFP_CLOSE_S;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- return true;
- }
+ if( err != ERR_GENERIC )
+ return false;
}
if ( event.type != EVENT_FRAME ) return true;
@@ -362,7 +389,7 @@ bool CAutoFactory::EventProcess(const Event &event)
delete fret;
}
- vehicle = SearchVehicle();
+ m_vehicle = vehicle = SearchVehicle();
if ( vehicle != 0 )
{
physics = vehicle->GetPhysics();
@@ -461,6 +488,17 @@ bool CAutoFactory::EventProcess(const Event &event)
m_object->SetZoomZ(10+i, 0.30f);
}
+ if ( m_program != nullptr )
+ {
+ CBrain* brain = m_vehicle->GetBrain();
+ if ( brain != nullptr )
+ {
+ brain->SendProgram(0, const_cast<const char*>(m_program));
+ brain->SetScriptRun(0);
+ brain->RunProgram(0);
+ }
+ }
+
SetBusy(false);
UpdateInterface();
diff --git a/src/object/auto/autofactory.h b/src/object/auto/autofactory.h
index 7c5013d..d9350e6 100644
--- a/src/object/auto/autofactory.h
+++ b/src/object/auto/autofactory.h
@@ -48,6 +48,9 @@ public:
void Init();
bool EventProcess(const Event &event);
+ Error StartAction(int param);
+ void SetProgram(const char* program);
+
bool CreateInterface(bool bSelect);
bool Write(char *line);
@@ -69,7 +72,10 @@ protected:
float m_progress;
float m_speed;
float m_lastParticle;
- Math::Vector m_fretPos;
+ Math::Vector m_fretPos;
int m_channelSound;
+
+ CObject* m_vehicle;
+ char* m_program;
};
diff --git a/src/object/auto/autoflag.cpp b/src/object/auto/autoflag.cpp
index 936546d..cc00db0 100644
--- a/src/object/auto/autoflag.cpp
+++ b/src/object/auto/autoflag.cpp
@@ -159,4 +159,3 @@ Error CAutoFlag::GetError()
return ERR_OK;
}
-
diff --git a/src/object/auto/autoinfo.cpp b/src/object/auto/autoinfo.cpp
index 56c21d2..6d4a484 100644
--- a/src/object/auto/autoinfo.cpp
+++ b/src/object/auto/autoinfo.cpp
@@ -428,7 +428,7 @@ void CAutoInfo::UpdateList()
{
info = m_object->GetInfo(i);
sprintf(text, "%s = %.2f", info.name, info.value);
- pl->SetName(i, text);
+ pl->SetItemName(i, text);
}
}
@@ -466,7 +466,7 @@ void CAutoInfo::UpdateListVirus()
}
text[j] = 0;
- pl->SetName(i, text);
+ pl->SetItemName(i, text);
}
}
@@ -513,4 +513,3 @@ bool CAutoInfo::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autojostle.cpp b/src/object/auto/autojostle.cpp
index 11952c2..5ce01c2 100644
--- a/src/object/auto/autojostle.cpp
+++ b/src/object/auto/autojostle.cpp
@@ -77,6 +77,11 @@ void CAutoJostle::Start(int param, float force)
}
}
+// Should never be called
+void CAutoJostle::Start(int param)
+{
+}
+
// Management of an event.
@@ -137,4 +142,3 @@ Error CAutoJostle::IsEnded()
return m_error;
}
-
diff --git a/src/object/auto/autojostle.h b/src/object/auto/autojostle.h
index 7b700ad..3822421 100644
--- a/src/object/auto/autojostle.h
+++ b/src/object/auto/autojostle.h
@@ -37,7 +37,9 @@ public:
bool EventProcess(const Event &event);
Error IsEnded();
-protected:
+private:
+ // Overriden to avoid warning about hiding virtual function
+ virtual void Start(int param) override;
protected:
float m_force;
diff --git a/src/object/auto/autokid.cpp b/src/object/auto/autokid.cpp
index a9f86b0..7d61d64 100644
--- a/src/object/auto/autokid.cpp
+++ b/src/object/auto/autokid.cpp
@@ -197,4 +197,3 @@ Error CAutoKid::GetError()
return ERR_OK;
}
-
diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp
index 6984fd6..172a618 100644
--- a/src/object/auto/autolabo.cpp
+++ b/src/object/auto/autolabo.cpp
@@ -42,7 +42,7 @@ const float LABO_DELAY = 20.0f; // duration of the analysis
// Object's constructor.
- CAutoLabo::CAutoLabo(CObject* object) : CAuto(object)
+CAutoLabo::CAutoLabo(CObject* object) : CAuto(object)
{
int i;
@@ -111,6 +111,48 @@ void CAutoLabo::Init()
}
+// Starts an action
+
+Error CAutoLabo::StartAction(int param)
+{
+ CObject* power;
+
+ if ( m_phase != ALAP_WAIT )
+ {
+ return ERR_GENERIC;
+ }
+
+ m_research = static_cast<ResearchType>(param);
+
+ if ( g_researchDone & m_research )
+ {
+ return ERR_LABO_ALREADY;
+ }
+
+ power = m_object->GetPower();
+ if ( power == 0 )
+ {
+ return ERR_LABO_NULL;
+ }
+ if ( power->GetType() != OBJECT_BULLET )
+ {
+ return ERR_LABO_BAD;
+ }
+
+ SetBusy(true);
+ InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f);
+ UpdateInterface();
+
+ power->SetLock(true); // ball longer usable
+
+ SoundManip(1.0f, 1.0f, 1.0f);
+ m_phase = ALAP_OPEN1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ return ERR_OK;
+}
+
+
// Management of an event.
bool CAutoLabo::EventProcess(const Event &event)
@@ -130,46 +172,17 @@ bool CAutoLabo::EventProcess(const Event &event)
if ( m_object->GetSelect() ) CreateInterface(true);
}
- if ( m_object->GetSelect() && // center selected?
- (event.type == EVENT_OBJECT_RiPAW ||
- event.type == EVENT_OBJECT_RiGUN) )
+ if ( m_object->GetSelect() ) // center selected?
{
- if ( m_phase != ALAP_WAIT )
- {
- return false;
- }
+ Error err = ERR_GENERIC;
+ if ( event.type == EVENT_OBJECT_RiPAW ) err = StartAction(RESEARCH_iPAW);
+ if ( event.type == EVENT_OBJECT_RiGUN ) err = StartAction(RESEARCH_iGUN);
- m_research = event.type;
+ if( err != ERR_OK && err != ERR_GENERIC )
+ m_displayText->DisplayError(err, m_object);
- if ( TestResearch(m_research) )
- {
- m_displayText->DisplayError(ERR_LABO_ALREADY, m_object);
+ if( err != ERR_GENERIC )
return false;
- }
-
- power = m_object->GetPower();
- if ( power == 0 )
- {
- m_displayText->DisplayError(ERR_LABO_NULL, m_object);
- return false;
- }
- if ( power->GetType() != OBJECT_BULLET )
- {
- m_displayText->DisplayError(ERR_LABO_BAD, m_object);
- return false;
- }
-
- SetBusy(true);
- InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f);
- UpdateInterface();
-
- power->SetLock(true); // ball longer usable
-
- SoundManip(1.0f, 1.0f, 1.0f);
- m_phase = ALAP_OPEN1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- return true;
}
if ( event.type != EVENT_FRAME ) return true;
@@ -341,7 +354,13 @@ bool CAutoLabo::EventProcess(const Event &event)
}
else
{
- SetResearch(m_research); // research done
+ g_researchDone |= m_research; // research done
+
+ m_main->WriteFreeParam();
+
+ Event newEvent(EVENT_UPDINTERFACE);
+ m_eventQueue->AddEvent(newEvent);
+ UpdateInterface();
power = m_object->GetPower();
if ( power != 0 )
@@ -606,11 +625,10 @@ bool CAutoLabo::Read(char *line)
m_phase = static_cast< AutoLaboPhase >(OpInt(line, "aPhase", ALAP_WAIT));
m_progress = OpFloat(line, "aProgress", 0.0f);
m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_research = static_cast< EventType >(OpInt(line, "aResearch", 0));
+ m_research = static_cast< ResearchType >(OpInt(line, "aResearch", 0));
m_lastParticle = 0.0f;
return true;
}
-
diff --git a/src/object/auto/autolabo.h b/src/object/auto/autolabo.h
index b61e8e3..b3b08bb 100644
--- a/src/object/auto/autolabo.h
+++ b/src/object/auto/autolabo.h
@@ -47,6 +47,7 @@ public:
void DeleteObject(bool bAll=false);
void Init();
+ Error StartAction(int param);
bool EventProcess(const Event &event);
Error GetError();
@@ -68,7 +69,7 @@ protected:
float m_speed;
float m_timeVirus;
float m_lastParticle;
- EventType m_research;
+ ResearchType m_research;
int m_partiRank[3];
int m_partiSphere;
int m_soundChannel;
diff --git a/src/object/auto/automush.cpp b/src/object/auto/automush.cpp
index e97e2a1..1e4796d 100644
--- a/src/object/auto/automush.cpp
+++ b/src/object/auto/automush.cpp
@@ -342,4 +342,3 @@ bool CAutoMush::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autonest.cpp b/src/object/auto/autonest.cpp
index 1cf13d6..8a2d644 100644
--- a/src/object/auto/autonest.cpp
+++ b/src/object/auto/autonest.cpp
@@ -273,4 +273,3 @@ bool CAutoNest::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autonuclear.cpp b/src/object/auto/autonuclear.cpp
index 75bfb45..224776d 100644
--- a/src/object/auto/autonuclear.cpp
+++ b/src/object/auto/autonuclear.cpp
@@ -484,4 +484,3 @@ bool CAutoNuclear::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autopara.cpp b/src/object/auto/autopara.cpp
index ad6517b..24bc119 100644
--- a/src/object/auto/autopara.cpp
+++ b/src/object/auto/autopara.cpp
@@ -327,4 +327,3 @@ bool CAutoPara::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autoradar.cpp b/src/object/auto/autoradar.cpp
index 1a10aa7..4afd3fe 100644
--- a/src/object/auto/autoradar.cpp
+++ b/src/object/auto/autoradar.cpp
@@ -305,4 +305,3 @@ bool CAutoRadar::SearchEnemy(Math::Vector &pos)
return true;
}
-
diff --git a/src/object/auto/autorepair.cpp b/src/object/auto/autorepair.cpp
index 95b6cc8..2f813f8 100644
--- a/src/object/auto/autorepair.cpp
+++ b/src/object/auto/autorepair.cpp
@@ -74,7 +74,7 @@ void CAutoRepair::Init()
bool CAutoRepair::EventProcess(const Event &event)
{
- CObject* vehicule;
+ CObject* vehicle;
Math::Vector pos, speed;
Math::Point dim;
float angle, shield;
@@ -137,16 +137,16 @@ bool CAutoRepair::EventProcess(const Event &event)
if ( m_phase == ARP_REPAIR )
{
- vehicule = SearchVehicle();
+ vehicle = SearchVehicle();
if ( m_progress < 1.0f ||
- (vehicule != 0 && vehicule->GetShield() < 1.0f) )
+ (vehicle != 0 && vehicle->GetShield() < 1.0f) )
{
- if ( vehicule != 0 )
+ if ( vehicle != 0 )
{
- shield = vehicule->GetShield();
+ shield = vehicle->GetShield();
shield += event.rTime*0.2f;
if ( shield > 1.0f ) shield = 1.0f;
- vehicule->SetShield(shield);
+ vehicle->SetShield(shield);
}
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
@@ -340,4 +340,3 @@ bool CAutoRepair::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autorepair.h b/src/object/auto/autorepair.h
index 31a3c65..f522a55 100644
--- a/src/object/auto/autorepair.h
+++ b/src/object/auto/autorepair.h
@@ -63,4 +63,3 @@ protected:
float m_lastParticle;
};
-
diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp
index 3c32307..8308ebe 100644
--- a/src/object/auto/autoresearch.cpp
+++ b/src/object/auto/autoresearch.cpp
@@ -92,6 +92,60 @@ void CAutoResearch::Init()
}
+// Starts an action
+
+Error CAutoResearch::StartAction(int param)
+{
+ CObject* power;
+ float time;
+
+ if ( m_phase != ALP_WAIT )
+ {
+ return ERR_GENERIC;
+ }
+
+ m_research = static_cast<ResearchType>(param);
+
+ if ( g_researchDone & m_research )
+ {
+ return ERR_RESEARCH_ALREADY;
+ }
+
+ power = m_object->GetPower();
+ if ( power == 0 )
+ {
+ return ERR_RESEARCH_POWER;
+ }
+ if ( power->GetCapacity() > 1.0f )
+ {
+ return ERR_RESEARCH_TYPE;
+ }
+ if ( power->GetEnergy() < 1.0f )
+ {
+ return ERR_RESEARCH_ENERGY;
+ }
+
+ time = SEARCH_TIME;
+ if ( m_research == RESEARCH_TANK ) time *= 0.3f;
+ if ( m_research == RESEARCH_FLY ) time *= 0.3f;
+ if ( m_research == RESEARCH_ATOMIC ) time *= 2.0f;
+
+ SetBusy(true);
+ InitProgressTotal(time);
+ UpdateInterface();
+
+ m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->GetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = ALP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/time;
+ return ERR_OK;
+}
+
+
// Management of an event.
bool CAutoResearch::EventProcess(const Event &event)
@@ -100,7 +154,7 @@ bool CAutoResearch::EventProcess(const Event &event)
Math::Vector pos, speed;
Error message;
Math::Point dim;
- float angle, time;
+ float angle;
CAuto::EventProcess(event);
@@ -111,64 +165,23 @@ bool CAutoResearch::EventProcess(const Event &event)
if ( m_object->GetSelect() ) CreateInterface(true);
}
- if ( m_object->GetSelect() && // center selected?
- (event.type == EVENT_OBJECT_RTANK ||
- event.type == EVENT_OBJECT_RFLY ||
- event.type == EVENT_OBJECT_RTHUMP ||
- event.type == EVENT_OBJECT_RCANON ||
- event.type == EVENT_OBJECT_RTOWER ||
- event.type == EVENT_OBJECT_RPHAZER ||
- event.type == EVENT_OBJECT_RSHIELD ||
- event.type == EVENT_OBJECT_RATOMIC ) )
+ if ( m_object->GetSelect() ) // center selected?
{
- if ( m_phase != ALP_WAIT )
- {
+ Error err = ERR_GENERIC;
+ if ( event.type == EVENT_OBJECT_RTANK ) err = StartAction(RESEARCH_TANK);
+ if ( event.type == EVENT_OBJECT_RFLY ) err = StartAction(RESEARCH_FLY);
+ if ( event.type == EVENT_OBJECT_RTHUMP ) err = StartAction(RESEARCH_THUMP);
+ if ( event.type == EVENT_OBJECT_RCANON ) err = StartAction(RESEARCH_CANON);
+ if ( event.type == EVENT_OBJECT_RTOWER ) err = StartAction(RESEARCH_TOWER);
+ if ( event.type == EVENT_OBJECT_RPHAZER ) err = StartAction(RESEARCH_PHAZER);
+ if ( event.type == EVENT_OBJECT_RSHIELD ) err = StartAction(RESEARCH_SHIELD);
+ if ( event.type == EVENT_OBJECT_RATOMIC ) err = StartAction(RESEARCH_ATOMIC);
+
+ if( err != ERR_OK && err != ERR_GENERIC )
+ m_displayText->DisplayError(err, m_object);
+
+ if( err != ERR_GENERIC )
return false;
- }
-
- m_research = event.type;
-
- if ( TestResearch(m_research) )
- {
- m_displayText->DisplayError(ERR_RESEARCH_ALREADY, m_object);
- return false;
- }
-
- power = m_object->GetPower();
- if ( power == 0 )
- {
- m_displayText->DisplayError(ERR_RESEARCH_POWER, m_object);
- return false;
- }
- if ( power->GetCapacity() > 1.0f )
- {
- m_displayText->DisplayError(ERR_RESEARCH_TYPE, m_object);
- return false;
- }
- if ( power->GetEnergy() < 1.0f )
- {
- m_displayText->DisplayError(ERR_RESEARCH_ENERGY, m_object);
- return false;
- }
-
- time = SEARCH_TIME;
- if ( event.type == EVENT_OBJECT_RTANK ) time *= 0.3f;
- if ( event.type == EVENT_OBJECT_RFLY ) time *= 0.3f;
- if ( event.type == EVENT_OBJECT_RATOMIC ) time *= 2.0f;
-
- SetBusy(true);
- InitProgressTotal(time);
- UpdateInterface();
-
- m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->GetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = ALP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/time;
- return true;
}
if ( event.type != EVENT_FRAME ) return true;
@@ -236,18 +249,25 @@ bool CAutoResearch::EventProcess(const Event &event)
}
else
{
- SetResearch(m_research); // research done
+ g_researchDone |= m_research; // research done
+
+ m_main->WriteFreeParam();
+
+ Event newEvent(EVENT_UPDINTERFACE);
+ m_eventQueue->AddEvent(newEvent);
+ UpdateInterface();
+
m_displayText->DisplayError(INFO_RESEARCH, m_object);
message = ERR_OK;
- if ( m_research == EVENT_OBJECT_RTANK ) message = INFO_RESEARCHTANK;
- if ( m_research == EVENT_OBJECT_RFLY ) message = INFO_RESEARCHFLY;
- if ( m_research == EVENT_OBJECT_RTHUMP ) message = INFO_RESEARCHTHUMP;
- if ( m_research == EVENT_OBJECT_RCANON ) message = INFO_RESEARCHCANON;
- if ( m_research == EVENT_OBJECT_RTOWER ) message = INFO_RESEARCHTOWER;
- if ( m_research == EVENT_OBJECT_RPHAZER ) message = INFO_RESEARCHPHAZER;
- if ( m_research == EVENT_OBJECT_RSHIELD ) message = INFO_RESEARCHSHIELD;
- if ( m_research == EVENT_OBJECT_RATOMIC ) message = INFO_RESEARCHATOMIC;
+ if ( m_research == RESEARCH_TANK ) message = INFO_RESEARCHTANK;
+ if ( m_research == RESEARCH_FLY ) message = INFO_RESEARCHFLY;
+ if ( m_research == RESEARCH_THUMP ) message = INFO_RESEARCHTHUMP;
+ if ( m_research == RESEARCH_CANON ) message = INFO_RESEARCHCANON;
+ if ( m_research == RESEARCH_TOWER ) message = INFO_RESEARCHTOWER;
+ if ( m_research == RESEARCH_PHAZER ) message = INFO_RESEARCHPHAZER;
+ if ( m_research == RESEARCH_SHIELD ) message = INFO_RESEARCHSHIELD;
+ if ( m_research == RESEARCH_ATOMIC ) message = INFO_RESEARCHATOMIC;
if ( message != ERR_OK )
{
m_displayText->DisplayError(message, m_object);
@@ -474,27 +494,6 @@ bool CAutoResearch::TestResearch(EventType event)
return false;
}
-// Indicates a search as made.
-
-void CAutoResearch::SetResearch(EventType event)
-{
-
- if ( event == EVENT_OBJECT_RTANK ) g_researchDone |= RESEARCH_TANK;
- if ( event == EVENT_OBJECT_RFLY ) g_researchDone |= RESEARCH_FLY;
- if ( event == EVENT_OBJECT_RTHUMP ) g_researchDone |= RESEARCH_THUMP;
- if ( event == EVENT_OBJECT_RCANON ) g_researchDone |= RESEARCH_CANON;
- if ( event == EVENT_OBJECT_RTOWER ) g_researchDone |= RESEARCH_TOWER;
- if ( event == EVENT_OBJECT_RPHAZER ) g_researchDone |= RESEARCH_PHAZER;
- if ( event == EVENT_OBJECT_RSHIELD ) g_researchDone |= RESEARCH_SHIELD;
- if ( event == EVENT_OBJECT_RATOMIC ) g_researchDone |= RESEARCH_ATOMIC;
-
- m_main->WriteFreeParam();
-
- Event newEvent(EVENT_UPDINTERFACE);
- m_eventQueue->AddEvent(newEvent);
- UpdateInterface();
-}
-
// Updates the stop lights.
@@ -600,7 +599,7 @@ bool CAutoResearch::Read(char *line)
m_phase = static_cast< AutoResearchPhase >(OpInt(line, "aPhase", ALP_WAIT));
m_progress = OpFloat(line, "aProgress", 0.0f);
m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_research = static_cast< EventType >(OpInt(line, "aResearch", 0));
+ m_research = static_cast< ResearchType >(OpInt(line, "aResearch", 0));
m_lastUpdateTime = 0.0f;
m_lastParticle = 0.0f;
@@ -608,4 +607,3 @@ bool CAutoResearch::Read(char *line)
return true;
}
-
diff --git a/src/object/auto/autoresearch.h b/src/object/auto/autoresearch.h
index 6c804ef..dcb9f7b 100644
--- a/src/object/auto/autoresearch.h
+++ b/src/object/auto/autoresearch.h
@@ -41,6 +41,7 @@ public:
void DeleteObject(bool bAll=false);
void Init();
+ Error StartAction(int result);
bool EventProcess(const Event &event);
Error GetError();
@@ -54,7 +55,6 @@ protected:
void UpdateInterface(float rTime);
void OkayButton(Ui::CWindow *pw, EventType event);
bool TestResearch(EventType event);
- void SetResearch(EventType event);
void FireStopUpdate(float progress, bool bLightOn);
protected:
@@ -64,7 +64,7 @@ protected:
float m_timeVirus;
float m_lastUpdateTime;
float m_lastParticle;
- EventType m_research;
+ ResearchType m_research;
int m_partiStop[6];
int m_channelSound;
};
diff --git a/src/object/auto/autoroot.cpp b/src/object/auto/autoroot.cpp
index a390e90..7e5c5e7 100644
--- a/src/object/auto/autoroot.cpp
+++ b/src/object/auto/autoroot.cpp
@@ -115,4 +115,3 @@ Error CAutoRoot::GetError()
return ERR_OK;
}
-
diff --git a/src/object/auto/autosafe.cpp b/src/object/auto/autosafe.cpp
index fc83400..2871a70 100644
--- a/src/object/auto/autosafe.cpp
+++ b/src/object/auto/autosafe.cpp
@@ -400,7 +400,7 @@ int CAutoSafe::CountKeys()
Math::Vector cPos, oPos;
Math::Point rot;
ObjectType oType;
- float dist, angle, limit, cAngle, oAngle;
+ float dist, angle, limit = 0.0f, cAngle, oAngle = 0.0f;
int i, index;
cPos = m_object->GetPosition(0);
@@ -611,5 +611,3 @@ CObject* CAutoSafe::SearchVehicle()
return 0;
}
-
-
diff --git a/src/object/auto/autostation.cpp b/src/object/auto/autostation.cpp
index a2f5b6b..2c0aa02 100644
--- a/src/object/auto/autostation.cpp
+++ b/src/object/auto/autostation.cpp
@@ -82,7 +82,7 @@ bool CAutoStation::EventProcess(const Event &event)
Math::Matrix* mat;
Math::Vector pos, ppos, speed;
Math::Point dim;
- CObject* vehicule;
+ CObject* vehicle;
CObject* power;
Gfx::TerrainRes res;
float big, energy, used, add, freq;
@@ -133,10 +133,10 @@ bool CAutoStation::EventProcess(const Event &event)
freq = 1.0f;
if ( big > 0.0f )
{
- vehicule = SearchVehicle();
- if ( vehicule != 0 )
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
{
- power = vehicule->GetPower();
+ power = vehicle->GetPower();
if ( power != 0 && power->GetCapacity() == 1.0f )
{
energy = power->GetEnergy();
@@ -149,7 +149,7 @@ bool CAutoStation::EventProcess(const Event &event)
big -= add/4.0f; // discharge the large battery
}
- power = vehicule->GetFret();
+ power = vehicle->GetFret();
if ( power != 0 && power->GetType() == OBJECT_POWER )
{
energy = power->GetEnergy();
@@ -368,4 +368,3 @@ void CAutoStation::UpdateInterface(float rTime)
}
}
-
diff --git a/src/object/auto/autotower.cpp b/src/object/auto/autotower.cpp
index e3b06cf..17a41f4 100644
--- a/src/object/auto/autotower.cpp
+++ b/src/object/auto/autotower.cpp
@@ -397,7 +397,7 @@ void CAutoTower::FireStopUpdate(float progress, bool bLightOn)
pos.y = 18.0f;
pos.z = listpos[i*2+1];
pos = Transform(*mat, pos);
-
+
m_partiStop[i] = m_particle->CreateParticle(pos, speed,
dim, Gfx::PARTISELR,
1.0f, 0.0f, 0.0f);
@@ -544,4 +544,3 @@ bool CAutoTower::Read(char *line)
return true;
}
-
diff --git a/src/object/brain.cpp b/src/object/brain.cpp
index fa3e425..9e5149e 100644
--- a/src/object/brain.cpp
+++ b/src/object/brain.cpp
@@ -1309,14 +1309,17 @@ bool CBrain::CreateInterface(bool bSelect)
type == OBJECT_ANT ||
type == OBJECT_SPIDER ||
type == OBJECT_BEE ||
- type == OBJECT_WORM ) // vehicle?
+ type == OBJECT_WORM ||
+ type == OBJECT_CONTROLLER) // vehicle?
{
- if (!(m_main->GetRetroMode())) {
+ if (!(m_main->GetRetroMode()))
+ {
ddim.x = dim.x*5.1f;
- ddim.y = dim.y*2.0f;
+ ddim.y = dim.y*2.0f; // default => 2
pos.x = ox+sx*0.0f;
pos.y = oy+sy*0.0f;
- pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, 1.10f);
+
+ pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, -1.10f);
UpdateScript(pw);
pos.x = ox+sx*5.2f;
@@ -1333,7 +1336,8 @@ bool CBrain::CreateInterface(bool bSelect)
type == OBJECT_MOBILEfi ||
type == OBJECT_MOBILEfs ||
type == OBJECT_MOBILEft ||
- type == OBJECT_BEE ) // driving?
+ type == OBJECT_BEE ||
+ type == OBJECT_CONTROLLER) // driving?
{
pos.x = ox+sx*6.4f;
pos.y = oy+sy*0;
@@ -1345,8 +1349,9 @@ bool CBrain::CreateInterface(bool bSelect)
pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP);
pb->SetImmediat(true);
- if ( type != OBJECT_HUMAN ||
- m_object->GetOption() != 2 )
+ if ( (type != OBJECT_HUMAN &&
+ type != OBJECT_CONTROLLER) ||
+ m_object->GetOption() != 2 )
{
pos.x = ox+sx*15.3f;
pos.y = oy+sy*0;
@@ -2056,7 +2061,7 @@ void CBrain::UpdateInterface(float rTime)
pc->SetState(Ui::STATE_VISIBLE, m_main->GetShowMap());
}
- pb = (Ui::CButton*)pw->SearchControl(EVENT_OBJECT_REC);
+ pb = static_cast<Ui::CButton*>(pw->SearchControl(EVENT_OBJECT_REC));
if ( pb != 0 )
{
if ( m_bTraceRecord && Math::Mod(m_time, 0.4f) >= 0.2f )
@@ -2304,7 +2309,8 @@ void CBrain::UpdateInterface()
type == OBJECT_ANT ||
type == OBJECT_SPIDER ||
type == OBJECT_BEE ||
- type == OBJECT_WORM ) // vehicle?
+ type == OBJECT_WORM ||
+ type == OBJECT_CONTROLLER) // vehicle?
{
bRun = false;
if ( m_script[m_selScript] != 0 )
@@ -2481,7 +2487,7 @@ void CBrain::UpdateScript(Ui::CWindow *pw)
}
}
- pl->SetName(i, name);
+ pl->SetItemName(i, name);
}
if ( !bSoluce )
@@ -2715,6 +2721,23 @@ bool CBrain::ReadSoluce(char* filename)
return true;
}
+// Load a script from text buffer.
+
+bool CBrain::SendProgram(int rank, const char* buffer)
+{
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_object, &m_secondaryTask);
+ }
+
+ if ( m_script[rank]->SendScript(buffer) ) return true;
+
+ delete m_script[rank];
+ m_script[rank] = 0;
+
+ return false;
+}
+
// Load a script with a text file.
bool CBrain::ReadProgram(int rank, const char* filename)
diff --git a/src/object/brain.h b/src/object/brain.h
index eba8004..dcf07a4 100644
--- a/src/object/brain.h
+++ b/src/object/brain.h
@@ -52,7 +52,7 @@ class CTerrain;
class CWater;
class CCamera;
class CParticle;
-} /* Gfx */
+} /* Gfx */
const int BRAINMAXSCRIPT = 10;
@@ -114,6 +114,7 @@ public:
char* GetScriptName(int rank);
void SetSoluceName(char *name);
char* GetSoluceName();
+ bool SendProgram(int rank, const char* buffer);
bool ReadSoluce(char* filename);
bool ReadProgram(int rank, const char* filename);
diff --git a/src/object/mainmovie.cpp b/src/object/mainmovie.cpp
index 04c0d56..85abee2 100644
--- a/src/object/mainmovie.cpp
+++ b/src/object/mainmovie.cpp
@@ -228,4 +228,3 @@ MainMovieType CMainMovie::GetStopType()
return m_stopType;
}
-
diff --git a/src/object/motion/motionant.cpp b/src/object/motion/motionant.cpp
index 384d683..16e53aa 100644
--- a/src/object/motion/motionant.cpp
+++ b/src/object/motion/motionant.cpp
@@ -75,7 +75,7 @@ bool CMotionAnt::Create(Math::Vector pos, float angle, ObjectType type,
// Creates the main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
modelManager->AddModelReference("ant1.mod", false, rank);
m_object->SetPosition(0, pos);
@@ -425,7 +425,7 @@ bool CMotionAnt::EventFrame(const Event &event)
{
Math::Vector dir, pos, speed;
Math::Point dim;
- float s, a, prog, time;
+ float s, a, prog = 0.0f, time;
float tSt[9], tNd[9];
int i, ii, st, nd, action;
bool bStop;
@@ -831,4 +831,3 @@ bool CMotionAnt::EventFrame(const Event &event)
return true;
}
-
diff --git a/src/object/motion/motionbee.cpp b/src/object/motion/motionbee.cpp
index 8f69945..2a052b2 100644
--- a/src/object/motion/motionbee.cpp
+++ b/src/object/motion/motionbee.cpp
@@ -73,7 +73,7 @@ bool CMotionBee::Create(Math::Vector pos, float angle, ObjectType type,
// Creates main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
modelManager->AddModelReference("bee1.mod", false, rank);
m_object->SetPosition(0, pos);
@@ -406,7 +406,7 @@ bool CMotionBee::EventProcess(const Event &event)
bool CMotionBee::EventFrame(const Event &event)
{
Math::Vector dir;
- float s, a, prog;
+ float s, a, prog = 0.0f;
int action, i, st, nd;
bool bStop;
@@ -610,4 +610,3 @@ bool CMotionBee::EventFrame(const Event &event)
return true;
}
-
diff --git a/src/object/motion/motiondummy.cpp b/src/object/motion/motiondummy.cpp
new file mode 100644
index 0000000..86e389e
--- /dev/null
+++ b/src/object/motion/motiondummy.cpp
@@ -0,0 +1,85 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2013 Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include "object/motion/motiondummy.h"
+#include "physics/physics.h"
+#include "graphics/engine/modelmanager.h"
+
+#include <stdio.h>
+#include <string.h>
+
+// Object's constructor.
+
+CMotionDummy::CMotionDummy(CObject* object) : CMotion(object)
+{
+}
+
+// Object's destructor.
+
+CMotionDummy::~CMotionDummy()
+{
+}
+
+
+// Removes an object.
+
+void CMotionDummy::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a Dummy traveling any lands on the ground.
+
+bool CMotionDummy::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ m_object->SetType(type);
+
+ // Creates the main base.
+ int rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ // Movement
+ m_physics->SetType(TYPE_FLYING);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 0.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 0.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 0.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 0.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 2.0f);
+
+ return true;
+}
+
diff --git a/src/object/motion/motiondummy.h b/src/object/motion/motiondummy.h
new file mode 100644
index 0000000..2cb3a88
--- /dev/null
+++ b/src/object/motion/motiondummy.h
@@ -0,0 +1,34 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2013 Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motiondummy.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+class CMotionDummy : public CMotion
+{
+public:
+ CMotionDummy(CObject* object);
+ ~CMotionDummy();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+};
+
diff --git a/src/object/motion/motionhuman.cpp b/src/object/motion/motionhuman.cpp
index dc5ff34..edee260 100644
--- a/src/object/motion/motionhuman.cpp
+++ b/src/object/motion/motionhuman.cpp
@@ -107,7 +107,7 @@ bool CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type,
if ( m_main->GetGamerOnlyHead() )
{
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
face = m_main->GetGamerFace();
sprintf(filename, "human2h%d.mod", face+1);
@@ -134,7 +134,7 @@ bool CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type,
// Creates the main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
if (option == 0) // head in helmet?
@@ -677,7 +677,7 @@ bool CMotionHuman::EventFrame(const Event &event)
float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl;
float al, ar, af;
float tSt[9], tNd[9];
- float aa, bb, shield, deadFactor, level;
+ float aa, bb, shield, deadFactor = 0.0f, level;
int i, ii, st, nd, action, legAction, armAction;
bool bOnBoard, bSwim;
@@ -1617,18 +1617,18 @@ bool CMotionHuman::EventFrame(const Event &event)
legAction == MH_MARCHTAKE )
{
Sound sound[2];
- float speed, synchro, volume[2], freq[2], hard, level;
+ float synchro, volume[2], freq[2], hard;
- speed = m_physics->GetLinMotionX(MO_REASPEED);
+ float speedX = m_physics->GetLinMotionX(MO_REASPEED);
if ( m_object->GetFret() == 0 )
{
- if ( speed > 0.0f ) synchro = 0.21f; // synchro forward
+ if ( speedX > 0.0f ) synchro = 0.21f; // synchro forward
else synchro = 0.29f; // synchro backward
}
else
{
- if ( speed > 0.0f ) synchro = 0.15f; // synchro forward
+ if ( speedX > 0.0f ) synchro = 0.15f; // synchro forward
else synchro = 0.35f; // synchro backward
}
time = rTime[1]+synchro;
@@ -1735,4 +1735,3 @@ void CMotionHuman::StopDisplayPerso()
m_bDisplayPerso = false;
}
-
diff --git a/src/object/motion/motionmother.cpp b/src/object/motion/motionmother.cpp
index 573a2e4..03e7c21 100644
--- a/src/object/motion/motionmother.cpp
+++ b/src/object/motion/motionmother.cpp
@@ -74,7 +74,7 @@ bool CMotionMother::Create(Math::Vector pos, float angle, ObjectType type,
// Creates main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
modelManager->AddModelReference("mother1.mod", false, rank);
m_object->SetPosition(0, pos);
@@ -493,4 +493,3 @@ bool CMotionMother::EventFrame(const Event &event)
return true;
}
-
diff --git a/src/object/motion/motionspider.cpp b/src/object/motion/motionspider.cpp
index 59bc6e0..8d339b6 100644
--- a/src/object/motion/motionspider.cpp
+++ b/src/object/motion/motionspider.cpp
@@ -101,7 +101,7 @@ bool CMotionSpider::Create(Math::Vector pos, float angle, ObjectType type,
// Creates the main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
// This is an "empty" object, without triangles
m_object->SetPosition(0, pos);
@@ -363,7 +363,7 @@ bool CMotionSpider::EventFrame(const Event &event)
{
Math::Vector dir, pos, speed;
Math::Point dim;
- float s, a, prog, time;
+ float s, a, prog = 0.0f, time;
float tSt[12], tNd[12];
int i, ii, st, nd, action;
bool bStop;
@@ -743,4 +743,3 @@ bool CMotionSpider::EventFrame(const Event &event)
return true;
}
-
diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp
index ddb1867..b4ed89d 100644
--- a/src/object/motion/motiontoto.cpp
+++ b/src/object/motion/motiontoto.cpp
@@ -88,7 +88,7 @@ bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type,
// Creates the head.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
modelManager->AddModelReference("toto1.mod", false, rank);
m_object->SetPosition(0, pos);
@@ -853,4 +853,3 @@ void CMotionToto::SetLinkType(ObjectType type)
m_type = type;
}
-
diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp
index 44b8fdd..a67ae24 100644
--- a/src/object/motion/motionvehicle.cpp
+++ b/src/object/motion/motionvehicle.cpp
@@ -102,7 +102,7 @@ bool CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type,
// Creates the main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
if (type == OBJECT_MOBILEfa ||
@@ -931,6 +931,7 @@ bool CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type,
rank = m_engine->CreateObject();
m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_FIX);
pPower->SetObjectRank(0, rank);
+ pPower->CreateShadowCircle(1.5f, 1.0f); //create a shadow for battary
if ( power <= 1.0f ) modelManager->AddModelCopy("power.mod", false, rank);
else modelManager->AddModelCopy("atomic.mod", false, rank);
@@ -1649,7 +1650,7 @@ bool CMotionVehicle::EventFrameFly(const Event &event)
bool CMotionVehicle::EventFrameInsect(const Event &event)
{
Math::Vector dir;
- float s, a, prog, time;
+ float s, a, prog = 0.0f, time;
int i, st, nd, action;
bool bStop, bOnBoard;
@@ -1943,4 +1944,3 @@ void CMotionVehicle::SetTraceWidth(float width)
m_traceWidth = width;
}
-
diff --git a/src/object/motion/motionworm.cpp b/src/object/motion/motionworm.cpp
index ee555a8..80bf7fc 100644
--- a/src/object/motion/motionworm.cpp
+++ b/src/object/motion/motionworm.cpp
@@ -89,9 +89,9 @@ bool CMotionWorm::Create(Math::Vector pos, float angle, ObjectType type,
// Creates the main base.
rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICULE); // this is a moving object
+ m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object
m_object->SetObjectRank(0, rank);
- // This is an "empty" object, without triangles
+ // This is an "empty" object, without triangles
m_object->SetPosition(0, pos);
m_object->SetAngleY(0, angle);
@@ -356,4 +356,3 @@ bool CMotionWorm::EventFrame(const Event &event)
return true;
}
-
diff --git a/src/object/object.cpp b/src/object/object.cpp
index 23a757a..4cf0688 100644
--- a/src/object/object.cpp
+++ b/src/object/object.cpp
@@ -64,6 +64,7 @@
#include "object/motion/motion.h"
#include "object/motion/motionant.h"
#include "object/motion/motionbee.h"
+#include "object/motion/motiondummy.h"
#include "object/motion/motionhuman.h"
#include "object/motion/motionmother.h"
#include "object/motion/motionspider.h"
@@ -71,6 +72,7 @@
#include "object/motion/motionvehicle.h"
#include "object/motion/motionworm.h"
#include "object/robotmain.h"
+#include "object/objman.h"
#include "physics/physics.h"
@@ -202,6 +204,10 @@ void uObject(CBotVar* botThis, void* user)
fret = object->GetFret();
if ( fret == 0 ) pVar->SetPointer(0);
else pVar->SetPointer(fret->GetBotVar());
+
+ pVar = pVar->GetNext(); // "id"
+ value = object->GetID();
+ pVar->SetValInt(value);
}
@@ -337,6 +343,8 @@ CObject::CObject()
m_botVar = CBotVar::Create("", CBotTypResult(CBotTypClass, "object"));
m_botVar->SetUserPtr(this);
m_botVar->SetIdent(m_id);
+
+ CObjectManager::GetInstancePointer()->AddInstance(this);
}
// Object's destructor.
@@ -360,6 +368,7 @@ CObject::~CObject()
m_auto = nullptr;
CInstanceManager::GetInstancePointer()->DeleteInstance(CLASS_OBJECT, this);
+ CObjectManager::GetInstancePointer()->DeleteInstance(this);
m_app = nullptr;
}
@@ -592,7 +601,7 @@ bool CObject::ExploObject(ExploType type, float force, float decay)
}
}
- if ( EXPLO_BOUM )
+ if ( type == EXPLO_BOUM )
{
if ( m_shotTime < 0.5f ) return false;
m_shotTime = 0.0f;
@@ -2137,6 +2146,10 @@ bool CObject::CreateVehicle(Math::Vector pos, float angle, ObjectType type,
{
m_motion = new CMotionHuman(this);
}
+ else if ( type == OBJECT_CONTROLLER )
+ {
+ m_motion = new CMotionDummy(this); //dummy object
+ }
else
{
m_motion = new CMotionVehicle(this);
@@ -7314,7 +7327,7 @@ bool CObject::GetTraceDown()
CMotionVehicle* mv = dynamic_cast<CMotionVehicle*>(m_motion);
if (mv == nullptr)
{
- GetLogger()->Debug("GetTraceDown() invalid m_motion class!\n");
+ GetLogger()->Trace("GetTraceDown() invalid m_motion class!\n");
return false;
}
return mv->GetTraceDown();
@@ -7326,7 +7339,7 @@ void CObject::SetTraceDown(bool bDown)
CMotionVehicle* mv = dynamic_cast<CMotionVehicle*>(m_motion);
if (mv == nullptr)
{
- GetLogger()->Debug("SetTraceDown() invalid m_motion class!\n");
+ GetLogger()->Trace("SetTraceDown() invalid m_motion class!\n");
return;
}
mv->SetTraceDown(bDown);
@@ -7338,7 +7351,7 @@ int CObject::GetTraceColor()
CMotionVehicle* mv = dynamic_cast<CMotionVehicle*>(m_motion);
if (mv == nullptr)
{
- GetLogger()->Debug("GetTraceColor() invalid m_motion class!\n");
+ GetLogger()->Trace("GetTraceColor() invalid m_motion class!\n");
return 0;
}
return mv->GetTraceColor();
@@ -7350,7 +7363,7 @@ void CObject::SetTraceColor(int color)
CMotionVehicle* mv = dynamic_cast<CMotionVehicle*>(m_motion);
if (mv == nullptr)
{
- GetLogger()->Debug("SetTraceColor() invalid m_motion class!\n");
+ GetLogger()->Trace("SetTraceColor() invalid m_motion class!\n");
return;
}
mv->SetTraceColor(color);
@@ -7362,7 +7375,7 @@ float CObject::GetTraceWidth()
CMotionVehicle* mv = dynamic_cast<CMotionVehicle*>(m_motion);
if (mv == nullptr)
{
- GetLogger()->Debug("GetTraceWidth() invalid m_motion class!\n");
+ GetLogger()->Trace("GetTraceWidth() invalid m_motion class!\n");
return 0.0f;
}
return mv->GetTraceWidth();
@@ -7374,10 +7387,9 @@ void CObject::SetTraceWidth(float width)
CMotionVehicle* mv = dynamic_cast<CMotionVehicle*>(m_motion);
if (mv == nullptr)
{
- GetLogger()->Debug("SetTraceWidth() invalid m_motion class!\n");
+ GetLogger()->Trace("SetTraceWidth() invalid m_motion class!\n");
return;
}
mv->SetTraceWidth(width);
}
-
diff --git a/src/object/object.h b/src/object/object.h
index 4d8cc02..25ea708 100644
--- a/src/object/object.h
+++ b/src/object/object.h
@@ -156,6 +156,7 @@ enum ObjectType
OBJECT_MOBILEsa = 210, //! < submarine
OBJECT_MOBILEtg = 211, //! < training target
OBJECT_MOBILEdr = 212, //! < robot drawing
+ OBJECT_CONTROLLER = 213, //! < mission controller
OBJECT_WAYPOINT = 250, //! < waypoint
OBJECT_FLAGb = 260, //! < blue flag
OBJECT_FLAGr = 261, //! < red flag
diff --git a/src/object/objman.cpp b/src/object/objman.cpp
new file mode 100644
index 0000000..e4102b8
--- /dev/null
+++ b/src/object/objman.cpp
@@ -0,0 +1,389 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "object/object.h"
+#include "object/auto/auto.h"
+
+#include "object/objman.h"
+
+
+template<> CObjectManager* CSingleton<CObjectManager>::m_instance = nullptr;
+
+
+CObjectManager::CObjectManager()
+{
+ for (int i = 0; i < MAX_OBJECTS; i++)
+ {
+ m_table[i] = nullptr;
+ }
+ usedCount = 0;
+}
+
+CObjectManager::~CObjectManager()
+{
+}
+
+bool CObjectManager::AddInstance(CObject* instance)
+{
+ if (usedCount >= MAX_OBJECTS) return false;
+
+ m_table[instance->GetID()] = instance;
+ usedCount++;
+ return true;
+}
+
+bool CObjectManager::DeleteInstance(CObject* instance)
+{
+ for (int i = 0; i < usedCount; i++)
+ {
+ if (m_table[i] == instance)
+ m_table[i] = nullptr;
+ }
+
+ return true;
+}
+
+CObject* CObjectManager::SearchInstance(int id)
+{
+ if (id >= MAX_OBJECTS) return nullptr;
+ return m_table[id];
+}
+
+CObject* CObjectManager::CreateObject(Math::Vector pos, float angle, float zoom, float height,
+ ObjectType type, float power,
+ bool trainer, bool toy,
+ int option)
+{
+ CObject* object = nullptr;
+
+ if ( type == OBJECT_NULL ) return nullptr;
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ trainer = false; // necessarily
+ }
+
+ if ( type == OBJECT_PORTICO ||
+ type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_TOWER ||
+ type == OBJECT_NEST ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_TARGET2 ||
+ type == OBJECT_START ||
+ type == OBJECT_END )
+ {
+ object = new CObject();
+ object->CreateBuilding(pos, angle, height, type, power);
+
+ CAuto* automat = object->GetAuto();
+ if (automat != nullptr)
+ {
+ automat->Init();
+ }
+ }
+ else
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_SHOW ||
+ type == OBJECT_WINFIRE ||
+ type == OBJECT_BAG ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_EGG )
+ {
+ object = new CObject();
+ object->CreateResource(pos, angle, type, power);
+ }
+ else
+ if ( type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv )
+ {
+ object = new CObject();
+ object->CreateFlag(pos, angle, type);
+ }
+ else
+ if ( type == OBJECT_BARRIER0 ||
+ type == OBJECT_BARRIER1 ||
+ type == OBJECT_BARRIER2 ||
+ type == OBJECT_BARRIER3 ||
+ type == OBJECT_BARRIER4 )
+ {
+ object = new CObject();
+ object->CreateBarrier(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_PLANT0 ||
+ type == OBJECT_PLANT1 ||
+ type == OBJECT_PLANT2 ||
+ type == OBJECT_PLANT3 ||
+ type == OBJECT_PLANT4 ||
+ type == OBJECT_PLANT5 ||
+ type == OBJECT_PLANT6 ||
+ type == OBJECT_PLANT7 ||
+ type == OBJECT_PLANT8 ||
+ type == OBJECT_PLANT9 ||
+ type == OBJECT_PLANT10 ||
+ type == OBJECT_PLANT11 ||
+ type == OBJECT_PLANT12 ||
+ type == OBJECT_PLANT13 ||
+ type == OBJECT_PLANT14 ||
+ type == OBJECT_PLANT15 ||
+ type == OBJECT_PLANT16 ||
+ type == OBJECT_PLANT17 ||
+ type == OBJECT_PLANT18 ||
+ type == OBJECT_PLANT19 ||
+ type == OBJECT_TREE0 ||
+ type == OBJECT_TREE1 ||
+ type == OBJECT_TREE2 ||
+ type == OBJECT_TREE3 ||
+ type == OBJECT_TREE4 ||
+ type == OBJECT_TREE5 ||
+ type == OBJECT_TREE6 ||
+ type == OBJECT_TREE7 ||
+ type == OBJECT_TREE8 ||
+ type == OBJECT_TREE9 )
+ {
+ object = new CObject();
+ object->CreatePlant(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_MUSHROOM0 ||
+ type == OBJECT_MUSHROOM1 ||
+ type == OBJECT_MUSHROOM2 ||
+ type == OBJECT_MUSHROOM3 ||
+ type == OBJECT_MUSHROOM4 ||
+ type == OBJECT_MUSHROOM5 ||
+ type == OBJECT_MUSHROOM6 ||
+ type == OBJECT_MUSHROOM7 ||
+ type == OBJECT_MUSHROOM8 ||
+ type == OBJECT_MUSHROOM9 )
+ {
+ object = new CObject();
+ object->CreateMushroom(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_TEEN0 ||
+ type == OBJECT_TEEN1 ||
+ type == OBJECT_TEEN2 ||
+ type == OBJECT_TEEN3 ||
+ type == OBJECT_TEEN4 ||
+ type == OBJECT_TEEN5 ||
+ type == OBJECT_TEEN6 ||
+ type == OBJECT_TEEN7 ||
+ type == OBJECT_TEEN8 ||
+ type == OBJECT_TEEN9 ||
+ type == OBJECT_TEEN10 ||
+ type == OBJECT_TEEN11 ||
+ type == OBJECT_TEEN12 ||
+ type == OBJECT_TEEN13 ||
+ type == OBJECT_TEEN14 ||
+ type == OBJECT_TEEN15 ||
+ type == OBJECT_TEEN16 ||
+ type == OBJECT_TEEN17 ||
+ type == OBJECT_TEEN18 ||
+ type == OBJECT_TEEN19 ||
+ type == OBJECT_TEEN20 ||
+ type == OBJECT_TEEN21 ||
+ type == OBJECT_TEEN22 ||
+ type == OBJECT_TEEN23 ||
+ type == OBJECT_TEEN24 ||
+ type == OBJECT_TEEN25 ||
+ type == OBJECT_TEEN26 ||
+ type == OBJECT_TEEN27 ||
+ type == OBJECT_TEEN28 ||
+ type == OBJECT_TEEN29 ||
+ type == OBJECT_TEEN30 ||
+ type == OBJECT_TEEN31 ||
+ type == OBJECT_TEEN32 ||
+ type == OBJECT_TEEN33 ||
+ type == OBJECT_TEEN34 ||
+ type == OBJECT_TEEN35 ||
+ type == OBJECT_TEEN36 ||
+ type == OBJECT_TEEN37 ||
+ type == OBJECT_TEEN38 ||
+ type == OBJECT_TEEN39 ||
+ type == OBJECT_TEEN40 ||
+ type == OBJECT_TEEN41 ||
+ type == OBJECT_TEEN42 ||
+ type == OBJECT_TEEN43 ||
+ type == OBJECT_TEEN44 ||
+ type == OBJECT_TEEN45 ||
+ type == OBJECT_TEEN46 ||
+ type == OBJECT_TEEN47 ||
+ type == OBJECT_TEEN48 ||
+ type == OBJECT_TEEN49 )
+ {
+ object = new CObject();
+ object->SetOption(option);
+ object->CreateTeen(pos, angle, zoom, height, type);
+ }
+ else
+ if ( type == OBJECT_QUARTZ0 ||
+ type == OBJECT_QUARTZ1 ||
+ type == OBJECT_QUARTZ2 ||
+ type == OBJECT_QUARTZ3 ||
+ type == OBJECT_QUARTZ4 ||
+ type == OBJECT_QUARTZ5 ||
+ type == OBJECT_QUARTZ6 ||
+ type == OBJECT_QUARTZ7 ||
+ type == OBJECT_QUARTZ8 ||
+ type == OBJECT_QUARTZ9 )
+ {
+ object = new CObject();
+ object->CreateQuartz(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_ROOT0 ||
+ type == OBJECT_ROOT1 ||
+ type == OBJECT_ROOT2 ||
+ type == OBJECT_ROOT3 ||
+ type == OBJECT_ROOT4 ||
+ type == OBJECT_ROOT5 ||
+ type == OBJECT_ROOT6 ||
+ type == OBJECT_ROOT7 ||
+ type == OBJECT_ROOT8 ||
+ type == OBJECT_ROOT9 )
+ {
+ object = new CObject();
+ object->CreateRoot(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_HOME1 )
+ {
+ object = new CObject();
+ object->CreateHome(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ||
+ type == OBJECT_RUINfactory ||
+ type == OBJECT_RUINdoor ||
+ type == OBJECT_RUINsupport ||
+ type == OBJECT_RUINradar ||
+ type == OBJECT_RUINconvert ||
+ type == OBJECT_RUINbase ||
+ type == OBJECT_RUINhead )
+ {
+ object = new CObject();
+ object->CreateRuin(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_APOLLO1 ||
+ type == OBJECT_APOLLO3 ||
+ type == OBJECT_APOLLO4 ||
+ type == OBJECT_APOLLO5 )
+ {
+ object = new CObject();
+ object->CreateApollo(pos, angle, type);
+ }
+ else
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ object = new CObject();
+ object->CreateInsect(pos, angle, type); // no eggs
+ }
+ else
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 )
+ {
+ object = new CObject();
+ object->SetOption(option);
+ object->CreateVehicle(pos, angle, type, power, trainer, toy);
+ }
+
+ return object;
+}
+
diff --git a/src/object/objman.h b/src/object/objman.h
new file mode 100644
index 0000000..3087383
--- /dev/null
+++ b/src/object/objman.h
@@ -0,0 +1,53 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+/**
+ * \file object/objman.h
+ * \brief Instance manager for objects
+ */
+
+#pragma once
+
+#include "object/object.h"
+
+#include "common/singleton.h"
+
+const int MAX_OBJECTS = 500;
+
+/**
+ * \class ObjectManager
+ * \brief Manager for objects
+ */
+class CObjectManager : public CSingleton<CObjectManager>
+{
+public:
+ CObjectManager();
+ virtual ~CObjectManager();
+
+ //! Registers new object
+ bool AddInstance(CObject* instance);
+ //! Deletes the registered object
+ bool DeleteInstance(CObject* instance);
+ //! Seeks for an object
+ CObject* SearchInstance(int id);
+ //! Creates an object
+ CObject* CreateObject(Math::Vector pos, float angle, float zoom, float height, ObjectType type, float power, bool trainer, bool toy, int option);
+
+protected:
+ CObject* m_table[MAX_OBJECTS];
+ int usedCount;
+};
+
diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp
index c1e4140..b58e5f8 100644
--- a/src/object/robotmain.cpp
+++ b/src/object/robotmain.cpp
@@ -34,7 +34,7 @@
#include "graphics/engine/engine.h"
#include "graphics/engine/lightman.h"
#include "graphics/engine/lightning.h"
-#include "graphics/engine/modelfile.h"
+#include "graphics/engine/modelmanager.h"
#include "graphics/engine/particle.h"
#include "graphics/engine/planet.h"
#include "graphics/engine/pyro.h"
@@ -79,6 +79,7 @@
#include "ui/slider.h"
#include "ui/window.h"
+#include <iomanip>
template<> CRobotMain* CSingleton<CRobotMain>::m_instance = nullptr;
@@ -602,11 +603,8 @@ bool rPoint(CBotVar* pThis, CBotVar* var, CBotVar* pResult, int& Exception)
return true; // no interruption
}
-
-
-
//! Constructor of robot application
-CRobotMain::CRobotMain(CApplication* app)
+CRobotMain::CRobotMain(CApplication* app, bool loadProfile)
{
m_app = app;
@@ -643,7 +641,7 @@ CRobotMain::CRobotMain(CApplication* app)
m_visitLast = EVENT_NULL;
m_visitObject = 0;
m_visitArrow = 0;
- m_audioTrack = 0;
+ m_audioTrack = "";
m_audioRepeat = true;
m_delayWriteMessage = 0;
m_selectObject = 0;
@@ -656,6 +654,7 @@ CRobotMain::CRobotMain(CApplication* app)
m_terrainCreate = false;
m_version = 1;
+ m_controller = nullptr;
m_retroStyle = false;
m_immediatSatCom = false;
m_beginSatCom = false;
@@ -670,11 +669,13 @@ CRobotMain::CRobotMain(CApplication* app)
m_showPos = false;
m_selectInsect = false;
m_showSoluce = false;
- #ifdef NDEBUG
- m_showAll = false;
- #else
+
+ #if DEV_BUILD
m_showAll = true; // for development
+ #else
+ m_showAll = false;
#endif
+
m_cheatRadar = false;
m_fixScene = false;
m_trainerPilot = false;
@@ -705,27 +706,31 @@ CRobotMain::CRobotMain(CApplication* app)
m_windowPos = Math::Point(0.15f, 0.17f);
m_windowDim = Math::Point(0.70f, 0.66f);
- // TODO: profile
- // float fValue;
- // int iValue;
+ float fValue;
+ int iValue;
- // if (GetLocalProfileFloat("Edit", "FontSize", fValue)) m_fontSize = fValue;
- // if (GetLocalProfileFloat("Edit", "WindowPos.x", fValue)) m_windowPos.x = fValue;
- // if (GetLocalProfileFloat("Edit", "WindowPos.y", fValue)) m_windowPos.y = fValue;
- // if (GetLocalProfileFloat("Edit", "WindowDim.x", fValue)) m_windowDim.x = fValue;
- // if (GetLocalProfileFloat("Edit", "WindowDim.y", fValue)) m_windowDim.y = fValue;
+ if (loadProfile)
+ {
+ if (GetProfile().GetLocalProfileFloat("Edit", "FontSize", fValue)) m_fontSize = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "WindowPosX", fValue)) m_windowPos.x = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "WindowPosY", fValue)) m_windowPos.y = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "WindowDimX", fValue)) m_windowDim.x = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "WindowDimY", fValue)) m_windowDim.y = fValue;
+ }
m_IOPublic = false;
m_IODim = Math::Point(320.0f/640.0f, (121.0f+18.0f*8)/480.0f);
m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle
m_IOPos.y = (1.0f-m_IODim.y)/2.0f;
- /* TODO: profile
- if (GetLocalProfileInt ("Edit", "IOPublic", iValue)) m_IOPublic = iValue;
- if (GetLocalProfileFloat("Edit", "IOPos.x", fValue)) m_IOPos.x = fValue;
- if (GetLocalProfileFloat("Edit", "IOPos.y", fValue)) m_IOPos.y = fValue;
- if (GetLocalProfileFloat("Edit", "IODim.x", fValue)) m_IODim.x = fValue;
- if (GetLocalProfileFloat("Edit", "IODim.y", fValue)) m_IODim.y = fValue; */
+ if (loadProfile)
+ {
+ if (GetProfile().GetLocalProfileInt ("Edit", "IOPublic", iValue)) m_IOPublic = iValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "IOPosX", fValue)) m_IOPos.x = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "IOPosY", fValue)) m_IOPos.y = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "IODimX", fValue)) m_IODim.x = fValue;
+ if (GetProfile().GetLocalProfileFloat("Edit", "IODimY", fValue)) m_IODim.y = fValue;
+ }
m_short->FlushShortcuts();
InitEye();
@@ -741,12 +746,11 @@ CRobotMain::CRobotMain(CApplication* app)
g_researchEnable = 0;
g_unit = UNIT;
- m_gamerName[0] = 0;
- /* TODO: profile
- GetLocalProfileString("Gamer", "LastName", m_gamerName, 100); */
+ m_gamerName = "";
+ if (loadProfile) GetProfile().GetLocalProfileString("Gamer", "LastName", m_gamerName);
SetGlobalGamerName(m_gamerName);
ReadFreeParam();
- m_dialog->SetupRecall();
+ if (loadProfile) m_dialog->SetupRecall();
for (int i = 0; i < MAXSHOWLIMIT; i++)
{
@@ -805,6 +809,48 @@ CRobotMain::CRobotMain(CApplication* app)
CBotProgram::DefineNum("FilterOnlyLanding", FILTER_ONLYLANDING);
CBotProgram::DefineNum("FilterOnlyFliying", FILTER_ONLYFLYING);
+ CBotProgram::DefineNum("ExploNone", 0);
+ CBotProgram::DefineNum("ExploBoum", EXPLO_BOUM);
+ CBotProgram::DefineNum("ExploBurn", EXPLO_BURN);
+ CBotProgram::DefineNum("ExploWater", EXPLO_WATER);
+
+ CBotProgram::DefineNum("ResultNotEnded", ERR_MISSION_NOTERM);
+ CBotProgram::DefineNum("ResultLost", INFO_LOST);
+ CBotProgram::DefineNum("ResultLostQuick", INFO_LOSTq);
+ CBotProgram::DefineNum("ResultWin", ERR_OK);
+
+ CBotProgram::DefineNum("BuildBotFactory", BUILD_FACTORY);
+ CBotProgram::DefineNum("BuildDerrick", BUILD_DERRICK);
+ CBotProgram::DefineNum("BuildConverter", BUILD_CONVERT);
+ CBotProgram::DefineNum("BuildRadarStation", BUILD_RADAR);
+ CBotProgram::DefineNum("BuildPowerPlant", BUILD_ENERGY);
+ CBotProgram::DefineNum("BuildNuclearPlant", BUILD_NUCLEAR);
+ CBotProgram::DefineNum("BuildPowerStation", BUILD_STATION);
+ CBotProgram::DefineNum("BuildRepairCenter", BUILD_REPAIR);
+ CBotProgram::DefineNum("BuildDefenseTower", BUILD_TOWER);
+ CBotProgram::DefineNum("BuildResearchCenter", BUILD_RESEARCH);
+ CBotProgram::DefineNum("BuildAutoLab", BUILD_LABO);
+ CBotProgram::DefineNum("BuildPowerCaptor", BUILD_PARA);
+ CBotProgram::DefineNum("BuildExchangePost", BUILD_INFO);
+ CBotProgram::DefineNum("BuildDestroyer", BUILD_DESTROYER);
+ CBotProgram::DefineNum("FlatGround", BUILD_GFLAT);
+ CBotProgram::DefineNum("UseFlags", BUILD_FLAG);
+ CBotProgram::DefineNum("ResearchTracked", RESEARCH_TANK);
+ CBotProgram::DefineNum("ResearchWinged", RESEARCH_FLY);
+ CBotProgram::DefineNum("ResearchShooter", RESEARCH_CANON);
+ CBotProgram::DefineNum("ResearchDefenseTower", RESEARCH_TOWER);
+ CBotProgram::DefineNum("ResearchNuclearPlant", RESEARCH_ATOMIC);
+ CBotProgram::DefineNum("ResearchThumper", RESEARCH_THUMP);
+ CBotProgram::DefineNum("ResearchShielder", RESEARCH_SHIELD);
+ CBotProgram::DefineNum("ResearchPhazerShooter", RESEARCH_PHAZER);
+ CBotProgram::DefineNum("ResearchLegged", RESEARCH_iPAW);
+ CBotProgram::DefineNum("ResearchOrgaShooter", RESEARCH_iGUN);
+ CBotProgram::DefineNum("ResearchRecycler", RESEARCH_RECYCLER);
+ CBotProgram::DefineNum("ResearchSubber", RESEARCH_SUBM);
+ CBotProgram::DefineNum("ResearchSniffer", RESEARCH_SNIFFER);
+
+//? CBotProgram::
+
CBotProgram::DefineNum("PolskiPortalColobota", 1337);
CBotClass* bc;
@@ -831,6 +877,11 @@ CRobotMain::CRobotMain(CApplication* app)
bc->AddItem("material", CBotTypResult(CBotTypInt), PR_READ);
bc->AddItem("energyCell", CBotTypResult(CBotTypPointer, "object"), PR_READ);
bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), PR_READ);
+ bc->AddItem("id", CBotTypResult(CBotTypInt), PR_READ);
+ bc->AddFunction("busy", CScript::rBusy, CScript::cBusy);
+ bc->AddFunction("factory", CScript::rFactory, CScript::cFactory);
+ bc->AddFunction("research", CScript::rResearch, CScript::cClassOneFloat);
+ bc->AddFunction("destroy", CScript::rDestroy, CScript::cClassNull);
// Initializes the class FILE.
InitClassFILE();
@@ -891,15 +942,32 @@ Ui::CDisplayText* CRobotMain::GetDisplayText()
return m_displayText;
}
+void CRobotMain::LoadSceneOnStart(const std::string& name, int rank)
+{
+ // TODO: fix this ugly dependency :(
+ m_dialog->SetSceneName(name.c_str());
+ m_dialog->SetSceneRank(rank);
+ ChangePhase(PHASE_LOADING);
+}
+
//! Creates the file colobot.ini at the first time
void CRobotMain::CreateIni()
{
- /* TODO: profile
- int iValue;
- // colobot.ini doesn't exist?
- if (!GetLocalProfileInt("Setup", "TotoMode", iValue))
- m_dialog->SetupMemorize();*/
+ m_dialog->SetupMemorize();
+
+ GetProfile().SetLocalProfileFloat("Edit", "FontSize", m_fontSize);
+ GetProfile().SetLocalProfileFloat("Edit", "WindowPosX", m_windowPos.x);
+ GetProfile().SetLocalProfileFloat("Edit", "WindowPosY", m_windowPos.y);
+ GetProfile().SetLocalProfileFloat("Edit", "WindowDimX", m_windowDim.x);
+ GetProfile().SetLocalProfileFloat("Edit", "WindowDimY", m_windowDim.y);
+ GetProfile().SetLocalProfileInt("Edit", "IOPublic", m_IOPublic);
+ GetProfile().SetLocalProfileFloat("Edit", "IOPosX", m_IOPos.x);
+ GetProfile().SetLocalProfileFloat("Edit", "IOPosY", m_IOPos.y);
+ GetProfile().SetLocalProfileFloat("Edit", "IODimX", m_IODim.x);
+ GetProfile().SetLocalProfileFloat("Edit", "IODimY", m_IODim.y);
+
+ GetProfile().SaveCurrentDirectory();
}
void CRobotMain::SetDefaultInputBindings()
@@ -952,28 +1020,24 @@ void CRobotMain::SetDefaultInputBindings()
void CRobotMain::SetInputBinding(InputSlot slot, InputBinding binding)
{
unsigned int index = static_cast<unsigned int>(slot);
- assert(index >= 0 && index < INPUT_SLOT_MAX);
m_inputBindings[index] = binding;
}
const InputBinding& CRobotMain::GetInputBinding(InputSlot slot)
{
unsigned int index = static_cast<unsigned int>(slot);
- assert(index >= 0 && index < INPUT_SLOT_MAX);
return m_inputBindings[index];
}
void CRobotMain::SetJoyAxisBinding(JoyAxisSlot slot, JoyAxisBinding binding)
{
unsigned int index = static_cast<unsigned int>(slot);
- assert(index >= 0 && index < JOY_AXIS_SLOT_MAX);
m_joyAxisBindings[index] = binding;
}
const JoyAxisBinding& CRobotMain::GetJoyAxisBinding(JoyAxisSlot slot)
{
unsigned int index = static_cast<unsigned int>(slot);
- assert(index >= 0 && index < JOY_AXIS_SLOT_MAX);
return m_joyAxisBindings[index];
}
@@ -1041,6 +1105,7 @@ void CRobotMain::ChangePhase(Phase phase)
FlushDisplayInfo();
m_engine->SetRankView(0);
m_engine->DeleteAllObjects();
+ Gfx::CModelManager::GetInstancePointer()->DeleteAllModelCopies();
m_engine->SetWaterAddColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f));
m_engine->SetBackground("");
m_engine->SetBackForce(false);
@@ -1137,6 +1202,8 @@ void CRobotMain::ChangePhase(Phase phase)
if (m_mapImage)
m_map->SetFixImage(m_mapFilename);
+ m_app->ResetTimeAfterLoading();
+
/*Math::Point ddim;
pos.x = 620.0f/640.0f;
@@ -1225,7 +1292,7 @@ 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();
}
}
@@ -1239,7 +1306,7 @@ void CRobotMain::ChangePhase(Phase phase)
}
//! Processes an event
-bool CRobotMain::EventProcess(Event &event)
+bool CRobotMain::ProcessEvent(Event &event)
{
/* Motion vector management */
@@ -1332,7 +1399,7 @@ bool CRobotMain::EventProcess(Event &event)
// Management of the console.
if (m_phase != PHASE_NAME &&
!m_movie->IsExist() &&
- !m_movieLock && !m_editLock &&
+ !m_movieLock && !m_editLock && !m_engine->GetPause() &&
event.type == EVENT_KEY_DOWN &&
event.key.key == KEY(PAUSE)) // Pause ?
{
@@ -1474,7 +1541,7 @@ bool CRobotMain::EventProcess(Event &event)
ChangePhase(PHASE_WIN);
else if (m_lostDelay > 0.0f)
ChangePhase(PHASE_LOST);
- else
+ else if (!m_cmdEdit)
m_dialog->StartAbort(); // do you want to leave?
}
if (event.key.key == KEY(PAUSE))
@@ -1760,12 +1827,47 @@ void CRobotMain::ExecuteCmd(char *cmd)
return;
}
+ if (strcmp(cmd, "allbuildings") == 0)
+ {
+ g_build = -1; // all buildings are available
+
+ m_eventQueue->AddEvent(Event(EVENT_UPDINTERFACE));
+ return;
+ }
+
+ if (strcmp(cmd, "all") == 0)
+ {
+ g_researchDone = -1; // all research are done
+ g_build = -1; // all buildings are available
+
+ m_eventQueue->AddEvent(Event(EVENT_UPDINTERFACE));
+ return;
+ }
+
if (strcmp(cmd, "nolimit") == 0)
{
m_terrain->SetFlyingMaxHeight(280.0f);
return;
}
+ if (strcmp(cmd, "controller") == 0)
+ {
+ if (m_controller != nullptr)
+ {
+ // Don't use SelectObject because it checks if the object is selectable
+ if (m_camera->GetType() == Gfx::CAM_TYPE_VISIT)
+ StopDisplayVisit();
+
+ CObject* prev = DeselectAll();
+ if (prev != nullptr && prev != m_controller)
+ m_controller->AddDeselList(prev);
+
+ SelectOneObject(m_controller, true);
+ m_short->UpdateShortcuts();
+ }
+ return;
+ }
+
if (strcmp(cmd, "photo1") == 0)
{
m_freePhoto = !m_freePhoto;
@@ -1834,7 +1936,7 @@ void CRobotMain::ExecuteCmd(char *cmd)
object->SetRange(object->GetRange()*10.0f);
return;
}
-
+
if (strcmp(cmd, "\155\157\157") == 0)
{
// VGhpcyBpcyBlYXN0ZXItZWdnIGFuZCBzbyBpdCBzaG91bGQgYmUgb2JmdXNjYXRlZCEgRG8gbm90
@@ -1901,7 +2003,14 @@ void CRobotMain::ExecuteCmd(char *cmd)
if (strcmp(cmd, "debugmode") == 0)
{
- m_app->SetDebugMode(!m_app->GetDebugMode());
+ if (m_app->IsDebugModeActive(DEBUG_ALL))
+ {
+ m_app->SetDebugModeActive(DEBUG_ALL, false);
+ }
+ else
+ {
+ m_app->SetDebugModeActive(DEBUG_ALL, true);
+ }
return;
}
@@ -1988,15 +2097,23 @@ void CRobotMain::ExecuteCmd(char *cmd)
return;
}
- if (strcmp(cmd, "speed4") == 0) {
+ if (strcmp(cmd, "speed4") == 0)
+ {
SetSpeed(4.0f);
UpdateSpeedLabel();
- return;
+ return;
}
- if (strcmp(cmd, "speed8") == 0) {
+ if (strcmp(cmd, "speed8") == 0)
+ {
SetSpeed(8.0f);
UpdateSpeedLabel();
- return;
+ return;
+ }
+ if (strcmp(cmd, "crazy") == 0)
+ {
+ SetSpeed(1000.0f);
+ UpdateSpeedLabel();
+ return;
}
if (m_phase == PHASE_SIMUL)
@@ -2020,7 +2137,7 @@ void CRobotMain::FlushDisplayInfo()
m_infoFilename[i][0] = 0;
m_infoPos[i] = 0;
}
- strcpy(m_infoFilename[SATCOM_OBJECT], "help/") + m_app->GetLanguageChar() + std::string("/objects.txt");
+ strcpy(m_infoFilename[SATCOM_OBJECT], "objects.txt");
m_infoIndex = 0;
}
@@ -2093,7 +2210,7 @@ void CRobotMain::StartDisplayInfo(const char *filename, int index)
void CRobotMain::StopDisplayInfo()
{
if (m_cmdEdit) return;
-
+
if (m_movieInfoIndex != -1) // film to read the SatCom?
m_movie->Start(MM_SATCOMclose, 2.0f);
@@ -2182,8 +2299,7 @@ float CRobotMain::GetGameTime()
void CRobotMain::SetFontSize(float size)
{
m_fontSize = size;
- /* TODO: profile
- SetLocalProfileFloat("Edit", "FontSize", m_fontSize); */
+ GetProfile().SetLocalProfileFloat("Edit", "FontSize", m_fontSize);
}
float CRobotMain::GetFontSize()
@@ -2195,9 +2311,8 @@ float CRobotMain::GetFontSize()
void CRobotMain::SetWindowPos(Math::Point pos)
{
m_windowPos = pos;
- /* TODO: profile
- SetLocalProfileFloat("Edit", "WindowPos.x", m_windowPos.x);
- SetLocalProfileFloat("Edit", "WindowPos.y", m_windowPos.y); */
+ GetProfile().SetLocalProfileFloat("Edit", "WindowPosX", m_windowPos.x);
+ GetProfile().SetLocalProfileFloat("Edit", "WindowPosY", m_windowPos.y);
}
Math::Point CRobotMain::GetWindowPos()
@@ -2208,9 +2323,8 @@ Math::Point CRobotMain::GetWindowPos()
void CRobotMain::SetWindowDim(Math::Point dim)
{
m_windowDim = dim;
- /* TODO: profile
- SetLocalProfileFloat("Edit", "WindowDim.x", m_windowDim.x);
- SetLocalProfileFloat("Edit", "WindowDim.y", m_windowDim.y); */
+ GetProfile().SetLocalProfileFloat("Edit", "WindowDimX", m_windowDim.x);
+ GetProfile().SetLocalProfileFloat("Edit", "WindowDimY", m_windowDim.y);
}
Math::Point CRobotMain::GetWindowDim()
@@ -2223,8 +2337,7 @@ Math::Point CRobotMain::GetWindowDim()
void CRobotMain::SetIOPublic(bool mode)
{
m_IOPublic = mode;
- /* TODO: profile
- SetLocalProfileInt("Edit", "IOPublic", m_IOPublic); */
+ GetProfile().SetLocalProfileInt("Edit", "IOPublic", m_IOPublic);
}
bool CRobotMain::GetIOPublic()
@@ -2235,9 +2348,8 @@ bool CRobotMain::GetIOPublic()
void CRobotMain::SetIOPos(Math::Point pos)
{
m_IOPos = pos;
- /* TODO: profile
- SetLocalProfileFloat("Edit", "IOPos.x", m_IOPos.x);
- SetLocalProfileFloat("Edit", "IOPos.y", m_IOPos.y); */
+ GetProfile().SetLocalProfileFloat("Edit", "IOPosX", m_IOPos.x);
+ GetProfile().SetLocalProfileFloat("Edit", "IOPosY", m_IOPos.y);
}
Math::Point CRobotMain::GetIOPos()
@@ -2248,9 +2360,8 @@ Math::Point CRobotMain::GetIOPos()
void CRobotMain::SetIODim(Math::Point dim)
{
m_IODim = dim;
- /* TODO: profile
- SetLocalProfileFloat("Edit", "IODim.x", m_IODim.x);
- SetLocalProfileFloat("Edit", "IODim.y", m_IODim.y); */
+ GetProfile().SetLocalProfileFloat("Edit", "IODimX", m_IODim.x);
+ GetProfile().SetLocalProfileFloat("Edit", "IODimY", m_IODim.y);
}
Math::Point CRobotMain::GetIODim()
@@ -2680,6 +2791,8 @@ CObject* CRobotMain::DetectObject(Math::Point pos)
if (obj == nullptr) break;
if (!obj->GetActif()) continue;
+ CObject* truck = obj->GetTruck();
+ if (truck != nullptr) if (!truck->GetActif()) continue;
if (obj->GetProxyActivate()) continue;
CObject* target = nullptr;
@@ -3446,6 +3559,7 @@ bool CRobotMain::EventFrame(const Event &event)
{
m_checkEndTime = m_time;
CheckEndMission(true);
+ UpdateAudio(true);
}
if (m_winDelay > 0.0f && !m_editLock)
@@ -3635,7 +3749,7 @@ void CRobotMain::Convert()
}
}
- if (Cmd(line, "EndMissionTake"))
+ if (Cmd(line, "EndMissionTake") || Cmd(line, "AudioChange"))
{
char* p = strstr(line, "pos=");
if (p != 0)
@@ -3729,6 +3843,7 @@ void CRobotMain::ScenePerso()
{
DeleteAllObjects(); // removes all the current 3D Scene
m_engine->DeleteAllObjects();
+ Gfx::CModelManager::GetInstancePointer()->DeleteAllModelCopies();
m_terrain->FlushRelief(); // all flat
m_terrain->FlushBuildingLevel();
m_terrain->FlushFlyingLimit();
@@ -3785,7 +3900,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
FlushDisplayInfo();
m_terrain->FlushMaterials();
- m_audioTrack = 0;
+ m_audioTrack = "";
m_audioRepeat = true;
m_displayText->SetDelay(1.0f);
m_displayText->SetEnable(true);
@@ -3793,8 +3908,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_lockedSatCom = false;
m_endingWinRank = 0;
m_endingLostRank = 0;
+ m_audioChangeTotal = 0;
m_endTakeTotal = 0;
m_endTakeResearch = 0;
+ m_endTakeNever = false;
m_endTakeWinDelay = 2.0f;
m_endTakeLostDelay = 2.0f;
m_obligatoryTotal = 0;
@@ -3803,6 +3920,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_mapImage = false;
m_mapFilename[0] = 0;
+ m_controller = nullptr;
+
m_colorRefBot.r = 10.0f/256.0f;
m_colorRefBot.g = 166.0f/256.0f;
m_colorRefBot.b = 254.0f/256.0f; // blue
@@ -3840,6 +3959,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_version = 1;
m_retroStyle = false;
+
+ m_missionResult = ERR_MISSION_NOTERM;
}
char line[500];
@@ -3864,12 +3985,12 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
int rankGadget = 0;
CObject* sel = 0;
- std::string oldLocale;
- char *locale = setlocale(LC_NUMERIC, nullptr);
- if (locale != nullptr)
- oldLocale = locale;
+ SetNumericLocale();
- setlocale(LC_NUMERIC, "C");
+ /*
+ * NOTE: Moving frequently used lines to the top
+ * may speed up loading
+ */
while (fgets(line, 500, file) != NULL)
{
@@ -3890,18 +4011,34 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
// TODO: Fallback to an non-localized entry
sprintf(op, "Title.%c", m_app->GetLanguageChar());
if (Cmd(line, op) && !resetObject)
+ {
OpString(line, "text", m_title);
+ continue;
+ }
sprintf(op, "Resume.%c", m_app->GetLanguageChar());
if (Cmd(line, op) && !resetObject)
+ {
OpString(line, "text", m_resume);
+ continue;
+ }
sprintf(op, "ScriptName.%c", m_app->GetLanguageChar());
if (Cmd(line, op) && !resetObject)
+ {
OpString(line, "text", m_scriptName);
+ continue;
+ }
+
+ if (Cmd(line, "Title")) continue; // Ignore
+ if (Cmd(line, "Resume")) continue; // Ignore
+ if (Cmd(line, "ScriptName")) continue; // Ignore
if (Cmd(line, "ScriptFile") && !resetObject)
+ {
OpString(line, "name", m_scriptFile);
+ continue;
+ }
if (Cmd(line, "Instructions") && !resetObject)
{
@@ -3910,7 +4047,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
strcpy(m_infoFilename[SATCOM_HUSTON], path.c_str());
m_immediatSatCom = OpInt(line, "immediat", 0);
- if(m_version >= 2) m_beginSatCom = m_lockedSatCom = OpInt(line, "lock", 0);
+ if (m_version >= 2) m_beginSatCom = m_lockedSatCom = OpInt(line, "lock", 0);
+ continue;
}
if (Cmd(line, "Satellite") && !resetObject)
@@ -3918,6 +4056,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpString(line, "name", name);
std::string path = m_app->GetDataFilePath(DIR_HELP, name);
strcpy(m_infoFilename[SATCOM_SAT], path.c_str());
+ continue;
}
if (Cmd(line, "Loading") && !resetObject)
@@ -3925,6 +4064,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpString(line, "name", name);
std::string path = m_app->GetDataFilePath(DIR_HELP, name);
strcpy(m_infoFilename[SATCOM_LOADING], path.c_str());
+ continue;
}
if (Cmd(line, "HelpFile") && !resetObject)
@@ -3932,66 +4072,131 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpString(line, "name", name);
std::string path = m_app->GetDataFilePath(DIR_HELP, name);
strcpy(m_infoFilename[SATCOM_PROG], path.c_str());
+ continue;
}
if (Cmd(line, "SoluceFile") && !resetObject)
{
OpString(line, "name", name);
std::string path = m_app->GetDataFilePath(DIR_HELP, name);
strcpy(m_infoFilename[SATCOM_SOLUCE], path.c_str());
+ continue;
}
if (Cmd(line, "EndingFile") && !resetObject)
{
m_endingWinRank = OpInt(line, "win", 0);
m_endingLostRank = OpInt(line, "lost", 0);
+ continue;
}
if (Cmd(line, "MessageDelay") && !resetObject)
{
m_displayText->SetDelay(OpFloat(line, "factor", 1.0f));
+ continue;
+ }
+
+ if (Cmd(line, "CacheAudio") && !resetObject && m_version >= 2)
+ {
+ OpString(line, "filename", name);
+ m_sound->CacheMusic(name);
+ continue;
+ }
+
+ if (Cmd(line, "AudioChange") && !resetObject && m_version >= 2 && m_controller == nullptr)
+ {
+ int i = m_audioChangeTotal;
+ if (i < 10)
+ {
+ m_audioChange[i].pos = OpPos(line, "pos")*g_unit;
+ m_audioChange[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
+ m_audioChange[i].type = OpTypeObject(line, "type", OBJECT_NULL);
+ m_audioChange[i].min = OpInt(line, "min", 1);
+ m_audioChange[i].max = OpInt(line, "max", 9999);
+ m_audioChange[i].powermin = OpInt(line, "powermin", -1);
+ m_audioChange[i].powermax = OpInt(line, "powermax", 100);
+ OpString(line, "filename", m_audioChange[i].music);
+ m_audioChange[i].repeat = OpInt(line, "repeat", 1);
+ m_audioChange[i].changed = false;
+ m_sound->CacheMusic(m_audioChange[i].music);
+ m_audioChangeTotal ++;
+ }
+ continue;
}
- if (Cmd(line, "Audio") && !resetObject)
+ if (Cmd(line, "Audio") && !resetObject && m_controller == nullptr)
{
- m_audioTrack = OpInt(line, "track", 0);
+ if (m_version < 2)
+ {
+ int trackid = OpInt(line, "track", 0);
+ if (trackid != 0)
+ {
+ std::stringstream filenameStr;
+ filenameStr << "music" << std::setfill('0') << std::setw(3) << trackid << ".ogg";
+ m_audioTrack = filenameStr.str();
+ }
+ }
+ else
+ {
+ char trackname[100];
+ OpString(line, "filename", trackname);
+ m_audioTrack = trackname;
+ }
m_audioRepeat = OpInt(line, "repeat", 1);
+ if (m_audioTrack != "") m_sound->CacheMusic(m_audioTrack);
+ continue;
}
if (Cmd(line, "AmbientColor") && !resetObject)
{
m_engine->SetAmbientColor(OpColor(line, "air", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f)), 0);
m_engine->SetAmbientColor(OpColor(line, "water", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f)), 1);
+ continue;
}
if (Cmd(line, "FogColor") && !resetObject)
{
m_engine->SetFogColor(OpColor(line, "air", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f)), 0);
m_engine->SetFogColor(OpColor(line, "water", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f)), 1);
+ continue;
}
if (Cmd(line, "VehicleColor") && !resetObject)
+ {
m_colorNewBot = OpColor(line, "color", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f));
+ continue;
+ }
if (Cmd(line, "InsectColor") && !resetObject)
+ {
m_colorNewAlien = OpColor(line, "color", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f));
+ continue;
+ }
if (Cmd(line, "GreeneryColor") && !resetObject)
+ {
m_colorNewGreen = OpColor(line, "color", Gfx::Color(0.533f, 0.533f, 0.533f, 0.533f));
+ continue;
+ }
if (Cmd(line, "DeepView") && !resetObject)
{
m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*g_unit, 0, true);
m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*g_unit, 1, true);
+ continue;
}
if (Cmd(line, "FogStart") && !resetObject)
{
m_engine->SetFogStart(OpFloat(line, "air", 0.5f), 0);
m_engine->SetFogStart(OpFloat(line, "water", 0.5f), 1);
+ continue;
}
if (Cmd(line, "SecondTexture") && !resetObject)
+ {
m_engine->SetSecondTexture(OpInt(line, "rank", 1));
+ continue;
+ }
if (Cmd(line, "Background") && !resetObject)
{
@@ -4002,6 +4207,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpColor(line, "cloudUp", Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)),
OpColor(line, "cloudDown", Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)),
OpInt(line, "full", 0));
+ continue;
}
if (Cmd(line, "Planet") && !resetObject)
@@ -4022,12 +4228,14 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
Math::Point(uv2.x, uv2.z),
strstr(name, "planet") != nullptr // TODO: add transparent op or modify textures
);
+ continue;
}
if (Cmd(line, "ForegroundName") && !resetObject)
{
OpString(line, "image", name);
m_engine->SetForegroundName(name);
+ continue;
}
if (((m_version == 1 && Cmd(line, "Global")) || (m_version >= 2 && Cmd(line, "Mission"))) && !resetObject)
@@ -4035,20 +4243,24 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
g_unit = OpFloat(line, "unitScale", 4.0f);
m_engine->SetTracePrecision(OpFloat(line, "traceQuality", 1.0f));
m_shortCut = OpInt(line, "shortcut", 1);
- if(m_version >= 2) {
+ if (m_version >= 2)
+ {
m_retroStyle = OpInt(line, "retro", 0);
- if(m_retroStyle) GetLogger()->Info("Retro mode enabled.\n");
+ if (m_retroStyle) GetLogger()->Info("Retro mode enabled.\n");
}
+ continue;
}
if (Cmd(line, "TerrainGenerate") && !resetObject)
{
- if(m_terrainCreate) {
+ if (m_terrainCreate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainGenerate after TerrainCreate\n", filename, lineNum);
continue;
}
- if(m_terrainInit) {
+ if (m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainGenerate after TerrainInit\n", filename, lineNum);
continue;
}
@@ -4061,67 +4273,81 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpFloat(line, "hard", 0.5f));
m_terrainGenerate = true;
+ continue;
}
- if (Cmd(line, "TerrainWind") && !resetObject) {
- if(m_terrainCreate) {
+ if (Cmd(line, "TerrainWind") && !resetObject)
+ {
+ if (m_terrainCreate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainWind after TerrainCreate\n", filename, lineNum);
continue;
}
- if(m_terrainInit) {
+ if (m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainWind after TerrainInit\n", filename, lineNum);
continue;
}
- if(!m_terrainGenerate) {
+ if (!m_terrainGenerate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainWind before TerrainGenerate\n", filename, lineNum);
continue;
}
m_terrain->SetWind(OpPos(line, "speed"));
+ continue;
}
if (Cmd(line, "TerrainRelief") && !resetObject)
{
- if(m_terrainCreate) {
+ if (m_terrainCreate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainRelief after TerrainCreate\n", filename, lineNum);
continue;
}
- if(m_terrainInit) {
+ if (m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainRelief after TerrainInit\n", filename, lineNum);
continue;
}
- if(!m_terrainGenerate) {
+ if (!m_terrainGenerate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainRelief before TerrainGenerate\n", filename, lineNum);
continue;
}
OpString(line, "image", name);
m_terrain->LoadRelief(name, OpFloat(line, "factor", 1.0f), OpInt(line, "border", 1));
+ continue;
}
if (Cmd(line, "TerrainResource") && !resetObject)
{
- if(m_terrainCreate) {
+ if (m_terrainCreate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainResource after TerrainCreate\n", filename, lineNum);
continue;
}
- if(m_terrainInit) {
+ if (m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainResource after TerrainInit\n", filename, lineNum);
continue;
}
- if(!m_terrainGenerate) {
+ if (!m_terrainGenerate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainResource before TerrainGenerate\n", filename, lineNum);
continue;
}
OpString(line, "image", name);
m_terrain->LoadResources(name);
+ continue;
}
if (Cmd(line, "TerrainWater") && !resetObject)
@@ -4141,10 +4367,14 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
pos);
m_colorNewWater = OpColor(line, "color", m_colorRefWater);
m_colorShiftWater = OpFloat(line, "brightness", 0.0f);
+ continue;
}
if (Cmd(line, "TerrainLava") && !resetObject)
+ {
m_water->SetLava(OpInt(line, "mode", 0));
+ continue;
+ }
if (Cmd(line, "TerrainCloud") && !resetObject)
{
@@ -4153,6 +4383,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpColor(line, "diffuse", Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)),
OpColor(line, "ambient", Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f)),
OpFloat(line, "level", 500.0f) * g_unit);
+ continue;
}
if (Cmd(line, "TerrainBlitz") && !resetObject)
@@ -4160,11 +4391,13 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_lightning->Create(OpFloat(line, "sleep", 0.0f),
OpFloat(line, "delay", 3.0f),
OpFloat(line, "magnetic", 50.0f) * g_unit);
+ continue;
}
if (Cmd(line, "TerrainInitTextures") && !resetObject)
{
- if(m_terrainInit) {
+ if (m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainInitTextures and TerrainInit at same time\n", filename, lineNum);
continue;
}
@@ -4173,10 +4406,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
AddExt(name, ".png");
int dx = OpInt(line, "dx", 1);
int dy = OpInt(line, "dy", 1);
- char* op = SearchOp(line, "table");
+ char* opTable = SearchOp(line, "table");
int tt[100];
for (int i = 0; i < dx*dy; i++)
- tt[i] = GetInt(op, i, 0);
+ tt[i] = GetInt(opTable, i, 0);
if (strstr(name, "%user%") != 0)
CopyFileListToTemp(name, tt, dx*dy);
@@ -4184,38 +4417,46 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_terrain->InitTextures(name, tt, dx, dy);
m_terrainInitTextures = true;
+ continue;
}
- if (Cmd(line, "TerrainInit") && !resetObject) {
- if(m_terrainInitTextures) {
+ if (Cmd(line, "TerrainInit") && !resetObject)
+ {
+ if (m_terrainInitTextures)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainInit and TerrainInitTextures at same time\n", filename, lineNum);
continue;
}
m_terrain->InitMaterials(OpInt(line, "id", 1));
m_terrainInit = true;
+ continue;
}
if (Cmd(line, "TerrainMaterial") && !resetObject)
{
- if(m_terrainCreate) {
+ if (m_terrainCreate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainMaterial after TerrainCreate\n", filename, lineNum);
continue;
}
- if(m_terrainInit) {
+ if (m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainMaterial after TerrainInit\n", filename, lineNum);
continue;
}
- if(m_terrainInitTextures) {
+ if (m_terrainInitTextures)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainMaterial and TerrainInitTextures at same time\n", filename, lineNum);
continue;
}
OpString(line, "image", name);
AddExt(name, ".png");
- if (strstr(name, "%user%") != 0) {
+ if (strstr(name, "%user%") != 0)
+ {
GetProfile().CopyFileToTemp(std::string(name));
}
@@ -4228,36 +4469,41 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpInt(line, "down", 1),
OpInt(line, "left", 1),
OpFloat(line, "hard", 0.5f));
+ continue;
}
if (Cmd(line, "TerrainLevel") && !resetObject)
{
- if(m_terrainCreate) {
+ if (m_terrainCreate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainLevel after TerrainCreate\n", filename, lineNum);
continue;
}
- if(!m_terrainInit) {
+ if (!m_terrainInit)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainLevel before TerrainInit\n", filename, lineNum);
continue;
}
- if(m_terrainInitTextures) {
+ if (m_terrainInitTextures)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainLevel and TerrainInitTextures at same time\n", filename, lineNum);
continue;
}
- if(!m_terrainGenerate) {
+ if (!m_terrainGenerate)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): TerrainLevel before TerrainGenerate\n", filename, lineNum);
continue;
}
- char* op = SearchOp(line, "id");
+ char* opId = SearchOp(line, "id");
int id[50];
int i = 0;
while (i < 50)
{
- id[i] = GetInt(op, i, 0);
+ id[i] = GetInt(opId, i, 0);
if (id[i++] == 0) break;
}
@@ -4268,11 +4514,14 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpFloat(line, "freq", 100.0f),
OpPos(line, "center")*g_unit,
OpFloat(line, "radius", 0.0f)*g_unit);
+ continue;
}
- if (Cmd(line, "TerrainCreate") && !resetObject) {
+ if (Cmd(line, "TerrainCreate") && !resetObject)
+ {
m_terrain->CreateObjects();
m_terrainCreate = true;
+ continue;
}
if (Cmd(line, "BeginObject"))
@@ -4284,11 +4533,35 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
sel = IOReadScene(read, stack);
m_beginObject = true;
+ continue;
+ }
+
+ if (Cmd(line, "MissionController") && read[0] == 0 && m_version >= 2)
+ {
+ /* TODO: ???
+ if (!m_beginObject)
+ {
+ GetLogger()->Error("Syntax error in file '%s' (line %d): MissionController before BeginObject\n", filename, lineNum);
+ continue;
+ }*/
+
+ m_controller = CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, 1.0f, 0.0f, OBJECT_CONTROLLER, 100.0f, false, false, 0);
+ m_controller->SetMagnifyDamage(100.0f);
+ CBrain* brain = m_controller->GetBrain();
+ if (brain != nullptr)
+ {
+ OpString(line, "script", name);
+ if (name[0] != 0)
+ brain->SetScriptName(0, name);
+ brain->SetScriptRun(0);
+ }
+ continue;
}
if (Cmd(line, "CreateObject") && read[0] == 0)
{
- if (!m_beginObject) {
+ if (!m_beginObject)
+ {
GetLogger()->Error("Syntax error in file '%s' (line %d): CreateObject before BeginObject\n", filename, lineNum);
continue;
}
@@ -4330,9 +4603,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
}
Math::Vector pos = OpPos(line, "pos")*g_unit;
- float dir = OpFloat(line, "dir", 0.0f)*Math::PI;
+ float dirAngle = OpFloat(line, "dir", 0.0f)*Math::PI;
bool trainer = OpInt(line, "trainer", 0);
- CObject* obj = CreateObject(pos, dir,
+ CObject* obj = CreateObject(pos, dirAngle,
OpFloat(line, "z", 1.0f),
OpFloat(line, "h", 0.0f),
type,
@@ -4391,7 +4664,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
sel = obj;
}
- obj->SetSelectable(OpInt(line, "selectable", 1));
+ bool selectable = OpInt(line, "selectable", 1);
+ obj->SetSelectable(selectable);
obj->SetEnable(OpInt(line, "enable", 1));
obj->SetProxyActivate(OpInt(line, "proxyActivate", 0));
obj->SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
@@ -4399,10 +4673,15 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
obj->SetShield(OpFloat(line, "shield", 1.0f));
obj->SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
obj->SetClip(OpInt(line, "clip", 1));
- obj->SetCheckToken(m_version >= 2 ? trainer : OpInt(line, "manual", 1));
- obj->SetManual(m_version >= 2 ? !trainer : OpInt(line, "manual", 0));
+ obj->SetCheckToken(m_version >= 2 ? trainer || !selectable : OpInt(line, "checkToken", 1));
+ // SetManual will affect bot speed
+ if (type == OBJECT_MOBILEdr)
+ {
+ obj->SetManual(m_version >= 2 ? !trainer : OpInt(line, "manual", 0));
+ }
- if(m_version >= 2) {
+ if (m_version >= 2)
+ {
Math::Vector zoom = OpDir(line, "zoom");
if (zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f)
obj->SetZoom(0, zoom);
@@ -4479,6 +4758,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
}
rankObj ++;
+ continue;
}
if (Cmd(line, "CreateFog") && !resetObject)
@@ -4494,6 +4774,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
dim.x = ddim;
dim.y = dim.x;
m_particle->CreateParticle(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, type, delay, 0.0f, 0.0f);
+ continue;
}
if (Cmd(line, "CreateLight") && !resetObject)
@@ -4505,7 +4786,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
type = OpTypeTerrain(line, "type", Gfx::ENG_OBJTYPE_NULL);
if (type == Gfx::ENG_OBJTYPE_TERRAIN)
+ {
+ m_lightMan->SetLightPriority(lightRank, Gfx::LIGHT_PRI_HIGHEST);
m_lightMan->SetLightIncludeType(lightRank, Gfx::ENG_OBJTYPE_TERRAIN);
+ }
if (type == Gfx::ENG_OBJTYPE_QUARTZ)
m_lightMan->SetLightIncludeType(lightRank, Gfx::ENG_OBJTYPE_QUARTZ);
@@ -4515,6 +4799,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
if (type == Gfx::ENG_OBJTYPE_FIX)
m_lightMan->SetLightExcludeType(lightRank, Gfx::ENG_OBJTYPE_TERRAIN);
+
+ continue;
}
if (Cmd(line, "CreateSpot") && !resetObject)
{
@@ -4535,6 +4821,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
if (type == Gfx::ENG_OBJTYPE_FIX)
m_lightMan->SetLightExcludeType(rankLight, Gfx::ENG_OBJTYPE_TERRAIN);
+
+ continue;
}
if (Cmd(line, "GroundSpot") && !resetObject)
@@ -4549,10 +4837,14 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_engine->SetObjectGroundSpotMinMax(rank, OpFloat(line, "min", 0.0f)*g_unit,
OpFloat(line, "max", 0.0f)*g_unit);
}
+ continue;
}
if (Cmd(line, "WaterColor") && !resetObject)
+ {
m_engine->SetWaterAddColor(OpColor(line, "color", Gfx::Color(0.0f, 0.0f, 0.0f, 1.0f)));
+ continue;
+ }
if (Cmd(line, "MapColor") && !resetObject)
{
@@ -4573,23 +4865,29 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpInt(line, "mode", 0),
OpInt(line, "debug", 0));
}
+ continue;
}
+
if (Cmd(line, "MapZoom") && !resetObject)
{
m_map->ZoomMap(OpFloat(line, "factor", 2.0f));
m_map->MapEnable(OpInt(line, "enable", 1));
+ continue;
}
if (Cmd(line, "MaxFlyingHeight") && !resetObject)
{
m_terrain->SetFlyingMaxHeight(OpFloat(line, "max", 280.0f)*g_unit);
+ continue;
}
+
if (Cmd(line, "AddFlyingHeight") && !resetObject)
{
m_terrain->AddFlyingLimit(OpPos(line, "center")*g_unit,
OpFloat(line, "extRadius", 20.0f)*g_unit,
OpFloat(line, "intRadius", 10.0f)*g_unit,
OpFloat(line, "maxHeight", 200.0f));
+ continue;
}
if (Cmd(line, "Camera"))
@@ -4602,32 +4900,51 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_camera->StartOver(Gfx::CAM_OVER_EFFECT_FADEIN_WHITE, Math::Vector(0.0f, 0.0f, 0.0f), 1.0f);
m_camera->SetFixDirection(OpFloat(line, "fixDirection", 0.25f)*Math::PI);
+ continue;
}
- if (Cmd(line, "EndMissionTake") && !resetObject)
+ if (Cmd(line, "EndMissionTake") && !resetObject && m_controller == nullptr)
{
int i = m_endTakeTotal;
if (i < 10)
{
- m_endTake[i].pos = OpPos(line, "pos")*g_unit;
- m_endTake[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
- m_endTake[i].type = OpTypeObject(line, "type", OBJECT_NULL);
- m_endTake[i].min = OpInt(line, "min", 1);
- m_endTake[i].max = OpInt(line, "max", 9999);
- m_endTake[i].lost = OpInt(line, "lost", -1);
+ m_endTake[i].pos = OpPos(line, "pos")*g_unit;
+ m_endTake[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
+ m_endTake[i].type = OpTypeObject(line, "type", OBJECT_NULL);
+ m_endTake[i].min = OpInt(line, "min", 1);
+ m_endTake[i].max = OpInt(line, "max", 9999);
+ if (m_version >= 2)
+ {
+ m_endTake[i].powermin = OpInt(line, "powermin", -1);
+ m_endTake[i].powermax = OpInt(line, "powermax", 100);
+ }
+ else
+ {
+ m_endTake[i].powermin = -1;
+ m_endTake[i].powermax = 100;
+ }
+ m_endTake[i].lost = OpInt(line, "lost", -1);
m_endTake[i].immediat = OpInt(line, "immediat", 0);
OpString(line, "message", m_endTake[i].message);
m_endTakeTotal ++;
}
+ continue;
}
- if (Cmd(line, "EndMissionDelay") && !resetObject)
+ if (Cmd(line, "EndMissionDelay") && !resetObject && m_controller == nullptr)
{
m_endTakeWinDelay = OpFloat(line, "win", 2.0f);
m_endTakeLostDelay = OpFloat(line, "lost", 2.0f);
+ continue;
}
- if (Cmd(line, "EndMissionResearch") && !resetObject)
+ if (Cmd(line, "EndMissionResearch") && !resetObject && m_controller == nullptr)
{
m_endTakeResearch |= OpResearch(line, "type");
+ continue;
+ }
+ if (Cmd(line, "EndMissionNever") && !resetObject && m_controller == nullptr)
+ {
+ m_endTakeNever = true;
+ continue;
}
if (Cmd(line, "ObligatoryToken") && !resetObject)
@@ -4638,6 +4955,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpString(line, "text", m_obligatoryToken[i]);
m_obligatoryTotal ++;
}
+ continue;
}
if (Cmd(line, "ProhibitedToken") && !resetObject)
@@ -4648,22 +4966,39 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpString(line, "text", m_prohibitedToken[i]);
m_prohibitedTotal ++;
}
+ continue;
}
if (Cmd(line, "EnableBuild") && !resetObject)
+ {
g_build |= OpBuild(line, "type");
+ continue;
+ }
if (Cmd(line, "EnableResearch") && !resetObject)
+ {
g_researchEnable |= OpResearch(line, "type");
+ continue;
+ }
- if (Cmd(line, "DoneResearch") && read[0] == 0 && !resetObject) // not loading file?
+ if (Cmd(line, "DoneResearch") && read[0] == 0 && !resetObject) // not loading file?
+ {
g_researchDone |= OpResearch(line, "type");
+ continue;
+ }
if (Cmd(line, "NewScript") && !resetObject)
{
OpString(line, "name", name);
AddNewScriptName(OpTypeObject(line, "type", OBJECT_NULL), name);
+ continue;
}
+
+ if (line[0] == '\n') continue; // Ignore empty lines
+ if (line[0] == '\0') continue; // Ignore empty lines
+ if (read[0] != 0) continue; // Ignore when loading saved game
+
+ GetLogger()->Error("Syntax error in file '%s' (line %d): Unknown command: %s", filename, lineNum, line); // Don't add \n at the end of log message - it's included in line variable
}
fclose(file);
@@ -4737,7 +5072,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_dialog->SetSceneRead("");
m_dialog->SetStackRead("");
- setlocale(LC_NUMERIC, oldLocale.c_str());
+ RestoreNumericLocale();
}
//! Creates an object of decoration mobile or stationary
@@ -5055,7 +5390,8 @@ CObject* CRobotMain::CreateObject(Math::Vector pos, float angle, float zoom, flo
type == OBJECT_MOBILEwt ||
type == OBJECT_MOBILEit ||
type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 )
+ type == OBJECT_APOLLO2 ||
+ type == OBJECT_CONTROLLER )
{
object = new CObject();
object->SetOption(option);
@@ -5643,7 +5979,7 @@ char* SearchLastDir(char *filename)
while (p != filename)
{
- if (*(--p) == '/') return p;
+ if (*(--p) == '/' || *p == '\\') return p;
}
return 0;
}
@@ -5748,7 +6084,7 @@ void CRobotMain::LoadOneScript(CObject *obj, int &nbError)
char filename[MAX_FNAME];
sprintf(filename, "%s/%s/%c%.3d%.3d%.1d.txt",
- GetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
+ GetSavegameDir(), m_gamerName.c_str(), name[0], rank, objRank, i);
brain->ReadProgram(i, filename);
if (!brain->GetCompile(i)) nbError++;
}
@@ -5818,7 +6154,7 @@ void CRobotMain::SaveOneScript(CObject *obj)
{
char filename[MAX_FNAME];
sprintf(filename, "%s/%s/%c%.3d%.3d%.1d.txt",
- GetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
+ GetSavegameDir(), m_gamerName.c_str(), name[0], rank, objRank, i);
brain->WriteProgram(i, filename);
}
}
@@ -5945,6 +6281,8 @@ void CRobotMain::IOWriteObject(FILE *file, CObject* obj, const char *cmd)
{
if (obj->GetType() == OBJECT_FIX) return;
+ SetNumericLocale();
+
char line[3000];
char name[100];
@@ -6031,6 +6369,8 @@ void CRobotMain::IOWriteObject(FILE *file, CObject* obj, const char *cmd)
strcat(line, "\n");
fputs(line, file);
+
+ RestoreNumericLocale();
}
//! Saves the current game
@@ -6039,6 +6379,8 @@ bool CRobotMain::IOWriteScene(const char *filename, const char *filecbot, char *
FILE* file = fopen(filename, "w");
if (file == NULL) return false;
+ SetNumericLocale();
+
char line[500];
sprintf(line, "Title text=\"%s\"\n", info);
@@ -6101,6 +6443,8 @@ bool CRobotMain::IOWriteScene(const char *filename, const char *filecbot, char *
}
fclose(file);
+ RestoreNumericLocale();
+
#if CBOT_STACK
// Writes the file of stacks of execution.
file = fOpen(filecbot, "wb");
@@ -6145,6 +6489,8 @@ CObject* CRobotMain::IOReadObject(char *line, const char* filename, int objRank)
if (type == OBJECT_NULL)
return nullptr;
+ SetNumericLocale();
+
int trainer = OpInt(line, "trainer", 0);
int toy = OpInt(line, "toy", 0);
int option = OpInt(line, "option", 0);
@@ -6210,6 +6556,8 @@ CObject* CRobotMain::IOReadObject(char *line, const char* filename, int objRank)
automat->Start(run); // starts the film
}
+ RestoreNumericLocale();
+
return obj;
}
@@ -6221,6 +6569,8 @@ CObject* CRobotMain::IOReadScene(const char *filename, const char *filecbot)
FILE* file = fopen(filename, "r");
if (file == NULL) return 0;
+ SetNumericLocale();
+
CObject* fret = nullptr;
CObject* power = nullptr;
CObject* sel = nullptr;
@@ -6342,6 +6692,8 @@ CObject* CRobotMain::IOReadScene(const char *filename, const char *filecbot)
}
#endif
+ RestoreNumericLocale();
+
return sel;
}
@@ -6352,10 +6704,10 @@ void CRobotMain::WriteFreeParam()
m_freeResearch |= g_researchDone;
m_freeBuild |= g_build;
- if (m_gamerName[0] == 0) return;
+ if (m_gamerName == "") return;
char filename[MAX_FNAME];
- sprintf(filename, "%s/%s/research.gam", GetSavegameDir(), m_gamerName);
+ sprintf(filename, "%s/%s/research.gam", GetSavegameDir(), m_gamerName.c_str());
FILE* file = fopen(filename, "w");
if (file == NULL) return;
@@ -6371,10 +6723,10 @@ void CRobotMain::ReadFreeParam()
m_freeResearch = 0;
m_freeBuild = 0;
- if (m_gamerName[0] == 0) return;
+ if (m_gamerName == "") return;
char filename[MAX_FNAME];
- sprintf(filename, "%s/%s/research.gam", GetSavegameDir(), m_gamerName);
+ sprintf(filename, "%s/%s/research.gam", GetSavegameDir(), m_gamerName.c_str());
FILE* file = fopen(filename, "r");
if (file == NULL) return;
@@ -6525,9 +6877,113 @@ void CRobotMain::ResetCreate()
}
}
+//! Updates the audiotracks
+void CRobotMain::UpdateAudio(bool frame)
+{
+ CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
+
+ for (int t = 0; t < m_audioChangeTotal; t++)
+ {
+ if (m_audioChange[t].changed) continue;
+
+ Math::Vector bPos = m_audioChange[t].pos;
+ bPos.y = 0.0f;
+
+ Math::Vector oPos;
+
+ int nb = 0;
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* obj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
+ if (obj == nullptr) break;
+
+ // Do not use GetActif () because an invisible worm (underground)
+ // should be regarded as existing here!
+ if (obj->GetLock()) continue;
+ if (obj->GetRuin()) continue;
+ if (!obj->GetEnable()) continue;
+
+ ObjectType type = obj->GetType();
+ if (type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5) // wastes?
+ {
+ type = OBJECT_SCRAP1;
+ }
+
+ if (type != m_audioChange[t].type) continue;
+
+ float energyLevel = -1;
+ CObject* power = obj->GetPower();
+ if (power != nullptr)
+ {
+ energyLevel = power->GetEnergy();
+ if (power->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
+ }
+ if (energyLevel < m_audioChange[t].powermin || energyLevel > m_audioChange[t].powermax) continue;
+
+ if (obj->GetTruck() == 0)
+ oPos = obj->GetPosition(0);
+ else
+ oPos = obj->GetTruck()->GetPosition(0);
+
+ oPos.y = 0.0f;
+
+ if (Math::DistanceProjected(oPos, bPos) <= m_audioChange[t].dist)
+ nb ++;
+ }
+
+ if (nb >= m_audioChange[t].min &&
+ nb <= m_audioChange[t].max)
+ {
+ CLogger::GetInstancePointer()->Debug("Changing music...\n");
+ m_sound->StopMusic();
+ m_sound->PlayMusic(std::string(m_audioChange[t].music), m_audioChange[t].repeat);
+ m_audioChange[t].changed = true;
+ }
+ }
+}
+
+void CRobotMain::SetEndMission(Error result, float delay)
+{
+ if (m_controller != nullptr)
+ {
+ m_endTakeWinDelay = delay;
+ m_endTakeLostDelay = delay;
+ m_missionResult = result;
+ }
+}
+
//! Checks if the mission is over
Error CRobotMain::CheckEndMission(bool frame)
{
+ if (m_controller != nullptr)
+ {
+ if (m_missionResult == INFO_LOST) //mission lost?
+ {
+ m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
+ m_winDelay = 0.0f;
+ if (m_lostDelay == 0) m_lostDelay = m_endTakeLostDelay;
+ m_displayText->SetEnable(false);
+ }
+ if (m_missionResult == INFO_LOSTq) //mission lost?
+ {
+ m_winDelay = 0.0f;
+ if (m_lostDelay == 0) m_lostDelay = 0.1f;
+ m_displayText->SetEnable(false);
+ }
+ if (frame && m_base) return ERR_MISSION_NOTERM;
+ if (m_missionResult == ERR_OK) { //mission win?
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
+ if (m_winDelay == 0) m_winDelay = m_endTakeWinDelay;
+ m_lostDelay = 0.0f;
+ m_displayText->SetEnable(false);
+ }
+ if (m_missionResult == ERR_MISSION_NOTERM) m_displayText->SetEnable(true);
+ return m_missionResult;
+ }
+
CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
for (int t = 0; t < m_endTakeTotal; t++)
@@ -6562,6 +7018,15 @@ Error CRobotMain::CheckEndMission(bool frame)
if (type != m_endTake[t].type) continue;
+ float energyLevel = -1;
+ CObject* power = obj->GetPower();
+ if (power != nullptr)
+ {
+ energyLevel = power->GetEnergy();
+ if (power->GetType() == OBJECT_ATOMIC) energyLevel *= 100;
+ }
+ if (energyLevel < m_endTake[t].powermin || energyLevel > m_endTake[t].powermax) continue;
+
if (obj->GetTruck() == 0)
oPos = obj->GetPosition(0);
else
@@ -6598,7 +7063,8 @@ Error CRobotMain::CheckEndMission(bool frame)
}
}
if (nb < m_endTake[t].min ||
- nb > m_endTake[t].max)
+ nb > m_endTake[t].max ||
+ m_endTakeNever )
{
m_displayText->SetEnable(true);
return ERR_MISSION_NOTERM;
@@ -6781,10 +7247,10 @@ bool CRobotMain::GetRadar()
for (int i = 0; i < 1000000; i++)
{
CObject* obj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
- if (obj == 0) break;
+ if (obj == nullptr) break;
ObjectType type = obj->GetType();
- if (type == OBJECT_RADAR)
+ if (type == OBJECT_RADAR && !obj->GetLock())
return true;
}
return false;
@@ -6813,15 +7279,15 @@ bool CRobotMain::GetRetroMode()
//! Change the player's name
void CRobotMain::SetGamerName(const char *name)
{
- strcpy(m_gamerName, name);
+ m_gamerName = std::string(name);
SetGlobalGamerName(m_gamerName);
ReadFreeParam();
}
-//! Getes the player's name
+//! Gets the player's name
char* CRobotMain::GetGamerName()
{
- return m_gamerName;
+ return const_cast<char*>(m_gamerName.c_str());
}
@@ -7025,7 +7491,8 @@ float CRobotMain::GetTracePrecision()
//! Starts music with a mission
void CRobotMain::StartMusic()
{
- if (m_audioTrack != 0)
+ CLogger::GetInstancePointer()->Debug("Starting music...\n");
+ if (m_audioTrack != "")
{
m_sound->StopMusic();
m_sound->PlayMusic(m_audioTrack, m_audioRepeat);
@@ -7038,3 +7505,18 @@ void CRobotMain::ClearInterface()
HiliteClear(); // removes setting evidence
m_tooltipName[0] = 0; // really removes the tooltip
}
+
+void CRobotMain::SetNumericLocale()
+{
+ char *locale = setlocale(LC_NUMERIC, nullptr);
+ if (locale != nullptr)
+ m_oldLocale = locale;
+
+ setlocale(LC_NUMERIC, "C");
+}
+
+void CRobotMain::RestoreNumericLocale()
+{
+ setlocale(LC_NUMERIC, m_oldLocale.c_str());
+}
+
diff --git a/src/object/robotmain.h b/src/object/robotmain.h
index fe5fbd5..525e5df 100644
--- a/src/object/robotmain.h
+++ b/src/object/robotmain.h
@@ -99,13 +99,29 @@ struct EndTake
Math::Vector pos;
float dist;
ObjectType type;
- int min; // wins if>
+ int min; // wins if >
int max; // wins if <
int lost; // lost if <=
+ float powermin; // wins if energy cell >=
+ float powermax; // wins if energy cell <=
bool immediat;
char message[100];
};
+struct AudioChange
+{
+ Math::Vector pos;
+ float dist;
+ ObjectType type;
+ int min; // change if >
+ int max; // change if <
+ float powermin; // change if energy cell >=
+ float powermax; // change if energy cell <=
+ char music[100];
+ bool repeat;
+ bool changed;
+};
+
const int MAXNEWSCRIPTNAME = 20;
@@ -175,14 +191,17 @@ const int AXIS_INVALID = -1;
class CRobotMain : public CSingleton<CRobotMain>
{
public:
- CRobotMain(CApplication* app);
- ~CRobotMain();
+ CRobotMain(CApplication* app, bool loadProfile);
+ virtual ~CRobotMain();
Gfx::CCamera* GetCamera();
Gfx::CTerrain* GetTerrain();
Ui::CInterface* GetInterface();
Ui::CDisplayText* GetDisplayText();
+ //! Caused the given mission to be loaded immediately after start
+ void LoadSceneOnStart(const std::string& name, int rank);
+
void CreateIni();
//! Sets the default input bindings (key and axes)
@@ -210,7 +229,7 @@ public:
void ResetKeyStates();
void ChangePhase(Phase phase);
- bool EventProcess(Event &event);
+ bool ProcessEvent(Event &event);
bool CreateShortcuts();
void ScenePerso();
@@ -248,6 +267,8 @@ public:
void ResetObject();
void ResetCreate();
+ void UpdateAudio(bool frame);
+ void SetEndMission(Error result, float delay);
Error CheckEndMission(bool frame);
void CheckEndMessage(const char* message);
int GetObligatoryToken();
@@ -353,6 +374,11 @@ public:
int CreateSpot(Math::Vector pos, Gfx::Color color);
+ void SetNumericLocale();
+ void RestoreNumericLocale();
+
+ CObject* GetSelect();
+
protected:
bool EventFrame(const Event &event);
bool EventObject(const Event &event);
@@ -383,7 +409,6 @@ protected:
void DeleteAllObjects();
void UpdateInfoText();
CObject* SearchObject(ObjectType type);
- CObject* GetSelect();
void StartDisplayVisit(EventType event);
void FrameVisit(float rTime);
void StopDisplayVisit();
@@ -391,6 +416,7 @@ protected:
bool TestGadgetQuantity(int rank);
void UpdateSpeedLabel();
+
protected:
CApplication* m_app;
CEventQueue* m_eventQueue;
@@ -444,10 +470,12 @@ protected:
bool m_cheatRadar;
bool m_audioRepeat;
bool m_shortCut;
- int m_audioTrack;
+ std::string m_audioTrack;
int m_delayWriteMessage;
int m_movieInfoIndex;
+ CObject* m_controller;
+
//Level Checker flags
bool m_beginObject;
bool m_terrainGenerate;
@@ -516,19 +544,25 @@ protected:
int m_endTakeTotal;
EndTake m_endTake[10];
long m_endTakeResearch;
+ bool m_endTakeNever;
float m_endTakeWinDelay;
float m_endTakeLostDelay;
+ int m_audioChangeTotal;
+ AudioChange m_audioChange[10];
+
int m_obligatoryTotal;
char m_obligatoryToken[100][20];
int m_prohibitedTotal;
char m_prohibitedToken[100][20];
- char m_gamerName[100];
+ std::string m_gamerName;
int m_freeBuild; // constructible buildings
int m_freeResearch; // researches possible
+ Error m_missionResult;
+
ShowLimit m_showLimit[MAXSHOWLIMIT];
Gfx::Color m_colorRefBot;
@@ -540,5 +574,7 @@ protected:
Gfx::Color m_colorRefWater;
Gfx::Color m_colorNewWater;
float m_colorShiftWater;
+
+ std::string m_oldLocale;
};
diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp
index 39fdccf..5ec6f8a 100644
--- a/src/object/task/task.cpp
+++ b/src/object/task/task.cpp
@@ -81,4 +81,3 @@ bool CTask::Abort()
return true;
}
-
diff --git a/src/object/task/task.h b/src/object/task/task.h
index 12961ef..41b3d3b 100644
--- a/src/object/task/task.h
+++ b/src/object/task/task.h
@@ -34,7 +34,7 @@ class CSoundInterface;
namespace Ui {
class CDisplayText;
-} /* Ui */
+} /* Ui */
namespace Gfx {
class CEngine;
@@ -43,7 +43,7 @@ class CParticle;
class CTerrain;
class CWater;
class CCamera;
-} /* Gfx */
+} /* Gfx */
const float TAKE_DIST = 6.0f; // distance to an object to pick it
diff --git a/src/object/task/taskadvance.cpp b/src/object/task/taskadvance.cpp
index 58eb939..885e100 100644
--- a/src/object/task/taskadvance.cpp
+++ b/src/object/task/taskadvance.cpp
@@ -139,4 +139,3 @@ Error CTaskAdvance::IsEnded()
return ERR_CONTINUE;
}
-
diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp
index b9af475..39479a6 100644
--- a/src/object/task/taskbuild.cpp
+++ b/src/object/task/taskbuild.cpp
@@ -557,7 +557,7 @@ Error CTaskBuild::FlatFloor()
ObjectType type;
Math::Vector center, pos, oPos, bPos;
Math::Point c, p;
- float radius, max, oRadius, bRadius, angle, dist;
+ float radius, max, oRadius, bRadius = 0.0f, angle, dist;
int i, j;
bool bLittleFlat, bBase;
diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp
index c4a2939..01ff38b 100644
--- a/src/object/task/taskgoto.cpp
+++ b/src/object/task/taskgoto.cpp
@@ -90,8 +90,11 @@ bool CTaskGoto::EventProcess(const Event &event)
rot.x = m_leakPos.x-pos.x;
rot.y = m_leakPos.z-pos.z;
dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
+ if (dist != 0)
+ {
+ rot.x /= dist;
+ rot.y /= dist;
+ }
a = m_object->GetAngleY(0);
g = Math::RotateAngle(rot.x, -rot.y); // CW !
@@ -754,7 +757,7 @@ Error CTaskGoto::Start(Math::Vector goal, float altitude,
Error CTaskGoto::IsEnded()
{
Math::Vector pos;
- float limit, angle, dist, h, level;
+ float limit, angle = 0.0f, dist, h, level;
if ( m_engine->GetPause() ) return ERR_CONTINUE;
if ( m_error != ERR_OK ) return m_error;
@@ -1308,16 +1311,6 @@ bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
return true;
}
- if ( type == OBJECT_DESTROYER )
- {
- mat = pObj->GetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
if ( type == OBJECT_PARA && m_physics->GetType() == TYPE_FLYING )
{
mat = pObj->GetWorldMatrix(0);
@@ -1336,7 +1329,7 @@ bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay)
{
- CObject *pObj, *pObstacle;
+ CObject *pObj, *pObstacle = nullptr;
Math::Vector iPos, oPos, bPos;
float iRadius, oRadius, bRadius, dist, min, dir;
int i, j;
@@ -1453,7 +1446,7 @@ void CTaskGoto::ComputeRepulse(Math::Point &dir)
// The worm goes everywhere and through everything!
iType = m_object->GetType();
- if ( iType == OBJECT_WORM ) return;
+ if ( iType == OBJECT_WORM || iType == OBJECT_CONTROLLER ) return;
m_object->GetCrashSphere(0, iPos, iRadius);
gDist = Math::Distance(iPos, m_goal);
@@ -2239,4 +2232,3 @@ bool CTaskGoto::BitmapTestDot(int rank, int x, int y)
return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8);
}
-
diff --git a/src/object/task/taskmanager.cpp b/src/object/task/taskmanager.cpp
index a2ce8b8..11fba6c 100644
--- a/src/object/task/taskmanager.cpp
+++ b/src/object/task/taskmanager.cpp
@@ -271,4 +271,3 @@ bool CTaskManager::Abort()
return m_task->Abort();
}
-
diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp
index b219185..974a53d 100644
--- a/src/object/task/tasksearch.cpp
+++ b/src/object/task/tasksearch.cpp
@@ -218,6 +218,13 @@ Error CTaskSearch::IsEnded()
bool CTaskSearch::Abort()
{
+ m_hand = TSH_UP;
+ InitAngle();
+ for (int i = 0; i < 3; i++)
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+
m_camera->StopCentering(m_object, 2.0f);
m_physics->SetFreeze(false); // is moving again
return true;
@@ -319,4 +326,3 @@ void CTaskSearch::DeleteMark(ObjectType type)
}
}
-
diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp
index 929dd5c..fe6eaeb 100644
--- a/src/object/task/taskshield.cpp
+++ b/src/object/task/taskshield.cpp
@@ -552,5 +552,3 @@ float CTaskShield::GetRadius()
return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->GetParam();
}
-
-
diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp
index 0037f85..c7f0530 100644
--- a/src/object/task/tasktake.cpp
+++ b/src/object/task/tasktake.cpp
@@ -598,4 +598,3 @@ bool CTaskTake::IsFreeDeposeObject(Math::Vector pos)
return true; // location free
}
-
diff --git a/src/object/task/taskturn.cpp b/src/object/task/taskturn.cpp
index 7a924cb..bf9d593 100644
--- a/src/object/task/taskturn.cpp
+++ b/src/object/task/taskturn.cpp
@@ -126,4 +126,3 @@ Error CTaskTurn::IsEnded()
return ERR_CONTINUE;
}
-
diff --git a/src/object/task/taskwait.cpp b/src/object/task/taskwait.cpp
index 3e201e0..5b9fdb3 100644
--- a/src/object/task/taskwait.cpp
+++ b/src/object/task/taskwait.cpp
@@ -64,4 +64,3 @@ Error CTaskWait::IsEnded()
return ERR_CONTINUE;
}
-
diff --git a/src/physics/README.txt b/src/physics/README.txt
index c068d4d..dd74709 100644
--- a/src/physics/README.txt
+++ b/src/physics/README.txt
@@ -2,3 +2,4 @@
* \dir src/physics
* \brief Physics engine
*/
+
diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp
index 6311ecf..2c5f95e 100644
--- a/src/physics/physics.cpp
+++ b/src/physics/physics.cpp
@@ -794,7 +794,8 @@ void CPhysics::MotorUpdate(float aTime, float rTime)
type == OBJECT_BEE ||
type == OBJECT_WORM ||
type == OBJECT_APOLLO2 ||
- type == OBJECT_MOBILEdr )
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_CONTROLLER)
{
power = 0;
}
@@ -1916,7 +1917,7 @@ void CPhysics::SoundMotorFull(float rTime, ObjectType type)
if ( m_object->GetToy() )
{
- sound = SOUND_MOTORd;
+ sound = SOUND_NONE; //SOUND_MOTORd;
amplitude = 1.0f;
time = 0.1f;
}
@@ -2015,7 +2016,7 @@ void CPhysics::SoundMotorSlow(float rTime, ObjectType type)
if ( m_object->GetToy() )
{
- sound = SOUND_MOTORd;
+ sound = SOUND_NONE; // SOUND_MOTORd;
amplitude = 0.0f;
}
diff --git a/src/physics/physics.h b/src/physics/physics.h
index cce57f3..834d7b8 100644
--- a/src/physics/physics.h
+++ b/src/physics/physics.h
@@ -250,4 +250,3 @@ protected:
bool m_bLowLevel;
};
-
diff --git a/src/script/cbottoken.cpp b/src/script/cbottoken.cpp
index 95b259b..505228e 100644
--- a/src/script/cbottoken.cpp
+++ b/src/script/cbottoken.cpp
@@ -220,7 +220,6 @@ std::string GetHelpFilename(const char *token)
{
if ( strcmp(token, "if" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/if.txt");
if ( strcmp(token, "else" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/if.txt");
- if ( strcmp(token, "repeat" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/repeat.txt");
if ( strcmp(token, "for" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/for.txt");
if ( strcmp(token, "while" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/while.txt");
if ( strcmp(token, "do" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/do.txt");
@@ -250,7 +249,15 @@ std::string GetHelpFilename(const char *token)
if ( strcmp(token, "pow" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/expr.txt");
if ( strcmp(token, "rand" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/expr.txt");
if ( strcmp(token, "abs" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/expr.txt");
+ if ( strcmp(token, "getbuild" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/getbuild.txt");
+ if ( strcmp(token, "getresearchenable" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/getresen.txt");
+ if ( strcmp(token, "getresearchdone" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/getresdo.txt");
if ( strcmp(token, "retobject" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/retobj.txt");
+ if ( strcmp(token, "progfunc" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/factory.txt");
+ if ( strcmp(token, "busy" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/busy.txt");
+ if ( strcmp(token, "factory" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/factory.txt");
+ if ( strcmp(token, "research" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/research.txt");
+ if ( strcmp(token, "destroy" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/destroy.txt");
if ( strcmp(token, "search" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/search.txt");
if ( strcmp(token, "radar" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/radar.txt");
if ( strcmp(token, "direction" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/direct.txt");
@@ -262,8 +269,9 @@ std::string GetHelpFilename(const char *token)
if ( strcmp(token, "move" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/move.txt");
if ( strcmp(token, "turn" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/turn.txt");
if ( strcmp(token, "goto" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/goto.txt");
- if ( strcmp(token, "find" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/find.txt");
if ( strcmp(token, "grab" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/grab.txt");
+ if ( strcmp(token, "canbuild" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/canbuild.txt");
+ if ( strcmp(token, "build" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/build.txt");
if ( strcmp(token, "drop" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/drop.txt");
if ( strcmp(token, "sniff" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/sniff.txt");
if ( strcmp(token, "receive" ) == 0 ) return std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + std::string("/cbot/receive.txt");
@@ -367,7 +375,16 @@ bool IsFunction(const char *token)
if ( strcmp(token, "pow" ) == 0 ) return true;
if ( strcmp(token, "rand" ) == 0 ) return true;
if ( strcmp(token, "abs" ) == 0 ) return true;
+ if ( strcmp(token, "getbuild" ) == 0 ) return true;
+ if ( strcmp(token, "getresearchenable" ) == 0 ) return true;
+ if ( strcmp(token, "getresearchdone" ) == 0 ) return true;
+ if ( strcmp(token, "retobjectbyid") == 0 ) return true;
if ( strcmp(token, "retobject" ) == 0 ) return true;
+ if ( strcmp(token, "progfunc" ) == 0 ) return true;
+ if ( strcmp(token, "busy" ) == 0 ) return true;
+ if ( strcmp(token, "factory" ) == 0 ) return true;
+ if ( strcmp(token, "research" ) == 0 ) return true;
+ if ( strcmp(token, "destroy" ) == 0 ) return true;
if ( strcmp(token, "search" ) == 0 ) return true;
if ( strcmp(token, "radar" ) == 0 ) return true;
if ( strcmp(token, "detect" ) == 0 ) return true;
@@ -380,8 +397,9 @@ bool IsFunction(const char *token)
if ( strcmp(token, "move" ) == 0 ) return true;
if ( strcmp(token, "turn" ) == 0 ) return true;
if ( strcmp(token, "goto" ) == 0 ) return true;
- if ( strcmp(token, "find" ) == 0 ) return true;
if ( strcmp(token, "grab" ) == 0 ) return true;
+ if ( strcmp(token, "canbuild" ) == 0 ) return true;
+ if ( strcmp(token, "build" ) == 0 ) return true;
if ( strcmp(token, "drop" ) == 0 ) return true;
if ( strcmp(token, "sniff" ) == 0 ) return true;
if ( strcmp(token, "receive" ) == 0 ) return true;
@@ -432,7 +450,6 @@ const char* GetHelpText(const char *token)
{
if ( strcmp(token, "if" ) == 0 ) return "if ( condition ) { bloc }";
if ( strcmp(token, "else" ) == 0 ) return "else { bloc }";
- if ( strcmp(token, "repeat" ) == 0 ) return "repeat ( number )";
if ( strcmp(token, "for" ) == 0 ) return "for ( before ; condition ; end )";
if ( strcmp(token, "while" ) == 0 ) return "while ( condition ) { bloc }";
if ( strcmp(token, "do" ) == 0 ) return "do { bloc } while ( condition );";
@@ -451,7 +468,16 @@ const char* GetHelpText(const char *token)
if ( strcmp(token, "pow" ) == 0 ) return "pow ( x, y );";
if ( strcmp(token, "rand" ) == 0 ) return "rand ( );";
if ( strcmp(token, "abs" ) == 0 ) return "abs ( value );";
- if ( strcmp(token, "retobject" ) == 0 ) return "retobject ( );";
+ if ( strcmp(token, "getbuild" ) == 0 ) return "getbuild ( );";
+ if ( strcmp(token, "getresearchenable" ) == 0 ) return "getresearchenable ( );";
+ if ( strcmp(token, "getresearchdone" ) == 0 ) return "getresearchdone ( );";
+ if ( strcmp(token, "retobject" ) == 0 ) return "retobject ( rank );";
+ if ( strcmp(token, "retobjectbyid") == 0 ) return "retobjectbyid ( rank );";
+ if ( strcmp(token, "progfunc" ) == 0 ) return "progfunc ( funcname );";
+ if ( strcmp(token, "busy" ) == 0 ) return "object.busy ( );";
+ if ( strcmp(token, "factory" ) == 0 ) return "object.factory ( cat, program );";
+ if ( strcmp(token, "research" ) == 0 ) return "object.research ( type );";
+ if ( strcmp(token, "destroy" ) == 0 ) return "object.destroy ( );";
if ( strcmp(token, "search" ) == 0 ) return "search ( );";
if ( strcmp(token, "radar" ) == 0 ) return "radar ( cat, angle, focus, min, max, sens );";
if ( strcmp(token, "detect" ) == 0 ) return "detect ( cat );";
@@ -464,8 +490,9 @@ const char* GetHelpText(const char *token)
if ( strcmp(token, "move" ) == 0 ) return "move ( distance );";
if ( strcmp(token, "turn" ) == 0 ) return "turn ( angle );";
if ( strcmp(token, "goto" ) == 0 ) return "goto ( position, altitude );";
- if ( strcmp(token, "find" ) == 0 ) return "find ( cat );";
if ( strcmp(token, "grab" ) == 0 ) return "grab ( order );";
+ if ( strcmp(token, "canbuild" ) == 0 ) return "canbuild ( category );";
+ if ( strcmp(token, "build" ) == 0 ) return "build ( category );";
if ( strcmp(token, "drop" ) == 0 ) return "drop ( order );";
if ( strcmp(token, "sniff" ) == 0 ) return "sniff ( );";
if ( strcmp(token, "receive" ) == 0 ) return "receive ( name, power );";
@@ -508,4 +535,3 @@ const char* GetHelpText(const char *token)
return "";
}
-
diff --git a/src/script/cbottoken.h b/src/script/cbottoken.h
index bc53f77..976d856 100644
--- a/src/script/cbottoken.h
+++ b/src/script/cbottoken.h
@@ -36,4 +36,3 @@ extern bool IsType(const char *token);
extern bool IsFunction(const char *token);
extern const char* GetHelpText(const char *token);
-
diff --git a/src/script/cmdtoken.cpp b/src/script/cmdtoken.cpp
index ab0528b..69df68b 100644
--- a/src/script/cmdtoken.cpp
+++ b/src/script/cmdtoken.cpp
@@ -401,6 +401,7 @@ ObjectType GetTypeObject(char *line, int rank, ObjectType def)
if ( Cmd(p, "ApolloAntenna" ) ) return OBJECT_APOLLO5;
if ( Cmd(p, "Me" ) ) return OBJECT_HUMAN;
if ( Cmd(p, "Tech" ) ) return OBJECT_TECH;
+ if ( Cmd(p, "MissionController" ) ) return OBJECT_CONTROLLER;
return def;
}
@@ -647,6 +648,7 @@ const char* GetTypeObject(ObjectType type)
if ( type == OBJECT_APOLLO5 ) return "ApolloAntenna";
if ( type == OBJECT_HUMAN ) return "Me";
if ( type == OBJECT_TECH ) return "Tech";
+ if ( type == OBJECT_CONTROLLER ) return "MissionController";
return "";
}
@@ -945,4 +947,3 @@ Gfx::Color OpColor(char *line, const char *op, Gfx::Color def)
return color;
}
-
diff --git a/src/script/dd.cpp b/src/script/dd.cpp
index 4110813..a7f5eb9 100644
--- a/src/script/dd.cpp
+++ b/src/script/dd.cpp
@@ -173,3 +173,4 @@ bool rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
}
return true;
}
+
diff --git a/src/script/script.cpp b/src/script/script.cpp
index d5fe2ce..b03702c 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -33,11 +33,17 @@
#include "object/object.h"
#include "object/robotmain.h"
#include "object/task/taskmanager.h"
+#include "object/objman.h"
+
+#include "object/auto/auto.h"
+#include "object/auto/autofactory.h"
#include "physics/physics.h"
#include "script/cbottoken.h"
+#include "sound/sound.h"
+
#include "ui/interface.h"
#include "ui/edit.h"
#include "ui/list.h"
@@ -64,6 +70,11 @@ CBotTypResult CScript::cNull(CBotVar* &var, void* user)
return CBotTypResult(CBotTypFloat);
}
+CBotTypResult CScript::cClassNull(CBotVar* thisclass, CBotVar* &var)
+{
+ return CScript::cNull(var, nullptr);
+}
+
// Compiling a procedure with a single real number.
CBotTypResult CScript::cOneFloat(CBotVar* &var, void* user)
@@ -75,6 +86,11 @@ CBotTypResult CScript::cOneFloat(CBotVar* &var, void* user)
return CBotTypResult(CBotTypFloat);
}
+CBotTypResult CScript::cClassOneFloat(CBotVar* thisclass, CBotVar* &var)
+{
+ return CScript::cOneFloat(var, nullptr);
+}
+
// Compiling a procedure with two real numbers.
CBotTypResult CScript::cTwoFloat(CBotVar* &var, void* user)
@@ -144,6 +160,18 @@ CBotTypResult CScript::cString(CBotVar* &var, void* user)
return CBotTypResult(CBotTypFloat);
}
+// Compiling a procedure with a single string, returning string.
+
+CBotTypResult CScript::cStringString(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() != CBotTypString &&
+ var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypString);
+}
+
// Seeking value in an array of integers.
@@ -312,6 +340,127 @@ bool CScript::rAbs(CBotVar* var, CBotVar* result, int& exception, void* user)
return true;
}
+// Compilation of the instruction "endmission(result, delay)"
+
+CBotTypResult CScript::cEndMission(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "endmission(result, delay)"
+
+bool CScript::rEndMission(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ Error ended;
+ float delay;
+
+ ended = static_cast<Error>(var->GetValFloat());
+ var = var->GetNext();
+
+ delay = var->GetValFloat();
+
+ CRobotMain::GetInstancePointer()->SetEndMission(ended, delay);
+ return true;
+}
+
+// Compilation of the instruction "playmusic(filename, repeat)"
+
+CBotTypResult CScript::cPlayMusic(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "playmusic(filename, repeat)"
+
+bool CScript::rPlayMusic(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ std::string filename;
+ CBotString cbs;
+ bool repeat;
+
+ cbs = var->GetValString();
+ filename = std::string(cbs);
+ var = var->GetNext();
+
+ repeat = var->GetValInt();
+
+ CApplication::GetInstancePointer()->GetSound()->StopMusic();
+ CApplication::GetInstancePointer()->GetSound()->PlayMusic(filename, repeat);
+ return true;
+}
+
+// Instruction "stopmusic()"
+
+bool CScript::rStopMusic(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CApplication::GetInstancePointer()->GetSound()->StopMusic();
+ return true;
+}
+
+// Instruction "getbuild()"
+
+bool CScript::rGetBuild(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ result->SetValInt(g_build);
+ return true;
+}
+
+// Instruction "getresearchenable()"
+
+bool CScript::rGetResearchEnable(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ result->SetValInt(g_researchEnable);
+ return true;
+}
+
+// Instruction "getresearchdone()"
+
+bool CScript::rGetResearchDone(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ result->SetValInt(g_researchDone);
+ return true;
+}
+
+// Instruction "setbuild()"
+
+bool CScript::rSetBuild(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ g_build = var->GetValInt();
+ CApplication::GetInstancePointer()->GetEventQueue()->AddEvent(Event(EVENT_UPDINTERFACE));
+ return true;
+}
+
+// Instruction "setresearchenable()"
+
+bool CScript::rSetResearchEnable(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ g_researchEnable = var->GetValInt();
+ CApplication::GetInstancePointer()->GetEventQueue()->AddEvent(Event(EVENT_UPDINTERFACE));
+ return true;
+}
+
+// Instruction "setresearchdone()"
+
+bool CScript::rSetResearchDone(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ g_researchDone = var->GetValInt();
+ CApplication::GetInstancePointer()->GetEventQueue()->AddEvent(Event(EVENT_UPDINTERFACE));
+ return true;
+}
// Compilation of the instruction "retobject(rank)".
@@ -325,19 +474,37 @@ CBotTypResult CScript::cGetObject(CBotVar* &var, void* user)
return CBotTypResult(CBotTypPointer, "object");
}
+// Instruction "retobjectbyid(rank)".
+
+bool CScript::rGetObjectById(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CObject* pObj;
+ int rank;
+
+ rank = var->GetValInt();
+
+ pObj = static_cast<CObject*>(CObjectManager::GetInstancePointer()->SearchInstance(rank));
+ if ( pObj == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pObj->GetBotVar());
+ }
+ return true;
+}
+
// Instruction "retobject(rank)".
bool CScript::rGetObject(CBotVar* var, CBotVar* result, int& exception, void* user)
{
- CScript* script = (static_cast<CObject*>(user))->GetRunScript();
CObject* pObj;
int rank;
rank = var->GetValInt();
- CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
-
- pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, rank));
+ pObj = static_cast<CObject*>(CInstanceManager::GetInstancePointer()->SearchInstance(CLASS_OBJECT, rank));
if ( pObj == 0 )
{
result->SetPointer(0);
@@ -350,6 +517,457 @@ bool CScript::rGetObject(CBotVar* var, CBotVar* result, int& exception, void* us
}
+// Instruction "progfunc(funcname)".
+
+bool CScript::rProgFunc(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CBotString cbs;
+ const char* funcname;
+ std::string program;
+
+ cbs = var->GetValString();
+ funcname = cbs;
+
+ //TODO: Translation :)
+ program = "extern void object::Auto()\n{\n\t\n\t//Automatically generated by progfunc(\"";
+ program += funcname;
+ program += "\");\n\t";
+ program += funcname;
+ program += "();\n\t\n}\n";
+
+ result->SetValString(program.c_str());
+
+ return true;
+}
+
+// Compilation of instruction "object.busy()"
+CBotTypResult CScript::cBusy(CBotVar* thisclass, CBotVar* &var)
+{
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypBoolean);
+}
+
+// Instruction "object.busy()"
+
+bool CScript::rBusy(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception)
+{
+ exception = 0;
+
+ CBotVar* classVars = thisclass->GetItemList(); // "category"
+ classVars = classVars->GetNext(); // "position"
+ classVars = classVars->GetNext(); // "orientation"
+ classVars = classVars->GetNext(); // "pitch"
+ classVars = classVars->GetNext(); // "roll"
+ classVars = classVars->GetNext(); // "energyLevel"
+ classVars = classVars->GetNext(); // "shieldLevel"
+ classVars = classVars->GetNext(); // "temperature"
+ classVars = classVars->GetNext(); // "altitude"
+ classVars = classVars->GetNext(); // "lifeTime"
+ classVars = classVars->GetNext(); // "material"
+ classVars = classVars->GetNext(); // "energyCell"
+ classVars = classVars->GetNext(); // "load"
+ classVars = classVars->GetNext(); // "id"
+ int rank = classVars->GetValInt();
+ CObject* obj = CObjectManager::GetInstancePointer()->SearchInstance(rank);
+ CAuto* automat = obj->GetAuto();
+
+ if ( automat != nullptr )
+ result->SetValInt(automat->GetBusy());
+ else
+ exception = ERR_WRONG_OBJ;
+
+ return true;
+}
+
+bool CScript::rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception)
+{
+ exception = 0;
+ Error err;
+
+ CBotVar* classVars = thisclass->GetItemList(); // "category"
+ ObjectType thisType = static_cast<ObjectType>(classVars->GetValInt());
+ classVars = classVars->GetNext(); // "position"
+ classVars = classVars->GetNext(); // "orientation"
+ classVars = classVars->GetNext(); // "pitch"
+ classVars = classVars->GetNext(); // "roll"
+ classVars = classVars->GetNext(); // "energyLevel"
+ classVars = classVars->GetNext(); // "shieldLevel"
+ classVars = classVars->GetNext(); // "temperature"
+ classVars = classVars->GetNext(); // "altitude"
+ classVars = classVars->GetNext(); // "lifeTime"
+ classVars = classVars->GetNext(); // "material"
+ classVars = classVars->GetNext(); // "energyCell"
+ classVars = classVars->GetNext(); // "load"
+ classVars = classVars->GetNext(); // "id"
+ int rank = classVars->GetValInt();
+ CObject* obj = CObjectManager::GetInstancePointer()->SearchInstance(rank);
+ CAuto* automat = obj->GetAuto();
+
+ if ( thisType == OBJECT_DESTROYER )
+ {
+ err = automat->StartAction(0);
+ } else
+ err = ERR_WRONG_OBJ;
+
+ if ( err != ERR_OK )
+ {
+ result->SetValInt(err); // return error
+//TODO: if ( script->m_errMode == ERM_STOP )
+ if( true )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+
+ return true;
+}
+
+
+// Compilation of instruction "object.factory(cat, program)"
+
+CBotTypResult CScript::cFactory(CBotVar* thisclass, CBotVar* &var)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var != 0 )
+ {
+ if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ }
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "object.factory(cat, program)"
+
+bool CScript::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception)
+{
+ Error err;
+
+ exception = 0;
+
+ ObjectType type = static_cast<ObjectType>(var->GetValInt());
+ var = var->GetNext();
+ CBotString cbs;
+ const char* program;
+ if ( var != 0 )
+ {
+ cbs = var->GetValString();
+ program = cbs;
+ }
+ else
+ program = "";
+
+ CBotVar* classVars = thisclass->GetItemList(); // "category"
+ ObjectType thisType = static_cast<ObjectType>(classVars->GetValInt());
+ classVars = classVars->GetNext(); // "position"
+ classVars = classVars->GetNext(); // "orientation"
+ classVars = classVars->GetNext(); // "pitch"
+ classVars = classVars->GetNext(); // "roll"
+ classVars = classVars->GetNext(); // "energyLevel"
+ classVars = classVars->GetNext(); // "shieldLevel"
+ classVars = classVars->GetNext(); // "temperature"
+ classVars = classVars->GetNext(); // "altitude"
+ classVars = classVars->GetNext(); // "lifeTime"
+ classVars = classVars->GetNext(); // "material"
+ classVars = classVars->GetNext(); // "energyCell"
+ classVars = classVars->GetNext(); // "load"
+ classVars = classVars->GetNext(); // "id"
+ int rank = classVars->GetValInt();
+ CObject* factory = CObjectManager::GetInstancePointer()->SearchInstance(rank);
+ CAutoFactory* automat = static_cast<CAutoFactory*>(factory->GetAuto());
+
+ if ( thisType == OBJECT_FACTORY )
+ {
+ bool bEnable = false;
+
+ if ( type == OBJECT_MOBILEwa )
+ {
+ bEnable = true;
+ }
+ if ( type == OBJECT_MOBILEta )
+ {
+ bEnable = g_researchDone&RESEARCH_TANK;
+ }
+ if ( type == OBJECT_MOBILEfa )
+ {
+ bEnable = g_researchDone&RESEARCH_FLY;
+ }
+ if ( type == OBJECT_MOBILEia )
+ {
+ bEnable = g_researchDone&RESEARCH_iPAW;
+ }
+
+ if ( type == OBJECT_MOBILEws )
+ {
+ bEnable = g_researchDone&RESEARCH_SNIFFER;
+ }
+ if ( type == OBJECT_MOBILEts )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( type == OBJECT_MOBILEfs )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( type == OBJECT_MOBILEis )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( type == OBJECT_MOBILEwc )
+ {
+ bEnable = g_researchDone&RESEARCH_CANON;
+ }
+ if ( type == OBJECT_MOBILEtc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( type == OBJECT_MOBILEfc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( type == OBJECT_MOBILEic )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( type == OBJECT_MOBILEwi )
+ {
+ bEnable = g_researchDone&RESEARCH_iGUN;
+ }
+ if ( type == OBJECT_MOBILEti )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( type == OBJECT_MOBILEfi )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( type == OBJECT_MOBILEii )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( type == OBJECT_MOBILErt )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_THUMP) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( type == OBJECT_MOBILErc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_PHAZER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( type == OBJECT_MOBILErr )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_RECYCLER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( type == OBJECT_MOBILErs )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SHIELD) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ bEnable = g_researchDone&RESEARCH_SUBM;
+ }
+
+ if ( bEnable )
+ {
+ if ( automat != nullptr )
+ {
+ err = automat->StartAction(type);
+ if ( err == ERR_OK ) automat->SetProgram(program);
+ }
+ else
+ err = ERR_GENERIC;
+ }
+ else
+ err = ERR_BUILD_DISABLED;
+ }
+ else
+ err = ERR_WRONG_OBJ;
+
+ if ( err != ERR_OK )
+ {
+ result->SetValInt(err); // return error
+//TODO: if ( script->m_errMode == ERM_STOP )
+ if( true )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+
+ return true;
+}
+
+// Instruction "object.research(type)"
+
+bool CScript::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception)
+{
+ Error err;
+
+ exception = 0;
+
+ ResearchType type = static_cast<ResearchType>(var->GetValInt());
+
+ CBotVar* classVars = thisclass->GetItemList(); // "category"
+ ObjectType thisType = static_cast<ObjectType>(classVars->GetValInt());
+ classVars = classVars->GetNext(); // "position"
+ classVars = classVars->GetNext(); // "orientation"
+ classVars = classVars->GetNext(); // "pitch"
+ classVars = classVars->GetNext(); // "roll"
+ classVars = classVars->GetNext(); // "energyLevel"
+ classVars = classVars->GetNext(); // "shieldLevel"
+ classVars = classVars->GetNext(); // "temperature"
+ classVars = classVars->GetNext(); // "altitude"
+ classVars = classVars->GetNext(); // "lifeTime"
+ classVars = classVars->GetNext(); // "material"
+ classVars = classVars->GetNext(); // "energyCell"
+ classVars = classVars->GetNext(); // "load"
+ classVars = classVars->GetNext(); // "id"
+ int rank = classVars->GetValInt();
+ CObject* center = CObjectManager::GetInstancePointer()->SearchInstance(rank);
+ CAuto* automat = center->GetAuto();
+
+ if ( thisType == OBJECT_RESEARCH ||
+ thisType == OBJECT_LABO )
+ {
+ bool ok = false;
+ if ( type == RESEARCH_iPAW ||
+ type == RESEARCH_iGUN )
+ {
+ if ( thisType != OBJECT_LABO )
+ err = ERR_WRONG_OBJ;
+ else
+ ok = true;
+ }
+ else
+ {
+ if ( thisType != OBJECT_RESEARCH )
+ err = ERR_WRONG_OBJ;
+ else
+ ok = true;
+ }
+ if ( ok )
+ {
+ bool bEnable = ( g_researchEnable & type );
+ if ( bEnable )
+ {
+ if ( automat != nullptr )
+ {
+ err = automat->StartAction(type);
+ }
+ else
+ err = ERR_GENERIC;
+ }
+ else
+ err = ERR_BUILD_DISABLED;
+ }
+ }
+ else
+ err = ERR_WRONG_OBJ;
+
+ if ( err != ERR_OK )
+ {
+ result->SetValInt(err); // return error
+//TODO: if ( script->m_errMode == ERM_STOP )
+ if( true )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+
+ return true;
+}
+
+// Compilation of the instruction "delete(rank[, exploType[, force]])".
+
+CBotTypResult CScript::cDelete(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+
+ if ( var != 0 )
+ {
+ if ( var->GetType() != CBotTypInt ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+
+ if ( var != 0 )
+ {
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ }
+ }
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "delete(rank[, exploType[, force]])".
+
+bool CScript::rDelete(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CObject* pObj;
+ int rank;
+ int exploType = 0;
+ float force = 1.0f;
+
+ rank = var->GetValInt();
+ var->GetNext();
+ if ( var != 0 )
+ {
+ exploType = var->GetValInt();
+ var->GetNext();
+ if ( var != 0 )
+ {
+ force = var->GetValFloat();
+ }
+ }
+
+ pObj = static_cast<CObject*>(CObjectManager::GetInstancePointer()->SearchInstance(rank));
+ if ( pObj == 0 )
+ {
+ return true;
+ }
+ else
+ {
+ if ( exploType )
+ {
+ pObj->ExploObject(static_cast<ExploType>(exploType), force);
+ }
+ else
+ {
+ pObj->DeleteObject(false);
+ }
+ }
+ return true;
+}
+
+
+
// Compilation of the instruction "search(type, pos)".
CBotTypResult CScript::cSearch(CBotVar* &var, void* user)
@@ -380,7 +998,6 @@ CBotTypResult CScript::cSearch(CBotVar* &var, void* user)
bool CScript::rSearch(CBotVar* var, CBotVar* result, int& exception, void* user)
{
- CScript* script = (static_cast<CObject *>(user))->GetRunScript();
CObject *pObj, *pBest;
CBotVar* array;
Math::Vector pos, oPos;
@@ -523,7 +1140,6 @@ CBotTypResult CScript::cRadar(CBotVar* &var, void* user)
bool CScript::rRadar(CBotVar* var, CBotVar* result, int& exception, void* user)
{
- CScript* script = (static_cast<CObject *>(user))->GetRunScript();
CObject* pThis = static_cast<CObject *>(user);
CObject *pObj, *pBest;
CPhysics* physics;
@@ -532,9 +1148,10 @@ bool CScript::rRadar(CBotVar* var, CBotVar* result, int& exception, void* user)
RadarFilter filter;
float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
int type, oType, i;
- bool bArray;
+ bool bArray = false;
type = OBJECT_NULL;
+ array = 0;
angle = 0.0f;
focus = Math::PI*2.0f;
minDist = 0.0f*g_unit;
@@ -612,7 +1229,7 @@ bool CScript::rRadar(CBotVar* var, CBotVar* result, int& exception, void* user)
if ( pObj->GetProxyActivate() ) continue;
oType = pObj->GetType();
- if ( oType == OBJECT_TOTO ) continue;
+ if ( oType == OBJECT_TOTO || oType == OBJECT_CONTROLLER ) continue;
if ( oType == OBJECT_RUINmobilew2 ||
oType == OBJECT_RUINmobilet1 ||
@@ -751,7 +1368,7 @@ bool CScript::rDetect(CBotVar* var, CBotVar* result, int& exception, void* user)
RadarFilter filter;
float bGoal, best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
int type, oType, i;
- bool bArray;
+ bool bArray = false;
Error err;
exception = 0;
@@ -759,6 +1376,7 @@ bool CScript::rDetect(CBotVar* var, CBotVar* result, int& exception, void* user)
if ( script->m_primaryTask == 0 ) // no task in progress?
{
type = OBJECT_NULL;
+ array = 0;
angle = 0.0f;
focus = 45.0f*Math::PI/180.0f;
minDist = 0.0f*g_unit;
@@ -947,6 +1565,148 @@ bool CScript::rDirection(CBotVar* var, CBotVar* result, int& exception, void* us
return true;
}
+// compilation of instruction "canbuild ( category );"
+
+CBotTypResult CScript::cCanBuild(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GetNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypBoolean);
+}
+
+// Instruction "canbuid ( category );"
+// returns true if this building can be built
+
+bool CScript::rCanBuild(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ ObjectType category = static_cast<ObjectType>(var->GetValInt()); //get category parameter
+ exception = 0;
+
+ bool can = false;
+
+ if ( (category == OBJECT_DERRICK && (g_build & BUILD_DERRICK)) ||
+ (category == OBJECT_FACTORY && (g_build & BUILD_FACTORY)) ||
+ (category == OBJECT_STATION && (g_build & BUILD_STATION)) ||
+ (category == OBJECT_CONVERT && (g_build & BUILD_CONVERT)) ||
+ (category == OBJECT_REPAIR && (g_build & BUILD_REPAIR)) ||
+ (category == OBJECT_TOWER && (g_build & BUILD_TOWER)) ||
+ (category == OBJECT_RESEARCH && (g_build & BUILD_RESEARCH)) ||
+ (category == OBJECT_RADAR && (g_build & BUILD_RADAR)) ||
+ (category == OBJECT_ENERGY && (g_build & BUILD_ENERGY)) ||
+ (category == OBJECT_LABO && (g_build & BUILD_LABO)) ||
+ (category == OBJECT_NUCLEAR && (g_build & BUILD_NUCLEAR)) ||
+ (category == OBJECT_INFO && (g_build & BUILD_INFO)) ||
+ (category == OBJECT_PARA && (g_build & BUILD_PARA)) ||
+ (category == OBJECT_DESTROYER && (g_build & BUILD_DESTROYER)))
+ {
+
+ //if we want to build not researched one
+ if ( (category == OBJECT_TOWER && !(g_researchDone & RESEARCH_TOWER)) ||
+ (category == OBJECT_NUCLEAR && !(g_researchDone & RESEARCH_ATOMIC))
+ )
+ {
+ can = false;
+ }
+ else
+ {
+ can = true;
+ }
+
+ }
+
+ result->SetValInt(can);
+
+
+ return true;
+}
+
+// Instruction "build(type)"
+// draws error if can not build (wher errormode stop), otherwise 0 <- error
+
+bool CScript::rBuild(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = (static_cast<CObject *>(user))->GetRunScript();
+ CObject* pThis = static_cast<CObject *>(user);
+ ObjectType oType;
+ ObjectType category;
+ Error err = ERR_BUILD_DISABLED;
+
+ exception = 0;
+
+ oType = pThis->GetType();
+
+ if ( oType != OBJECT_MOBILEfa && // allowed only for grabber bots
+ oType != OBJECT_MOBILEta &&
+ oType != OBJECT_MOBILEwa &&
+ oType != OBJECT_MOBILEia)
+ {
+ err = ERR_MANIP_VEH; //Wrong vehicle;
+ }
+ else
+ {
+ category = static_cast<ObjectType>(var->GetValInt()); //get category parameter
+ if ( (category == OBJECT_DERRICK && (g_build & BUILD_DERRICK)) ||
+ (category == OBJECT_FACTORY && (g_build & BUILD_FACTORY)) ||
+ (category == OBJECT_STATION && (g_build & BUILD_STATION)) ||
+ (category == OBJECT_CONVERT && (g_build & BUILD_CONVERT)) ||
+ (category == OBJECT_REPAIR && (g_build & BUILD_REPAIR)) ||
+ (category == OBJECT_TOWER && (g_build & BUILD_TOWER)) ||
+ (category == OBJECT_RESEARCH && (g_build & BUILD_RESEARCH)) ||
+ (category == OBJECT_RADAR && (g_build & BUILD_RADAR)) ||
+ (category == OBJECT_ENERGY && (g_build & BUILD_ENERGY)) ||
+ (category == OBJECT_LABO && (g_build & BUILD_LABO)) ||
+ (category == OBJECT_NUCLEAR && (g_build & BUILD_NUCLEAR)) ||
+ (category == OBJECT_INFO && (g_build & BUILD_INFO)) ||
+ (category == OBJECT_PARA && (g_build & BUILD_PARA)) ||
+ (category == OBJECT_DESTROYER && (g_build & BUILD_DESTROYER)))
+ {
+
+ //if we want to build not researched one
+ if ( (category == OBJECT_TOWER && !(g_researchDone & RESEARCH_TOWER)) ||
+ (category == OBJECT_NUCLEAR && !(g_researchDone & RESEARCH_ATOMIC))
+ )
+ {
+ err = ERR_BUILD_RESEARCH;
+ }
+ else
+ {
+ err = ERR_OK;
+ }
+
+ }
+
+ if (err == ERR_OK && script->m_primaryTask == 0) //if we can build and no task is present
+ {
+ script->m_primaryTask = new CTaskManager(script->m_object);
+ err = script->m_primaryTask->StartTaskBuild(category);
+
+ if (err != ERR_OK)
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ }
+ }
+ //When script is waiting for finishing this task, it sets ERR_OK, and continues executing Process
+ //without creating new task. I think, there was a problem with previous version in release configuration
+ //It did not init error variable in this situation, and code tried to use variable with trash inside
+ }
+
+ if ( err != ERR_OK )
+ {
+ result->SetValInt(err); // return error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+
+ return Process(script, result, exception);
+
+}
// Compilation of the instruction "produce(pos, angle, type[, scriptName[, power]])"
// or "produce(type[, power])".
@@ -957,13 +1717,17 @@ CBotTypResult CScript::cProduce(CBotVar* &var, void* user)
if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GetType() <= CBotTypDouble ) {
+ if ( var->GetType() <= CBotTypDouble )
+ {
var = var->GetNext();
- if( var != 0 ) {
+ if( var != 0 )
+ {
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
}
- } else {
+ }
+ else
+ {
ret = cPoint(var, user);
if ( ret.GetType() != 0 ) return ret;
@@ -975,11 +1739,13 @@ CBotTypResult CScript::cProduce(CBotVar* &var, void* user)
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
- if ( var != 0 ) {
+ if ( var != 0 )
+ {
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
- if ( var != 0 ) {
+ if ( var != 0 )
+ {
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
}
@@ -1006,7 +1772,8 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
ObjectType type;
float power;
- if ( var->GetType() <= CBotTypDouble ) {
+ if ( var->GetType() <= CBotTypDouble )
+ {
type = static_cast<ObjectType>(var->GetValInt());
var = var->GetNext();
@@ -1021,7 +1788,9 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
power = -1.0f;
name = "";
- } else {
+ }
+ else
+ {
if ( !GetPoint(var, exception, pos) ) return true;
angle = var->GetValFloat()*Math::PI/180.0f;
@@ -1030,16 +1799,22 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
type = static_cast<ObjectType>(var->GetValInt());
var = var->GetNext();
- if ( var != 0 ) {
+ if ( var != 0 )
+ {
cbs = var->GetValString();
name = cbs;
var = var->GetNext();
- if ( var != 0 ) {
+ if ( var != 0 )
+ {
power = var->GetValFloat();
- } else {
+ }
+ else
+ {
power = -1.0f;
}
- } else {
+ }
+ else
+ {
name = "";
power = -1.0f;
}
@@ -1086,12 +1861,11 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
}
object->SetActivity(false);
}
- else
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM )
+ else if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM )
{
CObject* egg;
@@ -1110,30 +1884,29 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
}
object->SetActivity(false);
}
- else
- if ( type == OBJECT_PORTICO ||
- type == OBJECT_BASE ||
- type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_TOWER ||
- type == OBJECT_NEST ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ||
- type == OBJECT_TARGET1 ||
- type == OBJECT_TARGET2 ||
- type == OBJECT_START ||
- type == OBJECT_END )
+ else if ( type == OBJECT_PORTICO ||
+ type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_TOWER ||
+ type == OBJECT_NEST ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_TARGET2 ||
+ type == OBJECT_START ||
+ type == OBJECT_END )
{
object = new CObject();
if ( !object->CreateBuilding(pos, angle, 0, type) )
@@ -1145,12 +1918,11 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
object->SetActivity(false);
script->m_main->CreateShortcuts();
}
- else
- if ( type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv )
+ else if ( type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv )
{
object = new CObject();
if ( !object->CreateFlag(pos, angle, type) )
@@ -1161,38 +1933,37 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
}
object->SetActivity(false);
}
- else
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_TOTO ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 )
+ else if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 )
{
object = new CObject();
if ( !object->CreateVehicle(pos, angle, type, power, false, false) )
@@ -1210,7 +1981,11 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
physics->SetFreeze(false); // can move
}
object->SetLock(false); // vehicle useable
- object->SetManual(true);
+ // SetManual will affect bot speed
+ if (type == OBJECT_MOBILEdr)
+ {
+ object->SetManual(true);
+ }
object->SetActivity(true);
script->m_main->CreateShortcuts();
}
@@ -1220,8 +1995,11 @@ bool CScript::rProduce(CBotVar* var, CBotVar* result, int& exception, void* user
return true;
}
- object->ReadProgram(0, static_cast<const char*>(name));
- object->RunProgram(0);
+ if (name[0] != 0)
+ {
+ object->ReadProgram(0, static_cast<const char*>(name));
+ object->RunProgram(0);
+ }
result->SetValInt(0); // no error
return true;
@@ -1576,147 +2354,6 @@ bool CScript::rGoto(CBotVar* var, CBotVar* result, int& exception, void* user)
return Process(script, result, exception);
}
-// Instruction "find(type)".
-
-bool CScript::rFind(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = (static_cast<CObject *>(user))->GetRunScript();
- Math::Vector pos;
- TaskGotoGoal goal;
- TaskGotoCrash crash;
- float altitude;
- Error err;
- CObject* pThis = static_cast<CObject *>(user);
- CObject *pObj, *pBest;
- CBotVar* array;
- Math::Vector iPos, oPos;
- float best, minDist, maxDist, iAngle, focus, d, a;
- int type, oType, i;
- bool bArray;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- type = OBJECT_NULL;
- focus = Math::PI*2.0f;
- minDist = 0.0f*g_unit;
- maxDist = 1000.0f*g_unit;
-
- if ( var->GetType() == CBotTypArrayPointer )
- {
- array = var->GetItemList();
- bArray = true;
- }
- else
- {
- type = var->GetValInt();
- bArray = false;
- }
-
- CInstanceManager* iMan = CInstanceManager::GetInstancePointer();
-
- best = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = static_cast<CObject*>(iMan->SearchInstance(CLASS_OBJECT, i));
- if ( pObj == 0 ) break;
- if ( pObj == pThis ) continue;
-
- if ( pObj->GetTruck() != 0 ) continue; // object transported?
- if ( !pObj->GetActif() ) continue;
- if ( pObj->GetProxyActivate() ) continue;
-
- oType = pObj->GetType();
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( oType == OBJECT_RUINmobilew2 ||
- oType == OBJECT_RUINmobilet1 ||
- oType == OBJECT_RUINmobilet2 ||
- oType == OBJECT_RUINmobiler1 ||
- oType == OBJECT_RUINmobiler2 )
- {
- oType = OBJECT_RUINmobilew1; // any ruin
- }
-
- if ( oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // wastes?
- {
- oType = OBJECT_SCRAP1; // any waste
- }
-
- if ( oType == OBJECT_BARRIER2 ||
- oType == OBJECT_BARRIER3 ) // barriers?
- {
- oType = OBJECT_BARRIER1; // any barrier
- }
-
- if ( bArray )
- {
- if ( !FindList(array, oType) ) continue;
- }
- else
- {
- if ( type != oType && type != OBJECT_NULL ) continue;
- }
-
- oPos = pObj->GetPosition(0);
- d = Math::DistanceProjected(iPos, oPos);
- if ( d < minDist || d > maxDist ) continue; // too close or too far?
-
- if ( focus >= Math::PI*2.0f )
- {
- if ( d < best )
- {
- best = d;
- pBest = pObj;
- }
- continue;
- }
-
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
- {
- if ( d < best )
- {
- best = d;
- pBest = pObj;
- }
- }
- }
-
- if ( pBest == 0 )
- {
- exception = ERR_FIND_IMPOSSIBLE;
- return false;
- }
-
- pos = pBest->GetPosition(0);
- goal = TGG_DEFAULT;
- crash = TGC_DEFAULT;
- altitude = 0.0f*g_unit;
-
- script->m_primaryTask = new CTaskManager(script->m_object);
- err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
// Compilation "grab/drop(oper)".
CBotTypResult CScript::cGrabDrop(CBotVar* &var, void* user)
@@ -2391,8 +3028,8 @@ bool CScript::rAim(CBotVar* var, CBotVar* result, int& exception, void* user)
{
script->m_primaryTask = new CTaskManager(script->m_object);
x = var->GetValFloat();
- var = var->GetNext();
- var == 0 ? y=0.0f : y=var->GetValFloat();
+ var = var->GetNext();
+ var == 0 ? y=0.0f : y=var->GetValFloat();
err = script->m_primaryTask->StartTaskGunGoal(x*Math::PI/180.0f, y*Math::PI/180.0f);
if ( err != ERR_OK )
{
@@ -2897,7 +3534,21 @@ void CScript::InitFonctions()
CBotProgram::AddFunction("rand", rRand, CScript::cNull);
CBotProgram::AddFunction("abs", rAbs, CScript::cOneFloat);
+ CBotProgram::AddFunction("endmission",rEndMission,CScript::cEndMission);
+ CBotProgram::AddFunction("playmusic", rPlayMusic ,CScript::cPlayMusic);
+ CBotProgram::AddFunction("stopmusic", rStopMusic ,CScript::cNull);
+
+ CBotProgram::AddFunction("getbuild", rGetBuild, CScript::cNull);
+ CBotProgram::AddFunction("getresearchenable", rGetResearchEnable, CScript::cNull);
+ CBotProgram::AddFunction("getresearchdone", rGetResearchDone, CScript::cNull);
+ CBotProgram::AddFunction("setbuild", rSetBuild, CScript::cOneFloat);
+ CBotProgram::AddFunction("setresearchenable", rSetResearchEnable, CScript::cOneFloat);
+ CBotProgram::AddFunction("setresearchdone", rSetResearchDone, CScript::cOneFloat);
+
+ CBotProgram::AddFunction("progfunc", rProgFunc, CScript::cStringString);
CBotProgram::AddFunction("retobject", rGetObject, CScript::cGetObject);
+ CBotProgram::AddFunction("retobjectbyid", rGetObjectById, CScript::cGetObject);
+ CBotProgram::AddFunction("delete", rDelete, CScript::cDelete);
CBotProgram::AddFunction("search", rSearch, CScript::cSearch);
CBotProgram::AddFunction("radar", rRadar, CScript::cRadar);
CBotProgram::AddFunction("detect", rDetect, CScript::cDetect);
@@ -2911,7 +3562,6 @@ void CScript::InitFonctions()
CBotProgram::AddFunction("move", rMove, CScript::cOneFloat);
CBotProgram::AddFunction("turn", rTurn, CScript::cOneFloat);
CBotProgram::AddFunction("goto", rGoto, CScript::cGoto);
- CBotProgram::AddFunction("find", rFind, CScript::cOneFloat);
CBotProgram::AddFunction("grab", rGrab, CScript::cGrabDrop);
CBotProgram::AddFunction("drop", rDrop, CScript::cGrabDrop);
CBotProgram::AddFunction("sniff", rSniff, CScript::cNull);
@@ -2938,6 +3588,10 @@ void CScript::InitFonctions()
CBotProgram::AddFunction("penup", rPenUp, CScript::cNull);
CBotProgram::AddFunction("pencolor", rPenColor, CScript::cOneFloat);
CBotProgram::AddFunction("penwidth", rPenWidth, CScript::cOneFloat);
+
+ CBotProgram::AddFunction("canbuild", rCanBuild, CScript::cCanBuild);
+ CBotProgram::AddFunction("build", rBuild, CScript::cOneFloat);
+
}
// Object's destructor.
@@ -3128,7 +3782,7 @@ bool CScript::Compile()
{
if ( liste.GetSize() == 0 )
{
- strcpy(m_title, "<sans nom>");
+ strcpy(m_title, "<extern missing>");
}
else
{
@@ -3165,7 +3819,7 @@ bool CScript::Compile()
{
m_cursor1 = m_cursor2 = 0;
}
- strcpy(m_title, "<erreur>");
+ strcpy(m_title, "<error>");
return false;
}
}
@@ -3404,7 +4058,7 @@ void PutList(const char *baseName, bool bArray, CBotVar *var, Ui::CList *list, i
if ( var == 0 && baseName[0] != 0 )
{
sprintf(buffer, "%s = null;", baseName);
- list->SetName(rankList++, buffer);
+ list->SetItemName(rankList++, buffer);
return;
}
@@ -3446,7 +4100,7 @@ void PutList(const char *baseName, bool bArray, CBotVar *var, Ui::CList *list, i
value = pStatic->GetValString();
p = value;
sprintf(buffer, "%s = %s;", varName, p);
- list->SetName(rankList++, buffer);
+ list->SetItemName(rankList++, buffer);
}
else if ( type == CBotTypString )
{
@@ -3454,7 +4108,7 @@ void PutList(const char *baseName, bool bArray, CBotVar *var, Ui::CList *list, i
value = pStatic->GetValString();
p = value;
sprintf(buffer, "%s = \"%s\";", varName, p);
- list->SetName(rankList++, buffer);
+ list->SetItemName(rankList++, buffer);
}
else if ( type == CBotTypArrayPointer )
{
@@ -3470,7 +4124,7 @@ void PutList(const char *baseName, bool bArray, CBotVar *var, Ui::CList *list, i
else
{
sprintf(buffer, "%s = ?;", varName);
- list->SetName(rankList++, buffer);
+ list->SetItemName(rankList++, buffer);
}
index ++;
@@ -3829,13 +4483,20 @@ void CScript::New(Ui::CEdit* edit, const char* name)
// Provided a script for all parts.
-bool CScript::SendScript(char* text)
+bool CScript::SendScript(const char* text)
{
- m_len = strlen(text);
+ /*m_len = strlen(text);
m_script = new char[m_len+1];
strcpy(m_script, text);
if ( !CheckToken() ) return false;
- if ( !Compile() ) return false;
+ if ( !Compile() ) return false;*/
+
+ Ui::CEdit* edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
+ edit->SetMaxChar(Ui::EDITSTUDIOMAX);
+ edit->SetAutoIndent(m_engine->GetEditIndentMode());
+ edit->SetText(text, true);
+ GetScript(edit);
+ m_interface->DeleteControl(EVENT_EDIT9);
return true;
}
diff --git a/src/script/script.h b/src/script/script.h
index 982d12b..7a5d075 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -38,13 +38,13 @@ class CDisplayText;
class CEdit;
class CInterface;
class CList;
-} /* Ui */
+} /* Ui */
namespace Gfx {
class CEngine;
class CTerrain;
class CWater;
-} /* Gfx */
+} /* Gfx */
@@ -78,7 +78,7 @@ public:
void GetError(char* buffer);
void New(Ui::CEdit* edit, const char* name);
- bool SendScript(char* text);
+ bool SendScript(const char* text);
bool ReadScript(const char* filename);
bool WriteScript(const char* filename);
bool ReadStack(FILE *file);
@@ -94,16 +94,20 @@ protected:
bool Compile();
private:
-
static CBotTypResult cNull(CBotVar* &var, void* user);
static CBotTypResult cOneFloat(CBotVar* &var, void* user);
static CBotTypResult cTwoFloat(CBotVar* &var, void* user);
static CBotTypResult cString(CBotVar* &var, void* user);
+ static CBotTypResult cStringString(CBotVar* &var, void* user);
+ static CBotTypResult cEndMission(CBotVar* &var, void* user);
+ static CBotTypResult cPlayMusic(CBotVar* &var, void* user);
static CBotTypResult cGetObject(CBotVar* &var, void* user);
+ static CBotTypResult cDelete(CBotVar* &var, void* user);
static CBotTypResult cSearch(CBotVar* &var, void* user);
static CBotTypResult cRadar(CBotVar* &var, void* user);
static CBotTypResult cDetect(CBotVar* &var, void* user);
static CBotTypResult cDirection(CBotVar* &var, void* user);
+ static CBotTypResult cCanBuild(CBotVar* &var, void* user);
static CBotTypResult cProduce(CBotVar* &var, void* user);
static CBotTypResult cDistance(CBotVar* &var, void* user);
static CBotTypResult cSpace(CBotVar* &var, void* user);
@@ -132,11 +136,25 @@ private:
static bool rPow(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rRand(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rAbs(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rEndMission(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rPlayMusic(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rStopMusic(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rGetBuild(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rGetResearchEnable(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rGetResearchDone(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rSetBuild(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rSetResearchEnable(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rSetResearchDone(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rGetObjectById(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rGetObject(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rProgFunc(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rDelete(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rSearch(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rRadar(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rDetect(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rDirection(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rCanBuild(CBotVar* var, CBotVar* result, int& exception, void* user);
+ static bool rBuild(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rProduce(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rDistance(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rDistance2d(CBotVar* var, CBotVar* result, int& exception, void* user);
@@ -174,6 +192,18 @@ private:
static bool rPenColor(CBotVar* var, CBotVar* result, int& exception, void* user);
static bool rPenWidth(CBotVar* var, CBotVar* result, int& exception, void* user);
+public:
+ static CBotTypResult cBusy(CBotVar* thisclass, CBotVar* &var);
+ static CBotTypResult cFactory(CBotVar* thisclass, CBotVar* &var);
+ static CBotTypResult cClassNull(CBotVar* thisclass, CBotVar* &var);
+ static CBotTypResult cClassOneFloat(CBotVar* thisclass, CBotVar* &var);
+
+ static bool rBusy(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception);
+ static bool rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception);
+ static bool rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception);
+ static bool rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception);
+
+private:
static bool Process(CScript* script, CBotVar* result, int &exception);
static CObject* SearchInfo(CScript* script, CObject* object, float power);
@@ -207,4 +237,3 @@ protected:
float m_returnValue;
};
-
diff --git a/src/sound/README.txt b/src/sound/README.txt
index fa2f531..f0ccb9e 100644
--- a/src/sound/README.txt
+++ b/src/sound/README.txt
@@ -2,3 +2,4 @@
* \dir src/sound
* \brief Sound module - playing sounds and music
*/
+
diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp
index 8c1cb81..992b8b2 100644
--- a/src/sound/oalsound/alsound.cpp
+++ b/src/sound/oalsound/alsound.cpp
@@ -16,18 +16,22 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
-#include "alsound.h"
+#include "sound/oalsound/alsound.h"
-#define MIN(a, b) (a > b ? b : a)
+#include <algorithm>
+#include <iomanip>
+
+#include <boost/filesystem.hpp>
ALSound::ALSound()
{
- mEnabled = false;
- m3D = false;
- mAudioVolume = 1.0f;
- mMusicVolume = 1.0f;
- mMute = false;
- mCurrentMusic = nullptr;
+ m_enabled = false;
+ m_3D = false;
+ m_audioVolume = 1.0f;
+ m_musicVolume = 1.0f;
+ m_currentMusic = nullptr;
+ m_eye.LoadZero();
+ m_lookat.LoadZero();
}
@@ -39,24 +43,36 @@ ALSound::~ALSound()
void ALSound::CleanUp()
{
- if (mEnabled) {
+ if (m_enabled)
+ {
GetLogger()->Info("Unloading files and closing device...\n");
StopAll();
+ StopMusic();
- for (auto channel : mChannels) {
+ for (auto channel : m_channels)
+ {
delete channel.second;
}
- for (auto item : mSounds) {
+ if (m_currentMusic)
+ {
+ delete m_currentMusic;
+ }
+
+ for (auto item : m_sounds)
+ {
delete item.second;
}
- mEnabled = false;
+ for (auto item : m_music)
+ {
+ delete item.second;
+ }
+
+ m_enabled = false;
- mCurrentMusic->FreeBuffer();
- delete mCurrentMusic;
- alcDestroyContext(mContext);
- alcCloseDevice(mDevice);
+ alcDestroyContext(m_context);
+ alcCloseDevice(m_device);
}
}
@@ -65,41 +81,43 @@ bool ALSound::Create(bool b3D)
{
CleanUp();
- if (mEnabled)
+ if (m_enabled)
return true;
GetLogger()->Info("Opening audio device...\n");
- mDevice = alcOpenDevice(NULL);
- if (!mDevice) {
+ m_device = alcOpenDevice(NULL);
+ if (!m_device)
+ {
GetLogger()->Error("Could not open audio device!\n");
return false;
}
- mContext = alcCreateContext(mDevice, NULL);
- if (!mContext) {
+ m_context = alcCreateContext(m_device, NULL);
+ if (!m_context)
+ {
GetLogger()->Error("Could not create audio context!\n");
return false;
}
- alcMakeContextCurrent(mContext);
+ alcMakeContextCurrent(m_context);
+ alListenerf(AL_GAIN, m_audioVolume);
+ alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
- mCurrentMusic = new Channel();
+ m_currentMusic = new Channel();
GetLogger()->Info("Done.\n");
- mEnabled = true;
+ m_enabled = true;
return true;
}
void ALSound::SetSound3D(bool bMode)
{
- // TODO stub! need to be implemented
- m3D = bMode;
+ m_3D = bMode;
}
bool ALSound::GetSound3D()
{
- // TODO stub! need to be implemented
- return true;
+ return m_3D;
}
@@ -112,54 +130,70 @@ bool ALSound::GetSound3DCap()
bool ALSound::GetEnable()
{
- return mEnabled;
+ return m_enabled;
}
void ALSound::SetAudioVolume(int volume)
{
- mAudioVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f);
- alListenerf(AL_GAIN, mAudioVolume);
+ m_audioVolume = static_cast<float>(volume) / MAXVOLUME;
}
int ALSound::GetAudioVolume()
{
- if ( !mEnabled )
+ if ( !m_enabled )
return 0;
- return mAudioVolume * MAXVOLUME;
+ return m_audioVolume * MAXVOLUME;
}
void ALSound::SetMusicVolume(int volume)
{
- mMusicVolume = MIN(static_cast<float>(volume) / MAXVOLUME, 1.0f);
- if (mCurrentMusic) {
- mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume);
+ m_musicVolume = static_cast<float>(volume) / MAXVOLUME;
+ if (m_currentMusic)
+ {
+ m_currentMusic->SetVolume(m_musicVolume);
}
}
int ALSound::GetMusicVolume()
{
- if ( !mEnabled )
+ if ( !m_enabled )
return 0.0f;
- return mMusicVolume * MAXVOLUME;
+ return m_musicVolume * MAXVOLUME;
}
bool ALSound::Cache(Sound sound, std::string filename)
{
Buffer *buffer = new Buffer();
- if (buffer->LoadFromFile(filename, sound)) {
- mSounds[sound] = buffer;
+ if (buffer->LoadFromFile(filename, sound))
+ {
+ m_sounds[sound] = buffer;
return true;
}
return false;
}
+bool ALSound::CacheMusic(std::string filename)
+{
+ if (m_music.find(filename) == m_music.end())
+ {
+ Buffer *buffer = new Buffer();
+ std::stringstream file;
+ file << m_soundPath << "/" << filename;
+ if (buffer->LoadFromFile(file.str(), static_cast<Sound>(-1)))
+ {
+ m_music[filename] = buffer;
+ return true;
+ }
+ }
+ return false;
+}
int ALSound::GetPriority(Sound sound)
{
@@ -215,7 +249,8 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
int priority = GetPriority(sound);
// Seeks a channel used which sound is stopped.
- for (auto it : mChannels) {
+ for (auto it : m_channels)
+ {
if (it.second->IsPlaying())
continue;
if (it.second->GetSoundType() != sound)
@@ -228,47 +263,55 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
}
// just add a new channel if we dont have any
- if (mChannels.size() == 0) {
+ if (m_channels.size() == 0)
+ {
Channel *chn = new Channel();
// check if we channel ready to play music, if not report error
- if (chn->IsReady()) {
+ if (chn->IsReady())
+ {
chn->SetPriority(priority);
- mChannels[1] = chn;
+ m_channels[1] = chn;
channel = 1;
bAlreadyLoaded = false;
return true;
}
delete chn;
- GetLogger()->Error("Could not open channel to play sound!");
+ GetLogger()->Error("Could not open channel to play sound!\n");
return false;
}
// Seeks a channel completely free.
- if (mChannels.size() < 64) {
- auto it = mChannels.end();
+ if (m_channels.size() < 64)
+ {
+ auto it = m_channels.end();
it--;
int i = (*it).first;
- while (++i) {
- if (mChannels.find(i) == mChannels.end()) {
+ while (++i)
+ {
+ if (m_channels.find(i) == m_channels.end())
+ {
Channel *chn = new Channel();
// check if channel is ready to play music, if not destroy it and seek free one
- if (chn->IsReady()) {
+ if (chn->IsReady())
+ {
chn->SetPriority(priority);
- mChannels[++i] = chn;
+ m_channels[++i] = chn;
channel = i;
bAlreadyLoaded = false;
return true;
}
delete chn;
- GetLogger()->Warn("Could not open additional channel to play sound!");
+ GetLogger()->Warn("Could not open additional channel to play sound!\n");
}
}
}
int lowerOrEqual = -1;
- for (auto it : mChannels) {
- if (it.second->GetPriority() < priority) {
- GetLogger()->Debug("Sound channel with lower priority will be reused.");
+ for (auto it : m_channels)
+ {
+ if (it.second->GetPriority() < priority)
+ {
+ GetLogger()->Debug("Sound channel with lower priority will be reused.\n");
channel = it.first;
return true;
}
@@ -276,9 +319,10 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
lowerOrEqual = it.first;
}
- if (lowerOrEqual != -1) {
+ if (lowerOrEqual != -1)
+ {
channel = lowerOrEqual;
- GetLogger()->Debug("Sound channel with lower or equal priority will be reused.");
+ GetLogger()->Debug("Sound channel with lower or equal priority will be reused.\n");
return true;
}
@@ -289,17 +333,18 @@ bool ALSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
int ALSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
{
- return Play(sound, Math::Vector(), amplitude, frequency, bLoop);
+ return Play(sound, m_eye, amplitude, frequency, bLoop);
}
int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequency, bool bLoop)
{
- if (!mEnabled) {
+ if (!m_enabled)
+ {
return -1;
}
-
- if (mSounds.find(sound) == mSounds.end()) {
+ if (m_sounds.find(sound) == m_sounds.end())
+ {
GetLogger()->Warn("Sound %d was not loaded!\n", sound);
return -1;
}
@@ -309,23 +354,34 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc
if (!SearchFreeBuffer(sound, channel, bAlreadyLoaded))
return -1;
- if (!bAlreadyLoaded) {
- if (!mChannels[channel]->SetBuffer(mSounds[sound])) {
- mChannels[channel]->SetBuffer(nullptr);
+ if (!bAlreadyLoaded)
+ {
+ if (!m_channels[channel]->SetBuffer(m_sounds[sound]))
+ {
+ m_channels[channel]->SetBuffer(nullptr);
return -1;
}
}
+
Position(channel, pos);
+ if (!m_3D)
+ {
+ ComputeVolumePan2D(channel, pos);
+ }
+ else
+ {
+ m_channels[channel]->SetVolumeAtrib(1.0f);
+ }
// setting initial values
- mChannels[channel]->SetStartAmplitude(amplitude);
- mChannels[channel]->SetStartFrequency(frequency);
- mChannels[channel]->SetChangeFrequency(1.0f);
- mChannels[channel]->ResetOper();
- mChannels[channel]->SetFrequency(frequency);
- mChannels[channel]->SetVolume(amplitude * mAudioVolume);
- mChannels[channel]->SetLoop(bLoop);
- mChannels[channel]->Play();
+ m_channels[channel]->SetStartAmplitude(amplitude);
+ m_channels[channel]->SetStartFrequency(frequency);
+ m_channels[channel]->SetChangeFrequency(1.0f);
+ m_channels[channel]->ResetOper();
+ m_channels[channel]->SetFrequency(frequency);
+ m_channels[channel]->SetVolume(powf(amplitude * m_channels[channel]->GetVolumeAtrib(), 0.2f) * m_audioVolume);
+ m_channels[channel]->SetLoop(bLoop);
+ m_channels[channel]->Play();
return channel;
}
@@ -333,31 +389,33 @@ int ALSound::Play(Sound sound, Math::Vector pos, float amplitude, float frequenc
bool ALSound::FlushEnvelope(int channel)
{
- if (mChannels.find(channel) == mChannels.end()) {
+ if (m_channels.find(channel) == m_channels.end())
+ {
return false;
}
- mChannels[channel]->ResetOper();
+ m_channels[channel]->ResetOper();
return true;
}
bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper)
{
- if (!mEnabled)
+ if (!m_enabled)
return false;
- if (mChannels.find(channel) == mChannels.end()) {
+ if (m_channels.find(channel) == m_channels.end())
+ {
return false;
}
-
+
SoundOper op;
op.finalAmplitude = amplitude;
op.finalFrequency = frequency;
op.totalTime = time;
op.nextOper = oper;
op.currentTime = 0.0f;
- mChannels[channel]->AddOper(op);
+ m_channels[channel]->AddOper(op);
return true;
}
@@ -365,43 +423,59 @@ bool ALSound::AddEnvelope(int channel, float amplitude, float frequency, float t
bool ALSound::Position(int channel, Math::Vector pos)
{
- if (!mEnabled)
+ if (!m_enabled)
return false;
- if (mChannels.find(channel) == mChannels.end()) {
+ if (m_channels.find(channel) == m_channels.end())
+ {
return false;
}
- mChannels[channel]->SetPosition(pos);
+ if (m_3D)
+ {
+ m_channels[channel]->SetPan(pos);
+ }
+ else
+ {
+ ComputeVolumePan2D(channel, pos);
+
+ if (!m_channels[channel]->HasEnvelope())
+ {
+ float volume = m_channels[channel]->GetStartAmplitude();
+ m_channels[channel]->SetVolume(powf(volume * m_channels[channel]->GetVolumeAtrib(), 0.2f) * m_audioVolume);
+ }
+ }
return true;
}
bool ALSound::Frequency(int channel, float frequency)
{
- if (!mEnabled)
+ if (!m_enabled)
return false;
- if (mChannels.find(channel) == mChannels.end()) {
+ if (m_channels.find(channel) == m_channels.end())
+ {
return false;
}
- mChannels[channel]->SetFrequency(frequency * mChannels[channel]->GetInitFrequency());
- mChannels[channel]->SetChangeFrequency(frequency);
+ m_channels[channel]->SetFrequency(frequency * m_channels[channel]->GetInitFrequency());
+ m_channels[channel]->SetChangeFrequency(frequency);
return true;
}
bool ALSound::Stop(int channel)
{
- if (!mEnabled)
+ if (!m_enabled)
return false;
- if (mChannels.find(channel) == mChannels.end()) {
+ if (m_channels.find(channel) == m_channels.end())
+ {
return false;
}
- mChannels[channel]->Stop();
- mChannels[channel]->ResetOper();
+ m_channels[channel]->Stop();
+ m_channels[channel]->ResetOper();
return true;
}
@@ -409,10 +483,11 @@ bool ALSound::Stop(int channel)
bool ALSound::StopAll()
{
- if (!mEnabled)
+ if (!m_enabled)
return false;
- for (auto channel : mChannels) {
+ for (auto channel : m_channels)
+ {
channel.second->Stop();
channel.second->ResetOper();
}
@@ -423,32 +498,46 @@ bool ALSound::StopAll()
bool ALSound::MuteAll(bool bMute)
{
- if (!mEnabled)
+ if (!m_enabled)
return false;
- float volume;
- mMute = bMute;
- if (mMute)
- volume = 0;
- else
- volume = mAudioVolume;
-
- for (auto channel : mChannels) {
- channel.second->SetVolume(volume * mAudioVolume);
+ for (auto it : m_channels)
+ {
+ if (it.second->IsPlaying())
+ {
+ it.second->Mute(bMute);
+ }
}
+ if (bMute)
+ {
+ m_currentMusic->SetVolume(0.0f);
+ }
+ else
+ {
+ m_currentMusic->SetVolume(m_musicVolume);
+ }
return true;
}
+
void ALSound::FrameMove(float delta)
{
- if (!mEnabled)
+ if (!m_enabled)
return;
float progress;
float volume, frequency;
- for (auto it : mChannels) {
- if (!it.second->IsPlaying()) {
+ for (auto it : m_channels)
+ {
+ if (!it.second->IsPlaying())
+ {
+ continue;
+ }
+
+ if (it.second->IsMuted())
+ {
+ it.second->SetVolume(0.0f);
continue;
}
@@ -458,25 +547,34 @@ void ALSound::FrameMove(float delta)
SoundOper &oper = it.second->GetEnvelope();
oper.currentTime += delta;
progress = oper.currentTime / oper.totalTime;
- progress = MIN(progress, 1.0f);
-
+ progress = std::min(progress, 1.0f);
+
// setting volume
volume = progress * (oper.finalAmplitude - it.second->GetStartAmplitude());
- volume = (volume + it.second->GetStartAmplitude()) * mAudioVolume;
- it.second->SetVolume(volume);
+ volume = volume + it.second->GetStartAmplitude();
+ it.second->SetVolume(powf(volume * it.second->GetVolumeAtrib(), 0.2f) * m_audioVolume);
// setting frequency
- frequency = progress * (oper.finalFrequency - it.second->GetStartFrequency()) * it.second->GetStartFrequency() * it.second->GetChangeFrequency() * it.second->GetInitFrequency();
- it.second->AdjustFrequency(frequency);
-
- if (oper.totalTime <= oper.currentTime) {
- if (oper.nextOper == SOPER_LOOP) {
+ frequency = progress;
+ frequency *= oper.finalFrequency - it.second->GetStartFrequency();
+ frequency += it.second->GetStartFrequency();
+ frequency *= it.second->GetChangeFrequency();
+ frequency = (frequency * it.second->GetInitFrequency());
+ it.second->SetFrequency(frequency);
+
+ if (oper.totalTime <= oper.currentTime)
+ {
+ if (oper.nextOper == SOPER_LOOP)
+ {
oper.currentTime = 0.0f;
it.second->Play();
- } else {
+ }
+ else
+ {
it.second->SetStartAmplitude(oper.finalAmplitude);
it.second->SetStartFrequency(oper.finalFrequency);
- if (oper.nextOper == SOPER_STOP) {
+ if (oper.nextOper == SOPER_STOP)
+ {
it.second->Stop();
}
@@ -489,94 +587,185 @@ void ALSound::FrameMove(float delta)
void ALSound::SetListener(Math::Vector eye, Math::Vector lookat)
{
- float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f};
- alListener3f(AL_POSITION, eye.x, eye.y, eye.z);
- alListenerfv(AL_ORIENTATION, orientation);
+ m_eye = eye;
+ m_lookat = lookat;
+ if (m_3D)
+ {
+ float orientation[] = {lookat.x, lookat.y, lookat.z, 0.f, 1.f, 0.f};
+ alListener3f(AL_POSITION, eye.x, eye.y, eye.z);
+ alListenerfv(AL_ORIENTATION, orientation);
+ }
+ else
+ {
+ float orientation[] = {0.0f, 0.0f, 0.0f, 0.f, 1.f, 0.f};
+ alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f);
+ alListenerfv(AL_ORIENTATION, orientation);
+
+ // recalculate sound position
+ for (auto it : m_channels)
+ {
+ if (it.second->IsPlaying())
+ {
+ Math::Vector pos = it.second->GetPosition();
+ ComputeVolumePan2D(it.first, pos);
+
+ if (!it.second->HasEnvelope())
+ {
+ float volume = it.second->GetStartAmplitude();
+ it.second->SetVolume(powf(volume * it.second->GetVolumeAtrib(), 0.2f) * m_audioVolume);
+ }
+ }
+ }
+ }
}
-
bool ALSound::PlayMusic(int rank, bool bRepeat)
{
- if (!mEnabled) {
+ std::stringstream filename;
+ filename << "music" << std::setfill('0') << std::setw(3) << rank << ".ogg";
+ return PlayMusic(filename.str(), bRepeat);
+}
+
+bool ALSound::PlayMusic(std::string filename, bool bRepeat)
+{
+ if (!m_enabled)
+ {
return false;
}
-
- if (static_cast<int>(mCurrentMusic->GetSoundType()) != rank) {
- // check if we have music in cache
- for (auto music : mMusicCache) {
- if (static_cast<int>(music->GetSoundType()) == rank) {
- GetLogger()->Debug("Music loaded from cache\n");
- mCurrentMusic->SetBuffer(music);
-
- mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume);
- mCurrentMusic->SetLoop(bRepeat);
- mCurrentMusic->Play();
- return true;
- }
- }
-
- // we cache only 3 music files
- if (mMusicCache.size() == 3) {
- mCurrentMusic->FreeBuffer();
- mMusicCache.pop_back();
- }
- if (mMusic.find(rank) == mMusic.end()) {
- GetLogger()->Info("Requested music %d was not found.\n", rank);
+ std::stringstream file;
+ file << m_soundPath << "/" << filename;
+
+ // check if we have music in cache
+ if (m_music.find(filename) == m_music.end())
+ {
+ GetLogger()->Warn("Music %s was not cached!\n", filename.c_str());
+ if (!boost::filesystem::exists(file.str()))
+ {
+ GetLogger()->Warn("Requested music %s was not found.\n", filename.c_str());
return false;
}
-
Buffer *buffer = new Buffer();
- mMusicCache.push_front(buffer);
- buffer->LoadFromFile(mMusic.at(rank), static_cast<Sound>(rank));
- mCurrentMusic->SetBuffer(buffer);
- mMusicCache[rank] = buffer;
- }
-
- mCurrentMusic->SetVolume(mMusicVolume * mAudioVolume);
- mCurrentMusic->SetLoop(bRepeat);
- mCurrentMusic->Play();
-
+ buffer->LoadFromFile(file.str(), static_cast<Sound>(-1));
+ m_currentMusic->SetBuffer(buffer);
+ }
+ else
+ {
+ GetLogger()->Debug("Music loaded from cache\n");
+ m_currentMusic->SetBuffer(m_music[filename]);
+ }
+
+ m_currentMusic->SetVolume(m_musicVolume);
+ m_currentMusic->SetLoop(bRepeat);
+ m_currentMusic->Play();
+
return true;
}
bool ALSound::RestartMusic()
{
- if (!mEnabled || !mCurrentMusic) {
+ if (!m_enabled || !m_currentMusic)
+ {
return false;
}
- mCurrentMusic->Stop();
- mCurrentMusic->Play();
+ m_currentMusic->Stop();
+ m_currentMusic->Play();
return true;
}
void ALSound::StopMusic()
{
- if (!mEnabled || !mCurrentMusic) {
+ if (!m_enabled || !m_currentMusic)
+ {
return;
}
-
+
SuspendMusic();
}
bool ALSound::IsPlayingMusic()
{
- if (!mEnabled || !mCurrentMusic) {
+ if (!m_enabled || !m_currentMusic)
+ {
return false;
}
-
- return mCurrentMusic->IsPlaying();
+
+ return m_currentMusic->IsPlaying();
}
void ALSound::SuspendMusic()
{
- if (!mEnabled || !mCurrentMusic) {
+ if (!m_enabled || !m_currentMusic)
+ {
+ return;
+ }
+
+ m_currentMusic->Stop();
+}
+
+
+void ALSound::ComputeVolumePan2D(int channel, Math::Vector &pos)
+{
+ float dist, a, g;
+ m_channels[channel]->SetPosition(pos);
+
+ if (VectorsEqual(pos, m_eye))
+ {
+ m_channels[channel]->SetVolumeAtrib(1.0f); // maximum volume
+ m_channels[channel]->SetPan(Math::Vector()); // at the center
return;
}
-
- mCurrentMusic->Stop();
+
+ dist = Distance(pos, m_eye);
+ if ( dist >= 110.0f ) // very far?
+ {
+ m_channels[channel]->SetVolumeAtrib(0.0f); // silence
+ m_channels[channel]->SetPan(Math::Vector()); // at the center
+ return;
+ }
+ else if ( dist <= 10.0f ) // very close?
+ {
+ m_channels[channel]->SetVolumeAtrib(1.0f); // maximum volume
+ m_channels[channel]->SetPan(Math::Vector()); // at the center
+ return;
+ }
+ m_channels[channel]->SetVolumeAtrib(1.0f - ((dist - 10.0f) / 100.0f));
+
+ Math::Vector one = Math::Vector(1.0f, 0.0f, 0.0f);
+ float angle_a = Angle(Math::Vector(m_lookat.x - m_eye.x, m_lookat.z - m_eye.z, 0.0f), one);
+ float angle_g = Angle(Math::Vector(pos.x - m_eye.x, pos.z - m_eye.z, 0.0f), one);
+
+ a = fmodf(angle_a, Math::PI * 2.0f);
+ g = fmodf(angle_g, Math::PI * 2.0f);
+
+ if ( a < 0.0f )
+ {
+ a += Math::PI * 2.0f;
+ }
+ if ( g < 0.0f )
+ {
+ g += Math::PI * 2.0f;
+ }
+
+ if ( a < g )
+ {
+ if (a + Math::PI * 2.0f - g < g - a )
+ {
+ a += Math::PI * 2.0f;
+ }
+ }
+ else
+ {
+ if ( g + Math::PI * 2.0f - a < a - g )
+ {
+ g += Math::PI * 2.0f;
+ }
+ }
+
+ m_channels[channel]->SetPan( Math::Vector(0.0f, 0.0f, sinf(g - a)) );
}
+
diff --git a/src/sound/oalsound/alsound.h b/src/sound/oalsound/alsound.h
index bdf06b1..ad32204 100644
--- a/src/sound/oalsound/alsound.h
+++ b/src/sound/oalsound/alsound.h
@@ -15,82 +15,90 @@
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
-// alsound.h
+/**
+ * \file alsound.h
+ * \brief OpenAL implementation of sound system
+ */
#pragma once
+#include "common/logger.h"
+#include "sound/sound.h"
+
+#include "sound/oalsound/buffer.h"
+#include "sound/oalsound/channel.h"
+#include "sound/oalsound/check.h"
+
#include <map>
#include <string>
#include <AL/al.h>
-#include "common/logger.h"
-#include "sound/sound.h"
-
-#include "buffer.h"
-#include "channel.h"
-#include "check.h"
-
class ALSound : public CSoundInterface
{
- public:
- ALSound();
- ~ALSound();
-
- bool Create(bool b3D);
- bool Cache(Sound, std::string);
-
- bool GetEnable();
-
- void SetSound3D(bool bMode);
- bool GetSound3D();
- bool GetSound3DCap();
-
- void SetAudioVolume(int volume);
- int GetAudioVolume();
- void SetMusicVolume(int volume);
- int GetMusicVolume();
-
- void SetListener(Math::Vector eye, Math::Vector lookat);
- void FrameMove(float rTime);
-
- int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
- int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
- bool FlushEnvelope(int channel);
- bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
- bool Position(int channel, Math::Vector pos);
- bool Frequency(int channel, float frequency);
- bool Stop(int channel);
- bool StopAll();
- bool MuteAll(bool bMute);
-
- bool PlayMusic(int rank, bool bRepeat);
- bool RestartMusic();
- void SuspendMusic();
- void StopMusic();
- bool IsPlayingMusic();
-
- // plugin interface
- std::string PluginName();
- int PluginVersion();
- void InstallPlugin();
- bool UninstallPlugin(std::string &);
-
- private:
- void CleanUp();
- int GetPriority(Sound);
- bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
-
- bool mEnabled;
- bool m3D;
- bool mMute;
- float mAudioVolume;
- float mMusicVolume;
- ALCdevice* mDevice;
- ALCcontext* mContext;
- std::map<Sound, Buffer*> mSounds;
- std::map<int, Channel*> mChannels;
- std::deque<Buffer*> mMusicCache;
- Channel *mCurrentMusic;
+public:
+ ALSound();
+ ~ALSound();
+
+ bool Create(bool b3D);
+ bool Cache(Sound, std::string);
+ bool CacheMusic(std::string);
+
+ bool GetEnable();
+
+ void SetSound3D(bool bMode);
+ bool GetSound3D();
+ bool GetSound3DCap();
+
+ void SetAudioVolume(int volume);
+ int GetAudioVolume();
+ void SetMusicVolume(int volume);
+ int GetMusicVolume();
+
+ void SetListener(Math::Vector eye, Math::Vector lookat);
+ void FrameMove(float rTime);
+
+ int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
+ int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
+ bool FlushEnvelope(int channel);
+ bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
+ bool Position(int channel, Math::Vector pos);
+ bool Frequency(int channel, float frequency);
+ bool Stop(int channel);
+ bool StopAll();
+ bool MuteAll(bool bMute);
+
+ bool PlayMusic(int rank, bool bRepeat);
+ bool PlayMusic(std::string filename, bool bRepeat);
+ bool RestartMusic();
+ void SuspendMusic();
+ void StopMusic();
+ bool IsPlayingMusic();
+
+ // plugin interface
+ std::string PluginName();
+ int PluginVersion();
+ void InstallPlugin();
+ bool UninstallPlugin(std::string &);
+
+private:
+ void CleanUp();
+ int GetPriority(Sound);
+ bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
+ void ComputeVolumePan2D(int channel, Math::Vector &pos);
+
+ bool m_enabled;
+ bool m_3D;
+ float m_audioVolume;
+ float m_musicVolume;
+ ALCdevice* m_device;
+ ALCcontext* m_context;
+ std::map<Sound, Buffer*> m_sounds;
+ std::map<std::string, Buffer*> m_music;
+ std::map<int, Channel*> m_channels;
+ Channel *m_currentMusic;
+ Math::Vector m_eye;
+ Math::Vector m_lookat;
};
+
diff --git a/src/sound/oalsound/buffer.cpp b/src/sound/oalsound/buffer.cpp
index edc3d74..0047f91 100644
--- a/src/sound/oalsound/buffer.cpp
+++ b/src/sound/oalsound/buffer.cpp
@@ -15,28 +15,35 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
-#include "buffer.h"
+#include "sound/oalsound/buffer.h"
-Buffer::Buffer() {
- mLoaded = false;
- mDuration = 0.0f;
+#include <cstring>
+
+Buffer::Buffer()
+{
+ m_loaded = false;
+ m_duration = 0.0f;
}
-Buffer::~Buffer() {
- if (mLoaded) {
- alDeleteBuffers(1, &mBuffer);
+Buffer::~Buffer()
+{
+ if (m_loaded)
+ {
+ alDeleteBuffers(1, &m_buffer);
if (alCheck())
GetLogger()->Warn("Failed to unload buffer. Code %d\n", alGetCode());
}
}
-bool Buffer::LoadFromFile(std::string filename, Sound sound) {
- mSound = sound;
+bool Buffer::LoadFromFile(std::string filename, Sound sound)
+{
+ m_sound = sound;
GetLogger()->Debug("Loading audio file: %s\n", filename.c_str());
SF_INFO fileInfo;
+ memset(&fileInfo, 0, sizeof(SF_INFO));
SNDFILE *file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
GetLogger()->Trace(" channels %d\n", fileInfo.channels);
@@ -45,16 +52,18 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound) {
GetLogger()->Trace(" samplerate %d\n", fileInfo.samplerate);
GetLogger()->Trace(" sections %d\n", fileInfo.sections);
- if (!file) {
+ if (!file)
+ {
GetLogger()->Warn("Could not load file. Reason: %s\n", sf_strerror(file));
- mLoaded = false;
+ m_loaded = false;
return false;
}
- alGenBuffers(1, &mBuffer);
- if (!mBuffer) {
+ alGenBuffers(1, &m_buffer);
+ if (!m_buffer)
+ {
GetLogger()->Warn("Could not create audio buffer\n");
- mLoaded = false;
+ m_loaded = false;
sf_close(file);
return false;
}
@@ -64,33 +73,39 @@ bool Buffer::LoadFromFile(std::string filename, Sound sound) {
std::array<int16_t, 4096> buffer;
data.reserve(fileInfo.frames);
size_t read = 0;
- while ((read = sf_read_short(file, buffer.data(), buffer.size())) != 0) {
+ while ((read = sf_read_short(file, buffer.data(), buffer.size())) != 0)
+ {
data.insert(data.end(), buffer.begin(), buffer.begin() + read);
}
- sf_close(file);
+ sf_close(file);
- alBufferData(mBuffer, fileInfo.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), fileInfo.samplerate);
- mDuration = static_cast<float>(fileInfo.frames) / fileInfo.samplerate;
- mLoaded = true;
+ alBufferData(m_buffer, fileInfo.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, &data.front(), data.size() * sizeof(uint16_t), fileInfo.samplerate);
+ m_duration = static_cast<float>(fileInfo.frames) / fileInfo.samplerate;
+ m_loaded = true;
return true;
}
-Sound Buffer::GetSoundType() {
- return mSound;
+Sound Buffer::GetSoundType()
+{
+ return m_sound;
}
-ALuint Buffer::GetBuffer() {
- return mBuffer;
+ALuint Buffer::GetBuffer()
+{
+ return m_buffer;
}
-bool Buffer::IsLoaded() {
- return mLoaded;
+bool Buffer::IsLoaded()
+{
+ return m_loaded;
}
-float Buffer::GetDuration() {
- return mDuration;
+float Buffer::GetDuration()
+{
+ return m_duration;
}
+
diff --git a/src/sound/oalsound/buffer.h b/src/sound/oalsound/buffer.h
index 7286deb..d847426 100644
--- a/src/sound/oalsound/buffer.h
+++ b/src/sound/oalsound/buffer.h
@@ -14,10 +14,18 @@
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
-// buffer.h
+/**
+ * \file buffer.h
+ * \brief OpenAL buffer
+ */
#pragma once
+#include "sound/sound.h"
+#include "common/logger.h"
+
+#include "sound/oalsound/check.h"
+
#include <string>
#include <vector>
#include <array>
@@ -25,27 +33,23 @@
#include <AL/al.h>
#include <sndfile.h>
-#include "sound/sound.h"
-#include "common/logger.h"
-
-#include "check.h"
-
class Buffer
{
- public:
- Buffer();
- ~Buffer();
-
- bool LoadFromFile(std::string, Sound);
- bool IsLoaded();
-
- Sound GetSoundType();
- ALuint GetBuffer();
- float GetDuration();
-
- private:
- ALuint mBuffer;
- Sound mSound;
- bool mLoaded;
- float mDuration;
+public:
+ Buffer();
+ ~Buffer();
+
+ bool LoadFromFile(std::string, Sound);
+ bool IsLoaded();
+
+ Sound GetSoundType();
+ ALuint GetBuffer();
+ float GetDuration();
+
+private:
+ ALuint m_buffer;
+ Sound m_sound;
+ bool m_loaded;
+ float m_duration;
};
+
diff --git a/src/sound/oalsound/channel.cpp b/src/sound/oalsound/channel.cpp
index 19394c6..4d89df5 100644
--- a/src/sound/oalsound/channel.cpp
+++ b/src/sound/oalsound/channel.cpp
@@ -15,59 +15,76 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
-#include "channel.h"
+#include "sound/oalsound/channel.h"
-#define MIN(a, b) (a > b ? b : a)
-
-Channel::Channel() {
- alGenSources(1, &mSource);
+Channel::Channel()
+{
+ alGenSources(1, &m_source);
- if (alCheck()) {
+ if (alCheck())
+ {
GetLogger()->Warn("Failed to create sound source. Code: %d\n", alGetCode());
- mReady = false;
- } else {
- mReady = true;
+ m_ready = false;
}
-
- mPriority = 0;
- mBuffer = nullptr;
- mLoop = false;
- mInitFrequency = 0.0f;
- mStartAmplitude = 0.0f;
- mStartFrequency = 0.0f;
- mChangeFrequency = 0.0f;
-}
-
-
-Channel::~Channel() {
- if (mReady) {
- alSourceStop(mSource);
- alSourcei(mSource, AL_BUFFER, 0);
- alDeleteSources(1, &mSource);
+ else
+ {
+ m_ready = true;
+ }
+
+ m_priority = 0;
+ m_buffer = nullptr;
+ m_loop = false;
+ m_mute = false;
+ m_initFrequency = 0.0f;
+ m_startAmplitude = 0.0f;
+ m_startFrequency = 0.0f;
+ m_changeFrequency = 0.0f;
+ m_volume = 0.0f;
+}
+
+
+Channel::~Channel()
+{
+ if (m_ready)
+ {
+ alSourceStop(m_source);
+ alSourcei(m_source, AL_BUFFER, 0);
+ alDeleteSources(1, &m_source);
if (alCheck())
GetLogger()->Warn("Failed to delete sound source. Code: %d\n", alGetCode());
}
}
-bool Channel::Play() {
- if (!mReady || mBuffer == nullptr)
+bool Channel::Play()
+{
+ if (!m_ready || m_buffer == nullptr)
+ {
return false;
+ }
- alSourcei(mSource, AL_LOOPING, static_cast<ALint>(mLoop));
- alSourcePlay(mSource);
+ alSourcei(m_source, AL_LOOPING, static_cast<ALint>(m_loop));
+ alSourcei(m_source, AL_REFERENCE_DISTANCE, 10.0f);
+ alSourcei(m_source, AL_MAX_DISTANCE, 110.0f);
+ alSourcePlay(m_source);
if (alCheck())
+ {
GetLogger()->Warn("Could not play audio sound source. Code: %d\n", alGetCode());
+ }
return true;
}
-bool Channel::SetPosition(Math::Vector pos) {
- if (!mReady || mBuffer == nullptr)
+bool Channel::SetPan(Math::Vector pos)
+{
+ if (!m_ready || m_buffer == nullptr)
+ {
return false;
-
- alSource3f(mSource, AL_POSITION, pos.x, pos.y, pos.z);
- if (alCheck()) {
+ }
+
+ alSource3f(m_source, AL_POSITION, pos.x, pos.y, pos.z);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not set sound position. Code: %d\n", alGetCode());
return false;
}
@@ -75,37 +92,46 @@ bool Channel::SetPosition(Math::Vector pos) {
}
-bool Channel::SetFrequency(float freq)
+void Channel::SetPosition(Math::Vector pos)
{
- if (!mReady || mBuffer == nullptr)
- return false;
+ m_position = pos;
+}
- alSourcef(mSource, AL_PITCH, freq);
- if (alCheck()) {
- GetLogger()->Warn("Could not set sound pitch to '%f'. Code: %d\n", freq, alGetCode());
- return false;
- }
- return true;
+
+Math::Vector Channel::GetPosition()
+{
+ return m_position;
}
-bool Channel::AdjustFrequency(float freq)
+bool Channel::SetFrequency(float freq)
{
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return false;
+ }
- return SetFrequency(mInitFrequency + fabs(freq));
+ alSourcef(m_source, AL_PITCH, freq);
+ if (alCheck())
+ {
+ GetLogger()->Warn("Could not set sound pitch to '%f'. Code: %d\n", freq, alGetCode());
+ return false;
+ }
+ return true;
}
float Channel::GetFrequency()
{
ALfloat freq;
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return 0;
-
- alGetSourcef(mSource, AL_PITCH, &freq);
- if (alCheck()) {
+ }
+
+ alGetSourcef(m_source, AL_PITCH, &freq);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not get sound pitch. Code: %d\n", alGetCode());
return 0;
}
@@ -116,11 +142,14 @@ float Channel::GetFrequency()
bool Channel::SetVolume(float vol)
{
- if (!mReady || vol < 0 || mBuffer == nullptr)
+ if (!m_ready || vol < 0 || m_buffer == nullptr)
+ {
return false;
-
- alSourcef(mSource, AL_GAIN, MIN(powf(vol, 0.2f), 1.0f));
- if (alCheck()) {
+ }
+
+ alSourcef(m_source, AL_GAIN, vol);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not set sound volume to '%f'. Code: %d\n", vol, alGetCode());
return false;
}
@@ -131,11 +160,14 @@ bool Channel::SetVolume(float vol)
float Channel::GetVolume()
{
ALfloat vol;
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return 0;
-
- alGetSourcef(mSource, AL_GAIN, &vol);
- if (alCheck()) {
+ }
+
+ alGetSourcef(m_source, AL_GAIN, &vol);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not get sound volume. Code: %d\n", alGetCode());
return 0;
}
@@ -144,125 +176,146 @@ float Channel::GetVolume()
}
+void Channel::SetVolumeAtrib(float volume)
+{
+ m_volume = volume;
+}
+
+
+float Channel::GetVolumeAtrib()
+{
+ return m_volume;
+}
+
+
+
int Channel::GetPriority()
{
- return mPriority;
+ return m_priority;
}
void Channel::SetPriority(int pri)
{
- mPriority = pri;
+ m_priority = pri;
}
void Channel::SetStartAmplitude(float gain)
{
- mStartAmplitude = gain;
- SetVolume(mStartAmplitude);
+ m_startAmplitude = gain;
}
void Channel::SetStartFrequency(float freq)
{
- mStartFrequency = freq;
+ m_startFrequency = freq;
}
void Channel::SetChangeFrequency(float freq)
{
- mChangeFrequency = freq;
+ m_changeFrequency = freq;
}
float Channel::GetStartAmplitude()
{
- return mStartAmplitude;
+ return m_startAmplitude;
}
float Channel::GetStartFrequency()
{
- return mStartFrequency;
+ return m_startFrequency;
}
float Channel::GetChangeFrequency()
{
- return mChangeFrequency;
+ return m_changeFrequency;
}
float Channel::GetInitFrequency()
{
- return mInitFrequency;
+ return m_initFrequency;
}
void Channel::AddOper(SoundOper oper)
{
- mOper.push_back(oper);
+ m_oper.push_back(oper);
}
void Channel::ResetOper()
{
- mOper.clear();
+ m_oper.clear();
}
-Sound Channel::GetSoundType() {
- if (!mReady || mBuffer == nullptr)
+Sound Channel::GetSoundType()
+{
+ if (!m_ready || m_buffer == nullptr)
+ {
return SOUND_NONE;
-
- return mBuffer->GetSoundType();
+ }
+
+ return m_buffer->GetSoundType();
}
-bool Channel::SetBuffer(Buffer *buffer) {
- if (!mReady)
+bool Channel::SetBuffer(Buffer *buffer)
+{
+ if (!m_ready)
return false;
- Stop();
- mBuffer = buffer;
- if (buffer == nullptr) {
- alSourcei(mSource, AL_BUFFER, 0);
+ Stop();
+ m_buffer = buffer;
+ if (buffer == nullptr)
+ {
+ alSourcei(m_source, AL_BUFFER, 0);
return true;
- }
-
- alSourcei(mSource, AL_BUFFER, buffer->GetBuffer());
- if (alCheck()) {
+ }
+
+ alSourcei(m_source, AL_BUFFER, buffer->GetBuffer());
+ if (alCheck())
+ {
GetLogger()->Warn("Could not set sound buffer. Code: %d\n", alGetCode());
return false;
}
- mInitFrequency = GetFrequency();
+ m_initFrequency = GetFrequency();
return true;
}
-bool Channel::FreeBuffer() {
- if (!mReady)
- return false;
-
- if (!mBuffer) {
+bool Channel::FreeBuffer()
+{
+ if (!m_ready || !m_buffer)
+ {
return false;
}
- alSourceStop(mSource);
- alSourcei(mSource, AL_BUFFER, 0);
- delete mBuffer;
- mBuffer = nullptr;
+ alSourceStop(m_source);
+ alSourcei(m_source, AL_BUFFER, 0);
+ delete m_buffer;
+ m_buffer = nullptr;
return true;
}
-bool Channel::IsPlaying() {
+bool Channel::IsPlaying()
+{
ALint status;
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return false;
-
- alGetSourcei(mSource, AL_SOURCE_STATE, &status);
- if (alCheck()) {
+ }
+
+ alGetSourcei(m_source, AL_SOURCE_STATE, &status);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not get sound status. Code: %d\n", alGetCode());
return false;
}
@@ -271,21 +324,27 @@ bool Channel::IsPlaying() {
}
-bool Channel::IsReady() {
- return mReady;
+bool Channel::IsReady()
+{
+ return m_ready;
}
-bool Channel::IsLoaded() {
- return mBuffer != nullptr;
+bool Channel::IsLoaded()
+{
+ return m_buffer != nullptr;
}
-bool Channel::Stop() {
- if (!mReady || mBuffer == nullptr)
+bool Channel::Stop()
+{
+ if (!m_ready || m_buffer == nullptr)
+ {
return false;
-
- alSourceStop(mSource);
- if (alCheck()) {
+ }
+
+ alSourceStop(m_source);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not stop sound. Code: %d\n", alGetCode());
return false;
}
@@ -295,12 +354,15 @@ bool Channel::Stop() {
float Channel::GetCurrentTime()
{
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return 0.0f;
-
+ }
+
ALfloat current;
- alGetSourcef(mSource, AL_SEC_OFFSET, &current);
- if (alCheck()) {
+ alGetSourcef(m_source, AL_SEC_OFFSET, &current);
+ if (alCheck())
+ {
GetLogger()->Warn("Could not get source current play time. Code: %d\n", alGetCode());
return 0.0f;
}
@@ -310,42 +372,62 @@ float Channel::GetCurrentTime()
void Channel::SetCurrentTime(float current)
{
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return;
-
- alSourcef(mSource, AL_SEC_OFFSET, current);
+ }
+
+ alSourcef(m_source, AL_SEC_OFFSET, current);
if (alCheck())
+ {
GetLogger()->Warn("Could not get source current play time. Code: %d\n", alGetCode());
+ }
}
float Channel::GetDuration()
{
- if (!mReady || mBuffer == nullptr)
+ if (!m_ready || m_buffer == nullptr)
+ {
return 0.0f;
-
- return mBuffer->GetDuration();
+ }
+
+ return m_buffer->GetDuration();
}
bool Channel::HasEnvelope()
{
- return mOper.size() > 0;
+ return m_oper.size() > 0;
}
SoundOper& Channel::GetEnvelope()
{
- return mOper.front();
+ return m_oper.front();
}
void Channel::PopEnvelope()
{
- mOper.pop_front();
+ m_oper.pop_front();
}
-void Channel::SetLoop(bool loop) {
- mLoop = loop;
+void Channel::SetLoop(bool loop)
+{
+ m_loop = loop;
+}
+
+
+void Channel::Mute(bool mute)
+{
+ m_mute = mute;
}
+
+
+bool Channel::IsMuted()
+{
+ return m_mute;
+}
+
diff --git a/src/sound/oalsound/channel.h b/src/sound/oalsound/channel.h
index 8965306..a04b509 100644
--- a/src/sound/oalsound/channel.h
+++ b/src/sound/oalsound/channel.h
@@ -14,10 +14,18 @@
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
-// channel.h
+/**
+ * \file channel.h
+ * \brief OpenAL channel
+ */
#pragma once
+#include "sound/sound.h"
+
+#include "sound/oalsound/buffer.h"
+#include "sound/oalsound/check.h"
+
#include <string>
#include <deque>
#include <cassert>
@@ -25,11 +33,6 @@
#include <AL/al.h>
#include <AL/alc.h>
-#include "sound/sound.h"
-
-#include "buffer.h"
-#include "check.h"
-
struct SoundOper
{
float finalAmplitude;
@@ -42,62 +45,73 @@ struct SoundOper
class Channel
{
- public:
- Channel();
- ~Channel();
-
- bool Play();
- bool Stop();
- bool SetPosition(Math::Vector);
-
- bool SetFrequency(float);
- float GetFrequency();
- bool AdjustFrequency(float);
-
- float GetCurrentTime();
- void SetCurrentTime(float);
- float GetDuration();
-
- bool SetVolume(float);
- float GetVolume();
- bool IsPlaying();
- bool IsReady();
- bool IsLoaded();
-
- bool SetBuffer(Buffer *);
- bool FreeBuffer();
-
- bool HasEnvelope();
- SoundOper& GetEnvelope();
- void PopEnvelope();
-
- int GetPriority();
- void SetPriority(int);
-
- void SetStartAmplitude(float);
- void SetStartFrequency(float);
- void SetChangeFrequency(float);
-
- float GetStartAmplitude();
- float GetStartFrequency();
- float GetChangeFrequency();
- float GetInitFrequency();
-
- void AddOper(SoundOper);
- void ResetOper();
- Sound GetSoundType();
- void SetLoop(bool);
-
- private:
- Buffer *mBuffer;
- ALuint mSource;
-
- int mPriority;
- float mStartAmplitude;
- float mStartFrequency;
- float mChangeFrequency;
- float mInitFrequency;
- std::deque<SoundOper> mOper;
- bool mReady;
- bool mLoop;
+public:
+ Channel();
+ ~Channel();
+
+ bool Play();
+ bool Stop();
+
+ bool SetPan(Math::Vector);
+ void SetPosition(Math::Vector);
+ Math::Vector GetPosition();
+
+ bool SetFrequency(float);
+ float GetFrequency();
+
+ float GetCurrentTime();
+ void SetCurrentTime(float);
+ float GetDuration();
+
+ bool SetVolume(float);
+ float GetVolume();
+ void SetVolumeAtrib(float);
+ float GetVolumeAtrib();
+
+ bool IsPlaying();
+ bool IsReady();
+ bool IsLoaded();
+
+ bool SetBuffer(Buffer *);
+ bool FreeBuffer();
+
+ bool HasEnvelope();
+ SoundOper& GetEnvelope();
+ void PopEnvelope();
+
+ int GetPriority();
+ void SetPriority(int);
+
+ void SetStartAmplitude(float);
+ void SetStartFrequency(float);
+ void SetChangeFrequency(float);
+
+ float GetStartAmplitude();
+ float GetStartFrequency();
+ float GetChangeFrequency();
+ float GetInitFrequency();
+
+ void AddOper(SoundOper);
+ void ResetOper();
+ Sound GetSoundType();
+ void SetLoop(bool);
+ void Mute(bool);
+ bool IsMuted();
+
+private:
+ Buffer *m_buffer;
+ ALuint m_source;
+
+ int m_priority;
+ float m_startAmplitude;
+ float m_startFrequency;
+ float m_changeFrequency;
+ float m_initFrequency;
+ float m_volume;
+ std::deque<SoundOper> m_oper;
+ bool m_ready;
+ bool m_loop;
+ bool m_mute;
+ Math::Vector m_position;
};
+
diff --git a/src/sound/oalsound/check.h b/src/sound/oalsound/check.h
index cf3e468..f677e17 100644
--- a/src/sound/oalsound/check.h
+++ b/src/sound/oalsound/check.h
@@ -37,3 +37,4 @@ inline ALenum alGetCode()
CODE = AL_NO_ERROR;
return ret;
}
+
diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp
new file mode 100644
index 0000000..d392612
--- /dev/null
+++ b/src/sound/sound.cpp
@@ -0,0 +1,191 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012-2013, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+#include "sound/sound.h"
+
+#include "math/vector.h"
+
+#include "common/logger.h"
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+#include <boost/filesystem.hpp>
+
+
+CSoundInterface::CSoundInterface()
+{
+}
+
+CSoundInterface::~CSoundInterface()
+{
+}
+
+bool CSoundInterface::Create(bool b3D)
+{
+ return true;
+}
+
+void CSoundInterface::CacheAll(std::string path)
+{
+ for ( int i = 1; i < SOUND_MAX; i++ )
+ {
+ std::stringstream filename;
+ filename << path << "/sound" << std::setfill('0') << std::setw(3) << i << ".wav";
+ if ( !Cache(static_cast<Sound>(i), filename.str()) )
+ GetLogger()->Warn("Unable to load audio: %s\n", filename.str().c_str());
+ }
+}
+
+void CSoundInterface::AddMusicFiles(std::string path)
+{
+ m_soundPath = path;
+ CacheMusic("Intro1.ogg");
+ CacheMusic("Intro2.ogg");
+ CacheMusic("music010.ogg");
+ CacheMusic("music011.ogg");
+}
+
+bool CSoundInterface::Cache(Sound bSound, std::string bFile)
+{
+ return true;
+}
+
+bool CSoundInterface::CacheMusic(std::string bFile)
+{
+ return true;
+}
+
+bool CSoundInterface::GetEnable()
+{
+ return true;
+}
+
+void CSoundInterface::SetSound3D(bool bMode)
+{
+}
+
+bool CSoundInterface::GetSound3D()
+{
+ return true;
+}
+
+bool CSoundInterface::GetSound3DCap()
+{
+ return true;
+}
+
+void CSoundInterface::SetAudioVolume(int volume)
+{
+}
+
+int CSoundInterface::GetAudioVolume()
+{
+ return 0;
+}
+
+void CSoundInterface::SetMusicVolume(int volume)
+{
+}
+
+int CSoundInterface::GetMusicVolume()
+{
+ return 0;
+}
+
+void CSoundInterface::SetListener(Math::Vector eye, Math::Vector lookat)
+{
+}
+
+void CSoundInterface::FrameMove(float rTime)
+{
+}
+
+int CSoundInterface::Play(Sound sound, float amplitude, float frequency, bool bLoop)
+{
+ return 0;
+}
+
+int CSoundInterface::Play(Sound sound, Math::Vector pos, float amplitude, float frequency, bool bLoop)
+{
+ return 0;
+}
+
+bool CSoundInterface::FlushEnvelope(int channel)
+{
+ return true;
+}
+
+bool CSoundInterface::AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper)
+{
+ return true;
+}
+
+bool CSoundInterface::Position(int channel, Math::Vector pos)
+{
+ return true;
+}
+
+bool CSoundInterface::Frequency(int channel, float frequency)
+{
+ return true;
+}
+
+bool CSoundInterface::Stop(int channel)
+{
+ return true;
+}
+
+bool CSoundInterface::StopAll()
+{
+ return true;
+}
+
+bool CSoundInterface::MuteAll(bool bMute)
+{
+ return true;
+}
+
+bool CSoundInterface::PlayMusic(int rank, bool bRepeat)
+{
+ return true;
+}
+
+bool CSoundInterface::PlayMusic(std::string filename, bool bRepeat)
+{
+ return true;
+}
+
+bool CSoundInterface::RestartMusic()
+{
+ return true;
+}
+
+void CSoundInterface::SuspendMusic()
+{
+}
+
+void CSoundInterface::StopMusic()
+{
+}
+
+bool CSoundInterface::IsPlayingMusic()
+{
+ return true;
+}
+
diff --git a/src/sound/sound.h b/src/sound/sound.h
index 70139ea..9ccc1b6 100644
--- a/src/sound/sound.h
+++ b/src/sound/sound.h
@@ -22,23 +22,16 @@
#pragma once
-#include <boost/filesystem.hpp>
-
#include "math/vector.h"
#include "common/logger.h"
#include <string>
-#include <iostream>
-#include <iomanip>
-#include <sstream>
-#include <map>
-
/*!
* Maximum possible audio volume
*/
-#define MAXVOLUME 100.0f
+const float MAXVOLUME = 100.0f;
/**
@@ -48,7 +41,7 @@
**/
enum Sound
{
- SOUND_NONE = -1,
+ SOUND_NONE = -1,
SOUND_CLICK = 0,
SOUND_BOUM = 1,
SOUND_EXPLO = 2,
@@ -130,7 +123,8 @@ enum Sound
SOUND_FIREp = 78, /*!< shooting with phazer */
SOUND_EXPLOg1 = 79, /*!< impact gun 1 */
SOUND_EXPLOg2 = 80, /*!< impact gun 2 */
- SOUND_MOTORd = 81, /*!< engine friction */
+// SOUND_MOTORd = 81, /*!< engine friction */
+ SOUND_MAX /** number of items in enum */
};
@@ -154,95 +148,88 @@ enum SoundNext
*/
class CSoundInterface
{
- public:
- inline CSoundInterface() {}
- inline virtual ~CSoundInterface() {}
+public:
+ CSoundInterface();
+ virtual ~CSoundInterface();
/** Function to initialize sound device
* \param b3D - enable support for 3D sound
*/
- inline virtual bool Create(bool b3D) { return true; };
+ virtual bool Create(bool b3D);
/** Function called to cache all sound effect files.
* Function calls \link CSoundInterface::Cache() \endlink for each file
*/
- inline void CacheAll(std::string path) {
- for ( int i = 1; i <= 81; i++ ) {
- std::stringstream filename;
- filename << path << "/sound" << std::setfill('0') << std::setw(3) << i << ".wav";
- if ( !Cache(static_cast<Sound>(i), filename.str()) )
- GetLogger()->Warn("Unable to load audio: %s\n", filename.str().c_str());
- }
- };
+ void CacheAll(std::string path);
/** Function called to add all music files to list */
- inline void AddMusicFiles(std::string path) {
- for ( int i = 1; i <= 12; i++ ) {
- std::stringstream filename;
- filename << path << "/music" << std::setfill('0') << std::setw(3) << i << ".ogg";
- if (boost::filesystem::exists(filename.str()))
- mMusic[i] = filename.str();
- }
- };
-
+ void AddMusicFiles(std::string path);
+
/** Function called to cache sound effect file.
* This function is called by plugin interface for each file.
* \param bSound - id of a file, will be used to identify sound files
* \param bFile - file to load
* \return return true on success
*/
- inline virtual bool Cache(Sound bSound, std::string bFile) { return true; };
+ virtual bool Cache(Sound bSound, std::string bFile);
+
+ /** Function called to cache music file.
+ * This function is called by CRobotMain for each file used in the mission.
+ * \param bFile - file to load
+ * \return return true on success
+ */
+ virtual bool CacheMusic(std::string bFile);
/** Return if plugin is enabled
* \return return true if plugin is enabled
*/
- inline virtual bool GetEnable() {return true;};
+ virtual bool GetEnable();
/** Change sound mode to 2D/3D
* \param bMode - true to enable 3D sound
*/
- inline virtual void SetSound3D(bool bMode) {};
+ virtual void SetSound3D(bool bMode);
/** Return if we use 3D sound
* \return true if we have 3D sound enabled
*/
- inline virtual bool GetSound3D() {return true;};
+ virtual bool GetSound3D();
/** Return if we have 3D sound capable card
* \return true for 3D sound support
*/
- inline virtual bool GetSound3DCap() {return true;};
+ virtual bool GetSound3DCap();
/** Change global sound volume
* \param volume - range from 0 to MAXVOLUME
*/
- inline virtual void SetAudioVolume(int volume) {};
+ virtual void SetAudioVolume(int volume);
/** Return global sound volume
* \return global volume as int in range from 0 to MAXVOLUME
*/
- inline virtual int GetAudioVolume() {return 0;};
+ virtual int GetAudioVolume();
/** Set music volume
* \param volume - range from 0 to MAXVOLUME
*/
- inline virtual void SetMusicVolume(int volume) {};
+ virtual void SetMusicVolume(int volume);
/** Return music volume
* \return music volume as int in range from 0 to MAXVOLUME
*/
- inline virtual int GetMusicVolume() {return 0;};
+ virtual int GetMusicVolume();
/** Set listener position
* \param eye - position of listener
* \param lookat - direction listener is looking at
*/
- inline virtual void SetListener(Math::Vector eye, Math::Vector lookat) {};
+ virtual void SetListener(Math::Vector eye, Math::Vector lookat);
/** Update data each frame
* \param rTime - time since last update
*/
- inline virtual void FrameMove(float rTime) {};
+ virtual void FrameMove(float rTime);
/** Play specific sound
* \param sound - sound to play
@@ -251,7 +238,7 @@ class CSoundInterface
* \param bLoop - loop sound
* \return identifier of channel that sound will be played on
*/
- inline virtual int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false) {return 0;};
+ virtual int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
/** Play specific sound
* \param sound - sound to play
@@ -261,13 +248,13 @@ class CSoundInterface
* \param bLoop - loop sound
* \return identifier of channel that sound will be played on
*/
- inline virtual int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false) {return 0;};
+ virtual int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop = false);
/** Remove all operations that would be made on sound in channel.
* \param channel - channel to work on
* \return return true on success
*/
- inline virtual bool FlushEnvelope(int channel) {return true;};
+ virtual bool FlushEnvelope(int channel);
/** Add envelope to sound. Envelope is a operatino that will be performend on sound in future like changing frequency
* \param channel - channel to work on
@@ -277,67 +264,74 @@ class CSoundInterface
* \param oper - operation to perform
* \return return true on success
*/
- inline virtual bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper) {return true;};
+ virtual bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
/** Set sound position in space
* \param channel - channel to work on
* \param pos - new positino of a sound
* \return return true on success
*/
- inline virtual bool Position(int channel, Math::Vector pos) {return true;};
+ virtual bool Position(int channel, Math::Vector pos);
/** Set sound frequency
* \param channel - channel to work on
* \param frequency - change sound frequency
* \return return true on success
*/
- inline virtual bool Frequency(int channel, float frequency) {return true;};
+ virtual bool Frequency(int channel, float frequency);
/** Stop playing sound
* \param channel - channel to work on
* \return return true on success
*/
- inline virtual bool Stop(int channel) {return true;};
+ virtual bool Stop(int channel);
/** Stop playing all sounds
* \return return true on success
*/
- inline virtual bool StopAll() {return true;};
+ virtual bool StopAll();
/** Mute/unmute all sounds
* \param bMute
* \return return true on success
*/
- inline virtual bool MuteAll(bool bMute) {return true;};
+ virtual bool MuteAll(bool bMute);
/** Start playing music
* \param rank - track number
* \param bRepeat - repeat playing
* \return return true on success
*/
- inline virtual bool PlayMusic(int rank, bool bRepeat) {return true;};
+ virtual bool PlayMusic(int rank, bool bRepeat);
+
+ /** Start playing music
+ * \param filename - name of file to play
+ * \param bRepeat - repeat playing
+ * \return return true on success
+ */
+ virtual bool PlayMusic(std::string filename, bool bRepeat);
/** Restart music
* @return return true on success
*/
- inline virtual bool RestartMusic() {return true;};
+ virtual bool RestartMusic();
/** Susspend paying music
* \return return true on success
*/
- inline virtual void SuspendMusic() {};
+ virtual void SuspendMusic();
/** Stop playing music
* \return return true on success
*/
- inline virtual void StopMusic() {};
+ virtual void StopMusic();
/** Check if music if playing
* \return return true if music is playing
*/
- inline virtual bool IsPlayingMusic() {return true;};
+ virtual bool IsPlayingMusic();
- protected:
- std::map<int, std::string> mMusic;
+protected:
+ std::string m_soundPath;
};
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index 0be2bd5..da590d8 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -12,3 +12,4 @@ include_directories(SYSTEM ${SDL_INCLUDE_DIR})
add_definitions(-DMODELFILE_NO_ENGINE)
add_executable(convert_model ${CONVERT_MODEL_SOURCES})
+
diff --git a/src/tools/README.txt b/src/tools/README.txt
index de2f087..3de9e75 100644
--- a/src/tools/README.txt
+++ b/src/tools/README.txt
@@ -2,3 +2,4 @@
* \dir tools
* \brief Various tools (separate programs)
*/
+
diff --git a/src/tools/convert_model.cpp b/src/tools/convert_model.cpp
index 463b83a..57e8789 100644
--- a/src/tools/convert_model.cpp
+++ b/src/tools/convert_model.cpp
@@ -279,3 +279,4 @@ int main(int argc, char *argv[])
return 0;
}
+
diff --git a/src/ui/README.txt b/src/ui/README.txt
index a159ed5..05f72a1 100644
--- a/src/ui/README.txt
+++ b/src/ui/README.txt
@@ -2,3 +2,4 @@
* \dir src/ui
* \brief 2D user interface controls
*/
+
diff --git a/src/ui/button.cpp b/src/ui/button.cpp
index a68b34d..348382d 100644
--- a/src/ui/button.cpp
+++ b/src/ui/button.cpp
@@ -245,3 +245,4 @@ bool CButton::GetRepeat()
}
}
+
diff --git a/src/ui/button.h b/src/ui/button.h
index a9aa020..b71ef4a 100644
--- a/src/ui/button.h
+++ b/src/ui/button.h
@@ -51,3 +51,4 @@ protected:
};
}
+
diff --git a/src/ui/check.cpp b/src/ui/check.cpp
index 761264d..362c930 100644
--- a/src/ui/check.cpp
+++ b/src/ui/check.cpp
@@ -163,3 +163,4 @@ void CCheck::Draw()
}
}
+
diff --git a/src/ui/color.cpp b/src/ui/color.cpp
index fd05bd9..623ff89 100644
--- a/src/ui/color.cpp
+++ b/src/ui/color.cpp
@@ -223,3 +223,4 @@ Gfx::Color CColor::GetColor()
}
+
diff --git a/src/ui/color.h b/src/ui/color.h
index ec2c537..fe96b87 100644
--- a/src/ui/color.h
+++ b/src/ui/color.h
@@ -54,3 +54,4 @@ protected:
};
}
+
diff --git a/src/ui/compass.cpp b/src/ui/compass.cpp
index ac97cb8..d0fe96f 100644
--- a/src/ui/compass.cpp
+++ b/src/ui/compass.cpp
@@ -171,3 +171,4 @@ float CCompass::GetDirection()
}
+
diff --git a/src/ui/compass.h b/src/ui/compass.h
index 18546e5..956631a 100644
--- a/src/ui/compass.h
+++ b/src/ui/compass.h
@@ -49,3 +49,4 @@ protected:
}
+
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 6dc92cd..7c77c95 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -75,10 +75,13 @@ bool CControl::Create(Math::Point pos, Math::Point dim, int icon, EventType even
GetResource(RES_EVENT, m_eventType, text);
str_text = std::string(text);
auto p = str_text.find("\\");
- if ( p == std::string::npos ) {
+ if ( p == std::string::npos )
+ {
if ( icon != -1 )
m_tooltip = str_text;
- } else {
+ }
+ else
+ {
m_tooltip = str_text.substr(p + 1);
}
@@ -174,15 +177,18 @@ int CControl::GetIcon()
void CControl::SetName(std::string name, bool bTooltip)
{
- if ( bTooltip ) {
+ if ( bTooltip )
+ {
auto p = name.find("\\");
if ( p == std::string::npos )
m_name = name;
- else {
+ else
+ {
m_tooltip = name.substr(p + 1);
m_name = name.substr(0, p);
}
- } else
+ }
+ else
m_name = name;
}
@@ -832,3 +838,4 @@ bool CControl::Detect(Math::Point pos)
}
}
+
diff --git a/src/ui/control.h b/src/ui/control.h
index 7f5077d..aee7d1c 100644
--- a/src/ui/control.h
+++ b/src/ui/control.h
@@ -141,3 +141,4 @@ protected:
};
} // namespace Ui
+
diff --git a/src/ui/displayinfo.cpp b/src/ui/displayinfo.cpp
index fcc77db..3aa3d73 100644
--- a/src/ui/displayinfo.cpp
+++ b/src/ui/displayinfo.cpp
@@ -154,28 +154,28 @@ bool CDisplayInfo::EventProcess(const Event &event)
{
m_main->SetFontSize(9.0f);
slider = static_cast<Ui::CSlider*>(pw->SearchControl(EVENT_STUDIO_SIZE));
- if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/6.0f);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/12.0f);
ViewDisplayInfo();
}
if ( event.type == EVENT_HYPER_SIZE2 ) // size 2?
{
m_main->SetFontSize(10.0f);
slider = static_cast<Ui::CSlider*>(pw->SearchControl(EVENT_STUDIO_SIZE));
- if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/6.0f);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/12.0f);
ViewDisplayInfo();
}
if ( event.type == EVENT_HYPER_SIZE3 ) // size 3?
{
m_main->SetFontSize(12.0f);
slider = static_cast<Ui::CSlider*>(pw->SearchControl(EVENT_STUDIO_SIZE));
- if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/6.0f);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/12.0f);
ViewDisplayInfo();
}
if ( event.type == EVENT_HYPER_SIZE4 ) // size 4?
{
m_main->SetFontSize(15.0f);
slider = static_cast<Ui::CSlider*>(pw->SearchControl(EVENT_STUDIO_SIZE));
- if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/6.0f);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->GetFontSize()-9.0f)/12.0f);
ViewDisplayInfo();
}
@@ -183,7 +183,7 @@ bool CDisplayInfo::EventProcess(const Event &event)
{
slider = static_cast<Ui::CSlider*>(pw->SearchControl(EVENT_STUDIO_SIZE));
if ( slider == 0 ) return false;
- m_main->SetFontSize(9.0f+slider->GetVisibleValue()*6.0f);
+ m_main->SetFontSize(9.0f+slider->GetVisibleValue()*12.0f);
ViewDisplayInfo();
}
@@ -1214,3 +1214,4 @@ void CDisplayInfo::CreateObjectsFile()
}
+
diff --git a/src/ui/displayinfo.h b/src/ui/displayinfo.h
index ab42d62..eea50b7 100644
--- a/src/ui/displayinfo.h
+++ b/src/ui/displayinfo.h
@@ -95,3 +95,4 @@ protected:
} // namespace Ui
+
diff --git a/src/ui/displaytext.cpp b/src/ui/displaytext.cpp
index 630b385..d88674a 100644
--- a/src/ui/displaytext.cpp
+++ b/src/ui/displaytext.cpp
@@ -606,3 +606,4 @@ CObject* CDisplayText::SearchToto()
}
}
+
diff --git a/src/ui/edit.cpp b/src/ui/edit.cpp
index e60a040..6fd1735 100644
--- a/src/ui/edit.cpp
+++ b/src/ui/edit.cpp
@@ -20,6 +20,8 @@
#include "app/app.h"
+#include "clipboard/clipboard.h"
+
#include <string.h>
namespace Ui {
@@ -261,7 +263,7 @@ bool CEdit::EventProcess(const Event &event)
if ( event.type == EVENT_MOUSE_MOVE )
{
- if ( Detect(event.mousePos) &&
+ if ( Detect(event.mousePos) &&
event.mousePos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
{
if ( m_bEdit )
@@ -298,55 +300,53 @@ bool CEdit::EventProcess(const Event &event)
bShift = ( (event.kmodState & KEY_MOD(SHIFT) ) != 0 );
bControl = ( (event.kmodState & KEY_MOD(CTRL) ) != 0);
- if ( (event.key.unicode == 'X' && !bShift && bControl) ||
- ((event.kmodState & KEY_MOD(CTRL)) != 0 && bShift && !bControl) )
+ if ( (event.key.key == KEY(x) && !bShift && bControl) ||
+ (event.key.key == KEY(DELETE) && bShift && !bControl) )
{
Cut();
return true;
}
- if ( (event.key.unicode == 'C' && !bShift && bControl) ||
- ((event.kmodState & KEY_MOD(CTRL)) != 0 && !bShift && bControl) )
+ if ( (event.key.key == KEY(c) && !bShift && bControl) ||
+ (event.key.key == KEY(INSERT) && !bShift && bControl) )
{
Copy();
return true;
}
- if ( (event.key.unicode == 'V' && !bShift && bControl) ||
- ((event.kmodState & KEY_MOD(CTRL)) != 0 && bShift && !bControl) )
+ if ( (event.key.key == KEY(v) && !bShift && bControl) ||
+ (event.key.key == KEY(INSERT) && bShift && !bControl) )
{
Paste();
return true;
}
- if ( event.key.unicode == 'A' && !bShift && bControl )
+ if ( event.key.key == KEY(a) && !bShift && bControl )
{
SetCursor(999999, 0);
return true;
}
- if ( event.key.unicode == 'O' && !bShift && bControl )
+ if ( event.key.key == KEY(o) && !bShift && bControl )
{
Event newEvent(EVENT_STUDIO_OPEN);
-// m_event->NewEvent(newEvent, EVENT_STUDIO_OPEN);
m_event->AddEvent(newEvent);
}
- if ( event.key.unicode == 'S' && !bShift && bControl )
+ if ( event.key.key == KEY(s) && !bShift && bControl )
{
Event newEvent( EVENT_STUDIO_SAVE );
-// m_event->MakeEvent(newEvent, EVENT_STUDIO_SAVE);
m_event->AddEvent(newEvent);
}
- if ( event.key.unicode == 'Z' && !bShift && bControl )
+ if ( event.key.key == KEY(z) && !bShift && bControl )
{
Undo();
return true;
}
- if ( event.key.unicode == 'U' && !bShift && bControl )
+ if ( event.key.key == KEY(u) && !bShift && bControl )
{
if ( MinMaj(false) ) return true;
}
- if ( event.key.unicode == 'U' && bShift && bControl )
+ if ( event.key.key == KEY(u) && bShift && bControl )
{
if ( MinMaj(true) ) return true;
}
@@ -688,7 +688,7 @@ void CEdit::MouseMove(Math::Point mouse)
int CEdit::MouseDetect(Math::Point mouse)
{
Math::Point pos;
- float indentLength, offset, size;
+ float indentLength = 0.0f, offset, size;
int i, len, c;
bool bTitle;
@@ -782,13 +782,16 @@ void CEdit::HyperJump(std::string name, std::string marker)
sMarker = marker;
//? sprintf(filename, "help\\%s.txt", name);
-
- if ( name[0] == '%' ) {
+
+ if ( name[0] == '%' )
+ {
filename = GetProfile().GetUserBasedPath(name, "") + ".txt";
- } else {
+ }
+ else
+ {
filename = std::string("help/") + CApplication::GetInstancePointer()->GetLanguageChar() + "/" + name + std::string(".txt");
}
-
+
if ( ReadText(filename) )
{
Justif();
@@ -886,7 +889,7 @@ bool CEdit::HyperGo(EventType event)
void CEdit::Draw()
{
Math::Point pos, ppos, dim, start, end;
- float size, indentLength;
+ float size = 0.0f, indentLength = 0.0f;
int i, j, beg, len, c1, c2, o1, o2, eol, iIndex, line;
if ( (m_state & STATE_VISIBLE) == 0 ) return;
@@ -1249,7 +1252,7 @@ void CEdit::SetText(const char *text, bool bNew)
{
int i, j, font;
bool bBOL;
-
+
if ( !bNew ) UndoMemorize(OPERUNDO_SPEC);
m_len = strlen(text);
@@ -1387,10 +1390,11 @@ int CEdit::GetTextLength()
std::string GetNameParam(std::string cmd, int rank)
{
- std::vector<std::string> results;
+ std::vector<std::string> results;
boost::split(results, cmd, boost::is_any_of(" ;"));
-
- if (results.size() > static_cast<unsigned int>(rank)) {
+
+ if (results.size() > static_cast<unsigned int>(rank))
+ {
return results.at(rank);
}
@@ -1402,11 +1406,12 @@ std::string GetNameParam(std::string cmd, int rank)
int GetValueParam(std::string cmd, int rank)
{
- std::vector<std::string> results;
+ 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)) {
+
+ if (results.size() > static_cast<unsigned int>(rank))
+ {
return_value = atoi(results.at(rank).c_str());
}
@@ -1419,7 +1424,8 @@ void CEdit::FreeImage()
{
std::string filename;
- for (int i = 0 ; i < m_imageTotal; i++ ) {
+ for (int i = 0 ; i < m_imageTotal; i++ )
+ {
filename = GetProfile().GetUserBasedPath(m_image[i].name, "diagram") + ".png";
m_engine->DeleteTexture(filename);
}
@@ -1448,12 +1454,14 @@ bool CEdit::ReadText(std::string filename, int addSize)
bool bInSoluce, bBOL;
if ( filename[0] == 0 ) return false;
+
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)) {
+ if (!fs::exists(path))
+ {
path = CApplication::GetInstancePointer()->GetDataDirPath() + "/" + filename;
}
@@ -1484,10 +1492,11 @@ bool CEdit::ReadText(std::string filename, int addSize)
m_format.clear();
m_format.reserve(m_maxChar+1);
- for (i = 0; i <= m_maxChar+1; i++) {
+ for (i = 0; i <= m_maxChar+1; i++)
+ {
m_format.push_back(0);
}
-
+
fclose(file);
bInSoluce = false;
@@ -1877,7 +1886,7 @@ bool CEdit::WriteText(std::string filename)
FILE* file;
char buffer[1000+20];
int i, j, k, n;
- float iDim;
+ float iDim = 0.0f;
if ( filename[0] == 0 ) return false;
file = fopen(filename.c_str(), "wb");
@@ -1951,7 +1960,8 @@ void CEdit::SetMaxChar(int max)
m_format.clear();
m_format.reserve(m_maxChar+1);
- for (int i = 0; i <= m_maxChar+1; i++) {
+ for (int i = 0; i <= m_maxChar+1; i++)
+ {
m_format.push_back(0);
}
@@ -2142,10 +2152,12 @@ bool CEdit::GetDisplaySpec()
void CEdit::SetMultiFont(bool bMulti)
{
m_format.clear();
-
- if (bMulti) {
+
+ if (bMulti)
+ {
m_format.reserve(m_maxChar+1);
- for (int i = 0; i <= m_maxChar+1; i++) {
+ for (int i = 0; i <= m_maxChar+1; i++)
+ {
m_format.push_back(0);
}
}
@@ -2397,7 +2409,7 @@ void CEdit::MoveChar(int move, bool bWord, bool bSelect)
void CEdit::MoveLine(int move, bool bWord, bool bSelect)
{
- float column, indentLength;
+ float column, indentLength = 0.0f;
int i, line, c;
if ( move == 0 ) return;
@@ -2501,200 +2513,113 @@ void CEdit::ColumnFix()
// Cut the selected characters or entire line.
-bool CEdit::Cut() // TODO MS Windows allocations
+bool CEdit::Cut()
{
- /* HGLOBAL hg;
- char* text;
- char c;
- int c1, c2, start, len, i, j;
-
- if ( !m_bEdit ) return false;
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( c1 == c2 )
- {
- while ( c1 > 0 )
- {
- if ( m_text[c1-1] == '\n' ) break;
- c1 --;
- }
- while ( c2 < m_len )
- {
- c2 ++;
- if ( m_text[c2-1] == '\n' ) break;
- }
- }
-
- if ( c1 == c2 ) return false;
-
- start = c1;
- len = c2-c1;
-
- if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
- {
- return false;
- }
- if ( !(text = (char*)GlobalLock(hg)) )
- {
- GlobalFree(hg);
- return false;
- }
-
- j = 0;
- for ( i=start ; i<start+len ; i++ )
- {
- c = m_text[i];
- if ( c == '\n' ) text[j++] = '\r';
- text[j++] = c;
- }
- text[j] = 0;
- GlobalUnlock(hg);
-
- if ( !OpenClipboard(NULL) )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !EmptyClipboard() )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !SetClipboardData(CF_TEXT, hg) )
- {
- GlobalFree(hg);
- return false;
- }
- CloseClipboard();
-
UndoMemorize(OPERUNDO_SPEC);
- m_cursor1 = c1;
- m_cursor2 = c2;
+ Copy(true);
+
DeleteOne(0); // deletes the selected characters
Justif();
ColumnFix();
- SendModifEvent();*/
+ SendModifEvent();
return true;
}
// Copy the selected characters or entire line.
-bool CEdit::Copy() // TODO
+bool CEdit::Copy(bool memorize_cursor)
{
- /* HGLOBAL hg;
- char* text;
- char c;
- int c1, c2, start, len, i, j;
+ int c1, c2, start, len;
+ char *text;
c1 = m_cursor1;
c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
+ if ( c1 > c2 )
+ {
+ Math::Swap(c1, c2); // always c1 <= c2
+ }
if ( c1 == c2 )
{
while ( c1 > 0 )
{
- if ( m_text[c1-1] == '\n' ) break;
- c1 --;
+ if ( m_text[c1 - 1] == '\n' )
+ {
+ break;
+ }
+ c1--;
}
while ( c2 < m_len )
{
- c2 ++;
- if ( m_text[c2-1] == '\n' ) break;
+ c2++;
+ if ( m_text[c2 - 1] == '\n' )
+ {
+ break;
+ }
}
}
- if ( c1 == c2 ) return false;
-
- start = c1;
- len = c2-c1;
-
- if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
- {
- return false;
- }
- if ( !(text = (char*)GlobalLock(hg)) )
+ if ( c1 == c2 )
{
- GlobalFree(hg);
return false;
}
- j = 0;
- for ( i=start ; i<start+len ; i++ )
- {
- c = m_text[i];
- if ( c == '\n' ) text[j++] = '\r';
- text[j++] = c;
- }
- text[j] = 0;
- GlobalUnlock(hg);
+ start = c1;
+ len = c2 - c1;
- if ( !OpenClipboard(NULL) )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !EmptyClipboard() )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !SetClipboardData(CF_TEXT, hg) )
+ text = new char[len + 1];
+ strncpy(text, m_text + start, len);
+ text[len] = 0;
+ widgetSetClipboardText(text);
+ delete []text;
+
+ if (memorize_cursor)
{
- GlobalFree(hg);
- return false;
+ m_cursor1 = c1;
+ m_cursor2 = c2;
}
- CloseClipboard();
-*/
+
return true;
}
// Paste the contents of the notebook.
-bool CEdit::Paste() // TODO
+bool CEdit::Paste()
{
- /*HANDLE h;
char c;
- char* p;
-
- if ( !m_bEdit ) return false;
+ char* text;
- if ( !OpenClipboard(NULL) )
+ if ( !m_bEdit )
{
return false;
}
- if ( !(h = GetClipboardData(CF_TEXT)) )
- {
- CloseClipboard();
- return false;
- }
+ text = widgetGetClipboardText();
- if ( !(p = (char*)GlobalLock(h)) )
+ if ( text == nullptr )
{
- CloseClipboard();
return false;
}
UndoMemorize(OPERUNDO_SPEC);
-
- while ( *p != 0 )
+ for ( unsigned int i = 0; i < strlen(text); i++ )
{
- c = *p++;
- if ( c == '\r' ) continue;
- if ( c == '\t' && m_bAutoIndent ) continue;
+ c = text[i];
+ if ( c == '\r' )
+ {
+ continue;
+ }
+ if ( c == '\t' && m_bAutoIndent )
+ {
+ continue;
+ }
InsertOne(c);
}
- GlobalUnlock(h);
- CloseClipboard();
-
+ free(text);
Justif();
ColumnFix();
- SendModifEvent();*/
+ SendModifEvent();
return true;
}
@@ -2703,7 +2628,10 @@ bool CEdit::Paste() // TODO
bool CEdit::Undo()
{
- if ( !m_bEdit ) return false;
+ if ( !m_bEdit )
+ {
+ return false;
+ }
return UndoRecall();
}
@@ -2715,7 +2643,10 @@ void CEdit::Insert(char character)
{
int i, level, tab;
- if ( !m_bEdit ) return;
+ if ( !m_bEdit )
+ {
+ return;
+ }
if ( !m_bMulti ) // single-line?
{
@@ -3052,7 +2983,7 @@ bool CEdit::MinMaj(bool bMaj)
void CEdit::Justif()
{
- float width, size, indentLength;
+ float width, size, indentLength = 0.0f;
int i, j, line, indent;
bool bDual, bString, bRem;
@@ -3315,7 +3246,7 @@ bool CEdit::SetFormat(int cursor1, int cursor2, int format)
void CEdit::UpdateScroll()
{
float value;
-
+
if ( m_scroll != nullptr )
{
if ( m_lineTotal <= m_lineVisible )
@@ -3339,3 +3270,4 @@ void CEdit::UpdateScroll()
}
}
+
diff --git a/src/ui/edit.h b/src/ui/edit.h
index 1cfec80..acdf72c 100644
--- a/src/ui/edit.h
+++ b/src/ui/edit.h
@@ -184,7 +184,7 @@ public:
bool GetMultiFont();
bool Cut();
- bool Copy();
+ bool Copy(bool memorize_cursor = false);
bool Paste();
bool Undo();
@@ -239,7 +239,7 @@ protected:
void UndoFlush();
void UndoMemorize(OperUndo oper);
bool UndoRecall();
-
+
void UpdateScroll();
protected:
@@ -294,3 +294,4 @@ protected:
}
+
diff --git a/src/ui/editvalue.cpp b/src/ui/editvalue.cpp
index 6397a73..3fb9b79 100644
--- a/src/ui/editvalue.cpp
+++ b/src/ui/editvalue.cpp
@@ -369,3 +369,4 @@ float CEditValue::GetMaxValue()
}
}
+
diff --git a/src/ui/editvalue.h b/src/ui/editvalue.h
index 5d6e643..2734847 100644
--- a/src/ui/editvalue.h
+++ b/src/ui/editvalue.h
@@ -85,3 +85,4 @@ protected:
}
+
diff --git a/src/ui/gauge.cpp b/src/ui/gauge.cpp
index c98e3b6..a8ee41c 100644
--- a/src/ui/gauge.cpp
+++ b/src/ui/gauge.cpp
@@ -144,3 +144,4 @@ float CGauge::GetLevel()
}
+
diff --git a/src/ui/gauge.h b/src/ui/gauge.h
index a2b689a..3dbeef8 100644
--- a/src/ui/gauge.h
+++ b/src/ui/gauge.h
@@ -31,24 +31,23 @@ namespace Ui {
class CGauge : public CControl
{
- public:
- CGauge();
- virtual ~CGauge();
+public:
+ CGauge();
+ virtual ~CGauge();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventType);
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventType);
- bool EventProcess(const Event &event);
+ bool EventProcess(const Event &event);
- void Draw();
+ void Draw();
- void SetLevel(float level);
- float GetLevel();
+ void SetLevel(float level);
+ float GetLevel();
- protected:
-
- protected:
- float m_level;
+protected:
+ float m_level;
};
}
+
diff --git a/src/ui/group.cpp b/src/ui/group.cpp
index c3c7028..908ac19 100644
--- a/src/ui/group.cpp
+++ b/src/ui/group.cpp
@@ -639,3 +639,4 @@ void CGroup::Draw()
}
+
diff --git a/src/ui/group.h b/src/ui/group.h
index fd31716..89996cc 100644
--- a/src/ui/group.h
+++ b/src/ui/group.h
@@ -46,3 +46,4 @@ protected:
}
+
diff --git a/src/ui/image.cpp b/src/ui/image.cpp
index 94b9586..9a14789 100644
--- a/src/ui/image.cpp
+++ b/src/ui/image.cpp
@@ -151,3 +151,4 @@ void CImage::Draw()
}
+
diff --git a/src/ui/image.h b/src/ui/image.h
index c40828c..fd71e33 100644
--- a/src/ui/image.h
+++ b/src/ui/image.h
@@ -52,3 +52,4 @@ protected:
}
+
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index 24d2626..845579e 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -47,8 +47,10 @@ CInterface::~CInterface()
void CInterface::Flush()
{
- for (int i = 0; i < MAXCONTROL; i++ ) {
- if ( m_table[i] != nullptr ) {
+ for (int i = 0; i < MAXCONTROL; i++ )
+ {
+ if ( m_table[i] != nullptr )
+ {
delete m_table[i];
m_table[i] = nullptr;
}
@@ -58,7 +60,8 @@ void CInterface::Flush()
int CInterface::GetNextFreeControl()
{
- for (int i = 10; i < MAXCONTROL-1; i++) {
+ for (int i = 10; i < MAXCONTROL-1; i++)
+ {
if (m_table[i] == nullptr)
return i;
}
@@ -92,7 +95,8 @@ CWindow* CInterface::CreateWindows(Math::Point pos, Math::Point dim, int icon, E
if (eventMsg == EVENT_NULL)
eventMsg = GetUniqueEventType();
- switch (eventMsg) {
+ switch (eventMsg)
+ {
case EVENT_WINDOW0: index = 0; break;
case EVENT_WINDOW1: index = 1; break;
case EVENT_WINDOW2: index = 2; break;
@@ -197,6 +201,9 @@ CSlider* CInterface::CreateSlider(Math::Point pos, Math::Point dim, int icon, Ev
}
// Creates a new list.
+// if expand is less then zero, then the list would try to use expand's absolute value,
+// and try to scale items to some size, so that dim of the list would not change after
+// adjusting
CList* CInterface::CreateList(Math::Point pos, Math::Point dim, int icon, EventType eventMsg, float expand)
{
@@ -246,9 +253,12 @@ CMap* CInterface::CreateMap(Math::Point pos, Math::Point dim, int icon, EventTyp
bool CInterface::DeleteControl(EventType eventMsg)
{
- for (int i = 0; i < MAXCONTROL; i++) {
- if ( m_table[i] != nullptr ) {
- if (eventMsg == m_table[i]->GetEventType()) {
+ for (int i = 0; i < MAXCONTROL; i++)
+ {
+ if ( m_table[i] != nullptr )
+ {
+ if (eventMsg == m_table[i]->GetEventType())
+ {
delete m_table[i];
m_table[i] = nullptr;
return true;
@@ -262,8 +272,10 @@ bool CInterface::DeleteControl(EventType eventMsg)
CControl* CInterface::SearchControl(EventType eventMsg)
{
- for (int i = 0; i < MAXCONTROL; i++) {
- if (m_table[i] != nullptr) {
+ for (int i = 0; i < MAXCONTROL; i++)
+ {
+ if (m_table[i] != nullptr)
+ {
if (eventMsg == m_table[i]->GetEventType())
return m_table[i];
}
@@ -323,4 +335,5 @@ void CInterface::Draw()
}
}
-}
+} // namespace Ui
+
diff --git a/src/ui/interface.h b/src/ui/interface.h
index ebc80e7..d5734f0 100644
--- a/src/ui/interface.h
+++ b/src/ui/interface.h
@@ -55,48 +55,49 @@ const int MAXCONTROL = 100;
class CInterface
{
- public:
- CInterface();
- ~CInterface();
-
- bool EventProcess(const Event &event);
- bool GetTooltip(Math::Point pos, std::string &name);
-
- void Flush();
- CButton* CreateButton(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CColor* CreateColor(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CCheck* CreateCheck(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CKey* CreateKey(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CGroup* CreateGroup(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CImage* CreateImage(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CEdit* CreateEdit(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CEditValue* CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CScroll* CreateScroll(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CSlider* CreateSlider(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CShortcut* CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CCompass* CreateCompass(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CTarget* CreateTarget(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CMap* CreateMap(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
-
- CWindow* CreateWindows(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- CList* CreateList(Math::Point pos, Math::Point dim, int icon, EventType eventMsg, float expand=1.2f);
- CLabel* CreateLabel(Math::Point pos, Math::Point dim, int icon, EventType eventMsg, std::string name);
-
- bool DeleteControl(EventType eventMsg);
- CControl* SearchControl(EventType eventMsg);
-
- void Draw();
-
- protected:
- int GetNextFreeControl();
- template <typename T> inline T* CreateControl(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
-
- CEventQueue* m_event;
- Gfx::CEngine* m_engine;
- Gfx::CCamera* m_camera;
-
- CControl* m_table[MAXCONTROL];
+public:
+ CInterface();
+ ~CInterface();
+
+ bool EventProcess(const Event &event);
+ bool GetTooltip(Math::Point pos, std::string &name);
+
+ void Flush();
+ CButton* CreateButton(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CColor* CreateColor(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CCheck* CreateCheck(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CKey* CreateKey(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CGroup* CreateGroup(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CImage* CreateImage(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CEdit* CreateEdit(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CEditValue* CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CScroll* CreateScroll(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CSlider* CreateSlider(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CShortcut* CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CCompass* CreateCompass(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CTarget* CreateTarget(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CMap* CreateMap(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+
+ CWindow* CreateWindows(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ CList* CreateList(Math::Point pos, Math::Point dim, int icon, EventType eventMsg, float expand=1.2f);
+ CLabel* CreateLabel(Math::Point pos, Math::Point dim, int icon, EventType eventMsg, std::string name);
+
+ bool DeleteControl(EventType eventMsg);
+ CControl* SearchControl(EventType eventMsg);
+
+ void Draw();
+
+protected:
+ int GetNextFreeControl();
+ template <typename T> inline T* CreateControl(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+
+ CEventQueue* m_event;
+ Gfx::CEngine* m_engine;
+ Gfx::CCamera* m_camera;
+
+ CControl* m_table[MAXCONTROL];
};
}
+
diff --git a/src/ui/key.cpp b/src/ui/key.cpp
index b181f70..1f8cff5 100644
--- a/src/ui/key.cpp
+++ b/src/ui/key.cpp
@@ -214,3 +214,4 @@ InputBinding CKey::GetBinding()
} // namespace Ui
+
diff --git a/src/ui/label.cpp b/src/ui/label.cpp
index b5195b5..76a95f2 100644
--- a/src/ui/label.cpp
+++ b/src/ui/label.cpp
@@ -66,7 +66,8 @@ void CLabel::Draw()
pos.y = m_pos.y + m_dim.y / 2.0f;
- switch (m_textAlign) {
+ switch (m_textAlign)
+ {
case Gfx::TEXT_ALIGN_LEFT: pos.x = m_pos.x; break;
case Gfx::TEXT_ALIGN_CENTER: pos.x = m_pos.x + m_dim.x / 2.0f; break;
case Gfx::TEXT_ALIGN_RIGHT: pos.x = m_pos.x + m_dim.x; break;
@@ -76,3 +77,4 @@ void CLabel::Draw()
}
}
+
diff --git a/src/ui/label.h b/src/ui/label.h
index c9e1050..305aca2 100644
--- a/src/ui/label.h
+++ b/src/ui/label.h
@@ -29,15 +29,16 @@ namespace Ui {
class CLabel : public CControl
{
- public:
- CLabel();
- virtual ~CLabel();
+public:
+ CLabel();
+ virtual ~CLabel();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- bool EventProcess(const Event &event);
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ bool EventProcess(const Event &event);
- void Draw();
+ void Draw();
};
}
+
diff --git a/src/ui/list.cpp b/src/ui/list.cpp
index 84aa8ca..f6c3ed9 100644
--- a/src/ui/list.cpp
+++ b/src/ui/list.cpp
@@ -33,13 +33,15 @@ CList::CList() : CControl()
m_button[i] = nullptr;
m_scroll = nullptr;
- for (int i = 0; i < LISTMAXTOTAL; i++) {
+ for (int i = 0; i < LISTMAXTOTAL; i++)
+ {
m_text[i][0] = 0;
m_check[i] = false;
m_enable[i] = true;
}
- for (int i = 0; i < 10; i++) {
+ for (int i = 0; i < 10; i++)
+ {
m_tabs[i] = 0.0f;
m_justifs[i] = Gfx::TEXT_ALIGN_LEFT;
}
@@ -57,7 +59,8 @@ CList::CList() : CControl()
CList::~CList()
{
- for (int i = 0; i < LISTMAXDISPLAY; i++) {
+ for (int i = 0; i < LISTMAXDISPLAY; i++)
+ {
if (m_button[i] != nullptr)
delete m_button[i];
}
@@ -68,6 +71,9 @@ CList::~CList()
// Creates a new list.
+// if expand is less then zero, then the list would try to use expand's absolute value,
+// and try to scale items to some size, so that dim of the list would not change after
+// adjusting
bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg, float expand)
{
@@ -85,6 +91,14 @@ bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventType eventMs
return MoveAdjust();
}
+// Should never be called
+bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventType eventType)
+{
+ assert(false);
+ return false;
+}
+
+
// Adjusted after a change of dimensions.
bool CList::MoveAdjust()
@@ -92,8 +106,10 @@ bool CList::MoveAdjust()
Math::Point ipos, idim, ppos, ddim;
float marging, h;
- for (int i = 0; i < LISTMAXDISPLAY; i++) {
- if (m_button[i] != nullptr) {
+ for (int i = 0; i < LISTMAXDISPLAY; i++)
+ {
+ if (m_button[i] != nullptr)
+ {
delete m_button[i];
m_button[i] = nullptr;
}
@@ -109,21 +125,30 @@ bool CList::MoveAdjust()
idim.x = m_dim.x - marging * 2.0f / 640.f;
idim.y = m_dim.y - marging * 2.0f / 480.f;
- h = m_engine->GetText()->GetHeight(m_fontType, m_fontSize) * m_expand;
-
+ //If m_expand is less then zero, then try to apply it's absolute value
+ h = m_engine->GetText()->GetHeight(m_fontType, m_fontSize) * ((m_expand < 0) ? -m_expand : m_expand);
m_displayLine = static_cast<int>(idim.y / h);
+
if (m_displayLine == 0)
return false;
if (m_displayLine > LISTMAXDISPLAY)
m_displayLine = LISTMAXDISPLAY;
- idim.y = h * m_displayLine;
+
+ // Stretch lines to fill whole area of a list, if needed
+ if (m_expand < 0 && (idim.y - (h * m_displayLine) < h))
+ {
+ h = idim.y / m_displayLine;
+ }
+
+ idim.y = h * m_displayLine; //Here cuts list size if height of shown elements is less then designed height
m_dim.y = idim.y + marging * 2.0f / 480.f;
ppos.x = ipos.x;
ppos.y = ipos.y + idim.y - h;
ddim.x = idim.x - SCROLL_WIDTH;
ddim.y = h;
- for (int i = 0; i < m_displayLine; i++) {
+ for (int i = 0; i < m_displayLine; i++)
+ {
m_button[i] = new CButton();
m_button[i]->Create(ppos, ddim, -1, EVENT_NULL);
m_button[i]->SetTextAlign(Gfx::TEXT_ALIGN_LEFT);
@@ -135,7 +160,8 @@ bool CList::MoveAdjust()
m_eventButton[i] = m_button[i]->GetEventType();
}
- if ( m_scroll != nullptr ) {
+ if ( m_scroll != nullptr )
+ {
ppos.x = ipos.x + idim.x - SCROLL_WIDTH;
ppos.y = ipos.y;
ddim.x = SCROLL_WIDTH;
@@ -187,8 +213,10 @@ void CList::SetDim(Math::Point dim)
bool CList::SetState(int state, bool bState)
{
- if (state & STATE_ENABLE) {
- for (int i = 0; i < m_displayLine; i++) {
+ if (state & STATE_ENABLE)
+ {
+ for (int i = 0; i < m_displayLine; i++)
+ {
if (m_button[i] != nullptr)
m_button[i]->SetState(state, bState);
}
@@ -202,8 +230,10 @@ bool CList::SetState(int state, bool bState)
bool CList::SetState(int state)
{
- if (state & STATE_ENABLE) {
- for (int i = 0; i < m_displayLine; i++) {
+ if (state & STATE_ENABLE)
+ {
+ for (int i = 0; i < m_displayLine; i++)
+ {
if (m_button[i] != nullptr)
m_button[i]->SetState(state);
}
@@ -217,8 +247,10 @@ bool CList::SetState(int state)
bool CList::ClearState(int state)
{
- if (state & STATE_ENABLE) {
- for (int i = 0; i < m_displayLine; i++) {
+ if (state & STATE_ENABLE)
+ {
+ for (int i = 0; i < m_displayLine; i++)
+ {
if (m_button[i] != nullptr)
m_button[i]->ClearState(state);
}
@@ -235,15 +267,20 @@ bool CList::ClearState(int state)
bool CList::EventProcess(const Event &event)
{
int i;
- if (m_bBlink && event.type == EVENT_FRAME) {
+ if (m_bBlink && event.type == EVENT_FRAME)
+ {
i = m_selectLine-m_firstLine;
- if (i >= 0 && i < 4 && m_button[i] != nullptr) {
+ if (i >= 0 && i < 4 && m_button[i] != nullptr)
+ {
m_blinkTime += event.rTime;
- if (Math::Mod(m_blinkTime, 0.7f) < 0.3f) {
+ if (Math::Mod(m_blinkTime, 0.7f) < 0.3f)
+ {
m_button[i]->ClearState(STATE_ENABLE);
m_button[i]->ClearState(STATE_CHECK);
- } else {
+ }
+ else
+ {
m_button[i]->SetState(STATE_ENABLE);
m_button[i]->SetState(STATE_CHECK);
}
@@ -255,7 +292,8 @@ bool CList::EventProcess(const Event &event)
if ((m_state & STATE_ENABLE) == 0)
return true;
- if (event.type == EVENT_MOUSE_WHEEL && event.mouseWheel.dir == WHEEL_UP && Detect(event.mousePos)) {
+ if (event.type == EVENT_MOUSE_WHEEL && event.mouseWheel.dir == WHEEL_UP && Detect(event.mousePos))
+ {
if (m_firstLine > 0)
m_firstLine--;
UpdateScroll();
@@ -263,7 +301,8 @@ bool CList::EventProcess(const Event &event)
return true;
}
- if (event.type == EVENT_MOUSE_WHEEL && event.mouseWheel.dir == WHEEL_DOWN && Detect(event.mousePos)) {
+ if (event.type == EVENT_MOUSE_WHEEL && event.mouseWheel.dir == WHEEL_DOWN && Detect(event.mousePos))
+ {
if (m_firstLine < m_totalLine - m_displayLine)
m_firstLine++;
UpdateScroll();
@@ -273,9 +312,11 @@ bool CList::EventProcess(const Event &event)
CControl::EventProcess(event);
- if (event.type == EVENT_MOUSE_MOVE && Detect(event.mousePos)) {
+ if (event.type == EVENT_MOUSE_MOVE && Detect(event.mousePos))
+ {
m_engine->SetMouseType(Gfx::ENG_MOUSE_NORM);
- for (i = 0; i < m_displayLine; i++) {
+ for (i = 0; i < m_displayLine; i++)
+ {
if (i + m_firstLine >= m_totalLine)
break;
if (m_button[i] != nullptr)
@@ -283,16 +324,20 @@ bool CList::EventProcess(const Event &event)
}
}
- if (m_bSelectCap) {
- for (i = 0; i < m_displayLine; i++) {
+ if (m_bSelectCap)
+ {
+ for (i = 0; i < m_displayLine; i++)
+ {
if (i + m_firstLine >= m_totalLine)
break;
- if (m_button[i] != nullptr) {
+ if (m_button[i] != nullptr)
+ {
if (!m_button[i]->EventProcess(event))
return false;
- if (event.type == m_eventButton[i]) {
+ if (event.type == m_eventButton[i])
+ {
SetSelect(m_firstLine + i);
Event newEvent = event;
@@ -303,11 +348,13 @@ bool CList::EventProcess(const Event &event)
}
}
- if (m_scroll != nullptr) {
+ if (m_scroll != nullptr)
+ {
if (!m_scroll->EventProcess(event))
return false;
- if (event.type == m_eventScroll) {
+ if (event.type == m_eventScroll)
+ {
MoveScroll();
UpdateButton();
}
@@ -335,10 +382,12 @@ void CList::Draw()
dp = 0.5f / 256.0f;
- if (m_icon != -1) {
+ if (m_icon != -1)
+ {
dim = m_dim;
- if (m_icon == 0) {
+ if (m_icon == 0)
+ {
m_engine->SetTexture("button2.png");
m_engine->SetState(Gfx::ENG_RSTATE_NORMAL);
@@ -346,7 +395,9 @@ void CList::Draw()
uv1.y = 64.0f / 256.0f; // u-v texture
uv2.x = 160.0f / 256.0f;
uv2.y = 96.0f / 256.0f;
- } else {
+ }
+ else
+ {
m_engine->SetTexture("button2.png");
m_engine->SetState(Gfx::ENG_RSTATE_NORMAL);
@@ -355,7 +406,8 @@ void CList::Draw()
uv2.x = 156.0f / 256.0f;
uv2.y = 92.0f / 256.0f;
- if (m_button[0] != nullptr) {
+ if (m_button[0] != nullptr)
+ {
dim = m_button[0]->GetDim();
dim.y *= m_displayLine; // background sounds spot behind
}
@@ -371,9 +423,11 @@ void CList::Draw()
DrawIcon(m_pos, dim, uv1, uv2, corner, 8.0f / 256.0f);
}
- if ( m_totalLine < m_displayLine ) { // no buttons to the bottom?
+ if ( m_totalLine < m_displayLine ) // no buttons to the bottom?
+ {
i = m_totalLine;
- if ( m_button[i] != 0 ) {
+ if ( m_button[i] != 0 )
+ {
pos = m_button[i]->GetPos();
dim = m_button[i]->GetDim();
pos.y += dim.y * 1.1f;
@@ -394,11 +448,13 @@ void CList::Draw()
}
}
- for (i = 0; i < m_displayLine; i++) {
+ for (i = 0; i < m_displayLine; i++)
+ {
if ( i + m_firstLine >= m_totalLine )
break;
- if ( m_button[i] != nullptr ) {
+ if ( m_button[i] != nullptr )
+ {
if ( !m_bBlink && i + m_firstLine < m_totalLine )
m_button[i]->SetState(STATE_ENABLE, m_enable[i+m_firstLine] && (m_state & STATE_ENABLE) );
@@ -407,22 +463,27 @@ void CList::Draw()
// draws text in the box
pos = m_button[i]->GetPos();
dim = m_button[i]->GetDim();
- if ( m_tabs[0] == 0.0f ) {
+ if ( m_tabs[0] == 0.0f )
+ {
ppos.x = pos.x + dim.y * 0.5f;
ppos.y = pos.y + dim.y * 0.5f;
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
ddim.x = dim.x-dim.y;
DrawCase(m_text[i + m_firstLine], ppos, ddim.x, Gfx::TEXT_ALIGN_LEFT);
- } else {
+ }
+ else
+ {
ppos.x = pos.x + dim.y * 0.5f;
ppos.y = pos.y + dim.y * 0.5f;
ppos.y -= m_engine->GetText()->GetHeight(m_fontType, m_fontSize) / 2.0f;
pb = m_text[i + m_firstLine];
- for (int j = 0; j < 10; j++) {
+ for (int j = 0; j < 10; j++)
+ {
pe = strchr(pb, '\t');
if ( pe == 0 )
strcpy(text, pb);
- else {
+ else
+ {
strncpy(text, pb, pe - pb);
text[pe - pb] = 0;
}
@@ -435,7 +496,8 @@ void CList::Draw()
}
}
- if ( (m_state & STATE_EXTEND) && i < m_totalLine) {
+ if ( (m_state & STATE_EXTEND) && i < m_totalLine)
+ {
pos = m_button[i]->GetPos();
dim = m_button[i]->GetDim();
pos.x += dim.x - dim.y * 0.75f;
@@ -445,7 +507,8 @@ void CList::Draw()
dim.x -= 4.0f / 640.0f;
dim.y -= 4.0f / 480.0f;
- if ( m_check[i + m_firstLine] ) {
+ if ( m_check[i + m_firstLine] )
+ {
m_engine->SetTexture("button1.png");
m_engine->SetState(Gfx::ENG_RSTATE_NORMAL);
uv1.x = 64.0f / 256.0f;
@@ -468,15 +531,20 @@ void CList::Draw()
uv2.x -= dp;
uv2.y -= dp;
DrawIcon(pos, dim, uv1, uv2); // draws v
- } else {
+ }
+ else
+ {
m_engine->SetTexture("button1.png");
m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE); // was D3DSTATETTw
- if ( i + m_firstLine == m_selectLine ) {
+ if ( i + m_firstLine == m_selectLine )
+ {
uv1.x =224.0f / 256.0f; // <
uv1.y =192.0f / 256.0f;
uv2.x =256.0f / 256.0f;
uv2.y =224.0f / 256.0f;
- } else {
+ }
+ else
+ {
uv1.x = 96.0f / 256.0f; // x
uv1.y = 32.0f / 256.0f;
uv2.x =128.0f / 256.0f;
@@ -541,7 +609,8 @@ void CList::SetSelect(int i)
{
if ( m_bSelectCap )
m_selectLine = i;
- else {
+ else
+ {
m_firstLine = i;
UpdateScroll();
}
@@ -584,8 +653,10 @@ void CList::SetBlink(bool bEnable)
i = m_selectLine-m_firstLine;
- if (i >= 0 && i < 4 && m_button[i] != nullptr) {
- if ( !bEnable ) {
+ if (i >= 0 && i < 4 && m_button[i] != nullptr)
+ {
+ if ( !bEnable )
+ {
m_button[i]->SetState(STATE_CHECK);
m_button[i]->ClearState(STATE_ENABLE);
}
@@ -600,7 +671,7 @@ bool CList::GetBlink()
// Specifies the text of a line.
-void CList::SetName(int i, const char* name)
+void CList::SetItemName(int i, const char* name)
{
if ( i < 0 || i >= LISTMAXTOTAL )
return;
@@ -619,7 +690,7 @@ void CList::SetName(int i, const char* name)
// Returns the text of a line.
-char* CList::GetName(int i)
+char* CList::GetItemName(int i)
{
if ( i < 0 || i >= m_totalLine )
return 0;
@@ -725,17 +796,21 @@ void CList::UpdateButton()
state = CControl::GetState();
j = m_firstLine;
- for (i = 0; i < m_displayLine; i++) {
+ for (i = 0; i < m_displayLine; i++)
+ {
if (m_button[i] == nullptr)
continue;
m_button[i]->SetState(STATE_CHECK, (j == m_selectLine));
- if ( j < m_totalLine ) {
+ if ( j < m_totalLine )
+ {
//? m_button[i]->SetName(m_text[j]);
m_button[i]->SetName(" "); // blank button
m_button[i]->SetState(STATE_ENABLE, (state & STATE_ENABLE));
- } else {
+ }
+ else
+ {
m_button[i]->SetName(" "); // blank button
m_button[i]->ClearState(STATE_ENABLE);
}
@@ -752,11 +827,14 @@ void CList::UpdateScroll()
if (m_scroll == nullptr)
return;
- if (m_totalLine <= m_displayLine) {
+ if (m_totalLine <= m_displayLine)
+ {
ratio = 1.0f;
value = 0.0f;
step = 0.0f;
- } else {
+ }
+ else
+ {
ratio = static_cast<float>(m_displayLine) / m_totalLine;
if ( ratio > 1.0f ) ratio = 1.0f;
@@ -797,4 +875,5 @@ void CList::MoveScroll()
}
-}
+} // namespace Ui
+
diff --git a/src/ui/list.h b/src/ui/list.h
index 97bd48c..a2e033f 100644
--- a/src/ui/list.h
+++ b/src/ui/list.h
@@ -69,8 +69,8 @@ class CList : public CControl
void SetBlink(bool bEnable);
bool GetBlink();
- void SetName(int i, const char* name);
- char* GetName(int i);
+ void SetItemName(int i, const char* name);
+ char* GetItemName(int i);
void SetCheck(int i, bool bMode);
bool GetCheck(int i);
@@ -93,6 +93,10 @@ class CList : public CControl
void MoveScroll();
void DrawCase(char *text, Math::Point pos, float width, Gfx::TextAlign justif);
+ private:
+ // Overridden to avoid warning about hiding the virtual function
+ virtual bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventType) override;
+
protected:
CButton* m_button[LISTMAXDISPLAY];
CScroll* m_scroll;
@@ -117,5 +121,5 @@ class CList : public CControl
};
-}
+} // namespace Ui
diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp
index 9060e8b..defff84 100644
--- a/src/ui/maindialog.cpp
+++ b/src/ui/maindialog.cpp
@@ -63,7 +63,7 @@ const int KEY_VISIBLE = 6; // number of visible keys redefinable
const int KEY_TOTAL = 21; // total number of keys redefinable
-const float WELCOME_LENGTH = 2.0f;
+const float WELCOME_LENGTH = 3.0f;
const int MAX_FNAME = 255; // TODO: remove after rewrite to std::string
@@ -174,10 +174,18 @@ CMainDialog::CMainDialog()
m_sceneDir = "levels";
- m_savegameDir = GetSystemUtils()->savegameDirectoryLocation();
+
+ #if DEV_BUILD
+ m_savegameDir = "savegame";
+ #else
+ m_savegameDir = GetSystemUtils()->GetSavegameDirectoryLocation();
+ #endif
+
m_publicDir = "program";
m_userDir = "user";
- m_filesDir = "files";
+ m_filesDir = m_savegameDir;
+
+ m_setupFull = m_app->GetVideoConfig().fullScreen;
m_bDialog = false;
}
@@ -193,7 +201,7 @@ CMainDialog::~CMainDialog()
void CMainDialog::ChangePhase(Phase phase)
{
- CWindow* pw;
+ CWindow* pw = nullptr;
CEdit* pe;
CEditValue* pv;
CLabel* pl;
@@ -358,7 +366,8 @@ pb->SetState(STATE_SHADOW);
}
// #endif
- if ( m_app->GetDebugMode() )
+ // TODO: remove?
+ if (m_app->GetProtoMode())
{
pos.x = 139.0f/640.0f;
pos.y = 313.0f/480.0f;
@@ -383,7 +392,7 @@ pb->SetState(STATE_SHADOW);
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
@@ -503,7 +512,7 @@ pb->SetState(STATE_SHADOW);
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
@@ -738,6 +747,24 @@ pb->SetState(STATE_SHADOW);
CameraPerso();
}
+ if ( m_phase != PHASE_SIMUL &&
+ m_phase != PHASE_WIN &&
+ m_phase != PHASE_LOST &&
+ m_phase != PHASE_WRITE &&
+ m_phase != PHASE_READs &&
+ m_phase != PHASE_WRITEs &&
+ m_phase != PHASE_SETUPds &&
+ m_phase != PHASE_SETUPgs &&
+ m_phase != PHASE_SETUPps &&
+ m_phase != PHASE_SETUPcs &&
+ m_phase != PHASE_SETUPss )
+ {
+ if (!m_sound->IsPlayingMusic())
+ {
+ m_sound->PlayMusic("Intro1.ogg", false);
+ }
+ }
+
if ( m_phase == PHASE_TRAINER ||
m_phase == PHASE_DEFI ||
m_phase == PHASE_MISSION ||
@@ -746,10 +773,6 @@ 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;
@@ -959,7 +982,7 @@ pb->SetState(STATE_SHADOW);
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
@@ -1158,7 +1181,7 @@ pb->SetState(STATE_SHADOW);
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
}
@@ -1604,7 +1627,7 @@ pos.y -= 0.048f;
}
if ( m_phase == PHASE_READ ||
- m_phase == PHASE_READs )
+ m_phase == PHASE_READs )
{
pos.x = 0.10f;
pos.y = 0.10f;
@@ -1683,7 +1706,7 @@ pos.y -= 0.048f;
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
}
@@ -1733,7 +1756,7 @@ pos.y -= 0.048f;
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
m_loadingCounter = 1; // enough time to display!
@@ -1741,9 +1764,6 @@ pos.y -= 0.048f;
if ( m_phase == PHASE_WELCOME1 )
{
- m_sound->StopMusic();
- m_sound->PlayMusic(11, false);
-
pos.x = 0.0f;
pos.y = 0.0f;
ddim.x = 0.0f;
@@ -1758,7 +1778,7 @@ pos.y -= 0.048f;
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(861.0f / 1024.0f, 646.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
if ( m_phase == PHASE_WELCOME2 )
@@ -1769,7 +1789,7 @@ pos.y -= 0.048f;
ddim.y = 0.0f;
pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
- m_engine->SetOverColor(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f), Gfx::ENG_RSTATE_TCOLOR_BLACK); // TODO: color ok?
+ m_engine->SetOverColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f), Gfx::ENG_RSTATE_TCOLOR_WHITE); // TODO: color ok?
m_engine->SetOverFront(true);
m_engine->SetBackground("colobot.png",
@@ -1777,7 +1797,7 @@ pos.y -= 0.048f;
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(640.0f / 1024.0f, 480.0f / 512.0f));
+ true);
m_engine->SetBackForce(true);
}
if ( m_phase == PHASE_WELCOME3 )
@@ -1796,7 +1816,7 @@ pos.y -= 0.048f;
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(640.0f / 1024.0f, 480.0f / 512.0f));
+ true);
m_engine->SetBackForce(true);
}
@@ -1932,7 +1952,7 @@ pos.y -= 0.048f;
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f),
- true, Math::Point(1.0f, 768.0f / 1024.0f));
+ true);
m_engine->SetBackForce(true);
}
@@ -2001,33 +2021,58 @@ bool CMainDialog::EventProcess(const Event &event)
//? else welcomeLength = WELCOME_LENGTH;
welcomeLength = WELCOME_LENGTH;
+ if ( m_phase != PHASE_SIMUL &&
+ m_phase != PHASE_WIN &&
+ m_phase != PHASE_LOST &&
+ m_phase != PHASE_WRITE &&
+ m_phase != PHASE_READs &&
+ m_phase != PHASE_WRITEs &&
+ m_phase != PHASE_SETUPds &&
+ m_phase != PHASE_SETUPgs &&
+ m_phase != PHASE_SETUPps &&
+ m_phase != PHASE_SETUPcs &&
+ m_phase != PHASE_SETUPss )
+ {
+ if (!m_sound->IsPlayingMusic())
+ {
+ m_sound->PlayMusic("Intro2.ogg", true);
+ }
+ }
+
if ( m_phase == PHASE_WELCOME1 ||
- m_phase == PHASE_WELCOME2 ||
- m_phase == PHASE_WELCOME3 )
+ m_phase == PHASE_WELCOME2 ||
+ m_phase == PHASE_WELCOME3 )
{
float intensity;
- int mode = Gfx::ENG_RSTATE_TCOLOR_BLACK;
+ int mode = Gfx::ENG_RSTATE_TCOLOR_WHITE;
+
+ // 1/4 of display time is animating
+ float animatingTime = welcomeLength / 4.0f;
- if ( m_phaseTime < 1.5f )
+ if ( m_phaseTime < animatingTime )
{
- intensity = 1.0f-(m_phaseTime-0.5f);
+ //appearing
+ intensity = m_phaseTime / animatingTime;
}
- else if ( m_phaseTime < welcomeLength-1.0f )
+ else if ( m_phaseTime < welcomeLength - animatingTime )
{
- intensity = 0.0f;
+ //showing
+ intensity = 1.0f;
}
else
{
- intensity = m_phaseTime-(welcomeLength-1.0f);
+ //hiding
+ intensity = (welcomeLength - m_phaseTime) / animatingTime;
}
+
if ( intensity < 0.0f ) intensity = 0.0f;
if ( intensity > 1.0f ) intensity = 1.0f;
- if ( (m_phase == PHASE_WELCOME2 && m_phaseTime > welcomeLength/2.0f) ||
- m_phase == PHASE_WELCOME3 )
+ //white first, others -> black fadding
+ if ( (m_phase == PHASE_WELCOME1) && ( m_phaseTime < welcomeLength/2.0f))
{
- intensity = 1.0f-intensity;
- mode = Gfx::ENG_RSTATE_TCOLOR_WHITE;
+ intensity = 1.0f - intensity;
+ mode = Gfx::ENG_RSTATE_TCOLOR_BLACK;
}
m_engine->SetOverColor(Gfx::Color(intensity, intensity, intensity, intensity), mode); // TODO: color ok?
@@ -2270,7 +2315,7 @@ bool CMainDialog::EventProcess(const Event &event)
if ( pw == 0 ) break;
pl = static_cast<CList*>(pw->SearchControl(EVENT_INTERFACE_NLIST));
if ( pl == 0 ) break;
- StartDeleteGame(pl->GetName(pl->GetSelect()));
+ StartDeleteGame(pl->GetItemName(pl->GetSelect()));
break;
default:
@@ -2587,15 +2632,18 @@ bool CMainDialog::EventProcess(const Event &event)
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
if ( pw == 0 ) break;
pc = static_cast<CCheck*>(pw->SearchControl(EVENT_INTERFACE_FULL));
- if ( pc == 0 ) break;
-
- if ( pc->TestState(STATE_CHECK) ) {
- m_setupFull = false;
- pc->ClearState(STATE_CHECK);
- } else {
- m_setupFull = true;
- pc->SetState(STATE_CHECK);
- }
+ if ( pc == 0 ) break;
+
+ if ( pc->TestState(STATE_CHECK) )
+ {
+ m_setupFull = false;
+ pc->ClearState(STATE_CHECK);
+ }
+ else
+ {
+ m_setupFull = true;
+ pc->SetState(STATE_CHECK);
+ }
UpdateApply();
break;
@@ -2607,7 +2655,7 @@ bool CMainDialog::EventProcess(const Event &event)
if ( pb == 0 ) break;
pb->ClearState(STATE_PRESS);
pb->ClearState(STATE_HILIGHT);
- // TODO: uncomment when changing display is implemented
+ // TODO: uncomment when changing display is implemented
//ChangeDisplay();
UpdateApply();
break;
@@ -3630,8 +3678,9 @@ void CMainDialog::ReadNameList()
{
fs::directory_iterator dirIt(m_savegameDir), dirEndIt;
- BOOST_FOREACH (const fs::path & p, std::make_pair(dirIt, dirEndIt))
+ for (; dirIt != dirEndIt; ++dirIt)
{
+ const fs::path& p = *dirIt;
if (fs::is_directory(p))
{
fileNames.push_back(p.leaf().string());
@@ -3648,7 +3697,7 @@ void CMainDialog::ReadNameList()
for (size_t i=0 ; i<fileNames.size() ; ++i )
{
- pl->SetName(i, fileNames.at(i).c_str());
+ pl->SetItemName(i, fileNames.at(i).c_str());
}
}
@@ -3724,7 +3773,7 @@ void CMainDialog::UpdateNameList()
for ( i=0 ; i<total ; i++ )
{
// TODO: stricmp?
- if ( strcmp(name, pl->GetName(i)) == 0 )
+ if ( strcmp(name, pl->GetItemName(i)) == 0 )
{
pl->SetSelect(i);
pl->ShowSelect(false);
@@ -3760,7 +3809,7 @@ void CMainDialog::UpdateNameEdit()
}
else
{
- name = pl->GetName(sel);
+ name = pl->GetItemName(sel);
pe->SetText(name);
pe->SetCursor(strlen(name), 0);
}
@@ -3784,7 +3833,7 @@ void CMainDialog::UpdateNameFace()
sel = pl->GetSelect();
if ( sel == -1 ) return;
- name = pl->GetName(sel);
+ name = pl->GetItemName(sel);
ReadGamerPerso(name);
}
@@ -3815,7 +3864,7 @@ void CMainDialog::NameSelect()
}
else
{
- m_main->SetGamerName(pl->GetName(sel));
+ m_main->SetGamerName(pl->GetItemName(sel));
m_main->ChangePhase(PHASE_INIT);
}
@@ -3942,7 +3991,7 @@ void CMainDialog::NameDelete()
m_sound->Play(SOUND_TZOING);
return;
}
- gamer = pl->GetName(sel);
+ gamer = pl->GetItemName(sel);
// Deletes all the contents of the file.
sprintf(dir, "%s/%s", m_savegameDir.c_str(), gamer);
@@ -4256,14 +4305,21 @@ void CMainDialog::DefPerso()
bool CMainDialog::IsIOReadScene()
{
- FILE* file;
- std::string filename;
+ fs::directory_iterator end_iter;
- filename = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + "000/data.sav";
- file = fopen(filename.c_str(), "r");
- if ( file == NULL ) return false;
- fclose(file);
- return true;
+ fs::path saveDir(m_savegameDir + "/" + m_main->GetGamerName());
+ if (fs::exists(saveDir) && fs::is_directory(saveDir))
+ {
+ for( fs::directory_iterator dir_iter(saveDir) ; dir_iter != end_iter ; ++dir_iter)
+ {
+ if ( fs::is_directory(dir_iter->status()) && fs::exists(dir_iter->path() / "data.sav") )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
// Builds the file name by default.
@@ -4283,9 +4339,9 @@ void CMainDialog::IOReadName()
int i;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw == 0 ) return;
+ if ( pw == nullptr ) return;
pe = static_cast<CEdit*>(pw->SearchControl(EVENT_INTERFACE_IONAME));
- if ( pe == 0 ) return;
+ if ( pe == nullptr ) return;
sprintf(resume, "%s %d", m_sceneName, m_chap[m_index]+1);
BuildSceneName(filename, m_sceneName, (m_chap[m_index]+1)*100);
@@ -4337,7 +4393,8 @@ void CMainDialog::IOReadList()
CList* pl;
char line[500];
char name[100];
- int i, j;
+ int i;
+ fs::directory_iterator end_iter;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
if ( pw == 0 ) return;
@@ -4346,49 +4403,53 @@ void CMainDialog::IOReadList()
pl->Flush();
- for ( j=0 ; j<999 ; j++ )
- {
- std::string filename;
- std::ostringstream rankStream;
- rankStream << std::setfill('0') << std::setw(3) << j;
- 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(fs::path(filename).make_preferred().string().c_str(), "r");
- if ( file == NULL ) break;
+ fs::path saveDir(m_savegameDir + "/" + m_main->GetGamerName());
+ m_saveList.clear();
- while ( fgets(line, 500, file) != NULL )
+ if (fs::exists(saveDir) && fs::is_directory(saveDir))
+ {
+ for( fs::directory_iterator dir_iter(saveDir) ; dir_iter != end_iter ; ++dir_iter)
{
- for ( i=0 ; i<500 ; i++ )
+ if ( fs::is_directory(dir_iter->status()) && fs::exists(dir_iter->path() / "data.sav") )
{
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
+
+ file = fopen((dir_iter->path() / "data.sav").make_preferred().string().c_str(), "r");
+ if ( file == NULL ) continue;
+
+ while ( fgets(line, 500, file) != NULL )
{
- line[i] = 0;
- break;
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Title") )
+ {
+ OpString(line, "text", name);
+ break;
+ }
}
- }
+ fclose(file);
- if ( Cmd(line, "Title") )
- {
- OpString(line, "text", name);
- break;
+ pl->SetItemName(m_saveList.size(), name);
+ m_saveList.push_back(dir_iter->path());
}
}
- fclose(file);
-
- pl->SetName(j, name);
}
- if ( m_phase == PHASE_WRITE ||
- m_phase == PHASE_WRITEs )
+ // invalid index
+ if ( m_phase == PHASE_WRITE || m_phase == PHASE_WRITEs )
{
GetResource(RES_TEXT, RT_IO_NEW, name);
- pl->SetName(j, name);
- j ++;
+ pl->SetItemName(m_saveList.size(), name);
}
- pl->SetSelect(j-1);
+ pl->SetSelect(m_saveList.size());
pl->ShowSelect(false); // shows the selected columns
}
@@ -4403,22 +4464,20 @@ void CMainDialog::IOUpdateList()
int sel, max;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw == 0 ) return;
+ if ( pw == nullptr ) return;
pl = static_cast<CList*>(pw->SearchControl(EVENT_INTERFACE_IOLIST));
- if ( pl == 0 ) return;
+ if ( pl == nullptr ) return;
pi = static_cast<CImage*>(pw->SearchControl(EVENT_INTERFACE_IOIMAGE));
- if ( pi == 0 ) return;
+ if ( pi == nullptr ) return;
sel = pl->GetSelect();
max = pl->GetTotal();
- std::string filename;
- std::ostringstream rankStream;
- rankStream << std::setfill('0') << std::setw(3) << sel;
- filename = m_savegameDir + "/" + m_main->GetGamerName() + "/save" + m_sceneName[0] + rankStream.str()+ "/screen.png";
+ if (m_saveList.size() <= static_cast<unsigned int>(sel))
+ return;
- if ( m_phase == PHASE_WRITE ||
- m_phase == PHASE_WRITEs )
+ std::string filename = (m_saveList.at(sel) / "screen.png").make_preferred().string();
+ if ( m_phase == PHASE_WRITE || m_phase == PHASE_WRITEs )
{
if ( sel < max-1 )
{
@@ -4430,7 +4489,7 @@ void CMainDialog::IOUpdateList()
}
pb = static_cast<CButton*>(pw->SearchControl(EVENT_INTERFACE_IODELETE));
- if ( pb != 0 )
+ if ( pb != nullptr )
{
pb->SetState(STATE_ENABLE, sel < max-1);
}
@@ -4455,34 +4514,44 @@ void CMainDialog::IODeleteScene()
if ( pl == 0 ) return;
sel = pl->GetSelect();
- if ( sel == -1 )
+ if ( sel == -1 || m_saveList.size() <= static_cast<unsigned int>(sel))
{
m_sound->Play(SOUND_TZOING);
return;
}
-
- std::ostringstream rankStream;
- std::string fileName;
- rankStream << std::setfill('0') << std::setw(3) << sel;
- fileName = m_savegameDir + "/" + m_main->GetGamerName() + "/save" + m_sceneName[0] + rankStream.str();
try
{
- if (fs::exists(fileName) && fs::is_directory(fileName))
+ if (fs::exists(m_saveList.at(sel)) && fs::is_directory(m_saveList.at(sel)))
{
- fs::remove_all(fileName);
+ fs::remove_all(m_saveList.at(sel));
}
}
catch (std::exception & e)
{
- GetLogger()->Error("Error on removing directory %s : %s\n", e.what());
+ GetLogger()->Error("Error removing save %s : %s\n", pl->GetItemName(sel), e.what());
}
IOReadList();
}
-// Writes the scene.
+// clears filename only to leave letter or numbers
+std::string clearName(char *name)
+{
+ std::string ret;
+ int len = strlen(name);
+ for (int i = 0; i < len; i++)
+ {
+ if (isalnum(name[i]))
+ {
+ ret += name[i];
+ }
+ }
+ return ret;
+}
+
+// Writes the scene.
bool CMainDialog::IOWriteScene()
{
CWindow* pw;
@@ -4492,36 +4561,40 @@ bool CMainDialog::IOWriteScene()
int sel;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw == 0 ) return false;
+ if ( pw == nullptr ) return false;
pl = static_cast<CList*>(pw->SearchControl(EVENT_INTERFACE_IOLIST));
- if ( pl == 0 ) return false;
+ if ( pl == nullptr ) return false;
pe = static_cast<CEdit*>(pw->SearchControl(EVENT_INTERFACE_IONAME));
- if ( pe == 0 ) return false;
+ if ( pe == nullptr ) return false;
sel = pl->GetSelect();
- if ( sel == -1 ) return false;
+ if ( sel == -1 )
+ {
+ return false;
+ }
- std::string directoryName;
- std::string fileName;
- std::string fileCBot;
- std::ostringstream selectStream;
+ fs::path dir;
+ pe->GetText(info, 100);
+ if (static_cast<unsigned int>(sel) >= m_saveList.size())
+ {
+ dir = fs::path(m_savegameDir) / m_main->GetGamerName() / ("save" + clearName(info));
+ }
+ else
+ {
+ dir = m_saveList.at(sel);
+ }
- //TODO: Change this to point user dir according to operating system
- GetLogger()->Debug("Creating save directory\n");
- selectStream << std::setfill('0') << std::setw(3) << sel;
- directoryName = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + selectStream.str();
- if (!fs::exists(directoryName))
+ if (!fs::exists(dir))
{
- fs::create_directories(directoryName);
+ fs::create_directories(dir);
}
- fileName = directoryName + "/data.sav";
- fileCBot = directoryName + "/cbot.run";
- pe->GetText(info, 100);
+ std::string fileName = (dir / "data.sav").make_preferred().string();
+ std::string fileCBot = (dir / "cbot.run").make_preferred().string();
m_main->IOWriteScene(fileName.c_str(), fileCBot.c_str(), info);
m_shotDelay = 3;
- m_shotName = directoryName + "/screen.png";
+ m_shotName = (dir / "screen.png").make_preferred().string();
return true;
}
@@ -4538,26 +4611,24 @@ bool CMainDialog::IOReadScene()
int sel, i;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw == 0 ) return false;
+ if ( pw == nullptr ) return false;
pl = static_cast<CList*>(pw->SearchControl(EVENT_INTERFACE_IOLIST));
- if ( pl == 0 ) return false;
+ if ( pl == nullptr ) return false;
sel = pl->GetSelect();
- if ( sel == -1 ) return false;
-
- //TODO: Change this to point user dir according to operating system
- std::string fileName;
- std::string fileCbot;
- std::string directoryName;
- std::ostringstream selectStream;
- selectStream << std::setfill('0') << std::setw(3) << sel;
- directoryName = m_savegameDir + "/" + m_main->GetGamerName() + "/" + "save" + m_sceneName[0] + selectStream.str();
+ if ( sel == -1 || m_saveList.size() <= static_cast<unsigned int>(sel) )
+ {
+ return false;
+ }
- fileName = directoryName + "/data.sav";
- fileCbot = directoryName + "/cbot.run";
+ std::string fileName = (m_saveList.at(sel) / "data.sav").make_preferred().string();
+ std::string fileCbot = (m_saveList.at(sel) / "cbot.run").make_preferred().string();
file = fopen(fileName.c_str(), "r");
- if ( file == NULL ) return false;
+ if ( file == NULL )
+ {
+ return false;
+ }
while ( fgets(line, 500, file) != NULL )
{
@@ -4598,8 +4669,8 @@ bool CMainDialog::IOReadScene()
}
fclose(file);
- m_chap[m_index] = (m_sceneRank/100)-1;
- m_sel[m_index] = (m_sceneRank%100)-1;
+ m_chap[m_index] = (m_sceneRank / 100)-1;
+ m_sel[m_index] = (m_sceneRank % 100)-1;
m_sceneRead = fileName;
m_stackRead = fileCbot;
@@ -4676,8 +4747,9 @@ void CMainDialog::UpdateSceneChap(int &chap)
fs::directory_iterator dirIt(m_savegameDir), dirEndIt;
m_userList.clear();
- BOOST_FOREACH (const fs::path & p, std::make_pair(dirIt, dirEndIt))
+ for (; dirIt != dirEndIt; ++dirIt)
{
+ const fs::path& p = *dirIt;
if (fs::is_directory(p))
{
m_userList.push_back(p.leaf().string());
@@ -4724,7 +4796,7 @@ void CMainDialog::UpdateSceneChap(int &chap)
fclose(file);
}
- pl->SetName(j, name);
+ pl->SetItemName(j, name);
pl->SetEnable(j, true);
}
}
@@ -4777,7 +4849,7 @@ void CMainDialog::UpdateSceneChap(int &chap)
bPassed = GetGamerInfoPassed((j+1)*100);
sprintf(line, "%d: %s", j+1, name);
- pl->SetName(j, line);
+ pl->SetItemName(j, line);
pl->SetCheck(j, bPassed);
pl->SetEnable(j, true);
@@ -4887,7 +4959,7 @@ void CMainDialog::UpdateSceneList(int chap, int &sel)
bPassed = GetGamerInfoPassed((chap+1)*100+(j+1));
sprintf(line, "%d: %s", j+1, name);
- pl->SetName(j, line);
+ pl->SetItemName(j, line);
pl->SetCheck(j, bPassed);
pl->SetEnable(j, true);
@@ -5016,6 +5088,9 @@ void CMainDialog::UpdateSceneResume(int rank)
{
for ( i=0 ; i<500 ; i++ )
{
+ if (line[i] == 0)
+ break;
+
if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
if ( line[i] == '/' && line[i+1] == '/' )
{
@@ -5066,7 +5141,7 @@ void CMainDialog::UpdateDisplayDevice()
j = 0;
while ( bufDevices[i] != 0 )
{
- pl->SetName(j++, bufDevices+i);
+ pl->SetItemName(j++, bufDevices+i);
while ( bufDevices[i++] != 0 );
}
@@ -5093,10 +5168,11 @@ void CMainDialog::UpdateDisplayMode()
m_app->GetVideoResolutionList(modes, true, true);
int i = 0;
std::stringstream mode_text;
- for (Math::IntPoint mode : modes) {
- mode_text.str("");
- mode_text << mode.x << "x" << mode.y;
- pl->SetName(i++, mode_text.str().c_str());
+ for (Math::IntPoint mode : modes)
+ {
+ mode_text.str("");
+ mode_text << mode.x << "x" << mode.y;
+ pl->SetItemName(i++, mode_text.str().c_str());
}
pl->SetSelect(m_setupSelMode);
@@ -5120,12 +5196,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->GetItemName(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->GetItemName(m_setupSelMode);
pc = static_cast<CCheck*>(pw->SearchControl(EVENT_INTERFACE_FULL));
if ( pc == 0 ) return;
@@ -5481,6 +5557,7 @@ void CMainDialog::SetupMemorize()
GetProfile().SetLocalProfileInt("Setup", "HimselfDamage", m_bHimselfDamage);
GetProfile().SetLocalProfileInt("Setup", "CameraScroll", m_bCameraScroll);
GetProfile().SetLocalProfileInt("Setup", "CameraInvertX", m_bCameraInvertX);
+ GetProfile().SetLocalProfileInt("Setup", "CameraInvertY", m_bCameraInvertY);
GetProfile().SetLocalProfileInt("Setup", "InterfaceEffect", m_bEffect);
GetProfile().SetLocalProfileInt("Setup", "GroundShadow", m_engine->GetShadow());
GetProfile().SetLocalProfileInt("Setup", "GroundSpot", m_engine->GetGroundSpot());
@@ -5501,23 +5578,29 @@ void CMainDialog::SetupMemorize()
GetProfile().SetLocalProfileInt("Setup", "Sound3D", m_sound->GetSound3D());
GetProfile().SetLocalProfileInt("Setup", "EditIndentMode", m_engine->GetEditIndentMode());
GetProfile().SetLocalProfileInt("Setup", "EditIndentValue", m_engine->GetEditIndentValue());
-
+
/* screen setup */
if (m_setupFull)
- GetProfile().SetLocalProfileInt("Setup", "Fullscreen", 1);
+ GetProfile().SetLocalProfileInt("Setup", "Fullscreen", 1);
else
- GetProfile().SetLocalProfileInt("Setup", "Fullscreen", 0);
-
+ GetProfile().SetLocalProfileInt("Setup", "Fullscreen", 0);
+
CList *pl;
CWindow *pw;
pw = static_cast<CWindow *>(m_interface->SearchControl(EVENT_WINDOW5));
- if ( pw != 0 ) {
- pl = static_cast<CList *>(pw->SearchControl(EVENT_LIST2));
- if ( pl != 0 ) {
- GetProfile().SetLocalProfileInt("Setup", "Resolution", pl->GetSelect());
- }
+ if ( pw != 0 )
+ {
+ pl = static_cast<CList *>(pw->SearchControl(EVENT_LIST2));
+ if ( pl != 0 )
+ {
+ GetProfile().SetLocalProfileInt("Setup", "Resolution", pl->GetSelect());
+ }
+ }
+ else
+ {
+ // TODO: Default value
}
-
+
std::stringstream key;
for (int i = 0; i < INPUT_SLOT_MAX; i++)
{
@@ -5730,6 +5813,11 @@ void CMainDialog::SetupRecall()
m_sound->SetMusicVolume(iValue);
}
+ if ( GetProfile().GetLocalProfileInt("Setup", "Sound3D", iValue) )
+ {
+ m_sound->SetSound3D(iValue == 1);
+ }
+
if ( GetProfile().GetLocalProfileInt("Setup", "EditIndentMode", iValue) )
{
m_engine->SetEditIndentMode(iValue);
@@ -5772,13 +5860,15 @@ void CMainDialog::SetupRecall()
{
m_bDeleteGamer = iValue;
}
-
- if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) ) {
- m_setupSelMode = iValue;
+
+ if ( GetProfile().GetLocalProfileInt("Setup", "Resolution", iValue) )
+ {
+ m_setupSelMode = iValue;
}
-
- if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) ) {
- m_setupFull = (iValue == 1);
+
+ if ( GetProfile().GetLocalProfileInt("Setup", "Fullscreen", iValue) )
+ {
+ m_setupFull = (iValue == 1);
}
}
@@ -6542,6 +6632,8 @@ void CMainDialog::WriteGamerPerso(char *gamer)
file = fopen(filename, "w");
if ( file == NULL ) return;
+ m_main->SetNumericLocale();
+
sprintf(line, "Head face=%d glasses=%d hair=%.2f;%.2f;%.2f;%.2f\n",
m_perso.face, m_perso.glasses,
m_perso.colorHair.r, m_perso.colorHair.g, m_perso.colorHair.b, m_perso.colorHair.a);
@@ -6553,6 +6645,8 @@ void CMainDialog::WriteGamerPerso(char *gamer)
fputs(line, file);
fclose(file);
+
+ m_main->RestoreNumericLocale();
}
// Reads the personalized player.
@@ -6571,6 +6665,8 @@ void CMainDialog::ReadGamerPerso(char *gamer)
file = fopen(filename, "r");
if ( file == NULL ) return;
+ m_main->SetNumericLocale();
+
while ( fgets(line, 100, file) != NULL )
{
if ( Cmd(line, "Head") )
@@ -6602,6 +6698,8 @@ void CMainDialog::ReadGamerPerso(char *gamer)
}
fclose(file);
+
+ m_main->RestoreNumericLocale();
}
// Specifies the face of the player.
@@ -6787,3 +6885,4 @@ bool CMainDialog::NextMission()
} // namespace Ui
+
diff --git a/src/ui/maindialog.h b/src/ui/maindialog.h
index a79b95e..96aff2a 100644
--- a/src/ui/maindialog.h
+++ b/src/ui/maindialog.h
@@ -26,6 +26,8 @@
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
+#include <vector>
+
namespace fs = boost::filesystem;
@@ -260,6 +262,8 @@ protected:
Math::Point m_partiPos[10];
SceneInfo m_sceneInfo[MAXSCENE];
+
+ std::vector<fs::path> m_saveList;
};
} // namespace Ui
diff --git a/src/ui/mainmap.cpp b/src/ui/mainmap.cpp
index 1143a77..8c81160 100644
--- a/src/ui/mainmap.cpp
+++ b/src/ui/mainmap.cpp
@@ -55,7 +55,8 @@ void CMainMap::CreateMap()
Math::Point pos, dim;
pw = static_cast<CWindow*>(m_interface->SearchControl(EVENT_WINDOW1));
- if (pw == nullptr) {
+ if (pw == nullptr)
+ {
pos.x = 0.0f;
pos.y = 0.0f;
dim.x = 0.0f;
@@ -106,7 +107,8 @@ void CMainMap::FloorColorMap(Gfx::Color floor, Gfx::Color water)
return;
pm = static_cast<CMap*>(pw->SearchControl(EVENT_OBJECT_MAP));
- if (pm != nullptr) {
+ if (pm != nullptr)
+ {
pm->SetFloorColor(floor);
pm->SetWaterColor(water);
}
@@ -124,9 +126,12 @@ void CMainMap::ShowMap(bool bShow)
if (pw == nullptr)
return;
- if (bShow) {
+ if (bShow)
+ {
DimMap();
- } else {
+ }
+ else
+ {
pm = static_cast<CMap*>(pw->SearchControl(EVENT_OBJECT_MAP));
if (pm != nullptr)
pm->ClearState(STATE_VISIBLE);
@@ -164,7 +169,8 @@ void CMainMap::DimMap()
pm->SetDim(dim);
ps = static_cast<CSlider*>(pw->SearchControl(EVENT_OBJECT_MAPZOOM));
- if (ps != nullptr) {
+ if (ps != nullptr)
+ {
ps->SetState(STATE_VISIBLE, (m_mapMode != 0));
dim.x = SCROLL_WIDTH;
@@ -392,3 +398,4 @@ void CMainMap::SetHighlight(CObject* pObj)
}
+
diff --git a/src/ui/mainmap.h b/src/ui/mainmap.h
index 9d0d72f..9b20548 100644
--- a/src/ui/mainmap.h
+++ b/src/ui/mainmap.h
@@ -34,37 +34,37 @@ namespace Ui {
class CMainMap
{
- public:
- CMainMap();
- ~CMainMap();
-
- void UpdateMap();
- void CreateMap();
- void SetFixImage(const char *filename);
- void FloorColorMap(Gfx::Color floor, Gfx::Color water);
- void ShowMap(bool bShow);
- void DimMap();
- float GetZoomMap();
- void ZoomMap(float zoom);
- void ZoomMap();
- void MapEnable(bool bEnable);
- bool GetShowMap();
- bool GetFixImage();
- CObject* DetectMap(Math::Point pos, bool &bInMap);
- void SetHighlight(CObject* pObj);
- void SetToy(bool bToy);
- void SetFixParam(float zoom, float ox, float oy, float angle, int mode, bool bDebug);
-
- protected:
- void CenterMap();
-
- protected:
- CEventQueue* m_event;
- Gfx::CEngine* m_engine;
- CInterface* m_interface;
-
- int m_mapMode;
- bool m_bFixImage;
+public:
+ CMainMap();
+ ~CMainMap();
+
+ void UpdateMap();
+ void CreateMap();
+ void SetFixImage(const char *filename);
+ void FloorColorMap(Gfx::Color floor, Gfx::Color water);
+ void ShowMap(bool bShow);
+ void DimMap();
+ float GetZoomMap();
+ void ZoomMap(float zoom);
+ void ZoomMap();
+ void MapEnable(bool bEnable);
+ bool GetShowMap();
+ bool GetFixImage();
+ CObject* DetectMap(Math::Point pos, bool &bInMap);
+ void SetHighlight(CObject* pObj);
+ void SetToy(bool bToy);
+ void SetFixParam(float zoom, float ox, float oy, float angle, int mode, bool bDebug);
+
+protected:
+ void CenterMap();
+
+protected:
+ CEventQueue* m_event;
+ Gfx::CEngine* m_engine;
+ CInterface* m_interface;
+
+ int m_mapMode;
+ bool m_bFixImage;
};
}
diff --git a/src/ui/mainshort.h b/src/ui/mainshort.h
index d679eb0..b185aed 100644
--- a/src/ui/mainshort.h
+++ b/src/ui/mainshort.h
@@ -34,29 +34,30 @@ namespace Ui {
class CMainShort
{
- public:
- CMainShort();
- ~CMainShort();
-
- void SetMode(bool bBuilding);
- void FlushShortcuts();
- bool CreateShortcuts();
- bool UpdateShortcuts();
- void SelectShortcut(EventType event);
- void SelectNext();
- CObject* DetectShort(Math::Point pos);
- void SetHighlight(CObject* pObj);
-
- protected:
-
- protected:
- CEventQueue* m_event;
- Gfx::CEngine* m_engine;
- CInterface* m_interface;
- CRobotMain* m_main;
-
- CObject* m_shortcuts[20];
- bool m_bBuilding;
+public:
+ CMainShort();
+ ~CMainShort();
+
+ void SetMode(bool bBuilding);
+ void FlushShortcuts();
+ bool CreateShortcuts();
+ bool UpdateShortcuts();
+ void SelectShortcut(EventType event);
+ void SelectNext();
+ CObject* DetectShort(Math::Point pos);
+ void SetHighlight(CObject* pObj);
+
+protected:
+
+protected:
+ CEventQueue* m_event;
+ Gfx::CEngine* m_engine;
+ CInterface* m_interface;
+ CRobotMain* m_main;
+
+ CObject* m_shortcuts[20];
+ bool m_bBuilding;
};
}
+
diff --git a/src/ui/map.cpp b/src/ui/map.cpp
index 33d0fb1..c5f0062 100644
--- a/src/ui/map.cpp
+++ b/src/ui/map.cpp
@@ -187,14 +187,17 @@ bool CMap::EventProcess(const Event &event)
if ( event.type == EVENT_FRAME )
m_time += event.rTime;
- if ( event.type == EVENT_MOUSE_MOVE && Detect(event.mousePos) ) {
+ if ( event.type == EVENT_MOUSE_MOVE && Detect(event.mousePos) )
+ {
m_engine->SetMouseType(Gfx::ENG_MOUSE_NORM);
if ( DetectObject(event.mousePos, bInMap) != 0 )
m_engine->SetMouseType(Gfx::ENG_MOUSE_HAND);
}
- if ( event.type == EVENT_MOUSE_BUTTON_DOWN && event.mouseButton.button == MOUSE_BUTTON_LEFT ) {
- if ( CControl::Detect(event.mousePos) ) {
+ if ( event.type == EVENT_MOUSE_BUTTON_DOWN && event.mouseButton.button == MOUSE_BUTTON_LEFT )
+ {
+ if ( CControl::Detect(event.mousePos) )
+ {
SelectObject(event.mousePos);
return false;
}
@@ -228,11 +231,13 @@ void CMap::SetHighlight(CObject* pObj)
if ( pObj == nullptr )
return;
- for (int i = 0; i < MAPMAXOBJECT; i++) {
+ for (int i = 0; i < MAPMAXOBJECT; i++)
+ {
if ( !m_map[i].bUsed )
continue;
- if ( m_map[i].object == pObj ) {
+ if ( m_map[i].object == pObj )
+ {
m_highlightRank = i;
break;
}
@@ -262,7 +267,8 @@ CObject* CMap::DetectObject(Math::Point pos, bool &bInMap)
min = 10000.0f;
best = -1;
- for (int i = MAPMAXOBJECT - 1; i >= 0; i--) {
+ for (int i = MAPMAXOBJECT - 1; i >= 0; i--)
+ {
if ( !m_map[i].bUsed )
continue;
if ( m_map[i].color == MAPCOLOR_BBOX && !m_bRadar )
@@ -273,7 +279,8 @@ CObject* CMap::DetectObject(Math::Point pos, bool &bInMap)
dist = Math::Point(m_map[i].pos.x - pos.x, m_map[i].pos.y - pos.y).Length();
if ( dist > m_half / m_zoom * 8.0f / 100.0f )
continue; // too far?
- if ( dist < min ) {
+ if ( dist < min )
+ {
min = dist;
best = i;
}
@@ -337,13 +344,15 @@ void CMap::Draw()
if ( m_map[i].bUsed ) // selection:
DrawFocus(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color);
- for ( i=0 ; i<m_totalFix ; i++ ) { // fixed objects:
+ for ( i=0 ; i<m_totalFix ; i++ ) // fixed objects:
+ {
if ( i == m_highlightRank )
continue;
DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, false);
}
- for ( i=MAPMAXOBJECT-2 ; i>m_totalMove ; i-- ) { // moving objects:
+ for ( i=MAPMAXOBJECT-2 ; i>m_totalMove ; i-- ) // moving objects:
+ {
if ( i == m_highlightRank )
continue;
DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, false);
@@ -353,7 +362,8 @@ void CMap::Draw()
if ( m_map[i].bUsed && i != m_highlightRank ) // selection:
DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, true, false);
- if ( m_highlightRank != -1 && m_map[m_highlightRank].bUsed ) {
+ if ( m_highlightRank != -1 && m_map[m_highlightRank].bUsed )
+ {
i = m_highlightRank;
DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, true);
DrawHighlight(m_map[i].pos);
@@ -375,23 +385,27 @@ Math::Point CMap::MapInter(Math::Point pos, float dir)
p1.y -= pos.y;
limit = m_mapPos.x + m_mapDim.x - pos.x;
- if ( p1.x > limit ) { // exceeds the right?
+ if ( p1.x > limit ) // exceeds the right?
+ {
p1.y = limit*p1.y/p1.x;
p1.x = limit;
}
limit = m_mapPos.y * 0.75f + m_mapDim.y * 0.75f - pos.y;
- if ( p1.y > limit ) { // exceeds the top?
+ if ( p1.y > limit ) // exceeds the top?
+ {
p1.x = limit * p1.x / p1.y;
p1.y = limit;
}
limit = m_mapPos.x - pos.x;
- if ( p1.x < limit ) { // exceeds the left?
+ if ( p1.x < limit ) // exceeds the left?
+ {
p1.y = limit * p1.y / p1.x;
p1.x = limit;
}
limit = m_mapPos.y * 0.75f - pos.y;
- if ( p1.y < limit ) { // exceeds the bottom?
+ if ( p1.y < limit ) // exceeds the bottom?
+ {
p1.x = limit * p1.x / p1.y;
p1.y = limit;
}
@@ -1152,7 +1166,7 @@ void CMap::UpdateObject(CObject* pObj)
pos.z = ppos.y;
dir += m_angle;
}
-
+
color = MAPCOLOR_NULL;
if ( type == OBJECT_BASE )
{
@@ -1303,3 +1317,4 @@ void CMap::UpdateObject(CObject* pObj)
}
}
+
diff --git a/src/ui/map.h b/src/ui/map.h
index 258dcdf..4ebe688 100644
--- a/src/ui/map.h
+++ b/src/ui/map.h
@@ -69,78 +69,79 @@ struct MapObject
class CMap : public CControl
{
- public:
- CMap();
- ~CMap();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- bool EventProcess(const Event &event);
- void Draw();
-
- void UpdateTerrain();
- void UpdateTerrain(int bx, int by, int ex, int ey);
-
- void SetFixImage(const char *filename);
- bool GetFixImage();
-
- void SetOffset(float ox, float oy);
- void SetAngle(float angle);
- void SetMode(int mode);
- void SetToy(bool bToy);
- void SetDebug(bool bDebug);
-
- void SetZoom(float value);
- float GetZoom();
-
- void SetEnable(bool bEnable);
- bool GetEnable();
-
- void SetFloorColor(Gfx::Color color);
- void SetWaterColor(Gfx::Color color);
-
- void FlushObject();
- void UpdateObject(CObject* pObj);
-
- CObject* DetectObject(Math::Point pos, bool &bInMap);
- void SetHighlight(CObject* pObj);
-
- protected:
- Math::Point AdjustOffset(Math::Point offset);
- void SelectObject(Math::Point pos);
- Math::Point MapInter(Math::Point pos, float dir);
- void DrawFocus(Math::Point pos, float dir, ObjectType type, MapColor color);
- void DrawObject(Math::Point pos, float dir, ObjectType type, MapColor color, bool bSelect, bool bHilite);
- void DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color, ObjectType type, bool bHilite);
- void DrawHighlight(Math::Point pos);
- void DrawTriangle(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point uv1, Math::Point uv2);
- void DrawPenta(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point p4, Math::Point p5, Math::Point uv1, Math::Point uv2);
- void DrawVertex(Math::Point uv1, Math::Point uv2, float zoom);
-
- protected:
- Gfx::CTerrain* m_terrain;
- Gfx::CWater* m_water;
- CRobotMain* m_main;
-
- bool m_bEnable;
- float m_time;
- float m_half;
- float m_zoom;
- Math::Point m_offset;
- float m_angle;
- Gfx::Color m_floorColor;
- Gfx::Color m_waterColor;
- MapObject m_map[MAPMAXOBJECT];
- int m_totalFix;
- int m_totalMove;
- int m_highlightRank;
- Math::Point m_mapPos;
- Math::Point m_mapDim;
- bool m_bRadar;
- char m_fixImage[100];
- int m_mode;
- bool m_bToy;
- bool m_bDebug;
+public:
+ CMap();
+ ~CMap();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void UpdateTerrain();
+ void UpdateTerrain(int bx, int by, int ex, int ey);
+
+ void SetFixImage(const char *filename);
+ bool GetFixImage();
+
+ void SetOffset(float ox, float oy);
+ void SetAngle(float angle);
+ void SetMode(int mode);
+ void SetToy(bool bToy);
+ void SetDebug(bool bDebug);
+
+ void SetZoom(float value);
+ float GetZoom();
+
+ void SetEnable(bool bEnable);
+ bool GetEnable();
+
+ void SetFloorColor(Gfx::Color color);
+ void SetWaterColor(Gfx::Color color);
+
+ void FlushObject();
+ void UpdateObject(CObject* pObj);
+
+ CObject* DetectObject(Math::Point pos, bool &bInMap);
+ void SetHighlight(CObject* pObj);
+
+protected:
+ Math::Point AdjustOffset(Math::Point offset);
+ void SelectObject(Math::Point pos);
+ Math::Point MapInter(Math::Point pos, float dir);
+ void DrawFocus(Math::Point pos, float dir, ObjectType type, MapColor color);
+ void DrawObject(Math::Point pos, float dir, ObjectType type, MapColor color, bool bSelect, bool bHilite);
+ void DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color, ObjectType type, bool bHilite);
+ void DrawHighlight(Math::Point pos);
+ void DrawTriangle(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point uv1, Math::Point uv2);
+ void DrawPenta(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point p4, Math::Point p5, Math::Point uv1, Math::Point uv2);
+ void DrawVertex(Math::Point uv1, Math::Point uv2, float zoom);
+
+protected:
+ Gfx::CTerrain* m_terrain;
+ Gfx::CWater* m_water;
+ CRobotMain* m_main;
+
+ bool m_bEnable;
+ float m_time;
+ float m_half;
+ float m_zoom;
+ Math::Point m_offset;
+ float m_angle;
+ Gfx::Color m_floorColor;
+ Gfx::Color m_waterColor;
+ MapObject m_map[MAPMAXOBJECT];
+ int m_totalFix;
+ int m_totalMove;
+ int m_highlightRank;
+ Math::Point m_mapPos;
+ Math::Point m_mapDim;
+ bool m_bRadar;
+ char m_fixImage[100];
+ int m_mode;
+ bool m_bToy;
+ bool m_bDebug;
};
}
+
diff --git a/src/ui/scroll.cpp b/src/ui/scroll.cpp
index ff7451d..b3422ec 100644
--- a/src/ui/scroll.cpp
+++ b/src/ui/scroll.cpp
@@ -467,3 +467,4 @@ float CScroll::GetArrowStep()
}
}
+
diff --git a/src/ui/scroll.h b/src/ui/scroll.h
index 57d6f8f..c115aa4 100644
--- a/src/ui/scroll.h
+++ b/src/ui/scroll.h
@@ -34,51 +34,52 @@ const float SCROLL_WIDTH = (15.0f/640.0f);
class CScroll : public CControl
{
- public:
- CScroll();
- ~CScroll();
+public:
+ CScroll();
+ ~CScroll();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
- bool SetState(int state, bool bState);
- bool SetState(int state);
- bool ClearState(int state);
+ bool SetState(int state, bool bState);
+ bool SetState(int state);
+ bool ClearState(int state);
- bool EventProcess(const Event &event);
- void Draw();
+ bool EventProcess(const Event &event);
+ void Draw();
- void SetVisibleValue(float value);
- float GetVisibleValue();
+ void SetVisibleValue(float value);
+ float GetVisibleValue();
- void SetVisibleRatio(float value);
- float GetVisibleRatio();
+ void SetVisibleRatio(float value);
+ float GetVisibleRatio();
- void SetArrowStep(float step);
- float GetArrowStep();
+ void SetArrowStep(float step);
+ float GetArrowStep();
- protected:
- void MoveAdjust();
- void AdjustGlint();
- void DrawVertex(Math::Point pos, Math::Point dim, int icon);
+protected:
+ void MoveAdjust();
+ void AdjustGlint();
+ void DrawVertex(Math::Point pos, Math::Point dim, int icon);
- protected:
- CButton* m_buttonUp;
- CButton* m_buttonDown;
+protected:
+ CButton* m_buttonUp;
+ CButton* m_buttonDown;
- float m_visibleValue;
- float m_visibleRatio;
- float m_step;
+ float m_visibleValue;
+ float m_visibleRatio;
+ float m_step;
- bool m_bCapture;
- Math::Point m_pressPos;
- float m_pressValue;
+ bool m_bCapture;
+ Math::Point m_pressPos;
+ float m_pressValue;
- EventType m_eventUp;
- EventType m_eventDown;
+ EventType m_eventUp;
+ EventType m_eventDown;
};
}
+
diff --git a/src/ui/shortcut.cpp b/src/ui/shortcut.cpp
index 4462140..a01864a 100644
--- a/src/ui/shortcut.cpp
+++ b/src/ui/shortcut.cpp
@@ -128,7 +128,7 @@ void CShortcut::Draw()
if ( m_state & STATE_FRAME )
{
Math::Point p1, p2, c, uv1, uv2;
- float zoom, dp;
+ float dp;
m_engine->SetTexture("button2.png");
m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE);
@@ -237,3 +237,4 @@ void CShortcut::DrawVertex(int icon, float zoom)
}
}
+
diff --git a/src/ui/shortcut.h b/src/ui/shortcut.h
index 7e7899e..6495ba0 100644
--- a/src/ui/shortcut.h
+++ b/src/ui/shortcut.h
@@ -27,22 +27,23 @@ namespace Ui {
class CShortcut : public CControl
{
- public:
- CShortcut();
- ~CShortcut();
+public:
+ CShortcut();
+ ~CShortcut();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventType);
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventType);
- bool EventProcess(const Event &event);
+ bool EventProcess(const Event &event);
- void Draw();
+ void Draw();
- protected:
- void DrawVertex(int icon, float zoom);
+protected:
+ void DrawVertex(int icon, float zoom);
- protected:
- float m_time;
+protected:
+ float m_time;
};
}
+
diff --git a/src/ui/slider.cpp b/src/ui/slider.cpp
index f516e70..33293d1 100644
--- a/src/ui/slider.cpp
+++ b/src/ui/slider.cpp
@@ -581,3 +581,4 @@ float CSlider::GetArrowStep()
}
+
diff --git a/src/ui/slider.h b/src/ui/slider.h
index 4912453..bc38aec 100644
--- a/src/ui/slider.h
+++ b/src/ui/slider.h
@@ -29,54 +29,55 @@ class CButton;
class CSlider : public CControl
{
- public:
- CSlider();
- ~CSlider();
+public:
+ CSlider();
+ ~CSlider();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
- bool SetState(int state, bool bState);
- bool SetState(int state);
- bool ClearState(int state);
+ bool SetState(int state, bool bState);
+ bool SetState(int state);
+ bool ClearState(int state);
- bool EventProcess(const Event &event);
- void Draw();
+ bool EventProcess(const Event &event);
+ void Draw();
- void SetLimit(float min, float max);
+ void SetLimit(float min, float max);
- void SetVisibleValue(float value);
- float GetVisibleValue();
+ void SetVisibleValue(float value);
+ float GetVisibleValue();
- void SetArrowStep(float step);
- float GetArrowStep();
+ void SetArrowStep(float step);
+ float GetArrowStep();
- protected:
- void MoveAdjust();
- void AdjustGlint();
- void DrawVertex(Math::Point pos, Math::Point dim, int icon);
+protected:
+ void MoveAdjust();
+ void AdjustGlint();
+ void DrawVertex(Math::Point pos, Math::Point dim, int icon);
- protected:
- CButton* m_buttonLeft;
- CButton* m_buttonRight;
+protected:
+ CButton* m_buttonLeft;
+ CButton* m_buttonRight;
- float m_min;
- float m_max;
- float m_visibleValue;
- float m_step;
+ float m_min;
+ float m_max;
+ float m_visibleValue;
+ float m_step;
- bool m_bHoriz;
- float m_marginButton;
+ bool m_bHoriz;
+ float m_marginButton;
- bool m_bCapture;
- Math::Point m_pressPos;
- float m_pressValue;
+ bool m_bCapture;
+ Math::Point m_pressPos;
+ float m_pressValue;
- EventType m_eventUp;
- EventType m_eventDown;
+ EventType m_eventUp;
+ EventType m_eventDown;
};
}
+
diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp
index 29dfebf..e44a465 100644
--- a/src/ui/studio.cpp
+++ b/src/ui/studio.cpp
@@ -167,7 +167,7 @@ bool CStudio::EventProcess(const Event &event)
{
slider = static_cast< CSlider* >(pw->SearchControl(EVENT_STUDIO_SIZE));
if ( slider == nullptr ) return false;
- m_main->SetFontSize(9.0f+slider->GetVisibleValue()*6.0f);
+ m_main->SetFontSize(9.0f+slider->GetVisibleValue()*12.0f);
ViewEditScript();
}
@@ -904,7 +904,7 @@ void CStudio::SetInfoText(std::string text, bool bClickable)
if ( list == 0 ) return;
list->Flush(); // just text
- list->SetName(0, text.c_str());
+ list->SetItemName(0, text.c_str());
if ( text[0] == 0 ) bClickable = false;
list->SetSelectCap(bClickable);
@@ -1397,7 +1397,7 @@ void CStudio::UpdateChangeList()
pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT));
if ( pe == nullptr ) return;
- strcpy(name, pl->GetName(pl->GetSelect()));
+ strcpy(name, pl->GetItemName(pl->GetSelect()));
name[pe->GetMaxChar()] = 0; // truncates according lg max editable
p = strchr(name, '\t'); // seeks first tab
if ( p != 0 ) *p = 0;
@@ -1511,7 +1511,6 @@ void CStudio::UpdateDialogList()
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;
@@ -1521,13 +1520,16 @@ void CStudio::UpdateDialogList()
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()) ) {
+ 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()) )
+ {
+ std::ostringstream temp;
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);
+ temp << file->path().filename().string() << '\t' << fs::file_size(file->path()) << " \t" << time;
+ pl->SetItemName(i++, temp.str().c_str());
}
}
}
@@ -1539,15 +1541,19 @@ void CStudio::UpdateDialogList()
std::string CStudio::SearchDirectory(bool bCreate)
{
char dir[MAX_FNAME];
- if ( m_main->GetIOPublic() ) {
+ if ( m_main->GetIOPublic() )
+ {
sprintf(dir, "%s/", m_main->GetPublicDir());
- } else {
+ }
+ else
+ {
sprintf(dir, "%s/%s/Program/", m_main->GetSavegameDir(), m_main->GetGamerName());
}
-
+
fs::path path = fs::path(dir);
-
- if ( bCreate ) {
+
+ if ( bCreate )
+ {
fs::create_directory(path);
}
@@ -1630,3 +1636,4 @@ bool CStudio::WriteProgram()
}
}
+
diff --git a/src/ui/target.cpp b/src/ui/target.cpp
index cc74750..455c530 100644
--- a/src/ui/target.cpp
+++ b/src/ui/target.cpp
@@ -272,3 +272,4 @@ CObject* CTarget::DetectFriendObject(Math::Point pos)
}
}
+
diff --git a/src/ui/target.h b/src/ui/target.h
index 054524b..2344e59 100644
--- a/src/ui/target.h
+++ b/src/ui/target.h
@@ -36,19 +36,20 @@ namespace Ui {
class CTarget : public CControl
{
- public:
- CTarget();
- ~CTarget();
+public:
+ CTarget();
+ ~CTarget();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventType eventMsg);
- bool EventProcess(const Event &event);
- void Draw();
- bool GetTooltip(Math::Point pos, std::string &name);
+ bool EventProcess(const Event &event);
+ void Draw();
+ bool GetTooltip(Math::Point pos, std::string &name);
- protected:
- CObject* DetectFriendObject(Math::Point pos);
+protected:
+ CObject* DetectFriendObject(Math::Point pos);
};
}
+
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index 6013d37..8005939 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -355,6 +355,9 @@ CSlider* CWindow::CreateSlider(Math::Point pos, Math::Point dim, int icon, Event
}
// Creates a new list.
+// if expand is less then zero, then the list would try to use expand's absolute value,
+// and try to scale items to some size, so that dim of the list would not change after
+// adjusting
CList* CWindow::CreateList(Math::Point pos, Math::Point dim, int icon, EventType eventMsg,
float expand)
@@ -573,12 +576,12 @@ bool CWindow::GetTooltip(Math::Point pos, std::string &name)
// Specifies the name for the title bar.
-void CWindow::SetName(std::string name)
+void CWindow::SetName(std::string name, bool tooltip)
{
CButton* pc;
bool bAdjust;
- CControl::SetName(name);
+ CControl::SetName(name, tooltip);
if ( m_buttonReduce != 0 )
{
@@ -1576,3 +1579,4 @@ void CWindow::DrawHach(Math::Point pos, Math::Point dim)
}
}
+
diff --git a/src/ui/window.h b/src/ui/window.h
index e39b8a9..87805e2 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -83,7 +83,7 @@ public:
EventType GetEventTypeFull();
EventType GetEventTypeClose();
- void SetName(std::string name);
+ virtual void SetName(std::string name, bool tooltip = true) override;
void SetTrashEvent(bool bTrash);
bool GetTrashEvent();
@@ -151,3 +151,4 @@ protected:
}
+
diff --git a/test/envs/opengl/CMakeLists.txt b/test/envs/opengl/CMakeLists.txt
index 0bcb43d..2855318 100644
--- a/test/envs/opengl/CMakeLists.txt
+++ b/test/envs/opengl/CMakeLists.txt
@@ -3,15 +3,16 @@ set(SRC_DIR ${colobot_SOURCE_DIR}/src)
configure_file(${SRC_DIR}/common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h)
# Platform-dependent implementation of system.h
-if (${PLATFORM_WINDOWS})
+if(PLATFORM_WINDOWS)
set(SYSTEM_CPP_MODULE "system_windows.cpp")
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
set(SYSTEM_CPP_MODULE "system_linux.cpp")
else()
set(SYSTEM_CPP_MODULE "system_other.cpp")
endif()
set(TEXTURE_SOURCES
+${SRC_DIR}/graphics/core/color.cpp
${SRC_DIR}/graphics/opengl/gldevice.cpp
${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/image.cpp
@@ -19,6 +20,7 @@ texture_test.cpp
)
set(MODEL_SOURCES
+${SRC_DIR}/graphics/core/color.cpp
${SRC_DIR}/graphics/opengl/gldevice.cpp
${SRC_DIR}/graphics/engine/modelfile.cpp
${SRC_DIR}/common/logger.cpp
@@ -30,6 +32,7 @@ model_test.cpp
)
set(TRANSFORM_SOURCES
+${SRC_DIR}/graphics/core/color.cpp
${SRC_DIR}/graphics/opengl/gldevice.cpp
${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/image.cpp
@@ -39,6 +42,7 @@ transform_test.cpp
)
set(LIGHT_SOURCES
+${SRC_DIR}/graphics/core/color.cpp
${SRC_DIR}/graphics/opengl/gldevice.cpp
${SRC_DIR}/common/logger.cpp
${SRC_DIR}/common/image.cpp
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 3d8a38c..95cf1b1 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -1,14 +1,14 @@
set(SRC_DIR ${colobot_SOURCE_DIR}/src)
# Additional libraries per platform
-if (${MXE}) # MXE requires special treatment
+if(MXE) # MXE requires special treatment
set(PLATFORM_LIBS ${MXE_LIBS})
-elseif (${PLATFORM_WINDOWS})
+elseif(PLATFORM_WINDOWS)
# because it isn't included in standard linking libraries
set(PLATFORM_LIBS "-lintl")
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
# for clock_gettime
- set(PLATFORM_LIBS "-lrt")
+ set(PLATFORM_LIBS "-lrt -lX11")
endif()
@@ -16,9 +16,9 @@ endif()
configure_file(${SRC_DIR}/common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h)
# Platform-dependent implementation of system.h
-if (${PLATFORM_WINDOWS})
+if(PLATFORM_WINDOWS)
set(SYSTEM_CPP_MODULE "system_windows.cpp")
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
set(SYSTEM_CPP_MODULE "system_linux.cpp")
else()
set(SYSTEM_CPP_MODULE "system_other.cpp")
@@ -89,7 +89,9 @@ ${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/motion/motiondummy.cpp
${SRC_DIR}/object/object.cpp
+${SRC_DIR}/object/objman.cpp
${SRC_DIR}/object/robotmain.cpp
${SRC_DIR}/object/task/task.cpp
${SRC_DIR}/object/task/taskadvance.cpp
@@ -116,6 +118,7 @@ ${SRC_DIR}/physics/physics.cpp
${SRC_DIR}/script/cbottoken.cpp
${SRC_DIR}/script/cmdtoken.cpp
${SRC_DIR}/script/script.cpp
+${SRC_DIR}/sound/sound.cpp
${SRC_DIR}/ui/button.cpp
${SRC_DIR}/ui/check.cpp
${SRC_DIR}/ui/color.cpp
@@ -146,7 +149,7 @@ ${SRC_DIR}/ui/window.cpp
set(OPENAL_SOURCES "")
-if (${OPENAL_SOUND})
+if(OPENAL_SOUND)
set(OPENAL_SOURCES
${SRC_DIR}/sound/oalsound/alsound.cpp
${SRC_DIR}/sound/oalsound/buffer.cpp
@@ -157,16 +160,16 @@ endif()
# Optional libraries
set(OPTIONAL_LIBS "")
-if (${OPENAL_SOUND})
+if(OPENAL_SOUND)
set(OPTIONAL_LIBS ${OPENAL_LIBRARY})
set(OPTIONAL_INCLUDES ${OPENAL_INCLUDE_DIR})
endif()
# Platform-dependent tests
-if (${PLATFORM_WINDOWS})
+if(PLATFORM_WINDOWS)
set(PLATFORM_TESTS app/system_windows_test.cpp)
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
set(PLATFORM_TESTS app/system_linux_test.cpp)
endif()
@@ -175,6 +178,7 @@ set(UT_SOURCES
main.cpp
app/app_test.cpp
graphics/engine/lightman_test.cpp
+math/func_test.cpp
math/geometry_test.cpp
math/matrix_test.cpp
math/vector_test.cpp
@@ -203,12 +207,16 @@ ${GLEW_INCLUDE_PATH}
${Boost_INCLUDE_DIRS}
${OPTIONAL_INCLUDE_DIRS}
${LIBSNDFILE_INCLUDE_DIR}
+${CLIPBOARD_INCLUDE_DIR}
+${LOCALENAME_INCLUDE_DIR}
)
set(LIBS
gtest
gmock
CBot
+clipboard
+localename
${SDL_LIBRARY}
${SDLIMAGE_LIBRARY}
${SDLTTF_LIBRARY}
diff --git a/test/unit/app/app_test.cpp b/test/unit/app/app_test.cpp
index 8c1e899..b517d7d 100644
--- a/test/unit/app/app_test.cpp
+++ b/test/unit/app/app_test.cpp
@@ -10,8 +10,6 @@
#include "app/system_mock.h"
-#include "common/logger.h"
-
#include <gtest/gtest.h>
using testing::_;
@@ -57,7 +55,6 @@ protected:
long long relTimeReal, long long absTimeReal);
protected:
- CLogger logger;
CApplicationWrapper* app;
CSystemUtilsMock* systemUtils;
diff --git a/test/unit/graphics/core/device_mock.h b/test/unit/graphics/core/device_mock.h
index 80e214f..9e75daf 100644
--- a/test/unit/graphics/core/device_mock.h
+++ b/test/unit/graphics/core/device_mock.h
@@ -10,6 +10,7 @@ public:
CDeviceMock() {}
MOCK_METHOD0(DebugHook, void());
+ MOCK_METHOD0(DebugLights, void());
MOCK_METHOD0(Create, bool());
MOCK_METHOD0(Destroy, void());
diff --git a/src/graphics/engine/test/modelfile_test.cpp b/test/unit/graphics/engine/modelfile_test.cpp
index e7078a9..0598e84 100644
--- a/src/graphics/engine/test/modelfile_test.cpp
+++ b/test/unit/graphics/engine/modelfile_test.cpp
@@ -1,22 +1,5 @@
-// * This file is part of the COLOBOT source code
-// * 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 "common/logger.h"
#include "graphics/engine/modelfile.h"
+
#include "math/func.h"
#include <gtest/gtest.h>
@@ -63,17 +46,17 @@ void Init()
{
TRIANGLE_1.p1 = Gfx::VertexTex2(Math::Vector(-12.4099, 10.0016, -2.54558),
- Math::Vector(1, 0, 1.87319e-07),
- Math::Point(0.970703, 0.751953),
- Math::Point(0, 0));
+ Math::Vector(1, 0, 1.87319e-07),
+ Math::Point(0.970703, 0.751953),
+ Math::Point(0, 0));
TRIANGLE_1.p2 = Gfx::VertexTex2(Math::Vector(-12.4099, 10.0016, 2.54558),
- Math::Vector(1, 0, 1.87319e-07),
- Math::Point(0.998047, 0.751953),
- Math::Point(0, 0));
+ Math::Vector(1, 0, 1.87319e-07),
+ Math::Point(0.998047, 0.751953),
+ Math::Point(0, 0));
TRIANGLE_1.p3 = Gfx::VertexTex2(Math::Vector(-12.4099, 4.00165, -2.54558),
- Math::Vector(1, 0, 1.87319e-07),
- Math::Point(0.970703, 0.998047),
- Math::Point(0, 0));
+ Math::Vector(1, 0, 1.87319e-07),
+ Math::Point(0.970703, 0.998047),
+ Math::Point(0, 0));
TRIANGLE_1.material.diffuse = Gfx::Color(1, 1, 1, 0);
TRIANGLE_1.material.ambient = Gfx::Color(0.5, 0.5, 0.5, 0);
TRIANGLE_1.material.specular = Gfx::Color(0, 0, 0, 0);
@@ -83,17 +66,17 @@ void Init()
TRIANGLE_1.state = 1024;
TRIANGLE_2.p1 = Gfx::VertexTex2(Math::Vector(-19, -1, 4),
- Math::Vector(-1, 0, 0),
- Math::Point(0.248047, 0.123047),
- Math::Point(0.905224, 0.52067));
+ Math::Vector(-1, 0, 0),
+ Math::Point(0.248047, 0.123047),
+ Math::Point(0.905224, 0.52067));
TRIANGLE_2.p2 = Gfx::VertexTex2(Math::Vector(-19, 4, 4),
- Math::Vector(-1, 0, 0),
- Math::Point(0.248047, 0.00195312),
- Math::Point(0.905224, 0.614223));
+ Math::Vector(-1, 0, 0),
+ Math::Point(0.248047, 0.00195312),
+ Math::Point(0.905224, 0.614223));
TRIANGLE_2.p3 = Gfx::VertexTex2(Math::Vector(-19, 4, -4),
- Math::Vector(-1, 0, 0),
- Math::Point(0.00195312, 0.00195312),
- Math::Point(0.0947756, 0.614223));
+ Math::Vector(-1, 0, 0),
+ Math::Point(0.00195312, 0.00195312),
+ Math::Point(0.0947756, 0.614223));
TRIANGLE_2.material.diffuse = Gfx::Color(1, 1, 1, 0);
TRIANGLE_2.material.ambient = Gfx::Color(0.5, 0.5, 0.5, 0);
TRIANGLE_2.material.specular = Gfx::Color(0, 0, 0, 0);
@@ -250,13 +233,3 @@ TEST(ModelFileTest, RWOldModel)
EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[0], TRIANGLE_1));
EXPECT_TRUE(CompareTriangles(modelFile.GetTriangles()[1], TRIANGLE_2));
}
-
-int main(int argc, char **argv)
-{
- CLogger logger;
-
- Init();
-
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/test/unit/main.cpp b/test/unit/main.cpp
index e978630..7d08f58 100644
--- a/test/unit/main.cpp
+++ b/test/unit/main.cpp
@@ -14,10 +14,14 @@
// * 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 "gtest/gtest.h"
+#include "common/logger.h"
+
+#include <gtest/gtest.h>
int main(int argc, char* argv[])
{
+ CLogger logger;
+
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/test/unit/math/func_test.cpp b/test/unit/math/func_test.cpp
new file mode 100644
index 0000000..57f1347
--- /dev/null
+++ b/test/unit/math/func_test.cpp
@@ -0,0 +1,39 @@
+/*
+ Unit tests for math functions.
+ */
+
+#include "math/func.h"
+
+#include <gtest/gtest.h>
+
+
+TEST(IsPowerOfTwo, TestDifferentValues)
+{
+ EXPECT_FALSE(Math::IsPowerOfTwo(0));
+ EXPECT_TRUE(Math::IsPowerOfTwo(1));
+ EXPECT_TRUE(Math::IsPowerOfTwo(2));
+ EXPECT_FALSE(Math::IsPowerOfTwo(3));
+ EXPECT_TRUE(Math::IsPowerOfTwo(4));
+
+ EXPECT_FALSE(Math::IsPowerOfTwo(31));
+ EXPECT_TRUE(Math::IsPowerOfTwo(32));
+ EXPECT_FALSE(Math::IsPowerOfTwo(33));
+
+ EXPECT_FALSE(Math::IsPowerOfTwo(1234));
+}
+
+TEST(NextPowerOfTwo, TestDifferentValues)
+{
+ EXPECT_EQ(2, Math::NextPowerOfTwo(2));
+ EXPECT_EQ(4, Math::NextPowerOfTwo(3));
+ EXPECT_EQ(4, Math::NextPowerOfTwo(4));
+ EXPECT_EQ(8, Math::NextPowerOfTwo(5));
+
+ EXPECT_EQ(8, Math::NextPowerOfTwo(7));
+ EXPECT_EQ(8, Math::NextPowerOfTwo(8));
+ EXPECT_EQ(16, Math::NextPowerOfTwo(9));
+
+ EXPECT_EQ(32, Math::NextPowerOfTwo(31));
+ EXPECT_EQ(32, Math::NextPowerOfTwo(32));
+ EXPECT_EQ(64, Math::NextPowerOfTwo(33));
+}
diff --git a/test/unit/math/geometry_test.cpp b/test/unit/math/geometry_test.cpp
index 7c3e26a..581ef89 100644
--- a/test/unit/math/geometry_test.cpp
+++ b/test/unit/math/geometry_test.cpp
@@ -1,25 +1,9 @@
-// * This file is part of the COLOBOT source code
-// * 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/.
-
/* Unit tests for functions in geometry.h */
#include "math/func.h"
#include "math/geometry.h"
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
const float TEST_TOLERANCE = 1e-5;
diff --git a/test/unit/math/matrix_test.cpp b/test/unit/math/matrix_test.cpp
index 5f5c3af..7693a85 100644
--- a/test/unit/math/matrix_test.cpp
+++ b/test/unit/math/matrix_test.cpp
@@ -1,19 +1,3 @@
-// * This file is part of the COLOBOT source code
-// * 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/.
-
/*
Unit tests for Matrix struct
@@ -24,7 +8,7 @@
#include "math/func.h"
#include "math/matrix.h"
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
const float TEST_TOLERANCE = 1e-6;
diff --git a/test/unit/math/vector_test.cpp b/test/unit/math/vector_test.cpp
index 41bac74..6fe30be 100644
--- a/test/unit/math/vector_test.cpp
+++ b/test/unit/math/vector_test.cpp
@@ -1,19 +1,3 @@
-// * This file is part of the COLOBOT source code
-// * 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/.
-
/*
Unit tests for Vector struct
@@ -24,7 +8,7 @@
#include "math/func.h"
#include "math/vector.h"
-#include "gtest/gtest.h"
+#include <gtest/gtest.h>
const float TEST_TOLERANCE = 1e-6;
diff --git a/test/unit/ui/CMakeLists.txt b/test/unit/ui/CMakeLists.txt
index c899834..c18af87 100644
--- a/test/unit/ui/CMakeLists.txt
+++ b/test/unit/ui/CMakeLists.txt
@@ -5,15 +5,18 @@ include_directories(
${SRC_DIR}
${GTEST_INCLUDE_DIR}
${GMOCK_INCLUDE_DIR}
+${CLIPBOARD_INCLUDE_DIR}
)
# Platform-dependent implementation of CSystemUtils
-if (${PLATFORM_WINDOWS})
+if(PLATFORM_WINDOWS)
set(SYSTEM_CPP_MODULE "system_windows.cpp")
-elseif(${PLATFORM_LINUX})
+elseif(PLATFORM_LINUX)
set(SYSTEM_CPP_MODULE "system_linux.cpp")
+ set(ADDITIONAL_LIB "-lX11")
else()
set(SYSTEM_CPP_MODULE "system_other.cpp")
+ set(ADDITIONAL_LIB "-lX11")
endif()
add_executable(edit_test
@@ -36,6 +39,9 @@ stubs/particle_stub.cpp
stubs/restext_stub.cpp
stubs/robotmain_stub.cpp
edit_test.cpp)
-target_link_libraries(edit_test gtest gmock ${SDL_LIBRARY} ${SDLTTF_LIBRARY} ${Boost_LIBRARIES})
+
+target_link_libraries(edit_test gtest gmock clipboard ${SDL_LIBRARY} ${SDLTTF_LIBRARY} ${Boost_LIBRARIES} ${ADDITIONAL_LIB})
+
+
add_test(edit_test ./edit_test)
diff --git a/test/unit/ui/edit_test.cpp b/test/unit/ui/edit_test.cpp
index 428b66a..21af00f 100644
--- a/test/unit/ui/edit_test.cpp
+++ b/test/unit/ui/edit_test.cpp
@@ -1,10 +1,13 @@
#include "app/app.h"
+
#include "ui/edit.h"
+
#include "mocks/text_mock.h"
+#include <fstream>
+
#include <gtest/gtest.h>
#include <gmock/gmock.h>
-#include <fstream>
class CEditTest : public testing::Test
{
@@ -17,7 +20,7 @@ public:
virtual void SetUp()
{
- m_robotMain = new CRobotMain(&m_app);
+ m_robotMain = new CRobotMain(&m_app, false);
m_engine = new Gfx::CEngine(nullptr);
diff --git a/test/unit/ui/stubs/app_stub.cpp b/test/unit/ui/stubs/app_stub.cpp
index 9b33e5e..960972f 100644
--- a/test/unit/ui/stubs/app_stub.cpp
+++ b/test/unit/ui/stubs/app_stub.cpp
@@ -21,7 +21,7 @@ CApplication::~CApplication()
{
}
-std::string CApplication::GetDataFilePath(DataDir /* dataDir */, const std::string& subpath)
+std::string CApplication::GetDataFilePath(DataDir /* dataDir */, const std::string& subpath) const
{
return subpath;
}
@@ -36,7 +36,7 @@ CEventQueue* CApplication::GetEventQueue()
return nullptr;
}
-std::string CApplication::GetDataDirPath()
+std::string CApplication::GetDataDirPath() const
{
return "";
}
@@ -46,7 +46,7 @@ Event CApplication::CreateUpdateEvent()
return Event(EVENT_NULL);
}
-char CApplication::GetLanguageChar()
+char CApplication::GetLanguageChar() const
{
return 'E';
}
diff --git a/test/unit/ui/stubs/robotmain_stub.cpp b/test/unit/ui/stubs/robotmain_stub.cpp
index 7988e9d..692f67f 100644
--- a/test/unit/ui/stubs/robotmain_stub.cpp
+++ b/test/unit/ui/stubs/robotmain_stub.cpp
@@ -3,7 +3,7 @@
template<> CRobotMain* CSingleton<CRobotMain>::m_instance = nullptr;
-CRobotMain::CRobotMain(CApplication* app)
+CRobotMain::CRobotMain(CApplication* app, bool loadProfile)
{
}
diff --git a/tools/fix-eof-eol.sh b/tools/fix-eof-eol.sh
new file mode 100755
index 0000000..a077c85
--- /dev/null
+++ b/tools/fix-eof-eol.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# Formats files to have one newline at the end of file
+
+for file in $@; do
+awk '/^$/ { ws++; next; }
+
+{
+ for (i = 0; i < ws; ++i) { print ""; }
+ print $0;
+ ws = 0;
+}
+
+END {
+ print "";
+}' $file > ${file}.out && mv ${file}.out $file
+done
diff --git a/tools/git-grep-braces.sh b/tools/git-grep-braces.sh
new file mode 100755
index 0000000..85823ab
--- /dev/null
+++ b/tools/git-grep-braces.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+# Finds all "hanging" braces
+git grep -n -E '^( *[^ ]+)+[^@]\{\s*$' -- '*.cpp' '*.h'