Merge branch 'rr1-maint'
This merges the basic movie editor functionality
This commit is contained in:
commit
5eaa80a5f2
18 changed files with 1258 additions and 569 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2-β2
|
||||
2-β2
|
||||
|
|
|
@ -183,7 +183,9 @@ struct port_controller_button
|
|||
TYPE_RAXIS //Relative Axis (mouse).
|
||||
};
|
||||
enum _type type;
|
||||
char symbol;
|
||||
const char* name;
|
||||
bool shadow;
|
||||
/**
|
||||
* Is analog?
|
||||
*/
|
||||
|
@ -452,7 +454,7 @@ public:
|
|||
const struct port_index_triple& t = _indices[pindex];
|
||||
if(!t.valid || t.port != port || t.controller != controller || t.control != _index)
|
||||
return 0xFFFFFFFFUL;
|
||||
return indices_tab[place];
|
||||
return pindex;
|
||||
}
|
||||
/**
|
||||
* Return number of controllers connected.
|
||||
|
|
|
@ -241,7 +241,37 @@ public:
|
|||
* Set the poll flag handler.
|
||||
*/
|
||||
void set_pflag_handler(poll_flag* handler);
|
||||
/**
|
||||
* Get the internal controller frame vector.
|
||||
*/
|
||||
controller_frame_vector& get_frame_vector() throw() { return movie_data; }
|
||||
/**
|
||||
* Flush caches.
|
||||
*/
|
||||
void clear_caches() throw();
|
||||
/**
|
||||
* Get sequence number (increments by 1 each time whole data is reloaded).
|
||||
*/
|
||||
uint64_t get_seqno() throw() { return seqno; }
|
||||
/**
|
||||
* Assignment.
|
||||
*/
|
||||
movie& operator=(const movie& m);
|
||||
/**
|
||||
* Get pollcounter vector.
|
||||
*/
|
||||
pollcounter_vector& get_pollcounters() { return pollcounters; }
|
||||
/**
|
||||
* Get first subframe of this frame.
|
||||
*/
|
||||
uint64_t get_current_frame_first_subframe() { return current_frame_first_subframe; }
|
||||
/**
|
||||
* Recount frames.
|
||||
*/
|
||||
void recount_frames() { frames_in_movie = movie_data.count_frames(); }
|
||||
private:
|
||||
//Sequence number.
|
||||
uint64_t seqno;
|
||||
//The poll flag handling.
|
||||
poll_flag* pflag_handler;
|
||||
//TRUE if readonly mode is active.
|
||||
|
@ -265,7 +295,6 @@ private:
|
|||
//Number of frames in movie.
|
||||
uint64_t frames_in_movie;
|
||||
//Cached subframes.
|
||||
void clear_caches() throw();
|
||||
uint64_t cached_frame;
|
||||
uint64_t cached_subframe;
|
||||
//Count present subframes in frame starting from first_subframe (returns 0 if out of movie).
|
||||
|
|
|
@ -50,6 +50,8 @@ void open_rom_select_window();
|
|||
void show_conflictwindow(wxWindow* parent);
|
||||
void open_vumeter_window(wxWindow* parent);
|
||||
void wxeditor_sounddev_display(wxWindow* parent);
|
||||
void wxeditor_movie_display(wxWindow* parent);
|
||||
void wxeditor_movie_update();
|
||||
|
||||
//Auxillary windows.
|
||||
void wxwindow_memorysearch_display();
|
||||
|
|
28
manual.lyx
28
manual.lyx
|
@ -6914,5 +6914,33 @@ Cleanup build by allowing dummy and real drivers to link together.
|
|||
Split duplex support
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
rr1-delta16epsilon1
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Wxwidgets: Fix memory watch rendering.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Wxwidgets: Allow setting voice stream gain.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Wxwidgets: VU meters and volume adjustment.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Lua: Custom fonts support.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Lua: Fix methods stopping working when resetting Lua.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Itemize
|
||||
Fix loading standard-format movies in preserve (readonly) mode.
|
||||
\end_layout
|
||||
|
||||
\end_body
|
||||
\end_document
|
||||
|
|
816
manual.txt
816
manual.txt
File diff suppressed because it is too large
Load diff
|
@ -102,6 +102,8 @@ namespace
|
|||
bool multi_analog = (controller.analog_actions() > 1);
|
||||
//This controller might be processed already, but perhaps only partially.
|
||||
for(unsigned i = 0; i < controller.button_count; i++) {
|
||||
if(controller.buttons[i]->shadow)
|
||||
continue;
|
||||
if(controller.buttons[i]->type != port_controller_button::TYPE_BUTTON)
|
||||
continue;
|
||||
std::string name = (stringfmt() << controller.cclass << "-" << number << "-"
|
||||
|
|
|
@ -221,6 +221,7 @@ namespace
|
|||
port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
|
||||
{
|
||||
port_index_triple x;
|
||||
x.valid = true;
|
||||
x.port = p;
|
||||
x.controller = c;
|
||||
x.control = i;
|
||||
|
|
|
@ -67,20 +67,20 @@ superscope_controller = {
|
|||
|
||||
system_controller = {
|
||||
["name"] = "(system)", ["class"] = "(system)", ["buttons"] = {
|
||||
{shadow, "F"},
|
||||
{shadow, "R"},
|
||||
{shadow_axis},
|
||||
{shadow_axis}
|
||||
{shadow, "F", "framesync"},
|
||||
{shadow, "R", "reset"},
|
||||
{shadow_axis, "rlow"},
|
||||
{shadow_axis, "rhigh"}
|
||||
}
|
||||
};
|
||||
|
||||
system_controller_hreset = {
|
||||
["name"] = "(system)", ["class"] = "(system)", ["buttons"] = {
|
||||
{shadow, "F"},
|
||||
{shadow, "R"},
|
||||
{shadow_axis},
|
||||
{shadow_axis},
|
||||
{shadow, "H"}
|
||||
{shadow, "F", "framesync"},
|
||||
{shadow, "R", "reset"},
|
||||
{shadow_axis, "rlow"},
|
||||
{shadow_axis, "rhigh"},
|
||||
{shadow, "H", "hard"}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -156,6 +156,7 @@ namespace
|
|||
port_index_triple t(unsigned p, unsigned c, unsigned i, bool nl)
|
||||
{
|
||||
port_index_triple x;
|
||||
x.valid = true;
|
||||
x.port = p;
|
||||
x.controller = c;
|
||||
x.control = i;
|
||||
|
|
|
@ -3,8 +3,8 @@ ports = {
|
|||
["symbol"] = "psystem", ["iname"] = "system", ["hname"] = "system", ["controllers"] = {
|
||||
{
|
||||
["name"] = "(system)", ["class"] = "(system)", ["buttons"] = {
|
||||
{shadow, "F"},
|
||||
{shadow, "R"}
|
||||
{shadow, "F", "framesync"},
|
||||
{shadow, "R", "reset"}
|
||||
}
|
||||
},{
|
||||
["name"] = "gamepad", ["class"] = "gb", ["buttons"] = {
|
||||
|
|
|
@ -37,31 +37,37 @@ for i = 1,#ports do
|
|||
if xbutton[1] == button then
|
||||
table.insert(bsyms, bsym);
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_BUTTON, "..
|
||||
"\""..xbutton[3].."\"};");
|
||||
"'" .. xbutton[2] .. "', \""..xbutton[3].."\", false};");
|
||||
bits = bits + 1;
|
||||
end
|
||||
if xbutton[1] == axis then
|
||||
table.insert(bsyms, bsym);
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_AXIS, \""..
|
||||
xbutton[2].."\"};");
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_AXIS, " ..
|
||||
"'\\0', \"".. xbutton[2].."\", false};");
|
||||
ints = ints + 1;
|
||||
end
|
||||
if xbutton[1] == raxis then
|
||||
table.insert(bsyms, bsym);
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_RAXIS, "..
|
||||
"\""..xbutton[2].."\"};");
|
||||
"'\\0', \""..xbutton[2].."\", false};");
|
||||
ints = ints + 1;
|
||||
end
|
||||
if xbutton[1] == shadow then
|
||||
table.insert(bsyms, bsym);
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_BUTTON, "..
|
||||
"'" .. xbutton[2] .. "', \""..xbutton[3].."\", true};");
|
||||
bits = bits + 1;
|
||||
end
|
||||
if xbutton[1] == shadow_axis then
|
||||
table.insert(bsyms, bsym);
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_AXIS, " ..
|
||||
"'\\0', \"".. xbutton[2].."\", true};");
|
||||
ints = ints + 1;
|
||||
end
|
||||
if xbutton[1] == null then
|
||||
table.insert(bsyms, bsym);
|
||||
print("\tport_controller_button "..bsym.." = {port_controller_button::TYPE_NULL, "..
|
||||
"NULL};");
|
||||
"'\\0', NULL, false};");
|
||||
end
|
||||
end
|
||||
local s = "\tport_controller_button* "..csym.."[] = {";
|
||||
|
@ -280,4 +286,4 @@ for i = 1,#ports do
|
|||
s = s .."&"..ports[i].symbol..", ";
|
||||
end
|
||||
s = s .. "NULL};";
|
||||
print(s);
|
||||
print(s);
|
||||
|
|
|
@ -520,7 +520,7 @@ unsigned port_controller::analog_actions() const
|
|||
{
|
||||
unsigned r = 0;
|
||||
for(unsigned i = 0; i < button_count; i++)
|
||||
if(buttons[i]->is_analog())
|
||||
if(buttons[i]->is_analog() && !buttons[i]->shadow)
|
||||
r++;
|
||||
return (r + 1)/ 2;
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ std::pair<unsigned, unsigned> port_controller::analog_action(unsigned k) const
|
|||
unsigned x2 = std::numeric_limits<unsigned>::max();
|
||||
unsigned r = 0;
|
||||
for(unsigned i = 0; i < button_count; i++)
|
||||
if(buttons[i]->is_analog()) {
|
||||
if(buttons[i]->is_analog() && !buttons[i]->shadow) {
|
||||
if(r == 2 * k)
|
||||
x1 = i;
|
||||
if(r == 2 * k + 1)
|
||||
|
|
|
@ -253,6 +253,7 @@ short movie::next_input(unsigned port, unsigned controller, unsigned ctrl) throw
|
|||
|
||||
movie::movie() throw(std::bad_alloc)
|
||||
{
|
||||
seqno = 0;
|
||||
readonly = false;
|
||||
rerecords = "0";
|
||||
_project_id = "";
|
||||
|
@ -269,6 +270,7 @@ void movie::load(const std::string& rerecs, const std::string& project_id, contr
|
|||
{
|
||||
if(input.size() > 0 && !input[0].sync())
|
||||
throw std::runtime_error("First subframe MUST have frame sync flag set");
|
||||
seqno++;
|
||||
clear_caches();
|
||||
frames_in_movie = 0;
|
||||
for(size_t i = 0; i < input.size(); i++)
|
||||
|
@ -438,6 +440,23 @@ void movie::fast_load(uint64_t& _frame, uint64_t& _ptr, uint64_t& _lagc, std::ve
|
|||
readonly_mode(false);
|
||||
}
|
||||
|
||||
movie& movie::operator=(const movie& m)
|
||||
{
|
||||
seqno++;
|
||||
readonly = m.readonly;
|
||||
rerecords = m.rerecords;
|
||||
_project_id = m._project_id;
|
||||
movie_data = m.movie_data;
|
||||
current_frame = m.current_frame;
|
||||
current_frame_first_subframe = m.current_frame_first_subframe;
|
||||
pollcounters = m.pollcounters;
|
||||
current_controls = m.current_controls;
|
||||
lag_frames = m.lag_frames;
|
||||
frames_in_movie = m.frames_in_movie;
|
||||
cached_frame = m.cached_frame;
|
||||
cached_subframe = m.cached_subframe;
|
||||
}
|
||||
|
||||
void movie::set_pflag_handler(poll_flag* handler)
|
||||
{
|
||||
pflag_handler = handler;
|
||||
|
@ -445,4 +464,4 @@ void movie::set_pflag_handler(poll_flag* handler)
|
|||
|
||||
movie::poll_flag::~poll_flag()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
861
src/platform/wxwidgets/editor-movie.cpp
Normal file
861
src/platform/wxwidgets/editor-movie.cpp
Normal file
|
@ -0,0 +1,861 @@
|
|||
#include "core/movie.hpp"
|
||||
#include "core/moviedata.hpp"
|
||||
#include "core/dispatch.hpp"
|
||||
#include "core/window.hpp"
|
||||
|
||||
#include "interface/controller.hpp"
|
||||
#include "platform/wxwidgets/platform.hpp"
|
||||
#include "platform/wxwidgets/textrender.hpp"
|
||||
#include "library/minmax.hpp"
|
||||
#include "library/string.hpp"
|
||||
#include "library/utf8.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/control.h>
|
||||
#include <wx/combobox.h>
|
||||
|
||||
void update_movie_state();
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned lines_to_display = 28;
|
||||
uint64_t divs[] = {1000000, 100000, 10000, 1000, 100, 10, 1};
|
||||
uint64_t divsl[] = {1000000, 100000, 10000, 1000, 100, 10, 0};
|
||||
const unsigned divcnt = sizeof(divs)/sizeof(divs[0]);
|
||||
|
||||
void connect_events(wxScrollBar* s, wxObjectEventFunction fun, wxEvtHandler* obj)
|
||||
{
|
||||
s->Connect(wxEVT_SCROLL_THUMBTRACK, fun, NULL, obj);
|
||||
s->Connect(wxEVT_SCROLL_PAGEDOWN, fun, NULL, obj);
|
||||
s->Connect(wxEVT_SCROLL_PAGEUP, fun, NULL, obj);
|
||||
s->Connect(wxEVT_SCROLL_LINEDOWN, fun, NULL, obj);
|
||||
s->Connect(wxEVT_SCROLL_LINEUP, fun, NULL, obj);
|
||||
s->Connect(wxEVT_SCROLL_TOP, fun, NULL, obj);
|
||||
s->Connect(wxEVT_SCROLL_BOTTOM, fun, NULL, obj);
|
||||
}
|
||||
}
|
||||
|
||||
struct control_info
|
||||
{
|
||||
unsigned position_left;
|
||||
unsigned reserved; //Must be at least 6 for axes.
|
||||
unsigned index; //Index in poll vector.
|
||||
int type; //-2 => Port, -1 => Fixed, 0 => Button, 1 => axis.
|
||||
char ch;
|
||||
std::string title;
|
||||
unsigned port;
|
||||
unsigned controller;
|
||||
static control_info portinfo(unsigned& p, unsigned port, unsigned controller);
|
||||
static control_info fixedinfo(unsigned& p, const std::string& str);
|
||||
static control_info buttoninfo(unsigned& p, char character, unsigned idx);
|
||||
static control_info axisinfo(unsigned& p, const std::string& title, unsigned idx);
|
||||
};
|
||||
|
||||
control_info control_info::portinfo(unsigned& p, unsigned port, unsigned controller)
|
||||
{
|
||||
control_info i;
|
||||
i.position_left = p;
|
||||
i.reserved = utf8_strlen((stringfmt() << port << "-" << controller).str());
|
||||
p += i.reserved;
|
||||
i.index = 0;
|
||||
i.type = -2;
|
||||
i.ch = 0;
|
||||
i.title = "";
|
||||
i.port = port;
|
||||
i.controller = controller;
|
||||
return i;
|
||||
}
|
||||
|
||||
control_info control_info::fixedinfo(unsigned& p, const std::string& str)
|
||||
{
|
||||
control_info i;
|
||||
i.position_left = p;
|
||||
i.reserved = utf8_strlen(str);
|
||||
p += i.reserved;
|
||||
i.index = 0;
|
||||
i.type = -1;
|
||||
i.ch = 0;
|
||||
i.title = str;
|
||||
i.port = 0;
|
||||
i.controller = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
control_info control_info::buttoninfo(unsigned& p, char character, unsigned idx)
|
||||
{
|
||||
control_info i;
|
||||
i.position_left = p;
|
||||
i.reserved = 1;
|
||||
p += i.reserved;
|
||||
i.index = idx;
|
||||
i.type = 0;
|
||||
i.ch = character;
|
||||
i.title = "";
|
||||
i.port = 0;
|
||||
i.controller = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
control_info control_info::axisinfo(unsigned& p, const std::string& title, unsigned idx)
|
||||
{
|
||||
control_info i;
|
||||
i.position_left = p;
|
||||
i.reserved = utf8_strlen(title);
|
||||
if(i.reserved < 6)
|
||||
i.reserved = 6;
|
||||
p += i.reserved;
|
||||
i.index = idx;
|
||||
i.type = 1;
|
||||
i.ch = 0;
|
||||
i.title = title;
|
||||
i.port = 0;
|
||||
i.controller = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
control_info axisinfo(unsigned& p, const std::string& title, unsigned idx);
|
||||
|
||||
|
||||
class frame_controls
|
||||
{
|
||||
public:
|
||||
frame_controls();
|
||||
void set_types(controller_frame& f);
|
||||
short read_index(controller_frame& f, unsigned idx);
|
||||
void write_index(controller_frame& f, unsigned idx, short value);
|
||||
uint32_t read_pollcount(pollcounter_vector& v, unsigned idx);
|
||||
const std::list<control_info>& get_controlinfo() { return controlinfo; }
|
||||
std::string line1() { return _line1; }
|
||||
std::string line2() { return _line2; }
|
||||
size_t width() { return _width; }
|
||||
private:
|
||||
size_t _width;
|
||||
std::string _line1;
|
||||
std::string _line2;
|
||||
void format_lines();
|
||||
void add_port(unsigned& c, unsigned pid, const port_type& p, const port_type_set& pts);
|
||||
std::string vector_to_string(const std::vector<uint32_t>& cp);
|
||||
std::vector<uint32_t> string_to_vector(const std::string& str);
|
||||
std::list<control_info> controlinfo;
|
||||
};
|
||||
|
||||
|
||||
frame_controls::frame_controls()
|
||||
{
|
||||
_width = 0;
|
||||
}
|
||||
|
||||
void frame_controls::set_types(controller_frame& f)
|
||||
{
|
||||
unsigned nextp = 0;
|
||||
unsigned nextc = 0;
|
||||
controlinfo.clear();
|
||||
const port_type_set& pts = f.porttypes();
|
||||
unsigned pcnt = pts.ports();
|
||||
for(unsigned i = 0; i < pcnt; i++)
|
||||
add_port(nextp, i, pts.port_type(i), pts);
|
||||
format_lines();
|
||||
}
|
||||
|
||||
void frame_controls::add_port(unsigned& c, unsigned pid, const port_type& p, const port_type_set& pts)
|
||||
{
|
||||
unsigned i = 0;
|
||||
const port_controller_set& pci = *(p.controller_info);
|
||||
for(unsigned i = 0; i < pci.controller_count; i++) {
|
||||
if(!pci.controllers[i])
|
||||
continue;
|
||||
const port_controller& pc = *(pci.controllers[i]);
|
||||
if(pid || i)
|
||||
controlinfo.push_back(control_info::fixedinfo(c, "│"));
|
||||
unsigned nextp = c;
|
||||
controlinfo.push_back(control_info::portinfo(nextp, pid, i + 1));
|
||||
for(unsigned j = 0; j < pc.button_count; j++) {
|
||||
if(!pc.buttons[j])
|
||||
continue;
|
||||
const port_controller_button& pcb = *(pc.buttons[j]);
|
||||
std::cerr << pid << "-" << (i + 1) << "-" << pcb.name << std::endl;
|
||||
unsigned idx = pts.triple_to_index(pid, i, j);
|
||||
if(idx == 0xFFFFFFFFUL) {
|
||||
std::cerr << "No index found!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
std::cerr << "Index is " << idx << std::endl;
|
||||
if(pcb.type == port_controller_button::TYPE_BUTTON) {
|
||||
controlinfo.push_back(control_info::buttoninfo(c, pcb.symbol, idx));
|
||||
} else if(pcb.type == port_controller_button::TYPE_AXIS) {
|
||||
controlinfo.push_back(control_info::axisinfo(c, pcb.name, idx));
|
||||
}
|
||||
}
|
||||
if(nextp > c)
|
||||
c = nextp;
|
||||
}
|
||||
}
|
||||
|
||||
short frame_controls::read_index(controller_frame& f, unsigned idx)
|
||||
{
|
||||
if(idx == 0)
|
||||
return f.sync() ? 1 : 0;
|
||||
return f.axis2(idx);
|
||||
}
|
||||
|
||||
void frame_controls::write_index(controller_frame& f, unsigned idx, short value)
|
||||
{
|
||||
if(idx == 0)
|
||||
return f.sync(value);
|
||||
return f.axis2(idx, value);
|
||||
}
|
||||
|
||||
uint32_t frame_controls::read_pollcount(pollcounter_vector& v, unsigned idx)
|
||||
{
|
||||
if(idx == 0)
|
||||
return max(v.max_polls(), (uint32_t)1);
|
||||
return v.get_polls(idx);
|
||||
}
|
||||
|
||||
std::string frame_controls::vector_to_string(const std::vector<uint32_t>& cp)
|
||||
{
|
||||
std::ostringstream s;
|
||||
for(auto i : cp) {
|
||||
if(i < 0x80)
|
||||
s << (unsigned char)i;
|
||||
else if(i < 0x800)
|
||||
s << (unsigned char)(0xC0 + (i >> 6)) << (unsigned char)(0x80 + (i & 0x3F));
|
||||
else if(i < 0x10000)
|
||||
s << (unsigned char)(0xE0 + (i >> 12)) << (unsigned char)(0x80 + ((i >> 6) & 0x3F))
|
||||
<< (unsigned char)(0x80 + (i & 0x3F));
|
||||
else if(i < 0x10FFFF)
|
||||
s << (unsigned char)(0xF0 + (i >> 18)) << (unsigned char)(0x80 + ((i >> 12) & 0x3F))
|
||||
<< (unsigned char)(0x80 + ((i >> 6) & 0x3F))
|
||||
<< (unsigned char)(0x80 + (i & 0x3F));
|
||||
}
|
||||
return s.str();
|
||||
}
|
||||
|
||||
std::vector<uint32_t> frame_controls::string_to_vector(const std::string& str)
|
||||
{
|
||||
std::vector<uint32_t> cp;
|
||||
size_t spos = 0;
|
||||
size_t slen = str.length();
|
||||
uint16_t state = utf8_initial_state;
|
||||
while(true) {
|
||||
int ch = (spos < slen) ? (unsigned char)str[spos] : - 1;
|
||||
int32_t u = utf8_parse_byte(ch, state);
|
||||
if(u >= 0)
|
||||
cp.push_back(u);
|
||||
if(ch < 0)
|
||||
break;
|
||||
spos++;
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
void frame_controls::format_lines()
|
||||
{
|
||||
_width = 0;
|
||||
for(auto i : controlinfo) {
|
||||
if(i.position_left + i.reserved > _width)
|
||||
_width = i.position_left + i.reserved;
|
||||
}
|
||||
std::vector<uint32_t> cp1;
|
||||
std::vector<uint32_t> cp2;
|
||||
uint32_t off = divcnt + 1;
|
||||
cp1.resize(_width + divcnt + 1);
|
||||
cp2.resize(_width + divcnt + 1);
|
||||
for(unsigned i = 0; i < cp1.size(); i++)
|
||||
cp1[i] = cp2[i] = 32;
|
||||
cp1[divcnt] = 0x2502;
|
||||
cp2[divcnt] = 0x2502;
|
||||
//Line1
|
||||
//For every port-controller, find the least coordinate.
|
||||
for(auto i : controlinfo) {
|
||||
if(i.type == -1) {
|
||||
auto _title = string_to_vector(i.title);
|
||||
std::copy(_title.begin(), _title.end(), &cp1[i.position_left + off]);
|
||||
} else if(i.type == -2) {
|
||||
auto _title = string_to_vector((stringfmt() << i.port << "-" << i.controller).str());
|
||||
std::copy(_title.begin(), _title.end(), &cp1[i.position_left + off]);
|
||||
}
|
||||
}
|
||||
//Line2
|
||||
for(auto i : controlinfo) {
|
||||
auto _title = string_to_vector(i.title);
|
||||
if(i.type == -1 || i.type == 1)
|
||||
std::copy(_title.begin(), _title.end(), &cp2[i.position_left + off]);
|
||||
if(i.type == 0)
|
||||
cp2[i.position_left + off] = i.ch;
|
||||
}
|
||||
_line1 = vector_to_string(cp1);
|
||||
_line2 = vector_to_string(cp2);
|
||||
}
|
||||
|
||||
|
||||
class wxeditor_movie : public wxDialog
|
||||
{
|
||||
public:
|
||||
wxeditor_movie(wxWindow* parent);
|
||||
~wxeditor_movie() throw();
|
||||
bool ShouldPreventAppExit() const;
|
||||
void on_close(wxCommandEvent& e);
|
||||
void on_wclose(wxCloseEvent& e);
|
||||
void on_focus_wrong(wxFocusEvent& e);
|
||||
void on_keyboard_down(wxKeyEvent& e);
|
||||
void on_keyboard_up(wxKeyEvent& e);
|
||||
wxScrollBar* get_scroll();
|
||||
void update();
|
||||
private:
|
||||
struct _moviepanel : public wxPanel, public information_dispatch
|
||||
{
|
||||
_moviepanel(wxeditor_movie* v);
|
||||
~_moviepanel();
|
||||
void signal_repaint();
|
||||
void on_scroll(wxScrollEvent& e);
|
||||
void on_paint(wxPaintEvent& e);
|
||||
void on_mouse(wxMouseEvent& e);
|
||||
private:
|
||||
int get_lines();
|
||||
void render(text_framebuffer& fb, unsigned long long pos);
|
||||
void on_mouse0(unsigned x, unsigned y, bool polarity);
|
||||
void on_mouse1(unsigned x, unsigned y, bool polarity);
|
||||
void on_mouse2(unsigned x, unsigned y, bool polarity);
|
||||
int width(controller_frame& f);
|
||||
std::string render_line1(controller_frame& f);
|
||||
std::string render_line2(controller_frame& f);
|
||||
void render_linen(text_framebuffer& fb, controller_frame& f, uint64_t sfn, int y);
|
||||
unsigned long long spos;
|
||||
void* prev_obj;
|
||||
uint64_t prev_seqno;
|
||||
void update_cache();
|
||||
std::map<uint64_t, uint64_t> subframe_to_frame;
|
||||
uint64_t max_subframe;
|
||||
frame_controls fcontrols;
|
||||
wxeditor_movie* m;
|
||||
bool requested;
|
||||
text_framebuffer fb;
|
||||
int movielines;
|
||||
int moviepos;
|
||||
unsigned new_width;
|
||||
std::vector<uint8_t> pixels;
|
||||
int scroll_delta;
|
||||
unsigned press_x;
|
||||
uint64_t press_line;
|
||||
bool pressed;
|
||||
bool recursing;
|
||||
};
|
||||
_moviepanel* moviepanel;
|
||||
wxButton* closebutton;
|
||||
wxScrollBar* moviescroll;
|
||||
bool closing;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
wxeditor_movie* movieeditor_open;
|
||||
|
||||
uint64_t first_editable(frame_controls& fc, unsigned idx)
|
||||
{
|
||||
uint64_t cffs = movb.get_movie().get_current_frame_first_subframe();
|
||||
pollcounter_vector& pv = movb.get_movie().get_pollcounters();
|
||||
return cffs + fc.read_pollcount(pv, idx);
|
||||
}
|
||||
}
|
||||
|
||||
wxeditor_movie::_moviepanel::~_moviepanel() {}
|
||||
wxeditor_movie::~wxeditor_movie() throw() {}
|
||||
|
||||
wxeditor_movie::_moviepanel::_moviepanel(wxeditor_movie* v)
|
||||
: wxPanel(v, wxID_ANY, wxDefaultPosition, wxSize(100, 100)),
|
||||
information_dispatch("movieeditor-listener")
|
||||
{
|
||||
m = v;
|
||||
Connect(wxEVT_PAINT, wxPaintEventHandler(_moviepanel::on_paint), NULL, this);
|
||||
new_width = 0;
|
||||
moviepos = 0;
|
||||
scroll_delta = 0;
|
||||
spos = 0;
|
||||
prev_obj = NULL;
|
||||
prev_seqno = 0;
|
||||
max_subframe = 0;
|
||||
recursing = false;
|
||||
|
||||
Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
Connect(wxEVT_LEFT_UP, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(_moviepanel::on_mouse), NULL, this);
|
||||
|
||||
signal_repaint();
|
||||
requested = false;
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::update_cache()
|
||||
{
|
||||
movie& m = movb.get_movie();
|
||||
controller_frame_vector& fv = m.get_frame_vector();
|
||||
if(&m == prev_obj && prev_seqno == m.get_seqno()) {
|
||||
//Just process new subframes if any.
|
||||
for(uint64_t i = max_subframe; i < fv.size(); i++) {
|
||||
uint64_t prev = (i > 0) ? subframe_to_frame[i - 1] : 0;
|
||||
controller_frame f = fv[i];
|
||||
if(f.sync())
|
||||
subframe_to_frame[i] = prev + 1;
|
||||
else
|
||||
subframe_to_frame[i] = prev;
|
||||
}
|
||||
max_subframe = fv.size();
|
||||
return;
|
||||
}
|
||||
//Reprocess all subframes.
|
||||
for(uint64_t i = 0; i < fv.size(); i++) {
|
||||
uint64_t prev = (i > 0) ? subframe_to_frame[i - 1] : 0;
|
||||
controller_frame f = fv[i];
|
||||
if(f.sync())
|
||||
subframe_to_frame[i] = prev + 1;
|
||||
else
|
||||
subframe_to_frame[i] = prev;
|
||||
}
|
||||
max_subframe = fv.size();
|
||||
controller_frame model = fv.blank_frame(false);
|
||||
fcontrols.set_types(model);
|
||||
prev_obj = &m;
|
||||
prev_seqno = m.get_seqno();
|
||||
}
|
||||
|
||||
int wxeditor_movie::_moviepanel::width(controller_frame& f)
|
||||
{
|
||||
update_cache();
|
||||
return divcnt + 1 + fcontrols.width();
|
||||
}
|
||||
|
||||
std::string wxeditor_movie::_moviepanel::render_line1(controller_frame& f)
|
||||
{
|
||||
update_cache();
|
||||
return fcontrols.line1();
|
||||
}
|
||||
|
||||
std::string wxeditor_movie::_moviepanel::render_line2(controller_frame& f)
|
||||
{
|
||||
update_cache();
|
||||
return fcontrols.line2();
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::render_linen(text_framebuffer& fb, controller_frame& f, uint64_t sfn, int y)
|
||||
{
|
||||
update_cache();
|
||||
size_t fbstride = fb.get_stride();
|
||||
auto fbsize = fb.get_characters();
|
||||
text_framebuffer::element* _fb = fb.get_buffer();
|
||||
text_framebuffer::element e;
|
||||
e.bg = 0xFFFFFF;
|
||||
e.fg = 0x000000;
|
||||
for(unsigned i = 0; i < divcnt; i++) {
|
||||
uint64_t fn = subframe_to_frame[sfn];
|
||||
e.ch = (fn >= divsl[i]) ? (((fn / divs[i]) % 10) + 48) : 32;
|
||||
_fb[y * fbstride + i] = e;
|
||||
}
|
||||
e.ch = 0x2502;
|
||||
_fb[y * fbstride + divcnt] = e;
|
||||
const std::list<control_info>& ctrlinfo = fcontrols.get_controlinfo();
|
||||
uint64_t curframe = movb.get_movie().get_current_frame();
|
||||
pollcounter_vector& pv = movb.get_movie().get_pollcounters();
|
||||
uint64_t cffs = movb.get_movie().get_current_frame_first_subframe();
|
||||
int past = -1;
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
past = 1;
|
||||
else if(subframe_to_frame[sfn] < curframe)
|
||||
past = 1;
|
||||
else if(subframe_to_frame[sfn] > curframe)
|
||||
past = 0;
|
||||
bool now = (subframe_to_frame[sfn] == curframe);
|
||||
for(auto i : ctrlinfo) {
|
||||
int rpast = past;
|
||||
if(rpast == -1) {
|
||||
unsigned polls = fcontrols.read_pollcount(pv, i.index);
|
||||
rpast = ((cffs + polls) > sfn) ? 1 : 0;
|
||||
}
|
||||
if(i.type == -1) {
|
||||
//Separator.
|
||||
fb.write(i.title, 0, divcnt + 1 + i.position_left, y, 0x000000, now ? 0xFFC0C0 : 0xFFFFFF);
|
||||
} else if(i.type == 0) {
|
||||
//Button.
|
||||
char c[2];
|
||||
bool v = (fcontrols.read_index(f, i.index) != 0);
|
||||
c[0] = v ? i.ch : ' ';
|
||||
c[1] = 0;
|
||||
fb.write(c, 0, divcnt + 1 + i.position_left, y, rpast ? 0x808080 : 0x000000,
|
||||
now ? 0xFFC0C0 : 0xFFFFFF);
|
||||
} else if(i.type == 1) {
|
||||
//Axis.
|
||||
char c[7];
|
||||
sprintf(c, "%6d", fcontrols.read_index(f, i.index));
|
||||
fb.write(c, 0, divcnt + 1 + i.position_left, y, rpast ? 0x808080 : 0x000000,
|
||||
now ? 0xFFC0C0 : 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::render(text_framebuffer& fb, unsigned long long pos)
|
||||
{
|
||||
spos = pos;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
controller_frame cf = fv.blank_frame(false);
|
||||
int _width = width(cf);
|
||||
fb.set_size(_width, lines_to_display + 3);
|
||||
size_t fbstride = fb.get_stride();
|
||||
auto fbsize = fb.get_characters();
|
||||
text_framebuffer::element* _fb = fb.get_buffer();
|
||||
fb.write((stringfmt() << "Current frame: " << movb.get_movie().get_current_frame()).str(), _width, 0, 0,
|
||||
0x000000, 0xFFFFFF);
|
||||
fb.write(render_line1(cf), _width, 0, 1, 0x000000, 0xFFFFFF);
|
||||
fb.write(render_line2(cf), _width, 0, 2, 0x000000, 0xFFFFFF);
|
||||
unsigned long long lines = fv.size();
|
||||
unsigned long long i;
|
||||
unsigned j;
|
||||
for(i = pos, j = 3; i < pos + lines_to_display; i++, j++) {
|
||||
text_framebuffer::element e;
|
||||
if(i >= lines) {
|
||||
//Out of range.
|
||||
e.bg = 0xFFFFFF;
|
||||
e.fg = 0x000000;
|
||||
e.ch = 32;
|
||||
for(unsigned k = 0; k < fbsize.first; k++)
|
||||
_fb[j * fbstride + k] = e;
|
||||
} else {
|
||||
controller_frame frame = fv[i];
|
||||
render_linen(fb, frame, i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::on_mouse0(unsigned x, unsigned y, bool polarity)
|
||||
{
|
||||
if(y < 3)
|
||||
return;
|
||||
if(polarity) {
|
||||
press_x = x;
|
||||
press_line = spos + y - 3;
|
||||
}
|
||||
pressed = polarity;
|
||||
if(polarity)
|
||||
return;
|
||||
uint64_t line = spos + y - 3;
|
||||
if(press_x < divcnt && x < divcnt) {
|
||||
//Press on frame count.
|
||||
recursing = true;
|
||||
auto _press_line = press_line;
|
||||
runemufn([_press_line, line]() {
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
auto a_press_line = _press_line;
|
||||
auto a_line = line;
|
||||
if(a_press_line > a_line)
|
||||
std::swap(a_press_line, a_line);
|
||||
for(uint64_t i = a_press_line; i <= a_line; i++)
|
||||
fv.append(fv.blank_frame(true));
|
||||
movb.get_movie().recount_frames();
|
||||
update_movie_state();
|
||||
graphics_driver_notify_status();
|
||||
});
|
||||
recursing = false;
|
||||
}
|
||||
for(auto i : fcontrols.get_controlinfo()) {
|
||||
unsigned off = divcnt + 1;
|
||||
unsigned idx = i.index;
|
||||
frame_controls* _fcontrols = &fcontrols;
|
||||
if(press_x >= i.position_left + off && press_x < i.position_left + i.reserved + off) {
|
||||
if(i.type == 0) {
|
||||
//Button.
|
||||
if(press_x == x) {
|
||||
//Drag action.
|
||||
auto _press_line = press_line;
|
||||
recursing = true;
|
||||
runemufn([idx, _press_line, line, _fcontrols]() {
|
||||
if(!movb.get_movie().readonly_mode())
|
||||
return;
|
||||
uint64_t fedit = first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
auto a_press_line = _press_line;
|
||||
auto a_line = line;
|
||||
if(a_press_line > a_line)
|
||||
std::swap(a_press_line, a_line);
|
||||
for(uint64_t i = a_press_line; i <= a_line; i++) {
|
||||
if(i >= fv.size())
|
||||
continue;
|
||||
if(i < fedit)
|
||||
continue;
|
||||
controller_frame cf = fv[i];
|
||||
_fcontrols->write_index(cf, idx,
|
||||
!_fcontrols->read_index(cf, idx));
|
||||
}
|
||||
if(idx == 0) {
|
||||
movb.get_movie().recount_frames();
|
||||
update_movie_state();
|
||||
graphics_driver_notify_status();
|
||||
}
|
||||
});
|
||||
recursing = false;
|
||||
if(idx == 0) {
|
||||
max_subframe = 0; //Reparse.
|
||||
}
|
||||
}
|
||||
} else if(i.type == 1) {
|
||||
if(press_x == x && press_line == line) {
|
||||
//Click change value.
|
||||
short value;
|
||||
bool valid = true;
|
||||
runemufn([idx, line, &value, _fcontrols, &valid]() {
|
||||
if(!movb.get_movie().readonly_mode()) {
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
uint64_t fedit = first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
if(line < fedit) {
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
if(line >= fv.size())
|
||||
return;
|
||||
controller_frame cf = fv[line];
|
||||
value = _fcontrols->read_index(cf, idx);
|
||||
});
|
||||
if(!valid)
|
||||
continue;
|
||||
try {
|
||||
std::string text = pick_text(m, "Set value", "Enter new value:",
|
||||
(stringfmt() << value).str());
|
||||
value = parse_value<short>(text);
|
||||
} catch(canceled_exception& e) {
|
||||
return;
|
||||
} catch(std::exception& e) {
|
||||
wxMessageBox(wxT("Invalid value"), _T("Error"), wxICON_EXCLAMATION |
|
||||
wxOK, m);
|
||||
return;
|
||||
}
|
||||
runemufn([idx, line, value, _fcontrols]() {
|
||||
uint64_t fedit = first_editable(*_fcontrols, idx);
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
if(line < fedit)
|
||||
return;
|
||||
if(line >= fv.size())
|
||||
return;
|
||||
controller_frame cf = fv[line];
|
||||
_fcontrols->write_index(cf, idx, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::on_mouse1(unsigned x, unsigned y, bool polarity) {}
|
||||
void wxeditor_movie::_moviepanel::on_mouse2(unsigned x, unsigned y, bool polarity) {}
|
||||
|
||||
int wxeditor_movie::_moviepanel::get_lines()
|
||||
{
|
||||
controller_frame_vector& fv = movb.get_movie().get_frame_vector();
|
||||
return fv.size();
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::signal_repaint()
|
||||
{
|
||||
if(requested || recursing)
|
||||
return;
|
||||
auto s = m->get_scroll();
|
||||
requested = true;
|
||||
int lines, width;
|
||||
wxeditor_movie* m2 = m;
|
||||
runemufn([&lines, &width, m2, this]() {
|
||||
lines = this->get_lines();
|
||||
if(lines < lines_to_display)
|
||||
this->moviepos = 0;
|
||||
else if(this->moviepos > lines - lines_to_display)
|
||||
this->moviepos = lines - lines_to_display;
|
||||
this->render(fb, moviepos);
|
||||
auto x = fb.get_characters();
|
||||
width = x.first;
|
||||
});
|
||||
int prev_width = new_width;
|
||||
new_width = width;
|
||||
if(s)
|
||||
s->SetScrollbar(moviepos, lines_to_display, lines, lines_to_display - 1);
|
||||
auto size = fb.get_pixels();
|
||||
pixels.resize(size.first * size.second * 3);
|
||||
fb.render((char*)&pixels[0]);
|
||||
if(prev_width != new_width) {
|
||||
auto cell = fb.get_cell();
|
||||
SetMinSize(wxSize(new_width * cell.first, (lines_to_display + 3) * cell.second));
|
||||
if(new_width > 0 && s)
|
||||
m->Fit();
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::on_mouse(wxMouseEvent& e)
|
||||
{
|
||||
auto cell = fb.get_cell();
|
||||
if(e.LeftDown())
|
||||
on_mouse0(e.GetX() / cell.first, e.GetY() / cell.second, true);
|
||||
if(e.LeftUp())
|
||||
on_mouse0(e.GetX() / cell.first, e.GetY() / cell.second, false);
|
||||
if(e.MiddleDown())
|
||||
on_mouse1(e.GetX() / cell.first, e.GetY() / cell.second, true);
|
||||
if(e.MiddleUp())
|
||||
on_mouse1(e.GetX() / cell.first, e.GetY() / cell.second, false);
|
||||
if(e.RightDown())
|
||||
on_mouse2(e.GetX() / cell.first, e.GetY() / cell.second, true);
|
||||
if(e.RightUp())
|
||||
on_mouse2(e.GetX() / cell.first, e.GetY() / cell.second, false);
|
||||
int wrotate = e.GetWheelRotation();
|
||||
int threshold = e.GetWheelDelta();
|
||||
bool scrolled = false;
|
||||
auto s = m->get_scroll();
|
||||
scroll_delta += wrotate;
|
||||
while(wrotate && scroll_delta <= -threshold) {
|
||||
//Scroll down by line.
|
||||
moviepos++;
|
||||
if(movielines <= lines_to_display)
|
||||
moviepos = 0;
|
||||
else if(moviepos > movielines - lines_to_display + 1)
|
||||
moviepos = movielines - lines_to_display + 1;
|
||||
scrolled = true;
|
||||
scroll_delta += threshold;
|
||||
}
|
||||
while(wrotate && scroll_delta >= threshold) {
|
||||
//Scroll up by line.
|
||||
if(moviepos > 0)
|
||||
moviepos--;
|
||||
scrolled = true;
|
||||
scroll_delta -= threshold;
|
||||
}
|
||||
if(scrolled)
|
||||
s->SetThumbPosition(moviepos);
|
||||
signal_repaint();
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::on_scroll(wxScrollEvent& e)
|
||||
{
|
||||
auto s = m->get_scroll();
|
||||
if(s)
|
||||
moviepos = s->GetThumbPosition();
|
||||
else
|
||||
moviepos = 0;
|
||||
signal_repaint();
|
||||
}
|
||||
|
||||
void wxeditor_movie::_moviepanel::on_paint(wxPaintEvent& e)
|
||||
{
|
||||
auto size = fb.get_pixels();
|
||||
if(!size.first || !size.second) {
|
||||
wxPaintDC dc(this);
|
||||
dc.Clear();
|
||||
requested = false;
|
||||
return;
|
||||
}
|
||||
wxPaintDC dc(this);
|
||||
dc.Clear();
|
||||
wxBitmap bmp(wxImage(size.first, size.second, &pixels[0], true));
|
||||
dc.DrawBitmap(bmp, 0, 0, false);
|
||||
requested = false;
|
||||
}
|
||||
|
||||
wxeditor_movie::wxeditor_movie(wxWindow* parent)
|
||||
: wxDialog(parent, wxID_ANY, wxT("lsnes: Edit movie"), wxDefaultPosition, wxSize(-1, -1))
|
||||
{
|
||||
closing = false;
|
||||
Centre();
|
||||
wxFlexGridSizer* top_s = new wxFlexGridSizer(2, 1, 0, 0);
|
||||
SetSizer(top_s);
|
||||
|
||||
wxBoxSizer* panel_s = new wxBoxSizer(wxHORIZONTAL);
|
||||
moviescroll = NULL;
|
||||
panel_s->Add(moviepanel = new _moviepanel(this), 1, wxGROW);
|
||||
panel_s->Add(moviescroll = new wxScrollBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxSB_VERTICAL), 0, wxGROW);
|
||||
top_s->Add(panel_s, 1, wxGROW);
|
||||
connect_events(moviescroll, wxScrollEventHandler(wxeditor_movie::_moviepanel::on_scroll), moviepanel);
|
||||
moviepanel->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(wxeditor_movie::on_keyboard_down), NULL, this);
|
||||
moviepanel->Connect(wxEVT_KEY_UP, wxKeyEventHandler(wxeditor_movie::on_keyboard_up), NULL, this);
|
||||
|
||||
wxBoxSizer* pbutton_s = new wxBoxSizer(wxHORIZONTAL);
|
||||
pbutton_s->AddStretchSpacer();
|
||||
pbutton_s->Add(closebutton = new wxButton(this, wxID_OK, wxT("Close")), 0, wxGROW);
|
||||
closebutton->Connect(wxEVT_COMMAND_BUTTON_CLICKED,
|
||||
wxCommandEventHandler(wxeditor_movie::on_close), NULL, this);
|
||||
top_s->Add(pbutton_s, 0, wxGROW);
|
||||
|
||||
moviepanel->SetFocus();
|
||||
moviescroll->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxeditor_movie::on_focus_wrong), NULL, this);
|
||||
closebutton->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxeditor_movie::on_focus_wrong), NULL, this);
|
||||
Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(wxeditor_movie::on_focus_wrong), NULL, this);
|
||||
|
||||
panel_s->SetSizeHints(this);
|
||||
pbutton_s->SetSizeHints(this);
|
||||
top_s->SetSizeHints(this);
|
||||
Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(wxeditor_movie::on_wclose));
|
||||
Fit();
|
||||
|
||||
moviepanel->signal_repaint();
|
||||
}
|
||||
|
||||
bool wxeditor_movie::ShouldPreventAppExit() const { return false; }
|
||||
|
||||
void wxeditor_movie::on_close(wxCommandEvent& e)
|
||||
{
|
||||
movieeditor_open = NULL;
|
||||
Destroy();
|
||||
closing = true;
|
||||
}
|
||||
|
||||
void wxeditor_movie::on_wclose(wxCloseEvent& e)
|
||||
{
|
||||
bool wasc = closing;
|
||||
closing = true;
|
||||
movieeditor_open = NULL;
|
||||
if(!wasc)
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void wxeditor_movie::update()
|
||||
{
|
||||
moviepanel->signal_repaint();
|
||||
}
|
||||
|
||||
wxScrollBar* wxeditor_movie::get_scroll()
|
||||
{
|
||||
return moviescroll;
|
||||
}
|
||||
|
||||
void wxeditor_movie::on_focus_wrong(wxFocusEvent& e)
|
||||
{
|
||||
moviepanel->SetFocus();
|
||||
}
|
||||
|
||||
void wxeditor_movie_display(wxWindow* parent)
|
||||
{
|
||||
if(movieeditor_open)
|
||||
return;
|
||||
wxeditor_movie* v = new wxeditor_movie(parent);
|
||||
v->Show();
|
||||
movieeditor_open = v;
|
||||
}
|
||||
|
||||
void wxeditor_movie::on_keyboard_down(wxKeyEvent& e)
|
||||
{
|
||||
handle_wx_keyboard(e, true);
|
||||
}
|
||||
|
||||
void wxeditor_movie::on_keyboard_up(wxKeyEvent& e)
|
||||
{
|
||||
handle_wx_keyboard(e, false);
|
||||
}
|
||||
|
||||
void wxeditor_movie_update()
|
||||
{
|
||||
if(movieeditor_open)
|
||||
movieeditor_open->update();
|
||||
}
|
|
@ -138,6 +138,7 @@ namespace
|
|||
} else if(c == UISERV_UPDATE_STATUS) {
|
||||
if(main_window)
|
||||
main_window->notify_update_status();
|
||||
wxeditor_movie_update();
|
||||
} else if(c == UISERV_UPDATE_SCREEN) {
|
||||
if(main_window)
|
||||
main_window->notify_update();
|
||||
|
@ -507,9 +508,9 @@ bool lsnes_app::OnInit()
|
|||
port_type_set& ports = port_type_set::make(ctrldata.ports, ctrldata.portindex);
|
||||
mov->input.clear(ports);
|
||||
mov->coreversion = rom->rtype->get_core_identifier();
|
||||
mov->projectid = get_random_hexstring(40);
|
||||
if(c_rom != "") {
|
||||
//Initialize the remainder.
|
||||
mov->projectid = get_random_hexstring(40);
|
||||
mov->rerecords = "0";
|
||||
for(size_t i = 0; i < sizeof(rom->romimg)/sizeof(rom->romimg[0]); i++) {
|
||||
mov->romimg_sha256[i] = rom->romimg[i].sha_256;
|
||||
|
|
|
@ -107,7 +107,8 @@ enum
|
|||
wxID_RROM_FIRST,
|
||||
wxID_RROM_LAST = wxID_RROM_FIRST + 16,
|
||||
wxID_CONFLICTRESOLUTION,
|
||||
wxID_VUDISPLAY
|
||||
wxID_VUDISPLAY,
|
||||
wxID_MOVIE_EDIT
|
||||
};
|
||||
|
||||
|
||||
|
@ -327,6 +328,8 @@ namespace
|
|||
const port_controller& ctrl = *pt.controller_info->controllers[controller];
|
||||
unsigned j = 0;
|
||||
for(unsigned i = 0; i < ctrl.button_count; i++) {
|
||||
if(ctrl.buttons[i]->shadow)
|
||||
continue;
|
||||
if(ctrl.buttons[i]->type != port_controller_button::TYPE_BUTTON)
|
||||
continue;
|
||||
int id = amenu.allocate_wxid();
|
||||
|
@ -861,6 +864,8 @@ wxwin_mainwindow::wxwin_mainwindow()
|
|||
menu_separator();
|
||||
menu_entry(wxID_MEMORY_SEARCH, wxT("Memory Search..."));
|
||||
menu_separator();
|
||||
menu_entry(wxID_MOVIE_EDIT, wxT("Edit movie..."));
|
||||
menu_separator();
|
||||
menu_special_sub(wxT("Video Capture"), reinterpret_cast<dumper_menu*>(dmenu = new dumper_menu(this,
|
||||
wxID_DUMP_FIRST, wxID_DUMP_LAST)));
|
||||
|
||||
|
@ -1247,5 +1252,8 @@ void wxwin_mainwindow::handle_menu_click_cancelable(wxCommandEvent& e)
|
|||
case wxID_VUDISPLAY:
|
||||
open_vumeter_window(this);
|
||||
return;
|
||||
case wxID_MOVIE_EDIT:
|
||||
wxeditor_movie_display(this);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -296,6 +296,7 @@ void wxwin_vumeter::refresh()
|
|||
|
||||
void wxwin_vumeter::on_close(wxCommandEvent& e)
|
||||
{
|
||||
closing = true;
|
||||
Destroy();
|
||||
vumeter_open = false;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue