1 // $Id: main.cpp 3275 2006-04-09 00:32:34Z sommer $
4 // Copyright (C) 2005 Matthias Braun <matze@braunis.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #include "script_manager.hpp"
29 #include <sqstdblob.h>
30 #include <sqstdmath.h>
31 #include <sqstdstring.h>
34 #include "console.hpp"
35 #include "scripting/wrapper.hpp"
36 #include "scripting/wrapper_util.hpp"
37 #include "scripting/squirrel_error.hpp"
38 #include "physfs/physfs_stream.hpp"
40 using namespace Scripting;
42 ScriptManager* ScriptManager::instance = NULL;
44 static void printfunc(HSQUIRRELVM, const char* str, ...)
48 va_start(arglist, str);
49 vsprintf(buf, str, arglist);
50 Console::output << (const char*) buf << std::flush;
54 ScriptManager::ScriptManager()
59 throw std::runtime_error("Couldn't initialize squirrel vm");
60 sq_setforeignptr(vm, (SQUserPointer) this);
62 // register squirrel libs
64 if(sqstd_register_bloblib(vm) < 0)
65 throw SquirrelError(vm, "Couldn't register blob lib");
66 if(sqstd_register_mathlib(vm) < 0)
67 throw SquirrelError(vm, "Couldn't register math lib");
68 if(sqstd_register_stringlib(vm) < 0)
69 throw SquirrelError(vm, "Couldn't register string lib");
70 // register supertux API
71 register_supertux_wrapper(vm);
74 // register print function
75 sq_setprintfunc(vm, printfunc);
76 // register default error handlers
77 sqstd_seterrorhandlers(vm);
80 ScriptManager::ScriptManager(ScriptManager* parent)
82 this->parent = parent;
84 parent->childs.push_back(this);
87 ScriptManager::~ScriptManager()
89 for(SquirrelVMs::iterator i = squirrel_vms.begin();
90 i != squirrel_vms.end(); ++i)
91 sq_release(vm, &(i->vm_obj));
95 std::remove(parent->childs.begin(), parent->childs.end(), this),
96 parent->childs.end());
103 ScriptManager::create_thread(bool leave_thread_on_stack)
105 HSQUIRRELVM new_vm = sq_newthread(vm, 64);
107 throw SquirrelError(vm, "Couldn't create new VM");
108 sq_setforeignptr(new_vm, (SQUserPointer) this);
110 // retrieve reference to thread from stack and increase refcounter
112 sq_resetobject(&vm_obj);
113 if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_obj))) {
114 throw SquirrelError(vm, "Couldn't get coroutine vm from stack");
116 sq_addref(vm, &vm_obj);
118 if(!leave_thread_on_stack)
121 squirrel_vms.push_back(SquirrelVM(new_vm, vm_obj));
127 ScriptManager::update()
129 for(SquirrelVMs::iterator i = squirrel_vms.begin(); i != squirrel_vms.end(); ) {
130 SquirrelVM& squirrel_vm = *i;
131 int vm_state = sq_getvmstate(squirrel_vm.vm);
133 if(vm_state == SQ_VMSTATE_SUSPENDED && squirrel_vm.wakeup_time > 0 && game_time >= squirrel_vm.wakeup_time) {
134 squirrel_vm.waiting_for_events = WakeupData(NO_EVENT);
136 if(SQ_FAILED(sq_wakeupvm(squirrel_vm.vm, false, false))) {
137 throw SquirrelError(squirrel_vm.vm, "Couldn't resume script");
139 } catch(std::exception& e) {
140 std::cerr << "Problem executing script: " << e.what() << "\n";
141 sq_release(vm, &squirrel_vm.vm_obj);
142 i = squirrel_vms.erase(i);
147 if (vm_state != SQ_VMSTATE_SUSPENDED) {
148 sq_release(vm, &(squirrel_vm.vm_obj));
149 i = squirrel_vms.erase(i);
157 ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupData event, float timeout)
159 assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT);
160 // find the VM in the list and update it
161 for(SquirrelVMs::iterator i = squirrel_vms.begin();
162 i != squirrel_vms.end(); ++i) {
163 SquirrelVM& squirrel_vm = *i;
164 if(squirrel_vm.vm == vm)
166 squirrel_vm.waiting_for_events = event;
169 squirrel_vm.wakeup_time = -1;
171 squirrel_vm.wakeup_time = game_time + timeout;
179 ScriptManager::fire_wakeup_event(WakeupData event)
181 assert(event.type >= 0 && event.type < WAKEUP_EVENT_COUNT);
182 for(SquirrelVMs::iterator i = squirrel_vms.begin();
183 i != squirrel_vms.end(); ++i) {
185 if(vm.waiting_for_events.type == event.type
186 && vm.waiting_for_events.type != NO_EVENT) {
187 vm.wakeup_time = game_time;
192 for(std::vector<ScriptManager*>::iterator i = childs.begin();
193 i != childs.end(); ++i) {
194 ScriptManager* child = *i;
195 child->fire_wakeup_event(event);
200 ScriptManager::set_wakeup_event(HSQUIRRELVM vm, WakeupEvent event, float timeout)
202 set_wakeup_event(vm, WakeupData(event), timeout);
206 ScriptManager::fire_wakeup_event(WakeupEvent event)
208 fire_wakeup_event(WakeupData(event));
211 ScriptManager::SquirrelVM::SquirrelVM(HSQUIRRELVM arg_vm, HSQOBJECT arg_obj)
212 : vm(arg_vm), vm_obj(arg_obj)
214 waiting_for_events = WakeupData(NO_EVENT);