1 /*********************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011-2012 OmegaSDG **
5 *********************************/
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 #include "resourcer.h"
30 #include "scriptinst.h"
32 struct validate_visitor
: public boost::static_visitor
<bool>
36 validate_visitor(const std::string
& context
) : context(context
) {}
38 bool operator()(void*) const
43 bool operator()(ScriptInst::strref ref
) const
45 Resourcer
* rc
= Resourcer::instance();
47 if (ref
.filename
.empty()) {
49 "script filename is empty");
53 if (!rc
->resourceExists(ref
.filename
)) {
55 ref
.filename
+ "script file not found");
62 bool operator()(boost::python::object
) const
68 struct invoke_visitor
: public boost::static_visitor
<bool>
70 bool operator()(void*) const
75 bool operator()(ScriptInst::strref ref
) const
77 Resourcer
* rc
= Resourcer::instance();
79 if (ref
.funcname
.size()) {
80 rc
->runPythonScript(ref
.filename
);
81 return pythonExec(ref
.funccall
);
84 return rc
->runPythonScript(ref
.filename
);
88 bool operator()(boost::python::object pyfn
) const
95 } catch (boost::python::error_already_set
) {
103 ScriptInst::ScriptInst()
108 ScriptInst::ScriptInst(const std::string
& strloc
)
110 size_t colon
= strloc
.find(':');
112 if (colon
== std::string::npos
) {
113 ref
.filename
= strloc
;
116 ref
.filename
= strloc
.substr(0, colon
);
117 ref
.funcname
= strloc
.substr(colon
+ 1);
118 ref
.funccall
= pythonCompile(
119 "<Tsunagari trigger>",
120 (ref
.funcname
).c_str()
126 ScriptInst::ScriptInst(boost::python::object pyfn
)
131 bool ScriptInst::validate(const std::string
& context
)
133 return boost::apply_visitor(validate_visitor(context
), data
);
136 bool ScriptInst::invoke()
138 return boost::apply_visitor(invoke_visitor(), data
);
148 struct topython_visitor
: public boost::static_visitor
<PyObject
*>
150 PyObject
* operator()(void*) const
152 using namespace boost::python
;
154 return incref(Py_None
);
157 PyObject
* operator()(ScriptInst::strref ref
) const
159 using namespace boost::python
;
161 // Prevent compilation name collisions with "object" by making
163 namespace bp
= boost::python
;
166 if (ref
.funcname
.size())
167 str
= bp::object(ref
.filename
+ ":" + ref
.funcname
);
169 str
= bp::object(ref
.filename
);
170 return incref(str
.ptr());
173 PyObject
* operator()(boost::python::object pyfn
) const
175 using namespace boost::python
;
177 return incref(pyfn
.ptr());
182 struct scriptinst_to_python
184 static PyObject
* convert(ScriptInst script
)
186 return boost::apply_visitor(topython_visitor(), script
.data
);
191 struct scriptinst_from_python
193 scriptinst_from_python()
195 boost::python::converter::registry::push_back(
198 boost::python::type_id
<ScriptInst
>());
201 // Can this be converted to a ScriptInst?
202 static void* convertible(PyObject
* obj
)
204 // XXX: Return non-NULL only if string or
205 // callable (fn or lambda?).
209 // Convert. boost::python provides us with a chunch of memory that we
210 // have to construct in-place.
211 static void construct(
213 boost::python::converter::rvalue_from_python_stage1_data
* data
)
215 using namespace boost::python
;
217 // Prevent compilation name collisions with "object" by making
219 namespace bp
= boost::python
;
222 ((converter::rvalue_from_python_storage
<ScriptInst
>*)data
)
225 if (PyString_Check(obj
)) {
226 const char* value
= PyString_AsString(obj
);
227 new (storage
) ScriptInst(value
);
230 // By default, the PyObject is a borrowed reference,
231 // which means it hasn't been incref'd.
232 handle
<> hndl(borrowed(obj
));
233 new (storage
) ScriptInst(bp::object(hndl
));
236 data
->convertible
= storage
;
240 void exportScriptInst()
242 using namespace boost::python
;
244 to_python_converter
<ScriptInst
, scriptinst_to_python
>();
245 scriptinst_from_python();