--- a/QTfrontend/hedgewars.qrc Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/hedgewars.qrc Mon Jan 14 12:07:51 2013 +0100
@@ -103,6 +103,7 @@
<file>res/iconRope.png</file>
<file>res/dice.png</file>
<file>res/Star.png</file>
+ <file>res/inverse-corner-bl.png</file>
<file>res/Flake.png</file>
<file>res/Egg.png</file>
<file>res/Confetti.png</file>
@@ -130,6 +131,7 @@
<file>res/StatsMostSelfDamage.png</file>
<file>res/StatsSelfKilled.png</file>
<file>res/StatsSkipped.png</file>
+ <file>res/Start.png</file>
<file>res/mapRandom.png</file>
<file>res/mapMaze.png</file>
<file>res/mapMissing.png</file>
--- a/QTfrontend/hwform.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/hwform.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -1716,7 +1716,7 @@
void HWForm::NetGameChangeStatus(bool isMaster)
{
- ui.pageNetGame->pGameCFG->setEnabled(isMaster);
+ ui.pageNetGame->pGameCFG->setMaster(isMaster);
ui.pageNetGame->pNetTeamsWidget->setInteractivity(isMaster);
if (isMaster)
@@ -1731,7 +1731,7 @@
ui.pageNetGame->restrictJoins->setChecked(false);
ui.pageNetGame->restrictTeamAdds->setChecked(false);
ui.pageNetGame->pGameCFG->GameSchemes->setModel(ammoSchemeModel);
- ui.pageNetGame->pGameCFG->setEnabled(true);
+ ui.pageNetGame->pGameCFG->setMaster(true);
ui.pageNetGame->pNetTeamsWidget->setInteractivity(true);
if (hwnet)
@@ -1759,7 +1759,7 @@
void HWForm::NetGameSlave()
{
- ui.pageNetGame->pGameCFG->setEnabled(false);
+ ui.pageNetGame->pGameCFG->setMaster(false);
ui.pageNetGame->pNetTeamsWidget->setInteractivity(false);
if (hwnet)
--- a/QTfrontend/model/HatModel.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/HatModel.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -26,26 +26,28 @@
#include <QDir>
#include <QPixmap>
#include <QPainter>
+#include <QList>
#include "hwform.h" // player hash
#include "DataManager.h"
HatModel::HatModel(QObject* parent) :
- QAbstractListModel(parent)
-{
- hats = QVector<QPair<QString, QIcon> >();
-}
+ QStandardItemModel(parent)
+{}
void HatModel::loadHats()
{
// this method resets the contents of this model (important to know for views).
- beginResetModel();
+ QStandardItemModel::beginResetModel();
+ QStandardItemModel::clear();
- // prepare hats Vector
- hats.clear();
+ // New hats to add to model
+ QList<QStandardItem *> hats;
+ // we'll need the DataManager a few times, so let's get a reference to it
DataManager & dataMgr = DataManager::instance();
+ // Default hat icon
QPixmap hhpix = QPixmap("physfs://Graphics/Hedgehog/Idle.png").copy(0, 0, 32, 32);
// my reserved hats
@@ -54,7 +56,6 @@
QDir::Files,
QStringList(playerHash+"*.png")
);
-
int nReserved = hatsList.size();
// regular hats
@@ -64,14 +65,15 @@
QStringList("*.png")
)
);
-
-
int nHats = hatsList.size();
+ // Add each hat
for (int i = 0; i < nHats; i++)
{
bool isReserved = (i < nReserved);
+ if (isReserved) continue; // For some reason, reserved hats were added in 9.19-dev, so this will hide them. Uncomment to show them.
+
QString str = hatsList.at(i);
str = str.remove(QRegExp("\\.png$"));
QPixmap pix(
@@ -94,51 +96,11 @@
painter.end();
if (str == "NoHat")
- hats.prepend(qMakePair(str, QIcon(tmppix)));
+ hats.prepend(new QStandardItem(QIcon(tmppix), str));
else
- hats.append(qMakePair(str, QIcon(tmppix)));
+ hats.append(new QStandardItem(QIcon(tmppix), str));
}
-
- endResetModel();
-}
-
-QVariant HatModel::headerData(int section,
- Qt::Orientation orientation, int role) const
-{
- Q_UNUSED(section);
- Q_UNUSED(orientation);
- Q_UNUSED(role);
-
- return QVariant();
-}
-
-int HatModel::rowCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
- else
- return hats.size();
-}
-
-/*int HatModel::columnCount(const QModelIndex & parent) const
-{
- if (parent.isValid())
- return 0;
- else
- return 2;
-}
-*/
-QVariant HatModel::data(const QModelIndex &index,
- int role) const
-{
- if (!index.isValid() || index.row() < 0
- || index.row() >= hats.size()
- || (role != Qt::DisplayRole && role != Qt::DecorationRole))
- return QVariant();
-
- if (role == Qt::DisplayRole)
- return hats.at(index.row()).first;
- else // role == Qt::DecorationRole
- return hats.at(index.row()).second;
-}
+ QStandardItemModel::appendColumn(hats);
+ QStandardItemModel::endResetModel();
+}
\ No newline at end of file
--- a/QTfrontend/model/HatModel.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/HatModel.h Mon Jan 14 12:07:51 2013 +0100
@@ -24,30 +24,22 @@
#ifndef HEDGEWARS_HATMODEL_H
#define HEDGEWARS_HATMODEL_H
-#include <QAbstractListModel>
+#include <QStandardItemModel>
#include <QStringList>
#include <QVector>
#include <QPair>
#include <QIcon>
-class HatModel : public QAbstractListModel
+class HatModel : public QStandardItemModel
{
Q_OBJECT
public:
HatModel(QObject *parent = 0);
- QVariant headerData(int section, Qt::Orientation orientation, int role) const;
- int rowCount(const QModelIndex & parent) const;
- //int columnCount(const QModelIndex & parent) const;
-
public slots:
/// Reloads hats using the DataManager.
void loadHats();
-
- QVariant data(const QModelIndex &index, int role) const;
- protected:
- QVector<QPair<QString, QIcon> > hats;
};
#endif // HEDGEWARS_HATMODEL_H
--- a/QTfrontend/model/MapModel.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/MapModel.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -22,9 +22,15 @@
*/
#include "MapModel.h"
+#include "hwapplication.h"
+#include <QSettings>
-void MapModel::loadMaps()
+MapModel::MapInfo MapModel::MapInfoRandom = {MapModel::GeneratedMap, "+rnd+", "", 0, "", "", ""};
+MapModel::MapInfo MapModel::MapInfoMaze = {MapModel::GeneratedMaze, "+maze+", "", 0, "", "", ""};
+MapModel::MapInfo MapModel::MapInfoDrawn = {MapModel::HandDrawnMap, "+drawn+", "", 0, "", "", ""};
+
+void MapModel::loadMaps(MapType maptype)
{
// this method resets the contents of this model (important to know for views).
beginResetModel();
@@ -39,19 +45,9 @@
// empty list, so that we can (re)fill it
QStandardItemModel::clear();
- QList<QStandardItem *> genMaps;
- QList<QStandardItem *> missionMaps;
- QList<QStandardItem *> staticMaps;
-
- // add generated/handdrawn maps to list
- // TODO: icons for these
-
- genMaps.append(
- infoToItem(QIcon(), QComboBox::tr("generated map..."), GeneratedMap, "+rnd+"));
- genMaps.append(
- infoToItem(QIcon(), QComboBox::tr("generated maze..."), GeneratedMaze, "+maze+"));
- genMaps.append(
- infoToItem(QIcon(), QComboBox::tr("hand drawn map..."), HandDrawnMap, "+drawn+"));
+ //QList<QStandardItem *> staticMaps;
+ //QList<QStandardItem *> missionMaps;
+ QList<QStandardItem *> mapList;
// only 2 map relate files are relevant:
// - the cfg file that contains the settings/info of the map
@@ -64,7 +60,7 @@
{
mapCfgFile.setFileName(QString("physfs://Maps/%1/map.cfg").arg(map));
mapLuaFile.setFileName(QString("physfs://Maps/%1/map.lua").arg(map));
-
+ QSettings descSettings(QString("physfs://Maps/%1/desc.txt").arg(map), QSettings::IniFormat);
if (mapCfgFile.open(QFile::ReadOnly))
{
@@ -73,25 +69,36 @@
quint32 limit = 0;
QString scheme;
QString weapons;
+ QString desc;
+
// if there is a lua file for this map, then it's a mission
bool isMission = mapLuaFile.exists();
- MapType type = isMission?MissionMap:StaticMap;
+ MapType type = isMission ? MissionMap : StaticMap;
+
+ // If we're supposed to ignore this type, continue
+ if (type != maptype) continue;
// load map info from file
QTextStream input(&mapCfgFile);
- input >> theme;
- input >> limit;
+ theme = input.readLine();
+ limit = input.readLine().toInt();
if (isMission) { // scheme and weapons are only relevant for missions
- input >> scheme;
- input >> weapons;
+ scheme = input.readLine();
+ weapons = input.readLine();
}
mapCfgFile.close();
+ // Load description (if applicable)
+ if (isMission)
+ {
+ QString locale = HWApplication::keyboardInputLocale().name();
+ desc = descSettings.value(locale, QString()).toString().replace("|", "\n");
+ }
+
// let's use some semi-sane hedgehog limit, rather than none
if (limit == 0)
limit = 18;
-
// the default scheme/weaponset for missions.
// if empty we assume the map sets these internally -> locked
if (isMission)
@@ -107,97 +114,54 @@
weapons.replace("_", " ");
}
- // add a mission caption prefix to missions
- if (isMission)
- {
- // TODO: icon
- caption = QComboBox::tr("Mission") + ": " + map;
- }
- else
- caption = map;
+ // caption
+ caption = map;
// we know everything there is about the map, let's get am item for it
- QStandardItem * item = infoToItem(
- QIcon(), caption, type, map, theme, limit, scheme, weapons);
+ QStandardItem * item = MapModel::infoToItem(
+ QIcon(), caption, type, map, theme, limit, scheme, weapons, desc);
// append item to the list
- if (isMission)
- missionMaps.append(item);
- else
- staticMaps.append(item);
-
+ mapList.append(item);
}
}
-
- // define a separator item
- QStandardItem separator("---");
- separator.setData(QLatin1String("separator"), Qt::AccessibleDescriptionRole);
- separator.setFlags(separator.flags() & ~( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) );
-
- // create list:
- // generated+handdrawn maps, 2 saperators, missions, 1 separator, static maps
- QList<QStandardItem * > items;
- items.append(genMaps);
- items.append(separator.clone());
- items.append(separator.clone());
- items.append(missionMaps);
- items.append(separator.clone());
- items.append(staticMaps);
-
-
- // create row-index lookup table
+ // Create column-index lookup table
m_mapIndexes.clear();
- int count = items.size();
+ int count = mapList.size();
for (int i = 0; i < count; i++)
{
- QStandardItem * si = items.at(i);
+ QStandardItem * si = mapList.at(i);
QVariant v = si->data(Qt::UserRole + 1);
if (v.canConvert<MapInfo>())
m_mapIndexes.insert(v.value<MapInfo>().name, i);
}
-
- // store start-index and count of relevant types
-
- m_typeLoc.insert(GeneratedMap, QPair<int,int>(0, 1));
- m_typeLoc.insert(GeneratedMaze, QPair<int,int>(1, 1));
- m_typeLoc.insert(HandDrawnMap, QPair<int,int>(2, 1));
- // mission maps
- int startIdx = genMaps.size() + 2; // start after genMaps and 2 separators
- count = missionMaps.size();
- m_typeLoc.insert(MissionMap, QPair<int,int>(startIdx, count));
- // static maps
- startIdx += count + 1; // start after missions and 2 separators
- count = staticMaps.size();
- m_typeLoc.insert(StaticMap, QPair<int,int>(startIdx, count));
-
- // store list contents in the item model
- QStandardItemModel::appendColumn(items);
-
+ QStandardItemModel::appendColumn(mapList);
endResetModel();
}
-
-int MapModel::randomMap(MapType type) const
+bool MapModel::mapExists(const QString & map) const
{
- // return a random index for this type or -1 if none available
- QPair<int,int> loc = m_typeLoc.value(type, QPair<int,int>(-1,0));
-
- int startIdx = loc.first;
- int count = loc.second;
-
- if (count < 1)
- return -1;
- else
- return startIdx + (rand() % count);
+ return findMap(map) >= 0;
}
+int MapModel::findMap(const QString & map) const
+{
+ return m_mapIndexes.value(map, -1);
+}
+
+QStandardItem * MapModel::getMap(const QString & map)
+{
+ int loc = findMap(map);
+ if (loc < 0) return NULL;
+ return item(loc);
+}
QStandardItem * MapModel::infoToItem(
const QIcon & icon,
@@ -207,8 +171,8 @@
QString theme,
quint32 limit,
QString scheme,
- QString weapons)
-const
+ QString weapons,
+ QString desc)
{
QStandardItem * item = new QStandardItem(icon, caption);
MapInfo mapInfo;
@@ -220,17 +184,10 @@
mapInfo.limit = limit;
mapInfo.scheme = scheme;
mapInfo.weapons = weapons;
-
+ mapInfo.desc = desc.isEmpty() ? tr("No description available.") : desc;
qvar.setValue(mapInfo);
item->setData(qvar, Qt::UserRole + 1);
return item;
}
-
-
-int MapModel::indexOf(const QString & map) const
-{
- return m_mapIndexes.value(map, -1);
-}
-
--- a/QTfrontend/model/MapModel.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/MapModel.h Mon Jan 14 12:07:51 2013 +0100
@@ -63,32 +63,49 @@
quint32 limit; ///< The maximum allowed number of hedgehogs.
QString scheme; ///< Default scheme name or "locked", for mission-maps.
QString weapons; ///< Default weaponset name or "locked", for missions-maps.
+ QString desc; ///< The brief 1-2 sentence description of the mission, for mission-maps.
};
/**
- * @brief Returns the row-index of the given map.
- * @param map map of which to get the row-index of.
- * @return row-index of map or -1 if not available.
+ * @brief Searches maps in model to find out if one exists
+ * @param map map of which to check existence
+ * @return true if it exists
*/
- int indexOf(const QString & map) const;
+ bool mapExists(const QString & map) const;
+
+ /**
+ * @brief Finds a map index (column, row) for a map name
+ * @param map map of which to find index+column
+ * @return QPair<int, int> with column, index, or (-1, -1) if map not found
+ */
+ //QPair<int, int> findMap(const QString & map) const;
/**
- * @brief Returns the row-index of a random map with a specified type.
- * @param type desired type of map.
- * @return row-index of a map with the desired type, -1 if none found.
+ * @brief Finds a map index for a map name
+ * @param map map of which to find index
+ * @return int of index, or -1 if map not found
*/
- int randomMap(MapType type) const;
+ int findMap(const QString & map) const;
+
+ /**
+ * @brief Finds and returns a map item for a map name
+ * @param map map
+ * @return QStandardItem of map, or NULL if map not found
+ */
+ QStandardItem * getMap(const QString & map);
+
+ // Static MapInfos for drawn and generated maps
+ static MapInfo MapInfoRandom, MapInfoMaze, MapInfoDrawn;
public slots:
/// Reloads the maps using the DataManager.
- void loadMaps();
+ /// Accepts two map types: StaticMap or MissionMap.
+ void loadMaps(MapType maptype);
private:
- /// start-index and map count for each map-type.
- QMap<MapType, QPair<int,int> > m_typeLoc;
-
- /// map index lookup table
+ /// map index lookup table. QPair<int, int> contains: <column, index>
+ //QHash<QString, QPair<int, int> > m_mapIndexes;
QHash<QString, int> m_mapIndexes;
/**
@@ -102,9 +119,10 @@
* @param limit the hedgehog limit of the map.
* @param scheme mission map: default scheme name or "locked".
* @param weapons mission map: default weaponset name or "locked".
+ * @param desc mission map: description of mission.
* @return pointer to item representing the map info: at Qt::UserRole + 1.
*/
- QStandardItem * infoToItem(
+ static QStandardItem * infoToItem(
const QIcon & icon,
const QString caption,
MapType type = Invalid,
@@ -112,7 +130,8 @@
QString theme = "",
quint32 limit = 0,
QString scheme = "",
- QString weapons = "") const;
+ QString weapons = "",
+ QString desc = "");
};
Q_DECLARE_METATYPE(MapModel::MapInfo)
--- a/QTfrontend/model/ThemeModel.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/ThemeModel.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -73,11 +73,16 @@
QMap<int, QVariant> dataset;
+ // set icon path
+ dataset.insert(Qt::UserRole + 1, iconpath);
+
// set name
dataset.insert(Qt::DisplayRole, theme);
// load and set icon
- QIcon icon(iconpath);
+ QIcon icon;
+ icon.addPixmap(QPixmap(iconpath), QIcon::Normal);
+ icon.addPixmap(QPixmap(iconpath), QIcon::Disabled);
dataset.insert(Qt::DecorationRole, icon);
--- a/QTfrontend/model/roomslistmodel.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/roomslistmodel.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -43,7 +43,8 @@
<< tr("Rules")
<< tr("Weapons");
- m_mapModel = DataManager::instance().mapModel();
+ m_staticMapModel = DataManager::instance().staticMapModel();
+ m_missionMapModel = DataManager::instance().missionMapModel();
}
@@ -134,7 +135,8 @@
}
// prefix ? if map not available
- if ((m_mapModel->indexOf(content) < 0))
+ if (!m_staticMapModel->mapExists(content) &&
+ !m_missionMapModel->mapExists(content))
return QString ("? %1").arg(content);
}
@@ -144,10 +146,14 @@
// dye map names red if map not available
if (role == Qt::ForegroundRole)
{
- if ((m_mapModel->indexOf(content) < 0))
+ if (content == "+rnd+" ||
+ content == "+maze+" ||
+ content == "+drawn+" ||
+ m_staticMapModel->mapExists(content) ||
+ m_missionMapModel->mapExists(content))
+ return QVariant();
+ else
return QBrush(QColor("darkred"));
- else
- return QVariant();
}
if (role == Qt::TextAlignmentRole)
--- a/QTfrontend/model/roomslistmodel.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/model/roomslistmodel.h Mon Jan 14 12:07:51 2013 +0100
@@ -64,7 +64,8 @@
const int c_nColumns;
QList<QStringList> m_data;
QStringList m_headerData;
- MapModel * m_mapModel;
+ MapModel * m_staticMapModel;
+ MapModel * m_missionMapModel;
QStringList roomInfo2RoomRecord(const QStringList & info);
};
Binary file QTfrontend/res/Start.png has changed
--- a/QTfrontend/res/css/qt.css Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/res/css/qt.css Mon Jan 14 12:07:51 2013 +0100
@@ -45,7 +45,7 @@
QTextBrowser, QSpinBox, QToolBox, QComboBox, QPlainTextEdit,
QComboBox QAbstractItemView, IconedGroupBox,
.QGroupBox, GameCFGWidget, TeamSelWidget, SelWeaponWidget,
-QTabWidget::pane, QTabBar::tab {
+QTabWidget::pane, QTabBar::tab, #mapPreview {
border: solid;
border-width: 3px;
border-color: #ffcc00;
@@ -56,8 +56,20 @@
border-color: yellow;
}
+QToolButton {
+background-color: #11084A;
+}
+
+QToolButton:hover {
+background-color: #150A61;
+}
+
+QToolButton:pressed {
+background-color: #100744;
+}
+
QLineEdit, QListWidget, QListView, QTableView, QTextBrowser,
-QSpinBox, QToolBox, QPlainTextEdit {
+QSpinBox, QToolBox, QPlainTextEdit, QToolButton, #mapPreview {
border-radius: 10px;
}
@@ -97,7 +109,7 @@
background-color: rgba(18, 42, 5, 70%);
}
-QPushButton:pressed{
+QPushButton:pressed, QToolButton:pressed {
border-color: white;
}
@@ -246,3 +258,42 @@
width: 8px;
}
+HatButton {
+text-align: left;
+}
+
+#hatList, #hatList:hover {
+border-color: #F6CB1C;
+}
+
+#hatList QScrollBar {
+background-color: #130F2A;
+border-top-right-radius: 10px;
+border-bottom-right-radius: 10px;
+}
+
+#hatList {
+border-color: #F6CB1C;
+border-width: 3px;
+border-style: solid;
+border-radius: 10px;
+border-top-left-radius: 0px;
+}
+
+#hatList::item {
+background-color: #11084A;
+padding: 4px;
+border-radius: 10px;
+color: #ffcc00 !important;
+font: 8px;
+border-width: 2px;
+border-color: #11084A;
+}
+
+#hatList::item:hover {
+background-color: #150A61;
+}
+
+#hatList::item:selected {
+background-color: #150A61;
+}
\ No newline at end of file
Binary file QTfrontend/res/inverse-corner-bl.png has changed
--- a/QTfrontend/ui/page/AbstractPage.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/AbstractPage.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -41,9 +41,10 @@
QGridLayout * pageLayout = new QGridLayout(this);
// stretch grid space for body and footer
- pageLayout->setColumnStretch(0,1);
- pageLayout->setColumnStretch(1,2);
+ pageLayout->setColumnStretch(0,0);
+ pageLayout->setColumnStretch(1,0);
pageLayout->setColumnStretch(2,1);
+ pageLayout->setColumnStretch(3,0);
pageLayout->setRowStretch(0,1);
pageLayout->setRowStretch(1,0);
@@ -53,7 +54,12 @@
pageLayout->addWidget(btnBack, 1, 0, 1, 1, Qt::AlignLeft | Qt::AlignBottom);
// add body layout as defined by the subclass
- pageLayout->addLayout(bodyLayoutDefinition(), 0, 0, 1, 3);
+ pageLayout->addLayout(bodyLayoutDefinition(), 0, 0, 1, 4);
+
+ // add left footer layout
+ QLayout * flld = footerLayoutLeftDefinition();
+ if (flld != NULL)
+ pageLayout->addLayout(flld, 1, 1);
descLabel = new QLabel();
descLabel->setAlignment(Qt::AlignCenter);
@@ -61,12 +67,12 @@
descLabel->setOpenExternalLinks(true);
descLabel->setFixedHeight(50);
descLabel->setStyleSheet("font-size: 16px");
- pageLayout->addWidget(descLabel, 1, 1);
+ pageLayout->addWidget(descLabel, 1, 2);
// add footer layout
QLayout * fld = footerLayoutDefinition();
if (fld != NULL)
- pageLayout->addLayout(fld, 1, 2);
+ pageLayout->addLayout(fld, 1, 3);
// connect signals
connect(btnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
--- a/QTfrontend/ui/page/AbstractPage.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/AbstractPage.h Mon Jan 14 12:07:51 2013 +0100
@@ -121,6 +121,17 @@
* @brief Used during page construction.
* You can implement this method in your subclass.
*
+ * Use it to define layout (not behavior) of the page's footer to the left of the help text.
+ */
+ virtual QLayout * footerLayoutLeftDefinition()
+ {
+ return NULL;
+ };
+
+ /**
+ * @brief Used during page construction.
+ * You can implement this method in your subclass.
+ *
* This is a good place to connect signals within your page in order
* to get the desired page behavior.<br />
* Keep in mind not to expose twidgets as public!
--- a/QTfrontend/ui/page/pageeditteam.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/pageeditteam.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -33,7 +33,7 @@
#include "keybinder.h"
#include "DataManager.h"
-#include "HatModel.h"
+#include "hatbutton.h"
#include "pageeditteam.h"
@@ -64,25 +64,32 @@
HatModel * hatModel = DataManager::instance().hatModel();
+ GBHLayout->addWidget(new QLabel(tr("Hat")), 0, 0);
+ GBHLayout->addWidget(new QLabel(tr("Name")), 0, 1);
+
for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
{
- HHHats[i] = new QComboBox(GBoxHedgehogs);
- HHHats[i]->setModel(hatModel);
- HHHats[i]->setIconSize(QSize(32, 37));
- //HHHats[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
- //HHHats[i]->setModelColumn(1);
- //HHHats[i]->setMinimumWidth(132);
- GBHLayout->addWidget(HHHats[i], i, 0);
+ HHHats[i] = new HatButton(GBoxHedgehogs);
+ GBHLayout->addWidget(HHHats[i], i + 1, 0);
HHNameEdit[i] = new QLineEdit(GBoxHedgehogs);
HHNameEdit[i]->setMaxLength(64);
HHNameEdit[i]->setMinimumWidth(120);
- GBHLayout->addWidget(HHNameEdit[i], i, 1);
+ HHNameEdit[i]->setFixedHeight(36);
+ HHNameEdit[i]->setWhatsThis(tr("This hedgehog's name"));
+ HHNameEdit[i]->setStyleSheet("padding: 6px;");
+ GBHLayout->addWidget(HHNameEdit[i], i + 1, 1);
- btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i, 3, 1, 1, true);
+ btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i + 1, 3, 1, 1, true);
+ btnRandomHogName[i]->setFixedHeight(HHNameEdit[i]->height());
+ btnRandomHogName[i]->setWhatsThis(tr("Randomize this hedgehog's name"));
}
- btnRandomTeam = addButton(QPushButton::tr("Random Team"), GBHLayout, 9, 0);
+ btnRandomTeam = new QPushButton();
+ btnRandomTeam->setText(tr("Random Team"));
+ btnRandomTeam->setStyleSheet("padding: 6px 10px;");
+ GBHLayout->addWidget(btnRandomTeam, 9, 0, 1, 4, Qt::AlignCenter);
+ btnRandomTeam->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
vbox1->addWidget(GBoxHedgehogs);
@@ -377,7 +384,7 @@
if (hh.Hat.startsWith("Reserved"))
hh.Hat = "Reserved "+hh.Hat.remove(0,40);
- HHHats[i]->setCurrentIndex(HHHats[i]->findData(hh.Hat, Qt::DisplayRole));
+ HHHats[i]->setCurrentHat(hh.Hat);
}
CBGrave->setCurrentIndex(CBGrave->findText(team.grave()));
@@ -409,7 +416,7 @@
{
HWHog hh;
hh.Name = HHNameEdit[i]->text();
- hh.Hat = HHHats[i]->currentText();
+ hh.Hat = HHHats[i]->currentHat();
if (hh.Hat.startsWith("Reserved"))
hh.Hat = "Reserved"+m_playerHash+hh.Hat.remove(0,9);
--- a/QTfrontend/ui/page/pageeditteam.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/pageeditteam.h Mon Jan 14 12:07:51 2013 +0100
@@ -29,6 +29,7 @@
class SquareLabel;
class KeyBinder;
+class HatButton;
class PageEditTeam : public AbstractPage
{
@@ -61,7 +62,7 @@
QToolBox *BindsBox;
QLineEdit * TeamNameEdit;
QLineEdit * HHNameEdit[HEDGEHOGS_PER_TEAM];
- QComboBox * HHHats[HEDGEHOGS_PER_TEAM];
+ HatButton * HHHats[HEDGEHOGS_PER_TEAM];
HWTeam data();
QString m_playerHash;
KeyBinder * binder;
--- a/QTfrontend/ui/page/pagemultiplayer.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/pagemultiplayer.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -36,10 +36,6 @@
gameCFG = new GameCFGWidget(this);
pageLayout->addWidget(gameCFG, 0, 0, 1, 2);
- btnSetup = new QPushButton(this);
- btnSetup->setText(QPushButton::tr("Setup"));
- pageLayout->addWidget(btnSetup, 1, 0, 1, 2);
-
pageLayout->setRowStretch(2, 1);
teamsSelect = new TeamSelWidget(this);
@@ -48,12 +44,30 @@
return pageLayout;
}
+QLayout * PageMultiplayer::footerLayoutLeftDefinition()
+{
+ QHBoxLayout * bottomLeftLayout = new QHBoxLayout();
+
+ btnSetup = addButton(":/res/Settings.png", bottomLeftLayout, 0, true);
+ btnSetup->setWhatsThis(tr("Edit game preferences"));
+
+ return bottomLeftLayout;
+}
+
QLayout * PageMultiplayer::footerLayoutDefinition()
{
QHBoxLayout * footerLayout = new QHBoxLayout();
- BtnStartMPGame = formattedButton(tr("Start"));
- BtnStartMPGame->setMinimumWidth(180);
+ const QIcon& lp = QIcon(":/res/Start.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ BtnStartMPGame = new QPushButton();
+ BtnStartMPGame->setText(tr("Start"));
+ BtnStartMPGame->setMinimumWidth(sz.width() + 60);
+ BtnStartMPGame->setIcon(lp);
+ BtnStartMPGame->setFixedHeight(50);
+ BtnStartMPGame->setIconSize(sz);
+ BtnStartMPGame->setFlat(true);
+ BtnStartMPGame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
footerLayout->addStretch();
footerLayout->addWidget(BtnStartMPGame);
--- a/QTfrontend/ui/page/pagemultiplayer.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/pagemultiplayer.h Mon Jan 14 12:07:51 2013 +0100
@@ -41,6 +41,7 @@
private:
QLayout * bodyLayoutDefinition();
QLayout * footerLayoutDefinition();
+ QLayout * footerLayoutLeftDefinition();
void connectSignals();
QPushButton * btnSetup;
--- a/QTfrontend/ui/page/pagenetgame.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/pagenetgame.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -40,24 +40,31 @@
chatWidget = new HWChatWidget(this, true);
chatWidget->setShowFollow(false); // don't show follow in nicks' context menus
chatWidget->setIgnoreListKick(true); // kick ignored players automatically
- pageLayout->addWidget(chatWidget, 2, 0, 1, 2);
- pageLayout->setRowStretch(1, 100);
- pageLayout->setRowStretch(2, 100);
+ pageLayout->addWidget(chatWidget, 1, 0, 1, 2);
+ pageLayout->setRowStretch(0, 0);
+ pageLayout->setRowStretch(1, 0);
pGameCFG = new GameCFGWidget(this);
pageLayout->addWidget(pGameCFG, 0, 0);
- btnSetup = new QPushButton(this);
- btnSetup->setText(QPushButton::tr("Setup"));
- pageLayout->addWidget(btnSetup, 1, 0);
-
pNetTeamsWidget = new TeamSelWidget(this);
pNetTeamsWidget->setAcceptOuter(true);
- pageLayout->addWidget(pNetTeamsWidget, 0, 1, 2, 1);
+ pNetTeamsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+ pageLayout->addWidget(pNetTeamsWidget, 0, 1, 1, 1);
return pageLayout;
}
+QLayout * PageNetGame::footerLayoutLeftDefinition()
+{
+ QHBoxLayout * bottomLeftLayout = new QHBoxLayout();
+
+ btnSetup = addButton(":/res/Settings.png", bottomLeftLayout, 0, true);
+ btnSetup->setWhatsThis(tr("Edit game preferences"));
+
+ return bottomLeftLayout;
+}
+
QLayout * PageNetGame::footerLayoutDefinition()
{
QHBoxLayout * bottomLayout = new QHBoxLayout;
@@ -84,7 +91,17 @@
BtnMaster = addButton(tr("Control"), bottomLayout, 3);
bottomLayout->insertStretch(3, 100);
- BtnStart = addButton(QAction::tr("Start"), bottomLayout, 3);
+ const QIcon& lp = QIcon(":/res/Start.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ BtnStart = new QPushButton();
+ BtnStart->setText(tr("Start"));
+ BtnStart->setMinimumWidth(sz.width() + 60);
+ BtnStart->setIcon(lp);
+ BtnStart->setFixedHeight(50);
+ BtnStart->setIconSize(sz);
+ BtnStart->setFlat(true);
+ BtnStart->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ bottomLayout->addWidget(BtnStart);
return bottomLayout;
}
--- a/QTfrontend/ui/page/pagenetgame.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/page/pagenetgame.h Mon Jan 14 12:07:51 2013 +0100
@@ -70,6 +70,7 @@
private:
QLayout * bodyLayoutDefinition();
QLayout * footerLayoutDefinition();
+ QLayout * footerLayoutLeftDefinition();
void connectSignals();
HistoryLineEdit * leRoomName;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/flowlayout.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,190 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ ** the names of its contributors may be used to endorse or promote
+ ** products derived from this software without specific prior written
+ ** permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+ #include <QtGui>
+
+ #include "flowlayout.h"
+
+ FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
+ : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
+ {
+ setContentsMargins(margin, margin, margin, margin);
+ }
+
+ FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
+ : m_hSpace(hSpacing), m_vSpace(vSpacing)
+ {
+ setContentsMargins(margin, margin, margin, margin);
+ }
+
+ FlowLayout::~FlowLayout()
+ {
+ QLayoutItem *item;
+ while ((item = takeAt(0)))
+ delete item;
+ }
+
+ void FlowLayout::addItem(QLayoutItem *item)
+ {
+ itemList.append(item);
+ }
+
+ int FlowLayout::horizontalSpacing() const
+ {
+ if (m_hSpace >= 0) {
+ return m_hSpace;
+ } else {
+ return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
+ }
+ }
+
+ int FlowLayout::verticalSpacing() const
+ {
+ if (m_vSpace >= 0) {
+ return m_vSpace;
+ } else {
+ return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
+ }
+ }
+
+ int FlowLayout::count() const
+ {
+ return itemList.size();
+ }
+
+ QLayoutItem *FlowLayout::itemAt(int index) const
+ {
+ return itemList.value(index);
+ }
+
+ QLayoutItem *FlowLayout::takeAt(int index)
+ {
+ if (index >= 0 && index < itemList.size())
+ return itemList.takeAt(index);
+ else
+ return 0;
+ }
+
+ Qt::Orientations FlowLayout::expandingDirections() const
+ {
+ return 0;
+ }
+
+ bool FlowLayout::hasHeightForWidth() const
+ {
+ return true;
+ }
+
+ int FlowLayout::heightForWidth(int width) const
+ {
+ int height = doLayout(QRect(0, 0, width, 0), true);
+ return height;
+ }
+
+ void FlowLayout::setGeometry(const QRect &rect)
+ {
+ QLayout::setGeometry(rect);
+ doLayout(rect, false);
+ }
+
+ QSize FlowLayout::sizeHint() const
+ {
+ return minimumSize();
+ }
+
+ QSize FlowLayout::minimumSize() const
+ {
+ QSize size;
+ QLayoutItem *item;
+ foreach (item, itemList)
+ size = size.expandedTo(item->minimumSize());
+
+ size += QSize(2*margin(), 2*margin());
+ return size;
+ }
+
+ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
+ {
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
+ int x = effectiveRect.x();
+ int y = effectiveRect.y();
+ int lineHeight = 0;
+
+ QLayoutItem *item;
+ foreach (item, itemList) {
+ QWidget *wid = item->widget();
+ int spaceX = horizontalSpacing();
+ if (spaceX == -1)
+ spaceX = wid->style()->layoutSpacing(
+ QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
+ int spaceY = verticalSpacing();
+ if (spaceY == -1)
+ spaceY = wid->style()->layoutSpacing(
+ QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
+ int nextX = x + item->sizeHint().width() + spaceX;
+ if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
+ x = effectiveRect.x();
+ y = y + lineHeight + spaceY;
+ nextX = x + item->sizeHint().width() + spaceX;
+ lineHeight = 0;
+ }
+
+ if (!testOnly)
+ item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
+
+ x = nextX;
+ lineHeight = qMax(lineHeight, item->sizeHint().height());
+ }
+ return y + lineHeight - rect.y() + bottom;
+ }
+ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
+ {
+ QObject *parent = this->parent();
+ if (!parent) {
+ return -1;
+ } else if (parent->isWidgetType()) {
+ QWidget *pw = static_cast<QWidget *>(parent);
+ return pw->style()->pixelMetric(pm, 0, pw);
+ } else {
+ return static_cast<QLayout *>(parent)->spacing();
+ }
+ }
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/flowlayout.h Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,77 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ ** the names of its contributors may be used to endorse or promote
+ ** products derived from this software without specific prior written
+ ** permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+ #ifndef FLOWLAYOUT_H
+ #define FLOWLAYOUT_H
+
+ #include <QLayout>
+ #include <QRect>
+ #include <QStyle>
+ #include <QWidgetItem>
+ class FlowLayout : public QLayout
+ {
+ public:
+ FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
+ FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
+ ~FlowLayout();
+
+ void addItem(QLayoutItem *item);
+ int horizontalSpacing() const;
+ int verticalSpacing() const;
+ Qt::Orientations expandingDirections() const;
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int count() const;
+ QLayoutItem *itemAt(int index) const;
+ QSize minimumSize() const;
+ void setGeometry(const QRect &rect);
+ QSize sizeHint() const;
+ QLayoutItem *takeAt(int index);
+
+ private:
+ int doLayout(const QRect &rect, bool testOnly) const;
+ int smartSpacing(QStyle::PixelMetric pm) const;
+
+ QList<QLayoutItem *> itemList;
+ int m_hSpace;
+ int m_vSpace;
+ };
+
+ #endif
\ No newline at end of file
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -25,6 +25,8 @@
#include <QMessageBox>
#include <QTableView>
#include <QPushButton>
+#include <QDebug>
+#include <QList>
#include "gamecfgwidget.h"
#include "igbox.h"
@@ -33,6 +35,7 @@
#include "ammoSchemeModel.h"
#include "proto.h"
#include "GameStyleModel.h"
+#include "themeprompt.h"
GameCFGWidget::GameCFGWidget(QWidget* parent) :
QGroupBox(parent)
@@ -40,13 +43,16 @@
, seedRegexp("\\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\}")
{
mainLayout.setMargin(0);
-// mainLayout.setSizeConstraint(QLayout::SetMinimumSize);
pMapContainer = new HWMapContainer(this);
- mainLayout.addWidget(pMapContainer, 0, 0);
+ mainLayout.addWidget(pMapContainer, 0, 0, Qt::AlignHCenter | Qt::AlignTop);
+ pMapContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ pMapContainer->setFixedSize(460, 275);
IconedGroupBox *GBoxOptions = new IconedGroupBox(this);
- GBoxOptions->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ m_childWidgets << GBoxOptions;
+ GBoxOptions->setFixedWidth(pMapContainer->width());
+ GBoxOptions->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
mainLayout.addWidget(GBoxOptions, 1, 0);
QGridLayout *GBoxOptionsLayout = new QGridLayout(GBoxOptions);
@@ -174,7 +180,7 @@
if (schemeData(18).toBool())
result |= 0x00080000; // ai survival
if (schemeData(19).toBool())
- result |= 0x00100000; // infinite attacks
+ result |= 0x00100000; // infinite attacks
if (schemeData(20).toBool())
result |= 0x00200000; // reset weaps
if (schemeData(21).toBool())
@@ -186,7 +192,7 @@
if (schemeData(24).toBool())
result |= 0x02000000; // tag team
if (schemeData(25).toBool())
- result |= 0x04000000; // bottom border
+ result |= 0x04000000; // bottom
return result;
}
@@ -235,6 +241,8 @@
bcfg << QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()).toUtf8();
bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8();
+
+
switch (mapgen)
{
case MAPGEN_MAZE:
@@ -271,7 +279,7 @@
bool illegal = ammo.size() != cDefaultAmmoStore->size();
if (illegal)
{
- QMessageBox illegalMsg(this);
+ QMessageBox illegalMsg(parentWidget());
illegalMsg.setIcon(QMessageBox::Warning);
illegalMsg.setWindowTitle(QMessageBox::tr("Error"));
illegalMsg.setText(QMessageBox::tr("Cannot use the ammo '%1'!").arg(name));
@@ -325,10 +333,6 @@
if (param == "SEED")
{
pMapContainer->setSeed(value);
- if (!seedRegexp.exactMatch(value))
- {
- pMapContainer->seedEdit->setVisible(true);
- }
return;
}
if (param == "THEME")
@@ -377,8 +381,6 @@
if (param == "FULLMAPCONFIG")
{
QString seed = slValue[3];
- if (!seedRegexp.exactMatch(seed))
- pMapContainer->seedEdit->setVisible(true);
pMapContainer->setAllMapParameters(
slValue[0],
@@ -586,3 +588,19 @@
Scripts->setCurrentIndex(0);
}
}
+
+bool GameCFGWidget::isMaster()
+{
+ return m_master;
+}
+
+void GameCFGWidget::setMaster(bool master)
+{
+ if (master == m_master) return;
+ m_master = master;
+
+ pMapContainer->setMaster(master);
+
+ foreach (QWidget *widget, m_childWidgets)
+ widget->setEnabled(master);
+}
--- a/QTfrontend/ui/widget/gamecfgwidget.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/widget/gamecfgwidget.h Mon Jan 14 12:07:51 2013 +0100
@@ -36,6 +36,8 @@
{
Q_OBJECT
+ Q_PROPERTY(bool master READ isMaster WRITE setMaster)
+
public:
GameCFGWidget(QWidget* parent);
quint32 getGameFlags() const;
@@ -47,11 +49,13 @@
HWMapContainer* pMapContainer;
QTableView * tv;
QVariant schemeData(int column) const;
+ bool isMaster();
public slots:
void setParam(const QString & param, const QStringList & value);
void fullNetConfig();
void resendSchemeData();
+ void setMaster(bool master);
signals:
void paramChanged(const QString & param, const QStringList & value);
@@ -81,6 +85,8 @@
QString curNetAmmo;
QRegExp seedRegexp;
QString m_curScript;
+ bool m_master;
+ QList<QWidget *> m_childWidgets;
void setNetAmmo(const QString& name, const QString& ammo);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatbutton.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,72 @@
+/*
+ * 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 <QDebug>
+
+#include "hatprompt.h"
+#include "DataManager.h"
+#include "HatModel.h"
+#include "hatbutton.h"
+
+HatButton::HatButton(QWidget* parent) : QPushButton(parent)
+{
+ setIconSize(QSize(32, 37));
+ setFixedSize(44, 44);
+
+ m_hatModel = DataManager::instance().hatModel();
+ connect(this, SIGNAL(clicked()), this, SLOT(showPrompt()));
+
+ setCurrentIndex(0);
+}
+
+void HatButton::setCurrentIndex(int index)
+{
+ m_hat = m_hatModel->index(index, 0);
+ setWhatsThis(QString(tr("Change hat (%1)")).arg(m_hat.data(Qt::DisplayRole).toString()));
+ setToolTip(m_hat.data(Qt::DisplayRole).toString());
+ setIcon(m_hat.data(Qt::DecorationRole).value<QIcon>());
+}
+
+int HatButton::currentIndex()
+{
+ return m_hat.row();
+}
+
+void HatButton::setCurrentHat(const QString & name)
+{
+ QList<QStandardItem *> hats = m_hatModel->findItems(name);
+
+ if (hats.count() > 0)
+ setCurrentIndex(hats[0]->row());
+}
+
+QString HatButton::currentHat() const
+{
+ return m_hat.data(Qt::DisplayRole).toString();
+}
+
+void HatButton::showPrompt()
+{
+ HatPrompt prompt(currentIndex(), this);
+ int hatID = prompt.exec() - 1; // Since 0 means canceled, so all indexes are +1'd
+ if (hatID < 0) return;
+
+ setCurrentIndex(hatID);
+ emit currentIndexChanged(hatID);
+ emit currentHatChanged(currentHat());
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatbutton.h Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,55 @@
+/*
+ * 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 HATBUTTON_H
+#define HATBUTTON_H
+
+#include <QPushButton>
+#include <QString>
+#include <QModelIndex>
+
+class HatModel;
+
+class HatButton : public QPushButton
+{
+ Q_OBJECT
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex)
+ Q_PROPERTY(QString currentHat READ currentHat WRITE setCurrentHat)
+
+ public:
+ HatButton(QWidget* parent);
+ int currentIndex();
+ QString currentHat() const;
+
+ private:
+ QModelIndex m_hat;
+ HatModel * m_hatModel;
+
+ signals:
+ void currentIndexChanged(int);
+ void currentHatChanged(const QString &);
+
+ public slots:
+ void setCurrentIndex(int index);
+ void setCurrentHat(const QString & name);
+
+ private slots:
+ void showPrompt();
+};
+
+#endif // HATBUTTON_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatprompt.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,169 @@
+/*
+ * 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 <QDialog>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QToolButton>
+#include <QWidgetItem>
+#include <QModelIndex>
+#include <QListView>
+#include <QLineEdit>
+#include <QLabel>
+#include <QSortFilterProxyModel>
+#include <QDebug>
+
+#include "DataManager.h"
+#include "lineeditcursor.h"
+#include "HatModel.h"
+#include "hatprompt.h"
+
+HatPrompt::HatPrompt(int currentIndex, QWidget* parent) : QDialog(parent)
+{
+ setModal(true);
+ setWindowFlags(Qt::Sheet);
+ setWindowModality(Qt::WindowModal);
+ setMinimumSize(550, 430);
+ resize(550, 430);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ setStyleSheet("QPushButton { padding: 5px; margin-top: 10px; }");
+
+ // Hat model, and a model for setting a filter
+ HatModel * hatModel = DataManager::instance().hatModel();
+ filterModel = new QSortFilterProxyModel();
+ filterModel->setSourceModel(hatModel);
+ filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+
+ // Grid
+ QGridLayout * dialogLayout = new QGridLayout(this);
+ dialogLayout->setSpacing(0);
+ dialogLayout->setColumnStretch(1, 1);
+
+ QHBoxLayout * topLayout = new QHBoxLayout();
+
+ // Help/prompt message at top
+ QLabel * lblDesc = new QLabel(tr("Select a hat"));
+ lblDesc->setObjectName("lblDesc");
+ lblDesc->setStyleSheet("#lblDesc { color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-top-left-radius: 10px; padding: 4px 10px;}");
+ lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ lblDesc->setFixedHeight(24);
+ lblDesc->setMinimumWidth(0);
+
+ // Filter text box
+ QWidget * filterContainer = new QWidget();
+ filterContainer->setFixedHeight(24);
+ filterContainer->setObjectName("filterContainer");
+ filterContainer->setStyleSheet("#filterContainer { background: #F6CB1C; border-top-right-radius: 10px; padding: 3px; }");
+ filterContainer->setFixedWidth(250);
+ txtFilter = new LineEditCursor(filterContainer);
+ txtFilter->setFixedWidth(250);
+ txtFilter->setFocus();
+ txtFilter->setFixedHeight(22);
+ connect(txtFilter, SIGNAL(textChanged(const QString &)), this, SLOT(filterChanged(const QString &)));
+ connect(txtFilter, SIGNAL(moveUp()), this, SLOT(moveUp()));
+ connect(txtFilter, SIGNAL(moveDown()), this, SLOT(moveDown()));
+ connect(txtFilter, SIGNAL(moveLeft()), this, SLOT(moveLeft()));
+ connect(txtFilter, SIGNAL(moveRight()), this, SLOT(moveRight()));
+
+ // Filter label
+ QLabel * lblFilter = new QLabel(tr("Filter: "), txtFilter);
+ lblFilter->setStyleSheet(QString("background: none; margin-left: -%1px; margin-top: 4px;").arg(lblFilter->width() / 2 - 3));
+ txtFilter->setStyleSheet(QString("border-width: 0px; background-color: rgb(13, 5, 68); border-radius: 6px; margin-top: 3px; margin-right: 3px; padding-left: %1px; padding-bottom: 2px;").arg(lblFilter->width() / 2));
+
+ // Corner widget
+ QLabel * corner = new QLabel();
+ corner->setPixmap(QPixmap(QString::fromUtf8(":/res/inverse-corner-bl.png")));
+ corner->setFixedSize(10, 10);
+
+ // Add widgets to top layout
+ topLayout->addWidget(lblDesc);
+ topLayout->addWidget(filterContainer);
+ topLayout->addWidget(corner, 0, Qt::AlignBottom);
+ topLayout->addStretch(1);
+
+ // Cancel button (closes dialog)
+ QPushButton * btnCancel = new QPushButton(tr("Cancel"));
+ connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+
+ // Select button
+ QPushButton * btnSelect = new QPushButton(tr("Use selected hat"));
+ btnSelect->setDefault(true);
+ connect(btnSelect, SIGNAL(clicked()), this, SLOT(onAccepted()));
+
+ // Add hats
+ list = new HatListView();
+ list->setModel(filterModel);
+ list->setViewMode(QListView::IconMode);
+ list->setResizeMode(QListView::Adjust);
+ list->setMovement(QListView::Static);
+ list->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ list->setSpacing(8);
+ list->setWordWrap(true);
+ list->setSelectionMode(QAbstractItemView::SingleSelection);
+ list->setObjectName("hatList");
+ list->setCurrentIndex(filterModel->index(currentIndex, 0));
+ connect(list, SIGNAL(activated(const QModelIndex &)), this, SLOT(hatChosen(const QModelIndex &)));
+ connect(list, SIGNAL(clicked(const QModelIndex &)), this, SLOT(hatChosen(const QModelIndex &)));
+
+ // Add elements to layouts
+ dialogLayout->addLayout(topLayout, 0, 0, 1, 3);
+ dialogLayout->addWidget(list, 1, 0, 1, 3);
+ dialogLayout->addWidget(btnCancel, 2, 0, 1, 1, Qt::AlignLeft);
+ dialogLayout->addWidget(btnSelect, 2, 2, 1, 1, Qt::AlignRight);
+}
+
+void HatPrompt::moveUp()
+{
+ list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier));
+}
+
+void HatPrompt::moveDown()
+{
+ list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier));
+}
+
+void HatPrompt::moveLeft()
+{
+ list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveLeft, Qt::NoModifier));
+}
+
+void HatPrompt::moveRight()
+{
+ list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveRight, Qt::NoModifier));
+}
+
+void HatPrompt::onAccepted()
+{
+ hatChosen(list->currentIndex());
+}
+
+// When a hat is selected
+void HatPrompt::hatChosen(const QModelIndex & index)
+{
+ done(filterModel->mapToSource(index).row() + 1); // Since returning 0 means canceled
+}
+
+// When the text in the filter text box is changed
+void HatPrompt::filterChanged(const QString & text)
+{
+ filterModel->setFilterFixedString(text);
+ list->setCurrentIndex(filterModel->index(0, 0));
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatprompt.h Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,61 @@
+/*
+ * 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 HATPROMPT_H
+#define HATPROMPT_H
+
+#include <QWidget>
+#include <QDialog>
+#include <QListView>
+
+class QLineEdit;
+class QModelIndex;
+class QSortFilterProxyModel;
+class LineEditCursor;
+
+class HatListView : public QListView
+{
+ friend class HatPrompt;
+
+ public:
+ HatListView(QWidget* parent = 0) {};
+};
+
+class HatPrompt : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ HatPrompt(int currentIndex = 0, QWidget* parent = 0);
+
+ private:
+ LineEditCursor * txtFilter;
+ HatListView * list;
+ QSortFilterProxyModel * filterModel;
+
+ private slots:
+ void onAccepted();
+ void hatChosen(const QModelIndex & index);
+ void filterChanged(const QString & text);
+ void moveUp();
+ void moveDown();
+ void moveLeft();
+ void moveRight();
+};
+
+#endif // HATPROMPT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/lineeditcursor.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,35 @@
+/*
+ * 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 <QKeyEvent>
+
+#include "lineeditcursor.h"
+
+void LineEditCursor::keyPressEvent(QKeyEvent * event)
+{
+ if (event->key() == Qt::Key_Up)
+ emit moveUp();
+ else if (event->key() == Qt::Key_Down)
+ emit moveDown();
+ else if (event->key() == Qt::Key_Left)
+ emit moveLeft();
+ else if (event->key() == Qt::Key_Right)
+ emit moveRight();
+ else
+ QLineEdit::keyPressEvent(event);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/lineeditcursor.h Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * 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 LINEEDITCURSOR_H
+#define LINEEDITCURSOR_H
+
+#include <QLineEdit>
+
+class LineEditCursor : public QLineEdit
+{
+ Q_OBJECT
+
+ public:
+ LineEditCursor(QWidget* parent = 0) : QLineEdit(parent) {};
+
+ signals:
+ void moveUp();
+ void moveDown();
+ void moveLeft();
+ void moveRight();
+
+ private:
+ void keyPressEvent(QKeyEvent * event);
+};
+
+#endif // LINEEDITCURSOR_H
\ No newline at end of file
--- a/QTfrontend/ui/widget/mapContainer.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -30,13 +30,24 @@
#include <QIcon>
#include <QLineEdit>
#include <QStringListModel>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QDebug>
+#include <QFile>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QMessageBox>
#include "hwconsts.h"
#include "mapContainer.h"
+#include "themeprompt.h"
+#include "seedprompt.h"
#include "igbox.h"
#include "HWApplication.h"
#include "ThemeModel.h"
+
+
HWMapContainer::HWMapContainer(QWidget * parent) :
QWidget(parent),
mainLayout(this),
@@ -47,6 +58,7 @@
hhSmall.load(":/res/hh_small.png");
hhLimit = 18;
templateFilter = 0;
+ m_master = true;
linearGrad = QLinearGradient(QPoint(128, 0), QPoint(128, 128));
linearGrad.setColorAt(1, QColor(0, 0, 192));
@@ -57,135 +69,192 @@
HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
HWApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
- QWidget* mapWidget = new QWidget(this);
- mainLayout.addWidget(mapWidget, 0, 0, Qt::AlignHCenter);
-
- QGridLayout* mapLayout = new QGridLayout(mapWidget);
- mapLayout->setMargin(0);
+ m_staticMapModel = DataManager::instance().staticMapModel();
+ m_missionMapModel = DataManager::instance().missionMapModel();
+ m_themeModel = DataManager::instance().themeModel();
- imageButt = new QPushButton(mapWidget);
- imageButt->setObjectName("imageButt");
- imageButt->setFixedSize(256 + 6, 128 + 6);
- imageButt->setFlat(true);
- imageButt->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);//QSizePolicy::Minimum, QSizePolicy::Minimum);
- mapLayout->addWidget(imageButt, 0, 0, 1, 2);
- connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomMap()));
+ /* Layouts */
- chooseMap = new QComboBox(mapWidget);
- chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- m_mapModel = DataManager::instance().mapModel();
- chooseMap->setEditable(false);
- chooseMap->setModel(m_mapModel);
+ QHBoxLayout * typeLayout = new QHBoxLayout();
+ QHBoxLayout * seedLayout = new QHBoxLayout();
+ QHBoxLayout * twoColumnLayout = new QHBoxLayout();
+ QVBoxLayout * leftLayout = new QVBoxLayout();
+ QVBoxLayout * rightLayout = new QVBoxLayout();
+ twoColumnLayout->addLayout(leftLayout, 0);
+ twoColumnLayout->addStretch(1);
+ twoColumnLayout->addLayout(rightLayout, 0);
+ QVBoxLayout * drawnControls = new QVBoxLayout();
+ leftLayout->addLayout(typeLayout, 0);
+ rightLayout->addLayout(seedLayout, 0);
+
+ /* Map type combobox */
- mapLayout->addWidget(chooseMap, 1, 1);
+ typeLayout->setSpacing(10);
+ typeLayout->addWidget(new QLabel(tr("Map type:")), 0);
+ cType = new QComboBox(this);
+ typeLayout->addWidget(cType, 1);
+ cType->insertItem(0, tr("Image map"), MapModel::StaticMap);
+ cType->insertItem(1, tr("Mission map"), MapModel::MissionMap);
+ cType->insertItem(2, tr("Hand-drawn"), MapModel::HandDrawnMap);
+ cType->insertItem(3, tr("Randomly generated"), MapModel::GeneratedMap);
+ cType->insertItem(4, tr("Random maze"), MapModel::GeneratedMaze);
+ connect(cType, SIGNAL(currentIndexChanged(int)), this, SLOT(mapTypeChanged(int)));
+ m_childWidgets << cType;
- QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
- mapLayout->addWidget(lblMap, 1, 0);
-
- lblFilter = new QLabel(tr("Filter"), mapWidget);
- mapLayout->addWidget(lblFilter, 2, 0);
+ /* Randomize button */
- cbTemplateFilter = new QComboBox(mapWidget);
- cbTemplateFilter->addItem(tr("All"), 0);
- cbTemplateFilter->addItem(tr("Small"), 1);
- cbTemplateFilter->addItem(tr("Medium"), 2);
- cbTemplateFilter->addItem(tr("Large"), 3);
- cbTemplateFilter->addItem(tr("Cavern"), 4);
- cbTemplateFilter->addItem(tr("Wacky"), 5);
- mapLayout->addWidget(cbTemplateFilter, 2, 1);
+ seedLayout->addStretch(1);
+ const QIcon& lp = QIcon(":/res/dice.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ btnRandomize = new QPushButton();
+ btnRandomize->setText(tr("Random"));
+ btnRandomize->setIcon(lp);
+ btnRandomize->setFixedHeight(30);
+ btnRandomize->setIconSize(sz);
+ btnRandomize->setFlat(true);
+ btnRandomize->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ connect(btnRandomize, SIGNAL(clicked()), this, SLOT(setRandomMap()));
+ m_childWidgets << btnRandomize;
+ btnRandomize->setStyleSheet("padding: 5px;");
+ btnRandomize->setFixedHeight(cType->height());
+ seedLayout->addWidget(btnRandomize, 1);
- connect(cbTemplateFilter, SIGNAL(activated(int)), this, SLOT(setTemplateFilter(int)));
+ /* Seed button */
+ btnSeed = new QPushButton(parentWidget()->parentWidget());
+ btnSeed->setText(tr("Seed"));
+ btnSeed->setStyleSheet("padding: 5px;");
+ btnSeed->setFixedHeight(cType->height());
+ connect(btnSeed, SIGNAL(clicked()), this, SLOT(showSeedPrompt()));
+ seedLayout->addWidget(btnSeed, 0);
- maze_size_label = new QLabel(tr("Type"), mapWidget);
- mapLayout->addWidget(maze_size_label, 2, 0);
- maze_size_label->hide();
- cbMazeSize = new QComboBox(mapWidget);
- cbMazeSize->addItem(tr("Small tunnels"), 0);
- cbMazeSize->addItem(tr("Medium tunnels"), 1);
- cbMazeSize->addItem(tr("Large tunnels"), 2);
- cbMazeSize->addItem(tr("Small floating islands"), 3);
- cbMazeSize->addItem(tr("Medium floating islands"), 4);
- cbMazeSize->addItem(tr("Large floating islands"), 5);
- cbMazeSize->setCurrentIndex(1);
+ /* Map preview label */
+
+ QLabel * lblMapPreviewText = new QLabel(this);
+ lblMapPreviewText->setText(tr("Map preview:"));
+ leftLayout->addWidget(lblMapPreviewText, 0, Qt::AlignLeft);
+
+ /* Map Preview */
- mapLayout->addWidget(cbMazeSize, 2, 1);
- cbMazeSize->hide();
- connect(cbMazeSize, SIGNAL(activated(int)), this, SLOT(setMazeSize(int)));
+ mapPreview = new QLabel(this);
+ mapPreview->setObjectName("mapPreview");
+ mapPreview->setFixedSize(256, 128);
+ leftLayout->addWidget(mapPreview, 0);
+
+ /* Bottom-Left layout */
- gbThemes = new IconedGroupBox(mapWidget);
- gbThemes->setTitleTextPadding(80);
- gbThemes->setContentTopPadding(15);
- gbThemes->setTitle(tr("Themes"));
+ QVBoxLayout * bottomLeftLayout = new QVBoxLayout();
+ leftLayout->addLayout(bottomLeftLayout, 1);
+
+ /* Map list label */
+
+ lblMapList = new QLabel();
+ rightLayout->addWidget(lblMapList, 0);
+
+ /* Static maps list */
- //gbThemes->setStyleSheet("padding: 0px"); // doesn't work - stylesheet is set with icon
- mapLayout->addWidget(gbThemes, 0, 2, 3, 1);
- // disallow row to be collapsed (so it can't get ignored when Qt applies rowSpan of gbThemes)
- mapLayout->setRowMinimumHeight(2, 13);
- QVBoxLayout * gbTLayout = new QVBoxLayout(gbThemes);
- gbTLayout->setContentsMargins(0, 0, 0 ,0);
- gbTLayout->setSpacing(0);
- lvThemes = new QListView(mapWidget);
- lvThemes->setMinimumHeight(30);
- lvThemes->setFixedWidth(140);
- m_themeModel = DataManager::instance().themeModel();
- lvThemes->setModel(m_themeModel);
- lvThemes->setIconSize(QSize(16, 16));
- lvThemes->setEditTriggers(QListView::NoEditTriggers);
+ staticMapList = new QListView;
+ staticMapList->setModel(m_staticMapModel);
+ rightLayout->addWidget(staticMapList, 1);
+ staticMapList->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_childWidgets << staticMapList;
+ QItemSelectionModel * staticSelectionModel = staticMapList->selectionModel();
+ connect(staticSelectionModel,
+ SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
+ this,
+ SLOT(staticMapChanged(const QModelIndex &, const QModelIndex &)));
- connect(lvThemes->selectionModel(), SIGNAL(currentRowChanged( const QModelIndex &, const QModelIndex &)), this, SLOT(themeSelected( const QModelIndex &, const QModelIndex &)));
+ /* Mission maps list */
- // override default style to tighten up theme scroller
- lvThemes->setStyleSheet(QString(
- "QListView{"
- "border: solid;"
- "border-width: 0px;"
- "border-radius: 0px;"
- "border-color: transparent;"
- "background-color: #0d0544;"
- "color: #ffcc00;"
- "font: bold 13px;"
- "}"
- )
- );
+ missionMapList = new QListView;
+ missionMapList->setModel(m_missionMapModel);
+ missionMapList->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ rightLayout->addWidget(missionMapList, 1);
+ m_childWidgets << missionMapList;
+ QItemSelectionModel * missionSelectionModel = missionMapList->selectionModel();
+ connect(missionSelectionModel,
+ SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
+ this,
+ SLOT(missionMapChanged(const QModelIndex &, const QModelIndex &)));
+
+ /* Map load and edit buttons */
+
+ drawnControls->addStretch(1);
- gbTLayout->addWidget(lvThemes);
- lvThemes->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
+ btnLoadMap = new QPushButton(tr("Load map drawing"));
+ btnLoadMap->setStyleSheet("padding: 20px;");
+ drawnControls->addWidget(btnLoadMap, 0);
+ m_childWidgets << btnLoadMap;
+ connect(btnLoadMap, SIGNAL(clicked()), this, SLOT(loadDrawing()));
+
+ btnEditMap = new QPushButton(tr("Edit map drawing"));
+ btnEditMap->setStyleSheet("padding: 20px;");
+ drawnControls->addWidget(btnEditMap, 0);
+ m_childWidgets << btnEditMap;
+ connect(btnEditMap, SIGNAL(clicked()), this, SIGNAL(drawMapRequested()));
+
+ drawnControls->addStretch(1);
+
+ rightLayout->addLayout(drawnControls);
+
+ /* Generator style list */
- mapLayout->setSizeConstraint(QLayout::SetFixedSize);
+ generationStyles = new QListWidget();
+ new QListWidgetItem(tr("All"), generationStyles);
+ new QListWidgetItem(tr("Small"), generationStyles);
+ new QListWidgetItem(tr("Medium"), generationStyles);
+ new QListWidgetItem(tr("Large"), generationStyles);
+ new QListWidgetItem(tr("Cavern"), generationStyles);
+ new QListWidgetItem(tr("Wacky"), generationStyles);
+ connect(generationStyles, SIGNAL(currentRowChanged(int)), this, SLOT(setTemplateFilter(int)));
+ m_childWidgets << generationStyles;
+ rightLayout->addWidget(generationStyles, 1);
+
+ /* Maze style list */
- QWidget* seedWidget = new QWidget(this);
- mainLayout.addWidget(seedWidget, 1, 0);
+ mazeStyles = new QListWidget();
+ new QListWidgetItem(tr("Small tunnels"), mazeStyles);
+ new QListWidgetItem(tr("Medium tunnels"), mazeStyles);
+ new QListWidgetItem(tr("Largetunnels"), mazeStyles);
+ new QListWidgetItem(tr("Small islands"), mazeStyles);
+ new QListWidgetItem(tr("Medium islands"), mazeStyles);
+ new QListWidgetItem(tr("Large islands"), mazeStyles);
+ connect(mazeStyles, SIGNAL(currentRowChanged(int)), this, SLOT(setMazeSize(int)));
+ m_childWidgets << mazeStyles;
+ rightLayout->addWidget(mazeStyles, 1);
- QGridLayout* seedLayout = new QGridLayout(seedWidget);
- seedLayout->setMargin(0);
+ /* Mission description */
- seedLabel = new QLabel(tr("Seed"), seedWidget);
- seedLayout->addWidget(seedLabel, 3, 0);
- seedEdit = new QLineEdit(seedWidget);
- seedEdit->setMaxLength(54);
- connect(seedEdit, SIGNAL(returnPressed()), this, SLOT(seedEdited()));
- seedLayout->addWidget(seedEdit, 3, 1);
- seedLayout->setColumnStretch(1, 5);
- seedSet = new QPushButton(seedWidget);
- seedSet->setText(QPushButton::tr("more"));
- connect(seedSet, SIGNAL(clicked()), this, SLOT(seedEdited()));
- seedLayout->setColumnStretch(2, 1);
- seedLayout->addWidget(seedSet, 3, 2);
+ lblDesc = new QLabel();
+ lblDesc->setWordWrap(true);
+ lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ lblDesc->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ bottomLeftLayout->addWidget(lblDesc, 100);
+
+ /* Spacing above theme chooser */
+
+ bottomLeftLayout->addStretch(1);
+
+ /* Theme chooser */
- seedLabel->setVisible(false);
- seedEdit->setVisible(false);
+ btnTheme = new QPushButton();
+ connect(btnTheme, SIGNAL(clicked()), this, SLOT(showThemePrompt()));
+ m_childWidgets << btnTheme;
+ bottomLeftLayout->addWidget(btnTheme, 1);
- setRandomSeed();
- setRandomTheme();
+ /* Add everything to main layout */
+
+ mainLayout.addLayout(twoColumnLayout, 0);
- chooseMap->setCurrentIndex(0);
- mapChanged(0);
- // use signal "activated" rather than currentIndexChanged
- // because index is somtimes changed a few times in a row programmatically
- connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
+ /* Set defaults */
- // update model views after model changes (to e.g. re-adjust separators)
- connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
+ setRandomTheme();
+ setRandomSeed();
+ setMazeSize(0);
+ setTemplateFilter(0);
+ staticMapChanged(m_staticMapModel->index(0, 0));
+ missionMapChanged(m_missionMapModel->index(0, 0));
+ updateTheme(m_themeModel->index(0, 0));
+ mapTypeChanged(0);
}
void HWMapContainer::setImage(const QImage newImage)
@@ -202,8 +271,9 @@
p.drawPixmap(QPoint(0, 0), px);
addInfoToPreview(pxres);
- //chooseMap->setCurrentIndex(mapgen);
pMap = 0;
+
+ cType->setEnabled(isMaster());
}
void HWMapContainer::setHHLimit(int newHHLimit)
@@ -211,70 +281,6 @@
hhLimit = newHHLimit;
}
-void HWMapContainer::mapChanged(int index)
-{
- if (chooseMap->currentIndex() != index)
- chooseMap->setCurrentIndex(index);
-
- if (index < 0)
- {
- m_mapInfo.type = MapModel::Invalid;
- updatePreview();
- return;
- }
-
- Q_ASSERT(chooseMap->itemData(index, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
- m_mapInfo = chooseMap->itemData(index, Qt::UserRole + 1).value<MapModel::MapInfo>();
- m_curMap = m_mapInfo.name;
-
- switch(m_mapInfo.type)
- {
- case MapModel::GeneratedMap:
- mapgen = MAPGEN_REGULAR;
- gbThemes->show();
- lblFilter->show();
- cbTemplateFilter->show();
- maze_size_label->hide();
- cbMazeSize->hide();
- break;
- case MapModel::GeneratedMaze:
- mapgen = MAPGEN_MAZE;
- gbThemes->show();
- lblFilter->hide();
- cbTemplateFilter->hide();
- maze_size_label->show();
- cbMazeSize->show();
- break;
- case MapModel::HandDrawnMap:
- mapgen = MAPGEN_DRAWN;
- gbThemes->show();
- lblFilter->hide();
- cbTemplateFilter->hide();
- maze_size_label->hide();
- cbMazeSize->hide();
- break;
- default:
- mapgen = MAPGEN_MAP;
- gbThemes->hide();
- lblFilter->hide();
- cbTemplateFilter->hide();
- maze_size_label->hide();
- cbMazeSize->hide();
- m_theme = m_mapInfo.theme;
- }
-
- // the map has no pre-defined theme, so let's use the selected one
- if (m_mapInfo.theme.isEmpty())
- {
- m_theme = lvThemes->currentIndex().data().toString();
- emit themeChanged(m_theme);
- }
-
- updatePreview();
- emit mapChanged(m_curMap);
- emit mapgenChanged(mapgen);
-}
-
// Should this add text to identify map size?
void HWMapContainer::addInfoToPreview(QPixmap image)
{
@@ -292,8 +298,7 @@
p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text);
p.drawPixmap(image.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall);
- imageButt->setIcon(finalImage);
- imageButt->setIconSize(image.size());
+ mapPreview->setPixmap(finalImage);
}
void HWMapContainer::askForGeneratedPreview()
@@ -322,14 +327,8 @@
p.drawPixmap(QPoint(x, y), waitIcon);
addInfoToPreview(waitImage);
-}
-void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
-{
- m_theme = current.data().toString();
-
- gbThemes->setIcon(qVariantValue<QIcon>(current.data(Qt::UserRole)));
- emit themeChanged(m_theme);
+ cType->setEnabled(false);
}
QString HWMapContainer::getCurrentSeed() const
@@ -339,8 +338,14 @@
QString HWMapContainer::getCurrentMap() const
{
- if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
- return(m_curMap);
+ switch (m_mapInfo.type)
+ {
+ case MapModel::StaticMap:
+ case MapModel::MissionMap:
+ return m_curMap;
+ default:
+ return QString();
+ }
}
QString HWMapContainer::getCurrentTheme() const
@@ -370,20 +375,17 @@
quint32 HWMapContainer::getTemplateFilter() const
{
- return cbTemplateFilter->itemData(cbTemplateFilter->currentIndex()).toInt();
+ return generationStyles->currentRow();
}
void HWMapContainer::resizeEvent ( QResizeEvent * event )
{
Q_UNUSED(event);
- //imageButt->setIconSize(imageButt->size());
}
void HWMapContainer::intSetSeed(const QString & seed)
{
m_seed = seed;
- if (seed != seedEdit->text())
- seedEdit->setText(seed);
}
void HWMapContainer::setSeed(const QString & seed)
@@ -395,11 +397,29 @@
void HWMapContainer::intSetMap(const QString & map)
{
- m_curMap = map;
-
- int id = m_mapModel->indexOf(map);
-
- mapChanged(id);
+ if (map == "+rnd+")
+ {
+ changeMapType(MapModel::GeneratedMap);
+ }
+ else if (map == "+maze+")
+ {
+ changeMapType(MapModel::GeneratedMaze);
+ }
+ else if (map == "+drawn+")
+ {
+ changeMapType(MapModel::HandDrawnMap);
+ }
+ else if (m_staticMapModel->mapExists(map))
+ {
+ changeMapType(MapModel::StaticMap, m_staticMapModel->index(m_staticMapModel->findMap(map), 0));
+ }
+ else if (m_missionMapModel->mapExists(map))
+ {
+ changeMapType(MapModel::MissionMap, m_missionMapModel->index(m_missionMapModel->findMap(map), 0));
+ } else
+ {
+ qDebug() << "HWMapContainer::intSetMap: Map doesn't exist: " << map;
+ }
}
void HWMapContainer::setMap(const QString & map)
@@ -413,13 +433,11 @@
QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, theme);
if(mdl.size())
- lvThemes->setCurrentIndex(mdl.at(0));
+ updateTheme(mdl.at(0));
}
void HWMapContainer::setRandomMap()
{
- int idx;
-
setRandomSeed();
switch(m_mapInfo.type)
{
@@ -427,17 +445,14 @@
case MapModel::GeneratedMaze:
setRandomTheme();
break;
- case MapModel::HandDrawnMap:
- emit drawMapRequested();
+ case MapModel::MissionMap:
+ missionMapChanged(m_missionMapModel->index(rand() % m_missionMapModel->rowCount(), 0));
break;
- case MapModel::MissionMap:
case MapModel::StaticMap:
- // get random map of same type
- idx = m_mapModel->randomMap(m_mapInfo.type);
- mapChanged(idx);
+ staticMapChanged(m_staticMapModel->index(rand() % m_staticMapModel->rowCount(), 0));
break;
- case MapModel::Invalid:
- mapChanged(0);
+ default:
+ break;
}
}
@@ -452,12 +467,12 @@
{
if(!m_themeModel->rowCount()) return;
quint32 themeNum = rand() % m_themeModel->rowCount();
- lvThemes->setCurrentIndex(m_themeModel->index(themeNum));
+ updateTheme(m_themeModel->index(themeNum));
}
void HWMapContainer::intSetTemplateFilter(int filter)
{
- cbTemplateFilter->setCurrentIndex(filter);
+ generationStyles->setCurrentRow(filter);
emit newTemplateFilter(filter);
}
@@ -475,12 +490,12 @@
int HWMapContainer::getMazeSize(void) const
{
- return cbMazeSize->currentIndex();
+ return mazeStyles->currentRow();
}
void HWMapContainer::intSetMazeSize(int size)
{
- cbMazeSize->setCurrentIndex(size);
+ mazeStyles->setCurrentRow(size);
emit mazeSizeChanged(size);
}
@@ -521,9 +536,6 @@
break;
}
- if(m != MAPGEN_MAP)
- chooseMap->setCurrentIndex(m);
-
emit mapgenChanged(m);
}
}
@@ -546,23 +558,10 @@
return drawMapScene.encode();
}
-void HWMapContainer::seedEdited()
+void HWMapContainer::setNewSeed(const QString & newSeed)
{
- if (seedLabel->isVisible() == false )
- {
- seedLabel->setVisible(true);
- seedEdit->setVisible(true);
- seedSet->setText(tr("Set"));
- return;
- }
-
- if (seedEdit->text().isEmpty())
- seedEdit->setText(m_seed);
- else
- {
- setSeed(seedEdit->text());
- emit seedChanged(seedEdit->text());
- }
+ setSeed(newSeed);
+ emit seedChanged(newSeed);
}
DrawMapScene * HWMapContainer::getDrawMapScene()
@@ -592,8 +591,7 @@
{
case MapModel::Invalid:
failIcon = QPixmap(":/res/btnDisabled.png");
- imageButt->setIcon(failIcon);
- imageButt->setIconSize(failIcon.size());
+ mapPreview->setPixmap(failIcon);
break;
case MapModel::GeneratedMap:
askForGeneratedPreview();
@@ -610,7 +608,7 @@
if(!success)
{
- imageButt->setIcon(QIcon());
+ mapPreview->setPixmap(QPixmap());
return;
}
@@ -638,13 +636,13 @@
{
QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, m_theme);
if (mdl.size() > 0)
- lvThemes->setCurrentIndex(mdl.at(0));
+ updateTheme(mdl.at(0));
else
setRandomTheme();
}
// restore map selection
- if ((!m_curMap.isEmpty()) && (chooseMap->currentIndex() < 0))
+ if (!m_curMap.isEmpty())
intSetMap(m_curMap);
else
updatePreview();
@@ -656,3 +654,227 @@
if (map == pMap)
pMap = 0;
}
+
+void HWMapContainer::mapTypeChanged(int index)
+{
+ changeMapType((MapModel::MapType)cType->itemData(index).toInt());
+}
+
+void HWMapContainer::changeMapType(MapModel::MapType type, const QModelIndex & newMap)
+{
+ staticMapList->hide();
+ missionMapList->hide();
+ lblMapList->hide();
+ generationStyles->hide();
+ mazeStyles->hide();
+ lblDesc->hide();
+ btnTheme->hide();
+ btnLoadMap->hide();
+ btnEditMap->hide();
+ btnRandomize->hide();
+
+ switch (type)
+ {
+ case MapModel::GeneratedMap:
+ mapgen = MAPGEN_REGULAR;
+ setMapInfo(MapModel::MapInfoRandom);
+ lblMapList->setText(tr("Map size:"));
+ lblMapList->show();
+ generationStyles->show();
+ btnRandomize->show();
+ btnTheme->show();
+ break;
+ case MapModel::GeneratedMaze:
+ mapgen = MAPGEN_MAZE;
+ setMapInfo(MapModel::MapInfoMaze);
+ lblMapList->setText(tr("Maze style:"));
+ lblMapList->show();
+ mazeStyles->show();
+ btnRandomize->show();
+ btnTheme->show();
+ break;
+ case MapModel::HandDrawnMap:
+ mapgen = MAPGEN_DRAWN;
+ setMapInfo(MapModel::MapInfoDrawn);
+ btnTheme->show();
+ btnLoadMap->show();
+ btnEditMap->show();
+ break;
+ case MapModel::MissionMap:
+ mapgen = MAPGEN_MAP;
+ missionMapChanged(newMap.isValid() ? newMap : missionMapList->currentIndex());
+ lblMapList->setText(tr("Mission:"));
+ lblMapList->show();
+ missionMapList->show();
+ lblDesc->setText(m_mapInfo.desc);
+ lblDesc->show();
+ btnRandomize->show();
+ emit mapChanged(m_curMap);
+ break;
+ case MapModel::StaticMap:
+ mapgen = MAPGEN_MAP;
+ staticMapChanged(newMap.isValid() ? newMap : staticMapList->currentIndex());
+ lblMapList->setText(tr("Map:"));
+ lblMapList->show();
+ staticMapList->show();
+ btnRandomize->show();
+ emit mapChanged(m_curMap);
+ break;
+ default:
+ break;
+ }
+
+ // Update cType combobox
+ for (int i = 0; i < cType->count(); i++)
+ {
+ if ((MapModel::MapType)cType->itemData(i).toInt() == type)
+ {
+ cType->setCurrentIndex(i);
+ break;
+ }
+ }
+
+ emit mapgenChanged(mapgen);
+}
+
+void HWMapContainer::showThemePrompt()
+{
+ ThemePrompt prompt(this);
+ int theme = prompt.exec() - 1; // Since 0 means canceled, so all indexes are +1'd
+ if (theme < 0) return;
+
+ QModelIndex current = m_themeModel->index(theme, 0);
+ updateTheme(current);
+
+ emit themeChanged(m_theme);
+}
+
+void HWMapContainer::updateTheme(const QModelIndex & current)
+{
+ m_theme = selectedTheme = current.data().toString();
+ QIcon icon = qVariantValue<QIcon>(current.data(Qt::UserRole));
+ QSize iconSize = icon.actualSize(QSize(65535, 65535));
+ btnTheme->setFixedHeight(iconSize.height());
+ btnTheme->setIconSize(iconSize);
+ btnTheme->setIcon(icon);
+ btnTheme->setText(tr("Theme: ") + current.data(Qt::DisplayRole).toString());
+ emit themeChanged(m_theme);
+}
+
+void HWMapContainer::staticMapChanged(const QModelIndex & map, const QModelIndex & old)
+{
+ mapChanged(map, 0, old);
+}
+
+void HWMapContainer::missionMapChanged(const QModelIndex & map, const QModelIndex & old)
+{
+ mapChanged(map, 1, old);
+}
+
+// Type: 0 = static, 1 = mission
+void HWMapContainer::mapChanged(const QModelIndex & map, int type, const QModelIndex & old)
+{
+ QListView * mapList;
+
+ if (type == 0) mapList = staticMapList;
+ else if (type == 1) mapList = missionMapList;
+ else return;
+
+ // Make sure it is a valid index
+ if (!map.isValid())
+ {
+ if (old.isValid())
+ {
+ mapList->setCurrentIndex(old);
+ mapList->scrollTo(old);
+ }
+ else
+ {
+ m_mapInfo.type = MapModel::Invalid;
+ updatePreview();
+ }
+
+ return;
+ }
+
+ // If map changed, update list selection
+ if (mapList->currentIndex() != map)
+ {
+ mapList->setCurrentIndex(map);
+ mapList->scrollTo(map);
+ }
+
+ if (map.data(Qt::UserRole + 1).canConvert<MapModel::MapInfo>())
+ setMapInfo(map.data(Qt::UserRole + 1).value<MapModel::MapInfo>());
+ else
+ Q_ASSERT(false); // Houston, we have a problem.
+
+}
+
+void HWMapContainer::setMapInfo(MapModel::MapInfo mapInfo)
+{
+ m_mapInfo = mapInfo;
+ m_curMap = m_mapInfo.name;
+ m_theme = m_mapInfo.theme;
+
+ // the map has no pre-defined theme, so let's use the selected one
+ if (m_mapInfo.theme.isEmpty())
+ {
+ m_theme = selectedTheme;
+ emit themeChanged(m_theme);
+ }
+
+ lblDesc->setText(mapInfo.desc);
+
+ updatePreview();
+ emit mapChanged(m_curMap);
+}
+
+void HWMapContainer::loadDrawing()
+{
+
+
+ QString fileName = QFileDialog::getOpenFileName(NULL, tr("Load drawn map"), ".", tr("Drawn Maps") + " (*.hwmap);;" + tr("All files") + " (*)");
+
+ if(fileName.isEmpty()) return;
+
+
+
+ QFile f(fileName);
+
+ if(!f.open(QIODevice::ReadOnly))
+ {
+ QMessageBox errorMsg(parentWidget());
+ errorMsg.setIcon(QMessageBox::Warning);
+ errorMsg.setWindowTitle(QMessageBox::tr("File error"));
+ errorMsg.setText(QMessageBox::tr("Cannot open '%1' for reading").arg(fileName));
+ errorMsg.setWindowModality(Qt::WindowModal);
+ errorMsg.exec();
+ }
+ else
+ {
+ drawMapScene.decode(qUncompress(QByteArray::fromBase64(f.readAll())));
+ mapDrawingFinished();
+ }
+}
+
+void HWMapContainer::showSeedPrompt()
+{
+ SeedPrompt prompt(parentWidget()->parentWidget(), getCurrentSeed(), isMaster());
+ connect(&prompt, SIGNAL(seedSelected(const QString &)), this, SLOT(setNewSeed(const QString &)));
+ prompt.exec();
+}
+
+bool HWMapContainer::isMaster()
+{
+ return m_master;
+}
+
+void HWMapContainer::setMaster(bool master)
+{
+ if (master == m_master) return;
+ m_master = master;
+
+ foreach (QWidget *widget, m_childWidgets)
+ widget->setEnabled(master);
+}
--- a/QTfrontend/ui/widget/mapContainer.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/ui/widget/mapContainer.h Mon Jan 14 12:07:51 2013 +0100
@@ -22,6 +22,7 @@
#include <QWidget>
#include <QGridLayout>
+#include <QVBoxLayout>
#include <QComboBox>
#include <QLabel>
#include <QByteArray>
@@ -37,6 +38,7 @@
class IconedGroupBox;
class QListView;
class SeparatorPainter;
+class QListWidget;
class MapFileErrorException
{
@@ -46,6 +48,8 @@
{
Q_OBJECT
+ Q_PROPERTY(bool master READ isMaster WRITE setMaster)
+
public:
HWMapContainer(QWidget * parent=0);
QString getCurrentSeed() const;
@@ -62,6 +66,7 @@
DrawMapScene * getDrawMapScene();
void mapDrawingFinished();
QLineEdit* seedEdit;
+ bool isMaster();
public slots:
void askForGeneratedPreview();
@@ -75,6 +80,7 @@
void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl);
void updateModelViews();
void onPreviewMapDestroyed(QObject * map);
+ void setMaster(bool master);
signals:
void seedChanged(const QString & seed);
@@ -89,22 +95,28 @@
private slots:
void setImage(const QImage newImage);
void setHHLimit(int hhLimit);
- void mapChanged(int index);
void setRandomSeed();
void setRandomTheme();
void setRandomMap();
- void themeSelected(const QModelIndex & current, const QModelIndex &);
void addInfoToPreview(QPixmap image);
- void seedEdited();
+ void setNewSeed(const QString & newSeed);
+ void mapTypeChanged(int);
+ void showThemePrompt();
+ void updateTheme(const QModelIndex & current);
+ void staticMapChanged(const QModelIndex & map, const QModelIndex & old = QModelIndex());
+ void missionMapChanged(const QModelIndex & map, const QModelIndex & old = QModelIndex());
+ void loadDrawing();
+ void showSeedPrompt();
protected:
virtual void resizeEvent ( QResizeEvent * event );
private:
- QGridLayout mainLayout;
- QPushButton* imageButt;
+ QVBoxLayout mainLayout;
+ QLabel* mapPreview;
QComboBox* chooseMap;
- MapModel * m_mapModel;
+ MapModel * m_staticMapModel;
+ MapModel * m_missionMapModel;
IconedGroupBox* gbThemes;
QListView* lvThemes;
ThemeModel * m_themeModel;
@@ -121,12 +133,30 @@
QComboBox *cbMazeSize;
MapGenerator mapgen;
DrawMapScene drawMapScene;
+ QComboBox * cType;
+ QListView * staticMapList;
+ QListView * missionMapList;
+ QListWidget * generationStyles;
+ QListWidget * mazeStyles;
+ QLabel * lblMapList;
+ QLabel * lblDesc;
+ QPushButton * btnTheme;
+ QPushButton * btnLoadMap;
+ QPushButton * btnEditMap;
+ QPushButton * btnRandomize;
+ QString selectedTheme;
+ QPushButton * btnSeed;
+ bool m_master;
+ QList<QWidget *> m_childWidgets;
void intSetSeed(const QString & seed);
void intSetMap(const QString & map);
void intSetMapgen(MapGenerator m);
void intSetTemplateFilter(int);
void intSetMazeSize(int size);
+ void mapChanged(const QModelIndex & map, int type, const QModelIndex & old = QModelIndex());
+ void setMapInfo(MapModel::MapInfo mapInfo);
+ void changeMapType(MapModel::MapType type, const QModelIndex & newMap = QModelIndex());
void updatePreview();
MapModel::MapInfo m_mapInfo;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/seedprompt.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,85 @@
+/*
+ * 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 <QDialog>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QLabel>
+#include <QDebug>
+
+#include "seedprompt.h"
+
+SeedPrompt::SeedPrompt(QWidget* parent, const QString & seed, bool editable) : QDialog(parent)
+{
+ setModal(true);
+ setWindowFlags(Qt::Sheet);
+ setWindowModality(Qt::WindowModal);
+ setMinimumSize(360, 160);
+ resize(360, 160);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ // Layout
+ QVBoxLayout * dialogLayout = new QVBoxLayout(this);
+
+ // Label
+ QLabel * label = new QLabel(tr("The map seed is the basis for all random values generated by the game."));
+ label->setWordWrap(true);
+ dialogLayout->addWidget(label, 0);
+
+ // Input box
+ editBox = new QLineEdit();
+ editBox->setText(seed);
+ editBox->setReadOnly(!editable);
+ editBox->setStyleSheet("QLineEdit { padding: 3px; }");
+ dialogLayout->addWidget(editBox, 1);
+
+ dialogLayout->addStretch(1);
+
+ // Buttons
+ QHBoxLayout * buttonLayout = new QHBoxLayout();
+ buttonLayout->addStretch(1);
+ dialogLayout->addLayout(buttonLayout);
+ if (editable)
+ {
+ QPushButton * btnCancel = new QPushButton(tr("Cancel"));
+ QPushButton * btnOkay = new QPushButton(tr("Set seed"));
+ connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(btnOkay, SIGNAL(clicked()), this, SLOT(accept()));
+ buttonLayout->addWidget(btnCancel);
+ buttonLayout->addWidget(btnOkay);
+ btnOkay->setDefault(true);
+ }
+ else
+ {
+ QPushButton * btnClose = new QPushButton(tr("Close"));
+ connect(btnClose, SIGNAL(clicked()), this, SLOT(reject()));
+ buttonLayout->addWidget(btnClose);
+ btnClose->setDefault(true);
+ }
+
+ setStyleSheet("QPushButton { padding: 5px; }");
+
+ connect(this, SIGNAL(accepted()), this, SLOT(setSeed()));
+}
+
+void SeedPrompt::setSeed()
+{
+ emit seedSelected(editBox->text());
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/seedprompt.h Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * 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 SEEDPROMPT_H
+#define SEEDPROMPT_H
+
+#include <QDialog>
+
+class QLineEdit;
+
+class SeedPrompt : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ SeedPrompt(QWidget* parent, const QString & seed, bool editable);
+
+ signals:
+ void seedSelected(const QString & seed);
+
+ private slots:
+ void setSeed();
+
+ private:
+ QLineEdit * editBox;
+};
+
+#endif // SEEDPROMPT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/themeprompt.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,100 @@
+/*
+ * 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 <QDialog>
+#include <QVBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QToolButton>
+#include <QWidgetItem>
+#include <QModelIndex>
+#include <QLabel>
+
+#include "flowlayout.h"
+#include "datamanager.h"
+#include "thememodel.h"
+#include "themeprompt.h"
+
+ThemePrompt::ThemePrompt(QWidget* parent) : QDialog(parent)
+{
+ setModal(true);
+ setWindowFlags(Qt::Sheet);
+ setWindowModality(Qt::WindowModal);
+ setMinimumSize(550, 430);
+ resize(550, 430);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ // Grid
+ QVBoxLayout * dialogLayout = new QVBoxLayout(this);
+ dialogLayout->setSpacing(0);
+
+ // Help/prompt message at top
+ QLabel * lblDesc = new QLabel(tr("Select a theme for this map"));
+ lblDesc->setStyleSheet("color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-top-left-radius: 10px; border-top-right-radius: 10px; padding: auto 20px;");
+ lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ lblDesc->setFixedHeight(24);
+ lblDesc->setMinimumWidth(0);
+
+ // Scroll area and container for theme icons
+ QWidget * themesContainer = new QWidget();
+ FlowLayout * themesGrid = new FlowLayout();
+ themesContainer->setLayout(themesGrid);
+ QScrollArea * scrollArea = new QScrollArea();
+ scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ scrollArea->setObjectName("scrollArea");
+ scrollArea->setStyleSheet("QScrollBar, #scrollArea { background-color: #130F2A; } #scrollArea { border-color: #F6CB1C; border-width: 3px; border-top-width: 0; border-style: solid; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }");
+ scrollArea->setWidgetResizable(true);
+ scrollArea->setFrameShape(QFrame::NoFrame);
+ scrollArea->setWidget(themesContainer);
+
+ // Cancel button (closes dialog)
+ QPushButton * btnCancel = new QPushButton(tr("Cancel"));
+ btnCancel->setStyleSheet("padding: 5px; margin-top: 10px;");
+ connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+
+ // Add elements to layouts
+ dialogLayout->addWidget(lblDesc, 0);
+ dialogLayout->addWidget(scrollArea, 1);
+ dialogLayout->addWidget(btnCancel, 0, Qt::AlignLeft);
+
+ // Tooltip label for theme name
+ lblToolTip = new QLabel(this);
+
+ // Add theme buttons
+ ThemeModel * themes = DataManager::instance().themeModel();
+ for (int i = 0; i < themes->rowCount(); i++)
+ {
+ QModelIndex index = themes->index(i, 0);
+ QToolButton * btn = new QToolButton();
+ btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ btn->setIcon(qVariantValue<QIcon>(themes->data(index, Qt::UserRole)));
+ btn->setText(themes->data(index, Qt::DisplayRole).toString());
+ btn->setIconSize(QSize(60, 60));
+ btn->setProperty("themeID", QVariant(i));
+ btn->setStyleSheet("padding: 2px;");
+ connect(btn, SIGNAL(clicked()), this, SLOT(themeClicked()));
+ themesGrid->addWidget(btn);
+ }
+}
+
+// When a theme is selected
+void ThemePrompt::themeClicked()
+{
+ QWidget * btn = (QWidget*)sender();
+ done(btn->property("themeID").toInt() + 1); // Since returning 0 means canceled
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/themeprompt.h Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * 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 THEMEPROMPT_H
+#define THEMEPROMPT_H
+
+#include <QWidget>
+#include <QDialog>
+
+class QLabel;
+
+class ThemePrompt : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ ThemePrompt(QWidget* parent);
+
+ private:
+ QLabel * lblToolTip;
+
+ private slots:
+ void themeClicked();
+};
+
+#endif // THEMEPROMPT_H
--- a/QTfrontend/util/DataManager.cpp Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/util/DataManager.cpp Mon Jan 14 12:07:51 2013 +0100
@@ -40,7 +40,8 @@
DataManager::DataManager()
{
m_hatModel = NULL;
- m_mapModel = NULL;
+ m_staticMapModel = NULL;
+ m_missionMapModel = NULL;
m_themeModel = NULL;
m_colorsModel = NULL;
m_bindsModel = NULL;
@@ -92,13 +93,22 @@
return m_hatModel;
}
-MapModel * DataManager::mapModel()
+MapModel * DataManager::staticMapModel()
{
- if (m_mapModel == NULL) {
- m_mapModel = new MapModel();
- m_mapModel->loadMaps();
+ if (m_staticMapModel == NULL) {
+ m_staticMapModel = new MapModel();
+ m_staticMapModel->loadMaps(MapModel::StaticMap);
}
- return m_mapModel;
+ return m_staticMapModel;
+}
+
+MapModel * DataManager::missionMapModel()
+{
+ if (m_missionMapModel == NULL) {
+ m_missionMapModel = new MapModel();
+ m_missionMapModel->loadMaps(MapModel::MissionMap);
+ }
+ return m_missionMapModel;
}
ThemeModel * DataManager::themeModel()
--- a/QTfrontend/util/DataManager.h Tue Jan 08 21:29:37 2013 +0200
+++ b/QTfrontend/util/DataManager.h Mon Jan 14 12:07:51 2013 +0100
@@ -88,13 +88,22 @@
HatModel * hatModel();
/**
- * @brief Returns pointer to a model of available maps.
+ * @brief Returns pointer to a model of available static maps.
*
* The model is updated automatically on data reload.
*
* @return map model pointer.
*/
- MapModel * mapModel();
+ MapModel * staticMapModel();
+
+ /**
+ * @brief Returns pointer to a model of available mission maps.
+ *
+ * The model is updated automatically on data reload.
+ *
+ * @return map model pointer.
+ */
+ MapModel * missionMapModel();
/**
* @brief Returns pointer to a model of available themes.
@@ -132,7 +141,8 @@
GameStyleModel * m_gameStyleModel; ///< game style model instance
HatModel * m_hatModel; ///< hat model instance
- MapModel * m_mapModel; ///< map model instance
+ MapModel * m_staticMapModel; ///< static map model instance
+ MapModel * m_missionMapModel; ///< mission map model instance
ThemeModel * m_themeModel; ///< theme model instance
QStandardItemModel * m_colorsModel;
QStandardItemModel * m_bindsModel;
--- a/gameServer/Actions.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/Actions.hs Mon Jan 14 12:07:51 2013 +0100
@@ -4,7 +4,6 @@
import Control.Concurrent
import qualified Data.Set as Set
-import qualified Data.Sequence as Seq
import qualified Data.List as L
import qualified Control.Exception as Exception
import System.Log.Logger
@@ -143,13 +142,13 @@
chan <- client's sendChan
clNick <- client's nick
- loggedIn <- client's logonPassed
+ loggedIn <- client's isVisible
when (ri /= lobbyId) $ do
processAction $ MoveToLobby ("quit: " `B.append` msg)
return ()
- clientsChans <- liftM (Prelude.map sendChan . Prelude.filter logonPassed) $! allClientsS
+ clientsChans <- liftM (Prelude.map sendChan . Prelude.filter isVisible) $! allClientsS
io $
infoM "Clients" (show ci ++ " quits: " ++ B.unpack msg)
@@ -158,7 +157,7 @@
mapM_ processAction
[
AnswerClients [chan] ["BYE", msg]
- , ModifyClient (\c -> c{nick = "", logonPassed = False}) -- this will effectively hide client from others while he isn't deleted from list
+ , ModifyClient (\c -> c{nick = "", isVisible = False}) -- this will effectively hide client from others while he isn't deleted from list
]
s <- get
@@ -374,7 +373,7 @@
ModifyRoom (\r -> r{
gameInfo = liftM (\g -> g{
teamsInGameNumber = teamsInGameNumber g - 1
- , roundMsgs = roundMsgs g Seq.|> rmTeamMsg
+ , roundMsgs = rmTeamMsg : roundMsgs g
}) $ gameInfo r
})
]
@@ -421,9 +420,11 @@
n <- client's nick
h <- client's host
p <- client's clientProto
+ checker <- client's isChecker
uid <- client's clUID
- haveSameNick <- liftM (not . null . tail . filter (\c -> caseInsensitiveCompare (nick c) n)) allClientsS
- if haveSameNick then
+ -- allow multiple checker logins
+ haveSameNick <- liftM (not . null . tail . filter (\c -> (not $ isChecker c) && caseInsensitiveCompare (nick c) n)) allClientsS
+ if haveSameNick && (not checker) then
if p < 38 then
processAction $ ByeClient "Nickname is already in use"
else
@@ -444,9 +445,8 @@
case info of
HasAccount passwd isAdmin -> do
b <- isBanned
- when (not b) $ do
- chan <- client's sendChan
- mapM_ processAction [AnswerClients [chan] ["ASKPASSWORD"], ModifyClient (\c -> c{webPassword = passwd, isAdministrator = isAdmin})]
+ c <- client's isChecker
+ when (not b) $ (if c then checkerLogin else playerLogin) passwd isAdmin
Guest -> do
b <- isBanned
when (not b) $
@@ -459,14 +459,21 @@
isBanned = do
processAction $ CheckBanned False
liftM B.null $ client's nick
-
+ checkerLogin p False = processAction $ ByeClient "No checker rights"
+ checkerLogin p True = do
+ wp <- client's webPassword
+ processAction $
+ if wp == p then ModifyClient $ \c -> c{logonPassed = True} else ByeClient "Authentication failed"
+ playerLogin p a = do
+ chan <- client's sendChan
+ mapM_ processAction [AnswerClients [chan] ["ASKPASSWORD"], ModifyClient (\c -> c{webPassword = p, isAdministrator = a})]
processAction JoinLobby = do
chan <- client's sendChan
clientNick <- client's nick
isAuthenticated <- liftM (not . B.null) $ client's webPassword
isAdmin <- client's isAdministrator
- loggedInClients <- liftM (Prelude.filter logonPassed) $! allClientsS
+ loggedInClients <- liftM (Prelude.filter isVisible) $! allClientsS
let (lobbyNicks, clientsChans) = unzip . L.map (nick &&& sendChan) $ loggedInClients
let authenticatedNicks = L.map nick . L.filter (not . B.null . webPassword) $ loggedInClients
let adminsNicks = L.map nick . L.filter isAdministrator $ loggedInClients
@@ -477,7 +484,7 @@
, [AnswerClients [chan] ("CLIENT_FLAGS" : "+u" : authenticatedNicks) | not $ null authenticatedNicks]
, [AnswerClients [chan] ("CLIENT_FLAGS" : "+a" : adminsNicks) | not $ null adminsNicks]
, [AnswerClients (chan : clientsChans) ["CLIENT_FLAGS", B.concat["+" , clFlags], clientNick] | not $ B.null clFlags]
- , [ModifyClient (\cl -> cl{logonPassed = True})]
+ , [ModifyClient (\cl -> cl{logonPassed = True, isVisible = True})]
, [SendServerMessage]
]
@@ -637,6 +644,7 @@
processAction SaveReplay = do
ri <- clientRoomA
rnc <- gets roomsClients
+
io $ do
r <- room'sM rnc id ri
saveReplay r
--- a/gameServer/ClientIO.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/ClientIO.hs Mon Jan 14 12:07:51 2013 +0100
@@ -30,25 +30,26 @@
return (B.splitWith (== '\n') packet : packets)
listenLoop :: Socket -> Chan CoreMessage -> ClientIndex -> IO ()
-listenLoop sock chan ci = recieveWithBufferLoop B.empty
+listenLoop sock chan ci = receiveWithBufferLoop B.empty
where
- recieveWithBufferLoop recvBuf = do
+ receiveWithBufferLoop recvBuf = do
recvBS <- recv sock 4096
unless (B.null recvBS) $ do
let (packets, newrecvBuf) = bs2Packets $ B.append recvBuf recvBS
forM_ packets sendPacket
- recieveWithBufferLoop newrecvBuf
+ receiveWithBufferLoop newrecvBuf
sendPacket packet = writeChan chan $ ClientMessage (ci, packet)
clientRecvLoop :: Socket -> Chan CoreMessage -> Chan [B.ByteString] -> ClientIndex -> (forall a. IO a -> IO a) -> IO ()
clientRecvLoop s chan clChan ci restore =
(myThreadId >>=
- \t -> (restore $ forkIO (clientSendLoop s t clChan ci) >>
+ (\t -> (restore $ forkIO (clientSendLoop s t clChan ci) >>
listenLoop s chan ci >> return "Connection closed")
`Exception.catch` (\(e :: ShutdownThreadException) -> return . B.pack . show $ e)
`Exception.catch` (\(e :: Exception.IOException) -> return . B.pack . show $ e)
`Exception.catch` (\(e :: Exception.SomeException) -> return . B.pack . show $ e)
+ )
>>= clientOff) `Exception.finally` remove
where
clientOff msg = writeChan chan $ ClientMessage (ci, ["QUIT", msg])
--- a/gameServer/CoreTypes.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/CoreTypes.hs Mon Jan 14 12:07:51 2013 +0100
@@ -4,7 +4,6 @@
import Control.Concurrent
import Data.Word
import qualified Data.Map as Map
-import Data.Sequence(Seq, empty)
import Data.Time
import Network
import Data.Function
@@ -29,6 +28,7 @@
nick :: B.ByteString,
webPassword :: B.ByteString,
logonPassed :: Bool,
+ isVisible :: Bool,
clientProto :: !Word16,
roomID :: RoomIndex,
pingsQueue :: !Word,
@@ -36,6 +36,7 @@
isReady :: !Bool,
isInGame :: Bool,
isAdministrator :: Bool,
+ isChecker :: Bool,
isKickedFromServer :: Bool,
clientClan :: Maybe B.ByteString,
teamsInGame :: Word
@@ -68,7 +69,7 @@
data GameInfo =
GameInfo
{
- roundMsgs :: Seq B.ByteString,
+ roundMsgs :: [B.ByteString],
leftTeams :: [B.ByteString],
teamsAtStart :: [TeamInfo],
teamsInGameNumber :: Int,
@@ -85,7 +86,7 @@
-> GameInfo
newGameInfo =
GameInfo
- Data.Sequence.empty
+ []
[]
data RoomInfo =
--- a/gameServer/HWProtoInRoomState.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/HWProtoInRoomState.hs Mon Jan 14 12:07:51 2013 +0100
@@ -2,13 +2,11 @@
module HWProtoInRoomState where
import qualified Data.Map as Map
-import Data.Sequence((|>))
import Data.List as L
import Data.Maybe
import qualified Data.ByteString.Char8 as B
import Control.Monad
import Control.Monad.Reader
-import Control.DeepSeq
--------------------------------------
import CoreTypes
import Actions
@@ -214,7 +212,8 @@
chans <- roomOthersChans
if teamsInGame cl > 0 && (isJust $ gameInfo rm) && isLegal then
- return $ AnswerClients chans ["EM", msg] : [ModifyRoom (\r -> r{gameInfo = liftM (\g -> g{roundMsgs = roundMsgs g |> msg}) $ gameInfo r}) | not isKeepAlive]
+ return $ AnswerClients chans ["EM", msg]
+ : [ModifyRoom (\r -> r{gameInfo = liftM (\g -> g{roundMsgs = msg : roundMsgs g}) $ gameInfo r}) | not isKeepAlive]
else
return []
where
--- a/gameServer/HWProtoLobbyState.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/HWProtoLobbyState.hs Mon Jan 14 12:07:51 2013 +0100
@@ -2,11 +2,9 @@
module HWProtoLobbyState where
import qualified Data.Map as Map
-import qualified Data.Foldable as Foldable
import Data.Maybe
import Data.List
import Control.Monad.Reader
-import qualified Data.ByteString.Char8 as B
--------------------------------------
import CoreTypes
import Actions
@@ -128,7 +126,7 @@
[AnswerClients [sendChan cl] ["RUN_GAME"]
, AnswerClients chans ["CLIENT_FLAGS", "+g", nick cl]
, ModifyClient (\c -> c{isInGame = True})
- , AnswerClients [sendChan cl] $ "EM" : toEngineMsg "e$spectate 1" : Foldable.toList (roundMsgs . fromJust . gameInfo $ jRoom)]
+ , AnswerClients [sendChan cl] $ "EM" : toEngineMsg "e$spectate 1" : (reverse . roundMsgs . fromJust . gameInfo $ jRoom)]
handleCmd_lobby ["JOIN_ROOM", roomName] =
--- a/gameServer/HWProtoNEState.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/HWProtoNEState.hs Mon Jan 14 12:07:51 2013 +0100
@@ -1,4 +1,4 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings, CPP #-}
module HWProtoNEState where
import Control.Monad.Reader
@@ -48,4 +48,18 @@
return [ByeClient "Authentication failed"]
+#if defined(OFFICIAL_SERVER)
+handleCmd_NotEntered ["CHECKER", protoNum, newNick, password] = do
+ (ci, irnc) <- ask
+ let cl = irnc `client` ci
+
+ if parsedProto == 0 then return [ProtocolError "Bad number"]
+ else
+ return $ [
+ ModifyClient (\c -> c{clientProto = parsedProto, nick = newNick, webPassword = password, isChecker = True})
+ , CheckRegistered]
+ where
+ parsedProto = readInt_ protoNum
+#endif
+
handleCmd_NotEntered _ = return [ProtocolError "Incorrect command (state: not entered)"]
--- a/gameServer/NetRoutines.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/NetRoutines.hs Mon Jan 14 12:07:51 2013 +0100
@@ -34,6 +34,7 @@
""
""
False
+ False
0
lobbyId
0
@@ -42,6 +43,7 @@
False
False
False
+ False
Nothing
0
)
--- a/gameServer/OfficialServer/GameReplayStore.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/OfficialServer/GameReplayStore.hs Mon Jan 14 12:07:51 2013 +0100
@@ -14,7 +14,7 @@
saveReplay :: RoomInfo -> IO ()
-saveReplay r = do
+saveReplay r = when allPlayersHaveRegisteredAccounts $ do
time <- getCurrentTime
u <- liftM hashUnique newUnique
let fileName = "replays/" ++ show time ++ "-" ++ show u
@@ -23,4 +23,3 @@
E.catch
(writeFile fileName (show replayInfo))
(\(e :: IOException) -> warningM "REPLAYS" $ "Couldn't write to " ++ fileName ++ ": " ++ show e)
-
\ No newline at end of file
--- a/gameServer/ServerState.hs Tue Jan 08 21:29:37 2013 +0200
+++ b/gameServer/ServerState.hs Mon Jan 14 12:07:51 2013 +0100
@@ -49,6 +49,6 @@
sameProtoClientsS p = liftM f allClientsS
where
f = filter (\c -> clientProto c == p)
-
+
io :: IO a -> StateT ServerState IO a
io = liftIO
--- a/hedgewars/ArgParsers.inc Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/ArgParsers.inc Mon Jan 14 12:07:51 2013 +0100
@@ -124,6 +124,8 @@
procedure startVideoRecording(var paramIndex: LongInt);
begin
+ // Silence the hint that appears when USE_VIDEO_RECORDING is not defined
+ paramIndex:= paramIndex;
{$IFDEF USE_VIDEO_RECORDING}
GameType:= gmtRecord;
inc(paramIndex);
@@ -245,6 +247,7 @@
tmpInt:= 1;
while (index < size) do
begin
+ newSyntax:= '';
inc(paramIndex);
cmd:= cmdArray[index];
arg:= ParamStr(paramIndex);
--- a/hedgewars/CMakeLists.txt Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/CMakeLists.txt Mon Jan 14 12:07:51 2013 +0100
@@ -239,25 +239,25 @@
endif()
-add_custom_target(${engine_output_name} ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}")
+add_custom_target(hwengine ALL DEPENDS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}")
#when system Lua is not found we need to compile it before engine
if(NOT LUA_FOUND)
- add_dependencies(${engine_output_name} lua)
+ add_dependencies(hwengine lua)
endif()
# compile physfs before engine
-add_dependencies(${engine_output_name} physfs)
+add_dependencies(hwengine physfs)
#when ffmpeg/libav is found we need to compile it before engine
#TODO: convert avwrapper to .pas unit so we can skip this step
if(${FFMPEG_FOUND})
- add_dependencies(${engine_output_name} avwrapper)
+ add_dependencies(hwengine avwrapper)
endif()
#this command is a workaround to some inlining issues present in older FreePascal versions and fixed in 2.6
if((FPC_VERSION VERSION_LESS "2.6") AND (NOVIDEOREC OR NOT ${FFMPEG_FOUND}))
- add_dependencies(${engine_output_name} ENGINECLEAN)
+ add_dependencies(hwengine ENGINECLEAN)
endif()
install(PROGRAMS "${EXECUTABLE_OUTPUT_PATH}/${engine_output_name}" DESTINATION ${destination_dir})
--- a/hedgewars/GSHandlers.inc Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/GSHandlers.inc Mon Jan 14 12:07:51 2013 +0100
@@ -5174,7 +5174,7 @@
if (Gear^.State and gstTmpFlag <> 0) or (GameTicks and $7 = 0) then
begin
doStepFallingGear(Gear);
- if (Gear^.State and gstInvisible <> 0) and (GameTicks and $FF = 0) and ((hwRound(Gear^.X) < leftX) or (hwRound(Gear^.X) > rightX) or (hwRound(Gear^.Y) < topY)) then
+ if (Gear^.State and gstInvisible <> 0) and (GameTicks and $FF = 0) and (hwRound(Gear^.X) < LongInt(leftX)) or (hwRound(Gear^.X) > LongInt(rightX)) or (hwRound(Gear^.Y) < LongInt(topY)) then
begin
Gear^.X:= int2hwFloat(GetRandom(rightX-leftX)+leftX);
Gear^.Y:= int2hwFloat(GetRandom(LAND_HEIGHT-topY)+topY);
@@ -5267,9 +5267,9 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepKnife(Gear: PGear);
-var ox, oy: LongInt;
- la: hwFloat;
- a: real;
+//var ox, oy: LongInt;
+// la: hwFloat;
+var a: real;
begin
// Gear is shrunk so it can actually escape the hog without carving into the terrain
if (Gear^.Radius = 6) and (Gear^.CollisionMask = $FFFF) then Gear^.Radius:= 16;
@@ -5291,14 +5291,14 @@
end
else if (Gear^.CollisionIndex = -1) and (Gear^.Timer = 0) then
begin
- ox:= 0; oy:= 0;
+ (*ox:= 0; oy:= 0;
if TestCollisionYwithGear(Gear, -1) <> 0 then oy:= -1;
if TestCollisionXwithGear(Gear, 1) then ox:= 1;
if TestCollisionXwithGear(Gear, -1) then ox:= -1;
if TestCollisionYwithGear(Gear, 1) <> 0 then oy:= 1;
if Gear^.Health > 0 then
PlaySound(sndRopeAttach);
-(*
+
la:= _10000;
if (ox <> 0) or (oy <> 0) then
la:= CalcSlopeNearGear(Gear, ox, oy);
--- a/hedgewars/hwengine.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/hwengine.pas Mon Jan 14 12:07:51 2013 +0100
@@ -330,8 +330,8 @@
///////////////////////////////////////////////////////////////////////////////
procedure Game{$IFDEF HWLIBRARY}(argc: LongInt; argv: PPChar); cdecl; export{$ENDIF};
-var p: TPathType;
- s: shortstring;
+//var p: TPathType;
+var s: shortstring;
i: LongInt;
begin
{$IFDEF HWLIBRARY}
--- a/hedgewars/uAIAmmoTests.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uAIAmmoTests.pas Mon Jan 14 12:07:51 2013 +0100
@@ -1140,7 +1140,7 @@
var i: Longword;
v: LongInt;
begin
-while (not TestColl(hwRound(Gear^.X), hwRound(Gear^.Y), 6)) and (Gear^.Y.Round < LAND_HEIGHT) do
+while (not TestColl(hwRound(Gear^.X), hwRound(Gear^.Y), 6)) and (Gear^.Y.Round < LongWord(LAND_HEIGHT)) do
Gear^.Y:= Gear^.Y + _1;
for i:= 0 to 2040 do
--- a/hedgewars/uCommandHandlers.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uCommandHandlers.pas Mon Jan 14 12:07:51 2013 +0100
@@ -89,11 +89,11 @@
end;
procedure chCheckProto(var s: shortstring);
-var i, c: LongInt;
+var i: LongInt;
begin
if isDeveloperMode then
begin
- val(s, i, c);
+ i:= StrToInt(s);
TryDo(i <= cNetProtoVersion, 'Protocol version mismatch: engine is too old (got '+intToStr(i)+', expecting '+intToStr(cNetProtoVersion)+')', true);
TryDo(i >= cNetProtoVersion, 'Protocol version mismatch: engine is too new (got '+intToStr(i)+', expecting '+intToStr(cNetProtoVersion)+')', true);
end
--- a/hedgewars/uGearsRender.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uGearsRender.pas Mon Jan 14 12:07:51 2013 +0100
@@ -41,7 +41,7 @@
const
// hog tag mask
- htNone = $00;
+ //htNone = $00;
htTeamName = $01;
htName = $02;
htHealth = $04;
--- a/hedgewars/uIO.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uIO.pas Mon Jan 14 12:07:51 2013 +0100
@@ -339,10 +339,12 @@
// these are equations solved for CursorPoint
// SDLNet_Read16(@(headcmd^.X)) == CursorPoint.X - WorldDx;
// SDLNet_Read16(@(headcmd^.Y)) == cScreenHeight - CursorPoint.Y - WorldDy;
- if not (CurrentTeam^.ExtDriven and bShowAmmoMenu) then
+ if CurrentTeam^.ExtDriven then
begin
- CursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.X))) + WorldDx;
- CursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.Y))) - WorldDy
+ TargetCursorPoint.X:= LongInt(SDLNet_Read32(@(headcmd^.X))) + WorldDx;
+ TargetCursorPoint.Y:= cScreenHeight - LongInt(SDLNet_Read32(@(headcmd^.Y))) - WorldDy;
+ if not bShowAmmoMenu and autoCameraOn then
+ CursorPoint:= TargetCursorPoint
end
end;
'w': ParseCommand('setweap ' + headcmd^.str[2], true);
--- a/hedgewars/uInputHandler.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uInputHandler.pas Mon Jan 14 12:07:51 2013 +0100
@@ -67,10 +67,10 @@
//ControllerNumBalls: array[0..5] of Integer;
ControllerNumHats: array[0..5] of Integer;
ControllerNumButtons: array[0..5] of Integer;
- ControllerAxes: array[0..5] of array[0..19] of Integer;
+ //ControllerAxes: array[0..5] of array[0..19] of Integer;
//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;
+ //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;
@@ -355,7 +355,7 @@
var Controller: array [0..5] of PSDL_Joystick;
procedure ControllerInit;
-var i, j: Integer;
+var j: Integer;
begin
ControllerEnabled:= 0;
{$IFDEF IPHONE}
@@ -400,18 +400,18 @@
if ControllerNumButtons[j] > 20 then
ControllerNumButtons[j]:= 20;
- // reset all buttons/axes
+ (*// reset all buttons/axes
for i:= 0 to pred(ControllerNumAxes[j]) do
ControllerAxes[j][i]:= 0;
- (*for i:= 0 to pred(ControllerNumBalls[j]) do
+ for i:= 0 to pred(ControllerNumBalls[j]) do
begin
ControllerBalls[j][i][0]:= 0;
ControllerBalls[j][i][1]:= 0;
- end;*)
+ end;
for i:= 0 to pred(ControllerNumHats[j]) do
ControllerHats[j][i]:= SDL_HAT_CENTERED;
for i:= 0 to pred(ControllerNumButtons[j]) do
- ControllerButtons[j][i]:= 0;
+ ControllerButtons[j][i]:= 0;*)
end;
end;
// enable event generation/controller updating
--- a/hedgewars/uLand.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uLand.pas Mon Jan 14 12:07:51 2013 +0100
@@ -523,7 +523,6 @@
procedure LoadMap;
var tmpsurf: PSDL_Surface;
- s: shortstring;
mapName: shortstring = '';
begin
WriteLnToConsole('Loading land from file...');
@@ -631,7 +630,7 @@
if Land[y, x] <> 0 then
begin
inc(c);
- if c > (LAND_WIDTH div 2) then // avoid accidental triggering
+ if c > LongWord((LAND_WIDTH div 2)) then // avoid accidental triggering
begin
hasBorder:= true;
break;
--- a/hedgewars/uLocale.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uLocale.pas Mon Jan 14 12:07:51 2013 +0100
@@ -40,14 +40,12 @@
trevt_n: array[TEventId] of integer;
procedure LoadLocale(FileName: shortstring);
-var s: ansistring;
+var s: ansistring = '';
f: pfsFile;
a, b, c: LongInt;
first: array[TEventId] of boolean;
e: TEventId;
- loaded: boolean;
begin
-loaded:= false;
for e:= Low(TEventId) to High(TEventId) do
first[e]:= true;
--- a/hedgewars/uScript.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uScript.pas Mon Jan 14 12:07:51 2013 +0100
@@ -230,8 +230,9 @@
begin
for i:= 1 to lua_gettop(L) do
if (GameFlags and lua_tointeger(L, i)) = 0 then
- GameFlags += lua_tointeger(L, i);
+ GameFlags := GameFlags + LongWord(lua_tointeger(L, i));
ScriptSetInteger('GameFlags', GameFlags);
+ lc_enablegameflags:= 0;
end;
function lc_disablegameflags(L : Plua_State) : LongInt; Cdecl;
@@ -239,14 +240,18 @@
begin
for i:= 1 to lua_gettop(L) do
if (GameFlags and lua_tointeger(L, i)) <> 0 then
- GameFlags -= lua_tointeger(L, i);
+ GameFlags := GameFlags - LongWord(lua_tointeger(L, i));
ScriptSetInteger('GameFlags', GameFlags);
+ lc_disablegameflags:= 0;
end;
function lc_cleargameflags(L : Plua_State) : LongInt; Cdecl;
begin
+ // Silence hint
+ L:= L;
GameFlags:= 0;
ScriptSetInteger('GameFlags', GameFlags);
+ lc_cleargameflags:= 0;
end;
function lc_addcaption(L : Plua_State) : LongInt; Cdecl;
@@ -1760,8 +1765,7 @@
end;
function lc_restorehog(L: Plua_State): LongInt; Cdecl;
-var hog: PHedgehog;
- i, h: LongInt;
+var i, h: LongInt;
uid: LongWord;
begin
if lua_gettop(L) <> 1 then
--- a/hedgewars/uSound.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uSound.pas Mon Jan 14 12:07:51 2013 +0100
@@ -106,7 +106,7 @@
implementation
-uses uVariables, uConsole, uUtils, uCommands, uDebug, uPhysFSLayer;
+uses uVariables, uConsole, uCommands, uDebug, uPhysFSLayer;
const chanTPU = 32;
var Volume: LongInt;
--- a/hedgewars/uStore.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uStore.pas Mon Jan 14 12:07:51 2013 +0100
@@ -605,6 +605,8 @@
begin
// check for file in user dir (never critical)
tmpsurf:= LoadImage(cPathz[path] + '/' + filename, imageFlags);
+
+ LoadDataImage:= tmpsurf;
end;
--- a/hedgewars/uTeams.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uTeams.pas Mon Jan 14 12:07:51 2013 +0100
@@ -40,7 +40,7 @@
procedure SwitchCurrentHedgehog(newHog: PHedgehog);
implementation
-uses uLocale, uAmmos, uChat, uVariables, uUtils, uIO, uCaptions, uCommands, uDebug, uScript,
+uses uLocale, uAmmos, uChat, uVariables, uUtils, uIO, uCaptions, uCommands, uDebug,
uGearsUtils, uGearsList
{$IFDEF USE_TOUCH_INTERFACE}, uTouch{$ENDIF};
@@ -503,7 +503,6 @@
procedure chAddHH(var id: shortstring);
var s: shortstring;
Gear: PGear;
- c: LongInt;
begin
s:= '';
if (not isDeveloperMode) or (CurrentTeam = nil) then
@@ -512,10 +511,10 @@
begin
SplitBySpace(id, s);
SwitchCurrentHedgehog(@Hedgehogs[HedgehogsNumber]);
- val(id, CurrentHedgehog^.BotLevel, c);
+ CurrentHedgehog^.BotLevel:= StrToInt(id);
Gear:= AddGear(0, 0, gtHedgehog, 0, _0, _0, 0);
SplitBySpace(s, id);
- val(s, Gear^.Health, c);
+ Gear^.Health:= StrToInt(s);
TryDo(Gear^.Health > 0, 'Invalid hedgehog health', true);
Gear^.Hedgehog^.Team:= CurrentTeam;
if (GameFlags and gfSharedAmmo) <> 0 then
@@ -536,7 +535,6 @@
procedure chAddTeam(var s: shortstring);
var Color: Longword;
- c: LongInt;
ts, cs: shortstring;
begin
cs:= '';
@@ -545,7 +543,7 @@
begin
SplitBySpace(s, cs);
SplitBySpace(cs, ts);
- val(cs, Color, c);
+ Color:= StrToInt(cs);
TryDo(Color <> 0, 'Error: black team color', true);
// color is always little endian so the mask must be constant also in big endian archs
@@ -562,16 +560,16 @@
procedure chSetHHCoords(var x: shortstring);
var y: shortstring;
- t, c: Longint;
+ t: Longint;
begin
-y:= '';
-if (not isDeveloperMode) or (CurrentHedgehog = nil) or (CurrentHedgehog^.Gear = nil) then
- exit;
-SplitBySpace(x, y);
-val(x, t, c);
-CurrentHedgehog^.Gear^.X:= int2hwFloat(t);
-val(y, t, c);
-CurrentHedgehog^.Gear^.Y:= int2hwFloat(t)
+ y:= '';
+ if (not isDeveloperMode) or (CurrentHedgehog = nil) or (CurrentHedgehog^.Gear = nil) then
+ exit;
+ SplitBySpace(x, y);
+ t:= StrToInt(x);
+ CurrentHedgehog^.Gear^.X:= int2hwFloat(t);
+ t:= StrToInt(y);
+ CurrentHedgehog^.Gear^.Y:= int2hwFloat(t)
end;
procedure chBind(var id: shortstring);
--- a/hedgewars/uUtils.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uUtils.pas Mon Jan 14 12:07:51 2013 +0100
@@ -188,7 +188,11 @@
function StrToInt(s: shortstring): LongInt;
var c: LongInt;
begin
-val(s, StrToInt, c)
+val(s, StrToInt, c);
+{$IFDEF DEBUGFILE}
+if c <> 0 then
+ writeln(f, 'Error at position ' + IntToStr(c) + ' : ' + s[c])
+{$ENDIF}
end;
function FloatToStr(n: hwFloat): shortstring;
--- a/hedgewars/uVariables.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uVariables.pas Mon Jan 14 12:07:51 2013 +0100
@@ -177,8 +177,9 @@
SDWaterColorArray : array[0..3] of HwColor4f;
SDTint : LongInt;
- CursorPoint : TPoint;
- TargetPoint : TPoint;
+ TargetCursorPoint : TPoint;
+ CursorPoint : TPoint;
+ TargetPoint : TPoint;
ScreenFade : TScreenFade;
ScreenFadeValue : LongInt;
--- a/hedgewars/uVideoRec.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uVideoRec.pas Mon Jan 14 12:07:51 2013 +0100
@@ -196,7 +196,7 @@
end;
function LoadNextCameraPosition(out newRealTicks, newGameTicks: LongInt): Boolean;
-var frame: TFrame;
+var frame: TFrame = (realTicks: 0; gameTicks: 0; CamX: 0; CamY: 0; zoom: 0);
begin
// we need to skip or duplicate frames to match target framerate
while Int64(curTime)*cVideoFramerateNum <= Int64(numFrames)*cVideoFramerateDen*1000 do
@@ -244,9 +244,12 @@
var inF, outF: file;
buffer: array[0..1023] of byte;
result: LongInt;
+ i: integer;
begin
{$IOCHECKS OFF}
- result:= 0; // avoid compiler hint
+ result:= 0; // avoid compiler hint and warning
+ for i:= 0 to 1023 do
+ buffer[i]:= 0;
Assign(inF, src);
Reset(inF, 1);
--- a/hedgewars/uVisualGears.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uVisualGears.pas Mon Jan 14 12:07:51 2013 +0100
@@ -57,7 +57,7 @@
const
cExplFrameTicks = 110;
- cSmokeZ = 499;
+ //cSmokeZ = 499;
var VGCounter: LongWord;
VisualGearLayers: array[0..6] of PVisualGear;
--- a/hedgewars/uWorld.pas Tue Jan 08 21:29:37 2013 +0200
+++ b/hedgewars/uWorld.pas Mon Jan 14 12:07:51 2013 +0100
@@ -75,7 +75,7 @@
FPS: Longword;
CountTicks: Longword;
SoundTimerTicks: Longword;
- prevPoint: TPoint;
+ prevPoint, prevTargetPoint: TPoint;
amSel: TAmmoType = amNothing;
missionTex: PTexture;
missionTimer: LongInt;
@@ -86,7 +86,6 @@
AmmoMenuTex : PTexture;
HorizontOffset: LongInt;
cOffsetY: LongInt;
- AFRToggle: Boolean;
const cStereo_Sky = 0.0500;
cStereo_Horizon = 0.0250;
@@ -105,7 +104,7 @@
AMTypeMaskX = $00000001;
AMTypeMaskY = $00000002;
AMTypeMaskAlpha = $00000004;
- AMTypeMaskSlide = $00000008;
+ //AMTypeMaskSlide = $00000008;
{$IFDEF MOBILE}
AMSlotSize = 48;
@@ -224,6 +223,8 @@
uCursor.init();
prevPoint.X:= 0;
prevPoint.Y:= cScreenHeight div 2;
+prevTargetPoint.X:= 0;
+prevTargetPoint.Y:= 0;
WorldDx:= -(LAND_WIDTH div 2) + cScreenWidth div 2;
WorldDy:= -(LAND_HEIGHT - (playHeight div 2)) + (cScreenHeight div 2);
@@ -643,6 +644,7 @@
AMShiftX:= AMShiftTargetX;
AMShiftY:= AMShiftTargetY;
prevPoint:= CursorPoint;
+ prevTargetPoint:= TargetCursorPoint;
AMState:= AMHidden;
end;
end;
@@ -1631,6 +1633,7 @@
begin
if not bShowAmmoMenu then
begin
+ if not CurrentTeam^.ExtDriven then TargetCursorPoint:= CursorPoint;
with CurrentHedgehog^ do
if (Gear <> nil) and ((Gear^.State and gstHHChooseTarget) <> 0) then
begin
@@ -1639,9 +1642,9 @@
i:= GetCurAmmoEntry(CurrentHedgehog^)^.Pos;
with Ammoz[CurAmmoType] do
if PosCount > 1 then
- DrawSprite(PosSprite, CursorPoint.X - (SpritesData[PosSprite].Width shr 1), cScreenHeight - CursorPoint.Y - (SpritesData[PosSprite].Height shr 1),i);
+ DrawSprite(PosSprite, TargetCursorPoint.X - (SpritesData[PosSprite].Width shr 1), cScreenHeight - TargetCursorPoint.Y - (SpritesData[PosSprite].Height shr 1),i);
end;
- DrawSprite(sprArrow, CursorPoint.X, cScreenHeight - CursorPoint.Y, (RealTicks shr 6) mod 8)
+ DrawSprite(sprArrow, TargetCursorPoint.X, cScreenHeight - TargetCursorPoint.Y, (RealTicks shr 6) mod 8)
end
end;
isFirstFrame:= false
@@ -1653,7 +1656,7 @@
var EdgesDist, wdy, shs,z, amNumOffsetX, amNumOffsetY: LongInt;
begin
{$IFNDEF MOBILE}
-if (not (CurrentTeam^.ExtDriven and isCursorVisible and (not bShowAmmoMenu))) and cHasFocus and (GameState <> gsConfirm) then
+if (not (CurrentTeam^.ExtDriven and isCursorVisible and (not bShowAmmoMenu) and autoCameraOn)) and cHasFocus and (GameState <> gsConfirm) then
uCursor.updatePosition();
{$ENDIF}
z:= round(200/zoom);
@@ -1724,7 +1727,8 @@
EdgesDist:= cGearScrEdgesDist;
// this generates the border around the screen that moves the camera when cursor is near it
-if isCursorVisible or ((FollowGear <> nil) and autoCameraOn) then
+if (CurrentTeam^.ExtDriven and isCursorVisible and autoCameraOn) or
+ (not CurrentTeam^.ExtDriven and isCursorVisible) or ((FollowGear <> nil) and autoCameraOn) then
begin
if CursorPoint.X < - cScreenWidth div 2 + EdgesDist then
begin
--- a/project_files/hedgewars.pro Tue Jan 08 21:29:37 2013 +0200
+++ b/project_files/hedgewars.pro Mon Jan 14 12:07:51 2013 +0100
@@ -189,6 +189,8 @@
../QTfrontend/model/roomslistmodel.cpp \
../QTfrontend/ui/dialog/input_password.cpp \
../QTfrontend/ui/widget/colorwidget.cpp \
+ ../QTfrontend/ui/widget/hatbutton.cpp \
+ ../QTfrontend/ui/widget/hatprompt.cpp \
../QTfrontend/model/HatModel.cpp \
../QTfrontend/model/GameStyleModel.cpp \
../QTfrontend/ui/page/pagevideos.cpp \
--- a/share/hedgewars/Data/Maps/Basketball/CMakeLists.txt Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/Basketball/CMakeLists.txt Mon Jan 14 12:07:51 2013 +0100
@@ -4,4 +4,5 @@
map.lua
mask.png
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/Basketball)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/Basketball/desc.txt Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Who said hedgehogs can't|play basketball?
--- a/share/hedgewars/Data/Maps/Basketball/map.cfg Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/Basketball/map.cfg Mon Jan 14 12:07:51 2013 +0100
@@ -1,2 +1,2 @@
Nature
-12
+12
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/CTF_Blizzard/CMakeLists.txt Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/CTF_Blizzard/CMakeLists.txt Mon Jan 14 12:07:51 2013 +0100
@@ -2,4 +2,5 @@
map.cfg
map.lua
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/CTF_Blizzard)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/CTF_Blizzard/desc.txt Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Capture the Flag, blizzard style!
--- a/share/hedgewars/Data/Maps/Control/CMakeLists.txt Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/Control/CMakeLists.txt Mon Jan 14 12:07:51 2013 +0100
@@ -3,4 +3,5 @@
map.lua
map.png
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/Control)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/Control/desc.txt Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Islands scattered everywhere, full set of|weapons.
--- a/share/hedgewars/Data/Maps/Control/map.cfg Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/Control/map.cfg Mon Jan 14 12:07:51 2013 +0100
@@ -1,4 +1,4 @@
Deepspace
48
Default
-Crazy
+Crazy
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/Knockball/CMakeLists.txt Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/Knockball/CMakeLists.txt Mon Jan 14 12:07:51 2013 +0100
@@ -3,4 +3,5 @@
map.cfg
map.lua
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/Knockball)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/Knockball/desc.txt Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Knock your opponents off the platforms|using only a bat!
--- a/share/hedgewars/Data/Maps/TrophyRace/CMakeLists.txt Tue Jan 08 21:29:37 2013 +0200
+++ b/share/hedgewars/Data/Maps/TrophyRace/CMakeLists.txt Mon Jan 14 12:07:51 2013 +0100
@@ -4,4 +4,5 @@
map.png
mask.png
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/TrophyRace)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/TrophyRace/desc.txt Mon Jan 14 12:07:51 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Ready, set, go! Who is going to|be the first in this|crazy race?