1
0
Fork 0

Stefan Seifert:

- read bindings from template
- automatic deadband detection

mf:
- write js name into output file
- poor man's progress bar during deadband detection
- fix header inclusion, fix mixed indentation
This commit is contained in:
mfranz 2006-07-04 23:29:05 +00:00
parent 1d0b6290c4
commit 2c7e01133f
4 changed files with 456 additions and 516 deletions

View file

@ -1,3 +1,5 @@
AM_CXXFLAGS = -DPKGLIBDIR=\"$(pkgdatadir)\"
noinst_LIBRARIES = libInput.a noinst_LIBRARIES = libInput.a
libInput_a_SOURCES = input.cxx input.hxx libInput_a_SOURCES = input.cxx input.hxx
@ -10,6 +12,7 @@ js_demo_LDADD = -lplibjs $(base_LIBS) $(joystick_LIBS) -lplibul
fgjs_SOURCES = fgjs.cxx jsinput.cxx jsinput.h jssuper.cxx jssuper.h fgjs_SOURCES = fgjs.cxx jsinput.cxx jsinput.h jssuper.cxx jssuper.h
fgjs_LDADD = -lplibjs $(base_LIBS) $(joystick_LIBS) -lplibul fgjs_LDADD = -lplibjs $(base_LIBS) $(joystick_LIBS) -lplibul \
-lsgprops -lsgmisc -lsgio -lsgdebug -lsgstructure -lsgxml -lz
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/Main

View file

