diff --git a/include/library/controller-data.hpp b/include/library/controller-data.hpp index b3a37fa1..ad70c634 100644 --- a/include/library/controller-data.hpp +++ b/include/library/controller-data.hpp @@ -191,6 +191,7 @@ struct port_controller_button TYPE_RAXIS, //Relative Axis (mouse). TYPE_TAXIS, //Throttle Axis (does not pair). TYPE_LIGHTGUN, //Lightgun axis. + TYPE_KEYBOARD, //Keyboard. The names are translated via namemap. }; enum _type type; char32_t symbol; @@ -216,6 +217,8 @@ struct port_controller std::string cclass; //Controller class. std::string type; //Controller type. std::vector buttons; //Buttons. + std::map namemap; //Button translation map. + unsigned reserved_idx; //Number of extra reserved indices. /** * Count number of analog actions on this controller. */ @@ -233,6 +236,15 @@ struct port_controller return NULL; return &buttons[i]; } +/** + * Access specified entry in namemap. Returns '???' if unknown. + */ + std::u32string get_namemap_entry(short entry) const + { + if(!namemap.count(entry)) + return U"???"; + return namemap.find(entry)->second; + } }; /** @@ -336,12 +348,12 @@ public: * Get number of used control indices on controller. * * Parameter controller: Number of controller. - * Returns: Number of used control indices. + * Returns: Number of used control indices. First is number of actual indices, second is number of reserved ones. */ - unsigned used_indices(unsigned controller) + std::pair used_indices(unsigned controller) const { auto c = controller_info->get(controller); - return c ? c->buttons.size() : 0; + return c ? std::make_pair((unsigned)c->buttons.size(), c->reserved_idx) : std::make_pair(0U, 0U); } /** * Human-readable name. @@ -519,6 +531,12 @@ public: throw std::runtime_error("Bad legacy PCID"); return legacy_pcids[pcid]; } +/** + * Set pollcounters mask. + * + * Parameter mask: The mask to write. + */ + void set_pollcounter_mask(uint32_t* mask) const; private: port_type_set(std::vector types, struct port_index_map control_map); size_t* port_offsets; @@ -566,10 +584,14 @@ public: * Assign the pollcounter_vector. */ pollcounter_vector& operator=(const pollcounter_vector& v) throw(std::bad_alloc); +/** + * Zero all unmasked poll counters and clear all DRDY bits. System flag is cleared. + */ + void clear_unmasked() throw(); /** * Zero all poll counters and clear all DRDY bits. System flag is cleared. */ - void clear() throw(); + void clear_all() throw(); /** * Set all DRDY bits. */ @@ -707,8 +729,47 @@ public: * Get raw pollcounter data. */ const uint32_t* rawdata() const throw() { return ctrs; } +/** + * Write reserved index for controller. + * + * Parameter port: The port. + * Parameter controller: The controller. + * Parameter _index: The reserved index (0-based). + * Parameter val: The value to write. + * Throws std::runtime_error: Specified reserved slot is not valid. + */ + void reserved(unsigned port, unsigned controller, unsigned _index, uint32_t val) + throw(std::runtime_error) + { + auto counts = (port < types->ports()) ? types->port_type(port).used_indices(controller) : + std::make_pair(0U, 0U); + unsigned pindex = types->triple_to_index(port, controller, _index + counts.first); + if(pindex == 0xFFFFFFFFU) + throw std::runtime_error("write_reserved: Invalid reserved index"); + ctrs[pindex] = val; + } +/** + * Read reserved index for controller. + * + * Parameter port: The port. + * Parameter controller: The controller. + * Parameter _index: The reserved index (0-based). + * Returns: The value read. + * Throws std::runtime_error: Specified reserved slot is not valid. + */ + uint32_t reserved(unsigned port, unsigned controller, unsigned _index) + throw(std::runtime_error) + { + auto counts = (port < types->ports()) ? types->port_type(port).used_indices(controller) : + std::make_pair(0U, 0U); + unsigned pindex = types->triple_to_index(port, controller, _index + counts.first); + if(pindex == 0xFFFFFFFFU) + throw std::runtime_error("write_reserved: Invalid reserved index"); + return ctrs[pindex]; + } private: uint32_t* ctrs; + uint32_t* ctrs_valid_mask; const port_type_set* types; bool framepflag; }; diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index 4c943bd6..cf86a3f2 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -161,6 +161,7 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo core.vi_prev_frame = false; } platform::flush_command_queue(); + //TODO: Collapse keyboard symbols. controller_frame tmp = core.controls->get(core.mlogic->get_movie().get_current_frame()); core.rom->pre_emulate_frame(tmp); //Preset controls, the lua will override if needed. core.lua2->callback_do_input(tmp, subframe); diff --git a/src/library/controller-data.cpp b/src/library/controller-data.cpp index 21f3011e..cc9bc68d 100644 --- a/src/library/controller-data.cpp +++ b/src/library/controller-data.cpp @@ -159,8 +159,10 @@ port_type_set::port_type_set(std::vector types, struct port_in //Count maximum number of controller indices to determine the controller multiplier. controller_multiplier = 1; for(size_t i = 0; i < port_count; i++) - for(unsigned j = 0; j < types[i]->controller_info->controllers.size(); j++) - controller_multiplier = max(controller_multiplier, (size_t)types[i]->used_indices(j)); + for(unsigned j = 0; j < types[i]->controller_info->controllers.size(); j++) { + auto idxcnt = types[i]->used_indices(j); + controller_multiplier = max(controller_multiplier, (size_t)(idxcnt.first + idxcnt.second)); + } //Count maximum number of controllers to determine the port multiplier. port_multiplier = 1; for(size_t i = 0; i < port_count; i++) @@ -193,6 +195,28 @@ port_type_set::port_type_set(std::vector types, struct port_in } } +void port_type_set::set_pollcounter_mask(uint32_t* mask) const +{ + for(unsigned i = 0; i < indices_size; i++) { + unsigned v = indices_tab[i]; + //i is the index into map (which decomposes into triple). v is the index in array (which may be + //invalid). + if(v == 0xFFFFFFFFUL) + continue; + unsigned _port = i / port_multiplier; + unsigned _controller = (i % port_multiplier) / controller_multiplier; + unsigned _button = i % controller_multiplier; + if(_port >= port_count) + continue; + //Determine if this is reserved or not (it is reserved if index is beyond limit) and set bit. + auto idxcnt = port_types[_port]->used_indices(_controller); + if(_button >= idxcnt.first) + mask[v >> 5] &= ~(1U << (v & 31)); + else + mask[v >> 5] |= (1U << (v & 31)); + } +} + short read_axis_value(const char* buf, size_t& idx) throw() { char ch; @@ -272,7 +296,6 @@ void controller_frame::display(unsigned port, unsigned controller, char32_t* buf } const port_controller& pc = ptype.controller_info->controllers[controller]; bool need_space = false; - short val; for(unsigned i = 0; i < pc.buttons.size(); i++) { const port_controller_button& pcb = pc.buttons[i]; if(need_space && pcb.type != port_controller_button::TYPE_NULL) { @@ -289,8 +312,14 @@ void controller_frame::display(unsigned port, unsigned controller, char32_t* buf case port_controller_button::TYPE_RAXIS: case port_controller_button::TYPE_TAXIS: case port_controller_button::TYPE_LIGHTGUN: - val = ptype.read(&ptype, backingmem, controller, i); - buf += writeu32val(buf, val); + buf += writeu32val(buf, ptype.read(&ptype, backingmem, controller, i)); + need_space = true; + break; + case port_controller_button::TYPE_KEYBOARD: + //Write name. + auto str = pc.get_namemap_entry(ptype.read(&ptype, backingmem, controller, i)); + for(auto x : str) + *(buf++) = x; need_space = true; break; } @@ -301,22 +330,34 @@ void controller_frame::display(unsigned port, unsigned controller, char32_t* buf pollcounter_vector::pollcounter_vector() throw(std::bad_alloc) { types = &dummytypes(); - ctrs = new uint32_t[types->indices()]; - clear(); + size_t elts_base = types->indices(); + size_t elts_mask = (elts_base + 31) / 32; + size_t elts_all = elts_base + elts_mask; + ctrs = new uint32_t[elts_all]; + memset(ctrs_valid_mask = ctrs + elts_base, 0xFF, sizeof(uint32_t) * elts_mask); + clear_all(); } pollcounter_vector::pollcounter_vector(const port_type_set& p) throw(std::bad_alloc) { types = &p; - ctrs = new uint32_t[types->indices()]; - clear(); + size_t elts_base = types->indices(); + size_t elts_mask = (elts_base + 31) / 32; + size_t elts_all = elts_base + elts_mask; + ctrs = new uint32_t[elts_all]; + types->set_pollcounter_mask(ctrs_valid_mask = ctrs + elts_base); + clear_all(); } pollcounter_vector::pollcounter_vector(const pollcounter_vector& p) throw(std::bad_alloc) { - ctrs = new uint32_t[p.types->indices()]; + size_t elts_base = p.types->indices(); + size_t elts_mask = (elts_base + 31) / 32; + size_t elts_all = elts_base + elts_mask; + ctrs = new uint32_t[elts_all]; + ctrs_valid_mask = ctrs + elts_base; types = p.types; - memcpy(ctrs, p.ctrs, sizeof(uint32_t) * p.types->indices()); + memcpy(ctrs, p.ctrs, sizeof(uint32_t) * elts_all); framepflag = p.framepflag; } @@ -324,21 +365,34 @@ pollcounter_vector& pollcounter_vector::operator=(const pollcounter_vector& p) t { if(this == &p) return *this; - uint32_t* n = new uint32_t[p.types->indices()]; + size_t elts_base = p.types->indices(); + size_t elts_mask = (elts_base + 31) / 32; + size_t elts_all = elts_base + elts_mask; + uint32_t* n = new uint32_t[elts_all]; types = p.types; - memcpy(n, p.ctrs, sizeof(uint32_t) * p.types->indices()); + memcpy(n, p.ctrs, sizeof(uint32_t) * elts_all); delete[] ctrs; ctrs = n; + ctrs_valid_mask = ctrs + elts_base; framepflag = p.framepflag; return *this; } pollcounter_vector::~pollcounter_vector() throw() { + //ctrs_valid_mask is part of this. delete[] ctrs; } -void pollcounter_vector::clear() throw() +void pollcounter_vector::clear_unmasked() throw() +{ + for(size_t i = 0; i < types->indices(); i++) + if((ctrs_valid_mask[i >> 5] >> (i & 31)) & 1) + ctrs[i] = 0; + framepflag = false; +} + +void pollcounter_vector::clear_all() throw() { memset(ctrs, 0, sizeof(uint32_t) * types->indices()); framepflag = false; @@ -346,46 +400,65 @@ void pollcounter_vector::clear() throw() void pollcounter_vector::set_all_DRDY() throw() { + //Only manipulate valid pcounters. for(size_t i = 0; i < types->indices(); i++) - ctrs[i] |= 0x80000000UL; + if((ctrs_valid_mask[i >> 5] >> (i & 31)) & 1) + ctrs[i] |= 0x80000000UL; } void pollcounter_vector::clear_DRDY(unsigned idx) throw() { - ctrs[idx] &= 0x7FFFFFFFUL; + //Only manipulate valid pcounters. + if((ctrs_valid_mask[idx >> 5] >> (idx & 31)) & 1) + ctrs[idx] &= 0x7FFFFFFFUL; } bool pollcounter_vector::get_DRDY(unsigned idx) throw() { - return ((ctrs[idx] & 0x80000000UL) != 0); + //For not valid pcounters, DRDY is permanently 1. + if((ctrs_valid_mask[idx >> 5] >> (idx & 31)) & 1) + return ((ctrs[idx] & 0x80000000UL) != 0); + else + return true; } bool pollcounter_vector::has_polled() throw() { uint32_t res = 0; - for(size_t i = 0; i < types->indices() ; i++) - res |= ctrs[i]; + for(size_t i = 0; i < types->indices(); i++) + if((ctrs_valid_mask[i >> 5] >> (i & 31)) & 1) + res |= ctrs[i]; return ((res & 0x7FFFFFFFUL) != 0); } uint32_t pollcounter_vector::get_polls(unsigned idx) throw() { - return ctrs[idx] & 0x7FFFFFFFUL; + //For not valid pcounters, polls is permanently 0. + if((ctrs_valid_mask[idx >> 5] >> (idx & 31)) & 1) + return ctrs[idx] & 0x7FFFFFFFUL; + else + return 0; } uint32_t pollcounter_vector::increment_polls(unsigned idx) throw() { - uint32_t x = ctrs[idx] & 0x7FFFFFFFUL; - ++ctrs[idx]; - return x; + //Only manipulate valid pcounters, for others, permanently 0. + if((ctrs_valid_mask[idx >> 5] >> (idx & 31)) & 1) { + uint32_t x = ctrs[idx] & 0x7FFFFFFFUL; + ++ctrs[idx]; + return x; + } else + return 0; } uint32_t pollcounter_vector::max_polls() throw() { uint32_t max = 0; for(unsigned i = 0; i < types->indices(); i++) { - uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL; - max = (max < tmp) ? tmp : max; + if((ctrs_valid_mask[i >> 5] >> (i & 31)) & 1) { + uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL; + max = (max < tmp) ? tmp : max; + } } return max; } @@ -393,7 +466,6 @@ uint32_t pollcounter_vector::max_polls() throw() void pollcounter_vector::save_state(std::vector& mem) throw(std::bad_alloc) { mem.resize(types->indices()); - //Compatiblity fun. for(size_t i = 0; i < types->indices(); i++) mem[i] = ctrs[i]; } @@ -824,6 +896,7 @@ unsigned port_controller::analog_actions() const break; case port_controller_button::TYPE_NULL: case port_controller_button::TYPE_BUTTON: + case port_controller_button::TYPE_KEYBOARD: ; }; } @@ -868,6 +941,7 @@ std::pair port_controller::analog_action(unsigned k) const break; case port_controller_button::TYPE_NULL: case port_controller_button::TYPE_BUTTON: + case port_controller_button::TYPE_KEYBOARD: ; }; } diff --git a/src/library/controller-parse.cpp b/src/library/controller-parse.cpp index ef929bef..9709c815 100644 --- a/src/library/controller-parse.cpp +++ b/src/library/controller-parse.cpp @@ -23,6 +23,22 @@ namespace return y.str(); } + std::string quote(const std::u32string& _s) + { + auto s = utf8::to8(_s); + std::ostringstream y; + y << "U\""; + for(auto i : s) + if(i == '\"') + y << "\""; + else if(i == '\\') + y << "\\\\"; + else + y << i; + y << "\""; + return y.str(); + } + std::string read_str(const JSON::node& root, const JSON::pointer& ptr) { if(root.type_of(ptr) != JSON::string) @@ -117,6 +133,22 @@ namespace return ret; } + port_controller_button pcb_key(const JSON::node& root, const JSON::pointer& ptr) + { + auto pshadow = ptr.field("shadow"); + auto pname = ptr.field("name"); + struct port_controller_button ret; + ret.type = port_controller_button::TYPE_KEYBOARD; + ret.symbol = U'\0'; + ret.shadow = (root.type_of(pshadow) != JSON::none) ? read_bool(root, pshadow) : false; + ret.rmin = 0; + ret.rmax = 0; + ret.centers = false; + ret.macro = ""; + ret.msymbol = '\0'; + return ret; + } + struct port_controller_button pcs_parse_button(const JSON::node& root, JSON::pointer ptr) { if(root.type_of_indirect(ptr) != JSON::object) @@ -129,6 +161,8 @@ namespace return pcb_button(root, ptr); else if(type == "axis" || type == "raxis" || type == "taxis" || type == "lightgun") return pcb_axis(root, ptr, type); + else if(type == "key") + return pcb_key(root, ptr); else (stringfmt() << "Unknown type '" << type << "' for '" << ptr << "'").throwex(); return pcb_null(root, ptr); //NOTREACHED. @@ -153,6 +187,22 @@ namespace ret.cclass = cclass; ret.type = type; ret.buttons = buttons; + JSON::pointer _buttonmap = ptr.field("buttonmap"); + //Namemap is OPTIONAL. If present, it must be an array, giving the entries as strings (or nil) + //for not present. + if(root.type_of_indirect(_buttonmap) != JSON::none) { + if(root.type_of_indirect(_buttonmap) != JSON::array) + (stringfmt() << "Expected array or not present for '" << _buttonmap << "'").throwex(); + for(auto i = root[_buttonmap].begin(); i != root[_buttonmap].end(); ++i) { + if(i->type() == JSON::string) { + ret.namemap[i.index()] = i->as_string(); + } else if(i->type() != JSON::none) { + (stringfmt() << "Expected string or not present for '" + << _buttonmap.index(i.index()) << "'").throwex(); + } + } + } + ret.reserved_idx = (ret.namemap.size() + 31) / 32; //One bit per namemap entry. return ret; } @@ -202,6 +252,7 @@ namespace case port_controller_button::TYPE_RAXIS: s << "RAXIS"; break; case port_controller_button::TYPE_TAXIS: s << "TAXIS"; break; case port_controller_button::TYPE_LIGHTGUN: s << "LIGHTGUN"; break; + case port_controller_button::TYPE_KEYBOARD: s << "KEYBOARD"; break; } s << "," << (int)b.symbol << ", " << quote(b.name) << ", " << b.shadow << ", " << b.rmin << ", " << b.rmax << ", " << b.centers << ", " << quote(b.macro) << ", " << (int)b.msymbol << "}"; @@ -216,7 +267,10 @@ namespace write_button(s, i); s << ",\n"; } - s << "}};\n"; + s << "},{"; + for(auto i : c.namemap) + s << "\t{" << i.first << ", " << quote(i.second) << "},\n"; + s << "}," << c.reserved_idx << "};\n"; } void write_portdata(std::ostream& s, const port_controller_set& cs, unsigned& idx) @@ -249,6 +303,7 @@ namespace case port_controller_button::TYPE_NULL: break; case port_controller_button::TYPE_RAXIS: x+=16; break; case port_controller_button::TYPE_TAXIS: x+=16; break; + case port_controller_button::TYPE_KEYBOARD: x+=16; break; }; } return (x + 7) / 8; @@ -266,6 +321,7 @@ namespace case port_controller_button::TYPE_NULL: break; case port_controller_button::TYPE_RAXIS: break; case port_controller_button::TYPE_TAXIS: break; + case port_controller_button::TYPE_KEYBOARD: break; }; } return (x + 7) / 8; @@ -297,6 +353,7 @@ namespace case port_controller_button::TYPE_RAXIS: case port_controller_button::TYPE_TAXIS: case port_controller_button::TYPE_LIGHTGUN: + case port_controller_button::TYPE_KEYBOARD: ii.type = 2; ii.offset = aoffset + 2 * axisidx2; axisidx2++; @@ -343,6 +400,7 @@ namespace case port_controller_button::TYPE_RAXIS: case port_controller_button::TYPE_TAXIS: case port_controller_button::TYPE_LIGHTGUN: + case port_controller_button::TYPE_KEYBOARD: ins.type = 1; ins.offset = aoffset + 2 * axisidx; ret.push_back(ins); diff --git a/src/library/movie.cpp b/src/library/movie.cpp index c71858ca..d9744401 100644 --- a/src/library/movie.cpp +++ b/src/library/movie.cpp @@ -120,7 +120,7 @@ void movie::next_frame() throw(std::bad_alloc) } //Reset the poll counters and DRDY flags. - pollcounters.clear(); + pollcounters.clear_unmasked(); //Increment the current frame counter and subframe counter. Note that first subframe is undefined for //frame 0 and 0 for frame 1. @@ -346,7 +346,7 @@ void movie::reset_state() throw() readonly = true; current_frame = 0; current_frame_first_subframe = 0; - pollcounters.clear(); + pollcounters.clear_all(); lag_frames = 0; clear_caches(); } diff --git a/src/lua/input.cpp b/src/lua/input.cpp index c82e9ac6..ecb4c549 100644 --- a/src/lua/input.cpp +++ b/src/lua/input.cpp @@ -465,6 +465,7 @@ namespace case port_controller_button::TYPE_RAXIS: L.pushstring("raxis"); break; case port_controller_button::TYPE_TAXIS: L.pushstring("axis"); break; case port_controller_button::TYPE_LIGHTGUN: L.pushstring("lightgun"); break; + case port_controller_button::TYPE_KEYBOARD: L.pushstring("keyboard"); break; }; L.rawset(-3); if(cs.buttons[i].symbol) { diff --git a/src/platform/wxwidgets/editor-movie.cpp b/src/platform/wxwidgets/editor-movie.cpp index 80f94f47..4b6dfa95 100644 --- a/src/platform/wxwidgets/editor-movie.cpp +++ b/src/platform/wxwidgets/editor-movie.cpp @@ -74,6 +74,16 @@ namespace uint64_t divsl[] = {1000000, 100000, 10000, 1000, 100, 10, 0}; const unsigned divcnt = sizeof(divs)/sizeof(divs[0]); + bool is_ctype(int type) + { + return (type == 0 || type == 1 || type == 2); + } + + bool is_wtype(int type) + { + return (type == -1 || type == 1 || type == 2); + } + class exp_imp_type { public: @@ -110,7 +120,7 @@ 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. + int type; //-2 => Port, -1 => Fixed, 0 => Button, 1 => axis, 2 => Key char32_t ch; std::u32string title; unsigned port; @@ -124,6 +134,7 @@ struct control_info unsigned port, unsigned controller); static control_info axisinfo(unsigned& p, const std::u32string& title, unsigned idx, unsigned port, unsigned controller, port_controller_button::_type _axistype, int _rmin, int _rmax); + //TODO: keyinfo(). }; control_info control_info::portinfo(unsigned& p, unsigned port, unsigned controller) @@ -261,6 +272,8 @@ void frame_controls::add_port(unsigned& c, unsigned pid, const port_type& p, con controlinfo.push_back(control_info::axisinfo(c, utf8::to32(pcb.name), idx, pid, i, pcb.type, pcb.rmin, pcb.rmax)); last_multibyte = true; + } else if(pcb.type == port_controller_button::TYPE_KEYBOARD) { + //TODO } } if(nextp > c) @@ -322,7 +335,7 @@ void frame_controls::format_lines() //Line2 for(auto i : controlinfo) { auto _title = i.title; - if(i.type == -1 || i.type == 1) + if(is_wtype(i.type)) std::copy(_title.begin(), _title.end(), &cp2[i.position_left + off]); if(i.type == 0) cp2[i.position_left + off] = i.ch; @@ -389,6 +402,9 @@ namespace first = false; last_axis = true; break; + case 2: //key + //TODO. + break; } } return x.str(); @@ -450,6 +466,9 @@ namespace first = false; last_axis = true; break; + case 2: //Key. + //TODO. + break; } } } @@ -496,7 +515,7 @@ namespace { std::set r; for(auto i : info.get_controlinfo()) { - if(i.port == port && i.controller == controller && (i.type == 0 || i.type == 1)) + if(i.port == port && i.controller == controller && is_ctype(i.type)) r.insert(i.index); } return r; @@ -1016,6 +1035,9 @@ void wxeditor_movie::_moviepanel::render_linen(text_framebuffer& fb, controller_ char c[7]; sprintf(c, "%6d", fcontrols.read_index(f, i.index)); fb.write(c, 0, divcnt + 1 + i.position_left, y, 0x000000, bgc); + } else if(i.type == 2) { + //Key. + //TODO. } } } @@ -1416,6 +1438,8 @@ void wxeditor_movie::_moviepanel::on_mouse0(unsigned x, unsigned y, bool polarit } } else do_alter_axis(idx, press_line, line); + } else if(i.type == 2) { + //TODO. } } } @@ -1831,7 +1855,7 @@ void wxeditor_movie::_moviepanel::on_mouse2(unsigned x, unsigned y, bool polarit } else { for(auto i : fcontrols.get_controlinfo()) if(press_x >= i.position_left + off && press_x < i.position_left + i.reserved + off) { - if(i.type == 0 || i.type == 1) { + if(is_ctype(i.type)) { clicked_button = true; clicked = i; controller_name = (stringfmt() << "controller " << i.port << "-" @@ -1847,7 +1871,7 @@ void wxeditor_movie::_moviepanel::on_mouse2(unsigned x, unsigned y, bool polarit uint64_t ebutton_low = clicked_button ? first_editable(clicked.index) : std::numeric_limits::max(); uint64_t econtroller_low = ebutton_low; for(auto i : fcontrols.get_controlinfo()) - if(i.port == clicked.port && i.controller == clicked.controller && (i.type == 0 || i.type == 1)) + if(i.port == clicked.port && i.controller == clicked.controller && is_ctype(i.type)) econtroller_low = max(econtroller_low, first_editable(i.index)); bool click_zero = (clicked_button && !clicked.port && !clicked.controller); @@ -1876,6 +1900,7 @@ void wxeditor_movie::_moviepanel::on_mouse2(unsigned x, unsigned y, bool polarit press_line < linecount) || (rpress_line >= ebutton_low && rpress_line < linecount))); //Sweep axis is enabled if change axis is enabled and lines don't match. enable_sweep_axis = (enable_change_axis && press_line != rpress_line); + //TODO: Handle clicked.type == 2. //Insert frame is enabled if this frame is completely editable and press and release lines match. enable_insert_frame = (!not_editable && press_line + 1 >= eframe_low && press_line < linecount && press_line == rpress_line); diff --git a/src/platform/wxwidgets/editor-tasinput.cpp b/src/platform/wxwidgets/editor-tasinput.cpp index d95d7ef9..59023eed 100644 --- a/src/platform/wxwidgets/editor-tasinput.cpp +++ b/src/platform/wxwidgets/editor-tasinput.cpp @@ -522,6 +522,8 @@ void wxeditor_tasinput::update_controls() current->Add(t.check); t.check->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(wxeditor_tasinput::on_control), NULL, this); + } else if(i.type == port_controller_button::TYPE_KEYBOARD) { + //TODO. } else { t.panel = new xypanel(current_p, inst, current, i, this, wxCommandEventHandler(wxeditor_tasinput::on_control), next_id);