diff options
Diffstat (limited to '')
-rw-r--r-- | Tools/QtBiomeVisualiser/MainWindow.cpp | 259 |
1 files changed, 235 insertions, 24 deletions
diff --git a/Tools/QtBiomeVisualiser/MainWindow.cpp b/Tools/QtBiomeVisualiser/MainWindow.cpp index 65d0ccf5e..eb45690c1 100644 --- a/Tools/QtBiomeVisualiser/MainWindow.cpp +++ b/Tools/QtBiomeVisualiser/MainWindow.cpp @@ -5,19 +5,34 @@ #include <QMenuBar> #include <QApplication> #include <QFileDialog> +#include <QSettings> +#include <QDirIterator> #include "inifile/iniFile.h" #include "ChunkSource.h" -#include "Generating/BioGen.h" +#include "src/Generating/BioGen.h" +#include "src/StringCompression.h" +#include "src/WorldStorage/FastNBT.h" +#include "GeneratorSetup.h" MainWindow::MainWindow(QWidget * parent) : - QMainWindow(parent) + QMainWindow(parent), + m_GeneratorSetup(nullptr), + m_LineSeparator(nullptr) { - m_BiomeView = new BiomeView(this); - setCentralWidget(m_BiomeView); + initMinecraftPath(); + + m_BiomeView = new BiomeView(); + m_MainLayout = new QHBoxLayout(); + m_MainLayout->addWidget(m_BiomeView, 1); + m_MainLayout->setMenuBar(menuBar()); + m_MainLayout->setMargin(0); + QWidget * central = new QWidget(); + central->setLayout(m_MainLayout); + setCentralWidget(central); createActions(); createMenus(); @@ -36,10 +51,35 @@ MainWindow::~MainWindow() -void MainWindow::generate() +void MainWindow::newGenerator() { + // (Re-)open the generator setup dialog with empty settings: + openGeneratorSetup(""); + + // Set the chunk source: + cIniFilePtr iniFile = m_GeneratorSetup->getIniFile(); + m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(iniFile))); + m_BiomeView->redraw(); +} + + + + + +void MainWindow::openGenerator() +{ + // Let the user specify the world.ini file: QString worldIni = QFileDialog::getOpenFileName(this, tr("Open world.ini"), QString(), tr("world.ini (world.ini)")); - m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(worldIni))); + if (worldIni.isEmpty()) + { + return; + } + + // (Re-)open the generator setup dialog: + openGeneratorSetup(worldIni.toStdString()); + + // Set the chunk source: + m_BiomeView->setChunkSource(std::shared_ptr<BioGenSource>(new BioGenSource(m_GeneratorSetup->getIniFile()))); m_BiomeView->redraw(); } @@ -47,9 +87,58 @@ void MainWindow::generate() -void MainWindow::open() +void MainWindow::openWorld() { - // TODO + // Let the user specify the world: + QString regionFolder = QFileDialog::getExistingDirectory(this, tr("Select the region folder"), QString()); + if (regionFolder.isEmpty()) + { + return; + } + + // Remove the generator setup dialog, if open: + closeGeneratorSetup(); + + // Set the chunk source: + m_BiomeView->setChunkSource(std::shared_ptr<AnvilSource>(new AnvilSource(regionFolder))); + m_BiomeView->redraw(); +} + + + + + +void MainWindow::openVanillaWorld() +{ + // The world is stored in the sender action's data, retrieve it: + QAction * action = qobject_cast<QAction *>(sender()); + if (action == nullptr) + { + return; + } + + // Remove the generator setup dialog, if open: + closeGeneratorSetup(); + + // Set the chunk source: + m_BiomeView->setChunkSource(std::shared_ptr<AnvilSource>(new AnvilSource(action->data().toString()))); + m_BiomeView->redraw(); +} + + + + + +void MainWindow::initMinecraftPath() +{ + #ifdef Q_OS_MAC + m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/Library/Application Support/minecraft"); + #elif defined Q_OS_WIN32 + QSettings ini(QSettings::IniFormat, QSettings::UserScope, ".minecraft", "minecraft1"); + m_MinecraftPath = QFileInfo(ini.fileName()).absolutePath(); + #else + m_MinecraftPath = QDir::homePath() + QDir::toNativeSeparators("/.minecraft"); + #endif } @@ -58,19 +147,26 @@ void MainWindow::open() void MainWindow::createActions() { - m_actGen = new QAction(tr("&Generate..."), this); - m_actGen->setShortcut(tr("Ctrl+N")); - m_actGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); - connect(m_actGen, SIGNAL(triggered()), this, SLOT(generate())); + createWorldActions(); + + m_actNewGen = new QAction(tr("&New generator"), this); + m_actNewGen->setShortcut(tr("Ctrl+N")); + m_actNewGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); + connect(m_actNewGen, SIGNAL(triggered()), this, SLOT(newGenerator())); - m_actOpen = new QAction(tr("&Open world..."), this); - m_actOpen->setShortcut(tr("Ctrl+O")); - m_actOpen->setStatusTip(tr("Open an existing world and display its biomes")); - connect(m_actOpen, SIGNAL(triggered()), this, SLOT(open())); + m_actOpenGen = new QAction(tr("&Open generator..."), this); + m_actOpenGen->setShortcut(tr("Ctrl+G")); + m_actOpenGen->setStatusTip(tr("Open a generator INI file and display the generated biomes")); + connect(m_actOpenGen, SIGNAL(triggered()), this, SLOT(openGenerator())); + + m_actOpenWorld = new QAction(tr("&Open world..."), this); + m_actOpenWorld->setShortcut(tr("Ctrl+O")); + m_actOpenWorld->setStatusTip(tr("Open an existing world and display its biomes")); + connect(m_actOpenWorld, SIGNAL(triggered()), this, SLOT(openWorld())); m_actReload = new QAction(tr("&Reload"), this); m_actReload->setShortcut(tr("F5")); - m_actReload->setStatusTip(tr("Open an existing world and display its biomes")); + m_actReload->setStatusTip(tr("Clear the view cache and force a reload of all the data")); connect(m_actReload, SIGNAL(triggered()), m_BiomeView, SLOT(reload())); m_actExit = new QAction(tr("E&xit"), this); @@ -83,15 +179,130 @@ void MainWindow::createActions() +void MainWindow::createWorldActions() +{ + QDir mc(m_MinecraftPath); + if (!mc.cd("saves")) + { + return; + } + + QDirIterator it(mc); + int key = 1; + while (it.hasNext()) + { + it.next(); + if (!it.fileInfo().isDir()) + { + continue; + } + QString name = getWorldName(it.filePath().toStdString()); + if (name.isEmpty()) + { + continue; + } + QAction * w = new QAction(this); + w->setText(name); + w->setData(it.filePath() + "/region"); + if (key < 10) + { + w->setShortcut("Ctrl+" + QString::number(key)); + key++; + } + connect(w, SIGNAL(triggered()), this, SLOT(openVanillaWorld())); + m_WorldActions.append(w); + } +} + + + + + void MainWindow::createMenus() { - QMenu * mFile = menuBar()->addMenu(tr("&World")); - mFile->addAction(m_actGen); - mFile->addAction(m_actOpen); - mFile->addSeparator(); - mFile->addAction(m_actReload); - mFile->addSeparator(); - mFile->addAction(m_actExit); + QMenu * file = menuBar()->addMenu(tr("&Map")); + file->addAction(m_actNewGen); + file->addAction(m_actOpenGen); + file->addSeparator(); + QMenu * worlds = file->addMenu(tr("Open existing")); + worlds->addActions(m_WorldActions); + if (m_WorldActions.empty()) + { + worlds->setEnabled(false); + } + file->addAction(m_actOpenWorld); + file->addSeparator(); + file->addAction(m_actReload); + file->addSeparator(); + file->addAction(m_actExit); +} + + + + + +QString MainWindow::getWorldName(const AString & a_Path) +{ + AString levelData = cFile::ReadWholeFile(a_Path + "/level.dat"); + if (levelData.empty()) + { + // No such file / no data + return QString(); + } + + AString uncompressed; + if (UncompressStringGZIP(levelData.data(), levelData.size(), uncompressed) != Z_OK) + { + return QString(); + } + cParsedNBT nbt(uncompressed.data(), uncompressed.size()); + if (!nbt.IsValid()) + { + return QString(); + } + AString name = nbt.GetName(1); + int levelNameTag = nbt.FindTagByPath(nbt.GetRoot(), "Data\\LevelName"); + if ((levelNameTag <= 0) || (nbt.GetType(levelNameTag) != TAG_String)) + { + return QString(); + } + return QString::fromStdString(nbt.GetString(levelNameTag)); +} + + + + + +void MainWindow::openGeneratorSetup(const AString & a_IniFileName) +{ + // Close any previous editor: + closeGeneratorSetup(); + + // Open up a new editor: + m_GeneratorSetup = new GeneratorSetup(a_IniFileName); + m_LineSeparator = new QWidget(); + m_LineSeparator->setFixedWidth(2); + m_LineSeparator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); + m_LineSeparator->setStyleSheet(QString("background-color: #c0c0c0;")); + m_MainLayout->addWidget(m_LineSeparator); + m_MainLayout->addWidget(m_GeneratorSetup); + + // Connect the signals from the setup pane: + connect(m_GeneratorSetup, SIGNAL(generatorUpdated()), m_BiomeView, SLOT(reload())); +} + + + + + +void MainWindow::closeGeneratorSetup() +{ + delete m_MainLayout->takeAt(2); + delete m_MainLayout->takeAt(1); + delete m_GeneratorSetup; + delete m_LineSeparator; + m_GeneratorSetup = nullptr; + m_LineSeparator = nullptr; } |