1 #include "lua/internal.hpp"
2 #include "library/string.hpp"
3 #include "library/minmax.hpp"
4 #include "core/dispatch.hpp"
5 #include "core/instance.hpp"
6 #include "core/moviedata.hpp"
7 #include "core/messages.hpp"
8 #include "core/window.hpp"
18 friend class lua_inputmovie
;
20 lua_inputframe(lua::state
& L
, controller_frame _f
);
21 static size_t overcommit(controller_frame _f
) { return 0; }
22 int get_button(lua::state
& L
, lua::parameters
& P
)
24 unsigned port
, controller
, button
;
26 P(P
.skipped(), port
, controller
, button
);
28 short value
= getbutton(port
, controller
, button
);
29 L
.pushboolean(value
? 1 : 0);
32 int get_axis(lua::state
& L
, lua::parameters
& P
)
34 unsigned port
, controller
, button
;
36 P(P
.skipped(), port
, controller
, button
);
38 short value
= getbutton(port
, controller
, button
);
42 int set_axis(lua::state
& L
, lua::parameters
& P
)
44 unsigned port
, controller
, button
;
47 P(P
.skipped(), port
, controller
, button
);
48 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
49 else if(P
.is_number()) value
= P
.arg
<short>();
51 P
.expected("number or boolean");
53 setbutton(port
, controller
, button
, value
);
56 int serialize(lua::state
& L
, lua::parameters
& P
)
58 char buf
[MAX_SERIALIZED_SIZE
];
63 int unserialize(lua::state
& L
, lua::parameters
& P
)
69 f
.deserialize(buf
.c_str());
72 int get_stride(lua::state
& L
, lua::parameters
& P
)
74 L
.pushnumber(f
.size());
77 controller_frame
& get_frame()
83 char buf
[MAX_SERIALIZED_SIZE
];
88 short getbutton(unsigned port
, unsigned controller
, unsigned index
)
90 return f
.axis3(port
, controller
, index
);
92 void setbutton(unsigned port
, unsigned controller
, unsigned index
, short value
)
94 return f
.axis3(port
, controller
, index
, value
);
99 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
= false);
100 int32_t get_pc_for(unsigned port
, unsigned controller
, unsigned button
, bool extra0
)
102 movie
& m
= CORE().mlogic
->get_movie();
103 if(port
== 0 && controller
== 0 && button
== 0)
104 return m
.get_pollcounters().max_polls() + (extra0
? 1 : 0);
105 if(port
== 0 && controller
== 0 && m
.get_pollcounters().get_framepflag())
106 return max(m
.get_pollcounters().get_polls(port
, controller
, button
), (uint32_t)1);
107 return m
.get_pollcounters().get_polls(port
, controller
, button
);
110 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
111 bool allow_past_end
= false);
113 void check_can_edit(unsigned port
, unsigned controller
, unsigned button
, uint64_t frame
,
117 movie
& m
= core
.mlogic
->get_movie();
118 if(!m
.readonly_mode())
119 throw std::runtime_error("Not in playback mode");
120 if(!allow_past_end
&& frame
>= core
.mlogic
->get_mfile().input
->size())
121 throw std::runtime_error("Index out of movie");
122 int32_t pc
= get_pc_for(port
, controller
, button
, true);
124 throw std::runtime_error("Invalid control to edit");
125 uint64_t firstframe
= m
.get_current_frame_first_subframe();
126 uint64_t minframe
= firstframe
+ pc
;
127 uint64_t msize
= core
.mlogic
->get_mfile().input
->size();
128 if(minframe
> msize
|| firstframe
>= msize
)
129 throw std::runtime_error("Can not edit finished movie");
131 throw std::runtime_error("Can not edit past");
134 int current_first_subframe(lua::state
& L
, lua::parameters
& P
)
136 movie
& m
= CORE().mlogic
->get_movie();
137 L
.pushnumber(m
.get_current_frame_first_subframe());
141 int pollcounter(lua::state
& L
, lua::parameters
& P
)
143 unsigned port
, controller
, button
;
145 P(port
, controller
, button
);
148 ret
= get_pc_for(port
, controller
, button
);
153 controller_frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
);
155 int _copy_movie(lua::state
& L
, lua::parameters
& P
)
157 controller_frame_vector
& v
= framevector(L
, P
);
159 lua::_class
<lua_inputmovie
>::create(L
, v
);
163 int _get_frame(lua::state
& L
, lua::parameters
& P
)
166 controller_frame_vector
& v
= framevector(L
, P
);
171 throw std::runtime_error("Requested frame outside movie");
172 controller_frame _f
= v
[n
];
173 lua::_class
<lua_inputframe
>::create(L
, _f
);
177 int _set_frame(lua::state
& L
, lua::parameters
& P
)
182 controller_frame_vector
& v
= framevector(L
, P
);
187 throw std::runtime_error("Requested frame outside movie");
188 //Checks if requested frame is from movie.
189 if(&v
== core
.mlogic
->get_mfile().input
)
190 check_can_edit(0, 0, 0, n
);
192 v
[n
] = f
->get_frame();
194 if(&v
== core
.mlogic
->get_mfile().input
) {
195 //This can't add frames, so no need to adjust the movie.
196 core
.supdater
->update();
197 core
.dispatch
->status_update();
202 int _get_size(lua::state
& L
, lua::parameters
& P
)
204 controller_frame_vector
& v
= framevector(L
, P
);
206 L
.pushnumber(v
.size());
210 int _count_frames(lua::state
& L
, lua::parameters
& P
)
212 controller_frame_vector
& v
= framevector(L
, P
);
214 L
.pushnumber(v
.count_frames());
218 int _find_frame(lua::state
& L
, lua::parameters
& P
)
221 controller_frame_vector
& v
= framevector(L
, P
);
225 L
.pushnumber(v
.find_frame(n
));
229 int _blank_frame(lua::state
& L
, lua::parameters
& P
)
231 controller_frame_vector
& v
= framevector(L
, P
);
233 controller_frame _f
= v
.blank_frame(true);
234 lua::_class
<lua_inputframe
>::create(L
, _f
);
238 int _append_frames(lua::state
& L
, lua::parameters
& P
)
242 controller_frame_vector
& v
= framevector(L
, P
);
247 controller_frame_vector::notify_freeze
freeze(v
);
248 for(uint64_t i
= 0; i
< count
; i
++)
249 v
.append(v
.blank_frame(true));
251 if(&v
== core
.mlogic
->get_mfile().input
) {
252 core
.supdater
->update();
253 core
.dispatch
->status_update();
258 int _append_frame(lua::state
& L
, lua::parameters
& P
)
262 controller_frame_vector
& v
= framevector(L
, P
);
266 v
.append(v
.blank_frame(true));
267 if(&v
== core
.mlogic
->get_mfile().input
) {
268 core
.supdater
->update();
269 core
.dispatch
->status_update();
270 check_can_edit(0, 0, 0, v
.size() - 1);
272 v
[v
.size() - 1] = f
->get_frame();
273 if(&v
== core
.mlogic
->get_mfile().input
) {
274 if(!v
[v
.size() - 1].sync()) {
275 core
.supdater
->update();
277 core
.dispatch
->status_update();
282 int _truncate(lua::state
& L
, lua::parameters
& P
)
286 controller_frame_vector
& v
= framevector(L
, P
);
291 throw std::runtime_error("Requested truncate length longer than existing");
292 if(&v
== core
.mlogic
->get_mfile().input
)
293 check_can_edit(0, 0, 0, n
);
295 if(&v
== core
.mlogic
->get_mfile().input
) {
296 core
.supdater
->update();
297 core
.dispatch
->status_update();
302 int _edit(lua::state
& L
, lua::parameters
& P
)
306 unsigned port
, controller
, button
;
308 controller_frame_vector
& v
= framevector(L
, P
);
310 P(frame
, port
, controller
, button
);
311 if(P
.is_boolean()) value
= P
.arg
<bool>() ? 1 : 0;
312 else if(P
.is_number()) P(value
);
314 P
.expected("number or boolean");
316 if(&v
== core
.mlogic
->get_mfile().input
)
317 check_can_edit(port
, controller
, button
, frame
);
318 v
[frame
].axis3(port
, controller
, button
, value
);
320 if(&v
== core
.mlogic
->get_mfile().input
) {
321 core
.supdater
->update();
322 core
.dispatch
->status_update();
328 int _copy_frames(lua::state
& L
, lua::parameters
& P
)
331 uint64_t dst
, src
, count
;
332 bool backwards
= same
;
334 controller_frame_vector
& dstv
= framevector(L
, P
);
336 controller_frame_vector
& srcv
= same
? dstv
: framevector(L
, P
);
338 if(same
) P(backwards
);
340 if(src
>= srcv
.size() || src
+ count
< src
)
341 throw std::runtime_error("Source index out of movie");
342 if(dst
> dstv
.size() || dst
+ count
< dst
)
343 throw std::runtime_error("Destination index out of movie");
345 if(&dstv
== core
.mlogic
->get_mfile().input
)
346 check_can_edit(0, 0, 0, dst
, true);
349 controller_frame_vector::notify_freeze
freeze(dstv
);
350 //Add enough blank frames to make the copy.
351 while(dst
+ count
> dstv
.size())
352 dstv
.append(dstv
.blank_frame(false));
354 for(uint64_t i
= backwards
? (count
- 1) : 0; i
< count
; i
= backwards
? (i
- 1) : (i
+ 1))
355 dstv
[dst
+ i
] = srcv
[src
+ i
];
357 if(&dstv
== core
.mlogic
->get_mfile().input
) {
358 core
.supdater
->update();
359 core
.dispatch
->status_update();
364 int _serialize(lua::state
& L
, lua::parameters
& P
)
366 std::string filename
;
369 controller_frame_vector
& v
= framevector(L
, P
);
373 std::ofstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::out
);
375 throw std::runtime_error("Can't open file to write output to");
377 uint64_t stride
= v
.get_stride();
378 uint64_t pageframes
= v
.get_frames_per_page();
379 uint64_t vsize
= v
.size();
382 uint64_t count
= (vsize
> pageframes
) ? pageframes
: vsize
;
383 size_t bytes
= count
* stride
;
384 unsigned char* content
= v
.get_page_buffer(pagenum
++);
385 file
.write(reinterpret_cast<char*>(content
), bytes
);
389 char buf
[MAX_SERIALIZED_SIZE
];
390 for(uint64_t i
= 0; i
< v
.size(); i
++) {
392 file
<< buf
<< std::endl
;
401 lua_inputmovie(lua::state
& L
, const controller_frame_vector
& _v
);
402 lua_inputmovie(lua::state
& L
, controller_frame
& _f
);
403 static size_t overcommit(const controller_frame_vector
& _v
) { return 0; }
404 static size_t overcommit(controller_frame
& _f
) { return 0; }
405 int copy_movie(lua::state
& L
, lua::parameters
& P
)
407 return _copy_movie(L
, P
);
409 int get_frame(lua::state
& L
, lua::parameters
& P
)
411 return _get_frame(L
, P
);
413 int set_frame(lua::state
& L
, lua::parameters
& P
)
415 return _set_frame(L
, P
);
417 int get_size(lua::state
& L
, lua::parameters
& P
)
419 return _get_size(L
, P
);
421 int count_frames(lua::state
& L
, lua::parameters
& P
)
423 return _count_frames(L
, P
);
425 int find_frame(lua::state
& L
, lua::parameters
& P
)
427 return _find_frame(L
, P
);
429 int blank_frame(lua::state
& L
, lua::parameters
& P
)
431 return _blank_frame(L
, P
);
433 int append_frames(lua::state
& L
, lua::parameters
& P
)
435 return _append_frames(L
, P
);
437 int append_frame(lua::state
& L
, lua::parameters
& P
)
439 return _append_frame(L
, P
);
441 int truncate(lua::state
& L
, lua::parameters
& P
)
443 return _truncate(L
, P
);
445 int edit(lua::state
& L
, lua::parameters
& P
)
449 int copy_frames(lua::state
& L
, lua::parameters
& P
)
451 return _copy_frames
<true>(L
, P
);
453 int serialize(lua::state
& L
, lua::parameters
& P
)
455 return _serialize(L
, P
);
457 int debugdump(lua::state
& L
, lua::parameters
& P
)
459 char buf
[MAX_SERIALIZED_SIZE
];
460 for(uint64_t i
= 0; i
< v
.size(); i
++) {
462 messages
<< buf
<< std::endl
;
466 controller_frame_vector
* get_frame_vector()
473 return (stringfmt() << s
<< " " << ((s
!= 1) ? "frames" : "frame")).str();
476 void common_init(lua::state
& L
);
477 controller_frame_vector v
;
480 int copy_movie(lua::state
& L
, lua::parameters
& P
)
482 return _copy_movie(L
, P
);
485 int get_frame(lua::state
& L
, lua::parameters
& P
)
487 return _get_frame(L
, P
);
490 int set_frame(lua::state
& L
, lua::parameters
& P
)
492 return _set_frame(L
, P
);
495 int get_size(lua::state
& L
, lua::parameters
& P
)
497 return _get_size(L
, P
);
500 int count_frames(lua::state
& L
, lua::parameters
& P
)
502 return _count_frames(L
, P
);
505 int find_frame(lua::state
& L
, lua::parameters
& P
)
507 return _find_frame(L
, P
);
510 int blank_frame(lua::state
& L
, lua::parameters
& P
)
512 return _blank_frame(L
, P
);
515 int append_frames(lua::state
& L
, lua::parameters
& P
)
517 return _append_frames(L
, P
);
520 int append_frame(lua::state
& L
, lua::parameters
& P
)
522 return _append_frame(L
, P
);
525 int truncate(lua::state
& L
, lua::parameters
& P
)
527 return _truncate(L
, P
);
530 int edit(lua::state
& L
, lua::parameters
& P
)
535 int copy_frames2(lua::state
& L
, lua::parameters
& P
)
537 return _copy_frames
<false>(L
, P
);
540 int copy_frames(lua::state
& L
, lua::parameters
& P
)
542 return _copy_frames
<true>(L
, P
);
545 int serialize(lua::state
& L
, lua::parameters
& P
)
547 return _serialize(L
, P
);
550 int unserialize(lua::state
& L
, lua::parameters
& P
)
553 std::string filename
;
556 P(f
, filename
, binary
);
558 std::ifstream
file(filename
, binary
? std::ios_base::binary
: std::ios_base::in
);
560 throw std::runtime_error("Can't open file to read input from");
561 lua_inputmovie
* m
= lua::_class
<lua_inputmovie
>::create(L
, f
->get_frame());
562 controller_frame_vector
& v
= *m
->get_frame_vector();
563 controller_frame_vector::notify_freeze
freeze(v
);
565 uint64_t stride
= v
.get_stride();
566 uint64_t pageframes
= v
.get_frames_per_page();
569 size_t pagesize
= stride
* pageframes
;
571 v
.resize(vsize
+ pageframes
);
572 unsigned char* contents
= v
.get_page_buffer(pagenum
++);
573 file
.read(reinterpret_cast<char*>(contents
), pagesize
);
574 vsize
+= (file
.gcount() / stride
);
579 controller_frame tmpl
= v
.blank_frame(false);
581 std::getline(file
, line
);
583 if(line
.length() == 0)
585 tmpl
.deserialize(line
.c_str());
592 int current_branch(lua::state
& L
, lua::parameters
& P
)
594 L
.pushlstring(CORE().mlogic
->get_mfile().current_branch());
598 int get_branches(lua::state
& L
, lua::parameters
& P
)
601 for(auto& i
: core
.mlogic
->get_mfile().branches
)
602 L
.pushlstring(i
.first
);
603 return core
.mlogic
->get_mfile().branches
.size();
606 controller_frame_vector
& framevector(lua::state
& L
, lua::parameters
& P
)
611 return *core
.mlogic
->get_mfile().input
;
612 } else if(P
.is_string()) {
615 if(!core
.mlogic
->get_mfile().branches
.count(x
))
616 throw std::runtime_error("No such branch");
617 return core
.mlogic
->get_mfile().branches
[x
];
618 } else if(P
.is
<lua_inputmovie
>())
619 return *(P
.arg
<lua_inputmovie
*>()->get_frame_vector());
621 return *core
.mlogic
->get_mfile().input
;
624 lua::_class
<lua_inputmovie
> LUA_class_inputmovie(lua_class_movie
, "INPUTMOVIE", {}, {
625 {"copy_movie", &lua_inputmovie::copy_movie
},
626 {"get_frame", &lua_inputmovie::get_frame
},
627 {"set_frame", &lua_inputmovie::set_frame
},
628 {"get_size", &lua_inputmovie::get_size
},
629 {"count_frames", &lua_inputmovie::count_frames
},
630 {"find_frame", &lua_inputmovie::find_frame
},
631 {"blank_frame", &lua_inputmovie::blank_frame
},
632 {"append_frames", &lua_inputmovie::append_frames
},
633 {"append_frame", &lua_inputmovie::append_frame
},
634 {"truncate", &lua_inputmovie::truncate
},
635 {"edit", &lua_inputmovie::edit
},
636 {"debugdump", &lua_inputmovie::debugdump
},
637 {"copy_frames", &lua_inputmovie::copy_frames
},
638 {"serialize", &lua_inputmovie::serialize
},
639 }, &lua_inputmovie::print
);
641 lua::_class
<lua_inputframe
> LUA_class_inputframe(lua_class_movie
, "INPUTFRAME", {}, {
642 {"get_button", &lua_inputframe::get_button
},
643 {"get_axis", &lua_inputframe::get_axis
},
644 {"set_axis", &lua_inputframe::set_axis
},
645 {"set_button", &lua_inputframe::set_axis
},
646 {"serialize", &lua_inputframe::serialize
},
647 {"unserialize", &lua_inputframe::unserialize
},
648 {"get_stride", &lua_inputframe::get_stride
},
649 }, &lua_inputframe::print
);
651 lua::functions
LUA_inputmovie_fns(lua_func_misc
, "movie", {
652 {"current_first_subframe", current_first_subframe
},
653 {"pollcounter", pollcounter
},
654 {"copy_movie", copy_movie
},
655 {"get_frame", get_frame
},
656 {"set_frame", set_frame
},
657 {"get_size", get_size
},
658 {"count_frames", count_frames
},
659 {"find_frame", find_frame
},
660 {"blank_frame", blank_frame
},
661 {"append_frames", append_frames
},
662 {"append_frame", append_frame
},
663 {"truncate", truncate
},
665 {"copy_frames2", copy_frames2
},
666 {"copy_frames", copy_frames
},
667 {"serialize", serialize
},
668 {"unserialize", unserialize
},
669 {"current_branch", current_branch
},
670 {"get_branches", get_branches
},
673 lua_inputframe::lua_inputframe(lua::state
& L
, controller_frame _f
)
678 void lua_inputmovie::common_init(lua::state
& L
)
682 lua_inputmovie::lua_inputmovie(lua::state
& L
, const controller_frame_vector
& _v
)
688 lua_inputmovie::lua_inputmovie(lua::state
& L
, controller_frame
& f
)
690 v
.clear(f
.porttypes());