Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/script/src/orxonox/core/Script.cc @ 1009

Last change on this file since 1009 was 999, checked in by bknecht, 17 years ago

some changes with the script. Made it singleton plus the files were moved into the core.

File size: 6.5 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Benjamin Knecht
23 *   Co-authors:
24 *      ...
25 *
26 */
27
28#include "Script.h"
29
30#include <fstream>
31#include <map>
32
33#include "../core/CoreIncludes.h"
34
35extern "C" {
36#include "lualib.h"
37#include "lauxlib.h"
38}
39
40#include "tolua++.h"
41#include "toluabind.h"
42
43namespace orxonox
44{
45
46  Script::Script()
47  {
48    luaState_ = lua_open();
49    luaSource_ = "";
50    tolua_something_open(luaState_);
51  }
52
53  void Script::luaPrint(std::string str)
54  {
55    output_ = str;
56  }
57
58  /**
59      @brief Loads the specified file line by line
60      @param filename The filename of the file
61      @param luaTags if true, the loaded file gets stripped off luaTags
62  */
63  void Script::loadFile(std::string filename, bool luaTags)
64  {
65    std::ifstream file;
66    file.open(filename.c_str(), std::fstream::in);
67
68    if (!file.is_open())
69    {
70      // some error msg
71    }
72
73    char line[1024];
74    std::string levelString = "";
75
76    while (file.good() && !file.eof())
77    {
78      file.getline(line, 1024);
79      levelString += line;
80    }
81
82    file.close();
83    //std::string output;
84
85    if (luaTags) luaSource_ = replaceLuaTags(levelString);
86  }
87
88  void Script::run()
89  {
90    int error = 0;
91    std::string init = "local scr = orxonox.Script:new()\n";
92    init += luaSource_;
93    error = luaL_loadstring(luaState_, init.c_str());
94    if (error == 0)
95      error = lua_pcall(luaState_, 0, 0, 0);
96    if (error != 0) COUT(0) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
97  }
98
99
100  unsigned int Script::getNextQuote(const std::string& text, unsigned int start)
101  {
102    unsigned int quote = start - 1;
103
104    while ((quote = text.find('\"', quote + 1)) != std::string::npos)
105    {
106      unsigned int backslash = quote;
107      unsigned int numbackslashes = 0;
108      for (; backslash > 0; backslash--, numbackslashes++)
109        if (text[backslash - 1] != '\\')
110          break;
111
112      if (numbackslashes % 2 == 0)
113        break;
114    }
115
116    return quote;
117  }
118
119  std::string Script::replaceLuaTags(const std::string& text)
120  {
121    // chreate map with all Lua tags
122    std::map<unsigned int, bool> luaTags;
123    {
124      unsigned int pos = 0;
125      while ((pos = text.find("<?lua", pos)) != std::string::npos)
126        luaTags[pos++] = true;
127    }
128    {
129      unsigned int pos = 0;
130      while ((pos = text.find("?>", pos)) != std::string::npos)
131        luaTags[pos++] = false;
132    }
133
134    // erase all tags from the map that are between two quotes
135    {
136      std::map<unsigned int, bool>::iterator it = luaTags.begin();
137      bool bBetweenQuotes = false;
138      unsigned int pos = 0;
139      while ((pos = getNextQuote(text, pos)) != std::string::npos)
140      {
141        while ((it != luaTags.end()) && ((*it).first < pos))
142        {
143          if (bBetweenQuotes)
144            luaTags.erase(it++);
145          else
146            ++it;
147        }
148        bBetweenQuotes = !bBetweenQuotes;
149        pos++;
150      }
151    }
152
153    // check whether on every opening <?lua tag a closing ?> tag follows
154    {
155      bool expectedValue = true;
156      for (std::map<unsigned int, bool>::iterator it = luaTags.begin(); it != luaTags.end(); ++it)
157      {
158        if ((*it).second == expectedValue)
159          expectedValue = !expectedValue;
160        else
161        {
162          expectedValue = false;
163          break;
164        }
165      }
166      if (!expectedValue) {
167        // todo: errorhandling
168        return "";
169      }
170    }
171
172    // cut the original string into pieces and put them together with print() instead of lua tags
173    std::string output;
174    {
175      std::map<unsigned int, bool>::iterator it = luaTags.begin();
176      bool bInPrintFunction = true;
177      unsigned int start = 0;
178      unsigned int end = 0;
179
180      do
181      {
182        if (it != luaTags.end())
183          end = (*(it++)).first;
184        else
185          end = std::string::npos;
186
187        unsigned int equalSignCounter = 0;
188
189        if (bInPrintFunction)
190        {
191          // count ['='[ and ]'='] and replace tags with print([[ and ]])
192          std::string temp = text.substr(start, end - start);
193          {
194            unsigned int pos = 0;
195            while ((pos = temp.find('[', pos)) != std::string::npos)
196            {
197              unsigned int tempCounter = 1;
198              unsigned int tempPos = pos++;
199              while(temp[++tempPos] == '=') {
200                tempCounter++;
201              }
202              if(temp[tempPos] != '[') {
203                tempCounter = 0;
204              }
205              else if(tempCounter == 0) {
206                tempCounter = 1;
207              }
208              if (tempCounter > equalSignCounter)
209                equalSignCounter = tempCounter;
210            }
211          }
212          {
213            unsigned int pos = 0;
214            while ((pos = temp.find(']', pos)) != std::string::npos)
215            {
216              unsigned int tempCounter = 1;
217              unsigned int tempPos = pos++;
218              while(temp[++tempPos] == '=') {
219                tempCounter++;
220              }
221              if(temp[tempPos] != ']') {
222                tempCounter = 0;
223              }
224              else if(tempCounter == 0) {
225                tempCounter = 1;
226              }
227              if (tempCounter > equalSignCounter)
228                equalSignCounter = tempCounter;
229            }
230          }
231          std::string equalSigns = "";
232          for(unsigned int i = 0; i < equalSignCounter; i++) {
233            equalSigns += "=";
234          }
235          output += "scr:luaPrint([" + equalSigns + "[" + temp + "]" + equalSigns +"])\n";
236          start = end + 5;
237        }
238        else
239        {
240          output += text.substr(start, end - start);
241          start = end + 2;
242        }
243
244        bInPrintFunction = !bInPrintFunction;
245      }
246      while (end != std::string::npos);
247    }
248
249    return output;
250  }
251
252}
Note: See TracBrowser for help on using the repository browser.