use custom model for encounter tables
This commit is contained in:
parent
5309eb5f0e
commit
23d790cc4a
11 changed files with 490 additions and 193 deletions
|
@ -30,6 +30,5 @@ struct EncounterField {
|
|||
typedef QVector<EncounterField> EncounterFields;
|
||||
|
||||
WildMonInfo getDefaultMonInfo(EncounterField field);
|
||||
WildMonInfo copyMonInfoFromTab(QTableWidget *table, EncounterField monField);
|
||||
|
||||
#endif // GUARD_WILDMONINFO_H
|
||||
|
|
45
include/ui/encountertabledelegates.h
Normal file
45
include/ui/encountertabledelegates.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#ifndef ENCOUNTERTABLEDELEGATES_H
|
||||
#define ENCOUNTERTABLEDELEGATES_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
|
||||
class Project;
|
||||
|
||||
class SpeciesComboDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SpeciesComboDelegate(Project *project, QObject *parent = nullptr);
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
Project *project = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SpinBoxDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SpinBoxDelegate(Project *project, QObject *parent = nullptr);
|
||||
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
Project *project = nullptr;
|
||||
};
|
||||
|
||||
#endif // ENCOUNTERTABLEDELEGATES_H
|
50
include/ui/encountertablemodel.h
Normal file
50
include/ui/encountertablemodel.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
#ifndef ENCOUNTERTABLEMODEL_H
|
||||
#define ENCOUNTERTABLEMODEL_H
|
||||
|
||||
#include "wildmoninfo.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
|
||||
class Editor;
|
||||
|
||||
class EncounterTableModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EncounterTableModel(WildMonInfo monInfo, EncounterFields allFields, int fieldIndex, QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
public:
|
||||
enum ColumnType {
|
||||
Slot, Group, Species, MinLevel, MaxLevel, EncounterChance, SlotRatio, EncounterRate, Count
|
||||
};
|
||||
|
||||
WildMonInfo encounterData();
|
||||
void resize(int rows, int cols);
|
||||
|
||||
private:
|
||||
WildMonInfo monInfo;
|
||||
EncounterFields encounterFields;
|
||||
int fieldIndex;
|
||||
|
||||
int numRows = 0;
|
||||
int numCols = 0;
|
||||
|
||||
QList<int> slotRatios;
|
||||
QList<QString> groupNames;
|
||||
QList<double> slotPercentages;
|
||||
|
||||
signals:
|
||||
void edited();
|
||||
};
|
||||
|
||||
#endif // ENCOUNTERTABLEMODEL_H
|
|
@ -17,14 +17,12 @@ public:
|
|||
~MonTabWidget(){};
|
||||
|
||||
void populate();
|
||||
void populateTab(int tabIndex, WildMonInfo monInfo, QString fieldName);
|
||||
void populateTab(int tabIndex, WildMonInfo monInfo);
|
||||
void clear();
|
||||
|
||||
void createSpeciesTableRow(QTableWidget *table, WildPokemon mon, int index, QString fieldName);
|
||||
|
||||
void clearTableAt(int index);
|
||||
|
||||
QTableWidget *tableAt(int tabIndex);
|
||||
QTableView *tableAt(int tabIndex);
|
||||
|
||||
public slots:
|
||||
void setTabActive(int index, bool active = true);
|
||||
|
|
|
@ -70,6 +70,8 @@ SOURCES += src/core/block.cpp \
|
|||
src/ui/noscrollcombobox.cpp \
|
||||
src/ui/noscrollspinbox.cpp \
|
||||
src/ui/montabwidget.cpp \
|
||||
src/ui/encountertablemodel.cpp \
|
||||
src/ui/encountertabledelegates.cpp \
|
||||
src/ui/paletteeditor.cpp \
|
||||
src/ui/selectablepixmapitem.cpp \
|
||||
src/ui/tileseteditor.cpp \
|
||||
|
@ -154,6 +156,8 @@ HEADERS += include/core/block.h \
|
|||
include/ui/noscrollcombobox.h \
|
||||
include/ui/noscrollspinbox.h \
|
||||
include/ui/montabwidget.h \
|
||||
include/ui/encountertablemodel.h \
|
||||
include/ui/encountertabledelegates.h \
|
||||
include/ui/adjustingstackedwidget.h \
|
||||
include/ui/paletteeditor.h \
|
||||
include/ui/selectablepixmapitem.h \
|
||||
|
|
|
@ -14,22 +14,3 @@ WildMonInfo getDefaultMonInfo(EncounterField field) {
|
|||
|
||||
return newInfo;
|
||||
}
|
||||
|
||||
WildMonInfo copyMonInfoFromTab(QTableWidget *monTable, EncounterField monField) {
|
||||
WildMonInfo newInfo;
|
||||
QVector<WildPokemon> newWildMons;
|
||||
|
||||
bool extraColumn = !monField.groups.empty();
|
||||
for (int row = 0; row < monTable->rowCount(); row++) {
|
||||
WildPokemon newWildMon;
|
||||
newWildMon.species = monTable->cellWidget(row, extraColumn ? 2 : 1)->findChild<QComboBox *>()->currentText();
|
||||
newWildMon.minLevel = monTable->cellWidget(row, extraColumn ? 3 : 2)->findChild<QSpinBox *>()->value();
|
||||
newWildMon.maxLevel = monTable->cellWidget(row, extraColumn ? 4 : 3)->findChild<QSpinBox *>()->value();
|
||||
newWildMons.append(newWildMon);
|
||||
}
|
||||
newInfo.active = true;
|
||||
newInfo.wildPokemon = newWildMons;
|
||||
newInfo.encounterRate = monTable->findChild<QSpinBox *>()->value();
|
||||
|
||||
return newInfo;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "mapsceneeventfilter.h"
|
||||
#include "metatile.h"
|
||||
#include "montabwidget.h"
|
||||
#include "encountertablemodel.h"
|
||||
#include "editcommands.h"
|
||||
#include "config.h"
|
||||
#include "scripting.h"
|
||||
|
@ -233,7 +234,7 @@ void Editor::displayWildMonTables() {
|
|||
tabWidget->clearTableAt(tabIndex);
|
||||
|
||||
if (project->wildMonData.contains(map->constantName) && header.wildMons[fieldName].active) {
|
||||
tabWidget->populateTab(tabIndex, header.wildMons[fieldName], fieldName);
|
||||
tabWidget->populateTab(tabIndex, header.wildMons[fieldName]);
|
||||
} else {
|
||||
tabWidget->setTabActive(tabIndex, false);
|
||||
}
|
||||
|
@ -338,7 +339,9 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
|||
if (copyCheckbox->isChecked()) {
|
||||
MonTabWidget *copyFrom = static_cast<MonTabWidget *>(stack->widget(stackIndex));
|
||||
if (copyFrom->isTabEnabled(tabIndex)) {
|
||||
header.wildMons[fieldName] = copyMonInfoFromTab(copyFrom->tableAt(tabIndex), monField);
|
||||
QTableView *monTable = copyFrom->tableAt(tabIndex);
|
||||
EncounterTableModel *model = static_cast<EncounterTableModel *>(monTable->model());
|
||||
header.wildMons[fieldName] = model->encounterData();
|
||||
}
|
||||
else {
|
||||
header.wildMons[fieldName] = getDefaultMonInfo(monField);
|
||||
|
@ -346,7 +349,7 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
|||
} else {
|
||||
header.wildMons[fieldName] = getDefaultMonInfo(monField);
|
||||
}
|
||||
tabWidget->populateTab(tabIndex, header.wildMons[fieldName], fieldName);
|
||||
tabWidget->populateTab(tabIndex, header.wildMons[fieldName]);
|
||||
} else {
|
||||
tabWidget->setTabActive(tabIndex, false);
|
||||
}
|
||||
|
@ -656,14 +659,13 @@ void Editor::saveEncounterTabData() {
|
|||
|
||||
if (!tabWidget->isTabEnabled(fieldIndex++)) continue;
|
||||
|
||||
QTableWidget *monTable = static_cast<QTableWidget *>(tabWidget->widget(fieldIndex - 1));
|
||||
QVector<WildPokemon> newWildMons;
|
||||
encounterHeader.wildMons[fieldName] = copyMonInfoFromTab(monTable, monField);
|
||||
QTableView *monTable = tabWidget->tableAt(fieldIndex - 1);
|
||||
EncounterTableModel *model = static_cast<EncounterTableModel *>(monTable->model());
|
||||
encounterHeader.wildMons[fieldName] = model->encounterData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update encounters for every map based on the new encounter JSON field data.
|
||||
void Editor::updateEncounterFields(EncounterFields newFields) {
|
||||
EncounterFields oldFields = project->wildMonFields;
|
||||
// Go through fields and determine whether we need to update a field.
|
||||
|
|
|
@ -1940,6 +1940,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
selectedObject = current->getPixmapItem();
|
||||
|
||||
QSignalBlocker b(this->ui->spinner_ObjectID);
|
||||
this->ui->spinner_ObjectID->setMinimum(event_offs);
|
||||
this->ui->spinner_ObjectID->setMaximum(current->getMap()->events.value(eventGroup).length() + event_offs - 1);
|
||||
this->ui->spinner_ObjectID->setValue(current->getEventIndex() + event_offs);
|
||||
|
@ -1952,6 +1953,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
selectedWarp = current->getPixmapItem();
|
||||
|
||||
QSignalBlocker b(this->ui->spinner_WarpID);
|
||||
this->ui->spinner_WarpID->setMinimum(event_offs);
|
||||
this->ui->spinner_WarpID->setMaximum(current->getMap()->events.value(eventGroup).length() + event_offs - 1);
|
||||
this->ui->spinner_WarpID->setValue(current->getEventIndex() + event_offs);
|
||||
|
@ -1964,6 +1966,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
selectedTrigger = current->getPixmapItem();
|
||||
|
||||
QSignalBlocker b(this->ui->spinner_TriggerID);
|
||||
this->ui->spinner_TriggerID->setMinimum(event_offs);
|
||||
this->ui->spinner_TriggerID->setMaximum(current->getMap()->events.value(eventGroup).length() + event_offs - 1);
|
||||
this->ui->spinner_TriggerID->setValue(current->getEventIndex() + event_offs);
|
||||
|
@ -1976,6 +1979,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
selectedBG = current->getPixmapItem();
|
||||
|
||||
QSignalBlocker b(this->ui->spinner_BgID);
|
||||
this->ui->spinner_BgID->setMinimum(event_offs);
|
||||
this->ui->spinner_BgID->setMaximum(current->getMap()->events.value(eventGroup).length() + event_offs - 1);
|
||||
this->ui->spinner_BgID->setValue(current->getEventIndex() + event_offs);
|
||||
|
@ -1988,6 +1992,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
selectedHealspot = current->getPixmapItem();
|
||||
|
||||
QSignalBlocker b(this->ui->spinner_HealID);
|
||||
this->ui->spinner_HealID->setMinimum(event_offs);
|
||||
this->ui->spinner_HealID->setMaximum(current->getMap()->events.value(eventGroup).length() + event_offs - 1);
|
||||
this->ui->spinner_HealID->setValue(current->getEventIndex() + event_offs);
|
||||
|
@ -2870,7 +2875,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||
}
|
||||
|
||||
#include <QElapsedTimer>
|
||||
void MainWindow::runSpeedTest() {
|
||||
/*void MainWindow::runSpeedTest() {
|
||||
// 10 iterations of this function:
|
||||
// 1 - load project
|
||||
// 2 - switch map
|
||||
|
@ -2929,4 +2934,51 @@ void MainWindow::runSpeedTest() {
|
|||
summary += "MIN: " + QString::number(min).leftJustified(6, ' ') + "MAX: " + QString::number(max).leftJustified(6, ' ') + "AVG: " + QString::number(avg) + "\n";
|
||||
|
||||
qDebug() << qUtf8Printable(summary);
|
||||
}*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
//#include <cstdlib>
|
||||
void MainWindow::runSpeedTest() {
|
||||
//
|
||||
QList<qint64> times;
|
||||
|
||||
// groupedMapNames
|
||||
QElapsedTimer timer;
|
||||
|
||||
//qDebug() << editor->project->groupedMapNames.first();
|
||||
|
||||
QStringList group0 = editor->project->groupedMapNames.first();
|
||||
|
||||
QString firstMap = group0.first();
|
||||
setMap(firstMap);
|
||||
|
||||
//std::srand(unsigned(std::time(0)));
|
||||
std::shuffle(group0.begin(), group0.end(), std::default_random_engine(69420));
|
||||
|
||||
timer.start();
|
||||
for (QString mapName : group0) {
|
||||
setMap(mapName);
|
||||
times.append(timer.restart());
|
||||
}
|
||||
|
||||
setMap(firstMap);
|
||||
|
||||
qint64 min = std::numeric_limits<qint64>::max();
|
||||
qint64 max = 0;
|
||||
qint64 average = 0;
|
||||
qint64 count = 0;
|
||||
|
||||
for (qint64 val : times) {
|
||||
if (val > max) max = val;
|
||||
if (val < min) min = val;
|
||||
average += val;
|
||||
count++;
|
||||
qDebug() << val;
|
||||
}
|
||||
|
||||
average /= count;
|
||||
|
||||
qDebug() << "*** TIMING SUMMARY ***";
|
||||
qDebug().nospace() << "min: " << min << " " << "max: " << max << " " << "avg: " << average;
|
||||
}
|
||||
|
|
94
src/ui/encountertabledelegates.cpp
Normal file
94
src/ui/encountertabledelegates.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "encountertabledelegates.h"
|
||||
#include "encountertablemodel.h"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include "project.h"
|
||||
#include "noscrollcombobox.h"
|
||||
|
||||
|
||||
|
||||
SpeciesComboDelegate::SpeciesComboDelegate(Project *project, QObject *parent) : QStyledItemDelegate(parent) {
|
||||
this->project = project;
|
||||
}
|
||||
|
||||
void SpeciesComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
|
||||
QString species = index.data(Qt::DisplayRole).toString();
|
||||
|
||||
QPixmap pm;
|
||||
if (!QPixmapCache::find(species, &pm)) {
|
||||
pm.load(this->project->speciesToIconPath.value(species));
|
||||
QPixmapCache::insert(species, pm);
|
||||
}
|
||||
QPixmap monIcon = pm.copy(0, 0, 32, 32);
|
||||
|
||||
painter->drawText(QRect(option.rect.topLeft() + QPoint(36, 0), option.rect.bottomRight()), Qt::AlignLeft | Qt::AlignVCenter, species);
|
||||
painter->drawPixmap(QRect(option.rect.topLeft(), QSize(32, 32)), monIcon, monIcon.rect());
|
||||
}
|
||||
|
||||
QWidget *SpeciesComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const {
|
||||
NoScrollComboBox *editor = new NoScrollComboBox(parent);
|
||||
editor->setFrame(false);
|
||||
editor->addItems(this->project->speciesToIconPath.keys());
|
||||
return editor;
|
||||
}
|
||||
|
||||
void SpeciesComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
|
||||
QString species = index.data(Qt::EditRole).toString();
|
||||
NoScrollComboBox *combo = static_cast<NoScrollComboBox *>(editor);
|
||||
combo->setCurrentText(species);
|
||||
}
|
||||
|
||||
void SpeciesComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
|
||||
NoScrollComboBox *combo = static_cast<NoScrollComboBox *>(editor);
|
||||
QString species = combo->currentText();
|
||||
model->setData(index, species, Qt::EditRole);
|
||||
}
|
||||
|
||||
void SpeciesComboDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const {
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SpinBoxDelegate::SpinBoxDelegate(Project *project, QObject *parent) : QStyledItemDelegate(parent) {
|
||||
this->project = project;
|
||||
}
|
||||
|
||||
QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const {
|
||||
QSpinBox *editor = new QSpinBox(parent);
|
||||
editor->setFrame(false);
|
||||
|
||||
int col = index.column();
|
||||
if (col == EncounterTableModel::ColumnType::MinLevel) {
|
||||
editor->setMinimum(this->project->miscConstants.value("min_level_define").toInt());
|
||||
editor->setMaximum(index.siblingAtColumn(EncounterTableModel::ColumnType::MaxLevel).data(Qt::EditRole).toInt());
|
||||
}
|
||||
else if (col == EncounterTableModel::ColumnType::MaxLevel) {
|
||||
editor->setMinimum(index.siblingAtColumn(EncounterTableModel::ColumnType::MinLevel).data(Qt::EditRole).toInt());
|
||||
editor->setMaximum(this->project->miscConstants.value("max_level_define").toInt());
|
||||
}
|
||||
else if (col == EncounterTableModel::ColumnType::EncounterRate) {
|
||||
editor->setMinimum(0);
|
||||
editor->setMaximum(180);
|
||||
}
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
|
||||
int value = index.model()->data(index, Qt::EditRole).toInt();
|
||||
|
||||
QSpinBox *spinBox = static_cast<QSpinBox *>(editor);
|
||||
spinBox->setValue(value);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
|
||||
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
|
||||
spinBox->interpretText();
|
||||
int value = spinBox->value();
|
||||
model->setData(index, value, Qt::EditRole);
|
||||
}
|
||||
|
||||
void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const {
|
||||
editor->setGeometry(option.rect);
|
||||
}
|
198
src/ui/encountertablemodel.cpp
Normal file
198
src/ui/encountertablemodel.cpp
Normal file
|
@ -0,0 +1,198 @@
|
|||
#include "encountertablemodel.h"
|
||||
#include "editor.h"
|
||||
|
||||
|
||||
|
||||
EncounterTableModel::EncounterTableModel(WildMonInfo info, EncounterFields fields, int index, QObject *parent) : QAbstractTableModel(parent) {
|
||||
this->fieldIndex = index;
|
||||
this->encounterFields = fields;
|
||||
this->monInfo = info;
|
||||
|
||||
this->resize(this->monInfo.wildPokemon.size(), ColumnType::Count);
|
||||
|
||||
this->slotRatios = fields[fieldIndex].encounterRates;
|
||||
|
||||
for (int r = 0; r < this->numRows; r++) {
|
||||
this->groupNames.append(QString());
|
||||
this->slotPercentages.append(0.0);
|
||||
}
|
||||
|
||||
if (!this->encounterFields[this->fieldIndex].groups.empty()) {
|
||||
for (auto groupKeyPair : fields[fieldIndex].groups) {
|
||||
int groupTotal = 0;
|
||||
for (int i : groupKeyPair.second) {
|
||||
this->groupNames[i] = groupKeyPair.first;
|
||||
groupTotal += this->slotRatios[i];
|
||||
}
|
||||
for (int i : groupKeyPair.second) {
|
||||
this->slotPercentages[i] = static_cast<double>(this->slotRatios[i]) / static_cast<double>(groupTotal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int groupTotal = 0;
|
||||
for (int chance : this->encounterFields[this->fieldIndex].encounterRates) {
|
||||
groupTotal += chance;
|
||||
}
|
||||
for (int i = 0; i < this->slotPercentages.count(); i++) {
|
||||
this->slotPercentages[i] = static_cast<double>(this->slotRatios[i]) / static_cast<double>(groupTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EncounterTableModel::resize(int rows, int cols) {
|
||||
this->numRows = rows;
|
||||
this->numCols = cols;
|
||||
}
|
||||
|
||||
int EncounterTableModel::rowCount(const QModelIndex &) const {
|
||||
return this->numRows;
|
||||
}
|
||||
|
||||
int EncounterTableModel::columnCount(const QModelIndex &) const {
|
||||
return this->numCols;
|
||||
}
|
||||
|
||||
QVariant EncounterTableModel::data(const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (col) {
|
||||
case ColumnType::Slot:
|
||||
return row;
|
||||
|
||||
case ColumnType::Group:
|
||||
return this->groupNames[row];
|
||||
|
||||
case ColumnType::Species:
|
||||
return this->monInfo.wildPokemon[row].species;
|
||||
|
||||
case ColumnType::MinLevel:
|
||||
return this->monInfo.wildPokemon[row].minLevel;
|
||||
|
||||
case ColumnType::MaxLevel:
|
||||
return this->monInfo.wildPokemon[row].maxLevel;
|
||||
|
||||
case ColumnType::EncounterChance:
|
||||
return QString::number(this->slotPercentages[row] * 100.0, 'f', 2) + "%";
|
||||
|
||||
case ColumnType::SlotRatio:
|
||||
return this->slotRatios[row];
|
||||
|
||||
case ColumnType::EncounterRate:
|
||||
if (row == 0) {
|
||||
return this->monInfo.encounterRate;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
else if (role == Qt::EditRole) {
|
||||
switch (col) {
|
||||
case ColumnType::Species:
|
||||
return this->monInfo.wildPokemon[row].species;
|
||||
|
||||
case ColumnType::MinLevel:
|
||||
return this->monInfo.wildPokemon[row].minLevel;
|
||||
|
||||
case ColumnType::MaxLevel:
|
||||
return this->monInfo.wildPokemon[row].maxLevel;
|
||||
|
||||
case ColumnType::EncounterRate:
|
||||
if (row == 0) {
|
||||
return this->monInfo.encounterRate;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant EncounterTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
|
||||
switch (section) {
|
||||
case ColumnType::Slot:
|
||||
return QString("Slot");
|
||||
case ColumnType::Group:
|
||||
return QString("Group");
|
||||
case ColumnType::Species:
|
||||
return QString("Species");
|
||||
case ColumnType::MinLevel:
|
||||
return QString("Min Level");
|
||||
case ColumnType::MaxLevel:
|
||||
return QString("Max Level");
|
||||
case ColumnType::EncounterChance:
|
||||
return QString("Encounter Chance");
|
||||
case ColumnType::SlotRatio:
|
||||
return QString("Slot Ratio");
|
||||
case ColumnType::EncounterRate:
|
||||
return QString("Encounter Rate");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool EncounterTableModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (role == Qt::EditRole) {
|
||||
if (!checkIndex(index))
|
||||
return false;
|
||||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
|
||||
switch (col) {
|
||||
case ColumnType::Species:
|
||||
this->monInfo.wildPokemon[row].species = value.toString();
|
||||
break;
|
||||
|
||||
case ColumnType::MinLevel:
|
||||
this->monInfo.wildPokemon[row].minLevel = value.toInt();
|
||||
break;
|
||||
|
||||
case ColumnType::MaxLevel:
|
||||
this->monInfo.wildPokemon[row].maxLevel = value.toInt();
|
||||
break;
|
||||
|
||||
case ColumnType::EncounterRate:
|
||||
this->monInfo.encounterRate = value.toInt();
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
emit edited();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags EncounterTableModel::flags(const QModelIndex &index) const {
|
||||
Qt::ItemFlags flags = Qt::NoItemFlags;
|
||||
switch (index.column()) {
|
||||
case ColumnType::Species:
|
||||
case ColumnType::MinLevel:
|
||||
case ColumnType::MaxLevel:
|
||||
flags |= Qt::ItemIsEditable;
|
||||
break;
|
||||
case ColumnType::EncounterRate:
|
||||
if (index.row() == 0) flags |= Qt::ItemIsEditable;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return flags | QAbstractTableModel::flags(index);
|
||||
}
|
||||
|
||||
WildMonInfo EncounterTableModel::encounterData() {
|
||||
return this->monInfo;
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
#include "montabwidget.h"
|
||||
#include "noscrollcombobox.h"
|
||||
#include "editor.h"
|
||||
#include "encountertablemodel.h"
|
||||
#include "encountertabledelegates.h"
|
||||
|
||||
|
||||
|
||||
MonTabWidget::MonTabWidget(Editor *editor, QWidget *parent) : QTabWidget(parent) {
|
||||
this->editor = editor;
|
||||
|
@ -26,11 +30,7 @@ void MonTabWidget::populate() {
|
|||
activeTabs = QVector<bool>(fields.size(), false);
|
||||
|
||||
for (EncounterField field : fields) {
|
||||
QTableWidget *table = new QTableWidget(this);
|
||||
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
table->setFocusPolicy(Qt::NoFocus);
|
||||
table->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
table->setTabKeyNavigation(false);
|
||||
QTableView *table = new QTableView(this);
|
||||
table->clearFocus();
|
||||
addTab(table, field.name);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ void MonTabWidget::askActivateTab(int tabIndex, QPoint menuPos) {
|
|||
QAction actionActivateTab(QString("Add %1 data for this map...").arg(tabText), this);
|
||||
connect(&actionActivateTab, &QAction::triggered, [=](){
|
||||
clearTableAt(tabIndex);
|
||||
populateTab(tabIndex, getDefaultMonInfo(editor->project->wildMonFields.at(tabIndex)), tabText);
|
||||
populateTab(tabIndex, getDefaultMonInfo(editor->project->wildMonFields.at(tabIndex)));
|
||||
editor->saveEncounterTabData();
|
||||
setCurrentIndex(tabIndex);
|
||||
emit editor->wildMonDataChanged();
|
||||
|
@ -55,173 +55,47 @@ void MonTabWidget::askActivateTab(int tabIndex, QPoint menuPos) {
|
|||
}
|
||||
|
||||
void MonTabWidget::clearTableAt(int tabIndex) {
|
||||
QTableWidget *table = tableAt(tabIndex);
|
||||
QTableView *table = tableAt(tabIndex);
|
||||
if (table) {
|
||||
table->clear();
|
||||
table->setModel(nullptr);
|
||||
table->horizontalHeader()->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void MonTabWidget::populateTab(int tabIndex, WildMonInfo monInfo, QString fieldName) {
|
||||
QTableWidget *speciesTable = tableAt(tabIndex);
|
||||
void MonTabWidget::populateTab(int tabIndex, WildMonInfo monInfo) {
|
||||
QTableView *speciesTable = tableAt(tabIndex);
|
||||
|
||||
int fieldIndex = 0;
|
||||
for (EncounterField field : editor->project->wildMonFields) {
|
||||
if (field.name == fieldName) break;
|
||||
fieldIndex++;
|
||||
EncounterTableModel *model = new EncounterTableModel(monInfo, editor->project->wildMonFields, tabIndex, this);
|
||||
connect(model, &EncounterTableModel::edited, editor, &Editor::saveEncounterTabData);
|
||||
speciesTable->setModel(model);
|
||||
|
||||
speciesTable->setItemDelegateForColumn(EncounterTableModel::ColumnType::Species, new SpeciesComboDelegate(editor->project, this));
|
||||
speciesTable->setItemDelegateForColumn(EncounterTableModel::ColumnType::MinLevel, new SpinBoxDelegate(editor->project, this));
|
||||
speciesTable->setItemDelegateForColumn(EncounterTableModel::ColumnType::MaxLevel, new SpinBoxDelegate(editor->project, this));
|
||||
speciesTable->setItemDelegateForColumn(EncounterTableModel::ColumnType::EncounterRate, new SpinBoxDelegate(editor->project, this));
|
||||
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::Slot, QHeaderView::ResizeToContents );
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::Group, QHeaderView::ResizeToContents );
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::Species, QHeaderView::Stretch);
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::MinLevel, QHeaderView::Stretch);
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::MaxLevel, QHeaderView::Stretch);
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::SlotRatio, QHeaderView::Stretch);
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::EncounterChance, QHeaderView::ResizeToContents);
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(EncounterTableModel::ColumnType::EncounterRate, QHeaderView::ResizeToContents);
|
||||
|
||||
// give enough vertical space for icons + margins
|
||||
speciesTable->verticalHeader()->setMinimumSectionSize(40);
|
||||
|
||||
if (editor->project->wildMonFields[tabIndex].groups.empty()) {
|
||||
speciesTable->setColumnHidden(1, true);
|
||||
}
|
||||
bool insertGroupLabel = false;
|
||||
if (!editor->project->wildMonFields[fieldIndex].groups.empty()) insertGroupLabel = true;
|
||||
|
||||
speciesTable->setRowCount(monInfo.wildPokemon.size());
|
||||
speciesTable->setColumnCount(insertGroupLabel ? 8 : 7);
|
||||
|
||||
QStringList landMonTableHeaders;
|
||||
landMonTableHeaders << "Slot";
|
||||
if (insertGroupLabel) landMonTableHeaders << "Group";
|
||||
landMonTableHeaders << "Species" << "Min Level" << "Max Level"
|
||||
<< "Encounter Chance" << "Slot Ratio" << "Encounter Rate";
|
||||
speciesTable->setHorizontalHeaderLabels(landMonTableHeaders);
|
||||
speciesTable->horizontalHeader()->show();
|
||||
speciesTable->verticalHeader()->hide();
|
||||
speciesTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
speciesTable->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
speciesTable->setShowGrid(false);
|
||||
|
||||
QFrame *encounterFrame = new QFrame;
|
||||
QHBoxLayout *encounterLayout = new QHBoxLayout;
|
||||
|
||||
QSpinBox *encounterRate = new QSpinBox;
|
||||
encounterRate->setMinimum(0);
|
||||
encounterRate->setMaximum(180);
|
||||
encounterRate->setValue(monInfo.encounterRate);
|
||||
connect(encounterRate, QOverload<int>::of(&QSpinBox::valueChanged), [this](int) {
|
||||
editor->saveEncounterTabData();
|
||||
emit editor->wildMonDataChanged();
|
||||
});
|
||||
encounterLayout->addWidget(encounterRate);
|
||||
encounterFrame->setLayout(encounterLayout);
|
||||
speciesTable->setCellWidget(0, insertGroupLabel? 7 : 6, encounterFrame);
|
||||
|
||||
int i = 0;
|
||||
for (WildPokemon mon : monInfo.wildPokemon) {
|
||||
createSpeciesTableRow(speciesTable, mon, i++, fieldName);
|
||||
}
|
||||
this->setTabActive(tabIndex, true);
|
||||
}
|
||||
|
||||
void MonTabWidget::createSpeciesTableRow(QTableWidget *table, WildPokemon mon, int index, QString fieldName) {
|
||||
QPixmap monIcon = QPixmap(editor->project->speciesToIconPath.value(mon.species)).copy(0, 0, 32, 32);
|
||||
|
||||
QLabel *monNum = new QLabel(QString("%1.").arg(QString::number(index)));
|
||||
|
||||
QLabel *monLabel = new QLabel();
|
||||
monLabel->setPixmap(monIcon);
|
||||
|
||||
NoScrollComboBox *monSelector = new NoScrollComboBox;
|
||||
monSelector->addItems(editor->project->speciesToIconPath.keys());
|
||||
monSelector->setCurrentText(mon.species);
|
||||
monSelector->setEditable(true);
|
||||
|
||||
QObject::connect(monSelector, &QComboBox::currentTextChanged, [=](QString newSpecies) {
|
||||
QPixmap monIcon = QPixmap(editor->project->speciesToIconPath.value(newSpecies)).copy(0, 0, 32, 32);
|
||||
monLabel->setPixmap(monIcon);
|
||||
emit editor->wildMonDataChanged();
|
||||
if (!monIcon.isNull()) editor->saveEncounterTabData();
|
||||
});
|
||||
|
||||
QSpinBox *minLevel = new QSpinBox;
|
||||
QSpinBox *maxLevel = new QSpinBox;
|
||||
minLevel->setMinimum(editor->project->miscConstants.value("min_level_define").toInt());
|
||||
minLevel->setMaximum(editor->project->miscConstants.value("max_level_define").toInt());
|
||||
maxLevel->setMinimum(editor->project->miscConstants.value("min_level_define").toInt());
|
||||
maxLevel->setMaximum(editor->project->miscConstants.value("max_level_define").toInt());
|
||||
minLevel->setValue(mon.minLevel);
|
||||
maxLevel->setValue(mon.maxLevel);
|
||||
|
||||
// Connect level spinboxes so max is never less than min.
|
||||
connect(minLevel, QOverload<int>::of(&QSpinBox::valueChanged), [maxLevel, this](int min) {
|
||||
maxLevel->setMinimum(min);
|
||||
editor->saveEncounterTabData();
|
||||
emit editor->wildMonDataChanged();
|
||||
});
|
||||
|
||||
connect(maxLevel, QOverload<int>::of(&QSpinBox::valueChanged), [this](int) {
|
||||
editor->saveEncounterTabData();
|
||||
emit editor->wildMonDataChanged();
|
||||
});
|
||||
|
||||
int fieldIndex = 0;
|
||||
for (EncounterField field : editor->project->wildMonFields) {
|
||||
if (field.name == fieldName) break;
|
||||
fieldIndex++;
|
||||
}
|
||||
|
||||
double slotChanceTotal = 0.0;
|
||||
if (!editor->project->wildMonFields[fieldIndex].groups.empty()) {
|
||||
for (auto groupKeyPair : editor->project->wildMonFields[fieldIndex].groups) {
|
||||
QString groupKey = groupKeyPair.first;
|
||||
if (editor->project->wildMonFields[fieldIndex].groups[groupKey].contains(index)) {
|
||||
for (int chanceIndex : editor->project->wildMonFields[fieldIndex].groups[groupKey]) {
|
||||
slotChanceTotal += static_cast<double>(editor->project->wildMonFields[fieldIndex].encounterRates[chanceIndex]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto chance : editor->project->wildMonFields[fieldIndex].encounterRates) {
|
||||
slotChanceTotal += static_cast<double>(chance);
|
||||
}
|
||||
}
|
||||
|
||||
QLabel *percentLabel = new QLabel(QString("%1%").arg(
|
||||
QString::number(editor->project->wildMonFields[fieldIndex].encounterRates[index] / slotChanceTotal * 100.0, 'f', 2)
|
||||
));
|
||||
QLabel *ratioLabel = new QLabel(QString("%1").arg(
|
||||
QString::number(editor->project->wildMonFields[fieldIndex].encounterRates[index]
|
||||
)));
|
||||
|
||||
QFrame *speciesSelector = new QFrame;
|
||||
QHBoxLayout *speciesSelectorLayout = new QHBoxLayout;
|
||||
speciesSelectorLayout->addWidget(monLabel);
|
||||
speciesSelectorLayout->addWidget(monSelector);
|
||||
speciesSelector->setLayout(speciesSelectorLayout);
|
||||
|
||||
// Prevent the spinboxes from being stupidly tall.
|
||||
QFrame *minLevelFrame = new QFrame;
|
||||
QVBoxLayout *minLevelSpinboxLayout = new QVBoxLayout;
|
||||
minLevelSpinboxLayout->addWidget(minLevel);
|
||||
minLevelFrame->setLayout(minLevelSpinboxLayout);
|
||||
QFrame *maxLevelFrame = new QFrame;
|
||||
QVBoxLayout *maxLevelSpinboxLayout = new QVBoxLayout;
|
||||
maxLevelSpinboxLayout->addWidget(maxLevel);
|
||||
maxLevelFrame->setLayout(maxLevelSpinboxLayout);
|
||||
|
||||
bool insertGroupLabel = false;
|
||||
if (!editor->project->wildMonFields[fieldIndex].groups.empty()) insertGroupLabel = true;
|
||||
table->setCellWidget(index, 0, monNum);
|
||||
if (insertGroupLabel) {
|
||||
QString groupName = QString();
|
||||
for (auto groupKeyPair : editor->project->wildMonFields[fieldIndex].groups) {
|
||||
QString groupKey = groupKeyPair.first;
|
||||
if (editor->project->wildMonFields[fieldIndex].groups[groupKey].contains(index)) {
|
||||
groupName = groupKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
QLabel *groupNameLabel = new QLabel(groupName);
|
||||
table->setCellWidget(index, 1, groupNameLabel);
|
||||
}
|
||||
table->setCellWidget(index, insertGroupLabel? 2 : 1, speciesSelector);
|
||||
table->setCellWidget(index, insertGroupLabel? 3 : 2, minLevelFrame);
|
||||
table->setCellWidget(index, insertGroupLabel? 4 : 3, maxLevelFrame);
|
||||
table->setCellWidget(index, insertGroupLabel? 5 : 4, percentLabel);
|
||||
table->setCellWidget(index, insertGroupLabel? 6 : 5, ratioLabel);
|
||||
}
|
||||
|
||||
QTableWidget *MonTabWidget::tableAt(int tabIndex) {
|
||||
return static_cast<QTableWidget *>(this->widget(tabIndex));
|
||||
QTableView *MonTabWidget::tableAt(int tabIndex) {
|
||||
return static_cast<QTableView *>(this->widget(tabIndex));
|
||||
}
|
||||
|
||||
void MonTabWidget::setTabActive(int index, bool active) {
|
||||
|
|
Loading…
Reference in a new issue