major clean up and rework of minimap generator. it is now much faster and never skips to load an asset. it should not stall the process either.
UX improvements for dock widgets and minimap selector widget. The long requested ADT coord promt is now back.
This commit is contained in:
@@ -11,21 +11,7 @@
|
||||
bool AsyncLoader::is_loading()
|
||||
{
|
||||
std::lock_guard<std::mutex> const lock (_guard);
|
||||
if (_currently_loading.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto async_obj : _currently_loading)
|
||||
{
|
||||
if ((!async_obj->loading_failed() && async_obj->filename.length())) // the filename check is a hack
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return !_currently_loading.empty();
|
||||
}
|
||||
|
||||
void AsyncLoader::process()
|
||||
|
||||
@@ -81,4 +81,5 @@ public:
|
||||
}
|
||||
|
||||
virtual void finishLoading() = 0;
|
||||
virtual void waitForChildrenLoaded() = 0;
|
||||
};
|
||||
|
||||
@@ -223,8 +223,8 @@ MPQFile::MPQFile(std::string const& filename)
|
||||
return;
|
||||
}
|
||||
|
||||
LogError << "File '" << filename << "' does not exist." << std::endl;
|
||||
//throw std::invalid_argument ("File '" + filename + "' does not exist.");
|
||||
//LogError << "File '" << filename << "' does not exist." << std::endl;
|
||||
throw std::invalid_argument ("File '" + filename + "' does not exist.");
|
||||
}
|
||||
|
||||
MPQFile::~MPQFile()
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
bool openFile(const std::string& filename, HANDLE* fileHandle) const;
|
||||
|
||||
void finishLoading();
|
||||
virtual void waitForChildrenLoaded() override {};
|
||||
|
||||
static bool allFinishedLoading();
|
||||
static void allFinishLoading();
|
||||
|
||||
@@ -602,6 +602,15 @@ void MapChunk::updateVerticesData()
|
||||
update_intersect_points();
|
||||
}
|
||||
|
||||
void MapChunk::recalcExtents()
|
||||
{
|
||||
for (int i(0); i < mapbufsize; ++i)
|
||||
{
|
||||
vmin.y = std::min(vmin.y, mVertices[i].y);
|
||||
vmax.y = std::max(vmax.y, mVertices[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
math::vector_3d MapChunk::getNeighborVertex(int i, unsigned dir)
|
||||
{
|
||||
// i - vertex index
|
||||
|
||||
@@ -132,6 +132,7 @@ public:
|
||||
bool hasColors() const { return hasMCCV; };
|
||||
|
||||
void updateVerticesData();
|
||||
void recalcExtents();
|
||||
void recalcNorms();
|
||||
void updateNormalsData();
|
||||
math::vector_3d getNeighborVertex(int i, unsigned dir);
|
||||
|
||||
@@ -78,8 +78,32 @@ MapTile::~MapTile()
|
||||
_world->remove_models_if_needed(uids);
|
||||
}
|
||||
|
||||
void MapTile::waitForChildrenLoaded()
|
||||
{
|
||||
for (auto& instance : object_instances)
|
||||
{
|
||||
instance.first->wait_until_loaded();
|
||||
instance.first->waitForChildrenLoaded();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
for (int k = 0; k < mChunks[i][j].get()->texture_set->num(); ++k)
|
||||
{
|
||||
(*mChunks[i][j].get()->texture_set->getTextures())[k].get()->wait_until_loaded();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapTile::finishLoading()
|
||||
{
|
||||
|
||||
if (finished)
|
||||
return;
|
||||
|
||||
MPQFile theFile(filename);
|
||||
|
||||
Log << "Opening tile " << index.x << ", " << index.z << " (\"" << filename << "\") from " << (theFile.isExternal() ? "disk" : "MPQ") << "." << std::endl;
|
||||
@@ -369,6 +393,20 @@ float MapTile::getMinHeight()
|
||||
return _extents[0].y;
|
||||
}
|
||||
|
||||
void MapTile::forceRecalcExtents()
|
||||
{
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
MapChunk* chunk = mChunks[i][j].get();
|
||||
chunk->recalcExtents();
|
||||
_extents[0].y = std::min(_extents[0].y, chunk->getMinHeight());
|
||||
_extents[1].y = std::max(_extents[1].y, chunk->getMaxHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapTile::convert_alphamap(bool to_big_alpha)
|
||||
{
|
||||
mBigAlpha = true;
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
~MapTile();
|
||||
|
||||
void finishLoading();
|
||||
void waitForChildrenLoaded();
|
||||
|
||||
//! \todo on destruction, unload ModelInstances and WMOInstances on this tile:
|
||||
// a) either keep up the information what tiles the instances are on at all times
|
||||
@@ -70,6 +71,7 @@ public:
|
||||
//! \brief Get the maximum height of terrain on this map tile.
|
||||
float getMaxHeight();
|
||||
float getMinHeight();
|
||||
void forceRecalcExtents();
|
||||
|
||||
void convert_alphamap(bool to_big_alpha);
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include <QDateTime>
|
||||
#include <QCursor>
|
||||
#include <QFileDialog>
|
||||
#include <QProgressDialog>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@@ -230,6 +231,7 @@ void MapView::set_editing_mode (editing_mode mode)
|
||||
_world->getTerrainParamsUniformBlock()->draw_impass_overlay = false;
|
||||
_world->getTerrainParamsUniformBlock()->draw_paintability_overlay = false;
|
||||
_world->getTerrainParamsUniformBlock()->draw_selection_overlay = false;
|
||||
_minimap->use_selection(nullptr);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
@@ -269,6 +271,7 @@ void MapView::set_editing_mode (editing_mode mode)
|
||||
break;
|
||||
case editing_mode::minimap:
|
||||
_world->getTerrainParamsUniformBlock()->draw_selection_overlay = true;
|
||||
_minimap->use_selection(minimapTool->getSelectedTiles());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -548,6 +551,7 @@ void MapView::setupTexturePainterUi()
|
||||
_texture_browser_dock->setFeatures(QDockWidget::DockWidgetMovable
|
||||
| QDockWidget::DockWidgetFloatable
|
||||
| QDockWidget::DockWidgetClosable);
|
||||
_texture_browser_dock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea);
|
||||
_main_window->addDockWidget(Qt::BottomDockWidgetArea, _texture_browser_dock);
|
||||
_texture_browser_dock->hide();
|
||||
|
||||
@@ -670,6 +674,7 @@ void MapView::setupTexturePainterUi()
|
||||
| QDockWidget::DockWidgetFloatable
|
||||
| QDockWidget::DockWidgetClosable);
|
||||
_main_window->addDockWidget(Qt::BottomDockWidgetArea, _texture_picker_dock);
|
||||
_texture_picker_dock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
|
||||
_texture_picker_dock->setFloating(true);
|
||||
_texture_picker_dock->hide();
|
||||
connect(this, &QObject::destroyed, _texture_picker_dock, &QObject::deleteLater);
|
||||
@@ -837,6 +842,7 @@ void MapView::setupNodeEditor()
|
||||
auto _node_editor = new noggit::Red::NodeEditor::Ui::NodeEditorWidget(this);
|
||||
_node_editor_dock = new QDockWidget("Node editor", this);
|
||||
_node_editor_dock->setWidget(_node_editor);
|
||||
_node_editor_dock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea);
|
||||
|
||||
_main_window->addDockWidget(Qt::LeftDockWidgetArea, _node_editor_dock);
|
||||
_node_editor_dock->setFeatures(QDockWidget::DockWidgetMovable
|
||||
@@ -913,6 +919,9 @@ void MapView::setupDetailInfos()
|
||||
| QDockWidget::DockWidgetFloatable
|
||||
| QDockWidget::DockWidgetClosable);
|
||||
|
||||
_detail_infos_dock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea);
|
||||
|
||||
|
||||
_main_window->addDockWidget(Qt::BottomDockWidgetArea, _detail_infos_dock);
|
||||
_detail_infos_dock->setFloating(true);
|
||||
_detail_infos_dock->hide();
|
||||
@@ -1011,8 +1020,6 @@ void MapView::setupFileMenu()
|
||||
}
|
||||
);
|
||||
|
||||
ADD_ACTION (file_menu, "Save minimaps", "Ctrl+Shift+P", [this] { saving_minimap = true; });
|
||||
|
||||
ADD_ACTION ( file_menu
|
||||
, "Write coordinates to port.txt"
|
||||
, Qt::Key_G
|
||||
@@ -2324,11 +2331,15 @@ void MapView::setupMinimap()
|
||||
{
|
||||
_minimap = new noggit::ui::minimap_widget(this);
|
||||
_minimap_dock = new QDockWidget("Minimap", this);
|
||||
_minimap_dock->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
_minimap_dock->setFixedSize(_minimap->sizeHint());
|
||||
_minimap_dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
|
||||
|
||||
_minimap->world (_world.get());
|
||||
_minimap->camera (&_camera);
|
||||
_minimap->draw_boundaries (_show_minimap_borders.get());
|
||||
_minimap->draw_skies (_show_minimap_skies.get());
|
||||
_minimap->set_resizeable(true);
|
||||
|
||||
connect ( _minimap, &noggit::ui::minimap_widget::map_clicked
|
||||
, [this] (math::vector_3d const& pos)
|
||||
@@ -2341,8 +2352,12 @@ void MapView::setupMinimap()
|
||||
| QDockWidget::DockWidgetFloatable
|
||||
| QDockWidget::DockWidgetClosable
|
||||
);
|
||||
_minimap_dock->setWidget(_minimap);
|
||||
_main_window->addDockWidget (Qt::RightDockWidgetArea, _minimap_dock);
|
||||
auto minimap_scroll_area = new QScrollArea(_minimap_dock);
|
||||
minimap_scroll_area->setWidget(_minimap);
|
||||
minimap_scroll_area->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
_minimap_dock->setWidget(minimap_scroll_area);
|
||||
_main_window->addDockWidget (Qt::LeftDockWidgetArea, _minimap_dock);
|
||||
_minimap_dock->setVisible (false);
|
||||
_minimap_dock->setFloating(true);
|
||||
_minimap_dock->move(_main_window->rect().center() - _minimap->rect().center());
|
||||
@@ -2679,12 +2694,14 @@ void MapView::initializeGL()
|
||||
|
||||
void MapView::saveMinimap(MinimapRenderSettings* settings)
|
||||
{
|
||||
// This convoluted logic is necessary here if we want to draw minimaps in the same OpenGL context.
|
||||
// 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());
|
||||
|
||||
bool mmap_render_success = false;
|
||||
|
||||
static QProgressBar* progress;
|
||||
static QPushButton* cancel_btn;
|
||||
|
||||
switch (settings->export_mode)
|
||||
{
|
||||
case MinimapGenMode::CURRENT_ADT:
|
||||
@@ -2693,121 +2710,240 @@ void MapView::saveMinimap(MinimapRenderSettings* settings)
|
||||
|
||||
if (_world->mapIndex.hasTile(tile))
|
||||
{
|
||||
mmap_render_success = _world->saveMinimap(tile, settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
saving_minimap = false;
|
||||
mmap_render_success = _world->saveMinimap(tile, settings, _mmap_combined_image);
|
||||
}
|
||||
|
||||
if (mmap_render_success)
|
||||
{
|
||||
saving_minimap = false;
|
||||
_world->mapIndex.saveMinimapMD5translate();
|
||||
}
|
||||
|
||||
saving_minimap = false;
|
||||
|
||||
break;
|
||||
}
|
||||
case MinimapGenMode::MAP:
|
||||
{
|
||||
tile_index tile = tile_index(mmap_render_index / 64, mmap_render_index % 64);
|
||||
|
||||
if (_world->mapIndex.hasTile(tile))
|
||||
// init progress
|
||||
if (!_mmap_async_index)
|
||||
{
|
||||
mmap_render_success = _world->saveMinimap(tile, settings);
|
||||
progress = new QProgressBar(nullptr);
|
||||
progress->setMinimum(0);
|
||||
progress->setMaximum(_world->mapIndex.getNumExistingTiles());
|
||||
_main_window->statusBar()->addPermanentWidget(progress);
|
||||
|
||||
if (mmap_render_success)
|
||||
cancel_btn = new QPushButton(nullptr);
|
||||
cancel_btn->setText("Cancel");
|
||||
|
||||
connect(cancel_btn, &QPushButton::clicked,
|
||||
[=, this]
|
||||
{
|
||||
_mmap_async_index = 0;
|
||||
_mmap_render_index = 0;
|
||||
saving_minimap = false;
|
||||
progress->deleteLater();
|
||||
cancel_btn->deleteLater();
|
||||
_mmap_combined_image.reset();
|
||||
});
|
||||
|
||||
_main_window->statusBar()->addPermanentWidget(cancel_btn);
|
||||
|
||||
connect(this, &MapView::updateProgress, progress, &QProgressBar::setValue);
|
||||
|
||||
// setup combined image if necessary
|
||||
if (settings->combined_minimap)
|
||||
{
|
||||
mmap_render_index++;
|
||||
_mmap_combined_image.emplace(8192, 8192, QImage::Format_RGBA8888);
|
||||
_mmap_combined_image->fill(Qt::black);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!saving_minimap)
|
||||
return;
|
||||
|
||||
if (_mmap_async_index < 4096 && _mmap_render_index < progress->maximum())
|
||||
{
|
||||
tile_index tile = tile_index(_mmap_async_index / 64, _mmap_async_index % 64);
|
||||
|
||||
if (_world->mapIndex.hasTile(tile))
|
||||
{
|
||||
opengl::context::scoped_setter const _(::gl, context());
|
||||
makeCurrent();
|
||||
mmap_render_success = _world->saveMinimap(tile, settings, _mmap_combined_image);
|
||||
|
||||
_mmap_render_index++;
|
||||
emit updateProgress(_mmap_render_index);
|
||||
|
||||
if (!mmap_render_success)
|
||||
{
|
||||
LogError << "Minimap rendered incorrectly for tile: " << tile.x << "_" << tile.z << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
_mmap_async_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
mmap_render_index++;
|
||||
tile.x = mmap_render_index / 64;
|
||||
tile.z = mmap_render_index % 64;
|
||||
|
||||
} while (!_world->mapIndex.hasTile(tile) && mmap_render_index != 4095 );
|
||||
|
||||
}
|
||||
|
||||
if (mmap_render_success && mmap_render_index >= 4095)
|
||||
{
|
||||
_mmap_async_index = 0;
|
||||
_mmap_render_index = 0;
|
||||
saving_minimap = false;
|
||||
mmap_render_index = 0;
|
||||
mmap_render_success = false;
|
||||
progress->deleteLater();
|
||||
cancel_btn->deleteLater();
|
||||
_world->mapIndex.saveMinimapMD5translate();
|
||||
|
||||
// save combined minimap
|
||||
if (settings->combined_minimap)
|
||||
{
|
||||
QString image_path = QString(std::string(_world->basename + "_combined_minimap.png").c_str());
|
||||
QSettings app_settings;
|
||||
QString str = app_settings.value("project/path").toString();
|
||||
if (!(str.endsWith('\\') || str.endsWith('/')))
|
||||
{
|
||||
str += "/";
|
||||
}
|
||||
|
||||
QDir dir(str + "/textures/minimap/");
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
|
||||
_mmap_combined_image->save(dir.filePath(image_path));
|
||||
_mmap_combined_image.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//_main_window->statusBar()->showMessage("Minimap rendering done.", 2000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case MinimapGenMode::SELECTED_ADTS:
|
||||
{
|
||||
auto selected_tiles = minimapTool->getSelectedTiles();
|
||||
|
||||
while (mmap_render_index < 4096)
|
||||
// init progress
|
||||
if (!_mmap_async_index)
|
||||
{
|
||||
progress = new QProgressBar(nullptr);
|
||||
progress->setMinimum(0);
|
||||
|
||||
bool is_selected = selected_tiles->at(mmap_render_index);
|
||||
unsigned n_selected_tiles = 0;
|
||||
|
||||
if (is_selected)
|
||||
for (int i = 0; i < 4096; ++i)
|
||||
{
|
||||
tile_index tile = tile_index(mmap_render_index / 64, mmap_render_index % 64);
|
||||
if (selected_tiles->at(i))
|
||||
n_selected_tiles++;
|
||||
}
|
||||
|
||||
progress->setMaximum(n_selected_tiles);
|
||||
_main_window->statusBar()->addPermanentWidget(progress);
|
||||
|
||||
cancel_btn = new QPushButton(nullptr);
|
||||
cancel_btn->setText("Cancel");
|
||||
|
||||
connect(cancel_btn, &QPushButton::clicked,
|
||||
[=, this]
|
||||
{
|
||||
_mmap_async_index = 0;
|
||||
_mmap_render_index = 0;
|
||||
saving_minimap = false;
|
||||
progress->deleteLater();
|
||||
cancel_btn->deleteLater();
|
||||
_mmap_combined_image.reset();
|
||||
});
|
||||
|
||||
_main_window->statusBar()->addPermanentWidget(cancel_btn);
|
||||
|
||||
connect(this, &MapView::updateProgress, progress, &QProgressBar::setValue);
|
||||
|
||||
// setup combined image if necessary
|
||||
if (settings->combined_minimap)
|
||||
{
|
||||
_mmap_combined_image.emplace(8192, 8192, QImage::Format_RGBA8888);
|
||||
_mmap_combined_image->fill(Qt::black);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!saving_minimap)
|
||||
return;
|
||||
|
||||
|
||||
if (_mmap_async_index < 4096 && _mmap_render_index < progress->maximum())
|
||||
{
|
||||
if (selected_tiles->at(_mmap_async_index))
|
||||
{
|
||||
tile_index tile = tile_index(_mmap_async_index / 64, _mmap_async_index % 64);
|
||||
|
||||
if (_world->mapIndex.hasTile(tile))
|
||||
{
|
||||
mmap_render_success = _world->saveMinimap(tile, settings);
|
||||
mmap_render_success = _world->saveMinimap(tile, settings, _mmap_combined_image);
|
||||
_mmap_render_index++;
|
||||
|
||||
if (mmap_render_success)
|
||||
emit updateProgress(_mmap_render_index);
|
||||
|
||||
|
||||
if (!mmap_render_success)
|
||||
{
|
||||
mmap_render_index++;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
LogError << "Minimap rendered incorrectly for tile: " << tile.x << "_" << tile.z << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mmap_render_index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mmap_render_index++;
|
||||
}
|
||||
_mmap_async_index++;
|
||||
|
||||
}
|
||||
|
||||
if (mmap_render_success && mmap_render_index >= 4095)
|
||||
else
|
||||
{
|
||||
_mmap_async_index = 0;
|
||||
_mmap_render_index = 0;
|
||||
saving_minimap = false;
|
||||
mmap_render_index = 0;
|
||||
mmap_render_success = false;
|
||||
progress->deleteLater();
|
||||
cancel_btn->deleteLater();
|
||||
_world->mapIndex.saveMinimapMD5translate();
|
||||
|
||||
// save combined minimap
|
||||
if (settings->combined_minimap)
|
||||
{
|
||||
QString image_path = QString(std::string(_world->basename + "_combined_minimap.png").c_str());
|
||||
QSettings app_settings;
|
||||
QString str = app_settings.value("project/path").toString();
|
||||
if (!(str.endsWith('\\') || str.endsWith('/')))
|
||||
{
|
||||
str += "/";
|
||||
}
|
||||
|
||||
QDir dir(str + "/textures/minimap/");
|
||||
if (!dir.exists())
|
||||
dir.mkpath(".");
|
||||
|
||||
_mmap_combined_image->save(dir.filePath(image_path));
|
||||
_mmap_combined_image.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
minimapTool->progressUpdate(mmap_render_index);
|
||||
|
||||
|
||||
//minimapTool->progressUpdate(0);
|
||||
}
|
||||
|
||||
void MapView::paintGL()
|
||||
{
|
||||
ZoneScoped;
|
||||
|
||||
static bool lock = false;
|
||||
|
||||
if (lock)
|
||||
return;
|
||||
|
||||
if (!_needs_redraw)
|
||||
return;
|
||||
else
|
||||
_needs_redraw = false;
|
||||
|
||||
ZoneScoped;
|
||||
|
||||
if (!_gl_initialized)
|
||||
{
|
||||
initializeGL();
|
||||
@@ -2819,36 +2955,36 @@ void MapView::paintGL()
|
||||
return;
|
||||
}
|
||||
|
||||
opengl::context::scoped_setter const _ (::gl, context());
|
||||
|
||||
if (saving_minimap)
|
||||
{
|
||||
saveMinimap(minimapTool->getMinimapRenderSettings());
|
||||
_main_window->setEnabled(false);
|
||||
}
|
||||
|
||||
const qreal now(_startup_time.elapsed() / 1000.0);
|
||||
|
||||
_last_frame_durations.emplace_back (now - _last_update);
|
||||
|
||||
// minimap rendering
|
||||
if (saving_minimap)
|
||||
{
|
||||
opengl::context::scoped_setter const _(::gl, context());
|
||||
makeCurrent();
|
||||
_camera_moved_since_last_draw = true;
|
||||
lock = true;
|
||||
saveMinimap(minimapTool->getMinimapRenderSettings());
|
||||
lock = false;
|
||||
return;
|
||||
}
|
||||
|
||||
opengl::context::scoped_setter const _(::gl, context());
|
||||
makeCurrent();
|
||||
|
||||
gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
draw_map();
|
||||
|
||||
if (!saving_minimap)
|
||||
{
|
||||
|
||||
draw_map();
|
||||
tick (now - _last_update);
|
||||
_main_window->setEnabled(true);
|
||||
}
|
||||
|
||||
_last_update = now;
|
||||
|
||||
if (saving_minimap)
|
||||
{
|
||||
gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if (_gizmo_on.get() && _world->has_selection())
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <unordered_set>
|
||||
#include <thread>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
#include <ui_MapViewOverlay.h>
|
||||
|
||||
@@ -182,9 +183,6 @@ private:
|
||||
|
||||
bool _rotation_editor_need_update = false;
|
||||
|
||||
bool mmap_render_success = false;
|
||||
int mmap_render_index = 0;
|
||||
|
||||
// Vars for the ground editing toggle mode store the status of some
|
||||
// view settings when the ground editing mode is switched on to
|
||||
// restore them if switch back again
|
||||
@@ -224,6 +222,7 @@ signals:
|
||||
void uid_fix_failed();
|
||||
void resized();
|
||||
void saved();
|
||||
void updateProgress(int value);
|
||||
public slots:
|
||||
void on_exit_prompt();
|
||||
|
||||
@@ -253,6 +252,7 @@ public:
|
||||
void randomizeShaderRotation();
|
||||
void randomizeStampRotation();
|
||||
void onSettingsSave();
|
||||
noggit::ui::minimap_widget* getMinimapWidget() const { return _minimap; }
|
||||
|
||||
void set_editing_mode (editing_mode);
|
||||
editing_mode get_editing_mode() { return terrainMode; };
|
||||
@@ -400,6 +400,10 @@ private:
|
||||
bool _destroying = false;
|
||||
bool _needs_redraw = false;
|
||||
|
||||
unsigned _mmap_async_index = 0;
|
||||
unsigned _mmap_render_index = 0;
|
||||
std::optional<QImage> _mmap_combined_image;
|
||||
|
||||
opengl::scoped::deferred_upload_buffers<2> _buffers;
|
||||
|
||||
public:
|
||||
|
||||
@@ -79,6 +79,19 @@ void Model::finishLoading()
|
||||
_state_changed.notify_all();
|
||||
}
|
||||
|
||||
void Model::waitForChildrenLoaded()
|
||||
{
|
||||
for (auto& tex : _textures)
|
||||
{
|
||||
tex.get()->wait_until_loaded();
|
||||
}
|
||||
|
||||
for (auto& pair : _replaceTextures)
|
||||
{
|
||||
pair.second.get()->wait_until_loaded();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Model::isAnimated(const MPQFile& f)
|
||||
{
|
||||
|
||||
@@ -253,6 +253,7 @@ public:
|
||||
void updateEmitters(float dt);
|
||||
|
||||
virtual void finishLoading();
|
||||
virtual void waitForChildrenLoaded() override;
|
||||
|
||||
bool is_hidden() const { return _hidden; }
|
||||
void toggle_visibility() { _hidden = !_hidden; }
|
||||
|
||||
@@ -222,7 +222,6 @@ math::vector_3d* ModelInstance::getExtents()
|
||||
return &extents[0];
|
||||
}
|
||||
|
||||
|
||||
wmo_doodad_instance::wmo_doodad_instance(std::string const& filename, MPQFile* f, noggit::NoggitRenderContext context)
|
||||
: ModelInstance(filename, context)
|
||||
{
|
||||
@@ -280,3 +279,4 @@ void wmo_doodad_instance::update_transform_matrix_wmo(WMOInstance* wmo)
|
||||
|
||||
_need_matrix_update = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,7 @@ public:
|
||||
|
||||
[[nodiscard]]
|
||||
virtual bool isWMODoodad() const override { return true; };
|
||||
|
||||
protected:
|
||||
// to avoid redefining recalcExtents
|
||||
void updateTransformMatrix() override { }
|
||||
|
||||
@@ -46,6 +46,7 @@ struct blp_texture : public AsyncObject
|
||||
{
|
||||
blp_texture (std::string const& filename, noggit::NoggitRenderContext context);
|
||||
void finishLoading();
|
||||
virtual void waitForChildrenLoaded() override {};
|
||||
|
||||
void loadFromUncompressedData(BLPHeader const* lHeader, char const* lData);
|
||||
void loadFromCompressedData(BLPHeader const* lHeader, char const* lData);
|
||||
|
||||
@@ -334,6 +334,20 @@ void WMO::finishLoading ()
|
||||
_state_changed.notify_all();
|
||||
}
|
||||
|
||||
void WMO::waitForChildrenLoaded()
|
||||
{
|
||||
for (auto& tex : textures)
|
||||
{
|
||||
tex.get()->wait_until_loaded();
|
||||
}
|
||||
|
||||
for (auto& doodad : modelis)
|
||||
{
|
||||
doodad.model->wait_until_loaded();
|
||||
doodad.model->waitForChildrenLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
void WMO::draw ( opengl::scoped::use_program& wmo_shader
|
||||
, math::matrix_4x4 const& model_view
|
||||
, math::matrix_4x4 const& projection
|
||||
@@ -728,9 +742,9 @@ void WMOGroup::upload()
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_call->samplers[draw_call->n_used_samplers] = _render_batches[batch_counter].tex_array1;
|
||||
_render_batches[batch_counter].tex_array1 = draw_call->n_used_samplers;
|
||||
draw_call->n_used_samplers++;
|
||||
//draw_call->samplers[draw_call->n_used_samplers] = _render_batches[batch_counter].tex_array1;
|
||||
//_render_batches[batch_counter].tex_array1 = draw_call->n_used_samplers;
|
||||
//draw_call->n_used_samplers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -891,7 +905,15 @@ void WMOGroup::load()
|
||||
|
||||
f.read (&header, sizeof (wmo_group_header));
|
||||
|
||||
WMOFog &wf = wmo->fogs[header.fogs[0]];
|
||||
unsigned fog_index = header.fogs[0];
|
||||
|
||||
// downport hack
|
||||
if (fog_index >= wmo->fogs.size())
|
||||
{
|
||||
fog_index = 0;
|
||||
}
|
||||
WMOFog &wf = wmo->fogs[fog_index];
|
||||
|
||||
if (wf.r2 <= 0) fog = -1; // default outdoor fog..?
|
||||
else fog = header.fogs[0];
|
||||
|
||||
@@ -1319,6 +1341,12 @@ void WMOGroup::load()
|
||||
|
||||
for (auto doodad : _doodad_ref)
|
||||
{
|
||||
if (doodad >= wmo->modelis.size())
|
||||
{
|
||||
continue;
|
||||
LogError << "The WMO file currently loaded is potentially corrupt. Non-existing doodad referenced." << std::endl;
|
||||
}
|
||||
|
||||
lenmin = 999999.0f * 999999.0f;
|
||||
ModelInstance& mi = wmo->modelis[doodad];
|
||||
for (unsigned int j = 0; j < wmo->lights.size(); j++)
|
||||
|
||||
@@ -328,6 +328,8 @@ public:
|
||||
|
||||
void finishLoading();
|
||||
|
||||
virtual void waitForChildrenLoaded() override;
|
||||
|
||||
void unload();
|
||||
|
||||
std::map<uint32_t, std::vector<wmo_doodad_instance>> doodads_per_group(uint16_t doodadset) const;
|
||||
|
||||
@@ -106,28 +106,28 @@ bool World::IsEditableWorld(int pMapId)
|
||||
}
|
||||
|
||||
World::World(const std::string& name, int map_id, noggit::NoggitRenderContext context, bool create_empty)
|
||||
: _model_instance_storage(this)
|
||||
, _tile_update_queue(this)
|
||||
, mapIndex (name, map_id, this, context, create_empty)
|
||||
, horizon(name, &mapIndex)
|
||||
, mWmoFilename("")
|
||||
, mWmoEntry(ENTRY_MODF())
|
||||
, ol(nullptr)
|
||||
, animtime(0)
|
||||
, time(1450)
|
||||
, basename(name)
|
||||
, fogdistance(777.0f)
|
||||
, culldistance(fogdistance)
|
||||
, skies(nullptr)
|
||||
, outdoorLightStats(OutdoorLightStats())
|
||||
, _current_selection()
|
||||
, _settings (new QSettings())
|
||||
, _view_distance(_settings->value ("view_distance", 1000.f).toFloat())
|
||||
, _context(context)
|
||||
, _liquid_texture_manager(context)
|
||||
: _model_instance_storage(this)
|
||||
, _tile_update_queue(this)
|
||||
, mapIndex(name, map_id, this, context, create_empty)
|
||||
, horizon(name, &mapIndex)
|
||||
, mWmoFilename("")
|
||||
, mWmoEntry(ENTRY_MODF())
|
||||
, ol(nullptr)
|
||||
, animtime(0)
|
||||
, time(1450)
|
||||
, basename(name)
|
||||
, fogdistance(777.0f)
|
||||
, culldistance(fogdistance)
|
||||
, skies(nullptr)
|
||||
, outdoorLightStats(OutdoorLightStats())
|
||||
, _current_selection()
|
||||
, _settings(new QSettings())
|
||||
, _view_distance(_settings->value("view_distance", 1000.f).toFloat())
|
||||
, _context(context)
|
||||
, _liquid_texture_manager(context)
|
||||
{
|
||||
LogDebug << "Loading world \"" << name << "\"." << std::endl;
|
||||
_loaded_tiles_buffer[0] = nullptr;
|
||||
_loaded_tiles_buffer[0] = std::make_pair<std::pair<int, int>, MapTile*>(std::make_pair(0, 0), nullptr);
|
||||
}
|
||||
|
||||
void World::update_selection_pivot()
|
||||
@@ -1093,11 +1093,25 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
tile->recalcObjectInstanceExtents();
|
||||
tile->recalcCombinedExtents();
|
||||
|
||||
if (minimap_render)
|
||||
{
|
||||
auto& tile_extents = tile->getCombinedExtents();
|
||||
tile->calcCamDist(camera_pos);
|
||||
tile->tile_frustum_culled = false;
|
||||
tile->objects_frustum_cull_test = 2;
|
||||
tile->tile_occluded = false;
|
||||
_loaded_tiles_buffer[tile_counter] = std::make_pair(std::make_pair(tile->index.x, tile->index.z), tile);
|
||||
|
||||
tile_counter++;
|
||||
_n_loaded_tiles++;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& tile_extents = tile->getCombinedExtents();
|
||||
if (frustum.intersects(tile_extents[1], tile_extents[0]) || tile->getChunkUpdateFlags())
|
||||
{
|
||||
tile->calcCamDist(camera_pos);
|
||||
_loaded_tiles_buffer[tile_counter] = tile;
|
||||
_loaded_tiles_buffer[tile_counter] = std::make_pair(std::make_pair(tile->index.x, tile->index.z), tile);
|
||||
|
||||
tile->objects_frustum_cull_test = 1;
|
||||
if (frustum.contains(tile_extents[0]) && frustum.contains(tile_extents[1]))
|
||||
@@ -1126,26 +1140,26 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
}
|
||||
|
||||
auto buf_end = _loaded_tiles_buffer.begin() + tile_counter;
|
||||
_loaded_tiles_buffer[tile_counter] = nullptr;
|
||||
_loaded_tiles_buffer[tile_counter] = std::make_pair<std::pair<int, int>, MapTile*>(std::make_pair<int, int>(0, 0), nullptr);
|
||||
|
||||
|
||||
// It is always import to sort tiles __front to back__.
|
||||
// Otherwise selection would not work. Overdraw overhead is gonna occur as well.
|
||||
// TODO: perhaps parallel sort?
|
||||
std::sort(_loaded_tiles_buffer.begin(), buf_end,
|
||||
[](MapTile* a, MapTile* b) -> bool
|
||||
[](std::pair<std::pair<int, int>, MapTile*>& a, std::pair<std::pair<int, int>, MapTile*>& b) -> bool
|
||||
{
|
||||
if (!a)
|
||||
if (!a.second)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!b)
|
||||
if (!b.second)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return a->camDist() < b->camDist();
|
||||
return a.second->camDist() < b.second->camDist();
|
||||
});
|
||||
|
||||
// only draw the sky in 3D
|
||||
@@ -1247,13 +1261,18 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
gl.bindVertexArray(_mapchunk_vao);
|
||||
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, _mapchunk_index);
|
||||
|
||||
for (MapTile* tile : _loaded_tiles_buffer)
|
||||
for (auto& pair : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = pair.second;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (minimap_render)
|
||||
tile->tile_occluded = false;
|
||||
|
||||
if (tile->tile_occluded && !tile->getChunkUpdateFlags() && !tile->tile_occlusion_cull_override)
|
||||
continue;
|
||||
|
||||
@@ -1319,13 +1338,18 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
frame++;
|
||||
}
|
||||
|
||||
for (MapTile* tile : _loaded_tiles_buffer)
|
||||
for (auto& pair : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = pair.second;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (minimap_render)
|
||||
tile->tile_occluded = false;
|
||||
|
||||
if (tile->tile_occluded && !tile->getChunkUpdateFlags() && !tile->tile_occlusion_cull_override)
|
||||
continue;
|
||||
|
||||
@@ -1454,8 +1478,10 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
gl.disable(GL_CULL_FACE); // TODO: figure out why indices are bad and we need this
|
||||
|
||||
math::matrix_4x4 identity_mtx = math::matrix_4x4{math::matrix_4x4::unit};
|
||||
for (MapTile* tile : _loaded_tiles_buffer)
|
||||
for (auto& pair : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = pair.second;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
break;
|
||||
@@ -1475,8 +1501,10 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
if (draw_occlusion_boxes)
|
||||
{
|
||||
|
||||
for (MapTile* tile : _loaded_tiles_buffer)
|
||||
for (auto& pair : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = pair.second;
|
||||
|
||||
if (!tile)
|
||||
{
|
||||
break;
|
||||
@@ -1709,8 +1737,10 @@ void World::draw ( math::matrix_4x4 const& model_view
|
||||
|
||||
water_shader.uniform ("use_transform", 0);
|
||||
|
||||
for (MapTile* tile : _loaded_tiles_buffer)
|
||||
for (auto& pair : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = pair.second;
|
||||
|
||||
if (!tile)
|
||||
break;
|
||||
|
||||
@@ -1826,12 +1856,21 @@ selection_result World::intersect ( math::matrix_4x4 const& model_view
|
||||
{
|
||||
ZoneScopedN("World::intersect() : intersect terrain");
|
||||
|
||||
for (auto tile : _loaded_tiles_buffer)
|
||||
for (auto& pair : _loaded_tiles_buffer)
|
||||
{
|
||||
MapTile* tile = pair.second;
|
||||
|
||||
if (!tile)
|
||||
break;
|
||||
|
||||
if (!tile->finishedLoading()) // TODO: crash
|
||||
tile_index index{ static_cast<std::size_t>(pair.first.first)
|
||||
, static_cast<std::size_t>(pair.first.second) };
|
||||
|
||||
// handle tiles that got unloaded mid-frame to avoid illegal access
|
||||
if (!mapIndex.tileLoaded(index) || mapIndex.tileAwaitingLoading(index))
|
||||
continue;
|
||||
|
||||
if (!tile->finishedLoading())
|
||||
continue;
|
||||
|
||||
if (tile->intersect(ray, &results))
|
||||
@@ -2332,12 +2371,26 @@ void World::drawMinimap ( MapTile *tile
|
||||
tile_index m_tile = tile_index(camera_pos);
|
||||
m_tile.z -= 1;
|
||||
|
||||
bool unload = !mapIndex.has_unsaved_changes(m_tile);
|
||||
|
||||
MapTile* mTile = mapIndex.loadTile(m_tile);
|
||||
|
||||
if (mTile)
|
||||
{
|
||||
mTile->wait_until_loaded();
|
||||
mTile->waitForChildrenLoaded();
|
||||
|
||||
}
|
||||
|
||||
draw(model_view, projection, math::vector_3d{}, 0, math::vector_4d{},
|
||||
CursorType::NONE, 0.f, false, 0.f, math::vector_3d{}, 0.f, 0.f, false, false, false, editing_mode::minimap, camera_pos, true, false, true, settings->draw_wmo, settings->draw_water, false, settings->draw_m2, false, false, true, settings, false, eTerrainType::eTerrainType_Linear, 0, display_mode::in_3D, false, true);
|
||||
|
||||
|
||||
if (unload)
|
||||
{
|
||||
mapIndex.unloadTile(m_tile);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
if (!_display_initialized)
|
||||
@@ -2673,12 +2726,12 @@ void World::drawMinimap ( MapTile *tile
|
||||
*/
|
||||
}
|
||||
|
||||
bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* settings)
|
||||
bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* settings, std::optional<QImage>& combined_image)
|
||||
{
|
||||
ZoneScoped;
|
||||
// Setup framebuffer
|
||||
QOpenGLFramebufferObjectFormat fmt;
|
||||
fmt.setSamples(1);
|
||||
fmt.setSamples(0);
|
||||
fmt.setInternalTextureFormat(GL_RGBA8);
|
||||
fmt.setAttachment(QOpenGLFramebufferObject::Depth);
|
||||
|
||||
@@ -2691,19 +2744,32 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
|
||||
// Load tile
|
||||
bool unload = !mapIndex.has_unsaved_changes(tile_idx);
|
||||
MapTile* mTile = mapIndex.loadTile(tile_idx);
|
||||
|
||||
if (!mapIndex.tileLoaded(tile_idx) && !mapIndex.tileAwaitingLoading(tile_idx))
|
||||
{
|
||||
MapTile* tile = mapIndex.loadTile(tile_idx);
|
||||
tile->wait_until_loaded();
|
||||
wait_for_all_tile_updates();
|
||||
tile->waitForChildrenLoaded();
|
||||
}
|
||||
|
||||
MapTile* mTile = mapIndex.getTile(tile_idx);
|
||||
|
||||
if (mTile)
|
||||
{
|
||||
mTile->wait_until_loaded();
|
||||
wait_for_all_tile_updates();
|
||||
unsigned counter = 0;
|
||||
constexpr unsigned TIMEOUT = 5000;
|
||||
|
||||
if (AsyncLoader::instance().is_loading())
|
||||
while (AsyncLoader::instance().is_loading() || !mTile->finishedLoading())
|
||||
{
|
||||
//return false;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
counter++;
|
||||
|
||||
if (counter >= TIMEOUT)
|
||||
break;
|
||||
}
|
||||
|
||||
float max_height = getMaxTileHeight(tile_idx);
|
||||
float max_height = std::max(getMaxTileHeight(tile_idx), 200.f);
|
||||
|
||||
// setup view matrices
|
||||
auto projection = math::ortho(
|
||||
@@ -2711,14 +2777,17 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
TILESIZE / 2.0f,
|
||||
-TILESIZE / 2.0f,
|
||||
TILESIZE / 2.0f,
|
||||
5.f,
|
||||
0.f,
|
||||
100000.0f
|
||||
);
|
||||
|
||||
auto look_at = math::look_at(math::vector_3d(TILESIZE * tile_idx.x + TILESIZE / 2.0f, max_height + 10.0f, TILESIZE * tile_idx.z + TILESIZE / 2.0f),
|
||||
math::vector_3d(TILESIZE * tile_idx.x + TILESIZE / 2.0f, max_height + 9.0f, TILESIZE * tile_idx.z + TILESIZE / 2.0 - 0.005f),
|
||||
math::vector_3d(TILESIZE * tile_idx.x + TILESIZE / 2.0f, max_height + 5.0f, TILESIZE * tile_idx.z + TILESIZE / 2.0 - 0.005f),
|
||||
math::vector_3d(0.f,1.f, 0.f));
|
||||
|
||||
glFinish();
|
||||
|
||||
|
||||
drawMinimap(mTile
|
||||
, look_at.transposed()
|
||||
, projection.transposed()
|
||||
@@ -2729,10 +2798,13 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
// Clearing alpha from image
|
||||
gl.colorMask(false, false, false, true);
|
||||
gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
gl.clear(GL_COLOR_BUFFER_BIT);
|
||||
gl.colorMask(true, true, true, true);
|
||||
|
||||
assert(pixel_buffer.isValid() && pixel_buffer.isBound());
|
||||
|
||||
QImage image = pixel_buffer.toImage();
|
||||
|
||||
image = image.convertToFormat(QImage::Format_RGBA8888);
|
||||
|
||||
QSettings app_settings;
|
||||
@@ -2776,24 +2848,9 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
}
|
||||
|
||||
// Write combined file
|
||||
if (settings->combined_minimap)
|
||||
if (settings->combined_minimap && combined_image.has_value())
|
||||
{
|
||||
QString image_path = QString(std::string(basename + "_combined_minimap.png").c_str());
|
||||
QImage combined_image;
|
||||
|
||||
if (dir.exists(image_path))
|
||||
{
|
||||
combined_image = QImage(dir.filePath(image_path));
|
||||
|
||||
if (combined_image.width() != 8192 | combined_image.height() != 8192)
|
||||
{
|
||||
combined_image = QImage(8192, 8192, QImage::Format_RGBA8888);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
combined_image = QImage(8192, 8192, QImage::Format_RGBA8888);
|
||||
}
|
||||
QImage& combined_image = combined_image;
|
||||
|
||||
QImage scaled_image = image.scaled(128, 128, Qt::KeepAspectRatio);
|
||||
|
||||
@@ -2805,22 +2862,18 @@ bool World::saveMinimap(tile_index const& tile_idx, MinimapRenderSettings* setti
|
||||
}
|
||||
}
|
||||
|
||||
combined_image.save(dir.filePath(image_path));
|
||||
|
||||
}
|
||||
|
||||
// Register in md5translate.trs
|
||||
std::string map_name = gMapDB.getMapName(mapIndex._map_id);
|
||||
std::string tilename_left = (boost::format("%s\\map_%d_%02d.blp") % map_name % tile_idx.x % tile_idx.z).str();
|
||||
std::string map_name = gMapDB.getByID(mapIndex._map_id).getString(MapDB::InternalName);
|
||||
std::string tilename_left = (boost::format("%s\\map%02d_%02d.blp") % map_name % tile_idx.x % tile_idx.z).str();
|
||||
mapIndex._minimap_md5translate[map_name][tilename_left] = tex_name;
|
||||
|
||||
/*
|
||||
if (unload)
|
||||
{
|
||||
mapIndex.unloadTile(tile_idx);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
pixel_buffer.release();
|
||||
@@ -3944,7 +3997,7 @@ void World::range_add_to_selection(math::vector_3d const& pos, float radius, boo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3953,6 +4006,7 @@ float World::getMaxTileHeight(const tile_index& tile)
|
||||
ZoneScoped;
|
||||
MapTile* m_tile = mapIndex.getTile(tile);
|
||||
|
||||
m_tile->forceRecalcExtents();
|
||||
float max_height = m_tile->getMaxHeight();
|
||||
|
||||
std::vector<uint32_t>* uids = m_tile->get_uids();
|
||||
@@ -3964,6 +4018,7 @@ float World::getMaxTileHeight(const tile_index& tile)
|
||||
if (instance.get().which() == eEntry_Object)
|
||||
{
|
||||
auto obj = boost::get<selected_object_type>(instance.get());
|
||||
obj->ensureExtents();
|
||||
max_height = std::max(max_height, std::max(obj->extents[0].y, obj->extents[1].y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ public:
|
||||
void updateTilesModel(ModelInstance* m2, model_update type);
|
||||
void wait_for_all_tile_updates();
|
||||
|
||||
bool saveMinimap (tile_index const& tile_idx, MinimapRenderSettings* settings);
|
||||
bool saveMinimap (tile_index const& tile_idx, MinimapRenderSettings* settings, std::optional<QImage>& combined_image);
|
||||
void drawMinimap ( MapTile *tile
|
||||
, math::matrix_4x4 const& model_view
|
||||
, math::matrix_4x4 const& projection
|
||||
@@ -491,7 +491,7 @@ private:
|
||||
|
||||
LiquidTextureManager _liquid_texture_manager;
|
||||
|
||||
std::array<MapTile*, 64 * 64> _loaded_tiles_buffer;
|
||||
std::array<std::pair<std::pair<int, int>, MapTile*>, 64 * 64 > _loaded_tiles_buffer;
|
||||
|
||||
bool _need_terrain_params_ubo_update = false;
|
||||
|
||||
|
||||
@@ -382,6 +382,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
||||
//QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QApplication qapp (argc, argv);
|
||||
qapp.setApplicationName ("Noggit");
|
||||
qapp.setOrganizationName ("Noggit");
|
||||
|
||||
@@ -1163,6 +1163,25 @@ void MapIndex::removeTile(const tile_index &tile)
|
||||
changed = true;
|
||||
}
|
||||
|
||||
unsigned MapIndex::getNumExistingTiles()
|
||||
{
|
||||
if (_n_existing_tiles >= 0)
|
||||
return _n_existing_tiles;
|
||||
|
||||
_n_existing_tiles = 0;
|
||||
for (int i = 0; i < 4096; ++i)
|
||||
{
|
||||
tile_index index(i / 64, i % 64);
|
||||
|
||||
if (hasTile(index))
|
||||
{
|
||||
_n_existing_tiles++;
|
||||
}
|
||||
}
|
||||
|
||||
return _n_existing_tiles;
|
||||
}
|
||||
|
||||
void MapIndex::set_basename(const std::string &pBasename)
|
||||
{
|
||||
basename = pBasename;
|
||||
|
||||
@@ -228,6 +228,8 @@ public:
|
||||
void addTile(const tile_index& tile);
|
||||
void removeTile(const tile_index& tile);
|
||||
|
||||
unsigned getNumExistingTiles();
|
||||
|
||||
// todo: find out how wow choose to use the green lava in outland
|
||||
inline bool use_mclq_green_lava() const
|
||||
{
|
||||
@@ -260,6 +262,7 @@ private:
|
||||
int _unload_interval;
|
||||
int _unload_dist;
|
||||
unsigned _n_loaded_tiles = 0; // to be loaded, not necessarily already loaded
|
||||
int _n_existing_tiles = -1;
|
||||
|
||||
// Is the WDT telling us to use a different alphamap structure.
|
||||
bool mBigAlpha;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <QWheelEvent>
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
#include <QProgressBar>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
@@ -130,10 +129,6 @@ namespace noggit
|
||||
draw_elements_box_layout->addWidget(combined_minimap, 3, 1);
|
||||
|
||||
|
||||
_progress_bar = new QProgressBar(this);
|
||||
_progress_bar->setRange(0, 4096);
|
||||
generate_layout->addRow(_progress_bar);
|
||||
|
||||
// Filter
|
||||
auto filter_widget = new QWidget(this);
|
||||
filter_widget->setContentsMargins(0, 0, 0, 0);
|
||||
@@ -351,22 +346,7 @@ namespace noggit
|
||||
|
||||
// Minimap
|
||||
|
||||
auto scroll_minimap = new QScrollArea(this);
|
||||
scroll_minimap->setFixedSize(226, 226);
|
||||
|
||||
_minimap_widget = new minimap_widget(this);
|
||||
layout->addWidget(scroll_minimap);
|
||||
|
||||
scroll_minimap->setAlignment(Qt::AlignCenter);
|
||||
scroll_minimap->setWidget(_minimap_widget);
|
||||
scroll_minimap->setWidgetResizable(true);
|
||||
|
||||
_minimap_widget->world(world);
|
||||
_minimap_widget->draw_boundaries(true);
|
||||
_minimap_widget->use_selection(&_render_settings.selected_tiles);
|
||||
_minimap_widget->camera(mapView->getCamera());
|
||||
|
||||
scroll_minimap->ensureWidgetVisible(_minimap_widget, 0, 0);
|
||||
_minimap_widget = mapView->getMinimapWidget();
|
||||
|
||||
loadFiltersFromJSON();
|
||||
|
||||
@@ -859,51 +839,6 @@ namespace noggit
|
||||
mapView->initMinimapSave();
|
||||
});
|
||||
|
||||
// Selection
|
||||
|
||||
QObject::connect
|
||||
( _minimap_widget, &minimap_widget::tile_clicked
|
||||
, [this, world] (QPoint tile)
|
||||
{
|
||||
if (QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier))
|
||||
{
|
||||
int x = tile.x() - 1;
|
||||
int y = tile.y() - 1;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (world->mapIndex.hasTile(tile_index(x + i, y + j)))
|
||||
{
|
||||
_render_settings.selected_tiles[64 * (x + i) + (y + j)]
|
||||
= !QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (world->mapIndex.hasTile(tile_index(tile.x(), tile.y())))
|
||||
{
|
||||
_render_settings.selected_tiles[64 * tile.x() + tile.y()]
|
||||
= !QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
);
|
||||
|
||||
QObject::connect
|
||||
( _minimap_widget, &minimap_widget::reset_selection
|
||||
, [this, world] ()
|
||||
{
|
||||
_render_settings.selected_tiles.fill(false);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
void MinimapCreator::changeRadius(float change)
|
||||
@@ -916,31 +851,6 @@ namespace noggit
|
||||
return QSize(width(), height());
|
||||
}
|
||||
|
||||
void MinimapCreator::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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MinimapCreator::includeM2Model(std::string filename, float size_cat)
|
||||
{
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
#include <QSlider>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QSpinBox>
|
||||
#include <QProgressBar>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QApplication>
|
||||
#include <qt-color-widgets/color_selector.hpp>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
@@ -89,9 +89,6 @@ namespace noggit
|
||||
MinimapRenderSettings* getMinimapRenderSettings() { return &_render_settings; };
|
||||
|
||||
QSize sizeHint() const override;
|
||||
void wheelEvent(QWheelEvent* event) override;
|
||||
|
||||
void progressUpdate(int value) { _progress_bar->setValue(value); };
|
||||
|
||||
void includeM2Model(std::string filename, float size_cat = 0.0f);
|
||||
void unincludeM2Model(std::string filename);
|
||||
@@ -112,7 +109,6 @@ namespace noggit
|
||||
QSlider* _radius_slider;
|
||||
QDoubleSpinBox* _radius_spin;
|
||||
minimap_widget* _minimap_widget;
|
||||
QProgressBar* _progress_bar;
|
||||
QListWidget* _m2_model_filter_include;
|
||||
QListWidget* _m2_instance_filter_include;
|
||||
QListWidget* _wmo_model_filter_exclude;
|
||||
|
||||
@@ -23,16 +23,96 @@ namespace noggit
|
||||
, _world (nullptr)
|
||||
, _camera (nullptr)
|
||||
, _draw_skies (false)
|
||||
, _selected_tiles(nullptr)
|
||||
, _resizeable(false)
|
||||
{
|
||||
setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
//setMouseTracking(true);
|
||||
setMouseTracking(true);
|
||||
setMaximumSize(QSize(1024, 1024));
|
||||
setMinimumSize(QSize(128, 128));
|
||||
|
||||
|
||||
|
||||
connect(this, &minimap_widget::tile_clicked
|
||||
, [this](QPoint tile)
|
||||
{
|
||||
if (!_selected_tiles)
|
||||
return;
|
||||
|
||||
if (QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier))
|
||||
{
|
||||
int x = tile.x() - 1;
|
||||
int y = tile.y() - 1;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
if (_world->mapIndex.hasTile(tile_index(x + i, y + j)))
|
||||
{
|
||||
(*_selected_tiles)[64 * (x + i) + (y + j)]
|
||||
= !QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_world->mapIndex.hasTile(tile_index(tile.x(), tile.y())))
|
||||
{
|
||||
(*_selected_tiles)[64 * tile.x() + tile.y()]
|
||||
= !QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
);
|
||||
|
||||
connect(this, &minimap_widget::reset_selection
|
||||
, [this]()
|
||||
{
|
||||
if (!_selected_tiles)
|
||||
return;
|
||||
|
||||
_selected_tiles->fill(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void minimap_widget::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
if (!_resizeable)
|
||||
return;
|
||||
|
||||
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
|
||||
{
|
||||
const int degrees = event->angleDelta().y() / 8;
|
||||
int steps = degrees / 15;
|
||||
|
||||
auto base_size = width();
|
||||
|
||||
if (steps > 0)
|
||||
{
|
||||
auto new_size = std::min(std::max(128, base_size + 64), 4096);
|
||||
setFixedSize(new_size, new_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto new_size = std::max(std::min(4096, base_size - 64), 128);
|
||||
setFixedSize(new_size, new_size);
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QSize minimap_widget::sizeHint() const
|
||||
{
|
||||
return QSize (1024, 1024);
|
||||
return QSize (512, 512);
|
||||
}
|
||||
|
||||
//! \todo Only redraw stuff as told in event.
|
||||
@@ -233,7 +313,7 @@ namespace noggit
|
||||
|
||||
void minimap_widget::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
if (world())
|
||||
if (_world)
|
||||
{
|
||||
QPoint tile = locateTile(event);
|
||||
|
||||
|
||||
@@ -41,10 +41,11 @@ namespace noggit
|
||||
inline const bool& draw_boundaries() const { return _draw_boundaries; }
|
||||
|
||||
inline const std::array<bool, 4096>* use_selection (std::array<bool, 4096>* selection_)
|
||||
{ _use_selection = true; _selected_tiles = selection_; update(); return _selected_tiles; }
|
||||
{ _use_selection = selection_; _selected_tiles = selection_; update(); return _selected_tiles; }
|
||||
inline const std::array<bool, 4096>* selection() const { return _selected_tiles; }
|
||||
|
||||
inline void camera (noggit::camera* camera) { _camera = camera; }
|
||||
void set_resizeable(bool state) { _resizeable = state; };
|
||||
|
||||
protected:
|
||||
virtual void paintEvent (QPaintEvent*) override;
|
||||
@@ -52,6 +53,7 @@ namespace noggit
|
||||
virtual void mouseMoveEvent(QMouseEvent*) override;
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void wheelEvent(QWheelEvent* event) override;
|
||||
|
||||
QPoint locateTile(QMouseEvent* event);
|
||||
|
||||
@@ -68,6 +70,7 @@ namespace noggit
|
||||
bool _draw_skies;
|
||||
bool _draw_camera;
|
||||
bool _draw_boundaries;
|
||||
bool _resizeable;
|
||||
|
||||
bool _use_selection = false;
|
||||
bool _is_selecting = false;
|
||||
|
||||
Reference in New Issue
Block a user