--- a/QTfrontend/binds.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/binds.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -20,17 +20,15 @@
const BindAction cbinds[BINDS_NUMBER] =
{
- {"+up", "up", QT_TRANSLATE_NOOP("binds", "up"), QT_TRANSLATE_NOOP("binds (categories)", "Basic controls"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move your hogs and aim:")},
+ {"+up", "up", QT_TRANSLATE_NOOP("binds", "up"), QT_TRANSLATE_NOOP("binds (categories)", "Movement"), QT_TRANSLATE_NOOP("binds (descriptions)", "Hedgehog movement")},
{"+left", "left", QT_TRANSLATE_NOOP("binds", "left"), NULL, NULL},
{"+right", "right", QT_TRANSLATE_NOOP("binds", "right"), NULL, NULL},
{"+down", "down", QT_TRANSLATE_NOOP("binds", "down"), NULL, NULL},
{"+precise", "left_shift", QT_TRANSLATE_NOOP("binds", "precise aim"), NULL, NULL},
{"ljump", "return", QT_TRANSLATE_NOOP("binds", "long jump"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Traverse gaps and obstacles by jumping:")},
{"hjump", "backspace", QT_TRANSLATE_NOOP("binds", "high jump"), NULL, NULL},
- {"+attack", "space", QT_TRANSLATE_NOOP("binds", "attack"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Fire your selected weapon or trigger an utility item:")},
- {"put", "mousel", QT_TRANSLATE_NOOP("binds", "put"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or a target location under the cursor:")},
{"switch", "tab", QT_TRANSLATE_NOOP("binds", "switch"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Switch your currently active hog (if possible):")},
- {"ammomenu", "mouser", QT_TRANSLATE_NOOP("binds", "ammo menu"), QT_TRANSLATE_NOOP("binds (categories)", "Weapon controls"), QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or utility item:")},
+ {"ammomenu", "mouser", QT_TRANSLATE_NOOP("binds", "ammo menu"), QT_TRANSLATE_NOOP("binds (categories)", "Weapons"), QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or utility item:")},
{"slot 1", "f1", QT_TRANSLATE_NOOP("binds", "slot 1"), NULL, NULL},
{"slot 2", "f2", QT_TRANSLATE_NOOP("binds", "slot 2"), NULL, NULL},
{"slot 3", "f3", QT_TRANSLATE_NOOP("binds", "slot 3"), NULL, NULL},
@@ -46,7 +44,9 @@
{"timer 3", "3", QT_TRANSLATE_NOOP("binds", "timer 3 sec"), NULL, NULL},
{"timer 4", "4", QT_TRANSLATE_NOOP("binds", "timer 4 sec"), NULL, NULL},
{"timer 5", "5", QT_TRANSLATE_NOOP("binds", "timer 5 sec"), NULL, NULL},
- {"findhh", "h", QT_TRANSLATE_NOOP("binds", "find hedgehog"), QT_TRANSLATE_NOOP("binds (categories)", "Camera and cursor controls"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move the camera to the active hog:")},
+ {"+attack", "space", QT_TRANSLATE_NOOP("binds", "attack"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Fire your selected weapon or trigger an utility item:")},
+ {"put", "mousel", QT_TRANSLATE_NOOP("binds", "put"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pick a weapon or a target location under the cursor:")},
+ {"findhh", "h", QT_TRANSLATE_NOOP("binds", "find hedgehog"), QT_TRANSLATE_NOOP("binds (categories)", "Camera"), QT_TRANSLATE_NOOP("binds (descriptions)", "Move the camera to the active hog:")},
{"+cur_u", "[8]", QT_TRANSLATE_NOOP("binds", "up"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Move the cursor or camera without using the mouse:")},
{"+cur_l", "[4]", QT_TRANSLATE_NOOP("binds", "left"), NULL, NULL},
{"+cur_r", "[6]", QT_TRANSLATE_NOOP("binds", "right"), NULL, NULL},
@@ -55,7 +55,7 @@
{"zoomin", "wheelup", QT_TRANSLATE_NOOP("binds", "zoom in"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Modify the camera's zoom level:")},
{"zoomout", "wheeldown", QT_TRANSLATE_NOOP("binds", "zoom out"), NULL, NULL},
{"zoomreset", "mousem", QT_TRANSLATE_NOOP("binds", "reset zoom"), NULL, NULL},
- {"chat", "t", QT_TRANSLATE_NOOP("binds", "chat"), QT_TRANSLATE_NOOP("binds (categories)", "Other"), QT_TRANSLATE_NOOP("binds (descriptions)", "Talk to your team or all participants:")},
+ {"chat", "t", QT_TRANSLATE_NOOP("binds", "chat"), QT_TRANSLATE_NOOP("binds (categories)", "Miscellaneous"), QT_TRANSLATE_NOOP("binds (descriptions)", "Talk to your team or all participants:")},
{"history", "`", QT_TRANSLATE_NOOP("binds", "chat history"), NULL, NULL},
{"pause", "p", QT_TRANSLATE_NOOP("binds", "pause"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Pause, continue or leave your game:")},
{"quit", "escape", QT_TRANSLATE_NOOP("binds", "quit"), NULL, NULL},
@@ -65,7 +65,7 @@
{"mute", "8", QT_TRANSLATE_NOOP("binds", "mute audio"), NULL, NULL},
{"fullscr", "f12", QT_TRANSLATE_NOOP("binds", "change mode"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle fullscreen mode:")},
{"capture", "c", QT_TRANSLATE_NOOP("binds", "capture"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Take a screenshot:")},
- {"rotmask", "delete", QT_TRANSLATE_NOOP("binds", "hedgehogs\ninfo"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")},
+ {"rotmask", "delete", QT_TRANSLATE_NOOP("binds", "hedgehog info"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Toggle labels above hedgehogs:")},
#ifdef VIDEOREC
{"record", "r", QT_TRANSLATE_NOOP("binds", "record"), NULL, QT_TRANSLATE_NOOP("binds (descriptions)", "Record video:")}
#endif
--- a/QTfrontend/game.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/game.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -29,6 +29,7 @@
#include "gamecfgwidget.h"
#include "teamselect.h"
#include "proto.h"
+#include "binds.h"
#include "campaign.h"
#include <QTextStream>
@@ -73,6 +74,18 @@
SetGameState(gsStopped);
}
+void HWGame::addKeyBindings(QByteArray * buf)
+{
+ for(int i = 0; i < BINDS_NUMBER; i++)
+ {
+ QString value = config->value(QString("Binds/%1").arg(cbinds[i].action), cbinds[i].strbind).toString();
+ if (value.isEmpty() || value == "default") continue;
+
+ QString bind = QString("edbind " + value + " " + cbinds[i].action);
+ HWProto::addStringToBuffer(*buf, bind);
+ }
+}
+
void HWGame::commonConfig()
{
QByteArray buf;
@@ -90,6 +103,8 @@
}
HWProto::addStringToBuffer(buf, gt);
+ addKeyBindings(&buf);
+
buf += gamecfg->getFullConfig();
if (m_pTeamSelWidget)
@@ -102,10 +117,11 @@
HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber)));
if(gamecfg->schemeData(15).toBool() || !gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore"));
HWProto::addStringListToBuffer(buf,
- team.teamGameConfig(gamecfg->getInitHealth()));
+ team.teamGameConfig(gamecfg->getInitHealth(), config));
;
}
}
+
RawSendIPC(buf);
}
@@ -119,6 +135,8 @@
QByteArray teamscfg;
ThemeModel * themeModel = DataManager::instance().themeModel();
+ addKeyBindings(&teamscfg);
+
HWProto::addStringToBuffer(teamscfg, "TL");
HWProto::addStringToBuffer(teamscfg, QString("etheme %1")
.arg((themeModel->rowCount() > 0) ? themeModel->index(rand() % themeModel->rowCount()).data().toString() : "steel"));
@@ -132,7 +150,7 @@
team1.setNumHedgehogs(4);
HWNamegen::teamRandomNames(team1,true);
HWProto::addStringListToBuffer(teamscfg,
- team1.teamGameConfig(100));
+ team1.teamGameConfig(100, config));
HWTeam team2;
team2.setDifficulty(4);
@@ -142,7 +160,7 @@
HWNamegen::teamRandomNames(team2,true);
while(!team2.name().compare(team1.name()) || !team2.hedgehog(0).Hat.compare(team1.hedgehog(0).Hat));
HWProto::addStringListToBuffer(teamscfg,
- team2.teamGameConfig(100));
+ team2.teamGameConfig(100, config));
HWProto::addStringToBuffer(teamscfg, QString("eammloadt %1").arg(cDefaultAmmoStore->mid(0, cAmmoNumber)));
HWProto::addStringToBuffer(teamscfg, QString("eammprob %1").arg(cDefaultAmmoStore->mid(cAmmoNumber, cAmmoNumber)));
@@ -150,6 +168,7 @@
HWProto::addStringToBuffer(teamscfg, QString("eammreinf %1").arg(cDefaultAmmoStore->mid(3 * cAmmoNumber, cAmmoNumber)));
HWProto::addStringToBuffer(teamscfg, QString("eammstore"));
HWProto::addStringToBuffer(teamscfg, QString("eammstore"));
+
RawSendIPC(teamscfg);
}
@@ -160,6 +179,8 @@
HWProto::addStringToBuffer(traincfg, "eseed " + QUuid::createUuid().toString());
HWProto::addStringToBuffer(traincfg, "escript " + training);
+ addKeyBindings(&traincfg);
+
RawSendIPC(traincfg);
}
@@ -171,6 +192,8 @@
HWProto::addStringToBuffer(campaigncfg, "escript " + campaignScript);
+ addKeyBindings(&campaigncfg);
+
RawSendIPC(campaigncfg);
}
--- a/QTfrontend/game.h Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/game.h Sat Dec 29 22:50:10 2012 +0100
@@ -103,6 +103,7 @@
TeamSelWidget* m_pTeamSelWidget;
GameType gameType;
+ void addKeyBindings(QByteArray * buf);
void commonConfig();
void SendConfig();
void SendQuickConfig();
--- a/QTfrontend/gameuiconfig.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/gameuiconfig.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -52,6 +52,13 @@
connect(Form->ui.pageOptions->CBFrontendMusic, SIGNAL(toggled(bool)), Form, SLOT(Music(bool)));
+ for(int i = 0; i < BINDS_NUMBER; i++)
+ {
+ m_binds.append(BindAction());
+ m_binds[i].action = cbinds[i].action;
+ m_binds[i].strbind = cbinds[i].strbind;
+ }
+
//Form->resize(value("frontend/width", 640).toUInt(), value("frontend/height", 450).toUInt());
resizeToConfigValues();
@@ -135,6 +142,15 @@
for(int i = model->rowCount() - 1; i >= 0; --i)
model->item(i)->setData(QColor(value(QString("colors/color%1").arg(i), model->item(i)->data().value<QColor>()).value<QColor>()));
}
+
+ { // load binds
+ QStandardItemModel * binds = DataManager::instance().bindsModel();
+ for(int i = 0; i < BINDS_NUMBER; i++)
+ {
+ m_binds[i].strbind = value(QString("Binds/%1").arg(m_binds[i].action), cbinds[i].strbind).toString();
+ if (m_binds[i].strbind.isEmpty() || m_binds[i].strbind == "default") m_binds[i].strbind = cbinds[i].strbind;
+ }
+ }
}
void GameUIConfig::reloadVideosValues(void)
@@ -581,3 +597,16 @@
{
return Form->ui.pageOptions->checkRecordAudio->isChecked();
}
+
+// Gets a bind for a bindID
+QString GameUIConfig::bind(int bindID)
+{
+ return m_binds[bindID].strbind;
+}
+
+// Sets a bind for a bindID and saves it
+void GameUIConfig::setBind(int bindID, QString & strbind)
+{
+ m_binds[bindID].strbind = strbind;
+ setValue(QString("Binds/%1").arg(m_binds[bindID].action), strbind);
+}
--- a/QTfrontend/gameuiconfig.h Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/gameuiconfig.h Sat Dec 29 22:50:10 2012 +0100
@@ -23,6 +23,8 @@
#include <QStringList>
#include <QRect>
#include <QEvent>
+#include <QList>
+#include "binds.h"
class HWForm;
class QSettings;
@@ -64,6 +66,8 @@
void resizeToConfigValues();
quint32 stereoMode() const;
void setValue(const QString & key, const QVariant & value);
+ QString bind(int bindID);
+ void setBind(int bindID, QString & strbind);
QString AVFormat();
QString videoCodec();
@@ -91,7 +95,8 @@
private:
bool netPasswordIsValid();
bool eventFilter(QObject *object, QEvent *event);
- QString temphash;
+ QString temphash;
+ QList<BindAction> m_binds;
};
#endif
--- a/QTfrontend/hwform.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/hwform.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -155,9 +155,9 @@
ui.pageRoomsList->setSettings(config);
ui.pageNetGame->chatWidget->setSettings(config);
ui.pageRoomsList->chatWidget->setSettings(config);
+ ui.pageOptions->setConfig(config);
#ifdef VIDEOREC
ui.pageVideos->init(config);
- ui.pageOptions->setConfig(config);
#endif
#ifdef __APPLE__
@@ -975,18 +975,8 @@
void HWForm::DeleteTeam(const QString & teamName)
{
- QMessageBox reallyDeleteMsg(this);
- reallyDeleteMsg.setIcon(QMessageBox::Question);
- reallyDeleteMsg.setWindowTitle(QMessageBox::tr("Teams - Are you sure?"));
- reallyDeleteMsg.setText(QMessageBox::tr("Do you really want to delete the team '%1'?").arg(teamName));
- reallyDeleteMsg.setWindowModality(Qt::WindowModal);
- reallyDeleteMsg.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
-
- if (reallyDeleteMsg.exec() == QMessageBox::Ok)
- {
- ui.pageEditTeam->deleteTeam(teamName);
- UpdateTeamsLists();
- }
+ ui.pageEditTeam->deleteTeam(teamName);
+ UpdateTeamsLists();
}
void HWForm::DeleteScheme()
--- a/QTfrontend/team.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/team.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -23,10 +23,12 @@
#include <QCryptographicHash>
#include <QSettings>
#include <QStandardItemModel>
+#include <QDebug>
#include "team.h"
#include "hwform.h"
#include "DataManager.h"
+#include "gameuiconfig.h"
HWTeam::HWTeam(const QString & teamname) :
QObject(0)
@@ -50,7 +52,7 @@
{
m_binds.append(BindAction());
m_binds[i].action = cbinds[i].action;
- m_binds[i].strbind = cbinds[i].strbind;
+ m_binds[i].strbind = QString();
}
m_rounds = 0;
m_wins = 0;
@@ -110,7 +112,7 @@
{
m_binds.append(BindAction());
m_binds[i].action = cbinds[i].action;
- m_binds[i].strbind = cbinds[i].strbind;
+ m_binds[i].strbind = QString();
}
m_rounds = 0;
m_wins = 0;
@@ -191,7 +193,7 @@
m_hedgehogs[i].Suicides = teamfile.value(hh + "Suicides", 0).toInt();
}
for(int i = 0; i < BINDS_NUMBER; i++)
- m_binds[i].strbind = teamfile.value(QString("Binds/%1").arg(m_binds[i].action), cbinds[i].strbind).toString();
+ m_binds[i].strbind = teamfile.value(QString("Binds/%1").arg(m_binds[i].action), QString()).toString();
for(int i = 0; i < MAX_ACHIEVEMENTS; i++)
if(achievements[i][0][0])
AchievementProgress[i] = teamfile.value(QString("Achievements/%1").arg(achievements[i][0]), 0).toUInt();
@@ -257,7 +259,7 @@
return true;
}
-QStringList HWTeam::teamGameConfig(quint32 InitHealth) const
+QStringList HWTeam::teamGameConfig(quint32 InitHealth, GameUIConfig * config) const
{
QStringList sl;
if (m_isNetTeam)
@@ -273,9 +275,15 @@
sl.push_back(QString("eflag " + m_flag));
if (!m_isNetTeam)
+ {
for(int i = 0; i < BINDS_NUMBER; i++)
- if(!m_binds[i].strbind.isEmpty())
+ {
+ if(m_binds[i].strbind.isEmpty() || m_binds[i].strbind == "default")
+ sl.push_back(QString("ebind " + config->bind(i) + " " + m_binds[i].action));
+ else
sl.push_back(QString("ebind " + m_binds[i].strbind + " " + m_binds[i].action));
+ }
+ }
for (int t = 0; t < m_numHedgehogs; t++)
{
--- a/QTfrontend/team.h Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/team.h Sat Dec 29 22:50:10 2012 +0100
@@ -93,7 +93,7 @@
void incWins();
// convert team info into strings for further computation
- QStringList teamGameConfig(quint32 InitHealth) const;
+ QStringList teamGameConfig(quint32 InitHealth, GameUIConfig * config) const;
// comparison operators
bool operator == (const HWTeam& t1) const;
--- a/QTfrontend/ui/page/pageeditteam.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/ui/page/pageeditteam.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -30,6 +30,7 @@
#include <QDebug>
#include "SquareLabel.h"
#include "HWApplication.h"
+#include "keybinder.h"
#include "DataManager.h"
#include "HatModel.h"
@@ -39,16 +40,16 @@
QLayout * PageEditTeam::bodyLayoutDefinition()
{
QGridLayout * pageLayout = new QGridLayout();
- QTabWidget * tbw = new QTabWidget();
+ tbw = new QTabWidget();
QWidget * page1 = new QWidget(this);
- QWidget * page2 = new QWidget(this);
+ binder = new KeyBinder(this, tr("Select an action to choose a custom key bind for this team"), tr("Use my default"), tr("Reset all binds"));
+ connect(binder, SIGNAL(resetAllBinds()), this, SLOT(resetAllBinds()));
tbw->addTab(page1, tr("General"));
- tbw->addTab(page2, tr("Advanced"));
+ tbw->addTab(binder, tr("Custom Controls"));
pageLayout->addWidget(tbw, 0, 0, 1, 3);
QHBoxLayout * page1Layout = new QHBoxLayout(page1);
page1Layout->setAlignment(Qt::AlignTop);
- QGridLayout * page2Layout = new QGridLayout(page2);
// ====== Page 1 ======
QVBoxLayout * vbox1 = new QVBoxLayout();
@@ -157,52 +158,6 @@
vbox1->addStretch();
vbox2->addStretch();
-// ====== Page 2 ======
- GBoxBinds = new QGroupBox(this);
- GBoxBinds->setTitle(QGroupBox::tr("Key binds"));
- QGridLayout * GBBLayout = new QGridLayout(GBoxBinds);
- BindsBox = new QToolBox(GBoxBinds);
- BindsBox->setLineWidth(0);
- GBBLayout->addWidget(BindsBox);
- page2Layout->addWidget(GBoxBinds, 0, 0);
-
- quint16 i = 0;
- quint16 num = 0;
- QWidget * curW = NULL;
- QGridLayout * pagelayout = NULL;
- QLabel* l = NULL;
- while (i < BINDS_NUMBER)
- {
- if(cbinds[i].category != NULL)
- {
- if(curW != NULL)
- {
- l = new QLabel(curW);
- l->setText("");
- pagelayout->addWidget(l, num++, 0, 1, 2);
- }
- curW = new QWidget(this);
- BindsBox->addItem(curW, HWApplication::translate("binds (categories)", cbinds[i].category));
- pagelayout = new QGridLayout(curW);
- num = 0;
- }
- if(cbinds[i].description != NULL)
- {
- l = new QLabel(curW);
- l->setText((num > 0 ? QString("\n") : QString("")) + HWApplication::translate("binds (descriptions)", cbinds[i].description));
- pagelayout->addWidget(l, num++, 0, 1, 2);
- }
-
- l = new QLabel(curW);
- l->setText(HWApplication::translate("binds", cbinds[i].name));
- l->setAlignment(Qt::AlignRight);
- pagelayout->addWidget(l, num, 0);
-
- CBBind[i] = new QComboBox(curW);
- CBBind[i]->setModel(DataManager::instance().bindsModel());
- pagelayout->addWidget(CBBind[i++], num++, 1);
- }
-
return pageLayout;
}
@@ -407,6 +362,9 @@
void PageEditTeam::loadTeam(const HWTeam & team)
{
+ tbw->setCurrentIndex(0);
+ binder->resetInterface();
+
TeamNameEdit->setText(team.name());
CBTeamLvl->setCurrentIndex(team.difficulty());
@@ -431,10 +389,12 @@
QStandardItemModel * binds = DataManager::instance().bindsModel();
for(int i = 0; i < BINDS_NUMBER; i++)
{
+ if (team.keyBind(i).isEmpty()) continue;
+
QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, team.keyBind(i), 1, Qt::MatchExactly);
if(mdl.size() == 1)
- CBBind[i]->setCurrentIndex(mdl[0].row());
+ binder->setBindIndex(i, mdl[0].row());
else
qDebug() << "Binds: cannot find" << team.keyBind(i);
}
@@ -465,7 +425,7 @@
QStandardItemModel * binds = DataManager::instance().bindsModel();
for(int i = 0; i < BINDS_NUMBER; i++)
{
- team.bindKey(i, binds->index(CBBind[i]->currentIndex(), 0).data(Qt::UserRole + 1).toString());
+ team.bindKey(i, binds->index(binder->bindIndex(i), 0).data(Qt::UserRole + 1).toString());
}
return team;
@@ -475,3 +435,10 @@
{
data().saveToFile();
}
+
+// When the "Use default for all binds" is pressed...
+void PageEditTeam::resetAllBinds()
+{
+ for (int i = 0; i < BINDS_NUMBER; i++)
+ binder->setBindIndex(i, 0);
+}
--- a/QTfrontend/ui/page/pageeditteam.h Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/ui/page/pageeditteam.h Sat Dec 29 22:50:10 2012 +0100
@@ -28,6 +28,7 @@
#include "team.h"
class SquareLabel;
+class KeyBinder;
class PageEditTeam : public AbstractPage
{
@@ -44,6 +45,7 @@
void CBFort_activated(const QString & gravename);
private:
+ QTabWidget * tbw;
QSignalMapper* signalMapper1;
QSignalMapper* signalMapper2;
QGroupBox *GBoxHedgehogs;
@@ -60,9 +62,9 @@
QLineEdit * TeamNameEdit;
QLineEdit * HHNameEdit[HEDGEHOGS_PER_TEAM];
QComboBox * HHHats[HEDGEHOGS_PER_TEAM];
- QComboBox * CBBind[BINDS_NUMBER];
HWTeam data();
QString m_playerHash;
+ KeyBinder * binder;
QLayout * bodyLayoutDefinition();
QLayout * footerLayoutDefinition();
@@ -85,6 +87,7 @@
void testSound();
void fixHHname(int idx);
+ void resetAllBinds();
};
#endif
--- a/QTfrontend/ui/page/pageoptions.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/ui/page/pageoptions.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -23,14 +23,17 @@
#include <QComboBox>
#include <QCheckBox>
#include <QLabel>
+#include <QTableWidget>
#include <QLineEdit>
#include <QSpinBox>
#include <QTextBrowser>
-#include <QTableWidget>
+#include <QScrollArea>
+#include <QHeaderView>
#include <QSlider>
#include <QSignalMapper>
#include <QColorDialog>
#include <QStandardItemModel>
+#include <QDebug>
#include "pageoptions.h"
#include "gameuiconfig.h"
@@ -40,6 +43,8 @@
#include "DataManager.h"
#include "LibavInteraction.h"
#include "AutoUpdater.h"
+#include "HWApplication.h"
+#include "keybinder.h"
#ifdef __APPLE__
#ifdef SPARKLE_ENABLED
@@ -56,9 +61,15 @@
pageLayout->addWidget(tabs);
QWidget * page1 = new QWidget(this);
QWidget * page2 = new QWidget(this);
+ binder = new KeyBinder(this, tr("Select an action to change what key controls it"), tr("Reset to default"), tr("Reset all binds"));
+ connect(binder, SIGNAL(bindUpdate(int)), this, SLOT(bindUpdated(int)));
+ connect(binder, SIGNAL(resetAllBinds()), this, SLOT(resetAllBinds()));
tabs->addTab(page1, tr("General"));
+ binderTab = tabs->addTab(binder, tr("Controls"));
tabs->addTab(page2, tr("Advanced"));
+ connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabIndexChanged(int)));
+
#ifdef VIDEOREC
QWidget * page3 = new QWidget(this);
tabs->addTab(page3, tr("Video Recording"));
@@ -914,3 +925,57 @@
return true;
}
+
+// When the current tab is switched
+void PageOptions::tabIndexChanged(int index)
+{
+ if (index == binderTab) // Switched to bind tab
+ {
+ binder->resetInterface();
+
+ if (!config) return;
+
+ QStandardItemModel * binds = DataManager::instance().bindsModel();
+ for(int i = 0; i < BINDS_NUMBER; i++)
+ {
+ QString value = config->bind(i);
+ QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, value, 1, Qt::MatchExactly);
+ if(mdl.size() == 1) binder->setBindIndex(i, mdl[0].row());
+ }
+ }
+
+ currentTab = index;
+}
+
+// When a key bind combobox is changed
+void PageOptions::bindUpdated(int bindID)
+{
+ int bindIndex = binder->bindIndex(bindID);
+
+ if (bindIndex == 0) bindIndex = resetBindToDefault(bindID);
+
+ // Save bind
+ QStandardItemModel * binds = DataManager::instance().bindsModel();
+ QString strbind = binds->index(binder->bindIndex(bindID), 0).data(Qt::UserRole + 1).toString();
+ config->setBind(bindID, strbind);
+}
+
+// Changes a key bind (bindID) to its default value. This updates the bind's combo-box in the UI.
+// Returns: The bind model index of the default.
+int PageOptions::resetBindToDefault(int bindID)
+{
+ QStandardItemModel * binds = DataManager::instance().bindsModel();
+ QModelIndexList mdl = binds->match(binds->index(0, 0), Qt::UserRole + 1, cbinds[bindID].strbind, 1, Qt::MatchExactly);
+ if(mdl.size() == 1) binder->setBindIndex(bindID, mdl[0].row());
+ return mdl[0].row();
+}
+
+// Called when "reset all binds" button is pressed
+void PageOptions::resetAllBinds()
+{
+ for (int i = 0; i < BINDS_NUMBER; i++)
+ {
+ resetBindToDefault(i);
+ bindUpdated(i);
+ }
+}
--- a/QTfrontend/ui/page/pageoptions.h Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/ui/page/pageoptions.h Sat Dec 29 22:50:10 2012 +0100
@@ -25,6 +25,7 @@
class FPSEdit;
class IconedGroupBox;
class QSignalMapper;
+class KeyBinder;
class PageOptions : public AbstractPage
{
@@ -118,6 +119,7 @@
QLayout * bodyLayoutDefinition();
QLayout * footerLayoutDefinition();
void connectSignals();
+ int resetBindToDefault(int bindID);
bool previousFullscreenValue;
int previousResolutionIndex;
@@ -134,6 +136,9 @@
QPushButton *btnDefaults;
QPushButton *btnUpdateNow;
GameUIConfig * config;
+ KeyBinder * binder;
+ int currentTab;
+ int binderTab;
private slots:
void forceFullscreen(int index);
@@ -151,6 +156,9 @@
void changeUseGameRes(int state);
void changeRecordAudio(int state);
void checkForUpdates();
+ void tabIndexChanged(int);
+ void bindUpdated(int bindID);
+ void resetAllBinds();
public slots:
void setDefaultOptions();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/keybinder.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -0,0 +1,301 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include "keybinder.h"
+#include "HWApplication.h"
+#include "DataManager.h"
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QStandardItemModel>
+#include <QAbstractItemModel>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QPushButton>
+#include <QHeaderView>
+#include <QComboBox>
+#include <QLabel>
+#include <QFrame>
+#include <QDebug>
+
+KeyBinder::KeyBinder(QWidget * parent, const QString & helpText, const QString & defaultText, const QString & resetButtonText) : QWidget(parent)
+{
+ this->defaultText = defaultText;
+ enableSignal = false;
+
+ // Two-column tab layout
+ QHBoxLayout * pageKeysLayout = new QHBoxLayout(this);
+ pageKeysLayout->setSpacing(0);
+ pageKeysLayout->setContentsMargins(0, 0, 0, 0);
+
+ // Table for category list
+ QVBoxLayout * catListContainer = new QVBoxLayout();
+ catListContainer->setContentsMargins(10, 10, 10, 10);
+ catList = new QListWidget();
+ catList->setFixedWidth(180);
+ catList->setStyleSheet("QListWidget::item { font-size: 14px; } QListWidget:hover { border-color: #F6CB1C; } QListWidget::item:selected { background: #150A61; color: yellow; }");
+ catList->setFocusPolicy(Qt::NoFocus);
+ connect(catList, SIGNAL(currentRowChanged(int)), this, SLOT(changeBindingsPage(int)));
+ catListContainer->addWidget(catList);
+ pageKeysLayout->addLayout(catListContainer);
+
+ // Reset all binds button
+ if (!resetButtonText.isEmpty())
+ {
+ QPushButton * btnResetAll = new QPushButton(resetButtonText);
+ catListContainer->addWidget(btnResetAll);
+ btnResetAll->setFixedHeight(40);
+ catListContainer->setStretch(1, 0);
+ catListContainer->setSpacing(10);
+ connect(btnResetAll, SIGNAL(clicked()), this, SIGNAL(resetAllBinds()));
+ }
+
+ // Container for pages of key bindings
+ QWidget * bindingsPagesContainer = new QWidget();
+ QVBoxLayout * rightLayout = new QVBoxLayout(bindingsPagesContainer);
+
+ // Scroll area for key bindings
+ QScrollArea * scrollArea = new QScrollArea();
+ scrollArea->setContentsMargins(0, 0, 0, 0);
+ scrollArea->setWidget(bindingsPagesContainer);
+ scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ scrollArea->setWidgetResizable(true);
+ scrollArea->setFrameShape(QFrame::NoFrame);
+ scrollArea->setStyleSheet("background: #130F2A;");
+
+ // Add key binding pages to bindings tab
+ pageKeysLayout->addWidget(scrollArea);
+ pageKeysLayout->setStretch(1, 1);
+
+ // Custom help text
+ QLabel * helpLabel = new QLabel();
+ helpLabel->setText(helpText);
+ helpLabel->setStyleSheet("color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-radius: 10px; padding: auto 20px;");
+ helpLabel->setFixedHeight(24);
+ rightLayout->addWidget(helpLabel, 0, Qt::AlignCenter);
+
+ // Category list and bind table row heights
+ const int rowHeight = 20;
+ QSize catSize, headerSize;
+ catSize.setHeight(36);
+ headerSize.setHeight(24);
+
+ // Category list header
+ QListWidgetItem * catListHeader = new QListWidgetItem(tr("Category"));
+ catListHeader->setSizeHint(headerSize);
+ catListHeader->setFlags(Qt::NoItemFlags);
+ catListHeader->setForeground(QBrush(QColor("#130F2A")));
+ catListHeader->setBackground(QBrush(QColor("#F6CB1C")));
+ catListHeader->setTextAlignment(Qt::AlignCenter);
+ catList->addItem(catListHeader);
+
+ // Populate
+ bindingsPages = new QHBoxLayout();
+ bindingsPages->setContentsMargins(0, 0, 0, 0);
+ rightLayout->addLayout(bindingsPages);
+ QWidget * curPage = NULL;
+ QVBoxLayout * curLayout = NULL;
+ QTableWidget * curTable = NULL;
+ bool bFirstPage = true;
+ selectedBindTable = NULL;
+ bindComboBoxCellMappings = new QHash<QObject *, QTableWidgetItem *>();
+ bindCellComboBoxMappings = new QHash<QTableWidgetItem *, QComboBox *>();
+ for (int i = 0; i < BINDS_NUMBER; i++)
+ {
+ if (cbinds[i].category != NULL)
+ {
+ // Add stretch at end of previous layout
+ if (curLayout != NULL) curLayout->insertStretch(-1, 1);
+
+ // Category list item
+ QListWidgetItem * catItem = new QListWidgetItem(HWApplication::translate("binds (categories)", cbinds[i].category));
+ catItem->setSizeHint(catSize);
+ catList->addItem(catItem);
+
+ // Create new page
+ curPage = new QWidget();
+ curLayout = new QVBoxLayout(curPage);
+ curLayout->setSpacing(2);
+ bindingsPages->addWidget(curPage);
+ if (!bFirstPage) curPage->setVisible(false);
+ }
+
+ // Description
+ if (cbinds[i].description != NULL)
+ {
+ QLabel * desc = new QLabel(HWApplication::translate("binds (descriptions)", cbinds[i].description));
+ curLayout->addWidget(desc, 0);
+ QFrame * divider = new QFrame();
+ divider->setFrameShape(QFrame::HLine);
+ divider->setFrameShadow(QFrame::Plain);
+ curLayout->addWidget(divider, 0);
+ }
+
+ // New table
+ if (cbinds[i].category != NULL || cbinds[i].description != NULL)
+ {
+ curTable = new QTableWidget(0, 2);
+ curTable->verticalHeader()->setVisible(false);
+ curTable->horizontalHeader()->setVisible(false);
+ curTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+ curTable->verticalHeader()->setDefaultSectionSize(rowHeight);
+ curTable->setShowGrid(false);
+ curTable->setStyleSheet("QTableWidget { border: none; } ");
+ curTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ curTable->setSelectionMode(QAbstractItemView::SingleSelection);
+ curTable->setFocusPolicy(Qt::NoFocus);
+ connect(curTable, SIGNAL(itemSelectionChanged()), this, SLOT(bindSelectionChanged()));
+ connect(curTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(bindCellClicked(QTableWidgetItem *)));
+ curLayout->addWidget(curTable, 0);
+ }
+
+ // Hidden combo box
+ QComboBox * comboBox = CBBind[i] = new QComboBox(curTable);
+ comboBox->setModel((QAbstractItemModel*)DataManager::instance().bindsModel());
+ comboBox->setVisible(false);
+ comboBox->setFixedWidth(200);
+
+ // Table row
+ int row = curTable->rowCount();
+ QTableWidgetItem * nameCell = new QTableWidgetItem(HWApplication::translate("binds", cbinds[i].name));
+ nameCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ curTable->insertRow(row);
+ curTable->setItem(row, 0, nameCell);
+ QTableWidgetItem * bindCell = new QTableWidgetItem(comboBox->currentText());
+ bindCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+ curTable->setItem(row, 1, bindCell);
+ curTable->resizeColumnsToContents();
+ curTable->setFixedHeight(curTable->verticalHeader()->length() + 10);
+
+ // Updates the text in the table cell
+ connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(bindChanged(const QString &)));
+
+ // Map combo box and that row's cells to each other
+ bindComboBoxCellMappings->insert(comboBox, bindCell);
+ bindCellComboBoxMappings->insert(nameCell, comboBox);
+ bindCellComboBoxMappings->insert(bindCell, comboBox);
+ }
+
+ // Add stretch at end of last layout
+ if (curLayout != NULL) curLayout->insertStretch(-1, 1);
+
+ // Go to first page
+ catList->setCurrentItem(catList->item(1));
+
+ enableSignal = true;
+}
+
+KeyBinder::~KeyBinder()
+{
+ delete bindComboBoxCellMappings;
+ delete bindCellComboBoxMappings;
+}
+
+// Switches between different pages of key binds
+void KeyBinder::changeBindingsPage(int page)
+{
+ page--; // Disregard first item (the list header)
+ int pages = bindingsPages->count();
+ for (int i = 0; i < pages; i++)
+ bindingsPages->itemAt(i)->widget()->setVisible(false);
+ bindingsPages->itemAt(page)->widget()->setVisible(true);
+}
+
+// When a key bind combobox value is changed, updates the table cell text
+void KeyBinder::bindChanged(const QString & text)
+{
+ bindComboBoxCellMappings->value(sender())->setText(text);
+
+ if (enableSignal)
+ {
+ for (int i = 0; i < BINDS_NUMBER; i++)
+ {
+ if (CBBind[i] == sender())
+ {
+ emit bindUpdate(i);
+ break;
+ }
+ }
+ }
+}
+
+// When a row in a key bind table is clicked, this shows the popup
+void KeyBinder::bindCellClicked(QTableWidgetItem * item)
+{
+ QComboBox * box = bindCellComboBoxMappings->value(item);
+ QTableWidget * table = item->tableWidget();
+ QFrame * frame = box->findChild<QFrame*>();
+
+ box->showPopup();
+ frame->move(
+ frame->x() + table->horizontalHeader()->sectionSize(0),
+ frame->y() + (table->verticalHeader()->defaultSectionSize() * item->row())
+ );
+}
+
+// When a new row in a bind table is *selected*, this clears selection in any other table
+void KeyBinder::bindSelectionChanged()
+{
+ QTableWidget * theSender = (QTableWidget*)sender();
+ if (theSender != selectedBindTable)
+ {
+ if (selectedBindTable != NULL)
+ selectedBindTable->clearSelection();
+ selectedBindTable = theSender;
+ }
+}
+
+// Set a combobox's index
+void KeyBinder::setBindIndex(int keyIndex, int bindIndex)
+{
+ enableSignal = false;
+ CBBind[keyIndex]->setCurrentIndex(bindIndex);
+ enableSignal = true;
+}
+
+// Return a combobox's selected index
+int KeyBinder::bindIndex(int keyIndex)
+{
+ return CBBind[keyIndex]->currentIndex();
+}
+
+// Clears selection and goes to first category
+void KeyBinder::resetInterface()
+{
+ enableSignal = false;
+
+ catList->setCurrentItem(catList->item(1));
+ changeBindingsPage(1);
+ if (selectedBindTable != NULL)
+ {
+ selectedBindTable->clearSelection();
+ selectedBindTable = NULL;
+ }
+
+ // Default bind text
+ DataManager::instance().bindsModel()->item(0)->setData(defaultText, Qt::DisplayRole);
+ for (int i = 0; i < BINDS_NUMBER; i++)
+ {
+ CBBind[i]->setModel(DataManager::instance().bindsModel());
+ CBBind[i]->setCurrentIndex(0);
+ bindComboBoxCellMappings->value(CBBind[i])->setText(defaultText);
+ }
+
+ enableSignal = true;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/keybinder.h Sat Dec 29 22:50:10 2012 +0100
@@ -0,0 +1,68 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef _KEY_BINDER_H
+#define _KEY_BINDER_H
+
+#include <QWidget>
+#include <QHash>
+
+#include "binds.h"
+
+class QListWidget;
+class QTableWidgetItem;
+class QTableWidget;
+class QBoxLayout;
+class QComboBox;
+
+// USAGE NOTE: Every time the widget comes into view, you must call resetInterface()
+
+class KeyBinder : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ KeyBinder(QWidget * parent = NULL, const QString & helpText = QString(), const QString & defaultText = QString(), const QString & resetButtonText = QString());
+ ~KeyBinder();
+
+ void setBindIndex(int keyIndex, int bindIndex);
+ int bindIndex(int keyIndex);
+ void resetInterface();
+
+ private:
+ QHash<QObject *, QTableWidgetItem *> * bindComboBoxCellMappings;
+ QHash<QTableWidgetItem *, QComboBox *> * bindCellComboBoxMappings;
+ QTableWidget * selectedBindTable;
+ QListWidget * catList;
+ QBoxLayout *bindingsPages;
+ QComboBox * CBBind[BINDS_NUMBER];
+ QString defaultText;
+ bool enableSignal;
+
+ signals:
+ void bindUpdate(int bindID);
+ void resetAllBinds();
+
+ private slots:
+ void changeBindingsPage(int page);
+ void bindChanged(const QString &);
+ void bindCellClicked(QTableWidgetItem * item);
+ void bindSelectionChanged();
+};
+
+#endif // _KEY_BINDER_H
--- a/QTfrontend/util/DataManager.cpp Fri Dec 28 23:54:42 2012 +0100
+++ b/QTfrontend/util/DataManager.cpp Sat Dec 29 22:50:10 2012 +0100
@@ -135,6 +135,11 @@
{
m_bindsModel = new QStandardItemModel();
+ QStandardItem * firstItem = new QStandardItem();
+ firstItem->setData(tr("Use Default"), Qt::DisplayRole);
+ firstItem->setData("default", Qt::UserRole + 1);
+ m_bindsModel->appendRow(firstItem);
+
for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
{
QStandardItem * item = new QStandardItem();
--- a/hedgewars/hwengine.pas Fri Dec 28 23:54:42 2012 +0100
+++ b/hedgewars/hwengine.pas Sat Dec 29 22:50:10 2012 +0100
@@ -264,6 +264,9 @@
end; //end case event.type_ of
end; //end while SDL_PollEvent(@event) <> 0 do
+ if (CursorMovementX <> 0) or (CursorMovementY <> 0) then
+ handlePositionUpdate(CursorMovementX * cameraKeyboardSpeed, CursorMovementY * cameraKeyboardSpeed);
+
if (cScreenResizeDelay <> 0) and (cScreenResizeDelay < RealTicks) and
((cNewScreenWidth <> cScreenWidth) or (cNewScreenHeight <> cScreenHeight)) then
begin
--- a/hedgewars/uConsts.pas Fri Dec 28 23:54:42 2012 +0100
+++ b/hedgewars/uConsts.pas Sat Dec 29 22:50:10 2012 +0100
@@ -43,6 +43,9 @@
msgFailedSize = 'failed due to size';
msgGettingConfig = 'Getting game config...';
+ // camera movement multipliers
+ cameraKeyboardSpeed : ShortInt = 10;
+
// color constants
cWhiteColorChannels : TSDL_Color = (r:$FF; g:$FF; b:$FF; unused:$FF);
cNearBlackColorChannels : TSDL_Color = (r:$00; g:$00; b:$10; unused:$FF);
--- a/hedgewars/uCursor.pas Fri Dec 28 23:54:42 2012 +0100
+++ b/hedgewars/uCursor.pas Sat Dec 29 22:50:10 2012 +0100
@@ -5,6 +5,7 @@
procedure init;
procedure resetPosition;
procedure updatePosition;
+procedure handlePositionUpdate(x, y: LongInt);
implementation
@@ -24,15 +25,20 @@
var x, y: LongInt;
begin
SDL_GetMouseState(@x, @y);
-
+
if(x <> cScreenWidth div 2) or (y <> cScreenHeight div 2) then
- begin
- CursorPoint.X:= CursorPoint.X + x - cScreenWidth div 2;
- CursorPoint.Y:= CursorPoint.Y - y + cScreenHeight div 2;
+ begin
+ handlePositionUpdate(x - cScreenWidth div 2, y - cScreenHeight div 2);
if cHasFocus then
SDL_WarpMouse(cScreenWidth div 2, cScreenHeight div 2);
- end
+ end
+end;
+
+procedure handlePositionUpdate(x, y: LongInt);
+begin
+ CursorPoint.X:= CursorPoint.X + x;
+ CursorPoint.Y:= CursorPoint.Y - y;
end;
end.
--- a/hedgewars/uInputHandler.pas Fri Dec 28 23:54:42 2012 +0100
+++ b/hedgewars/uInputHandler.pas Sat Dec 29 22:50:10 2012 +0100
@@ -39,6 +39,7 @@
procedure SetBinds(var binds: TBinds);
procedure SetDefaultBinds;
+procedure chDefaultBind(var id: shortstring);
procedure ControllerInit;
procedure ControllerAxisEvent(joy, axis: Byte; value: Integer);
@@ -70,6 +71,7 @@
//ControllerBalls: array[0..5] of array[0..19] of array[0..1] of Integer;
ControllerHats: array[0..5] of array[0..19] of Byte;
ControllerButtons: array[0..5] of array[0..19] of Byte;
+ usingDBinds: boolean;
function KeyNameToCode(name: shortstring): LongInt; inline;
begin
@@ -329,9 +331,9 @@
binds:= binds; // avoid hint
CurrentBinds:= DefaultBinds;
{$ELSE}
-for t:= 0 to cKbdMaxIndex do
- if (CurrentBinds[t] <> binds[t]) and tkbd[t] then
- ProcessKey(t, False);
+ for t:= 0 to cKbdMaxIndex do
+ if (CurrentBinds[t] <> binds[t]) and tkbd[t] then
+ ProcessKey(t, False);
CurrentBinds:= binds;
{$ENDIF}
@@ -450,8 +452,45 @@
ProcessKey(k + ControllerNumAxes[joy]*2 + ControllerNumHats[joy]*4 + button, pressed);
end;
+// Bind that isn't a team bind, but overrides defaultbinds.
+// When first called, DefaultBinds is cleared, because we assume we are getting a full list of dbinds.
+procedure chDefaultBind(var id: shortstring);
+var KeyName, Modifier, tmp: shortstring;
+ b: LongInt;
+begin
+KeyName:= '';
+Modifier:= '';
+
+if (not usingDBinds) then
+ begin
+ usingDBinds:= true;
+ FillByte(DefaultBinds, SizeOf(DefaultBinds), 0);
+ end;
+
+if (Pos('mod:', id) <> 0) then
+ begin
+ tmp:= '';
+ SplitBySpace(id, tmp);
+ Modifier:= id;
+ id:= tmp;
+ end;
+
+SplitBySpace(id, KeyName);
+if KeyName[1]='"' then
+ Delete(KeyName, 1, 1);
+if KeyName[byte(KeyName[0])]='"' then
+ Delete(KeyName, byte(KeyName[0]), 1);
+b:= KeyNameToCode(id, Modifier);
+if b = 0 then
+ OutError(errmsgUnknownVariable + ' "' + id + '"', false)
+else
+ DefaultBinds[b]:= KeyName;
+end;
+
procedure initModule;
begin
+ usingDBinds:= false;
+ RegisterVariable('dbind', @chDefaultBind, true );
end;
procedure freeModule;
--- a/hedgewars/uTeams.pas Fri Dec 28 23:54:42 2012 +0100
+++ b/hedgewars/uTeams.pas Sat Dec 29 22:50:10 2012 +0100
@@ -330,7 +330,7 @@
function AddTeam(TeamColor: Longword): PTeam;
var team: PTeam;
- c: LongInt;
+ c, t: LongInt;
begin
TryDo(TeamsCount < cMaxTeams, 'Too many teams', true);
New(team);
@@ -343,6 +343,9 @@
TeamsArray[TeamsCount]:= team;
inc(TeamsCount);
+for t:= 0 to cKbdMaxIndex do
+ team^.Binds[t]:= '';
+
c:= Pred(ClansCount);
while (c >= 0) and (ClansArray[c]^.Color <> TeamColor) do dec(c);
if c < 0 then