FEATURE: Entity "stance" phase (fallback)
[Tsunagari.git] / src / scriptinst.cpp
blob8304b770c8795786111d909813d7a7af0b04103c
1 #include "log.h"
2 #include "python.h"
3 #include "resourcer.h"
4 #include "scriptinst.h"
6 struct validate_visitor : public boost::static_visitor<bool>
8 std::string context;
10 validate_visitor(const std::string& context) : context(context) {}
12 bool operator()(void*) const
14 return true;
17 bool operator()(ScriptInst::strref ref) const
19 Resourcer* rc = Resourcer::instance();
21 if (ref.filename.empty()) {
22 Log::err(context,
23 "script filename is empty");
24 return false;
27 if (!rc->resourceExists(ref.filename)) {
28 Log::err(context,
29 ref.filename + "script file not found");
30 return false;
33 return true;
36 bool operator()(boost::python::object) const
38 return true;
42 struct invoke_visitor : public boost::static_visitor<bool>
44 bool operator()(void*) const
46 return true;
49 bool operator()(ScriptInst::strref ref) const
51 Resourcer* rc = Resourcer::instance();
53 if (ref.funcname.size()) {
54 rc->runPythonScript(ref.filename);
55 return pythonExec(ref.funccall);
57 else {
58 return rc->runPythonScript(ref.filename);
62 bool operator()(boost::python::object pyfn) const
64 try {
65 inPythonScript++;
66 pyfn();
67 inPythonScript--;
68 return true;
69 } catch (boost::python::error_already_set) {
70 inPythonScript--;
71 pythonErr();
72 return false;
77 ScriptInst::ScriptInst()
78 : data((void*)NULL)
82 ScriptInst::ScriptInst(const std::string& strloc)
84 size_t colon = strloc.find(':');
85 strref ref;
86 if (colon == std::string::npos) {
87 ref.filename = strloc;
89 else {
90 ref.filename = strloc.substr(0, colon);
91 ref.funcname = strloc.substr(colon + 1);
92 ref.funccall = pythonCompile(
93 "<Tsunagari trigger>",
94 (ref.funcname).c_str()
97 data = ref;
100 ScriptInst::ScriptInst(boost::python::object pyfn)
101 : data(pyfn)
105 bool ScriptInst::validate(const std::string& context)
107 return boost::apply_visitor(validate_visitor(context), data);
110 bool ScriptInst::invoke()
112 return boost::apply_visitor(invoke_visitor(), data);
122 struct topython_visitor : public boost::static_visitor<PyObject*>
124 PyObject* operator()(void*) const
126 using namespace boost::python;
128 return incref(Py_None);
131 PyObject* operator()(ScriptInst::strref ref) const
133 using namespace boost::python;
135 object str;
136 if (ref.funcname.size())
137 str = object(ref.filename + ":" + ref.funcname);
138 else
139 str = object(ref.filename);
140 return incref(str.ptr());
143 PyObject* operator()(boost::python::object pyfn) const
145 using namespace boost::python;
147 return incref(pyfn.ptr());
152 struct scriptinst_to_python
154 static PyObject* convert(ScriptInst script)
156 return boost::apply_visitor(topython_visitor(), script.data);
161 struct scriptinst_from_python
163 scriptinst_from_python()
165 boost::python::converter::registry::push_back(
166 &convertible,
167 &construct,
168 boost::python::type_id<ScriptInst>());
171 // Can this be converted to a ScriptInst?
172 static void* convertible(PyObject* obj)
174 // XXX: Return non-NULL only if string or
175 // callable (fn or lambda?).
176 return obj;
179 // Convert. boost::python provides us with a chunch of memory that we
180 // have to construct in-place.
181 static void construct(
182 PyObject* obj,
183 boost::python::converter::rvalue_from_python_stage1_data* data)
185 using namespace boost::python;
187 void* storage =
188 ((converter::rvalue_from_python_storage<ScriptInst>*)data)
189 ->storage.bytes;
191 if (PyString_Check(obj)) {
192 const char* value = PyString_AsString(obj);
193 new (storage) ScriptInst(value);
195 else {
196 // By default, the PyObject is a borrowed reference,
197 // which means it hasn't been incref'd.
198 handle<> hndl(borrowed(obj));
199 new (storage) ScriptInst(object(hndl));
202 data->convertible = storage;
206 void exportScriptInst()
208 using namespace boost::python;
210 to_python_converter<ScriptInst, scriptinst_to_python>();
211 scriptinst_from_python();