3 #include "script_interpreter.h"
10 #include <sqstdblob.h>
11 #include <sqstdsystem.h>
12 #include <sqstdmath.h>
13 #include <sqstdstring.h>
16 #include "wrapper_util.h"
18 #include "object/text_object.h"
19 #include "object/scripted_object.h"
20 #include "object/display_effect.h"
21 #include "scripting/sound.h"
22 #include "scripting/scripted_object.h"
23 #include "scripting/display_effect.h"
25 static void printfunc(HSQUIRRELVM, const char* str, ...)
28 va_start(arglist, str);
29 vprintf(str, arglist);
33 ScriptInterpreter* ScriptInterpreter::_current = 0;
35 ScriptInterpreter::ScriptInterpreter(Sector* sector)
40 throw std::runtime_error("Couldn't initialize squirrel vm");
42 // register default error handlers
43 sqstd_seterrorhandlers(v);
44 // register squirrel libs
46 if(sqstd_register_bloblib(v) < 0)
47 throw SquirrelError(v, "Couldn't register blob lib");
48 if(sqstd_register_iolib(v) < 0)
49 throw SquirrelError(v, "Couldn't register io lib");
50 if(sqstd_register_systemlib(v) < 0)
51 throw SquirrelError(v, "Couldn't register system lib");
52 if(sqstd_register_mathlib(v) < 0)
53 throw SquirrelError(v, "Couldn't register math lib");
54 if(sqstd_register_stringlib(v) < 0)
55 throw SquirrelError(v, "Couldn't register string lib");
57 // register print function
58 sq_setprintfunc(v, printfunc);
60 // register supertux API
61 register_functions(v, supertux_global_functions);
62 register_classes(v, supertux_classes);
64 // expose ScriptedObjects to the script
65 for(Sector::GameObjects::iterator i = sector->gameobjects.begin();
66 i != sector->gameobjects.end(); ++i) {
67 GameObject* object = *i;
68 Scripting::ScriptedObject* scripted_object
69 = dynamic_cast<Scripting::ScriptedObject*> (object);
73 expose_object(scripted_object, scripted_object->get_name(),
76 // expose some "global" objects
77 sound = new Scripting::Sound();
78 expose_object(sound, "Sound", "Sound");
80 level = new Scripting::Level();
81 expose_object(level, "Level", "Level");
83 TextObject* text_object = new TextObject();
84 sector->add_object(text_object);
85 Scripting::Text* text = static_cast<Scripting::Text*> (text_object);
86 expose_object(text, "Text", "Text");
88 DisplayEffect* display_effect = new DisplayEffect();
89 sector->add_object(display_effect);
90 Scripting::DisplayEffect* display_effect_api
91 = static_cast<Scripting::DisplayEffect*> (display_effect);
92 expose_object(display_effect_api, "DisplayEffect", "DisplayEffect");
95 ScriptInterpreter::~ScriptInterpreter()
102 static SQInteger squirrel_read_char(SQUserPointer file)
104 std::istream* in = reinterpret_cast<std::istream*> (file);
113 ScriptInterpreter::load_script(std::istream& in, const std::string& sourcename)
115 if(sq_compile(v, squirrel_read_char, &in, sourcename.c_str(), true) < 0)
116 throw SquirrelError(v, "Couldn't parse script");
120 ScriptInterpreter::start_script()
124 if(sq_call(v, 1, false) < 0)
125 throw SquirrelError(v, "Couldn't start script");
127 if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) {
128 printf("script ended...\n");
134 ScriptInterpreter::expose_object(void* object, const std::string& name,
135 const std::string& type)
137 // part1 of registration of the instance in the root table
139 sq_pushstring(v, name.c_str(), -1);
141 // resolve class name
143 sq_pushstring(v, type.c_str(), -1);
144 if(sq_get(v, -2) < 0) {
145 std::ostringstream msg;
146 msg << "Couldn't resolve squirrel type '" << type << "'.";
147 throw std::runtime_error(msg.str());
149 sq_remove(v, -2); // remove roottable
151 // create an instance and set pointer to c++ object
152 if(sq_createinstance(v, -1) < 0 || sq_setinstanceup(v, -1, object)) {
153 std::ostringstream msg;
154 msg << "Couldn't setup squirrel instance for object '"
155 << name << "' of type '" << type << "'.";
156 throw SquirrelError(v, msg.str());
159 sq_remove(v, -2); // remove class from stack
161 // part2 of registration of the instance in the root table
162 if(sq_createslot(v, -3) < 0)
163 throw SquirrelError(v, "Couldn't register object in squirrel root table"); sq_pop(v, 1);
167 ScriptInterpreter::set_wakeup_time(float seconds)
169 wakeup_timer.start(seconds);
173 ScriptInterpreter::update(float )
175 if(!wakeup_timer.check())
179 if(sq_wakeupvm(v, false, false) < 0)
180 throw SquirrelError(v, "Couldn't resume script");
182 if(sq_getvmstate(v) != SQ_VMSTATE_SUSPENDED) {
183 printf("script ended...\n");
189 ScriptInterpreter::draw(DrawingContext& )