Release 0.1.10-alpha: Merge branch 'dev'
commit
1dcc70c097
|
@ -16,9 +16,9 @@ set(COLOBOT_VERSION_MINOR 1)
|
|||
set(COLOBOT_VERSION_REVISION 9)
|
||||
|
||||
# Used on official releases
|
||||
set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha")
|
||||
#set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha")
|
||||
# Used on unreleased, development builds
|
||||
#set(COLOBOT_VERSION_UNRELEASED "+alpha")
|
||||
set(COLOBOT_VERSION_UNRELEASED "+alpha")
|
||||
|
||||
# Append git characteristics to version
|
||||
if(DEFINED COLOBOT_VERSION_UNRELEASED)
|
||||
|
@ -132,8 +132,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
|||
|
||||
message(STATUS "Detected GCC version 4.7+")
|
||||
|
||||
set(NORMAL_CXX_FLAGS "-std=gnu++11 -Wall -Wold-style-cast -pedantic-errors")
|
||||
set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -fno-delete-null-pointer-checks") # Temporary hack, see #828
|
||||
set(NORMAL_CXX_FLAGS "-std=gnu++11 -Wall -Werror -Wold-style-cast -pedantic-errors")
|
||||
set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -Wno-error=deprecated-declarations") # updated version of physfs is not available on some platforms so we keep using deprecated functions, see #958
|
||||
set(RELEASE_CXX_FLAGS "-O2")
|
||||
set(DEBUG_CXX_FLAGS "-g -O0")
|
||||
set(TEST_CXX_FLAGS "-pthread")
|
||||
|
@ -145,7 +145,8 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|||
|
||||
message(STATUS "Detected Clang version 3.1+")
|
||||
|
||||
set(NORMAL_CXX_FLAGS "-std=c++11 -Wall -Wold-style-cast -pedantic-errors")
|
||||
set(NORMAL_CXX_FLAGS "-std=c++11 -Wall -Werror -Wold-style-cast -pedantic-errors")
|
||||
set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -Wno-error=deprecated-declarations") # updated version of physfs is not available on some platforms so we keep using deprecated functions, see #958
|
||||
set(RELEASE_CXX_FLAGS "-O2")
|
||||
set(DEBUG_CXX_FLAGS "-g -O0")
|
||||
set(TEST_CXX_FLAGS "-pthread")
|
||||
|
|
|
@ -351,7 +351,7 @@ IDL_PROPERTY_SUPPORT = YES
|
|||
# all members of a group must be documented explicitly.
|
||||
# The default value is: NO.
|
||||
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
DISTRIBUTE_GROUP_DOC = YES
|
||||
|
||||
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
|
||||
# (for instance a group of public functions) to be put as a subgroup of that
|
||||
|
@ -993,7 +993,7 @@ USE_HTAGS = NO
|
|||
# See also: Section \class.
|
||||
# The default value is: YES.
|
||||
|
||||
VERBATIM_HEADERS = YES
|
||||
VERBATIM_HEADERS = NO
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
|
||||
# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
|
||||
|
|
|
@ -1,50 +1,67 @@
|
|||
node('master') {
|
||||
stage 'Pull changes'
|
||||
checkout scm
|
||||
|
||||
stage 'Build Windows'
|
||||
sh 'mkdir -p build/windows'
|
||||
dir('build/windows') {
|
||||
sh '''
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=/install \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/opt/mxe/usr/i686-w64-mingw32.static/share/cmake/mxe-conf.cmake \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=0 ../..
|
||||
make
|
||||
rm -rf install
|
||||
DESTDIR=. make install
|
||||
'''
|
||||
}
|
||||
sh 'rm -f windows-debug.zip'
|
||||
zip zipFile: 'windows-debug.zip', archive: true, dir: 'build/windows/install'
|
||||
|
||||
stage 'Build Linux'
|
||||
sh 'mkdir -p build/linux'
|
||||
dir('build/linux') {
|
||||
sh '''
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=/install -DCOLOBOT_INSTALL_BIN_DIR=/install -DCOLOBOT_INSTALL_LIB_DIR=/install -DCOLOBOT_INSTALL_DATA_DIR=/install/data -DCOLOBOT_INSTALL_I18N_DIR=/install/lang -DCMAKE_SKIP_INSTALL_RPATH=ON \
|
||||
-DBOOST_STATIC=ON -DGLEW_STATIC=ON -DGLEW_LIBRARY=/usr/lib64/libGLEW.a \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=0 ../..
|
||||
make
|
||||
rm -rf install
|
||||
DESTDIR=. make install
|
||||
patchelf --set-rpath '.' install/colobot
|
||||
'''
|
||||
}
|
||||
sh 'rm -f linux-debug.zip'
|
||||
zip zipFile: 'linux-debug.zip', archive: true, dir: 'build/linux/install'
|
||||
|
||||
stage 'Doxygen'
|
||||
dir('build/linux') {
|
||||
sh 'make doc'
|
||||
}
|
||||
publishHTML target: [$class: 'HtmlPublisherTarget', reportName: 'Doxygen', reportDir: 'build/linux/doc/html', reportFiles: 'index.html']
|
||||
|
||||
stage 'Run tests'
|
||||
dir('build/linux') {
|
||||
sh './colobot_ut --gtest_output=xml:gtestresults.xml || true'
|
||||
}
|
||||
step([$class: 'XUnitBuilder', testTimeMargin: '3000', thresholdMode: 1, thresholds: [[$class: 'FailedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: '0'], [$class: 'SkippedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: '']], tools: [[$class: 'GoogleTestType', deleteOutputFiles: true, failIfNotNew: true, pattern: 'build/linux/gtestresults.xml', skipNoTestFiles: false, stopProcessingIfError: true]]])
|
||||
#!/usr/bin/env groovy
|
||||
if (env.BRANCH_NAME.startsWith('PR-')) {
|
||||
properties([[$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactNumToKeepStr: '1']]])
|
||||
} else {
|
||||
properties([[$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '30', artifactNumToKeepStr: '20']]])
|
||||
}
|
||||
|
||||
node('master') {
|
||||
stage('Pull changes') {
|
||||
checkout scm
|
||||
}
|
||||
|
||||
stage('Build Windows') {
|
||||
sh 'mkdir -p build/windows'
|
||||
dir('build/windows') {
|
||||
sh '''
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=/install \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/opt/mxe/usr/i686-w64-mingw32.static/share/cmake/mxe-conf.cmake \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=0 ../..
|
||||
make
|
||||
rm -rf install
|
||||
DESTDIR=. make install
|
||||
'''
|
||||
}
|
||||
sh 'rm -f windows-debug.zip'
|
||||
zip zipFile: 'windows-debug.zip', archive: true, dir: 'build/windows/install'
|
||||
}
|
||||
|
||||
stage('Build Linux') {
|
||||
sh 'mkdir -p build/linux'
|
||||
dir('build/linux') {
|
||||
sh '''
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=/install -DCOLOBOT_INSTALL_BIN_DIR=/install -DCOLOBOT_INSTALL_LIB_DIR=/install -DCOLOBOT_INSTALL_DATA_DIR=/install/data -DCOLOBOT_INSTALL_I18N_DIR=/install/lang -DCMAKE_SKIP_INSTALL_RPATH=ON \
|
||||
-DBOOST_STATIC=ON -DGLEW_STATIC=ON -DGLEW_LIBRARY=/usr/lib64/libGLEW.a \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=0 ../..
|
||||
make
|
||||
rm -rf install
|
||||
DESTDIR=. make install
|
||||
patchelf --set-rpath '.' install/colobot
|
||||
'''
|
||||
}
|
||||
sh 'rm -f linux-debug.zip'
|
||||
zip zipFile: 'linux-debug.zip', archive: true, dir: 'build/linux/install'
|
||||
}
|
||||
|
||||
stage('Doxygen') {
|
||||
dir('build/linux') {
|
||||
sh 'make doc'
|
||||
}
|
||||
publishHTML target: [$class: 'HtmlPublisherTarget', reportName: 'Doxygen', reportDir: 'build/linux/doc/html', reportFiles: 'index.html']
|
||||
}
|
||||
|
||||
stage('Run tests') {
|
||||
dir('build/linux') {
|
||||
sh './colobot_ut --gtest_output=xml:gtestresults.xml || true'
|
||||
}
|
||||
step([$class: 'XUnitBuilder', testTimeMargin: '3000', thresholdMode: 1, thresholds: [[$class: 'FailedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: '0'], [$class: 'SkippedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: '']], tools: [[$class: 'GoogleTestType', deleteOutputFiles: true, failIfNotNew: true, pattern: 'build/linux/gtestresults.xml', skipNoTestFiles: false, stopProcessingIfError: true]]])
|
||||
}
|
||||
|
||||
// Clean workspace after building pull requests
|
||||
// to save disk space on the Jenkins host
|
||||
if (env.BRANCH_NAME.startsWith('PR-')) {
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ This is official repository for the open-source Colobot: Gold Edition project de
|
|||
|
||||
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 ICC 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](http://colobot.info/wiki/dev/) or [our forum](http://colobot.info/forum/). However, the freshest source of information is our IRC channels (see below).
|
||||
More information for developers (in English) can be found on [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).
|
||||
|
||||
|
|
2
data
2
data
|
@ -1 +1 @@
|
|||
Subproject commit f96cf394a327210ac9e40d68d68963f25633f758
|
||||
Subproject commit 2794fd57c32412d4c9103d20c1ec0c888e1e97a0
|
|
@ -260,6 +260,19 @@ msgstr ""
|
|||
msgid "Generating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Results"
|
||||
msgstr ""
|
||||
|
||||
msgid "The battle has ended"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s: %d pts"
|
||||
msgstr ""
|
||||
|
||||
msgid "Code battle"
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1346,6 +1359,9 @@ msgstr ""
|
|||
msgid "Unknown command"
|
||||
msgstr ""
|
||||
|
||||
msgid "This object is currently busy"
|
||||
msgstr ""
|
||||
|
||||
msgid "Impossible when flying"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1598,6 +1614,18 @@ msgstr ""
|
|||
msgid "Press \\key help; to read instructions on your SatCom"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s finished! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s lost! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s recieved %d points >>>"
|
||||
msgstr ""
|
||||
|
||||
msgid "Opening bracket missing"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1733,6 +1761,18 @@ msgstr ""
|
|||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Class name expected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Non-void function needs \"return;\""
|
||||
msgstr ""
|
||||
|
||||
msgid "This parameter needs a default value"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dividing by zero"
|
||||
msgstr ""
|
||||
|
||||
|
|
286
po/de.po
286
po/de.po
|
@ -1,21 +1,21 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
# Chris <marius.romanus@gmx.net>, 2016.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: DATE\n"
|
||||
"PO-Revision-Date: 2014-07-28 09:27+0200\n"
|
||||
"Last-Translator: krzys_h <krzys_h@interia.pl>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"PO-Revision-Date: 2016-10-28 21:29+0200\n"
|
||||
"Last-Translator: Chris <marius.romanus@gmx.net>\n"
|
||||
"Language-Team: Colobot: Gold Edition freelancer\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Pootle 2.5.1.1\n"
|
||||
"X-Generator: Virtaal 0.7.1\n"
|
||||
"X-Language: de_DE\n"
|
||||
"X-Source-Language: en_US\n"
|
||||
"X-POOTLE-MTIME: 1406536037.000000\n"
|
||||
|
@ -29,6 +29,10 @@ msgstr "Es fehlt eine offene eckige Klammer \" [ \""
|
|||
msgid "\" ] \" missing"
|
||||
msgstr "Es fehlt eine geschlossene eckige Klammer \" ] \""
|
||||
|
||||
#, c-format
|
||||
msgid "%s: %d pts"
|
||||
msgstr ""
|
||||
|
||||
msgid "..behind"
|
||||
msgstr "..hinten"
|
||||
|
||||
|
@ -42,7 +46,7 @@ msgid "1) First click on the key you want to redefine."
|
|||
msgstr "1) Klicken Sie auf die neu zu definierende Taste."
|
||||
|
||||
msgid "2) Then press the key you want to use instead."
|
||||
msgstr "2) Drücken Sie auf die neue Taste."
|
||||
msgstr "2) Drücken Sie auf die neu zu verwendende Taste."
|
||||
|
||||
msgid "<< Back \\Back to the previous screen"
|
||||
msgstr "<< Zurück \\Zurück zum Hauptmenü"
|
||||
|
@ -50,6 +54,18 @@ msgstr "<< Zurück \\Zurück zum Hauptmenü"
|
|||
msgid "<<< Sorry; mission failed >>>"
|
||||
msgstr "<<< Mission gescheitert >>>"
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s finished! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s lost! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s recieved %d points >>>"
|
||||
msgstr ""
|
||||
|
||||
msgid "<<< Well done; mission accomplished >>>"
|
||||
msgstr "<<< Bravo, Mission vollendet >>>"
|
||||
|
||||
|
@ -57,7 +73,7 @@ msgid "A label must be followed by \"for\"; \"while\"; \"do\" or \"switch\""
|
|||
msgstr "Ein Label kann nur vor den Anweisungen \"for\", \"while\", \"do\" oder \"switch\" vorkommen"
|
||||
|
||||
msgid "A variable can not be declared twice"
|
||||
msgstr "Eine Variable wird zum zweiten Mal deklariert"
|
||||
msgstr "Eine Variable darf nicht zwei Mal deklariert werden"
|
||||
|
||||
msgid "Abort\\Abort the current mission"
|
||||
msgstr "Abbrechen\\Mission abbrechen"
|
||||
|
@ -72,7 +88,7 @@ msgid "Access to solutions\\Show program \"4: Solution\" in the exercises"
|
|||
msgstr "Lösung zugänglich\\Die Lösung ist im Programmslot \"4: Lösung\" zugänglich"
|
||||
|
||||
msgid "Add new program"
|
||||
msgstr ""
|
||||
msgstr "Neues Programm hinzufügen"
|
||||
|
||||
msgid "Alien Queen"
|
||||
msgstr "Insektenkönigin"
|
||||
|
@ -85,6 +101,8 @@ msgstr "Trägt schon etwas"
|
|||
|
||||
msgid "Alternative camera mode\\Move sideways instead of rotating (in free camera)"
|
||||
msgstr ""
|
||||
"Alternativer Kameramodus\\Seitwärts bewegen statt rotieren (bei freier "
|
||||
"Kamera)"
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
@ -99,7 +117,7 @@ msgid "Analyzes only organic matter"
|
|||
msgstr "Analysiert nur Orgastoff"
|
||||
|
||||
msgid "Anisotropy level\\Anisotropy level"
|
||||
msgstr ""
|
||||
msgstr "Anisotropie-Level\\Anisotropie-Level"
|
||||
|
||||
msgid "Ant"
|
||||
msgstr "Ameise"
|
||||
|
@ -111,7 +129,7 @@ msgid "Appearance\\Choose your appearance"
|
|||
msgstr "Aussehen\\Erscheinungsbild des Astronauten einstellen"
|
||||
|
||||
msgid "Apply changes\\Activates the changed settings"
|
||||
msgstr "Änderungen ausführen\\Getätigte Einstellungen ausführen"
|
||||
msgstr "Änderungen anwenden\\Getätigte Einstellungen anwenden"
|
||||
|
||||
msgid "Appropriate constructor missing"
|
||||
msgstr "Es gibt keinen geeigneten Konstruktor"
|
||||
|
@ -127,19 +145,22 @@ msgstr "Automatisches Einrücken\\Beim Bearbeiten der Programme"
|
|||
|
||||
msgid "Autosave interval\\How often your game will autosave"
|
||||
msgstr ""
|
||||
"Auto-Speichern Zeitintervall\\Wie oft das Spiel automatisch abgespeichert "
|
||||
"wird"
|
||||
|
||||
msgid "Autosave slots\\How many autosave slots you'll have"
|
||||
msgstr ""
|
||||
"Auto-Speicherplätze\\Wie viele Plätze zum automatischen Speichern zur "
|
||||
"Verfügung stehen"
|
||||
|
||||
msgid "Autosave\\Enables autosave"
|
||||
msgstr ""
|
||||
msgstr "Auto-Speichern\\Aktiviert die automatische Speicherung"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Vorherg. Seite"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Background sound:\\Volume of audio tracks"
|
||||
msgstr "Geräuschkulisse:\\Lautstärke der Soundtracks der CD"
|
||||
msgstr "Hintergrundgeräusche:\\Lautstärke der Soundtracks"
|
||||
|
||||
msgid "Backward (\\key down;)"
|
||||
msgstr "Rückwärts (\\key down;)"
|
||||
|
@ -157,7 +178,7 @@ msgid "Black box"
|
|||
msgstr "Flugschreiber"
|
||||
|
||||
msgid "Blood\\Display blood when the astronaut is hit"
|
||||
msgstr ""
|
||||
msgstr "Blut\\Blut anzeigen, wenn der Astronaut verletzt wird"
|
||||
|
||||
msgid "Blue"
|
||||
msgstr "Blau"
|
||||
|
@ -294,28 +315,25 @@ msgstr "Kamera (\\key camera;)"
|
|||
msgid "Camera back\\Moves the camera backward"
|
||||
msgstr "Kamera weiter\\Bewegung der Kamera rückwärts"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera border scrolling\\Scrolling when the mouse touches right or left border"
|
||||
msgstr "Kameradrehung mit der Maus\\Die Kamera dreht wenn die Maus den Rand erreicht"
|
||||
msgstr ""
|
||||
"Kamerabewegung am Bildschirmrand\\Die Kamera dreht wenn die Maus den rechten "
|
||||
"oder linken Rand erreicht"
|
||||
|
||||
msgid "Camera closer\\Moves the camera forward"
|
||||
msgstr "Kamera näher\\Bewegung der Kamera vorwärts"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera down\\Turns the camera down"
|
||||
msgstr "Kamera näher\\Bewegung der Kamera vorwärts"
|
||||
msgstr "Kamera ab\\Bewegt die Kamera abwärts"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera left\\Turns the camera left"
|
||||
msgstr "Kamera näher\\Bewegung der Kamera vorwärts"
|
||||
msgstr "Kamera links\\Schwenkt die Kamera nach links"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera right\\Turns the camera right"
|
||||
msgstr "Drehung nach rechts\\Steuer rechts"
|
||||
msgstr "Kamera rechts\\Schwenkt die Kamera nach rechts"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera up\\Turns the camera up"
|
||||
msgstr "Kamera (\\key camera;)"
|
||||
msgstr "Kamera auf\\Bewegt die Kamera aufwärts"
|
||||
|
||||
msgid "Can not produce not researched object"
|
||||
msgstr "Das erforschte Objekt kann nicht produziert werden"
|
||||
|
@ -333,13 +351,13 @@ msgid "Cancel\\Cancel all changes"
|
|||
msgstr "Abbrechen\\Editor schließen"
|
||||
|
||||
msgid "Challenges"
|
||||
msgstr "Challenges"
|
||||
msgstr "Herausforderungen"
|
||||
|
||||
msgid "Challenges in the chapter:"
|
||||
msgstr "Liste der Challenges des Kapitels:"
|
||||
msgstr "Herausforderungen in diesem Kapitel:"
|
||||
|
||||
msgid "Challenges\\Programming challenges"
|
||||
msgstr "Challenges\\Herausforderungen"
|
||||
msgstr "Herausforderungen\\Programmieraufgaben"
|
||||
|
||||
msgid "Change camera\\Switches between onboard camera and following camera"
|
||||
msgstr "Andere Kamera\\Sichtpunkt einstellen"
|
||||
|
@ -351,20 +369,22 @@ msgid "Chapters:"
|
|||
msgstr "Liste der Kapitel:"
|
||||
|
||||
msgid "Cheat console\\Show cheat console"
|
||||
msgstr ""
|
||||
msgstr "Mogel-Konsole\\Zeige die Mogel-Konsole"
|
||||
|
||||
msgid "Checkpoint"
|
||||
msgstr "Checkpoint"
|
||||
msgstr "Kontrollstelle"
|
||||
|
||||
msgid "Class name expected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Climb\\Increases the power of the jet"
|
||||
msgstr "Steigen\\Leistung des Triebwerks steigern"
|
||||
|
||||
msgid "Clone program"
|
||||
msgstr ""
|
||||
msgstr "Programm duplizieren"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Clone selected program"
|
||||
msgstr "Gewähltes Programm bearbeiten"
|
||||
msgstr "Gewähltes Programm duplizieren"
|
||||
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
|
@ -372,11 +392,14 @@ msgstr "Schließen"
|
|||
msgid "Closing bracket missing"
|
||||
msgstr "Es fehlt eine geschlossene Klammer \")\""
|
||||
|
||||
msgid "Code battles"
|
||||
msgid "Code battle"
|
||||
msgstr ""
|
||||
|
||||
msgid "Code battles"
|
||||
msgstr "Programmierschlacht"
|
||||
|
||||
msgid "Code battles\\Program your robot to be the best of them all!"
|
||||
msgstr ""
|
||||
msgstr "Programmierschlacht\\Schreibe das Programm für den besten Roboter!"
|
||||
|
||||
msgid "Colobot rules!"
|
||||
msgstr "Colobot ist wunderbar!"
|
||||
|
@ -385,7 +408,7 @@ msgid "Colobot: Gold Edition"
|
|||
msgstr "Colobot: Gold Edition"
|
||||
|
||||
msgid "Command line"
|
||||
msgstr "Befehleingabe"
|
||||
msgstr "Befehlseingabe"
|
||||
|
||||
msgid "Compilation ok (0 errors)"
|
||||
msgstr "Kompilieren OK (0 Fehler)"
|
||||
|
@ -403,7 +426,7 @@ msgid "Controls\\Keyboard, joystick and mouse settings"
|
|||
msgstr "Steuerung\\Auswahl der Tasten"
|
||||
|
||||
msgid "Converts ore to titanium"
|
||||
msgstr "Konverter Erz-Titan"
|
||||
msgstr "Konvertiert Erz in Titan"
|
||||
|
||||
msgid "Copy"
|
||||
msgstr "Kopieren"
|
||||
|
@ -414,12 +437,11 @@ msgstr "Kopieren (Ctrl+C)"
|
|||
msgid "Current mission saved"
|
||||
msgstr "Mission gespeichert"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Custom levels:"
|
||||
msgstr "Userlevels:"
|
||||
msgstr "Benutzerdefinierte Level:"
|
||||
|
||||
msgid "Custom levels\\Levels from mods created by the users"
|
||||
msgstr ""
|
||||
msgstr "Benutzerdefinierte Level\\Level die von anderen Spieler erstellt wurden"
|
||||
|
||||
msgid "Customize your appearance"
|
||||
msgstr "Aussehen einstellen"
|
||||
|
@ -430,9 +452,8 @@ msgstr "Ausschneiden (Ctrl+X)"
|
|||
msgid "Defense tower"
|
||||
msgstr "Geschützturm"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Delete mark"
|
||||
msgstr "Zerstören"
|
||||
msgstr "Markierung entfernen"
|
||||
|
||||
msgid "Delete player\\Deletes the player from the list"
|
||||
msgstr "Spieler löschen\\Löscht den Spieler aus der Liste"
|
||||
|
@ -459,7 +480,7 @@ msgid "Device\\Driver and resolution settings"
|
|||
msgstr "Bildschirm\\Driver und Bildschirmauflösung"
|
||||
|
||||
msgid "Dividing by zero"
|
||||
msgstr "Teilung durch Null"
|
||||
msgstr "Division durch Null"
|
||||
|
||||
msgid "Do you really want to destroy the selected building?"
|
||||
msgstr "Wollen Sie das angewählte Gebäude wirklich zerstören ?"
|
||||
|
@ -484,10 +505,10 @@ msgid "Dynamic lighting\\Mobile light sources"
|
|||
msgstr "Dynamische Beleuchtung\\Dynamische Beleuchtung"
|
||||
|
||||
msgid "Dynamic shadows ++\\Dynamic shadows + self shadowing"
|
||||
msgstr ""
|
||||
msgstr "Dynamische Schatten ++\\Dynamische Schatten + Eigenschatten"
|
||||
|
||||
msgid "Dynamic shadows\\Beautiful shadows!"
|
||||
msgstr ""
|
||||
msgstr "Dynamische Schatten\\Hübsche Schatten!"
|
||||
|
||||
msgid "Edit the selected program"
|
||||
msgstr "Gewähltes Programm bearbeiten"
|
||||
|
@ -529,7 +550,7 @@ msgid "Explosive"
|
|||
msgstr "Sprengstoff"
|
||||
|
||||
msgid "Expression expected after ="
|
||||
msgstr ""
|
||||
msgstr "Nach = wird ein Ausdruck erwartet"
|
||||
|
||||
msgid "Extend shield (\\key action;)"
|
||||
msgstr "Schutzschild ausfahren (\\key action;)"
|
||||
|
@ -556,7 +577,7 @@ msgid "Fixed mine"
|
|||
msgstr "Landmine"
|
||||
|
||||
msgid "Flat ground not large enough"
|
||||
msgstr "Ebener Boden nicht groß genug"
|
||||
msgstr "Ebene Fläche nicht groß genug"
|
||||
|
||||
msgid "Fog\\Fog"
|
||||
msgstr "Nebel\\Nebelschwaden"
|
||||
|
@ -569,7 +590,7 @@ msgid "Folder: %s"
|
|||
msgstr "Ordner: %s"
|
||||
|
||||
msgid "Font size"
|
||||
msgstr "Zeichengröße"
|
||||
msgstr "Schriftgröße"
|
||||
|
||||
msgid "Forward"
|
||||
msgstr "Nächste Seite"
|
||||
|
@ -599,13 +620,13 @@ msgid "Found key D (site for derrick)"
|
|||
msgstr "Markierung für vergrabenen Schlüssel D"
|
||||
|
||||
msgid "Free game"
|
||||
msgstr "Freestyle"
|
||||
msgstr "Freies Spiel"
|
||||
|
||||
msgid "Free game on this planet:"
|
||||
msgstr "Liste der freien Levels des Planeten:"
|
||||
|
||||
msgid "Free game\\Free game without a specific goal"
|
||||
msgstr "Freestyle\\Freies Spielen ohne vorgegebenes Ziel"
|
||||
msgstr "Freies Spiel\\Freies Spielen ohne vorgegebenes Ziel"
|
||||
|
||||
msgid "Full screen\\Full screen or window mode"
|
||||
msgstr "Vollbildschirm\\Vollbildschirm oder Fenster"
|
||||
|
@ -616,6 +637,9 @@ msgstr "Diese Funktion gibt es schon"
|
|||
msgid "Function name missing"
|
||||
msgstr "Hier muss der Name der Funktion stehen"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Spielgeschwindigkeit"
|
||||
|
||||
|
@ -626,10 +650,10 @@ msgid "Gantry crane"
|
|||
msgstr "Träger"
|
||||
|
||||
msgid "Generating"
|
||||
msgstr ""
|
||||
msgstr "Generieren"
|
||||
|
||||
msgid "Gold Edition development by:"
|
||||
msgstr "Goldausgabe Entwicklung von:"
|
||||
msgstr "Gold-Edition entwickelt von:"
|
||||
|
||||
msgid "Goto: destination occupied"
|
||||
msgstr "Ziel ist schon besetzt"
|
||||
|
@ -641,7 +665,7 @@ msgid "Grab or drop (\\key action;)"
|
|||
msgstr "Nehmen oder hinlegen (\\key action;)"
|
||||
|
||||
msgid "Graphics\\Graphics settings"
|
||||
msgstr "Grafik\\Grafische Einstellungen"
|
||||
msgstr "Grafik\\Grafik-Einstellungen"
|
||||
|
||||
msgid "Green"
|
||||
msgstr "Grün"
|
||||
|
@ -662,7 +686,7 @@ msgid "Help about selected object"
|
|||
msgstr "Anweisungen über das ausgewählte Objekt"
|
||||
|
||||
msgid "Help balloons\\Explain the function of the buttons"
|
||||
msgstr "Hilfsblasen\\Hilfsblasen"
|
||||
msgstr "Hilfeblasen\\Hilfeblasen"
|
||||
|
||||
msgid "Highest\\Highest graphic quality (lowest frame rate)"
|
||||
msgstr "Max.\\Beste Qualität (niedriges Framerate)"
|
||||
|
@ -697,9 +721,8 @@ msgstr "Roboter ungeeignet"
|
|||
msgid "Inappropriate cell type"
|
||||
msgstr "Falscher Batterietyp"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Inappropriate object"
|
||||
msgstr "Roboter ungeeignet"
|
||||
msgstr "Objekt ungeeignet"
|
||||
|
||||
msgid "Incorrect index type"
|
||||
msgstr "Falscher Typ für einen Index"
|
||||
|
@ -738,10 +761,10 @@ msgid "Instructions\\Shows the instructions for the current mission"
|
|||
msgstr "Anweisungen\\Anweisungen für die Mission oder Übung"
|
||||
|
||||
msgid "Internal error - tell the developers"
|
||||
msgstr "Interner Fehler - Benachrichtige die Entwickler"
|
||||
msgstr "Interner Fehler - Benachrichtige bitte die Entwickler"
|
||||
|
||||
msgid "Invert\\Invert values on this axis"
|
||||
msgstr ""
|
||||
msgstr "Invertieren\\Die Werte dieser Achse invertieren"
|
||||
|
||||
msgid "Jet temperature"
|
||||
msgstr "Triebwerktemperatur"
|
||||
|
@ -801,39 +824,37 @@ msgid "Load\\Loads the selected mission"
|
|||
msgstr "Laden\\Öffnet eine gespeicherte Mission"
|
||||
|
||||
msgid "Loading basic level settings"
|
||||
msgstr ""
|
||||
msgstr "Lade Level-Grundeinstellungen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Loading finished!"
|
||||
msgstr "Programm beendet"
|
||||
msgstr "Laden beendet!"
|
||||
|
||||
msgid "Loading music"
|
||||
msgstr ""
|
||||
msgstr "Lade Musik"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Loading objects"
|
||||
msgstr "Liste der Objekte"
|
||||
msgstr "Lade Objekte"
|
||||
|
||||
msgid "Loading terrain"
|
||||
msgstr ""
|
||||
msgstr "Lade Gelände"
|
||||
|
||||
msgid "Lowest\\Minimum graphic quality (highest frame rate)"
|
||||
msgstr "Min.\\Minimale Qualität (großes Framerate)"
|
||||
|
||||
msgid "Lunar Roving Vehicle"
|
||||
msgstr "Lunar Roving Vehicle"
|
||||
msgstr "Mondlandefahrzeug"
|
||||
|
||||
msgid "MSAA\\Multisample anti-aliasing"
|
||||
msgstr ""
|
||||
msgstr "MSAA\\Multisample anti-aliasing"
|
||||
|
||||
msgid "Maximize"
|
||||
msgstr "Großes Fenster"
|
||||
|
||||
msgid "Minimize"
|
||||
msgstr "Reduzieren"
|
||||
msgstr "Verkleinern"
|
||||
|
||||
msgid "Mipmap level\\Mipmap level"
|
||||
msgstr ""
|
||||
msgstr "Mipmap-Level\\Mipmap-Level"
|
||||
|
||||
msgid "Mission name"
|
||||
msgstr "Name der Mission"
|
||||
|
@ -853,13 +874,11 @@ msgstr "Umkehr X\\Umkehr der Kameradrehung X-Achse"
|
|||
msgid "Mouse inversion Y\\Inversion of the scrolling direction on the Y axis"
|
||||
msgstr "Umkehr Y\\Umkehr der Kameradrehung Y-Achse"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Move selected program down"
|
||||
msgstr "Gewähltes Programm bearbeiten"
|
||||
msgstr "Gewähltes Programm nach unten"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Move selected program up"
|
||||
msgstr "Gewähltes Programm bearbeiten"
|
||||
msgstr "Gewähltes Programm nach oben"
|
||||
|
||||
msgid "Mute\\No sound"
|
||||
msgstr "Kein Ton\\Keine Geräusche und Geräuschkulisse"
|
||||
|
@ -889,7 +908,7 @@ msgid "Next object\\Selects the next object"
|
|||
msgstr "Nächstes auswählen\\Nächstes Objekt auswählen"
|
||||
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
msgstr "Nein"
|
||||
|
||||
msgid "No energy in the subsoil"
|
||||
msgstr "Kein unterirdisches Energievorkommen"
|
||||
|
@ -901,10 +920,10 @@ msgid "No function running"
|
|||
msgstr "Keine Funktion wird ausgeführt"
|
||||
|
||||
msgid "No function with this name accepts this kind of parameter"
|
||||
msgstr "Keine Funktion mit diesem Namen verträgt Parameter diesen Typs"
|
||||
msgstr "Keine Funktion mit diesem Namen akzeptiert Parameter diesen Typs"
|
||||
|
||||
msgid "No function with this name accepts this number of parameters"
|
||||
msgstr "Keine Funktion mit diesem Namen verträgt diese Anzahl Parameter"
|
||||
msgstr "Keine Funktion mit diesem Namen akzeptiert diese Anzahl Parameter"
|
||||
|
||||
msgid "No information exchange post within range"
|
||||
msgstr "Kein Infoserver in Reichweite"
|
||||
|
@ -934,6 +953,9 @@ msgid "No uranium to transform"
|
|||
msgstr "Kein konvertierbares Platin"
|
||||
|
||||
msgid "No userlevels installed!"
|
||||
msgstr "Keine benutzerdefinierten Level vorhanden"
|
||||
|
||||
msgid "Non-void function needs \"return;\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Normal size"
|
||||
|
@ -1012,7 +1034,7 @@ msgid "Opening bracket missing"
|
|||
msgstr "Es fehlt eine offene Klammer \"(\""
|
||||
|
||||
msgid "Operation impossible with value \"nan\""
|
||||
msgstr "Operation mit dem Wert \"nan\""
|
||||
msgstr "Operation mit dem Wert \"nan\" nicht möglich"
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Einstellungen"
|
||||
|
@ -1039,16 +1061,18 @@ msgid "Paste (Ctrl+V)"
|
|||
msgstr "Einfügen (Ctrl+V)"
|
||||
|
||||
msgid "Pause blur\\Blur the background on the pause screen"
|
||||
msgstr ""
|
||||
msgstr "Pausen-Unschärfe\\Während der Pause den Hintergrund unscharf zeichnen"
|
||||
|
||||
msgid "Pause in background\\Pause the game when the window is unfocused"
|
||||
msgstr ""
|
||||
"Pausieren im Hintergrund\\Spiel anhalten,enn das Spielfenster im Hintergrund "
|
||||
"ist"
|
||||
|
||||
msgid "Pause/continue"
|
||||
msgstr "Pause/Weitermachen"
|
||||
|
||||
msgid "Pause\\Pause the game without opening menu"
|
||||
msgstr ""
|
||||
msgstr "Pause\\Spiel pausieren, ohne das Menü zu öffnen"
|
||||
|
||||
msgid "Phazer shooter"
|
||||
msgstr "Phazershooter"
|
||||
|
@ -1093,10 +1117,10 @@ msgid "Player"
|
|||
msgstr "Spieler"
|
||||
|
||||
msgid "Player name"
|
||||
msgstr "Name "
|
||||
msgstr "Spielername "
|
||||
|
||||
msgid "Player's name"
|
||||
msgstr "Name "
|
||||
msgstr "Name des Spielers"
|
||||
|
||||
msgid "Power cell"
|
||||
msgstr "Elektrolytische Batterie"
|
||||
|
@ -1117,7 +1141,7 @@ msgid "Press \\key help; to read instructions on your SatCom"
|
|||
msgstr "Beziehen Sie sich auf Ihren SatCom, indem Sie auf \\key help; drücken"
|
||||
|
||||
msgid "Previous"
|
||||
msgstr "Vorherg"
|
||||
msgstr "Vorherg."
|
||||
|
||||
msgid "Previous object\\Selects the previous object"
|
||||
msgstr "Vorherg. Auswahl\\Das vorhergehende Objekt auswählen"
|
||||
|
@ -1132,11 +1156,10 @@ msgid "Private\\Private folder"
|
|||
msgstr "Privat\\Privater Ordner"
|
||||
|
||||
msgid "Processing level file"
|
||||
msgstr ""
|
||||
msgstr "Verarbeite Level-Datei"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Program cloned"
|
||||
msgstr "Programm beendet"
|
||||
msgstr "Programm dupliziert"
|
||||
|
||||
msgid "Program editor"
|
||||
msgstr "Programmeditor"
|
||||
|
@ -1172,7 +1195,7 @@ msgid "Quake at explosions\\The screen shakes at explosions"
|
|||
msgstr "Beben bei Explosionen\\Die Kamera bebt bei Explosionen"
|
||||
|
||||
msgid "Quit\\Quit Colobot: Gold Edition"
|
||||
msgstr ""
|
||||
msgstr "Beenden\\Colobot: Gold Edition schließen"
|
||||
|
||||
msgid "Quit\\Quit the current mission or exercise"
|
||||
msgstr "Mission verlassen\\Eine Mission oder Übung verlassen"
|
||||
|
@ -1207,11 +1230,9 @@ msgstr "Überreste einer Apollo-Mission"
|
|||
msgid "Remove a flag"
|
||||
msgstr "Sammelt die Fahne ein"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Remove selected program"
|
||||
msgstr "Gewähltes Programm bearbeiten"
|
||||
msgstr "Gewähltes Programm entfernen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Render distance\\Maximum visibility"
|
||||
msgstr "Sichtweite\\Maximale Sichtweite"
|
||||
|
||||
|
@ -1227,9 +1248,8 @@ msgstr "Forschungsprogramm schon ausgeführt"
|
|||
msgid "Research program completed"
|
||||
msgstr "Forschungsprogramm abgeschlossen"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Reserved keyword of CBOT language"
|
||||
msgstr "Dieses Wort ist reserviert"
|
||||
msgstr "Reserviertes Schlüsselwort in der CBOT Sprache"
|
||||
|
||||
msgid "Resolution"
|
||||
msgstr "Auflösung"
|
||||
|
@ -1238,15 +1258,18 @@ msgid "Resolution:"
|
|||
msgstr "Auflösung:"
|
||||
|
||||
msgid "Resources"
|
||||
msgstr ""
|
||||
msgstr "Ressourcen"
|
||||
|
||||
msgid "Restart\\Restart the mission from the beginning"
|
||||
msgstr "Neu anfangen\\Die Mission von vorne anfangen"
|
||||
|
||||
msgid "Restoring CBot execution state"
|
||||
msgstr ""
|
||||
msgstr "CBOT Ausführungsstatus wiederherstellen"
|
||||
|
||||
msgid "Restoring saved objects"
|
||||
msgstr "Gespeicherte Objekte wiederherstellen"
|
||||
|
||||
msgid "Results"
|
||||
msgstr ""
|
||||
|
||||
msgid "Return to start"
|
||||
|
@ -1316,10 +1339,10 @@ msgid "Semicolon terminator missing"
|
|||
msgstr "Es fehlt ein Strichpunkt \";\" am Ende der Anweisung"
|
||||
|
||||
msgid "Shadow resolution\\Higher means better range and quality, but slower"
|
||||
msgstr ""
|
||||
msgstr "Schatten-Auflösung\\Höher heißt bessere Qualität, aber langsamer"
|
||||
|
||||
msgid "Shield level"
|
||||
msgstr "Schäden"
|
||||
msgstr "Schildstärke"
|
||||
|
||||
msgid "Shield radius"
|
||||
msgstr "Reichweite Schutzschild"
|
||||
|
@ -1345,9 +1368,8 @@ msgstr "Zeigt die Lösung"
|
|||
msgid "Sign \" : \" missing"
|
||||
msgstr "Es fehlt ein Doppelpunkt \" : \""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Simple shadows\\Shadows spots on the ground"
|
||||
msgstr "Schatten\\Schlagschatten auf dem Boden"
|
||||
msgstr "Einfacher Schatten\\Schlagschatten auf dem Boden"
|
||||
|
||||
msgid "Size 1"
|
||||
msgstr "Größe 1"
|
||||
|
@ -1380,11 +1402,10 @@ msgid "Spaceship"
|
|||
msgstr "Raumschiff"
|
||||
|
||||
msgid "Spaceship ruin"
|
||||
msgstr "Raumschiffruine"
|
||||
msgstr "Raumschiffswrack"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Speed 0.5x\\Half speed"
|
||||
msgstr "Geschwindigkeit 1.0x\\Normale Spielgeschwindigkeit"
|
||||
msgstr "Geschwindigkeit 0.5x\\Halbe Spielgeschwindigkeit"
|
||||
|
||||
msgid "Speed 1.0x\\Normal speed"
|
||||
msgstr "Geschwindigkeit 1.0x\\Normale Spielgeschwindigkeit"
|
||||
|
@ -1395,17 +1416,14 @@ msgstr "Geschwindigkeit 1.5x\\Spielgeschwindigkeit anderthalb Mal schneller"
|
|||
msgid "Speed 2.0x\\Double speed"
|
||||
msgstr "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Speed 3.0x\\Triple speed"
|
||||
msgstr "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell"
|
||||
msgstr "Geschwindigkeit 3.0x\\Dreifache Spielgeschwindigkeit"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Speed 4.0x\\Quadruple speed"
|
||||
msgstr "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell"
|
||||
msgstr "Geschwindigkeit 4.0x\\Vierfache Spielgeschwindigkeit"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Speed 6.0x\\Sextuple speed"
|
||||
msgstr "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell"
|
||||
msgstr "Geschwindigkeit 6.0x\\Sechsfache Spielgeschwindigkeit"
|
||||
|
||||
msgid "Spider"
|
||||
msgstr "Spinne"
|
||||
|
@ -1428,12 +1446,11 @@ msgstr "Standard\\Standardfarben einsetzen"
|
|||
msgid "Start"
|
||||
msgstr "Startfläche"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Starting..."
|
||||
msgstr "Startfläche"
|
||||
msgstr "Starte..."
|
||||
|
||||
msgid "Still working ..."
|
||||
msgstr "Prozess im Gang ..."
|
||||
msgstr "Verarbeitung ..."
|
||||
|
||||
msgid "String missing"
|
||||
msgstr "Hier wird eine Zeichenkette erwartet"
|
||||
|
@ -1469,12 +1486,15 @@ msgid "Target bot"
|
|||
msgstr "Mobile Zielscheibe"
|
||||
|
||||
msgid "Terrain relief"
|
||||
msgstr ""
|
||||
msgstr "Geländestruktur"
|
||||
|
||||
msgid "Texture filtering\\Texture filtering"
|
||||
msgstr ""
|
||||
msgstr "Texturfilterung\\Texturfilterung"
|
||||
|
||||
msgid "Textures"
|
||||
msgstr "Texturen"
|
||||
|
||||
msgid "The battle has ended"
|
||||
msgstr ""
|
||||
|
||||
msgid "The expression must return a boolean value"
|
||||
|
@ -1496,7 +1516,7 @@ msgid "This class does not exist"
|
|||
msgstr "Diese Klasse existiert nicht"
|
||||
|
||||
msgid "This is example code that cannot be run directly"
|
||||
msgstr ""
|
||||
msgstr "Das ist ein Beispiel Programm, das nicht direkt ausgeführt werden kann"
|
||||
|
||||
msgid "This is not a member of this class"
|
||||
msgstr "Dieses Element gibt es nicht in dieser Klasse"
|
||||
|
@ -1506,13 +1526,21 @@ msgstr "Dieses Label existiert nicht"
|
|||
|
||||
msgid "This menu is for userlevels from mods, but you didn't install any"
|
||||
msgstr ""
|
||||
"Dieses Menü ist für nachinstallierte Benutzer-Level, aber Du hast keine "
|
||||
"installiert"
|
||||
|
||||
msgid "This object is currently busy"
|
||||
msgstr ""
|
||||
|
||||
msgid "This object is not a member of a class"
|
||||
msgstr "Das Objekt ist nicht eine Instanz einer Klasse"
|
||||
|
||||
msgid "This program is read-only, clone it to edit"
|
||||
msgid "This parameter needs a default value"
|
||||
msgstr ""
|
||||
|
||||
msgid "This program is read-only, clone it to edit"
|
||||
msgstr "Dieses Programm ist schreibgeschützt. Dupliziere es zum Bearbeiten"
|
||||
|
||||
msgid "Thump (\\key action;)"
|
||||
msgstr "Stampfen (\\key action;)"
|
||||
|
||||
|
@ -1589,10 +1617,10 @@ msgid "Type declaration missing"
|
|||
msgstr "Hier muss ein Variablentyp stehen"
|
||||
|
||||
msgid "Unable to control enemy objects"
|
||||
msgstr ""
|
||||
msgstr "Feindliches Objekt kann nicht gesteuert werden"
|
||||
|
||||
msgid "Undo (Ctrl+Z)"
|
||||
msgstr "Widerrufen (Ctrl+Z)"
|
||||
msgstr "Rückgängig (Ctrl+Z)"
|
||||
|
||||
msgid "Unit"
|
||||
msgstr "Einheit"
|
||||
|
@ -1691,7 +1719,7 @@ msgid "Yellow flag"
|
|||
msgstr "Gelbe Fahne"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "Ja"
|
||||
|
||||
msgid "You can fly with the keys (\\key gup;) and (\\key gdown;)"
|
||||
msgstr "Sie können jetzt mit den Tasten \\key gup; und \\key gdown; fliegen"
|
||||
|
@ -1702,27 +1730,35 @@ msgstr "Sie können keinen radioaktiven Gegenstand tragen"
|
|||
msgid "You can not carry an object under water"
|
||||
msgstr "Sie können unter Wasser nichts tragen"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "You cannot use \"%s\" in this exercise (used: %d)"
|
||||
msgstr "In dieser Übung verboten"
|
||||
msgstr "\"%s\" kann in dieser Übung nicht verwendet werden (benutzt: %d)"
|
||||
|
||||
msgid "You found a usable object"
|
||||
msgstr "Sie haben ein brauchbares Objekt gefunden"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "You have to use \"%1$s\" at least once in this exercise (used: %2$d)"
|
||||
msgid_plural "You have to use \"%1$s\" at least %3$d times in this exercise (used: %2$d)"
|
||||
msgstr[0] "In dieser Übung verboten"
|
||||
msgstr[1] "In dieser Übung verboten"
|
||||
msgstr[0] ""
|
||||
"In dieser Übung \"%1$s\" muß mindestens einmal verwendet werden (benutzt: %"
|
||||
"2$d)"
|
||||
msgstr[1] ""
|
||||
"In dieser Übung muß \"%1$s\" mindestes %3$d Mal verwendet werden (benutzt: %"
|
||||
"2$d)"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "You have to use \"%1$s\" at most once in this exercise (used: %2$d)"
|
||||
msgid_plural "You have to use \"%1$s\" at most %3$d times in this exercise (used: %2$d)"
|
||||
msgstr[0] "In dieser Übung verboten"
|
||||
msgstr[1] "In dieser Übung verboten"
|
||||
msgstr[0] ""
|
||||
"In dieser Übung darf \"%1$s\" höchstens einmal verwendet werden (benutzt: %"
|
||||
"2$d)"
|
||||
msgstr[1] ""
|
||||
"In dieser Übung darf \"%1$s\" höchstens %3$d Mal verwendet werden (benutzt: %"
|
||||
"2$d)"
|
||||
|
||||
msgid "You must get on the spaceship to take off"
|
||||
msgstr "Gehen Sie an Bord, bevor Sie abheben"
|
||||
msgstr "Begib Dich an Bord, bevor Du abhebst"
|
||||
|
||||
msgid "Zoom mini-map"
|
||||
msgstr "Zoom Minikarte"
|
||||
|
@ -1773,7 +1809,7 @@ msgid "\\Red flags"
|
|||
msgstr "\\Rote Fahne"
|
||||
|
||||
msgid "\\Return to Colobot: Gold Edition"
|
||||
msgstr ""
|
||||
msgstr "\\Zurück zu Colobot: Gold-Edition"
|
||||
|
||||
msgid "\\SatCom on standby"
|
||||
msgstr "\\SatCom in Standby"
|
||||
|
|
93
po/fr.po
93
po/fr.po
|
@ -1,11 +1,12 @@
|
|||
# Didier Raboud <odyx@debian.org>, 2012, 2015, 2016.
|
||||
# Martin Quinson <mquinson@debian.org>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Colobot 0.1.6\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: DATE\n"
|
||||
"PO-Revision-Date: 2016-03-25 15:01+0100\n"
|
||||
"Last-Translator: Didier Raboud <odyx@debian.org>\n"
|
||||
"PO-Revision-Date: 2016-12-02 15:31+0100\n"
|
||||
"Last-Translator: Martin Quinson <mquinson@debian.org>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
|
@ -24,6 +25,10 @@ msgstr "\" [ \" attendu"
|
|||
msgid "\" ] \" missing"
|
||||
msgstr "\" ] \" attendu"
|
||||
|
||||
#, c-format
|
||||
msgid "%s: %d pts"
|
||||
msgstr ""
|
||||
|
||||
msgid "..behind"
|
||||
msgstr "..derrière"
|
||||
|
||||
|
@ -45,6 +50,18 @@ msgstr "<< Retour \\Retour au niveau précédent"
|
|||
msgid "<<< Sorry; mission failed >>>"
|
||||
msgstr "<<< Désolé; mission échouée >>>"
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s finished! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s lost! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s recieved %d points >>>"
|
||||
msgstr ""
|
||||
|
||||
msgid "<<< Well done; mission accomplished >>>"
|
||||
msgstr "<<< Bravo; mission terminée >>>"
|
||||
|
||||
|
@ -79,10 +96,10 @@ msgid "Already carrying something"
|
|||
msgstr "Porte déjà quelque chose"
|
||||
|
||||
msgid "Alternative camera mode\\Move sideways instead of rotating (in free camera)"
|
||||
msgstr ""
|
||||
msgstr "Mode caméra alternatif\\Déplacements latéraux au lieu des rotations (pour la caméra libre)"
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
msgstr "Appel ambigu à une fonction surchargée"
|
||||
|
||||
msgid "Analysis already performed"
|
||||
msgstr "Analyse déjà effectuée"
|
||||
|
@ -294,21 +311,17 @@ msgstr "Défilement dans les bords\\Défilement lorsque la souris touche les bor
|
|||
msgid "Camera closer\\Moves the camera forward"
|
||||
msgstr "Caméra plus proche\\Avance la caméra"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera down\\Turns the camera down"
|
||||
msgstr "Caméra plus proche\\Avance la caméra"
|
||||
msgstr "Baisser caméra\\Baisse la caméra"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera left\\Turns the camera left"
|
||||
msgstr "Caméra plus proche\\Avance la caméra"
|
||||
msgstr "Caméra à gauche\\Tourne la caméra vers la gauche"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera right\\Turns the camera right"
|
||||
msgstr "Tourner à droite\\Moteur à droite"
|
||||
msgstr "Caméra à droite\\Tourne la caméra vers la droite"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Camera up\\Turns the camera up"
|
||||
msgstr "Caméra (\\key camera;)"
|
||||
msgstr "Lever caméra\\Monte la caméra"
|
||||
|
||||
msgid "Can not produce not researched object"
|
||||
msgstr "Impossible de créer un objet n'ayant pas été recherché"
|
||||
|
@ -349,6 +362,9 @@ msgstr "Console de triche\\Montre la console de triche"
|
|||
msgid "Checkpoint"
|
||||
msgstr "Indicateur"
|
||||
|
||||
msgid "Class name expected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Climb\\Increases the power of the jet"
|
||||
msgstr "Monter\\Augmenter la puissance du réacteur"
|
||||
|
||||
|
@ -364,6 +380,10 @@ msgstr "Fermer"
|
|||
msgid "Closing bracket missing"
|
||||
msgstr "Il manque une parenthèse fermante"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Code battle"
|
||||
msgstr "Batailles de code"
|
||||
|
||||
msgid "Code battles"
|
||||
msgstr "Batailles de code"
|
||||
|
||||
|
@ -519,7 +539,7 @@ msgid "Explosive"
|
|||
msgstr "Explosif"
|
||||
|
||||
msgid "Expression expected after ="
|
||||
msgstr ""
|
||||
msgstr "Expression attendue après ="
|
||||
|
||||
msgid "Extend shield (\\key action;)"
|
||||
msgstr "Déploie le bouclier (\\key action;)"
|
||||
|
@ -606,6 +626,9 @@ msgstr "Cette fonction existe déjà"
|
|||
msgid "Function name missing"
|
||||
msgstr "Nom de la fonction attendu"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Vitesse du jeu"
|
||||
|
||||
|
@ -730,7 +753,7 @@ msgid "Internal error - tell the developers"
|
|||
msgstr "Erreur interne - contacter les développeurs"
|
||||
|
||||
msgid "Invert\\Invert values on this axis"
|
||||
msgstr ""
|
||||
msgstr "Inversion\\Inverse les valeurs sur cet axe"
|
||||
|
||||
msgid "Jet temperature"
|
||||
msgstr "Température du réacteur"
|
||||
|
@ -921,6 +944,9 @@ msgstr "Pas d'uranium à transformer"
|
|||
msgid "No userlevels installed!"
|
||||
msgstr "Pas de niveaux spéciaux installés !"
|
||||
|
||||
msgid "Non-void function needs \"return;\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Normal size"
|
||||
msgstr "Taille normale"
|
||||
|
||||
|
@ -1024,10 +1050,10 @@ msgid "Paste (Ctrl+V)"
|
|||
msgstr "Coller (Ctrl+V)"
|
||||
|
||||
msgid "Pause blur\\Blur the background on the pause screen"
|
||||
msgstr ""
|
||||
msgstr "Flouter les pauses\\Floute le fond de l'écran de pause"
|
||||
|
||||
msgid "Pause in background\\Pause the game when the window is unfocused"
|
||||
msgstr ""
|
||||
msgstr "Pause en arrière-plan\\Met le jeu en pause quand la fenêtre n'a plus le focus"
|
||||
|
||||
msgid "Pause/continue"
|
||||
msgstr "Pause/continuer"
|
||||
|
@ -1219,15 +1245,18 @@ msgid "Resolution:"
|
|||
msgstr "Résolutions :"
|
||||
|
||||
msgid "Resources"
|
||||
msgstr ""
|
||||
msgstr "Ressources"
|
||||
|
||||
msgid "Restart\\Restart the mission from the beginning"
|
||||
msgstr "Recommencer\\Recommencer la mission au début"
|
||||
|
||||
msgid "Restoring CBot execution state"
|
||||
msgstr ""
|
||||
msgstr "Restaurer l'état d'exécution CBOT"
|
||||
|
||||
msgid "Restoring saved objects"
|
||||
msgstr "Restaurer des objets sauvés"
|
||||
|
||||
msgid "Results"
|
||||
msgstr ""
|
||||
|
||||
msgid "Return to start"
|
||||
|
@ -1452,6 +1481,9 @@ msgstr "Filtrage de textures\\Filtrage de textures"
|
|||
msgid "Textures"
|
||||
msgstr "Textures"
|
||||
|
||||
msgid "The battle has ended"
|
||||
msgstr ""
|
||||
|
||||
msgid "The expression must return a boolean value"
|
||||
msgstr "L'expression doit ętre un boolean"
|
||||
|
||||
|
@ -1482,9 +1514,15 @@ msgstr "Cette étiquette n'existe pas"
|
|||
msgid "This menu is for userlevels from mods, but you didn't install any"
|
||||
msgstr "Ce menu donne accès aux niveaux spéciaux (importés ou personnalisés), mais aucun n'est installé."
|
||||
|
||||
msgid "This object is currently busy"
|
||||
msgstr ""
|
||||
|
||||
msgid "This object is not a member of a class"
|
||||
msgstr "L'objet n'est pas une instance d'une classe"
|
||||
|
||||
msgid "This parameter needs a default value"
|
||||
msgstr ""
|
||||
|
||||
msgid "This program is read-only, clone it to edit"
|
||||
msgstr "Ce programme est en lecture-seule, le dupliquer pour pouvoir l'éditer"
|
||||
|
||||
|
@ -1677,24 +1715,24 @@ msgstr "Vous ne pouvez pas transporter un objet radioactif"
|
|||
msgid "You can not carry an object under water"
|
||||
msgstr "Vous ne pouvez pas transporter un objet sous l'eau"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "You cannot use \"%s\" in this exercise (used: %d)"
|
||||
msgstr "Interdit dans cet exercice"
|
||||
msgstr "Vous ne pouvez pas utiliser «%s» dans cet exercice (utilisé : %d)"
|
||||
|
||||
msgid "You found a usable object"
|
||||
msgstr "Vous avez trouvé un objet utilisable"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "You have to use \"%1$s\" at least once in this exercise (used: %2$d)"
|
||||
msgid_plural "You have to use \"%1$s\" at least %3$d times in this exercise (used: %2$d)"
|
||||
msgstr[0] "Interdit dans cet exercice"
|
||||
msgstr[1] "Interdit dans cet exercice"
|
||||
msgstr[0] "Vous devez utiliser «%1$s» au moins une fois dans cet exercice (utilisé %2$d fois)"
|
||||
msgstr[1] "Vous devez utiliser «%1$s» au moins %3$d fois dans cet exercice (utilisé %2$d fois)"
|
||||
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "You have to use \"%1$s\" at most once in this exercise (used: %2$d)"
|
||||
msgid_plural "You have to use \"%1$s\" at most %3$d times in this exercise (used: %2$d)"
|
||||
msgstr[0] "Interdit dans cet exercice"
|
||||
msgstr[1] "Interdit dans cet exercice"
|
||||
msgstr[0] "Vous devez utiliser «%1$s» au plus une fois dans cet exercice (utilisé %2$d fois)"
|
||||
msgstr[1] "Vous devez utiliser «%1$s» au plus %3$d fois dans cet exercice (utilisé %2$d fois)"
|
||||
|
||||
msgid "You must get on the spaceship to take off"
|
||||
msgstr "Vous devez embarquer pour pouvoir décoller"
|
||||
|
@ -1864,9 +1902,8 @@ msgstr "epsitec.com"
|
|||
#~ msgid "Developed by :"
|
||||
#~ msgstr "Développé par :"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "Do you want to quit Colobot: Gold Edition?"
|
||||
#~ msgstr "Voulez-vous quitter COLOBOT ?"
|
||||
#~ msgstr "Voulez-vous quitter Colobot: Édition Gold ?"
|
||||
|
||||
#~ msgid "Exit film\\Film at the exit of exercises"
|
||||
#~ msgstr "Retour animé\\Retour animé dans les exercices"
|
||||
|
|
40
po/pl.po
40
po/pl.po
|
@ -27,6 +27,10 @@ msgstr "Oczekiwane \" [ \""
|
|||
msgid "\" ] \" missing"
|
||||
msgstr "Brak \" ] \""
|
||||
|
||||
#, c-format
|
||||
msgid "%s: %d pts"
|
||||
msgstr "%s: %d pkt"
|
||||
|
||||
msgid "..behind"
|
||||
msgstr "..za"
|
||||
|
||||
|
@ -48,6 +52,18 @@ msgstr "<< Wstecz \\Wraca do poprzedniego ekranu"
|
|||
msgid "<<< Sorry; mission failed >>>"
|
||||
msgstr "<<< Niestety, misja nie powiodła się >>>"
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s finished! >>>"
|
||||
msgstr "<<< Drużyna %s zakończyła rozgrywkę! >>>"
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s lost! >>>"
|
||||
msgstr "<<< Drużyna %s odpadła! >>>"
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s recieved %d points >>>"
|
||||
msgstr "<<< Drużyna %s zdobyła %d punktów >>>"
|
||||
|
||||
msgid "<<< Well done; mission accomplished >>>"
|
||||
msgstr "<<< Dobra robota, misja wypełniona >>>"
|
||||
|
||||
|
@ -348,6 +364,9 @@ msgstr "Konsola komend\\Pokaż konsolę komend"
|
|||
msgid "Checkpoint"
|
||||
msgstr "Punkt kontrolny"
|
||||
|
||||
msgid "Class name expected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Climb\\Increases the power of the jet"
|
||||
msgstr "W górę\\Zwiększa moc silnika"
|
||||
|
||||
|
@ -363,6 +382,9 @@ msgstr "Zamknij"
|
|||
msgid "Closing bracket missing"
|
||||
msgstr "Brak nawiasu zamykającego"
|
||||
|
||||
msgid "Code battle"
|
||||
msgstr "Programobitwa"
|
||||
|
||||
msgid "Code battles"
|
||||
msgstr "Programobitwy"
|
||||
|
||||
|
@ -605,6 +627,9 @@ msgstr "Funkcja już istnieje"
|
|||
msgid "Function name missing"
|
||||
msgstr "Brakująca nazwa funkcji"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Prędkość gry"
|
||||
|
||||
|
@ -920,6 +945,9 @@ msgstr "Brak uranu do przetworzenia"
|
|||
msgid "No userlevels installed!"
|
||||
msgstr "Brak zainstalowanych poziomów użytkownika!"
|
||||
|
||||
msgid "Non-void function needs \"return;\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Normal size"
|
||||
msgstr "Normalna wielkość"
|
||||
|
||||
|
@ -1229,6 +1257,9 @@ msgstr "Przywracanie stanu CBot"
|
|||
msgid "Restoring saved objects"
|
||||
msgstr "Przywracanie obiektów"
|
||||
|
||||
msgid "Results"
|
||||
msgstr "Wyniki"
|
||||
|
||||
msgid "Return to start"
|
||||
msgstr "Powrót do początku"
|
||||
|
||||
|
@ -1451,6 +1482,9 @@ msgstr "Filtrowanie tekstur\\Filtrowanie tekstur"
|
|||
msgid "Textures"
|
||||
msgstr "Tekstury"
|
||||
|
||||
msgid "The battle has ended"
|
||||
msgstr "Bitwa zakończyła się"
|
||||
|
||||
msgid "The expression must return a boolean value"
|
||||
msgstr "Wyrażenie musi zwrócić wartość logiczną"
|
||||
|
||||
|
@ -1481,9 +1515,15 @@ msgstr "Taka etykieta nie istnieje"
|
|||
msgid "This menu is for userlevels from mods, but you didn't install any"
|
||||
msgstr "To menu jest przeznaczone na poziomy użytkownika z modyfikacji, ale żadne nie są zainstalowane"
|
||||
|
||||
msgid "This object is currently busy"
|
||||
msgstr "Ten objekt jest obecnie zajęty"
|
||||
|
||||
msgid "This object is not a member of a class"
|
||||
msgstr "Ten obiekt nie jest członkiem klasy"
|
||||
|
||||
msgid "This parameter needs a default value"
|
||||
msgstr ""
|
||||
|
||||
msgid "This program is read-only, clone it to edit"
|
||||
msgstr "Ten program jest tylko do odczytu, skopiuj go, aby edytować"
|
||||
|
||||
|
|
55
po/ru.po
55
po/ru.po
|
@ -27,6 +27,10 @@ msgstr "Ожидалось \" [ \""
|
|||
msgid "\" ] \" missing"
|
||||
msgstr "Отсутствует \"]\" "
|
||||
|
||||
#, c-format
|
||||
msgid "%s: %d pts"
|
||||
msgstr ""
|
||||
|
||||
msgid "..behind"
|
||||
msgstr "Сзади"
|
||||
|
||||
|
@ -48,6 +52,18 @@ msgstr "<< Назад \\Вернуться на предыдущую стран
|
|||
msgid "<<< Sorry; mission failed >>>"
|
||||
msgstr "<<< Миссия провалена >>>"
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s finished! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s lost! >>>"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "<<< Team %s recieved %d points >>>"
|
||||
msgstr ""
|
||||
|
||||
msgid "<<< Well done; mission accomplished >>>"
|
||||
msgstr "<<< Отлично, миссия выполнена >>>"
|
||||
|
||||
|
@ -85,7 +101,7 @@ msgid "Alternative camera mode\\Move sideways instead of rotating (in free camer
|
|||
msgstr "Альтернативный режим камеры\\Движение в стороны вместо поворачивания (в режиме свободной камеры)"
|
||||
|
||||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
msgstr "Странный вызов перегруженной функции"
|
||||
|
||||
msgid "Analysis already performed"
|
||||
msgstr "Анализ уже выполнен"
|
||||
|
@ -353,6 +369,9 @@ msgstr "Консоль чит-кодов\\Показать консоль для
|
|||
msgid "Checkpoint"
|
||||
msgstr "Контрольная точка"
|
||||
|
||||
msgid "Class name expected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Climb\\Increases the power of the jet"
|
||||
msgstr "Взлет и подъем\\Увеличивает мощность реактивного двигателя"
|
||||
|
||||
|
@ -369,11 +388,15 @@ msgstr "Закрыть"
|
|||
msgid "Closing bracket missing"
|
||||
msgstr "Закрывающая скобка отсутствует"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Code battle"
|
||||
msgstr "Битвы роботов"
|
||||
|
||||
msgid "Code battles"
|
||||
msgstr ""
|
||||
msgstr "Битвы роботов"
|
||||
|
||||
msgid "Code battles\\Program your robot to be the best of them all!"
|
||||
msgstr "Code battles\\Запрограммируйте собственного робота чтобы быть лучшим среди них!"
|
||||
msgstr "Битвы роботов\\Запрограммируйте собственного робота чтобы быть лучшим среди них!"
|
||||
|
||||
msgid "Colobot rules!"
|
||||
msgstr "Правила игры!"
|
||||
|
@ -612,6 +635,9 @@ msgstr "Функция уже существует"
|
|||
msgid "Function name missing"
|
||||
msgstr "Имя функции отсутствует"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Скорость игры"
|
||||
|
||||
|
@ -817,7 +843,7 @@ msgid "Lunar Roving Vehicle"
|
|||
msgstr "Луноход"
|
||||
|
||||
msgid "MSAA\\Multisample anti-aliasing"
|
||||
msgstr ""
|
||||
msgstr "MSAA\\Улучшенная фильтрация"
|
||||
|
||||
msgid "Maximize"
|
||||
msgstr "Развернуть"
|
||||
|
@ -826,7 +852,7 @@ msgid "Minimize"
|
|||
msgstr "Свернуть"
|
||||
|
||||
msgid "Mipmap level\\Mipmap level"
|
||||
msgstr ""
|
||||
msgstr "Уровень уменьшающей фильтрации\\Уровень уменьшающей фильтрации"
|
||||
|
||||
msgid "Mission name"
|
||||
msgstr "Название миссии"
|
||||
|
@ -929,6 +955,9 @@ msgstr "Нет урана для преобразования"
|
|||
msgid "No userlevels installed!"
|
||||
msgstr "Не установленны пользовательские уровни!"
|
||||
|
||||
msgid "Non-void function needs \"return;\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Normal size"
|
||||
msgstr "Нормальный размер"
|
||||
|
||||
|
@ -1230,17 +1259,20 @@ msgid "Resolution:"
|
|||
msgstr "Разрешение:"
|
||||
|
||||
msgid "Resources"
|
||||
msgstr ""
|
||||
msgstr "Ресурсы"
|
||||
|
||||
msgid "Restart\\Restart the mission from the beginning"
|
||||
msgstr "Заново\\Начать данную миссию с начала"
|
||||
|
||||
msgid "Restoring CBot execution state"
|
||||
msgstr ""
|
||||
msgstr "Восстановление состояния CBot"
|
||||
|
||||
msgid "Restoring saved objects"
|
||||
msgstr "Восстановить сохранённые объекты"
|
||||
|
||||
msgid "Results"
|
||||
msgstr ""
|
||||
|
||||
msgid "Return to start"
|
||||
msgstr "Вернуться в начало"
|
||||
|
||||
|
@ -1465,6 +1497,9 @@ msgstr "Фильтрация текстур\\Фильтрация текстур
|
|||
msgid "Textures"
|
||||
msgstr "Текстуры"
|
||||
|
||||
msgid "The battle has ended"
|
||||
msgstr ""
|
||||
|
||||
msgid "The expression must return a boolean value"
|
||||
msgstr "Выражение должно возвращать логическое значение"
|
||||
|
||||
|
@ -1495,9 +1530,15 @@ msgstr "Эта метка не существует"
|
|||
msgid "This menu is for userlevels from mods, but you didn't install any"
|
||||
msgstr "Это меню для пользовательских уровней из модов, но вы ни одного не уставили"
|
||||
|
||||
msgid "This object is currently busy"
|
||||
msgstr ""
|
||||
|
||||
msgid "This object is not a member of a class"
|
||||
msgstr "Этот объект не член класса"
|
||||
|
||||
msgid "This parameter needs a default value"
|
||||
msgstr ""
|
||||
|
||||
msgid "This program is read-only, clone it to edit"
|
||||
msgstr "Эта программа только для чтения, для редактирования клонируйте её"
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
|||
val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
|
||||
if (val.GetType() < 0)
|
||||
{
|
||||
val = m_prog->GetFunctions()->CompileCall(p->GetString(), ppVars, nIdent);
|
||||
val = CBotFunction::CompileCall(m_prog->GetFunctions(), p->GetString(), ppVars, nIdent);
|
||||
if ( val.GetType() < 0 )
|
||||
{
|
||||
// pVar = nullptr; // the error is not on a particular parameter
|
||||
|
@ -369,8 +369,7 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
|||
|
||||
if ( m_prog->GetExternalCalls()->CheckCall(name) ) return true;
|
||||
|
||||
CBotFunction* pp = m_prog->GetFunctions();
|
||||
while ( pp != nullptr )
|
||||
for (CBotFunction* pp : m_prog->GetFunctions())
|
||||
{
|
||||
if ( pToken->GetString() == pp->GetName() )
|
||||
{
|
||||
|
@ -378,7 +377,6 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
|||
if ( pp->CheckParam( pParam ) )
|
||||
return true;
|
||||
}
|
||||
pp = pp->Next();
|
||||
}
|
||||
|
||||
for (CBotFunction* pp : CBotFunction::m_publicFunctions)
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Colobot: Gold Edition source code
|
||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||
*
|
||||
* 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://gnu.org/licenses
|
||||
*/
|
||||
|
||||
#include "CBot/CBotCallMethode.h"
|
||||
|
||||
#include "CBot/CBotUtils.h"
|
||||
#include "CBot/CBotStack.h"
|
||||
#include "CBot/CBotCStack.h"
|
||||
|
||||
#include "CBot/CBotVar/CBotVar.h"
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotCallMethode::CBotCallMethode(const std::string& name,
|
||||
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
||||
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar))
|
||||
{
|
||||
m_name = name;
|
||||
m_rExec = rExec;
|
||||
m_rComp = rCompile;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotCallMethode::~CBotCallMethode()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotTypResult CBotCallMethode::CompileCall(const std::string& name, CBotVar* pThis, CBotVar** ppVar,
|
||||
CBotCStack* pStack)
|
||||
{
|
||||
CBotCallMethode* pt = this;
|
||||
|
||||
while ( pt != nullptr )
|
||||
{
|
||||
if ( pt->m_name == name )
|
||||
{
|
||||
CBotVar* pVar = MakeListVars(ppVar, true);
|
||||
CBotVar* pVar2 = pVar;
|
||||
CBotTypResult r = pt->m_rComp(pThis, pVar2);
|
||||
int ret = r.GetType();
|
||||
if ( ret > 20 )
|
||||
{
|
||||
if (pVar2) pStack->SetError(static_cast<CBotError>(ret), pVar2->GetToken());
|
||||
}
|
||||
delete pVar;
|
||||
return r;
|
||||
}
|
||||
pt = pt->m_next;
|
||||
}
|
||||
return CBotTypResult(-1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotCallMethode::DoCall(const std::string& name, CBotVar* pThis, CBotVar** ppVars, CBotVar*& pResult,
|
||||
CBotStack* pStack, CBotToken* pToken)
|
||||
{
|
||||
CBotCallMethode* pt = this;
|
||||
|
||||
// search by name
|
||||
|
||||
while ( pt != nullptr )
|
||||
{
|
||||
if ( pt->m_name == name )
|
||||
{
|
||||
// lists the parameters depending on the contents of the stack (pStackVar)
|
||||
|
||||
CBotVar* pVar = MakeListVars(ppVars, true);
|
||||
CBotVar* pVarToDelete = pVar;
|
||||
|
||||
int Exception = 0; // TODO: Change this to CBotError
|
||||
int res = pt->m_rExec(pThis, pVar, pResult, Exception, pStack->GetUserPtr());
|
||||
pStack->SetVar(pResult);
|
||||
|
||||
if (res == false)
|
||||
{
|
||||
if (Exception!=0)
|
||||
{
|
||||
// pStack->SetError(Exception, pVar->GetToken());
|
||||
pStack->SetError(static_cast<CBotError>(Exception), pToken);
|
||||
}
|
||||
delete pVarToDelete;
|
||||
return false;
|
||||
}
|
||||
delete pVarToDelete;
|
||||
return true;
|
||||
}
|
||||
pt = pt->m_next;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace CBot
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Colobot: Gold Edition source code
|
||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||
*
|
||||
* 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://gnu.org/licenses
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CBot/CBotTypResult.h"
|
||||
#include "CBot/CBotUtils.h"
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
||||
class CBotVar;
|
||||
class CBotCStack;
|
||||
class CBotStack;
|
||||
class CBotToken;
|
||||
|
||||
/*!
|
||||
* \brief The CBotCallMethode class Class managing the methods declared by
|
||||
* AddFunction on a class.
|
||||
*/
|
||||
class CBotCallMethode : public CBotLinkedList<CBotCallMethode>
|
||||
{
|
||||
public:
|
||||
|
||||
/*!
|
||||
* \brief CBotCallMethode
|
||||
* \param name
|
||||
* \param rExec
|
||||
* \param rCompile
|
||||
*/
|
||||
CBotCallMethode(const std::string& name,
|
||||
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
||||
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar));
|
||||
|
||||
/*!
|
||||
* \brief ~CBotCallMethode
|
||||
*/
|
||||
~CBotCallMethode();
|
||||
|
||||
/*!
|
||||
* \brief CompileCall Is acceptable by a call procedure name and given
|
||||
* parameters.
|
||||
* \param name
|
||||
* \param pThis
|
||||
* \param ppVars
|
||||
* \param pStack
|
||||
* \return
|
||||
*/
|
||||
CBotTypResult CompileCall(const std::string& name, CBotVar* pThis, CBotVar** ppVars,
|
||||
CBotCStack* pStack);
|
||||
|
||||
/*!
|
||||
* \brief DoCall
|
||||
* \param name
|
||||
* \param pThis
|
||||
* \param ppVars
|
||||
* \param pResult
|
||||
* \param pStack
|
||||
* \param pFunc
|
||||
* \return
|
||||
*/
|
||||
int DoCall(const std::string& name, CBotVar* pThis, CBotVar** ppVars, CBotVar*& pResult,
|
||||
CBotStack* pStack, CBotToken* pFunc);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
bool (*m_rExec) (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user);
|
||||
CBotTypResult (*m_rComp) (CBotVar* pThis, CBotVar* &pVar);
|
||||
friend class CBotClass;
|
||||
};
|
||||
|
||||
} // namespace CBot
|
|
@ -37,7 +37,6 @@
|
|||
#include "CBot/CBotDefParam.h"
|
||||
#include "CBot/CBotUtils.h"
|
||||
#include "CBot/CBotFileUtils.h"
|
||||
#include "CBot/CBotCallMethode.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -55,8 +54,7 @@ CBotClass::CBotClass(const std::string& name,
|
|||
m_parent = parent;
|
||||
m_name = name;
|
||||
m_pVar = nullptr;
|
||||
m_pCalls = nullptr;
|
||||
m_pMethod = nullptr;
|
||||
m_externalMethods = new CBotExternalCallList();
|
||||
m_rUpdate = nullptr;
|
||||
m_IsDef = true;
|
||||
m_bIntrinsic= bIntrinsic;
|
||||
|
@ -71,8 +69,7 @@ CBotClass::~CBotClass()
|
|||
m_publicClasses.erase(this);
|
||||
|
||||
delete m_pVar;
|
||||
delete m_pCalls;
|
||||
delete m_pMethod;
|
||||
delete m_externalMethods;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -86,26 +83,24 @@ CBotClass* CBotClass::Create(const std::string& name,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotClass::ClearPublic()
|
||||
{
|
||||
m_publicClasses.clear();
|
||||
while ( !m_publicClasses.empty() )
|
||||
{
|
||||
auto it = m_publicClasses.begin();
|
||||
delete *it; // calling destructor removes the class from the list
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotClass::Purge()
|
||||
{
|
||||
assert ( this != nullptr );
|
||||
|
||||
delete m_pVar;
|
||||
m_pVar = nullptr;
|
||||
delete m_pCalls;
|
||||
m_pCalls = nullptr;
|
||||
delete m_pMethod;
|
||||
m_pMethod = nullptr;
|
||||
m_externalMethods->Clear();
|
||||
for (CBotFunction* f : m_pMethod) delete f;
|
||||
m_pMethod.clear();
|
||||
m_IsDef = false;
|
||||
|
||||
m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar;
|
||||
|
||||
if (m_next != nullptr) m_next->Purge();
|
||||
m_next = nullptr; // no longer belongs to this chain
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -205,7 +200,6 @@ std::string CBotClass::GetName()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotClass* CBotClass::GetParent()
|
||||
{
|
||||
assert ( this != nullptr );
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
|
@ -255,6 +249,19 @@ CBotVar* CBotClass::GetItemRef(int nIdent)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotClass::CheckVar(const std::string &name)
|
||||
{
|
||||
CBotVar* p = m_pVar;
|
||||
|
||||
while ( p != nullptr )
|
||||
{
|
||||
if ( p->GetName() == name ) return true;
|
||||
p = p->GetNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotClass::IsIntrinsic()
|
||||
{
|
||||
|
@ -283,29 +290,7 @@ bool CBotClass::AddFunction(const std::string& name,
|
|||
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
||||
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar))
|
||||
{
|
||||
// stores pointers to the two functions
|
||||
CBotCallMethode* p = m_pCalls;
|
||||
CBotCallMethode* pp = nullptr;
|
||||
|
||||
while ( p != nullptr )
|
||||
{
|
||||
if ( name == p->m_name )
|
||||
{
|
||||
if ( pp == nullptr ) m_pCalls = p->m_next;
|
||||
else pp->m_next = p->m_next;
|
||||
delete p;
|
||||
break;
|
||||
}
|
||||
pp = p;
|
||||
p = p->m_next;
|
||||
}
|
||||
|
||||
p = new CBotCallMethode(name, rExec, rCompile);
|
||||
|
||||
if (m_pCalls == nullptr) m_pCalls = p;
|
||||
else m_pCalls->AddNext(p); // added to the list
|
||||
|
||||
return true;
|
||||
return m_externalMethods->AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallClass(rExec, rCompile)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -316,22 +301,22 @@ bool CBotClass::SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user))
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotTypResult CBotClass::CompileMethode(const std::string& name,
|
||||
CBotTypResult CBotClass::CompileMethode(CBotToken* name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppParams,
|
||||
CBotCStack* pStack,
|
||||
long& nIdent)
|
||||
long &nIdent)
|
||||
{
|
||||
nIdent = 0; // forget the previous one if necessary
|
||||
|
||||
// find the methods declared by AddFunction
|
||||
|
||||
CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack);
|
||||
CBotTypResult r = m_externalMethods->CompileCall(name, pThis, ppParams, pStack);
|
||||
if ( r.GetType() >= 0) return r;
|
||||
|
||||
// find the methods declared by user
|
||||
|
||||
r = m_pMethod->CompileCall(name, ppParams, nIdent);
|
||||
r = CBotFunction::CompileCall(m_pMethod, name->GetString(), ppParams, nIdent);
|
||||
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
|
||||
return m_parent->CompileMethode(name, pThis, ppParams, pStack, nIdent);
|
||||
return r;
|
||||
|
@ -339,37 +324,39 @@ CBotTypResult CBotClass::CompileMethode(const std::string& name,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotClass::ExecuteMethode(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppParams,
|
||||
CBotVar*& pResult,
|
||||
CBotTypResult pResultType,
|
||||
CBotStack*& pStack,
|
||||
CBotToken* pToken)
|
||||
{
|
||||
int ret = m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
||||
if (ret>=0) return ret;
|
||||
int ret = m_externalMethods->DoCall(pToken, pThis, ppParams, pStack, pResultType);
|
||||
if (ret >= 0) return ret;
|
||||
|
||||
ret = m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, this);
|
||||
ret = CBotFunction::DoCall(m_pMethod, nIdent, pToken->GetString(), pThis, ppParams, pStack, pToken, this);
|
||||
if (ret >= 0) return ret;
|
||||
|
||||
if (m_parent != nullptr)
|
||||
{
|
||||
ret = m_parent->ExecuteMethode(nIdent, name, pThis, ppParams, pResult, pStack, pToken);
|
||||
ret = m_parent->ExecuteMethode(nIdent, pThis, ppParams, pResultType, pStack, pToken);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotClass::RestoreMethode(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotToken* name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppParams,
|
||||
CBotStack*& pStack)
|
||||
{
|
||||
if (m_externalMethods->RestoreCall(name, pThis, ppParams, pStack))
|
||||
return;
|
||||
|
||||
CBotClass* pClass = this;
|
||||
while (pClass != nullptr)
|
||||
{
|
||||
bool ok = pClass->m_pMethod->RestoreCall(nIdent, name, pThis, ppParams, pStack, pClass);
|
||||
bool ok = CBotFunction::RestoreCall(pClass->m_pMethod, nIdent, name->GetString(), pThis, ppParams, pStack, pClass);
|
||||
if (ok) return;
|
||||
pClass = pClass->m_parent;
|
||||
}
|
||||
|
@ -455,8 +442,7 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
|
|||
|
||||
if ( program->GetExternalCalls()->CheckCall(name) ) return true;
|
||||
|
||||
CBotFunction* pp = m_pMethod;
|
||||
while ( pp != nullptr )
|
||||
for (CBotFunction* pp : m_pMethod)
|
||||
{
|
||||
if ( pToken->GetString() == pp->GetName() )
|
||||
{
|
||||
|
@ -464,7 +450,6 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
|
|||
if ( pp->CheckParam( pParam ) )
|
||||
return true;
|
||||
}
|
||||
pp = pp->Next();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -483,30 +468,32 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
|
|||
|
||||
std::string name = p->GetString();
|
||||
|
||||
CBotClass* pOld = CBotClass::Find(name);
|
||||
if ( pOld != nullptr && pOld->m_IsDef )
|
||||
{
|
||||
pStack->SetError( CBotErrRedefClass, p );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// a name of the class is there?
|
||||
if (IsOfType(p, TokenTypVar))
|
||||
{
|
||||
CBotClass* pOld = CBotClass::Find(name);
|
||||
if ((pOld != nullptr && pOld->m_IsDef) || /* public class exists in different program */
|
||||
pStack->GetProgram()->ClassExists(name)) /* class exists in this program */
|
||||
{
|
||||
pStack->SetError(CBotErrRedefClass, p->GetPrev());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CBotClass* pPapa = nullptr;
|
||||
if ( IsOfType( p, ID_EXTENDS ) )
|
||||
{
|
||||
std::string name = p->GetString();
|
||||
pPapa = CBotClass::Find(name);
|
||||
CBotToken* pp = p;
|
||||
|
||||
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr )
|
||||
{
|
||||
pStack->SetError( CBotErrNotClass, p );
|
||||
pStack->SetError(CBotErrNoClassName, pp);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld;
|
||||
classe->Purge(); // empty the old definitions // TODO: Doesn't this remove all classes of the current program?
|
||||
classe->Purge(); // empty the old definitions
|
||||
classe->m_IsDef = false; // current definition
|
||||
|
||||
classe->m_pOpenblk = p;
|
||||
|
@ -518,27 +505,29 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
|
|||
}
|
||||
|
||||
int level = 1;
|
||||
do // skip over the definition
|
||||
while (level > 0 && p != nullptr)
|
||||
{
|
||||
int type = p->GetType();
|
||||
p = p->GetNext();
|
||||
if (type == ID_OPBLK) level++;
|
||||
if (type == ID_CLBLK) level--;
|
||||
}
|
||||
while (level > 0 && p != nullptr);
|
||||
|
||||
if (level > 0) pStack->SetError(CBotErrCloseBlock, classe->m_pOpenblk);
|
||||
|
||||
if (pStack->IsOk()) return classe;
|
||||
}
|
||||
else
|
||||
pStack->SetError(CBotErrNoClassName, p);
|
||||
|
||||
pStack->SetError(CBotErrNoTerminator, p);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotClass::DefineClasses(CBotClass* pClass, CBotCStack* pStack)
|
||||
void CBotClass::DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack)
|
||||
{
|
||||
while (pClass != nullptr)
|
||||
for (CBotClass* pClass : pClassList)
|
||||
{
|
||||
CBotClass* pParent = pClass->m_parent;
|
||||
pClass->m_nbVar = (pParent == nullptr) ? 0 : pParent->m_nbVar;
|
||||
|
@ -550,8 +539,6 @@ void CBotClass::DefineClasses(CBotClass* pClass, CBotCStack* pStack)
|
|||
}
|
||||
|
||||
if (!pStack->IsOk()) return;
|
||||
|
||||
pClass = pClass->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -587,6 +574,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
while (pStack->IsOk())
|
||||
{
|
||||
CBotTypResult type2 = CBotTypResult(type); // reset type after comma
|
||||
CBotToken* varToken = p;
|
||||
|
||||
std::string pp = p->GetString();
|
||||
if ( IsOfType(p, ID_NOT) )
|
||||
{
|
||||
|
@ -595,60 +584,30 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
|
||||
if (IsOfType(p, TokenTypVar))
|
||||
{
|
||||
CBotInstr* limites = nullptr;
|
||||
while ( IsOfType( p, ID_OPBRK ) ) // a table?
|
||||
{
|
||||
CBotInstr* i = nullptr;
|
||||
pStack->SetStartError( p->GetStart() );
|
||||
if ( p->GetType() != ID_CLBRK )
|
||||
{
|
||||
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
||||
if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
|
||||
{
|
||||
pStack->SetError(CBotErrBadIndex, p->GetStart());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
i = new CBotEmpty(); // special if not a formula
|
||||
|
||||
type2 = CBotTypResult(CBotTypArrayPointer, type2);
|
||||
|
||||
if (limites == nullptr) limites = i;
|
||||
else limites->AddNext3(i);
|
||||
|
||||
if (IsOfType(p, ID_CLBRK)) continue;
|
||||
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( p->GetType() == ID_OPENPAR )
|
||||
{
|
||||
if ( !bSecond )
|
||||
{
|
||||
p = pBase;
|
||||
CBotFunction* f =
|
||||
CBotFunction::Compile1(p, pStack, this);
|
||||
CBotFunction* f = CBotFunction::Compile1(p, pStack, this);
|
||||
|
||||
if ( f == nullptr ) return false;
|
||||
|
||||
if (m_pMethod == nullptr) m_pMethod = f;
|
||||
else m_pMethod->AddNext(f);
|
||||
m_pMethod.push_back(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// return a method precompiled in pass 1
|
||||
CBotFunction* pf = m_pMethod;
|
||||
CBotToken* ppp = p;
|
||||
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
|
||||
CBotDefParam* params = CBotDefParam::Compile(p, pStk );
|
||||
delete pStk;
|
||||
p = ppp;
|
||||
while ( pf != nullptr ) // search by name and parameters
|
||||
std::list<CBotFunction*>::iterator pfIter = std::find_if(m_pMethod.begin(), m_pMethod.end(), [&pp, ¶ms](CBotFunction* x)
|
||||
{
|
||||
if (pf->GetName() == pp && pf->CheckParam( params )) break;
|
||||
pf = pf->Next();
|
||||
}
|
||||
return x->GetName() == pp && x->CheckParam( params );
|
||||
});
|
||||
assert(pfIter != m_pMethod.end());
|
||||
CBotFunction* pf = *pfIter;
|
||||
delete params;
|
||||
|
||||
bool bConstructor = (pp == GetName());
|
||||
CBotCStack* pile = pStack->TokenStack(nullptr, true);
|
||||
|
@ -706,12 +665,51 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
}
|
||||
|
||||
// definition of an element
|
||||
if (type2.Eq(0))
|
||||
if (type.Eq(0))
|
||||
{
|
||||
pStack->SetError(CBotErrNoTerminator, p);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pp[0] == '~' || pp == GetName()) // bad variable name
|
||||
{
|
||||
pStack->SetError(CBotErrNoVar, varToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bSecond && CheckVar(pp)) // variable already exists
|
||||
{
|
||||
pStack->SetError(CBotErrRedefVar, varToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
CBotInstr* limites = nullptr;
|
||||
while ( IsOfType( p, ID_OPBRK ) ) // an array
|
||||
{
|
||||
CBotInstr* i = nullptr;
|
||||
pStack->SetStartError( p->GetStart() );
|
||||
if ( p->GetType() != ID_CLBRK )
|
||||
{
|
||||
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
||||
if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
|
||||
{
|
||||
pStack->SetError(CBotErrBadIndex, p->GetStart());
|
||||
}
|
||||
}
|
||||
else
|
||||
i = new CBotEmpty(); // special if not a formula
|
||||
|
||||
type2 = CBotTypResult(CBotTypArrayPointer, type2);
|
||||
|
||||
if (limites == nullptr) limites = i;
|
||||
else limites->AddNext3(i);
|
||||
|
||||
if (pStack->IsOk() && IsOfType(p, ID_CLBRK)) continue;
|
||||
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
||||
delete limites;
|
||||
return false;
|
||||
}
|
||||
|
||||
CBotInstr* i = nullptr;
|
||||
if ( IsOfType(p, ID_ASS ) )
|
||||
{
|
||||
|
@ -781,7 +779,10 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete i;
|
||||
delete limites;
|
||||
}
|
||||
|
||||
if ( IsOfType(p, ID_COMMA) ) continue;
|
||||
if ( IsOfType(p, ID_SEP) ) break;
|
||||
|
@ -810,10 +811,11 @@ CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
// TODO: Not sure how correct is that - I have no idea how the precompilation (Compile1 method) works ~krzys_h
|
||||
std::string name = p->GetString();
|
||||
CBotClass* pPapa = CBotClass::Find(name);
|
||||
CBotToken* pp = p;
|
||||
|
||||
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr)
|
||||
{
|
||||
pStack->SetError( CBotErrNotClass, p );
|
||||
pStack->SetError(CBotErrNoClassName, pp);
|
||||
return nullptr;
|
||||
}
|
||||
pOld->m_parent = pPapa;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <string>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
@ -37,6 +38,7 @@ class CBotStack;
|
|||
class CBotDefParam;
|
||||
class CBotToken;
|
||||
class CBotCStack;
|
||||
class CBotExternalCallList;
|
||||
|
||||
/**
|
||||
* \brief A CBot class definition
|
||||
|
@ -102,7 +104,7 @@ class CBotCStack;
|
|||
* float y = var->GetValFloat();
|
||||
* \endcode
|
||||
*/
|
||||
class CBotClass : public CBotLinkedList<CBotClass>
|
||||
class CBotClass
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
|
@ -133,13 +135,8 @@ public:
|
|||
bool intrinsic = false);
|
||||
|
||||
/*!
|
||||
* \brief AddFunction This call allows to add as external new method
|
||||
* used by the objects of this class. See (**) at end of this file for
|
||||
* more details.
|
||||
* \param name
|
||||
* \param rExec
|
||||
* \param rCompile
|
||||
* \return
|
||||
* \brief Add a function that can be called from CBot
|
||||
* \see CBotProgram::AddFunction
|
||||
*/
|
||||
bool AddFunction(const std::string& name,
|
||||
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
||||
|
@ -224,6 +221,13 @@ public:
|
|||
*/
|
||||
CBotVar* GetItemRef(int nIdent);
|
||||
|
||||
/*!
|
||||
* \brief Check whether a variable is already defined in a class
|
||||
* \param name Name of the variable
|
||||
* \return True if a variable is defined in the class
|
||||
*/
|
||||
bool CheckVar(const std::string &name);
|
||||
|
||||
/*!
|
||||
* \brief CompileMethode Compiles a method associated with an instance of
|
||||
* class the method can be declared by the user or AddFunction.
|
||||
|
@ -234,11 +238,11 @@ public:
|
|||
* \param nIdent
|
||||
* \return
|
||||
*/
|
||||
CBotTypResult CompileMethode(const std::string& name,
|
||||
CBotTypResult CompileMethode(CBotToken* name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppParams,
|
||||
CBotCStack* pStack,
|
||||
long& nIdent);
|
||||
long &nIdent);
|
||||
|
||||
/*!
|
||||
* \brief ExecuteMethode Executes a method.
|
||||
|
@ -246,18 +250,13 @@ public:
|
|||
* \param name
|
||||
* \param pThis
|
||||
* \param ppParams
|
||||
* \param pResult
|
||||
* \param pResultType
|
||||
* \param pStack
|
||||
* \param pToken
|
||||
* \return
|
||||
*/
|
||||
bool ExecuteMethode(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppParams,
|
||||
CBotVar*& pResult,
|
||||
CBotStack*& pStack,
|
||||
CBotToken* pToken);
|
||||
bool ExecuteMethode(long &nIdent, CBotVar* pThis, CBotVar** ppParams, CBotTypResult pResultType,
|
||||
CBotStack*&pStack, CBotToken* pToken);
|
||||
|
||||
/*!
|
||||
* \brief RestoreMethode Restored the execution stack.
|
||||
|
@ -267,11 +266,11 @@ public:
|
|||
* \param ppParams
|
||||
* \param pStack
|
||||
*/
|
||||
void RestoreMethode(long& nIdent,
|
||||
const std::string& name,
|
||||
void RestoreMethode(long &nIdent,
|
||||
CBotToken* name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppParams,
|
||||
CBotStack*& pStack);
|
||||
CBotStack*&pStack);
|
||||
|
||||
/*!
|
||||
* \brief Compile Compiles a class declared by the user.
|
||||
|
@ -283,10 +282,15 @@ public:
|
|||
CBotCStack* pStack);
|
||||
|
||||
/*!
|
||||
* \brief Compile1
|
||||
* \param p
|
||||
* \param pStack
|
||||
* \return
|
||||
* \brief Pre-compile a new class
|
||||
* \param p[in, out] Pointer to first token of the class, will be updated to point to first token after the class definition
|
||||
* \param pStack Compile stack
|
||||
*
|
||||
* This function is used to find the beginning and end of class definition.
|
||||
*
|
||||
* If any errors in the code are detected, this function will set the error on compile stack and return nullptr.
|
||||
*
|
||||
* \return Precompiled class, or nullptr in case of error
|
||||
*/
|
||||
static CBotClass* Compile1(CBotToken* &p,
|
||||
CBotCStack* pStack);
|
||||
|
@ -294,10 +298,10 @@ public:
|
|||
/*!
|
||||
* \brief DefineClasses Calls CompileDefItem for each class in a list
|
||||
* of classes, defining fields and pre-compiling methods.
|
||||
* \param pClass List of classes
|
||||
* \param pClassList List of classes
|
||||
* \param pStack
|
||||
*/
|
||||
static void DefineClasses(CBotClass* pClass, CBotCStack* pStack);
|
||||
static void DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack);
|
||||
|
||||
/*!
|
||||
* \brief CompileDefItem
|
||||
|
@ -388,9 +392,9 @@ private:
|
|||
//! Linked list of all class fields
|
||||
CBotVar* m_pVar;
|
||||
//! Linked list of all class external calls
|
||||
CBotCallMethode* m_pCalls;
|
||||
//! Linked list of all class methods
|
||||
CBotFunction* m_pMethod;
|
||||
CBotExternalCallList* m_externalMethods;
|
||||
//! List of all class methods
|
||||
std::list<CBotFunction*> m_pMethod{};
|
||||
void (*m_rUpdate)(CBotVar* thisVar, void* user);
|
||||
|
||||
CBotToken* m_pOpenblk;
|
||||
|
|
|
@ -36,12 +36,10 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
|||
std::stringstream ss;
|
||||
ss << "digraph {" << std::endl;
|
||||
|
||||
CBotFunction* func = program->GetFunctions();
|
||||
std::map<long, CBotFunction*> funcIdMap;
|
||||
while (func != nullptr)
|
||||
for (CBotFunction* func : program->GetFunctions())
|
||||
{
|
||||
funcIdMap[func->m_nFuncIdent] = func;
|
||||
func = func->Next();
|
||||
}
|
||||
|
||||
std::set<CBotInstr*> finished;
|
||||
|
@ -111,9 +109,8 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
|||
{
|
||||
DumpInstr(program->m_entryPoint);
|
||||
}
|
||||
func = program->GetFunctions();
|
||||
std::string prev = GetPointerAsString(program->m_entryPoint);
|
||||
while (func != nullptr)
|
||||
for (CBotFunction* func : program->GetFunctions())
|
||||
{
|
||||
if (func != program->m_entryPoint)
|
||||
{
|
||||
|
@ -122,8 +119,6 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
|||
//ss << prev << " -> " << GetPointerAsString(func) << " [style=invis]" << std::endl;
|
||||
prev = GetPointerAsString(func);
|
||||
}
|
||||
|
||||
func = func->Next();
|
||||
}
|
||||
|
||||
ss << "}" << std::endl;
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#include "CBot/CBotDefParam.h"
|
||||
|
||||
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||
#include "CBot/CBotInstr/CBotParExpr.h"
|
||||
|
||||
#include "CBot/CBotUtils.h"
|
||||
#include "CBot/CBotCStack.h"
|
||||
|
||||
|
@ -33,11 +36,13 @@ namespace CBot
|
|||
CBotDefParam::CBotDefParam()
|
||||
{
|
||||
m_nIdent = 0;
|
||||
m_expr = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotDefParam::~CBotDefParam()
|
||||
{
|
||||
delete m_expr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -51,8 +56,9 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
if (IsOfType(p, ID_OPENPAR))
|
||||
{
|
||||
CBotDefParam* list = nullptr;
|
||||
bool prevHasDefault = false;
|
||||
|
||||
while (!IsOfType(p, ID_CLOSEPAR))
|
||||
if (!IsOfType(p, ID_CLOSEPAR)) while (true)
|
||||
{
|
||||
CBotDefParam* param = new CBotDefParam();
|
||||
if (list == nullptr) list = param;
|
||||
|
@ -77,6 +83,26 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
break;
|
||||
}
|
||||
|
||||
if (IsOfType(p, ID_ASS)) // default value assignment
|
||||
{
|
||||
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
|
||||
if (nullptr != (param->m_expr = CBotParExpr::CompileLitExpr(p, pStk)))
|
||||
{
|
||||
CBotTypResult valueType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
|
||||
if (!TypesCompatibles(type, valueType))
|
||||
pStack->SetError(CBotErrBadType1, p->GetPrev());
|
||||
|
||||
prevHasDefault = true;
|
||||
}
|
||||
else pStack->SetError(CBotErrNoExpression, p);
|
||||
delete pStk;
|
||||
}
|
||||
else
|
||||
if (prevHasDefault) pStack->SetError(CBotErrDefaultValue, p->GetPrev());
|
||||
|
||||
if (!pStack->IsOk()) break;
|
||||
|
||||
if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
|
||||
CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable
|
||||
// if ( pClass ) var->SetClass(pClass);
|
||||
|
@ -85,10 +111,12 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
var->SetUniqNum(param->m_nIdent);
|
||||
pStack->AddVar(var); // place on the stack
|
||||
|
||||
if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
|
||||
continue;
|
||||
if (IsOfType(p, ID_COMMA)) continue;
|
||||
if (IsOfType(p, ID_CLOSEPAR)) break;
|
||||
|
||||
pStack->SetError(CBotErrClosePar, p->GetStart());
|
||||
}
|
||||
pStack->SetError(CBotErrClosePar, p->GetStart());
|
||||
pStack->SetError(CBotErrNoVar, p->GetStart());
|
||||
}
|
||||
pStack->SetError(CBotErrNoType, p);
|
||||
delete list;
|
||||
|
@ -106,40 +134,71 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
|||
int i = 0;
|
||||
CBotDefParam* p = this;
|
||||
|
||||
bool useDefault = false;
|
||||
CBotStack* pile = pj->AddStack();
|
||||
|
||||
while ( p != nullptr )
|
||||
{
|
||||
pile = pile->AddStack();
|
||||
if (pile->GetState() == 1) // already done?
|
||||
{
|
||||
if (ppVars != nullptr && ppVars[i] != nullptr) ++i;
|
||||
p = p->m_next;
|
||||
continue; // next param
|
||||
}
|
||||
|
||||
CBotVar* pVar = nullptr;
|
||||
|
||||
if (useDefault || (ppVars == nullptr || ppVars[i] == nullptr))
|
||||
{
|
||||
assert(p->m_expr != nullptr);
|
||||
|
||||
useDefault = true;
|
||||
|
||||
if (!p->m_expr->Execute(pile)) return false; // interupt here
|
||||
|
||||
pVar = pile->GetVar();
|
||||
}
|
||||
else
|
||||
pVar = ppVars[i];
|
||||
|
||||
pile->SetState(1); // mark this param done
|
||||
|
||||
// creates a local variable on the stack
|
||||
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
|
||||
|
||||
// serves to make the transformation of types:
|
||||
if ( ppVars != nullptr && ppVars[i] != nullptr )
|
||||
if ((useDefault && pVar != nullptr) ||
|
||||
(ppVars != nullptr && pVar != nullptr))
|
||||
{
|
||||
switch (p->m_type.GetType())
|
||||
{
|
||||
case CBotTypInt:
|
||||
newvar->SetValInt(ppVars[i]->GetValInt());
|
||||
newvar->SetValInt(pVar->GetValInt());
|
||||
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||
break;
|
||||
case CBotTypFloat:
|
||||
newvar->SetValFloat(ppVars[i]->GetValFloat());
|
||||
newvar->SetValFloat(pVar->GetValFloat());
|
||||
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||
break;
|
||||
case CBotTypString:
|
||||
newvar->SetValString(ppVars[i]->GetValString());
|
||||
newvar->SetValString(pVar->GetValString());
|
||||
break;
|
||||
case CBotTypBoolean:
|
||||
newvar->SetValInt(ppVars[i]->GetValInt());
|
||||
newvar->SetValInt(pVar->GetValInt());
|
||||
break;
|
||||
case CBotTypIntrinsic:
|
||||
(static_cast<CBotVarClass*>(newvar))->Copy(ppVars[i], false);
|
||||
(static_cast<CBotVarClass*>(newvar))->Copy(pVar, false);
|
||||
break;
|
||||
case CBotTypPointer:
|
||||
{
|
||||
newvar->SetPointer(ppVars[i]->GetPointer());
|
||||
newvar->SetPointer(pVar->GetPointer());
|
||||
newvar->SetType(p->m_type); // keep pointer type
|
||||
}
|
||||
break;
|
||||
case CBotTypArrayPointer:
|
||||
{
|
||||
newvar->SetPointer(ppVars[i]->GetPointer());
|
||||
newvar->SetPointer(pVar->GetPointer());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -149,23 +208,41 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
|||
newvar->SetUniqNum(p->m_nIdent);
|
||||
pj->AddVar(newvar); // add a variable
|
||||
p = p->m_next;
|
||||
i++;
|
||||
if (!useDefault) i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotDefParam::HasDefault()
|
||||
{
|
||||
return (m_expr != nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
|
||||
{
|
||||
// int i = 0;
|
||||
CBotDefParam* p = this;
|
||||
|
||||
CBotStack* pile = nullptr;
|
||||
if (bMain) pile = pj->RestoreStack();
|
||||
|
||||
while ( p != nullptr )
|
||||
{
|
||||
if (bMain && pile != nullptr)
|
||||
{
|
||||
pile = pile->RestoreStack();
|
||||
if (pile != nullptr && pile->GetState() == 0)
|
||||
{
|
||||
assert(p->m_expr != nullptr);
|
||||
p->m_expr->RestoreState(pile, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// creates a local variable on the stack
|
||||
CBotVar* var = pj->FindVar(p->m_token.GetString());
|
||||
var->SetUniqNum(p->m_nIdent);
|
||||
if (var != nullptr) var->SetUniqNum(p->m_nIdent);
|
||||
p = p->m_next;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,12 @@ public:
|
|||
*/
|
||||
bool Execute(CBotVar** ppVars, CBotStack* &pj);
|
||||
|
||||
/*!
|
||||
* \brief Check if this parameter has a default value expression.
|
||||
* \return true if the parameter was compiled with a default value.
|
||||
*/
|
||||
bool HasDefault();
|
||||
|
||||
/*!
|
||||
* \brief RestoreState
|
||||
* \param pj
|
||||
|
@ -96,6 +102,9 @@ private:
|
|||
//! Type of paramteter.
|
||||
CBotTypResult m_type;
|
||||
long m_nIdent;
|
||||
|
||||
//! Default value expression for the parameter.
|
||||
CBotInstr* m_expr;
|
||||
};
|
||||
|
||||
} // namespace CBot
|
||||
|
|
|
@ -237,6 +237,10 @@ enum CBotError : int
|
|||
CBotErrNoPublic = 5042, //!< missing word "public"
|
||||
CBotErrNoExpression = 5043, //!< expression expected after =
|
||||
CBotErrAmbiguousCall = 5044, //!< ambiguous call to overloaded function
|
||||
CBotErrFuncNotVoid = 5045, //!< function needs return type "void"
|
||||
CBotErrNoClassName = 5046, //!< class name expected
|
||||
CBotErrNoReturn = 5047, //!< non-void function needs "return;"
|
||||
CBotErrDefaultValue = 5048, //!< this parameter needs a default value
|
||||
|
||||
// Runtime errors
|
||||
CBotErrZeroDiv = 6000, //!< division by zero
|
||||
|
|
|
@ -168,4 +168,48 @@ bool CBotExternalCallDefault::Run(CBotVar* thisVar, CBotStack* pStack)
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CBotExternalCallClass::CBotExternalCallClass(RuntimeFunc rExec, CompileFunc rCompile)
|
||||
{
|
||||
m_rExec = rExec;
|
||||
m_rComp = rCompile;
|
||||
}
|
||||
|
||||
CBotExternalCallClass::~CBotExternalCallClass()
|
||||
{
|
||||
}
|
||||
|
||||
CBotTypResult CBotExternalCallClass::Compile(CBotVar* thisVar, CBotVar* args, void* user)
|
||||
{
|
||||
return m_rComp(thisVar, args);
|
||||
}
|
||||
|
||||
bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack)
|
||||
{
|
||||
if (pStack->IsCallFinished()) return true;
|
||||
CBotStack* pile = pStack->AddStackExternalCall(this);
|
||||
CBotVar* args = pile->GetVar();
|
||||
|
||||
CBotStack* pile2 = pile->AddStack();
|
||||
|
||||
CBotVar* result = pile2->GetVar();
|
||||
|
||||
int exception = CBotNoErr; // TODO: Change to CBotError
|
||||
bool res = m_rExec(thisVar, args, result, exception, pStack->GetUserPtr());
|
||||
|
||||
if (!res)
|
||||
{
|
||||
if (exception != CBotNoErr)
|
||||
{
|
||||
pStack->SetError(static_cast<CBotError>(exception));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result != nullptr) pStack->SetCopyVar(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -105,6 +105,36 @@ private:
|
|||
CompileFunc m_rComp;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Implementation of CBot external call for class methods, using compilation and runtime functions
|
||||
*/
|
||||
class CBotExternalCallClass : public CBotExternalCall
|
||||
{
|
||||
public:
|
||||
typedef bool (*RuntimeFunc)(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user);
|
||||
typedef CBotTypResult (*CompileFunc)(CBotVar* pThis, CBotVar*& pVar);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param rExec Runtime function
|
||||
* \param rCompile Compilation function
|
||||
* \see CBotProgram::AddFunction()
|
||||
*/
|
||||
CBotExternalCallClass(RuntimeFunc rExec, CompileFunc rCompile);
|
||||
|
||||
/**
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~CBotExternalCallClass();
|
||||
|
||||
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user) override;
|
||||
virtual bool Run(CBotVar* thisVar, CBotStack* pStack) override;
|
||||
|
||||
private:
|
||||
RuntimeFunc m_rExec;
|
||||
CompileFunc m_rComp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Class for mangaging CBot external calls
|
||||
|
|
|
@ -51,6 +51,9 @@ CBotDefClass::CBotDefClass()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotDefClass::~CBotDefClass()
|
||||
{
|
||||
delete m_parameters;
|
||||
delete m_exprRetVar;
|
||||
delete m_expr;
|
||||
delete m_var;
|
||||
}
|
||||
|
||||
|
@ -131,7 +134,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
|
|||
{
|
||||
// the constructor is there?
|
||||
// std::string noname;
|
||||
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent);
|
||||
CBotTypResult r = pClass->CompileMethode(&token, var, ppVars, pStk, inst->m_nMethodeIdent);
|
||||
delete pStk->TokenStack(); // releases the supplement stack
|
||||
int typ = r.GetType();
|
||||
|
||||
|
@ -246,9 +249,9 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
|||
|
||||
if (m_exprRetVar != nullptr) // Class c().method();
|
||||
{
|
||||
if (pile->IfStep()) return false;
|
||||
if (pile->GetState() == 4)
|
||||
{
|
||||
if (pile->IfStep()) return false;
|
||||
CBotStack* pile3 = pile->AddStack();
|
||||
if (!m_exprRetVar->Execute(pile3)) return false;
|
||||
pile3->SetVar(nullptr);
|
||||
|
@ -369,11 +372,7 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
|||
ppVars[i] = nullptr;
|
||||
|
||||
// creates a variable for the result
|
||||
CBotVar* pResult = nullptr; // constructor still void
|
||||
|
||||
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
|
||||
pThis, ppVars,
|
||||
pResult, pile2, GetToken())) return false; // interrupt
|
||||
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pThis, ppVars, CBotTypResult(CBotTypVoid), pile2, GetToken())) return false; // interrupt
|
||||
|
||||
pThis->SetInit(CBotVar::InitType::DEF);
|
||||
pThis->ConstructorSet(); // indicates that the constructor has been called
|
||||
|
@ -483,9 +482,7 @@ void CBotDefClass::RestoreState(CBotStack* &pj, bool bMain)
|
|||
ppVars[i] = nullptr;
|
||||
|
||||
// creates a variable for the result
|
||||
// CBotVar* pResult = nullptr; // constructor still void
|
||||
|
||||
pClass->RestoreMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pile2);
|
||||
pClass->RestoreMethode(m_nMethodeIdent, pt, pThis, ppVars, pile2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ CBotExprUnaire::~CBotExprUnaire()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral)
|
||||
{
|
||||
int op = p->GetType();
|
||||
CBotToken* pp = p;
|
||||
|
@ -52,7 +52,10 @@ CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
CBotExprUnaire* inst = new CBotExprUnaire();
|
||||
inst->SetToken(pp);
|
||||
|
||||
if (nullptr != (inst->m_expr = CBotParExpr::Compile(p, pStk )))
|
||||
if (!bLiteral) inst->m_expr = CBotParExpr::Compile(p, pStk);
|
||||
else inst->m_expr = CBotParExpr::CompileLitExpr(p, pStk);
|
||||
|
||||
if (inst->m_expr != nullptr)
|
||||
{
|
||||
if (op == ID_ADD && pStk->GetType() < CBotTypBoolean) // only with the number
|
||||
return pStack->Return(inst, pStk);
|
||||
|
|
|
@ -34,12 +34,13 @@ public:
|
|||
~CBotExprUnaire();
|
||||
|
||||
/*!
|
||||
* \brief Compile
|
||||
* \param p
|
||||
* \param pStack
|
||||
* \return
|
||||
* \brief Compile an expression with a unary operator
|
||||
* \param p[in, out] Pointer to first token of the expression, will be updated to point to first token after the expression
|
||||
* \param pStack Current compilation stack frame
|
||||
* \param bLiteral If true, compiles only literal expressions Ex: ~11, -4.0, !false, not true
|
||||
* \return The compiled instruction or nullptr
|
||||
*/
|
||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral = false);
|
||||
|
||||
/*!
|
||||
* \brief Execute
|
||||
|
|
|
@ -44,7 +44,7 @@ CBotExprVar::~CBotExprVar()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::ProtectionLevel privat)
|
||||
CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckReadOnly)
|
||||
{
|
||||
// CBotToken* pDebut = p;
|
||||
CBotCStack* pStk = pStack->TokenStack();
|
||||
|
@ -67,7 +67,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
|||
|
||||
if (ident > 0 && ident < 9000)
|
||||
{
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, privat))
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, bCheckReadOnly))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, p);
|
||||
goto err;
|
||||
|
@ -122,6 +122,8 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
|||
{
|
||||
if (p->GetNext()->GetType() == ID_OPENPAR) // a method call?
|
||||
{
|
||||
if (bCheckReadOnly) goto err; // don't allow increment a method call "++"
|
||||
|
||||
CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
|
||||
if (!pStk->IsOk()) goto err;
|
||||
inst->AddNext3(i); // added after
|
||||
|
@ -137,7 +139,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
|||
if (var != nullptr)
|
||||
{
|
||||
i->SetUniqNum(var->GetUniqNum());
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, privat))
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, bCheckReadOnly))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, pp);
|
||||
goto err;
|
||||
|
|
|
@ -40,14 +40,13 @@ public:
|
|||
~CBotExprVar();
|
||||
|
||||
/*!
|
||||
* \brief Compile
|
||||
* \param p
|
||||
* \param pStack
|
||||
* \param privat
|
||||
* \brief Compile an expression of a variable, possibly chained with index operators and/or dot operators
|
||||
* \param p[in, out] Pointer to first token of the expression, will be updated to point to first token after the expression
|
||||
* \param pStack Current compilation stack frame
|
||||
* \param bCheckReadOnly True for operations that would modify the value of the variable
|
||||
* \return
|
||||
*/
|
||||
static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack,
|
||||
CBotVar::ProtectionLevel privat = CBotVar::ProtectionLevel::Protected);
|
||||
static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckReadOnly = false);
|
||||
|
||||
/*!
|
||||
* \brief CompileMethode
|
||||
|
@ -81,6 +80,8 @@ public:
|
|||
*/
|
||||
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep);
|
||||
|
||||
using CBotInstr::ExecuteVar;
|
||||
|
||||
/*!
|
||||
* \brief RestoreStateVar Fetch variable at runtime.
|
||||
* \param pj
|
||||
|
|
|
@ -135,12 +135,11 @@ std::string CBotFieldExpr::GetDebugData()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar,
|
||||
CBotVar::ProtectionLevel privat)
|
||||
bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar, bool bCheckReadOnly)
|
||||
{
|
||||
CBotVar::ProtectionLevel varPriv = pVar->GetPrivate();
|
||||
|
||||
if (privat == CBotVar::ProtectionLevel::ReadOnly && varPriv == privat)
|
||||
if (bCheckReadOnly && varPriv == CBotVar::ProtectionLevel::ReadOnly)
|
||||
return true;
|
||||
|
||||
if (varPriv == CBotVar::ProtectionLevel::Public) return false;
|
||||
|
|
|
@ -72,13 +72,12 @@ public:
|
|||
* This function doesn't set the error flag itself.
|
||||
*
|
||||
* \param pStack Current compilation stack frame
|
||||
* \param pPrev Class instance which variable to check is part of, or nullptr if not part of a class
|
||||
* \param pPrev Class instance which variable to check is part of, or nullptr when compiler inserts 'this.' before
|
||||
* \param pVar Variable to check
|
||||
* \param privat CBotVar::ProtectionLevel::ReadOnly if requesting read-only access, anything else otherwise
|
||||
* \param bCheckReadOnly True for operations that would modify the value of the variable
|
||||
* \return true if pVar is inaccessible in the current context, false if access should be allowed
|
||||
*/
|
||||
static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar,
|
||||
CBotVar::ProtectionLevel privat = CBotVar::ProtectionLevel::Protected);
|
||||
static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar, bool bCheckReadOnly = false);
|
||||
|
||||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotFieldExpr"; }
|
||||
|
|
|
@ -46,7 +46,6 @@ CBotFunction::CBotFunction()
|
|||
{
|
||||
m_param = nullptr; // empty parameter list
|
||||
m_block = nullptr; // the instruction block
|
||||
m_next = nullptr; // functions can be chained
|
||||
m_bPublic = false; // function not public
|
||||
m_bExtern = false; // function not extern
|
||||
m_pProg = nullptr;
|
||||
|
@ -63,7 +62,6 @@ CBotFunction::~CBotFunction()
|
|||
{
|
||||
delete m_param; // empty parameter list
|
||||
delete m_block; // the instruction block
|
||||
delete m_next;
|
||||
|
||||
// remove public list if there is
|
||||
if (m_bPublic)
|
||||
|
@ -167,6 +165,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
if ( IsOfType(p, ID_NOT) )
|
||||
{
|
||||
CBotToken d(std::string("~") + p->GetString());
|
||||
d.SetPos(pp->GetStart(), p->GetEnd());
|
||||
func->m_token = d;
|
||||
}
|
||||
|
||||
|
@ -178,7 +177,11 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
func->m_MasterClass = pp->GetString();
|
||||
func->m_classToken = *pp;
|
||||
CBotClass* pClass = CBotClass::Find(pp);
|
||||
if ( pClass == nullptr ) goto bad;
|
||||
if ( pClass == nullptr )
|
||||
{
|
||||
pStk->SetError(CBotErrNoClassName, pp);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
// pp = p;
|
||||
func->m_token = *p;
|
||||
|
@ -186,6 +189,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
|
||||
}
|
||||
func->m_openpar = *p;
|
||||
delete func->m_param;
|
||||
func->m_param = CBotDefParam::Compile(p, pStk );
|
||||
func->m_closepar = *(p->GetPrev());
|
||||
if (pStk->IsOk())
|
||||
|
@ -224,6 +228,12 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
func->m_closeblk = (p != nullptr && p->GetPrev() != nullptr) ? *(p->GetPrev()) : CBotToken();
|
||||
if ( pStk->IsOk() )
|
||||
{
|
||||
if (!func->m_retTyp.Eq(CBotTypVoid) && !func->HasReturn())
|
||||
{
|
||||
int errPos = func->m_closeblk.GetStart();
|
||||
pStk->ResetError(CBotErrNoReturn, errPos, errPos);
|
||||
goto bad;
|
||||
}
|
||||
return pStack->ReturnFunc(func, pStk);
|
||||
}
|
||||
}
|
||||
|
@ -270,6 +280,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
|||
if ( IsOfType(p, ID_NOT) )
|
||||
{
|
||||
CBotToken d(std::string("~") + p->GetString());
|
||||
d.SetPos(pp->GetStart(), p->GetEnd());
|
||||
func->m_token = d;
|
||||
}
|
||||
|
||||
|
@ -279,22 +290,47 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
|||
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
|
||||
{
|
||||
func->m_MasterClass = pp->GetString();
|
||||
CBotClass* pClass = CBotClass::Find(pp);
|
||||
if ( pClass == nullptr )
|
||||
{
|
||||
pStk->SetError(CBotErrNotClass, pp);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
// existence of the class is checked
|
||||
// later in CBotFunction::Compile()
|
||||
pp = p;
|
||||
func->m_token = *p;
|
||||
if (!IsOfType(p, TokenTypVar)) goto bad;
|
||||
|
||||
}
|
||||
func->m_param = CBotDefParam::Compile(p, pStk );
|
||||
|
||||
CBotToken* openPar = p;
|
||||
func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters
|
||||
|
||||
if (pStk->IsOk() && pClass != nullptr) // method in a class
|
||||
{
|
||||
// check if a constructor has return type void
|
||||
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||
{
|
||||
pp = &(func->m_retToken);
|
||||
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||
}
|
||||
|
||||
if (pStk->IsOk() && pp->GetString() == "~") // destructor
|
||||
{
|
||||
// check destructor name
|
||||
if (func->GetName() != ("~" + pClass->GetName()))
|
||||
pStk->SetError(CBotErrNoFunc, pp);
|
||||
// confirm no parameters
|
||||
if (pStk->IsOk() && func->m_param != nullptr)
|
||||
pStk->SetError(CBotErrClosePar, openPar->GetNext());
|
||||
// must return void
|
||||
if (pStk->IsOk() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||
{
|
||||
pp = &(func->m_retToken);
|
||||
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pStk->IsOk())
|
||||
{
|
||||
// looks if the function exists elsewhere
|
||||
pp = &(func->m_token);
|
||||
if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param)) &&
|
||||
( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
|
||||
{
|
||||
|
@ -334,9 +370,19 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
|||
|
||||
pile->SetProgram(m_pProg); // bases for routines
|
||||
|
||||
if ( pile->IfStep() ) return false;
|
||||
|
||||
if ( pile->GetState() == 0 )
|
||||
{
|
||||
if ( !m_param->Execute(ppVars, pile) ) return false; // define parameters
|
||||
if (m_param != nullptr)
|
||||
{
|
||||
// stack for parameters and default args
|
||||
CBotStack* pile3b = pile->AddStack();
|
||||
pile3b->SetState(1);
|
||||
|
||||
if ( !m_param->Execute(ppVars, pile) ) return false; // define parameters
|
||||
pile3b->Delete(); // done with param stack
|
||||
}
|
||||
pile->IncState();
|
||||
}
|
||||
|
||||
|
@ -369,8 +415,6 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
|||
pile->IncState();
|
||||
}
|
||||
|
||||
if ( pile->IfStep() ) return false;
|
||||
|
||||
if ( !m_block->Execute(pile) )
|
||||
{
|
||||
if ( pile->GetError() < 0 )
|
||||
|
@ -399,7 +443,22 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
|
|||
pile2->Delete();
|
||||
}
|
||||
|
||||
m_param->RestoreState(pile2, true); // parameters
|
||||
if ( pile->GetState() == 0 )
|
||||
{
|
||||
if (m_param != nullptr)
|
||||
{
|
||||
CBotStack* pile3b = pile2->RestoreStack();
|
||||
|
||||
if (pile3b != nullptr && pile3b->GetState() == 1)
|
||||
m_param->RestoreState(pile2, true); // restore executing default arguments
|
||||
else
|
||||
m_param->RestoreState(pile2, false); // restore parameter IDs
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_param != nullptr)
|
||||
m_param->RestoreState(pile2, false); // restore parameter IDs
|
||||
|
||||
if ( !m_MasterClass.empty() )
|
||||
{
|
||||
|
@ -412,37 +471,28 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotFunction::AddNext(CBotFunction* p)
|
||||
CBotTypResult CBotFunction::CompileCall(const std::list<CBotFunction*>& localFunctionList, const std::string &name, CBotVar** ppVars, long &nIdent)
|
||||
{
|
||||
CBotFunction* pp = this;
|
||||
while (pp->m_next != nullptr) pp = pp->m_next;
|
||||
|
||||
pp->m_next = p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotTypResult CBotFunction::CompileCall(const std::string& name, CBotVar** ppVars, long& nIdent)
|
||||
{
|
||||
nIdent = 0;
|
||||
CBotTypResult type;
|
||||
|
||||
// CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
||||
FindLocalOrPublic(nIdent, name, ppVars, type);
|
||||
CBotTypResult type;
|
||||
if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type))
|
||||
{
|
||||
// Reset the identifier to "not found" value
|
||||
nIdent = 0;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& name, CBotVar** ppVars,
|
||||
CBotTypResult& TypeOrError, bool bPublic)
|
||||
CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic)
|
||||
{
|
||||
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
||||
CBotFunction* pt;
|
||||
|
||||
if ( nIdent )
|
||||
{
|
||||
if ( this != nullptr ) for ( pt = this ; pt != nullptr ; pt = pt->m_next )
|
||||
for (CBotFunction* pt : localFunctionList)
|
||||
{
|
||||
if ( pt->m_nFuncIdent == nIdent )
|
||||
if (pt->m_nFuncIdent == nIdent)
|
||||
{
|
||||
TypeOrError = pt->m_retTyp;
|
||||
return pt;
|
||||
|
@ -464,62 +514,64 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
|||
|
||||
std::map<CBotFunction*, int> funcMap;
|
||||
|
||||
if ( this != nullptr )
|
||||
for (CBotFunction* pt : localFunctionList)
|
||||
{
|
||||
for ( pt = this ; pt != nullptr ; pt = pt->m_next )
|
||||
if ( pt->m_token.GetString() == name )
|
||||
{
|
||||
if ( pt->m_token.GetString() == name )
|
||||
int i = 0;
|
||||
int alpha = 0; // signature of parameters
|
||||
// parameters are compatible?
|
||||
CBotDefParam* pv = pt->m_param; // expected list of parameters
|
||||
CBotVar* pw = ppVars[i++]; // provided list parameter
|
||||
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )
|
||||
{
|
||||
int i = 0;
|
||||
int alpha = 0; // signature of parameters
|
||||
// parameters are compatible?
|
||||
CBotDefParam* pv = pt->m_param; // expected list of parameters
|
||||
CBotVar* pw = ppVars[i++]; // provided list parameter
|
||||
while ( pv != nullptr && pw != nullptr)
|
||||
if (pw == nullptr) // end of arguments
|
||||
{
|
||||
CBotTypResult paramType = pv->GetTypResult();
|
||||
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
|
||||
if (!TypesCompatibles(paramType, argType))
|
||||
{
|
||||
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
|
||||
break;
|
||||
}
|
||||
|
||||
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
|
||||
{
|
||||
CBotClass* c1 = paramType.GetClass();
|
||||
CBotClass* c2 = argType.GetClass();
|
||||
while (c2 != c1 && c2 != nullptr) // implicit cast
|
||||
{
|
||||
alpha += 10;
|
||||
c2 = c2->GetParent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
||||
}
|
||||
pv = pv->GetNext();
|
||||
pw = ppVars[i++];
|
||||
continue; // skip params with default values
|
||||
}
|
||||
if ( pw != nullptr )
|
||||
CBotTypResult paramType = pv->GetTypResult();
|
||||
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
|
||||
if (!TypesCompatibles(paramType, argType))
|
||||
{
|
||||
if ( !funcMap.empty() ) continue;
|
||||
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
||||
continue; // too many parameters
|
||||
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
|
||||
break;
|
||||
}
|
||||
if ( pv != nullptr )
|
||||
|
||||
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
|
||||
{
|
||||
if ( !funcMap.empty() ) continue;
|
||||
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
||||
continue; // not enough parameters
|
||||
CBotClass* c1 = paramType.GetClass();
|
||||
CBotClass* c2 = argType.GetClass();
|
||||
while (c2 != c1 && c2 != nullptr) // implicit cast
|
||||
{
|
||||
alpha += 10;
|
||||
c2 = c2->GetParent();
|
||||
}
|
||||
}
|
||||
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||
else
|
||||
{
|
||||
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
||||
}
|
||||
pv = pv->GetNext();
|
||||
pw = ppVars[i++];
|
||||
}
|
||||
if ( pw != nullptr )
|
||||
{
|
||||
if ( !funcMap.empty() ) continue;
|
||||
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
||||
continue; // too many parameters
|
||||
}
|
||||
if ( pv != nullptr )
|
||||
{
|
||||
if ( !funcMap.empty() ) continue;
|
||||
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
||||
continue; // not enough parameters
|
||||
}
|
||||
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,8 +586,13 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
|||
// parameters sont-ils compatibles ?
|
||||
CBotDefParam* pv = pt->m_param; // list of expected parameters
|
||||
CBotVar* pw = ppVars[i++]; // list of provided parameters
|
||||
while ( pv != nullptr && pw != nullptr)
|
||||
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )
|
||||
{
|
||||
if (pw == nullptr) // end of arguments
|
||||
{
|
||||
pv = pv->GetNext();
|
||||
continue; // skip params with default values
|
||||
}
|
||||
CBotTypResult paramType = pv->GetTypResult();
|
||||
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||
|
||||
|
@ -610,12 +667,13 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
|
||||
int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
|
||||
{
|
||||
CBotTypResult type;
|
||||
CBotFunction* pt = nullptr;
|
||||
|
||||
pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
||||
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
|
||||
|
||||
if ( pt != nullptr )
|
||||
{
|
||||
|
@ -632,9 +690,12 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
|||
|
||||
if ( pStk1->GetState() == 0 )
|
||||
{
|
||||
if ( !pt->m_MasterClass.empty() )
|
||||
// stack for parameters and default args
|
||||
CBotStack* pStk3b = pStk3->AddStack();
|
||||
|
||||
if (pStk3b->GetState() == 0 && !pt->m_MasterClass.empty())
|
||||
{
|
||||
CBotVar* pInstance = m_pProg->m_thisVar;
|
||||
CBotVar* pInstance = program->m_thisVar;
|
||||
// make "this" known
|
||||
CBotVar* pThis ;
|
||||
if ( pInstance == nullptr )
|
||||
|
@ -658,10 +719,21 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
|||
pThis->SetUniqNum(-2);
|
||||
pStk1->AddVar(pThis);
|
||||
}
|
||||
pStk3b->SetState(1); // set 'this' was created
|
||||
|
||||
// initializes the variables as parameters
|
||||
pt->m_param->Execute(ppVars, pStk3); // cannot be interrupted
|
||||
|
||||
if (pt->m_param != nullptr)
|
||||
{
|
||||
if (!pt->m_param->Execute(ppVars, pStk3)) // interupt here
|
||||
{
|
||||
if (!pStk3->IsOk() && pt->m_pProg != program)
|
||||
{
|
||||
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pStk3b->Delete(); // done with param stack
|
||||
pStk1->IncState();
|
||||
}
|
||||
|
||||
|
@ -670,7 +742,7 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
|||
if ( !pStk3->GetRetVar( // puts the result on the stack
|
||||
pt->m_block->Execute(pStk3) )) // GetRetVar said if it is interrupted
|
||||
{
|
||||
if ( !pStk3->IsOk() && pt->m_pProg != m_pProg )
|
||||
if ( !pStk3->IsOk() && pt->m_pProg != program )
|
||||
{
|
||||
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||
}
|
||||
|
@ -683,7 +755,8 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar** ppVars, CBotStack* pStack)
|
||||
void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList,
|
||||
long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack)
|
||||
{
|
||||
CBotTypResult type;
|
||||
CBotFunction* pt = nullptr;
|
||||
|
@ -692,7 +765,7 @@ void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar**
|
|||
|
||||
// search function to return the ok identifier
|
||||
|
||||
pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
||||
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
|
||||
|
||||
if ( pt != nullptr )
|
||||
{
|
||||
|
@ -729,24 +802,33 @@ void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar**
|
|||
|
||||
if ( pStk1->GetState() == 0 )
|
||||
{
|
||||
pt->m_param->RestoreState(pStk3, true);
|
||||
if (pt->m_param != nullptr)
|
||||
{
|
||||
CBotStack* pStk3b = pStk3->RestoreStack();
|
||||
|
||||
if (pStk3b != nullptr && pStk3b->GetState() == 1)
|
||||
pt->m_param->RestoreState(pStk3, true); // restore executing default arguments
|
||||
else
|
||||
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// initializes the variables as parameters
|
||||
pt->m_param->RestoreState(pStk3, false);
|
||||
if (pt->m_param != nullptr)
|
||||
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||
pt->m_block->RestoreState(pStk3, true);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack,
|
||||
CBotToken* pToken, CBotClass* pClass)
|
||||
int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
||||
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
|
||||
{
|
||||
CBotTypResult type;
|
||||
CBotProgram* pProgCurrent = pStack->GetProgram();
|
||||
|
||||
CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type, false);
|
||||
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, false);
|
||||
|
||||
if ( pt != nullptr )
|
||||
{
|
||||
|
@ -762,23 +844,42 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis,
|
|||
|
||||
if ( pStk->GetState() == 0 )
|
||||
{
|
||||
// sets the variable "this" on the stack
|
||||
CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
|
||||
pthis->Copy(pThis, false);
|
||||
pthis->SetUniqNum(-2); // special value
|
||||
pStk->AddVar(pthis);
|
||||
// stack for parameters and default args
|
||||
CBotStack* pStk3b = pStk3->AddStack();
|
||||
|
||||
CBotClass* pClass = pThis->GetClass()->GetParent();
|
||||
if ( pClass )
|
||||
if (pStk3b->GetState() == 0)
|
||||
{
|
||||
// sets the variable "super" on the stack
|
||||
CBotVar* psuper = CBotVar::Create("super", CBotTypNullPointer);
|
||||
psuper->Copy(pThis, false); // in fact identical to "this"
|
||||
psuper->SetUniqNum(-3); // special value
|
||||
pStk->AddVar(psuper);
|
||||
// sets the variable "this" on the stack
|
||||
CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
|
||||
pthis->Copy(pThis, false);
|
||||
pthis->SetUniqNum(-2); // special value
|
||||
pStk->AddVar(pthis);
|
||||
|
||||
CBotClass* pClass = pThis->GetClass()->GetParent();
|
||||
if ( pClass )
|
||||
{
|
||||
// sets the variable "super" on the stack
|
||||
CBotVar* psuper = CBotVar::Create("super", CBotTypNullPointer);
|
||||
psuper->Copy(pThis, false); // in fact identical to "this"
|
||||
psuper->SetUniqNum(-3); // special value
|
||||
pStk->AddVar(psuper);
|
||||
}
|
||||
}
|
||||
pStk3b->SetState(1); // set 'this' was created
|
||||
|
||||
// initializes the variables as parameters
|
||||
pt->m_param->Execute(ppVars, pStk3); // cannot be interrupted
|
||||
if (pt->m_param != nullptr)
|
||||
{
|
||||
if (!pt->m_param->Execute(ppVars, pStk3)) // interupt here
|
||||
{
|
||||
if (!pStk3->IsOk() && pt->m_pProg != pProgCurrent)
|
||||
{
|
||||
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pStk3b->Delete(); // done with param stack
|
||||
pStk->IncState();
|
||||
}
|
||||
|
||||
|
@ -822,11 +923,11 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar* pThis, CBotVar** ppVars,
|
||||
CBotStack* pStack, CBotClass* pClass)
|
||||
bool CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
||||
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
|
||||
{
|
||||
CBotTypResult type;
|
||||
CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
||||
CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type);
|
||||
|
||||
if ( pt != nullptr )
|
||||
{
|
||||
|
@ -846,7 +947,21 @@ bool CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar* p
|
|||
CBotStack* pStk3 = pStk->RestoreStack(nullptr); // to set parameters passed
|
||||
if ( pStk3 == nullptr ) return true;
|
||||
|
||||
pt->m_param->RestoreState(pStk3, true); // parameters
|
||||
if ( pStk->GetState() == 0 )
|
||||
{
|
||||
if (pt->m_param != nullptr)
|
||||
{
|
||||
CBotStack* pStk3b = pStk3->RestoreStack();
|
||||
if (pStk3b != nullptr && pStk3b->GetState() == 1)
|
||||
pt->m_param->RestoreState(pStk3, true); // restore executing default arguments
|
||||
else
|
||||
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pt->m_param != nullptr)
|
||||
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||
|
||||
if ( pStk->GetState() > 1 && // latching is effective?
|
||||
pt->m_bSynchro )
|
||||
|
@ -903,18 +1018,18 @@ std::string CBotFunction::GetParams()
|
|||
return params;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotFunction* CBotFunction::Next()
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotFunction::AddPublic(CBotFunction* func)
|
||||
{
|
||||
m_publicFunctions.insert(func);
|
||||
}
|
||||
|
||||
bool CBotFunction::HasReturn()
|
||||
{
|
||||
if (m_block != nullptr) return m_block->HasReturn();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string CBotFunction::GetDebugData()
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -60,11 +60,16 @@ public:
|
|||
bool bLocal = true);
|
||||
|
||||
/*!
|
||||
* \brief Compile1 Pre-compile a new function.
|
||||
* \param p
|
||||
* \param pStack
|
||||
* \param pClass
|
||||
* \return
|
||||
* \brief Pre-compile a new function
|
||||
* \param p[in, out] Pointer to first token of the function, will be updated to point to first token after the function definition
|
||||
* \param pStack Compile stack
|
||||
* \param pClass If this is a class method, pointer to class this function is part of, otherwise nullptr
|
||||
*
|
||||
* This function is used to find the beginning and end of function definition.
|
||||
*
|
||||
* If any errors in the code are detected, this function will set the error on compile stack and return nullptr.
|
||||
*
|
||||
* \return Precompiled function, or nullptr in case of error
|
||||
*/
|
||||
static CBotFunction* Compile1(CBotToken* &p,
|
||||
CBotCStack* pStack,
|
||||
|
@ -81,6 +86,8 @@ public:
|
|||
CBotStack* &pj,
|
||||
CBotVar* pInstance = nullptr);
|
||||
|
||||
using CBotInstr::Execute;
|
||||
|
||||
/*!
|
||||
* \brief RestoreState
|
||||
* \param ppVars
|
||||
|
@ -91,40 +98,46 @@ public:
|
|||
CBotStack* &pj,
|
||||
CBotVar* pInstance = nullptr);
|
||||
|
||||
/*!
|
||||
* \brief AddNext
|
||||
* \param p
|
||||
*/
|
||||
void AddNext(CBotFunction* p);
|
||||
using CBotInstr::RestoreState;
|
||||
|
||||
/*!
|
||||
* \brief CompileCall
|
||||
* \param name
|
||||
* \param ppVars
|
||||
* \param nIdent
|
||||
* \return
|
||||
* \brief Compile a function call
|
||||
*
|
||||
* See FindLocalOrPublic for more detailed explanation
|
||||
*
|
||||
* \param localFunctionList Linked list of local functions to search in, can be null
|
||||
* \param name Name of the function
|
||||
* \param ppVars List of function arguments
|
||||
* \param nIdent[in, out] Unique identifier of the function
|
||||
* \return Type returned by the function or error code
|
||||
* \see FindLocalOrPublic
|
||||
*/
|
||||
CBotTypResult CompileCall(const std::string& name,
|
||||
CBotVar** ppVars,
|
||||
long& nIdent);
|
||||
static CBotTypResult CompileCall(const std::list<CBotFunction*>& localFunctionList,
|
||||
const std::string &name, CBotVar** ppVars, long &nIdent);
|
||||
|
||||
/*!
|
||||
* \brief FindLocalOrPublic Is a function according to its unique identifier
|
||||
* if the identifier is not found, looking by name and parameters.
|
||||
* \param nIdent
|
||||
* \param name
|
||||
* \param ppVars
|
||||
* \param TypeOrError
|
||||
* \param bPublic
|
||||
* \return
|
||||
* \brief Finds a local or public function
|
||||
*
|
||||
* <p>Finds a local or (if bPublic is true) public function to call
|
||||
*
|
||||
* <p>First, it looks for a function according to its unique identifier.<br>
|
||||
* If the identifier is not found, looks by name and parameters.
|
||||
*
|
||||
* \param localFunctionList Linked list of local functions to search in, can be null
|
||||
* \param nIdent[in, out] Unique identifier of the function
|
||||
* \param name Name of the function
|
||||
* \param ppVars List of function arguments
|
||||
* \param TypeOrError Type returned by the function or error code
|
||||
* \param bPublic Whether to look in public functions or not
|
||||
* \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code)
|
||||
*/
|
||||
CBotFunction* FindLocalOrPublic(long& nIdent, const std::string& name,
|
||||
CBotVar** ppVars,
|
||||
CBotTypResult& TypeOrError,
|
||||
bool bPublic = true);
|
||||
static CBotFunction* FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||
CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic = true);
|
||||
|
||||
/*!
|
||||
* \brief DoCall Fait un appel à une fonction.
|
||||
* \param program
|
||||
* \param localFunctionList
|
||||
* \param nIdent
|
||||
* \param name
|
||||
* \param ppVars
|
||||
|
@ -133,27 +146,24 @@ public:
|
|||
* \return
|
||||
*/
|
||||
|
||||
int DoCall(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar** ppVars,
|
||||
CBotStack* pStack,
|
||||
CBotToken* pToken);
|
||||
static int DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken);
|
||||
|
||||
/*!
|
||||
* \brief RestoreCall
|
||||
* \param localFunctionList
|
||||
* \param nIdent
|
||||
* \param name
|
||||
* \param ppVars
|
||||
* \param pStack
|
||||
*/
|
||||
void RestoreCall(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar** ppVars,
|
||||
CBotStack* pStack);
|
||||
static void RestoreCall(const std::list<CBotFunction*>& localFunctionList,
|
||||
long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack);
|
||||
|
||||
/*!
|
||||
* \brief DoCall Makes call of a method note: this is already on the stack,
|
||||
* the pointer pThis is just to simplify.
|
||||
* \brief DoCall Makes call of a method
|
||||
* note: this is already on the stack, the pointer pThis is just to simplify.
|
||||
* \param localFunctionList
|
||||
* \param nIdent
|
||||
* \param name
|
||||
* \param pThis
|
||||
|
@ -163,16 +173,12 @@ public:
|
|||
* \param pClass
|
||||
* \return
|
||||
*/
|
||||
int DoCall(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppVars,
|
||||
CBotStack* pStack,
|
||||
CBotToken* pToken,
|
||||
CBotClass* pClass);
|
||||
static int DoCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
||||
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass);
|
||||
|
||||
/*!
|
||||
* \brief RestoreCall
|
||||
* \param localFunctionList
|
||||
* \param nIdent
|
||||
* \param name
|
||||
* \param pThis
|
||||
|
@ -181,12 +187,8 @@ public:
|
|||
* \param pClass
|
||||
* \return Returns true if the method call was restored.
|
||||
*/
|
||||
bool RestoreCall(long& nIdent,
|
||||
const std::string& name,
|
||||
CBotVar* pThis,
|
||||
CBotVar** ppVars,
|
||||
CBotStack* pStack,
|
||||
CBotClass* pClass);
|
||||
static bool RestoreCall(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis,
|
||||
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass);
|
||||
|
||||
/*!
|
||||
* \brief CheckParam See if the "signature" of parameters is identical.
|
||||
|
@ -225,12 +227,6 @@ public:
|
|||
*/
|
||||
bool IsExtern();
|
||||
|
||||
/*!
|
||||
* \brief Next
|
||||
* \return
|
||||
*/
|
||||
CBotFunction* Next();
|
||||
|
||||
/*!
|
||||
* \brief GetPosition
|
||||
* \param start
|
||||
|
@ -243,6 +239,12 @@ public:
|
|||
CBotGet modestart,
|
||||
CBotGet modestop);
|
||||
|
||||
/*!
|
||||
* \brief Check if the function has a return statment that will execute.
|
||||
* \return true if a return statment was found.
|
||||
*/
|
||||
bool HasReturn() override;
|
||||
|
||||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotFunction"; }
|
||||
virtual std::string GetDebugData() override;
|
||||
|
@ -258,7 +260,6 @@ private:
|
|||
CBotDefParam* m_param;
|
||||
//! The instruction block.
|
||||
CBotInstr* m_block;
|
||||
CBotFunction* m_next;
|
||||
//! If returns CBotTypClass.
|
||||
CBotToken m_retToken;
|
||||
//! Complete type of the result.
|
||||
|
|
|
@ -163,6 +163,15 @@ void CBotIf :: RestoreState(CBotStack* &pj, bool bMain)
|
|||
}
|
||||
}
|
||||
|
||||
bool CBotIf::HasReturn()
|
||||
{
|
||||
if (m_block != nullptr && m_blockElse != nullptr)
|
||||
{
|
||||
if (m_block->HasReturn() && m_blockElse->HasReturn()) return true;
|
||||
}
|
||||
return CBotInstr::HasReturn(); // check next block or instruction
|
||||
}
|
||||
|
||||
std::map<std::string, CBotInstr*> CBotIf::GetDebugLinks()
|
||||
{
|
||||
auto links = CBotInstr::GetDebugLinks();
|
||||
|
|
|
@ -56,6 +56,14 @@ public:
|
|||
*/
|
||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||
|
||||
/**
|
||||
* \brief Check 'if' and 'else' for return statements.
|
||||
* Returns true when 'if' and 'else' have return statements,
|
||||
* if not, the next block or instruction is checked.
|
||||
* \return true if a return statement is found.
|
||||
*/
|
||||
bool HasReturn() override;
|
||||
|
||||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotIf"; }
|
||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
||||
|
|
|
@ -359,6 +359,12 @@ CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypRes
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool CBotInstr::HasReturn()
|
||||
{
|
||||
if (m_next != nullptr) return m_next->HasReturn();
|
||||
return false; // end of the list
|
||||
}
|
||||
|
||||
std::map<std::string, CBotInstr*> CBotInstr::GetDebugLinks()
|
||||
{
|
||||
return {
|
||||
|
|
|
@ -281,6 +281,12 @@ public:
|
|||
*/
|
||||
static bool ChkLvl(const std::string& label, int type);
|
||||
|
||||
/**
|
||||
* \brief Check a list of instructions for a return statement.
|
||||
* \return true if a return statement was found.
|
||||
*/
|
||||
virtual bool HasReturn();
|
||||
|
||||
protected:
|
||||
friend class CBotDebug;
|
||||
/**
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace CBot
|
|||
CBotInstrCall::CBotInstrCall()
|
||||
{
|
||||
m_parameters = nullptr;
|
||||
m_exprRetVar = nullptr;
|
||||
m_nFuncIdent = 0;
|
||||
}
|
||||
|
||||
|
@ -43,6 +44,7 @@ CBotInstrCall::CBotInstrCall()
|
|||
CBotInstrCall::~CBotInstrCall()
|
||||
{
|
||||
delete m_parameters;
|
||||
delete m_exprRetVar;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace CBot
|
|||
CBotInstrMethode::CBotInstrMethode()
|
||||
{
|
||||
m_parameters = nullptr;
|
||||
m_exprRetVar = nullptr;
|
||||
m_MethodeIdent = 0;
|
||||
}
|
||||
|
||||
|
@ -43,6 +44,7 @@ CBotInstrMethode::CBotInstrMethode()
|
|||
CBotInstrMethode::~CBotInstrMethode()
|
||||
{
|
||||
delete m_parameters;
|
||||
delete m_exprRetVar;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -67,8 +69,7 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
|
|||
inst->m_thisIdent = var->GetUniqNum();
|
||||
CBotClass* pClass = var->GetClass(); // pointer to the class
|
||||
inst->m_className = pClass->GetName(); // name of the class
|
||||
CBotTypResult r = pClass->CompileMethode(inst->m_methodName, var, ppVars,
|
||||
pStack, inst->m_MethodeIdent);
|
||||
CBotTypResult r = pClass->CompileMethode(pp, var, ppVars, pStack, inst->m_MethodeIdent);
|
||||
delete pStack->TokenStack(); // release parameters on the stack
|
||||
inst->m_typRes = r;
|
||||
|
||||
|
@ -176,18 +177,7 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
|
|||
else
|
||||
pClass = pThis->GetClass();
|
||||
|
||||
CBotVar* pResult = nullptr;
|
||||
if (m_typRes.GetType() > 0) pResult = CBotVar::Create("", m_typRes);
|
||||
if (m_typRes.Eq(CBotTypClass))
|
||||
{
|
||||
pResult->SetClass(m_typRes.GetClass());
|
||||
}
|
||||
CBotVar* pRes = pResult;
|
||||
|
||||
if ( !pClass->ExecuteMethode(m_MethodeIdent, m_methodName,
|
||||
pThis, ppVars,
|
||||
pResult, pile2, GetToken())) return false;
|
||||
if (pRes != pResult) delete pRes;
|
||||
if ( !pClass->ExecuteMethode(m_MethodeIdent, pThis, ppVars, m_typRes, pile2, GetToken())) return false;
|
||||
|
||||
if (m_exprRetVar != nullptr) // .func().member
|
||||
{
|
||||
|
@ -264,8 +254,7 @@ void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
|
|||
|
||||
// CBotVar* pRes = pResult;
|
||||
|
||||
pClass->RestoreMethode(m_MethodeIdent, m_methodName,
|
||||
pThis, ppVars, pile2);
|
||||
pClass->RestoreMethode(m_MethodeIdent, &m_token, pThis, ppVars, pile2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -316,24 +305,12 @@ bool CBotInstrMethode::Execute(CBotStack* &pj)
|
|||
else
|
||||
pClass = pThis->GetClass();
|
||||
|
||||
CBotVar* pResult = nullptr;
|
||||
if (m_typRes.GetType()>0) pResult = CBotVar::Create("", m_typRes);
|
||||
if (m_typRes.Eq(CBotTypClass))
|
||||
{
|
||||
pResult->SetClass(m_typRes.GetClass());
|
||||
}
|
||||
CBotVar* pRes = pResult;
|
||||
|
||||
if ( !pClass->ExecuteMethode(m_MethodeIdent, m_methodName,
|
||||
pThis, ppVars,
|
||||
pResult, pile2, GetToken())) return false; // interupted
|
||||
if ( !pClass->ExecuteMethode(m_MethodeIdent, pThis, ppVars, m_typRes, pile2, GetToken())) return false; // interupted
|
||||
|
||||
// set the new value of this in place of the old variable
|
||||
CBotVar* old = pile1->FindVar(m_token, false);
|
||||
old->Copy(pThis, false);
|
||||
|
||||
if (pRes != pResult) delete pRes;
|
||||
|
||||
return pj->Return(pile2); // release the entire stack
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars);
|
|||
|
||||
* For assignment or compound assignment operations (it's reversed):
|
||||
* see CBotReturn::Compile & CBotExpression::Compile
|
||||
* TypeCompatible( valueType, varType, opType )
|
||||
* TypeCompatible( valueType, varType, opType )
|
||||
* \param type1
|
||||
* \param type2
|
||||
* \param op
|
||||
|
|
|
@ -64,7 +64,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
inst->m_nIdent = var->GetUniqNum();
|
||||
if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
|
||||
{
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, CBotVar::ProtectionLevel::ReadOnly))
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, true))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, p);
|
||||
goto err;
|
||||
|
@ -128,8 +128,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
var = var->GetItem(p->GetString()); // get item correspondent
|
||||
if (var != nullptr)
|
||||
{
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var,
|
||||
CBotVar::ProtectionLevel::ReadOnly))
|
||||
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, true))
|
||||
{
|
||||
pStk->SetError(CBotErrPrivate, pp);
|
||||
goto err;
|
||||
|
|
|
@ -61,6 +61,8 @@ public:
|
|||
*/
|
||||
bool Execute(CBotStack* &pStack, CBotStack* array);
|
||||
|
||||
using CBotInstr::Execute;
|
||||
|
||||
/*!
|
||||
* \brief ExecuteVar Fetch a variable during compilation.
|
||||
* \param pVar
|
||||
|
@ -69,6 +71,8 @@ public:
|
|||
*/
|
||||
bool ExecuteVar(CBotVar* &pVar, CBotCStack* &pile) override;
|
||||
|
||||
using CBotInstr::ExecuteVar;
|
||||
|
||||
/*!
|
||||
* \brief ExecuteVar Fetch the variable at runtume.
|
||||
* \param pVar
|
||||
|
|
|
@ -52,7 +52,7 @@ CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal
|
|||
if (IsOfType(p, ID_SEP)) continue; // empty statement ignored
|
||||
if (p->GetType() == ID_CLBLK) break;
|
||||
|
||||
if (IsOfType(p, 0))
|
||||
if (p->GetType() == TokenTypNone)
|
||||
{
|
||||
pStack->SetError(CBotErrCloseBlock, p->GetStart());
|
||||
delete inst;
|
||||
|
@ -117,6 +117,12 @@ void CBotListInstr::RestoreState(CBotStack* &pj, bool bMain)
|
|||
if (p != nullptr) p->RestoreState(pile, true);
|
||||
}
|
||||
|
||||
bool CBotListInstr::HasReturn()
|
||||
{
|
||||
if (m_instr != nullptr && m_instr->HasReturn()) return true;
|
||||
return CBotInstr::HasReturn(); // check next block or instruction
|
||||
}
|
||||
|
||||
std::map<std::string, CBotInstr*> CBotListInstr::GetDebugLinks()
|
||||
{
|
||||
auto links = CBotInstr::GetDebugLinks();
|
||||
|
|
|
@ -56,6 +56,13 @@ public:
|
|||
*/
|
||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||
|
||||
/**
|
||||
* \brief Check this block of instructions for a return statement.
|
||||
* If not found, the next block or instruction is checked.
|
||||
* \return true if a return statement was found.
|
||||
*/
|
||||
bool HasReturn() override;
|
||||
|
||||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotListInstr"; }
|
||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
||||
|
|
|
@ -36,12 +36,15 @@ namespace CBot
|
|||
CBotNew::CBotNew()
|
||||
{
|
||||
m_parameters = nullptr;
|
||||
m_exprRetVar = nullptr;
|
||||
m_nMethodeIdent = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotNew::~CBotNew()
|
||||
{
|
||||
delete m_parameters;
|
||||
delete m_exprRetVar;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -83,7 +86,7 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
if (!pStk->IsOk()) goto error;
|
||||
|
||||
// constructor exist?
|
||||
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), pVar, ppVars, pStk, inst->m_nMethodeIdent);
|
||||
CBotTypResult r = pClass->CompileMethode(&inst->m_vartoken, pVar, ppVars, pStk, inst->m_nMethodeIdent);
|
||||
delete pStk->TokenStack(); // release extra stack
|
||||
int typ = r.GetType();
|
||||
|
||||
|
@ -197,12 +200,7 @@ bool CBotNew::Execute(CBotStack* &pj)
|
|||
}
|
||||
ppVars[i] = nullptr;
|
||||
|
||||
// create a variable for the result
|
||||
CBotVar* pResult = nullptr; // constructos still void
|
||||
|
||||
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
|
||||
pThis, ppVars,
|
||||
pResult, pile2, GetToken())) return false; // interrupt
|
||||
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pThis, ppVars, CBotTypResult(CBotTypVoid), pile2, &m_vartoken)) return false; // interrupt
|
||||
|
||||
pThis->ConstructorSet(); // indicates that the constructor has been called
|
||||
}
|
||||
|
@ -284,8 +282,7 @@ void CBotNew::RestoreState(CBotStack* &pj, bool bMain)
|
|||
}
|
||||
ppVars[i] = nullptr;
|
||||
|
||||
pClass->RestoreMethode(m_nMethodeIdent, m_vartoken.GetString(), pThis,
|
||||
ppVars, pile2) ; // interrupt here!
|
||||
pClass->RestoreMethode(m_nMethodeIdent, &m_vartoken, pThis, ppVars, pile2); // interrupt here!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,17 +90,16 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
// post incremented or decremented?
|
||||
if (IsOfType(p, ID_INC, ID_DEC))
|
||||
{
|
||||
// recompile the variable for read-only
|
||||
delete inst;
|
||||
p = pvar;
|
||||
inst = CBotExprVar::Compile(p, pStk, true);
|
||||
if (pStk->GetType() >= CBotTypBoolean)
|
||||
{
|
||||
pStk->SetError(CBotErrBadType1, pp);
|
||||
delete inst;
|
||||
return pStack->Return(nullptr, pStk);
|
||||
}
|
||||
|
||||
// recompile the variable for read-only
|
||||
delete inst;
|
||||
p = pvar;
|
||||
inst = CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly);
|
||||
p = p->GetNext();
|
||||
|
||||
CBotPostIncExpr* i = new CBotPostIncExpr();
|
||||
|
@ -115,26 +114,39 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
CBotToken* pp = p;
|
||||
if (IsOfType(p, ID_INC, ID_DEC))
|
||||
{
|
||||
CBotPreIncExpr* i = new CBotPreIncExpr();
|
||||
i->SetToken(pp);
|
||||
|
||||
if (p->GetType() == TokenTypVar)
|
||||
{
|
||||
if (nullptr != (i->m_instr = CBotExprVar::Compile(p, pStk, CBotVar::ProtectionLevel::ReadOnly)))
|
||||
if (nullptr != (inst = CBotExprVar::Compile(p, pStk, true)))
|
||||
{
|
||||
if (pStk->GetType() >= CBotTypBoolean)
|
||||
if (pStk->GetType() < CBotTypBoolean) // a number ?
|
||||
{
|
||||
pStk->SetError(CBotErrBadType1, pp);
|
||||
delete inst;
|
||||
return pStack->Return(nullptr, pStk);
|
||||
CBotPreIncExpr* i = new CBotPreIncExpr();
|
||||
i->SetToken(pp);
|
||||
i->m_instr = inst;
|
||||
return pStack->Return(i, pStk);
|
||||
}
|
||||
return pStack->Return(i, pStk);
|
||||
delete inst;
|
||||
}
|
||||
delete i;
|
||||
return pStack->Return(nullptr, pStk);
|
||||
}
|
||||
pStk->SetError(CBotErrBadType1, pp);
|
||||
return pStack->Return(nullptr, pStk);
|
||||
}
|
||||
|
||||
return CBotParExpr::CompileLitExpr(p, pStack);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack)
|
||||
{
|
||||
CBotCStack* pStk = pStack->TokenStack();
|
||||
|
||||
CBotToken* pp = p;
|
||||
|
||||
// is this a unary operation?
|
||||
CBotInstr* inst = CBotExprUnaire::Compile(p, pStk, true);
|
||||
if (inst != nullptr || !pStk->IsOk())
|
||||
return pStack->Return(inst, pStk);
|
||||
|
||||
// is it a number or DefineNum?
|
||||
if (p->GetType() == TokenTypNum ||
|
||||
p->GetType() == TokenTypDef )
|
||||
|
|
|
@ -54,6 +54,14 @@ public:
|
|||
*/
|
||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
||||
|
||||
/*!
|
||||
* \brief Compile a literal expression ("string", number, true, false, null, nan, new)
|
||||
* \param p[in, out] Pointer to first token of the expression, will be updated to point to first token after the expression
|
||||
* \param pStack Current compilation stack frame
|
||||
* \return The compiled instruction or nullptr on error
|
||||
*/
|
||||
static CBotInstr* CompileLitExpr(CBotToken* &p, CBotCStack* pStack);
|
||||
|
||||
private:
|
||||
CBotParExpr() = delete;
|
||||
CBotParExpr(const CBotParExpr&) = delete;
|
||||
|
|
|
@ -111,6 +111,11 @@ void CBotReturn::RestoreState(CBotStack* &pj, bool bMain)
|
|||
}
|
||||
}
|
||||
|
||||
bool CBotReturn::HasReturn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<std::string, CBotInstr*> CBotReturn::GetDebugLinks()
|
||||
{
|
||||
auto links = CBotInstr::GetDebugLinks();
|
||||
|
|
|
@ -55,6 +55,12 @@ public:
|
|||
*/
|
||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||
|
||||
/*!
|
||||
* \brief Always returns true.
|
||||
* \return true to signal a return statment has been found.
|
||||
*/
|
||||
bool HasReturn() override;
|
||||
|
||||
protected:
|
||||
virtual const std::string GetDebugName() override { return "CBotReturn"; }
|
||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "CBot/stdlib/stdlib.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
||||
|
@ -47,27 +49,30 @@ CBotProgram::CBotProgram(CBotVar* thisVar)
|
|||
CBotProgram::~CBotProgram()
|
||||
{
|
||||
// delete m_classes;
|
||||
if (m_classes != nullptr) m_classes->Purge();
|
||||
m_classes = nullptr;
|
||||
for (CBotClass* c : m_classes)
|
||||
c->Purge();
|
||||
m_classes.clear();
|
||||
|
||||
CBotClass::FreeLock(this);
|
||||
|
||||
delete m_functions;
|
||||
if (m_stack != nullptr) m_stack->Delete();
|
||||
for (CBotFunction* f : m_functions) delete f;
|
||||
m_functions.clear();
|
||||
}
|
||||
|
||||
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& functions, void* pUser)
|
||||
bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& externFunctions, void* pUser)
|
||||
{
|
||||
// Cleanup the previously compiled program
|
||||
Stop();
|
||||
|
||||
// delete m_classes;
|
||||
if (m_classes != nullptr) m_classes->Purge(); // purge the old definitions of classes
|
||||
// but without destroying the object
|
||||
m_classes = nullptr;
|
||||
delete m_functions; m_functions = nullptr;
|
||||
for (CBotClass* c : m_classes)
|
||||
c->Purge(); // purge the old definitions of classes
|
||||
// but without destroying the object
|
||||
|
||||
functions.clear();
|
||||
m_classes.clear();
|
||||
for (CBotFunction* f : m_functions) delete f;
|
||||
m_functions.clear();
|
||||
|
||||
externFunctions.clear();
|
||||
m_error = CBotNoErr;
|
||||
|
||||
// Step 1. Process the code into tokens
|
||||
|
@ -88,15 +93,15 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
|||
if ( p->GetType() == ID_CLASS ||
|
||||
( p->GetType() == ID_PUBLIC && p->GetNext()->GetType() == ID_CLASS ))
|
||||
{
|
||||
CBotClass* nxt = CBotClass::Compile1(p, pStack.get());
|
||||
if (m_classes == nullptr ) m_classes = nxt;
|
||||
else m_classes->AddNext(nxt);
|
||||
CBotClass* newclass = CBotClass::Compile1(p, pStack.get());
|
||||
if (newclass != nullptr)
|
||||
m_classes.push_back(newclass);
|
||||
}
|
||||
else
|
||||
{
|
||||
CBotFunction* next = CBotFunction::Compile1(p, pStack.get(), nullptr);
|
||||
if (m_functions == nullptr ) m_functions = next;
|
||||
else m_functions->AddNext(next);
|
||||
CBotFunction* newfunc = CBotFunction::Compile1(p, pStack.get(), nullptr);
|
||||
if (newfunc != nullptr)
|
||||
m_functions.push_back(newfunc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,17 +111,14 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
|||
if ( !pStack->IsOk() )
|
||||
{
|
||||
m_error = pStack->GetError(m_errorStart, m_errorEnd);
|
||||
delete m_functions;
|
||||
m_functions = nullptr;
|
||||
for (CBotFunction* f : m_functions) delete f;
|
||||
m_functions.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3. Real compilation
|
||||
// CBotFunction* temp = nullptr;
|
||||
CBotFunction* next = m_functions; // rewind the list
|
||||
|
||||
std::list<CBotFunction*>::iterator next = m_functions.begin();
|
||||
p = tokens.get()->GetNext(); // returns to the beginning
|
||||
|
||||
while ( pStack->IsOk() && p != nullptr && p->GetType() != 0 )
|
||||
{
|
||||
if ( IsOfType(p, ID_SEP) ) continue; // semicolons lurking
|
||||
|
@ -128,43 +130,35 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>&
|
|||
}
|
||||
else
|
||||
{
|
||||
CBotFunction::Compile(p, pStack.get(), next);
|
||||
if (next->IsExtern()) functions.push_back(next->GetName()/* + next->GetParams()*/);
|
||||
if (next->IsPublic()) CBotFunction::AddPublic(next);
|
||||
next->m_pProg = this; // keeps pointers to the module
|
||||
next = next->Next();
|
||||
CBotFunction::Compile(p, pStack.get(), *next);
|
||||
if ((*next)->IsExtern()) externFunctions.push_back((*next)->GetName()/* + next->GetParams()*/);
|
||||
if ((*next)->IsPublic()) CBotFunction::AddPublic(*next);
|
||||
(*next)->m_pProg = this; // keeps pointers to the module
|
||||
++next;
|
||||
}
|
||||
}
|
||||
|
||||
// delete m_Prog; // the list of first pass
|
||||
// m_Prog = temp; // list of the second pass
|
||||
|
||||
if ( !pStack->IsOk() )
|
||||
{
|
||||
m_error = pStack->GetError(m_errorStart, m_errorEnd);
|
||||
delete m_functions;
|
||||
m_functions = nullptr;
|
||||
for (CBotFunction* f : m_functions) delete f;
|
||||
m_functions.clear();
|
||||
}
|
||||
|
||||
return (m_functions != nullptr);
|
||||
return !m_functions.empty();
|
||||
}
|
||||
|
||||
bool CBotProgram::Start(const std::string& name)
|
||||
{
|
||||
Stop();
|
||||
|
||||
m_entryPoint = m_functions;
|
||||
while (m_entryPoint != nullptr)
|
||||
{
|
||||
if (m_entryPoint->GetName() == name ) break;
|
||||
m_entryPoint = m_entryPoint->m_next;
|
||||
}
|
||||
|
||||
if (m_entryPoint == nullptr)
|
||||
auto it = std::find_if(m_functions.begin(), m_functions.end(), [&name](CBotFunction* x) { return x->GetName() == name; });
|
||||
if (it == m_functions.end())
|
||||
{
|
||||
m_error = CBotErrNoRun;
|
||||
return false;
|
||||
}
|
||||
m_entryPoint = *it;
|
||||
|
||||
m_stack = CBotStack::AllocateStack();
|
||||
m_stack->SetProgram(this);
|
||||
|
@ -174,16 +168,10 @@ bool CBotProgram::Start(const std::string& name)
|
|||
|
||||
bool CBotProgram::GetPosition(const std::string& name, int& start, int& stop, CBotGet modestart, CBotGet modestop)
|
||||
{
|
||||
CBotFunction* p = m_functions;
|
||||
while (p != nullptr)
|
||||
{
|
||||
if ( p->GetName() == name ) break;
|
||||
p = p->m_next;
|
||||
}
|
||||
auto it = std::find_if(m_functions.begin(), m_functions.end(), [&name](CBotFunction* x) { return x->GetName() == name; });
|
||||
if (it == m_functions.end()) return false;
|
||||
|
||||
if ( p == nullptr ) return false;
|
||||
|
||||
p->GetPosition(start, stop, modestart, modestop);
|
||||
(*it)->GetPosition(start, stop, modestart, modestop);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -212,16 +200,16 @@ bool CBotProgram::Run(void* pUser, int timer)
|
|||
}
|
||||
|
||||
// completed on a mistake?
|
||||
if (!ok && !m_stack->IsOk())
|
||||
if (ok || !m_stack->IsOk())
|
||||
{
|
||||
m_error = m_stack->GetError(m_errorStart, m_errorEnd);
|
||||
m_stack->Delete();
|
||||
m_stack = nullptr;
|
||||
CBotClass::FreeLock(this);
|
||||
m_entryPoint = nullptr;
|
||||
return true; // execution is finished!
|
||||
}
|
||||
|
||||
if ( ok ) m_entryPoint = nullptr; // more function in execution
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -288,11 +276,21 @@ bool CBotProgram::GetError(CBotError& code, int& start, int& end, CBotProgram*&
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotFunction* CBotProgram::GetFunctions()
|
||||
const std::list<CBotFunction*>& CBotProgram::GetFunctions()
|
||||
{
|
||||
return m_functions;
|
||||
}
|
||||
|
||||
bool CBotProgram::ClassExists(std::string name)
|
||||
{
|
||||
for (CBotClass* p : m_classes)
|
||||
{
|
||||
if ( p->GetName() == name ) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotTypResult cSizeOf( CBotVar* &pVar, void* pUser )
|
||||
{
|
||||
|
@ -304,7 +302,7 @@ CBotTypResult cSizeOf( CBotVar* &pVar, void* pUser )
|
|||
|
||||
bool rSizeOf( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
|
||||
{
|
||||
if ( pVar == nullptr ) return CBotErrLowParam;
|
||||
if ( pVar == nullptr ) { ex = CBotErrLowParam; return true; }
|
||||
|
||||
int i = 0;
|
||||
pVar = pVar->GetItemList();
|
||||
|
@ -375,8 +373,7 @@ bool CBotProgram::RestoreState(FILE* pf)
|
|||
}
|
||||
|
||||
// retrieves the stack from the memory
|
||||
// uses a nullptr pointer (m_stack) but it's ok like that
|
||||
// TODO: no it's not okay like that! but it looks like it doesn't get optimized out at least ~krzys_h
|
||||
m_stack = CBotStack::AllocateStack();
|
||||
if (!m_stack->RestoreState(pf, m_stack)) return false;
|
||||
m_stack->SetProgram(this); // bases for routines
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "CBot/CBotEnums.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
@ -124,12 +125,12 @@ public:
|
|||
* 3. Second pass - compiling definitions of all functions and classes
|
||||
*
|
||||
* \param program Code to compile
|
||||
* \param[out] functions Returns the names of functions declared as extern
|
||||
* \param[out] externFunctions Returns the names of functions declared as extern
|
||||
* \param pUser Optional pointer to be passed to compile function (see AddFunction())
|
||||
* \return true if compilation is successful, false if an compilation error occurs
|
||||
* \see GetError() to retrieve the error
|
||||
*/
|
||||
bool Compile(const std::string& program, std::vector<std::string>& functions, void* pUser = nullptr);
|
||||
bool Compile(const std::string& program, std::vector<std::string>& externFunctions, void* pUser = nullptr);
|
||||
|
||||
/**
|
||||
* \brief Returns the last error
|
||||
|
@ -328,9 +329,15 @@ public:
|
|||
*
|
||||
* This list includes all the functions (not only extern)
|
||||
*
|
||||
* \return Linked list of CBotFunction instances
|
||||
* \return List of CBotFunction instances
|
||||
*/
|
||||
CBotFunction* GetFunctions();
|
||||
const std::list<CBotFunction*>& GetFunctions();
|
||||
|
||||
/**
|
||||
* \brief Check if class with that name was created in this program
|
||||
* \return True if class was defined in this program, otherwise, false
|
||||
*/
|
||||
bool ClassExists(std::string name);
|
||||
|
||||
/**
|
||||
* \brief Returns static list of all registered external calls
|
||||
|
@ -341,11 +348,11 @@ private:
|
|||
//! All external calls
|
||||
static CBotExternalCallList* m_externalCalls;
|
||||
//! All user-defined functions
|
||||
CBotFunction* m_functions = nullptr;
|
||||
std::list<CBotFunction*> m_functions{};
|
||||
//! The entry point function
|
||||
CBotFunction* m_entryPoint = nullptr;
|
||||
//! Classes defined in this program
|
||||
CBotClass* m_classes = nullptr;
|
||||
std::list<CBotClass*> m_classes{};
|
||||
//! Execution stack
|
||||
CBotStack* m_stack = nullptr;
|
||||
//! "this" variable
|
||||
|
|
|
@ -82,8 +82,6 @@ CBotStack* CBotStack::AllocateStack()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CBotStack::Delete()
|
||||
{
|
||||
assert ( this != nullptr );
|
||||
|
||||
if (m_next != nullptr) m_next->Delete();
|
||||
if (m_next2 != nullptr) m_next2->Delete();
|
||||
|
||||
|
@ -192,8 +190,18 @@ bool CBotStack::Return(CBotStack* pfils)
|
|||
m_var = pfils->m_var; // result transmitted
|
||||
pfils->m_var = nullptr; // not to destroy the variable
|
||||
|
||||
if (m_next != nullptr) m_next->Delete();m_next = nullptr; // releases the stack above
|
||||
if (m_next2 != nullptr) m_next2->Delete();m_next2 = nullptr; // also the second stack (catch)
|
||||
if (m_next != nullptr)
|
||||
{
|
||||
// releases the stack above
|
||||
m_next->Delete();
|
||||
m_next = nullptr;
|
||||
}
|
||||
if (m_next2 != nullptr)
|
||||
{
|
||||
// also the second stack (catch)
|
||||
m_next2->Delete();
|
||||
m_next2 = nullptr;
|
||||
}
|
||||
|
||||
return IsOk(); // interrupted if error
|
||||
}
|
||||
|
@ -260,7 +268,7 @@ bool CBotStack::IfStep()
|
|||
bool CBotStack::BreakReturn(CBotStack* pfils, const std::string& name)
|
||||
{
|
||||
if ( m_error>=0 ) return false; // normal output
|
||||
if ( m_error==-3 ) return false; // normal output (return current)
|
||||
if ( m_error==CBotError(-3) ) return false; // normal output (return current)
|
||||
|
||||
if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name))
|
||||
return false; // it's not for me
|
||||
|
@ -273,7 +281,7 @@ bool CBotStack::BreakReturn(CBotStack* pfils, const std::string& name)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotStack::IfContinue(int state, const std::string& name)
|
||||
{
|
||||
if ( m_error != -2 ) return false;
|
||||
if ( m_error != CBotError(-2) ) return false;
|
||||
|
||||
if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name))
|
||||
return false; // it's not for me
|
||||
|
@ -301,7 +309,7 @@ void CBotStack::SetBreak(int val, const std::string& name)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotStack::GetRetVar(bool bRet)
|
||||
{
|
||||
if (m_error == -3)
|
||||
if (m_error == CBotError(-3))
|
||||
{
|
||||
if ( m_var ) delete m_var;
|
||||
m_var = m_retvar;
|
||||
|
@ -568,7 +576,7 @@ bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, con
|
|||
res = m_prog->GetExternalCalls()->DoCall(nullptr, nullptr, ppVar, this, rettype);
|
||||
if (res >= 0) return res;
|
||||
|
||||
res = m_prog->GetFunctions()->DoCall(nIdent, "", ppVar, this, token );
|
||||
res = CBotFunction::DoCall(m_prog, m_prog->GetFunctions(), nIdent, "", ppVar, this, token);
|
||||
if (res >= 0) return res;
|
||||
|
||||
// if not found (recompile?) seeks by name
|
||||
|
@ -577,7 +585,7 @@ bool CBotStack::ExecuteCall(long& nIdent, CBotToken* token, CBotVar** ppVar, con
|
|||
res = m_prog->GetExternalCalls()->DoCall(token, nullptr, ppVar, this, rettype);
|
||||
if (res >= 0) return res;
|
||||
|
||||
res = m_prog->GetFunctions()->DoCall(nIdent, token->GetString(), ppVar, this, token );
|
||||
res = CBotFunction::DoCall(m_prog, m_prog->GetFunctions(), nIdent, token->GetString(), ppVar, this, token);
|
||||
if (res >= 0) return res;
|
||||
|
||||
SetError(CBotErrUndefFunc, token);
|
||||
|
@ -592,7 +600,7 @@ void CBotStack::RestoreCall(long& nIdent, CBotToken* token, CBotVar** ppVar)
|
|||
if (m_prog->GetExternalCalls()->RestoreCall(token, nullptr, ppVar, this))
|
||||
return;
|
||||
|
||||
m_prog->GetFunctions()->RestoreCall(nIdent, token->GetString(), ppVar, this);
|
||||
CBotFunction::RestoreCall(m_prog->GetFunctions(), nIdent, token->GetString(), ppVar, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -727,12 +735,11 @@ bool CBotStack::RestoreState(FILE* pf, CBotStack* &pStack)
|
|||
{
|
||||
unsigned short w;
|
||||
|
||||
pStack = nullptr;
|
||||
if (pStack != this) pStack = nullptr;
|
||||
if (!ReadWord(pf, w)) return false;
|
||||
if ( w == 0 ) return true; // 0 - terminator
|
||||
|
||||
if ( this == nullptr ) pStack = AllocateStack();
|
||||
else pStack = AddStack();
|
||||
if (pStack == nullptr) pStack = AddStack();
|
||||
|
||||
if ( w == 2 ) // 2 - m_next2
|
||||
{
|
||||
|
|
|
@ -199,7 +199,6 @@ const CBotToken& CBotToken::operator=(const CBotToken& src)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotToken::GetType()
|
||||
{
|
||||
if (this == nullptr) return 0;
|
||||
if (m_type == TokenTypKeyWord) return m_keywordId;
|
||||
return m_type;
|
||||
}
|
||||
|
@ -225,14 +224,12 @@ void CBotToken::SetString(const std::string& name)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotToken::GetStart()
|
||||
{
|
||||
if (this == nullptr) return -1;
|
||||
return m_start;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CBotToken::GetEnd()
|
||||
{
|
||||
if (this == nullptr) return -1;
|
||||
return m_end;
|
||||
}
|
||||
|
||||
|
@ -439,6 +436,13 @@ std::unique_ptr<CBotToken> CBotToken::CompileTokens(const std::string& program)
|
|||
pp = p;
|
||||
}
|
||||
|
||||
// terminator token
|
||||
nxt = new CBotToken();
|
||||
nxt->m_type = TokenTypNone;
|
||||
nxt->m_end = nxt->m_start = pos;
|
||||
prv->m_next = nxt;
|
||||
nxt->m_prev = prv;
|
||||
|
||||
return std::unique_ptr<CBotToken>(tokenbase);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,11 +167,16 @@ CBotTypResult& CBotTypResult::operator=(const CBotTypResult& src)
|
|||
m_type = src.m_type;
|
||||
m_limite = src.m_limite;
|
||||
m_class = src.m_class;
|
||||
m_next = nullptr;
|
||||
if (src.m_next != nullptr )
|
||||
{
|
||||
delete m_next;
|
||||
m_next = new CBotTypResult(*src.m_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_next;
|
||||
m_next = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "CBot/CBotStack.h"
|
||||
|
||||
#include "CBot/CBotInstr/CBotInstr.h"
|
||||
#include "CBot/CBotVar/CBotVarArray.h"
|
||||
#include "CBot/CBotVar/CBotVarPointer.h"
|
||||
#include "CBot/CBotVar/CBotVarClass.h"
|
||||
|
@ -70,6 +71,8 @@ CBotVar::CBotVar(const CBotToken &name) : CBotVar()
|
|||
CBotVar::~CBotVar( )
|
||||
{
|
||||
delete m_token;
|
||||
delete m_InitExpr;
|
||||
delete m_LimExpr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -394,12 +394,13 @@ void CBotVarClass::DecrementUse()
|
|||
|
||||
CBotVar* pThis = CBotVar::Create("this", CBotTypNullPointer);
|
||||
pThis->SetPointer(this);
|
||||
CBotVar* pResult = nullptr;
|
||||
|
||||
std::string nom = std::string("~") + m_pClass->GetName();
|
||||
long ident = 0;
|
||||
|
||||
while ( pile->IsOk() && !m_pClass->ExecuteMethode(ident, nom, pThis, ppVars, pResult, pile, nullptr)) ; // waits for the end
|
||||
CBotToken token(nom); // TODO
|
||||
|
||||
while ( pile->IsOk() && !m_pClass->ExecuteMethode(ident, pThis, ppVars, CBotTypResult(CBotTypVoid), pile, &token)) ; // waits for the end
|
||||
|
||||
pile->ResetError(err, start,end);
|
||||
|
||||
|
|
|
@ -48,12 +48,12 @@ public:
|
|||
SetValString(ToString(val));
|
||||
}
|
||||
|
||||
int GetValInt()
|
||||
int GetValInt() override
|
||||
{
|
||||
return FromString<int>(GetValString());
|
||||
}
|
||||
|
||||
float GetValFloat()
|
||||
float GetValFloat() override
|
||||
{
|
||||
return FromString<float>(GetValString());
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ set(SOURCES
|
|||
CBot.h
|
||||
CBotCStack.cpp
|
||||
CBotCStack.h
|
||||
CBotCallMethode.cpp
|
||||
CBotCallMethode.h
|
||||
CBotClass.cpp
|
||||
CBotClass.h
|
||||
CBotDebug.cpp
|
||||
|
|
|
@ -38,7 +38,7 @@ int g_nextFileId = 1;
|
|||
|
||||
bool FileClassOpenFile(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
|
||||
{
|
||||
std::string mode;
|
||||
CBotFileAccessHandler::OpenMode openMode = CBotFileAccessHandler::OpenMode::Read;
|
||||
|
||||
// must be a character string
|
||||
if ( pVar->GetType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
|
||||
|
@ -50,8 +50,11 @@ bool FileClassOpenFile(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exc
|
|||
if ( pVar != nullptr )
|
||||
{
|
||||
// recover mode
|
||||
mode = pVar->GetValString();
|
||||
if ( mode != "r" && mode != "w" && mode != "a" ) { Exception = CBotErrBadParam; return false; }
|
||||
std::string mode = pVar->GetValString();
|
||||
if ( mode == "r" ) openMode = CBotFileAccessHandler::OpenMode::Read;
|
||||
else if ( mode == "w" ) openMode = CBotFileAccessHandler::OpenMode::Write;
|
||||
else if ( mode == "a" ) openMode = CBotFileAccessHandler::OpenMode::Append;
|
||||
else { Exception = CBotErrBadParam; return false; }
|
||||
|
||||
// no third parameter
|
||||
if ( pVar->GetNext() != nullptr ) { Exception = CBotErrOverParam; return false; }
|
||||
|
@ -66,27 +69,20 @@ bool FileClassOpenFile(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exc
|
|||
// which must not be initialized
|
||||
if ( pVar->IsDefined()) { Exception = CBotErrFileOpen; return false; }
|
||||
|
||||
if ( !mode.empty() )
|
||||
{
|
||||
// opens the requested file
|
||||
assert(g_fileHandler != nullptr);
|
||||
// opens the requested file
|
||||
assert(g_fileHandler != nullptr);
|
||||
|
||||
CBotFileAccessHandler::OpenMode openMode;
|
||||
if ( mode == "r" ) openMode = CBotFileAccessHandler::OpenMode::Read;
|
||||
else if ( mode == "w" ) openMode = CBotFileAccessHandler::OpenMode::Write;
|
||||
else if ( mode == "a" ) openMode = CBotFileAccessHandler::OpenMode::Append;
|
||||
std::unique_ptr<CBotFile> file = g_fileHandler->OpenFile(filename, openMode);
|
||||
|
||||
std::unique_ptr<CBotFile> file = g_fileHandler->OpenFile(filename, openMode);
|
||||
if (!file->Opened()) { Exception = CBotErrFileOpen; return false; }
|
||||
|
||||
if (!file->Opened()) { Exception = CBotErrFileOpen; return false; }
|
||||
int fileHandle = g_nextFileId++;
|
||||
g_files[fileHandle] = std::move(file);
|
||||
|
||||
int fileHandle = g_nextFileId++;
|
||||
g_files[fileHandle] = std::move(file);
|
||||
// save the file handle
|
||||
pVar = pThis->GetItem("handle");
|
||||
pVar->SetValInt(fileHandle);
|
||||
|
||||
// save the file handle
|
||||
pVar = pThis->GetItem("handle");
|
||||
pVar->SetValInt(fileHandle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -225,8 +225,14 @@ bool rStrFind( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
|
|||
|
||||
// puts the result on the stack
|
||||
std::size_t res = s.find(s2);
|
||||
pResult->SetValInt( res != std::string::npos ? res : -1 );
|
||||
if ( res < 0 ) pResult->SetInit( CBotVar::InitType::IS_NAN );
|
||||
if (res != std::string::npos)
|
||||
{
|
||||
pResult->SetValInt(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
pResult->SetInit(CBotVar::InitType::IS_NAN);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,8 @@ set(BASE_SOURCES
|
|||
graphics/core/nulldevice.cpp
|
||||
graphics/core/nulldevice.h
|
||||
graphics/core/texture.h
|
||||
graphics/core/type.cpp
|
||||
graphics/core/type.h
|
||||
graphics/core/vertex.h
|
||||
graphics/engine/camera.cpp
|
||||
graphics/engine/camera.h
|
||||
|
@ -239,10 +241,14 @@ set(BASE_SOURCES
|
|||
level/robotmain.h
|
||||
level/scene_conditions.cpp
|
||||
level/scene_conditions.h
|
||||
level/scoreboard.cpp
|
||||
level/scoreboard.h
|
||||
math/all.h
|
||||
math/const.h
|
||||
math/func.h
|
||||
math/geometry.h
|
||||
math/half.cpp
|
||||
math/half.h
|
||||
math/intpoint.h
|
||||
math/matrix.h
|
||||
math/point.h
|
||||
|
|
|
@ -674,7 +674,8 @@ bool CApplication::Create()
|
|||
// Create the robot application.
|
||||
m_controller = MakeUnique<CController>();
|
||||
|
||||
CThread musicLoadThread([this]() {
|
||||
CThread musicLoadThread([this]()
|
||||
{
|
||||
GetLogger()->Debug("Cache sounds...\n");
|
||||
SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp();
|
||||
m_systemUtils->GetCurrentTimeStamp(musicLoadStart);
|
||||
|
@ -685,7 +686,8 @@ bool CApplication::Create()
|
|||
m_systemUtils->GetCurrentTimeStamp(musicLoadEnd);
|
||||
float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC);
|
||||
GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime);
|
||||
}, "Sound loading thread");
|
||||
},
|
||||
"Sound loading thread");
|
||||
musicLoadThread.Start();
|
||||
|
||||
if (m_runSceneCategory == LevelCategory::Max)
|
||||
|
@ -1852,9 +1854,10 @@ bool CApplication::GetSceneTestMode()
|
|||
return m_sceneTest;
|
||||
}
|
||||
|
||||
void CApplication::SetTextInput(bool textInputEnabled)
|
||||
void CApplication::SetTextInput(bool textInputEnabled, int id)
|
||||
{
|
||||
if (textInputEnabled)
|
||||
m_textInputEnabled[id] = textInputEnabled;
|
||||
if (std::any_of(m_textInputEnabled.begin(), m_textInputEnabled.end(), [](std::pair<int, bool> v) { return v.second; }))
|
||||
{
|
||||
SDL_StartTextInput();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
||||
class CEventQueue;
|
||||
|
@ -245,7 +246,7 @@ public:
|
|||
|
||||
//! Enable/disable text input, this toggles the on-screen keyboard on some platforms
|
||||
/** This also allows for writing in CJK languages (not tested!), see https://wiki.libsdl.org/Tutorials/TextInput for detailed explanation */
|
||||
void SetTextInput(bool textInputEnabled);
|
||||
void SetTextInput(bool textInputEnabled, int id);
|
||||
|
||||
//! Moves (warps) the mouse cursor to the specified position (in interface coords)
|
||||
void MoveMouse(Math::Point pos);
|
||||
|
@ -403,4 +404,6 @@ protected:
|
|||
|
||||
//! Static buffer for putenv locale
|
||||
static char m_languageLocale[50];
|
||||
|
||||
std::map<int, bool> m_textInputEnabled;
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ void CSignalHandlers::Init(CSystemUtils* systemUtils)
|
|||
|
||||
void CSignalHandlers::SignalHandler(int sig)
|
||||
{
|
||||
std::string signalStr = StrUtils::ToString(signal);
|
||||
std::string signalStr = StrUtils::ToString(sig);
|
||||
switch(sig)
|
||||
{
|
||||
case SIGSEGV: signalStr = "SIGSEGV, segmentation fault"; break;
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* \file common/error.h
|
||||
* \brief Definition of the Error enum
|
||||
*/
|
||||
|
||||
/**
|
||||
* \enum Error
|
||||
|
@ -26,87 +30,88 @@
|
|||
*/
|
||||
enum Error
|
||||
{
|
||||
ERR_OK = 0, //! < ok
|
||||
ERR_UNKNOWN = 1, //! < any error
|
||||
ERR_CONTINUE = 2, //! < continues
|
||||
ERR_STOP = 3, //! < stops
|
||||
ERR_CMD = 4, //! < unknown command
|
||||
ERR_MANIP_FLY = 101, //! < impossible in flight
|
||||
ERR_MANIP_BUSY = 102, //! < taking: hands already occupied
|
||||
ERR_MANIP_NIL = 103, //! < taking: nothing has to take
|
||||
ERR_MANIP_MOTOR = 105, //! < busy: impossible to move
|
||||
ERR_MANIP_OCC = 106, //! < busy: location already occupied
|
||||
ERR_MANIP_RADIO = 108, //! < impossible because radioactive
|
||||
ERR_MANIP_WATER = 109, //! < not possible under water
|
||||
ERR_MANIP_EMPTY = 110, //! < nothing to deposit
|
||||
ERR_BUILD_FLY = 120, //! < not possible in flight
|
||||
ERR_BUILD_WATER = 121, //! < not possible under water
|
||||
ERR_BUILD_METALAWAY = 123, //! < lack of metal (too far)
|
||||
ERR_BUILD_METALNEAR = 124, //! < lack of metal (too close)
|
||||
ERR_BUILD_METALINEX = 125, //! < lack of metal
|
||||
ERR_BUILD_FLAT = 126, //! < not enough flat ground
|
||||
ERR_BUILD_FLATLIT = 127, //! < not enough flat ground space
|
||||
ERR_BUILD_BUSY = 128, //! < location occupied
|
||||
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_MOTOR = 142, //! < impossible in movement
|
||||
ERR_TERRA_ENERGY = 151, //! < not enough energy
|
||||
ERR_FIRE_ENERGY = 161, //! < not enough energy
|
||||
ERR_RECOVER_ENERGY = 171, //! < not enough energy
|
||||
ERR_RECOVER_NULL = 172, //! < lack of ruin
|
||||
ERR_CONVERT_EMPTY = 180, //! < no stone was transformed
|
||||
ERR_SHIELD_ENERGY = 191, //! < not enough energy
|
||||
ERR_MOVE_IMPOSSIBLE = 200, //! < move impossible
|
||||
ERR_GOTO_IMPOSSIBLE = 210, //! < goto impossible
|
||||
ERR_GOTO_ITER = 211, //! < goto too complicated
|
||||
ERR_GOTO_BUSY = 212, //! < goto destination occupied
|
||||
ERR_DERRICK_NULL = 300, //! < no ore underground
|
||||
ERR_STATION_NULL = 301, //! < no energy underground
|
||||
ERR_TOWER_POWER = 310, //! < no battery
|
||||
ERR_TOWER_ENERGY = 311, //! < more energy
|
||||
ERR_RESEARCH_POWER = 320, //! < no battery
|
||||
ERR_RESEARCH_ENERGY = 321, //! < more energy
|
||||
ERR_RESEARCH_TYPE = 322, //! < the wrong type of battery
|
||||
ERR_RESEARCH_ALREADY = 323, //! < research already done
|
||||
ERR_ENERGY_NULL = 330, //! < no energy underground
|
||||
ERR_ENERGY_LOW = 331, //! < not enough energy
|
||||
ERR_ENERGY_EMPTY = 332, //! < lack of metal
|
||||
ERR_ENERGY_BAD = 333, //! < transforms only the metal
|
||||
ERR_BASE_DLOCK = 340, //! < doors locked
|
||||
ERR_BASE_DHUMAN = 341, //! < you must be on spaceship
|
||||
ERR_LABO_NULL = 350, //! < nothing to analyze
|
||||
ERR_LABO_BAD = 351, //! < analyzes only organic ball
|
||||
ERR_LABO_ALREADY = 352, //! < analysis already made
|
||||
ERR_NUCLEAR_EMPTY = 362, //! < lack of uranium
|
||||
ERR_NUCLEAR_BAD = 363, //! < transforms only uranium
|
||||
ERR_FACTORY_NULL = 370, //! < no metal
|
||||
ERR_FACTORY_NEAR = 371, //! < vehicle too close
|
||||
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
|
||||
ERR_FLAG_WATER = 511, //! < impossible during swimming
|
||||
ERR_FLAG_MOTOR = 512, //! < impossible in movement
|
||||
ERR_FLAG_BUSY = 513, //! < taking: already creating flag
|
||||
ERR_FLAG_CREATE = 514, //! < too many flags
|
||||
ERR_FLAG_PROXY = 515, //! < too close
|
||||
ERR_FLAG_DELETE = 516, //! < nothing to remove
|
||||
ERR_MISSION_NOTERM = 600, //! < Mission not completed
|
||||
ERR_DELETEMOBILE = 700, //! < vehicle destroyed
|
||||
ERR_DELETEBUILDING = 701, //! < building destroyed
|
||||
ERR_ENEMY_OBJECT = 703, //! < can't control enemy object
|
||||
ERR_OBLIGATORYTOKEN = 800, //! < compulsory instruction missing
|
||||
ERR_PROHIBITEDTOKEN = 801, //! < instruction prohibited
|
||||
ERR_AIM_IMPOSSIBLE = 900, //! < cannot aim at specified angle(s)
|
||||
ERR_WRONG_BOT = 910, //! < inappropriate bot
|
||||
ERR_OK = 0, //!< ok
|
||||
ERR_UNKNOWN = 1, //!< any error
|
||||
ERR_CONTINUE = 2, //!< continues
|
||||
ERR_STOP = 3, //!< stops
|
||||
ERR_CMD = 4, //!< unknown command
|
||||
ERR_OBJ_BUSY = 5, //!< object is busy
|
||||
ERR_MANIP_FLY = 101, //!< impossible in flight
|
||||
ERR_MANIP_BUSY = 102, //!< taking: hands already occupied
|
||||
ERR_MANIP_NIL = 103, //!< taking: nothing has to take
|
||||
ERR_MANIP_MOTOR = 105, //!< busy: impossible to move
|
||||
ERR_MANIP_OCC = 106, //!< busy: location already occupied
|
||||
ERR_MANIP_RADIO = 108, //!< impossible because radioactive
|
||||
ERR_MANIP_WATER = 109, //!< not possible under water
|
||||
ERR_MANIP_EMPTY = 110, //!< nothing to deposit
|
||||
ERR_BUILD_FLY = 120, //!< not possible in flight
|
||||
ERR_BUILD_WATER = 121, //!< not possible under water
|
||||
ERR_BUILD_METALAWAY = 123, //!< lack of metal (too far)
|
||||
ERR_BUILD_METALNEAR = 124, //!< lack of metal (too close)
|
||||
ERR_BUILD_METALINEX = 125, //!< lack of metal
|
||||
ERR_BUILD_FLAT = 126, //!< not enough flat ground
|
||||
ERR_BUILD_FLATLIT = 127, //!< not enough flat ground space
|
||||
ERR_BUILD_BUSY = 128, //!< location occupied
|
||||
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_MOTOR = 142, //!< impossible in movement
|
||||
ERR_TERRA_ENERGY = 151, //!< not enough energy
|
||||
ERR_FIRE_ENERGY = 161, //!< not enough energy
|
||||
ERR_RECOVER_ENERGY = 171, //!< not enough energy
|
||||
ERR_RECOVER_NULL = 172, //!< lack of ruin
|
||||
ERR_CONVERT_EMPTY = 180, //!< no stone was transformed
|
||||
ERR_SHIELD_ENERGY = 191, //!< not enough energy
|
||||
ERR_MOVE_IMPOSSIBLE = 200, //!< move impossible
|
||||
ERR_GOTO_IMPOSSIBLE = 210, //!< goto impossible
|
||||
ERR_GOTO_ITER = 211, //!< goto too complicated
|
||||
ERR_GOTO_BUSY = 212, //!< goto destination occupied
|
||||
ERR_DERRICK_NULL = 300, //!< no ore underground
|
||||
ERR_STATION_NULL = 301, //!< no energy underground
|
||||
ERR_TOWER_POWER = 310, //!< no battery
|
||||
ERR_TOWER_ENERGY = 311, //!< more energy
|
||||
ERR_RESEARCH_POWER = 320, //!< no battery
|
||||
ERR_RESEARCH_ENERGY = 321, //!< more energy
|
||||
ERR_RESEARCH_TYPE = 322, //!< the wrong type of battery
|
||||
ERR_RESEARCH_ALREADY = 323, //!< research already done
|
||||
ERR_ENERGY_NULL = 330, //!< no energy underground
|
||||
ERR_ENERGY_LOW = 331, //!< not enough energy
|
||||
ERR_ENERGY_EMPTY = 332, //!< lack of metal
|
||||
ERR_ENERGY_BAD = 333, //!< transforms only the metal
|
||||
ERR_BASE_DLOCK = 340, //!< doors locked
|
||||
ERR_BASE_DHUMAN = 341, //!< you must be on spaceship
|
||||
ERR_LABO_NULL = 350, //!< nothing to analyze
|
||||
ERR_LABO_BAD = 351, //!< analyzes only organic ball
|
||||
ERR_LABO_ALREADY = 352, //!< analysis already made
|
||||
ERR_NUCLEAR_EMPTY = 362, //!< lack of uranium
|
||||
ERR_NUCLEAR_BAD = 363, //!< transforms only uranium
|
||||
ERR_FACTORY_NULL = 370, //!< no metal
|
||||
ERR_FACTORY_NEAR = 371, //!< vehicle too close
|
||||
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
|
||||
ERR_FLAG_WATER = 511, //!< impossible during swimming
|
||||
ERR_FLAG_MOTOR = 512, //!< impossible in movement
|
||||
ERR_FLAG_BUSY = 513, //!< taking: already creating flag
|
||||
ERR_FLAG_CREATE = 514, //!< too many flags
|
||||
ERR_FLAG_PROXY = 515, //!< too close
|
||||
ERR_FLAG_DELETE = 516, //!< nothing to remove
|
||||
ERR_MISSION_NOTERM = 600, //!< Mission not completed
|
||||
ERR_DELETEMOBILE = 700, //!< vehicle destroyed
|
||||
ERR_DELETEBUILDING = 701, //!< building destroyed
|
||||
ERR_ENEMY_OBJECT = 703, //!< can't control enemy object
|
||||
ERR_OBLIGATORYTOKEN = 800, //!< compulsory instruction missing
|
||||
ERR_PROHIBITEDTOKEN = 801, //!< instruction prohibited
|
||||
ERR_AIM_IMPOSSIBLE = 900, //!< cannot aim at specified angle(s)
|
||||
ERR_WRONG_BOT = 910, //!< inappropriate bot
|
||||
|
||||
INFO_FIRST = 10000, //! < first information
|
||||
INFO_BUILD = 10001, //! < construction builded
|
||||
|
@ -142,6 +147,9 @@ enum Error
|
|||
INFO_DELETEWORM = 10103, //! < insect killed
|
||||
INFO_DELETESPIDER = 10104, //! < insect killed
|
||||
INFO_BEGINSATCOM = 10105, //! < use your SatCom
|
||||
INFO_TEAM_FINISH = 10110,
|
||||
INFO_TEAM_DEAD = 10111,
|
||||
INFO_TEAM_SCORE = 10112,
|
||||
|
||||
ERR_MAX //! < number of values
|
||||
};
|
||||
|
|
|
@ -172,7 +172,7 @@ enum EventType
|
|||
EVENT_LABEL16 = 106,
|
||||
EVENT_LABEL17 = 107,
|
||||
EVENT_LABEL18 = 108,
|
||||
EVENT_LABEL19 = 109,
|
||||
EVENT_LABEL19 = 109, // cursor position overlay
|
||||
|
||||
EVENT_LIST0 = 110,
|
||||
EVENT_LIST1 = 111,
|
||||
|
@ -187,6 +187,11 @@ enum EventType
|
|||
|
||||
EVENT_LOADING = 120,
|
||||
|
||||
EVENT_LABEL_CODE_BATTLE = 121,
|
||||
|
||||
EVENT_SCOREBOARD = 130,
|
||||
EVENT_SCOREBOARD_MAX = 169,
|
||||
|
||||
EVENT_TOOLTIP = 200,
|
||||
|
||||
EVENT_DIALOG_OK = 300,
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
/** Construct and Open Stream for writing
|
||||
*
|
||||
* \param filename
|
||||
* \param Mode one of: std::ios_base::out - Open for writing, std::ios_base::app - Append to file
|
||||
* \param mode one of: std::ios_base::out - Open for writing, std::ios_base::app - Append to file
|
||||
*
|
||||
*/
|
||||
COutputStream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out);
|
||||
|
@ -48,7 +48,7 @@ public:
|
|||
/** Open Stream for writing
|
||||
*
|
||||
* \param filename
|
||||
* \param Mode one of: std::ios_base::out - Open for writing, std::ios_base::app - Append to file
|
||||
* \param mode one of: std::ios_base::out - Open for writing, std::ios_base::app - Append to file
|
||||
*
|
||||
*/
|
||||
void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out);
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
/** Open Stream Buffer for writing
|
||||
*
|
||||
* \param filename
|
||||
* \param Mode one of: std::ios_base::out - Open for writing, std::ios_base::app - Append to file
|
||||
* \param mode one of: std::ios_base::out - Open for writing, std::ios_base::app - Append to file
|
||||
*
|
||||
*/
|
||||
void open(const std::string &filename, std::ios_base::openmode mode);
|
||||
|
|
|
@ -143,8 +143,14 @@ void InitializeRestext()
|
|||
stringsText[RT_LOADING_TERRAIN_TEX] = TR("Textures");
|
||||
stringsText[RT_LOADING_TERRAIN_GEN] = TR("Generating");
|
||||
|
||||
stringsText[RT_SCOREBOARD_RESULTS] = TR("Results");
|
||||
stringsText[RT_SCOREBOARD_RESULTS_TEXT]= TR("The battle has ended");
|
||||
stringsText[RT_SCOREBOARD_RESULTS_LINE]= TR("%s: %d pts");
|
||||
|
||||
|
||||
|
||||
stringsEvent[EVENT_LABEL_CODE_BATTLE] = TR("Code battle");
|
||||
|
||||
stringsEvent[EVENT_BUTTON_OK] = TR("OK");
|
||||
stringsEvent[EVENT_BUTTON_CANCEL] = TR("Cancel");
|
||||
stringsEvent[EVENT_BUTTON_NEXT] = TR("Next");
|
||||
|
@ -563,6 +569,7 @@ void InitializeRestext()
|
|||
|
||||
stringsErr[ERR_UNKNOWN] = TR("Internal error - tell the developers");
|
||||
stringsErr[ERR_CMD] = TR("Unknown command");
|
||||
stringsErr[ERR_OBJ_BUSY] = TR("This object is currently busy");
|
||||
stringsErr[ERR_MANIP_FLY] = TR("Impossible when flying");
|
||||
stringsErr[ERR_MANIP_BUSY] = TR("Already carrying something");
|
||||
stringsErr[ERR_MANIP_NIL] = TR("Nothing to grab");
|
||||
|
@ -670,6 +677,9 @@ void InitializeRestext()
|
|||
stringsErr[INFO_DELETEWORM] = TR("Worm fatally wounded");
|
||||
stringsErr[INFO_DELETESPIDER] = TR("Spider fatally wounded");
|
||||
stringsErr[INFO_BEGINSATCOM] = TR("Press \\key help; to read instructions on your SatCom");
|
||||
stringsErr[INFO_TEAM_FINISH] = TR("<<< Team %s finished! >>>");
|
||||
stringsErr[INFO_TEAM_DEAD] = TR("<<< Team %s lost! >>>");
|
||||
stringsErr[INFO_TEAM_SCORE] = TR("<<< Team %s recieved %d points >>>");
|
||||
|
||||
|
||||
|
||||
|
@ -718,6 +728,10 @@ void InitializeRestext()
|
|||
stringsCbot[CBot::CBotErrNoPublic] = TR("Public required");
|
||||
stringsCbot[CBot::CBotErrNoExpression] = TR("Expression expected after =");
|
||||
stringsCbot[CBot::CBotErrAmbiguousCall] = TR("Ambiguous call to overloaded function");
|
||||
stringsCbot[CBot::CBotErrFuncNotVoid] = TR("Function needs return type \"void\"");
|
||||
stringsCbot[CBot::CBotErrNoClassName] = TR("Class name expected");
|
||||
stringsCbot[CBot::CBotErrNoReturn] = TR("Non-void function needs \"return;\"");
|
||||
stringsCbot[CBot::CBotErrDefaultValue] = TR("This parameter needs a default value");
|
||||
|
||||
stringsCbot[CBot::CBotErrZeroDiv] = TR("Dividing by zero");
|
||||
stringsCbot[CBot::CBotErrNotInit] = TR("Variable not initialized");
|
||||
|
|
|
@ -140,6 +140,10 @@ enum ResTextType
|
|||
RT_LOADING_TERRAIN_TEX = 222,
|
||||
RT_LOADING_TERRAIN_GEN = 223,
|
||||
|
||||
RT_SCOREBOARD_RESULTS = 230,
|
||||
RT_SCOREBOARD_RESULTS_TEXT= 231,
|
||||
RT_SCOREBOARD_RESULTS_LINE= 232,
|
||||
|
||||
|
||||
RT_MAX //! < number of values
|
||||
};
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "common/config.h"
|
||||
|
||||
#include "common/make_unique.h"
|
||||
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
#include "common/system/system_windows.h"
|
||||
#elif defined(PLATFORM_LINUX)
|
||||
|
@ -32,8 +34,6 @@
|
|||
#include "common/system/system_other.h"
|
||||
#endif
|
||||
|
||||
#include "common/make_unique.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "graphics/core/color.h"
|
||||
#include "graphics/core/texture.h"
|
||||
#include "graphics/core/vertex.h"
|
||||
|
||||
#include "math/intpoint.h"
|
||||
|
||||
|
@ -267,8 +268,10 @@ enum PrimitiveType
|
|||
PRIMITIVE_POINTS,
|
||||
PRIMITIVE_LINES,
|
||||
PRIMITIVE_LINE_STRIP,
|
||||
PRIMITIVE_LINE_LOOP,
|
||||
PRIMITIVE_TRIANGLES,
|
||||
PRIMITIVE_TRIANGLE_STRIP
|
||||
PRIMITIVE_TRIANGLE_STRIP,
|
||||
PRIMITIVE_TRIANGLE_FAN
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -413,6 +416,14 @@ public:
|
|||
//! Sets only the texture wrap modes (for faster than thru stage params)
|
||||
virtual void SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wrapT) = 0;
|
||||
|
||||
//! Renders primitive composed of generic vertices
|
||||
virtual void DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount) = 0;
|
||||
|
||||
//! Renders multiple primitives composed of generic vertices
|
||||
virtual void DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount) = 0;
|
||||
|
||||
//! Renders primitive composed of vertices with single texture
|
||||
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) = 0;
|
||||
|
|
|
@ -168,6 +168,16 @@ void CNullDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i
|
|||
{
|
||||
}
|
||||
|
||||
void CNullDevice::DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount)
|
||||
{
|
||||
}
|
||||
|
||||
void CNullDevice::DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount)
|
||||
{
|
||||
}
|
||||
|
||||
void CNullDevice::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
||||
int first[], int count[], int drawCount, Color color)
|
||||
{
|
||||
|
|
|
@ -81,6 +81,11 @@ public:
|
|||
|
||||
void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override;
|
||||
|
||||
void DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount) override;
|
||||
void DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount) override;
|
||||
|
||||
void DrawPrimitive(PrimitiveType type, const Vertex* vertices, int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
|
||||
void DrawPrimitive(PrimitiveType type, const VertexTex2* vertices, int vertexCount, Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
|
||||
void DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) override;
|
||||
|
|
|
@ -205,47 +205,6 @@ struct TextureStageParams
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct TexGenMode
|
||||
* \brief Texture generation mode
|
||||
*/
|
||||
enum TexGenMode
|
||||
{
|
||||
//! No texture generation
|
||||
TEX_GEN_NONE,
|
||||
//! Object linear mode
|
||||
TEX_GEN_OBJECT_LINEAR,
|
||||
//! Eye linear mode
|
||||
TEX_GEN_EYE_LINEAR,
|
||||
//! Spherical mapping mode
|
||||
TEX_GEN_SPHERE_MAP,
|
||||
//! Normal mapping mode
|
||||
TEX_GEN_NORMAL_MAP,
|
||||
//! Reflection mapping mode
|
||||
TEX_GEN_REFLECTION_MAP
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct TextureGenerationParams
|
||||
* \brief Parameters for texture coordinate generation
|
||||
*
|
||||
* These params define the generation of texture coordinate for given texture unit.
|
||||
*/
|
||||
struct TextureGenerationParams
|
||||
{
|
||||
struct Coord
|
||||
{
|
||||
TexGenMode mode = TEX_GEN_NONE;
|
||||
float plane[4] = {};
|
||||
};
|
||||
Coord coords[4];
|
||||
|
||||
void LoadDefault()
|
||||
{
|
||||
*this = TextureGenerationParams();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct Texture
|
||||
* \brief Info about a texture
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* This file is part of the Colobot: Gold Edition source code
|
||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||
*
|
||||
* 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://gnu.org/licenses
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file graphics/core/type.cpp
|
||||
* \brief Type support and conversion
|
||||
*/
|
||||
|
||||
#include "graphics/core/type.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
// Graphics module namespace
|
||||
namespace Gfx
|
||||
{
|
||||
|
||||
//! Returns size in bytes of given type
|
||||
int GetTypeSize(Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::BYTE:
|
||||
case Type::UBYTE:
|
||||
return 1;
|
||||
case Type::SHORT:
|
||||
case Type::USHORT:
|
||||
case Type::HALF:
|
||||
return 2;
|
||||
case Type::INT:
|
||||
case Type::UINT:
|
||||
case Type::FLOAT:
|
||||
return 4;
|
||||
case Type::DOUBLE:
|
||||
return 8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* This file is part of the Colobot: Gold Edition source code
|
||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||
*
|
||||
* 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://gnu.org/licenses
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file graphics/core/type.h
|
||||
* \brief Type support and conversion
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Graphics module namespace
|
||||
namespace Gfx
|
||||
{
|
||||
|
||||
/**
|
||||
* \enum class Type
|
||||
* \brief Value types for vertex attributes
|
||||
*/
|
||||
enum class Type : unsigned char
|
||||
{
|
||||
//! Unsigned byte (8-bit)
|
||||
UBYTE = 0,
|
||||
//! Signed byte (8-bit)
|
||||
BYTE,
|
||||
//! Unsigned short (16-bit)
|
||||
USHORT,
|
||||
//! Signed short (16-bit)
|
||||
SHORT,
|
||||
//! Unsigned int (32-bit)
|
||||
UINT,
|
||||
//! Signed int (32-bit)
|
||||
INT,
|
||||
//! Half precision floating-point (16-bit)
|
||||
HALF,
|
||||
//! Single precision floating-point (32-bit)
|
||||
FLOAT,
|
||||
//! Double precision floating-point (64-bit)
|
||||
DOUBLE,
|
||||
};
|
||||
|
||||
//! Returns size in bytes of given type
|
||||
int GetTypeSize(Type type);
|
||||
|
||||
// TODO: functions for conversion between types
|
||||
|
||||
} // namespace Gfx
|
|
@ -26,11 +26,13 @@
|
|||
|
||||
|
||||
#include "graphics/core/color.h"
|
||||
#include "graphics/core/type.h"
|
||||
|
||||
#include "math/point.h"
|
||||
#include "math/vector.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
// Graphics module namespace
|
||||
|
@ -38,6 +40,58 @@ namespace Gfx
|
|||
{
|
||||
|
||||
|
||||
/**
|
||||
* \struct VertexAttribute
|
||||
* \brief Vertex attribute
|
||||
*
|
||||
* This structure contains parameters for a vertex attribute.
|
||||
*/
|
||||
struct VertexAttribute
|
||||
{
|
||||
//! true enables vertex attribute
|
||||
bool enabled = false;
|
||||
//! true means normalized value (integer types only)
|
||||
bool normalized = false;
|
||||
//! Number of elements in the vertex attribute.
|
||||
//! Valid values are 1, 2, 3, and 4. Depends on specific attribute.
|
||||
unsigned char size = 0;
|
||||
//! Type of values in vertex attribute
|
||||
Type type = Type::UBYTE;
|
||||
//! Offset to the vertex attribute
|
||||
int offset = 0;
|
||||
//! Stride of vertex attribute
|
||||
int stride = 0;
|
||||
//! Default values used when attribute is disabled
|
||||
float values[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct VertexFormat
|
||||
* \brief Vertex format
|
||||
*
|
||||
* This structure defines vertex formats for generic vertex arrays.
|
||||
*
|
||||
* It contains:
|
||||
* - vertex coordinate specification
|
||||
* - color specification
|
||||
* - normal specification
|
||||
* - texture coordinate 1 specification
|
||||
* - texture coordinate 2 specification
|
||||
*/
|
||||
struct VertexFormat
|
||||
{
|
||||
//! Vertex coordinate
|
||||
VertexAttribute vertex{};
|
||||
//! Color
|
||||
VertexAttribute color{};
|
||||
//! Normal
|
||||
VertexAttribute normal{};
|
||||
//! Texture coordinate 1
|
||||
VertexAttribute tex1{};
|
||||
//! Texture coordinate 2
|
||||
VertexAttribute tex2{};
|
||||
};
|
||||
|
||||
/**
|
||||
* \struct Vertex
|
||||
* \brief Vertex of a primitive
|
||||
|
|
|
@ -234,8 +234,6 @@ void CCloud::Create(const std::string& fileName,
|
|||
m_lines.clear();
|
||||
for (int y = 0; y < m_brickCount; y++)
|
||||
CreateLine(0, y, m_brickCount);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void CCloud::Flush()
|
||||
|
|
|
@ -2194,7 +2194,7 @@ void CEngine::SetState(int state, const Color& color)
|
|||
m_device->SetTextureStageWrap(0, TEX_WRAP_REPEAT, TEX_WRAP_REPEAT);
|
||||
m_device->SetTextureStageWrap(1, TEX_WRAP_REPEAT, TEX_WRAP_REPEAT);
|
||||
}
|
||||
else // if (state & ENG_RSTATE_CLAMP) or otherwise
|
||||
else if (state & ENG_RSTATE_CLAMP)
|
||||
{
|
||||
m_device->SetTextureStageWrap(0, TEX_WRAP_CLAMP, TEX_WRAP_CLAMP);
|
||||
m_device->SetTextureStageWrap(1, TEX_WRAP_CLAMP, TEX_WRAP_CLAMP);
|
||||
|
@ -3087,6 +3087,11 @@ const Math::Matrix& CEngine::GetMatView()
|
|||
return m_matView;
|
||||
}
|
||||
|
||||
const Math::Matrix& CEngine::GetMatProj()
|
||||
{
|
||||
return m_matProj;
|
||||
}
|
||||
|
||||
Math::Vector CEngine::GetEyePt()
|
||||
{
|
||||
return m_eyePt;
|
||||
|
@ -3261,7 +3266,9 @@ void CEngine::Draw3DScene()
|
|||
m_device->SetTransform(TRANSFORM_PROJECTION, m_matProj);
|
||||
m_device->SetTransform(TRANSFORM_VIEW, m_matView);
|
||||
|
||||
m_water->DrawBack(); // draws water background
|
||||
// TODO: This causes a rendering artifact and I can't see anything that breaks if you just comment it out
|
||||
// So I'll just leave it like that for now ~krzys_h
|
||||
//m_water->DrawBack(); // draws water background
|
||||
|
||||
CProfiler::StartPerformanceCounter(PCNT_RENDER_TERRAIN);
|
||||
|
||||
|
@ -4262,15 +4269,15 @@ void CEngine::UpdateGroundSpotTextures()
|
|||
else
|
||||
intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
|
||||
|
||||
Gfx::Color color;
|
||||
color.r = Math::Norm(m_groundSpots[i].color.r+intensity);
|
||||
color.g = Math::Norm(m_groundSpots[i].color.g+intensity);
|
||||
color.b = Math::Norm(m_groundSpots[i].color.b+intensity);
|
||||
|
||||
ppx -= min.x; // on the texture
|
||||
ppy -= min.y;
|
||||
Math::IntPoint pp(ppx, ppy);
|
||||
|
||||
shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
|
||||
Gfx::Color color = shadowImg.GetPixel(pp);
|
||||
color.r *= Math::Norm(m_groundSpots[i].color.r+intensity);
|
||||
color.g *= Math::Norm(m_groundSpots[i].color.g+intensity);
|
||||
color.b *= Math::Norm(m_groundSpots[i].color.b+intensity);
|
||||
shadowImg.SetPixel(pp, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4298,12 +4305,13 @@ void CEngine::UpdateGroundSpotTextures()
|
|||
|
||||
if (intensity < 0.0f) intensity = 0.0f;
|
||||
|
||||
Gfx::Color color;
|
||||
color.r = Math::Norm(m_groundSpots[i].color.r+intensity);
|
||||
color.g = Math::Norm(m_groundSpots[i].color.g+intensity);
|
||||
color.b = Math::Norm(m_groundSpots[i].color.b+intensity);
|
||||
Math::IntPoint pp(ix, iy);
|
||||
|
||||
shadowImg.SetPixel(Math::IntPoint(ix, iy), color);
|
||||
Gfx::Color color = shadowImg.GetPixel(pp);
|
||||
color.r *= Math::Norm(m_groundSpots[i].color.r+intensity);
|
||||
color.g *= Math::Norm(m_groundSpots[i].color.g+intensity);
|
||||
color.b *= Math::Norm(m_groundSpots[i].color.b+intensity);
|
||||
shadowImg.SetPixel(pp, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4351,19 +4359,21 @@ void CEngine::UpdateGroundSpotTextures()
|
|||
int j = (ix+dot) + (iy+dot) * m_groundMark.dx;
|
||||
if (m_groundMark.table[j] == 1) // green ?
|
||||
{
|
||||
Gfx::Color color;
|
||||
color.r = Math::Norm(1.0f-intensity);
|
||||
color.g = 1.0f;
|
||||
color.b = Math::Norm(1.0f-intensity);
|
||||
shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
|
||||
Math::IntPoint pp(ppx, ppy);
|
||||
Gfx::Color color = shadowImg.GetPixel(pp);
|
||||
color.r *= Math::Norm(1.0f-intensity);
|
||||
color.g *= 1.0f;
|
||||
color.b *= Math::Norm(1.0f-intensity);
|
||||
shadowImg.SetPixel(pp, color);
|
||||
}
|
||||
if (m_groundMark.table[j] == 2) // red ?
|
||||
{
|
||||
Gfx::Color color;
|
||||
color.r = 1.0f;
|
||||
color.g = Math::Norm(1.0f-intensity);
|
||||
color.b = Math::Norm(1.0f-intensity);
|
||||
shadowImg.SetPixel(Math::IntPoint(ppx, ppy), color);
|
||||
Math::IntPoint pp(ppx, ppy);
|
||||
Gfx::Color color = shadowImg.GetPixel(pp);
|
||||
color.r *= 1.0f;
|
||||
color.g *= Math::Norm(1.0f-intensity);
|
||||
color.b *= Math::Norm(1.0f-intensity);
|
||||
shadowImg.SetPixel(pp, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4401,6 +4411,9 @@ void CEngine::UpdateGroundSpotTextures()
|
|||
{
|
||||
int px = x / 4.0f / 254.0f * size.x;
|
||||
int py = y / 4.0f / 254.0f * size.y;
|
||||
// This can happen because the shadow??.png textures have a 1 pixel margin around them
|
||||
if (px < 0 || px >= size.x || py < 0 || py >= size.y)
|
||||
continue;
|
||||
shadowImg.SetPixelInt(Math::IntPoint(x-min.x, y-min.y), m_displayGotoImage->GetPixelInt(Math::IntPoint(px, py)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1135,6 +1135,8 @@ public:
|
|||
|
||||
//! Returns the view matrix
|
||||
const Math::Matrix& GetMatView();
|
||||
//! Returns the projection matrix
|
||||
const Math::Matrix& GetMatProj();
|
||||
//! Returns the camera center point
|
||||
TEST_VIRTUAL Math::Vector GetEyePt();
|
||||
//! Returns the camera target point
|
||||
|
|
|
@ -131,7 +131,7 @@ bool CLightning::EventFrame(const Event &event)
|
|||
else
|
||||
{
|
||||
assert(obj->Implements(ObjectInterfaceType::Destroyable));
|
||||
dynamic_cast<CDestroyableObject*>(obj)->DamageObject(DamageType::Lightning);
|
||||
dynamic_cast<CDestroyableObject*>(obj)->DamageObject(DamageType::Lightning, std::numeric_limits<float>::infinity());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -952,10 +952,9 @@ void CParticle::FrameParticle(float rTime)
|
|||
{
|
||||
CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
|
||||
m_particle[i].goal = m_particle[i].pos;
|
||||
if (object != nullptr)
|
||||
if (object != nullptr && object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Phazer, 0.002f);
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Phazer, 0.002f, m_particle[i].objFather);
|
||||
}
|
||||
|
||||
m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
|
||||
|
@ -1107,7 +1106,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (m_particle[i].testTime >= 0.1f)
|
||||
if (m_particle[i].testTime >= 0.05f)
|
||||
{
|
||||
m_particle[i].testTime = 0.0f;
|
||||
|
||||
|
@ -1156,8 +1155,10 @@ void CParticle::FrameParticle(float rTime)
|
|||
m_particle[i].goal = m_particle[i].pos;
|
||||
if (object != nullptr)
|
||||
{
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire, 0.002f);
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire, 0.001f, m_particle[i].objFather);
|
||||
}
|
||||
|
||||
m_exploGunCounter++;
|
||||
|
||||
|
@ -1215,7 +1216,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (m_particle[i].testTime >= 0.2f)
|
||||
if (m_particle[i].testTime >= 0.1f)
|
||||
{
|
||||
m_particle[i].testTime = 0.0f;
|
||||
CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
|
||||
|
@ -1238,8 +1239,10 @@ void CParticle::FrameParticle(float rTime)
|
|||
if (object->GetType() != OBJECT_HUMAN)
|
||||
Play(SOUND_TOUCH, m_particle[i].pos, 1.0f);
|
||||
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.2f); // starts explosion
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.1f, m_particle[i].objFather); // starts explosion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1261,7 +1264,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (m_particle[i].testTime >= 0.2f)
|
||||
if (m_particle[i].testTime >= 0.1f)
|
||||
{
|
||||
m_particle[i].testTime = 0.0f;
|
||||
CObject* object = SearchObjectGun(m_particle[i].goal, m_particle[i].pos, m_particle[i].type, m_particle[i].objFather);
|
||||
|
@ -1281,8 +1284,10 @@ void CParticle::FrameParticle(float rTime)
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire); // starts explosion
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire, std::numeric_limits<float>::infinity(), m_particle[i].objFather); // starts explosion
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1301,7 +1306,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (m_particle[i].testTime >= 0.1f)
|
||||
if (m_particle[i].testTime >= 0.05f)
|
||||
{
|
||||
m_particle[i].testTime = 0.0f;
|
||||
|
||||
|
@ -1338,8 +1343,10 @@ void CParticle::FrameParticle(float rTime)
|
|||
m_particle[i].goal = m_particle[i].pos;
|
||||
if (object != nullptr)
|
||||
{
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.002f);
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.001f, m_particle[i].objFather);
|
||||
}
|
||||
|
||||
m_exploGunCounter ++;
|
||||
|
||||
|
@ -2416,7 +2423,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
if (object != nullptr)
|
||||
{
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Tower);
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Tower, std::numeric_limits<float>::infinity(), m_particle[i].objFather);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3502,6 +3509,7 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
|
|||
box2.z += min;
|
||||
|
||||
CObject* best = nullptr;
|
||||
float best_dist = std::numeric_limits<float>::infinity();
|
||||
bool shield = false;
|
||||
for (CObject* obj : CObjectManager::GetInstancePointer()->GetAllObjects())
|
||||
{
|
||||
|
@ -3535,7 +3543,7 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (!obj->Implements(ObjectInterfaceType::Damageable)) continue;
|
||||
if (!obj->Implements(ObjectInterfaceType::Damageable) && !obj->IsBulletWall()) continue;
|
||||
|
||||
Math::Vector oPos = obj->GetPosition();
|
||||
|
||||
|
@ -3563,8 +3571,12 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
|
|||
// Test the center of the object, which is necessary for objects
|
||||
// that have no sphere in the center (station).
|
||||
float dist = Math::Distance(oPos, pos)-4.0f;
|
||||
if (dist < min)
|
||||
float obj_dist = Math::Distance(old, oPos);
|
||||
if (dist < min && obj_dist < best_dist)
|
||||
{
|
||||
best = obj;
|
||||
best_dist = obj_dist;
|
||||
}
|
||||
|
||||
for (const auto& crashSphere : obj->GetAllCrashSpheres())
|
||||
{
|
||||
|
@ -3577,8 +3589,12 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos,
|
|||
|
||||
Math::Vector p = Math::Projection(old, pos, oPos);
|
||||
float ddist = Math::Distance(p, oPos)-oRadius;
|
||||
if (ddist < min)
|
||||
float obj_dist = Math::Distance(old, oPos);
|
||||
if (ddist < min && obj_dist < best_dist)
|
||||
{
|
||||
best = obj;
|
||||
best_dist = obj_dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3724,4 +3740,24 @@ Color CParticle::GetFogColor(Math::Vector pos)
|
|||
return result;
|
||||
}
|
||||
|
||||
void CParticle::CutObjectLink(CObject* obj)
|
||||
{
|
||||
for (int i = 0; i < MAXPARTICULE*MAXPARTITYPE; i++)
|
||||
{
|
||||
if (!m_particle[i].used) continue;
|
||||
|
||||
if (m_particle[i].objLink == obj)
|
||||
{
|
||||
// If the object this particle's coordinates are linked to doesn't exist anymore, remove the particle
|
||||
DeleteRank(i);
|
||||
}
|
||||
|
||||
if (m_particle[i].objFather == obj)
|
||||
{
|
||||
// If the object that spawned this partcle doesn't exist anymore, remove the link
|
||||
m_particle[i].objFather = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Gfx
|
||||
|
|
|
@ -291,6 +291,9 @@ public:
|
|||
//! Draws all the particles
|
||||
void DrawParticle(int sheet);
|
||||
|
||||
//! Indicates that the object binds to the particle no longer exists, without deleting it
|
||||
void CutObjectLink(CObject* obj);
|
||||
|
||||
protected:
|
||||
//! Removes a particle of given rank
|
||||
void DeleteRank(int rank);
|
||||
|
|
|
@ -2157,6 +2157,9 @@ bool CPyro::BurnIsKeepPart(int part)
|
|||
|
||||
void CPyro::BurnTerminate()
|
||||
{
|
||||
if (m_object == nullptr)
|
||||
return;
|
||||
|
||||
if (m_type == PT_BURNO) // organic object is burning?
|
||||
{
|
||||
DeleteObject(true, true); // removes the insect
|
||||
|
@ -2296,6 +2299,7 @@ void CPyro::FallProgress(float rTime)
|
|||
if (floor) // reaches the ground?
|
||||
{
|
||||
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
|
||||
// TODO: implement "killer"?
|
||||
dynamic_cast<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::Explosion);
|
||||
}
|
||||
}
|
||||
|
@ -2319,6 +2323,7 @@ void CPyro::FallProgress(float rTime)
|
|||
else
|
||||
{
|
||||
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
|
||||
// TODO: implement "killer"?
|
||||
dynamic_cast<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::Explosion);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ bool CTerrain::LoadResources(const std::string& fileName)
|
|||
|
||||
if ( (data->surface->w != size) || (data->surface->h != size) )
|
||||
{
|
||||
GetLogger()->Error("Invalid resource file\n");
|
||||
GetLogger()->Error("Invalid resource file! Expected %dx%d\n", size, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -311,10 +311,11 @@ bool CTerrain::LoadRelief(const std::string &fileName, float scaleRelief,
|
|||
ImageData *data = img.GetData();
|
||||
|
||||
int size = (m_mosaicCount*m_brickCount)+1;
|
||||
GetLogger()->Debug("Expected relief size for current terrain configuration is %dx%d\n", size, size);
|
||||
|
||||
if ( (data->surface->w != size) || (data->surface->h != size) )
|
||||
{
|
||||
GetLogger()->Error("Invalid relief file!\n");
|
||||
GetLogger()->Error("Invalid relief file! Expected %dx%d\n", size, size);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -643,37 +643,37 @@ UTF8Char CText::TranslateSpecialChar(int specialChar)
|
|||
|
||||
case CHAR_NEWLINE:
|
||||
// Unicode: U+21B2
|
||||
ch.c1 = 0xE2;
|
||||
ch.c2 = 0x86;
|
||||
ch.c3 = 0xB2;
|
||||
ch.c1 = static_cast<char>(0xE2);
|
||||
ch.c2 = static_cast<char>(0x86);
|
||||
ch.c3 = static_cast<char>(0xB2);
|
||||
break;
|
||||
|
||||
case CHAR_DOT:
|
||||
// Unicode: U+23C5
|
||||
ch.c1 = 0xE2;
|
||||
ch.c2 = 0x8F;
|
||||
ch.c3 = 0x85;
|
||||
ch.c1 = static_cast<char>(0xE2);
|
||||
ch.c2 = static_cast<char>(0x8F);
|
||||
ch.c3 = static_cast<char>(0x85);
|
||||
break;
|
||||
|
||||
case CHAR_SQUARE:
|
||||
// Unicode: U+25FD
|
||||
ch.c1 = 0xE2;
|
||||
ch.c2 = 0x97;
|
||||
ch.c3 = 0xBD;
|
||||
ch.c1 = static_cast<char>(0xE2);
|
||||
ch.c2 = static_cast<char>(0x97);
|
||||
ch.c3 = static_cast<char>(0xBD);
|
||||
break;
|
||||
|
||||
case CHAR_SKIP_RIGHT:
|
||||
// Unicode: U+25B6
|
||||
ch.c1 = 0xE2;
|
||||
ch.c2 = 0x96;
|
||||
ch.c3 = 0xB6;
|
||||
ch.c1 = static_cast<char>(0xE2);
|
||||
ch.c2 = static_cast<char>(0x96);
|
||||
ch.c3 = static_cast<char>(0xB6);
|
||||
break;
|
||||
|
||||
case CHAR_SKIP_LEFT:
|
||||
// Unicode: U+25C0
|
||||
ch.c1 = 0xE2;
|
||||
ch.c2 = 0x97;
|
||||
ch.c3 = 0x80;
|
||||
ch.c1 = static_cast<char>(0xE2);
|
||||
ch.c2 = static_cast<char>(0x97);
|
||||
ch.c3 = static_cast<char>(0x80);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -258,11 +258,25 @@ bool CGL14Device::Create()
|
|||
{
|
||||
GetLogger()->Info("Core VBO supported\n", glMajor, glMinor);
|
||||
m_vertexBufferType = VBT_VBO_CORE;
|
||||
|
||||
// Set function pointers
|
||||
m_glGenBuffers = glGenBuffers;
|
||||
m_glDeleteBuffers = glDeleteBuffers;
|
||||
m_glBindBuffer = glBindBuffer;
|
||||
m_glBufferData = glBufferData;
|
||||
m_glBufferSubData = glBufferSubData;
|
||||
}
|
||||
else if (vboARB) // VBO ARB extension available
|
||||
{
|
||||
GetLogger()->Info("ARB VBO supported\n");
|
||||
m_vertexBufferType = VBT_VBO_ARB;
|
||||
|
||||
// Set function pointers
|
||||
m_glGenBuffers = glGenBuffersARB;
|
||||
m_glDeleteBuffers = glDeleteBuffersARB;
|
||||
m_glBindBuffer = glBindBufferARB;
|
||||
m_glBufferData = glBufferDataARB;
|
||||
m_glBufferSubData = glBufferSubDataARB;
|
||||
}
|
||||
else // no VBO support
|
||||
{
|
||||
|
@ -800,44 +814,22 @@ Texture CGL14Device::CreateDepthTexture(int width, int height, int depth)
|
|||
|
||||
GLuint format = GL_DEPTH_COMPONENT;
|
||||
|
||||
if (m_shadowMappingSupport == SMS_CORE)
|
||||
switch (depth)
|
||||
{
|
||||
switch (depth)
|
||||
{
|
||||
case 16:
|
||||
format = GL_DEPTH_COMPONENT16;
|
||||
break;
|
||||
case 24:
|
||||
format = GL_DEPTH_COMPONENT24;
|
||||
break;
|
||||
case 32:
|
||||
format = GL_DEPTH_COMPONENT32;
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_INT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
case 16:
|
||||
format = GL_DEPTH_COMPONENT16;
|
||||
break;
|
||||
case 24:
|
||||
format = GL_DEPTH_COMPONENT24;
|
||||
break;
|
||||
case 32:
|
||||
format = GL_DEPTH_COMPONENT32;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (depth)
|
||||
{
|
||||
case 16:
|
||||
format = GL_DEPTH_COMPONENT16_ARB;
|
||||
break;
|
||||
case 24:
|
||||
format = GL_DEPTH_COMPONENT24_ARB;
|
||||
break;
|
||||
case 32:
|
||||
format = GL_DEPTH_COMPONENT32_ARB;
|
||||
break;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_INT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_INT, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||
|
||||
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
|
@ -1379,6 +1371,168 @@ void CGL14Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i
|
|||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
void CGL14Device::DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount)
|
||||
{
|
||||
const char *ptr = reinterpret_cast<const char*>(vertices);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(format.vertex.size,
|
||||
TransformType(format.vertex.type),
|
||||
format.vertex.stride,
|
||||
ptr + format.vertex.offset);
|
||||
|
||||
if (format.color.enabled)
|
||||
{
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(format.color.size,
|
||||
TransformType(format.color.type),
|
||||
format.color.stride,
|
||||
ptr + format.color.offset);
|
||||
}
|
||||
else
|
||||
glColor4fv(format.color.values);
|
||||
|
||||
if (format.normal.enabled)
|
||||
{
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(TransformType(format.normal.type),
|
||||
format.normal.stride,
|
||||
ptr + format.normal.offset);
|
||||
}
|
||||
else
|
||||
glNormal3fv(format.normal.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex1.size,
|
||||
TransformType(format.tex1.type),
|
||||
format.tex1.stride,
|
||||
ptr + format.tex1.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex1.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex2.size,
|
||||
TransformType(format.tex2.type),
|
||||
format.tex2.stride,
|
||||
ptr + format.tex2.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex2.values);
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY);
|
||||
if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void CGL14Device::DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount)
|
||||
{
|
||||
const char *ptr = reinterpret_cast<const char*>(vertices);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(format.vertex.size,
|
||||
TransformType(format.vertex.type),
|
||||
format.vertex.stride,
|
||||
ptr + format.vertex.offset);
|
||||
|
||||
if (format.color.enabled)
|
||||
{
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(format.color.size,
|
||||
TransformType(format.color.type),
|
||||
format.color.stride,
|
||||
ptr + format.color.offset);
|
||||
}
|
||||
else
|
||||
glColor4fv(format.color.values);
|
||||
|
||||
if (format.normal.enabled)
|
||||
{
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(TransformType(format.normal.type),
|
||||
format.normal.stride,
|
||||
ptr + format.normal.offset);
|
||||
}
|
||||
else
|
||||
glNormal3fv(format.normal.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex1.size,
|
||||
TransformType(format.tex1.type),
|
||||
format.tex1.stride,
|
||||
ptr + format.tex1.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex1.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex2.size,
|
||||
TransformType(format.tex2.type),
|
||||
format.tex2.stride,
|
||||
ptr + format.tex2.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex2.values);
|
||||
|
||||
GLenum t = TranslateGfxPrimitive(type);
|
||||
|
||||
if (m_multiDrawArrays)
|
||||
{
|
||||
glMultiDrawArrays(t, first, count, drawCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
glDrawArrays(t, first[i], count[i]);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY);
|
||||
if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void CGL14Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
||||
int first[], int count[], int drawCount, Color color)
|
||||
{
|
||||
|
@ -1494,20 +1648,10 @@ unsigned int CGL14Device::CreateStaticBuffer(PrimitiveType primitiveType, const
|
|||
info.vertexCount = vertexCount;
|
||||
info.bufferId = 0;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
{
|
||||
glGenBuffers(1, &info.bufferId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glGenBuffersARB(1, &info.bufferId);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW_ARB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
m_glGenBuffers(1, &info.bufferId);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
m_glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
m_vboObjects[id] = info;
|
||||
}
|
||||
|
@ -1538,20 +1682,10 @@ unsigned int CGL14Device::CreateStaticBuffer(PrimitiveType primitiveType, const
|
|||
info.vertexCount = vertexCount;
|
||||
info.bufferId = 0;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
{
|
||||
glGenBuffers(1, &info.bufferId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glGenBuffersARB(1, &info.bufferId);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW_ARB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
m_glGenBuffers(1, &info.bufferId);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
m_glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
m_vboObjects[id] = info;
|
||||
}
|
||||
|
@ -1582,20 +1716,10 @@ unsigned int CGL14Device::CreateStaticBuffer(PrimitiveType primitiveType, const
|
|||
info.vertexCount = vertexCount;
|
||||
info.bufferId = 0;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
{
|
||||
glGenBuffers(1, &info.bufferId);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glGenBuffersARB(1, &info.bufferId);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW_ARB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
m_glGenBuffers(1, &info.bufferId);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
m_glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
m_vboObjects[id] = info;
|
||||
}
|
||||
|
@ -1626,18 +1750,9 @@ void CGL14Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
|||
info.vertexType = VERTEX_TYPE_NORMAL;
|
||||
info.vertexCount = vertexCount;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW_ARB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
m_glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1662,18 +1777,9 @@ void CGL14Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
|||
info.vertexType = VERTEX_TYPE_TEX2;
|
||||
info.vertexCount = vertexCount;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW_ARB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
m_glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1698,18 +1804,9 @@ void CGL14Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
|||
info.vertexType = VERTEX_TYPE_COL;
|
||||
info.vertexCount = vertexCount;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, info.bufferId);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW_ARB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
}
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, info.bufferId);
|
||||
m_glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1729,10 +1826,7 @@ void CGL14Device::DrawStaticBuffer(unsigned int bufferId)
|
|||
if (it == m_vboObjects.end())
|
||||
return;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId);
|
||||
else
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, (*it).second.bufferId);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId);
|
||||
|
||||
if ((*it).second.vertexType == VERTEX_TYPE_NORMAL)
|
||||
{
|
||||
|
@ -1795,10 +1889,7 @@ void CGL14Device::DrawStaticBuffer(unsigned int bufferId)
|
|||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
else
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
|
||||
m_glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1814,10 +1905,7 @@ void CGL14Device::DestroyStaticBuffer(unsigned int bufferId)
|
|||
if (it == m_vboObjects.end())
|
||||
return;
|
||||
|
||||
if(m_vertexBufferType == VBT_VBO_CORE)
|
||||
glDeleteBuffers(1, &(*it).second.bufferId);
|
||||
else
|
||||
glDeleteBuffersARB(1, &(*it).second.bufferId);
|
||||
m_glDeleteBuffers(1, &(*it).second.bufferId);
|
||||
|
||||
m_vboObjects.erase(it);
|
||||
}
|
||||
|
|
|
@ -119,6 +119,11 @@ public:
|
|||
|
||||
void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override;
|
||||
|
||||
virtual void DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount) override;
|
||||
virtual void DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount) override;
|
||||
|
||||
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||
|
@ -290,6 +295,14 @@ private:
|
|||
bool m_shadowMapping = false;
|
||||
//! true means that quality shadows are enabled
|
||||
bool m_shadowQuality = true;
|
||||
|
||||
|
||||
//! Pointers to OpenGL functions
|
||||
PFNGLGENBUFFERSPROC m_glGenBuffers = nullptr;
|
||||
PFNGLDELETEBUFFERSPROC m_glDeleteBuffers = nullptr;
|
||||
PFNGLBINDBUFFERPROC m_glBindBuffer = nullptr;
|
||||
PFNGLBUFFERDATAPROC m_glBufferData = nullptr;
|
||||
PFNGLBUFFERSUBDATAPROC m_glBufferSubData = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ bool CGL21Device::Create()
|
|||
glViewport(0, 0, m_config.size.x, m_config.size.y);
|
||||
|
||||
// this is set in shader
|
||||
int numLights = 8;
|
||||
int numLights = 4;
|
||||
|
||||
m_lights = std::vector<Light>(numLights, Light());
|
||||
m_lightsEnabled = std::vector<bool> (numLights, false);
|
||||
|
@ -408,7 +408,7 @@ bool CGL21Device::Create()
|
|||
uni.fogColor = glGetUniformLocation(m_normalProgram, "uni_FogColor");
|
||||
|
||||
uni.shadowColor = glGetUniformLocation(m_normalProgram, "uni_ShadowColor");
|
||||
uni.lightingEnabled = glGetUniformLocation(m_normalProgram, "uni_LightingEnabled");
|
||||
uni.lightCount = glGetUniformLocation(m_normalProgram, "uni_LightCount");
|
||||
|
||||
uni.ambientColor = glGetUniformLocation(m_normalProgram, "uni_Material.ambient");
|
||||
uni.diffuseColor = glGetUniformLocation(m_normalProgram, "uni_Material.diffuse");
|
||||
|
@ -417,12 +417,6 @@ bool CGL21Device::Create()
|
|||
GLchar name[64];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
sprintf(name, "uni_Light[%d].Enabled", i);
|
||||
uni.lights[i].enabled = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
sprintf(name, "uni_Light[%d].Type", i);
|
||||
uni.lights[i].type = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
sprintf(name, "uni_Light[%d].Position", i);
|
||||
uni.lights[i].position = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
|
@ -434,18 +428,6 @@ bool CGL21Device::Create()
|
|||
|
||||
sprintf(name, "uni_Light[%d].Specular", i);
|
||||
uni.lights[i].specular = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
sprintf(name, "uni_Light[%d].Attenuation", i);
|
||||
uni.lights[i].attenuation = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
sprintf(name, "uni_Light[%d].SpotDirection", i);
|
||||
uni.lights[i].spotDirection = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
sprintf(name, "uni_Light[%d].Exponent", i);
|
||||
uni.lights[i].spotExponent = glGetUniformLocation(m_normalProgram, name);
|
||||
|
||||
sprintf(name, "uni_Light[%d].SpotCutoff", i);
|
||||
uni.lights[i].spotCutoff = glGetUniformLocation(m_normalProgram, name);
|
||||
}
|
||||
|
||||
// Set default uniform values
|
||||
|
@ -476,10 +458,7 @@ bool CGL21Device::Create()
|
|||
|
||||
glUniform1f(uni.shadowColor, 0.5f);
|
||||
|
||||
glUniform1i(uni.lightingEnabled, 0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
glUniform1i(uni.lights[i].enabled, 0);
|
||||
glUniform1i(uni.lightCount, 0);
|
||||
}
|
||||
|
||||
// Obtain uniform locations from interface rendering program and initialize them
|
||||
|
@ -594,6 +573,7 @@ void CGL21Device::ConfigChanged(const DeviceConfig& newConfig)
|
|||
|
||||
// Reset state
|
||||
m_lighting = false;
|
||||
m_updateLights = true;
|
||||
|
||||
glViewport(0, 0, m_config.size.x, m_config.size.y);
|
||||
|
||||
|
@ -721,36 +701,7 @@ void CGL21Device::SetLight(int index, const Light &light)
|
|||
|
||||
m_lights[index] = light;
|
||||
|
||||
LightLocations &loc = m_uniforms[m_mode].lights[index];
|
||||
|
||||
glUniform4fv(loc.ambient, 1, light.ambient.Array());
|
||||
glUniform4fv(loc.diffuse, 1, light.diffuse.Array());
|
||||
glUniform4fv(loc.specular, 1, light.specular.Array());
|
||||
glUniform3f(loc.attenuation, light.attenuation0, light.attenuation1, light.attenuation2);
|
||||
|
||||
if (light.type == LIGHT_DIRECTIONAL)
|
||||
{
|
||||
glUniform1i(loc.type, 1);
|
||||
glUniform4f(loc.position, -light.direction.x, -light.direction.y, -light.direction.z, 0.0f);
|
||||
}
|
||||
else if (light.type == LIGHT_POINT)
|
||||
{
|
||||
glUniform1i(loc.type, 2);
|
||||
glUniform4f(loc.position, light.position.x, light.position.y, light.position.z, 1.0f);
|
||||
|
||||
glUniform3f(loc.spotDirection, 0.0f, 1.0f, 0.0f);
|
||||
glUniform1f(loc.spotCutoff, -1.0f);
|
||||
glUniform1f(loc.spotExponent, 1.0f);
|
||||
}
|
||||
else if (light.type == LIGHT_SPOT)
|
||||
{
|
||||
glUniform1i(loc.type, 3);
|
||||
glUniform4f(loc.position, light.position.x, light.position.y, light.position.z, 1.0f);
|
||||
|
||||
glUniform3f(loc.spotDirection, -light.direction.x, -light.direction.y, -light.direction.z);
|
||||
glUniform1f(loc.spotCutoff, std::cos(light.spotAngle));
|
||||
glUniform1f(loc.spotExponent, light.spotIntensity);
|
||||
}
|
||||
m_updateLights = true;
|
||||
}
|
||||
|
||||
void CGL21Device::SetLightEnabled(int index, bool enabled)
|
||||
|
@ -760,7 +711,7 @@ void CGL21Device::SetLightEnabled(int index, bool enabled)
|
|||
|
||||
m_lightsEnabled[index] = enabled;
|
||||
|
||||
glUniform1i(m_uniforms[m_mode].lights[index].enabled, enabled ? 1 : 0);
|
||||
m_updateLights = true;
|
||||
}
|
||||
|
||||
/** If image is invalid, returns invalid texture.
|
||||
|
@ -798,12 +749,13 @@ Texture CGL21Device::CreateTexture(ImageData *data, const TextureCreateParams &p
|
|||
|
||||
result.originalSize = result.size;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glGenTextures(1, &result.id);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, result.id);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Set texture parameters
|
||||
GLint minF = GL_NEAREST, magF = GL_NEAREST;
|
||||
int mipmapLevel = 1;
|
||||
|
@ -991,7 +943,7 @@ void CGL21Device::SetTexture(int index, const Texture &texture)
|
|||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
|
||||
// Params need to be updated for the new bound texture
|
||||
UpdateTextureStatus();
|
||||
UpdateTextureState(index);
|
||||
UpdateTextureParams(index);
|
||||
}
|
||||
|
||||
|
@ -1009,7 +961,7 @@ void CGL21Device::SetTexture(int index, unsigned int textureId)
|
|||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
|
||||
// Params need to be updated for the new bound texture
|
||||
UpdateTextureStatus();
|
||||
UpdateTextureState(index);
|
||||
UpdateTextureParams(index);
|
||||
}
|
||||
|
||||
|
@ -1024,15 +976,54 @@ void CGL21Device::SetTextureEnabled(int index, bool enabled)
|
|||
if (same)
|
||||
return; // nothing to do
|
||||
|
||||
UpdateTextureStatus();
|
||||
UpdateTextureState(index);
|
||||
}
|
||||
|
||||
void CGL21Device::UpdateTextureStatus()
|
||||
void CGL21Device::UpdateTextureState(int index)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
bool enabled = m_texturesEnabled[index] && (m_currentTextures[index].id != 0);
|
||||
glUniform1i(m_uniforms[m_mode].textureEnabled[index], enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
void CGL21Device::UpdateLights()
|
||||
{
|
||||
m_updateLights = false;
|
||||
|
||||
// If not in normal rendering mode, return immediately
|
||||
if (m_mode != 0) return;
|
||||
|
||||
// Lighting enabled
|
||||
if (m_lighting)
|
||||
{
|
||||
bool enabled = m_texturesEnabled[i] && (m_currentTextures[i].id != 0);
|
||||
glUniform1i(m_uniforms[m_mode].textureEnabled[i], enabled ? 1 : 0);
|
||||
int index = 0;
|
||||
|
||||
// Iterate all lights
|
||||
for (unsigned int i = 0; i < m_lights.size(); i++)
|
||||
{
|
||||
// If disabled, ignore and continue
|
||||
if (!m_lightsEnabled[i]) continue;
|
||||
|
||||
// If not directional, ignore and continue
|
||||
if (m_lights[i].type != LIGHT_DIRECTIONAL) continue;
|
||||
|
||||
Light &light = m_lights[i];
|
||||
LightLocations &uni = m_uniforms[m_mode].lights[index];
|
||||
|
||||
glUniform4fv(uni.ambient, 1, light.ambient.Array());
|
||||
glUniform4fv(uni.diffuse, 1, light.diffuse.Array());
|
||||
glUniform4fv(uni.specular, 1, light.specular.Array());
|
||||
|
||||
glUniform4f(uni.position, -light.direction.x, -light.direction.y, -light.direction.z, 0.0f);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
glUniform1i(m_uniforms[m_mode].lightCount, index);
|
||||
}
|
||||
// Lighting disabled
|
||||
else
|
||||
{
|
||||
glUniform1i(m_uniforms[m_mode].lightCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1044,6 +1035,12 @@ inline void CGL21Device::BindVBO(GLuint vbo)
|
|||
m_currentVBO = vbo;
|
||||
}
|
||||
|
||||
inline void CGL21Device::BindTexture(int index, GLuint texture)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the texture parameters for the given texture stage.
|
||||
If the given texture was not set (bound) yet, nothing happens.
|
||||
|
@ -1121,6 +1118,8 @@ void CGL21Device::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode
|
|||
void CGL21Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int vertexCount,
|
||||
Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
Vertex* vs = const_cast<Vertex*>(vertices);
|
||||
|
@ -1148,6 +1147,8 @@ void CGL21Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int
|
|||
void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||
Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
VertexTex2* vs = const_cast<VertexTex2*>(vertices);
|
||||
|
@ -1180,6 +1181,8 @@ void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices,
|
|||
|
||||
void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
VertexCol* vs = const_cast<VertexCol*>(vertices);
|
||||
|
@ -1196,9 +1199,171 @@ void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i
|
|||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
void CGL21Device::DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
const char *ptr = reinterpret_cast<const char*>(vertices);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(format.vertex.size,
|
||||
TransformType(format.vertex.type),
|
||||
format.vertex.stride,
|
||||
ptr + format.vertex.offset);
|
||||
|
||||
if (format.color.enabled)
|
||||
{
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(format.color.size,
|
||||
TransformType(format.color.type),
|
||||
format.color.stride,
|
||||
ptr + format.color.offset);
|
||||
}
|
||||
else
|
||||
glColor4fv(format.color.values);
|
||||
|
||||
if (format.normal.enabled)
|
||||
{
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(TransformType(format.normal.type),
|
||||
format.normal.stride,
|
||||
ptr + format.normal.offset);
|
||||
}
|
||||
else
|
||||
glNormal3fv(format.normal.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex1.size,
|
||||
TransformType(format.tex1.type),
|
||||
format.tex1.stride,
|
||||
ptr + format.tex1.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex1.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex2.size,
|
||||
TransformType(format.tex2.type),
|
||||
format.tex2.stride,
|
||||
ptr + format.tex2.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex2.values);
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY);
|
||||
if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void CGL21Device::DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
const char *ptr = reinterpret_cast<const char*>(vertices);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glVertexPointer(format.vertex.size,
|
||||
TransformType(format.vertex.type),
|
||||
format.vertex.stride,
|
||||
ptr + format.vertex.offset);
|
||||
|
||||
if (format.color.enabled)
|
||||
{
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glColorPointer(format.color.size,
|
||||
TransformType(format.color.type),
|
||||
format.color.stride,
|
||||
ptr + format.color.offset);
|
||||
}
|
||||
else
|
||||
glColor4fv(format.color.values);
|
||||
|
||||
if (format.normal.enabled)
|
||||
{
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(TransformType(format.normal.type),
|
||||
format.normal.stride,
|
||||
ptr + format.normal.offset);
|
||||
}
|
||||
else
|
||||
glNormal3fv(format.normal.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex1.size,
|
||||
TransformType(format.tex1.type),
|
||||
format.tex1.stride,
|
||||
ptr + format.tex1.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex1.values);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(format.tex2.size,
|
||||
TransformType(format.tex2.type),
|
||||
format.tex2.stride,
|
||||
ptr + format.tex2.offset);
|
||||
}
|
||||
else
|
||||
glTexCoord2fv(format.tex2.values);
|
||||
|
||||
glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (format.color.enabled) glDisableClientState(GL_COLOR_ARRAY);
|
||||
if (format.normal.enabled) glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
if (format.tex1.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (format.tex2.enabled)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void CGL21Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
||||
int first[], int count[], int drawCount, Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
Vertex* vs = const_cast<Vertex*>(vertices);
|
||||
|
@ -1225,6 +1390,8 @@ void CGL21Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
|||
void CGL21Device::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
|
||||
int first[], int count[], int drawCount, Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
VertexTex2* vs = const_cast<VertexTex2*>(vertices);
|
||||
|
@ -1258,6 +1425,8 @@ void CGL21Device::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
|
|||
void CGL21Device::DrawPrimitives(PrimitiveType type, const VertexCol *vertices,
|
||||
int first[], int count[], int drawCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO(0);
|
||||
|
||||
VertexCol* vs = const_cast<VertexCol*>(vertices);
|
||||
|
@ -1418,6 +1587,8 @@ void CGL21Device::DrawStaticBuffer(unsigned int bufferId)
|
|||
if (it == m_vboObjects.end())
|
||||
return;
|
||||
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
BindVBO((*it).second.bufferId);
|
||||
|
||||
if ((*it).second.vertexType == VERTEX_TYPE_NORMAL)
|
||||
|
@ -1585,9 +1756,11 @@ void CGL21Device::SetRenderState(RenderState state, bool enabled)
|
|||
}
|
||||
else if (state == RENDER_STATE_LIGHTING)
|
||||
{
|
||||
if (m_lighting == enabled) return;
|
||||
|
||||
m_lighting = enabled;
|
||||
|
||||
glUniform1i(m_uniforms[m_mode].lightingEnabled, enabled ? 1 : 0);
|
||||
m_updateLights = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -100,6 +100,11 @@ public:
|
|||
|
||||
void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override;
|
||||
|
||||
virtual void DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount) override;
|
||||
virtual void DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount) override;
|
||||
|
||||
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||
|
@ -178,10 +183,14 @@ public:
|
|||
private:
|
||||
//! Updates the texture params for given texture stage
|
||||
void UpdateTextureParams(int index);
|
||||
//! Updates texture status
|
||||
void UpdateTextureStatus();
|
||||
//! Updates texture state
|
||||
void UpdateTextureState(int index);
|
||||
//! Update light parameters
|
||||
void UpdateLights();
|
||||
//! Binds VBO
|
||||
inline void BindVBO(GLuint vbo);
|
||||
//! Binds texture
|
||||
inline void BindTexture(int index, GLuint texture);
|
||||
|
||||
private:
|
||||
//! Current config
|
||||
|
@ -203,6 +212,8 @@ private:
|
|||
|
||||
//! Whether lighting is enabled
|
||||
bool m_lighting = false;
|
||||
//! true means that lights need to be updated
|
||||
bool m_updateLights = false;
|
||||
//! Current lights
|
||||
std::vector<Light> m_lights;
|
||||
//! Current lights enable status
|
||||
|
|
|
@ -233,7 +233,7 @@ bool CGL33Device::Create()
|
|||
glViewport(0, 0, m_config.size.x, m_config.size.y);
|
||||
|
||||
// this is set in shader
|
||||
m_capabilities.maxLights = 8;
|
||||
m_capabilities.maxLights = 4;
|
||||
|
||||
m_lights = std::vector<Light>(m_capabilities.maxLights, Light());
|
||||
m_lightsEnabled = std::vector<bool>(m_capabilities.maxLights, false);
|
||||
|
@ -381,14 +381,14 @@ bool CGL33Device::Create()
|
|||
|
||||
uni.shadowColor = glGetUniformLocation(m_normalProgram, "uni_ShadowColor");
|
||||
|
||||
uni.lightingEnabled = glGetUniformLocation(m_normalProgram, "uni_LightingEnabled");
|
||||
uni.lightCount = glGetUniformLocation(m_normalProgram, "uni_LightCount");
|
||||
|
||||
uni.ambientColor = glGetUniformLocation(m_normalProgram, "uni_AmbientColor");
|
||||
uni.diffuseColor = glGetUniformLocation(m_normalProgram, "uni_DiffuseColor");
|
||||
uni.specularColor = glGetUniformLocation(m_normalProgram, "uni_SpecularColor");
|
||||
|
||||
GLchar name[64];
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < m_capabilities.maxLights; i++)
|
||||
{
|
||||
LightLocations &light = uni.lights[i];
|
||||
|
||||
|
@ -440,12 +440,9 @@ bool CGL33Device::Create()
|
|||
glUniform1f(uni.shadowColor, 0.5f);
|
||||
|
||||
glUniform1i(uni.alphaTestEnabled, 0);
|
||||
glUniform1f(uni.alphaReference, 1.0f);
|
||||
glUniform1f(uni.alphaReference, 0.5f);
|
||||
|
||||
glUniform1i(uni.lightingEnabled, 0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
glUniform1i(uni.lights[i].enabled, 0);
|
||||
glUniform1i(uni.lightCount, 0);
|
||||
}
|
||||
|
||||
// Obtain uniform locations for interface program
|
||||
|
@ -523,21 +520,18 @@ bool CGL33Device::Create()
|
|||
|
||||
m_framebuffers["default"] = MakeUnique<CDefaultFramebuffer>(framebufferParams);
|
||||
|
||||
// create dynamic buffers
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
glGenVertexArrays(1, &m_dynamicBuffers[i].vao);
|
||||
// create dynamic buffer
|
||||
glGenVertexArrays(1, &m_dynamicBuffer.vao);
|
||||
|
||||
m_dynamicBuffers[i].size = 4 * 1024 * 1024;
|
||||
m_dynamicBuffers[i].offset = 0;
|
||||
m_dynamicBuffer.size = 4 * 1024 * 1024;
|
||||
m_dynamicBuffer.offset = 0;
|
||||
|
||||
glGenBuffers(1, &m_dynamicBuffers[i].vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_dynamicBuffers[i].vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_dynamicBuffers[i].size, nullptr, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glGenBuffers(1, &m_dynamicBuffer.vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_dynamicBuffer.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, m_dynamicBuffer.size, nullptr, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
m_vboMemory += m_dynamicBuffers[i].size;
|
||||
}
|
||||
m_vboMemory += m_dynamicBuffer.size;
|
||||
|
||||
GetLogger()->Info("CDevice created successfully\n");
|
||||
|
||||
|
@ -563,13 +557,10 @@ void CGL33Device::Destroy()
|
|||
DestroyAllTextures();
|
||||
|
||||
// delete dynamic buffer
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
glDeleteVertexArrays(1, &m_dynamicBuffers[i].vao);
|
||||
glDeleteBuffers(1, &m_dynamicBuffers[i].vbo);
|
||||
glDeleteVertexArrays(1, &m_dynamicBuffer.vao);
|
||||
glDeleteBuffers(1, &m_dynamicBuffer.vbo);
|
||||
|
||||
m_vboMemory -= m_dynamicBuffers[i].size;
|
||||
}
|
||||
m_vboMemory -= m_dynamicBuffer.size;
|
||||
|
||||
m_lights.clear();
|
||||
m_lightsEnabled.clear();
|
||||
|
@ -643,7 +634,9 @@ void CGL33Device::SetRenderMode(RenderMode mode)
|
|||
|
||||
m_uni = &m_uniforms[m_mode];
|
||||
|
||||
UpdateRenderingMode();
|
||||
UpdateTextureState(0);
|
||||
UpdateTextureState(1);
|
||||
UpdateTextureState(2);
|
||||
}
|
||||
|
||||
void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix)
|
||||
|
@ -714,23 +707,7 @@ void CGL33Device::SetLight(int index, const Light &light)
|
|||
|
||||
m_lights[index] = light;
|
||||
|
||||
LightLocations &uni = m_uni->lights[index];
|
||||
|
||||
glUniform4fv(uni.ambient, 1, light.ambient.Array());
|
||||
glUniform4fv(uni.diffuse, 1, light.diffuse.Array());
|
||||
glUniform4fv(uni.specular, 1, light.specular.Array());
|
||||
glUniform3f(uni.attenuation, light.attenuation0, light.attenuation1, light.attenuation2);
|
||||
|
||||
if (light.type == LIGHT_DIRECTIONAL)
|
||||
{
|
||||
glUniform4f(uni.position, -light.direction.x, -light.direction.y, -light.direction.z, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUniform4f(uni.position, light.position.x, light.position.y, light.position.z, 1.0f);
|
||||
}
|
||||
|
||||
// TODO: add spotlight params
|
||||
m_updateLights = true;
|
||||
}
|
||||
|
||||
void CGL33Device::SetLightEnabled(int index, bool enabled)
|
||||
|
@ -740,7 +717,7 @@ void CGL33Device::SetLightEnabled(int index, bool enabled)
|
|||
|
||||
m_lightsEnabled[index] = enabled;
|
||||
|
||||
glUniform1i(m_uni->lights[index].enabled, enabled ? 1 : 0);
|
||||
m_updateLights = true;
|
||||
}
|
||||
|
||||
/** If image is invalid, returns invalid texture.
|
||||
|
@ -775,10 +752,9 @@ Texture CGL33Device::CreateTexture(ImageData *data, const TextureCreateParams &p
|
|||
|
||||
result.originalSize = result.size;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glGenTextures(1, &result.id);
|
||||
glBindTexture(GL_TEXTURE_2D, result.id);
|
||||
|
||||
BindTexture(m_freeTexture, result.id);
|
||||
|
||||
// Set texture parameters
|
||||
GLint minF = GL_NEAREST, magF = GL_NEAREST;
|
||||
|
@ -841,9 +817,6 @@ Texture CGL33Device::CreateTexture(ImageData *data, const TextureCreateParams &p
|
|||
|
||||
m_allTextures.insert(result);
|
||||
|
||||
// Restore the previous state of 1st stage
|
||||
glBindTexture(GL_TEXTURE_2D, m_currentTextures[0].id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -855,10 +828,9 @@ Texture CGL33Device::CreateDepthTexture(int width, int height, int depth)
|
|||
result.size.x = width;
|
||||
result.size.y = height;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glGenTextures(1, &result.id);
|
||||
glBindTexture(GL_TEXTURE_2D, result.id);
|
||||
|
||||
BindTexture(m_freeTexture, result.id);
|
||||
|
||||
GLuint format = GL_DEPTH_COMPONENT;
|
||||
|
||||
|
@ -887,16 +859,14 @@ Texture CGL33Device::CreateDepthTexture(int width, int height, int depth)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_currentTextures[0].id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CGL33Device::UpdateTexture(const Texture& texture, Math::IntPoint offset, ImageData* data, TexImgFormat format)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (texture.id == 0) return;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
BindTexture(m_freeTexture, texture.id);
|
||||
|
||||
PreparedTextureData texData = PrepareTextureData(data, format);
|
||||
|
||||
|
@ -951,18 +921,16 @@ void CGL33Device::SetTexture(int index, const Texture &texture)
|
|||
{
|
||||
assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
|
||||
|
||||
bool same = m_currentTextures[index].id == texture.id;
|
||||
if (m_currentTextures[index].id == texture.id)
|
||||
return;
|
||||
|
||||
BindTexture(index, texture.id);
|
||||
|
||||
m_currentTextures[index] = texture; // remember the new value
|
||||
|
||||
if (same)
|
||||
return; // nothing to do
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
|
||||
// Params need to be updated for the new bound texture
|
||||
UpdateTextureParams(index);
|
||||
UpdateTextureState(index);
|
||||
}
|
||||
|
||||
void CGL33Device::SetTexture(int index, unsigned int textureId)
|
||||
|
@ -972,27 +940,25 @@ void CGL33Device::SetTexture(int index, unsigned int textureId)
|
|||
if (m_currentTextures[index].id == textureId)
|
||||
return; // nothing to do
|
||||
|
||||
m_currentTextures[index].id = textureId;
|
||||
BindTexture(index, textureId);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
m_currentTextures[index].id = textureId;
|
||||
|
||||
// Params need to be updated for the new bound texture
|
||||
UpdateTextureParams(index);
|
||||
UpdateTextureState(index);
|
||||
}
|
||||
|
||||
void CGL33Device::SetTextureEnabled(int index, bool enabled)
|
||||
{
|
||||
assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
|
||||
|
||||
bool same = m_texturesEnabled[index] == enabled;
|
||||
if (m_texturesEnabled[index] == enabled)
|
||||
return;
|
||||
|
||||
m_texturesEnabled[index] = enabled;
|
||||
|
||||
if (same)
|
||||
return; // nothing to do
|
||||
|
||||
UpdateRenderingMode();
|
||||
UpdateTextureState(index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1071,148 +1037,176 @@ void CGL33Device::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode
|
|||
|
||||
void CGL33Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int vertexCount, Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
Vertex* vs = const_cast<Vertex*>(vertices);
|
||||
|
||||
unsigned int size = vertexCount * sizeof(Vertex);
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffers[0];
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vs, size);
|
||||
|
||||
// Start of the buffer, reinitialize binding state
|
||||
if (offset == 0)
|
||||
{
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, coord)));
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offset + offsetof(Vertex, coord)));
|
||||
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, texCoord)));
|
||||
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
}
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offset + offsetof(Vertex, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
glVertexAttrib4fv(2, color.Array());
|
||||
|
||||
UpdateRenderingMode();
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offset + offsetof(Vertex, texCoord)));
|
||||
|
||||
int first = offset / sizeof(Vertex);
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(type), first, vertexCount);
|
||||
glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount);
|
||||
}
|
||||
|
||||
void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
VertexTex2* vs = const_cast<VertexTex2*>(vertices);
|
||||
|
||||
unsigned int size = vertexCount * sizeof(VertexTex2);
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffers[1];
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vs, size);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, coord)));
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, coord)));
|
||||
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, texCoord)));
|
||||
|
||||
// Texture coordinate 1
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, texCoord2)));
|
||||
}
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
glVertexAttrib4fv(2, color.Array());
|
||||
|
||||
UpdateRenderingMode();
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, texCoord)));
|
||||
|
||||
int first = offset / sizeof(VertexTex2);
|
||||
// Texture coordinate 1
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, texCoord2)));
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(type), first, vertexCount);
|
||||
glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount);
|
||||
}
|
||||
|
||||
void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
VertexCol* vs = const_cast<VertexCol*>(vertices);
|
||||
|
||||
unsigned int size = vertexCount * sizeof(VertexCol);
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffers[2];
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vs, size);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offsetof(VertexCol, coord)));
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexCol, coord)));
|
||||
|
||||
// Normal
|
||||
glDisableVertexAttribArray(1);
|
||||
glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f);
|
||||
// Normal
|
||||
glDisableVertexAttribArray(1);
|
||||
glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offsetof(VertexCol, color)));
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexCol, color)));
|
||||
|
||||
// Texture coordinate 0
|
||||
glDisableVertexAttribArray(3);
|
||||
glVertexAttrib2f(3, 0.0f, 0.0f);
|
||||
// Texture coordinate 0
|
||||
glDisableVertexAttribArray(3);
|
||||
glVertexAttrib2f(3, 0.0f, 0.0f);
|
||||
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
}
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
|
||||
UpdateRenderingMode();
|
||||
glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount);
|
||||
}
|
||||
|
||||
int first = offset / sizeof(VertexCol);
|
||||
void CGL33Device::DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(type), first, vertexCount);
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vertices, size);
|
||||
|
||||
// Update vertex attribute bindings
|
||||
UpdateVertexAttribute(0, format.vertex, offset);
|
||||
UpdateVertexAttribute(1, format.normal, offset);
|
||||
UpdateVertexAttribute(2, format.color, offset);
|
||||
UpdateVertexAttribute(3, format.tex1, offset);
|
||||
UpdateVertexAttribute(4, format.tex2, offset);
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount);
|
||||
}
|
||||
|
||||
void CGL33Device::DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vertices, size);
|
||||
|
||||
// Update vertex attribute bindings
|
||||
UpdateVertexAttribute(0, format.vertex, offset);
|
||||
UpdateVertexAttribute(1, format.normal, offset);
|
||||
UpdateVertexAttribute(2, format.color, offset);
|
||||
UpdateVertexAttribute(3, format.tex1, offset);
|
||||
UpdateVertexAttribute(4, format.tex2, offset);
|
||||
|
||||
glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount);
|
||||
}
|
||||
|
||||
void CGL33Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
||||
int first[], int count[], int drawCount, Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
Vertex* vs = const_cast<Vertex*>(vertices);
|
||||
|
||||
int vertexCount = 0;
|
||||
|
@ -1227,56 +1221,44 @@ void CGL33Device::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
|||
|
||||
unsigned int size = vertexCount * sizeof(Vertex);
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffers[0];
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vs, size);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, coord)));
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offset + offsetof(Vertex, coord)));
|
||||
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offsetof(Vertex, texCoord)));
|
||||
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
}
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offset + offsetof(Vertex, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
glVertexAttrib4fv(2, color.Array());
|
||||
|
||||
UpdateRenderingMode();
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
|
||||
reinterpret_cast<void*>(offset + offsetof(Vertex, texCoord)));
|
||||
|
||||
int firstOffset = offset / sizeof(Vertex);
|
||||
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
first[i] += firstOffset;
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
|
||||
glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount);
|
||||
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
first[i] -= firstOffset;
|
||||
}
|
||||
|
||||
void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
|
||||
int first[], int count[], int drawCount, Color color)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
VertexTex2* vs = const_cast<VertexTex2*>(vertices);
|
||||
|
||||
int vertexCount = 0;
|
||||
|
@ -1291,57 +1273,45 @@ void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
|
|||
|
||||
unsigned int size = vertexCount * sizeof(VertexTex2);
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffers[1];
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vs, size);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, coord)));
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, coord)));
|
||||
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, texCoord)));
|
||||
|
||||
// Texture coordinate 1
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offsetof(VertexTex2, texCoord2)));
|
||||
}
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, normal)));
|
||||
|
||||
// Color
|
||||
glDisableVertexAttribArray(2);
|
||||
glVertexAttrib4fv(2, color.Array());
|
||||
|
||||
UpdateRenderingMode();
|
||||
// Texture coordinate 0
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, texCoord)));
|
||||
|
||||
int firstOffset = offset / sizeof(VertexTex2);
|
||||
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
first[i] += firstOffset;
|
||||
// Texture coordinate 1
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexTex2, texCoord2)));
|
||||
|
||||
glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount);
|
||||
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
first[i] -= firstOffset;
|
||||
}
|
||||
|
||||
void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexCol *vertices,
|
||||
int first[], int count[], int drawCount)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
VertexCol* vs = const_cast<VertexCol*>(vertices);
|
||||
|
||||
int vertexCount = 0;
|
||||
|
@ -1356,49 +1326,36 @@ void CGL33Device::DrawPrimitives(PrimitiveType type, const VertexCol *vertices,
|
|||
|
||||
unsigned int size = vertexCount * sizeof(VertexCol);
|
||||
|
||||
DynamicBuffer& buffer = m_dynamicBuffers[2];
|
||||
DynamicBuffer& buffer = m_dynamicBuffer;
|
||||
|
||||
BindVAO(buffer.vao);
|
||||
BindVBO(buffer.vbo);
|
||||
|
||||
unsigned int offset = UploadVertexData(buffer, vs, size);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offsetof(VertexCol, coord)));
|
||||
// Vertex coordinate
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexCol, coord)));
|
||||
|
||||
// Normal
|
||||
glDisableVertexAttribArray(1);
|
||||
glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f);
|
||||
// Normal
|
||||
glDisableVertexAttribArray(1);
|
||||
glVertexAttrib3f(1, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offsetof(VertexCol, color)));
|
||||
// Color
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(VertexCol),
|
||||
reinterpret_cast<void*>(offset + offsetof(VertexCol, color)));
|
||||
|
||||
// Texture coordinate 0
|
||||
glDisableVertexAttribArray(3);
|
||||
glVertexAttrib2f(3, 0.0f, 0.0f);
|
||||
// Texture coordinate 0
|
||||
glDisableVertexAttribArray(3);
|
||||
glVertexAttrib2f(3, 0.0f, 0.0f);
|
||||
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
UpdateRenderingMode();
|
||||
|
||||
int firstOffset = offset / sizeof(VertexCol);
|
||||
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
first[i] += firstOffset;
|
||||
// Texture coordinate 1
|
||||
glDisableVertexAttribArray(4);
|
||||
glVertexAttrib2f(4, 0.0f, 0.0f);
|
||||
|
||||
glMultiDrawArrays(TranslateGfxPrimitive(type), first, count, drawCount);
|
||||
|
||||
for (int i = 0; i < drawCount; i++)
|
||||
first[i] -= firstOffset;
|
||||
}
|
||||
|
||||
unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount)
|
||||
|
@ -1716,14 +1673,14 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit
|
|||
|
||||
void CGL33Device::DrawStaticBuffer(unsigned int bufferId)
|
||||
{
|
||||
if (m_updateLights) UpdateLights();
|
||||
|
||||
auto it = m_vboObjects.find(bufferId);
|
||||
if (it == m_vboObjects.end())
|
||||
return;
|
||||
|
||||
VertexBufferInfo &info = (*it).second;
|
||||
|
||||
UpdateRenderingMode();
|
||||
|
||||
BindVAO(info.vao);
|
||||
|
||||
GLenum mode = TranslateGfxPrimitive(info.primitiveType);
|
||||
|
@ -1851,7 +1808,9 @@ void CGL33Device::SetRenderState(RenderState state, bool enabled)
|
|||
{
|
||||
m_lighting = enabled;
|
||||
|
||||
glUniform1i(m_uni->lightingEnabled, enabled ? 1 : 0);
|
||||
m_updateLights = true;
|
||||
|
||||
//glUniform1i(m_uni->lightingEnabled, enabled ? 1 : 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1977,13 +1936,9 @@ void CGL33Device::CopyFramebufferToTexture(Texture& texture, int xOffset, int yO
|
|||
{
|
||||
if (texture.id == 0) return;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
BindTexture(m_freeTexture, texture.id);
|
||||
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height);
|
||||
|
||||
// Restore previous texture
|
||||
glBindTexture(GL_TEXTURE_2D, m_currentTextures[0].id);
|
||||
}
|
||||
|
||||
std::unique_ptr<CFrameBufferPixels> CGL33Device::GetFrameBufferPixels() const
|
||||
|
@ -2029,16 +1984,52 @@ void CGL33Device::DeleteFramebuffer(std::string name)
|
|||
}
|
||||
}
|
||||
|
||||
void CGL33Device::UpdateRenderingMode()
|
||||
inline void CGL33Device::UpdateTextureState(int index)
|
||||
{
|
||||
bool enabled = m_texturesEnabled[0] && m_currentTextures[0].id != 0;
|
||||
glUniform1i(m_uni->textureEnabled[0], enabled ? 1 : 0);
|
||||
bool enabled = m_texturesEnabled[index] && (m_currentTextures[index].id != 0);
|
||||
glUniform1i(m_uni->textureEnabled[index], enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
enabled = m_texturesEnabled[1] && m_currentTextures[1].id != 0;
|
||||
glUniform1i(m_uni->textureEnabled[1], enabled ? 1 : 0);
|
||||
void CGL33Device::UpdateLights()
|
||||
{
|
||||
m_updateLights = false;
|
||||
|
||||
enabled = m_texturesEnabled[2] && m_currentTextures[2].id != 0;
|
||||
glUniform1i(m_uni->textureEnabled[2], enabled ? 1 : 0);
|
||||
// If not in normal rendering mode, return immediately
|
||||
if (m_mode != 0) return;
|
||||
|
||||
// Lighting enabled
|
||||
if (m_lighting)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
// Iterate all lights
|
||||
for (unsigned int i = 0; i < m_lights.size(); i++)
|
||||
{
|
||||
// If disabled, ignore and continue
|
||||
if (!m_lightsEnabled[i]) continue;
|
||||
|
||||
// If not directional, ignore and continue
|
||||
if (m_lights[i].type != LIGHT_DIRECTIONAL) continue;
|
||||
|
||||
Light &light = m_lights[i];
|
||||
LightLocations &uni = m_uni->lights[index];
|
||||
|
||||
glUniform4fv(uni.ambient, 1, light.ambient.Array());
|
||||
glUniform4fv(uni.diffuse, 1, light.diffuse.Array());
|
||||
glUniform4fv(uni.specular, 1, light.specular.Array());
|
||||
|
||||
glUniform4f(uni.position, -light.direction.x, -light.direction.y, -light.direction.z, 0.0f);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
glUniform1i(m_uni->lightCount, index);
|
||||
}
|
||||
// Lighting disabled
|
||||
else
|
||||
{
|
||||
glUniform1i(m_uni->lightCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline void CGL33Device::BindVBO(GLuint vbo)
|
||||
|
@ -2057,7 +2048,13 @@ inline void CGL33Device::BindVAO(GLuint vao)
|
|||
m_currentVAO = vao;
|
||||
}
|
||||
|
||||
unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, void* data, unsigned int size)
|
||||
inline void CGL33Device::BindTexture(int index, GLuint texture)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, const void* data, unsigned int size)
|
||||
{
|
||||
unsigned int nextOffset = buffer.offset + size;
|
||||
|
||||
|
@ -2095,6 +2092,25 @@ unsigned int CGL33Device::UploadVertexData(DynamicBuffer& buffer, void* data, un
|
|||
return currentOffset;
|
||||
}
|
||||
|
||||
void CGL33Device::UpdateVertexAttribute(int index, const VertexAttribute &attribute, int offset)
|
||||
{
|
||||
if (attribute.enabled)
|
||||
{
|
||||
glEnableVertexAttribArray(index);
|
||||
glVertexAttribPointer(index,
|
||||
attribute.size,
|
||||
TranslateType(attribute.type),
|
||||
attribute.normalized ? GL_TRUE : GL_FALSE,
|
||||
attribute.stride,
|
||||
reinterpret_cast<void*>(offset + attribute.offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisableVertexAttribArray(index);
|
||||
glVertexAttrib4fv(index, attribute.values);
|
||||
}
|
||||
}
|
||||
|
||||
bool CGL33Device::IsAnisotropySupported()
|
||||
{
|
||||
return m_capabilities.anisotropySupported;
|
||||
|
|
|
@ -115,6 +115,11 @@ public:
|
|||
|
||||
void SetTextureStageWrap(int index, Gfx::TexWrapMode wrapS, Gfx::TexWrapMode wrapT) override;
|
||||
|
||||
virtual void DrawPrimitive(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int vertexCount) override;
|
||||
virtual void DrawPrimitives(PrimitiveType type, const void *vertices,
|
||||
int size, const VertexFormat &format, int first[], int count[], int drawCount) override;
|
||||
|
||||
virtual void DrawPrimitive(PrimitiveType type, const Vertex *vertices , int vertexCount,
|
||||
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f)) override;
|
||||
virtual void DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount,
|
||||
|
@ -193,16 +198,22 @@ public:
|
|||
private:
|
||||
//! Updates the texture params for given texture stage
|
||||
void UpdateTextureParams(int index);
|
||||
//! Updates rendering mode
|
||||
void UpdateRenderingMode();
|
||||
//! Updates texture state
|
||||
inline void UpdateTextureState(int index);
|
||||
//! Update light parameters
|
||||
void UpdateLights();
|
||||
|
||||
//! Binds VBO
|
||||
inline void BindVBO(GLuint vbo);
|
||||
//! Binds VAO
|
||||
inline void BindVAO(GLuint vao);
|
||||
//! Binds texture
|
||||
inline void BindTexture(int index, GLuint texture);
|
||||
|
||||
//! Uploads data to dynamic buffer and returns offset to it
|
||||
unsigned int UploadVertexData(DynamicBuffer& buffer, void* data, unsigned int size);
|
||||
unsigned int UploadVertexData(DynamicBuffer& buffer, const void* data, unsigned int size);
|
||||
|
||||
inline void UpdateVertexAttribute(int index, const VertexAttribute &attribute, int offset);
|
||||
|
||||
private:
|
||||
//! Current config
|
||||
|
@ -226,6 +237,8 @@ private:
|
|||
|
||||
//! Whether lighting is enabled
|
||||
bool m_lighting = false;
|
||||
//! true means that light update is needed
|
||||
bool m_updateLights = false;
|
||||
//! Current lights
|
||||
std::vector<Light> m_lights;
|
||||
//! Current lights enable status
|
||||
|
@ -240,6 +253,8 @@ private:
|
|||
|
||||
//! Set of all created textures
|
||||
std::set<Texture> m_allTextures;
|
||||
//! Free texture unit
|
||||
const int m_freeTexture = 3;
|
||||
|
||||
//! Type of vertex structure
|
||||
enum VertexType
|
||||
|
@ -283,7 +298,7 @@ private:
|
|||
//! Shader program for shadow rendering
|
||||
GLuint m_shadowProgram = 0;
|
||||
|
||||
DynamicBuffer m_dynamicBuffers[3];
|
||||
DynamicBuffer m_dynamicBuffer;
|
||||
|
||||
//! Current mode
|
||||
unsigned int m_mode = 0;
|
||||
|
|
|
@ -335,8 +335,10 @@ GLenum TranslateGfxPrimitive(PrimitiveType type)
|
|||
case PRIMITIVE_POINTS: flag = GL_POINTS; break;
|
||||
case PRIMITIVE_LINES: flag = GL_LINES; break;
|
||||
case PRIMITIVE_LINE_STRIP: flag = GL_LINE_STRIP; break;
|
||||
case PRIMITIVE_LINE_LOOP: flag = GL_LINE_LOOP; break;
|
||||
case PRIMITIVE_TRIANGLES: flag = GL_TRIANGLES; break;
|
||||
case PRIMITIVE_TRIANGLE_STRIP: flag = GL_TRIANGLE_STRIP; break;
|
||||
case PRIMITIVE_TRIANGLE_FAN: flag = GL_TRIANGLE_FAN; break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
return flag;
|
||||
|
@ -441,6 +443,23 @@ GLenum TranslateTextureCoordinateGen(int index)
|
|||
return textureCoordGen[index];
|
||||
}
|
||||
|
||||
GLenum TranslateType(Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::BYTE: return GL_BYTE;
|
||||
case Type::UBYTE: return GL_UNSIGNED_BYTE;
|
||||
case Type::SHORT: return GL_SHORT;
|
||||
case Type::USHORT: return GL_UNSIGNED_SHORT;
|
||||
case Type::INT: return GL_INT;
|
||||
case Type::UINT: return GL_UNSIGNED_INT;
|
||||
case Type::HALF: return GL_HALF_FLOAT;
|
||||
case Type::FLOAT: return GL_FLOAT;
|
||||
case Type::DOUBLE: return GL_DOUBLE;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string lastShaderError;
|
||||
|
||||
std::string GetLastShaderError()
|
||||
|
|
|
@ -93,6 +93,8 @@ GLenum TranslateTextureCoordinate(int index);
|
|||
|
||||
GLenum TranslateTextureCoordinateGen(int index);
|
||||
|
||||
GLenum TranslateType(Type type);
|
||||
|
||||
std::string GetLastShaderError();
|
||||
|
||||
GLint LoadShader(GLint type, const char* filename);
|
||||
|
@ -192,8 +194,8 @@ struct UniformLocations
|
|||
//! Shadow color
|
||||
GLint shadowColor = -1;
|
||||
|
||||
//! true enables lighting
|
||||
GLint lightingEnabled = -1;
|
||||
// Number of enabled lights
|
||||
GLint lightCount = -1;
|
||||
//! Ambient color
|
||||
GLint ambientColor = -1;
|
||||
//! Diffuse color
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
// FRAGMENT SHADER - NORMAL MODE
|
||||
#version 120
|
||||
|
||||
#define CONFIG_QUALITY_SHADOWS 1
|
||||
|
||||
uniform sampler2D uni_PrimaryTexture;
|
||||
uniform sampler2D uni_SecondaryTexture;
|
||||
uniform sampler2DShadow uni_ShadowTexture;
|
||||
|
@ -34,6 +36,26 @@ uniform vec4 uni_FogColor;
|
|||
|
||||
uniform float uni_ShadowColor;
|
||||
|
||||
struct LightParams
|
||||
{
|
||||
vec4 Position;
|
||||
vec4 Ambient;
|
||||
vec4 Diffuse;
|
||||
vec4 Specular;
|
||||
};
|
||||
|
||||
struct Material
|
||||
{
|
||||
vec4 ambient;
|
||||
vec4 diffuse;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform Material uni_Material;
|
||||
|
||||
uniform int uni_LightCount;
|
||||
uniform LightParams uni_Light[4];
|
||||
|
||||
varying float pass_Distance;
|
||||
varying vec4 pass_Color;
|
||||
varying vec3 pass_Normal;
|
||||
|
@ -47,6 +69,55 @@ void main()
|
|||
{
|
||||
vec4 color = pass_Color;
|
||||
|
||||
if (uni_LightCount > 0)
|
||||
{
|
||||
vec4 ambient = vec4(0.0f);
|
||||
vec4 diffuse = vec4(0.0f);
|
||||
vec4 specular = vec4(0.0f);
|
||||
|
||||
vec3 normal = normalize(pass_Normal);
|
||||
|
||||
for (int i = 0; i < uni_LightCount; i++)
|
||||
{
|
||||
LightParams light = uni_Light[i];
|
||||
|
||||
vec3 lightDirection = light.Position.xyz;
|
||||
vec3 reflectDirection = -reflect(lightDirection, normal);
|
||||
|
||||
float diffuseComponent = clamp(dot(normal, lightDirection), 0.0f, 1.0f);
|
||||
float specularComponent = clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f);
|
||||
|
||||
ambient += light.Ambient;
|
||||
diffuse += diffuseComponent * light.Diffuse;
|
||||
specular += specularComponent * light.Specular;
|
||||
}
|
||||
|
||||
float shadow = 1.0f;
|
||||
|
||||
if (uni_TextureEnabled[2])
|
||||
{
|
||||
#ifdef CONFIG_QUALITY_SHADOWS
|
||||
float offset = 0.00025f;
|
||||
|
||||
float value = (1.0f / 5.0f) * (shadow2D(uni_ShadowTexture, pass_TexCoord2).x
|
||||
+ shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( offset, 0.0f, 0.0f)).x
|
||||
+ shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3(-offset, 0.0f, 0.0f)).x
|
||||
+ shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( 0.0f, offset, 0.0f)).x
|
||||
+ shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( 0.0f, -offset, 0.0f)).x);
|
||||
|
||||
shadow = mix(uni_ShadowColor, 1.0f, value);
|
||||
#else
|
||||
shadow = mix(uni_ShadowColor, 1.0f, shadow2D(uni_ShadowTexture, pass_TexCoord2).x);
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 result = ambient * uni_Material.ambient
|
||||
+ diffuse * uni_Material.diffuse * shadow
|
||||
+ specular * uni_Material.specular * shadow;
|
||||
|
||||
color = clamp(vec4(result.rgb, 1.0f), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
if (uni_TextureEnabled[0])
|
||||
{
|
||||
color = color * texture2D(uni_PrimaryTexture, pass_TexCoord0);
|
||||
|
@ -57,16 +128,6 @@ void main()
|
|||
color = color * texture2D(uni_SecondaryTexture, pass_TexCoord1);
|
||||
}
|
||||
|
||||
if (uni_TextureEnabled[2])
|
||||
{
|
||||
vec3 normal = pass_Normal * (2.0f * gl_Color.x - 1.0f);
|
||||
|
||||
if (dot(normal, const_LightDirection) < 0.0f)
|
||||
color.rgb *= uni_ShadowColor;
|
||||
else
|
||||
color.rgb *= mix(uni_ShadowColor, 1.0f, shadow2D(uni_ShadowTexture, pass_TexCoord2).x);
|
||||
}
|
||||
|
||||
if (uni_FogEnabled)
|
||||
{
|
||||
float interpolate = (pass_Distance - uni_FogRange.x) / (uni_FogRange.y - uni_FogRange.x);
|
||||
|
|
|
@ -25,33 +25,6 @@ uniform mat4 uni_ModelMatrix;
|
|||
uniform mat4 uni_ShadowMatrix;
|
||||
uniform mat4 uni_NormalMatrix;
|
||||
|
||||
struct LightParams
|
||||
{
|
||||
bool Enabled;
|
||||
int Type;
|
||||
vec4 Position;
|
||||
vec4 Ambient;
|
||||
vec4 Diffuse;
|
||||
vec4 Specular;
|
||||
float Shininess;
|
||||
vec3 Attenuation;
|
||||
vec3 SpotDirection;
|
||||
float SpotCutoff;
|
||||
float SpotExponent;
|
||||
};
|
||||
|
||||
struct Material
|
||||
{
|
||||
vec4 ambient;
|
||||
vec4 diffuse;
|
||||
vec4 specular;
|
||||
};
|
||||
|
||||
uniform Material uni_Material;
|
||||
|
||||
uniform bool uni_LightingEnabled;
|
||||
uniform LightParams uni_Light[8];
|
||||
|
||||
varying float pass_Distance;
|
||||
varying vec4 pass_Color;
|
||||
varying vec3 pass_Normal;
|
||||
|
@ -65,75 +38,11 @@ void main()
|
|||
vec4 eyeSpace = uni_ViewMatrix * position;
|
||||
vec4 shadowCoord = uni_ShadowMatrix * position;
|
||||
|
||||
vec4 color = gl_Color;
|
||||
|
||||
vec3 normal = normalize((uni_NormalMatrix * vec4(gl_Normal, 0.0f)).xyz);
|
||||
|
||||
if (uni_LightingEnabled)
|
||||
{
|
||||
vec4 ambient = vec4(0.0f);
|
||||
vec4 diffuse = vec4(0.0f);
|
||||
vec4 specular = vec4(0.0f);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (uni_Light[i].Enabled)
|
||||
{
|
||||
LightParams light = uni_Light[i];
|
||||
|
||||
vec3 lightDirection = light.Position.xyz;
|
||||
float atten = 1.0f;
|
||||
|
||||
if (light.Position.w > 0.5f)
|
||||
{
|
||||
float dist = distance(light.Position.xyz, position.xyz);
|
||||
|
||||
float atten = 1.0f / dot(light.Attenuation,
|
||||
vec3(1.0f, dist, dist * dist));
|
||||
|
||||
lightDirection = normalize(light.Position.xyz - position.xyz);
|
||||
}
|
||||
|
||||
float spot = 1.0f;
|
||||
|
||||
if (light.SpotCutoff > 0.0f)
|
||||
{
|
||||
float cone = dot(light.SpotDirection, lightDirection);
|
||||
|
||||
if (cone > light.SpotCutoff)
|
||||
{
|
||||
spot = pow(cone, light.SpotExponent);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 reflectDirection = -reflect(lightDirection, normal);
|
||||
|
||||
float component = atten * spot;
|
||||
float diffuseComponent = clamp(dot(normal, lightDirection), 0.0f, 1.0f);
|
||||
float specularComponent = clamp(pow(dot(normal, lightDirection + reflectDirection), light.Shininess), 0.0f, 1.0f);
|
||||
|
||||
ambient += component * light.Ambient * uni_Material.ambient;
|
||||
diffuse += component * diffuseComponent * light.Diffuse * uni_Material.diffuse;
|
||||
specular += component * specularComponent * light.Specular * uni_Material.specular;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 result = ambient + diffuse + specular;
|
||||
|
||||
color = clamp(vec4(result.rgb, uni_Material.diffuse), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
gl_Position = uni_ProjectionMatrix * eyeSpace;
|
||||
gl_FrontColor = vec4(1.0f);
|
||||
gl_BackColor = vec4(0.0f);
|
||||
|
||||
pass_Color = gl_Color;
|
||||
pass_Normal = normalize((uni_NormalMatrix * vec4(gl_Normal, 0.0f)).xyz);
|
||||
pass_Distance = abs(eyeSpace.z / eyeSpace.w);
|
||||
pass_Color = color;
|
||||
pass_Normal = normal;
|
||||
pass_TexCoord0 = gl_MultiTexCoord0.st;
|
||||
pass_TexCoord1 = gl_MultiTexCoord1.st;
|
||||
pass_TexCoord2 = shadowCoord.xyz / shadowCoord.w;
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
// FRAGMENT SHADER - NORMAL MODE
|
||||
#version 330 core
|
||||
|
||||
#define CONFIG_QUALITY_SHADOWS 1
|
||||
|
||||
uniform sampler2D uni_PrimaryTexture;
|
||||
uniform sampler2D uni_SecondaryTexture;
|
||||
uniform sampler2DShadow uni_ShadowTexture;
|
||||
|
@ -37,11 +39,27 @@ uniform float uni_ShadowColor;
|
|||
uniform bool uni_AlphaTestEnabled;
|
||||
uniform float uni_AlphaReference;
|
||||
|
||||
struct LightParams
|
||||
{
|
||||
vec4 Position;
|
||||
vec4 Ambient;
|
||||
vec4 Diffuse;
|
||||
vec4 Specular;
|
||||
};
|
||||
|
||||
uniform vec4 uni_AmbientColor;
|
||||
uniform vec4 uni_DiffuseColor;
|
||||
uniform vec4 uni_SpecularColor;
|
||||
|
||||
uniform int uni_LightCount;
|
||||
uniform LightParams uni_Light[4];
|
||||
|
||||
in VertexData
|
||||
{
|
||||
vec4 Color;
|
||||
vec2 TexCoord0;
|
||||
vec2 TexCoord1;
|
||||
vec3 Normal;
|
||||
vec4 ShadowCoord;
|
||||
vec4 LightColor;
|
||||
float Distance;
|
||||
|
@ -53,6 +71,53 @@ void main()
|
|||
{
|
||||
vec4 color = data.Color;
|
||||
|
||||
if (uni_LightCount > 0)
|
||||
{
|
||||
vec4 ambient = vec4(0.0f);
|
||||
vec4 diffuse = vec4(0.0f);
|
||||
vec4 specular = vec4(0.0f);
|
||||
|
||||
vec3 normal = normalize(data.Normal);
|
||||
|
||||
for (int i = 0; i < uni_LightCount; i++)
|
||||
{
|
||||
vec3 lightDirection = uni_Light[i].Position.xyz;
|
||||
|
||||
vec3 reflectDirection = -reflect(lightDirection, normal);
|
||||
|
||||
ambient += uni_Light[i].Ambient;
|
||||
diffuse += clamp(dot(normal, lightDirection), 0.0f, 1.0f)
|
||||
* uni_Light[i].Diffuse;
|
||||
specular += clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f)
|
||||
* uni_Light[i].Specular;
|
||||
}
|
||||
|
||||
float shadow = 1.0f;
|
||||
|
||||
if (uni_ShadowTextureEnabled)
|
||||
{
|
||||
#ifdef CONFIG_QUALITY_SHADOWS
|
||||
float offset = 0.00025f;
|
||||
|
||||
float value = (1.0f / 5.0f) * (texture(uni_ShadowTexture, data.ShadowCoord.xyz)
|
||||
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3( offset, 0.0f, 0.0f))
|
||||
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3(-offset, 0.0f, 0.0f))
|
||||
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3( 0.0f, offset, 0.0f))
|
||||
+ texture(uni_ShadowTexture, data.ShadowCoord.xyz + vec3( 0.0f, -offset, 0.0f)));
|
||||
|
||||
shadow = mix(uni_ShadowColor, 1.0f, value);
|
||||
#else
|
||||
shadow = mix(uni_ShadowColor, 1.0f, texture(uni_ShadowTexture, data.ShadowCoord.xyz));
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 result = uni_AmbientColor * ambient
|
||||
+ uni_DiffuseColor * diffuse * shadow
|
||||
+ uni_SpecularColor * specular * shadow;
|
||||
|
||||
color = vec4(min(vec3(1.0f), result.rgb), 1.0f);
|
||||
}
|
||||
|
||||
if (uni_PrimaryTextureEnabled)
|
||||
{
|
||||
color = color * texture(uni_PrimaryTexture, data.TexCoord0);
|
||||
|
@ -63,11 +128,6 @@ void main()
|
|||
color = color * texture(uni_SecondaryTexture, data.TexCoord1);
|
||||
}
|
||||
|
||||
if (uni_ShadowTextureEnabled)
|
||||
{
|
||||
color = color * mix(uni_ShadowColor, 1.0f, texture(uni_ShadowTexture, data.ShadowCoord.xyz));
|
||||
}
|
||||
|
||||
if (uni_FogEnabled)
|
||||
{
|
||||
float interpolate = (data.Distance - uni_FogRange.x) / (uni_FogRange.y - uni_FogRange.x);
|
||||
|
|
|
@ -20,24 +20,6 @@
|
|||
// VERTEX SHADER - NORMAL MODE
|
||||
#version 330 core
|
||||
|
||||
struct LightParams
|
||||
{
|
||||
bool Enabled;
|
||||
vec4 Position;
|
||||
vec4 Ambient;
|
||||
vec4 Diffuse;
|
||||
vec4 Specular;
|
||||
float Shininess;
|
||||
vec3 Attenuation;
|
||||
};
|
||||
|
||||
uniform vec4 uni_AmbientColor;
|
||||
uniform vec4 uni_DiffuseColor;
|
||||
uniform vec4 uni_SpecularColor;
|
||||
|
||||
uniform bool uni_LightingEnabled;
|
||||
uniform LightParams uni_Light[8];
|
||||
|
||||
uniform mat4 uni_ProjectionMatrix;
|
||||
uniform mat4 uni_ViewMatrix;
|
||||
uniform mat4 uni_ModelMatrix;
|
||||
|
@ -55,6 +37,7 @@ out VertexData
|
|||
vec4 Color;
|
||||
vec2 TexCoord0;
|
||||
vec2 TexCoord1;
|
||||
vec3 Normal;
|
||||
vec4 ShadowCoord;
|
||||
vec4 LightColor;
|
||||
float Distance;
|
||||
|
@ -70,58 +53,7 @@ void main()
|
|||
data.Color = in_Color;
|
||||
data.TexCoord0 = in_TexCoord0;
|
||||
data.TexCoord1 = in_TexCoord1;
|
||||
data.Normal = normalize((uni_NormalMatrix * vec4(in_Normal, 0.0f)).xyz);
|
||||
data.ShadowCoord = vec4(shadowCoord.xyz / shadowCoord.w, 1.0f);
|
||||
data.Distance = abs(eyeSpace.z);
|
||||
|
||||
vec4 color = in_Color;
|
||||
|
||||
if (uni_LightingEnabled)
|
||||
{
|
||||
vec4 ambient = vec4(0.0f);
|
||||
vec4 diffuse = vec4(0.0f);
|
||||
vec4 specular = vec4(0.0f);
|
||||
|
||||
vec3 normal = normalize((uni_NormalMatrix * vec4(in_Normal, 0.0f)).xyz);
|
||||
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
if(uni_Light[i].Enabled)
|
||||
{
|
||||
vec3 lightDirection = vec3(0.0f);
|
||||
float atten;
|
||||
|
||||
// Directional light
|
||||
if(uni_Light[i].Position[3] == 0.0f)
|
||||
{
|
||||
lightDirection = uni_Light[i].Position.xyz;
|
||||
atten = 1.0f;
|
||||
}
|
||||
// Point light
|
||||
else
|
||||
{
|
||||
vec3 lightDirection = normalize(uni_Light[i].Position.xyz - position.xyz);
|
||||
float dist = distance(uni_Light[i].Position.xyz, position.xyz);
|
||||
|
||||
atten = 1.0f / (uni_Light[i].Attenuation.x
|
||||
+ uni_Light[i].Attenuation.y * dist
|
||||
+ uni_Light[i].Attenuation.z * dist * dist);
|
||||
}
|
||||
|
||||
vec3 reflectDirection = -reflect(lightDirection, normal);
|
||||
|
||||
ambient += uni_Light[i].Ambient;
|
||||
diffuse += atten * clamp(dot(normal, lightDirection), 0.0f, 1.0f) * uni_Light[i].Diffuse;
|
||||
specular += atten * clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f) * uni_Light[i].Specular;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 result = uni_AmbientColor * ambient
|
||||
+ uni_DiffuseColor * diffuse
|
||||
+ uni_SpecularColor * specular;
|
||||
|
||||
color.rgb = min(vec3(1.0f), result.rgb);
|
||||
color.a = 1.0f; //min(1.0f, 1.0f);
|
||||
|
||||
data.Color = color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -467,6 +467,8 @@ ObjectType CLevelParserParam::ToObjectType(std::string value)
|
|||
if (value == "Barrier1" ) return OBJECT_BARRIER1;
|
||||
if (value == "Barrier2" ) return OBJECT_BARRIER2;
|
||||
if (value == "Barrier3" ) return OBJECT_BARRIER3;
|
||||
if (value == "Barricade0" ) return OBJECT_BARRICADE0;
|
||||
if (value == "Barricade1" ) return OBJECT_BARRICADE1;
|
||||
if (value == "Teen0" ) return OBJECT_TEEN0;
|
||||
if (value == "Teen1" ) return OBJECT_TEEN1;
|
||||
if (value == "Teen2" ) return OBJECT_TEEN2;
|
||||
|
@ -662,6 +664,8 @@ const std::string CLevelParserParam::FromObjectType(ObjectType value)
|
|||
if (value == OBJECT_BARRIER1 ) return "Barrier1";
|
||||
if (value == OBJECT_BARRIER2 ) return "Barrier2";
|
||||
if (value == OBJECT_BARRIER3 ) return "Barrier3";
|
||||
if (value == OBJECT_BARRICADE0 ) return "Barricade0";
|
||||
if (value == OBJECT_BARRICADE1 ) return "Barricade1";
|
||||
if (value == OBJECT_TEEN0 ) return "Teen0";
|
||||
if (value == OBJECT_TEEN1 ) return "Teen1";
|
||||
if (value == OBJECT_TEEN2 ) return "Teen2";
|
||||
|
|
|
@ -133,7 +133,7 @@ std::string CPlayerProfile::GetLastName()
|
|||
{
|
||||
std::string name;
|
||||
|
||||
if(!GetConfigFile().GetStringProperty("Gamer", "LastName", name))
|
||||
if(!GetConfigFile().GetStringProperty("Gamer", "LastName", name) || name.empty())
|
||||
GetResource(RES_TEXT, RT_NAME_DEFAULT, name);
|
||||
|
||||
return name;
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "level/mainmovie.h"
|
||||
#include "level/player_profile.h"
|
||||
#include "level/scene_conditions.h"
|
||||
#include "level/scoreboard.h"
|
||||
|
||||
#include "level/parser/parser.h"
|
||||
|
||||
|
@ -202,8 +203,8 @@ CRobotMain::CRobotMain()
|
|||
m_editLock = false;
|
||||
m_editFull = false;
|
||||
m_hilite = false;
|
||||
m_selectInsect = false;
|
||||
m_showSoluce = false;
|
||||
m_cheatSelectInsect = false;
|
||||
m_cheatShowSoluce = false;
|
||||
|
||||
m_codeBattleInit = false;
|
||||
m_codeBattleStarted = false;
|
||||
|
@ -211,14 +212,14 @@ CRobotMain::CRobotMain()
|
|||
m_teamNames.clear();
|
||||
|
||||
#if DEV_BUILD
|
||||
m_showAll = true; // for development
|
||||
m_cheatAllMission = true; // for development
|
||||
#else
|
||||
m_showAll = false;
|
||||
m_cheatAllMission = false;
|
||||
#endif
|
||||
|
||||
m_cheatRadar = false;
|
||||
m_fixScene = false;
|
||||
m_trainerPilot = false;
|
||||
m_cheatTrainerPilot = false;
|
||||
m_friendAim = false;
|
||||
m_resetCreate = false;
|
||||
m_shortCut = true;
|
||||
|
@ -451,7 +452,7 @@ void CRobotMain::ChangePhase(Phase phase)
|
|||
m_lightning->Flush();
|
||||
m_planet->Flush();
|
||||
m_interface->Flush();
|
||||
FlushNewScriptName();
|
||||
m_newScriptName.clear();
|
||||
m_sound->SetListener(Math::Vector(0.0f, 0.0f, 0.0f), Math::Vector(0.0f, 0.0f, 1.0f));
|
||||
m_sound->StopAll();
|
||||
m_camera->SetType(Gfx::CAM_TYPE_NULL);
|
||||
|
@ -763,6 +764,7 @@ bool CRobotMain::ProcessEvent(Event &event)
|
|||
m_interface->SetFocus(pe);
|
||||
if (m_phase == PHASE_SIMUL) m_cmdEditPause = m_pause->ActivatePause(PAUSE_ENGINE);
|
||||
m_cmdEdit = true;
|
||||
m_commandHistoryIndex = -1; // no element selected in command history
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -777,6 +779,28 @@ bool CRobotMain::ProcessEvent(Event &event)
|
|||
}
|
||||
}
|
||||
|
||||
// Browse forward command history with UP key
|
||||
if (event.type == EVENT_KEY_DOWN &&
|
||||
event.GetData<KeyEventData>()->key == KEY(UP) && m_cmdEdit)
|
||||
{
|
||||
Ui::CEdit* pe = static_cast<Ui::CEdit*>(m_interface->SearchControl(EVENT_CMD));
|
||||
if (pe == nullptr) return false;
|
||||
std::string cmd = GetNextFromCommandHistory();
|
||||
if (!cmd.empty()) pe->SetText(cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Browse backward command history with DOWN key
|
||||
if (event.type == EVENT_KEY_DOWN &&
|
||||
event.GetData<KeyEventData>()->key == KEY(DOWN) && m_cmdEdit)
|
||||
{
|
||||
Ui::CEdit* pe = static_cast<Ui::CEdit*>(m_interface->SearchControl(EVENT_CMD));
|
||||
if (pe == nullptr) return false;
|
||||
std::string cmd = GetPreviousFromCommandHistory();
|
||||
if (!cmd.empty()) pe->SetText(cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.type == EVENT_KEY_DOWN &&
|
||||
event.GetData<KeyEventData>()->key == KEY(RETURN) && m_cmdEdit)
|
||||
{
|
||||
|
@ -793,6 +817,7 @@ bool CRobotMain::ProcessEvent(Event &event)
|
|||
m_cmdEditPause = nullptr;
|
||||
}
|
||||
ExecuteCmd(cmd);
|
||||
PushToCommandHistory(cmd);
|
||||
m_cmdEdit = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -922,7 +947,7 @@ bool CRobotMain::ProcessEvent(Event &event)
|
|||
}
|
||||
if (data->slot == INPUT_SLOT_HUMAN)
|
||||
{
|
||||
SelectHuman();
|
||||
SelectObject(SearchHuman());
|
||||
}
|
||||
if (data->slot == INPUT_SLOT_NEXT && ((event.kmodState & KEY_MOD(CTRL)) != 0))
|
||||
{
|
||||
|
@ -1159,7 +1184,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
|
||||
if (cmd == "trainerpilot")
|
||||
{
|
||||
m_trainerPilot = !m_trainerPilot;
|
||||
m_cheatTrainerPilot = !m_cheatTrainerPilot;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1410,20 +1435,20 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
|
||||
if (cmd == "selectinsect")
|
||||
{
|
||||
m_selectInsect = !m_selectInsect;
|
||||
m_cheatSelectInsect = !m_cheatSelectInsect;
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd == "showsoluce")
|
||||
{
|
||||
m_showSoluce = !m_showSoluce;
|
||||
m_cheatShowSoluce = !m_cheatShowSoluce;
|
||||
m_ui->ShowSoluceUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd == "allmission")
|
||||
{
|
||||
m_showAll = !m_showAll;
|
||||
m_cheatAllMission = !m_cheatAllMission;
|
||||
m_ui->AllMissionUpdate();
|
||||
return;
|
||||
}
|
||||
|
@ -1763,20 +1788,17 @@ void CRobotMain::StopDisplayVisit()
|
|||
|
||||
|
||||
|
||||
//! Updates all the shortcuts
|
||||
void CRobotMain::UpdateShortcuts()
|
||||
{
|
||||
m_short->UpdateShortcuts();
|
||||
}
|
||||
|
||||
//! Returns the object that default was select after the creation of a scene
|
||||
CObject* CRobotMain::GetSelectObject()
|
||||
{
|
||||
if (m_selectObject != nullptr) return m_selectObject;
|
||||
return SearchHuman();
|
||||
}
|
||||
|
||||
//! Deselects everything, and returns the object that was selected
|
||||
CObject* CRobotMain::DeselectAll()
|
||||
{
|
||||
CObject* prev = nullptr;
|
||||
|
@ -1833,17 +1855,8 @@ void CRobotMain::SelectOneObject(CObject* obj, bool displayError)
|
|||
{
|
||||
m_camera->SetType(Gfx::CAM_TYPE_BACK);
|
||||
}
|
||||
|
||||
CObject* toto = SearchToto();
|
||||
if (toto != nullptr)
|
||||
{
|
||||
assert(toto->Implements(ObjectInterfaceType::Movable));
|
||||
CMotionToto* mt = static_cast<CMotionToto*>(dynamic_cast<CMovableObject*>(toto)->GetMotion());
|
||||
mt->SetLinkType(type);
|
||||
}
|
||||
}
|
||||
|
||||
//! Selects the object aimed by the mouse
|
||||
bool CRobotMain::SelectObject(CObject* obj, bool displayError)
|
||||
{
|
||||
if (m_camera->GetType() == Gfx::CAM_TYPE_VISIT)
|
||||
|
@ -1851,7 +1864,8 @@ bool CRobotMain::SelectObject(CObject* obj, bool displayError)
|
|||
|
||||
if (m_movieLock || m_editLock) return false;
|
||||
if (m_movie->IsExist()) return false;
|
||||
if (obj != nullptr && !IsSelectable(obj)) return false;
|
||||
if (obj != nullptr &&
|
||||
(!obj->Implements(ObjectInterfaceType::Controllable) || !(dynamic_cast<CControllableObject*>(obj)->GetSelectable() || m_cheatSelectInsect))) return false;
|
||||
|
||||
if (m_missionType == MISSION_CODE_BATTLE && m_codeBattleStarted && m_codeBattleSpectator)
|
||||
{
|
||||
|
@ -1882,7 +1896,6 @@ bool CRobotMain::SelectObject(CObject* obj, bool displayError)
|
|||
return true;
|
||||
}
|
||||
|
||||
//! Deselects the selected object
|
||||
bool CRobotMain::DeselectObject()
|
||||
{
|
||||
DeselectAll();
|
||||
|
@ -1918,49 +1931,11 @@ void CRobotMain::DeleteAllObjects()
|
|||
m_objMan->DeleteAllObjects();
|
||||
}
|
||||
|
||||
//! Selects the human
|
||||
void CRobotMain::SelectHuman()
|
||||
{
|
||||
SelectObject(SearchHuman());
|
||||
}
|
||||
|
||||
//! Returns the object human
|
||||
CObject* CRobotMain::SearchHuman()
|
||||
{
|
||||
return m_objMan->FindNearest(nullptr, OBJECT_HUMAN);
|
||||
}
|
||||
|
||||
//! Returns the object toto
|
||||
CObject* CRobotMain::SearchToto()
|
||||
{
|
||||
return m_objMan->FindNearest(nullptr, OBJECT_TOTO);
|
||||
}
|
||||
|
||||
//! Returns the nearest selectable object from a given position
|
||||
CObject* CRobotMain::SearchNearest(Math::Vector pos, CObject* exclu)
|
||||
{
|
||||
float min = 100000.0f;
|
||||
CObject* best = nullptr;
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (obj == exclu) continue;
|
||||
if (!IsSelectable(obj)) continue;
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
if (type == OBJECT_TOTO) continue;
|
||||
|
||||
Math::Vector oPos = obj->GetPosition();
|
||||
float dist = Math::DistanceProjected(oPos, pos);
|
||||
if (dist < min)
|
||||
{
|
||||
min = dist;
|
||||
best = obj;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
//! Returns the selected object
|
||||
CObject* CRobotMain::GetSelect()
|
||||
{
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
|
@ -2019,30 +1994,6 @@ CObject* CRobotMain::DetectObject(Math::Point pos)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
//! Indicates whether an object is selectable
|
||||
// TODO: Refactor this, calling CControllableObject::GetSelectable should always be enough
|
||||
bool CRobotMain::IsSelectable(CObject* obj)
|
||||
{
|
||||
if (obj->GetType() == OBJECT_TOTO) return true;
|
||||
if (!obj->Implements(ObjectInterfaceType::Controllable)) return false;
|
||||
|
||||
if (!m_selectInsect)
|
||||
{
|
||||
// TODO: Some function in CControllableObject
|
||||
if ( obj->GetType() == OBJECT_MOTHER ||
|
||||
obj->GetType() == OBJECT_ANT ||
|
||||
obj->GetType() == OBJECT_SPIDER ||
|
||||
obj->GetType() == OBJECT_BEE ||
|
||||
obj->GetType() == OBJECT_WORM ||
|
||||
obj->GetType() == OBJECT_MOBILEtg )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return dynamic_cast<CControllableObject*>(obj)->GetSelectable();
|
||||
}
|
||||
|
||||
|
||||
//! Deletes the selected object
|
||||
bool CRobotMain::DestroySelectedObject()
|
||||
|
@ -2136,10 +2087,13 @@ void CRobotMain::HiliteObject(Math::Point pos)
|
|||
}
|
||||
}
|
||||
|
||||
if (IsSelectable(obj))
|
||||
if (obj->Implements(ObjectInterfaceType::Controllable) && (dynamic_cast<CControllableObject*>(obj)->GetSelectable() || m_cheatSelectInsect))
|
||||
{
|
||||
assert(obj->Implements(ObjectInterfaceType::Controllable));
|
||||
dynamic_cast<CControllableObject*>(obj)->SetHighlight(true);
|
||||
if (dynamic_cast<CControllableObject*>(obj)->GetSelectable())
|
||||
{
|
||||
// Don't highlight objects that would not be selectable without selectinsect
|
||||
dynamic_cast<CControllableObject*>(obj)->SetHighlight(true);
|
||||
}
|
||||
m_map->SetHighlight(obj);
|
||||
m_short->SetHighlight(obj);
|
||||
m_hilite = true;
|
||||
|
@ -2565,7 +2519,7 @@ bool CRobotMain::EventFrame(const Event &event)
|
|||
|
||||
if (m_phase == PHASE_SIMUL)
|
||||
{
|
||||
if (!m_editLock)
|
||||
if (!m_editLock && !m_engine->GetPause())
|
||||
{
|
||||
CheckEndMission(true);
|
||||
UpdateAudio(true);
|
||||
|
@ -2589,31 +2543,34 @@ bool CRobotMain::EventFrame(const Event &event)
|
|||
if (m_lostDelay <= 0.0f)
|
||||
{
|
||||
if (m_movieLock)
|
||||
m_winDelay = 1.0f;
|
||||
m_lostDelay = 1.0f;
|
||||
else
|
||||
m_eventQueue->AddEvent(Event(EVENT_LOST));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetMissionType() == MISSION_CODE_BATTLE)
|
||||
{
|
||||
if (!m_codeBattleInit)
|
||||
if (GetMissionType() == MISSION_CODE_BATTLE)
|
||||
{
|
||||
// NOTE: It's important to do this AFTER the first update event finished processing
|
||||
// because otherwise all robot parts are misplaced
|
||||
m_userPause = m_pause->ActivatePause(PAUSE_ENGINE);
|
||||
m_codeBattleInit = true; // Will start on resume
|
||||
}
|
||||
if (!m_codeBattleInit)
|
||||
{
|
||||
// NOTE: It's important to do this AFTER the first update event finished processing
|
||||
// because otherwise all robot parts are misplaced
|
||||
m_userPause = m_pause->ActivatePause(PAUSE_ENGINE);
|
||||
m_codeBattleInit = true; // Will start on resume
|
||||
}
|
||||
|
||||
if (!m_codeBattleStarted && m_userPause == nullptr)
|
||||
{
|
||||
m_codeBattleStarted = true;
|
||||
CreateCodeBattleInterface();
|
||||
if (!m_codeBattleStarted && m_userPause == nullptr)
|
||||
{
|
||||
m_codeBattleStarted = true;
|
||||
ApplyCodeBattleInterface();
|
||||
CreateCodeBattleInterface();
|
||||
|
||||
SetCodeBattleSpectatorMode(true);
|
||||
SetCodeBattleSpectatorMode(true);
|
||||
|
||||
m_eventQueue->AddEvent(Event(EVENT_UPDINTERFACE));
|
||||
m_eventQueue->AddEvent(Event(EVENT_UPDINTERFACE));
|
||||
}
|
||||
|
||||
UpdateCodeBattleInterface();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2672,7 +2629,6 @@ bool CRobotMain::EventObject(const Event &event)
|
|||
|
||||
|
||||
|
||||
//! Load the scene for the character
|
||||
void CRobotMain::ScenePerso()
|
||||
{
|
||||
DeleteAllObjects(); // removes all the current 3D Scene
|
||||
|
@ -2743,6 +2699,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
m_endTakeResearch = 0;
|
||||
m_endTakeWinDelay = 2.0f;
|
||||
m_endTakeLostDelay = 2.0f;
|
||||
m_teamFinished.clear();
|
||||
m_scoreboard.reset();
|
||||
m_globalMagnifyDamage = 1.0f;
|
||||
m_obligatoryTokens.clear();
|
||||
m_mapShow = true;
|
||||
|
@ -3365,6 +3323,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
assert(m_controller->Implements(ObjectInterfaceType::Programmable));
|
||||
assert(m_controller->Implements(ObjectInterfaceType::ProgramStorage));
|
||||
|
||||
assert(m_controller->Implements(ObjectInterfaceType::Old));
|
||||
dynamic_cast<COldObject*>(m_controller)->SetCheckToken(false);
|
||||
|
||||
if (line->GetParam("script")->IsDefined())
|
||||
{
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(m_controller);
|
||||
|
@ -3600,6 +3561,34 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "Scoreboard" && !resetObject)
|
||||
{
|
||||
if (line->GetParam("enable")->AsBool(false))
|
||||
{
|
||||
// Create the scoreboard
|
||||
m_scoreboard = MakeUnique<CScoreboard>();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (line->GetCommand() == "ScoreboardKillRule" && !resetObject)
|
||||
{
|
||||
if (!m_scoreboard)
|
||||
throw CLevelParserException("ScoreboardKillRule encountered but scoreboard is not enabled");
|
||||
auto rule = MakeUnique<CScoreboard::CScoreboardKillRule>();
|
||||
rule->Read(line.get());
|
||||
m_scoreboard->AddKillRule(std::move(rule));
|
||||
continue;
|
||||
}
|
||||
if (line->GetCommand() == "ScoreboardEndTakeRule" && !resetObject)
|
||||
{
|
||||
if (!m_scoreboard)
|
||||
throw CLevelParserException("ScoreboardEndTakeRule encountered but scoreboard is not enabled");
|
||||
auto rule = MakeUnique<CScoreboard::CScoreboardEndTakeRule>();
|
||||
rule->Read(line.get());
|
||||
m_scoreboard->AddEndTakeRule(std::move(rule));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line->GetCommand() == "ObligatoryToken" && !resetObject)
|
||||
{
|
||||
std::string token = line->GetParam("text")->AsString();
|
||||
|
@ -3649,7 +3638,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
|
||||
if (line->GetCommand() == "NewScript" && !resetObject)
|
||||
{
|
||||
AddNewScriptName(line->GetParam("type")->AsObjectType(OBJECT_NULL), const_cast<char*>(line->GetParam("name")->AsPath("ai").c_str()));
|
||||
m_newScriptName.push_back(NewScriptName(line->GetParam("type")->AsObjectType(OBJECT_NULL), const_cast<char*>(line->GetParam("name")->AsPath("ai").c_str())));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3970,15 +3959,17 @@ void CRobotMain::ChangeColor()
|
|||
}
|
||||
|
||||
//! Calculates the distance to the nearest object
|
||||
float CRobotMain::SearchNearestObject(Math::Vector center, CObject *exclu)
|
||||
namespace
|
||||
{
|
||||
float SearchNearestObject(CObjectManager* objMan, Math::Vector center, CObject* exclu)
|
||||
{
|
||||
float min = 100000.0f;
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
for (CObject* obj : objMan->GetAllObjects())
|
||||
{
|
||||
if (!obj->GetDetectable()) continue; // inactive?
|
||||
if (IsObjectBeingTransported(obj)) continue;
|
||||
|
||||
if (obj == exclu) continue;
|
||||
if (obj == exclu) continue;
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
|
||||
|
@ -3988,35 +3979,36 @@ float CRobotMain::SearchNearestObject(Math::Vector center, CObject *exclu)
|
|||
if (oPos.x != center.x ||
|
||||
oPos.z != center.z)
|
||||
{
|
||||
float dist = Math::Distance(center, oPos)-80.0f;
|
||||
float dist = Math::Distance(center, oPos) - 80.0f;
|
||||
if (dist < 0.0f) dist = 0.0f;
|
||||
min = Math::Min(min, dist);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == OBJECT_STATION ||
|
||||
type == OBJECT_REPAIR ||
|
||||
if (type == OBJECT_STATION ||
|
||||
type == OBJECT_REPAIR ||
|
||||
type == OBJECT_DESTROYER)
|
||||
{
|
||||
Math::Vector oPos = obj->GetPosition();
|
||||
float dist = Math::Distance(center, oPos)-8.0f;
|
||||
float dist = Math::Distance(center, oPos) - 8.0f;
|
||||
if (dist < 0.0f) dist = 0.0f;
|
||||
min = Math::Min(min, dist);
|
||||
}
|
||||
|
||||
for (const auto& crashSphere : obj->GetAllCrashSpheres())
|
||||
for (const auto &crashSphere : obj->GetAllCrashSpheres())
|
||||
{
|
||||
Math::Vector oPos = crashSphere.sphere.pos;
|
||||
float oRadius = crashSphere.sphere.radius;
|
||||
|
||||
float dist = Math::Distance(center, oPos)-oRadius;
|
||||
float dist = Math::Distance(center, oPos) - oRadius;
|
||||
if (dist < 0.0f) dist = 0.0f;
|
||||
min = Math::Min(min, dist);
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
}
|
||||
|
||||
//! Calculates a free space
|
||||
bool CRobotMain::FreeSpace(Math::Vector ¢er, float minRadius, float maxRadius,
|
||||
|
@ -4038,7 +4030,7 @@ bool CRobotMain::FreeSpace(Math::Vector ¢er, float minRadius, float maxRadiu
|
|||
pos.z = p.y;
|
||||
pos.y = 0.0f;
|
||||
m_terrain->AdjustToFloor(pos, true);
|
||||
float dist = SearchNearestObject(pos, exclu);
|
||||
float dist = SearchNearestObject(m_objMan.get(), pos, exclu);
|
||||
if (dist >= space)
|
||||
{
|
||||
float flat = m_terrain->GetFlatZoneRadius(pos, dist/2.0f);
|
||||
|
@ -4067,7 +4059,7 @@ bool CRobotMain::FreeSpace(Math::Vector ¢er, float minRadius, float maxRadiu
|
|||
pos.z = p.y;
|
||||
pos.y = 0.0f;
|
||||
m_terrain->AdjustToFloor(pos, true);
|
||||
float dist = SearchNearestObject(pos, exclu);
|
||||
float dist = SearchNearestObject(m_objMan.get(), pos, exclu);
|
||||
if (dist >= space)
|
||||
{
|
||||
float flat = m_terrain->GetFlatZoneRadius(pos, dist/2.0f);
|
||||
|
@ -4103,7 +4095,7 @@ bool CRobotMain::FlatFreeSpace(Math::Vector ¢er, float minFlat, float minRad
|
|||
pos.z = p.y;
|
||||
pos.y = 0.0f;
|
||||
m_terrain->AdjustToFloor(pos, true);
|
||||
float dist = SearchNearestObject(pos, exclu);
|
||||
float dist = SearchNearestObject(m_objMan.get(), pos, exclu);
|
||||
if (dist >= space)
|
||||
{
|
||||
float flat = m_terrain->GetFlatZoneRadius(pos, dist/2.0f);
|
||||
|
@ -4136,7 +4128,7 @@ bool CRobotMain::FlatFreeSpace(Math::Vector ¢er, float minFlat, float minRad
|
|||
pos.z = p.y;
|
||||
pos.y = 0.0f;
|
||||
m_terrain->AdjustToFloor(pos, true);
|
||||
float dist = SearchNearestObject(pos, exclu);
|
||||
float dist = SearchNearestObject(m_objMan.get(), pos, exclu);
|
||||
if (dist >= space)
|
||||
{
|
||||
float flat = m_terrain->GetFlatZoneRadius(pos, dist/2.0f);
|
||||
|
@ -4160,7 +4152,7 @@ bool CRobotMain::FlatFreeSpace(Math::Vector ¢er, float minFlat, float minRad
|
|||
float CRobotMain::GetFlatZoneRadius(Math::Vector center, float maxRadius,
|
||||
CObject *exclu)
|
||||
{
|
||||
float dist = SearchNearestObject(center, exclu);
|
||||
float dist = SearchNearestObject(m_objMan.get(), center, exclu);
|
||||
if (dist == 0.0f) return 0.0f;
|
||||
if (dist < maxRadius)
|
||||
maxRadius = dist;
|
||||
|
@ -4432,36 +4424,19 @@ bool CRobotMain::ReadFileStack(CObject *obj, FILE *file, int objRank)
|
|||
return programmable->ReadStack(file);
|
||||
}
|
||||
|
||||
|
||||
//! Empty the list
|
||||
void CRobotMain::FlushNewScriptName()
|
||||
std::vector<std::string> CRobotMain::GetNewScriptNames(ObjectType type)
|
||||
{
|
||||
m_newScriptName.clear();
|
||||
}
|
||||
|
||||
//! Adds a script name
|
||||
void CRobotMain::AddNewScriptName(ObjectType type, const std::string& name)
|
||||
{
|
||||
NewScriptName newscript;
|
||||
newscript.type = type;
|
||||
newscript.name = name;
|
||||
m_newScriptName.push_back(newscript);
|
||||
}
|
||||
|
||||
//! Seeks a script name for a given type
|
||||
std::string CRobotMain::GetNewScriptName(ObjectType type, int rank)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_newScriptName.size(); i++)
|
||||
std::vector<std::string> names;
|
||||
for (const auto& newScript : m_newScriptName)
|
||||
{
|
||||
if (m_newScriptName[i].type == type ||
|
||||
m_newScriptName[i].type == OBJECT_NULL )
|
||||
if (newScript.type == type ||
|
||||
newScript.type == OBJECT_NULL )
|
||||
{
|
||||
if (rank == 0) return m_newScriptName[i].name;
|
||||
else rank --;
|
||||
names.push_back(newScript.name);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4960,56 +4935,81 @@ Error CRobotMain::ProcessEndMissionTakeForGroup(std::vector<CSceneEndCondition*>
|
|||
Error CRobotMain::ProcessEndMissionTake()
|
||||
{
|
||||
// Sort end conditions by teams
|
||||
std::map<int, std::vector<CSceneEndCondition*>> teams;
|
||||
std::map<int, std::vector<CSceneEndCondition*>> teamsEndTake;
|
||||
for (std::unique_ptr<CSceneEndCondition>& endTake : m_endTake)
|
||||
teams[endTake->winTeam].push_back(endTake.get());
|
||||
teamsEndTake[endTake->winTeam].push_back(endTake.get());
|
||||
|
||||
int teamCount = 0;
|
||||
bool usesTeamConditions = false;
|
||||
for (auto it : teams)
|
||||
{
|
||||
int team = it.first;
|
||||
if (team == 0) continue;
|
||||
usesTeamConditions = true;
|
||||
if (!m_objMan->TeamExists(team)) continue;
|
||||
teamCount++;
|
||||
}
|
||||
// This is just a smart way to check if we have any map values other than 0 defined
|
||||
bool usesTeamConditions = teamsEndTake.size() > teamsEndTake.count(0);
|
||||
|
||||
if (!usesTeamConditions)
|
||||
{
|
||||
m_missionResult = ProcessEndMissionTakeForGroup(teams[0]);
|
||||
m_missionResult = ProcessEndMissionTakeForGroup(teamsEndTake[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special handling for teams
|
||||
m_missionResult = ERR_MISSION_NOTERM;
|
||||
|
||||
if (teamCount == 0)
|
||||
if (GetAllActiveTeams().empty())
|
||||
{
|
||||
GetLogger()->Info("All teams died, mission ended with failure\n");
|
||||
m_missionResult = INFO_LOST;
|
||||
GetLogger()->Info("All teams died, mission ended\n");
|
||||
if (m_scoreboard)
|
||||
{
|
||||
std::string title, text, details_line;
|
||||
GetResource(RES_TEXT, RT_SCOREBOARD_RESULTS, title);
|
||||
GetResource(RES_TEXT, RT_SCOREBOARD_RESULTS_TEXT, text);
|
||||
GetResource(RES_TEXT, RT_SCOREBOARD_RESULTS_LINE, details_line);
|
||||
std::string details = "";
|
||||
for (int team : GetAllTeams())
|
||||
{
|
||||
if (!details.empty())
|
||||
details += ", ";
|
||||
details += StrUtils::Format(details_line.c_str(), GetTeamName(team).c_str(), m_scoreboard->GetScore(team));
|
||||
}
|
||||
m_ui->GetDialog()->StartInformation(
|
||||
title,
|
||||
text,
|
||||
details,
|
||||
false, true,
|
||||
[&]() {
|
||||
ChangePhase(PHASE_WIN);
|
||||
}
|
||||
);
|
||||
m_endTakeWinDelay = 0.0f;
|
||||
m_missionResult = ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_missionResult = INFO_LOST;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto it : teams)
|
||||
for (auto it : teamsEndTake)
|
||||
{
|
||||
int team = it.first;
|
||||
if (team == 0) continue;
|
||||
if (!m_objMan->TeamExists(team)) continue;
|
||||
if (m_teamFinished[team]) continue;
|
||||
|
||||
Error result = ProcessEndMissionTakeForGroup(it.second);
|
||||
if (result == INFO_LOST || result == INFO_LOSTq)
|
||||
{
|
||||
GetLogger()->Info("Team %d lost\n", team);
|
||||
m_displayText->DisplayText(("<<< Team "+boost::lexical_cast<std::string>(team)+" lost! >>>").c_str(), Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 10.0f, Ui::TT_ERROR);
|
||||
std::string text;
|
||||
GetResource(RES_ERR, INFO_TEAM_DEAD, text);
|
||||
text = StrUtils::Format(text.c_str(), GetTeamName(team).c_str());
|
||||
m_displayText->DisplayText(text.c_str(), Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 10.0f, Ui::TT_ERROR);
|
||||
|
||||
m_displayText->SetEnable(false); // To prevent "bot destroyed" messages
|
||||
m_objMan->DestroyTeam(team);
|
||||
m_displayText->SetEnable(true);
|
||||
|
||||
m_teamFinished[team] = true;
|
||||
}
|
||||
else if (result == ERR_OK)
|
||||
{
|
||||
if (m_winDelay == 0.0f)
|
||||
/*if (m_winDelay == 0.0f)
|
||||
{
|
||||
GetLogger()->Info("Team %d won\n", team);
|
||||
|
||||
|
@ -5025,7 +5025,16 @@ Error CRobotMain::ProcessEndMissionTake()
|
|||
m_displayText->SetEnable(false);
|
||||
}
|
||||
m_missionResult = ERR_OK;
|
||||
return ERR_OK;
|
||||
return ERR_OK;*/
|
||||
GetLogger()->Info("Team %d finished\n", team);
|
||||
std::string text;
|
||||
GetResource(RES_ERR, INFO_TEAM_FINISH, text);
|
||||
text = StrUtils::Format(text.c_str(), GetTeamName(team).c_str());
|
||||
m_displayText->DisplayText(text.c_str(), Math::Vector(0.0f,0.0f,0.0f));
|
||||
if (m_scoreboard)
|
||||
m_scoreboard->ProcessEndTake(team);
|
||||
m_objMan->DestroyTeam(team, DestructionType::Win);
|
||||
m_teamFinished[team] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5054,7 +5063,6 @@ Error CRobotMain::CheckEndMission(bool frame)
|
|||
Error result = ProcessEndMissionTake();
|
||||
if (result != ERR_MISSION_NOTERM) return result;
|
||||
}
|
||||
|
||||
// Take action depending on m_missionResult
|
||||
|
||||
if (m_missionResult == INFO_LOSTq)
|
||||
|
@ -5135,7 +5143,7 @@ const std::map<std::string, MinMax>& CRobotMain::GetObligatoryTokenList()
|
|||
//! Indicates whether it is possible to control a driving robot
|
||||
bool CRobotMain::GetTrainerPilot()
|
||||
{
|
||||
return m_trainerPilot;
|
||||
return m_cheatTrainerPilot;
|
||||
}
|
||||
|
||||
//! Indicates whether the scene is fixed, without interaction
|
||||
|
@ -5158,7 +5166,7 @@ const std::string& CRobotMain::GetScriptFile()
|
|||
|
||||
bool CRobotMain::GetShowSoluce()
|
||||
{
|
||||
return m_showSoluce;
|
||||
return m_cheatShowSoluce;
|
||||
}
|
||||
|
||||
bool CRobotMain::GetSceneSoluce()
|
||||
|
@ -5169,7 +5177,7 @@ bool CRobotMain::GetSceneSoluce()
|
|||
|
||||
bool CRobotMain::GetShowAll()
|
||||
{
|
||||
return m_showAll;
|
||||
return m_cheatAllMission;
|
||||
}
|
||||
|
||||
bool CRobotMain::GetRadar()
|
||||
|
@ -5293,7 +5301,6 @@ void CRobotMain::UpdateSpeedLabel()
|
|||
}
|
||||
|
||||
|
||||
//! Creates interface shortcuts to the units
|
||||
bool CRobotMain::CreateShortcuts()
|
||||
{
|
||||
if (m_phase != PHASE_SIMUL) return false;
|
||||
|
@ -5638,7 +5645,7 @@ bool CRobotMain::IsBuildingEnabled(ObjectType type)
|
|||
if(type == OBJECT_PARA) return IsBuildingEnabled(BUILD_PARA);
|
||||
if(type == OBJECT_DESTROYER) return IsBuildingEnabled(BUILD_DESTROYER);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CRobotMain::IsResearchEnabled(ResearchType type)
|
||||
|
@ -5683,11 +5690,6 @@ Error CRobotMain::CanBuildError(ObjectType type, int team)
|
|||
return ERR_OK;
|
||||
}
|
||||
|
||||
bool CRobotMain::CanBuild(ObjectType type, int team)
|
||||
{
|
||||
return CanBuildError(type, team) == ERR_OK;
|
||||
}
|
||||
|
||||
Error CRobotMain::CanFactoryError(ObjectType type, int team)
|
||||
{
|
||||
ToolType tool = GetToolFromObject(type);
|
||||
|
@ -5711,11 +5713,6 @@ Error CRobotMain::CanFactoryError(ObjectType type, int team)
|
|||
return ERR_OK;
|
||||
}
|
||||
|
||||
bool CRobotMain::CanFactory(ObjectType type, int team)
|
||||
{
|
||||
return CanFactoryError(type, team) == ERR_OK;
|
||||
}
|
||||
|
||||
void CRobotMain::PushToSelectionHistory(CObject* obj)
|
||||
{
|
||||
if (!m_selectionHistory.empty() && m_selectionHistory.back() == obj)
|
||||
|
@ -5791,12 +5788,16 @@ void CRobotMain::StartDetectEffect(COldObject* object, CObject* target)
|
|||
|
||||
void CRobotMain::CreateCodeBattleInterface()
|
||||
{
|
||||
if(m_phase == PHASE_SIMUL)
|
||||
if (m_phase == PHASE_SIMUL)
|
||||
{
|
||||
Math::Point pos, ddim;
|
||||
|
||||
int numTeams = m_scoreboard ? GetAllTeams().size() : 0;
|
||||
assert(numTeams < EVENT_SCOREBOARD_MAX-EVENT_SCOREBOARD+1);
|
||||
float textHeight = m_engine->GetText()->GetHeight(Gfx::FONT_COLOBOT, Gfx::FONT_SIZE_SMALL);
|
||||
|
||||
ddim.x = 100.0f/640.0f;
|
||||
ddim.y = 100.0f/480.0f;
|
||||
ddim.y = 100.0f/480.0f + numTeams * textHeight;
|
||||
pos.x = 540.0f/640.0f;
|
||||
pos.y = 100.0f/480.0f;
|
||||
Ui::CWindow* pw = m_interface->CreateWindows(pos, ddim, 3, EVENT_WINDOW6);
|
||||
|
@ -5804,8 +5805,10 @@ void CRobotMain::CreateCodeBattleInterface()
|
|||
ddim.x = 100.0f/640.0f;
|
||||
ddim.y = 16.0f/480.0f;
|
||||
pos.x = 540.0f/640.0f;
|
||||
pos.y = 178.0f/480.0f;
|
||||
pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, "Code battle");
|
||||
pos.y = 178.0f/480.0f + numTeams * textHeight;
|
||||
std::string text;
|
||||
GetResource(RES_EVENT, EVENT_LABEL_CODE_BATTLE, text);
|
||||
pw->CreateLabel(pos, ddim, 0, EVENT_LABEL_CODE_BATTLE, text);
|
||||
|
||||
float titleBarSize = (11.0f/64.0f); // this is from the texture
|
||||
ddim.x = 80.0f/640.0f;
|
||||
|
@ -5820,6 +5823,84 @@ void CRobotMain::CreateCodeBattleInterface()
|
|||
{
|
||||
pw->CreateButton(pos, ddim, 13, EVENT_CODE_BATTLE_SPECTATOR);
|
||||
}
|
||||
|
||||
pos.y += ddim.y;
|
||||
ddim.y = textHeight;
|
||||
int i = 0;
|
||||
auto teams = GetAllTeams();
|
||||
for (auto it = teams.rbegin(); it != teams.rend(); ++it)
|
||||
{
|
||||
int team = *it;
|
||||
Ui::CControl* pl;
|
||||
ddim.x = 55.0f/640.0f;
|
||||
pl = m_codeBattleStarted
|
||||
? static_cast<Ui::CControl*>(pw->CreateLabel(pos, ddim, 0, static_cast<EventType>(EVENT_SCOREBOARD+2*(numTeams-i-1)+0), "XXXXX"))
|
||||
: static_cast<Ui::CControl*>(pw->CreateEdit( pos, ddim, 0, static_cast<EventType>(EVENT_SCOREBOARD+2*(numTeams-i-1)+0)));
|
||||
pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT);
|
||||
pl->SetFontSize(m_codeBattleStarted ? Gfx::FONT_SIZE_SMALL : Gfx::FONT_SIZE_SMALL*0.75f);
|
||||
m_codeBattleStarted ? pl->SetName(GetTeamName(team)) : static_cast<Ui::CEdit*>(pl)->SetText(GetTeamName(team));
|
||||
pos.x += 57.5f/640.0f;
|
||||
ddim.x = 22.5f/640.0f;
|
||||
pl = m_codeBattleStarted
|
||||
? static_cast<Ui::CControl*>(pw->CreateLabel(pos, ddim, 0, static_cast<EventType>(EVENT_SCOREBOARD+2*(numTeams-i-1)+1), "???"))
|
||||
: static_cast<Ui::CControl*>(pw->CreateEdit( pos, ddim, 0, static_cast<EventType>(EVENT_SCOREBOARD+2*(numTeams-i-1)+1)));
|
||||
pl->SetTextAlign(Gfx::TEXT_ALIGN_RIGHT);
|
||||
pl->SetFontSize(m_codeBattleStarted ? Gfx::FONT_SIZE_SMALL : Gfx::FONT_SIZE_SMALL*0.75f);
|
||||
m_codeBattleStarted ? pl->SetName(StrUtils::ToString<int>(m_scoreboard->GetScore(team))) : static_cast<Ui::CEdit*>(pl)->SetText(StrUtils::ToString<int>(m_scoreboard->GetScore(team)));
|
||||
pos.x -= 57.5f/640.0f;
|
||||
pos.y += ddim.y;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRobotMain::ApplyCodeBattleInterface()
|
||||
{
|
||||
assert(GetMissionType() == MISSION_CODE_BATTLE);
|
||||
if (!m_scoreboard) return;
|
||||
|
||||
Ui::CWindow* pw = static_cast<Ui::CWindow*>(m_interface->SearchControl(EVENT_WINDOW6));
|
||||
assert(pw != nullptr);
|
||||
|
||||
int i = 0;
|
||||
for (int team : GetAllTeams())
|
||||
{
|
||||
Ui::CEdit* pl;
|
||||
|
||||
pl = static_cast<Ui::CEdit*>(pw->SearchControl(static_cast<EventType>(EVENT_SCOREBOARD+2*i+0)));
|
||||
assert(pl != nullptr);
|
||||
m_teamNames[team] = pl->GetText(pl->GetTextLength());
|
||||
|
||||
pl = static_cast<Ui::CEdit*>(pw->SearchControl(static_cast<EventType>(EVENT_SCOREBOARD+2*i+1)));
|
||||
assert(pl != nullptr);
|
||||
m_scoreboard->SetScore(team, StrUtils::FromString<int>(pl->GetText(pl->GetTextLength())));
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void CRobotMain::UpdateCodeBattleInterface()
|
||||
{
|
||||
assert(GetMissionType() == MISSION_CODE_BATTLE);
|
||||
if (!m_scoreboard) return;
|
||||
|
||||
Ui::CWindow* pw = static_cast<Ui::CWindow*>(m_interface->SearchControl(EVENT_WINDOW6));
|
||||
assert(pw != nullptr);
|
||||
|
||||
int i = 0;
|
||||
for (int team : GetAllTeams())
|
||||
{
|
||||
Ui::CControl* pl;
|
||||
|
||||
pl = pw->SearchControl(static_cast<EventType>(EVENT_SCOREBOARD+2*i+0));
|
||||
assert(pl != nullptr);
|
||||
pl->SetName(GetTeamName(team));
|
||||
|
||||
pl = pw->SearchControl(static_cast<EventType>(EVENT_SCOREBOARD+2*i+1));
|
||||
assert(pl != nullptr);
|
||||
pl->SetName(StrUtils::ToString<int>(m_scoreboard->GetScore(team)));
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5866,3 +5947,55 @@ bool CRobotMain::GetDebugCrashSpheres()
|
|||
{
|
||||
return m_debugCrashSpheres;
|
||||
}
|
||||
|
||||
void CRobotMain::PushToCommandHistory(std::string str)
|
||||
{
|
||||
if (!m_commandHistory.empty() && m_commandHistory.front() == str) // already in history
|
||||
return;
|
||||
|
||||
m_commandHistory.push_front(str);
|
||||
|
||||
if (m_commandHistory.size() > 50) // to avoid infinite growth
|
||||
m_commandHistory.pop_back();
|
||||
}
|
||||
|
||||
std::string CRobotMain::GetNextFromCommandHistory()
|
||||
{
|
||||
if (m_commandHistory.empty() || static_cast<int>(m_commandHistory.size()) <= m_commandHistoryIndex + 1) // no next element
|
||||
return "";
|
||||
return m_commandHistory[++m_commandHistoryIndex];
|
||||
}
|
||||
|
||||
std::string CRobotMain::GetPreviousFromCommandHistory()
|
||||
{
|
||||
if (m_commandHistory.empty() || m_commandHistoryIndex < 1) // first or none element selected
|
||||
return "";
|
||||
return m_commandHistory[--m_commandHistoryIndex];
|
||||
}
|
||||
|
||||
CScoreboard* CRobotMain::GetScoreboard()
|
||||
{
|
||||
return m_scoreboard.get();
|
||||
}
|
||||
|
||||
std::set<int> CRobotMain::GetAllTeams()
|
||||
{
|
||||
std::set<int> teams = GetAllActiveTeams();
|
||||
for(auto& it : m_teamFinished)
|
||||
{
|
||||
teams.insert(it.first);
|
||||
}
|
||||
return teams;
|
||||
}
|
||||
|
||||
std::set<int> CRobotMain::GetAllActiveTeams()
|
||||
{
|
||||
std::set<int> teams;
|
||||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
int team = obj->GetTeam();
|
||||
if (team == 0) continue;
|
||||
teams.insert(team);
|
||||
}
|
||||
return teams;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,7 @@ class CInput;
|
|||
class CObjectManager;
|
||||
class CSceneEndCondition;
|
||||
class CAudioChangeCondition;
|
||||
class CScoreboard;
|
||||
class CPlayerProfile;
|
||||
class CSettings;
|
||||
class COldObject;
|
||||
|
@ -120,6 +121,8 @@ struct NewScriptName
|
|||
{
|
||||
ObjectType type = OBJECT_NULL;
|
||||
std::string name = "";
|
||||
|
||||
NewScriptName(ObjectType type, const std::string& name) : type(type), name(name) {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -156,6 +159,17 @@ const int SATCOM_PROG = 4;
|
|||
const int SATCOM_SOLUCE = 5;
|
||||
const int SATCOM_MAX = 6;
|
||||
|
||||
/**
|
||||
* \brief Main class managing the game world
|
||||
*
|
||||
* This is the main class of the whole game engine. It's main job is to manage main parts of the gameplay,
|
||||
* like loading levels and checking for win conditions, but it's also a place where all things that don't fit
|
||||
* elsewhere have landed.
|
||||
*
|
||||
* \todo In the future, it would be nice to refactor this class to remove as much unrelated stuff as possible
|
||||
*
|
||||
* \nosubgrouping
|
||||
*/
|
||||
class CRobotMain : public CSingleton<CRobotMain>
|
||||
{
|
||||
public:
|
||||
|
@ -168,11 +182,16 @@ public:
|
|||
Ui::CDisplayText* GetDisplayText();
|
||||
CPauseManager* GetPauseManager();
|
||||
|
||||
/**
|
||||
* \name Phase management
|
||||
*/
|
||||
//@{
|
||||
void ChangePhase(Phase phase);
|
||||
bool ProcessEvent(Event &event);
|
||||
Phase GetPhase();
|
||||
//@}
|
||||
|
||||
bool CreateShortcuts();
|
||||
//! Load the scene for apperance customization
|
||||
void ScenePerso();
|
||||
|
||||
void SetMovieLock(bool lock);
|
||||
|
@ -187,16 +206,32 @@ public:
|
|||
void SetFriendAim(bool friendAim);
|
||||
bool GetFriendAim();
|
||||
|
||||
//! \name Simulation speed management
|
||||
//@{
|
||||
void SetSpeed(float speed);
|
||||
float GetSpeed();
|
||||
//@}
|
||||
|
||||
//! \brief Create the shortcuts at the top of the screen, if they should be visible
|
||||
//! \see CMainShort::CreateShortcuts
|
||||
bool CreateShortcuts();
|
||||
//! \brief Update the shortcuts at the top of the screen
|
||||
//! \see CMainShort::UpdateShortcuts
|
||||
void UpdateShortcuts();
|
||||
void SelectHuman();
|
||||
//! Find the astronaut (::OBJECT_HUMAN) object
|
||||
CObject* SearchHuman();
|
||||
CObject* SearchToto();
|
||||
CObject* SearchNearest(Math::Vector pos, CObject* exclu);
|
||||
/**
|
||||
* \brief Select an object
|
||||
* \param obj Object to select
|
||||
* \param displayError If true and the object is currently in error state, automatically display the error message
|
||||
*
|
||||
* \note This function automatically adds objects to selection history (see PushToSelectionHistory())
|
||||
*/
|
||||
bool SelectObject(CObject* obj, bool displayError=true);
|
||||
//! Return the object that was selected at the start of the scene
|
||||
CObject* GetSelectObject();
|
||||
//! Deselect currently selected object
|
||||
//! \return Object that was deselected
|
||||
CObject* DeselectAll();
|
||||
|
||||
void ResetObject();
|
||||
|
@ -251,9 +286,10 @@ public:
|
|||
void ClearInterface();
|
||||
void ChangeColor();
|
||||
|
||||
float SearchNearestObject(Math::Vector center, CObject *exclu);
|
||||
bool FreeSpace(Math::Vector ¢er, float minRadius, float maxRadius, float space, CObject *exclu);
|
||||
bool FlatFreeSpace(Math::Vector ¢er, float minFlat, float minRadius, float maxRadius, float space, CObject *exclu);
|
||||
//! \name In-world indicators
|
||||
//@{
|
||||
float GetFlatZoneRadius(Math::Vector center, float maxRadius, CObject *exclu);
|
||||
void HideDropZone(CObject* metal);
|
||||
void ShowDropZone(CObject* metal, CObject* transporter);
|
||||
|
@ -262,28 +298,38 @@ public:
|
|||
float radius, float duration=SHOWLIMITTIME);
|
||||
void StartShowLimit();
|
||||
void FrameShowLimit(float rTime);
|
||||
//@}
|
||||
|
||||
void SaveAllScript();
|
||||
void SaveOneScript(CObject *obj);
|
||||
bool SaveFileStack(CObject *obj, FILE *file, int objRank);
|
||||
bool ReadFileStack(CObject *obj, FILE *file, int objRank);
|
||||
|
||||
void FlushNewScriptName();
|
||||
void AddNewScriptName(ObjectType type, const std::string& name);
|
||||
std::string GetNewScriptName(ObjectType type, int rank);
|
||||
//! Return list of scripts to load to robot created in BotFactory
|
||||
std::vector<std::string> GetNewScriptNames(ObjectType type);
|
||||
|
||||
//! Return the scoreboard manager
|
||||
//! Note: this may return nullptr if the scoreboard is not enabled!
|
||||
CScoreboard* GetScoreboard();
|
||||
|
||||
void SelectPlayer(std::string playerName);
|
||||
CPlayerProfile* GetPlayerProfile();
|
||||
|
||||
/**
|
||||
* \name Saved game read/write
|
||||
*/
|
||||
//@{
|
||||
bool IOIsBusy();
|
||||
bool IOWriteScene(std::string filename, std::string filecbot, std::string filescreenshot, const std::string& info, bool emergencySave = false);
|
||||
void IOWriteSceneFinished();
|
||||
CObject* IOReadScene(std::string filename, std::string filecbot);
|
||||
void IOWriteObject(CLevelParserLine *line, CObject* obj, const std::string& programDir, int objRank);
|
||||
CObject* IOReadObject(CLevelParserLine *line, const std::string& programDir, const std::string& objCounterText, float objectProgress, int objRank = -1);
|
||||
//@}
|
||||
|
||||
int CreateSpot(Math::Vector pos, Gfx::Color color);
|
||||
|
||||
//! Find the currently selected object
|
||||
CObject* GetSelect();
|
||||
|
||||
void DisplayError(Error err, CObject* pObj, float time=10.0f);
|
||||
|
@ -298,12 +344,17 @@ public:
|
|||
|
||||
void StartMissionTimer();
|
||||
|
||||
/**
|
||||
* \name Autosave management
|
||||
*/
|
||||
//@{
|
||||
void SetAutosave(bool enable);
|
||||
bool GetAutosave();
|
||||
void SetAutosaveInterval(int interval);
|
||||
int GetAutosaveInterval();
|
||||
void SetAutosaveSlots(int slots);
|
||||
int GetAutosaveSlots();
|
||||
//@}
|
||||
|
||||
//! Enable mode where completing mission closes the game
|
||||
void SetExitAfterMission(bool exit);
|
||||
|
@ -311,49 +362,97 @@ public:
|
|||
//! Returns true if player can interact with things manually
|
||||
bool CanPlayerInteract();
|
||||
|
||||
/**
|
||||
* \name Team definition management
|
||||
*/
|
||||
//@{
|
||||
//! Returns team name for the given team id
|
||||
const std::string& GetTeamName(int id);
|
||||
|
||||
//! Returns true if team-specific colored texture is available
|
||||
bool IsTeamColorDefined(int id);
|
||||
//@}
|
||||
|
||||
//! Get/set enabled buildings
|
||||
/**
|
||||
* \name EnableBuild/EnableResearch/DoneResearch
|
||||
* Management of enabled buildings, enabled researches, and completed researches
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* \brief Get enabled buildings
|
||||
* \return Bitmask of BuildType values
|
||||
*/
|
||||
int GetEnableBuild();
|
||||
/**
|
||||
* \brief Set enabled buildings
|
||||
* \param enableBuild Bitmask of BuildType values
|
||||
*/
|
||||
void SetEnableBuild(int enableBuild);
|
||||
//@}
|
||||
//! Get/set enabled researches
|
||||
//@{
|
||||
int GetEnableResearch();
|
||||
void SetEnableResearch(int enableResearch);
|
||||
//@}
|
||||
//! Get/set done researches
|
||||
//@{
|
||||
int GetDoneResearch(int team);
|
||||
void SetDoneResearch(int doneResearch, int team);
|
||||
//@}
|
||||
|
||||
//! Returns true if the given building is enabled
|
||||
//@{
|
||||
/**
|
||||
* \brief Get enabled researches
|
||||
* \return Bitmask of ResearchType values
|
||||
*/
|
||||
int GetEnableResearch();
|
||||
/**
|
||||
* \brief Set enabled researches
|
||||
* \param enableResearch Bitmask of ResearchType values
|
||||
*/
|
||||
void SetEnableResearch(int enableResearch);
|
||||
/**
|
||||
* \brief Get done researches
|
||||
* \param team Team to get researches for
|
||||
* \return Bitmask of ResearchType values
|
||||
*/
|
||||
int GetDoneResearch(int team = 0);
|
||||
/**
|
||||
* \brief Set done researches
|
||||
* \param doneResearch Bitmask of ResearchType values
|
||||
* \param team Team to set researches for
|
||||
*/
|
||||
void SetDoneResearch(int doneResearch, int team = 0);
|
||||
|
||||
//! \brief Check if the given building is enabled
|
||||
bool IsBuildingEnabled(BuildType type);
|
||||
//! \brief Check if the given building is enabled
|
||||
bool IsBuildingEnabled(ObjectType type);
|
||||
//@}
|
||||
//! Returns true if the given research is enabled
|
||||
//! \brief Check if the given research is enabled
|
||||
bool IsResearchEnabled(ResearchType type);
|
||||
//! Returns true if the given research is done
|
||||
//! \brief Check if the given research is done
|
||||
bool IsResearchDone(ResearchType type, int team);
|
||||
//! Marks research as done
|
||||
//! \brief Mark given research as done
|
||||
void MarkResearchDone(ResearchType type, int team);
|
||||
|
||||
//! Retruns true if all requirements to build this object are met (EnableBuild + DoneResearch)
|
||||
//@{
|
||||
bool CanBuild(ObjectType type, int team);
|
||||
/**
|
||||
* \brief Check if all requirements to build this object are met (EnableBuild + DoneResearch)
|
||||
* \return true if the building can be built, false otherwise
|
||||
* \see CanBuildError() for a version which returns a specific reason for the build being denied
|
||||
*/
|
||||
inline bool CanBuild(ObjectType type, int team)
|
||||
{
|
||||
return CanBuildError(type, team) == ERR_OK;
|
||||
}
|
||||
/**
|
||||
* \brief Check if all requirements to build this object are met (EnableBuild + DoneResearch)
|
||||
* \return One of Error values - ::ERR_OK if the building can be built, ::ERR_BUILD_DISABLED or ::ERR_BUILD_RESEARCH otherwise
|
||||
* \see CanBuild() for a version which returns a boolean
|
||||
*/
|
||||
Error CanBuildError(ObjectType type, int team);
|
||||
//@}
|
||||
|
||||
//! Retruns true if all requirements to create this object in BotFactory are met (DoneResearch)
|
||||
//@{
|
||||
bool CanFactory(ObjectType type, int team);
|
||||
/**
|
||||
* \brief Check if all requirements to build this object in BotFactory are met (DoneResearch)
|
||||
* \return true if the robot can be built, false otherwise
|
||||
* \see CanFactoryError() for a version which returns a specific reason for the build being denied
|
||||
*/
|
||||
inline bool CanFactory(ObjectType type, int team)
|
||||
{
|
||||
return CanFactoryError(type, team) == ERR_OK;
|
||||
}
|
||||
/**
|
||||
* \brief Check if all requirements to build this object in BotFactory are met (DoneResearch)
|
||||
* \return One of Error values - ::ERR_OK if the robot can be built, ::ERR_BUILD_DISABLED or ::ERR_BUILD_RESEARCH otherwise
|
||||
* \see CanFactory() for a version which returns a boolean
|
||||
*/
|
||||
Error CanFactoryError(ObjectType type, int team);
|
||||
//@}
|
||||
|
||||
|
@ -364,12 +463,16 @@ public:
|
|||
|
||||
void StartDetectEffect(COldObject* object, CObject* target);
|
||||
|
||||
bool IsSelectable(CObject* obj);
|
||||
|
||||
//! Enable crash sphere debug rendering
|
||||
void SetDebugCrashSpheres(bool draw);
|
||||
|
||||
//! Check if crash sphere debug rendering is enabled
|
||||
bool GetDebugCrashSpheres();
|
||||
|
||||
//! Returns a set of all team IDs in the current level
|
||||
std::set<int> GetAllTeams();
|
||||
//! Returns a set of all team IDs in the current level that are still active
|
||||
std::set<int> GetAllActiveTeams();
|
||||
|
||||
protected:
|
||||
bool EventFrame(const Event &event);
|
||||
bool EventObject(const Event &event);
|
||||
|
@ -391,8 +494,11 @@ protected:
|
|||
CObject* DetectObject(Math::Point pos);
|
||||
void ChangeCamera();
|
||||
void AbortMovie();
|
||||
//! \brief Select an object, without deselecting the previous one
|
||||
void SelectOneObject(CObject* obj, bool displayError=true);
|
||||
void HelpObject();
|
||||
//! \brief Switch to previous object
|
||||
//! \see PopFromSelectionHistory()
|
||||
bool DeselectObject();
|
||||
void DeleteAllObjects();
|
||||
void UpdateInfoText();
|
||||
|
@ -408,11 +514,24 @@ protected:
|
|||
void PushToSelectionHistory(CObject* obj);
|
||||
CObject* PopFromSelectionHistory();
|
||||
|
||||
//! \name Code battle interface
|
||||
//@{
|
||||
void CreateCodeBattleInterface();
|
||||
void UpdateCodeBattleInterface();
|
||||
void ApplyCodeBattleInterface();
|
||||
void DestroyCodeBattleInterface();
|
||||
void SetCodeBattleSpectatorMode(bool mode);
|
||||
//@}
|
||||
|
||||
void UpdateDebugCrashSpheres();
|
||||
|
||||
//! Adds element to the beginning of command history
|
||||
void PushToCommandHistory(std::string obj);
|
||||
//! Returns next/previous element from command history and updates index
|
||||
//@{
|
||||
std::string GetNextFromCommandHistory();
|
||||
std::string GetPreviousFromCommandHistory();
|
||||
//@}
|
||||
|
||||
protected:
|
||||
CApplication* m_app = nullptr;
|
||||
|
@ -472,9 +591,9 @@ protected:
|
|||
ActivePause* m_freePhotoPause = nullptr;
|
||||
bool m_cmdEdit = false;
|
||||
ActivePause* m_cmdEditPause = nullptr;
|
||||
bool m_selectInsect = false;
|
||||
bool m_showSoluce = false;
|
||||
bool m_showAll = false;
|
||||
bool m_cheatSelectInsect = false;
|
||||
bool m_cheatShowSoluce = false;
|
||||
bool m_cheatAllMission = false;
|
||||
bool m_cheatRadar = false;
|
||||
bool m_shortCut = false;
|
||||
std::string m_audioTrack;
|
||||
|
@ -496,7 +615,7 @@ protected:
|
|||
bool m_editLock = false; // edition in progress?
|
||||
bool m_editFull = false; // edition in full screen?
|
||||
bool m_hilite = false;
|
||||
bool m_trainerPilot = false; // remote trainer?
|
||||
bool m_cheatTrainerPilot = false; // remote trainer?
|
||||
bool m_friendAim = false;
|
||||
bool m_resetCreate = false;
|
||||
bool m_mapShow = false;
|
||||
|
@ -548,9 +667,15 @@ protected:
|
|||
long m_endTakeResearch = 0;
|
||||
float m_endTakeWinDelay = 0.0f;
|
||||
float m_endTakeLostDelay = 0.0f;
|
||||
//! Set to true for teams that have already finished
|
||||
std::map<int, bool> m_teamFinished;
|
||||
|
||||
std::vector<std::unique_ptr<CAudioChangeCondition>> m_audioChange;
|
||||
|
||||
//! The scoreboard
|
||||
//! If the scoreboard is not enabled for this level, this will be null
|
||||
std::unique_ptr<CScoreboard> m_scoreboard;
|
||||
|
||||
std::map<std::string, MinMax> m_obligatoryTokens;
|
||||
|
||||
//! Enabled buildings
|
||||
|
@ -585,4 +710,9 @@ protected:
|
|||
|
||||
std::deque<CObject*> m_selectionHistory;
|
||||
bool m_debugCrashSpheres;
|
||||
|
||||
//! Cheat console command history
|
||||
std::deque<std::string> m_commandHistory;
|
||||
//! Index of currently selected element in command history
|
||||
int m_commandHistoryIndex;
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue