mirror of
https://github.com/Cubitect/cubiomes-viewer.git
synced 2025-01-08 11:57:50 +08:00
Changes for v3.4
added headless search mode (#237) added user defined font selection added translatable biomes names added shortcut to copy active seed with CTRL+C and remapped copy-seed-list (#238) changed warning messages to work in headless mode changed zoom shortcuts to accept Qt defaults (#217) removed dejavu fonts
This commit is contained in:
parent
e67bcbb588
commit
026a9c6e03
2
cubiomes
2
cubiomes
@ -1 +1 @@
|
||||
Subproject commit f2c96306c77e216120beb4c65b90624c526a3ba5
|
||||
Subproject commit f81c2e4fdea0fa96d89c963be5948e0a1d1025d9
|
@ -33,17 +33,23 @@ static_gnu: {
|
||||
LIBS += -static -static-libgcc -static-libstdc++
|
||||
}
|
||||
|
||||
gcc {
|
||||
greaterThan(QMAKE_GCC_MAJOR_VERSION, 9): QMAKE_CXXFLAGS += -Wno-deprecated-copy
|
||||
}
|
||||
|
||||
CONFIG(debug, debug|release): {
|
||||
CUTARGET = debug
|
||||
QMAKE_CFLAGS += -fsanitize=undefined
|
||||
LIBS += -lubsan -ldl
|
||||
!win32 {
|
||||
QMAKE_CFLAGS += -fsanitize=undefined
|
||||
LIBS += -lubsan -ldl
|
||||
}
|
||||
} else {
|
||||
CUTARGET = release
|
||||
}
|
||||
|
||||
# compile cubiomes
|
||||
CUPATH = $$PWD/cubiomes
|
||||
QMAKE_PRE_LINK += $(MAKE) -C $$CUPATH -f $$CUPATH/makefile CFLAGS=\"$$QMAKE_CFLAGS\" $$CUTARGET
|
||||
QMAKE_PRE_LINK += $(MAKE) -C $$CUPATH -f $$CUPATH/makefile CC=\"$$QMAKE_CC\" CFLAGS=\"$$QMAKE_CFLAGS\" $$CUTARGET
|
||||
QMAKE_CLEAN += $$CUPATH/*.o $$CUPATH/libcubiomes.a
|
||||
LIBS += -lm $$CUPATH/libcubiomes.a
|
||||
|
||||
@ -96,6 +102,8 @@ SOURCES += \
|
||||
src/formgen48.cpp \
|
||||
src/formsearchcontrol.cpp \
|
||||
src/gotodialog.cpp \
|
||||
src/headless.cpp \
|
||||
src/message.cpp \
|
||||
src/presetdialog.cpp \
|
||||
src/protobasedialog.cpp \
|
||||
src/layerdialog.cpp \
|
||||
@ -159,6 +167,8 @@ HEADERS += \
|
||||
src/formgen48.h \
|
||||
src/formsearchcontrol.h \
|
||||
src/gotodialog.h \
|
||||
src/headless.h \
|
||||
src/message.h \
|
||||
src/presetdialog.h \
|
||||
src/protobasedialog.h \
|
||||
src/layerdialog.h \
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -73,8 +73,8 @@
|
||||
<file>icons/check_include_d.png</file>
|
||||
<file>icons/check_unchecked.png</file>
|
||||
<file>icons/height.png</file>
|
||||
<file>icons/trail.png</file>
|
||||
<file>icons/trail_d.png</file>
|
||||
<file>icons/trails.png</file>
|
||||
<file>icons/trails_d.png</file>
|
||||
<file>icons/missing.png</file>
|
||||
<file>icons/well.png</file>
|
||||
<file>icons/well_d.png</file>
|
||||
|
Before Width: | Height: | Size: 371 B After Width: | Height: | Size: 371 B |
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
@ -209,8 +209,5 @@
|
||||
<file>dark/window_undock_pressed.png</file>
|
||||
<file>dark/window_undock_pressed@2x.png</file>
|
||||
<file>dark.qss</file>
|
||||
<file>fonts/DejaVuSans.ttf</file>
|
||||
<file>fonts/DejaVuSans-Bold.ttf</file>
|
||||
<file>fonts/DejaVuSansMono.ttf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <QString>
|
||||
|
||||
#define VERS_MAJOR 3
|
||||
#define VERS_MINOR 3
|
||||
#define VERS_PATCH 0 // negative patch number designates a development version
|
||||
#define VERS_MINOR 4
|
||||
#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)
|
||||
|
@ -2,14 +2,6 @@
|
||||
<ui version="4.0">
|
||||
<class>AboutDialog</class>
|
||||
<widget class="QDialog" name="AboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>615</width>
|
||||
<height>427</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
@ -27,7 +19,7 @@
|
||||
<item row="0" column="2" rowspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-size:16pt; font-weight:600;">Cubiomes-Viewer _VERSION_</span></p><p>Built: _DATE_</p><p>URL: <a href="https://github.com/Cubitect/cubiomes-viewer"><span style=" text-decoration: underline; color:#0057ae;">https://github.com/Cubitect/cubiomes-viewer</span></a></p><p>License: <a href="https://www.gnu.org/licenses/gpl-3.0.en.html"><span style=" text-decoration: underline; color:#0057ae;">GPLv3</span></a></p><p><br/><span style=" font-size:12pt; font-weight:600;">Components and Legal Information</span></p><p>— Minecraft biome and structure generation from <a href="https://github.com/Cubitect/cubiomes/"><span style=" text-decoration: underline; color:#0057ae;">cubiomes</span></a>, licensed under <a href="https://mit-license.org/"><span style=" text-decoration: underline; color:#0057ae;">MIT</span></a>.</p><p>— Cross platform GUI toolkit: Qt _QT_MAJOR_._QT_MINOR_, available under <a href="https://www.qt.io/licensing/"><span style=" text-decoration: underline; color:#0057ae;">(L)GPLv3</span></a>.</p><p>— Dark Qt theme derived from <a href="https://github.com/ColinDuquesnoy/QDarkStyleSheet"><span style=" text-decoration: underline; color:#0057ae;">QDarkStyleSheet</span></a>, licensed under MIT.</p><p>— A copy of the <a href="https://dejavu-fonts.github.io/License.html"><span style=" text-decoration: underline; color:#0057ae;">DejaVu Fonts</span></a> is included in this build.</p><p>— Biome colors and icons are inspired by <a href="https://github.com/toolbox4minecraft/amidst"><span style=" text-decoration: underline; color:#0057ae;">Amidst</span></a>, licensed under GPLv3.</p><p>— <a href="https://www.lua.org/license.html"><span style=" text-decoration: underline; color:#0057ae;">Lua _LUA_VERS_</span></a> is distributed under the terms of the MIT license.<br/></p><p>NOT APPROVED BY OR ASSOCIATED WITH MOJANG.</p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:16pt; font-weight:600;">Cubiomes-Viewer _VERSION_</span></p><p>Built: _DATE_</p><p>URL: <a href="https://github.com/Cubitect/cubiomes-viewer"><span style=" text-decoration: underline; color:#0057ae;">https://github.com/Cubitect/cubiomes-viewer</span></a></p><p>License: <a href="https://www.gnu.org/licenses/gpl-3.0.en.html"><span style=" text-decoration: underline; color:#0057ae;">GPLv3</span></a></p><p><br/><span style=" font-size:12pt; font-weight:600;">Components and Legal Information</span></p><p>— Minecraft biome and structure generation from <a href="https://github.com/Cubitect/cubiomes/"><span style=" text-decoration: underline; color:#0057ae;">cubiomes</span></a>, licensed under <a href="https://mit-license.org/"><span style=" text-decoration: underline; color:#0057ae;">MIT</span></a>.</p><p>— Cross platform GUI toolkit: Qt _QT_MAJOR_._QT_MINOR_, available under <a href="https://www.qt.io/licensing/"><span style=" text-decoration: underline; color:#0057ae;">(L)GPLv3</span></a>.</p><p>— Dark Qt theme derived from <a href="https://github.com/ColinDuquesnoy/QDarkStyleSheet"><span style=" text-decoration: underline; color:#0057ae;">QDarkStyleSheet</span></a>, licensed under MIT.</p><p>— Biome colors and icons are inspired by <a href="https://github.com/toolbox4minecraft/amidst"><span style=" text-decoration: underline; color:#0057ae;">Amidst</span></a>, licensed under GPLv3.</p><p>— <a href="https://www.lua.org/license.html"><span style=" text-decoration: underline; color:#0057ae;">Lua _LUA_VERS_</span></a> is distributed under the terms of the MIT license.<br/></p><p>NOT APPROVED BY OR ASSOCIATED WITH MOJANG.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
@ -69,8 +69,8 @@ BiomeColorDialog::BiomeColorDialog(QWidget *parent, QString initrc, int mc, int
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
const char *bname = biome2str(mc, i);
|
||||
if (!bname)
|
||||
QString bname = getBiomeDisplay(mc, i);
|
||||
if (bname.isEmpty() || bname == "?")
|
||||
continue;
|
||||
|
||||
QColor col;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "mainwindow.h"
|
||||
#include "scripts.h"
|
||||
#include "layerdialog.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QIntValidator>
|
||||
@ -11,7 +12,6 @@
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QMessageBox>
|
||||
#include <QScrollBar>
|
||||
#include <QSpacerItem>
|
||||
#include <QTextStream>
|
||||
@ -38,10 +38,10 @@ static QString getTip(int mc, int layer, uint32_t flags, int id)
|
||||
QString tip = ConditionDialog::tr("Generates any of:");
|
||||
for (int j = 0; j < 64; j++)
|
||||
if (mL & (1ULL << j))
|
||||
tip += QString("\n") + biome2str(mc, j);
|
||||
tip += QString("\n") + getBiomeDisplay(mc, j);
|
||||
for (int j = 0; j < 64; j++)
|
||||
if (mM & (1ULL << j))
|
||||
tip += QString("\n") + biome2str(mc, 128+j);
|
||||
tip += QString("\n") + getBiomeDisplay(mc, 128+j);
|
||||
return tip;
|
||||
}
|
||||
|
||||
@ -66,8 +66,6 @@ ConditionDialog::ConditionDialog(FormConditions *parent, Config *config, int mcv
|
||||
QString mcs = tr("MC %1", "Minecraft version").arg(p_mcs ? p_mcs : "?");
|
||||
ui->labelMC->setText(mcs);
|
||||
|
||||
ui->lineSummary->setFont(*gp_font_mono);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
|
||||
ui->textEditLua->setTabStopWidth(QFontMetrics(ui->textEditLua->font()).width(" ") * 4);
|
||||
#else
|
||||
@ -92,7 +90,7 @@ ConditionDialog::ConditionDialog(FormConditions *parent, Config *config, int mcv
|
||||
if (c.save == initcond->relative)
|
||||
initindex = ui->comboBoxRelative->count();
|
||||
}
|
||||
QString condstr = c.summary().simplified();
|
||||
QString condstr = c.summary(nullptr).simplified();
|
||||
ui->comboBoxRelative->addItem(condstr, c.save);
|
||||
}
|
||||
if (initindex < 0)
|
||||
@ -130,10 +128,10 @@ ConditionDialog::ConditionDialog(FormConditions *parent, Config *config, int mcv
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
const char *str = biome2str(mc, i);
|
||||
if (!str)
|
||||
QString bname = getBiomeDisplay(mc, i);
|
||||
if (bname.isEmpty())
|
||||
continue;
|
||||
QCheckBox *cb = new QCheckBox(str);
|
||||
QCheckBox *cb = new QCheckBox(bname);
|
||||
ui->gridLayoutBiomes->addWidget(cb, i % 128, i / 128);
|
||||
cb->setTristate(true);
|
||||
biomecboxes[i] = cb;
|
||||
@ -245,7 +243,7 @@ ConditionDialog::ConditionDialog(FormConditions *parent, Config *config, int mcv
|
||||
const int *lim = getBiomeParaLimits(mc, id);
|
||||
if (!lim)
|
||||
continue;
|
||||
NoiseBiomeIndicator *cb = new NoiseBiomeIndicator(biome2str(mc, id), this);
|
||||
NoiseBiomeIndicator *cb = new NoiseBiomeIndicator(getBiomeDisplay(mc, id), this);
|
||||
QString tip = "<pre>";
|
||||
for (int j = 0; j < NP_MAX; j++)
|
||||
{
|
||||
@ -327,7 +325,7 @@ ConditionDialog::ConditionDialog(FormConditions *parent, Config *config, int mcv
|
||||
on_comboBoxRelative_activated(initindex);
|
||||
ui->textEditLua->document()->setModified(false);
|
||||
|
||||
ui->comboMatchBiome->insertItem(0, biome2str(mc, cond.biomeId), QVariant::fromValue(cond.biomeId));
|
||||
ui->comboMatchBiome->insertItem(0, getBiomeDisplay(mc, cond.biomeId), QVariant::fromValue(cond.biomeId));
|
||||
ui->comboMatchBiome->setCurrentIndex(0);
|
||||
|
||||
ui->comboClimatePara->setCurrentIndex(ui->comboClimatePara->findData(QVariant::fromValue(cond.para)));
|
||||
@ -610,7 +608,7 @@ void ConditionDialog::updateMode()
|
||||
ui->lineEditX2->setToolTip(uptip);
|
||||
ui->lineEditZ2->setToolTip(uptip);
|
||||
ui->buttonOk->setEnabled(filterindex != F_SELECT);
|
||||
textDescription->setText(ft.description);
|
||||
textDescription->setText(QApplication::translate("Filter", ft.description));
|
||||
}
|
||||
|
||||
void ConditionDialog::updateBiomeSelection()
|
||||
@ -668,12 +666,12 @@ void ConditionDialog::updateBiomeSelection()
|
||||
for (int j = 0; j < 64; j++)
|
||||
{
|
||||
if (mL & (1ULL << j))
|
||||
tip += QString("\n") + biome2str(mc, j);
|
||||
tip += QString("\n") + getBiomeDisplay(mc, j);
|
||||
}
|
||||
for (int j = 0; j < 64; j++)
|
||||
{
|
||||
if (mM & (1ULL << j))
|
||||
tip += QString("\n") + biome2str(mc, j+128);
|
||||
tip += QString("\n") + getBiomeDisplay(mc, j+128);
|
||||
}
|
||||
cb->setToolTip(tip);
|
||||
}
|
||||
@ -741,7 +739,7 @@ void ConditionDialog::updateBiomeSelection()
|
||||
|
||||
for (int id: available)
|
||||
{
|
||||
QString s = biome2str(mc, id);
|
||||
QString s = getBiomeDisplay(mc, id);
|
||||
ui->comboMatchBiome->addItem(getBiomeIcon(id), s, QVariant::fromValue(id));
|
||||
allowed_matches.append(s);
|
||||
}
|
||||
@ -754,7 +752,7 @@ void ConditionDialog::updateBiomeSelection()
|
||||
}
|
||||
else
|
||||
{
|
||||
QString s = QString("%1 %2").arg(WARNING_CHAR).arg(biome2str(mc, curid.toInt()));
|
||||
QString s = QString("%1 %2").arg(WARNING_CHAR).arg(getBiomeDisplay(mc, curid.toInt()));
|
||||
ui->comboMatchBiome->insertItem(0, getBiomeIcon(curid.toInt(), true), s, curid);
|
||||
ui->comboMatchBiome->setCurrentIndex(0);
|
||||
allowed_matches.append(s);
|
||||
@ -778,7 +776,7 @@ int ConditionDialog::warnIfBad(Condition cond)
|
||||
if (ui->checkStartPieces->isEnabled())
|
||||
{
|
||||
QString text = tr("No allowed start pieces specified. Condition can never be true.");
|
||||
QMessageBox::warning(this, tr("Missing Start Piece"), text, QMessageBox::Ok);
|
||||
warn(this, tr("Missing Start Piece"), text);
|
||||
return QMessageBox::Cancel;
|
||||
}
|
||||
}
|
||||
@ -792,8 +790,7 @@ int ConditionDialog::warnIfBad(Condition cond)
|
||||
"The condition contains a climate range which is unbounded "
|
||||
"with the full range required, which can never be satisfied."
|
||||
);
|
||||
QMessageBox::warning(this, tr("Bad Climate Range"), text,
|
||||
QMessageBox::Ok);
|
||||
warn(this, tr("Bad Climate Range"), text);
|
||||
return QMessageBox::Cancel;
|
||||
}
|
||||
}
|
||||
@ -808,7 +805,7 @@ int ConditionDialog::warnIfBad(Condition cond)
|
||||
"The biome locator checks for %1 instances of size %2 each, "
|
||||
"which cannot be satisfied by an area of size %3%4%5 = %6.")
|
||||
.arg(cond.count).arg(cond.biomeSize).arg(w).arg(QChar(0xD7)).arg(h).arg(w * h);
|
||||
QMessageBox::warning(this, tr("Area Insufficient"), text, QMessageBox::Ok);
|
||||
warn(this, tr("Area Insufficient"), text);
|
||||
return QMessageBox::Cancel;
|
||||
}
|
||||
}
|
||||
@ -823,7 +820,7 @@ int ConditionDialog::warnIfBad(Condition cond)
|
||||
(1ULL << (deep_dark-128));
|
||||
if ((m & underground) && cond.y > 246)
|
||||
{
|
||||
return QMessageBox::warning(this, tr("Bad Surface Height"),
|
||||
return warn(this, tr("Bad Surface Height"),
|
||||
tr("Cave biomes do not generate above Y = 246. "
|
||||
"You should consider lowering the sampling height."
|
||||
"\n\n"
|
||||
@ -1234,9 +1231,9 @@ void ConditionDialog::on_lineBiomeSize_textChanged(const QString &)
|
||||
double area = ui->lineBiomeSize->text().toInt();
|
||||
QString s;
|
||||
if (filterindex == F_BIOME_CENTER_256)
|
||||
s = QString::asprintf(tr("(~%g sq. chunks)").toStdString().c_str(), area * 256);
|
||||
s = tr("(~%1 sq. chunks)").arg(area * 256);
|
||||
else
|
||||
s = QString::asprintf(tr("(%g sq. chunks)").toStdString().c_str(), area / 16.0);
|
||||
s = tr("(%1 sq. chunks)").arg(area / 16.0);
|
||||
ui->labelBiomeSize->setText(s);
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>26</number>
|
||||
<number>25</number>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string/>
|
||||
@ -685,8 +685,8 @@ QPushButton:hover {
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>634</width>
|
||||
<height>301</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
@ -1069,8 +1069,8 @@ QPushButton:hover {
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>634</width>
|
||||
<height>254</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
@ -1174,7 +1174,7 @@ QPushButton:hover {
|
||||
<widget class="QComboBox" name="comboOctaves">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
@ -1316,7 +1316,7 @@ QPushButton:hover {
|
||||
<widget class="ScriptEditor" name="textEditLua">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
@ -1344,7 +1344,7 @@ QPushButton:hover {
|
||||
<widget class="QPlainTextEdit" name="textEditLuaOut">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
@ -1356,7 +1356,7 @@ QPushButton:hover {
|
||||
<widget class="QLabel" name="labelLuaCall">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
@ -1453,8 +1453,8 @@ QPushButton:hover {
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>634</width>
|
||||
<height>336</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3_1">
|
||||
@ -1510,8 +1510,8 @@ QPushButton:hover {
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>634</width>
|
||||
<height>336</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3_2">
|
||||
@ -1615,8 +1615,8 @@ QPushButton:hover {
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>634</width>
|
||||
<height>336</height>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3_3">
|
||||
|
101
src/config.cpp
101
src/config.cpp
@ -1,8 +1,10 @@
|
||||
#include "config.h"
|
||||
#include "cutil.h"
|
||||
#include "seedtables.h"
|
||||
|
||||
#include <QThread>
|
||||
#include <QCoreApplication>
|
||||
#include <QFontDatabase>
|
||||
|
||||
|
||||
void ExtGenConfig::reset()
|
||||
@ -120,8 +122,41 @@ bool LayerOpt::isClimate(int mc) const
|
||||
return mode >= LOPT_NOISE_T_4 && mode <= LOPT_NOISE_W_4;
|
||||
}
|
||||
|
||||
QString mapopt2display(int opt)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case D_GRID: return QApplication::translate("Map", "Grid");
|
||||
case D_SLIME: return QApplication::translate("Map", "Slime Chunks");
|
||||
case D_DESERT: return QApplication::translate("Map", "Desert Pyramid");
|
||||
case D_JUNGLE: return QApplication::translate("Map", "Jungle Temple");
|
||||
case D_HUT: return QApplication::translate("Map", "Swamp Hut");
|
||||
case D_IGLOO: return QApplication::translate("Map", "Igloo");
|
||||
case D_VILLAGE: return QApplication::translate("Map", "Village");
|
||||
case D_MANSION: return QApplication::translate("Map", "Woodland Mansion");
|
||||
case D_MONUMENT: return QApplication::translate("Map", "Ocean Monument");
|
||||
case D_RUINS: return QApplication::translate("Map", "Ocean Ruins");
|
||||
case D_SHIPWRECK: return QApplication::translate("Map", "Shipwreck");
|
||||
case D_TREASURE: return QApplication::translate("Map", "Buried Treasure");
|
||||
case D_MINESHAFT: return QApplication::translate("Map", "Mineshaft");
|
||||
case D_WELL: return QApplication::translate("Map", "Desert Well");
|
||||
case D_GEODE: return QApplication::translate("Map", "Geode");
|
||||
case D_OUTPOST: return QApplication::translate("Map", "Pillager Outpost");
|
||||
case D_ANCIENTCITY: return QApplication::translate("Map", "Ancient City");
|
||||
case D_TRAILS: return QApplication::translate("Map", "Trail Ruins");
|
||||
case D_PORTAL: return QApplication::translate("Map", "Ruined Portal");
|
||||
case D_PORTALN: return QApplication::translate("Map", "Ruined Portal (Nether)");
|
||||
case D_SPAWN: return QApplication::translate("Map", "Spawn");
|
||||
case D_STRONGHOLD: return QApplication::translate("Map", "Stronghold");
|
||||
case D_FORTESS: return QApplication::translate("Map", "Nether Fortress");
|
||||
case D_BASTION: return QApplication::translate("Map", "Bastion Remnant");
|
||||
case D_ENDCITY: return QApplication::translate("Map", "End City");
|
||||
case D_GATEWAY: return QApplication::translate("Map", "End Gateway");
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char *mapopt2str(int opt)
|
||||
const char *mapopt2str(int opt) // to resource string
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@ -142,7 +177,7 @@ const char *mapopt2str(int opt)
|
||||
case D_GEODE: return "geode";
|
||||
case D_OUTPOST: return "outpost";
|
||||
case D_ANCIENTCITY: return "ancient_city";
|
||||
case D_TRAIL: return "trails";
|
||||
case D_TRAILS: return "trails";
|
||||
case D_PORTAL: return "portal";
|
||||
case D_PORTALN: return "portaln";
|
||||
case D_SPAWN: return "spawn";
|
||||
@ -155,7 +190,7 @@ const char *mapopt2str(int opt)
|
||||
}
|
||||
}
|
||||
|
||||
int str2mapopt(const char *s)
|
||||
int str2mapopt(const char *s) // from resource string
|
||||
{
|
||||
if (!strcmp(s, "grid")) return D_GRID;
|
||||
if (!strcmp(s, "slime")) return D_SLIME;
|
||||
@ -174,7 +209,7 @@ int str2mapopt(const char *s)
|
||||
if (!strcmp(s, "geode")) return D_GEODE;
|
||||
if (!strcmp(s, "outpost")) return D_OUTPOST;
|
||||
if (!strcmp(s, "ancient_city")) return D_ANCIENTCITY;
|
||||
if (!strcmp(s, "trail")) return D_TRAIL;
|
||||
if (!strcmp(s, "trails")) return D_TRAILS;
|
||||
if (!strcmp(s, "portal")) return D_PORTAL;
|
||||
if (!strcmp(s, "portaln")) return D_PORTALN;
|
||||
if (!strcmp(s, "spawn")) return D_SPAWN;
|
||||
@ -205,7 +240,7 @@ int mapopt2stype(int opt)
|
||||
case D_GEODE: return Geode;
|
||||
case D_OUTPOST: return Outpost;
|
||||
case D_ANCIENTCITY: return Ancient_City;
|
||||
case D_TRAIL: return Trail_Ruin;
|
||||
case D_TRAILS: return Trail_Ruin;
|
||||
case D_PORTAL: return Ruined_Portal;
|
||||
case D_PORTALN: return Ruined_Portal_N;
|
||||
case D_FORTESS: return Fortress;
|
||||
@ -287,6 +322,14 @@ void Config::reset()
|
||||
biomeColorPath = "";
|
||||
separator = ";";
|
||||
quote = "";
|
||||
fontNorm = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
|
||||
fontMono = QFontDatabase::systemFont(QFontDatabase::FixedFont);
|
||||
//fontNorm.setFamily(QString::fromUtf8("DejaVu Sans"));
|
||||
//fontMono.setFamily(QString::fromUtf8("DejaVu Sans Mono"));
|
||||
fontMono.setStyleHint(QFont::Monospace);
|
||||
fontNorm.setStyleHint(QFont::AnyStyle);
|
||||
fontMono.setPointSize(10);
|
||||
fontNorm.setPointSize(10);
|
||||
}
|
||||
|
||||
void Config::load(QSettings& settings)
|
||||
@ -306,6 +349,8 @@ void Config::load(QSettings& settings)
|
||||
biomeColorPath = settings.value("config/biomeColorPath", biomeColorPath).toString();
|
||||
separator = settings.value("config/separator", separator).toString();
|
||||
quote = settings.value("config/quote", quote).toString();
|
||||
fontNorm = settings.value("config/fontNorm", fontNorm).value<QFont>();
|
||||
fontMono = settings.value("config/fontMono", fontMono).value<QFont>();
|
||||
}
|
||||
|
||||
void Config::save(QSettings& settings)
|
||||
@ -325,6 +370,8 @@ void Config::save(QSettings& settings)
|
||||
settings.setValue("config/biomeColorPath", biomeColorPath);
|
||||
settings.setValue("config/separator", separator);
|
||||
settings.setValue("config/quote", quote);
|
||||
settings.setValue("config/fontNorm", fontNorm);
|
||||
settings.setValue("config/fontMono", fontMono);
|
||||
}
|
||||
|
||||
void Gen48Config::reset()
|
||||
@ -376,6 +423,50 @@ void Gen48Config::write(QTextStream& stream)
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Gen48Config::estimateSeedCnt(uint64_t slist48len)
|
||||
{
|
||||
uint64_t cnt = 0;
|
||||
if (mode == GEN48_QH)
|
||||
{
|
||||
switch (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 (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]) >= qmarea)
|
||||
cnt++;
|
||||
}
|
||||
else if (mode == GEN48_LIST)
|
||||
{
|
||||
cnt = slist48len;
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt = MASK48 + 1;
|
||||
}
|
||||
|
||||
if (mode != GEN48_NONE)
|
||||
{
|
||||
uint64_t w = x2 - x1 + 1;
|
||||
uint64_t h = z2 - z1 + 1;
|
||||
uint64_t n = w*h * cnt; // div sizeof(uint64_t)
|
||||
if (cnt > 0 && n < PRECOMPUTE48_BUFSIZ * sizeof(uint64_t) && n / cnt == w*h)
|
||||
cnt = n;
|
||||
else
|
||||
cnt = MASK48 + 1;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
void SearchConfig::reset()
|
||||
{
|
||||
searchtype = SEARCH_INC;
|
||||
|
10
src/config.h
10
src/config.h
@ -12,6 +12,9 @@
|
||||
|
||||
#define APP_STRING "cubiomes-viewer"
|
||||
|
||||
#define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30)
|
||||
|
||||
|
||||
struct ExtGenConfig
|
||||
{
|
||||
bool experimentalVers;
|
||||
@ -113,7 +116,7 @@ enum {
|
||||
D_GEODE,
|
||||
D_OUTPOST,
|
||||
D_ANCIENTCITY,
|
||||
D_TRAIL,
|
||||
D_TRAILS,
|
||||
D_PORTAL,
|
||||
D_PORTALN,
|
||||
D_FORTESS,
|
||||
@ -126,6 +129,7 @@ enum {
|
||||
D_STRUCT_NUM
|
||||
};
|
||||
|
||||
QString mapopt2display(int opt);
|
||||
const char *mapopt2str(int opt);
|
||||
int str2mapopt(const char *s);
|
||||
int mapopt2stype(int opt);
|
||||
@ -176,6 +180,8 @@ struct Config
|
||||
QString biomeColorPath;
|
||||
QString separator;
|
||||
QString quote;
|
||||
QFont fontNorm;
|
||||
QFont fontMono;
|
||||
|
||||
Config() { reset(); }
|
||||
|
||||
@ -205,6 +211,8 @@ struct Gen48Config
|
||||
void reset();
|
||||
bool read(const QString& line);
|
||||
void write(QTextStream& stream);
|
||||
|
||||
uint64_t estimateSeedCnt(uint64_t slist48len);
|
||||
};
|
||||
|
||||
// search type options from combobox
|
||||
|
@ -29,8 +29,6 @@ ConfigDialog::ConfigDialog(QWidget *parent, Config *config)
|
||||
}
|
||||
#endif
|
||||
|
||||
ui->buttonBiomeColor->setFont(*gp_font_mono);
|
||||
|
||||
ui->lineMatching->setValidator(new QIntValidator(1, 99999999, ui->lineMatching));
|
||||
ui->spinThreads->setRange(1, QThread::idealThreadCount());
|
||||
|
||||
@ -75,6 +73,10 @@ void ConfigDialog::initConfig(Config *config)
|
||||
ui->lineSep->setText(config->separator);
|
||||
int idx = config->quote == "\'" ? 1 : config->quote== "\"" ? 2 : 0;
|
||||
ui->comboQuote->setCurrentIndex(idx);
|
||||
ui->fontComboNorm->setCurrentFont(config->fontNorm);
|
||||
ui->fontComboMono->setCurrentFont(config->fontMono);
|
||||
ui->spinFontSizeNorm->setValue(config->fontNorm.pointSize());
|
||||
ui->spinFontSizeMono->setValue(config->fontMono.pointSize());
|
||||
|
||||
setBiomeColorPath(config->biomeColorPath);
|
||||
}
|
||||
@ -97,6 +99,13 @@ Config ConfigDialog::getConfig()
|
||||
int idx = ui->comboQuote->currentIndex();
|
||||
conf.quote = idx == 1 ? "\'" : idx == 2 ? "\"" : "";
|
||||
|
||||
conf.fontNorm = ui->fontComboNorm->currentFont();
|
||||
conf.fontMono = ui->fontComboMono->currentFont();
|
||||
conf.fontNorm.setPointSize(ui->spinFontSizeNorm->value());
|
||||
conf.fontMono.setPointSize(ui->spinFontSizeMono->value());
|
||||
conf.fontNorm.setStyleHint(QFont::AnyStyle);
|
||||
conf.fontMono.setStyleHint(QFont::Monospace);
|
||||
|
||||
if (!conf.maxMatching) conf.maxMatching = 65536;
|
||||
|
||||
return conf;
|
||||
|
@ -145,28 +145,111 @@
|
||||
<string>Interface</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="buttonClear">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="toolTip">
|
||||
<string>Use a fixed grid in blocks instead of outlining the generated map tiles
|
||||
Leave blank for the default behaviour</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../rc/icons.qrc">
|
||||
<normaloff>:/icons/clear.png</normaloff>:/icons/clear.png</iconset>
|
||||
<property name="text">
|
||||
<string>Custom grid spacing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Map cache size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Font default:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="5">
|
||||
<widget class="QCheckBox" name="checkBBoxes">
|
||||
<property name="text">
|
||||
<string>Outline known bounding boxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Biome color customization:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Maximum structure zoom:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="lineGridSpacing"/>
|
||||
</item>
|
||||
<item row="5" column="2" colspan="2">
|
||||
<widget class="QPushButton" name="buttonBiomeColor">
|
||||
<property name="text">
|
||||
<string>[none]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboLang"/>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="3">
|
||||
<widget class="QPushButton" name="buttonBiomeColorEditor">
|
||||
<property name="text">
|
||||
<string>Edit biome colors...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Custom grid multiplier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" colspan="3">
|
||||
<widget class="QPushButton" name="buttonStructVisEdit">
|
||||
<property name="text">
|
||||
<string>Edit map visibility limits...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>GUI style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="5">
|
||||
<widget class="QCheckBox" name="checkSmooth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Simulate inertia for the map view</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Smooth map motion</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2" colspan="3">
|
||||
<widget class="QSpinBox" name="spinCacheSize">
|
||||
<property name="suffix">
|
||||
<string> MB</string>
|
||||
@ -185,50 +268,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboStyle">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>System</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dark</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="lineGridSpacing"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Maximum structure zoom:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboLang"/>
|
||||
</item>
|
||||
<item row="8" column="2" colspan="3">
|
||||
<widget class="QSpinBox" name="spinThreads"/>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="2">
|
||||
<widget class="QPushButton" name="buttonBiomeColor">
|
||||
<property name="text">
|
||||
<string>[none]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboGridMult">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
@ -260,53 +300,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="3">
|
||||
<widget class="QPushButton" name="buttonBiomeColorEditor">
|
||||
<property name="text">
|
||||
<string>Edit biome colors...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="5">
|
||||
<widget class="QCheckBox" name="checkBBoxes">
|
||||
<property name="text">
|
||||
<string>Outline known bounding boxes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Custom grid multiplier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2" colspan="3">
|
||||
<widget class="QPushButton" name="buttonStructVisEdit">
|
||||
<property name="text">
|
||||
<string>Edit map visibility limits...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="toolTip">
|
||||
<string>Use a fixed grid in blocks instead of outlining the generated map tiles
|
||||
Leave blank for the default behaviour</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Custom grid spacing:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
@ -342,37 +336,96 @@ QPushButton:hover {
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>GUI style:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="5">
|
||||
<widget class="QCheckBox" name="checkSmooth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Simulate inertia for the map view</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Smooth map motion</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Map cache size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Threads for map:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QPushButton" name="buttonClear">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../rc/icons.qrc">
|
||||
<normaloff>:/icons/clear.png</normaloff>:/icons/clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QComboBox" name="comboStyle">
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>System</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dark</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="2" colspan="3">
|
||||
<widget class="QSpinBox" name="spinThreads"/>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Font monospace:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QFontComboBox" name="fontComboNorm">
|
||||
<property name="fontFilters">
|
||||
<set>QFontComboBox::ScalableFonts</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3" colspan="2">
|
||||
<widget class="QSpinBox" name="spinFontSizeNorm">
|
||||
<property name="minimum">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QFontComboBox" name="fontComboMono">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="fontFilters">
|
||||
<set>QFontComboBox::MonospacedFonts</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3" colspan="2">
|
||||
<widget class="QSpinBox" name="spinFontSizeMono">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
167
src/cutil.h
167
src/cutil.h
@ -10,37 +10,6 @@
|
||||
#include "cubiomes/quadbase.h"
|
||||
#include "cubiomes/util.h"
|
||||
|
||||
|
||||
inline const char* struct2str(int stype)
|
||||
{
|
||||
switch (stype)
|
||||
{
|
||||
case Desert_Pyramid: return QApplication::translate("StructureDialog", "desert_pyramid").toUtf8().data();
|
||||
case Jungle_Temple: return QApplication::translate("StructureDialog", "jungle_temple").toUtf8().data();
|
||||
case Swamp_Hut: return QApplication::translate("StructureDialog", "swamp_hut").toUtf8().data();
|
||||
case Igloo: return QApplication::translate("StructureDialog", "igloo").toUtf8().data();
|
||||
case Village: return QApplication::translate("StructureDialog", "village").toUtf8().data();
|
||||
case Ocean_Ruin: return QApplication::translate("StructureDialog", "ocean_ruin").toUtf8().data();
|
||||
case Shipwreck: return QApplication::translate("StructureDialog", "shipwreck").toUtf8().data();
|
||||
case Monument: return QApplication::translate("StructureDialog", "monument").toUtf8().data();
|
||||
case Mansion: return QApplication::translate("StructureDialog", "mansion").toUtf8().data();
|
||||
case Outpost: return QApplication::translate("StructureDialog", "outpost").toUtf8().data();
|
||||
case Treasure: return QApplication::translate("StructureDialog", "treasure").toUtf8().data();
|
||||
case Mineshaft: return QApplication::translate("StructureDialog", "mineshaft").toUtf8().data();
|
||||
case Desert_Well: return QApplication::translate("StructureDialog", "desert_well").toUtf8().data();
|
||||
case Ruined_Portal: return QApplication::translate("StructureDialog", "ruined_portal").toUtf8().data();
|
||||
case Ruined_Portal_N: return QApplication::translate("StructureDialog", "ruined_portal (nether)").toUtf8().data();
|
||||
case Geode: return QApplication::translate("StructureDialog", "amethyst_geode").toUtf8().data();
|
||||
case Ancient_City: return QApplication::translate("StructureDialog", "ancient_city").toUtf8().data();
|
||||
case Trail_Ruin: return QApplication::translate("StructureDialog", "trail_ruins").toUtf8().data();
|
||||
case Fortress: return QApplication::translate("StructureDialog", "fortress").toUtf8().data();
|
||||
case Bastion: return QApplication::translate("StructureDialog", "bastion").toUtf8().data();
|
||||
case End_City: return QApplication::translate("StructureDialog", "end_city").toUtf8().data();
|
||||
case End_Gateway: return QApplication::translate("StructureDialog", "end_gateway").toUtf8().data();
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
struct StartPiece
|
||||
{
|
||||
int stype;
|
||||
@ -107,6 +76,142 @@ inline QString getStartPieceName(int stype, const StructureVariant *sv)
|
||||
return name;
|
||||
}
|
||||
|
||||
static inline QString getBiomeDisplay(int mc, int id)
|
||||
{
|
||||
if (mc >= MC_1_18)
|
||||
{
|
||||
// a bunch of 'new' biomes in 1.18 actually just got renamed
|
||||
// (based on their features and biome id conversion when upgrading)
|
||||
switch (id)
|
||||
{
|
||||
case old_growth_birch_forest: return QApplication::translate("Biome", "Old Growth Birch Forest");
|
||||
case old_growth_pine_taiga: return QApplication::translate("Biome", "Old Growth Pine Taiga");
|
||||
case old_growth_spruce_taiga: return QApplication::translate("Biome", "Old Growth Spruce Taiga");
|
||||
case snowy_plains: return QApplication::translate("Biome", "Snowy Plains");
|
||||
case sparse_jungle: return QApplication::translate("Biome", "Sparse Jungle");
|
||||
case stony_shore: return QApplication::translate("Biome", "Stony Shore");
|
||||
case windswept_hills: return QApplication::translate("Biome", "Windswept Hills");
|
||||
case windswept_forest: return QApplication::translate("Biome", "Windswept Forest");
|
||||
case windswept_gravelly_hills: return QApplication::translate("Biome", "Windswept Gravelly Hills");
|
||||
case windswept_savanna: return QApplication::translate("Biome", "Windswept Savanna");
|
||||
case wooded_badlands: return QApplication::translate("Biome", "Wooded Badlands");
|
||||
}
|
||||
}
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case ocean: return QApplication::translate("Biome", "Ocean");
|
||||
case plains: return QApplication::translate("Biome", "Plains");
|
||||
case desert: return QApplication::translate("Biome", "Desert");
|
||||
case mountains: return QApplication::translate("Biome", "Mountains");
|
||||
case forest: return QApplication::translate("Biome", "Forest");
|
||||
case taiga: return QApplication::translate("Biome", "Taiga");
|
||||
case swamp: return QApplication::translate("Biome", "Swamp");
|
||||
case river: return QApplication::translate("Biome", "River");
|
||||
case nether_wastes: return QApplication::translate("Biome", "Nether Wastes");
|
||||
case the_end: return QApplication::translate("Biome", "The End");
|
||||
// 10
|
||||
case frozen_ocean: return QApplication::translate("Biome", "Frozen Ocean");
|
||||
case frozen_river: return QApplication::translate("Biome", "Frozen River");
|
||||
case snowy_tundra: return QApplication::translate("Biome", "Snowy Plains");
|
||||
case snowy_mountains: return QApplication::translate("Biome", "Snowy Mountains");
|
||||
case mushroom_fields: return QApplication::translate("Biome", "Mushroom Fields");
|
||||
case mushroom_field_shore: return QApplication::translate("Biome", "Mushroom Field Shore");
|
||||
case beach: return QApplication::translate("Biome", "Beach");
|
||||
case desert_hills: return QApplication::translate("Biome", "Desert Hills");
|
||||
case wooded_hills: return QApplication::translate("Biome", "Wooded Hills");
|
||||
case taiga_hills: return QApplication::translate("Biome", "Taiga Hills");
|
||||
// 20
|
||||
case mountain_edge: return QApplication::translate("Biome", "Mountain Edge");
|
||||
case jungle: return QApplication::translate("Biome", "Jungle");
|
||||
case jungle_hills: return QApplication::translate("Biome", "Jungle Hills");
|
||||
case jungle_edge: return QApplication::translate("Biome", "Jungle Edge");
|
||||
case deep_ocean: return QApplication::translate("Biome", "Deep Ocean");
|
||||
case stone_shore: return QApplication::translate("Biome", "Stone Shore");
|
||||
case snowy_beach: return QApplication::translate("Biome", "Snowy Beach");
|
||||
case birch_forest: return QApplication::translate("Biome", "Birch Forest");
|
||||
case birch_forest_hills: return QApplication::translate("Biome", "Birch Forest Hills");
|
||||
case dark_forest: return QApplication::translate("Biome", "Dark Forest");
|
||||
// 30
|
||||
case snowy_taiga: return QApplication::translate("Biome", "Snowy Taiga");
|
||||
case snowy_taiga_hills: return QApplication::translate("Biome", "Snowy Taiga Hills");
|
||||
case giant_tree_taiga: return QApplication::translate("Biome", "Giant Tree Taiga");
|
||||
case giant_tree_taiga_hills: return QApplication::translate("Biome", "Giant Tree Taiga Hills");
|
||||
case wooded_mountains: return QApplication::translate("Biome", "Wooded Mountains");
|
||||
case savanna: return QApplication::translate("Biome", "Savanna");
|
||||
case savanna_plateau: return QApplication::translate("Biome", "Savanna Plateau");
|
||||
case badlands: return QApplication::translate("Biome", "Badlands");
|
||||
case wooded_badlands_plateau: return QApplication::translate("Biome", "Wooded Badlands Plateau");
|
||||
case badlands_plateau: return QApplication::translate("Biome", "Badlands Plateau");
|
||||
// 40 -- 1.13
|
||||
case small_end_islands: return QApplication::translate("Biome", "Small End Islands");
|
||||
case end_midlands: return QApplication::translate("Biome", "End Midlands");
|
||||
case end_highlands: return QApplication::translate("Biome", "End Highlands");
|
||||
case end_barrens: return QApplication::translate("Biome", "End Barrens");
|
||||
case warm_ocean: return QApplication::translate("Biome", "Warm Ocean");
|
||||
case lukewarm_ocean: return QApplication::translate("Biome", "Lukewarm Ocean");
|
||||
case cold_ocean: return QApplication::translate("Biome", "Cold Ocean");
|
||||
case deep_warm_ocean: return QApplication::translate("Biome", "Deep Warm Ocean");
|
||||
case deep_lukewarm_ocean: return QApplication::translate("Biome", "Deep Lukewarm Ocean");
|
||||
case deep_cold_ocean: return QApplication::translate("Biome", "Deep Cold Ocean");
|
||||
// 50
|
||||
case deep_frozen_ocean: return QApplication::translate("Biome", "Deep Frozen Ocean");
|
||||
// Alpha 1.2 - Beta 1.7
|
||||
case seasonal_forest: return QApplication::translate("Biome", "Seasonal Forest");
|
||||
case shrubland: return QApplication::translate("Biome", "Shrubland");
|
||||
case rainforest: return QApplication::translate("Biome", "Rain Forest");
|
||||
|
||||
case the_void: return QApplication::translate("Biome", "The Void");
|
||||
|
||||
// mutated variants
|
||||
case sunflower_plains: return QApplication::translate("Biome", "Sunflower Plains");
|
||||
case desert_lakes: return QApplication::translate("Biome", "Desert Lakes");
|
||||
case gravelly_mountains: return QApplication::translate("Biome", "Gravelly Mountains");
|
||||
case flower_forest: return QApplication::translate("Biome", "Flower Forest");
|
||||
case taiga_mountains: return QApplication::translate("Biome", "Taiga Mountains");
|
||||
case swamp_hills: return QApplication::translate("Biome", "Swamp Hills");
|
||||
case ice_spikes: return QApplication::translate("Biome", "Ice Spikes");
|
||||
case modified_jungle: return QApplication::translate("Biome", "Modified Jungle");
|
||||
case modified_jungle_edge: return QApplication::translate("Biome", "Modified Jungle Edge");
|
||||
case tall_birch_forest: return QApplication::translate("Biome", "Tall Birch Forest");
|
||||
case tall_birch_hills: return QApplication::translate("Biome", "Tall Birch Hills");
|
||||
case dark_forest_hills: return QApplication::translate("Biome", "Dark Forest Hills");
|
||||
case snowy_taiga_mountains: return QApplication::translate("Biome", "Snowy Taiga Mountains");
|
||||
case giant_spruce_taiga: return QApplication::translate("Biome", "Giant Spruce Taiga");
|
||||
case giant_spruce_taiga_hills: return QApplication::translate("Biome", "Giant Spruce Taiga Hills");
|
||||
case modified_gravelly_mountains: return QApplication::translate("Biome", "Gravelly Mountains+");
|
||||
case shattered_savanna: return QApplication::translate("Biome", "Shattered Savanna");
|
||||
case shattered_savanna_plateau: return QApplication::translate("Biome", "Shattered Savanna Plateau");
|
||||
case eroded_badlands: return QApplication::translate("Biome", "Eroded Badlands");
|
||||
case modified_wooded_badlands_plateau: return QApplication::translate("Biome", "Modified Wooded Badlands Plateau");
|
||||
case modified_badlands_plateau: return QApplication::translate("Biome", "Modified Badlands Plateau");
|
||||
// 1.14
|
||||
case bamboo_jungle: return QApplication::translate("Biome", "Bamboo Jungle");
|
||||
case bamboo_jungle_hills: return QApplication::translate("Biome", "Bamboo Jungle Hills");
|
||||
// 1.16
|
||||
case soul_sand_valley: return QApplication::translate("Biome", "Soul Sand Valley");
|
||||
case crimson_forest: return QApplication::translate("Biome", "Crimson Forest");
|
||||
case warped_forest: return QApplication::translate("Biome", "Warped Forest");
|
||||
case basalt_deltas: return QApplication::translate("Biome", "Basalt Deltas");
|
||||
// 1.17
|
||||
case dripstone_caves: return QApplication::translate("Biome", "Dripstone Caves");
|
||||
case lush_caves: return QApplication::translate("Biome", "Lush Caves");
|
||||
// 1.18
|
||||
case meadow: return QApplication::translate("Biome", "Meadow");
|
||||
case grove: return QApplication::translate("Biome", "Grove");
|
||||
case snowy_slopes: return QApplication::translate("Biome", "Snowy Slopes");
|
||||
case stony_peaks: return QApplication::translate("Biome", "Stony Peaks");
|
||||
case jagged_peaks: return QApplication::translate("Biome", "Jagged Peaks");
|
||||
case frozen_peaks: return QApplication::translate("Biome", "Frozen Peaks");
|
||||
// 1.19
|
||||
case deep_dark: return QApplication::translate("Biome", "Deep Dark");
|
||||
case mangrove_swamp: return QApplication::translate("Biome", "Mangrove Swamp");
|
||||
// 1.20
|
||||
case cherry_grove: return QApplication::translate("Biome", "Cherry Grove");
|
||||
}
|
||||
const char *name = biome2str(mc, id);
|
||||
return name ? name : "";
|
||||
}
|
||||
|
||||
// get a random 64-bit integer
|
||||
static inline uint64_t getRnd64()
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "mainwindow.h"
|
||||
#include "mapview.h"
|
||||
#include "cutil.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <QIntValidator>
|
||||
#include <QFileDialog>
|
||||
@ -86,7 +87,7 @@ void ExportWorker::run()
|
||||
|
||||
static void setCombo(QComboBox *cb, const char *setting)
|
||||
{
|
||||
QSettings settings("cubiomes-viewer", "cubiomes-viewer");
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
int idx = settings.value(setting, cb->currentIndex()).toInt();
|
||||
if (idx < cb->count())
|
||||
cb->setCurrentIndex(idx);
|
||||
@ -136,7 +137,7 @@ ExportDialog::ExportDialog(MainWindow *parent)
|
||||
connect(ui->comboTileSize, SIGNAL(activated(int)), this, SLOT(update()));
|
||||
connect(ui->groupTiled, SIGNAL(toggled(bool)), this, SLOT(update()));
|
||||
|
||||
QSettings settings("cubiomes-viewer", "cubiomes-viewer");
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
|
||||
ui->lineDir->setText(settings.value("export/prevdir", mainwindow->prevdir).toString());
|
||||
ui->linePattern->setText(settings.value("export/pattern", "%S_%x_%z.png").toString());
|
||||
@ -173,7 +174,7 @@ bool ExportDialog::initWork(ExportWorkItem *work, uint64_t seed, int tx, int tz)
|
||||
work->tx = tx;
|
||||
work->tz = tz;
|
||||
work->fnam = pattern;
|
||||
work->fnam.replace("%S", QString::number(seed));
|
||||
work->fnam.replace("%S", QString::number((int64_t)seed));
|
||||
work->fnam.replace("%x", QString::number(tx));
|
||||
work->fnam.replace("%z", QString::number(tz));
|
||||
work->fnam = dir.filePath(work->fnam);
|
||||
@ -213,7 +214,7 @@ void ExportDialog::update()
|
||||
|
||||
if (ui->comboSeed->currentIndex() == 1)
|
||||
{
|
||||
const QVector<uint64_t>& seeds = mainwindow->formControl->getResults();
|
||||
const std::vector<uint64_t>& seeds = mainwindow->formControl->getResults();
|
||||
seedcnt = seeds.size();
|
||||
}
|
||||
|
||||
@ -313,7 +314,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
WorldInfo wi;
|
||||
mainwindow->getSeed(&wi, true);
|
||||
|
||||
QVector<uint64_t> seeds;
|
||||
std::vector<uint64_t> seeds;
|
||||
if (seedmode == 0)
|
||||
seeds.push_back(wi.seed);
|
||||
else if (seedmode == 1)
|
||||
@ -321,17 +322,15 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
|
||||
if (seeds.size() > 1 && !pattern.contains("%S"))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Warning"),
|
||||
tr("When exporting more than one seed, the file pattern "
|
||||
"has to include the \"%S\" format specifier for the seed number."));
|
||||
warn(this, tr("When exporting more than one seed, the file pattern has to "
|
||||
"include the \"%S\" format specifier for the seed number."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (tiled && (!pattern.contains("%x") || !pattern.contains("%z")))
|
||||
{
|
||||
QMessageBox::warning(this, tr("Warning"),
|
||||
tr("Exporting as tiled images requires both the \"%x\" and \"%z\" "
|
||||
"format specifiers in the file pattern, representing the tile coordinates."));
|
||||
warn(this, tr("Exporting as tiled images requires both the \"%x\" and \"%z\" "
|
||||
"format specifiers in the file pattern, representing the tile coordinates."));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -348,7 +347,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
|
||||
if (x1 <= x0 || z1 <= z0)
|
||||
{
|
||||
QMessageBox::warning(this, tr("Warning"), tr("Invalid area."));
|
||||
warn(this, tr("Invalid area."));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -379,7 +378,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
this->tilesize = tilesize;
|
||||
this->bgmode = bgmode;
|
||||
|
||||
for (uint64_t seed : qAsConst(seeds))
|
||||
for (uint64_t seed : seeds)
|
||||
{
|
||||
for (int x = tx0; x < tx1; x++)
|
||||
{
|
||||
@ -397,9 +396,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
int maxsiz = 0x8000;
|
||||
if (x1 - x0 >= maxsiz || z1 - z0 >= maxsiz)
|
||||
{
|
||||
int button = QMessageBox::warning(this, tr("Warning"),
|
||||
tr("Consider tiling very large images into smaller sections.\n"
|
||||
"Continue?"),
|
||||
int button = warn(this, tr("Consider tiling very large images into smaller sections.\nContinue?"),
|
||||
QMessageBox::Cancel | QMessageBox::Yes);
|
||||
if (button == QMessageBox::Cancel)
|
||||
{
|
||||
@ -407,7 +404,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
}
|
||||
}
|
||||
|
||||
for (uint64_t seed : qAsConst(seeds))
|
||||
for (uint64_t seed : seeds)
|
||||
{
|
||||
ExportWorkItem work;
|
||||
existwarn |= initWork(&work, seed, 0, 0);
|
||||
@ -417,9 +414,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
|
||||
if (existwarn)
|
||||
{
|
||||
int button = QMessageBox::warning(this, tr("Warning"),
|
||||
tr("One or more of files already exist.\n"
|
||||
"Continue and overwrite?"),
|
||||
int button = warn(this, tr("One or more of files already exist.\nContinue and overwrite?"),
|
||||
QMessageBox::Cancel | QMessageBox::Yes);
|
||||
if (button == QMessageBox::Cancel)
|
||||
{
|
||||
@ -427,7 +422,7 @@ void ExportDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
}
|
||||
}
|
||||
|
||||
QSettings settings("cubiomes-viewer", "cubiomes-viewer");
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
settings.setValue("export/seedIdx", ui->comboSeed->currentIndex());
|
||||
settings.setValue("export/prevdir", ui->lineDir->text());
|
||||
settings.setValue("export/pattern", ui->linePattern->text());
|
||||
|
@ -39,8 +39,6 @@ FormConditions::FormConditions(QWidget *parent)
|
||||
|
||||
qRegisterMetaType< Condition >("Condition");
|
||||
qRegisterMetaTypeStreamOperators< Condition >("Condition");
|
||||
|
||||
ui->listConditionsFull->setFont(*gp_font_mono);
|
||||
}
|
||||
|
||||
FormConditions::~FormConditions()
|
||||
@ -52,9 +50,9 @@ QVector<Condition> FormConditions::getConditions() const
|
||||
{
|
||||
QVector<Condition> conds;
|
||||
|
||||
for (int i = 0, ie = ui->listConditionsFull->count(); i < ie; i++)
|
||||
for (int i = 0, ie = ui->listConditions->count(); i < ie; i++)
|
||||
{
|
||||
Condition c = qvariant_cast<Condition>(ui->listConditionsFull->item(i)->data(Qt::UserRole));
|
||||
Condition c = qvariant_cast<Condition>(ui->listConditions->item(i)->data(Qt::UserRole));
|
||||
conds.push_back(c);
|
||||
}
|
||||
return conds;
|
||||
@ -64,7 +62,7 @@ void FormConditions::updateSensitivity()
|
||||
{
|
||||
if (!parent)
|
||||
return;
|
||||
QList<QListWidgetItem*> selected = ui->listConditionsFull->selectedItems();
|
||||
QList<QListWidgetItem*> selected = ui->listConditions->selectedItems();
|
||||
|
||||
if (selected.size() == 0)
|
||||
{
|
||||
@ -155,7 +153,7 @@ void FormConditions::setItemCondition(QListWidget *list, QListWidgetItem *item,
|
||||
cond->save = getIndex(cond->save);
|
||||
}
|
||||
|
||||
QString s = cond->summary();
|
||||
QString s = cond->summary(&ui->listConditions->font());
|
||||
|
||||
const FilterInfo& ft = g_filterinfo.list[cond->type];
|
||||
if (ft.cat == CAT_QUAD)
|
||||
@ -189,25 +187,25 @@ static void remove_selected(QListWidget *list)
|
||||
|
||||
void FormConditions::on_buttonRemoveAll_clicked()
|
||||
{
|
||||
ui->listConditionsFull->clear();
|
||||
ui->listConditions->clear();
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::on_buttonRemove_clicked()
|
||||
{
|
||||
remove_selected(ui->listConditionsFull);
|
||||
remove_selected(ui->listConditions);
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::on_buttonDisable_clicked()
|
||||
{
|
||||
emit changed();
|
||||
QList<QListWidgetItem*> selected = ui->listConditionsFull->selectedItems();
|
||||
QList<QListWidgetItem*> selected = ui->listConditions->selectedItems();
|
||||
for (QListWidgetItem *item : selected)
|
||||
{
|
||||
Condition c = qvariant_cast<Condition>(item->data(Qt::UserRole));
|
||||
c.meta ^= Condition::DISABLED;
|
||||
item->setText(c.summary());
|
||||
item->setText(c.summary(&font()));
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(c));
|
||||
}
|
||||
updateSensitivity();
|
||||
@ -216,7 +214,7 @@ void FormConditions::on_buttonDisable_clicked()
|
||||
void FormConditions::on_buttonEdit_clicked()
|
||||
{
|
||||
QListWidgetItem* edit = 0;
|
||||
QList<QListWidgetItem*> selected = ui->listConditionsFull->selectedItems();
|
||||
QList<QListWidgetItem*> selected = ui->listConditions->selectedItems();
|
||||
|
||||
if (!selected.empty())
|
||||
edit = lockItem(selected.first());
|
||||
@ -236,13 +234,13 @@ void FormConditions::on_buttonAddFilter_clicked()
|
||||
dialog->show();
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_customContextMenuRequested(const QPoint &pos)
|
||||
void FormConditions::on_listConditions_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QMenu menu(this);
|
||||
// this is a contextual temporary menu so shortcuts are only indicated here,
|
||||
// but will not function - see keyReleaseEvent() for shortcut implementation
|
||||
|
||||
int n = ui->listConditionsFull->selectedItems().size();
|
||||
int n = ui->listConditions->selectedItems().size();
|
||||
|
||||
if (parent)
|
||||
{
|
||||
@ -285,17 +283,17 @@ void FormConditions::on_listConditionsFull_customContextMenuRequested(const QPoi
|
||||
actcopy->setEnabled(n > 0);
|
||||
}
|
||||
|
||||
menu.exec(ui->listConditionsFull->mapToGlobal(pos));
|
||||
menu.exec(ui->listConditions->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_itemDoubleClicked(QListWidgetItem *item)
|
||||
void FormConditions::on_listConditions_itemDoubleClicked(QListWidgetItem *item)
|
||||
{
|
||||
if (!parent)
|
||||
return;
|
||||
editCondition(lockItem(item));
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_itemSelectionChanged()
|
||||
void FormConditions::on_listConditions_itemSelectionChanged()
|
||||
{
|
||||
updateSensitivity();
|
||||
}
|
||||
@ -325,7 +323,7 @@ void FormConditions::conditionsCut()
|
||||
void FormConditions::conditionsCopy()
|
||||
{
|
||||
QString text;
|
||||
QList<QListWidgetItem*> selected = ui->listConditionsFull->selectedItems();
|
||||
QList<QListWidgetItem*> selected = ui->listConditions->selectedItems();
|
||||
for (QListWidgetItem *item : selected)
|
||||
{
|
||||
Condition c = qvariant_cast<Condition>(item->data(Qt::UserRole));
|
||||
@ -372,17 +370,17 @@ void FormConditions::addItemCondition(QListWidgetItem *item, Condition cond, int
|
||||
item = new QListWidgetItem();
|
||||
modified = 1;
|
||||
}
|
||||
setItemCondition(ui->listConditionsFull, item, &cond);
|
||||
setItemCondition(ui->listConditions, item, &cond);
|
||||
}
|
||||
else if (item)
|
||||
{
|
||||
setItemCondition(ui->listConditionsFull, item, &cond);
|
||||
setItemCondition(ui->listConditions, item, &cond);
|
||||
}
|
||||
else
|
||||
{
|
||||
modified = 1;
|
||||
item = new QListWidgetItem();
|
||||
setItemCondition(ui->listConditionsFull, item, &cond);
|
||||
setItemCondition(ui->listConditions, item, &cond);
|
||||
|
||||
if (cond.type >= F_QH_IDEAL && cond.type <= F_QH_BARELY)
|
||||
{
|
||||
@ -396,8 +394,8 @@ void FormConditions::addItemCondition(QListWidgetItem *item, Condition cond, int
|
||||
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);
|
||||
QListWidgetItem *item = new QListWidgetItem(ui->listConditions, QListWidgetItem::UserType);
|
||||
setItemCondition(ui->listConditions, item, &cq);
|
||||
}
|
||||
else if (cond.type == F_QM_90 || cond.type == F_QM_95)
|
||||
{
|
||||
@ -411,8 +409,8 @@ void FormConditions::addItemCondition(QListWidgetItem *item, Condition cond, int
|
||||
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);
|
||||
QListWidgetItem *item = new QListWidgetItem(ui->listConditions, QListWidgetItem::UserType);
|
||||
setItemCondition(ui->listConditions, item, &cq);
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,14 +418,14 @@ void FormConditions::addItemCondition(QListWidgetItem *item, Condition cond, int
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::on_listConditionsFull_indexesMoved(const QModelIndexList &)
|
||||
void FormConditions::on_listConditions_indexesMoved(const QModelIndexList &)
|
||||
{
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void FormConditions::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if (ui->listConditionsFull->hasFocus())
|
||||
if (ui->listConditions->hasFocus())
|
||||
{
|
||||
if (event->matches(QKeySequence::New))
|
||||
conditionsAdd();
|
||||
|
@ -40,9 +40,9 @@ public slots:
|
||||
void on_buttonEdit_clicked();
|
||||
void on_buttonAddFilter_clicked();
|
||||
|
||||
void on_listConditionsFull_customContextMenuRequested(const QPoint &pos);
|
||||
void on_listConditionsFull_itemDoubleClicked(QListWidgetItem *item);
|
||||
void on_listConditionsFull_itemSelectionChanged();
|
||||
void on_listConditions_customContextMenuRequested(const QPoint &pos);
|
||||
void on_listConditions_itemDoubleClicked(QListWidgetItem *item);
|
||||
void on_listConditions_itemSelectionChanged();
|
||||
|
||||
void conditionsAdd();
|
||||
void conditionsEdit();
|
||||
@ -54,7 +54,7 @@ public slots:
|
||||
void addItemCondition(QListWidgetItem *item, Condition cond, int modified = 1);
|
||||
|
||||
private slots:
|
||||
void on_listConditionsFull_indexesMoved(const QModelIndexList &indexes);
|
||||
void on_listConditions_indexesMoved(const QModelIndexList &indexes);
|
||||
|
||||
protected:
|
||||
void keyReleaseEvent(QKeyEvent *event) override;
|
||||
|
@ -30,7 +30,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="5">
|
||||
<widget class="QListWidget" name="listConditionsFull">
|
||||
<widget class="QListWidget" name="listConditions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
|
@ -4,12 +4,12 @@
|
||||
#include "mainwindow.h"
|
||||
#include "search.h"
|
||||
#include "seedtables.h"
|
||||
#include "message.h"
|
||||
|
||||
#include "cubiomes/util.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QSpinBox>
|
||||
#include <QList>
|
||||
|
||||
@ -79,8 +79,6 @@ FormGen48::FormGen48(MainWindow *parent)
|
||||
connect(ui->lineSalt, SIGNAL(editingFinished()), SLOT(onChange()));
|
||||
connect(ui->lineListSalt, SIGNAL(editingFinished()), SLOT(onChange()));
|
||||
|
||||
ui->lineList48->setFont(*gp_font_mono);
|
||||
|
||||
cond.type = 0;
|
||||
Gen48Config defaults;
|
||||
setConfig(defaults, true);
|
||||
@ -114,10 +112,8 @@ bool FormGen48::setList48(QString path, bool quiet)
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
int button = QMessageBox::warning(
|
||||
this, tr("Warning"),
|
||||
tr("Failed to load 48-bit seed list from file:\n\"%1\"").arg(path),
|
||||
QMessageBox::Reset, QMessageBox::Ignore);
|
||||
int button = warn(this, tr("Failed to load 48-bit seed list from file:\n\"%1\"").arg(path),
|
||||
QMessageBox::Reset|QMessageBox::Ignore);
|
||||
if (button == QMessageBox::Reset)
|
||||
{
|
||||
slist48path.clear();
|
||||
@ -205,48 +201,7 @@ Gen48Config FormGen48::getConfig(bool resolveauto)
|
||||
|
||||
uint64_t FormGen48::estimateSeedCnt()
|
||||
{
|
||||
const Gen48Config& gen48 = getConfig(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(uint64_t) && n / cnt == w*h)
|
||||
cnt = n;
|
||||
else
|
||||
cnt = MASK48+1;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
return getConfig(true).estimateSeedCnt(slist48.size());
|
||||
}
|
||||
|
||||
void FormGen48::updateCount()
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>435</width>
|
||||
<height>182</height>
|
||||
<height>188</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -20,26 +20,53 @@
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<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="margin">
|
||||
<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" colspan="2">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabAuto">
|
||||
<attribute name="title">
|
||||
<string>Auto/None</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="margin">
|
||||
<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">
|
||||
@ -63,7 +90,16 @@
|
||||
<string>Quad-feature</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="margin">
|
||||
<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="1" column="0">
|
||||
@ -154,7 +190,16 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
|
||||
<string>Seed list</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<property name="margin">
|
||||
<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">
|
||||
@ -172,7 +217,6 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
@ -226,7 +270,16 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="margin">
|
||||
<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="1">
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "mainwindow.h"
|
||||
#include "search.h"
|
||||
#include "rangedialog.h"
|
||||
#include "message.h"
|
||||
|
||||
#include "cubiomes/util.h"
|
||||
|
||||
@ -99,9 +100,9 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
|
||||
, proxy(new SeedSortProxy(this))
|
||||
, protodialog()
|
||||
, sthread(this)
|
||||
, stimer()
|
||||
, elapsed()
|
||||
, proghist()
|
||||
, stimer()
|
||||
, resultfile()
|
||||
, slist64path()
|
||||
, slist64fnam()
|
||||
, slist64()
|
||||
@ -114,17 +115,12 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
|
||||
ui->setupUi(this);
|
||||
protodialog = new ProtoBaseDialog(this);
|
||||
|
||||
QFont mono = *gp_font_mono;
|
||||
ui->results->setFont(mono);
|
||||
ui->progressBar->setFont(mono);
|
||||
ui->labelStatus->setFont(mono);
|
||||
|
||||
proxy->setSourceModel(model);
|
||||
ui->results->setModel(proxy);
|
||||
|
||||
ui->results->horizontalHeader()->setFont(mono);
|
||||
ui->results->horizontalHeader()->setFont(ui->results->font());
|
||||
ui->results->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
ui->results->verticalHeader()->setDefaultSectionSize(QFontMetrics(mono).height());
|
||||
ui->results->verticalHeader()->setDefaultSectionSize(QFontMetrics(ui->results->font()).height());
|
||||
ui->results->setColumnWidth(SeedTableModel::COL_SEED, 200);
|
||||
ui->results->setColumnWidth(SeedTableModel::COL_TOP16, 60);
|
||||
ui->results->setColumnWidth(SeedTableModel::COL_HEX48, 120);
|
||||
@ -132,9 +128,10 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
|
||||
connect(ui->results->horizontalHeader(), &QHeaderView::sortIndicatorChanged, this, &FormSearchControl::onSort);
|
||||
ui->results->sortByColumn(-1, Qt::AscendingOrder);
|
||||
|
||||
connect(&sthread, &SearchMaster::searchResult, this, &FormSearchControl::searchResult, Qt::QueuedConnection);
|
||||
connect(&sthread, &SearchMaster::searchFinish, this, &FormSearchControl::searchFinish, Qt::QueuedConnection);
|
||||
|
||||
connect(&stimer, &QTimer::timeout, this, QOverload<>::of(&FormSearchControl::resultTimeout));
|
||||
connect(&stimer, &QTimer::timeout, this, QOverload<>::of(&FormSearchControl::progressTimeout));
|
||||
|
||||
connect(
|
||||
ui->results->selectionModel(),
|
||||
@ -157,10 +154,10 @@ FormSearchControl::~FormSearchControl()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QVector<uint64_t> FormSearchControl::getResults()
|
||||
std::vector<uint64_t> FormSearchControl::getResults()
|
||||
{
|
||||
int n = proxy->rowCount();
|
||||
QVector<uint64_t> results = QVector<uint64_t>(n);
|
||||
std::vector<uint64_t> results (n);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
results[i] = proxy->data(proxy->index(i, SeedTableModel::COL_SEED), Qt::UserRole).toULongLong();
|
||||
@ -229,16 +226,14 @@ bool FormSearchControl::setList64(QString path, bool quiet)
|
||||
if (l != NULL)
|
||||
{
|
||||
slist64.assign(l, l+len);
|
||||
searchProgress(0, len, l[0]);
|
||||
updateSearchProgress(0, len, l[0]);
|
||||
free(l);
|
||||
return true;
|
||||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
int button = QMessageBox::warning(
|
||||
this, tr("Warning"),
|
||||
tr("Failed to load 64-bit seed list from file:\n\"%1\"").arg(path),
|
||||
QMessageBox::Reset, QMessageBox::Ignore);
|
||||
int button = warn(this, tr("Failed to load 64-bit seed list from file:\n\"%1\"").arg(path),
|
||||
QMessageBox::Reset|QMessageBox::Ignore);
|
||||
if (button == QMessageBox::Reset)
|
||||
{
|
||||
slist64fnam.clear();
|
||||
@ -250,6 +245,12 @@ bool FormSearchControl::setList64(QString path, bool quiet)
|
||||
return false;
|
||||
}
|
||||
|
||||
void FormSearchControl::setResultsPath(QString path)
|
||||
{
|
||||
resultfile.close();
|
||||
resultfile.setFileName(path);
|
||||
}
|
||||
|
||||
void FormSearchControl::searchLockUi(bool lock)
|
||||
{
|
||||
if (lock)
|
||||
@ -290,7 +291,7 @@ void FormSearchControl::setSearchMode(int mode)
|
||||
|
||||
int FormSearchControl::warning(QString text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return QMessageBox::warning(this, tr("Warning"), text, buttons);
|
||||
return warn(this, text, buttons);
|
||||
}
|
||||
|
||||
void FormSearchControl::openProtobaseMsg(QString path)
|
||||
@ -316,46 +317,52 @@ void FormSearchControl::on_buttonStart_clicked()
|
||||
{
|
||||
if (ui->buttonStart->isChecked())
|
||||
{
|
||||
WorldInfo wi;
|
||||
parent->getSeed(&wi);
|
||||
const Config& config = parent->config;
|
||||
QVector<Condition> condvec = parent->formCond->getConditions();
|
||||
SearchConfig sc = getSearchConfig();
|
||||
Session session;
|
||||
parent->getSeed(&session.wi);
|
||||
session.cv = parent->formCond->getConditions();
|
||||
session.sc = getSearchConfig();
|
||||
int ok = true;
|
||||
|
||||
if (condvec.empty())
|
||||
if (session.cv.empty())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Warning"), tr("Please define some constraints using the \"Add\" button."), QMessageBox::Ok);
|
||||
warn(this, tr("Please define some constraints using the \"Add\" button."));
|
||||
ok = false;
|
||||
}
|
||||
if (sc.searchtype == SEARCH_LIST && slist64.empty())
|
||||
if (session.sc.searchtype == SEARCH_LIST && slist64.empty())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Warning"), tr("No seed list file selected."), QMessageBox::Ok);
|
||||
warn(this, tr("No seed list file selected."));
|
||||
ok = false;
|
||||
}
|
||||
if (sthread.isRunning())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Warning"), tr("Search is still running."), QMessageBox::Ok);
|
||||
warn(this, tr("Search is still running."));
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
Gen48Config gen48 = parent->formGen48->getConfig(true);
|
||||
session.gen48 = parent->formGen48->getConfig(true);
|
||||
// the search can either use a full list or a 48-bit list
|
||||
if (sc.searchtype == SEARCH_LIST)
|
||||
slist = slist64;
|
||||
else if (gen48.mode == GEN48_LIST)
|
||||
slist = parent->formGen48->getList48();
|
||||
if (session.sc.searchtype == SEARCH_LIST)
|
||||
session.slist = slist64;
|
||||
else if (session.gen48.mode == GEN48_LIST)
|
||||
session.slist = parent->formGen48->getList48();
|
||||
else
|
||||
slist.clear();
|
||||
session.slist.clear();
|
||||
|
||||
ok = sthread.set(wi, sc, gen48, config, slist, condvec);
|
||||
ok = sthread.set(parent, session);
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, (int64_t)sc.startseed));
|
||||
if (!resultfile.fileName().isEmpty())
|
||||
{
|
||||
resultfile.close();
|
||||
resultfile.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text);
|
||||
QTextStream stream(&resultfile);
|
||||
session.writeHeader(stream);
|
||||
}
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, (int64_t)session.sc.startseed));
|
||||
ui->buttonStart->setText(tr("Abort search"));
|
||||
ui->buttonStart->setIcon(QIcon(":/icons/cancel.png"));
|
||||
searchLockUi(true);
|
||||
@ -431,12 +438,17 @@ void FormSearchControl::on_results_customContextMenuRequested(const QPoint &pos)
|
||||
QAction *actremove = menu.addAction(QIcon::fromTheme("list-remove"),
|
||||
tr("Remove selected seed"), this,
|
||||
&FormSearchControl::removeCurrent, QKeySequence::Delete);
|
||||
actremove->setEnabled(!ui->results->selectionModel()->hasSelection());
|
||||
actremove->setEnabled(ui->results->selectionModel()->hasSelection());
|
||||
|
||||
QAction *actcopy = menu.addAction(QIcon::fromTheme("edit-copy"),
|
||||
tr("Copy list to clipboard"), this,
|
||||
&FormSearchControl::copyResults, QKeySequence::Copy);
|
||||
actcopy->setEnabled(ui->results->model()->rowCount() > 0);
|
||||
QAction *actcopyseed = menu.addAction(QIcon::fromTheme("edit-copy"),
|
||||
tr("Copy selected seed"), this,
|
||||
&FormSearchControl::copySeed, QKeySequence::Copy);
|
||||
actcopyseed->setEnabled(ui->results->selectionModel()->hasSelection());
|
||||
|
||||
QAction *actcopylist = menu.addAction(QIcon::fromTheme("edit-copy"),
|
||||
tr("Copy seed list"), this,
|
||||
&FormSearchControl::copyResults, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_C));
|
||||
actcopylist->setEnabled(ui->results->model()->rowCount() > 0);
|
||||
|
||||
int n = pasteList(true);
|
||||
QAction *actpaste = menu.addAction(QIcon::fromTheme("edit-paste"),
|
||||
@ -489,9 +501,9 @@ int FormSearchControl::pasteList(bool dummy)
|
||||
{
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
QStringList slist = clipboard->text().split('\n');
|
||||
QVector<uint64_t> seeds;
|
||||
std::vector<uint64_t> seeds;
|
||||
|
||||
for (QString s : slist)
|
||||
for (QString s : qAsConst(slist))
|
||||
{
|
||||
s = s.trimmed();
|
||||
if (s.isEmpty())
|
||||
@ -532,8 +544,16 @@ void FormSearchControl::onSort(int, Qt::SortOrder)
|
||||
}
|
||||
}
|
||||
|
||||
void FormSearchControl::onSearchResult(uint64_t seed)
|
||||
void FormSearchControl::searchResult(uint64_t seed)
|
||||
{
|
||||
if (resultfile.isOpen())
|
||||
{
|
||||
char s[32];
|
||||
snprintf(s, sizeof(s), "%" PRId64 "\n", seed);
|
||||
resultfile.write(s);
|
||||
resultfile.flush();
|
||||
}
|
||||
|
||||
qbuf.push_back(seed);
|
||||
if (ui->checkStop->isChecked())
|
||||
{
|
||||
@ -564,14 +584,14 @@ void FormSearchControl::onBufferTimeout()
|
||||
nextupdate = elapsed.nsecsElapsed() + 1e6 * updt;
|
||||
}
|
||||
|
||||
int FormSearchControl::searchResultsAdd(QVector<uint64_t> seeds, bool countonly)
|
||||
int FormSearchControl::searchResultsAdd(std::vector<uint64_t> seeds, bool countonly)
|
||||
{
|
||||
const Config& config = parent->config;
|
||||
int ns = model->seeds.size();
|
||||
int n = ns;
|
||||
if (n >= config.maxMatching)
|
||||
return 0;
|
||||
if (seeds.size() + n > config.maxMatching)
|
||||
if ((ssize_t)seeds.size() + n > config.maxMatching)
|
||||
seeds.resize(config.maxMatching - n);
|
||||
if (seeds.empty())
|
||||
return 0;
|
||||
@ -604,8 +624,7 @@ int FormSearchControl::searchResultsAdd(QVector<uint64_t> seeds, bool countonly)
|
||||
if (countonly == false && n >= config.maxMatching)
|
||||
{
|
||||
sthread.stop();
|
||||
QString msg = tr("Maximum number of results reached (%1).").arg(config.maxMatching);
|
||||
QMessageBox::warning(this, tr("Warning"), msg, QMessageBox::Ok);
|
||||
warn(this, tr("Maximum number of results reached (%1).").arg(config.maxMatching));
|
||||
}
|
||||
|
||||
int addcnt = n - ns;
|
||||
@ -620,8 +639,7 @@ int FormSearchControl::searchResultsAdd(QVector<uint64_t> seeds, bool countonly)
|
||||
|
||||
void FormSearchControl::searchProgressReset()
|
||||
{
|
||||
uint64_t cnt;
|
||||
cnt = parent->formGen48->estimateSeedCnt();
|
||||
uint64_t cnt = parent->formGen48->estimateSeedCnt();
|
||||
if (cnt > MASK48)
|
||||
cnt = ~(uint64_t)0;
|
||||
else
|
||||
@ -655,7 +673,7 @@ void FormSearchControl::searchProgressReset()
|
||||
ui->progressBar->setFormat(fmt);
|
||||
}
|
||||
|
||||
void FormSearchControl::searchProgress(uint64_t prog, uint64_t end, int64_t seed)
|
||||
void FormSearchControl::updateSearchProgress(uint64_t prog, uint64_t end, int64_t seed)
|
||||
{
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, seed));
|
||||
|
||||
@ -689,112 +707,27 @@ void FormSearchControl::searchProgress(uint64_t prog, uint64_t end, int64_t seed
|
||||
void FormSearchControl::searchFinish(bool done)
|
||||
{
|
||||
stimer.stop();
|
||||
resultTimeout();
|
||||
progressTimeout();
|
||||
if (done)
|
||||
{
|
||||
ui->lineStart->setText(QString::asprintf("%" PRId64, sthread.smax));
|
||||
ui->progressBar->setValue(10000);
|
||||
ui->progressBar->setFormat(tr("Done", "Progressbar when finished"));
|
||||
ui->progressBar->setFormat(tr("Done", "Progressbar"));
|
||||
}
|
||||
ui->labelStatus->setText(tr("Idle"));
|
||||
proghist.clear();
|
||||
ui->labelStatus->setText(tr("Idle", "Progressbar"));
|
||||
searchLockUi(false);
|
||||
}
|
||||
|
||||
#define SAMPLE_SEC 20
|
||||
|
||||
static void estmateSpeed(const std::deque<FormSearchControl::TProg>& hist,
|
||||
double *min, double *avg, double *max)
|
||||
{ // We will try to get a decent estimate for the search speed.
|
||||
std::vector<double> samples;
|
||||
samples.reserve(hist.size());
|
||||
auto it_last = hist.begin();
|
||||
auto it = it_last;
|
||||
while (++it != hist.end())
|
||||
{
|
||||
double dp = it_last->prog - it->prog;
|
||||
double dt = 1e-9 * (it_last->ns - it->ns);
|
||||
if (dt > 0)
|
||||
samples.push_back(dp / dt);
|
||||
it_last = it;
|
||||
}
|
||||
std::sort(samples.begin(), samples.end());
|
||||
double speedtot = 0;
|
||||
double weightot = 1e-6;
|
||||
int n = (int) samples.size();
|
||||
int r = (int) (n / SAMPLE_SEC);
|
||||
int has_zeros = 0;
|
||||
for (int i = -r; i <= r; i++)
|
||||
{
|
||||
int j = n/2 + i;
|
||||
if (j < 0 || j >= n)
|
||||
continue;
|
||||
has_zeros += samples[j] == 0;
|
||||
speedtot += samples[j];
|
||||
weightot += 1.0;
|
||||
}
|
||||
if (min) *min = samples[n*1/4]; // lower quartile
|
||||
if (avg) *avg = speedtot / weightot; // median
|
||||
if (max) *max = samples[n*3/4]; // upper quartile
|
||||
if (avg && has_zeros)
|
||||
{ // probably a slow sampling regime, use whole range for estimate
|
||||
speedtot = 0;
|
||||
for (double s : samples)
|
||||
speedtot += s;
|
||||
*avg = speedtot / n;
|
||||
}
|
||||
}
|
||||
|
||||
static QString getAbbrNum(double x)
|
||||
{
|
||||
if (x >= 10e9)
|
||||
return QString::asprintf("%.1fG", x * 1e-9);
|
||||
if (x >= 10e6)
|
||||
return QString::asprintf("%.1fM", x * 1e-6);
|
||||
if (x >= 10e3)
|
||||
return QString::asprintf("%.1fK", x * 1e-3);
|
||||
return QString::asprintf("%.2f", x);
|
||||
}
|
||||
|
||||
void FormSearchControl::resultTimeout()
|
||||
void FormSearchControl::progressTimeout()
|
||||
{
|
||||
uint64_t prog, end, seed;
|
||||
if (!sthread.getProgress(&prog, &end, &seed))
|
||||
qreal min, avg, max;
|
||||
QString status = tr("Running...", "Progressbar");
|
||||
if (!sthread.getProgress(&status, &prog, &end, &seed, &min, &avg, &max))
|
||||
return;
|
||||
searchProgress(prog, end, seed);
|
||||
|
||||
// track the progress over a few seconds so we can estimate the search speed
|
||||
TProg tp = { (uint64_t) elapsed.nsecsElapsed(), prog };
|
||||
proghist.push_front(tp);
|
||||
while (proghist.size() > 1 && proghist.back().ns < tp.ns - SAMPLE_SEC*1e9)
|
||||
proghist.pop_back();
|
||||
updateSearchProgress(prog, end, seed);
|
||||
|
||||
QString status = tr("Running...");
|
||||
if (proghist.size() > 1 && proghist.front().ns > proghist.back().ns)
|
||||
{
|
||||
double min, avg, max;
|
||||
estmateSpeed(proghist, &min, &avg, &max);
|
||||
double remain = ((double)end - prog) / (avg + 1e-6);
|
||||
QString eta;
|
||||
if (remain >= 3600*24*1000)
|
||||
eta = "years";
|
||||
else
|
||||
{
|
||||
int s = (int) remain;
|
||||
if (s > 86400)
|
||||
eta = QString("%1d:%2").arg(s / 86400).arg((s % 86400) / 3600, 2, 10, QLatin1Char('0'));
|
||||
else if (s > 3600)
|
||||
eta = QString("%1h:%2").arg(s / 3600).arg((s % 3600) / 60, 2, 10, QLatin1Char('0'));
|
||||
else
|
||||
eta = QString("%1:%2").arg(s / 60).arg(s % 60, 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
status = tr("seeds/sec: %1 min: %2 max: %3 isize: %4 eta: %5")
|
||||
.arg(getAbbrNum(avg), -8)
|
||||
.arg(getAbbrNum(min), -8)
|
||||
.arg(getAbbrNum(max), -8)
|
||||
.arg(sthread.itemsize, -3)
|
||||
.arg(eta);
|
||||
}
|
||||
ui->labelStatus->setText(status);
|
||||
|
||||
update();
|
||||
@ -810,6 +743,17 @@ void FormSearchControl::removeCurrent()
|
||||
}
|
||||
}
|
||||
|
||||
void FormSearchControl::copySeed()
|
||||
{
|
||||
QModelIndex index = ui->results->currentIndex();
|
||||
if (index.isValid())
|
||||
{
|
||||
uint64_t seed = ui->results->model()->data(index, Qt::UserRole).toULongLong();
|
||||
QClipboard *clipboard = QGuiApplication::clipboard();
|
||||
clipboard->setText(QString::asprintf("%" PRId64, seed));
|
||||
}
|
||||
}
|
||||
|
||||
void FormSearchControl::copyResults()
|
||||
{
|
||||
QString text;
|
||||
@ -832,6 +776,8 @@ void FormSearchControl::keyReleaseEvent(QKeyEvent *event)
|
||||
if (event->matches(QKeySequence::Delete))
|
||||
removeCurrent();
|
||||
else if (event->matches(QKeySequence::Copy))
|
||||
copySeed();
|
||||
else if ((event->modifiers() & Qt::CTRL) && (event->modifiers() & Qt::SHIFT) && event->key() == Qt::Key_C)
|
||||
copyResults();
|
||||
else if (event->matches(QKeySequence::Paste))
|
||||
pasteResults();
|
||||
|
@ -98,13 +98,15 @@ public:
|
||||
explicit FormSearchControl(MainWindow *parent);
|
||||
~FormSearchControl();
|
||||
|
||||
QVector<uint64_t> getResults();
|
||||
std::vector<uint64_t> getResults();
|
||||
SearchConfig getSearchConfig();
|
||||
bool setSearchConfig(SearchConfig s, bool quiet);
|
||||
|
||||
void stopSearch();
|
||||
bool setList64(QString path, bool quiet);
|
||||
|
||||
void setResultsPath(QString path);
|
||||
|
||||
void searchLockUi(bool lock);
|
||||
|
||||
void setSearchMode(int mode);
|
||||
@ -135,21 +137,19 @@ public slots:
|
||||
void pasteResults();
|
||||
int pasteList(bool dummy);
|
||||
void onBufferTimeout();
|
||||
void onSearchResult(uint64_t seed);
|
||||
int searchResultsAdd(QVector<uint64_t> seeds, bool countonly);
|
||||
void searchResult(uint64_t seed);
|
||||
int searchResultsAdd(std::vector<uint64_t> seeds, bool countonly);
|
||||
void searchProgressReset();
|
||||
void searchProgress(uint64_t last, uint64_t end, int64_t seed);
|
||||
void updateSearchProgress(uint64_t last, uint64_t end, int64_t seed);
|
||||
void searchFinish(bool done);
|
||||
void resultTimeout();
|
||||
void progressTimeout();
|
||||
void removeCurrent();
|
||||
void copySeed();
|
||||
void copyResults();
|
||||
|
||||
protected:
|
||||
void keyReleaseEvent(QKeyEvent *event) override;
|
||||
|
||||
public:
|
||||
struct TProg { uint64_t ns, prog; };
|
||||
|
||||
private:
|
||||
MainWindow *parent;
|
||||
Ui::FormSearchControl *ui;
|
||||
@ -157,23 +157,20 @@ private:
|
||||
SeedSortProxy *proxy;
|
||||
ProtoBaseDialog *protodialog;
|
||||
SearchMaster sthread;
|
||||
QTimer stimer;
|
||||
QElapsedTimer elapsed;
|
||||
std::deque<TProg> proghist;
|
||||
QTimer stimer;
|
||||
QFile resultfile;
|
||||
|
||||
// the seed list option is not stored in a widget but is loaded with the "..." button
|
||||
QString slist64path;
|
||||
QString slist64fnam; // file name without directory
|
||||
std::vector<uint64_t> slist64;
|
||||
|
||||
// buffer for seed candidates while search is running
|
||||
std::vector<uint64_t> slist;
|
||||
|
||||
// min and max seeds values
|
||||
uint64_t smin, smax;
|
||||
|
||||
// found seeds that are waiting to be added to results
|
||||
QVector<uint64_t> qbuf;
|
||||
std::vector<uint64_t> qbuf;
|
||||
quint64 nextupdate;
|
||||
quint64 updt;
|
||||
};
|
||||
|
@ -162,6 +162,11 @@ QPushButton:hover {
|
||||
</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>Queued progress within search set</string>
|
||||
</property>
|
||||
@ -212,8 +217,7 @@ QPushButton:hover {
|
||||
<widget class="QLabel" name="labelStatus">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<pointsize>9</pointsize>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
@ -239,8 +243,7 @@ QPushButton:hover {
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<pointsize>9</pointsize>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
|
@ -2,11 +2,11 @@
|
||||
#include "ui_gotodialog.h"
|
||||
|
||||
#include "mapview.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <QDoubleValidator>
|
||||
#include <QKeyEvent>
|
||||
#include <QClipboard>
|
||||
#include <QMessageBox>
|
||||
|
||||
static bool g_animate;
|
||||
|
||||
@ -46,9 +46,8 @@ void GotoDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
qreal scale = ui->lineScale->text().toDouble();
|
||||
if (scale > 4096)
|
||||
{
|
||||
int button = QMessageBox::warning(this, tr("Unsafe Scale"),
|
||||
tr("Setting a very large scale may be unsafe.\n"
|
||||
"Continue anyway?"), QMessageBox::Abort|QMessageBox::Yes);
|
||||
int button = warn(this, tr("Setting a very large scale may be unsafe.\n"
|
||||
"Continue anyway?"), QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return;
|
||||
}
|
||||
@ -69,7 +68,7 @@ void GotoDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
}
|
||||
}
|
||||
|
||||
void GotoDialog::keyReleaseEvent(QKeyEvent *event)
|
||||
void GotoDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->matches(QKeySequence::Paste))
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
explicit GotoDialog(MapView *map, qreal x, qreal z, qreal scale);
|
||||
~GotoDialog();
|
||||
|
||||
void keyReleaseEvent(QKeyEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
211
src/headless.cpp
Normal file
211
src/headless.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
#include "headless.h"
|
||||
#include "message.h"
|
||||
#include "aboutdialog.h"
|
||||
|
||||
#include <QStandardPaths>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "cubiomes/util.h"
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
short get_term_width()
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
|
||||
return 80;
|
||||
return csbi.srWindow.Right - csbi.srWindow.Left + 1;
|
||||
}
|
||||
#else
|
||||
#include <sys/ioctl.h>
|
||||
short get_term_width()
|
||||
{
|
||||
struct winsize ws;
|
||||
if (ioctl(0, TIOCGWINSZ, &ws) < 0)
|
||||
return 80;
|
||||
return ws.ws_col;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static QTextStream& qOut()
|
||||
{
|
||||
static QTextStream out (stdout);
|
||||
return out;
|
||||
}
|
||||
|
||||
Headless::Headless(QString sessionpath, QString resultspath)
|
||||
: QObject(nullptr)
|
||||
, sthread(nullptr)
|
||||
, sessionpath(sessionpath)
|
||||
, resultfile(resultspath)
|
||||
, resultstream(stdout)
|
||||
{
|
||||
sthread.isdone = true;
|
||||
QTimer::singleShot(0, this, SLOT(start()));
|
||||
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
g_extgen.load(settings);
|
||||
|
||||
if (!loadSession(sessionpath))
|
||||
return;
|
||||
|
||||
if (!sthread.set(nullptr, session))
|
||||
return;
|
||||
|
||||
connect(&sthread, &SearchMaster::searchResult, this, &Headless::searchResult, Qt::QueuedConnection);
|
||||
connect(&sthread, &SearchMaster::searchFinish, this, &Headless::searchFinish, Qt::QueuedConnection);
|
||||
connect(&timer, &QTimer::timeout, this, QOverload<>::of(&Headless::progressTimeout));
|
||||
|
||||
if (!resultfile.fileName().isEmpty())
|
||||
{
|
||||
if (resultfile.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text))
|
||||
resultstream.setDevice(&resultfile);
|
||||
else
|
||||
warn(nullptr, "Output file for results coult not be created - using stdout instead.");
|
||||
}
|
||||
}
|
||||
|
||||
Headless::~Headless()
|
||||
{
|
||||
}
|
||||
|
||||
static bool load_seeds(std::vector<uint64_t>& seeds, QString path)
|
||||
{
|
||||
QByteArray ba = path.toLocal8Bit();
|
||||
uint64_t len;
|
||||
if (uint64_t *l = loadSavedSeeds(ba.data(), &len))
|
||||
{
|
||||
seeds.assign(l, l+len);
|
||||
free(l);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Headless::loadSession(QString sessionpath)
|
||||
{
|
||||
qOut() << "Loading session: \"" << sessionpath << "\"\n";
|
||||
qOut().flush();
|
||||
|
||||
if (!session.load(nullptr, sessionpath, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (session.cv.empty())
|
||||
{
|
||||
warn(nullptr, "Session defines no search constraints.");
|
||||
return false;
|
||||
}
|
||||
if (session.sc.searchtype == SEARCH_LIST)
|
||||
{
|
||||
if (!load_seeds(session.slist, session.sc.slist64path))
|
||||
{
|
||||
warn(nullptr, QString("Failed to load 64-bit seed list:\n\"%1\"").arg(session.sc.slist64path));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (session.gen48.mode == GEN48_LIST)
|
||||
{
|
||||
if (!load_seeds(session.slist, session.gen48.slist48path))
|
||||
{
|
||||
warn(nullptr, QString("Failed to load 48-bit seed list:\n\"%1\"").arg(session.gen48.slist48path));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
session.slist.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Headless::start()
|
||||
{
|
||||
qOut() << "Condition summary:\n";
|
||||
for (const Condition& cond : qAsConst(session.cv))
|
||||
qOut() << cond.summary(nullptr) << "\n";
|
||||
|
||||
if (sthread.isdone)
|
||||
{
|
||||
qOut() << "Search parameters invalid or incomplete.\n";
|
||||
qOut().flush();
|
||||
searchFinish(false);
|
||||
return;
|
||||
}
|
||||
|
||||
qOut() << "\nSearching for seeds...\n\n";
|
||||
qOut().flush();
|
||||
|
||||
session.writeHeader(resultstream);
|
||||
resultstream.flush();
|
||||
|
||||
sthread.start();
|
||||
|
||||
if (resultfile.isOpen())
|
||||
{
|
||||
qOut() << "\n\n\n\n\n\n";
|
||||
qOut().flush();
|
||||
timer.start(250);
|
||||
}
|
||||
}
|
||||
|
||||
void Headless::searchResult(uint64_t seed)
|
||||
{
|
||||
results.push_back(seed);
|
||||
resultstream << (int64_t) seed << "\n";
|
||||
resultstream.flush();
|
||||
}
|
||||
|
||||
void Headless::searchFinish(bool done)
|
||||
{
|
||||
if (timer.isActive())
|
||||
{
|
||||
timer.stop();
|
||||
progressTimeout();
|
||||
}
|
||||
if (done)
|
||||
qOut() << "Search done!\n";
|
||||
qOut() << "Stopping event loop.\n";
|
||||
qOut().flush();
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
|
||||
void Headless::progressTimeout()
|
||||
{
|
||||
QString status;
|
||||
uint64_t prog, end, seed;
|
||||
qreal min, avg, max;
|
||||
sthread.getProgress(&status, &prog, &end, &seed, &min, &avg, &max);
|
||||
|
||||
short width = get_term_width();
|
||||
if (width <= 24)
|
||||
return;
|
||||
|
||||
qreal perc = (qreal) prog / end;
|
||||
|
||||
int cols = floor(perc * (width - 4) + 1e-6);
|
||||
|
||||
QStringList l;
|
||||
l += QString(" Found matching seeds:%1 ").arg(results.size(), width-23);
|
||||
l += QString(" Scheduled seed:%1 ").arg((int64_t)seed, width-17);
|
||||
l += QString(" Progress:%1 ").arg(QString("%1 / %2 : %3%").arg(prog).arg(end).arg(100*perc, 5, 'f', 2), width-11);
|
||||
l += QString(" [%1%2] ").arg("", cols, '#').arg("", width-cols-4, '-');
|
||||
l += QString(" %1").arg(status, 1-width);
|
||||
l += "";
|
||||
|
||||
qOut() << "\e[999D\e[" << l.size() << "A";
|
||||
for (QString& s : l)
|
||||
{
|
||||
s.truncate(width);
|
||||
qOut() << s << "\n";
|
||||
}
|
||||
qOut().flush();
|
||||
}
|
||||
|
||||
|
34
src/headless.h
Normal file
34
src/headless.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef HEADLESS_H
|
||||
#define HEADLESS_H
|
||||
|
||||
#include "searchthread.h"
|
||||
#include <QTimer>
|
||||
#include <QFile>
|
||||
|
||||
class Headless : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Headless(QString sessionpath, QString resultspath);
|
||||
virtual ~Headless();
|
||||
|
||||
bool loadSession(QString sessionpath);
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
void searchResult(uint64_t seed);
|
||||
void searchFinish(bool done);
|
||||
void progressTimeout();
|
||||
|
||||
public:
|
||||
SearchMaster sthread;
|
||||
QString sessionpath;
|
||||
Session session;
|
||||
std::vector<uint64_t> results;
|
||||
QFile resultfile;
|
||||
QTextStream resultstream;
|
||||
QTimer timer;
|
||||
};
|
||||
|
||||
#endif // HEADLESS_H
|
@ -42,80 +42,80 @@ const char *getLayerOptionText(int mode, int disp)
|
||||
{
|
||||
case LOPT_BIOMES:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "1:1").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "1:4").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "1:16").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "1:64").toUtf8().data();
|
||||
case 4: return QApplication::translate("LayerDialog", "1:256").toUtf8().data();
|
||||
case 0: return "1:1";
|
||||
case 1: return "1:4";
|
||||
case 2: return "1:16";
|
||||
case 3: return "1:64";
|
||||
case 4: return "1:256";
|
||||
default: return nullptr;
|
||||
}
|
||||
case LOPT_NOISE_T_4:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "All").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "+A[0] 1:4096 x0.952381").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "+B[0] 1:4023 x0.952381").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "+A[1] 1:1024 x0.158730").toUtf8().data();
|
||||
case 4: return QApplication::translate("LayerDialog", "+B[1] 1:1005 x0.158730").toUtf8().data();
|
||||
case 0: return "All";
|
||||
case 1: return "+A[0] 1:4096 x0.952381";
|
||||
case 2: return "+B[0] 1:4023 x0.952381";
|
||||
case 3: return "+A[1] 1:1024 x0.158730";
|
||||
case 4: return "+B[1] 1:1005 x0.158730";
|
||||
default: return nullptr;
|
||||
}
|
||||
case LOPT_NOISE_H_4:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "All").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "+A[0] 1:1024 x0.564374").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "+B[0] 1:1005 x0.564374").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "+A[1] 1:512 x0.282187").toUtf8().data();
|
||||
case 4: return QApplication::translate("LayerDialog", "+B[1] 1:502 x0.282187").toUtf8().data();
|
||||
case 0: return "All";
|
||||
case 1: return "+A[0] 1:1024 x0.564374";
|
||||
case 2: return "+B[0] 1:1005 x0.564374";
|
||||
case 3: return "+A[1] 1:512 x0.282187";
|
||||
case 4: return "+B[1] 1:502 x0.282187";
|
||||
default: return nullptr;
|
||||
}
|
||||
case LOPT_NOISE_C_4:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "All").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "+A[0] 1:2048 x0.751468").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "+B[0] 1:2011 x0.751468").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "+A[1] 1:1024 x0.375734").toUtf8().data();
|
||||
case 4: return QApplication::translate("LayerDialog", "+B[1] 1:1005 x0.375734").toUtf8().data();
|
||||
case 5: return QApplication::translate("LayerDialog", "+A[2] 1:512 x0.375734").toUtf8().data();
|
||||
case 6: return QApplication::translate("LayerDialog", "+B[2] 1:502 x0.375734").toUtf8().data();
|
||||
case 7: return QApplication::translate("LayerDialog", "+A[3] 1:256 x0.187867").toUtf8().data();
|
||||
case 8: return QApplication::translate("LayerDialog", "+B[3] 1:251 x0.187867").toUtf8().data();
|
||||
case 9: return QApplication::translate("LayerDialog", "+A[4] 1:128 x0.093933").toUtf8().data();
|
||||
case 10: return QApplication::translate("LayerDialog", "+B[4] 1:125 x0.093933").toUtf8().data();
|
||||
case 11: return QApplication::translate("LayerDialog", "+A[5] 1:64 x0.023483").toUtf8().data();
|
||||
case 12: return QApplication::translate("LayerDialog", "+B[5] 1:62 x0.023483").toUtf8().data();
|
||||
case 13: return QApplication::translate("LayerDialog", "+A[6] 1:32 x0.011742").toUtf8().data();
|
||||
case 14: return QApplication::translate("LayerDialog", "+B[6] 1:31 x0.011742").toUtf8().data();
|
||||
case 0: return "All";
|
||||
case 1: return "+A[0] 1:2048 x0.751468";
|
||||
case 2: return "+B[0] 1:2011 x0.751468";
|
||||
case 3: return "+A[1] 1:1024 x0.375734";
|
||||
case 4: return "+B[1] 1:1005 x0.375734";
|
||||
case 5: return "+A[2] 1:512 x0.375734";
|
||||
case 6: return "+B[2] 1:502 x0.375734";
|
||||
case 7: return "+A[3] 1:256 x0.187867";
|
||||
case 8: return "+B[3] 1:251 x0.187867";
|
||||
case 9: return "+A[4] 1:128 x0.093933";
|
||||
case 10: return "+B[4] 1:125 x0.093933";
|
||||
case 11: return "+A[5] 1:64 x0.023483";
|
||||
case 12: return "+B[5] 1:62 x0.023483";
|
||||
case 13: return "+A[6] 1:32 x0.011742";
|
||||
case 14: return "+B[6] 1:31 x0.011742";
|
||||
default: return nullptr;
|
||||
}
|
||||
case LOPT_NOISE_E_4:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "All").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "+A[0] 1:2048 x0.716846").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "+B[0] 1:2011 x0.716846").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "+A[1] 1:1024 x0.358423").toUtf8().data();
|
||||
case 4: return QApplication::translate("LayerDialog", "+B[1] 1:1005 x0.358423").toUtf8().data();
|
||||
case 5: return QApplication::translate("LayerDialog", "+A[2] 1:256 x0.089606").toUtf8().data();
|
||||
case 6: return QApplication::translate("LayerDialog", "+B[2] 1:251 x0.089606").toUtf8().data();
|
||||
case 7: return QApplication::translate("LayerDialog", "+A[3] 1:128 x0.044803").toUtf8().data();
|
||||
case 8: return QApplication::translate("LayerDialog", "+B[3] 1:125 x0.044803").toUtf8().data();
|
||||
case 0: return "All";
|
||||
case 1: return "+A[0] 1:2048 x0.716846";
|
||||
case 2: return "+B[0] 1:2011 x0.716846";
|
||||
case 3: return "+A[1] 1:1024 x0.358423";
|
||||
case 4: return "+B[1] 1:1005 x0.358423";
|
||||
case 5: return "+A[2] 1:256 x0.089606";
|
||||
case 6: return "+B[2] 1:251 x0.089606";
|
||||
case 7: return "+A[3] 1:128 x0.044803";
|
||||
case 8: return "+B[3] 1:125 x0.044803";
|
||||
default: return nullptr;
|
||||
}
|
||||
case LOPT_NOISE_W_4:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "All").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "+A[0] 1:512 x0.634921").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "+B[0] 1:502 x0.634921").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "+A[1] 1:256 x0.634921").toUtf8().data();
|
||||
case 4: return QApplication::translate("LayerDialog", "+B[1] 1:251 x0.634921").toUtf8().data();
|
||||
case 5: return QApplication::translate("LayerDialog", "+A[2] 1:128 x0.158730").toUtf8().data();
|
||||
case 6: return QApplication::translate("LayerDialog", "+B[2] 1:125 x0.158730").toUtf8().data();
|
||||
case 0: return "All";
|
||||
case 1: return "+A[0] 1:512 x0.634921";
|
||||
case 2: return "+B[0] 1:502 x0.634921";
|
||||
case 3: return "+A[1] 1:256 x0.634921";
|
||||
case 4: return "+B[1] 1:251 x0.634921";
|
||||
case 5: return "+A[2] 1:128 x0.158730";
|
||||
case 6: return "+B[2] 1:125 x0.158730";
|
||||
default: return nullptr;
|
||||
}
|
||||
case LOPT_HEIGHT_4:
|
||||
switch (disp) {
|
||||
case 0: return QApplication::translate("LayerDialog", "Grayscale").toUtf8().data();
|
||||
case 1: return QApplication::translate("LayerDialog", "Shaded biome map").toUtf8().data();
|
||||
case 2: return QApplication::translate("LayerDialog", "Contours on biomes").toUtf8().data();
|
||||
case 3: return QApplication::translate("LayerDialog", "Shaded with contours").toUtf8().data();
|
||||
case 0: return QT_TRANSLATE_NOOP("LayerDialog", "Grayscale");
|
||||
case 1: return QT_TRANSLATE_NOOP("LayerDialog", "Shaded biome map");
|
||||
case 2: return QT_TRANSLATE_NOOP("LayerDialog", "Contours on biomes");
|
||||
case 3: return QT_TRANSLATE_NOOP("LayerDialog", "Shaded with contours");
|
||||
default: return nullptr;
|
||||
}
|
||||
default:
|
||||
@ -163,7 +163,7 @@ LayerDialog::LayerDialog(QWidget *parent, int mc)
|
||||
const char *item = getLayerOptionText(i, j);
|
||||
if (!item)
|
||||
break;
|
||||
QString s = QString::asprintf("%-24s", item);
|
||||
QString s = QApplication::translate("LayerDialog", item).leftJustified(24);
|
||||
if (j < 9)
|
||||
s += "\tALT+"+QString::number(j+1);
|
||||
items.append(s);
|
||||
@ -171,13 +171,15 @@ LayerDialog::LayerDialog(QWidget *parent, int mc)
|
||||
combo[i]->addItems(items);
|
||||
}
|
||||
|
||||
QFont fmono;
|
||||
fmono.setFamily(QString::fromUtf8("Monospace"));
|
||||
for (int i = 0; i < LOPT_MAX; i++)
|
||||
{
|
||||
if (!radio[i])
|
||||
continue;
|
||||
connect(radio[i], &QRadioButton::toggled, this, &LayerDialog::onRadioChange);
|
||||
if (combo[i])
|
||||
combo[i]->setFont(*gp_font_mono);
|
||||
combo[i]->setFont(fmono);
|
||||
if (i >= LOPT_NOISE_T_4 && i <= LOPT_NOISE_W_4)
|
||||
{
|
||||
radio[i]->setEnabled(mc > MC_1_17);
|
||||
|
@ -20,7 +20,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>DejaVu Sans Mono</family>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
|
118
src/main.cpp
118
src/main.cpp
@ -1,11 +1,14 @@
|
||||
#include "mainwindow.h"
|
||||
#include "headless.h"
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "world.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFontDatabase>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
|
||||
#include "world.h"
|
||||
|
||||
#include "cubiomes/generator.h"
|
||||
#include "cubiomes/util.h"
|
||||
|
||||
@ -16,9 +19,6 @@ unsigned char g_tempsColors[256][3];
|
||||
|
||||
ExtGenConfig g_extgen;
|
||||
|
||||
QFont *gp_font_default;
|
||||
QFont *gp_font_mono;
|
||||
|
||||
extern "C"
|
||||
int getStructureConfig_override(int stype, int mc, StructureConfig *sconf)
|
||||
{
|
||||
@ -33,53 +33,97 @@ int getStructureConfig_override(int stype, int mc, StructureConfig *sconf)
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
#include "QDebug"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
initBiomes();
|
||||
initBiomeColors(g_biomeColors);
|
||||
initBiomeTypeColors(g_tempsColors);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName(APP_STRING);
|
||||
|
||||
bool version = false;
|
||||
bool nogui = false;
|
||||
bool reset = false;
|
||||
bool usage = false;
|
||||
QString sessionpath;
|
||||
QString resultspath;
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--reset-all") == 0)
|
||||
{
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
settings.clear();
|
||||
if (strcmp(argv[i], "--version") == 0)
|
||||
version = true;
|
||||
else if (strcmp(argv[i], "--nogui") == 0)
|
||||
nogui = true;
|
||||
else if (strcmp(argv[i], "--reset-all") == 0)
|
||||
reset = true;
|
||||
else if (strncmp(argv[i], "--session=", 10) == 0)
|
||||
sessionpath = argv[i] + 10;
|
||||
else if (strncmp(argv[i], "--session", 9) == 0 && i+1 < argc)
|
||||
sessionpath = argv[++i];
|
||||
else if (strncmp(argv[i], "--out=", 6) == 0)
|
||||
resultspath = argv[i] + 6;
|
||||
else if (strncmp(argv[i], "--out", 5) == 0 && i+1 < argc)
|
||||
resultspath = argv[++i];
|
||||
else
|
||||
usage = true;
|
||||
}
|
||||
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
QDir dir(path);
|
||||
if (dir.exists() && path.contains(APP_STRING))
|
||||
{
|
||||
dir.removeRecursively();
|
||||
}
|
||||
if (usage)
|
||||
{
|
||||
const char *msg =
|
||||
"Usage: cubiomes-viewer [options]\n"
|
||||
"Options:\n"
|
||||
" --help Display this help and exit.\n"
|
||||
" --version Output version information and exit.\n"
|
||||
" --nogui Run in headless search mode.\n"
|
||||
" --reset-all Clear settings and remove all session data.\n"
|
||||
" --session=file Open this session file.\n"
|
||||
" --out=file Write matching seeds to this file while searching.\n"
|
||||
"\n";
|
||||
printf("%s", msg);
|
||||
exit(0);
|
||||
}
|
||||
if (version)
|
||||
{
|
||||
printf("%s %s\n", APP_STRING, getVersStr().toLocal8Bit().data());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (reset)
|
||||
{
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
settings.clear();
|
||||
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
QDir dir(path);
|
||||
if (dir.exists() && path.contains(APP_STRING))
|
||||
{
|
||||
dir.removeRecursively();
|
||||
}
|
||||
}
|
||||
|
||||
//int fontid = QFontDatabase::addApplicationFont(":/fonts/test.ttf");
|
||||
int fontid = QFontDatabase::addApplicationFont(":/fonts/DejaVuSans.ttf");
|
||||
if (fontid >= 0)
|
||||
if (sessionpath.isEmpty())
|
||||
{
|
||||
QFontDatabase::addApplicationFont(":/fonts/DejaVuSans-Bold.ttf");
|
||||
int fontid_mono = QFontDatabase::addApplicationFont(":/fonts/DejaVuSansMono.ttf");
|
||||
|
||||
static QFont font_default = QFontDatabase::applicationFontFamilies(fontid).at(0);
|
||||
font_default.setPointSize(10);
|
||||
static QFont font_mono = QFontDatabase::applicationFontFamilies(fontid_mono).at(0);
|
||||
font_mono.setPointSize(9);
|
||||
|
||||
app.setFont(font_default);
|
||||
|
||||
gp_font_default = &font_default;
|
||||
gp_font_mono = &font_mono;
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
QDir dir(path);
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
sessionpath = path + "/session.save";
|
||||
}
|
||||
|
||||
MainWindow mw;
|
||||
mw.show();
|
||||
int ret = app.exec();
|
||||
|
||||
return ret;
|
||||
if (nogui)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
Headless(sessionpath, resultspath);
|
||||
return app.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
MainWindow mw(sessionpath, resultspath);
|
||||
mw.show();
|
||||
return app.exec();
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "tabtriggers.h"
|
||||
#include "tabbiomes.h"
|
||||
#include "tabstructures.h"
|
||||
#include "message.h"
|
||||
|
||||
#if WITH_UPDATER
|
||||
#include "updater.h"
|
||||
@ -37,7 +38,7 @@
|
||||
#include <QLibraryInfo>
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui()
|
||||
, dock()
|
||||
@ -48,6 +49,7 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
, lopt()
|
||||
, config()
|
||||
, mconfig(false)
|
||||
, sessionpath(sessionpath)
|
||||
, prevdir(".")
|
||||
, autosaveTimer()
|
||||
, prevtab(-1)
|
||||
@ -57,7 +59,10 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
QSettings settings(APP_STRING, APP_STRING);
|
||||
QString lang = settings.value("config/lang", QLocale().name()).toString();
|
||||
if (!loadTranslation(lang))
|
||||
{
|
||||
loadTranslation("en_US");
|
||||
settings.setValue("config/lang", "en_US");
|
||||
}
|
||||
|
||||
ui = new Ui::MainWindow;
|
||||
dock = new QDockWidget(tr("Map"), this);
|
||||
@ -127,9 +132,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
ui->toolBar->addAction(toorigin);
|
||||
ui->toolBar->addSeparator();
|
||||
|
||||
dimactions[0] = addMapAction(-1, "overworld", tr("Overworld"));
|
||||
dimactions[1] = addMapAction(-1, "nether", tr("Nether"));
|
||||
dimactions[2] = addMapAction(-1, "the_end", tr("End"));
|
||||
dimactions[0] = addMapAction(":/icons/overworld", tr("Overworld"));
|
||||
dimactions[1] = addMapAction(":/icons/nether", tr("Nether"));
|
||||
dimactions[2] = addMapAction(":/icons/the_end", tr("End"));
|
||||
dimgroup = new QActionGroup(this);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
@ -141,33 +146,33 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
dimactions[0]->setChecked(true);
|
||||
|
||||
saction.resize(D_STRUCT_NUM);
|
||||
addMapAction(D_GRID, "grid", tr("Show grid"));
|
||||
addMapAction(D_SLIME, "slime", tr("Show slime chunks"));
|
||||
addMapAction(D_SPAWN, "spawn", tr("Show world spawn"));
|
||||
addMapAction(D_STRONGHOLD, "stronghold", tr("Show strongholds"));
|
||||
addMapAction(D_VILLAGE, "village", tr("Show villages"));
|
||||
addMapAction(D_MINESHAFT, "mineshaft", tr("Show abandoned mineshafts"));
|
||||
addMapAction(D_DESERT, "desert", tr("Show desert pyramids"));
|
||||
addMapAction(D_JUNGLE, "jungle", tr("Show jungle temples"));
|
||||
addMapAction(D_HUT, "hut", tr("Show swamp huts"));
|
||||
addMapAction(D_MONUMENT, "monument", tr("Show ocean monuments"));
|
||||
addMapAction(D_IGLOO, "igloo", tr("Show igloos"));
|
||||
addMapAction(D_MANSION, "mansion", tr("Show woodland mansions"));
|
||||
addMapAction(D_RUINS, "ruins", tr("Show ocean ruins"));
|
||||
addMapAction(D_SHIPWRECK, "shipwreck", tr("Show shipwrecks"));
|
||||
addMapAction(D_TREASURE, "treasure", tr("Show buried treasures"));
|
||||
addMapAction(D_WELL, "well", tr("Show desert wells"));
|
||||
addMapAction(D_GEODE, "geode", tr("Show amethyst geodes"));
|
||||
addMapAction(D_OUTPOST, "outpost", tr("Show pillager outposts"));
|
||||
addMapAction(D_PORTAL, "portal", tr("Show ruined portals"));
|
||||
addMapAction(D_ANCIENTCITY, "ancient_city", tr("Show ancient cities"));
|
||||
addMapAction(D_TRAIL, "trail", tr("Show trail ruins"));
|
||||
addMapAction(D_GRID);
|
||||
addMapAction(D_SLIME);
|
||||
addMapAction(D_SPAWN);
|
||||
addMapAction(D_STRONGHOLD);
|
||||
addMapAction(D_VILLAGE);
|
||||
addMapAction(D_MINESHAFT);
|
||||
addMapAction(D_DESERT);
|
||||
addMapAction(D_JUNGLE);
|
||||
addMapAction(D_HUT);
|
||||
addMapAction(D_MONUMENT);
|
||||
addMapAction(D_IGLOO);
|
||||
addMapAction(D_MANSION);
|
||||
addMapAction(D_RUINS);
|
||||
addMapAction(D_SHIPWRECK);
|
||||
addMapAction(D_TREASURE);
|
||||
addMapAction(D_WELL);
|
||||
addMapAction(D_GEODE);
|
||||
addMapAction(D_OUTPOST);
|
||||
addMapAction(D_PORTAL);
|
||||
addMapAction(D_ANCIENTCITY);
|
||||
addMapAction(D_TRAILS);
|
||||
ui->toolBar->addSeparator();
|
||||
addMapAction(D_FORTESS, "fortress", tr("Show nether fortresses"));
|
||||
addMapAction(D_BASTION, "bastion", tr("Show bastions"));
|
||||
addMapAction(D_FORTESS);
|
||||
addMapAction(D_BASTION);
|
||||
ui->toolBar->addSeparator();
|
||||
addMapAction(D_ENDCITY, "endcity", tr("Show end cities"));
|
||||
addMapAction(D_GATEWAY, "gateway", tr("Show end gateways"));
|
||||
addMapAction(D_ENDCITY);
|
||||
addMapAction(D_GATEWAY);
|
||||
|
||||
saction[D_GRID]->setChecked(true);
|
||||
|
||||
@ -246,6 +251,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
ui->collapseControl->init(tr("Matching seeds"), formControl, false);
|
||||
connect(formControl, &FormSearchControl::selectedSeedChanged, this, &MainWindow::onSelectedSeedChanged);
|
||||
connect(formControl, &FormSearchControl::searchStatusChanged, this, &MainWindow::onSearchStatusChanged);
|
||||
if (!resultspath.isEmpty())
|
||||
formControl->setResultsPath(resultspath);
|
||||
ui->collapseControl->setInfo(
|
||||
tr("Help: Matching seeds"),
|
||||
tr(
|
||||
@ -299,31 +306,34 @@ bool MainWindow::loadTranslation(QString lang)
|
||||
return true;
|
||||
}
|
||||
|
||||
QAction *MainWindow::addMapAction(int sopt, const char *iconpath, QString tip)
|
||||
QAction *MainWindow::addMapAction(int opt)
|
||||
{
|
||||
QIcon icon;
|
||||
QString inam = QString(":icons/") + iconpath;
|
||||
QPixmap pix_on = QPixmap(inam + ".png");
|
||||
QPixmap pix_off = QPixmap(inam + "_d.png");
|
||||
QString rc = QString(":/icons/") + mapopt2str(opt);
|
||||
QString tip = tr("Show %1").arg(mapopt2display(opt));
|
||||
QAction *action = addMapAction(rc, tip);
|
||||
action->connect(action, &QAction::toggled, [=](bool state){ this->onActionMapToggled(opt, state); });
|
||||
saction[opt] = action;
|
||||
return action;
|
||||
}
|
||||
|
||||
QAction *MainWindow::addMapAction(QString rcbase, QString tip)
|
||||
{
|
||||
QPixmap pix_on = QPixmap(rcbase + ".png");
|
||||
QPixmap pix_off = QPixmap(rcbase + "_d.png");
|
||||
if (pix_on.size().width() > 20)
|
||||
{
|
||||
pix_on = pix_on.scaledToWidth(20);
|
||||
pix_off = pix_off.scaledToWidth(20);
|
||||
}
|
||||
QIcon icon;
|
||||
icon.addPixmap(pix_on, QIcon::Normal, QIcon::On);
|
||||
icon.addPixmap(pix_off, QIcon::Normal, QIcon::Off);
|
||||
QAction *action = new QAction(icon, tip, this);
|
||||
action->setCheckable(true);
|
||||
ui->toolBar->addAction(action);
|
||||
if (sopt >= 0)
|
||||
{
|
||||
action->connect(action, &QAction::toggled, [=](bool state){ this->onActionMapToggled(sopt, state); });
|
||||
saction[sopt] = action;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
MapView* MainWindow::getMapView()
|
||||
{
|
||||
return mapView;
|
||||
@ -375,29 +385,24 @@ bool MainWindow::setSeed(WorldInfo wi, int dim)
|
||||
else
|
||||
dim = getDim();
|
||||
|
||||
MapView *mapview = getMapView();
|
||||
uint64_t current = mapview->world ? mapview->world->wi.seed : wi.seed;
|
||||
if (current != wi.seed)
|
||||
const QList<QAction*> hist = ui->menuHistory->actions();
|
||||
|
||||
if (hist.empty() || hist.front()->data().toULongLong() != wi.seed)
|
||||
{
|
||||
QList<QAction*> hist = ui->menuHistory->actions();
|
||||
bool rm = false;
|
||||
for (QAction *act : qAsConst(hist))
|
||||
QAction *rm = nullptr;
|
||||
if (hist.size() >= 16)
|
||||
rm = hist.back();
|
||||
for (QAction *act : hist)
|
||||
if (act->data().toULongLong() == wi.seed)
|
||||
rm = act;
|
||||
if (rm)
|
||||
{
|
||||
if (act->data().toULongLong() == current)
|
||||
{
|
||||
ui->menuHistory->removeAction(act);
|
||||
hist.back()->deleteLater();
|
||||
rm = true;
|
||||
}
|
||||
ui->menuHistory->removeAction(rm);
|
||||
rm->deleteLater();
|
||||
}
|
||||
if (!rm && hist.size() >= 12)
|
||||
{
|
||||
ui->menuHistory->removeAction(hist.back());
|
||||
hist.back()->deleteLater();
|
||||
}
|
||||
QString s = QString::asprintf("%" PRId64, current);
|
||||
QString s = QString::asprintf("%" PRId64, wi.seed);
|
||||
QAction *act = new QAction(s, this);
|
||||
act->setData(QVariant::fromValue(current));
|
||||
act->setData(QVariant::fromValue(wi.seed));
|
||||
act->connect(act, &QAction::triggered, [=](){ this->onActionHistory(act); });
|
||||
ui->menuHistory->insertAction(hist.empty() ? 0 : hist.first(), act);
|
||||
ui->menuHistory->setEnabled(true);
|
||||
@ -476,11 +481,7 @@ void MainWindow::saveSettings()
|
||||
|
||||
if (config.restoreSession)
|
||||
{
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
QDir dir(path);
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
saveProgress(path + "/session.save", true);
|
||||
saveSession(sessionpath, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,176 +536,52 @@ void MainWindow::loadSettings()
|
||||
onUpdateConfig();
|
||||
onUpdateMapConfig();
|
||||
|
||||
if (config.restoreSession)
|
||||
if (config.restoreSession && QFile::exists(sessionpath))
|
||||
{
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
path += "/session.save";
|
||||
if (QFile::exists(path))
|
||||
{
|
||||
loadProgress(path, false, false);
|
||||
}
|
||||
loadSession(sessionpath, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MainWindow::saveProgress(QString fnam, bool quiet)
|
||||
bool MainWindow::saveSession(QString fnam, bool quiet)
|
||||
{
|
||||
QFile file(fnam);
|
||||
Session session;
|
||||
session.sc = formControl->getSearchConfig();
|
||||
session.gen48 = formGen48->getConfig(false);
|
||||
session.cv = formCond->getConditions();
|
||||
session.slist = formControl->getResults();
|
||||
getSeed(&session.wi);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
if (!quiet)
|
||||
warning(tr("Failed to open file:\n\"%1\"").arg(fnam));
|
||||
return false;
|
||||
}
|
||||
|
||||
SearchConfig searchconf = formControl->getSearchConfig();
|
||||
Gen48Config gen48 = formGen48->getConfig(false);
|
||||
QVector<Condition> condvec = formCond->getConditions();
|
||||
QVector<uint64_t> results = formControl->getResults();
|
||||
|
||||
WorldInfo wi;
|
||||
getSeed(&wi);
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream << "#Version: " << VERS_MAJOR << "." << VERS_MINOR << "." << VERS_PATCH << "\n";
|
||||
stream << "#Time: " << QDateTime::currentDateTime().toString() << "\n";
|
||||
// MC version of the session should take priority over the one in the settings
|
||||
wi.write(stream);
|
||||
|
||||
searchconf.write(stream);
|
||||
gen48.write(stream);
|
||||
|
||||
for (Condition &c : condvec)
|
||||
stream << "#Cond: " << c.toHex() << "\n";
|
||||
|
||||
for (uint64_t s : qAsConst(results))
|
||||
stream << QString::asprintf("%" PRId64 "\n", (int64_t)s);
|
||||
|
||||
return true;
|
||||
return session.save(this, fnam, quiet);
|
||||
}
|
||||
|
||||
bool MainWindow::loadProgress(QString fnam, bool keepresults, bool quiet)
|
||||
bool MainWindow::loadSession(QString fnam, bool keepresults, bool quiet)
|
||||
{
|
||||
QFile file(fnam);
|
||||
Session session;
|
||||
// build current session before loading to keep unspecified values the same
|
||||
getSeed(&session.wi);
|
||||
session.sc = formControl->getSearchConfig();
|
||||
session.gen48 = formGen48->getConfig(false);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!quiet)
|
||||
warning(tr("Failed to open progress file:\n\"%1\"").arg(fnam));
|
||||
if (!session.load(this, fnam, quiet))
|
||||
return false;
|
||||
}
|
||||
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
SearchConfig searchconf = formControl->getSearchConfig();
|
||||
Gen48Config gen48 = formGen48->getConfig(false);
|
||||
QVector<Condition> condvec;
|
||||
QVector<uint64_t> seeds;
|
||||
|
||||
WorldInfo wi;
|
||||
getSeed(&wi, true);
|
||||
|
||||
QTextStream stream(&file);
|
||||
QString line;
|
||||
line = stream.readLine();
|
||||
int lno = 1;
|
||||
|
||||
if (sscanf(line.toLocal8Bit().data(), "#Version: %d.%d.%d", &major, &minor, &patch) != 3)
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
int button = QMessageBox::warning(this, tr("Warning"),
|
||||
tr("File does not look like a progress file.\n"
|
||||
"Progress may be incomplete or broken.\n\n"
|
||||
"Continue anyway?"),
|
||||
QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
else if (cmpVers(major, minor, patch) > 0)
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
int button = QMessageBox::warning(this, tr("Warning"),
|
||||
tr("File was created with a newer version.\n"
|
||||
"Progress may be incomplete or broken.\n\n"
|
||||
"Continue loading progress anyway?"),
|
||||
QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
|
||||
while (stream.status() == QTextStream::Ok && !stream.atEnd())
|
||||
{
|
||||
lno++;
|
||||
line = stream.readLine();
|
||||
|
||||
if (line.isEmpty()) continue;
|
||||
if (line.startsWith("#Time:")) continue;
|
||||
if (line.startsWith("#Title:")) continue;
|
||||
if (line.startsWith("#Desc:")) continue;
|
||||
if (searchconf.read(line)) continue;
|
||||
if (gen48.read(line)) continue;
|
||||
if (wi.read(line)) continue;
|
||||
|
||||
if (line.startsWith("#Cond:"))
|
||||
{ // Conditions
|
||||
Condition c;
|
||||
if (c.readHex(line.mid(6).trimmed()))
|
||||
{
|
||||
condvec.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
int button = QMessageBox::warning(this, tr("Warning"),
|
||||
tr("Condition [%1] at line %2 is not supported.\n\n"
|
||||
"Continue anyway?").arg(c.save).arg(lno),
|
||||
QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Seeds
|
||||
QByteArray ba = line.toLocal8Bit();
|
||||
const char *p = ba.data();
|
||||
uint64_t s;
|
||||
if (sscanf(p, "%" PRId64, (int64_t*)&s) == 1)
|
||||
{
|
||||
seeds.push_back(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
int button = QMessageBox::warning(this, tr("Warning"),
|
||||
tr("Failed to parse line %1 of progress file:\n%2\n\n"
|
||||
"Continue anyway?").arg(lno).arg(line),
|
||||
QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setSeed(wi);
|
||||
setSeed(session.wi);
|
||||
|
||||
formCond->on_buttonRemoveAll_clicked();
|
||||
for (Condition &c : condvec)
|
||||
for (Condition &c : session.cv)
|
||||
{
|
||||
QListWidgetItem *item = new QListWidgetItem();
|
||||
formCond->addItemCondition(item, c);
|
||||
}
|
||||
|
||||
formGen48->setConfig(gen48, quiet);
|
||||
formGen48->setConfig(session.gen48, quiet);
|
||||
formGen48->updateCount();
|
||||
|
||||
if (!keepresults)
|
||||
formControl->on_buttonClear_clicked();
|
||||
formControl->setSearchConfig(searchconf, quiet);
|
||||
formControl->searchResultsAdd(seeds, false);
|
||||
formControl->setSearchConfig(session.sc, quiet);
|
||||
formControl->searchResultsAdd(session.slist, false);
|
||||
formControl->searchProgressReset();
|
||||
|
||||
return true;
|
||||
@ -760,27 +637,6 @@ void MainWindow::setDockable(bool dockable)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::applyConfigChanges(const Config old, const Config conf)
|
||||
{
|
||||
this->config = conf;
|
||||
getMapView()->setConfig(conf);
|
||||
if (old.uistyle != conf.uistyle)
|
||||
onStyleChanged(conf.uistyle);
|
||||
|
||||
if (conf.autosaveCycle)
|
||||
{
|
||||
autosaveTimer.setInterval(conf.autosaveCycle * 60000);
|
||||
autosaveTimer.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
autosaveTimer.stop();
|
||||
}
|
||||
|
||||
if (!conf.biomeColorPath.isEmpty() || !old.biomeColorPath.isEmpty())
|
||||
onBiomeColorChange();
|
||||
}
|
||||
|
||||
void MainWindow::setMCList(bool experimental)
|
||||
{
|
||||
WorldInfo wi;
|
||||
@ -808,11 +664,6 @@ void MainWindow::setMCList(bool experimental)
|
||||
ui->comboBoxMC->setEnabled(true);
|
||||
}
|
||||
|
||||
int MainWindow::warning(QString text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return QMessageBox::warning(this, tr("Warning"), text, buttons);
|
||||
}
|
||||
|
||||
void MainWindow::mapGoto(qreal x, qreal z, qreal scale)
|
||||
{
|
||||
getMapView()->setView(x, z, scale);
|
||||
@ -867,7 +718,7 @@ void MainWindow::on_actionSave_triggered()
|
||||
{
|
||||
QFileInfo finfo(fnam);
|
||||
prevdir = finfo.absolutePath();
|
||||
saveProgress(fnam);
|
||||
saveSession(fnam);
|
||||
}
|
||||
}
|
||||
|
||||
@ -879,7 +730,7 @@ void MainWindow::on_actionLoad_triggered()
|
||||
{
|
||||
QFileInfo finfo(fnam);
|
||||
prevdir = finfo.absolutePath();
|
||||
loadProgress(fnam, false, false);
|
||||
loadSession(fnam, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -934,7 +785,7 @@ void MainWindow::on_actionPresetLoad_triggered()
|
||||
PresetDialog *dialog = new PresetDialog(this, wi, false);
|
||||
dialog->setActiveFilter(formCond->getConditions());
|
||||
if (dialog->exec() && !dialog->rc.isEmpty())
|
||||
loadProgress(dialog->rc, true, false);
|
||||
loadSession(dialog->rc, true, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExamples_triggered()
|
||||
@ -944,7 +795,7 @@ void MainWindow::on_actionExamples_triggered()
|
||||
PresetDialog *dialog = new PresetDialog(this, wi, true);
|
||||
dialog->setActiveFilter(formCond->getConditions());
|
||||
if (dialog->exec() && !dialog->rc.isEmpty())
|
||||
loadProgress(dialog->rc, true, false);
|
||||
loadSession(dialog->rc, true, false);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_triggered()
|
||||
@ -965,8 +816,8 @@ void MainWindow::on_actionPaste_triggered()
|
||||
|
||||
void MainWindow::on_actionAddShadow_triggered()
|
||||
{
|
||||
const QVector<uint64_t> results = formControl->getResults();
|
||||
QVector<uint64_t> shadows;
|
||||
const std::vector<uint64_t> results = formControl->getResults();
|
||||
std::vector<uint64_t> shadows;
|
||||
shadows.reserve(results.size());
|
||||
for (uint64_t s : results)
|
||||
shadows.push_back( getShadow(s) );
|
||||
@ -1059,7 +910,7 @@ void MainWindow::onAutosaveTimeout()
|
||||
if (config.autosaveCycle)
|
||||
{
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
saveProgress(path + "/session.save", true);
|
||||
saveSession(path + "/session.save", true);
|
||||
//int dispms = 10000;
|
||||
//if (saveProgress(path + "/session.save", true))
|
||||
// ui->statusBar->showMessage(tr("Session autosaved"), dispms);
|
||||
@ -1072,8 +923,8 @@ void MainWindow::onActionHistory(QAction *act)
|
||||
{
|
||||
uint64_t seed = act->data().toULongLong();
|
||||
onSelectedSeedChanged(seed);
|
||||
ui->menuHistory->removeAction(act);
|
||||
act->deleteLater();
|
||||
//ui->menuHistory->removeAction(act);
|
||||
//act->deleteLater();
|
||||
}
|
||||
|
||||
void MainWindow::onActionMapToggled(int sopt, bool show)
|
||||
@ -1129,8 +980,7 @@ void MainWindow::onUpdateConfig()
|
||||
|
||||
if (old.lang != config.lang)
|
||||
{
|
||||
QString msg = tr("The application will need to be restarted before all changes can take effect.");
|
||||
QMessageBox::information(this, tr("Restart required"), msg);
|
||||
info(this, tr("The application will need to be restarted before all changes can take effect."));
|
||||
}
|
||||
|
||||
getMapView()->setConfig(config);
|
||||
@ -1139,6 +989,38 @@ void MainWindow::onUpdateConfig()
|
||||
if (!old.biomeColorPath.isEmpty() || !config.biomeColorPath.isEmpty())
|
||||
onBiomeColorChange();
|
||||
|
||||
if (old.fontNorm != config.fontNorm || old.fontMono != config.fontMono)
|
||||
{
|
||||
QFont fnorm = config.fontNorm;
|
||||
QFont fmono = config.fontMono;
|
||||
QFont fbold;
|
||||
if (fnorm.family() == "Monospace") // avoid identification conflict
|
||||
fnorm = QApplication::font();
|
||||
fnorm.setStyleHint(QFont::AnyStyle);
|
||||
fmono.setStyleHint(QFont::Monospace);
|
||||
fmono.setFixedPitch(true);
|
||||
|
||||
fbold = fnorm;
|
||||
fbold.setBold(true);
|
||||
|
||||
QApplication::setFont(fnorm);
|
||||
|
||||
QWidgetList wlist = QApplication::allWidgets();
|
||||
for (QWidget *w : qAsConst(wlist))
|
||||
{
|
||||
const QFont& f = w->font();
|
||||
if (f.styleHint() == QFont::Monospace || f.family() == "Monospace")
|
||||
w->setFont(fmono);
|
||||
else if (f.bold())
|
||||
w->setFont(fbold);
|
||||
else
|
||||
w->setFont(fnorm);
|
||||
}
|
||||
// update cascade
|
||||
for (QWidget *w : qAsConst(wlist))
|
||||
w->update();
|
||||
}
|
||||
|
||||
if (config.autosaveCycle)
|
||||
{
|
||||
autosaveTimer.setInterval(config.autosaveCycle * 60000);
|
||||
|
@ -30,7 +30,6 @@ namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
|
||||
struct ISaveTab
|
||||
{
|
||||
virtual void save(QSettings& settings) = 0;
|
||||
@ -45,13 +44,14 @@ class MainWindow : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
explicit MainWindow(QString sessionpath, QString resultspath, QWidget *parent = 0);
|
||||
virtual ~MainWindow();
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
bool loadTranslation(QString lang);
|
||||
|
||||
QAction *addMapAction(int sopt, const char *iconpath, QString tip);
|
||||
QAction *addMapAction(int opt);
|
||||
QAction *addMapAction(QString rcbase, QString tip);
|
||||
|
||||
bool getSeed(WorldInfo *wi, bool applyrand = true);
|
||||
bool setSeed(WorldInfo wi, int dim = DIM_UNDEF);
|
||||
@ -61,18 +61,16 @@ public:
|
||||
protected:
|
||||
void saveSettings();
|
||||
void loadSettings();
|
||||
bool saveProgress(QString fnam, bool quiet = false);
|
||||
bool loadProgress(QString fnam, bool keepresults, bool quiet);
|
||||
bool saveSession(QString fnam, bool quiet = false);
|
||||
bool loadSession(QString fnam, bool keepresults, bool quiet);
|
||||
void updateMapSeed();
|
||||
void setDockable(bool dockable);
|
||||
void applyConfigChanges(const Config old, const Config conf);
|
||||
void setMCList(bool experimental);
|
||||
|
||||
signals:
|
||||
void mapUpdated();
|
||||
|
||||
public slots:
|
||||
int warning(QString text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||
void mapGoto(qreal x, qreal z, qreal scale);
|
||||
void setBiomeColorRc(QString rc);
|
||||
|
||||
@ -134,6 +132,7 @@ public:
|
||||
LayerOpt lopt;
|
||||
Config config;
|
||||
MapConfig mconfig;
|
||||
QString sessionpath;
|
||||
QString prevdir;
|
||||
QTimer autosaveTimer;
|
||||
int prevtab;
|
||||
|
@ -54,8 +54,9 @@ MapView::MapView(QWidget *parent)
|
||||
{
|
||||
memset(sshow, 0, sizeof(sshow));
|
||||
|
||||
QFont mono = *gp_font_mono;
|
||||
setFont(mono);
|
||||
QFont fmono;
|
||||
fmono.setFamily(QString::fromUtf8("Monospace"));
|
||||
setFont(fmono);
|
||||
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Background, Qt::black);
|
||||
@ -68,7 +69,7 @@ MapView::MapView(QWidget *parent)
|
||||
|
||||
overlay = new MapOverlay(this);
|
||||
overlay->setMouseTracking(true);
|
||||
overlay->setFont(mono);
|
||||
overlay->setFont(font());
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||
@ -377,27 +378,35 @@ void MapView::showContextMenu(const QPoint &pos)
|
||||
cpy_dat.push_back({ tr("Copy chunk:"), QString::asprintf("%d %d", vp.p.x >> 4, vp.p.z >> 4) });
|
||||
cpy_dat.push_back({ tr("Copy region:"), QString::asprintf("%d %d", vp.p.x >> 9, vp.p.z >> 9) });
|
||||
|
||||
int pad = 0;
|
||||
int wmax = 0;
|
||||
for (auto& it : cpy_dat)
|
||||
{
|
||||
if (it.txt.length() > pad)
|
||||
pad = it.txt.length();
|
||||
int w = menu.fontMetrics().horizontalAdvance(it.txt + " ");
|
||||
if (w > wmax)
|
||||
wmax = w;
|
||||
}
|
||||
pad += 1;
|
||||
|
||||
|
||||
menu.addAction(tr("Go to coordinates..."), this, &MapView::onGoto, QKeySequence(Qt::CTRL + Qt::Key_G));
|
||||
if (world)
|
||||
{
|
||||
QString txt = tr("Copy seed:").leftJustified(pad) + QString::asprintf("%" PRId64, (int64_t)world->wi.seed);
|
||||
QString txt = tr("Copy seed:");
|
||||
while (menu.fontMetrics().horizontalAdvance(txt + " ") < wmax)
|
||||
txt += " ";
|
||||
txt += QString::asprintf("%" PRId64, (int64_t)world->wi.seed);
|
||||
menu.addAction(txt, this, &MapView::copySeed, QKeySequence::Copy);
|
||||
}
|
||||
for (auto& it : cpy_dat)
|
||||
{
|
||||
QString txt = it.txt.leftJustified(pad) + it.cpy;
|
||||
QString txt = it.txt;
|
||||
while (menu.fontMetrics().horizontalAdvance(txt + " ") < wmax)
|
||||
txt += " ";
|
||||
txt += it.cpy;
|
||||
menu.addAction(txt, [=](){ this->copyText(it.cpy); });
|
||||
}
|
||||
//menu.addAction(tr("Animation"), this, &MapView::runAni);
|
||||
|
||||
for (QAction *act : menu.actions())
|
||||
act->setFont(font());
|
||||
menu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
@ -616,6 +625,11 @@ void MapView::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->matches(QKeySequence::Copy))
|
||||
copySeed();
|
||||
else if (e->matches(QKeySequence::ZoomIn) || e->key() == Qt::Key_Plus)
|
||||
zoom(pow(2, +0.125));
|
||||
else if (e->matches(QKeySequence::ZoomOut) || e->key() == Qt::Key_Minus)
|
||||
zoom(pow(2, -0.125));
|
||||
|
||||
qreal step = 4 / blocks2pix;
|
||||
switch (e->key())
|
||||
{
|
||||
@ -623,12 +637,6 @@ void MapView::keyPressEvent(QKeyEvent *e)
|
||||
if (e->modifiers() == 0)
|
||||
setView(0, 0);
|
||||
break;
|
||||
case Qt::Key_Plus:
|
||||
zoom(pow(2, +0.125));
|
||||
break;
|
||||
case Qt::Key_Minus:
|
||||
zoom(pow(2, -0.125));
|
||||
break;
|
||||
case Qt::Key_Up:
|
||||
focusz -= step;
|
||||
update();
|
||||
|
81
src/message.cpp
Normal file
81
src/message.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "message.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTextStream>
|
||||
|
||||
|
||||
static
|
||||
int term_prompt(const QString& title, const QString& text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
QTextStream out (stdout);
|
||||
out << QString("[%1]\n%2\n---\n").arg(title).arg(text);
|
||||
std::vector<std::pair<QString, int>> opts;
|
||||
if (buttons & QMessageBox::Ok)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "OK"), QMessageBox::Ok));
|
||||
if (buttons & QMessageBox::Yes)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Yes"), QMessageBox::Yes));
|
||||
if (buttons & QMessageBox::No)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "No"), QMessageBox::No));
|
||||
if (buttons & QMessageBox::Abort)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Abort"), QMessageBox::Abort));
|
||||
if (buttons & QMessageBox::Cancel)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Cancel"), QMessageBox::Cancel));
|
||||
if (buttons & QMessageBox::Ignore)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Ignore"), QMessageBox::Ignore));
|
||||
if (buttons & QMessageBox::Reset)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Reset"), QMessageBox::Reset));
|
||||
if (buttons & QMessageBox::Save)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Save"), QMessageBox::Save));
|
||||
if (buttons & QMessageBox::Discard)
|
||||
opts.push_back(std::make_pair(QApplication::translate("QPlatformTheme", "Discard"), QMessageBox::Discard));
|
||||
if (opts.size() <= 1)
|
||||
return buttons;
|
||||
for (size_t i = 0; i < opts.size(); i++)
|
||||
out << QString("%1%2 [%3]").arg(i==0 ? "" : ", ").arg(opts[i].first).arg(i+1);
|
||||
out << ":";
|
||||
out.flush();
|
||||
QTextStream in (stdin);
|
||||
uint num = 0;
|
||||
while (true)
|
||||
{
|
||||
num = in.readLine().toUInt();
|
||||
if (num >= 1 && num <= opts.size())
|
||||
break;
|
||||
out << "Invalid option, try again: ";
|
||||
out.flush();
|
||||
}
|
||||
return opts[num-1].second;
|
||||
}
|
||||
|
||||
static
|
||||
int message(QWidget *parent, QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
if (!parent)
|
||||
return term_prompt(title, text, buttons);
|
||||
|
||||
// emulate the behaviour of QMessageBox::warning(...), but raise as active window
|
||||
QMessageBox w(icon, title, text, QMessageBox::NoButton, parent);
|
||||
for (uint mask = QMessageBox::FirstButton; mask <= QMessageBox::LastButton; mask <<= 1)
|
||||
if (mask & buttons)
|
||||
w.addButton((QMessageBox::StandardButton)mask);
|
||||
parent->setWindowState(Qt::WindowActive);
|
||||
//w.setWindowState(Qt::WindowActive);
|
||||
if (w.exec() == -1)
|
||||
return QMessageBox::Cancel;
|
||||
return w.standardButton(w.clickedButton());
|
||||
}
|
||||
|
||||
int warn(QWidget *parent, const QString& title, const QString& text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return message(parent, QMessageBox::Warning, title, text, buttons);
|
||||
}
|
||||
|
||||
int warn(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return message(parent, QMessageBox::Warning, QApplication::tr("Warning"), text, buttons);
|
||||
}
|
||||
|
||||
int info(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return message(parent, QMessageBox::Information, QApplication::tr("Information"), text, buttons);
|
||||
}
|
10
src/message.h
Normal file
10
src/message.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef MESSAGE_H
|
||||
#define MESSAGE_H
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
int warn(QWidget *parent, const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||
int warn(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||
int info(QWidget *parent, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok);
|
||||
|
||||
#endif // MESSAGE_H
|
@ -61,8 +61,6 @@ PresetDialog::PresetDialog(QWidget *parent, WorldInfo wi, bool showEamples)
|
||||
connect(ui->buttonOk, &QPushButton::clicked, this, &QDialog::accept);
|
||||
connect(ui->buttonCancel, &QPushButton::clicked, this, &QDialog::reject);
|
||||
|
||||
ui->listFilters->setFont(*gp_font_mono);
|
||||
|
||||
if (showEamples)
|
||||
ui->tabWidget->setCurrentWidget(ui->tabExamples);
|
||||
else
|
||||
|
@ -60,7 +60,6 @@
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
@ -83,7 +82,6 @@
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
|
186
src/search.cpp
186
src/search.cpp
@ -12,12 +12,13 @@
|
||||
#include <QApplication>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define MULTIPLY_CHAR QChar(0xD7)
|
||||
|
||||
QString Condition::summary() const
|
||||
QString Condition::summary(const QFont *font) const
|
||||
{
|
||||
const FilterInfo& ft = g_filterinfo.list[type];
|
||||
QString s;
|
||||
@ -32,7 +33,7 @@ QString Condition::summary() const
|
||||
return s;
|
||||
}
|
||||
|
||||
QString cnts = "";
|
||||
QString cnts;
|
||||
if (ft.count)
|
||||
cnts += MULTIPLY_CHAR + QString::number(count);
|
||||
if (skipref)
|
||||
@ -57,8 +58,19 @@ QString Condition::summary() const
|
||||
}
|
||||
}
|
||||
|
||||
s += QString(" %2%3").arg(txts, -28, ' ').arg(cnts, -4, QChar(' '));
|
||||
|
||||
if (font)
|
||||
{
|
||||
s += " " + txts;
|
||||
QFontMetrics fm(*font);
|
||||
int w = fm.horizontalAdvance(QString("%1").arg("#", 30));
|
||||
while (fm.horizontalAdvance(s + "\t") < w)
|
||||
s += "\t";
|
||||
}
|
||||
else
|
||||
{
|
||||
s += QString(" %1").arg(txts, -25);
|
||||
}
|
||||
s += QString("\t%1").arg(cnts, -3);
|
||||
if (relative)
|
||||
s += QString::asprintf("[%02d]+", relative);
|
||||
else
|
||||
@ -273,7 +285,6 @@ void SearchThreadEnv::prepareSurfaceNoise(int dim)
|
||||
}
|
||||
}
|
||||
|
||||
#include <QDebug>
|
||||
static
|
||||
int testTreeAt(
|
||||
Pos at, // relative origin
|
||||
@ -573,67 +584,115 @@ int testTreeAt(
|
||||
}
|
||||
|
||||
|
||||
static const int g_qh_c_n = sizeof(low20QuadHutBarely) / sizeof(uint64_t);
|
||||
static QuadInfo qh_constellations[g_qh_c_n];
|
||||
|
||||
// initialize global tables
|
||||
void _init(void) __attribute__((constructor));
|
||||
void _init(void)
|
||||
static const QuadInfo *getQHInfo(uint64_t cst)
|
||||
{
|
||||
int st = Swamp_Hut;
|
||||
StructureConfig sc;
|
||||
getStructureConfig(st, MC_NEWEST, &sc);
|
||||
sc.salt = 0; // ignore version dependent salt offsets
|
||||
static std::map<uint64_t, QuadInfo> qh_info;
|
||||
static QMutex mutex;
|
||||
|
||||
for (int i = 0; i < g_qh_c_n; i++)
|
||||
mutex.lock();
|
||||
if (qh_info.size() == 0)
|
||||
{
|
||||
uint64_t b = low20QuadHutBarely[i];
|
||||
for (uint64_t s = b;; s += 0x100000)
|
||||
StructureConfig sc;
|
||||
getStructureConfig(Swamp_Hut, MC_NEWEST, &sc);
|
||||
sc.salt = 0; // ignore version dependent salt offsets
|
||||
|
||||
for (size_t i = 0, n = sizeof(low20QuadHutBarely) / sizeof(uint64_t); i < n; i++)
|
||||
{
|
||||
QuadInfo *qi = &qh_constellations[i];
|
||||
Pos pc;
|
||||
if (scanForQuads(sc, 128, s, low20QuadHutBarely, g_qh_c_n,
|
||||
20, 0, 0, 0, 1, 1, &pc, 1) < 1)
|
||||
continue;
|
||||
if ( !(qi->rad = isQuadBase(sc, s, 160)) )
|
||||
continue;
|
||||
uint64_t c = low20QuadHutBarely[i];
|
||||
for (uint64_t s = c;; s += 0x100000)
|
||||
{
|
||||
// find a quad-hut for this constellation
|
||||
Pos pc;
|
||||
if (scanForQuads(sc, 128, s, low20QuadHutBarely, n, 20, 0, 0, 0, 1, 1, &pc, 1) < 1)
|
||||
continue;
|
||||
qreal rad = isQuadBase(sc, s, 160);
|
||||
if (rad == 0)
|
||||
continue;
|
||||
|
||||
qi->c = b;
|
||||
qi->p[0] = getFeaturePos(sc, s, 0, 0);
|
||||
qi->p[1] = getFeaturePos(sc, s, 0, 1);
|
||||
qi->p[2] = getFeaturePos(sc, s, 1, 0);
|
||||
qi->p[3] = getFeaturePos(sc, s, 1, 1);
|
||||
qi->afk = getOptimalAfk(qi->p, 7,7,9, &qi->spcnt);
|
||||
qi->typ = st;
|
||||
QuadInfo *qi = &qh_info[c];
|
||||
qi->rad = rad;
|
||||
qi->c = c;
|
||||
qi->p[0] = getFeaturePos(sc, s, 0, 0);
|
||||
qi->p[1] = getFeaturePos(sc, s, 0, 1);
|
||||
qi->p[2] = getFeaturePos(sc, s, 1, 0);
|
||||
qi->p[3] = getFeaturePos(sc, s, 1, 1);
|
||||
qi->afk = getOptimalAfk(qi->p, 7,7,9, &qi->spcnt);
|
||||
qi->typ = Swamp_Hut;
|
||||
|
||||
qi->flt = F_QH_BARELY;
|
||||
int j, n;
|
||||
n = sizeof(low20QuadHutNormal) / sizeof(uint64_t);
|
||||
for (j = 0; j < n; j++) {
|
||||
if (low20QuadHutNormal[j] == b) {
|
||||
qi->flt = F_QH_NORMAL;
|
||||
break;
|
||||
qi->flt = F_QH_BARELY;
|
||||
int j, m;
|
||||
m = sizeof(low20QuadHutNormal) / sizeof(uint64_t);
|
||||
for (j = 0; j < m; j++) {
|
||||
if (low20QuadHutNormal[j] == c) {
|
||||
qi->flt = F_QH_NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
n = sizeof(low20QuadClassic) / sizeof(uint64_t);
|
||||
for (j = 0; j < n; j++) {
|
||||
if (low20QuadClassic[j] == b) {
|
||||
qi->flt = F_QH_CLASSIC;
|
||||
break;
|
||||
m = sizeof(low20QuadClassic) / sizeof(uint64_t);
|
||||
for (j = 0; j < m; j++) {
|
||||
if (low20QuadClassic[j] == c) {
|
||||
qi->flt = F_QH_CLASSIC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
n = sizeof(low20QuadIdeal) / sizeof(uint64_t);
|
||||
for (j = 0; j < n; j++) {
|
||||
if (low20QuadIdeal[j] == b) {
|
||||
qi->flt = F_QH_IDEAL;
|
||||
break;
|
||||
m = sizeof(low20QuadIdeal) / sizeof(uint64_t);
|
||||
for (j = 0; j < m; j++) {
|
||||
if (low20QuadIdeal[j] == c) {
|
||||
qi->flt = F_QH_IDEAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
|
||||
auto it = qh_info.find(cst);
|
||||
if (it == qh_info.end())
|
||||
return nullptr;
|
||||
else
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
static const QuadInfo *getQMInfo(uint64_t s48)
|
||||
{
|
||||
static std::map<uint64_t, QuadInfo> qm_info;
|
||||
static QMutex mutex;
|
||||
|
||||
mutex.lock();
|
||||
if (qm_info.size() == 0)
|
||||
{
|
||||
StructureConfig sc;
|
||||
getStructureConfig(Monument, MC_NEWEST, &sc);
|
||||
sc.salt = 0;
|
||||
|
||||
for (size_t i = 0, n = sizeof(g_qm_90) / sizeof(uint64_t); i < n; i++)
|
||||
{
|
||||
uint64_t s = g_qm_90[i];
|
||||
QuadInfo *qi = &qm_info[s];
|
||||
qi->rad = isQuadBase(sc, s, 160);
|
||||
qi->c = s;
|
||||
qi->p[0] = getLargeStructurePos(sc, s, 0, 0);
|
||||
qi->p[1] = getLargeStructurePos(sc, s, 0, 1);
|
||||
qi->p[2] = getLargeStructurePos(sc, s, 1, 0);
|
||||
qi->p[3] = getLargeStructurePos(sc, s, 1, 1);
|
||||
qi->afk = getOptimalAfk(qi->p, 58,0/*23*/,58, &qi->spcnt);
|
||||
qi->afk.x -= 29;
|
||||
qi->afk.z -= 29;
|
||||
qi->typ = Monument;
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
|
||||
auto it = qm_info.find(s48);
|
||||
if (it == qm_info.end())
|
||||
return nullptr;
|
||||
else
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
|
||||
static bool isVariantOk(const Condition *c, SearchThreadEnv *e, int stype, int varbiome, Pos *pos)
|
||||
{
|
||||
StructureVariant sv;
|
||||
@ -853,7 +912,7 @@ testCondAt(
|
||||
int qual, valid;
|
||||
int xt, zt;
|
||||
int st;
|
||||
int i, j, n, icnt;
|
||||
int i, n, icnt;
|
||||
int64_t s, r, rmin, rmax;
|
||||
const uint64_t *seeds;
|
||||
Pos p[MAX_INSTANCES];
|
||||
@ -918,16 +977,7 @@ L_qh_any:
|
||||
s = moveStructure(env->seed, -pc.x, -pc.z);
|
||||
|
||||
// find the constellation info
|
||||
uint64_t cst = (s + sconf.salt) & 0xfffff;
|
||||
QuadInfo *qi = NULL;
|
||||
for (j = 0; j < g_qh_c_n; j++)
|
||||
{
|
||||
if (qh_constellations[j].c == cst)
|
||||
{
|
||||
qi = &qh_constellations[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
const QuadInfo *qi = getQHInfo((s + sconf.salt) & 0xfffff);
|
||||
if (!qi || qi->flt > cond->type)
|
||||
continue;
|
||||
// we don't support finding the center of multiple
|
||||
@ -969,13 +1019,9 @@ L_qm_any:
|
||||
s = moveStructure(env->seed, -rx, -rz);
|
||||
if (qmonumentQual(s + sconf.salt) >= qual)
|
||||
{
|
||||
getStructurePos(st, env->mc, env->seed, rx+0, rz+0, p+0);
|
||||
getStructurePos(st, env->mc, env->seed, rx+0, rz+1, p+1);
|
||||
getStructurePos(st, env->mc, env->seed, rx+1, rz+0, p+2);
|
||||
getStructurePos(st, env->mc, env->seed, rx+1, rz+1, p+3);
|
||||
pc = getOptimalAfk(p, 58,23,58, 0);
|
||||
pc.x -= 29; // monument is centered
|
||||
pc.z -= 29;
|
||||
const QuadInfo *qi = getQMInfo(s + sconf.salt);
|
||||
pc.x = (rx << 9) + qi->afk.x;
|
||||
pc.z = (rz << 9) + qi->afk.z;
|
||||
cent[icnt] = pc;
|
||||
icnt++;
|
||||
if (imax && icnt >= *imax)
|
||||
|
@ -10,8 +10,6 @@
|
||||
#include <QMap>
|
||||
#include <atomic>
|
||||
|
||||
#define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30)
|
||||
|
||||
enum
|
||||
{
|
||||
CAT_NONE,
|
||||
@ -721,7 +719,7 @@ struct /*__attribute__((packed))*/ Condition
|
||||
QString toHex() const;
|
||||
bool readHex(const QString& hex);
|
||||
|
||||
QString summary() const;
|
||||
QString summary(const QFont *font) const;
|
||||
};
|
||||
|
||||
static_assert(
|
||||
|
@ -2,22 +2,155 @@
|
||||
#include "formsearchcontrol.h"
|
||||
#include "cutil.h"
|
||||
#include "seedtables.h"
|
||||
#include "message.h"
|
||||
#include "aboutdialog.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QEventLoop>
|
||||
#include <QApplication>
|
||||
#include <QStandardPaths>
|
||||
#include <QElapsedTimer>
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
#include <QDateTime>
|
||||
|
||||
|
||||
SearchMaster::SearchMaster(FormSearchControl *parent)
|
||||
void Session::writeHeader(QTextStream& stream)
|
||||
{
|
||||
stream << "#Version: " << VERS_MAJOR << "." << VERS_MINOR << "." << VERS_PATCH << "\n";
|
||||
stream << "#Time: " << QDateTime::currentDateTime().toString() << "\n";
|
||||
// MC version of the session should take priority over the one in the settings
|
||||
wi.write(stream);
|
||||
|
||||
sc.write(stream);
|
||||
gen48.write(stream);
|
||||
|
||||
for (Condition &c : cv)
|
||||
stream << "#Cond: " << c.toHex() << "\n";
|
||||
}
|
||||
|
||||
bool Session::save(QWidget *widget, QString fnam, bool quiet)
|
||||
{
|
||||
QFile file(fnam);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
if (!quiet)
|
||||
warn(widget, QApplication::tr("Failed to open file:\n\"%1\"").arg(fnam));
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
writeHeader(stream);
|
||||
|
||||
for (uint64_t s : slist)
|
||||
stream << QString::asprintf("%" PRId64 "\n", (int64_t)s);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Session::load(QWidget *widget, QString fnam, bool quiet)
|
||||
{
|
||||
QFile file(fnam);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
if (!quiet)
|
||||
warn(widget, QApplication::tr("Failed to open session file:\n\"%1\"").arg(fnam));
|
||||
return false;
|
||||
}
|
||||
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
QTextStream stream(&file);
|
||||
QString line;
|
||||
line = stream.readLine();
|
||||
int lno = 1;
|
||||
|
||||
if (sscanf(line.toLocal8Bit().data(), "#Version: %d.%d.%d", &major, &minor, &patch) != 3)
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
QString msg = QApplication::tr("File does not look like a session file.\n"
|
||||
"Progress may be incomplete or broken.\n\n"
|
||||
"Continue anyway?");
|
||||
int button = warn(widget, msg, QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
else if (cmpVers(major, minor, patch) > 0)
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
QString msg = QApplication::tr("Session file was created with a newer version.\n"
|
||||
"Progress may be incomplete or broken.\n\n"
|
||||
"Continue loading progress anyway?");
|
||||
int button = warn(widget, msg, QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
|
||||
while (stream.status() == QTextStream::Ok && !stream.atEnd())
|
||||
{
|
||||
lno++;
|
||||
line = stream.readLine();
|
||||
|
||||
if (line.isEmpty()) continue;
|
||||
if (line.startsWith("#Time:")) continue;
|
||||
if (line.startsWith("#Title:")) continue;
|
||||
if (line.startsWith("#Desc:")) continue;
|
||||
if (sc.read(line)) continue;
|
||||
if (gen48.read(line)) continue;
|
||||
if (wi.read(line)) continue;
|
||||
|
||||
if (line.startsWith("#Cond:"))
|
||||
{ // Conditions
|
||||
Condition c;
|
||||
if (c.readHex(line.mid(6).trimmed()))
|
||||
{
|
||||
cv.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
QString msg = QApplication::tr("Condition [%1] at line %2 is not supported.\n\n"
|
||||
"Continue anyway?");
|
||||
int button = warn(widget, msg.arg(c.save).arg(lno), QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Seeds
|
||||
QByteArray ba = line.toLocal8Bit();
|
||||
const char *p = ba.data();
|
||||
uint64_t s;
|
||||
if (sscanf(p, "%" PRId64, (int64_t*)&s) == 1)
|
||||
{
|
||||
slist.push_back(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quiet)
|
||||
return false;
|
||||
QString msg = QApplication::tr("Failed to parse line %1 of file:\n%2\n\n"
|
||||
"Continue anyway?");
|
||||
int button = warn(widget, msg.arg(lno).arg(line), QMessageBox::Abort|QMessageBox::Yes);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SearchMaster::SearchMaster(QWidget *parent)
|
||||
: QThread(parent)
|
||||
, parent(parent)
|
||||
, mutex()
|
||||
, abort()
|
||||
, timer()
|
||||
, proghist()
|
||||
, progtimer()
|
||||
, itemtimer()
|
||||
, count()
|
||||
, env()
|
||||
, searchtype()
|
||||
@ -43,39 +176,27 @@ SearchMaster::~SearchMaster()
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
bool SearchMaster::set(
|
||||
WorldInfo wi,
|
||||
const SearchConfig& sc,
|
||||
const Gen48Config& gen48,
|
||||
const Config& config,
|
||||
std::vector<uint64_t>& slist,
|
||||
const QVector<Condition>& cv
|
||||
)
|
||||
bool SearchMaster::set(QWidget *widget, const Session& s)
|
||||
{
|
||||
(void) config;
|
||||
char refbuf[100] = {};
|
||||
char disabled[100] = {};
|
||||
|
||||
for (const Condition& c : cv)
|
||||
for (const Condition& c : s.cv)
|
||||
if (c.meta & Condition::DISABLED)
|
||||
disabled[c.save] = 1;
|
||||
|
||||
for (const Condition& c : cv)
|
||||
for (const Condition& c : s.cv)
|
||||
{
|
||||
char cid[8];
|
||||
snprintf(cid, sizeof(cid), "[%02d]", c.save);
|
||||
if (c.save < 1 || c.save > 99)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Condition with invalid ID %1.").arg(cid));
|
||||
warn(widget, tr("Condition with invalid ID %1.").arg(cid));
|
||||
return false;
|
||||
}
|
||||
if (c.type < 0 || c.type >= FILTER_MAX)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Error"),
|
||||
tr("Encountered invalid filter type %1 in condition ID %2.")
|
||||
.arg(c.type).arg(cid));
|
||||
warn(widget, tr("Encountered invalid filter type %1 in condition ID %2.").arg(c.type).arg(cid));
|
||||
return false;
|
||||
}
|
||||
if (disabled[c.save])
|
||||
@ -85,39 +206,32 @@ bool SearchMaster::set(
|
||||
|
||||
if (c.relative && refbuf[c.relative] == 0)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Condition with ID %1 has a broken reference position:\n"
|
||||
"condition missing or out of order.").arg(cid));
|
||||
warn(widget, tr("Condition with ID %1 has a broken reference position:\n"
|
||||
"condition missing or out of order.").arg(cid));
|
||||
return false;
|
||||
}
|
||||
if (++refbuf[c.save] > 1)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("More than one condition with ID %1.").arg(cid));
|
||||
warn(widget, tr("More than one condition with ID %1.").arg(cid));
|
||||
return false;
|
||||
}
|
||||
if (c.relative && disabled[c.relative])
|
||||
{
|
||||
int button = QMessageBox::information(NULL, tr("Warning"),
|
||||
tr("Condition %1 has been indirectly disabled by reference.")
|
||||
.arg(cid), QMessageBox::Abort|QMessageBox::Ignore);
|
||||
int button = info(widget, tr("Condition %1 has been indirectly disabled by reference.").arg(cid),
|
||||
QMessageBox::Abort|QMessageBox::Ignore);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
if (wi.mc < finfo.mcmin)
|
||||
if (s.wi.mc < finfo.mcmin)
|
||||
{
|
||||
const char *mcs = mc2str(finfo.mcmin);
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Condition %1 requires a minimum Minecraft version of %2.")
|
||||
.arg(cid, mcs));
|
||||
warn(widget, tr("Condition %1 requires a minimum Minecraft version of %2.").arg(cid, mcs));
|
||||
return false;
|
||||
}
|
||||
if (wi.mc > finfo.mcmax)
|
||||
if (s.wi.mc > finfo.mcmax)
|
||||
{
|
||||
const char *mcs = mc2str(finfo.mcmax);
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Condition %1 not available for Minecraft versions above %2.")
|
||||
.arg(cid, mcs));
|
||||
warn(widget, tr("Condition %1 not available for Minecraft versions above %2.").arg(cid, mcs));
|
||||
return false;
|
||||
}
|
||||
if (finfo.cat == CAT_BIOMES &&
|
||||
@ -131,41 +245,37 @@ bool SearchMaster::set(
|
||||
uint64_t m = c.biomeToFindM;
|
||||
if ((c.biomeToExcl & b) || (c.biomeToExclM & m))
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Biome condition with ID %1 has contradicting "
|
||||
"flags for include and exclude.").arg(cid));
|
||||
warn(widget, tr("Biome condition with ID %1 has contradicting flags for include and exclude.").arg(cid));
|
||||
return false;
|
||||
}
|
||||
if ((b | m | c.biomeToExcl | c.biomeToExclM) == 0)
|
||||
{
|
||||
int button = QMessageBox::information(parent, tr("Info"),
|
||||
tr("Biome condition with ID %1 specifies no biomes.")
|
||||
.arg(cid), QMessageBox::Abort|QMessageBox::Ignore);
|
||||
int button = info(widget, tr("Biome condition with ID %1 specifies no biomes.").arg(cid),
|
||||
QMessageBox::Abort|QMessageBox::Ignore);
|
||||
if (button == QMessageBox::Abort)
|
||||
return false;
|
||||
}
|
||||
|
||||
int layerId = finfo.layer;
|
||||
if (layerId == 0 && wi.mc <= MC_1_17)
|
||||
if (layerId == 0 && s.wi.mc <= MC_1_17)
|
||||
{
|
||||
Generator tmp;
|
||||
setupGenerator(&tmp, wi.mc, 0);
|
||||
setupGenerator(&tmp, s.wi.mc, 0);
|
||||
const Layer *l = getLayerForScale(&tmp, finfo.step);
|
||||
if (l)
|
||||
layerId = l - tmp.ls.layers;
|
||||
}
|
||||
uint64_t ab, am;
|
||||
uint32_t flags = 0;
|
||||
getAvailableBiomes(&ab, &am, layerId, wi.mc, flags);
|
||||
getAvailableBiomes(&ab, &am, layerId, s.wi.mc, flags);
|
||||
b ^= (ab & b);
|
||||
m ^= (am & m);
|
||||
if (b || m)
|
||||
{
|
||||
int cnt = __builtin_popcountll(b) + __builtin_popcountll(m);
|
||||
QString msg = tr("Biome condition with ID %1 includes %n "
|
||||
"biome(s) that do not generate in MC %2.", "", cnt)
|
||||
.arg(cid, mc2str(wi.mc));
|
||||
QMessageBox::warning(parent, tr("Warning"), msg);
|
||||
QString msg = tr("Biome condition with ID %1 includes %n biome(s) "
|
||||
"that do not generate in MC %2.", "", cnt);
|
||||
warn(widget, msg.arg(cid, mc2str(s.wi.mc)));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -175,10 +285,9 @@ bool SearchMaster::set(
|
||||
int h = c.z2 - c.z1 + 1;
|
||||
if (c.count > w * h)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Temperature category condition with ID %1 has too "
|
||||
"many restrictions (%2) for the area (%3 x %4).")
|
||||
.arg(cid).arg(c.count).arg(w).arg(h));
|
||||
QString msg = tr("Temperature category condition with ID %1 has too "
|
||||
"many restrictions (%2) for the area (%3 x %4).");
|
||||
warn(widget, msg.arg(cid).arg(c.count).arg(w).arg(h));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -186,46 +295,41 @@ bool SearchMaster::set(
|
||||
{
|
||||
if (c.count >= 128)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Structure condition %1 checks for too many instances (>= 128).")
|
||||
.arg(cid));
|
||||
warn(widget, tr("Structure condition %1 checks for too many instances (>= 128).").arg(cid));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (c.skipref && c.rmax == 0 && c.x1 == 0 && c.x2 == 0 && c.z1 == 0 && c.z2 == 0)
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Condition %1 ignores its only location of size 1.")
|
||||
.arg(cid));
|
||||
warn(widget, tr("Condition %1 ignores its only location of size 1.").arg(cid));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QString err = condtree.set(cv, wi.mc);
|
||||
QString err = condtree.set(s.cv, s.wi.mc);
|
||||
if (err.isEmpty())
|
||||
{
|
||||
err = env.init(wi.mc, wi.large, &condtree);
|
||||
err = env.init(s.wi.mc, s.wi.large, &condtree);
|
||||
}
|
||||
if (!err.isEmpty())
|
||||
{
|
||||
QMessageBox::warning(parent, tr("Warning"),
|
||||
tr("Failed to setup search environment:\n%1").arg(err));
|
||||
warn(widget, tr("Failed to setup search environment:\n%1").arg(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->searchtype = sc.searchtype;
|
||||
this->mc = wi.mc;
|
||||
this->large = wi.large;
|
||||
this->itemsize = 1; //config.seedsPerItem;
|
||||
this->threadcnt = sc.threads;
|
||||
this->slist = slist;
|
||||
this->gen48 = gen48;
|
||||
this->searchtype = s.sc.searchtype;
|
||||
this->mc = s.wi.mc;
|
||||
this->large = s.wi.large;
|
||||
this->itemsize = 1;
|
||||
this->threadcnt = s.sc.threads;
|
||||
this->slist = s.slist;
|
||||
this->gen48 = s.gen48;
|
||||
this->idx = 0;
|
||||
this->scnt = ~(uint64_t)0;
|
||||
this->prog = 0;
|
||||
this->seed = sc.startseed;
|
||||
this->smin = sc.smin;
|
||||
this->smax = sc.smax;
|
||||
this->seed = s.sc.startseed;
|
||||
this->smin = s.sc.smin;
|
||||
this->smax = s.sc.smax;
|
||||
this->isdone = false;
|
||||
this->abort = false;
|
||||
return true;
|
||||
@ -282,24 +386,30 @@ static void genQHBases(QObject *qtobj, int qual, uint64_t salt, std::vector<uint
|
||||
|
||||
if ((qb = loadSavedSeeds(fnam.data(), &qn)) == NULL)
|
||||
{
|
||||
printf("Writing quad-protobases to: %s\n", fnam.data());
|
||||
printf("[INFO]: Writing quad-protobases to: %s\n", fnam.data());
|
||||
fflush(stdout);
|
||||
|
||||
QMetaObject::invokeMethod(qtobj, "openProtobaseMsg", Qt::QueuedConnection, Q_ARG(QString, path));
|
||||
if (qtobj)
|
||||
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, SearchMaster::tr("Failed to generate protobases.")));
|
||||
printf("[WARN]: Failed to generate protobases.\n");
|
||||
if (qtobj)
|
||||
{
|
||||
QMetaObject::invokeMethod(
|
||||
qtobj, "warning", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QString, SearchMaster::tr("Failed to generate protobases.")));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(qtobj, "closeProtobaseMsg", Qt::BlockingQueuedConnection);
|
||||
if (qtobj)
|
||||
QMetaObject::invokeMethod(qtobj, "closeProtobaseMsg", Qt::BlockingQueuedConnection);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -355,10 +465,27 @@ static bool applyTranspose(std::vector<uint64_t>& slist,
|
||||
return !slist.empty();
|
||||
}
|
||||
|
||||
void SearchMaster::presearch()
|
||||
void SearchMaster::presearch(QObject *qtobj)
|
||||
{
|
||||
uint64_t sstart = seed;
|
||||
|
||||
if (gen48.mode == GEN48_AUTO)
|
||||
{ // resolve automatic mode
|
||||
for (const Condition& c : qAsConst(condtree.condvec))
|
||||
{
|
||||
if (c.type >= F_QH_IDEAL && c.type <= F_QH_BARELY)
|
||||
{
|
||||
gen48.mode = GEN48_QH;
|
||||
break;
|
||||
}
|
||||
else if (c.type >= F_QM_95 && c.type <= F_QM_90)
|
||||
{
|
||||
gen48.mode = GEN48_QM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchtype != SEARCH_LIST)
|
||||
{
|
||||
if (gen48.mode == GEN48_QH)
|
||||
@ -373,7 +500,7 @@ void SearchMaster::presearch()
|
||||
salt = sconf.salt;
|
||||
}
|
||||
slist.clear();
|
||||
genQHBases(parent, gen48.qual, salt, slist);
|
||||
genQHBases(qtobj, gen48.qual, salt, slist);
|
||||
}
|
||||
else if (gen48.mode == GEN48_QM)
|
||||
{
|
||||
@ -494,7 +621,7 @@ void SearchMaster::presearch()
|
||||
|
||||
void SearchMaster::run()
|
||||
{
|
||||
presearch();
|
||||
presearch(parent());
|
||||
stop();
|
||||
|
||||
for (int i = 0; i < threadcnt; i++)
|
||||
@ -502,7 +629,7 @@ void SearchMaster::run()
|
||||
SearchWorker *worker = new SearchWorker(this);
|
||||
QObject::connect(
|
||||
worker, &SearchWorker::result,
|
||||
parent, &FormSearchControl::onSearchResult,
|
||||
this, &SearchMaster::onWorkerResult,
|
||||
Qt::BlockingQueuedConnection);
|
||||
QObject::connect(
|
||||
worker, &SearchWorker::finished,
|
||||
@ -515,7 +642,9 @@ void SearchMaster::run()
|
||||
QMutexLocker locker(&mutex);
|
||||
|
||||
abort = false;
|
||||
timer.start();
|
||||
proghist.clear();
|
||||
progtimer.start();
|
||||
itemtimer.start();
|
||||
count = 0;
|
||||
|
||||
for (SearchWorker *worker: workers)
|
||||
@ -524,7 +653,6 @@ void SearchMaster::run()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SearchMaster::stop()
|
||||
{
|
||||
abort = true;
|
||||
@ -548,6 +676,8 @@ void SearchMaster::stop()
|
||||
}
|
||||
if (!running)
|
||||
break;
|
||||
if (parent() == nullptr)
|
||||
continue;
|
||||
int button = 0;
|
||||
Qt::ConnectionType connectiontype = Qt::BlockingQueuedConnection;
|
||||
if (QThread::currentThread() == QApplication::instance()->thread())
|
||||
@ -555,7 +685,7 @@ void SearchMaster::stop()
|
||||
connectiontype = Qt::DirectConnection;
|
||||
}
|
||||
QMetaObject::invokeMethod(
|
||||
parent, "warning", connectiontype,
|
||||
parent(), "warning", connectiontype,
|
||||
Q_RETURN_ARG(int, button),
|
||||
Q_ARG(QString, tr("Failed to stop %n worker thread(s).\n"
|
||||
"Keep waiting for threads to stop?", "", running)),
|
||||
@ -580,7 +710,19 @@ void SearchMaster::stop()
|
||||
emit searchFinish(false);
|
||||
}
|
||||
|
||||
bool SearchMaster::getProgress(uint64_t *prog, uint64_t *end, uint64_t *seed)
|
||||
|
||||
static QString getAbbrNum(double x)
|
||||
{
|
||||
if (x >= 10e9)
|
||||
return QString::asprintf("%.1fG", x * 1e-9);
|
||||
if (x >= 10e6)
|
||||
return QString::asprintf("%.1fM", x * 1e-6);
|
||||
if (x >= 10e3)
|
||||
return QString::asprintf("%.1fK", x * 1e-3);
|
||||
return QString::asprintf("%.2f", x);
|
||||
}
|
||||
|
||||
bool SearchMaster::getProgress(QString *status, uint64_t *prog, uint64_t *end, uint64_t *seed, qreal *min, qreal *avg, qreal *max)
|
||||
{
|
||||
if (!mutex.tryLock(10))
|
||||
{
|
||||
@ -597,6 +739,7 @@ bool SearchMaster::getProgress(uint64_t *prog, uint64_t *end, uint64_t *seed)
|
||||
*prog = this->prog;
|
||||
*end = this->scnt;
|
||||
*seed = this->seed;
|
||||
*min = *avg = *max = nan("");
|
||||
|
||||
bool valid = false;
|
||||
for (SearchWorker *worker: workers)
|
||||
@ -608,7 +751,86 @@ bool SearchMaster::getProgress(uint64_t *prog, uint64_t *end, uint64_t *seed)
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isdone)
|
||||
{
|
||||
*prog = this->scnt;
|
||||
}
|
||||
|
||||
mutex.unlock();
|
||||
|
||||
// track the progress over a few seconds so we can estimate the search speed
|
||||
enum { SAMPLE_SEC = 20 };
|
||||
if (valid)
|
||||
{
|
||||
TProg tp = { (uint64_t) progtimer.nsecsElapsed(), *prog };
|
||||
proghist.push_front(tp);
|
||||
while (proghist.size() > 1 && proghist.back().ns < tp.ns - SAMPLE_SEC*1e9)
|
||||
proghist.pop_back();
|
||||
}
|
||||
|
||||
if (proghist.size() > 1 && proghist.front().ns > proghist.back().ns)
|
||||
{
|
||||
std::vector<qreal> samples;
|
||||
samples.reserve(proghist.size());
|
||||
auto it_prev = proghist.begin();
|
||||
auto it = it_prev;
|
||||
while (++it != proghist.end())
|
||||
{
|
||||
qreal dp = it_prev->prog - it->prog;
|
||||
qreal dt = 1e-9 * (it_prev->ns - it->ns);
|
||||
if (dt > 0)
|
||||
samples.push_back(dp / dt);
|
||||
it_prev = it;
|
||||
}
|
||||
std::sort(samples.begin(), samples.end());
|
||||
qreal speedtot = 0;
|
||||
qreal weightot = 1e-6;
|
||||
int n = (int) samples.size();
|
||||
int r = (int) (n / SAMPLE_SEC);
|
||||
int has_zeros = 0;
|
||||
for (int i = -r; i <= r; i++)
|
||||
{
|
||||
int j = n/2 + i;
|
||||
if (j < 0 || j >= n)
|
||||
continue;
|
||||
has_zeros += samples[j] == 0;
|
||||
speedtot += samples[j];
|
||||
weightot += 1.0;
|
||||
}
|
||||
*min = samples[n*1/4]; // lower quartile
|
||||
*avg = speedtot / weightot; // median
|
||||
*max = samples[n*3/4]; // upper quartile
|
||||
if (*avg && has_zeros)
|
||||
{ // probably a slow sampling regime, use whole range for estimate
|
||||
speedtot = 0;
|
||||
for (qreal s : samples)
|
||||
speedtot += s;
|
||||
*avg = speedtot / n;
|
||||
}
|
||||
}
|
||||
|
||||
qreal remain = ((qreal)*end - *prog) / (*avg + 1e-6);
|
||||
QString eta;
|
||||
if (remain >= 3600*24*1000)
|
||||
eta = "years";
|
||||
else if (remain > 0)
|
||||
{
|
||||
int s = (int) remain;
|
||||
if (s > 86400)
|
||||
eta = QString("%1d:%2").arg(s / 86400).arg((s % 86400) / 3600, 2, 10, QLatin1Char('0'));
|
||||
else if (s > 3600)
|
||||
eta = QString("%1h:%2").arg(s / 3600).arg((s % 3600) / 60, 2, 10, QLatin1Char('0'));
|
||||
else
|
||||
eta = QString("%1:%2").arg(s / 60).arg(s % 60, 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
*status = QString("seeds/sec: %1 min: %2 max: %3 isize: %4 eta: %5")
|
||||
.arg(getAbbrNum(*avg), -8)
|
||||
.arg(getAbbrNum(*min), -8)
|
||||
.arg(getAbbrNum(*max), -8)
|
||||
.arg(itemsize, -3)
|
||||
.arg(eta);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
@ -620,7 +842,7 @@ bool SearchMaster::requestItem(SearchWorker *item)
|
||||
QMutexLocker locker(&mutex);
|
||||
|
||||
// check if we should adjust the item size
|
||||
uint64_t nsec = timer.nsecsElapsed();
|
||||
uint64_t nsec = itemtimer.nsecsElapsed();
|
||||
count++;
|
||||
if (nsec > 0.1e9)
|
||||
{
|
||||
@ -628,7 +850,7 @@ bool SearchMaster::requestItem(SearchWorker *item)
|
||||
itemsize /= 2;
|
||||
if (count > 1e3 && itemsize < 0x10000)
|
||||
itemsize *= 2;
|
||||
timer.start();
|
||||
itemtimer.start();
|
||||
count = 0;
|
||||
}
|
||||
|
||||
@ -723,10 +945,16 @@ bool SearchMaster::requestItem(SearchWorker *item)
|
||||
return true;
|
||||
}
|
||||
|
||||
void SearchMaster::onWorkerResult(uint64_t seed)
|
||||
{
|
||||
emit searchResult(seed);
|
||||
}
|
||||
|
||||
void SearchMaster::onWorkerFinished()
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
if (workers.empty())
|
||||
return;
|
||||
for (SearchWorker *worker : workers)
|
||||
if (!worker->isFinished())
|
||||
return;
|
||||
|
@ -8,46 +8,72 @@
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
#include <QElapsedTimer>
|
||||
#include <QTimer>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <deque>
|
||||
|
||||
struct Session
|
||||
{
|
||||
void writeHeader(QTextStream& stream);
|
||||
bool save(QWidget *widget, QString fnam, bool quiet);
|
||||
bool load(QWidget *widget, QString fnam, bool quiet);
|
||||
|
||||
WorldInfo wi;
|
||||
SearchConfig sc;
|
||||
Gen48Config gen48;
|
||||
QVector<Condition> cv;
|
||||
std::vector<uint64_t> slist;
|
||||
};
|
||||
|
||||
class FormSearchControl;
|
||||
struct SearchWorker;
|
||||
|
||||
struct SearchMaster : QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SearchMaster(FormSearchControl *parent);
|
||||
SearchMaster(QWidget *parent);
|
||||
virtual ~SearchMaster();
|
||||
|
||||
bool set(WorldInfo wi, const SearchConfig& sc, const Gen48Config& gen48, const Config& config,
|
||||
std::vector<uint64_t>& slist, const QVector<Condition>& cv);
|
||||
bool set(QWidget *widget, const Session& s);
|
||||
|
||||
void presearch();
|
||||
void presearch(QObject *qtobj);
|
||||
|
||||
virtual void run() override;
|
||||
void stop();
|
||||
|
||||
// Determines the lowest seed/prog that is about to be processed.
|
||||
// (This is the point at which you would want to reload a previous search.)
|
||||
bool getProgress(uint64_t *prog, uint64_t *end, uint64_t *seed);
|
||||
// Get search progress:
|
||||
// status : progress status summary
|
||||
// prog : scheduled progress in search space
|
||||
// end : size of search space
|
||||
// seed : current seed to be processed
|
||||
// Get the search speed (provided it is called at regular intervals):
|
||||
// min,max : lower and upper search speed quartiles
|
||||
// avg : search speed average
|
||||
bool getProgress(QString *status, uint64_t *prog, uint64_t *end, uint64_t *seed, qreal *min, qreal *avg, qreal *max);
|
||||
|
||||
bool requestItem(SearchWorker *item);
|
||||
|
||||
public slots:
|
||||
void onWorkerResult(uint64_t seed);
|
||||
void onWorkerFinished();
|
||||
|
||||
signals:
|
||||
void searchResult(uint64_t seed);
|
||||
void searchFinish(bool done);
|
||||
|
||||
public:
|
||||
FormSearchControl * parent;
|
||||
struct TProg { uint64_t ns, prog; };
|
||||
|
||||
public:
|
||||
std::vector<SearchWorker*> workers;
|
||||
|
||||
QMutex mutex;
|
||||
std::atomic_bool abort;
|
||||
|
||||
QElapsedTimer timer;
|
||||
std::deque<TProg> proghist;
|
||||
QElapsedTimer progtimer;
|
||||
QElapsedTimer itemtimer;
|
||||
uint64_t count;
|
||||
|
||||
SearchThreadEnv env;
|
||||
@ -58,7 +84,7 @@ public:
|
||||
ConditionTree condtree;
|
||||
int itemsize; // number of seeds per search item
|
||||
int threadcnt; // numbr of worker threads
|
||||
Gen48Config gen48; // 48-bit generator settings
|
||||
Gen48Config gen48; // 48-bit generator settings
|
||||
std::vector<uint64_t> slist; // candidate list
|
||||
uint64_t idx; // index within candidate list
|
||||
uint64_t scnt; // search space size
|
||||
|
@ -37,7 +37,7 @@ StructureDialog::StructureDialog(QWidget *parent)
|
||||
icon->setPixmap(getMapIcon(opt));
|
||||
grid->addWidget(icon, i, j++);
|
||||
|
||||
QString name = struct2str(mapopt2stype(opt));
|
||||
QString name = mapopt2display(opt);
|
||||
QLabel *label = new QLabel(name + ":");
|
||||
grid->addWidget(label, i, j++);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "ui_tabbiomes.h"
|
||||
#include "cutil.h"
|
||||
#include "world.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
@ -18,7 +19,7 @@ void AnalysisBiomes::run()
|
||||
Generator g;
|
||||
setupGenerator(&g, wi.mc, wi.large);
|
||||
|
||||
for (idx = 0; idx < seeds.size(); idx++)
|
||||
for (idx = 0; idx < (long)seeds.size(); idx++)
|
||||
{
|
||||
if (stop) break;
|
||||
wi.seed = seeds[idx];
|
||||
@ -169,7 +170,7 @@ QVariant BiomeTableModel::headerData(int section, Qt::Orientation orientation, i
|
||||
if (section < ids.size())
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
return QVariant::fromValue(QString(biome2str(cmp.mc, ids[section])));
|
||||
return QVariant::fromValue(QString(getBiomeDisplay(cmp.mc, ids[section])));
|
||||
else
|
||||
return QVariant::fromValue(ids[section]);
|
||||
}
|
||||
@ -338,7 +339,6 @@ TabBiomes::TabBiomes(MainWindow *parent)
|
||||
//QHeaderView *header = ui->table->horizontalHeader();
|
||||
connect(header, &QHeaderView::sortIndicatorChanged, this, &TabBiomes::onTableSort);
|
||||
|
||||
ui->table->setFont(*gp_font_mono);
|
||||
ui->table->setSortingEnabled(true);
|
||||
|
||||
ui->treeLocate->setColumnWidth(0, 160);
|
||||
@ -363,10 +363,10 @@ TabBiomes::TabBiomes(MainWindow *parent)
|
||||
|
||||
for (int id = 0; id < 256; id++)
|
||||
{
|
||||
const char *s;
|
||||
if ((s = biome2str(MC_1_17, id)))
|
||||
QString s;
|
||||
if (!(s = getBiomeDisplay(MC_1_17, id)).isEmpty())
|
||||
str2biome[s] = id;
|
||||
if ((s = biome2str(MC_NEWEST, id)))
|
||||
if (!(s = getBiomeDisplay(MC_NEWEST, id)).isEmpty())
|
||||
str2biome[s] = id;
|
||||
}
|
||||
|
||||
@ -454,10 +454,10 @@ void TabBiomes::refreshBiomes(int activeid)
|
||||
std::sort(ids.begin(), ids.end(), cmp);
|
||||
ui->comboBiome->clear();
|
||||
for (int i : ids)
|
||||
ui->comboBiome->addItem(getBiomeIcon(i), biome2str(wi.mc, i), QVariant::fromValue(i));
|
||||
ui->comboBiome->addItem(getBiomeIcon(i), getBiomeDisplay(wi.mc, i), QVariant::fromValue(i));
|
||||
if (activeid >= 0)
|
||||
{
|
||||
int idx = ui->comboBiome->findText(biome2str(wi.mc, activeid));
|
||||
int idx = ui->comboBiome->findText(getBiomeDisplay(wi.mc, activeid));
|
||||
ui->comboBiome->setCurrentIndex(idx);
|
||||
}
|
||||
}
|
||||
@ -587,7 +587,7 @@ void TabBiomes::onBufferTimeout()
|
||||
qbufl.clear();
|
||||
}
|
||||
|
||||
QString progress = QString::asprintf(" (%d/%d)", thread.idx.load(), thread.seeds.size());
|
||||
QString progress = QString::asprintf(" (%ld/%zu)", thread.idx.load(), thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
|
||||
QApplication::processEvents(); // force processing of events so we can time correctly
|
||||
@ -613,7 +613,7 @@ void TabBiomes::on_pushStart_clicked()
|
||||
parent->getSeed(&thread.wi);
|
||||
thread.seeds.clear();
|
||||
if (ui->comboSeedSource->currentIndex() == 0)
|
||||
thread.seeds.append(thread.wi.seed);
|
||||
thread.seeds.push_back(thread.wi.seed);
|
||||
else
|
||||
thread.seeds = parent->formControl->getResults();
|
||||
|
||||
@ -650,7 +650,7 @@ void TabBiomes::on_pushStart_clicked()
|
||||
{
|
||||
QString msg = tr("The locate biome feature is limited to an area "
|
||||
"size smaller than the integer limit: (%1 x %2) > %3.");
|
||||
parent->warning(msg.arg(sx).arg(sz).arg(INT_MAX));
|
||||
warn(parent, msg.arg(sx).arg(sz).arg(INT_MAX));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -686,7 +686,7 @@ void TabBiomes::on_pushStart_clicked()
|
||||
|
||||
ui->pushExport->setEnabled(false);
|
||||
ui->pushStart->setChecked(true);
|
||||
QString progress = QString::asprintf(" (0/%d)", thread.seeds.size());
|
||||
QString progress = QString::asprintf(" (0/%zu)", thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
thread.start();
|
||||
}
|
||||
@ -716,7 +716,7 @@ void TabBiomes::on_pushExport_clicked()
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
parent->warning(tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -821,7 +821,7 @@ void TabBiomes::on_radioFullSample_toggled(bool checked)
|
||||
void TabBiomes::on_lineBiomeSize_textChanged(const QString &text)
|
||||
{
|
||||
double area = text.toInt();
|
||||
ui->labelBiomeSize->setText(QString::asprintf(tr("(%g sq. chunks)").toStdString().c_str(), area / 16));
|
||||
ui->labelBiomeSize->setText(tr("(%1 sq. chunks)").arg(area / 16));
|
||||
}
|
||||
|
||||
void TabBiomes::on_treeLocate_itemClicked(QTreeWidgetItem *item, int column)
|
||||
|
@ -32,10 +32,10 @@ signals:
|
||||
void seedItem(QTreeWidgetItem *item);
|
||||
|
||||
public:
|
||||
QVector<uint64_t> seeds;
|
||||
std::vector<uint64_t> seeds;
|
||||
WorldInfo wi;
|
||||
std::atomic_bool stop;
|
||||
std::atomic_int idx;
|
||||
std::atomic_long idx;
|
||||
int dims[3];
|
||||
struct Dat {
|
||||
int x1, z1, x2, z2;
|
||||
|
@ -412,6 +412,11 @@
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QTableView" name="table">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "ui_tabstructures.h"
|
||||
|
||||
#include "cutil.h"
|
||||
#include "message.h"
|
||||
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QFileDialog>
|
||||
@ -34,7 +35,7 @@ void AnalysisStructures::run()
|
||||
Generator g;
|
||||
setupGenerator(&g, wi.mc, wi.large);
|
||||
|
||||
for (idx = 0; idx < seeds.size(); idx++)
|
||||
for (idx = 0; idx < (long)seeds.size(); idx++)
|
||||
{
|
||||
if (stop) break;
|
||||
wi.seed = seeds[idx];
|
||||
@ -169,7 +170,7 @@ void AnalysisStructures::runStructs(Generator *g)
|
||||
return;
|
||||
}
|
||||
if (stop)
|
||||
seeditem->setText(0, QString::asprintf("%" PRId64, wi.seed) + " " + tr("(incomplete)"));
|
||||
seeditem->setText(0, QString::asprintf("%" PRId64, wi.seed) + " " + "(incomplete)");
|
||||
emit itemDone(seeditem);
|
||||
}
|
||||
|
||||
@ -192,9 +193,9 @@ void AnalysisStructures::runQuads(Generator *g)
|
||||
{
|
||||
QString label;
|
||||
if (qi.typ == Swamp_Hut)
|
||||
label = tr("quad-hut");
|
||||
label = "quad-hut";
|
||||
else
|
||||
label = tr("quad-monument");
|
||||
label = "quad-monument";
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(seeditem);
|
||||
|
||||
@ -363,7 +364,7 @@ void TabStructures::onBufferTimeout()
|
||||
ui->treeQuads->setSortingEnabled(true);
|
||||
qbufq.clear();
|
||||
}
|
||||
QString progress = QString::asprintf(" (%d/%d)", thread.idx.load(), thread.seeds.size());
|
||||
QString progress = QString::asprintf(" (%d/%zu)", thread.idx.load(), thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
|
||||
QApplication::processEvents(); // force processing of events so we can time correctly
|
||||
@ -411,7 +412,7 @@ void TabStructures::on_pushStart_clicked()
|
||||
parent->getSeed(&thread.wi);
|
||||
thread.seeds.clear();
|
||||
if (ui->comboSeedSource->currentIndex() == 0)
|
||||
thread.seeds.append(thread.wi.seed);
|
||||
thread.seeds.push_back(thread.wi.seed);
|
||||
else
|
||||
thread.seeds = parent->formControl->getResults();
|
||||
|
||||
@ -449,7 +450,7 @@ void TabStructures::on_pushStart_clicked()
|
||||
|
||||
ui->pushExport->setEnabled(false);
|
||||
ui->pushStart->setChecked(true);
|
||||
QString progress = QString::asprintf(" (0/%d)", thread.seeds.size());
|
||||
QString progress = QString::asprintf(" (0/%zu)", thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
thread.start();
|
||||
}
|
||||
@ -479,7 +480,7 @@ void TabStructures::on_pushExport_clicked()
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
parent->warning(tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ signals:
|
||||
void quadDone(QTreeWidgetItem *item);
|
||||
|
||||
public:
|
||||
QVector<uint64_t> seeds;
|
||||
std::vector<uint64_t> seeds;
|
||||
WorldInfo wi;
|
||||
std::atomic_bool stop;
|
||||
std::atomic_int idx;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "tabtriggers.h"
|
||||
#include "ui_tabtriggers.h"
|
||||
|
||||
#include "message.h"
|
||||
#include "cutil.h"
|
||||
#include "config.h"
|
||||
|
||||
@ -27,8 +28,9 @@ QTreeWidgetItem *setConditionTreeItems(ConditionTree& ctree, int node, int64_t s
|
||||
else
|
||||
{
|
||||
item = new QTreeWidgetItem(parent);
|
||||
QFont font = item->font(1);
|
||||
item->setText(0, "-");
|
||||
item->setText(1, c.summary());
|
||||
item->setText(1, c.summary(&font));
|
||||
|
||||
if ((p.x == -1 && p.z == -1) || c.type == F_LOGIC_NOT)
|
||||
posval = false;
|
||||
@ -54,7 +56,7 @@ void AnalysisTriggers::run()
|
||||
{
|
||||
stop = false;
|
||||
|
||||
for (idx = 0; idx < seeds.size(); idx++)
|
||||
for (idx = 0; idx < (long)seeds.size(); idx++)
|
||||
{
|
||||
if (stop) break;
|
||||
int64_t seed = seeds[idx];
|
||||
@ -113,7 +115,7 @@ TabTriggers::TabTriggers(MainWindow *parent)
|
||||
ui->treeWidget->setColumnWidth(3, 65);
|
||||
ui->treeWidget->setSortingEnabled(false); // sortable triggers are not necessary
|
||||
|
||||
connect(&thread, &AnalysisTriggers::warning, parent, &MainWindow::warning, Qt::BlockingQueuedConnection);
|
||||
connect(&thread, &AnalysisTriggers::warning, this, &TabTriggers::warning, Qt::BlockingQueuedConnection);
|
||||
connect(&thread, &AnalysisTriggers::itemDone, this, &TabTriggers::onAnalysisItemDone, Qt::BlockingQueuedConnection);
|
||||
connect(&thread, &AnalysisTriggers::finished, this, &TabTriggers::onAnalysisFinished);
|
||||
}
|
||||
@ -136,6 +138,11 @@ void TabTriggers::load(QSettings& settings)
|
||||
ui->comboSeedSource->setCurrentIndex(idx);
|
||||
}
|
||||
|
||||
int TabTriggers::warning(QString text, QMessageBox::StandardButtons buttons)
|
||||
{
|
||||
return warn(parent, text, buttons);
|
||||
}
|
||||
|
||||
void TabTriggers::onAnalysisItemDone(QTreeWidgetItem *item)
|
||||
{
|
||||
qbuf.push_back(item);
|
||||
@ -165,7 +172,7 @@ void TabTriggers::onBufferTimeout()
|
||||
ui->treeWidget->addTopLevelItems(qbuf);
|
||||
ui->treeWidget->setUpdatesEnabled(true);
|
||||
|
||||
QString progress = QString::asprintf(" (%d/%d)", thread.idx.load(), thread.seeds.size());
|
||||
QString progress = QString::asprintf(" (%ld/%zu)", thread.idx.load(), thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
|
||||
qbuf.clear();
|
||||
@ -194,7 +201,7 @@ void TabTriggers::on_pushStart_clicked()
|
||||
thread.conds = parent->formCond->getConditions();
|
||||
thread.seeds.clear();
|
||||
if (ui->comboSeedSource->currentIndex() == 0)
|
||||
thread.seeds.append(thread.wi.seed);
|
||||
thread.seeds.push_back(thread.wi.seed);
|
||||
else
|
||||
thread.seeds = parent->formControl->getResults();
|
||||
|
||||
@ -204,7 +211,7 @@ void TabTriggers::on_pushStart_clicked()
|
||||
|
||||
ui->pushExport->setEnabled(false);
|
||||
ui->pushStart->setChecked(true);
|
||||
QString progress = QString::asprintf(" (0/%d)", thread.seeds.size());
|
||||
QString progress = QString::asprintf(" (0/%zu)", thread.seeds.size());
|
||||
ui->pushStart->setText(tr("Stop") + progress);
|
||||
thread.start();
|
||||
}
|
||||
@ -263,7 +270,7 @@ void TabTriggers::on_pushExport_clicked()
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
parent->warning(tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
warn(parent, tr("Failed to open file for export:\n\"%1\"").arg(fnam));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,10 @@ signals:
|
||||
|
||||
public:
|
||||
QVector<Condition> conds;
|
||||
QVector<uint64_t> seeds;
|
||||
std::vector<uint64_t> seeds;
|
||||
WorldInfo wi;
|
||||
std::atomic_bool stop;
|
||||
std::atomic_int idx;
|
||||
std::atomic_long idx;
|
||||
};
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ public:
|
||||
virtual void load(QSettings& settings) override;
|
||||
|
||||
private slots:
|
||||
int warning(QString text, QMessageBox::StandardButtons buttons);
|
||||
void onAnalysisItemDone(QTreeWidgetItem *item);
|
||||
void onAnalysisFinished();
|
||||
void onBufferTimeout();
|
||||
|
@ -83,8 +83,8 @@ void replyFinished(QNetworkReply *reply, bool quiet)
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
NULL, QApplication::translate("UpdaterDialog", "New Version"),
|
||||
QApplication::translate("UpdaterDialog", "<p>A new version: <b>%1</b> is available.</p><p>Open the download page in browser?</p>").arg(newest),
|
||||
NULL, QObject::tr("New Version"),
|
||||
QObject::tr("<p>A new version: <b>%1</b> is available.</p><p>Open the download page in browser?</p>").arg(newest),
|
||||
QMessageBox::Yes|QMessageBox::No);
|
||||
|
||||
if (answer == QMessageBox::Yes)
|
||||
|
@ -23,30 +23,8 @@ const QPixmap& getMapIcon(int opt, VarPos *vp)
|
||||
if (!init)
|
||||
{
|
||||
init = true;
|
||||
icons[D_DESERT] = QPixmap(":/icons/desert.png");
|
||||
icons[D_JUNGLE] = QPixmap(":/icons/jungle.png");
|
||||
icons[D_IGLOO] = QPixmap(":/icons/igloo.png");
|
||||
icons[D_HUT] = QPixmap(":/icons/hut.png");
|
||||
icons[D_VILLAGE] = QPixmap(":/icons/village.png");
|
||||
icons[D_MANSION] = QPixmap(":/icons/mansion.png");
|
||||
icons[D_MONUMENT] = QPixmap(":/icons/monument.png");
|
||||
icons[D_RUINS] = QPixmap(":/icons/ruins.png");
|
||||
icons[D_SHIPWRECK] = QPixmap(":/icons/shipwreck.png");
|
||||
icons[D_TREASURE] = QPixmap(":/icons/treasure.png");
|
||||
icons[D_MINESHAFT] = QPixmap(":/icons/mineshaft.png");
|
||||
icons[D_WELL] = QPixmap(":/icons/well.png");
|
||||
icons[D_GEODE] = QPixmap(":/icons/geode.png");
|
||||
icons[D_OUTPOST] = QPixmap(":/icons/outpost.png");
|
||||
icons[D_ANCIENTCITY]= QPixmap(":/icons/ancient_city.png");
|
||||
icons[D_TRAIL] = QPixmap(":/icons/trail.png");
|
||||
icons[D_PORTAL] = QPixmap(":/icons/portal.png");
|
||||
icons[D_PORTALN] = QPixmap(":/icons/portal.png");
|
||||
icons[D_SPAWN] = QPixmap(":/icons/spawn.png");
|
||||
icons[D_STRONGHOLD] = QPixmap(":/icons/stronghold.png");
|
||||
icons[D_FORTESS] = QPixmap(":/icons/fortress.png");
|
||||
icons[D_BASTION] = QPixmap(":/icons/bastion.png");
|
||||
icons[D_ENDCITY] = QPixmap(":/icons/endcity.png");
|
||||
icons[D_GATEWAY] = QPixmap(":/icons/gateway.png");
|
||||
for (int sopt = D_DESERT; sopt <= D_STRONGHOLD; sopt++)
|
||||
icons[sopt] = QPixmap(QString(":/icons/") + mapopt2str(sopt) + ".png");
|
||||
iconzvil = QPixmap(":/icons/zombie.png");
|
||||
icongiant = QPixmap(":/icons/portal_giant.png");
|
||||
iconship = QPixmap(":/icons/end_ship.png");
|
||||
@ -903,8 +881,7 @@ QString QWorld::getBiomeName(Pos p)
|
||||
c += "." + QString::number(lopt.activeDisp());
|
||||
return c + "=" + QString::number(id);
|
||||
}
|
||||
const char *s = biome2str(wi.mc, id);
|
||||
QString ret = s ? s : "";
|
||||
QString ret = getBiomeDisplay(wi.mc, id);
|
||||
if (lopt.mode == LOPT_HEIGHT_4 && dim == DIM_OVERWORLD)
|
||||
ret = QString::asprintf("Y~%d ", estimateSurface(p)) + ret;
|
||||
return ret;
|
||||
@ -1169,7 +1146,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
|
||||
QFont oldfont = painter.font();
|
||||
QFont smallfont = oldfont;
|
||||
smallfont.setPointSize(8);
|
||||
smallfont.setPointSize(oldfont.pointSize() - 2);
|
||||
painter.setFont(smallfont);
|
||||
|
||||
int gridpix = 128;
|
||||
|
Loading…
Reference in New Issue
Block a user