WIP: Support keyboard input device
This commit is contained in:
parent
425e1fc097
commit
6736ecc285
8 changed files with 260 additions and 38 deletions
|
@ -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<port_controller_button> buttons; //Buttons.
|
||||
std::map<signed, std::u32string> 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<unsigned, unsigned> 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<class port_type*> 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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -159,8 +159,10 @@ port_type_set::port_type_set(std::vector<class port_type*> 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<class port_type*> 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<uint32_t>& 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<unsigned, unsigned> 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:
|
||||
;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<unsigned> 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<uint64_t>::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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue