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_RAXIS, //Relative Axis (mouse).
|
||||||
TYPE_TAXIS, //Throttle Axis (does not pair).
|
TYPE_TAXIS, //Throttle Axis (does not pair).
|
||||||
TYPE_LIGHTGUN, //Lightgun axis.
|
TYPE_LIGHTGUN, //Lightgun axis.
|
||||||
|
TYPE_KEYBOARD, //Keyboard. The names are translated via namemap.
|
||||||
};
|
};
|
||||||
enum _type type;
|
enum _type type;
|
||||||
char32_t symbol;
|
char32_t symbol;
|
||||||
|
@ -216,6 +217,8 @@ struct port_controller
|
||||||
std::string cclass; //Controller class.
|
std::string cclass; //Controller class.
|
||||||
std::string type; //Controller type.
|
std::string type; //Controller type.
|
||||||
std::vector<port_controller_button> buttons; //Buttons.
|
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.
|
* Count number of analog actions on this controller.
|
||||||
*/
|
*/
|
||||||
|
@ -233,6 +236,15 @@ struct port_controller
|
||||||
return NULL;
|
return NULL;
|
||||||
return &buttons[i];
|
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.
|
* Get number of used control indices on controller.
|
||||||
*
|
*
|
||||||
* Parameter controller: Number of 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);
|
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.
|
* Human-readable name.
|
||||||
|
@ -519,6 +531,12 @@ public:
|
||||||
throw std::runtime_error("Bad legacy PCID");
|
throw std::runtime_error("Bad legacy PCID");
|
||||||
return legacy_pcids[pcid];
|
return legacy_pcids[pcid];
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Set pollcounters mask.
|
||||||
|
*
|
||||||
|
* Parameter mask: The mask to write.
|
||||||
|
*/
|
||||||
|
void set_pollcounter_mask(uint32_t* mask) const;
|
||||||
private:
|
private:
|
||||||
port_type_set(std::vector<class port_type*> types, struct port_index_map control_map);
|
port_type_set(std::vector<class port_type*> types, struct port_index_map control_map);
|
||||||
size_t* port_offsets;
|
size_t* port_offsets;
|
||||||
|
@ -566,10 +584,14 @@ public:
|
||||||
* Assign the pollcounter_vector.
|
* Assign the pollcounter_vector.
|
||||||
*/
|
*/
|
||||||
pollcounter_vector& operator=(const pollcounter_vector& v) throw(std::bad_alloc);
|
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.
|
* Zero all poll counters and clear all DRDY bits. System flag is cleared.
|
||||||
*/
|
*/
|
||||||
void clear() throw();
|
void clear_all() throw();
|
||||||
/**
|
/**
|
||||||
* Set all DRDY bits.
|
* Set all DRDY bits.
|
||||||
*/
|
*/
|
||||||
|
@ -707,8 +729,47 @@ public:
|
||||||
* Get raw pollcounter data.
|
* Get raw pollcounter data.
|
||||||
*/
|
*/
|
||||||
const uint32_t* rawdata() const throw() { return ctrs; }
|
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:
|
private:
|
||||||
uint32_t* ctrs;
|
uint32_t* ctrs;
|
||||||
|
uint32_t* ctrs_valid_mask;
|
||||||
const port_type_set* types;
|
const port_type_set* types;
|
||||||
bool framepflag;
|
bool framepflag;
|
||||||
};
|
};
|
||||||
|
|
|
@ -161,6 +161,7 @@ controller_frame movie_logic::update_controls(bool subframe) throw(std::bad_allo
|
||||||
core.vi_prev_frame = false;
|
core.vi_prev_frame = false;
|
||||||
}
|
}
|
||||||
platform::flush_command_queue();
|
platform::flush_command_queue();
|
||||||
|
//TODO: Collapse keyboard symbols.
|
||||||
controller_frame tmp = core.controls->get(core.mlogic->get_movie().get_current_frame());
|
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.rom->pre_emulate_frame(tmp); //Preset controls, the lua will override if needed.
|
||||||
core.lua2->callback_do_input(tmp, subframe);
|
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.
|
//Count maximum number of controller indices to determine the controller multiplier.
|
||||||
controller_multiplier = 1;
|
controller_multiplier = 1;
|
||||||
for(size_t i = 0; i < port_count; i++)
|
for(size_t i = 0; i < port_count; i++)
|
||||||
for(unsigned j = 0; j < types[i]->controller_info->controllers.size(); j++)
|
for(unsigned j = 0; j < types[i]->controller_info->controllers.size(); j++) {
|
||||||
controller_multiplier = max(controller_multiplier, (size_t)types[i]->used_indices(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.
|
//Count maximum number of controllers to determine the port multiplier.
|
||||||
port_multiplier = 1;
|
port_multiplier = 1;
|
||||||
for(size_t i = 0; i < port_count; i++)
|
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()
|
short read_axis_value(const char* buf, size_t& idx) throw()
|
||||||
{
|
{
|
||||||
char ch;
|
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];
|
const port_controller& pc = ptype.controller_info->controllers[controller];
|
||||||
bool need_space = false;
|
bool need_space = false;
|
||||||
short val;
|
|
||||||
for(unsigned i = 0; i < pc.buttons.size(); i++) {
|
for(unsigned i = 0; i < pc.buttons.size(); i++) {
|
||||||
const port_controller_button& pcb = pc.buttons[i];
|
const port_controller_button& pcb = pc.buttons[i];
|
||||||
if(need_space && pcb.type != port_controller_button::TYPE_NULL) {
|
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_RAXIS:
|
||||||
case port_controller_button::TYPE_TAXIS:
|
case port_controller_button::TYPE_TAXIS:
|
||||||
case port_controller_button::TYPE_LIGHTGUN:
|
case port_controller_button::TYPE_LIGHTGUN:
|
||||||
val = ptype.read(&ptype, backingmem, controller, i);
|
buf += writeu32val(buf, ptype.read(&ptype, backingmem, controller, i));
|
||||||
buf += writeu32val(buf, val);
|
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;
|
need_space = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -301,22 +330,34 @@ void controller_frame::display(unsigned port, unsigned controller, char32_t* buf
|
||||||
pollcounter_vector::pollcounter_vector() throw(std::bad_alloc)
|
pollcounter_vector::pollcounter_vector() throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
types = &dummytypes();
|
types = &dummytypes();
|
||||||
ctrs = new uint32_t[types->indices()];
|
size_t elts_base = types->indices();
|
||||||
clear();
|
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)
|
pollcounter_vector::pollcounter_vector(const port_type_set& p) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
types = &p;
|
types = &p;
|
||||||
ctrs = new uint32_t[types->indices()];
|
size_t elts_base = types->indices();
|
||||||
clear();
|
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)
|
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;
|
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;
|
framepflag = p.framepflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,21 +365,34 @@ pollcounter_vector& pollcounter_vector::operator=(const pollcounter_vector& p) t
|
||||||
{
|
{
|
||||||
if(this == &p)
|
if(this == &p)
|
||||||
return *this;
|
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;
|
types = p.types;
|
||||||
memcpy(n, p.ctrs, sizeof(uint32_t) * p.types->indices());
|
memcpy(n, p.ctrs, sizeof(uint32_t) * elts_all);
|
||||||
delete[] ctrs;
|
delete[] ctrs;
|
||||||
ctrs = n;
|
ctrs = n;
|
||||||
|
ctrs_valid_mask = ctrs + elts_base;
|
||||||
framepflag = p.framepflag;
|
framepflag = p.framepflag;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
pollcounter_vector::~pollcounter_vector() throw()
|
pollcounter_vector::~pollcounter_vector() throw()
|
||||||
{
|
{
|
||||||
|
//ctrs_valid_mask is part of this.
|
||||||
delete[] ctrs;
|
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());
|
memset(ctrs, 0, sizeof(uint32_t) * types->indices());
|
||||||
framepflag = false;
|
framepflag = false;
|
||||||
|
@ -346,46 +400,65 @@ void pollcounter_vector::clear() throw()
|
||||||
|
|
||||||
void pollcounter_vector::set_all_DRDY() throw()
|
void pollcounter_vector::set_all_DRDY() throw()
|
||||||
{
|
{
|
||||||
|
//Only manipulate valid pcounters.
|
||||||
for(size_t i = 0; i < types->indices(); i++)
|
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()
|
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()
|
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()
|
bool pollcounter_vector::has_polled() throw()
|
||||||
{
|
{
|
||||||
uint32_t res = 0;
|
uint32_t res = 0;
|
||||||
for(size_t i = 0; i < types->indices() ; i++)
|
for(size_t i = 0; i < types->indices(); i++)
|
||||||
res |= ctrs[i];
|
if((ctrs_valid_mask[i >> 5] >> (i & 31)) & 1)
|
||||||
|
res |= ctrs[i];
|
||||||
return ((res & 0x7FFFFFFFUL) != 0);
|
return ((res & 0x7FFFFFFFUL) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pollcounter_vector::get_polls(unsigned idx) throw()
|
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 pollcounter_vector::increment_polls(unsigned idx) throw()
|
||||||
{
|
{
|
||||||
uint32_t x = ctrs[idx] & 0x7FFFFFFFUL;
|
//Only manipulate valid pcounters, for others, permanently 0.
|
||||||
++ctrs[idx];
|
if((ctrs_valid_mask[idx >> 5] >> (idx & 31)) & 1) {
|
||||||
return x;
|
uint32_t x = ctrs[idx] & 0x7FFFFFFFUL;
|
||||||
|
++ctrs[idx];
|
||||||
|
return x;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pollcounter_vector::max_polls() throw()
|
uint32_t pollcounter_vector::max_polls() throw()
|
||||||
{
|
{
|
||||||
uint32_t max = 0;
|
uint32_t max = 0;
|
||||||
for(unsigned i = 0; i < types->indices(); i++) {
|
for(unsigned i = 0; i < types->indices(); i++) {
|
||||||
uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
|
if((ctrs_valid_mask[i >> 5] >> (i & 31)) & 1) {
|
||||||
max = (max < tmp) ? tmp : max;
|
uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
|
||||||
|
max = (max < tmp) ? tmp : max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 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)
|
void pollcounter_vector::save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc)
|
||||||
{
|
{
|
||||||
mem.resize(types->indices());
|
mem.resize(types->indices());
|
||||||
//Compatiblity fun.
|
|
||||||
for(size_t i = 0; i < types->indices(); i++)
|
for(size_t i = 0; i < types->indices(); i++)
|
||||||
mem[i] = ctrs[i];
|
mem[i] = ctrs[i];
|
||||||
}
|
}
|
||||||
|
@ -824,6 +896,7 @@ unsigned port_controller::analog_actions() const
|
||||||
break;
|
break;
|
||||||
case port_controller_button::TYPE_NULL:
|
case port_controller_button::TYPE_NULL:
|
||||||
case port_controller_button::TYPE_BUTTON:
|
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;
|
break;
|
||||||
case port_controller_button::TYPE_NULL:
|
case port_controller_button::TYPE_NULL:
|
||||||
case port_controller_button::TYPE_BUTTON:
|
case port_controller_button::TYPE_BUTTON:
|
||||||
|
case port_controller_button::TYPE_KEYBOARD:
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,22 @@ namespace
|
||||||
return y.str();
|
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)
|
std::string read_str(const JSON::node& root, const JSON::pointer& ptr)
|
||||||
{
|
{
|
||||||
if(root.type_of(ptr) != JSON::string)
|
if(root.type_of(ptr) != JSON::string)
|
||||||
|
@ -117,6 +133,22 @@ namespace
|
||||||
return ret;
|
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)
|
struct port_controller_button pcs_parse_button(const JSON::node& root, JSON::pointer ptr)
|
||||||
{
|
{
|
||||||
if(root.type_of_indirect(ptr) != JSON::object)
|
if(root.type_of_indirect(ptr) != JSON::object)
|
||||||
|
@ -129,6 +161,8 @@ namespace
|
||||||
return pcb_button(root, ptr);
|
return pcb_button(root, ptr);
|
||||||
else if(type == "axis" || type == "raxis" || type == "taxis" || type == "lightgun")
|
else if(type == "axis" || type == "raxis" || type == "taxis" || type == "lightgun")
|
||||||
return pcb_axis(root, ptr, type);
|
return pcb_axis(root, ptr, type);
|
||||||
|
else if(type == "key")
|
||||||
|
return pcb_key(root, ptr);
|
||||||
else
|
else
|
||||||
(stringfmt() << "Unknown type '" << type << "' for '" << ptr << "'").throwex();
|
(stringfmt() << "Unknown type '" << type << "' for '" << ptr << "'").throwex();
|
||||||
return pcb_null(root, ptr); //NOTREACHED.
|
return pcb_null(root, ptr); //NOTREACHED.
|
||||||
|
@ -153,6 +187,22 @@ namespace
|
||||||
ret.cclass = cclass;
|
ret.cclass = cclass;
|
||||||
ret.type = type;
|
ret.type = type;
|
||||||
ret.buttons = buttons;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +252,7 @@ namespace
|
||||||
case port_controller_button::TYPE_RAXIS: s << "RAXIS"; break;
|
case port_controller_button::TYPE_RAXIS: s << "RAXIS"; break;
|
||||||
case port_controller_button::TYPE_TAXIS: s << "TAXIS"; break;
|
case port_controller_button::TYPE_TAXIS: s << "TAXIS"; break;
|
||||||
case port_controller_button::TYPE_LIGHTGUN: s << "LIGHTGUN"; 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 << ", "
|
s << "," << (int)b.symbol << ", " << quote(b.name) << ", " << b.shadow << ", " << b.rmin << ", "
|
||||||
<< b.rmax << ", " << b.centers << ", " << quote(b.macro) << ", " << (int)b.msymbol << "}";
|
<< b.rmax << ", " << b.centers << ", " << quote(b.macro) << ", " << (int)b.msymbol << "}";
|
||||||
|
@ -216,7 +267,10 @@ namespace
|
||||||
write_button(s, i);
|
write_button(s, i);
|
||||||
s << ",\n";
|
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)
|
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_NULL: break;
|
||||||
case port_controller_button::TYPE_RAXIS: x+=16; break;
|
case port_controller_button::TYPE_RAXIS: x+=16; break;
|
||||||
case port_controller_button::TYPE_TAXIS: 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;
|
return (x + 7) / 8;
|
||||||
|
@ -266,6 +321,7 @@ namespace
|
||||||
case port_controller_button::TYPE_NULL: break;
|
case port_controller_button::TYPE_NULL: break;
|
||||||
case port_controller_button::TYPE_RAXIS: break;
|
case port_controller_button::TYPE_RAXIS: break;
|
||||||
case port_controller_button::TYPE_TAXIS: break;
|
case port_controller_button::TYPE_TAXIS: break;
|
||||||
|
case port_controller_button::TYPE_KEYBOARD: break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return (x + 7) / 8;
|
return (x + 7) / 8;
|
||||||
|
@ -297,6 +353,7 @@ namespace
|
||||||
case port_controller_button::TYPE_RAXIS:
|
case port_controller_button::TYPE_RAXIS:
|
||||||
case port_controller_button::TYPE_TAXIS:
|
case port_controller_button::TYPE_TAXIS:
|
||||||
case port_controller_button::TYPE_LIGHTGUN:
|
case port_controller_button::TYPE_LIGHTGUN:
|
||||||
|
case port_controller_button::TYPE_KEYBOARD:
|
||||||
ii.type = 2;
|
ii.type = 2;
|
||||||
ii.offset = aoffset + 2 * axisidx2;
|
ii.offset = aoffset + 2 * axisidx2;
|
||||||
axisidx2++;
|
axisidx2++;
|
||||||
|
@ -343,6 +400,7 @@ namespace
|
||||||
case port_controller_button::TYPE_RAXIS:
|
case port_controller_button::TYPE_RAXIS:
|
||||||
case port_controller_button::TYPE_TAXIS:
|
case port_controller_button::TYPE_TAXIS:
|
||||||
case port_controller_button::TYPE_LIGHTGUN:
|
case port_controller_button::TYPE_LIGHTGUN:
|
||||||
|
case port_controller_button::TYPE_KEYBOARD:
|
||||||
ins.type = 1;
|
ins.type = 1;
|
||||||
ins.offset = aoffset + 2 * axisidx;
|
ins.offset = aoffset + 2 * axisidx;
|
||||||
ret.push_back(ins);
|
ret.push_back(ins);
|
||||||
|
|
|
@ -120,7 +120,7 @@ void movie::next_frame() throw(std::bad_alloc)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reset the poll counters and DRDY flags.
|
//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
|
//Increment the current frame counter and subframe counter. Note that first subframe is undefined for
|
||||||
//frame 0 and 0 for frame 1.
|
//frame 0 and 0 for frame 1.
|
||||||
|
@ -346,7 +346,7 @@ void movie::reset_state() throw()
|
||||||
readonly = true;
|
readonly = true;
|
||||||
current_frame = 0;
|
current_frame = 0;
|
||||||
current_frame_first_subframe = 0;
|
current_frame_first_subframe = 0;
|
||||||
pollcounters.clear();
|
pollcounters.clear_all();
|
||||||
lag_frames = 0;
|
lag_frames = 0;
|
||||||
clear_caches();
|
clear_caches();
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,6 +465,7 @@ namespace
|
||||||
case port_controller_button::TYPE_RAXIS: L.pushstring("raxis"); break;
|
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_TAXIS: L.pushstring("axis"); break;
|
||||||
case port_controller_button::TYPE_LIGHTGUN: L.pushstring("lightgun"); break;
|
case port_controller_button::TYPE_LIGHTGUN: L.pushstring("lightgun"); break;
|
||||||
|
case port_controller_button::TYPE_KEYBOARD: L.pushstring("keyboard"); break;
|
||||||
};
|
};
|
||||||
L.rawset(-3);
|
L.rawset(-3);
|
||||||
if(cs.buttons[i].symbol) {
|
if(cs.buttons[i].symbol) {
|
||||||
|
|
|
@ -74,6 +74,16 @@ namespace
|
||||||
uint64_t divsl[] = {1000000, 100000, 10000, 1000, 100, 10, 0};
|
uint64_t divsl[] = {1000000, 100000, 10000, 1000, 100, 10, 0};
|
||||||
const unsigned divcnt = sizeof(divs)/sizeof(divs[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
|
class exp_imp_type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -110,7 +120,7 @@ struct control_info
|
||||||
unsigned position_left;
|
unsigned position_left;
|
||||||
unsigned reserved; //Must be at least 6 for axes.
|
unsigned reserved; //Must be at least 6 for axes.
|
||||||
unsigned index; //Index in poll vector.
|
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;
|
char32_t ch;
|
||||||
std::u32string title;
|
std::u32string title;
|
||||||
unsigned port;
|
unsigned port;
|
||||||
|
@ -124,6 +134,7 @@ struct control_info
|
||||||
unsigned port, unsigned controller);
|
unsigned port, unsigned controller);
|
||||||
static control_info axisinfo(unsigned& p, const std::u32string& title, unsigned idx,
|
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);
|
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)
|
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,
|
controlinfo.push_back(control_info::axisinfo(c, utf8::to32(pcb.name), idx, pid, i,
|
||||||
pcb.type, pcb.rmin, pcb.rmax));
|
pcb.type, pcb.rmin, pcb.rmax));
|
||||||
last_multibyte = true;
|
last_multibyte = true;
|
||||||
|
} else if(pcb.type == port_controller_button::TYPE_KEYBOARD) {
|
||||||
|
//TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(nextp > c)
|
if(nextp > c)
|
||||||
|
@ -322,7 +335,7 @@ void frame_controls::format_lines()
|
||||||
//Line2
|
//Line2
|
||||||
for(auto i : controlinfo) {
|
for(auto i : controlinfo) {
|
||||||
auto _title = i.title;
|
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]);
|
std::copy(_title.begin(), _title.end(), &cp2[i.position_left + off]);
|
||||||
if(i.type == 0)
|
if(i.type == 0)
|
||||||
cp2[i.position_left + off] = i.ch;
|
cp2[i.position_left + off] = i.ch;
|
||||||
|
@ -389,6 +402,9 @@ namespace
|
||||||
first = false;
|
first = false;
|
||||||
last_axis = true;
|
last_axis = true;
|
||||||
break;
|
break;
|
||||||
|
case 2: //key
|
||||||
|
//TODO.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return x.str();
|
return x.str();
|
||||||
|
@ -450,6 +466,9 @@ namespace
|
||||||
first = false;
|
first = false;
|
||||||
last_axis = true;
|
last_axis = true;
|
||||||
break;
|
break;
|
||||||
|
case 2: //Key.
|
||||||
|
//TODO.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -496,7 +515,7 @@ namespace
|
||||||
{
|
{
|
||||||
std::set<unsigned> r;
|
std::set<unsigned> r;
|
||||||
for(auto i : info.get_controlinfo()) {
|
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);
|
r.insert(i.index);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -1016,6 +1035,9 @@ void wxeditor_movie::_moviepanel::render_linen(text_framebuffer& fb, controller_
|
||||||
char c[7];
|
char c[7];
|
||||||
sprintf(c, "%6d", fcontrols.read_index(f, i.index));
|
sprintf(c, "%6d", fcontrols.read_index(f, i.index));
|
||||||
fb.write(c, 0, divcnt + 1 + i.position_left, y, 0x000000, bgc);
|
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
|
} else
|
||||||
do_alter_axis(idx, press_line, line);
|
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 {
|
} else {
|
||||||
for(auto i : fcontrols.get_controlinfo())
|
for(auto i : fcontrols.get_controlinfo())
|
||||||
if(press_x >= i.position_left + off && press_x < i.position_left + i.reserved + off) {
|
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_button = true;
|
||||||
clicked = i;
|
clicked = i;
|
||||||
controller_name = (stringfmt() << "controller " << i.port << "-"
|
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 ebutton_low = clicked_button ? first_editable(clicked.index) : std::numeric_limits<uint64_t>::max();
|
||||||
uint64_t econtroller_low = ebutton_low;
|
uint64_t econtroller_low = ebutton_low;
|
||||||
for(auto i : fcontrols.get_controlinfo())
|
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));
|
econtroller_low = max(econtroller_low, first_editable(i.index));
|
||||||
|
|
||||||
bool click_zero = (clicked_button && !clicked.port && !clicked.controller);
|
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)));
|
press_line < linecount) || (rpress_line >= ebutton_low && rpress_line < linecount)));
|
||||||
//Sweep axis is enabled if change axis is enabled and lines don't match.
|
//Sweep axis is enabled if change axis is enabled and lines don't match.
|
||||||
enable_sweep_axis = (enable_change_axis && press_line != rpress_line);
|
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.
|
//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 &&
|
enable_insert_frame = (!not_editable && press_line + 1 >= eframe_low && press_line < linecount &&
|
||||||
press_line == rpress_line);
|
press_line == rpress_line);
|
||||||
|
|
|
@ -522,6 +522,8 @@ void wxeditor_tasinput::update_controls()
|
||||||
current->Add(t.check);
|
current->Add(t.check);
|
||||||
t.check->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
|
t.check->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED,
|
||||||
wxCommandEventHandler(wxeditor_tasinput::on_control), NULL, this);
|
wxCommandEventHandler(wxeditor_tasinput::on_control), NULL, this);
|
||||||
|
} else if(i.type == port_controller_button::TYPE_KEYBOARD) {
|
||||||
|
//TODO.
|
||||||
} else {
|
} else {
|
||||||
t.panel = new xypanel(current_p, inst, current, i, this,
|
t.panel = new xypanel(current_p, inst, current, i, this,
|
||||||
wxCommandEventHandler(wxeditor_tasinput::on_control), next_id);
|
wxCommandEventHandler(wxeditor_tasinput::on_control), next_id);
|
||||||
|
|
Loading…
Add table
Reference in a new issue