implement loading and rendering global wmo maps
This commit is contained in:
@@ -2811,7 +2811,11 @@ void MapView::move_camera_with_auto_height (glm::vec3 const& pos)
|
||||
makeCurrent();
|
||||
OpenGL::context::scoped_setter const _ (::gl, context());
|
||||
|
||||
_world->mapIndex.loadTile(pos)->wait_until_loaded();
|
||||
TileIndex tile_index = TileIndex(pos);
|
||||
if (_world->mapIndex.hasTile(tile_index))
|
||||
{
|
||||
_world->mapIndex.loadTile(pos)->wait_until_loaded();
|
||||
}
|
||||
|
||||
_camera.position = pos;
|
||||
_camera.position.y = 0.0f;
|
||||
|
||||
@@ -64,7 +64,7 @@ bool World::IsEditableWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow
|
||||
// Not using the libWDT here doubles performance. You might want to look at your lib again and improve it.
|
||||
const int lFlags = *(reinterpret_cast<const int*>(lPointer + 8 + 4 + 8));
|
||||
if (lFlags & 1)
|
||||
return false;
|
||||
return true; // filter them later
|
||||
|
||||
const int * lData = reinterpret_cast<const int*>(lPointer + 8 + 4 + 8 + 0x20 + 8);
|
||||
for (int i = 0; i < 8192; i += 2)
|
||||
@@ -76,14 +76,33 @@ bool World::IsEditableWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow
|
||||
return false;
|
||||
}
|
||||
|
||||
bool World::IsWMOWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow& record)
|
||||
{
|
||||
ZoneScoped;
|
||||
std::string lMapName = record.Columns["Directory"].Value;
|
||||
|
||||
std::stringstream ssfilename;
|
||||
ssfilename << "World\\Maps\\" << lMapName << "\\" << lMapName << ".wdt";
|
||||
|
||||
BlizzardArchive::ClientFile mf(ssfilename.str(), Noggit::Application::NoggitApplication::instance()->clientData());
|
||||
|
||||
const char* lPointer = reinterpret_cast<const char*>(mf.getPointer());
|
||||
|
||||
const int lFlags = *(reinterpret_cast<const int*>(lPointer + 8 + 4 + 8));
|
||||
if (lFlags & 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
World::World(const std::string& name, int map_id, Noggit::NoggitRenderContext context, bool create_empty)
|
||||
: _renderer(Noggit::Rendering::WorldRender(this))
|
||||
, _model_instance_storage(this)
|
||||
, _tile_update_queue(this)
|
||||
, mapIndex(name, map_id, this, context, create_empty)
|
||||
, horizon(name, &mapIndex)
|
||||
, mWmoFilename("")
|
||||
, mWmoEntry(ENTRY_MODF())
|
||||
, mWmoFilename(mapIndex.globalWMOName)
|
||||
, mWmoEntry(mapIndex.wmoEntry)
|
||||
, animtime(0)
|
||||
, time(1450)
|
||||
, basename(name)
|
||||
|
||||
@@ -312,6 +312,8 @@ public:
|
||||
|
||||
static bool IsEditableWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow& record);
|
||||
|
||||
static bool IsWMOWorld(BlizzardDatabaseLib::Structures::BlizzardDatabaseRow& record);
|
||||
|
||||
void clearHeight(glm::vec3 const& pos);
|
||||
void clearAllModelsOnADT(TileIndex const& tile);
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ MapIndex::MapIndex (const std::string &pBasename, int map_id, World* world,
|
||||
//! \bug MODF reads wrong. The assertion fails every time. Somehow, it keeps being MWMO. Or are there two blocks?
|
||||
//! \nofuckingbug on eof read returns just without doing sth to the var and some wdts have a MWMO without having a MODF so only checking for eof above is not enough
|
||||
|
||||
mHasAGlobalWMO = false;
|
||||
// mHasAGlobalWMO = false;
|
||||
|
||||
// - MWMO ----------------------------------------------
|
||||
|
||||
|
||||
@@ -273,10 +273,9 @@ private:
|
||||
public:
|
||||
int const _map_id;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> _minimap_md5translate;
|
||||
|
||||
private:
|
||||
std::string globalWMOName;
|
||||
|
||||
ENTRY_MODF wmoEntry;
|
||||
private:
|
||||
int _last_unload_time;
|
||||
int _unload_interval;
|
||||
int _unload_dist;
|
||||
@@ -295,7 +294,6 @@ private:
|
||||
|
||||
uint32_t highestGUID;
|
||||
|
||||
ENTRY_MODF wmoEntry;
|
||||
MPHD mphd;
|
||||
|
||||
// Holding all MapTiles there can be in a World.
|
||||
|
||||
@@ -464,6 +464,19 @@ void WorldRender::draw (glm::mat4x4 const& model_view
|
||||
|
||||
wmo_program.uniform("camera", glm::vec3(camera_pos.x, camera_pos.y, camera_pos.z));
|
||||
|
||||
// make this check per WMO or global WMO with tiles may not work
|
||||
bool disable_cull = false;
|
||||
|
||||
if (_world->mapIndex.hasAGlobalWMO() && !wmos_to_draw.size())
|
||||
{
|
||||
auto global_wmo = _world->_model_instance_storage.get_wmo_instance(_world->mWmoEntry.uniqueID);
|
||||
if (global_wmo.has_value())
|
||||
{
|
||||
wmos_to_draw.push_back(global_wmo.value());
|
||||
disable_cull = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (auto& instance: wmos_to_draw)
|
||||
{
|
||||
@@ -526,7 +539,7 @@ void WorldRender::draw (glm::mat4x4 const& model_view
|
||||
, _world->animtime
|
||||
, _skies->hasSkies()
|
||||
, display
|
||||
, false
|
||||
, disable_cull
|
||||
, draw_wmo_exterior
|
||||
|
||||
);
|
||||
|
||||
@@ -248,7 +248,33 @@ namespace Noggit
|
||||
|
||||
painter.drawLine (camera_vector);
|
||||
}
|
||||
}
|
||||
|
||||
if (_world->mapIndex.hasAGlobalWMO())
|
||||
{
|
||||
painter.setPen(QColor::fromRgbF(1.0f, 0.0f, 0.0f, 1.f));
|
||||
|
||||
auto extents = _world->mWmoEntry.extents;
|
||||
|
||||
// WMOInstance inst(_world->mWmoFilename, &_world->mWmoEntry, _world->_context);
|
||||
|
||||
float pos = tile_size * 64 / 2; // TODO : convert wmo pos
|
||||
|
||||
float min_point_x = pos + (extents[0][0] / TILESIZE * tile_size); // extents[min][x]
|
||||
float min_point_y = pos + (extents[0][1] / TILESIZE * tile_size); // extents[min][y]
|
||||
float max_point_x = pos + (extents[1][0] / TILESIZE * tile_size);
|
||||
float max_point_y = pos + (extents[1][1] / TILESIZE * tile_size);
|
||||
// tile_size = 14 | max size = 896
|
||||
|
||||
float width = max_point_x - min_point_x;
|
||||
float height = max_point_y - min_point_y;
|
||||
painter.drawRect(QRectF(min_point_x
|
||||
, min_point_y
|
||||
, width // width
|
||||
, height // height
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//! \todo Draw something so user realizes this will become the minimap.
|
||||
@@ -283,7 +309,7 @@ namespace Noggit
|
||||
|
||||
QPoint tile = locateTile(event);
|
||||
|
||||
if (!world()->mapIndex.hasTile (TileIndex (tile.x(), tile.y())))
|
||||
if (!world()->mapIndex.hasTile (TileIndex (tile.x(), tile.y())) && !_world->mapIndex.hasAGlobalWMO())
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
|
||||
@@ -173,6 +173,28 @@ namespace Noggit::Ui::Windows
|
||||
bool from_bookmark
|
||||
)
|
||||
{
|
||||
if (_world->mapIndex.hasAGlobalWMO())
|
||||
{
|
||||
// enter at mdoel's position
|
||||
// pos = glm::vec3(_world->mWmoEntry[0], _world->mWmoEntry.pos[1], _world->mWmoEntry.pos[2]);
|
||||
|
||||
// better, enter at model's max extent, facing toward min extent
|
||||
auto min_extent = glm::vec3(_world->mWmoEntry.extents[0][0], _world->mWmoEntry.extents[0][1], _world->mWmoEntry.extents[0][2]);
|
||||
auto max_extent = glm::vec3(_world->mWmoEntry.extents[1][0], _world->mWmoEntry.extents[1][1] * 2, _world->mWmoEntry.extents[1][2]);
|
||||
float dx = min_extent.x - max_extent.x;
|
||||
float dy = min_extent.z - max_extent.z; // flipping z and y works better for some reason
|
||||
float dz = min_extent.y - max_extent.y;
|
||||
|
||||
pos = max_extent;
|
||||
|
||||
camera_yaw = math::degrees(math::radians(std::atan2(dx, dy)));
|
||||
|
||||
float distance = std::sqrt(dx * dx + dy * dy + dz * dz);
|
||||
camera_pitch = math::degrees(math::radians(std::asin(dz / distance)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
_map_creation_wizard->destroyFakeWorld();
|
||||
_map_view = (new MapView(camera_yaw, camera_pitch, pos, this, _project, std::move(_world), uid_fix, from_bookmark));
|
||||
connect(_map_view, &MapView::uid_fix_failed, [this]()
|
||||
@@ -187,7 +209,7 @@ namespace Noggit::Ui::Windows
|
||||
|
||||
}
|
||||
|
||||
void NoggitWindow::applyFilterSearch(const QString &name, int type, int expansion)
|
||||
void NoggitWindow::applyFilterSearch(const QString &name, int type, int expansion, bool wmo_maps)
|
||||
{
|
||||
for (int i = 0; i < _continents_table->count(); ++i)
|
||||
{
|
||||
@@ -215,6 +237,11 @@ namespace Noggit::Ui::Windows
|
||||
{
|
||||
item_widget->setHidden(true);
|
||||
}
|
||||
|
||||
if (!(widget->wmo_map() == wmo_maps))
|
||||
{
|
||||
item_widget->setHidden(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,26 +321,33 @@ namespace Noggit::Ui::Windows
|
||||
_combo_exp_search->addItem(QIcon(":/icon-shadow"), tr("Shadowlands"));
|
||||
_combo_exp_search->setCurrentIndex(0);
|
||||
|
||||
QObject::connect(_line_edit_search, QOverload<const QString&>::of(&QLineEdit::textChanged), [this, _combo_search, _combo_exp_search](const QString &name)
|
||||
QCheckBox* _wmo_maps_search = new QCheckBox("Display WMO maps (No terrain)", this);
|
||||
|
||||
QObject::connect(_line_edit_search, QOverload<const QString&>::of(&QLineEdit::textChanged), [this, _combo_search, _combo_exp_search, _wmo_maps_search](const QString &name)
|
||||
{
|
||||
applyFilterSearch(name, _combo_search->currentIndex(), _combo_exp_search->currentIndex());
|
||||
applyFilterSearch(name, _combo_search->currentIndex(), _combo_exp_search->currentIndex(), _wmo_maps_search->isChecked());
|
||||
});
|
||||
|
||||
QObject::connect(_combo_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_exp_search](int index)
|
||||
QObject::connect(_combo_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_exp_search, _wmo_maps_search](int index)
|
||||
{
|
||||
applyFilterSearch(_line_edit_search->text(), index, _combo_exp_search->currentIndex());
|
||||
applyFilterSearch(_line_edit_search->text(), index, _combo_exp_search->currentIndex(), _wmo_maps_search->isChecked());
|
||||
});
|
||||
|
||||
QObject::connect(_combo_exp_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_search](int index)
|
||||
QObject::connect(_combo_exp_search, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, _line_edit_search, _combo_search, _wmo_maps_search](int index)
|
||||
{
|
||||
applyFilterSearch(_line_edit_search->text(), _combo_search->currentIndex(), index);
|
||||
applyFilterSearch(_line_edit_search->text(), _combo_search->currentIndex(), index, _wmo_maps_search->isChecked());
|
||||
});
|
||||
|
||||
QObject::connect(_wmo_maps_search, &QCheckBox::stateChanged, [this, _line_edit_search, _combo_search, _combo_exp_search](bool b)
|
||||
{
|
||||
applyFilterSearch(_line_edit_search->text(), _combo_search->currentIndex(), _combo_exp_search->currentIndex(), b);
|
||||
});
|
||||
|
||||
QFormLayout* _group_layout = new QFormLayout();
|
||||
_group_layout->addRow(tr("Name : "), _line_edit_search);
|
||||
_group_layout->addRow(tr("Type : "), _combo_search);
|
||||
_group_layout->addRow(tr("Expansion : "), _combo_exp_search);
|
||||
_group_layout->addRow( _wmo_maps_search);
|
||||
_group_search->setLayout(_group_layout);
|
||||
|
||||
_first_tab_layout->addWidget(_group_search);
|
||||
@@ -374,7 +408,10 @@ namespace Noggit::Ui::Windows
|
||||
|
||||
QObject::connect(_minimap, &minimap_widget::map_clicked, [this](::glm::vec3 const& pos)
|
||||
{
|
||||
check_uid_then_enter_map(pos, math::degrees(30.f), math::degrees(90.f));
|
||||
if (_world->mapIndex.hasAGlobalWMO()) // skip uid check
|
||||
enterMapAt(pos, math::degrees(30.f), math::degrees(90.f), uid_fix_mode::none, false);
|
||||
else
|
||||
check_uid_then_enter_map(pos, math::degrees(30.f), math::degrees(90.f));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Noggit::Ui::Windows
|
||||
QListWidget* _continents_table;
|
||||
QString _filter_name;
|
||||
|
||||
void applyFilterSearch(const QString& name, int type, int expansion);
|
||||
void applyFilterSearch(const QString& name, int type, int expansion, bool wmo_maps);
|
||||
|
||||
std::unique_ptr<World> _world;
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ void BuildMapListComponent::buildMapList(Noggit::Ui::Windows::NoggitWindow* pare
|
||||
if (map_list_data.map_type_id < 0 || map_list_data.map_type_id > 5 || !World::IsEditableWorld(record))
|
||||
continue;
|
||||
|
||||
map_list_data.wmo_map = (World::IsWMOWorld(record));
|
||||
|
||||
auto project_pinned_maps = parent->_project->PinnedMaps;
|
||||
|
||||
auto pinned_map_found = std::find_if(std::begin(project_pinned_maps), std::end(project_pinned_maps),
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace Noggit::Ui::Widget
|
||||
int map_type_id;
|
||||
int expansion_id;
|
||||
bool pinned;
|
||||
bool wmo_map;
|
||||
};
|
||||
|
||||
class MapListItem : public QWidget
|
||||
@@ -40,6 +41,7 @@ namespace Noggit::Ui::Widget
|
||||
int id() { return _map_data.map_id; };
|
||||
int type() { return _map_data.map_type_id; };
|
||||
int expansion() { return _map_data.expansion_id; };
|
||||
bool wmo_map() { return _map_data.wmo_map; };
|
||||
|
||||
private:
|
||||
QString toCamelCase(const QString& s);
|
||||
|
||||
Reference in New Issue
Block a user