Noggit is now able to write DBC.
Add Map Creation Wizard ui.
This commit is contained in:
@@ -5,6 +5,19 @@
|
||||
#include <noggit/MPQ.h>
|
||||
|
||||
#include <string>
|
||||
#include <QSettings>
|
||||
#include <QDir>
|
||||
#include <fstream>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
template<typename T> inline
|
||||
auto write(std::ostream& stream, T const& val) -> void
|
||||
{
|
||||
stream.write(reinterpret_cast<char const*>(&val), sizeof(T));
|
||||
}
|
||||
|
||||
DBCFile::DBCFile(const std::string& _filename)
|
||||
: filename(_filename)
|
||||
@@ -43,3 +56,115 @@ void DBCFile::open()
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
||||
void DBCFile::save()
|
||||
{
|
||||
QSettings app_settings;
|
||||
QString str = app_settings.value ("project/path").toString();
|
||||
if (!(str.endsWith('\\') || str.endsWith('/')))
|
||||
{
|
||||
str += "/";
|
||||
}
|
||||
|
||||
std::string filename_proj = noggit::mpq::normalized_filename(str.toStdString() + filename);
|
||||
QDir dir(str + "/DBFilesClient/");
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
|
||||
std::ofstream stream(filename_proj, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
|
||||
|
||||
stream << 'W' << 'D' << 'B' << 'C';
|
||||
|
||||
|
||||
write(stream, recordCount);
|
||||
write(stream, fieldCount);
|
||||
write(stream, recordSize);
|
||||
write(stream, stringSize);
|
||||
|
||||
stream.write(reinterpret_cast<char*>(data.data()), data.size());
|
||||
stream.write(stringTable.data(), stringSize);
|
||||
stream.close();
|
||||
}
|
||||
|
||||
DBCFile::Record DBCFile::addRecord(size_t id, size_t id_field)
|
||||
{
|
||||
recordCount++;
|
||||
|
||||
for (Iterator i = begin(); i != end(); ++i)
|
||||
{
|
||||
if (i->getUInt(id_field) == id)
|
||||
throw AlreadyExists();
|
||||
}
|
||||
|
||||
size_t old_size = data.size();
|
||||
data.resize(old_size + recordSize);
|
||||
*reinterpret_cast<unsigned int*>(data.data() + old_size + id_field * sizeof(std::uint32_t)) = id;
|
||||
|
||||
return Record(*this, data.data() + old_size);
|
||||
}
|
||||
|
||||
DBCFile::Record DBCFile::addRecordCopy(size_t id, size_t id_from, size_t id_field)
|
||||
{
|
||||
recordCount++;
|
||||
|
||||
bool from_found = false;
|
||||
size_t from_idx = 0;
|
||||
|
||||
for (Iterator i = begin(); i != end(); ++i)
|
||||
{
|
||||
if (i->getUInt(id_field) == id)
|
||||
throw AlreadyExists();
|
||||
|
||||
if (i->getUInt(id_field) == id_from)
|
||||
{
|
||||
from_found = true;
|
||||
}
|
||||
|
||||
if (!from_found)
|
||||
{
|
||||
from_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!from_found)
|
||||
{
|
||||
throw NotFound();
|
||||
}
|
||||
|
||||
size_t old_size = data.size();
|
||||
data.resize(old_size + recordSize);
|
||||
|
||||
Record record_from = getRecord(from_idx);
|
||||
std::copy(data.data() + from_idx * recordSize, data.data() + from_idx * recordSize + recordSize, data.data() + old_size);
|
||||
*reinterpret_cast<unsigned int*>(data.data() + old_size + id_field * sizeof(std::uint32_t)) = id;
|
||||
|
||||
return Record(*this, data.data() + old_size);
|
||||
}
|
||||
|
||||
void DBCFile::removeRecord(size_t id, size_t id_field)
|
||||
{
|
||||
recordCount--;
|
||||
size_t counter = 0;
|
||||
|
||||
for (Iterator i = begin(); i != end(); ++i)
|
||||
{
|
||||
if (i->getUInt(id_field) == id)
|
||||
{
|
||||
size_t initial_size = data.size();
|
||||
|
||||
unsigned char* record = data.data() + counter * recordSize;
|
||||
std::memmove(record, record + recordSize, recordSize * (recordCount - counter + 1));
|
||||
data.resize(initial_size - recordSize);
|
||||
return;
|
||||
}
|
||||
|
||||
counter++;
|
||||
|
||||
}
|
||||
|
||||
throw NotFound();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
class DBCFile
|
||||
{
|
||||
@@ -14,11 +16,19 @@ public:
|
||||
|
||||
// Open database. It must be openened before it can be used.
|
||||
void open();
|
||||
void save();
|
||||
|
||||
class NotFound : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
NotFound() : std::runtime_error("Key was not found")
|
||||
NotFound() : std::runtime_error("Key was not found.")
|
||||
{ }
|
||||
};
|
||||
|
||||
class AlreadyExists : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
AlreadyExists() : std::runtime_error("Key already exists.")
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -26,35 +36,35 @@ public:
|
||||
class Record
|
||||
{
|
||||
public:
|
||||
const float& getFloat(size_t field) const
|
||||
float& getFloat(size_t field)
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
return *reinterpret_cast<float*>(offset + field * 4);
|
||||
}
|
||||
const unsigned int& getUInt(size_t field) const
|
||||
unsigned int& getUInt(size_t field)
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
return *reinterpret_cast<unsigned int*>(offset + field * 4);
|
||||
}
|
||||
const int& getInt(size_t field) const
|
||||
int& getInt(size_t field)
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
return *reinterpret_cast<int*>(offset + field * 4);
|
||||
}
|
||||
const char *getString(size_t field) const
|
||||
char *getString(size_t field)
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
size_t stringOffset = getUInt(field);
|
||||
assert(stringOffset < file.stringSize);
|
||||
return file.stringTable.data() + stringOffset;
|
||||
}
|
||||
const char *getLocalizedString(size_t field, int locale = -1) const
|
||||
char *getLocalizedString(size_t field, int locale = -1)
|
||||
{
|
||||
int loc = locale;
|
||||
if (locale == -1)
|
||||
{
|
||||
assert(field < file.fieldCount - 8);
|
||||
for (loc = 0; loc < 9; loc++)
|
||||
for (loc = 0; loc < 16; loc++)
|
||||
{
|
||||
size_t stringOffset = getUInt(field + loc);
|
||||
if (stringOffset != 0)
|
||||
@@ -67,9 +77,38 @@ public:
|
||||
assert(stringOffset < file.stringSize);
|
||||
return file.stringTable.data() + stringOffset;
|
||||
}
|
||||
|
||||
template<typename T> inline
|
||||
void write(size_t field, T val)
|
||||
{
|
||||
static_assert(sizeof(T) == 4, "This function only writes int/uint/float values.");
|
||||
assert(field < file.fieldCount);
|
||||
*reinterpret_cast<T*>(offset + field * 4) = val;
|
||||
}
|
||||
|
||||
void writeString(size_t field, std::string& val)
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
|
||||
size_t old_size = file.stringTable.size();
|
||||
*reinterpret_cast<unsigned int*>(offset + field * 4) = file.stringTable.size();
|
||||
file.stringTable.resize(old_size + val.size() + 1);
|
||||
std::copy(val.c_str(), val.c_str() + val.size() + 1, file.stringTable.data() + old_size);
|
||||
}
|
||||
|
||||
void writeLocalizedString(size_t field, std::string& val, int locale)
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
|
||||
size_t old_size = file.stringTable.size();
|
||||
*reinterpret_cast<unsigned int*>(offset + field + locale * 4) = file.stringTable.size();
|
||||
file.stringTable.resize(old_size + val.size() + 1);
|
||||
std::copy(val.c_str(), val.c_str() + val.size() + 1, file.stringTable.data() + old_size);
|
||||
}
|
||||
|
||||
private:
|
||||
Record(const DBCFile &pfile, unsigned char *poffset) : file(pfile), offset(poffset) {}
|
||||
const DBCFile &file;
|
||||
Record(DBCFile &pfile, unsigned char *poffset) : file(pfile), offset(poffset) {}
|
||||
DBCFile &file;
|
||||
unsigned char *offset;
|
||||
|
||||
friend class DBCFile;
|
||||
@@ -80,7 +119,7 @@ public:
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
Iterator(const DBCFile &file, unsigned char *offset) :
|
||||
Iterator(DBCFile &file, unsigned char *offset) :
|
||||
record(file, offset) {}
|
||||
/// Advance (prefix only)
|
||||
Iterator & operator++() {
|
||||
@@ -88,16 +127,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
/// Return address of current instance
|
||||
Record const & operator*() const { return record; }
|
||||
const Record* operator->() const {
|
||||
Record & operator*() { return record; }
|
||||
Record* operator->() {
|
||||
return &record;
|
||||
}
|
||||
/// Comparison
|
||||
bool operator==(const Iterator &b) const
|
||||
bool operator==( Iterator const &b)
|
||||
{
|
||||
return record.offset == b.record.offset;
|
||||
}
|
||||
bool operator!=(const Iterator &b) const
|
||||
bool operator!=( Iterator const &b)
|
||||
{
|
||||
return record.offset != b.record.offset;
|
||||
}
|
||||
@@ -119,8 +158,8 @@ public:
|
||||
return Iterator(*this, data.data() + data.size());
|
||||
}
|
||||
|
||||
inline size_t getRecordCount() const { return recordCount; }
|
||||
inline size_t getFieldCount() const { return fieldCount; }
|
||||
inline size_t getRecordCount() { return recordCount; }
|
||||
inline size_t getFieldCount() { return fieldCount; }
|
||||
inline Record getByID(unsigned int id, size_t field = 0)
|
||||
{
|
||||
for (Iterator i = begin(); i != end(); ++i)
|
||||
@@ -131,12 +170,16 @@ public:
|
||||
throw NotFound();
|
||||
}
|
||||
|
||||
Record addRecord(size_t id, size_t id_field = 0);
|
||||
Record addRecordCopy(size_t id, size_t id_from, size_t id_field = 0);
|
||||
void removeRecord(size_t id, size_t id_field = 0);
|
||||
|
||||
private:
|
||||
std::string filename;
|
||||
size_t recordSize;
|
||||
size_t recordCount;
|
||||
size_t fieldCount;
|
||||
size_t stringSize;
|
||||
std::uint32_t recordSize;
|
||||
std::uint32_t recordCount;
|
||||
std::uint32_t fieldCount;
|
||||
std::uint32_t stringSize;
|
||||
std::vector<unsigned char> data;
|
||||
std::vector<char> stringTable;
|
||||
};
|
||||
|
||||
@@ -1605,6 +1605,8 @@ void MapView::saveMinimap(MinimapRenderSettings* settings)
|
||||
// And we do, to avoid loading geometry twice. Even though, offscreen one in the background would be nice.
|
||||
// The idea is, if rendering fails due to unfinished loading, we skip to the next frame until we are able to render.
|
||||
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
|
||||
switch (settings->export_mode)
|
||||
{
|
||||
case MinimapGenMode::CURRENT_ADT:
|
||||
|
||||
350
src/noggit/Red/MapCreationWizard/UI/MapCreationWizard.cpp
Normal file
350
src/noggit/Red/MapCreationWizard/UI/MapCreationWizard.cpp
Normal file
@@ -0,0 +1,350 @@
|
||||
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
|
||||
|
||||
#include "MapCreationWizard.hpp"
|
||||
|
||||
#include <noggit/ui/font_awesome.hpp>
|
||||
#include <noggit/MapView.h>
|
||||
#include <noggit/World.h>
|
||||
#include <noggit/Log.h>
|
||||
|
||||
#include <util/qt/overload.hpp>
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QCheckBox>
|
||||
#include <QButtonGroup>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QWheelEvent>
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QStackedWidget>
|
||||
|
||||
using namespace noggit::Red::MapCreationWizard::Ui;
|
||||
|
||||
MapCreationWizard::MapCreationWizard(QWidget* parent) : noggit::ui::widget(parent)
|
||||
{
|
||||
setWindowTitle ("Map Creation Wizard");
|
||||
setWindowIcon (QIcon (":/icon"));
|
||||
setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint);
|
||||
|
||||
//setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
auto layout = new QHBoxLayout(this);
|
||||
|
||||
// Left side
|
||||
auto layout_left = new QFormLayout (this);
|
||||
layout->addLayout(layout_left);
|
||||
|
||||
auto scroll_minimap = new QScrollArea(this);
|
||||
scroll_minimap->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
_minimap_widget = new noggit::ui::minimap_widget(this);
|
||||
_minimap_widget->draw_boundaries(true);
|
||||
|
||||
layout_left->addWidget(scroll_minimap);
|
||||
|
||||
scroll_minimap->setAlignment(Qt::AlignCenter);
|
||||
scroll_minimap->setWidget(_minimap_widget);
|
||||
scroll_minimap->setWidgetResizable(true);
|
||||
scroll_minimap->setFixedSize(QSize(512, 512));
|
||||
|
||||
// Right side
|
||||
auto layout_right = new QVBoxLayout (this);
|
||||
layout->addLayout(layout_right);
|
||||
|
||||
auto layout_selector = new QHBoxLayout(this);
|
||||
layout_right->addItem(layout_selector);
|
||||
|
||||
_selected_map = new QComboBox(this);
|
||||
layout_selector->addWidget(new QLabel("Map:"));
|
||||
layout_selector->addWidget(_selected_map);
|
||||
|
||||
_corpse_map_id = new QComboBox(this);
|
||||
_corpse_map_id->addItem("None");
|
||||
_corpse_map_id->setItemData(0, QVariant (-1));
|
||||
|
||||
// Fill selector combo
|
||||
int count = 0;
|
||||
for (DBCFile::Iterator i = gMapDB.begin(); i != gMapDB.end(); ++i)
|
||||
{
|
||||
int map_id = i->getInt(MapDB::MapID);
|
||||
std::string name = i->getLocalizedString(MapDB::Name);
|
||||
int area_type = i->getUInt(MapDB::AreaType);
|
||||
|
||||
if (area_type < 0 ||area_type > 4 || !World::IsEditableWorld(map_id))
|
||||
continue;
|
||||
|
||||
_selected_map->addItem(QString::number(map_id) + " - " + QString::fromUtf8 (name.c_str()));
|
||||
_selected_map->setItemData(count, QVariant (map_id));
|
||||
|
||||
_corpse_map_id->addItem(QString::number(map_id) + " - " + QString::fromUtf8 (name.c_str()));
|
||||
_corpse_map_id->setItemData(count + 1, QVariant (map_id));
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
auto add_btn = new QPushButton(this);
|
||||
add_btn->setIcon(noggit::ui::font_awesome_icon(noggit::ui::font_awesome::plus));
|
||||
layout_selector->addWidget(add_btn);
|
||||
|
||||
auto remove_btn = new QPushButton(this);
|
||||
remove_btn->setIcon(noggit::ui::font_awesome_icon(noggit::ui::font_awesome::timescircle));
|
||||
layout_selector->addWidget(remove_btn);
|
||||
|
||||
_map_settings = new QGroupBox("Map settings", this);
|
||||
layout_right->addWidget(_map_settings);
|
||||
|
||||
auto map_settings_layout = new QFormLayout(_map_settings);
|
||||
_map_settings->setLayout(map_settings_layout);
|
||||
|
||||
_directory = new QLineEdit(_map_settings);
|
||||
map_settings_layout->addRow("Map directory:", _directory);
|
||||
|
||||
_instance_type = new QComboBox(_map_settings);
|
||||
_instance_type->addItem("None");
|
||||
_instance_type->setItemData(0, QVariant(0));
|
||||
|
||||
_instance_type->addItem("Instance Crusade");
|
||||
_instance_type->setItemData(1, QVariant(1));
|
||||
|
||||
_instance_type->addItem("Raid");
|
||||
_instance_type->setItemData(2, QVariant(2));
|
||||
|
||||
_instance_type->addItem("Battleground");
|
||||
_instance_type->setItemData(3, QVariant(3));
|
||||
|
||||
_instance_type->addItem("Arena");
|
||||
_instance_type->setItemData(4, QVariant(4));
|
||||
|
||||
map_settings_layout->addRow("Map type:",_instance_type);
|
||||
|
||||
_map_name = new LocaleDBCEntry(_map_settings);
|
||||
map_settings_layout->addRow("Map name:",_map_name);
|
||||
|
||||
_area_table_id = new QSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Area ID:",_area_table_id);
|
||||
|
||||
_map_desc_alliance = new LocaleDBCEntry(_map_settings);
|
||||
map_settings_layout->addRow("Description (Alliance):",_map_desc_alliance);
|
||||
|
||||
_map_desc_horde = new LocaleDBCEntry(_map_settings);
|
||||
map_settings_layout->addRow("Description (Horde):",_map_desc_horde);
|
||||
|
||||
_loading_screen = new QSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Loading screen:",_loading_screen);
|
||||
|
||||
_minimap_icon_scale = new QDoubleSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Minimap icon scale:",_minimap_icon_scale);
|
||||
|
||||
_corpse_map_id->setCurrentText("None");
|
||||
map_settings_layout->addRow("Corpse map:",_corpse_map_id);
|
||||
|
||||
_corpse_x = new QDoubleSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Corpse X:",_corpse_x);
|
||||
|
||||
_corpse_y = new QDoubleSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Corpse Y:",_corpse_y);
|
||||
|
||||
_time_of_day_override = new QSpinBox(_map_settings);
|
||||
_time_of_day_override->setMinimum(-1);
|
||||
_time_of_day_override->setValue(-1);
|
||||
|
||||
map_settings_layout->addRow("Daytime override:",_time_of_day_override);
|
||||
|
||||
_expansion_id = new QComboBox(_map_settings);
|
||||
|
||||
_expansion_id->addItem("Classic");
|
||||
_expansion_id->setItemData(0, QVariant(0));
|
||||
|
||||
_expansion_id->addItem("Burning Crusade");
|
||||
_expansion_id->setItemData(1, QVariant(1));
|
||||
|
||||
_expansion_id->addItem("Wrath of the Lich King");
|
||||
_expansion_id->setItemData(2, QVariant(2));
|
||||
|
||||
map_settings_layout->addRow("Expansion:",_expansion_id);
|
||||
|
||||
_raid_offset = new QSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Raid offset:",_raid_offset);
|
||||
|
||||
_max_players = new QSpinBox(_map_settings);
|
||||
map_settings_layout->addRow("Max players:",_max_players);
|
||||
|
||||
selectMap(_selected_map->itemData(_selected_map->currentIndex()).toInt());
|
||||
|
||||
// Connections
|
||||
|
||||
connect(_selected_map, QOverload<int>::of(&QComboBox::currentIndexChanged)
|
||||
, [&] (int index)
|
||||
{
|
||||
selectMap(_selected_map->itemData(index).toInt());
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void MapCreationWizard::selectMap(int map_id)
|
||||
{
|
||||
|
||||
DBCFile::Record record = gMapDB.getByID(map_id);
|
||||
|
||||
_world = std::make_unique<World>(record.getString(MapDB::InternalName), map_id); // verify if leaks here
|
||||
_minimap_widget->world(_world.get());
|
||||
|
||||
_directory->setText(record.getString(1));
|
||||
_instance_type->setCurrentIndex(record.getInt(2));
|
||||
|
||||
_map_name->fill(record, 5);
|
||||
|
||||
_area_table_id->setValue(record.getInt(22));
|
||||
|
||||
_map_desc_alliance->fill(record, 23);
|
||||
_map_desc_horde->fill(record, 40);
|
||||
|
||||
_loading_screen->setValue(record.getInt(57));
|
||||
_minimap_icon_scale->setValue(record.getFloat(58));
|
||||
|
||||
int corpse_map_idx = record.getInt(59);
|
||||
for (int i = 0; i < _corpse_map_id->count(); ++i)
|
||||
{
|
||||
if (_corpse_map_id->itemData(i) == corpse_map_idx)
|
||||
{
|
||||
_corpse_map_id->setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
_corpse_x->setValue(record.getFloat(60));
|
||||
_corpse_y->setValue(record.getFloat(61));
|
||||
_time_of_day_override->setValue(record.getInt(62));
|
||||
_expansion_id->setCurrentIndex(record.getInt(63));
|
||||
_raid_offset->setValue(record.getInt(64));
|
||||
_max_players->setValue(record.getInt(65));
|
||||
}
|
||||
|
||||
void MapCreationWizard::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
|
||||
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
|
||||
{
|
||||
const int degrees = event->angleDelta().y() / 8;
|
||||
int steps = degrees / 15;
|
||||
|
||||
auto base_size = _minimap_widget->width();
|
||||
|
||||
if (steps > 0)
|
||||
{
|
||||
auto new_size = std::max(512, base_size + 64);
|
||||
_minimap_widget->setFixedSize(new_size, new_size);
|
||||
} else
|
||||
{
|
||||
auto new_size = std::min(4096, base_size - 64);
|
||||
_minimap_widget->setFixedSize(new_size, new_size);
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LocaleDBCEntry::LocaleDBCEntry(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
auto layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
_show_entry = new QStackedWidget(this);
|
||||
|
||||
_en = new QLineEdit(this);
|
||||
_kr = new QLineEdit(this);
|
||||
_fr = new QLineEdit(this);
|
||||
_de = new QLineEdit(this);
|
||||
_cn = new QLineEdit(this);
|
||||
_tw = new QLineEdit(this);
|
||||
_es = new QLineEdit(this);
|
||||
_mx = new QLineEdit(this);
|
||||
_ru = new QLineEdit(this);
|
||||
_jp = new QLineEdit(this);
|
||||
_pt = new QLineEdit(this);
|
||||
_it = new QLineEdit(this);
|
||||
|
||||
_unk1 = new QLineEdit(this);
|
||||
_unk2 = new QLineEdit(this);
|
||||
_unk3 = new QLineEdit(this);
|
||||
_unk4 = new QLineEdit(this);
|
||||
|
||||
_flags = new QSpinBox(this);
|
||||
_flags->setVisible(false);
|
||||
|
||||
_show_entry->addWidget(_en);
|
||||
_show_entry->addWidget(_kr);
|
||||
_show_entry->addWidget(_fr);
|
||||
_show_entry->addWidget(_de);
|
||||
_show_entry->addWidget(_cn);
|
||||
_show_entry->addWidget(_tw);
|
||||
_show_entry->addWidget(_es);
|
||||
_show_entry->addWidget(_mx);
|
||||
_show_entry->addWidget(_ru);
|
||||
_show_entry->addWidget(_jp);
|
||||
_show_entry->addWidget(_pt);
|
||||
_show_entry->addWidget(_it);
|
||||
_show_entry->addWidget(_unk1);
|
||||
_show_entry->addWidget(_unk2);
|
||||
_show_entry->addWidget(_unk3);
|
||||
_show_entry->addWidget(_unk4);
|
||||
|
||||
layout->addWidget(_show_entry);
|
||||
|
||||
_current_locale = new QComboBox(this);
|
||||
|
||||
for (auto const &loc : _locale_names)
|
||||
{
|
||||
_current_locale->addItem(QString::fromStdString(loc));
|
||||
}
|
||||
|
||||
_widget_map = {
|
||||
|
||||
{"enUS", _en},
|
||||
{"koKR", _kr},
|
||||
{"frFR", _fr},
|
||||
{"deDE", _de},
|
||||
{"zhCN", _cn},
|
||||
{"zhTW", _tw},
|
||||
{"esES", _es},
|
||||
{"esMX", _mx},
|
||||
{"ruRU", _ru},
|
||||
{"jaJP", _jp},
|
||||
{"ptPT", _pt},
|
||||
{"itIT", _it},
|
||||
{"Unknown 1", _unk1},
|
||||
{"Unknown 2", _unk2},
|
||||
{"Unknown 3", _unk3},
|
||||
{"Unknown 4", _unk4}
|
||||
};
|
||||
|
||||
layout->addWidget(_current_locale);
|
||||
// Connect
|
||||
|
||||
connect ( _current_locale, &QComboBox::currentTextChanged
|
||||
, [&] (QString s)
|
||||
{
|
||||
setCurrentLocale(_current_locale->currentText().toStdString());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void LocaleDBCEntry::setCurrentLocale(const std::string& locale)
|
||||
{
|
||||
_show_entry->setCurrentWidget(_widget_map.at(locale));
|
||||
}
|
||||
|
||||
void LocaleDBCEntry::fill(DBCFile::Record& record, size_t field, size_t id_field)
|
||||
{
|
||||
for (int loc = 0; loc < 16; ++loc)
|
||||
{
|
||||
setValue(record.getLocalizedString(field, loc), loc);
|
||||
}
|
||||
|
||||
_flags->setValue(record.getInt(field + 16));
|
||||
}
|
||||
|
||||
|
||||
|
||||
113
src/noggit/Red/MapCreationWizard/UI/MapCreationWizard.hpp
Normal file
113
src/noggit/Red/MapCreationWizard/UI/MapCreationWizard.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QGroupBox>
|
||||
#include <QSpinBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QStackedWidget>
|
||||
|
||||
#include <noggit/DBC.h>
|
||||
#include <noggit/DBCFile.h>
|
||||
|
||||
#include <noggit/ui/minimap_widget.hpp>
|
||||
#include <noggit/ui/widget.hpp>
|
||||
|
||||
class World;
|
||||
|
||||
namespace noggit
|
||||
{
|
||||
|
||||
namespace Red::MapCreationWizard::Ui
|
||||
{
|
||||
|
||||
class LocaleDBCEntry : public QWidget
|
||||
{
|
||||
public:
|
||||
LocaleDBCEntry(QWidget *parent = nullptr);
|
||||
|
||||
void setCurrentLocale(const std::string& locale);
|
||||
|
||||
void setValue(const std::string& val, int locale)
|
||||
{
|
||||
_widget_map.at(_locale_names[locale])->setText(QString::fromStdString(val));
|
||||
}
|
||||
|
||||
void fill(DBCFile::Record& record, size_t field, size_t id_field = 0);
|
||||
|
||||
private:
|
||||
QComboBox* _current_locale;
|
||||
QStackedWidget* _show_entry;
|
||||
|
||||
std::unordered_map<std::string, QLineEdit*> _widget_map;
|
||||
std::vector<std::string> _locale_names = {"enUS", "koKR", "frFR", "deDE", "zhCN",
|
||||
"zhTW", "esES", "esMX", "ruRU", "jaJP", "ptPT", "itIT",
|
||||
"Unknown 1", "Unknown 2", "Unknown 3", "Unknown 4"};
|
||||
|
||||
QLineEdit* _en;
|
||||
QLineEdit* _kr;
|
||||
QLineEdit* _fr;
|
||||
QLineEdit* _de;
|
||||
QLineEdit* _cn; // + nCN
|
||||
QLineEdit* _tw;
|
||||
QLineEdit* _es;
|
||||
QLineEdit* _mx;
|
||||
QLineEdit* _ru;
|
||||
QLineEdit* _jp;
|
||||
QLineEdit* _pt;
|
||||
QLineEdit* _it;
|
||||
QLineEdit* _unk1;
|
||||
QLineEdit* _unk2;
|
||||
QLineEdit* _unk3;
|
||||
QLineEdit* _unk4;
|
||||
QSpinBox* _flags;
|
||||
};
|
||||
|
||||
class MapCreationWizard : public ui::widget
|
||||
{
|
||||
public:
|
||||
MapCreationWizard(QWidget *parent = nullptr);
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
|
||||
private:
|
||||
ui::minimap_widget *_minimap_widget;
|
||||
QComboBox *_selected_map;
|
||||
QGroupBox* _map_settings;
|
||||
|
||||
// Map settings
|
||||
QLineEdit* _directory;
|
||||
QComboBox* _instance_type;
|
||||
|
||||
LocaleDBCEntry* _map_name;
|
||||
|
||||
QSpinBox* _area_table_id;
|
||||
|
||||
LocaleDBCEntry* _map_desc_alliance;
|
||||
LocaleDBCEntry* _map_desc_horde;
|
||||
|
||||
QSpinBox* _loading_screen;
|
||||
QDoubleSpinBox* _minimap_icon_scale;
|
||||
QComboBox *_corpse_map_id;
|
||||
|
||||
QDoubleSpinBox* _corpse_x;
|
||||
QDoubleSpinBox* _corpse_y;
|
||||
|
||||
QSpinBox* _time_of_day_override;
|
||||
QComboBox* _expansion_id;
|
||||
QSpinBox* _raid_offset;
|
||||
QSpinBox* _max_players;
|
||||
|
||||
std::unique_ptr<World> _world;
|
||||
|
||||
void selectMap(int map_id);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2186,6 +2186,7 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
gl.colorMask(true, true, true, true);
|
||||
|
||||
QImage image = pixel_buffer.toImage();
|
||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||
|
||||
QSettings app_settings;
|
||||
QString str = app_settings.value ("project/path").toString();
|
||||
@@ -2203,12 +2204,13 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
buffer.open( QIODevice::WriteOnly );
|
||||
|
||||
image.save( &buffer, "PNG" );
|
||||
image.save(std::string(basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".png").c_str());
|
||||
|
||||
auto blp = Png2Blp();
|
||||
blp.load(reinterpret_cast<const void*>(bytes.constData()), bytes.size());
|
||||
|
||||
uint32_t file_size;
|
||||
void* blp_image = blp.createBlpDxtInMemory(true, FORMAT_DXT5, file_size);
|
||||
void* blp_image = blp.createBlpUncompressedInMemory(true, file_size);
|
||||
|
||||
std::string tex_name = std::string(basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".blp");
|
||||
|
||||
@@ -2232,12 +2234,12 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
|
||||
if (combined_image.width() != 8192 | combined_image.height() != 8192)
|
||||
{
|
||||
combined_image = QImage(8192, 8192, QImage::Format_ARGB32);
|
||||
combined_image = QImage(8192, 8192, QImage::Format_RGBA8888);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
combined_image = QImage(8192, 8192, QImage::Format_ARGB32);
|
||||
combined_image = QImage(8192, 8192, QImage::Format_RGBA8888);
|
||||
}
|
||||
|
||||
QImage scaled_image = image.scaled(128, 128, Qt::KeepAspectRatio);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <noggit/ui/minimap_widget.hpp>
|
||||
#include <noggit/ui/uid_fix_window.hpp>
|
||||
#include <noggit/uid_storage.hpp>
|
||||
#include <noggit/Red/MapCreationWizard/UI/MapCreationWizard.hpp>
|
||||
|
||||
#include <QtGui/QCloseEvent>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
@@ -261,6 +262,9 @@ namespace noggit
|
||||
layout->addWidget (_minimap);
|
||||
|
||||
setCentralWidget (widget);
|
||||
|
||||
auto test = new noggit::Red::MapCreationWizard::Ui::MapCreationWizard();
|
||||
test->show();
|
||||
}
|
||||
|
||||
void main_window::rebuild_menu()
|
||||
|
||||
@@ -187,7 +187,7 @@ namespace noggit
|
||||
|
||||
void minimap_widget::mouseDoubleClickEvent (QMouseEvent* event)
|
||||
{
|
||||
if (event->button() != Qt::LeftButton)
|
||||
if (event->button() != Qt::LeftButton || !_world)
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user