minimap editor: add missing functionality that was present in UI only

map wizard: add ability to edit existing maps. WIP.
This commit is contained in:
Skarn
2020-11-02 18:27:49 +03:00
parent 3c4e548c6a
commit dd69b29007
6 changed files with 200 additions and 45 deletions

View File

@@ -86,24 +86,38 @@ public:
*reinterpret_cast<T*>(offset + field * 4) = val;
}
void writeString(size_t field, std::string& val)
void writeString(size_t field, const std::string& val)
{
assert(field < file.fieldCount);
if (!val.size())
{
*reinterpret_cast<unsigned int*>(offset + field * 4) = 0;
return;
}
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);
file.stringSize += val.size() + 1;
}
void writeLocalizedString(size_t field, std::string& val, int locale)
void writeLocalizedString(size_t field, const std::string& val, int locale)
{
assert(field < file.fieldCount);
if (!val.size())
{
*reinterpret_cast<unsigned int*>(offset + ((field + locale) * 4)) = 0;
return;
}
size_t old_size = file.stringTable.size();
*reinterpret_cast<unsigned int*>(offset + field + locale * 4) = 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);
file.stringSize += val.size() + 1;
}
private:

View File

@@ -111,7 +111,7 @@ MapCreationWizard::MapCreationWizard(QWidget* parent) : noggit::ui::widget(paren
_instance_type->addItem("None");
_instance_type->setItemData(0, QVariant(0));
_instance_type->addItem("Instance Crusade");
_instance_type->addItem("Instance");
_instance_type->setItemData(1, QVariant(1));
_instance_type->addItem("Raid");
@@ -177,10 +177,34 @@ MapCreationWizard::MapCreationWizard(QWidget* parent) : noggit::ui::widget(paren
_max_players = new QSpinBox(_map_settings);
map_settings_layout->addRow("Max players:",_max_players);
// Bottom row
auto btn_row_layout = new QHBoxLayout(this);
btn_row_layout->setAlignment(Qt::AlignRight);
auto save_btn = new QPushButton("Save", this);
auto discard_btn = new QPushButton("Discard", this);
btn_row_layout->addWidget(save_btn);
btn_row_layout->addWidget(discard_btn);
layout_right->addItem(btn_row_layout);
selectMap(_selected_map->itemData(_selected_map->currentIndex()).toInt());
// Connections
connect(save_btn, &QPushButton::clicked
,[&] ()
{
saveCurrentEntry();
});
connect(discard_btn, &QPushButton::clicked
,[&] ()
{
});
connect(_selected_map, QOverload<int>::of(&QComboBox::currentIndexChanged)
, [&] (int index)
{
@@ -205,19 +229,33 @@ MapCreationWizard::MapCreationWizard(QWidget* parent) : noggit::ui::widget(paren
{
if (!_world->mapIndex.hasTile(tile_index(x + i, y + j)))
{
_world->mapIndex.addTile(tile_index(x + i, y + j));
// _world->mapIndex.saveTile(tile_index(x + i, y + j), _world.get(), true);
// _world->mapIndex.save();
if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.addTile(tile_index(x + i, y + j));
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.removeTile(tile_index(x + i, y + j));
}
}
}
}
else
{
if (_world->mapIndex.hasTile(tile_index(tile.x(), tile.y())))
int x = tile.x();
int y = tile.y();
if (!_world->mapIndex.hasTile(tile_index(x, y)))
{
//
if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.addTile(tile_index(x, y));
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.removeTile(tile_index(x, y));
}
}
@@ -231,6 +269,7 @@ void MapCreationWizard::selectMap(int map_id)
{
DBCFile::Record record = gMapDB.getByID(map_id);
_cur_map_id = map_id;
_world = std::make_unique<World>(record.getString(MapDB::InternalName), map_id);
_minimap_widget->world(_world.get());
@@ -290,6 +329,42 @@ void MapCreationWizard::wheelEvent(QWheelEvent* event)
}
void MapCreationWizard::saveCurrentEntry()
{
// Save ADTs to disk
_world->mapIndex.saveChanged(_world.get(), true);
_world->mapIndex.save();
// Save Map.dbc record
DBCFile::Record record = _is_new_record ? gMapDB.addRecord(_cur_map_id) : gMapDB.getByID(_cur_map_id);
record.writeString(1, _directory->text().toStdString());
record.write(2, _instance_type->itemData(_instance_type->currentIndex()).toInt());
_map_name->toRecord(record, 5);
record.write(22, _area_table_id->value());
_map_desc_alliance->toRecord(record, 23);
_map_desc_horde->toRecord(record, 40);
record.write(57, _loading_screen->value());
record.write(58, static_cast<float>(_minimap_icon_scale->value()));
record.write(59, _corpse_map_id->itemData(_corpse_map_id->currentIndex()).toInt());
record.write(60, static_cast<float>(_corpse_x->value()));
record.write(61, static_cast<float>(_corpse_y->value()));
record.write(62, _time_of_day_override->value());
record.write(63, _expansion_id->itemData(_expansion_id->currentIndex()).toInt());
record.write(64, _raid_offset->value());
record.write(65, _max_players->value());
gMapDB.save();
}
void MapCreationWizard::discardChanges()
{
}
LocaleDBCEntry::LocaleDBCEntry(QWidget* parent) : QWidget(parent)
{
auto layout = new QHBoxLayout(this);
@@ -379,7 +454,7 @@ 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)
void LocaleDBCEntry::fill(DBCFile::Record& record, size_t field)
{
for (int loc = 0; loc < 16; ++loc)
{
@@ -389,5 +464,15 @@ void LocaleDBCEntry::fill(DBCFile::Record& record, size_t field, size_t id_field
_flags->setValue(record.getInt(field + 16));
}
void LocaleDBCEntry::toRecord(DBCFile::Record &record, size_t field)
{
for (int loc = 0; loc < 16; ++loc)
{
record.writeLocalizedString(field,getValue(loc), loc);
}
record.write(field + 16, _flags->value());
}

View File

@@ -41,7 +41,10 @@ namespace noggit
_widget_map.at(_locale_names[locale])->setText(QString::fromStdString(val));
}
void fill(DBCFile::Record& record, size_t field, size_t id_field = 0);
std::string getValue(int locale) { return _widget_map.at(_locale_names[locale])->text().toStdString(); };
void fill(DBCFile::Record& record, size_t field);
void toRecord(DBCFile::Record& record, size_t field);
private:
QComboBox* _current_locale;
@@ -107,8 +110,14 @@ namespace noggit
std::unique_ptr<World> _world;
bool _is_new_record = false;
int _cur_map_id = 0;
void selectMap(int map_id);
void saveCurrentEntry();
void discardChanges();
};
}
}

View File

@@ -1868,7 +1868,7 @@ void World::drawMinimap ( MapTile *tile
mcnk_shader.uniform("tex2", 3);
mcnk_shader.uniform("tex3", 4);
mcnk_shader.uniform("draw_shadows", 0);
mcnk_shader.uniform("draw_shadows", static_cast<int>(settings->draw_shadows));
mcnk_shader.uniform("shadow_map", 5);
mcnk_shader.uniform("tex_anim_0", math::vector_2d());
@@ -2168,28 +2168,34 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
if (!dir.exists())
dir.mkpath(".");
QByteArray bytes;
QBuffer buffer( &bytes );
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.createBlpUncompressedInMemory(true, file_size);
std::string tex_name = std::string(basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".blp");
QFile file(dir.filePath(tex_name.c_str()));
file.open(QIODevice::WriteOnly);
if (settings->file_format == ".png")
{
image.save(std::string(basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".png").c_str());
}
else if (settings->file_format == ".blp")
{
QByteArray bytes;
QBuffer buffer( &bytes );
buffer.open( QIODevice::WriteOnly );
QDataStream out(&file);
out.writeRawData(reinterpret_cast<char*>(blp_image), file_size);
image.save( &buffer, "PNG" );
file.close();
auto blp = Png2Blp();
blp.load(reinterpret_cast<const void*>(bytes.constData()), bytes.size());
uint32_t file_size;
void* blp_image = blp.createBlpUncompressedInMemory(true, file_size);
QFile file(dir.filePath(tex_name.c_str()));
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out.writeRawData(reinterpret_cast<char*>(blp_image), file_size);
file.close();
}
// Write combined file
if (settings->combined_minimap)
@@ -2230,8 +2236,6 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
std::string tilename_left = (boost::format("%s\\map_%d_%02d.blp") % map_name % tile_idx.x % tile_idx.z).str();
mapIndex._minimap_md5translate[map_name][tilename_left] = tex_name;
// image.save(dir.filePath(std::string(basename + "_" + std::to_string(tile_idx.x) + "_" + std::to_string(tile_idx.z) + ".png").c_str()));
if (unload)
{
mapIndex.unloadTile(tile_idx);

View File

@@ -432,7 +432,7 @@ void MapIndex::saveTile(const tile_index& tile, World* world, bool save_unloaded
}
}
void MapIndex::saveChanged (World* world)
void MapIndex::saveChanged (World* world, bool save_unloaded)
{
world->wait_for_all_tile_updates();
@@ -441,7 +441,43 @@ void MapIndex::saveChanged (World* world)
save();
}
saveMaxUID();
if (!save_unloaded)
{
saveMaxUID();
}
else
{
for (int i = 0; i < 64; ++i)
{
for (int j = 0; j < 64; ++j)
{
if (!(mTiles[i][j].tile && mTiles[i][j].tile->changed.load()))
{
continue;
}
QSettings settings;
auto filepath = boost::filesystem::path (settings.value ("project/path").toString().toStdString())
/ noggit::mpq::normalized_filename (mTiles[i][j].tile->filename);
if (mTiles[i][j].flags & 0x1)
{
QFile file(filepath.string().c_str());
file.open(QIODevice::WriteOnly);
mTiles[i][j].tile->initEmptyChunks();
mTiles[i][j].tile->saveTile(world);
mTiles[i][j].tile->changed = false;
}
else
{
QFile file(filepath.string().c_str());
file.remove();
}
}
}
return;
}
for (MapTile* tile : loaded_tiles())
{
@@ -1069,23 +1105,29 @@ void MapIndex::saveMinimapMD5translate()
void MapIndex::addTile(const tile_index& tile)
{
int j = tile.z;
int i = tile.x;
std::stringstream filename;
filename << "World\\Maps\\" << basename << "\\" << basename << "_" << tile.x << "_" << tile.z << ".adt";
mTiles[tile.z][tile.x].tile = std::make_unique<MapTile> (tile.x, tile.z, filename.str(),
mBigAlpha, true, use_mclq_green_lava(), false, _world);
mTiles[tile.z][tile.x].onDisc = true;
mTiles[tile.z][tile.x].flags |= 0x1;
mTiles[tile.z][tile.x].tile->changed = true;
if (mTiles[tile.z][tile.x].onDisc)
{
mTiles[tile.z][tile.x].flags |= 1;
}
changed = true;
}
void MapIndex::removeTile(const tile_index &tile)
{
mTiles[tile.z][tile.x].flags &= ~0x1;
std::stringstream filename;
filename << "World\\Maps\\" << basename << "\\" << basename << "_" << tile.x << "_" << tile.z << ".adt";
mTiles[tile.z][tile.x].tile = std::make_unique<MapTile> (tile.x, tile.z, filename.str(),
mBigAlpha, true, use_mclq_green_lava(), false, _world);
mTiles[tile.z][tile.x].tile->changed = true;
mTiles[tile.z][tile.x].onDisc = false;
changed = true;
}

View File

@@ -163,8 +163,8 @@ public:
void setFlag(bool to, math::vector_3d const& pos, uint32_t flag);
bool has_unsaved_changes(const tile_index& tile) const;
void saveTile(const tile_index& tile, World*, bool save_unloaded=false);
void saveChanged (World*);
void saveTile(const tile_index& tile, World*, bool save_unloaded = false);
void saveChanged (World*, bool save_unloaded = false);
void reloadTile(const tile_index& tile);
void unloadTiles(const tile_index& tile); // unloads all tiles more then x adts away from given
void unloadTile(const tile_index& tile); // unload given tile
@@ -200,6 +200,7 @@ public:
void loadMaxUID();
void addTile(const tile_index& tile);
void removeTile(const tile_index& tile);
// todo: find out how wow choose to use the green lava in outland
inline bool use_mclq_green_lava() const