more janet bindings
s-ol
3 years ago
20 | 20 | |
21 | 21 | Janet janet_wrap_point(Geom::Point const &x); |
22 | 22 | Janet janet_wrap_point(Geom::IntPoint const &x); |
23 | Geom::Point janet_unwrap_point(Janet x); | |
23 | Geom::Point &janet_unwrap_point(Janet x); | |
24 | 24 | |
25 | 25 | /* input.cpp */ |
26 | 26 | void janet_lib_input(JanetTable *env); |
12 | 12 | return *_context; |
13 | 13 | } |
14 | 14 | |
15 | extern "C" Janet cfun_input_point(int32_t argc, Janet *argv) { | |
16 | janet_fixarity(argc, 2); | |
17 | ctx().input_point(janet_getcstring(argv, 0), | |
18 | &janet_unwrap_point(argv[1])); | |
19 | return janet_wrap_nil(); | |
20 | } | |
21 | ||
22 | extern "C" Janet cfun_input_line(int32_t argc, Janet *argv) { | |
23 | janet_fixarity(argc, 3); | |
24 | ctx().input_line(janet_getcstring(argv, 0), | |
25 | &janet_unwrap_point(argv[1]), | |
26 | &janet_unwrap_point(argv[2])); | |
27 | return janet_wrap_nil(); | |
28 | } | |
29 | ||
30 | extern "C" Janet cfun_input_arrow(int32_t argc, Janet *argv) { | |
31 | janet_fixarity(argc, 3); | |
32 | ctx().input_arrow(janet_getcstring(argv, 0), | |
33 | &janet_unwrap_point(argv[1]), | |
34 | &janet_unwrap_point(argv[2])); | |
35 | return janet_wrap_nil(); | |
36 | } | |
37 | ||
38 | const JanetReg it_cfuns[] = { | |
39 | { | |
40 | "input/point", cfun_input_point, | |
41 | "(input/point id p)\n\nMake p modifiable via a handle.\n" | |
42 | "This function mutates p." | |
43 | }, | |
44 | { | |
45 | "input/line", cfun_input_line, | |
46 | "(input/line id p1 p2)\n\nMake a modifiable line between p1 and p2\n" | |
47 | "This function mutates p1 and p2." | |
48 | }, | |
49 | { | |
50 | "input/arrow", cfun_input_arrow, | |
51 | "(input/arrow id from to)\n\nMake a modifiable arrow between from and to\n" | |
52 | "This function mutates from and to." | |
53 | }, | |
54 | {NULL, NULL, NULL} | |
55 | }; | |
56 | ||
15 | 57 | void janet_lib_context(JanetTable *env, Context &context) { |
16 | 58 | _context = &context; |
59 | janet_cfuns(env, NULL, it_cfuns); | |
17 | 60 | } |
18 | 61 | |
19 | 62 | } |
105 | 105 | |
106 | 106 | |
107 | 107 | void janet_lib_input(JanetTable *env) { |
108 | janet_printf("yoloading"); | |
108 | 109 | janet_cfuns(env, NULL, it_cfuns); |
109 | 110 | } |
110 | 111 |
9 | 9 | |
10 | 10 | extern "C" void geom_point_tostring(void *p, JanetBuffer *buffer) { |
11 | 11 | std::stringstream stream; |
12 | stream << "<2geom/point " << *static_cast<Geom::Point *>(p) << ">"; | |
12 | stream << "<geom/point " << *static_cast<Geom::Point *>(p) << ">"; | |
13 | 13 | janet_buffer_push_cstring(buffer, stream.str().c_str()); |
14 | 14 | } |
15 | 15 | |
16 | 16 | |
17 | 17 | const JanetAbstractType geom_point_type = { |
18 | "2geom/point", | |
18 | "geom/point", | |
19 | 19 | NULL, |
20 | 20 | NULL, |
21 | 21 | geom_point_get, |
38 | 38 | return janet_wrap_abstract(box); |
39 | 39 | } |
40 | 40 | |
41 | Geom::Point janet_unwrap_point(Janet x) { | |
41 | Geom::Point &janet_unwrap_point(Janet x) { | |
42 | 42 | if (janet_checktype(x, JANET_ABSTRACT)) { |
43 | 43 | void *abst = janet_unwrap_abstract(x); |
44 | 44 | if (janet_abstract_type(abst) == &geom_point_type) |
56 | 56 | } else if (janet_checktype(x, JANET_NUMBER)) { |
57 | 57 | double val = janet_unwrap_number(x); |
58 | 58 | return Geom::Point(val, val); |
59 | } | |
60 | ||
61 | janet_panic("expected a geom/point"); | |
62 | } | |
63 | ||
64 | ||
65 | Geom::Point& janet_unwrap_point_ref(Janet x) { | |
66 | if (janet_checktype(x, JANET_ABSTRACT)) { | |
67 | void *abst = janet_unwrap_abstract(x); | |
68 | if (janet_abstract_type(abst) == &geom_point_type) | |
69 | return *(Geom::Point *)abst; | |
70 | 59 | } |
71 | 60 | |
72 | 61 | janet_panic("expected a geom/point"); |
88 | 77 | |
89 | 78 | const JanetReg it_cfuns[] = { |
90 | 79 | { |
91 | "point", cfun_geom_point_new, | |
80 | "geom/point", cfun_geom_point_new, | |
92 | 81 | "(geom/point x y)\n\nCreate a Point from x/y coordinate values." |
93 | 82 | }, |
94 | 83 | {NULL, NULL, NULL} |
176 | 165 | |
177 | 166 | static Janet cfun_geom_point_eq(int32_t argc, Janet *argv) { |
178 | 167 | janet_fixarity(argc, 2); |
179 | Geom::Point& v1 = janet_unwrap_point_ref(argv[0]); | |
180 | Geom::Point& v2 = janet_unwrap_point_ref(argv[1]); | |
168 | Geom::Point &v1 = janet_unwrap_point(argv[0]); | |
169 | Geom::Point &v2 = janet_unwrap_point(argv[1]); | |
181 | 170 | return janet_wrap_boolean(v1 == v2); |
182 | 171 | } |
183 | 172 | |
184 | 173 | static Janet cfun_geom_point_lt(int32_t argc, Janet *argv) { |
185 | 174 | janet_fixarity(argc, 2); |
186 | Geom::Point& v1 = janet_unwrap_point_ref(argv[0]); | |
187 | Geom::Point& v2 = janet_unwrap_point_ref(argv[1]); | |
175 | Geom::Point &v1 = janet_unwrap_point(argv[0]); | |
176 | Geom::Point &v2 = janet_unwrap_point(argv[1]); | |
188 | 177 | return janet_wrap_boolean(v1 < v2); |
189 | 178 | } |
190 | 179 |
8 | 8 | * Released under GNU GPL v2+, read the file 'COPYING' for more information. |
9 | 9 | */ |
10 | 10 | |
11 | #include <giomm/file.h> | |
11 | #include <memory> | |
12 | 12 | |
13 | 13 | #include "svg/stringstream.h" |
14 | 14 | #include "svg/svg-color.h" |
22 | 22 | namespace Inkscape { |
23 | 23 | namespace Livecode { |
24 | 24 | |
25 | Script::Script(JanetTable *env, std::string const &path) | |
26 | : env(env) | |
27 | , function(nullptr) | |
28 | , file(Gio::File::create_for_path(path)) | |
29 | , monitor(file->monitor_file()) | |
30 | { | |
31 | monitor->signal_changed().connect(sigc::mem_fun(this, &Script::file_changed)); | |
32 | reload(); | |
33 | } | |
34 | ||
35 | void Script::frame() { | |
36 | if (function) { | |
37 | Janet result; | |
38 | janet_pcall(function, 0, NULL, &result, NULL); | |
39 | } | |
40 | } | |
41 | ||
42 | void Script::commit() { | |
43 | } | |
44 | ||
45 | void Script::reload() { | |
46 | try { | |
47 | uint8_t *data; | |
48 | size_t length; | |
49 | file->load_contents((char *&)data, (gsize &)length); | |
50 | ||
51 | Janet result; | |
52 | janet_dobytes(env, data, length, file->get_path().c_str(), &result); | |
53 | if (janet_checktype(result, JANET_FUNCTION)) { | |
54 | function = janet_unwrap_function(result); | |
55 | } else { | |
56 | g_message("Janet script didn't return a function"); | |
57 | } | |
58 | } catch (...) { | |
59 | g_message("error loading file"); | |
60 | } | |
61 | } | |
62 | ||
63 | void Script::file_changed(const Glib::RefPtr<Gio::File>& file, | |
64 | const Glib::RefPtr<Gio::File>& other_file, | |
65 | Gio::FileMonitorEvent event) | |
66 | { | |
67 | reload(); | |
68 | } | |
69 | ||
25 | 70 | Context::Context(SPDesktop *desktop) |
26 | 71 | : desktop(desktop) |
72 | , _mouse(*this) | |
27 | 73 | , doc_root(nullptr) |
28 | 74 | , ui_root(nullptr) |
29 | , _mouse(*this) | |
30 | , script_function(nullptr) | |
31 | 75 | { |
32 | 76 | janet_init(); |
33 | 77 | |
121 | 165 | |
122 | 166 | Geom::Point back = from - to; |
123 | 167 | back.normalize(); |
124 | Geom::Point const cross_a = back.cw() + back * 2.0; | |
125 | Geom::Point const cross_b = back.cw() + back * 2.0; | |
168 | Geom::Point const cross_a = back.cw() * 5.0 + back * 10.0; | |
169 | Geom::Point const cross_b = back.ccw() * 5.0 + back * 10.0; | |
126 | 170 | |
127 | 171 | gchar* d = g_strdup_printf("M %f,%f %f,%f l %f,%f M %f,%f l %f,%f", |
128 | 172 | from.x(), from.y(), |
133 | 177 | repr->setAttribute("d", d); |
134 | 178 | g_free(d); |
135 | 179 | |
136 | Glib::ustring css_str; | |
137 | 180 | if (css) { |
181 | Glib::ustring css_str; | |
138 | 182 | sp_repr_css_write_string(css, css_str); |
139 | 183 | sp_repr_css_attr_unref(css); |
140 | } else { | |
141 | css_str = "stroke: #000000;"; | |
142 | } | |
143 | repr->setAttribute("style", css_str.c_str()); | |
184 | repr->setAttribute("style", css_str.c_str()); | |
185 | } | |
144 | 186 | |
145 | 187 | return repr; |
146 | 188 | } |
199 | 241 | if (input_point(id + "_p2", p2)) { |
200 | 242 | change = true; |
201 | 243 | } |
202 | draw_doc("", make_line(*p1, *p2)); | |
244 | ||
245 | SPCSSAttr *css = sp_repr_css_attr_new(); | |
246 | sp_repr_css_set_property(css, "stroke-width", "1"); | |
247 | sp_repr_css_set_property(css, "stroke", "#000000"); | |
248 | sp_repr_css_set_property(css, "fill", "none"); | |
249 | draw_doc("", make_line(*p1, *p2, css)); | |
203 | 250 | return change; |
204 | 251 | } |
205 | 252 | |
211 | 258 | if (input_point(id + "_to", to)) { |
212 | 259 | change = true; |
213 | 260 | } |
214 | draw_doc("", make_line(*from, *to)); | |
261 | ||
262 | SPCSSAttr *css = sp_repr_css_attr_new(); | |
263 | sp_repr_css_set_property(css, "stroke-width", "1"); | |
264 | sp_repr_css_set_property(css, "stroke", "#000000"); | |
265 | sp_repr_css_set_property(css, "fill", "none"); | |
266 | draw_doc("", make_arrow(*from, *to, css)); | |
215 | 267 | return change; |
216 | 268 | } |
217 | 269 | |
242 | 294 | _mouse.push_event(event); |
243 | 295 | } |
244 | 296 | |
297 | void Context::frame() { | |
298 | setup_frame(); | |
299 | ||
300 | if (_script) { | |
301 | _script->frame(); | |
302 | } | |
303 | ||
304 | finish_frame(); | |
305 | } | |
306 | ||
245 | 307 | void Context::setup_frame() { |
246 | 308 | hot = ""; |
247 | 309 | |
266 | 328 | ui_root = SP_ITEM(desktop->currentLayer()->appendChildRepr(rui)); |
267 | 329 | ui_root->doWriteTransform(ui2doc(), nullptr, true); |
268 | 330 | Inkscape::GC::release(rui); |
269 | ||
270 | if (script_file) { | |
271 | try { | |
272 | char *data; | |
273 | gsize length; | |
274 | script_file->load_contents(data, length); | |
275 | ||
276 | Janet result; | |
277 | janet_dobytes(env, (uint8_t *)data, length, script_file->get_path().c_str(), &result); | |
278 | if (janet_checktype(result, JANET_FUNCTION)) { | |
279 | script_function = janet_unwrap_function(result); | |
280 | } | |
281 | } catch (...) { | |
282 | g_message("error loading file"); | |
283 | } | |
284 | } | |
285 | ||
286 | if (script_function) { | |
287 | Janet result; | |
288 | janet_pcall(script_function, 0, NULL, &result, NULL); | |
289 | } | |
290 | 331 | } |
291 | 332 | |
292 | 333 | void Context::finish_frame() { |
296 | 337 | } |
297 | 338 | |
298 | 339 | void Context::load_script(Glib::ustring const &path) { |
299 | g_message("loading file %s", path.c_str()); | |
300 | script_file = Gio::File::create_for_path(path); | |
340 | g_message("loading script %s", path.c_str()); | |
341 | _script = nullptr; | |
342 | ||
343 | try { | |
344 | _script.reset(new Script(env, path)); | |
345 | g_message("loaded."); | |
346 | } catch (...) { | |
347 | g_message("error creating script"); | |
348 | } | |
301 | 349 | } |
302 | 350 | |
303 | 351 | void Context::draw_doc(Glib::ustring const &id, Inkscape::XML::Node *repr) { |
15 | 15 | #include <2geom/point.h> |
16 | 16 | #include <2geom/rect.h> |
17 | 17 | #include <gdk/gdk.h> |
18 | #include <giomm/file.h> | |
19 | #include <giomm/filemonitor.h> | |
18 | 20 | #include <janet.h> |
19 | 21 | |
20 | 22 | #include "xml/repr.h" |
25 | 27 | class SPDocument; |
26 | 28 | class SPItem; |
27 | 29 | |
28 | namespace Gio { | |
29 | class File; | |
30 | }; | |
31 | ||
32 | 30 | namespace Inkscape { |
33 | 31 | namespace Livecode { |
34 | 32 | |
35 | 33 | class Mouse; |
34 | ||
35 | class Script { | |
36 | public: | |
37 | Script(JanetTable *env, std::string const &path); | |
38 | ||
39 | void frame(); | |
40 | void commit(); | |
41 | ||
42 | private: | |
43 | JanetTable *env; | |
44 | JanetFunction *function; | |
45 | Glib::RefPtr<Gio::File> file; | |
46 | Glib::RefPtr<Gio::FileMonitor> monitor; | |
47 | ||
48 | void reload(); | |
49 | void file_changed(const Glib::RefPtr<Gio::File>& file, | |
50 | const Glib::RefPtr<Gio::File>& other_file, | |
51 | Gio::FileMonitorEvent event); | |
52 | }; | |
36 | 53 | |
37 | 54 | class Context { |
38 | 55 | public: |
53 | 70 | void draw_ui(Glib::ustring const &id, Inkscape::XML::Node *item); |
54 | 71 | |
55 | 72 | void push_event(GdkEvent *event); |
56 | void setup_frame(); | |
57 | void finish_frame(); | |
73 | void frame(); | |
58 | 74 | |
59 | 75 | inline Geom::Affine ui2dt() const { |
60 | 76 | return doc_root->i2doc_affine(); |
80 | 96 | void load_script(Glib::ustring const &path); |
81 | 97 | |
82 | 98 | private: |
99 | void setup_frame(); | |
100 | void finish_frame(); | |
101 | ||
83 | 102 | SPDesktop *desktop; |
84 | 103 | SPItem *doc_root, *ui_root; |
85 | 104 | |
86 | 105 | JanetTable *env; |
87 | JanetFunction *script_function; | |
88 | Glib::RefPtr<Gio::File> script_file; | |
89 | 106 | |
107 | std::unique_ptr<Script> _script; | |
90 | 108 | Mouse _mouse; |
91 | 109 | |
92 | 110 | Glib::ustring hot, active; |
99 | 99 | |
100 | 100 | bool LivecodeTool::handle_tick(Glib::RefPtr<Gdk::FrameClock> const &frame_clock) |
101 | 101 | { |
102 | context.setup_frame(); | |
102 | context.frame(); | |
103 | 103 | |
104 | /* | |
104 | 105 | context.input_point("p", &p); |
105 | 106 | context.input_arrow("a->b", &a, &b); |
106 | 107 | context.input_rect("rect", &rect); |
107 | 108 | |
108 | 109 | context.finish_frame(); |
110 | */ | |
109 | 111 | return true; |
110 | 112 | } |
111 | 113 |