Merge pull request #1108 from Scrumplex/better_texture_packs
This commit is contained in:
commit
c6bcb6228b
@ -320,6 +320,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/mod/ResourcePack.cpp
|
minecraft/mod/ResourcePack.cpp
|
||||||
minecraft/mod/ResourcePackFolderModel.h
|
minecraft/mod/ResourcePackFolderModel.h
|
||||||
minecraft/mod/ResourcePackFolderModel.cpp
|
minecraft/mod/ResourcePackFolderModel.cpp
|
||||||
|
minecraft/mod/TexturePack.h
|
||||||
|
minecraft/mod/TexturePack.cpp
|
||||||
minecraft/mod/TexturePackFolderModel.h
|
minecraft/mod/TexturePackFolderModel.h
|
||||||
minecraft/mod/TexturePackFolderModel.cpp
|
minecraft/mod/TexturePackFolderModel.cpp
|
||||||
minecraft/mod/ShaderPackFolderModel.h
|
minecraft/mod/ShaderPackFolderModel.h
|
||||||
@ -332,6 +334,8 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/mod/tasks/LocalModUpdateTask.cpp
|
minecraft/mod/tasks/LocalModUpdateTask.cpp
|
||||||
minecraft/mod/tasks/LocalResourcePackParseTask.h
|
minecraft/mod/tasks/LocalResourcePackParseTask.h
|
||||||
minecraft/mod/tasks/LocalResourcePackParseTask.cpp
|
minecraft/mod/tasks/LocalResourcePackParseTask.cpp
|
||||||
|
minecraft/mod/tasks/LocalTexturePackParseTask.h
|
||||||
|
minecraft/mod/tasks/LocalTexturePackParseTask.cpp
|
||||||
|
|
||||||
# Assets
|
# Assets
|
||||||
minecraft/AssetsUtils.h
|
minecraft/AssetsUtils.h
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
|
|
||||||
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
|
ModFolderModel::ModFolderModel(const QString &dir, bool is_indexed) : ResourceFolderModel(QDir(dir)), m_is_indexed(is_indexed)
|
||||||
{
|
{
|
||||||
FS::ensureFolderPathExists(m_dir.absolutePath());
|
|
||||||
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE };
|
m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::VERSION, SortType::DATE };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent) : QAbstractListModel(parent), m_dir(dir), m_watcher(this)
|
ResourceFolderModel::ResourceFolderModel(QDir dir, QObject* parent) : QAbstractListModel(parent), m_dir(dir), m_watcher(this)
|
||||||
{
|
{
|
||||||
|
FS::ensureFolderPathExists(m_dir.absolutePath());
|
||||||
|
|
||||||
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs);
|
||||||
m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
|
m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware);
|
||||||
|
|
||||||
|
64
launcher/minecraft/mod/TexturePack.cpp
Normal file
64
launcher/minecraft/mod/TexturePack.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TexturePack.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
#include "minecraft/mod/tasks/LocalTexturePackParseTask.h"
|
||||||
|
|
||||||
|
void TexturePack::setDescription(QString new_description)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_data_lock);
|
||||||
|
|
||||||
|
m_description = new_description;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TexturePack::setImage(QImage new_image)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_data_lock);
|
||||||
|
|
||||||
|
Q_ASSERT(!new_image.isNull());
|
||||||
|
|
||||||
|
if (m_pack_image_cache_key.key.isValid())
|
||||||
|
QPixmapCache::remove(m_pack_image_cache_key.key);
|
||||||
|
|
||||||
|
m_pack_image_cache_key.key = QPixmapCache::insert(QPixmap::fromImage(new_image));
|
||||||
|
m_pack_image_cache_key.was_ever_used = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap TexturePack::image(QSize size)
|
||||||
|
{
|
||||||
|
QPixmap cached_image;
|
||||||
|
if (QPixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
|
||||||
|
if (size.isNull())
|
||||||
|
return cached_image;
|
||||||
|
return cached_image.scaled(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No valid image we can get
|
||||||
|
if (!m_pack_image_cache_key.was_ever_used)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
// Imaged got evicted from the cache. Re-process it and retry.
|
||||||
|
TexturePackUtils::process(*this);
|
||||||
|
return image(size);
|
||||||
|
}
|
67
launcher/minecraft/mod/TexturePack.h
Normal file
67
launcher/minecraft/mod/TexturePack.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Resource.h"
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QPixmapCache>
|
||||||
|
|
||||||
|
class Version;
|
||||||
|
|
||||||
|
class TexturePack : public Resource {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
using Ptr = shared_qobject_ptr<Resource>;
|
||||||
|
|
||||||
|
TexturePack(QObject* parent = nullptr) : Resource(parent) {}
|
||||||
|
TexturePack(QFileInfo file_info) : Resource(file_info) {}
|
||||||
|
|
||||||
|
/** Gets the description of the texture pack. */
|
||||||
|
[[nodiscard]] QString description() const { return m_description; }
|
||||||
|
|
||||||
|
/** Gets the image of the texture pack, converted to a QPixmap for drawing, and scaled to size. */
|
||||||
|
[[nodiscard]] QPixmap image(QSize size);
|
||||||
|
|
||||||
|
/** Thread-safe. */
|
||||||
|
void setDescription(QString new_description);
|
||||||
|
|
||||||
|
/** Thread-safe. */
|
||||||
|
void setImage(QImage new_image);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
mutable QMutex m_data_lock;
|
||||||
|
|
||||||
|
/** The texture pack's description, as defined in the pack.txt file.
|
||||||
|
*/
|
||||||
|
QString m_description;
|
||||||
|
|
||||||
|
/** The texture pack's image file cache key, for access in the QPixmapCache global instance.
|
||||||
|
*
|
||||||
|
* The 'was_ever_used' state simply identifies whether the key was never inserted on the cache (true),
|
||||||
|
* so as to tell whether a cache entry is inexistent or if it was just evicted from the cache.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
QPixmapCache::Key key;
|
||||||
|
bool was_ever_used = false;
|
||||||
|
} m_pack_image_cache_key;
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
/*
|
/*
|
||||||
* PolyMC - Minecraft Launcher
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -35,4 +36,17 @@
|
|||||||
|
|
||||||
#include "TexturePackFolderModel.h"
|
#include "TexturePackFolderModel.h"
|
||||||
|
|
||||||
|
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
|
||||||
|
#include "minecraft/mod/tasks/LocalTexturePackParseTask.h"
|
||||||
|
|
||||||
TexturePackFolderModel::TexturePackFolderModel(const QString &dir) : ResourceFolderModel(QDir(dir)) {}
|
TexturePackFolderModel::TexturePackFolderModel(const QString &dir) : ResourceFolderModel(QDir(dir)) {}
|
||||||
|
|
||||||
|
Task* TexturePackFolderModel::createUpdateTask()
|
||||||
|
{
|
||||||
|
return new BasicFolderLoadTask(m_dir, [](QFileInfo const& entry) { return new TexturePack(entry); });
|
||||||
|
}
|
||||||
|
|
||||||
|
Task* TexturePackFolderModel::createParseTask(Resource& resource)
|
||||||
|
{
|
||||||
|
return new LocalTexturePackParseTask(m_next_resolution_ticket, static_cast<TexturePack&>(resource));
|
||||||
|
}
|
||||||
|
@ -1,3 +1,39 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This file incorporates work covered by the following copyright and
|
||||||
|
* permission notice:
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 MultiMC Contributors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ResourceFolderModel.h"
|
#include "ResourceFolderModel.h"
|
||||||
@ -8,4 +44,6 @@ class TexturePackFolderModel : public ResourceFolderModel
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TexturePackFolderModel(const QString &dir);
|
explicit TexturePackFolderModel(const QString &dir);
|
||||||
|
[[nodiscard]] Task* createUpdateTask() override;
|
||||||
|
[[nodiscard]] Task* createParseTask(Resource&) override;
|
||||||
};
|
};
|
||||||
|
155
launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
Normal file
155
launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LocalTexturePackParseTask.h"
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#include <quazip/quazip.h>
|
||||||
|
#include <quazip/quazipfile.h>
|
||||||
|
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
namespace TexturePackUtils {
|
||||||
|
|
||||||
|
bool process(TexturePack& pack)
|
||||||
|
{
|
||||||
|
switch (pack.type()) {
|
||||||
|
case ResourceType::FOLDER:
|
||||||
|
TexturePackUtils::processFolder(pack);
|
||||||
|
return true;
|
||||||
|
case ResourceType::ZIPFILE:
|
||||||
|
TexturePackUtils::processZIP(pack);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
qWarning() << "Invalid type for resource pack parse task!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processFolder(TexturePack& pack)
|
||||||
|
{
|
||||||
|
Q_ASSERT(pack.type() == ResourceType::FOLDER);
|
||||||
|
|
||||||
|
QFileInfo mcmeta_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.txt"));
|
||||||
|
if (mcmeta_file_info.isFile()) {
|
||||||
|
QFile mcmeta_file(mcmeta_file_info.filePath());
|
||||||
|
if (!mcmeta_file.open(QIODevice::ReadOnly))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto data = mcmeta_file.readAll();
|
||||||
|
|
||||||
|
TexturePackUtils::processPackTXT(pack, std::move(data));
|
||||||
|
|
||||||
|
mcmeta_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
|
||||||
|
if (image_file_info.isFile()) {
|
||||||
|
QFile mcmeta_file(image_file_info.filePath());
|
||||||
|
if (!mcmeta_file.open(QIODevice::ReadOnly))
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto data = mcmeta_file.readAll();
|
||||||
|
|
||||||
|
TexturePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
|
||||||
|
mcmeta_file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processZIP(TexturePack& pack)
|
||||||
|
{
|
||||||
|
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
|
||||||
|
|
||||||
|
QuaZip zip(pack.fileinfo().filePath());
|
||||||
|
if (!zip.open(QuaZip::mdUnzip))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QuaZipFile file(&zip);
|
||||||
|
|
||||||
|
if (zip.setCurrentFile("pack.txt")) {
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical() << "Failed to open file in zip.";
|
||||||
|
zip.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = file.readAll();
|
||||||
|
|
||||||
|
TexturePackUtils::processPackTXT(pack, std::move(data));
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zip.setCurrentFile("pack.png")) {
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical() << "Failed to open file in zip.";
|
||||||
|
zip.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = file.readAll();
|
||||||
|
|
||||||
|
TexturePackUtils::processPackPNG(pack, std::move(data));
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
zip.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void processPackTXT(TexturePack& pack, QByteArray&& raw_data)
|
||||||
|
{
|
||||||
|
pack.setDescription(QString(raw_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void processPackPNG(TexturePack& pack, QByteArray&& raw_data)
|
||||||
|
{
|
||||||
|
auto img = QImage::fromData(raw_data);
|
||||||
|
if (!img.isNull()) {
|
||||||
|
pack.setImage(img);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Failed to parse pack.png.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace TexturePackUtils
|
||||||
|
|
||||||
|
LocalTexturePackParseTask::LocalTexturePackParseTask(int token, TexturePack& rp)
|
||||||
|
: Task(nullptr, false), m_token(token), m_texture_pack(rp)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool LocalTexturePackParseTask::abort()
|
||||||
|
{
|
||||||
|
m_aborted = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalTexturePackParseTask::executeTask()
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_texture_pack.valid());
|
||||||
|
|
||||||
|
if (!TexturePackUtils::process(m_texture_pack))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_aborted)
|
||||||
|
emitAborted();
|
||||||
|
else
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
57
launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
Normal file
57
launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "minecraft/mod/TexturePack.h"
|
||||||
|
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
|
||||||
|
namespace TexturePackUtils {
|
||||||
|
bool process(TexturePack& pack);
|
||||||
|
|
||||||
|
void processZIP(TexturePack& pack);
|
||||||
|
void processFolder(TexturePack& pack);
|
||||||
|
|
||||||
|
void processPackTXT(TexturePack& pack, QByteArray&& raw_data);
|
||||||
|
void processPackPNG(TexturePack& pack, QByteArray&& raw_data);
|
||||||
|
} // namespace TexturePackUtils
|
||||||
|
|
||||||
|
class LocalTexturePackParseTask : public Task {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
LocalTexturePackParseTask(int token, TexturePack& rp);
|
||||||
|
|
||||||
|
[[nodiscard]] bool canAbort() const override { return true; }
|
||||||
|
bool abort() override;
|
||||||
|
|
||||||
|
void executeTask() override;
|
||||||
|
|
||||||
|
[[nodiscard]] int token() const { return m_token; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_token;
|
||||||
|
|
||||||
|
TexturePack& m_texture_pack;
|
||||||
|
|
||||||
|
bool m_aborted = false;
|
||||||
|
};
|
@ -39,6 +39,7 @@
|
|||||||
#include "ui_ExternalResourcesPage.h"
|
#include "ui_ExternalResourcesPage.h"
|
||||||
|
|
||||||
#include "minecraft/mod/TexturePackFolderModel.h"
|
#include "minecraft/mod/TexturePackFolderModel.h"
|
||||||
|
#include "minecraft/mod/TexturePack.h"
|
||||||
|
|
||||||
class TexturePackPage : public ExternalResourcesPage
|
class TexturePackPage : public ExternalResourcesPage
|
||||||
{
|
{
|
||||||
@ -60,4 +61,15 @@ public:
|
|||||||
{
|
{
|
||||||
return m_instance->traits().contains("texturepacks");
|
return m_instance->traits().contains("texturepacks");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override
|
||||||
|
{
|
||||||
|
auto sourceCurrent = m_filterModel->mapToSource(current);
|
||||||
|
int row = sourceCurrent.row();
|
||||||
|
auto& rp = static_cast<TexturePack&>(m_model->at(row));
|
||||||
|
ui->frame->updateWithTexturePack(rp);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -105,10 +105,7 @@ static const QMap<QChar, QString> s_value_to_color = {
|
|||||||
{'f', "#FFFFFF"}
|
{'f', "#FFFFFF"}
|
||||||
};
|
};
|
||||||
|
|
||||||
void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack)
|
QString InfoFrame::renderColorCodes(QString input) {
|
||||||
{
|
|
||||||
setName(resource_pack.name());
|
|
||||||
|
|
||||||
// We have to manually set the colors for use.
|
// We have to manually set the colors for use.
|
||||||
//
|
//
|
||||||
// A color is set using §x, with x = a hex number from 0 to f.
|
// A color is set using §x, with x = a hex number from 0 to f.
|
||||||
@ -119,39 +116,49 @@ void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack)
|
|||||||
// TODO: Make the same logic for font formatting too.
|
// TODO: Make the same logic for font formatting too.
|
||||||
// TODO: Wrap links inside <a> tags
|
// TODO: Wrap links inside <a> tags
|
||||||
|
|
||||||
auto description = resource_pack.description();
|
QString html("<html>");
|
||||||
|
|
||||||
QString description_parsed("<html>");
|
|
||||||
bool in_div = false;
|
bool in_div = false;
|
||||||
|
|
||||||
auto desc_it = description.constBegin();
|
auto it = input.constBegin();
|
||||||
while (desc_it != description.constEnd()) {
|
while (it != input.constEnd()) {
|
||||||
if (*desc_it == u'§') {
|
if (*it == u'§') {
|
||||||
if (in_div)
|
if (in_div)
|
||||||
description_parsed += "</span>";
|
html += "</span>";
|
||||||
|
|
||||||
auto const& num = *(++desc_it);
|
auto const& num = *(++it);
|
||||||
description_parsed += QString("<span style=\"color: %1;\">").arg(s_value_to_color.constFind(num).value());
|
html += QString("<span style=\"color: %1;\">").arg(s_value_to_color.constFind(num).value());
|
||||||
|
|
||||||
in_div = true;
|
in_div = true;
|
||||||
|
|
||||||
desc_it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
description_parsed += *desc_it;
|
html += *it;
|
||||||
desc_it++;
|
it++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_div)
|
if (in_div)
|
||||||
description_parsed += "</span>";
|
html += "</span>";
|
||||||
description_parsed += "</html>";
|
html += "</html>";
|
||||||
|
|
||||||
description_parsed.replace("\n", "<br>");
|
html.replace("\n", "<br>");
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
setDescription(description_parsed);
|
void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack)
|
||||||
|
{
|
||||||
|
setName(resource_pack.name());
|
||||||
|
setDescription(renderColorCodes(resource_pack.description()));
|
||||||
setImage(resource_pack.image({64, 64}));
|
setImage(resource_pack.image({64, 64}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InfoFrame::updateWithTexturePack(TexturePack& texture_pack)
|
||||||
|
{
|
||||||
|
setName(texture_pack.name());
|
||||||
|
setDescription(renderColorCodes(texture_pack.description()));
|
||||||
|
setImage(texture_pack.image({64, 64}));
|
||||||
|
}
|
||||||
|
|
||||||
void InfoFrame::clear()
|
void InfoFrame::clear()
|
||||||
{
|
{
|
||||||
setName();
|
setName();
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "minecraft/mod/Mod.h"
|
#include "minecraft/mod/Mod.h"
|
||||||
#include "minecraft/mod/ResourcePack.h"
|
#include "minecraft/mod/ResourcePack.h"
|
||||||
|
#include "minecraft/mod/TexturePack.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -41,6 +42,9 @@ class InfoFrame : public QFrame {
|
|||||||
void updateWithMod(Mod const& m);
|
void updateWithMod(Mod const& m);
|
||||||
void updateWithResource(Resource const& resource);
|
void updateWithResource(Resource const& resource);
|
||||||
void updateWithResourcePack(ResourcePack& rp);
|
void updateWithResourcePack(ResourcePack& rp);
|
||||||
|
void updateWithTexturePack(TexturePack& tp);
|
||||||
|
|
||||||
|
static QString renderColorCodes(QString input);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void descriptionEllipsisHandler(QString link);
|
void descriptionEllipsisHandler(QString link);
|
||||||
|
@ -24,6 +24,9 @@ ecm_add_test(ResourceFolderModel_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_V
|
|||||||
ecm_add_test(ResourcePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
ecm_add_test(ResourcePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||||
TEST_NAME ResourcePackParse)
|
TEST_NAME ResourcePackParse)
|
||||||
|
|
||||||
|
ecm_add_test(TexturePackParse_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||||
|
TEST_NAME TexturePackParse)
|
||||||
|
|
||||||
ecm_add_test(ParseUtils_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
ecm_add_test(ParseUtils_test.cpp LINK_LIBRARIES Launcher_logic Qt${QT_VERSION_MAJOR}::Test
|
||||||
TEST_NAME ParseUtils)
|
TEST_NAME ParseUtils)
|
||||||
|
|
||||||
|
@ -146,7 +146,6 @@ slots:
|
|||||||
for (auto mod : model.allMods())
|
for (auto mod : model.allMods())
|
||||||
qDebug() << mod->name();
|
qDebug() << mod->name();
|
||||||
|
|
||||||
// FIXME: It considers every file in the directory as a mod, but we should probably filter that out somehow.
|
|
||||||
QCOMPARE(model.size(), 4);
|
QCOMPARE(model.size(), 4);
|
||||||
|
|
||||||
model.stopWatching();
|
model.stopWatching();
|
||||||
|
71
tests/TexturePackParse_test.cpp
Normal file
71
tests/TexturePackParse_test.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
/*
|
||||||
|
* PolyMC - Minecraft Launcher
|
||||||
|
* Copyright (c) 2022 flowln <flowlnlnln@gmail.com>
|
||||||
|
* Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QTest>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
|
#include "minecraft/mod/TexturePack.h"
|
||||||
|
#include "minecraft/mod/tasks/LocalTexturePackParseTask.h"
|
||||||
|
|
||||||
|
class TexturePackParseTest : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void test_parseZIP()
|
||||||
|
{
|
||||||
|
QString source = QFINDTESTDATA("testdata/TexturePackParse");
|
||||||
|
|
||||||
|
QString zip_rp = FS::PathCombine(source, "test_texture_pack_idk.zip");
|
||||||
|
TexturePack pack { QFileInfo(zip_rp) };
|
||||||
|
|
||||||
|
TexturePackUtils::processZIP(pack);
|
||||||
|
|
||||||
|
QVERIFY(pack.description() == "joe biden, wake up");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_parseFolder()
|
||||||
|
{
|
||||||
|
QString source = QFINDTESTDATA("testdata/TexturePackParse");
|
||||||
|
|
||||||
|
QString folder_rp = FS::PathCombine(source, "test_texturefolder");
|
||||||
|
TexturePack pack { QFileInfo(folder_rp) };
|
||||||
|
|
||||||
|
TexturePackUtils::processFolder(pack);
|
||||||
|
|
||||||
|
QVERIFY(pack.description() == "Some texture pack surely");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_parseFolder2()
|
||||||
|
{
|
||||||
|
QString source = QFINDTESTDATA("testdata/TexturePackParse");
|
||||||
|
|
||||||
|
QString folder_rp = FS::PathCombine(source, "another_test_texturefolder");
|
||||||
|
TexturePack pack { QFileInfo(folder_rp) };
|
||||||
|
|
||||||
|
TexturePackUtils::process(pack);
|
||||||
|
|
||||||
|
QVERIFY(pack.description() == "quieres\nfor real");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(TexturePackParseTest)
|
||||||
|
|
||||||
|
#include "TexturePackParse_test.moc"
|
BIN
tests/testdata/TexturePackParse/another_test_texturefolder/pack.txt
vendored
Normal file
BIN
tests/testdata/TexturePackParse/another_test_texturefolder/pack.txt
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/TexturePackParse/test_texture_pack_idk.zip
vendored
Normal file
BIN
tests/testdata/TexturePackParse/test_texture_pack_idk.zip
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/TexturePackParse/test_texturefolder/assets/minecraft/textures/blah.txt
vendored
Normal file
BIN
tests/testdata/TexturePackParse/test_texturefolder/assets/minecraft/textures/blah.txt
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/TexturePackParse/test_texturefolder/pack.txt
vendored
Normal file
BIN
tests/testdata/TexturePackParse/test_texturefolder/pack.txt
vendored
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user