mirror of
https://github.com/Sinbing/cubiomes-viewer.git
synced 2025-01-08 11:47:52 +08:00
Redesigned UI for search tab + moved settings storage
1) sections are now collapsable 2) merged conditions list, 48-bit list was 'replaced' by seed generator 3) added section for 48-bit seed generator: 3a) offers advanced controls 3b) better indication of how the search is managed 3c) includes basic preview of search space size 4) all settings in search-tab are saved in the 'session' 5) added cyclic autosave option for session data 6) session and protobase files moved to system provided config directory 7) config path changed - settings will be created anew
This commit is contained in:
parent
a6a28916b9
commit
b20ba50166
@ -15,7 +15,7 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
||||
if (VERS_PATCH >= 0)
|
||||
text.replace("_PATCH_", QString::number(VERS_PATCH));
|
||||
else
|
||||
text.replace("_PATCH_", "dev");
|
||||
text.replace("_PATCH_", "dev" + QString::number(-1-VERS_PATCH));
|
||||
ui->label->setText(text);
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <QDialog>
|
||||
|
||||
#define VERS_MAJOR 1
|
||||
#define VERS_MINOR 5
|
||||
#define VERS_PATCH 0
|
||||
#define VERS_MINOR 6
|
||||
#define VERS_PATCH -1 // negative patch number designates a development version
|
||||
|
||||
// returns +1 if newer, -1 if older and 0 if equal
|
||||
inline int cmpVers(int major, int minor, int patch)
|
||||
@ -15,7 +15,9 @@ inline int cmpVers(int major, int minor, int patch)
|
||||
if (s) return s;
|
||||
s = (minor > VERS_MINOR) - (minor < VERS_MINOR);
|
||||
if (s) return s;
|
||||
s = (patch > VERS_PATCH) - (patch < VERS_PATCH);
|
||||
int p0 = VERS_PATCH >= 0 ? 1000+VERS_PATCH : -VERS_PATCH;
|
||||
int p1 = patch >= 0 ? 1000+patch : -patch;
|
||||
s = (p1 > p0) - (p1 < p0);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
126
collapsable.cpp
Normal file
126
collapsable.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
#include "collapsable.h"
|
||||
|
||||
#include <QPropertyAnimation>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QFont>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
Collapsable::Collapsable(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, animgroup(new QParallelAnimationGroup(this))
|
||||
, toggleButton(new QToolButton(this))
|
||||
, frameBar(new QFrame(this))
|
||||
, content()
|
||||
, contentHeight()
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
QFont font = toggleButton->font();
|
||||
//font.setPixelSize(12);
|
||||
font.setBold(true);
|
||||
toggleButton->setFont(font);
|
||||
toggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
toggleButton->setCheckable(true);
|
||||
|
||||
|
||||
frameBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
frameBar->setFrameShape(QFrame::HLine);
|
||||
|
||||
QVBoxLayout *vbox = new QVBoxLayout();
|
||||
layoutBar = new QHBoxLayout();
|
||||
layoutBar->addWidget(toggleButton, Qt::AlignBottom);
|
||||
layoutBar->addWidget(frameBar, Qt::AlignCenter);
|
||||
layoutBar->setSpacing(5);
|
||||
vbox->addLayout(layoutBar);
|
||||
|
||||
layoutContent = new QHBoxLayout();
|
||||
layoutContent->setContentsMargins(20, 0, 0, 0);
|
||||
vbox->addLayout(layoutContent);
|
||||
|
||||
vbox->setSizeConstraint(QLayout::SetMaximumSize);
|
||||
vbox->setContentsMargins(0, 0, 0, 8);
|
||||
vbox->setSpacing(0);
|
||||
setLayout(vbox);
|
||||
|
||||
connect(toggleButton, &QToolButton::toggled, this, &Collapsable::toggle);
|
||||
connect(animgroup, &QAbstractAnimation::finished, this, &Collapsable::finishAnimation);
|
||||
}
|
||||
|
||||
void Collapsable::toggle(bool collapsed)
|
||||
{
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
if (collapsed)
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(0);
|
||||
toggleButton->setArrowType(Qt::ArrowType::DownArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Forward);
|
||||
}
|
||||
else
|
||||
{
|
||||
contentHeight = content->size().height();
|
||||
toggleButton->setArrowType(Qt::ArrowType::RightArrow);
|
||||
animgroup->setDirection(QAbstractAnimation::Backward);
|
||||
}
|
||||
|
||||
for (int i = 0, n = animgroup->animationCount(); i < n; i++)
|
||||
{
|
||||
QPropertyAnimation *anim;
|
||||
anim = (QPropertyAnimation*) animgroup->animationAt(i);
|
||||
anim->setStartValue(0);
|
||||
anim->setEndValue(contentHeight);
|
||||
anim->setDuration(150);
|
||||
}
|
||||
|
||||
animgroup->start();
|
||||
}
|
||||
|
||||
void Collapsable::finishAnimation()
|
||||
{
|
||||
if (toggleButton->isChecked())
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(16777215);
|
||||
}
|
||||
}
|
||||
|
||||
void Collapsable::init(const QString& title, QWidget *widget, bool collapsed)
|
||||
{
|
||||
toggleButton->setText(title);
|
||||
toggleButton->setChecked(!collapsed);
|
||||
layoutContent->addWidget(widget);
|
||||
contentHeight = widget->sizeHint().height();
|
||||
content = widget;
|
||||
animgroup->addAnimation(new QPropertyAnimation(content, "minimumHeight"));
|
||||
animgroup->addAnimation(new QPropertyAnimation(content, "maximumHeight"));
|
||||
if (collapsed)
|
||||
{
|
||||
content->setMinimumHeight(0);
|
||||
content->setMaximumHeight(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Collapsable::setInfo(const QString& title, const QString& text)
|
||||
{
|
||||
QPixmap pixmap = QPixmap(":/icons/info.png");
|
||||
QPushButton *button = new QPushButton(pixmap, "", this);
|
||||
button->setStyleSheet("border: none;");
|
||||
button->setIconSize(pixmap.rect().size());
|
||||
button->setToolTip("Show help");
|
||||
|
||||
connect(button, SIGNAL(clicked()), this, SLOT(showInfo()));
|
||||
|
||||
layoutBar->addWidget(button, Qt::AlignLeft);
|
||||
infotitle = title;
|
||||
infomsg = text;
|
||||
}
|
||||
|
||||
void Collapsable::showInfo()
|
||||
{
|
||||
QMessageBox::information(this, infotitle, infomsg, QMessageBox::Ok);
|
||||
}
|
36
collapsable.h
Normal file
36
collapsable.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef COLLAPSABLE_H
|
||||
#define COLLAPSABLE_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QParallelAnimationGroup>
|
||||
#include <QToolButton>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
class Collapsable : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Collapsable(QWidget *parent = nullptr);
|
||||
void init(const QString& title, QWidget *widget, bool collapsed);
|
||||
void setInfo(const QString& title, const QString& text);
|
||||
|
||||
public slots:
|
||||
void toggle(bool collapsed);
|
||||
void finishAnimation();
|
||||
void showInfo();
|
||||
|
||||
public:
|
||||
QParallelAnimationGroup* animgroup;
|
||||
QToolButton* toggleButton;
|
||||
QFrame* frameBar;
|
||||
QWidget *content;
|
||||
QHBoxLayout *layoutBar;
|
||||
QHBoxLayout *layoutContent;
|
||||
|
||||
int contentHeight;
|
||||
QString infotitle;
|
||||
QString infomsg;
|
||||
};
|
||||
|
||||
#endif // COLLAPSABLE_H
|
@ -3,16 +3,6 @@
|
||||
|
||||
#include <QThread>
|
||||
|
||||
void Config::reset()
|
||||
{
|
||||
restoreSession = true;
|
||||
smoothMotion = true;
|
||||
seedsPerItem = 1024;
|
||||
queueSize = QThread::idealThreadCount();
|
||||
maxMatching = 65536;
|
||||
}
|
||||
|
||||
|
||||
ConfigDialog::ConfigDialog(QWidget *parent, Config *config) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ConfigDialog)
|
||||
@ -32,16 +22,20 @@ ConfigDialog::~ConfigDialog()
|
||||
|
||||
void ConfigDialog::initSettings(Config *config)
|
||||
{
|
||||
ui->checkRestore->setChecked(config->restoreSession);
|
||||
ui->checkSmooth->setChecked(config->smoothMotion);
|
||||
ui->checkRestore->setChecked(config->restoreSession);
|
||||
ui->checkAutosave->setChecked(config->autosaveCycle != 0);
|
||||
if (config->autosaveCycle)
|
||||
ui->spinAutosave->setValue(config->autosaveCycle);
|
||||
ui->cboxItemSize->setCurrentText(QString::number(config->seedsPerItem));
|
||||
ui->lineQueueSize->setText(QString::number(config->queueSize));
|
||||
ui->lineMatching->setText(QString::number(config->maxMatching));
|
||||
}
|
||||
|
||||
Config ConfigDialog::getConfig()
|
||||
Config ConfigDialog::getSettings()
|
||||
{
|
||||
conf.restoreSession = ui->checkRestore->isChecked();
|
||||
conf.autosaveCycle = ui->checkAutosave->isChecked() ? ui->spinAutosave->value() : 0;
|
||||
conf.smoothMotion = ui->checkSmooth->isChecked();
|
||||
conf.seedsPerItem = ui->cboxItemSize->currentText().toInt();
|
||||
conf.queueSize = ui->lineQueueSize->text().toInt();
|
||||
|
@ -4,20 +4,13 @@
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class ConfigDialog;
|
||||
}
|
||||
|
||||
struct Config
|
||||
{
|
||||
bool restoreSession;
|
||||
bool smoothMotion;
|
||||
int seedsPerItem;
|
||||
int queueSize;
|
||||
int maxMatching;
|
||||
|
||||
void reset();
|
||||
};
|
||||
|
||||
class ConfigDialog : public QDialog
|
||||
{
|
||||
@ -29,7 +22,7 @@ public:
|
||||
|
||||
void initSettings(Config *config);
|
||||
|
||||
Config getConfig();
|
||||
Config getSettings();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
@ -2,14 +2,6 @@
|
||||
<ui version="4.0">
|
||||
<class>ConfigDialog</class>
|
||||
<widget class="QDialog" name="ConfigDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>411</width>
|
||||
<height>228</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
@ -17,15 +9,40 @@
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/map.png</normaloff>:/icons/map.png</iconset>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkRestore">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Restore previous session at launch</string>
|
||||
<string>Maximum number of matching seeds:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Size of search item queue:
|
||||
(limits usable threads)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Seeds per thread search item:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkSmooth">
|
||||
<property name="toolTip">
|
||||
<string>Simulate innertia for the map view</string>
|
||||
@ -35,44 +52,42 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Seeds per thread search item:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="cboxItemSize"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Size of search item queue:
|
||||
(limits usable threads)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLineEdit" name="lineQueueSize"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkRestore">
|
||||
<property name="text">
|
||||
<string>Maximum number of matching seeds:</string>
|
||||
<string>Restore previous session at launch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="cboxItemSize"/>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="lineMatching"/>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="checkAutosave">
|
||||
<property name="text">
|
||||
<string>Autosave every:</string>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinAutosave">
|
||||
<property name="suffix">
|
||||
<string> min</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
2
cubiomes
2
cubiomes
@ -1 +1 @@
|
||||
Subproject commit ae227c67c283deb0c862e520df092267ac017228
|
||||
Subproject commit 4ec179680619c2f031af08bece760bcd6b9c4b85
|
@ -14,7 +14,7 @@ win32: {
|
||||
}
|
||||
|
||||
QMAKE_CFLAGS = -fwrapv
|
||||
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -std=gnu++11
|
||||
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -std=gnu++11 -Wno-deprecated-copy -Wno-missing-field-initilizers
|
||||
QMAKE_CXXFLAGS_RELEASE *= -O3
|
||||
|
||||
TARGET = cubiomes-viewer
|
||||
@ -36,48 +36,60 @@ CONFIG += static
|
||||
|
||||
SOURCES += \
|
||||
aboutdialog.cpp \
|
||||
collapsable.cpp \
|
||||
configdialog.cpp \
|
||||
formconditions.cpp \
|
||||
formgen48.cpp \
|
||||
formsearchcontrol.cpp \
|
||||
gotodialog.cpp \
|
||||
protobasedialog.cpp \
|
||||
filterdialog.cpp \
|
||||
quadlistdialog.cpp \
|
||||
mainwindow.cpp \
|
||||
mapview.cpp \
|
||||
quad.cpp \
|
||||
search.cpp \
|
||||
searchitem.cpp \
|
||||
searchthread.cpp \
|
||||
mainwindow.cpp \
|
||||
main.cpp
|
||||
|
||||
HEADERS += \
|
||||
configdialog.h \
|
||||
collapsable.h \
|
||||
cubiomes/finders.h \
|
||||
cubiomes/generator.h \
|
||||
cubiomes/javarnd.h \
|
||||
cubiomes/layers.h \
|
||||
cubiomes/util.h \
|
||||
aboutdialog.h \
|
||||
configdialog.h \
|
||||
formconditions.h \
|
||||
formgen48.h \
|
||||
formsearchcontrol.h \
|
||||
gotodialog.h \
|
||||
protobasedialog.h \
|
||||
filterdialog.h \
|
||||
quadlistdialog.h \
|
||||
mainwindow.h \
|
||||
mapview.h \
|
||||
quad.h \
|
||||
cutil.h \
|
||||
search.h \
|
||||
searchitem.h \
|
||||
searchthread.h \
|
||||
seedtables.h
|
||||
seedtables.h \
|
||||
mainwindow.h \
|
||||
settings.h
|
||||
|
||||
FORMS += \
|
||||
aboutdialog.ui \
|
||||
configdialog.ui \
|
||||
formconditions.ui \
|
||||
formgen48.ui \
|
||||
formsearchcontrol.ui \
|
||||
gotodialog.ui \
|
||||
mainwindow.ui \
|
||||
protobasedialog.ui \
|
||||
filterdialog.ui \
|
||||
quadlistdialog.ui
|
||||
quadlistdialog.ui\
|
||||
mainwindow.ui
|
||||
|
||||
RESOURCES += \
|
||||
icons.qrc
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "filterdialog.h"
|
||||
#include "ui_filterdialog.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "cutil.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
@ -40,11 +41,11 @@ static QString getTip(int mc, int layer, int id)
|
||||
}
|
||||
|
||||
|
||||
FilterDialog::FilterDialog(MainWindow *parent, int mcversion, QListWidgetItem *item, Condition *initcond) :
|
||||
QDialog(parent, Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
|
||||
ui(new Ui::FilterDialog),
|
||||
item(item),
|
||||
mc(mcversion)
|
||||
FilterDialog::FilterDialog(FormConditions *parent, int mcversion, QListWidgetItem *item, Condition *initcond)
|
||||
: QDialog(parent, Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint)
|
||||
, ui(new Ui::FilterDialog)
|
||||
, item(item)
|
||||
, mc(mcversion)
|
||||
{
|
||||
memset(&cond, 0, sizeof(cond));
|
||||
ui->setupUi(this);
|
||||
|
@ -5,9 +5,12 @@
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidgetItem>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "search.h"
|
||||
#include "formconditions.h"
|
||||
|
||||
class MainWindow;
|
||||
|
||||
namespace Ui {
|
||||
class FilterDialog;
|
||||
@ -53,14 +56,15 @@ public slots:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FilterDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit FilterDialog(MainWindow *parent, int mc, QListWidgetItem *item = 0, Condition *initcond = 0);
|
||||
~FilterDialog();
|
||||
explicit FilterDialog(FormConditions *parent, int mc, QListWidgetItem *item = 0, Condition *initcond = 0);
|
||||
virtual ~FilterDialog();
|
||||
|
||||
void updateMode();
|
||||
void updateBiomeSelection();
|
||||
|
276
formconditions.cpp
Normal file
276
formconditions.cpp
Normal file
@ -0,0 +1,276 @@
|
||||
#include "formconditions.h"
|
||||
#include "ui_formconditions.h"
|
||||
|
||||
#include "filterdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
QDataStream& operator<<(QDataStream& out, const Condition& v)
|
||||
{
|
||||
out.writeRawData((const char*)&v, sizeof(Condition));
|
||||
return out;
|
||||
}
|
||||
|
||||
QDataStream& operator>>(QDataStream& in, Condition& v)
|
||||
{
|
||||
in.readRawData((char*)&v, sizeof(Condition));
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
FormConditions::FormConditions(MainWindow *parent)
|
||||
: QWidget(parent)
|
||||
, parent(parent)
|
||||
, ui(new Ui::FormConditions)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
qRegisterMetaType< Condition >("Condition");
|
||||
qRegisterMetaTypeStreamOperators< Condition >("Condition");
|
||||
|
||||
QFont mono = QFont("Monospace", 9);
|
||||
mono.setStyleHint(QFont::TypeWriter);
|
||||
ui->listConditionsFull->setFont(mono);
|
||||
}
|
||||
|
||||
FormConditions::~FormConditions()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QVector<Condition> FormConditions::getConditions() const
|
||||
{
|
||||
QVector<Condition> conds;
|
||||
|
||||
for (int i = 0, ie = ui->listConditionsFull->count(); i < ie; i++)
|
||||
conds.push_back(qvariant_cast<Condition>(ui->listConditionsFull->item(i)->data(Qt::UserRole)));
|
||||
|
||||
return conds;
|
||||
}
|
||||
|
||||
|
||||
void FormConditions::updateSensitivity()
|
||||
{
|
||||
int selectcnt = 0;
|
||||
selectcnt += ui->listConditionsFull->selectedItems().size();
|
||||
|
||||
if (selectcnt == 0)
|
||||
{
|
||||
ui->buttonRemove->setEnabled(false);
|
||||
ui->buttonEdit->setEnabled(false);
|
||||
}
|
||||
else if (selectcnt == 1)
|
||||
{
|
||||
ui->buttonRemove->setEnabled(true);
|
||||
ui->buttonEdit->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->buttonRemove->setEnabled(true);
|
||||
ui->buttonEdit->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int FormConditions::getIndex(int idx) const
|
||||
{
|
||||
const QVector<Condition> condvec = getConditions();
|
||||
int cnt[100] = {};
|
||||
for (const Condition& c : condvec)
|
||||
if (c.save > 0 || c.save < 100)
|
||||
cnt[c.save]++;
|
||||
else return 0;
|
||||
if (idx <= 0)
|
||||
idx = 1;
|
||||
if (cnt[idx] == 0)
|
||||
return idx;
|
||||
for (int i = 1; i < 100; i++)
|
||||
if (cnt[i] == 0)
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QListWidgetItem *FormConditions::lockItem(QListWidgetItem *item)
|
||||
{
|
||||
QListWidgetItem *edit = item->clone();
|
||||
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
|
||||
item->setSelected(false);
|
||||
item->setBackground(QColor(Qt::lightGray));
|
||||
edit->setData(Qt::UserRole+1, (qulonglong)item);
|
||||
return edit;
|
||||
}
|
||||
|
||||
bool list_contains(QListWidget *list, QListWidgetItem *item)
|
||||
{
|
||||
if (!item)
|
||||
return false;
|
||||
int n = list->count();
|
||||
for (int i = 0; i < n; i++)
|
||||
if (list->item(i) == item)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// [ID] Condition Cnt Rel Area
|
||||
void FormConditions::setItemCondition(QListWidget *list, QListWidgetItem *item, Condition *cond)
|
||||
{
|
||||
QListWidgetItem *target = (QListWidgetItem*) item->data(Qt::UserRole+1).toULongLong();
|
||||
if (list_contains(list, target) && !(target->flags() & Qt::ItemIsSelectable))
|
||||
{
|
||||
item->setData(Qt::UserRole+1, (qulonglong)0);
|
||||
*target = *item;
|
||||
delete item;
|
||||
item = target;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->addItem(item);
|
||||
cond->save = getIndex(cond->save);
|
||||
}
|
||||
|
||||
const FilterInfo& ft = g_filterinfo.list[cond->type];
|
||||
QString s = QString::asprintf("[%02d] %-28sx%-3d", cond->save, ft.name, cond->count);
|
||||
|
||||
if (cond->relative)
|
||||
s += QString::asprintf("[%02d]+", cond->relative);
|
||||
else
|
||||
s += " ";
|
||||
|
||||
if (ft.coord)
|
||||
s += QString::asprintf("(%d,%d)", cond->x1*ft.step, cond->z1*ft.step);
|
||||
if (ft.area)
|
||||
s += QString::asprintf(",(%d,%d)", (cond->x2+1)*ft.step-1, (cond->z2+1)*ft.step-1);
|
||||
|
||||
if (ft.cat == CAT_48)
|
||||
item->setBackground(QColor(Qt::yellow));
|
||||
else if (ft.cat == CAT_FULL)
|
||||
item->setBackground(QColor(Qt::green));
|
||||
|
||||
item->setText(s);
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(*cond));
|
||||
}
|
||||
|
||||
|
||||
void FormConditions::editCondition(QListWidgetItem *item)
|
||||
{
|
||||
if (!(item->flags() & Qt::ItemIsSelectable))
|
||||
return;
|
||||
int mc = MC_1_16;
|
||||
parent->getSeed(&mc, 0);
|
||||
FilterDialog *dialog = new FilterDialog(this, mc, item, (Condition*)item->data(Qt::UserRole).data());
|
||||
QObject::connect(dialog, SIGNAL(setCond(QListWidgetItem*,Condition)), this, SLOT(addItemCondition(QListWidgetItem*,Condition)), Qt::QueuedConnection);
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
|
||||
static void remove_selected(QListWidget *list)
|
||||
{
|
||||
QList<QListWidgetItem*> selected = list->selectedItems();
|
||||
for (QListWidgetItem *item : selected)
|
||||
{
|
||||
delete list->takeItem(list->row(item));
|
||||
}
|
||||
}
|
||||
|
||||
void FormConditions::on_buttonRemoveAll_clicked()
|
||||
{
|
||||
ui->listConditionsFull->clear();
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::on_buttonRemove_clicked()
|
||||
{
|
||||
remove_selected(ui->listConditionsFull);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::on_buttonEdit_clicked()
|
||||
{
|
||||
QListWidget *list = 0;
|
||||
QListWidgetItem* edit = 0;
|
||||
QList<QListWidgetItem*> selected;
|
||||
|
||||
list = ui->listConditionsFull;
|
||||
selected = list->selectedItems();
|
||||
if (!selected.empty())
|
||||
edit = lockItem(selected.first());
|
||||
|
||||
if (edit)
|
||||
editCondition(edit);
|
||||
}
|
||||
|
||||
void FormConditions::on_buttonAddFilter_clicked()
|
||||
{
|
||||
int mc = MC_1_16;
|
||||
parent->getSeed(&mc, 0);
|
||||
FilterDialog *dialog = new FilterDialog(this, mc);
|
||||
QObject::connect(dialog, SIGNAL(setCond(QListWidgetItem*,Condition)), this, SLOT(addItemCondition(QListWidgetItem*,Condition)), Qt::QueuedConnection);
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_itemDoubleClicked(QListWidgetItem *item)
|
||||
{
|
||||
editCondition(lockItem(item));
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_itemSelectionChanged()
|
||||
{
|
||||
updateSensitivity();
|
||||
}
|
||||
|
||||
void FormConditions::addItemCondition(QListWidgetItem *item, Condition cond)
|
||||
{
|
||||
const FilterInfo& ft = g_filterinfo.list[cond.type];
|
||||
|
||||
if (ft.cat == CAT_FULL)
|
||||
{
|
||||
if (!item)
|
||||
item = new QListWidgetItem();
|
||||
setItemCondition(ui->listConditionsFull, item, &cond);
|
||||
}
|
||||
else if (ft.cat == CAT_48 && item)
|
||||
{
|
||||
setItemCondition(ui->listConditionsFull, item, &cond);
|
||||
}
|
||||
else if (ft.cat == CAT_48 && item == NULL)
|
||||
{
|
||||
item = new QListWidgetItem();
|
||||
setItemCondition(ui->listConditionsFull, item, &cond);
|
||||
|
||||
if (cond.type >= F_QH_IDEAL && cond.type <= F_QH_BARELY)
|
||||
{
|
||||
Condition cq = cond;
|
||||
cq.type = F_HUT;
|
||||
cq.x1 = -128; cq.z1 = -128;
|
||||
cq.x2 = +128; cq.z2 = +128;
|
||||
cq.relative = cond.save;
|
||||
cq.save = cond.save+1;
|
||||
cq.count = 4;
|
||||
QListWidgetItem *item = new QListWidgetItem(ui->listConditionsFull, QListWidgetItem::UserType);
|
||||
setItemCondition(ui->listConditionsFull, item, &cq);
|
||||
}
|
||||
else if (cond.type == F_QM_90 || cond.type == F_QM_95)
|
||||
{
|
||||
Condition cq = cond;
|
||||
cq.type = F_MONUMENT;
|
||||
cq.x1 = -160; cq.z1 = -160;
|
||||
cq.x2 = +160; cq.z2 = +160;
|
||||
cq.relative = cond.save;
|
||||
cq.save = cond.save+1;
|
||||
cq.count = 4;
|
||||
QListWidgetItem *item = new QListWidgetItem(ui->listConditionsFull, QListWidgetItem::UserType);
|
||||
setItemCondition(ui->listConditionsFull, item, &cq);
|
||||
}
|
||||
}
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_indexesMoved(const QModelIndexList &)
|
||||
{
|
||||
emit changed();
|
||||
}
|
55
formconditions.h
Normal file
55
formconditions.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef FORMCONDITIONS_H
|
||||
#define FORMCONDITIONS_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QListWidgetItem>
|
||||
|
||||
#include "searchthread.h"
|
||||
|
||||
namespace Ui {
|
||||
class FormConditions;
|
||||
}
|
||||
|
||||
class MainWindow;
|
||||
|
||||
Q_DECLARE_METATYPE(Condition)
|
||||
|
||||
class FormConditions : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FormConditions(MainWindow *parent);
|
||||
~FormConditions();
|
||||
|
||||
QVector<Condition> getConditions() const;
|
||||
void updateSensitivity();
|
||||
int getIndex(int idx) const;
|
||||
|
||||
QListWidgetItem *lockItem(QListWidgetItem *item);
|
||||
void setItemCondition(QListWidget *list, QListWidgetItem *item, Condition *cond);
|
||||
void editCondition(QListWidgetItem *item);
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
public slots:
|
||||
void on_buttonRemoveAll_clicked();
|
||||
void on_buttonRemove_clicked();
|
||||
void on_buttonEdit_clicked();
|
||||
void on_buttonAddFilter_clicked();
|
||||
|
||||
void on_listConditionsFull_itemDoubleClicked(QListWidgetItem *item);
|
||||
void on_listConditionsFull_itemSelectionChanged();
|
||||
|
||||
void addItemCondition(QListWidgetItem *item, Condition cond);
|
||||
|
||||
private slots:
|
||||
void on_listConditionsFull_indexesMoved(const QModelIndexList &indexes);
|
||||
|
||||
private:
|
||||
MainWindow *parent;
|
||||
Ui::FormConditions *ui;
|
||||
};
|
||||
|
||||
#endif // FORMCONDITIONS_H
|
94
formconditions.ui
Normal file
94
formconditions.ui
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FormConditions</class>
|
||||
<widget class="QWidget" name="FormConditions">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>420</width>
|
||||
<height>221</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="buttonRemoveAll">
|
||||
<property name="text">
|
||||
<string>Remove all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="buttonRemove">
|
||||
<property name="text">
|
||||
<string>Remove selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="buttonEdit">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="buttonAddFilter">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QListWidget" name="listConditionsFull">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="movement">
|
||||
<enum>QListView::Snap</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
352
formgen48.cpp
Normal file
352
formgen48.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
#include "formgen48.h"
|
||||
#include "ui_formgen48.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "search.h"
|
||||
#include "seedtables.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
FormGen48::FormGen48(MainWindow *parent)
|
||||
: QWidget(parent)
|
||||
, parent(parent)
|
||||
, ui(new Ui::FormGen48)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QIntValidator *intval = new QIntValidator(this);
|
||||
ui->lineSalt->setValidator(intval);
|
||||
ui->lineEditX1->setValidator(intval);
|
||||
ui->lineEditZ1->setValidator(intval);
|
||||
ui->lineEditX2->setValidator(intval);
|
||||
ui->lineEditZ2->setValidator(intval);
|
||||
|
||||
QFont mono = QFont("Monospace", 9);
|
||||
mono.setStyleHint(QFont::TypeWriter);
|
||||
ui->lineList48->setFont(mono);
|
||||
|
||||
cond.type = 0;
|
||||
Gen48Settings defaults;
|
||||
setSettings(defaults, true);
|
||||
}
|
||||
|
||||
FormGen48::~FormGen48()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool FormGen48::setList48(QString path, bool quiet)
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
if (!path.isEmpty())
|
||||
{
|
||||
QFileInfo finfo(path);
|
||||
slist48path = path;
|
||||
parent->prevdir = finfo.absolutePath();
|
||||
|
||||
int64_t *l = NULL;
|
||||
int64_t len;
|
||||
QByteArray ba = path.toLatin1();
|
||||
l = loadSavedSeeds(ba.data(), &len);
|
||||
if (l && len > 0)
|
||||
{
|
||||
slist48.assign(l, l+len);
|
||||
free(l);
|
||||
ui->lineList48->setText("[" + QString::number(len) + " seeds] " + finfo.baseName());
|
||||
ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!quiet)
|
||||
QMessageBox::warning(this, "Warning", "Failed to load seed list from file", QMessageBox::Ok);
|
||||
ui->lineList48->setText("[no seeds!] " + finfo.baseName());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
slist48path.clear();
|
||||
ui->lineList48->setText("[none]");
|
||||
slist48.clear();
|
||||
}
|
||||
emit changed();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void FormGen48::setSettings(const Gen48Settings& gen48, bool quiet)
|
||||
{
|
||||
ui->comboMode->setCurrentIndex(gen48.mode);
|
||||
ui->comboLow20->setCurrentIndex(gen48.qual);
|
||||
ui->spinMonumentArea->setValue(gen48.qmarea);
|
||||
ui->lineSalt->setText(QString::number(gen48.salt));
|
||||
ui->lineEditX1->setText(QString::number(gen48.x1));
|
||||
ui->lineEditZ1->setText(QString::number(gen48.z1));
|
||||
ui->lineEditX2->setText(QString::number(gen48.x2));
|
||||
ui->lineEditZ2->setText(QString::number(gen48.z2));
|
||||
|
||||
setList48(gen48.slist48path, quiet);
|
||||
|
||||
if (gen48.manualarea)
|
||||
ui->radioManual->setChecked(true);
|
||||
else
|
||||
ui->radioAuto->setChecked(true);
|
||||
|
||||
on_comboMode_currentIndexChanged(gen48.mode);
|
||||
}
|
||||
|
||||
Gen48Settings FormGen48::getSettings(bool resolveauto)
|
||||
{
|
||||
Gen48Settings s;
|
||||
|
||||
s.mode = ui->comboMode->currentIndex();
|
||||
s.qual = ui->comboLow20->currentIndex();
|
||||
s.qmarea = ui->spinMonumentArea->value();
|
||||
s.salt = ui->lineSalt->text().toLongLong();
|
||||
s.manualarea = ui->radioManual->isChecked();
|
||||
s.x1 = ui->lineEditX1->text().toInt();
|
||||
s.z1 = ui->lineEditZ1->text().toInt();
|
||||
s.x2 = ui->lineEditX2->text().toInt();
|
||||
s.z2 = ui->lineEditZ2->text().toInt();
|
||||
|
||||
s.slist48path = slist48path;
|
||||
|
||||
if (resolveauto)
|
||||
{
|
||||
if (s.mode == GEN48_AUTO)
|
||||
{
|
||||
bool isqh = cond.type >= F_QH_IDEAL && cond.type <= F_QH_BARELY;
|
||||
bool isqm = cond.type >= F_QM_95 && cond.type <= F_QM_90;
|
||||
if (isqh) s.mode = GEN48_QH;
|
||||
if (isqm) s.mode = GEN48_QM;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
uint64_t FormGen48::estimateSeedCnt()
|
||||
{
|
||||
const Gen48Settings& gen48 = getSettings(true);
|
||||
uint64_t cnt = 0;
|
||||
if (gen48.mode == GEN48_QH)
|
||||
{
|
||||
switch (gen48.qual)
|
||||
{ // simply hardcoded number of seeds in each category
|
||||
case IDEAL_SALTED: // falltrough
|
||||
case IDEAL: cnt = 74474; break;
|
||||
case CLASSIC: cnt = 107959; break;
|
||||
case NORMAL: cnt = 293716; break;
|
||||
case BARELY: cnt = 755745; break;
|
||||
default: cnt = 0;
|
||||
}
|
||||
}
|
||||
else if (gen48.mode == GEN48_QM)
|
||||
{
|
||||
cnt = 0;
|
||||
for (int i = 0, n = sizeof(g_qm_90) / sizeof(int64_t); i < n; i++)
|
||||
if (qmonumentQual(g_qm_90[i]) >= gen48.qmarea)
|
||||
cnt++;
|
||||
}
|
||||
else if (gen48.mode == GEN48_LIST)
|
||||
{
|
||||
cnt = this->slist48.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt = MASK48+1;
|
||||
}
|
||||
|
||||
if (gen48.mode != GEN48_NONE)
|
||||
{
|
||||
uint64_t w = gen48.x2 - gen48.x1 + 1;
|
||||
uint64_t h = gen48.z2 - gen48.z1 + 1;
|
||||
uint64_t n = w*h * cnt;
|
||||
if (cnt > 0 && n < PRECOMPUTE48_BUFSIZ*sizeof(int64_t) && n / cnt == w*h)
|
||||
cnt = n;
|
||||
else
|
||||
cnt = MASK48+1;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void FormGen48::updateCount()
|
||||
{
|
||||
uint64_t cnt = estimateSeedCnt();
|
||||
|
||||
if (cnt >= MASK48+1)
|
||||
{
|
||||
ui->labelCount->setText("all");
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t total = cnt << 16;
|
||||
ui->labelCount->setText(QString::asprintf("%" PRIu64 " * 65536 = %" PRIu64, cnt, total));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FormGen48::updateAutoConditions(const QVector<Condition>& condlist)
|
||||
{
|
||||
cond.type = 0;
|
||||
for (const Condition& c : condlist)
|
||||
{
|
||||
const FilterInfo& finfo = g_filterinfo.list[c.type];
|
||||
if (finfo.cat == CAT_48)
|
||||
{
|
||||
cond = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateAutoUi();
|
||||
}
|
||||
|
||||
void FormGen48::updateAutoUi()
|
||||
{
|
||||
QString modestr = "[Auto]";
|
||||
bool isqh = cond.type >= F_QH_IDEAL && cond.type <= F_QH_BARELY;
|
||||
bool isqm = cond.type >= F_QM_95 && cond.type <= F_QM_90;
|
||||
if (isqh)
|
||||
modestr += " (Quad-hut)";
|
||||
else if (isqm)
|
||||
modestr += " (Quad-monument)";
|
||||
|
||||
ui->comboMode->setItemText(GEN48_AUTO, modestr);
|
||||
|
||||
if (cond.type != 0)
|
||||
{
|
||||
if (ui->comboMode->currentIndex() == GEN48_AUTO)
|
||||
{
|
||||
ui->radioAuto->setChecked(true);
|
||||
|
||||
if (isqh)
|
||||
ui->comboLow20->setCurrentIndex(cond.type - F_QH_IDEAL);
|
||||
else if (isqm)
|
||||
ui->spinMonumentArea->setValue((int) ceil( 58*58*4 * (cond.type == F_QM_95 ? 0.95 : 0.90) ));
|
||||
}
|
||||
if (ui->radioAuto->isChecked())
|
||||
{
|
||||
ui->lineEditX1->setText(QString::number(cond.x1));
|
||||
ui->lineEditZ1->setText(QString::number(cond.z1));
|
||||
ui->lineEditX2->setText(QString::number(cond.x2));
|
||||
ui->lineEditZ2->setText(QString::number(cond.z2));
|
||||
}
|
||||
}
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormGen48::setPathEnabled(bool enabled)
|
||||
{
|
||||
ui->buttonBrowse->setEnabled(enabled);
|
||||
ui->lineList48->setEnabled(enabled);
|
||||
ui->labelPath->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void FormGen48::setSaltEnabled(bool enabled)
|
||||
{
|
||||
ui->lineSalt->setEnabled(enabled);
|
||||
ui->labelSalt->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void FormGen48::setAreaEnabled(bool enabled)
|
||||
{
|
||||
ui->labelTranspose->setEnabled(enabled);
|
||||
ui->radioAuto->setEnabled(enabled);
|
||||
ui->radioManual->setEnabled(enabled);
|
||||
|
||||
enabled &= ui->radioManual->isChecked();
|
||||
ui->labelX1->setEnabled(enabled);
|
||||
ui->labelZ1->setEnabled(enabled);
|
||||
ui->labelX2->setEnabled(enabled);
|
||||
ui->labelZ2->setEnabled(enabled);
|
||||
ui->lineEditX1->setEnabled(enabled);
|
||||
ui->lineEditZ1->setEnabled(enabled);
|
||||
ui->lineEditX2->setEnabled(enabled);
|
||||
ui->lineEditZ2->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void FormGen48::setQualEnabled(bool enabled)
|
||||
{
|
||||
ui->comboLow20->setEnabled(enabled);
|
||||
ui->labelLow20->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void FormGen48::setQMEnabled(bool enabled)
|
||||
{
|
||||
ui->spinMonumentArea->setEnabled(enabled);
|
||||
ui->labelQM->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void FormGen48::updateMode()
|
||||
{
|
||||
int mode = ui->comboMode->currentIndex();
|
||||
int qual = ui->comboLow20->currentIndex();
|
||||
|
||||
if (mode == GEN48_AUTO)
|
||||
{
|
||||
updateAutoUi();
|
||||
}
|
||||
|
||||
if (mode == GEN48_AUTO || mode == GEN48_NONE)
|
||||
{
|
||||
setAreaEnabled(false);
|
||||
setPathEnabled(false);
|
||||
setSaltEnabled(false);
|
||||
setQualEnabled(false);
|
||||
setQMEnabled(false);
|
||||
}
|
||||
else if (mode == GEN48_QH && qual == IDEAL_SALTED)
|
||||
{
|
||||
setAreaEnabled(true);
|
||||
setPathEnabled(false);
|
||||
setSaltEnabled(true);
|
||||
setQualEnabled(true);
|
||||
setQMEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
setAreaEnabled(true);
|
||||
setPathEnabled(mode == GEN48_LIST);
|
||||
setSaltEnabled(mode == GEN48_LIST);
|
||||
setQualEnabled(mode == GEN48_QH);
|
||||
setQMEnabled(mode == GEN48_QM);
|
||||
}
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormGen48::on_comboMode_currentIndexChanged(int)
|
||||
{
|
||||
updateMode();
|
||||
}
|
||||
|
||||
void FormGen48::on_comboLow20_currentIndexChanged(int)
|
||||
{
|
||||
updateMode();
|
||||
}
|
||||
|
||||
void FormGen48::on_buttonBrowse_clicked()
|
||||
{
|
||||
QString fnam = QFileDialog::getOpenFileName(this, "Load seed list", parent->prevdir, "Text files (*.txt);;Any files (*)");
|
||||
if (!fnam.isEmpty())
|
||||
setList48(fnam, false);
|
||||
}
|
||||
|
||||
void FormGen48::on_radioAuto_toggled()
|
||||
{
|
||||
setAreaEnabled(true);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormGen48::on_spinMonumentArea_editingFinished()
|
||||
{
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormGen48::on_lineSalt_editingFinished()
|
||||
{
|
||||
emit changed();
|
||||
}
|
71
formgen48.h
Normal file
71
formgen48.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef FORMGEN48_H
|
||||
#define FORMGEN48_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QThread>
|
||||
|
||||
#include "settings.h"
|
||||
#include "search.h"
|
||||
|
||||
namespace Ui {
|
||||
class FormGen48;
|
||||
}
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class FormGen48 : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FormGen48(MainWindow *parent);
|
||||
~FormGen48();
|
||||
|
||||
void setSettings(const Gen48Settings& gen48, bool quiet);
|
||||
Gen48Settings getSettings(bool resolveauto = false);
|
||||
|
||||
bool setList48(QString path, bool quiet);
|
||||
const std::vector<int64_t>& getList48() { return slist48; }
|
||||
|
||||
uint64_t estimateSeedCnt();
|
||||
void updateCount();
|
||||
|
||||
void updateAutoConditions(const QVector<Condition>& condlist);
|
||||
void updateAutoUi();
|
||||
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
private:
|
||||
void setPathEnabled(bool enabled);
|
||||
void setSaltEnabled(bool enabled);
|
||||
void setAreaEnabled(bool enabled);
|
||||
void setQualEnabled(bool enabled);
|
||||
void setQMEnabled(bool enabled);
|
||||
|
||||
void updateMode();
|
||||
|
||||
private slots:
|
||||
void on_comboMode_currentIndexChanged(int idx);
|
||||
void on_comboLow20_currentIndexChanged(int idx);
|
||||
|
||||
void on_buttonBrowse_clicked();
|
||||
|
||||
void on_radioAuto_toggled();
|
||||
|
||||
void on_spinMonumentArea_editingFinished();
|
||||
|
||||
void on_lineSalt_editingFinished();
|
||||
|
||||
private:
|
||||
MainWindow *parent;
|
||||
Ui::FormGen48 *ui;
|
||||
|
||||
// main condition for "auto" mode (updated when conditions change)
|
||||
Condition cond;
|
||||
|
||||
QString slist48path;
|
||||
std::vector<int64_t> slist48;
|
||||
};
|
||||
|
||||
#endif // FORMGEN48_H
|
407
formgen48.ui
Normal file
407
formgen48.ui
Normal file
@ -0,0 +1,407 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FormGen48</class>
|
||||
<widget class="QWidget" name="FormGen48">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>428</width>
|
||||
<height>251</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="10" column="2" colspan="4">
|
||||
<widget class="QLabel" name="labelCount">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="6">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelTranspose">
|
||||
<property name="text">
|
||||
<string>Transpose by regions (multiplied by x512):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QRadioButton" name="radioAuto">
|
||||
<property name="text">
|
||||
<string>Auto</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QRadioButton" name="radioManual">
|
||||
<property name="text">
|
||||
<string>Manual</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="5">
|
||||
<widget class="QComboBox" name="comboMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>[Auto]</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-feature</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-monument</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Seed list</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>[None] (All seeds)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="5">
|
||||
<widget class="QComboBox" name="comboLow20">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-hut (ideal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-hut (classic)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-hut (normal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-hut (barely)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Quad-feature (ideal, custom salt)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="5">
|
||||
<widget class="QLineEdit" name="lineSalt">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelMode">
|
||||
<property name="text">
|
||||
<string>Generator mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelPath">
|
||||
<property name="toolTip">
|
||||
<string>Use a custom seed list as source for 48-bit seed candidates</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load 48-bit seed list:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="5">
|
||||
<widget class="QSpinBox" name="spinMonumentArea">
|
||||
<property name="minimum">
|
||||
<number>12115</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>13028</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>13028</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="4">
|
||||
<widget class="QLineEdit" name="lineList48">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelLow20">
|
||||
<property name="toolTip">
|
||||
<string>Selects a set of values for the lower 20-bits of the seed, corresponding to quad-feature constellations
|
||||
Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in particular swamp-huts</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Restrict lower bits:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QLabel" name="labelSpace">
|
||||
<property name="text">
|
||||
<string>Seeds in search space:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="6">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelX1">
|
||||
<property name="toolTip">
|
||||
<string>Lower bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X<sub>1</sub>=</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEditX1">
|
||||
<property name="toolTip">
|
||||
<string>Lower bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelZ1">
|
||||
<property name="toolTip">
|
||||
<string>Lower bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Z<sub>1</sub>=</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEditZ1">
|
||||
<property name="toolTip">
|
||||
<string>Lower bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelX2">
|
||||
<property name="toolTip">
|
||||
<string>Upper bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>X<sub>2</sub>=</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEditX2">
|
||||
<property name="toolTip">
|
||||
<string>Upper bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelZ2">
|
||||
<property name="toolTip">
|
||||
<string>Upper bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Z<sub>2</sub>=</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEditZ2">
|
||||
<property name="toolTip">
|
||||
<string>Upper bound (inclusive)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelSalt">
|
||||
<property name="toolTip">
|
||||
<string>Value (such as a structure salt) added to the 48-bit seeds</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add structure salt:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QPushButton" name="buttonBrowse">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelQM">
|
||||
<property name="toolTip">
|
||||
<string>Number of planar spawning spaces inside monuments that are within 128 blocks of a center position
|
||||
(i.e. this is a measure quality, out of 4*58*58)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Min. monument area:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
457
formsearchcontrol.cpp
Normal file
457
formsearchcontrol.cpp
Normal file
@ -0,0 +1,457 @@
|
||||
#include "formsearchcontrol.h"
|
||||
#include "ui_formsearchcontrol.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "search.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QClipboard>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
FormSearchControl::FormSearchControl(MainWindow *parent)
|
||||
: QWidget(parent)
|
||||
, parent(parent)
|
||||
, ui(new Ui::FormSearchControl)
|
||||
, sthread(this)
|
||||
, stimer()
|
||||
, slist64path()
|
||||
, slist64()
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QFont mono = QFont("Monospace", 9);
|
||||
mono.setStyleHint(QFont::TypeWriter);
|
||||
ui->listResults->setFont(mono);
|
||||
ui->progressBar->setFont(mono);
|
||||
|
||||
//connect(&sthread, &SearchThread::results, this, &MainWindow::searchResultsAdd, Qt::BlockingQueuedConnection);
|
||||
connect(&sthread, &SearchThread::progress, this, &FormSearchControl::searchProgress, Qt::QueuedConnection);
|
||||
connect(&sthread, &SearchThread::searchFinish, this, &FormSearchControl::searchFinish, Qt::QueuedConnection);
|
||||
|
||||
connect(&stimer, &QTimer::timeout, this, QOverload<>::of(&FormSearchControl::resultTimeout));
|
||||
stimer.start(500);
|
||||
|
||||
searchProgressReset();
|
||||
ui->spinThreads->setMaximum(QThread::idealThreadCount());
|
||||
ui->spinThreads->setValue(QThread::idealThreadCount());
|
||||
|
||||
searchLockUi(false);
|
||||
}
|
||||
|
||||
FormSearchControl::~FormSearchControl()
|
||||
{
|
||||
stimer.stop();
|
||||
sthread.stop(); // tell search to stop at next convenience
|
||||
sthread.quit(); // tell the event loop to exit
|
||||
sthread.wait(); // wait for search to finish
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QVector<int64_t> FormSearchControl::getResults()
|
||||
{
|
||||
int n = ui->listResults->rowCount();
|
||||
QVector<int64_t> results = QVector<int64_t>(n);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
results[i] = ui->listResults->item(i, 0)->data(Qt::UserRole).toLongLong();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
SearchConfig FormSearchControl::getSearchConfig()
|
||||
{
|
||||
SearchConfig s;
|
||||
s.searchmode = ui->comboSearchType->currentIndex();
|
||||
s.threads = ui->spinThreads->value();
|
||||
s.slist64path = slist64path;
|
||||
s.startseed = ui->lineStart->text().toLongLong();
|
||||
s.stoponres = ui->checkStop->isChecked();
|
||||
return s;
|
||||
}
|
||||
|
||||
bool FormSearchControl::setSearchConfig(SearchConfig s, bool quiet)
|
||||
{
|
||||
bool ok = true;
|
||||
if (s.searchmode >= SEARCH_INC && s.searchmode <= SEARCH_LIST)
|
||||
ui->comboSearchType->setCurrentIndex(s.searchmode);
|
||||
else
|
||||
ok = false;
|
||||
|
||||
ui->spinThreads->setValue(s.threads);
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, s.startseed));
|
||||
ui->checkStop->setChecked(s.stoponres);
|
||||
|
||||
return ok && setList64(s.slist64path, quiet);
|
||||
}
|
||||
|
||||
bool FormSearchControl::isbusy()
|
||||
{
|
||||
return ui->buttonStart->isChecked() || sthread.isRunning();
|
||||
}
|
||||
|
||||
bool FormSearchControl::setList64(QString path, bool quiet)
|
||||
{
|
||||
if (!path.isEmpty())
|
||||
{
|
||||
QFileInfo finfo(path);
|
||||
parent->prevdir = finfo.absolutePath();
|
||||
slist64path = finfo.fileName();
|
||||
int64_t *l = NULL;
|
||||
int64_t len;
|
||||
QByteArray ba = path.toLatin1();
|
||||
l = loadSavedSeeds(ba.data(), &len);
|
||||
if (l && len > 0)
|
||||
{
|
||||
slist64.assign(l, l+len);
|
||||
searchProgress(0, len, l[0]);
|
||||
free(l);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!quiet)
|
||||
QMessageBox::warning(this, "Warning", "Failed to load seed list from file", QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FormSearchControl::searchLockUi(bool lock)
|
||||
{
|
||||
if (lock)
|
||||
{
|
||||
ui->comboSearchType->setEnabled(false);
|
||||
ui->spinThreads->setEnabled(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->buttonStart->setText("Start search");
|
||||
ui->buttonStart->setIcon(QIcon(":/icons/search.png"));
|
||||
ui->buttonStart->setChecked(false);
|
||||
ui->buttonStart->setEnabled(true);
|
||||
ui->comboSearchType->setEnabled(true);
|
||||
ui->spinThreads->setEnabled(true);
|
||||
}
|
||||
emit searchStatusChanged(lock);
|
||||
}
|
||||
|
||||
void FormSearchControl::setSearchMode(int mode)
|
||||
{
|
||||
ui->comboSearchType->setCurrentIndex(mode);
|
||||
if (mode == SEARCH_LIST)
|
||||
{
|
||||
on_buttonLoadList_clicked();
|
||||
}
|
||||
else
|
||||
{
|
||||
slist64.clear();
|
||||
slist64path.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FormSearchControl::on_buttonClear_clicked()
|
||||
{
|
||||
ui->listResults->clearContents();
|
||||
ui->listResults->setRowCount(0);
|
||||
searchProgressReset();
|
||||
}
|
||||
|
||||
void FormSearchControl::on_buttonStart_clicked()
|
||||
{
|
||||
if (ui->buttonStart->isChecked())
|
||||
{
|
||||
int mc = MC_1_16;
|
||||
parent->getSeed(&mc, NULL);
|
||||
const Config& config = parent->config;
|
||||
const QVector<Condition>& condvec = parent->formCond->getConditions();
|
||||
int64_t sstart = (int64_t) ui->lineStart->text().toLongLong();
|
||||
int searchtype = ui->comboSearchType->currentIndex();
|
||||
int threads = ui->spinThreads->value();
|
||||
int ok = true;
|
||||
|
||||
if (condvec.empty())
|
||||
{
|
||||
QMessageBox::warning(this, "Warning", "Please define some constraints using the \"Add\" button.", QMessageBox::Ok);
|
||||
ok = false;
|
||||
}
|
||||
if (searchtype == SEARCH_LIST && slist64.empty())
|
||||
{
|
||||
QMessageBox::warning(this, "Warning", "No seed list file selected.", QMessageBox::Ok);
|
||||
ok = false;
|
||||
}
|
||||
if (sthread.isRunning())
|
||||
{
|
||||
QMessageBox::warning(this, "Warning", "Search is still running.", QMessageBox::Ok);
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
Gen48Settings gen48 = parent->formGen48->getSettings(true);
|
||||
// the search can either use a full list or a 48-bit list
|
||||
if (searchtype == SEARCH_LIST)
|
||||
slist = slist64;
|
||||
else if (gen48.mode == GEN48_LIST)
|
||||
slist = parent->formGen48->getList48();
|
||||
else
|
||||
slist.clear();
|
||||
|
||||
ok = sthread.set(parent, searchtype, threads, gen48, slist, sstart, mc, condvec, config.seedsPerItem, config.queueSize);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, sstart));
|
||||
ui->buttonStart->setText("Abort search");
|
||||
ui->buttonStart->setIcon(QIcon(":/icons/cancel.png"));
|
||||
sthread.start();
|
||||
searchLockUi(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->buttonStart->setChecked(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sthread.stop(); // tell search to stop at next convenience
|
||||
//sthread.quit(); // tell the event loop to exit
|
||||
//sthread.wait(); // wait for search to finish
|
||||
ui->buttonStart->setText("Start search");
|
||||
ui->buttonStart->setIcon(QIcon(":/icons/search.png"));
|
||||
ui->buttonStart->setChecked(false);
|
||||
|
||||
// disable until finish
|
||||
ui->buttonStart->setEnabled(false);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void FormSearchControl::on_buttonLoadList_clicked()
|
||||
{
|
||||
QString fnam = QFileDialog::getOpenFileName(this, "Load seed list", parent->prevdir, "Text files (*.txt);;Any files (*)");
|
||||
setList64(fnam, false);
|
||||
}
|
||||
|
||||
void FormSearchControl::on_listResults_itemSelectionChanged()
|
||||
{
|
||||
int row = ui->listResults->currentRow();
|
||||
if (row >= 0 && row < ui->listResults->rowCount())
|
||||
{
|
||||
int64_t s = ui->listResults->item(row, 0)->data(Qt::UserRole).toLongLong();
|
||||
emit selectedSeedChanged(s);
|
||||
}
|
||||
}
|
||||
|
||||
void FormSearchControl::on_listResults_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QMenu menu(this);
|
||||
|
||||
QAction *actremove = menu.addAction(QIcon::fromTheme("list-remove"), "Remove selected seed", this, &FormSearchControl::removeCurrent);
|
||||
actremove->setEnabled(!ui->listResults->selectedItems().empty());
|
||||
|
||||
QAction *actcopy = menu.addAction(QIcon::fromTheme("edit-copy"), "Copy list to clipboard", this, &FormSearchControl::copyResults);
|
||||
actcopy->setEnabled(ui->listResults->rowCount() > 0);
|
||||
|
||||
int n = pasteList(true);
|
||||
QAction *actpaste = menu.addAction(QIcon::fromTheme("edit-paste"), QString::asprintf("Paste %d seeds from clipboard", n), this, &FormSearchControl::pasteResults);
|
||||
actpaste->setEnabled(n > 0);
|
||||
menu.exec(ui->listResults->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void FormSearchControl::on_buttonSearchHelp_clicked()
|
||||
{
|
||||
const char* msg =
|
||||
"<html><head/><body><p>The <span style=\" font-weight:600;\">incremental</span> "
|
||||
"search checks seeds in numerical order, save for grouping into work items for parallelization. "
|
||||
"This type of search is best suited for a non-exhaustive search space and with strong biome dependencies.</p>"
|
||||
"<p>With <span style=\" font-weight:600;\">48-bit family blocks</span> the search looks for suitable "
|
||||
"48-bit seeds first and parallelizes the search through the upper 16-bits. "
|
||||
"This type of search is best suited for exhaustive searches and for many types of structure restrictions.</p>"
|
||||
"<p>Load a <span style=\" font-weight:600;\">seed list from a file</span> to search through an existing set of seeds. "
|
||||
"The seeds should be in decimal ASCII text, separated by newline characters. "
|
||||
"You can browse for a file using the "..." button. (The seed generator is ignored with this option.)"
|
||||
"</p></body></html>"
|
||||
;
|
||||
QMessageBox::information(this, "Help: search types", msg, QMessageBox::Ok);
|
||||
}
|
||||
|
||||
void FormSearchControl::on_comboSearchType_currentIndexChanged(int index)
|
||||
{
|
||||
ui->buttonLoadList->setEnabled(index == SEARCH_LIST);
|
||||
}
|
||||
|
||||
void FormSearchControl::pasteResults()
|
||||
{
|
||||
pasteList(false);
|
||||
}
|
||||
|
||||
int FormSearchControl::pasteList(bool dummy)
|
||||
{
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
QStringList slist = clipboard->text().split('\n');
|
||||
QVector<int64_t> seeds;
|
||||
|
||||
for (QString s : slist)
|
||||
{
|
||||
s = s.trimmed();
|
||||
if (s.isEmpty())
|
||||
continue;
|
||||
bool ok = true;
|
||||
int64_t seed = s.toLongLong(&ok);
|
||||
if (!ok)
|
||||
return 0;
|
||||
seeds.push_back(seed);
|
||||
}
|
||||
|
||||
if (!seeds.empty())
|
||||
{
|
||||
return searchResultsAdd(seeds, dummy);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FormSearchControl::searchResultsAdd(QVector<int64_t> seeds, bool countonly)
|
||||
{
|
||||
const Config& config = parent->config;
|
||||
int ns = ui->listResults->rowCount();
|
||||
int n = ns;
|
||||
if (n >= config.maxMatching)
|
||||
return 0;
|
||||
if (seeds.size() + n > config.maxMatching)
|
||||
seeds.resize(config.maxMatching - n);
|
||||
if (seeds.empty())
|
||||
return 0;
|
||||
|
||||
QSet<int64_t> current;
|
||||
current.reserve(n + seeds.size());
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int64_t seed = ui->listResults->item(i, 0)->data(Qt::UserRole).toLongLong();
|
||||
current.insert(seed);
|
||||
}
|
||||
|
||||
ui->listResults->setSortingEnabled(false);
|
||||
for (int64_t s : seeds)
|
||||
{
|
||||
if (current.contains(s))
|
||||
continue;
|
||||
if (countonly)
|
||||
{
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
current.insert(s);
|
||||
QTableWidgetItem* s48item = new QTableWidgetItem();
|
||||
QTableWidgetItem* seeditem = new QTableWidgetItem();
|
||||
s48item->setData(Qt::UserRole, QVariant::fromValue(s));
|
||||
s48item->setText(QString::asprintf("%012llx|%04x",
|
||||
(qulonglong)(s & MASK48), (uint)(s >> 48) & 0xffff));
|
||||
seeditem->setData(Qt::DisplayRole, QVariant::fromValue(s));
|
||||
ui->listResults->insertRow(n);
|
||||
ui->listResults->setItem(n, 0, s48item);
|
||||
ui->listResults->setItem(n, 1, seeditem);
|
||||
n++;
|
||||
}
|
||||
ui->listResults->setSortingEnabled(true);
|
||||
|
||||
if (countonly == false && n >= config.maxMatching)
|
||||
{
|
||||
sthread.stop();
|
||||
QString msg = QString::asprintf("Maximum number of results reached (%d).", config.maxMatching);
|
||||
QMessageBox::warning(this, "Warning", msg, QMessageBox::Ok);
|
||||
}
|
||||
|
||||
int addcnt = n - ns;
|
||||
if (ui->checkStop->isChecked() && addcnt)
|
||||
{
|
||||
sthread.reqstop = true;
|
||||
sthread.pool.clear();
|
||||
}
|
||||
|
||||
if (addcnt)
|
||||
emit resultsAdded(addcnt);
|
||||
|
||||
return addcnt;
|
||||
}
|
||||
|
||||
void FormSearchControl::searchProgressReset()
|
||||
{
|
||||
uint64_t cnt = parent->formGen48->estimateSeedCnt();
|
||||
if (cnt > MASK48)
|
||||
cnt = ~(uint64_t)0;
|
||||
else
|
||||
cnt <<= 16;
|
||||
QString fmt = QString::asprintf("0 / %" PRIu64 " (0.00%%)", cnt);
|
||||
if (!slist64path.isEmpty() && ui->comboSearchType->currentIndex() == SEARCH_LIST)
|
||||
fmt = slist64path + ": " + fmt;
|
||||
|
||||
ui->lineStart->setText("0");
|
||||
ui->progressBar->setValue(0);
|
||||
ui->progressBar->setFormat(fmt);
|
||||
}
|
||||
|
||||
void FormSearchControl::searchProgress(uint64_t last, uint64_t end, int64_t seed)
|
||||
{
|
||||
// if (sthread.itemgen.searchtype == SEARCH_BLOCKS)
|
||||
// seed &= MASK48;
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, seed));
|
||||
|
||||
if (end)
|
||||
{
|
||||
int v = (int) floor(10000 * (double)last / end);
|
||||
ui->progressBar->setValue(v);
|
||||
QString fmt = QString::asprintf(
|
||||
"%" PRIu64 " / %" PRIu64 " (%d.%02d%%)", last, end, v / 100, v % 100);
|
||||
if (!slist64path.isEmpty() && ui->comboSearchType->currentIndex() == SEARCH_LIST)
|
||||
fmt = slist64path + ": " + fmt;
|
||||
ui->progressBar->setFormat(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
void FormSearchControl::searchFinish()
|
||||
{
|
||||
if (!sthread.abort)
|
||||
{
|
||||
searchProgress(0, 0, sthread.itemgen.seed);
|
||||
}
|
||||
if (sthread.itemgen.isdone)
|
||||
{
|
||||
ui->progressBar->setValue(10000);
|
||||
ui->progressBar->setFormat(QString::asprintf("Done"));
|
||||
}
|
||||
searchLockUi(false);
|
||||
}
|
||||
|
||||
void FormSearchControl::resultTimeout()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void FormSearchControl::removeCurrent()
|
||||
{
|
||||
int row = ui->listResults->currentRow();
|
||||
if (row >= 0)
|
||||
ui->listResults->removeRow(row);
|
||||
}
|
||||
|
||||
void FormSearchControl::copyResults()
|
||||
{
|
||||
QString text;
|
||||
int n = ui->listResults->rowCount();
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
int64_t seed = ui->listResults->item(i, 0)->data(Qt::UserRole).toLongLong();
|
||||
text += QString::asprintf("%" PRId64 "\n", seed);
|
||||
}
|
||||
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
clipboard->setText(text);
|
||||
}
|
78
formsearchcontrol.h
Normal file
78
formsearchcontrol.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef FORMSEARCHCONTROL_H
|
||||
#define FORMSEARCHCONTROL_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTimer>
|
||||
|
||||
#include "searchthread.h"
|
||||
#include "protobasedialog.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace Ui {
|
||||
class FormSearchControl;
|
||||
}
|
||||
|
||||
class MainWindow;
|
||||
|
||||
|
||||
class FormSearchControl : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FormSearchControl(MainWindow *parent);
|
||||
~FormSearchControl();
|
||||
|
||||
QVector<int64_t> getResults();
|
||||
SearchConfig getSearchConfig();
|
||||
bool setSearchConfig(SearchConfig s, bool quiet);
|
||||
|
||||
bool isbusy();
|
||||
bool setList64(QString path, bool quiet);
|
||||
|
||||
void searchLockUi(bool lock);
|
||||
|
||||
void setSearchMode(int mode);
|
||||
|
||||
signals:
|
||||
void selectedSeedChanged(int64_t seed);
|
||||
void searchStatusChanged(bool running);
|
||||
void resultsAdded(int cnt);
|
||||
|
||||
public slots:
|
||||
void on_buttonClear_clicked();
|
||||
void on_buttonStart_clicked();
|
||||
void on_buttonLoadList_clicked();
|
||||
|
||||
void on_listResults_itemSelectionChanged();
|
||||
void on_listResults_customContextMenuRequested(const QPoint& pos);
|
||||
|
||||
void on_buttonSearchHelp_clicked();
|
||||
|
||||
void on_comboSearchType_currentIndexChanged(int index);
|
||||
|
||||
void pasteResults();
|
||||
int pasteList(bool dummy);
|
||||
int searchResultsAdd(QVector<int64_t> seeds, bool countonly);
|
||||
void searchProgressReset();
|
||||
void searchProgress(uint64_t last, uint64_t end, int64_t seed);
|
||||
void searchFinish();
|
||||
void resultTimeout();
|
||||
void removeCurrent();
|
||||
void copyResults();
|
||||
|
||||
private:
|
||||
MainWindow *parent;
|
||||
Ui::FormSearchControl *ui;
|
||||
SearchThread sthread;
|
||||
QTimer stimer;
|
||||
|
||||
// the seed list option is not stored in a widget but is loaded with the "..." button
|
||||
QString slist64path;
|
||||
std::vector<int64_t> slist64;
|
||||
|
||||
// buffer for seed candidates while search is running
|
||||
std::vector<int64_t> slist;
|
||||
};
|
||||
|
||||
#endif // FORMSEARCHCONTROL_H
|
286
formsearchcontrol.ui
Normal file
286
formsearchcontrol.ui
Normal file
@ -0,0 +1,286 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FormSearchControl</class>
|
||||
<widget class="QWidget" name="FormSearchControl">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>420</width>
|
||||
<height>315</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableWidget" name="listResults">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>160</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Hex (Low-48 | Top-16)</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignLeading|AlignVCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Seed</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignLeading|AlignVCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="buttonLoadList">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="lineStart">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Threads:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4" colspan="3">
|
||||
<widget class="QCheckBox" name="checkStop">
|
||||
<property name="toolTip">
|
||||
<string>stop as soon as the next set of matching seeds is found</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop on results</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>searching algorithm</p><p>incremental: best for non-exhaustive biome searches</p><p>48-bit family blocks: best for searches with strong structure restrictions</p><p>seed list from file...: load and search through a pre-computed list of seed</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="buttonSearchHelp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">border: none;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/info.png</normaloff>:/icons/info.png</iconset>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>14</width>
|
||||
<height>14</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Seed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QSpinBox" name="spinThreads">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="comboSearchType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>incremental</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48-bit family blocks</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>seed list from a file...</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="7">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Progress within the set of all 48-bit seeds.</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="7">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonClear">
|
||||
<property name="text">
|
||||
<string>Clear results</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/clear.png</normaloff>:/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonStart">
|
||||
<property name="text">
|
||||
<string>Start search</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="icons.qrc">
|
||||
<normaloff>:/icons/search.png</normaloff>:/icons/search.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -41,5 +41,11 @@
|
||||
<file>icons/slime_d.png</file>
|
||||
<file>icons/slime.png</file>
|
||||
<file>icons/grid_d.png</file>
|
||||
<file>icons/splitter_v.png</file>
|
||||
<file>icons/splitter_h.png</file>
|
||||
<file>icons/search.png</file>
|
||||
<file>icons/cancel.png</file>
|
||||
<file>icons/clear.png</file>
|
||||
<file>icons/info.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
icons/cancel.png
Normal file
BIN
icons/cancel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
icons/clear.png
Normal file
BIN
icons/clear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
icons/info.png
Normal file
BIN
icons/info.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
icons/search.png
Normal file
BIN
icons/search.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
icons/splitter_h.png
Normal file
BIN
icons/splitter_h.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
BIN
icons/splitter_v.png
Normal file
BIN
icons/splitter_v.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
938
mainwindow.cpp
938
mainwindow.cpp
File diff suppressed because it is too large
Load Diff
76
mainwindow.h
76
mainwindow.h
@ -16,8 +16,10 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "searchthread.h"
|
||||
#include "protobasedialog.h"
|
||||
#include "configdialog.h"
|
||||
#include "formconditions.h"
|
||||
#include "formgen48.h"
|
||||
#include "formsearchcontrol.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
@ -26,10 +28,11 @@ class MainWindow;
|
||||
Q_DECLARE_METATYPE(int64_t)
|
||||
Q_DECLARE_METATYPE(uint64_t)
|
||||
Q_DECLARE_METATYPE(Pos)
|
||||
Q_DECLARE_METATYPE(Condition)
|
||||
Q_DECLARE_METATYPE(Config)
|
||||
|
||||
class MapView;
|
||||
class Gen48Settings;
|
||||
class ProtoBaseDialog;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
@ -43,7 +46,6 @@ public:
|
||||
|
||||
bool getSeed(int *mc, int64_t *seed, bool applyrand = true);
|
||||
bool setSeed(int mc, int64_t seed);
|
||||
QVector<Condition> getConditions() const;
|
||||
MapView *getMapView();
|
||||
|
||||
protected:
|
||||
@ -51,60 +53,30 @@ protected:
|
||||
void loadSettings();
|
||||
bool saveProgress(QString fnam, bool quiet = false);
|
||||
bool loadProgress(QString fnam, bool quiet = false);
|
||||
QListWidgetItem *lockItem(QListWidgetItem *item);
|
||||
void setItemCondition(QListWidget *list, QListWidgetItem *item, Condition *cond);
|
||||
void editCondition(QListWidgetItem *item);
|
||||
void updateMapSeed();
|
||||
void updateSensitivity();
|
||||
int getIndex(int idx) const;
|
||||
|
||||
public slots:
|
||||
void warning(QString title, QString text);
|
||||
void mapGoto(qreal x, qreal z, qreal scale);
|
||||
|
||||
void openProtobaseMsg(QString path);
|
||||
void closeProtobaseMsg();
|
||||
|
||||
int searchResultsAdd(QVector<int64_t> seeds, bool countonly);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMC_currentIndexChanged(int a);
|
||||
void on_seedEdit_editingFinished();
|
||||
void on_seedEdit_textChanged(const QString &arg1);
|
||||
|
||||
void on_buttonRemoveAll_clicked();
|
||||
void on_buttonRemove_clicked();
|
||||
void on_buttonEdit_clicked();
|
||||
void on_buttonAddFilter_clicked();
|
||||
|
||||
void on_listConditions48_itemDoubleClicked(QListWidgetItem *item);
|
||||
void on_listConditionsFull_itemDoubleClicked(QListWidgetItem *item);
|
||||
void on_listConditions48_itemSelectionChanged();
|
||||
void on_listConditionsFull_itemSelectionChanged();
|
||||
|
||||
void on_buttonClear_clicked();
|
||||
void on_buttonStart_clicked();
|
||||
|
||||
void on_listResults_itemSelectionChanged();
|
||||
void on_listResults_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void on_buttonInfo_clicked();
|
||||
void on_buttonSearchHelp_clicked();
|
||||
|
||||
void on_actionSave_triggered();
|
||||
void on_actionLoad_triggered();
|
||||
void on_actionQuit_triggered();
|
||||
void on_actionCopy_triggered();
|
||||
void on_actionPaste_triggered();
|
||||
void on_actionPreferences_triggered();
|
||||
void on_actionGo_to_triggered();
|
||||
void on_actionScan_seed_for_Quad_Huts_triggered();
|
||||
void on_actionOpen_shadow_seed_triggered();
|
||||
void on_actionAbout_triggered();
|
||||
|
||||
void on_actionSearch_seed_list_triggered();
|
||||
void on_actionSearch_full_seed_space_triggered();
|
||||
void on_comboSearchType_currentIndexChanged(int index);
|
||||
void on_buttonLoadList_clicked();
|
||||
void on_actionCopy_triggered();
|
||||
void on_actionPaste_triggered();
|
||||
|
||||
void on_mapView_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
@ -115,30 +87,30 @@ private slots:
|
||||
void on_treeAnalysis_itemDoubleClicked(QTreeWidgetItem *item);
|
||||
void on_buttonExport_clicked();
|
||||
|
||||
// internal events
|
||||
void on_actionSearch_seed_list_triggered();
|
||||
void on_actionSearch_full_seed_space_triggered();
|
||||
|
||||
// internal events
|
||||
void onAutosaveTimeout();
|
||||
void onActionMapToggled(int stype, bool a);
|
||||
void addItemCondition(QListWidgetItem *item, Condition cond);
|
||||
void searchProgress(uint64_t last, uint64_t end, int64_t seed);
|
||||
void searchFinish();
|
||||
void resultTimeout();
|
||||
void removeCurrent();
|
||||
void copyResults();
|
||||
void pasteResults();
|
||||
int pasteList(bool dummy = false);
|
||||
void onConditionsChanged();
|
||||
void onGen48Changed();
|
||||
void onSelectedSeedChanged(int64_t seed);
|
||||
void onSearchStatusChanged(bool running);
|
||||
void copyCoord();
|
||||
|
||||
|
||||
public:
|
||||
Ui::MainWindow *ui;
|
||||
QVector<QAction*> saction;
|
||||
SearchThread sthread;
|
||||
QTimer stimer;
|
||||
ProtoBaseDialog *protodialog;
|
||||
QString prevdir;
|
||||
QString slistfnam;
|
||||
std::vector<int64_t> slist64;
|
||||
FormConditions *formCond;
|
||||
FormGen48 *formGen48;
|
||||
FormSearchControl *formControl;
|
||||
Config config;
|
||||
QString prevdir;
|
||||
QTimer autosaveTimer;
|
||||
|
||||
QVector<QAction*> saction;
|
||||
ProtoBaseDialog *protodialog;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
434
mainwindow.ui
434
mainwindow.ui
@ -23,7 +23,14 @@
|
||||
!checked { background-color:rgb(240, 240, 240); }
|
||||
border: 2px solid #8f8f91;
|
||||
border-radius:3px;
|
||||
}</string>
|
||||
}
|
||||
QSplitter::handle:horizontal {
|
||||
image: url(:/icons/splitter_h.png);
|
||||
}
|
||||
QSplitter::handle:vertical {
|
||||
image: url(:/icons/splitter_v.png);
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
@ -161,373 +168,110 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabSearch">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Search</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitterSearch">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>480</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="groupConstraints">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1227</width>
|
||||
<height>697</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Constraints</string>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>440</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="buttonInfo">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitterSearch">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="buttonRemoveAll">
|
||||
<property name="text">
|
||||
<string>Remove all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="5">
|
||||
<widget class="QSplitter" name="splitterConditions">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QListWidget" name="listConditions48">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Conditions for the 48-bit seed generator</string>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="movement">
|
||||
<enum>QListView::Snap</enum>
|
||||
<widget class="Collapsable" name="collapseConstraints" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QListWidget" name="listConditionsFull">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
<widget class="Collapsable" name="collapseGen48" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Conditions with full biome dependency</string>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::InternalMove</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="movement">
|
||||
<enum>QListView::Snap</enum>
|
||||
</widget>
|
||||
<widget class="Collapsable" name="collapseControl" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="buttonEdit">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="buttonRemove">
|
||||
<property name="text">
|
||||
<string>Remove selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="buttonAddFilter">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupMatching">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Matching seeds</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableWidget" name="listResults">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||
<number>160</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>20</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Hex (Low-48 | Top-16)</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignLeading|AlignVCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Seed</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignLeading|AlignVCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="buttonLoadList">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="QComboBox" name="comboSearchType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>incremental</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48-bit family blocks</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>seed list from a file...</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QSpinBox" name="spinThreads">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>searching algorithm</p><p>incremental: best for non-exhaustive biome searches</p><p>48-bit family blocks: best for searches with strong structure restrictions</p><p>seed list from file...: load and search through a pre-computed list of seed</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="7">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Progress within the set of all 48-bit seeds.</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>10000</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="buttonSearchHelp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Seed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4" colspan="3">
|
||||
<widget class="QCheckBox" name="checkStop">
|
||||
<property name="toolTip">
|
||||
<string>stop as soon as the next set of matching seeds is found</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stop on results</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Threads:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="lineStart">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="7">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonClear">
|
||||
<property name="text">
|
||||
<string>Clear results</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="buttonStart">
|
||||
<property name="text">
|
||||
<string>Start search</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
@ -923,6 +667,12 @@ QToolButton:checked {
|
||||
<header>mapview.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Collapsable</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>collapsable.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="icons.qrc"/>
|
||||
|
22
quad.cpp
22
quad.cpp
@ -59,17 +59,6 @@ void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<VarPos> *Quad::addStruct(const StructureConfig sconf)
|
||||
{
|
||||
LayerStack g;
|
||||
setupGenerator(&g, mc);
|
||||
int x0 = ti*blocks, x1 = (ti+1)*blocks;
|
||||
int z0 = tj*blocks, z1 = (tj+1)*blocks;
|
||||
|
||||
std::vector<VarPos>* st = new std::vector<VarPos>();
|
||||
getStructs(st, sconf, &g, mc, seed, x0, z0, x1, z1);
|
||||
return st;
|
||||
}
|
||||
|
||||
void Quad::run()
|
||||
{
|
||||
@ -108,7 +97,16 @@ void Quad::run()
|
||||
}
|
||||
if (structureType >= 0)
|
||||
{
|
||||
spos = addStruct(getConfig(structureType, mc));
|
||||
LayerStack g;
|
||||
setupGenerator(&g, mc);
|
||||
int x0 = ti*blocks, x1 = (ti+1)*blocks;
|
||||
int z0 = tj*blocks, z1 = (tj+1)*blocks;
|
||||
|
||||
std::vector<VarPos>* st = new std::vector<VarPos>();
|
||||
StructureConfig sconf;
|
||||
if (getConfig(structureType, mc, &sconf))
|
||||
getStructs(st, sconf, &g, mc, seed, x0, z0, x1, z1);
|
||||
spos = st;
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
|
46
quad.h
46
quad.h
@ -29,6 +29,50 @@ enum {
|
||||
STRUCT_NUM
|
||||
};
|
||||
|
||||
inline const char *mapopt2str(int opt)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case D_GRID: return "grid";
|
||||
case D_SLIME: return "slime";
|
||||
case D_DESERT: return "desert";
|
||||
case D_JUNGLE: return "jungle";
|
||||
case D_IGLOO: return "igloo";
|
||||
case D_HUT: return "hut";
|
||||
case D_VILLAGE: return "village";
|
||||
case D_MANSION: return "mansion";
|
||||
case D_MONUMENT: return "monument";
|
||||
case D_RUINS: return "ruins";
|
||||
case D_SHIPWRECK: return "shipwreck";
|
||||
case D_TREASURE: return "treasure";
|
||||
case D_OUTPOST: return "outpost";
|
||||
case D_PORTAL: return "portal";
|
||||
case D_SPAWN: return "spawn";
|
||||
case D_STRONGHOLD: return "stronghold";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
inline int str2mapopt(const char *s)
|
||||
{
|
||||
if (!strcmp(s, "grid")) return D_GRID;
|
||||
if (!strcmp(s, "slime")) return D_SLIME;
|
||||
if (!strcmp(s, "desert")) return D_DESERT;
|
||||
if (!strcmp(s, "jungle")) return D_JUNGLE;
|
||||
if (!strcmp(s, "igloo")) return D_IGLOO;
|
||||
if (!strcmp(s, "hut")) return D_HUT;
|
||||
if (!strcmp(s, "village")) return D_VILLAGE;
|
||||
if (!strcmp(s, "mansion")) return D_MANSION;
|
||||
if (!strcmp(s, "monument")) return D_MONUMENT;
|
||||
if (!strcmp(s, "ruins")) return D_RUINS;
|
||||
if (!strcmp(s, "shipwreck")) return D_SHIPWRECK;
|
||||
if (!strcmp(s, "treasure")) return D_TREASURE;
|
||||
if (!strcmp(s, "outpost")) return D_OUTPOST;
|
||||
if (!strcmp(s, "portal")) return D_PORTAL;
|
||||
if (!strcmp(s, "spawn")) return D_SPAWN;
|
||||
if (!strcmp(s, "stronghold")) return D_STRONGHOLD;
|
||||
return D_NONE;
|
||||
}
|
||||
|
||||
struct Level;
|
||||
|
||||
@ -47,8 +91,6 @@ public:
|
||||
Quad(const Level* l, int i, int j);
|
||||
~Quad();
|
||||
|
||||
|
||||
std::vector<VarPos> *addStruct(const StructureConfig sconf);
|
||||
void run();
|
||||
|
||||
int mc;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "quadlistdialog.h"
|
||||
#include "ui_quadlistdialog.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "mapview.h"
|
||||
#include "cutil.h"
|
||||
#include "seedtables.h"
|
||||
@ -10,7 +11,6 @@
|
||||
#include <QMenu>
|
||||
|
||||
|
||||
|
||||
QuadListDialog::QuadListDialog(MainWindow *mainwindow)
|
||||
: QDialog(mainwindow)
|
||||
, ui(new Ui::QuadListDialog)
|
||||
|
@ -2,7 +2,8 @@
|
||||
#define QUADLISTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "mainwindow.h"
|
||||
|
||||
class MainWindow;
|
||||
|
||||
namespace Ui {
|
||||
class QuadListDialog;
|
||||
|
277
search.cpp
277
search.cpp
@ -9,175 +9,6 @@
|
||||
extern MainWindow *gMainWindowInstance;
|
||||
|
||||
|
||||
int check(int64_t s48, void *data)
|
||||
{
|
||||
const StructureConfig sconf = *(const StructureConfig*) data;
|
||||
return isQuadBase(sconf, s48 - sconf.salt, 128);
|
||||
}
|
||||
|
||||
/* Loads a seed list for a filter type from disk, or generates it if neccessary.
|
||||
* @mc mincreaft version
|
||||
* @ftyp filter type
|
||||
* @qb output seed base list
|
||||
* @qbn output length of seed base list
|
||||
* @dyn list was dynamically allocated and requires a free
|
||||
* @sconf structure configuration used for the bases
|
||||
*/
|
||||
static void genSeedBases(int mc, int ftyp, const int64_t **qb, int64_t *qbn,
|
||||
int *dyn, StructureConfig *sconf)
|
||||
{
|
||||
char fnam[128];
|
||||
|
||||
const char *lbstr = NULL;
|
||||
const int64_t *lbset = NULL;
|
||||
int64_t lbcnt = 0;
|
||||
int64_t *dqb = NULL;
|
||||
|
||||
*qb = NULL;
|
||||
*qbn = 0;
|
||||
*dyn = 0;
|
||||
|
||||
switch (ftyp)
|
||||
{
|
||||
case F_QH_IDEAL:
|
||||
lbstr = "ideal";
|
||||
lbset = low20QuadIdeal;
|
||||
lbcnt = sizeof(low20QuadIdeal) / sizeof(int64_t);
|
||||
goto L_QH_ANY;
|
||||
case F_QH_CLASSIC:
|
||||
lbstr = "cassic";
|
||||
lbset = low20QuadClassic;
|
||||
lbcnt = sizeof(low20QuadClassic) / sizeof(int64_t);
|
||||
goto L_QH_ANY;
|
||||
case F_QH_NORMAL:
|
||||
lbstr = "normal";
|
||||
lbset = low20QuadHutNormal;
|
||||
lbcnt = sizeof(low20QuadHutNormal) / sizeof(int64_t);
|
||||
goto L_QH_ANY;
|
||||
case F_QH_BARELY:
|
||||
lbstr = "barely";
|
||||
lbset = low20QuadHutBarely;
|
||||
lbcnt = sizeof(low20QuadHutBarely) / sizeof(int64_t);
|
||||
goto L_QH_ANY;
|
||||
L_QH_ANY:
|
||||
snprintf(fnam, sizeof(fnam), "protobases/quad_%s.txt", lbstr);
|
||||
*sconf = mc <= MC_1_12 ? SWAMP_HUT_CONFIG_112 : SWAMP_HUT_CONFIG;
|
||||
|
||||
if ((dqb = loadSavedSeeds(fnam, qbn)) == NULL)
|
||||
{
|
||||
QMetaObject::invokeMethod(gMainWindowInstance, "openProtobaseMsg", Qt::QueuedConnection, Q_ARG(QString, QString(fnam)));
|
||||
|
||||
int threads = QThread::idealThreadCount();
|
||||
int err = searchAll48(&dqb, qbn, fnam, threads, lbset, lbcnt, 20, check, sconf);
|
||||
|
||||
QMetaObject::invokeMethod(gMainWindowInstance, "closeProtobaseMsg", Qt::BlockingQueuedConnection);
|
||||
|
||||
if (err)
|
||||
{
|
||||
QMetaObject::invokeMethod(
|
||||
gMainWindowInstance, "warning", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QString, QString("Warning")),
|
||||
Q_ARG(QString, QString("Failed to generate protobases.")));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dqb)
|
||||
{
|
||||
// convert protobases to proper bases by subtracting the salt
|
||||
for (int64_t i = 0; i < (*qbn); i++)
|
||||
dqb[i] -= sconf->salt;
|
||||
*qb = (const int64_t*)dqb;
|
||||
*dyn = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case F_QM_95:
|
||||
*qb = g_qm_95;
|
||||
*qbn = sizeof(g_qm_95) / sizeof(int64_t);
|
||||
*sconf = MONUMENT_CONFIG;
|
||||
*dyn = 0;
|
||||
break;
|
||||
case F_QM_90:
|
||||
*qb = g_qm_90;
|
||||
*qbn = sizeof(g_qm_90) / sizeof(int64_t);
|
||||
*sconf = MONUMENT_CONFIG;
|
||||
*dyn = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Produces a list of seed bases from precomputed lists, provided all candidates fit into a buffer.
|
||||
*
|
||||
* @param list output list
|
||||
* @param mc mincraft version
|
||||
* @param cond conditions
|
||||
* @param ccnt number of conditions
|
||||
* @param bufmax maximum allowed buffer size
|
||||
*/
|
||||
void getCandidates(std::vector<int64_t>& list, int mc, const Condition *cond, int ccnt, int64_t bufmax)
|
||||
{
|
||||
int ci;
|
||||
|
||||
for (ci = 0; ci < ccnt; ci++)
|
||||
{
|
||||
if (cond[ci].relative)
|
||||
continue;
|
||||
|
||||
int64_t q, qbn = 0, *p;
|
||||
const int64_t *qb = NULL;
|
||||
StructureConfig sconf;
|
||||
int dyn;
|
||||
int i, j;
|
||||
|
||||
genSeedBases(mc, cond[ci].type, &qb, &qbn, &dyn, &sconf);
|
||||
if (!qb)
|
||||
continue;
|
||||
|
||||
int x = cond[ci].x1;
|
||||
int z = cond[ci].z1;
|
||||
int w = cond[ci].x2 - x + 1;
|
||||
int h = cond[ci].z2 - z + 1;
|
||||
|
||||
// does the set of candidates for this condition fit in memory?
|
||||
if (qbn * w*h * 4 * (int64_t)sizeof(int64_t) >= bufmax)
|
||||
goto L_next_cond;
|
||||
|
||||
try {
|
||||
list.resize(qbn * w*h);
|
||||
} catch (...) {
|
||||
goto L_next_cond;
|
||||
}
|
||||
|
||||
p = list.data();
|
||||
for (j = 0; j < h; j++)
|
||||
{
|
||||
for (i = 0; i < w; i++)
|
||||
{
|
||||
for (q = 0; q < qbn; q++)
|
||||
{
|
||||
*p++ = moveStructure(qb[q], x+i, z+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
L_next_cond:
|
||||
if (dyn && qb)
|
||||
free((void*)qb);
|
||||
|
||||
if (!list.empty())
|
||||
break;
|
||||
}
|
||||
|
||||
if (!list.empty())
|
||||
{
|
||||
std::sort(list.begin(), list.end());
|
||||
auto last = std::unique(list.begin(), list.end());
|
||||
list.erase(last, list.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool intersectLineLine(double ax1, double az1, double ax2, double az2, double bx1, double bz1, double bx2, double bz2)
|
||||
{
|
||||
double ax = ax2 - ax1, az = az2 - az1;
|
||||
@ -243,6 +74,13 @@ int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, Layer
|
||||
Pos p[128];
|
||||
|
||||
StructPos *sout = spos + cond->save;
|
||||
const FilterInfo& finfo = g_filterinfo.list[cond->type];
|
||||
|
||||
if (finfo.stype > 0)
|
||||
{
|
||||
if (!getConfig(finfo.stype, mc, &sconf))
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (cond->type)
|
||||
{
|
||||
@ -250,7 +88,6 @@ int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, Layer
|
||||
case F_QH_CLASSIC:
|
||||
case F_QH_NORMAL:
|
||||
case F_QH_BARELY:
|
||||
sconf = mc <= MC_1_12 ? SWAMP_HUT_CONFIG_112 : SWAMP_HUT_CONFIG;
|
||||
qual = cond->type;
|
||||
|
||||
if (cond->relative)
|
||||
@ -293,7 +130,6 @@ int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, Layer
|
||||
case F_QM_95: qual = 58*58*4 * 95 / 100; goto L_qm_any;
|
||||
case F_QM_90: qual = 58*58*4 * 90 / 100;
|
||||
L_qm_any:
|
||||
sconf = MONUMENT_CONFIG;
|
||||
|
||||
if (cond->relative)
|
||||
{
|
||||
@ -333,19 +169,19 @@ L_qm_any:
|
||||
return 0;
|
||||
|
||||
|
||||
case F_DESERT: sconf = getConfig(Desert_Pyramid, mc); goto L_struct_any;
|
||||
case F_HUT: sconf = getConfig(Swamp_Hut, mc); goto L_struct_any;
|
||||
case F_JUNGLE: sconf = getConfig(Jungle_Pyramid, mc); goto L_struct_any;
|
||||
case F_IGLOO: sconf = getConfig(Igloo, mc); goto L_struct_any;
|
||||
case F_MONUMENT: sconf = getConfig(Monument, mc); goto L_struct_any;
|
||||
case F_VILLAGE: sconf = getConfig(Village, mc); goto L_struct_any;
|
||||
case F_OUTPOST: sconf = getConfig(Outpost, mc); goto L_struct_any;
|
||||
case F_MANSION: sconf = getConfig(Mansion, mc); goto L_struct_any;
|
||||
case F_RUINS: sconf = getConfig(Ocean_Ruin, mc); goto L_struct_any;
|
||||
case F_SHIPWRECK: sconf = getConfig(Shipwreck, mc); goto L_struct_any;
|
||||
case F_PORTAL: sconf = getConfig(Ruined_Portal, mc); goto L_struct_any;
|
||||
case F_DESERT:
|
||||
case F_HUT:
|
||||
case F_JUNGLE:
|
||||
case F_IGLOO:
|
||||
case F_MONUMENT:
|
||||
case F_VILLAGE:
|
||||
case F_OUTPOST:
|
||||
case F_MANSION:
|
||||
case F_RUINS:
|
||||
case F_SHIPWRECK:
|
||||
case F_TREASURE:
|
||||
case F_PORTAL:
|
||||
|
||||
L_struct_any:
|
||||
x1 = cond->x1;
|
||||
z1 = cond->z1;
|
||||
x2 = cond->x2;
|
||||
@ -365,6 +201,13 @@ L_struct_any:
|
||||
rx2 = x2 >> 9;
|
||||
rz2 = z2 >> 9;
|
||||
}
|
||||
else if (sconf.regionSize == 1)
|
||||
{
|
||||
rx1 = x1 >> 4;
|
||||
rz1 = z1 >> 4;
|
||||
rx2 = x2 >> 4;
|
||||
rz2 = z2 >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
rx1 = (x1 / (sconf.regionSize << 4)) - (x1 < 0);
|
||||
@ -407,54 +250,6 @@ L_struct_any:
|
||||
}
|
||||
return 0;
|
||||
|
||||
case F_TREASURE:
|
||||
sconf = TREASURE_CONFIG;
|
||||
x1 = cond->x1;
|
||||
z1 = cond->z1;
|
||||
x2 = cond->x2;
|
||||
z2 = cond->z2;
|
||||
if (cond->relative)
|
||||
{
|
||||
x1 += spos[cond->relative].cx;
|
||||
z1 += spos[cond->relative].cz;
|
||||
x2 += spos[cond->relative].cx;
|
||||
z2 += spos[cond->relative].cz;
|
||||
}
|
||||
rx1 = x1 >> 4;
|
||||
rz1 = z1 >> 4;
|
||||
rx2 = x2 >> 4;
|
||||
rz2 = z2 >> 4;
|
||||
|
||||
sout->cx = xt = 0;
|
||||
sout->cz = zt = 0;
|
||||
qual = 0;
|
||||
|
||||
for (int rz = rz1; rz <= rz2; rz++)
|
||||
{
|
||||
for (int rx = rx1; rx <= rx2; rx++)
|
||||
{
|
||||
pc = { (rx << 4) + 9, (rz << 4) + 9 };
|
||||
if (pc.x < x1 || pc.x > x2 || pc.z < z1 || pc.z > z2)
|
||||
continue;
|
||||
if (!isTreasureChunk(seed, rx, rz))
|
||||
continue;
|
||||
if (g && !isViableStructurePos(sconf.structType, mc, g, seed, pc.x, pc.z))
|
||||
continue;
|
||||
|
||||
xt += pc.x;
|
||||
zt += pc.z;
|
||||
|
||||
if (++qual >= cond->count)
|
||||
{
|
||||
sout->sconf = sconf;
|
||||
sout->cx = xt / qual;
|
||||
sout->cz = zt / qual;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case F_SPAWN:
|
||||
// TODO: warn if spawn is used for relative positioning
|
||||
sout->cx = 0;
|
||||
@ -608,12 +403,14 @@ L_struct_any:
|
||||
}
|
||||
return 0;
|
||||
|
||||
case F_BIOME: s = 0; qual = L_VORONOI_ZOOM_1; goto L_biome_filter_any;
|
||||
case F_BIOME_4_RIVER: s = 2; qual = L_RIVER_MIX_4; goto L_biome_filter_any;
|
||||
case F_BIOME_16_SHORE: s = 4; qual = L_SHORE_16; goto L_biome_filter_any;
|
||||
case F_BIOME_64_RARE: s = 6; qual = L_RARE_BIOME_64; goto L_biome_filter_any;
|
||||
case F_BIOME_256_BIOME: s = 8; qual = L_BIOME_256; goto L_biome_filter_any;
|
||||
case F_BIOME_256_OTEMP: s = 8; qual = L13_OCEAN_TEMP_256; goto L_biome_filter_any;
|
||||
// biome filters reference specific layers
|
||||
// MAYBE: options for layers in different versions?
|
||||
case F_BIOME: s = 0; goto L_biome_filter_any;
|
||||
case F_BIOME_4_RIVER: s = 2; goto L_biome_filter_any;
|
||||
case F_BIOME_16_SHORE: s = 4; goto L_biome_filter_any;
|
||||
case F_BIOME_64_RARE: s = 6; goto L_biome_filter_any;
|
||||
case F_BIOME_256_BIOME: s = 8; goto L_biome_filter_any;
|
||||
case F_BIOME_256_OTEMP: s = 8; goto L_biome_filter_any;
|
||||
|
||||
L_biome_filter_any:
|
||||
if (cond->relative)
|
||||
@ -634,7 +431,7 @@ L_biome_filter_any:
|
||||
sout->cz = ((rz1 + rz2) << s) >> 1;
|
||||
if (!g)
|
||||
{
|
||||
if (qual != L13_OCEAN_TEMP_256)
|
||||
if (finfo.layer != L_OCEAN_TEMP_256)
|
||||
return 1;
|
||||
if (mc < MC_1_13)
|
||||
return 0;
|
||||
@ -648,8 +445,8 @@ L_biome_filter_any:
|
||||
{
|
||||
int w = rx2-rx1+1;
|
||||
int h = rz2-rz1+1;
|
||||
int *area = allocCache(&g->layers[qual], w, h);
|
||||
if (checkForBiomes(g, qual, area, seed, rx1, rz1, w, h, cond->bfilter, 0) > 0)
|
||||
int *area = allocCache(&g->layers[finfo.layer], w, h);
|
||||
if (checkForBiomes(g, finfo.layer, area, seed, rx1, rz1, w, h, cond->bfilter, 0) > 0)
|
||||
{
|
||||
// check biome exclusion
|
||||
uint64_t b = 0, bm = 0;
|
||||
|
69
search.h
69
search.h
@ -3,9 +3,10 @@
|
||||
|
||||
#include "cubiomes/finders.h"
|
||||
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
|
||||
#define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30)
|
||||
|
||||
enum
|
||||
{
|
||||
CAT_NONE,
|
||||
@ -19,6 +20,7 @@ struct FilterInfo
|
||||
bool coord; // requires coordinate entry
|
||||
bool area; // requires area entry
|
||||
int layer; // associated generator layer
|
||||
int stype; // structure type
|
||||
int step; // coordinate multiplier
|
||||
int count; //
|
||||
int mcmin; // minimum version
|
||||
@ -69,14 +71,14 @@ static const struct FilterList
|
||||
FilterList() : list{}
|
||||
{
|
||||
list[F_SELECT] = FilterInfo{
|
||||
CAT_NONE, 0, 0, 0, 0, 0, MC_1_0,
|
||||
CAT_NONE, 0, 0, 0, 0, 0, 0, MC_1_0,
|
||||
NULL,
|
||||
"",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_QH_IDEAL] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (ideal)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -84,7 +86,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QH_CLASSIC] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (classic)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -94,7 +96,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QH_NORMAL] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (normal)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -104,7 +106,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QH_BARELY] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (barely)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -113,7 +115,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QM_95] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, 512, 0, MC_1_8,
|
||||
CAT_48, 1, 1, 0, Monument, 512, 0, MC_1_8,
|
||||
":icons/quad.png",
|
||||
"Quad-ocean-monument (>95%)",
|
||||
"The lower 48-bits provide potential for 95% of the area of "
|
||||
@ -122,7 +124,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QM_90] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, 512, 0, MC_1_8,
|
||||
CAT_48, 1, 1, 0, Monument, 512, 0, MC_1_8,
|
||||
":icons/quad.png",
|
||||
"Quad-ocean-monument (>90%)",
|
||||
"The lower 48-bits provide potential for 90% of the area of "
|
||||
@ -131,7 +133,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_VORONOI_1, 1, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_VORONOI_1, 0, 1, 0, MC_1_0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:1",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -139,7 +141,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_4_RIVER] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_RIVER_MIX_4, 4, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_RIVER_MIX_4, 0, 4, 0, MC_1_0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:4 RIVER",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -148,7 +150,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_16_SHORE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_SHORE_16, 16, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_SHORE_16, 0, 16, 0, MC_1_0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:16 SHORE",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -157,7 +159,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_64_RARE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_SUNFLOWER_64, 64, 0, MC_1_7,
|
||||
CAT_FULL, 1, 1, L_SUNFLOWER_64, 0, 64, 0, MC_1_7,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:64 RARE",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -166,7 +168,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_256_BIOME] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_BIOME_256, 256, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_BIOME_256, 0, 256, 0, MC_1_0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:256 BIOME",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -175,7 +177,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_256_OTEMP] = FilterInfo{
|
||||
CAT_48, 1, 1, L13_OCEAN_TEMP_256, 256, 0, MC_1_13,
|
||||
CAT_48, 1, 1, L_OCEAN_TEMP_256, 0, 256, 0, MC_1_13,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:256 O.TEMP",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -185,112 +187,112 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_TEMPS] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1024, 0, MC_1_7,
|
||||
CAT_FULL, 1, 1, 0, 0, 1024, 0, MC_1_7,
|
||||
":icons/tempcat.png",
|
||||
"Temperature categories",
|
||||
"Checks that the area has a minimum of all the required temperature categories."
|
||||
};
|
||||
|
||||
list[F_SLIME] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 16, 1, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, 0, 16, 1, MC_1_0,
|
||||
":icons/slime.png",
|
||||
"Slime chunk",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_SPAWN] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, 0, 1, 0, MC_1_0,
|
||||
":icons/spawn.png",
|
||||
"Spawn",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_STRONGHOLD] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, 0, 1, 1, MC_1_0,
|
||||
":icons/stronghold.png",
|
||||
"Stronghold",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_DESERT] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_3,
|
||||
CAT_FULL, 1, 1, 0, Desert_Pyramid, 1, 1, MC_1_3,
|
||||
":icons/desert.png",
|
||||
"Desert pyramid",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_JUNGLE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_3,
|
||||
CAT_FULL, 1, 1, 0, Jungle_Pyramid, 1, 1, MC_1_3,
|
||||
":icons/jungle.png",
|
||||
"Jungle temple",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_HUT] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_4,
|
||||
CAT_FULL, 1, 1, 0, Swamp_Hut, 1, 1, MC_1_4,
|
||||
":icons/hut.png",
|
||||
"Swamp hut",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_IGLOO] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_9,
|
||||
CAT_FULL, 1, 1, 0, Igloo, 1, 1, MC_1_9,
|
||||
":icons/igloo.png",
|
||||
"Igloo",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_MONUMENT] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_8,
|
||||
CAT_FULL, 1, 1, 0, Monument, 1, 1, MC_1_8,
|
||||
":icons/monument.png",
|
||||
"Ocean monument",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_VILLAGE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, Village, 1, 1, MC_1_0,
|
||||
":icons/village.png",
|
||||
"Village",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_OUTPOST] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_14,
|
||||
CAT_FULL, 1, 1, 0, Outpost, 1, 1, MC_1_14,
|
||||
":icons/outpost.png",
|
||||
"Pillager outpost",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_MANSION] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_11,
|
||||
CAT_FULL, 1, 1, 0, Mansion, 1, 1, MC_1_11,
|
||||
":icons/mansion.png",
|
||||
"Woodland mansion",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_TREASURE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_13,
|
||||
CAT_FULL, 1, 1, 0, Treasure, 1, 1, MC_1_13,
|
||||
":icons/treasure.png",
|
||||
"Buried treasure",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_RUINS] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_13,
|
||||
CAT_FULL, 1, 1, 0, Ocean_Ruin, 1, 1, MC_1_13,
|
||||
":icons/ruins.png",
|
||||
"Ocean ruins",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_SHIPWRECK] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_13,
|
||||
CAT_FULL, 1, 1, 0, Shipwreck, 1, 1, MC_1_13,
|
||||
":icons/shipwreck.png",
|
||||
"Shipwreck",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_PORTAL] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 1, 1, MC_1_16,
|
||||
CAT_FULL, 1, 1, 0, Ruined_Portal, 1, 1, MC_1_16,
|
||||
":icons/portal.png",
|
||||
"Ruined portal",
|
||||
""
|
||||
@ -319,15 +321,8 @@ struct StructPos
|
||||
int cx, cz; // effective center position
|
||||
};
|
||||
|
||||
/* Attempts to construct a list of 48-bit bases that should be further checked.
|
||||
* Any conditions that would result in a list larger than a buffer size will
|
||||
* not be preloaded in this way.
|
||||
*/
|
||||
void getCandidates(std::vector<int64_t>& list, int mc, const Condition *cond, int ccnt, int64_t bufmax);
|
||||
|
||||
|
||||
int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort);
|
||||
|
||||
|
||||
|
||||
#endif // SEARCH_H
|
||||
|
157
searchitem.cpp
157
searchitem.cpp
@ -1,4 +1,8 @@
|
||||
#include "searchitem.h"
|
||||
#include "seedtables.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
|
||||
|
||||
SearchItem::~SearchItem()
|
||||
@ -116,10 +120,11 @@ void SearchItem::run()
|
||||
|
||||
|
||||
void SearchItemGenerator::init(
|
||||
int mc, const Condition *cond, int ccnt,
|
||||
const std::vector<int64_t>& seedlist,
|
||||
QObject *mainwin, int mc, const Condition *cond, int ccnt,
|
||||
Gen48Settings gen48, const std::vector<int64_t>& seedlist,
|
||||
int itemsize, int searchtype, int64_t sstart)
|
||||
{
|
||||
this->mainwin = mainwin;
|
||||
this->searchtype = searchtype;
|
||||
this->mc = mc;
|
||||
this->cond = cond;
|
||||
@ -127,18 +132,164 @@ void SearchItemGenerator::init(
|
||||
this->itemid = 0;
|
||||
this->itemsiz = itemsize;
|
||||
this->slist = seedlist;
|
||||
this->gen48 = gen48;
|
||||
this->idx = 0;
|
||||
this->scnt = ~(uint64_t)0;
|
||||
this->seed = sstart;
|
||||
this->isdone = false;
|
||||
}
|
||||
|
||||
|
||||
static int check(int64_t s48, void *data)
|
||||
{
|
||||
(void) data;
|
||||
const StructureConfig sconf = {};
|
||||
return isQuadBaseFeature24(sconf, s48, 7+1, 7+1, 9+1) != 0;
|
||||
}
|
||||
|
||||
static void genQHBases(QObject *qtobj, int qual, int64_t salt, std::vector<int64_t>& list48)
|
||||
{
|
||||
const char *lbstr = NULL;
|
||||
const int64_t *lbset = NULL;
|
||||
int64_t lbcnt = 0;
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
if (path.isEmpty())
|
||||
path = "protobases";
|
||||
|
||||
switch (qual)
|
||||
{
|
||||
case IDEAL_SALTED:
|
||||
case IDEAL:
|
||||
lbstr = "ideal";
|
||||
lbset = low20QuadIdeal;
|
||||
lbcnt = sizeof(low20QuadIdeal) / sizeof(int64_t);
|
||||
break;
|
||||
case CLASSIC:
|
||||
lbstr = "cassic";
|
||||
lbset = low20QuadClassic;
|
||||
lbcnt = sizeof(low20QuadClassic) / sizeof(int64_t);
|
||||
break;
|
||||
case NORMAL:
|
||||
lbstr = "normal";
|
||||
lbset = low20QuadHutNormal;
|
||||
lbcnt = sizeof(low20QuadHutNormal) / sizeof(int64_t);
|
||||
break;
|
||||
case BARELY:
|
||||
lbstr = "barely";
|
||||
lbset = low20QuadHutBarely;
|
||||
lbcnt = sizeof(low20QuadHutBarely) / sizeof(int64_t);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
path += QString("/quad_") + lbstr + ".txt";
|
||||
QByteArray fnam = path.toLatin1();
|
||||
int64_t *qb = NULL;
|
||||
int64_t qn = 0;
|
||||
|
||||
if ((qb = loadSavedSeeds(fnam.data(), &qn)) == NULL)
|
||||
{
|
||||
printf("Writing quad-protobases to: %s\n", fnam.data());
|
||||
fflush(stdout);
|
||||
|
||||
QMetaObject::invokeMethod(qtobj, "openProtobaseMsg", Qt::QueuedConnection, Q_ARG(QString, path));
|
||||
|
||||
int threads = QThread::idealThreadCount();
|
||||
int err = searchAll48(&qb, &qn, fnam.data(), threads, lbset, lbcnt, 20, check, NULL);
|
||||
|
||||
if (err)
|
||||
{
|
||||
QMetaObject::invokeMethod(
|
||||
qtobj, "warning", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QString, QString("Warning")),
|
||||
Q_ARG(QString, QString("Failed to generate protobases.")));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(qtobj, "closeProtobaseMsg", Qt::BlockingQueuedConnection);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Loaded quad-protobases from: %s\n", fnam.data());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (qb)
|
||||
{
|
||||
// convert protobases to proper bases by subtracting the salt
|
||||
list48.resize(qn);
|
||||
for (int64_t i = 0; i < qn; i++)
|
||||
list48[i] = qb[i] - salt;
|
||||
free(qb);
|
||||
}
|
||||
}
|
||||
|
||||
// Produces a list of seed bases from precomputed lists, provided all candidates fit into a buffer.
|
||||
bool getQuadCandidates(std::vector<int64_t>& list48, QObject *qtobj, Gen48Settings gen48, int mc, int64_t bufmax)
|
||||
{
|
||||
std::vector<int64_t> qlist;
|
||||
list48.clear();
|
||||
|
||||
if (gen48.mode == GEN48_QH)
|
||||
{
|
||||
int64_t salt = 0;
|
||||
if (gen48.qual == IDEAL_SALTED)
|
||||
salt = gen48.salt;
|
||||
else
|
||||
salt = (mc <= MC_1_12 ? SWAMP_HUT_CONFIG_112.salt : SWAMP_HUT_CONFIG.salt);
|
||||
genQHBases(qtobj, gen48.qual, salt, qlist);
|
||||
}
|
||||
else if (gen48.mode == GEN48_QM)
|
||||
{
|
||||
const int64_t *qb = g_qm_90;
|
||||
int64_t qn = sizeof(g_qm_90) / sizeof(int64_t);
|
||||
qlist.reserve(qn);
|
||||
for (int64_t i = 0; i < qn; i++)
|
||||
if (qmonumentQual(qb[i]) >= gen48.qmarea)
|
||||
qlist.push_back(qb[i]);
|
||||
}
|
||||
|
||||
if (qlist.empty())
|
||||
return false;
|
||||
|
||||
int x = gen48.x1;
|
||||
int z = gen48.z1;
|
||||
int w = gen48.x2 - x + 1;
|
||||
int h = gen48.z2 - z + 1;
|
||||
|
||||
// does the set of candidates for this condition fit in memory?
|
||||
if ((int64_t)qlist.size() * (int64_t)sizeof(int64_t) * w*h >= bufmax)
|
||||
return false;
|
||||
|
||||
try {
|
||||
list48.resize(qlist.size() * w*h);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t *p = list48.data();
|
||||
for (int j = 0; j < h; j++)
|
||||
for (int i = 0; i < w; i++)
|
||||
for (int64_t b : qlist)
|
||||
*p++ = moveStructure(b, x+i, z+j);
|
||||
|
||||
std::sort(list48.begin(), list48.end());
|
||||
auto last = std::unique(list48.begin(), list48.end());
|
||||
list48.erase(last, list48.end());
|
||||
|
||||
return !list48.empty();
|
||||
}
|
||||
|
||||
|
||||
void SearchItemGenerator::presearch()
|
||||
{
|
||||
int64_t sstart = seed;
|
||||
|
||||
if (slist.empty() && searchtype != SEARCH_LIST)
|
||||
getCandidates(slist, mc, cond, ccnt, PRECOMPUTE48_BUFSIZ);
|
||||
getQuadCandidates(slist, mainwin, gen48, mc, PRECOMPUTE48_BUFSIZ);
|
||||
|
||||
if (searchtype == SEARCH_LIST && !slist.empty())
|
||||
{
|
||||
|
14
searchitem.h
14
searchitem.h
@ -8,12 +8,9 @@
|
||||
#include <QVector>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include "settings.h"
|
||||
#include "search.h"
|
||||
|
||||
#define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30)
|
||||
|
||||
// search type options from combobox
|
||||
enum { SEARCH_INC = 0, SEARCH_BLOCKS = 1, SEARCH_LIST = 2 };
|
||||
|
||||
struct SearchItem : public QObject, QRunnable
|
||||
{
|
||||
@ -71,24 +68,27 @@ public:
|
||||
// (or the last entry in the seed list)
|
||||
};
|
||||
|
||||
|
||||
struct SearchItemGenerator
|
||||
{
|
||||
void init(
|
||||
int mc, const Condition *cond, int ccnt,
|
||||
const std::vector<int64_t>& slist,
|
||||
int itemsize, int searchtype, int64_t sstart);
|
||||
QObject *mainwin, int mc, const Condition *cond, int ccnt,
|
||||
Gen48Settings gen48, const std::vector<int64_t>& seedlist,
|
||||
int itemsize, int searchtype, int64_t sstart);
|
||||
|
||||
void presearch();
|
||||
|
||||
SearchItem *requestItem();
|
||||
void getProgress(uint64_t *prog, uint64_t *end);
|
||||
|
||||
QObject * mainwin;
|
||||
int searchtype;
|
||||
int mc;
|
||||
const Condition * cond;
|
||||
int ccnt;
|
||||
uint64_t itemid; // item incrementor
|
||||
int itemsiz; // number of seeds per search item
|
||||
Gen48Settings gen48; // 48-bit generator settings
|
||||
std::vector<int64_t> slist; // candidate list
|
||||
uint64_t idx; // index within candidate list
|
||||
uint64_t scnt; // size of search space
|
||||
|
@ -1,21 +1,20 @@
|
||||
#include "searchthread.h"
|
||||
#include "mainwindow.h"
|
||||
#include "formsearchcontrol.h"
|
||||
#include "cutil.h"
|
||||
#include "mainwindow.h" // TODO: remove
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QEventLoop>
|
||||
|
||||
#include <x86intrin.h>
|
||||
|
||||
#define TSC_INTERRUPT_CNT ((uint64_t)1 << 30)
|
||||
|
||||
#define ITEM_SIZE 1024
|
||||
|
||||
|
||||
extern MainWindow *gMainWindowInstance;
|
||||
|
||||
|
||||
SearchThread::SearchThread(MainWindow *parent)
|
||||
SearchThread::SearchThread(FormSearchControl *parent)
|
||||
: QThread()
|
||||
, parent(parent)
|
||||
, condvec()
|
||||
@ -30,7 +29,8 @@ SearchThread::SearchThread(MainWindow *parent)
|
||||
itemgen.abort = &abort;
|
||||
}
|
||||
|
||||
bool SearchThread::set(int type, int threads, std::vector<int64_t>& slist64, int64_t sstart, int mc,
|
||||
bool SearchThread::set(QObject *mainwin, int type, int threads, Gen48Settings gen48,
|
||||
std::vector<int64_t>& slist, int64_t sstart, int mc,
|
||||
const QVector<Condition>& cv, int itemsize, int queuesize)
|
||||
{
|
||||
char refbuf[100] = {};
|
||||
@ -95,7 +95,7 @@ bool SearchThread::set(int type, int threads, std::vector<int64_t>& slist64, int
|
||||
}
|
||||
|
||||
condvec = cv;
|
||||
itemgen.init(mc, condvec.data(), condvec.size(), slist64, itemsize, type, sstart);
|
||||
itemgen.init(mainwin, mc, condvec.data(), condvec.size(), gen48, slist, itemsize, type, sstart);
|
||||
pool.setMaxThreadCount(threads);
|
||||
recieved.resize(queuesize);
|
||||
lastid = itemgen.itemid;
|
||||
@ -109,11 +109,18 @@ void SearchThread::run()
|
||||
{
|
||||
itemgen.presearch();
|
||||
pool.waitForDone();
|
||||
|
||||
uint64_t prog, end;
|
||||
itemgen.getProgress(&prog, &end);
|
||||
emit progress(prog, end, itemgen.seed);
|
||||
|
||||
for (int idx = 0; idx < recieved.size(); idx++)
|
||||
{
|
||||
recieved[idx].valid = false;
|
||||
startNextItem();
|
||||
}
|
||||
|
||||
emit searchEnded();
|
||||
}
|
||||
|
||||
|
||||
@ -126,7 +133,7 @@ SearchItem *SearchThread::startNextItem()
|
||||
QObject::connect(item, &SearchItem::itemDone, this, &SearchThread::onItemDone, Qt::BlockingQueuedConnection);
|
||||
QObject::connect(item, &SearchItem::canceled, this, &SearchThread::onItemCanceled, Qt::QueuedConnection);
|
||||
// redirect results to mainwindow
|
||||
QObject::connect(item, &SearchItem::results, parent, &MainWindow::searchResultsAdd, Qt::BlockingQueuedConnection);
|
||||
QObject::connect(item, &SearchItem::results, parent, &FormSearchControl::searchResultsAdd, Qt::BlockingQueuedConnection);
|
||||
++activecnt;
|
||||
pool.start(item);
|
||||
return item;
|
||||
|
@ -9,10 +9,8 @@
|
||||
|
||||
#include "searchitem.h"
|
||||
|
||||
#define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30)
|
||||
|
||||
|
||||
class MainWindow;
|
||||
class FormSearchControl;
|
||||
|
||||
struct SearchThread : QThread
|
||||
{
|
||||
@ -24,9 +22,10 @@ public:
|
||||
int64_t seed;
|
||||
};
|
||||
|
||||
SearchThread(MainWindow *parent);
|
||||
SearchThread(FormSearchControl *parent);
|
||||
|
||||
bool set(int type, int threads, std::vector<int64_t>& slist64, int64_t sstart, int mc,
|
||||
bool set(QObject *mainwin, int type, int threads, Gen48Settings gen48,
|
||||
std::vector<int64_t>& slist, int64_t sstart, int mc,
|
||||
const QVector<Condition>& cv, int itemsize, int queuesize);
|
||||
|
||||
virtual void run() override;
|
||||
@ -36,14 +35,15 @@ public:
|
||||
|
||||
signals:
|
||||
void progress(uint64_t last, uint64_t end, int64_t seed);
|
||||
void searchFinish();
|
||||
void searchEnded(); // search thread is exiting (e.g. abort or done)
|
||||
void searchFinish(); // search ended and is comlete
|
||||
|
||||
public slots:
|
||||
void onItemDone(uint64_t itemid, int64_t seed, bool isdone);
|
||||
void onItemCanceled(uint64_t itemid);
|
||||
|
||||
public:
|
||||
MainWindow * parent;
|
||||
FormSearchControl * parent;
|
||||
|
||||
QVector<Condition> condvec;
|
||||
SearchItemGenerator itemgen;
|
||||
|
79
settings.h
Normal file
79
settings.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
struct Config
|
||||
{
|
||||
bool smoothMotion;
|
||||
bool restoreSession;
|
||||
int autosaveCycle;
|
||||
int seedsPerItem;
|
||||
int queueSize;
|
||||
int maxMatching;
|
||||
|
||||
Config() { reset(); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
smoothMotion = true;
|
||||
restoreSession = true;
|
||||
autosaveCycle = 10;
|
||||
seedsPerItem = 256;
|
||||
queueSize = QThread::idealThreadCount();
|
||||
maxMatching = 65536;
|
||||
}
|
||||
};
|
||||
|
||||
enum { GEN48_AUTO, GEN48_QH, GEN48_QM, GEN48_LIST, GEN48_NONE };
|
||||
enum { IDEAL, CLASSIC, NORMAL, BARELY, IDEAL_SALTED };
|
||||
|
||||
struct Gen48Settings
|
||||
{
|
||||
int mode;
|
||||
QString slist48path;
|
||||
int64_t salt;
|
||||
int qual;
|
||||
int qmarea;
|
||||
bool manualarea;
|
||||
int x1, z1, x2, z2;
|
||||
|
||||
Gen48Settings() { reset(); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
mode = GEN48_AUTO;
|
||||
slist48path = "";
|
||||
salt = 0;
|
||||
qual = IDEAL;
|
||||
qmarea = 13028;
|
||||
manualarea = false;
|
||||
x1 = z1 = x2 = z2 = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// search type options from combobox
|
||||
enum { SEARCH_INC = 0, SEARCH_BLOCKS = 1, SEARCH_LIST = 2 };
|
||||
|
||||
struct SearchConfig
|
||||
{
|
||||
int searchmode;
|
||||
QString slist64path;
|
||||
int threads;
|
||||
int64_t startseed;
|
||||
bool stoponres;
|
||||
|
||||
SearchConfig() { reset(); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
searchmode = SEARCH_INC;
|
||||
slist64path = "";
|
||||
threads = QThread::idealThreadCount();
|
||||
startseed = 0;
|
||||
stoponres = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // SETTINGS_H
|
Loading…
Reference in New Issue
Block a user