@ -6,6 +6,7 @@
// Written by Tony Peden, started May 2001 // Written by Tony Peden, started May 2001
// //
// Copyright (C) 2001 Tony Peden (apeden@earthlink.net) // Copyright (C) 2001 Tony Peden (apeden@earthlink.net)
// Copyright (C) 2006 Stefan Seifert
// //
// This program is free software; you can redistribute it and/or // This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as // modify it under the terms of the GNU General Public License as
@ -29,8 +30,6 @@
#include STL_FSTREAM #include STL_FSTREAM
#include STL_STRING #include STL_STRING
#include <jsinput.h>
SG_USING_STD(fstream); SG_USING_STD(fstream);
SG_USING_STD(cout); SG_USING_STD(cout);
SG_USING_STD(cin); SG_USING_STD(cin);
@ -38,305 +37,42 @@ SG_USING_STD(endl);
SG_USING_STD(ios); SG_USING_STD(ios);
SG_USING_STD(string); SG_USING_STD(string);
string axes_humannames[8] = { "Aileron", "Elevator", "Rudder", "Throttle", #include <simgear/constants.h>
"Mixture", "Pitch", "View Direction", #include <simgear/debug/logstream.hxx>
"View Elevation" #include <simgear/misc/sg_path.hxx>
}; #include <simgear/misc/sgstream.hxx>
#include <simgear/structure/exception.hxx>
string axes_propnames[8]={ "/controls/flight/aileron","/controls/flight/elevator", #include <Main/fg_io.hxx>
"/controls/flight/rudder","/controls/engines/engine[%d]/throttle", #include <Main/fg_props.hxx>
"/controls/engines/engine[%d]/mixture","/controls/engines/engine[%d]/pitch", #include <Main/globals.hxx>
"/sim/current-view/goal-heading-offset-deg",
"/sim/current-view/goal-pitch-offset-deg"
};
string axis_posdir[8]= { "right", "down/forward", "right", "forward", "forward", "forward", "left", "upward" }; #include "jsinput.h"
bool half_range[8]={ false,false,false,true,true,true,false,false }; bool confirmAnswer() {
char answer;
bool repeatable[8]={ false,false,false,false,false,false,true,true }; do {
cout << "Is this correct? (y/n) $ ";
bool invert[8]= { false,false,false,false,false,false,false,false }; cin >> answer;
cin.ignore(256, '\n');
string button_humannames[8]= { "Left Brake", "Right Brake", if (answer == 'y')
"Flaps Up", "Flaps Down", return true;
"Elevator Trim Forward", "Elevator Trim Backward", if (answer == 'n')
"Landing Gear Up", "Landing Gear Down" return false;
}; } while (true);
string button_propnames[8]={ "/controls/gear/brake-left",
"/controls/gear/brake-right",
"/controls/flight/flaps",
"/controls/flight/flaps",
"/controls/flight/elevator-trim",
"/controls/flight/elevator-trim",
"/controls/gear/gear-down",
"/controls/gear/gear-down"
};
bool button_modup[8]={ true,true,false,false,false,false,false,false };
bool button_boolean[8]={ false,false,false,false,false,false,true,true };
float button_step[8]={ 1.0, 1.0, -0.34, 0.34, 0.001, -0.001, 0.0, 1.0 };
string button_repeat[8]={ "false", "false", "false", "false", "true", "true", "false", "false" };
void writeAxisXML(fstream &fs, int control, int axis) {
char axisline[16];
snprintf(axisline,16," <axis n=\"%d\">",axis);
fs << axisline << endl;
fs << " <desc>" << axes_humannames[control] << "</desc>" << endl;
if (half_range[control]) {
for (int i=0; i<=7; i++) {
fs << " <binding>" << endl;
fs << " <command>property-scale</command>" << endl;
char propertyline[256];
snprintf(propertyline,256,axes_propnames[control].c_str(),i);
fs << " <property>" << propertyline << "</property>" << endl;
fs << " <offset type=\"double\">-1.0</offset>" << endl;
fs << " <factor type=\"double\">-0.5</factor>" << endl;
fs << " </binding>" << endl;
}
} else if (repeatable[control]) {
fs << " <low>" << endl;
fs << " <repeatable>true</repeatable>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-adjust</command>" << endl;
fs << " <property>" << axes_propnames[control] << "</property>" << endl;
if (invert[control]) {
fs << " <step type=\"double\">1.0</step>" << endl;
} else {
fs << " <step type=\"double\">-1.0</step>" << endl;
}
fs << " </binding>" << endl;
fs << " </low>" << endl;
fs << " <high>" << endl;
fs << " <repeatable>true</repeatable>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-adjust</command>" << endl;
fs << " <property>" << axes_propnames[control] << "</property>" << endl;
if (invert[control]) {
fs << " <step type=\"double\">-1.0</step>" << endl;
} else {
fs << " <step type=\"double\">1.0</step>" << endl;
}
fs << " </binding>" << endl;
fs << " </high>" << endl;
} else {
fs << " <binding>" << endl;
fs << " <command>property-scale</command>" << endl;
fs << " <property>" << axes_propnames[control] << "</property>" << endl;
fs << " <dead-band type=\"double\">0.02</dead-band>" << endl;
fs << " <offset type=\"double\">0.0</offset>" << endl;
if (invert[control]) {
fs << " <factor type=\"double\">-1.0</factor>" << endl;
} else {
fs << " <factor type=\"double\">1.0</factor>" << endl;
}
fs << " </binding>" << endl;
}
fs << " </axis>" << endl << endl;
} }
void writeAxisProperties(fstream &fs, int control,int joystick, int axis) { string getFGRoot( int argc, char *argv[] );
char jsDesc[80];
snprintf(jsDesc,80,"--prop:/input/joysticks/js[%d]/axis[%d]",joystick,axis);
if( half_range[control] == true) {
for (int i=0; i<=7; i++) {
char bindno[64];
snprintf(bindno,64,"/binding[%d]",i);
char propertyline[256];
snprintf(propertyline,256,axes_propnames[control].c_str(),i);
fs << jsDesc << bindno << "/command=property-scale" << endl;
fs << jsDesc << bindno << "/property=" << propertyline << endl;
fs << jsDesc << bindno << "/offset=-1.0" << endl;
fs << jsDesc << bindno << "/factor=-0.5" << endl;
}
} else if (repeatable[control]) {
fs << jsDesc << "/low/repeatable=true" << endl;
fs << jsDesc << "/low/binding/command=property-adjust" << endl;
fs << jsDesc << "/low/binding/property=" << axes_propnames[control] << endl;
if (invert[control]) {
fs << jsDesc << "/low/binding/step=1.0" << endl;
} else {
fs << jsDesc << "/low/binding/step=-1.0" << endl;
}
fs << jsDesc << "/high/repeatable=true" << endl;
fs << jsDesc << "/high/binding/command=property-adjust" << endl;
fs << jsDesc << "/high/binding/property=" << axes_propnames[control] << endl;
if (invert[control]) {
fs << jsDesc << "/high/binding/step=-1.0" << endl;
} else {
fs << jsDesc << "/high/binding/step=1.0" << endl;
}
} else {
fs << jsDesc << "/binding/command=property-scale" << endl;
fs << jsDesc << "/binding/property=" << axes_propnames[control] << endl;
fs << jsDesc << "/binding/dead-band=0.02" << endl;
fs << jsDesc << "/binding/offset=0.0" << endl;
if (invert[control]) {
fs << jsDesc << "/binding/factor=-1.0" << endl;
} else {
fs << jsDesc << "/binding/factor=1.0" << endl;
}
}
fs << endl;
}
void writeButtonXML(fstream &fs, int property, int button) {
char buttonline[32];
snprintf(buttonline,32," <button n=\"%d\">",button);
fs << buttonline << endl;
if (property==-2) {
fs << " <desc>View Cycle</desc>" << endl;
fs << " <repeatable>false</repeatable>" << endl;
fs << " <binding>" << endl;
fs << " <command>view-cycle</command>" << endl;
fs << " <step type=\"double\">1</step>" << endl;
fs << " </binding>" << endl;
} else if (property==-1) {
fs << " <desc>Brakes</desc>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[0] << "</property>" << endl;
fs << " <value type=\"double\">" << button_step[0] << "</value>" << endl;
fs << " </binding>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[1] << "</property>" << endl;
fs << " <value type=\"double\">" << button_step[1] << "</value>" << endl;
fs << " </binding>" << endl;
fs << " <mod-up>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[0] << "</property>" << endl;
fs << " <value type=\"double\">0</value>" << endl;
fs << " </binding>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[1] << "</property>" << endl;
fs << " <value type=\"double\">0</value>" << endl;
fs << " </binding>" << endl;
fs << " </mod-up>" << endl;
} else {
fs << " <desc>" << button_humannames[property] << "</desc>" << endl;
if (button_modup[property]) {
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[property] << "</property>" << endl;
fs << " <value type=\"double\">" << button_step[property] << "</value>" << endl;
fs << " </binding>" << endl;
fs << " <mod-up>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[property] << "</property>" << endl;
fs << " <value type=\"double\">0</value>" << endl;
fs << " </binding>" << endl;
fs << " </mod-up>" << endl;
} else if (button_boolean[property]) {
fs << " <repeatable>" << button_repeat[property] << "</repeatable>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-assign</command>" << endl;
fs << " <property>" << button_propnames[property] << "</property>" << endl;
fs << " <value type=\"bool\">";
if (button_step[property]==1) {
fs << "true";
} else {
fs << "false";
}
fs << "</value>" << endl;
fs << " </binding>" << endl;
} else {
fs << " <repeatable>" << button_repeat[property] << "</repeatable>" << endl;
fs << " <binding>" << endl;
fs << " <command>property-adjust</command>" << endl;
fs << " <property>" << button_propnames[property] << "</property>" << endl;
fs << " <step type=\"double\">" << button_step[property] << "</step>" << endl;
fs << " </binding>" << endl;
}
}
fs << " </button>" << endl << endl;
}
void writeButtonProperties(fstream &fs, int property,int joystick, int button) {
char jsDesc[80];
snprintf(jsDesc,80,"--prop:/input/joysticks/js[%d]/button[%d]",joystick,button);
if (property==-1) {
fs << jsDesc << "/binding[0]/command=property-assign" << endl;
fs << jsDesc << "/binding[0]/property=" << button_propnames[0] << endl;
fs << jsDesc << "/binding[0]/value=" << button_step[0] << endl;
fs << jsDesc << "/binding[1]/command=property-assign" << endl;
fs << jsDesc << "/binding[1]/property=" << button_propnames[1] << endl;
fs << jsDesc << "/binding[1]/value=" << button_step[1] << endl;
fs << jsDesc << "/mod-up/binding[0]/command=property-assign" << endl;
fs << jsDesc << "/mod-up/binding[0]/property=" << button_propnames[0] << endl;
fs << jsDesc << "/mod-up/binding[0]/value=0" << endl;
fs << jsDesc << "/mod-up/binding[1]/command=property-assign" << endl;
fs << jsDesc << "/mod-up/binding[1]/property=" << button_propnames[1] << endl;
fs << jsDesc << "/mod-up/binding[1]/value=0" << endl;
fs << endl;
} else if (button_modup[property]) {
fs << jsDesc << "/binding/command=property-assign" << endl;
fs << jsDesc << "/binding/property=" << button_propnames[property] << endl;
fs << jsDesc << "/binding/value=" << button_step[property] << endl;
fs << jsDesc << "/mod-up/binding/command=property-assign" << endl;
fs << jsDesc << "/mod-up/binding/property=" << button_propnames[property] << endl;
fs << jsDesc << "/mod-up/binding/value=0" << endl;
fs << endl;
} else if (button_boolean[property]) {
fs << jsDesc << "/repeatable=" << button_repeat[property] << endl;
fs << jsDesc << "/binding/command=property-assign" << endl;
fs << jsDesc << "/binding/property=" << button_propnames[property] << endl;
fs << jsDesc << "/binding/value=";
if (button_step[property]==1) {
fs << "true";
} else {
fs << "false";
}
fs << endl << endl;
} else {
fs << jsDesc << "/repeatable=" << button_repeat[property] << endl;
fs << jsDesc << "/binding/command=property-adjust" << endl;
fs << jsDesc << "/binding/property=" << button_propnames[property] << endl;
fs << jsDesc << "/binding/step=" << button_step[property] << endl;
fs << endl;
}
}
int main( int argc, char *argv[] ) { int main( int argc, char *argv[] ) {
bool usexml=true;
float deadband=0;
char answer[128];
int btninit=-2;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (strcmp("--help", argv[i]) == 0) { if (strcmp("--help", argv[i]) == 0) {
cout << "Usage:" << endl; cout << "Usage:" << endl;
cout << " --help\t\t\tShow this help" << endl; cout << " --help\t\t\tShow this help" << endl;
cout << " --prop\t\t\tOutput property list" << endl;
cout << " --xml\t\t\t\tOutput xml (default)" << endl;
cout << " --deadband <float>\t\tSet deadband (for this program only, useful" << endl;
cout << "\t\t\t\tfor 'twitchy' joysticks)" << endl;
exit(0); exit(0);
} else if (strcmp("--prop",argv[i])==0) { } else {
usexml=false;
btninit=-1;
} else if (strcmp("--deadband",argv[i])==0) {
i++;
deadband=atoi(argv[i]);
cout << "Deadband set to " << argv[i] << endl;
} else if (strcmp("--xml",argv[i])!=0) {
cout << "Unknown option \"" << argv[i] << "\"" << endl; cout << "Unknown option \"" << argv[i] << "\"" << endl;
exit(0); exit(0);
} }
@ -347,7 +83,6 @@ int main( int argc, char *argv[] ) {
jsSuper *jss = new jsSuper(); jsSuper *jss = new jsSuper();
jsInput *jsi = new jsInput(jss); jsInput *jsi = new jsInput(jss);
jsi->displayValues(false); jsi->displayValues(false);
int control=0;
cout << "Found " << jss->getNumJoysticks() << " joystick(s)" << endl; cout << "Found " << jss->getNumJoysticks() << " joystick(s)" << endl;
@ -355,143 +90,283 @@ int main( int argc, char *argv[] ) {
cout << "Can't find any joysticks ..." << endl; cout << "Can't find any joysticks ..." << endl;
exit(1); exit(1);
} }
cout << endl << "Now measuring the dead band of your joystick. The dead band is the area " << endl
fstream fs; << "where the joystick is centered and should not generate any input. Move all " << endl
fstream *xfs = new fstream[jss->getNumJoysticks()]; << "axes around in this dead zone during the ten seconds this test will take." << endl;
if (!usexml) { cout << "Press enter to continue." << endl;
fs.open("fgfsrc.js",ios::out); cin.ignore(1024, '\n');
} jsi->findDeadBand();
cout << endl << "Dead band calibration finished. Press enter to start control assignment." << endl;
cin.ignore(1024, '\n');
jss->firstJoystick(); jss->firstJoystick();
fstream *xfs = new fstream[ jss->getNumJoysticks() ];
SGPropertyNode_ptr *jstree = new SGPropertyNode_ptr[ jss->getNumJoysticks() ];
do { do {
cout << "Joystick #" << jss->getCurrentJoystickId() cout << "Joystick #" << jss->getCurrentJoystickId()
<< " \"" << jss->getJoystick()->getName() << "\" has " << " \"" << jss->getJoystick()->getName() << "\" has "
<< jss->getJoystick()->getNumAxes() << " axes" << endl; << jss->getJoystick()->getNumAxes() << " axes" << endl;
for (int i=0; i<jss->getJoystick()->getNumAxes(); i++) {
jss->getJoystick()->setDeadBand(i,deadband);
}
if (usexml) {
char filename[16]; char filename[16];
snprintf(filename, 16, "js%i.xml", jss->getCurrentJoystickId()); snprintf(filename, 16, "js%i.xml", jss->getCurrentJoystickId());
xfs[ jss->getCurrentJoystickId() ].open(filename, ios::out); xfs[ jss->getCurrentJoystickId() ].open(filename, ios::out);
xfs[jss->getCurrentJoystickId()] << "<?xml version=\"1.0\" ?>" << endl jstree[ jss->getCurrentJoystickId() ] = new SGPropertyNode();
<< endl << "<PropertyList>" << endl << endl << " <name>"
<< jss->getJoystick()->getName() << "</name>" << endl << endl;
}
} while ( jss->nextJoystick() ); } while ( jss->nextJoystick() );
for(control=0;control<=7;control++) { SGPath templatefile( getFGRoot(argc, argv) );
cout << "Move the control you wish to use for " << axes_humannames[control] templatefile.append("Input");
<< " " << axis_posdir[control] << endl; templatefile.append("Joysticks");
cout << "Pressing a button skips this axis\n"; templatefile.append("template.xml");
SGPropertyNode *templatetree = new SGPropertyNode();
try {
readProperties(templatefile.str().c_str(), templatetree);
} catch (sg_io_exception e) {
cout << e.getFormattedMessage ();
}
vector<SGPropertyNode_ptr> axes = templatetree->getChildren("axis");
for(vector<SGPropertyNode_ptr>::iterator iter = axes.begin(); iter != axes.end(); iter++) {
cout << "Move the control you wish to use for " << (*iter)->getStringValue("desc")
<< " " << (*iter)->getStringValue("direction") << endl;
cout << "Pressing a button skips this axis" << endl;
fflush( stdout ); fflush( stdout );
jsi->getInput(); jsi->getInput();
if (jsi->getInputAxis() != -1) { if (jsi->getInputAxis() != -1) {
cout << endl << "Assigned axis " << jsi->getInputAxis() cout << endl << "Assigned axis " << jsi->getInputAxis()
<< " on joystick " << jsi->getInputJoystick() << " on joystick " << jsi->getInputJoystick()
<< " to control " << axes_humannames[control] << " to control " << (*iter)->getStringValue("desc") << endl;
<< endl; if ( confirmAnswer() ) {
bool badanswer=true; SGPropertyNode *axis = jstree[ jsi->getInputJoystick() ]->getChild("axis", jsi->getInputAxis(), true);
do { copyProperties(*iter, axis);
cout << "Is this correct? (y/n) $ "; axis->setDoubleValue("dead-band", jss->getJoystick(jsi->getInputJoystick())
cin >> answer; ->getDeadBand(jsi->getInputAxis()));
if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; } axis->setDoubleValue("binding/factor", jsi->getInputAxisPositive() ? 1.0 : -1.0);
} while (badanswer);
if (strcmp(answer,"n")==0) {
control--;
} else { } else {
invert[control]=!jsi->getInputAxisPositive(); iter--;
if (usexml) {
writeAxisXML( xfs[jsi->getInputJoystick()], control, jsi->getInputAxis() );
} else {
writeAxisProperties( fs, control, jsi->getInputJoystick(), jsi->getInputAxis() );
}
} }
} else { } else {
cout << "Skipping control" << endl; cout << "Skipping control" << endl;
bool badanswer=true; if ( ! confirmAnswer() )
do { iter--;
cout << "Is this correct? (y/n) $ ";
cin >> answer;
if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
} while (badanswer);
if (strcmp(answer,"n")==0) { control--; }
} }
cout << endl; cout << endl;
} }
for(control=btninit;control<=7;control++) { vector<SGPropertyNode_ptr> buttons = templatetree->getChildren("button");
if ( control == -2 ) { for(vector<SGPropertyNode_ptr>::iterator iter = buttons.begin(); iter != buttons.end(); iter++) {
cout << "Press the button you wish to use for View Cycle" << endl; cout << "Press the button you wish to use for " << (*iter)->getStringValue("desc") << endl;
} else if ( control == -1 ) { cout << "Moving a joystick axis skips this button" << endl;
cout << "Press the button you wish to use for Brakes" << endl;
} else {
cout << "Press the button you wish to use for " << button_humannames[control] << endl;
}
cout << "Moving a joystick axis skips this button\n";
fflush( stdout ); fflush( stdout );
jsi->getInput(); jsi->getInput();
if (jsi->getInputButton() != -1) { if (jsi->getInputButton() != -1) {
cout << endl << "Assigned button " << jsi->getInputButton() cout << endl << "Assigned button " << jsi->getInputButton()
<< " on joystick " << jsi->getInputJoystick() << " on joystick " << jsi->getInputJoystick()
<< " to control "; << " to control " << (*iter)->getStringValue("desc") << endl;
if ( control == -2 ) { cout << "View Cycle" << endl; } if ( confirmAnswer() ) {
else if ( control == -1 ) { cout << "Brakes" << endl; } SGPropertyNode *button = jstree[ jsi->getInputJoystick() ]->getChild("button", jsi->getInputButton(), true);
else { cout << button_humannames[control] << endl; } copyProperties(*iter, button);
bool badanswer=true;
do {
cout << "Is this correct? (y/n) $ ";
cin >> answer;
if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
} while (badanswer);
if (strcmp(answer,"n")==0) {
control--;
} else { } else {
if (usexml) { iter--;
writeButtonXML( xfs[jsi->getInputJoystick()], control, jsi->getInputButton() );
} else {
writeButtonProperties( fs, control, jsi->getInputJoystick(), jsi->getInputButton() );
}
} }
} else { } else {
cout << "Skipping control" << endl; cout << "Skipping control" << endl;
bool badanswer=true; if (! confirmAnswer())
do { iter--;
cout << "Is this correct? (y/n) $ ";
cin >> answer;
if ((strcmp(answer,"y")==0) || (strcmp(answer,"n")==0)) { badanswer=false; }
} while (badanswer);
if (strcmp(answer,"n")==0) { control--; }
} }
cout << endl; cout << endl;
} }
if (usexml) {
cout << "Your joystick settings are in ";
for (int i = 0; i < jss->getNumJoysticks(); i++) { for (int i = 0; i < jss->getNumJoysticks(); i++) {
xfs[i] << "</PropertyList>" << endl << endl << "<!-- end of joystick.xml -->" << endl; try {
cout << "js" << i << ".xml";
if (i + 2 < jss->getNumJoysticks())
cout << ", ";
else if (i + 1 < jss->getNumJoysticks())
cout << " and ";
jstree[i]->setStringValue("name", jss->getJoystick(i)->getName());
writeProperties(xfs[i], jstree[i], true);
} catch (sg_io_exception e) {
cout << e.getFormattedMessage ();
}
xfs[i].close(); xfs[i].close();
} }
} else { cout << "." << endl << "Check and edit as desired. Once you are happy," << endl
fs.close(); << "move relevant js<n>.xml files to $FG_ROOT/Input/Joysticks/ (if you didn't use" << endl
} << "an attached controller, you don't need to move the corresponding file)" << endl;
delete jsi; delete jsi;
delete[] xfs; delete[] xfs;
delete jss; delete jss;
cout << "Your joystick settings are in ";
if (usexml) {
cout << "js0.xml, js1.xml, etc. depending on how many" << endl << "devices you have." << endl;
} else {
cout << "fgfsrc.js" << endl;
}
cout << endl << "Check and edit as desired. Once you are happy," << endl;
if (usexml) {
cout << "move relevant js<n>.xml files to $FG_ROOT/Input/Joysticks/ (if you didn't use" << endl
<< "an attached controller, you don't need to move the corresponding file)" << endl;
} else {
cout << "append its contents to your .fgfsrc or system.fgfsrc" << endl;
}
return 1; return 1;
} }
char *homedir = ::getenv( "HOME" );
char *hostname = ::getenv( "HOSTNAME" );
bool free_hostname = false;
// Scan the command line options for the specified option and return
// the value.
static string fgScanForOption( const string& option, int argc, char **argv ) {
int i = 1;
if (hostname == NULL)
{
char _hostname[256];
gethostname(_hostname, 256);
hostname = strdup(_hostname);
free_hostname = true;
}
SG_LOG(SG_GENERAL, SG_INFO, "Scanning command line for: " << option );
int len = option.length();
while ( i < argc ) {
SG_LOG( SG_GENERAL, SG_DEBUG, "argv[" << i << "] = " << argv[i] );
string arg = argv[i];
if ( arg.find( option ) == 0 ) {
return arg.substr( len );
}
i++;
}
return "";
}
// Scan the user config files for the specified option and return
// the value.
static string fgScanForOption( const string& option, const string& path ) {
sg_gzifstream in( path );
if ( !in.is_open() ) {
return "";
}
SG_LOG( SG_GENERAL, SG_INFO, "Scanning " << path << " for: " << option );
int len = option.length();
in >> skipcomment;
#ifndef __MWERKS__
while ( ! in.eof() ) {
#else
char c = '\0';
while ( in.get(c) && c != '\0' ) {
in.putback(c);
#endif
string line;
#if defined( macintosh )
getline( in, line, '\r' );
#else
getline( in, line, '\n' );
#endif
// catch extraneous (DOS) line ending character
if ( line[line.length() - 1] < 32 ) {
line = line.substr( 0, line.length()-1 );
}
if ( line.find( option ) == 0 ) {
return line.substr( len );
}
in >> skipcomment;
}
return "";
}
// Scan the user config files for the specified option and return
// the value.
static string fgScanForOption( const string& option ) {
string arg("");
#if defined( unix ) || defined( __CYGWIN__ )
// Next check home directory for .fgfsrc.hostname file
if ( arg.empty() ) {
if ( homedir != NULL ) {
SGPath config( homedir );
config.append( ".fgfsrc" );
config.concat( "." );
config.concat( hostname );
arg = fgScanForOption( option, config.str() );
}
}
#endif
// Next check home directory for .fgfsrc file
if ( arg.empty() ) {
if ( homedir != NULL ) {
SGPath config( homedir );
config.append( ".fgfsrc" );
arg = fgScanForOption( option, config.str() );
}
}
return arg;
}
// Read in configuration (files and command line options) but only set
// fg_root
string getFGRoot ( int argc, char **argv ) {
string root;
// First parse command line options looking for --fg-root=, this
// will override anything specified in a config file
root = fgScanForOption( "--fg-root=", argc, argv);
// Check in one of the user configuration files.
if (root.empty() )
root = fgScanForOption( "--fg-root=" );
// Next check if fg-root is set as an env variable
if ( root.empty() ) {
char *envp = ::getenv( "FG_ROOT" );
if ( envp != NULL ) {
root = envp;
}
}
// Otherwise, default to a random compiled-in location if we can't
// find fg-root any other way.
if ( root.empty() ) {
#if defined( __CYGWIN__ )
root = "/FlightGear";
#elif defined( WIN32 )
root = "\\FlightGear";
#elif defined(OSX_BUNDLE)
/* the following code looks for the base package directly inside
the application bundle. This can be changed fairly easily by
fiddling with the code below. And yes, I know it's ugly and verbose.
*/
CFBundleRef appBundle = CFBundleGetMainBundle();
CFURLRef appUrl = CFBundleCopyBundleURL(appBundle);
CFRelease(appBundle);
// look for a 'data' subdir directly inside the bundle : is there
// a better place? maybe in Resources? I don't know ...
CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent(NULL, appUrl, CFSTR("data"), true);
// now convert down to a path, and the a c-string
CFStringRef path = CFURLCopyFileSystemPath(dataDir, kCFURLPOSIXPathStyle);
root = CFStringGetCStringPtr(path, CFStringGetSystemEncoding());
// tidy up.
CFRelease(appBundle);
CFRelease(dataDir);
CFRelease(path);
#else
root = PKGLIBDIR;
#endif
}
SG_LOG(SG_INPUT, SG_INFO, "fg_root = " << root );
return root;
}

View file

@ -18,6 +18,14 @@
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <simgear/compiler.h>
#include STL_IOSTREAM
SG_USING_STD(cout);
SG_USING_STD(cin);
SG_USING_STD(endl);
#include "jsinput.h" #include "jsinput.h"
jsInput::jsInput(jsSuper *j) { jsInput::jsInput(jsSuper *j) {
@ -44,7 +52,7 @@ int jsInput::getInput(){
printf ( "| Btns " ) ; printf ( "| Btns " ) ;
for ( i = 0 ; i < jss->getJoystick()->getNumAxes() ; i++ ) for ( i = 0 ; i < jss->getJoystick()->getNumAxes() ; i++ )
printf ( "Ax:%1d ", i ) ; printf ( "Ax:%3d ", i ) ;
for ( ; i < 8 ; i++ ) for ( ; i < 8 ; i++ )
printf ( " " ) ; printf ( " " ) ;
@ -74,7 +82,7 @@ int jsInput::getInput(){
for ( i = 0 ; i < jss->getJoystick()->getNumAxes(); i++ ) { for ( i = 0 ; i < jss->getJoystick()->getNumAxes(); i++ ) {
delta = axes[i] - axes_iv[jss->getCurrentJoystickId()][i]; delta = axes[i] - axes_iv[jss->getCurrentJoystickId()][i];
if(pretty_display) printf ( "%+.1f ", delta ) ; if(pretty_display) printf ( "%+.3f ", delta ) ;
if(!gotit) { if(!gotit) {
if( fabs(delta) > axis_threshold ) { if( fabs(delta) > axis_threshold ) {
gotit=true; gotit=true;
@ -115,3 +123,56 @@ int jsInput::getInput(){
return 0; return 0;
} }
void jsInput::findDeadBand() {
float delta;
int i;
float dead_band[MAX_JOYSTICKS][_JS_MAX_AXES];
jss->firstJoystick();
do {
jss->getJoystick()->read ( NULL,
axes_iv[jss->getCurrentJoystickId()] ) ;
for ( i = 0; i < jss->getJoystick()->getNumAxes(); i++ ) {
dead_band[jss->getCurrentJoystickId()][i] = 0;
}
} while( jss->nextJoystick() );
ulClock clock;
cout << 10;
cout.flush();
for (int j = 9; j >= 0; j--) {
double start_time = clock.getAbsTime();
do {
jss->firstJoystick();
do {
jss->getJoystick()->read ( NULL, axes ) ;
for ( i = 0 ; i < jss->getJoystick()->getNumAxes(); i++ ) {
delta = axes[i] - axes_iv[jss->getCurrentJoystickId()][i];
if (fabs(delta) > dead_band[jss->getCurrentJoystickId()][i])
dead_band[jss->getCurrentJoystickId()][i] = delta;
}
} while( jss->nextJoystick());
ulMilliSecondSleep(1);
clock.update();
} while (clock.getAbsTime() - start_time < 1.0);
cout << " - " << j;
cout.flush();
}
cout << endl << endl;
jss->firstJoystick();
do {
for ( i = 0; i < jss->getJoystick()->getNumAxes(); i++ ) {
jss->getJoystick()->setDeadBand(i, dead_band[jss->getCurrentJoystickId()][i]);
printf("Joystick %i, axis %i: %f\n", jss->getCurrentJoystickId(), i, dead_band[jss->getCurrentJoystickId()][i]);
}
} while( jss->nextJoystick() );
}

View file

@ -45,6 +45,7 @@ class jsInput {
inline void displayValues(bool bb) { pretty_display=bb; } inline void displayValues(bool bb) { pretty_display=bb; }
int getInput(void); int getInput(void);
void findDeadBand(void);
inline int getInputJoystick(void) { return joystick; } inline int getInputJoystick(void) { return joystick; }
inline int getInputAxis(void) { return axis; } inline int getInputAxis(void) { return axis; }