Merge branch 'sql_update' into 'noggit-shadowlands'
Update See merge request prophecy-rp/noggit-red!44
This commit is contained in:
@@ -81,8 +81,10 @@ namespace mysql
|
||||
{
|
||||
|
||||
prompt.setIcon(QMessageBox::Warning);
|
||||
prompt.setText("Failed to load MySQL database, check your settings.");
|
||||
prompt.setText("Failed to load MySQL database, check your settings. \nIf you did not intend to use this feature, disable it in Noggit->settings->MySQL");
|
||||
prompt.setWindowTitle("Noggit Database Error");
|
||||
// disable if connection is not valid
|
||||
// settings.value("project/mysql/enabled") = false;
|
||||
std::stringstream promptText;
|
||||
|
||||
promptText << "\n# ERR: " << e.what();
|
||||
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
|
||||
MapChunk* getChunk() { return _chunk; };
|
||||
TileWater* getWaterTile() { return _water_tile; };
|
||||
|
||||
std::optional<MH2O_Render> Render;
|
||||
float xbase, zbase;
|
||||
|
||||
private:
|
||||
@@ -84,9 +84,11 @@ private:
|
||||
void copy_height_to_layer(liquid_layer& target, glm::vec3 const& pos, float radius);
|
||||
|
||||
|
||||
std::optional<MH2O_Render> Render;
|
||||
|
||||
|
||||
std::vector<liquid_layer> _layers;
|
||||
MapChunk* _chunk;
|
||||
TileWater* _water_tile;
|
||||
|
||||
friend class MapView;
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
#include <QImage>
|
||||
#include <limits>
|
||||
|
||||
MapChunk::MapChunk(MapTile* maintile, BlizzardArchive::ClientFile* f, bool bigAlpha,
|
||||
tile_mode mode, Noggit::NoggitRenderContext context, bool init_empty, int chunk_idx)
|
||||
MapChunk::MapChunk(MapTile* maintile, BlizzardArchive::ClientFile* f, bool bigAlpha,tile_mode mode
|
||||
, Noggit::NoggitRenderContext context, bool init_empty, int chunk_idx, bool load_textures)
|
||||
: _mode(mode)
|
||||
, mt(maintile)
|
||||
, use_big_alphamap(bigAlpha)
|
||||
@@ -148,6 +148,11 @@ MapChunk::MapChunk(MapTile* maintile, BlizzardArchive::ClientFile* f, bool bigAl
|
||||
xbase = xbase*-1.0f + ZEROPOINT;
|
||||
}
|
||||
|
||||
if (!load_textures)
|
||||
{
|
||||
this->header.nLayers = 0;
|
||||
}
|
||||
|
||||
texture_set = std::make_unique<TextureSet>(this, f, base, maintile, bigAlpha,
|
||||
!!header_flags.flags.do_not_fix_alpha_map, mode == tile_mode::uid_fix_all, _context);
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
|
||||
public:
|
||||
MapChunk(MapTile* mt, BlizzardArchive::ClientFile* f, bool bigAlpha, tile_mode mode, Noggit::NoggitRenderContext context
|
||||
, bool init_empty = false, int chunk_idx = 0);
|
||||
, bool init_empty = false, int chunk_idx = 0, bool load_textures = true);
|
||||
|
||||
auto getHoleMask(void) const -> unsigned { return static_cast<unsigned>(holes); }
|
||||
MapTile *mt;
|
||||
|
||||
@@ -41,6 +41,7 @@ MapTile::MapTile( int pX
|
||||
, World* world
|
||||
, Noggit::NoggitRenderContext context
|
||||
, tile_mode mode
|
||||
, bool pLoadTextures
|
||||
)
|
||||
: AsyncObject(pFilename)
|
||||
, _renderer(this)
|
||||
@@ -54,6 +55,7 @@ MapTile::MapTile( int pX
|
||||
, _tile_is_being_reloaded(reloading_tile)
|
||||
, mBigAlpha(pBigAlpha)
|
||||
, _load_models(pLoadModels)
|
||||
, _load_textures(pLoadTextures)
|
||||
, _world(world)
|
||||
, _context(context)
|
||||
, _chunk_update_flags(ChunkUpdateFlags::VERTEX | ChunkUpdateFlags::ALPHAMAP
|
||||
@@ -161,23 +163,25 @@ void MapTile::finishLoading()
|
||||
|
||||
// - MTEX ----------------------------------------------
|
||||
|
||||
theFile.seek(Header.mtex + 0x14);
|
||||
theFile.read(&fourcc, 4);
|
||||
theFile.read(&size, 4);
|
||||
|
||||
assert(fourcc == 'MTEX');
|
||||
|
||||
if (_load_textures)
|
||||
{
|
||||
char const* lCurPos = reinterpret_cast<char const*>(theFile.getPointer());
|
||||
char const* lEnd = lCurPos + size;
|
||||
theFile.seek(Header.mtex + 0x14);
|
||||
theFile.read(&fourcc, 4);
|
||||
theFile.read(&size, 4);
|
||||
|
||||
assert(fourcc == 'MTEX');
|
||||
|
||||
while (lCurPos < lEnd)
|
||||
{
|
||||
mTextureFilenames.push_back(BlizzardArchive::ClientData::normalizeFilenameInternal(std::string(lCurPos)));
|
||||
lCurPos += strlen(lCurPos) + 1;
|
||||
char const* lCurPos = reinterpret_cast<char const*>(theFile.getPointer());
|
||||
char const* lEnd = lCurPos + size;
|
||||
|
||||
while (lCurPos < lEnd)
|
||||
{
|
||||
mTextureFilenames.push_back(BlizzardArchive::ClientData::normalizeFilenameInternal(std::string(lCurPos)));
|
||||
lCurPos += strlen(lCurPos) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_load_models)
|
||||
{
|
||||
// - MMDX ----------------------------------------------
|
||||
@@ -359,7 +363,7 @@ void MapTile::finishLoading()
|
||||
unsigned x = nextChunk / 16;
|
||||
unsigned z = nextChunk % 16;
|
||||
|
||||
mChunks[x][z] = std::make_unique<MapChunk> (this, &theFile, mBigAlpha, _mode, _context);
|
||||
mChunks[x][z] = std::make_unique<MapChunk> (this, &theFile, mBigAlpha, _mode, _context, false, 0, _load_textures);
|
||||
|
||||
auto& chunk = mChunks[x][z];
|
||||
_renderer.initChunkData(chunk.get());
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
, World*
|
||||
, Noggit::NoggitRenderContext context
|
||||
, tile_mode mode = tile_mode::edit
|
||||
, bool pLoadTextures = true
|
||||
);
|
||||
~MapTile();
|
||||
|
||||
@@ -205,6 +206,7 @@ private:
|
||||
std::array<float, 145 * 256 * 4> _chunk_heightmap_buffer;
|
||||
|
||||
bool _load_models;
|
||||
bool _load_textures;
|
||||
World* _world;
|
||||
|
||||
|
||||
|
||||
@@ -232,16 +232,31 @@ void MapView::set_editing_mode(editing_mode mode)
|
||||
_viewport_overlay_ui->gizmoBar->hide();
|
||||
}
|
||||
|
||||
auto previous_mode = _left_sec_toolbar->getCurrentMode();
|
||||
|
||||
_left_sec_toolbar->setCurrentMode(this, mode);
|
||||
|
||||
if (context() && context()->isValid())
|
||||
{
|
||||
if (mode == editing_mode::holes && previous_mode != editing_mode::holes)
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_lines = true;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_hole_lines = true;
|
||||
}
|
||||
else if (previous_mode == editing_mode::holes && mode != editing_mode::holes)
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_lines = _draw_lines.get();
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_hole_lines = _draw_hole_lines.get();
|
||||
}
|
||||
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_areaid_overlay = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_impass_overlay = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = false;
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_selection_overlay = false;
|
||||
_minimap->use_selection(nullptr);
|
||||
|
||||
bool use_classic_ui = _settings->value("classicUI", true).toBool();
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case editing_mode::ground:
|
||||
@@ -255,9 +270,20 @@ void MapView::set_editing_mode(editing_mode mode)
|
||||
{
|
||||
texturingTool->updateMaskImage();
|
||||
}
|
||||
if (_left_sec_toolbar->showUnpaintableChunk())
|
||||
|
||||
if (use_classic_ui)
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = true;
|
||||
if (texturingTool->show_unpaintable_chunks())
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_left_sec_toolbar->showUnpaintableChunk())
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case editing_mode::mccv:
|
||||
@@ -1877,62 +1903,63 @@ void MapView::setupViewMenu()
|
||||
view_menu->addAction(createTextSeparator("Drawing"));
|
||||
view_menu->addSeparator();
|
||||
ADD_TOGGLE (view_menu, "Doodads", Qt::Key_F1, _draw_models);
|
||||
ADD_TOGGLE (view_menu, "WMOs", Qt::Key_F2, _draw_wmo);
|
||||
ADD_TOGGLE (view_menu, "WMO doodads", Qt::Key_F3, _draw_wmo_doodads);
|
||||
ADD_TOGGLE (view_menu, "Terrain", Qt::Key_F4, _draw_terrain);
|
||||
ADD_TOGGLE (view_menu, "Water", Qt::Key_F5, _draw_water);
|
||||
ADD_TOGGLE (view_menu, "WMO doodads", Qt::Key_F2, _draw_wmo_doodads);
|
||||
ADD_TOGGLE (view_menu, "Terrain", Qt::Key_F3, _draw_terrain);
|
||||
ADD_TOGGLE (view_menu, "Water", Qt::Key_F4, _draw_water);
|
||||
ADD_TOGGLE (view_menu, "WMOs", Qt::Key_F6, _draw_wmo);
|
||||
|
||||
ADD_TOGGLE_POST (view_menu, "Lines", Qt::SHIFT | Qt::Key_F1, _draw_lines,
|
||||
ADD_TOGGLE_POST (view_menu, "Lines", Qt::Key_F7, _draw_lines,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_lines = _draw_lines.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST (view_menu, "Hole lines", Qt::SHIFT | Qt::Key_F2, _draw_hole_lines,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_hole_lines = _draw_hole_lines.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST (view_menu, "Wireframe", Qt::SHIFT | Qt::Key_F3, _draw_wireframe,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_wireframe = _draw_wireframe.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST (view_menu, "Contours", Qt::SHIFT | Qt::Key_F4, _draw_contour,
|
||||
ADD_TOGGLE_POST (view_menu, "Contours", Qt::Key_F9, _draw_contour,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_terrain_height_contour = _draw_contour.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST(view_menu, "Climb", Qt::SHIFT | Qt::Key_F5, _draw_climb,
|
||||
ADD_TOGGLE_POST (view_menu, "Wireframe", Qt::Key_F10, _draw_wireframe,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_wireframe = _draw_wireframe.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE (view_menu, "Toggle Animation", Qt::Key_F11, _draw_model_animations);
|
||||
ADD_TOGGLE (view_menu, "Draw fog", Qt::Key_F12, _draw_fog);
|
||||
|
||||
ADD_TOGGLE_POST (view_menu, "Hole lines", Qt::SHIFT | Qt::Key_F1, _draw_hole_lines,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_hole_lines = _draw_hole_lines.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST(view_menu, "Climb", Qt::SHIFT | Qt::Key_F2, _draw_climb,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_impassible_climb = _draw_climb.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST(view_menu, "Vertex Color", Qt::SHIFT | Qt::Key_F6, _draw_vertex_color,
|
||||
ADD_TOGGLE_POST(view_menu, "Vertex Color", Qt::SHIFT | Qt::Key_F3, _draw_vertex_color,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_vertex_color = _draw_vertex_color.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE_POST(view_menu, "Baked Shadows", Qt::SHIFT | Qt::Key_F7, _draw_baked_shadows,
|
||||
ADD_TOGGLE_POST(view_menu, "Baked Shadows", Qt::SHIFT | Qt::Key_F4, _draw_baked_shadows,
|
||||
[=]
|
||||
{
|
||||
_world->renderer()->getTerrainParamsUniformBlock()->draw_shadows = _draw_baked_shadows.get();
|
||||
_world->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
ADD_TOGGLE (view_menu, "Toggle Animation", Qt::Key_F11, _draw_model_animations);
|
||||
ADD_TOGGLE (view_menu, "Draw fog", Qt::Key_F12, _draw_fog);
|
||||
ADD_TOGGLE_NS (view_menu, "Flight Bounds", _draw_mfbo);
|
||||
|
||||
ADD_TOGGLE_NS (view_menu, "Models with box", _draw_models_with_box);
|
||||
@@ -2042,7 +2069,6 @@ void MapView::setupViewMenu()
|
||||
{
|
||||
_camera.add_to_yaw(math::degrees(180.f));
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -2265,6 +2291,7 @@ void MapView::setupHotkeys()
|
||||
, [&]
|
||||
{
|
||||
_left_sec_toolbar->nextFlattenMode(this);
|
||||
flattenTool->nextFlattenMode();
|
||||
}
|
||||
, [&] { return terrainMode == editing_mode::flatten_blur && !NOGGIT_CUR_ACTION; }
|
||||
);
|
||||
@@ -2796,7 +2823,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;
|
||||
@@ -2813,7 +2844,6 @@ void MapView::move_camera_with_auto_height (glm::vec3 const& pos)
|
||||
|
||||
_camera.position.y += 50.0f;
|
||||
|
||||
_minimap->update();
|
||||
_camera_moved_since_last_draw = true;
|
||||
}
|
||||
|
||||
@@ -3968,20 +3998,22 @@ void MapView::tick (float dt)
|
||||
if (moving)
|
||||
{
|
||||
_camera.move_forward(moving, dt);
|
||||
_camera_moved_since_last_draw = true;
|
||||
// TODO use normalized speed (doesn't slow down when looking up)
|
||||
// _camera.move_forward_normalized(moving, dt);
|
||||
}
|
||||
if (strafing)
|
||||
{
|
||||
_camera.move_horizontal(strafing, dt);
|
||||
_camera_moved_since_last_draw = true;
|
||||
}
|
||||
|
||||
// get ground z position
|
||||
// can be optimized by calling this only when moving/strafing or changing camera mode.
|
||||
auto ground_pos = _world.get()->get_ground_height(_camera.position);
|
||||
_camera.position.y = ground_pos.y + 2;
|
||||
_camera_moved_since_last_draw = true;
|
||||
|
||||
// hack to update camera when entering mode in void ViewToolbar::add_tool_icon()
|
||||
if (_camera_moved_since_last_draw)
|
||||
{
|
||||
auto ground_pos = _world.get()->get_ground_height(_camera.position);
|
||||
_camera.position.y = ground_pos.y + 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4033,7 +4065,7 @@ void MapView::tick (float dt)
|
||||
}
|
||||
}
|
||||
|
||||
_minimap->update();
|
||||
// _minimap->update(); // causes massive performance issues
|
||||
|
||||
_world->time += this->mTimespeed * dt;
|
||||
_world->animtime += dt * 1000.0f;
|
||||
@@ -4485,6 +4517,13 @@ void MapView::draw_map()
|
||||
doSelection(true);
|
||||
}
|
||||
|
||||
if (_camera_moved_since_last_draw)
|
||||
{
|
||||
_minimap->update();
|
||||
}
|
||||
|
||||
bool classic_ui = _settings->value("classicUI", true).toBool();
|
||||
bool show_unpaintable = classic_ui ? texturingTool->show_unpaintable_chunks() : _left_sec_toolbar->showUnpaintableChunk();
|
||||
_world->renderer()->draw (
|
||||
model_view()
|
||||
, projection()
|
||||
@@ -4493,7 +4532,7 @@ void MapView::draw_map()
|
||||
, terrainMode == editing_mode::mccv ? shaderTool->shaderColor() : cursor_color
|
||||
, _cursorType
|
||||
, radius
|
||||
, _left_sec_toolbar->showUnpaintableChunk()
|
||||
, show_unpaintable
|
||||
, _left_sec_toolbar->drawOnlyInsideSphereLight()
|
||||
, _left_sec_toolbar->drawWireframeSphereLight()
|
||||
, _left_sec_toolbar->getAlphaSphereLight()
|
||||
@@ -4663,7 +4702,6 @@ void MapView::keyPressEvent (QKeyEvent *event)
|
||||
{
|
||||
_camera.position = glm::vec3(_cursor_pos.x, _cursor_pos.y + 50, _cursor_pos.z);
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
|
||||
if (event->key() == Qt::Key_L)
|
||||
@@ -4680,28 +4718,24 @@ void MapView::keyPressEvent (QKeyEvent *event)
|
||||
auto next_z = cur_tile.z - 1;
|
||||
_camera.position = glm::vec3((cur_tile.x * TILESIZE) + (TILESIZE / 2), _camera.position.y, (next_z * TILESIZE) + (TILESIZE / 2));
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
else if (event->key() == Qt::Key_Down)
|
||||
{
|
||||
auto next_z = cur_tile.z + 1;
|
||||
_camera.position = glm::vec3((cur_tile.x * TILESIZE) + (TILESIZE / 2), _camera.position.y, (next_z * TILESIZE) + (TILESIZE / 2));
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
else if (event->key() == Qt::Key_Left)
|
||||
{
|
||||
auto next_x = cur_tile.x - 1;
|
||||
_camera.position = glm::vec3((next_x * TILESIZE) + (TILESIZE / 2), _camera.position.y, (cur_tile.z * TILESIZE) + (TILESIZE / 2));
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
else if (event->key() == Qt::Key_Right)
|
||||
{
|
||||
auto next_x = cur_tile.x + 1;
|
||||
_camera.position = glm::vec3((next_x * TILESIZE) + (TILESIZE / 2), _camera.position.y, (cur_tile.z * TILESIZE) + (TILESIZE / 2));
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4849,7 +4883,6 @@ void MapView::mouseMoveEvent (QMouseEvent* event)
|
||||
_camera.add_to_yaw(math::degrees(relative_movement.dx() / XSENS));
|
||||
_camera.add_to_pitch(math::degrees(mousedir * relative_movement.dy() / YSENS));
|
||||
_camera_moved_since_last_draw = true;
|
||||
_minimap->update();
|
||||
}
|
||||
|
||||
if (MoveObj)
|
||||
|
||||
@@ -280,6 +280,7 @@ public:
|
||||
void randomizeStampRotation();
|
||||
void onSettingsSave();
|
||||
void updateRotationEditor() { _rotation_editor_need_update = true; };
|
||||
void setCameraDirty() { _camera_moved_since_last_draw = true; };
|
||||
|
||||
[[nodiscard]]
|
||||
Noggit::Ui::minimap_widget* getMinimapWidget() const { return _minimap; }
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <math/bounding_box.hpp>
|
||||
#include <math/frustum.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <noggit/Log.h>
|
||||
#include <noggit/Misc.h> // checkinside
|
||||
#include <noggit/Model.h> // Model, etc.
|
||||
@@ -237,6 +238,10 @@ void ModelInstance::updateDetails(Noggit::Ui::detail_infos* detail_widget)
|
||||
<< "<br><b>position X/Y/Z:</b> {" << pos.x << " , " << pos.y << " , " << pos.z << "}"
|
||||
<< "<br><b>rotation X/Y/Z:</b> {" << dir.x << " , " << dir.y << " , " << dir.z << "}"
|
||||
<< "<br><b>scale:</b> " << scale
|
||||
|
||||
<< "<br><b>server position X/Y/Z: </b>{" << (ZEROPOINT - pos.z) << ", " << (ZEROPOINT - pos.x) << ", " << pos.y << "}"
|
||||
<< "<br><b>server orientation: </b>" << fabs(2 * glm::pi<float>() - glm::pi<float>() / 180.0 * (float(dir.y) < 0 ? fabs(float(dir.y)) + 180.0 : fabs(float(dir.y) - 180.0)))
|
||||
|
||||
<< "<br><b>textures Used:</b> " << model->header.nTextures
|
||||
<< "<br><b>size category:</b><span> " << size_cat;
|
||||
|
||||
|
||||
@@ -24,6 +24,31 @@ void selected_chunk_type::updateDetails(Noggit::Ui::detail_infos* detail_widget)
|
||||
<< "<br><b>textures used:</b> " << chunk->texture_set->num()
|
||||
<< "<br><b>textures:</b><span>";
|
||||
|
||||
// liquid details if the chunk has liquid data
|
||||
if (chunk->mt->Water.hasData(0))
|
||||
{
|
||||
ChunkWater* waterchunk = chunk->liquid_chunk();
|
||||
|
||||
MH2O_Render liquid_render = waterchunk->Render.value_or(MH2O_Render{ 0xffffffffffffffff,0xffffffffffffffff });
|
||||
|
||||
if (waterchunk->hasData(0))
|
||||
{
|
||||
|
||||
liquid_layer liquid = waterchunk->getLayers()->at(0); // only getting data from layer 0, maybe loop them ?
|
||||
int liquid_flags = liquid.getSubchunks();
|
||||
|
||||
select_info << "\nliquid type: " << liquid.liquidID() << " (\"" << gLiquidTypeDB.getLiquidName(liquid.liquidID()) << "\")"
|
||||
<< "\nliquid flags: "
|
||||
// getting flags from the center tile
|
||||
<< ((liquid_render.fishable >> (4 * 8 + 4)) & 1 ? "fishable " : "")
|
||||
<< ((liquid_render.fatigue >> (4 * 8 + 4)) & 1 ? "fatigue" : "");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
select_info << "\nno liquid data";
|
||||
}
|
||||
|
||||
unsigned counter = 0;
|
||||
for (auto& tex : *(chunk->texture_set->getTextures()))
|
||||
{
|
||||
|
||||
@@ -173,6 +173,10 @@ void WMOInstance::updateDetails(Noggit::Ui::detail_infos* detail_widget)
|
||||
<< "<br><b>WMO Id: </b>" << wmo->WmoId
|
||||
<< "<br><b>doodad set: </b>" << doodadset()
|
||||
<< "<br><b>name set: </b>" << mNameset
|
||||
|
||||
<< "<br><b>server position X/Y/Z: </b>{" << (ZEROPOINT - pos.z) << ", " << (ZEROPOINT - pos.x) << ", " << pos.y << "}"
|
||||
<< "<br><b>server orientation: </b>" << fabs(2 * glm::pi<float>() - glm::pi<float>() / 180.0 * (float(dir.y) < 0 ? fabs(float(dir.y)) + 180.0 : fabs(float(dir.y) - 180.0)))
|
||||
|
||||
<< "<br><b>textures used: </b>" << wmo->textures.size()
|
||||
<< "<span>";
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -357,10 +376,11 @@ void World::rotate_selected_models_to_ground_normal(bool smoothNormals)
|
||||
}
|
||||
});
|
||||
|
||||
// We shouldn't end up with empty ever.
|
||||
// !\ todo We shouldn't end up with empty ever (but we do, on completely flat ground)
|
||||
if (results.empty())
|
||||
{
|
||||
LogError << "rotate_selected_models_to_ground_normal ray intersection failed" << std::endl;
|
||||
// just to avoid models disappearing when this happens
|
||||
updateTilesEntry(entry, model_update::add);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -836,15 +856,14 @@ MapChunk* World::getChunkAt(glm::vec3 const& pos)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool World::isInIndoorWmoGroup(std::array<glm::vec3, 2> obj_bounds)
|
||||
bool World::isInIndoorWmoGroup(std::array<glm::vec3, 2> obj_bounds, glm::mat4x4 obj_transform)
|
||||
{
|
||||
bool is_indoor = false;
|
||||
// check if model bounds is within wmo bounds then check each indor wmo group bounds
|
||||
_model_instance_storage.for_each_wmo_instance([&](WMOInstance& wmo_instance)
|
||||
{
|
||||
auto wmo_extents = wmo_instance.getExtents();
|
||||
|
||||
|
||||
// check if global wmo bounds intersect
|
||||
if (obj_bounds[1].x >= wmo_extents[0].x
|
||||
&& obj_bounds[1].y >= wmo_extents[0].y
|
||||
&& obj_bounds[1].z >= wmo_extents[0].z
|
||||
@@ -864,15 +883,23 @@ bool World::isInIndoorWmoGroup(std::array<glm::vec3, 2> obj_bounds)
|
||||
auto& group_extents = wmo_instance.getGroupExtents().at(i);
|
||||
|
||||
// TODO : do a precise calculation instead of using axis aligned bounding boxes.
|
||||
auto test = obj_bounds[1].x >= group_extents.first.x
|
||||
bool aabb_test = obj_bounds[1].x >= group_extents.first.x
|
||||
&& obj_bounds[1].y >= group_extents.first.y
|
||||
&& obj_bounds[1].z >= group_extents.first.z
|
||||
&& group_extents.second.x >= obj_bounds[0].x
|
||||
&& group_extents.second.y >= obj_bounds[0].y
|
||||
&& group_extents.second.z >= obj_bounds[0].z;
|
||||
|
||||
is_indoor = test;
|
||||
return;
|
||||
if (aabb_test) // oriented box check
|
||||
{
|
||||
/* TODO
|
||||
if (collide_test)
|
||||
{
|
||||
is_indoor = true;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1797,7 +1824,10 @@ void World::remove_models_if_needed(std::vector<uint32_t> const& uids)
|
||||
reset_selection();
|
||||
}
|
||||
|
||||
update_models_by_filename();
|
||||
if (uids.size())
|
||||
{
|
||||
update_models_by_filename();
|
||||
}
|
||||
}
|
||||
|
||||
void World::reload_tile(TileIndex const& tile)
|
||||
@@ -2695,7 +2725,7 @@ void World::update_models_by_filename()
|
||||
{
|
||||
_models_by_filename[model_instance.model->file_key().filepath()].push_back(&model_instance);
|
||||
// to make sure the transform matrix are up to date
|
||||
model_instance.recalcExtents();
|
||||
model_instance.ensureExtents();
|
||||
});
|
||||
|
||||
need_model_updates = false;
|
||||
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
|
||||
MapChunk* getChunkAt(glm::vec3 const& pos);
|
||||
|
||||
bool isInIndoorWmoGroup(std::array<glm::vec3, 2> obj_bounds);
|
||||
bool isInIndoorWmoGroup(std::array<glm::vec3, 2> obj_bounds, glm::mat4x4 obj_transform);
|
||||
|
||||
protected:
|
||||
// Information about the currently selected model / WMO / triangle.
|
||||
@@ -316,6 +316,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);
|
||||
|
||||
|
||||
@@ -104,4 +104,6 @@ private:
|
||||
private:
|
||||
glm::vec3 pos;
|
||||
ChunkWater* _chunk;
|
||||
|
||||
friend class MapView;
|
||||
};
|
||||
|
||||
@@ -217,6 +217,35 @@ map_horizon::map_horizon(const std::string& basename, const MapIndex * const ind
|
||||
set_minimap(index);
|
||||
}
|
||||
|
||||
void map_horizon::update_minimap_tile(int y, int x, bool has_data = false )
|
||||
{
|
||||
if (_tiles[y][x])
|
||||
{
|
||||
//! \todo There also is a second heightmap appended which has additional 16*16 pixels.
|
||||
//! \todo There also is MAHO giving holes into this heightmap.
|
||||
|
||||
for (int j(0); j < 16; ++j)
|
||||
{
|
||||
for (int i(0); i < 16; ++i)
|
||||
{
|
||||
//! \todo R and B are inverted here
|
||||
_qt_minimap.setPixel(x * 16 + i, y * 16 + j, color_for_height(_tiles[y][x]->height_17[j][i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
// the adt exist but there's no data in the wdl
|
||||
else if (has_data)
|
||||
{
|
||||
for (int j(0); j < 16; ++j)
|
||||
{
|
||||
for (int i(0); i < 16; ++i)
|
||||
{
|
||||
_qt_minimap.setPixel(x * 16 + i, y * 16 + j, color(200, 100, 25));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_horizon::set_minimap(const MapIndex* const index)
|
||||
{
|
||||
_qt_minimap = QImage(16 * 64, 16 * 64, QImage::Format_ARGB32);
|
||||
@@ -226,31 +255,20 @@ void map_horizon::set_minimap(const MapIndex* const index)
|
||||
{
|
||||
for (int x(0); x < 64; ++x)
|
||||
{
|
||||
if (_tiles[y][x])
|
||||
{
|
||||
//! \todo There also is a second heightmap appended which has additional 16*16 pixels.
|
||||
//! \todo There also is MAHO giving holes into this heightmap.
|
||||
update_minimap_tile(y, x, index->hasTile(TileIndex(x, y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j(0); j < 16; ++j)
|
||||
{
|
||||
for (int i(0); i < 16; ++i)
|
||||
{
|
||||
//! \todo R and B are inverted here
|
||||
_qt_minimap.setPixel(x * 16 + i, y * 16 + j, color_for_height(_tiles[y][x]->height_17[j][i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
// the adt exist but there's no data in the wdl
|
||||
else if (index->hasTile(TileIndex(x, y)))
|
||||
{
|
||||
for (int j(0); j < 16; ++j)
|
||||
{
|
||||
for (int i(0); i < 16; ++i)
|
||||
{
|
||||
_qt_minimap.setPixel(x * 16 + i, y * 16 + j, color(200, 100, 25));
|
||||
}
|
||||
}
|
||||
}
|
||||
void map_horizon::remove_horizon_tile(int y, int x)
|
||||
{
|
||||
_tiles[y][x].reset();
|
||||
|
||||
for (int j(0); j < 16; ++j)
|
||||
{
|
||||
for (int i(0); i < 16; ++i)
|
||||
{
|
||||
_qt_minimap.setPixel(x * 16 + i, y * 16 + j, color(255, 25, 25));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,6 +296,9 @@ int16_t map_horizon::getWdlheight(MapTile* tile, float x, float y)
|
||||
// truncate and clamp the float value
|
||||
auto chunk = tile->getChunk(cx, cy);
|
||||
// float height = heights[cy * 16 + cx][17 * (row / 2) + (inner ? 9 : 0) + col];
|
||||
if (!chunk)
|
||||
return 0.0f;
|
||||
|
||||
float height = chunk->getHeightmap()[17 * (row / 2) + (inner ? 9 : 0) + col].y;
|
||||
return std::min(std::max(static_cast<int16_t>(height), static_cast<int16_t>(SHRT_MIN)), static_cast<int16_t>(SHRT_MAX));
|
||||
}
|
||||
@@ -318,6 +339,8 @@ void map_horizon::update_horizon_tile(MapTile* mTile)
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
auto chunk = mTile->getChunk(j, i);
|
||||
if (!chunk)
|
||||
continue;
|
||||
// the ordering seems to be : short array = Y axis, flags values = X axis and the values are for a whole chunk.
|
||||
|
||||
std::bitset<16> holeBits(chunk->getHoleMask());
|
||||
@@ -327,6 +350,8 @@ void map_horizon::update_horizon_tile(MapTile* mTile)
|
||||
}
|
||||
_tiles[tile_index.z][tile_index.x].get()->holes[i] = static_cast<int16_t>(wdlHoleMask.to_ulong());
|
||||
}
|
||||
|
||||
update_minimap_tile(tile_index.z, tile_index.x, true);
|
||||
}
|
||||
|
||||
void map_horizon::save_wdl(World* world, bool regenerate)
|
||||
@@ -405,7 +430,9 @@ void map_horizon::save_wdl(World* world, bool regenerate)
|
||||
if (!horizon_tile || regenerate)
|
||||
{
|
||||
bool unload = !world->mapIndex.tileLoaded(index) && !world->mapIndex.tileAwaitingLoading(index);
|
||||
MapTile* mTile = world->mapIndex.loadTile(index);
|
||||
MapTile* mTile = world->mapIndex.loadTile(index, false, false, false);
|
||||
|
||||
auto nloadedtiles = world->mapIndex.getNLoadedTiles();
|
||||
|
||||
if (mTile)
|
||||
mTile->wait_until_loaded();
|
||||
|
||||
@@ -80,8 +80,12 @@ public:
|
||||
|
||||
map_horizon(const std::string& basename, const MapIndex * const index);
|
||||
|
||||
void update_minimap_tile(int y, int x, bool has_data);
|
||||
|
||||
void set_minimap(const MapIndex* const index);
|
||||
|
||||
void remove_horizon_tile(int y, int x);
|
||||
|
||||
Noggit::map_horizon_tile* get_horizon_tile(int y, int x);
|
||||
|
||||
QImage _qt_minimap;
|
||||
|
||||
@@ -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 ----------------------------------------------
|
||||
|
||||
@@ -360,7 +360,7 @@ void MapIndex::setFlag(bool to, glm::vec3 const& pos, uint32_t flag)
|
||||
}
|
||||
}
|
||||
|
||||
MapTile* MapIndex::loadTile(const TileIndex& tile, bool reloading)
|
||||
MapTile* MapIndex::loadTile(const TileIndex& tile, bool reloading, bool load_models, bool load_textures)
|
||||
{
|
||||
if (!hasTile(tile))
|
||||
{
|
||||
@@ -382,7 +382,7 @@ MapTile* MapIndex::loadTile(const TileIndex& tile, bool reloading)
|
||||
}
|
||||
|
||||
mTiles[tile.z][tile.x].tile = std::make_unique<MapTile> (static_cast<int>(tile.x), static_cast<int>(tile.z), filename.str(),
|
||||
mBigAlpha, true, use_mclq_green_lava(), reloading, _world, _context);
|
||||
mBigAlpha, load_models, use_mclq_green_lava(), reloading, _world, _context, tile_mode::edit, load_textures);
|
||||
|
||||
MapTile* adt = mTiles[tile.z][tile.x].tile.get();
|
||||
|
||||
@@ -1162,6 +1162,8 @@ void MapIndex::addTile(const TileIndex& tile)
|
||||
mTiles[tile.z][tile.x].flags |= 0x1;
|
||||
mTiles[tile.z][tile.x].tile->changed = true;
|
||||
|
||||
_world->horizon.update_horizon_tile(mTiles[tile.z][tile.x].tile.get());
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -1177,6 +1179,8 @@ void MapIndex::removeTile(const TileIndex &tile)
|
||||
mTiles[tile.z][tile.x].tile->changed = true;
|
||||
mTiles[tile.z][tile.x].onDisc = false;
|
||||
|
||||
_world->horizon.remove_horizon_tile(tile.z, tile.x);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ public:
|
||||
void create_empty_wdl();
|
||||
|
||||
void enterTile(const TileIndex& tile);
|
||||
MapTile *loadTile(const TileIndex& tile, bool reloading = false);
|
||||
MapTile *loadTile(const TileIndex& tile, bool reloading = false, bool load_models = true, bool load_textures = true);
|
||||
|
||||
void update_model_tile(const TileIndex& tile, model_update type, SceneObject* instance);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -229,7 +229,7 @@ void WorldRender::draw (glm::mat4x4 const& model_view
|
||||
_cull_distance= draw_fog ? _skies->fog_distance_end() : _view_distance;
|
||||
|
||||
// Draw verylowres heightmap
|
||||
if (draw_fog && draw_terrain)
|
||||
if (!_world->mapIndex.hasAGlobalWMO() && draw_fog && draw_terrain)
|
||||
{
|
||||
ZoneScopedN("World::draw() : Draw horizon");
|
||||
_horizon_render->draw (model_view, projection, &_world->mapIndex, _skies->color_set[FOG_COLOR], _cull_distance, frustum, camera_pos, display);
|
||||
@@ -457,6 +457,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)
|
||||
{
|
||||
@@ -519,7 +532,7 @@ void WorldRender::draw (glm::mat4x4 const& model_view
|
||||
, _world->animtime
|
||||
, _skies->hasSkies()
|
||||
, display
|
||||
, false
|
||||
, disable_cull
|
||||
, draw_wmo_exterior
|
||||
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <noggit/MapHeaders.h>
|
||||
#include <noggit/MapView.h>
|
||||
#include <noggit/World.h>
|
||||
#include <noggit/ChunkWater.hpp>
|
||||
#include <noggit/ContextObject.hpp>
|
||||
|
||||
namespace Noggit
|
||||
@@ -150,6 +151,73 @@ namespace Noggit
|
||||
return vert(state(), _chunk, index);
|
||||
}
|
||||
|
||||
bool chunk::has_render_flags()
|
||||
{
|
||||
return _chunk->liquid_chunk()->Render.has_value();
|
||||
}
|
||||
|
||||
MH2O_Render chunk::getRenderOrDefault()
|
||||
{
|
||||
std::optional<MH2O_Render> render = _chunk->liquid_chunk()->Render;
|
||||
if (render.has_value())
|
||||
{
|
||||
return render.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
return { 0xFFFFFFFFFFFFFFFF,1 };
|
||||
}
|
||||
}
|
||||
|
||||
MH2O_Render& chunk::getOrCreateRender()
|
||||
{
|
||||
std::optional<MH2O_Render>& render = _chunk->liquid_chunk()->Render;
|
||||
if (!render.has_value())
|
||||
{
|
||||
render.emplace();
|
||||
}
|
||||
return render.value();
|
||||
}
|
||||
|
||||
void chunk::set_deep_flag(std::uint32_t low, std::uint32_t high)
|
||||
{
|
||||
getOrCreateRender().fatigue = std::uint64_t(low) | (std::uint64_t(high) << 32);
|
||||
}
|
||||
|
||||
void chunk::set_deep_flag_1(std::uint32_t low)
|
||||
{
|
||||
set_deep_flag(low, 0);
|
||||
}
|
||||
|
||||
std::uint32_t chunk::get_deep_flag()
|
||||
{
|
||||
return static_cast<std::uint32_t>(getRenderOrDefault().fatigue);
|
||||
}
|
||||
|
||||
std::uint32_t chunk::get_deep_flag_high()
|
||||
{
|
||||
return static_cast<std::uint32_t>(getRenderOrDefault().fatigue >> 32);
|
||||
}
|
||||
|
||||
void chunk::set_fishable_flag(std::uint32_t low, std::uint32_t high)
|
||||
{
|
||||
getOrCreateRender().fishable = std::uint64_t(low) | (std::uint64_t(high) << 32);
|
||||
}
|
||||
|
||||
void chunk::set_fishable_flag_1(std::uint32_t low)
|
||||
{
|
||||
set_fishable_flag(low, 0);
|
||||
}
|
||||
|
||||
std::uint32_t chunk::get_fishable_flag()
|
||||
{
|
||||
return static_cast<std::uint32_t>(getRenderOrDefault().fishable);
|
||||
}
|
||||
std::uint32_t chunk::get_fishable_flag_high()
|
||||
{
|
||||
return static_cast<std::uint32_t>(getRenderOrDefault().fishable >> 32);
|
||||
}
|
||||
|
||||
std::shared_ptr<selection> chunk::to_selection()
|
||||
{
|
||||
return std::make_shared<selection>(state(), "chunk#to_selection", _chunk->vmin,_chunk->vmax);
|
||||
@@ -185,6 +253,18 @@ namespace Noggit
|
||||
, "to_selection", &chunk::to_selection
|
||||
, "get_tex", &chunk::get_tex
|
||||
, "get_vert", &chunk::get_vert
|
||||
, "set_deep_flag", sol::overload(
|
||||
&chunk::set_deep_flag
|
||||
, &chunk::set_deep_flag_1
|
||||
)
|
||||
, "get_deep_flag", &chunk::get_deep_flag
|
||||
, "get_deep_flag_high", &chunk::get_deep_flag_high
|
||||
, "set_fishable_flag", sol::overload(
|
||||
&chunk::set_fishable_flag
|
||||
, &chunk::set_fishable_flag_1
|
||||
)
|
||||
, "get_fishable_flag", &chunk::get_fishable_flag
|
||||
, "get_fishable_flag_high", &chunk::get_fishable_flag_high
|
||||
);
|
||||
}
|
||||
} // namespace Scripting
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <noggit/scripting/script_vert.hpp>
|
||||
#include <noggit/scripting/script_object.hpp>
|
||||
#include <noggit/MapChunk.h>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Noggit
|
||||
{
|
||||
@@ -32,6 +33,18 @@ namespace Noggit
|
||||
void apply_heightmap();
|
||||
void apply_vertex_color();
|
||||
void apply_all();
|
||||
|
||||
void set_deep_flag(std::uint32_t low, std::uint32_t high);
|
||||
void set_deep_flag_1(std::uint32_t low);
|
||||
std::uint32_t get_deep_flag();
|
||||
std::uint32_t get_deep_flag_high();
|
||||
|
||||
void set_fishable_flag(std::uint32_t low, std::uint32_t high);
|
||||
void set_fishable_flag_1(std::uint32_t low);
|
||||
std::uint32_t get_fishable_flag();
|
||||
std::uint32_t get_fishable_flag_high();
|
||||
bool has_render_flags();
|
||||
|
||||
void set_impassable(bool add);
|
||||
int get_area_id();
|
||||
void set_area_id(int value);
|
||||
@@ -39,6 +52,8 @@ namespace Noggit
|
||||
vert get_vert(int index);
|
||||
std::shared_ptr<selection> to_selection();
|
||||
private:
|
||||
MH2O_Render getRenderOrDefault();
|
||||
MH2O_Render& getOrCreateRender();
|
||||
MapChunk* _chunk;
|
||||
friend class selection;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <noggit/World.h>
|
||||
#include <util/qt/overload.hpp>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
@@ -78,6 +79,29 @@ namespace Noggit
|
||||
|
||||
layout->addWidget(settings_group);
|
||||
|
||||
QGroupBox* flatten_blur_group = new QGroupBox("Flatten/Blur", this);
|
||||
flatten_blur_group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||
auto flatten_blur_layout = new QGridLayout(flatten_blur_group);
|
||||
|
||||
flatten_blur_layout->addWidget(_lock_up_checkbox = new QCheckBox(this), 0, 0);
|
||||
flatten_blur_layout->addWidget(_lock_down_checkbox = new QCheckBox(this), 0, 1);
|
||||
|
||||
_lock_up_checkbox->setChecked(_flatten_mode.raise);
|
||||
_lock_up_checkbox->setText("Raise");
|
||||
_lock_up_checkbox->setToolTip("Raise the terrain when using the tool");
|
||||
_lock_down_checkbox->setChecked(_flatten_mode.lower);
|
||||
_lock_down_checkbox->setText("Lower");
|
||||
_lock_down_checkbox->setToolTip("Lower the terrain when using the tool");
|
||||
|
||||
QSettings settings;
|
||||
bool use_classic_ui = settings.value("classicUI", true).toBool();
|
||||
if (use_classic_ui)
|
||||
flatten_blur_group->show();
|
||||
else
|
||||
flatten_blur_group->hide();
|
||||
|
||||
layout->addWidget(flatten_blur_group);
|
||||
|
||||
QGroupBox* flatten_only_group = new QGroupBox("Flatten only", this);
|
||||
auto flatten_only_layout = new QVBoxLayout(flatten_only_group);
|
||||
|
||||
@@ -142,6 +166,20 @@ namespace Noggit
|
||||
}
|
||||
);
|
||||
|
||||
connect(_lock_up_checkbox, &QCheckBox::stateChanged
|
||||
, [&](int state)
|
||||
{
|
||||
_flatten_mode.raise = state;
|
||||
}
|
||||
);
|
||||
|
||||
connect(_lock_down_checkbox, &QCheckBox::stateChanged
|
||||
, [&](int state)
|
||||
{
|
||||
_flatten_mode.lower = state;
|
||||
}
|
||||
);
|
||||
|
||||
connect ( _angle_slider, &QSlider::valueChanged
|
||||
, [&] (int v)
|
||||
{
|
||||
@@ -230,6 +268,16 @@ namespace Noggit
|
||||
}
|
||||
}
|
||||
|
||||
void flatten_blur_tool::nextFlattenMode()
|
||||
{
|
||||
_flatten_mode.next();
|
||||
|
||||
QSignalBlocker const up_lock(_lock_up_checkbox);
|
||||
QSignalBlocker const down_lock(_lock_down_checkbox);
|
||||
_lock_up_checkbox->setChecked(_flatten_mode.raise);
|
||||
_lock_down_checkbox->setChecked(_flatten_mode.lower);
|
||||
}
|
||||
|
||||
void flatten_blur_tool::nextFlattenType()
|
||||
{
|
||||
_flatten_type = ( ++_flatten_type ) % eFlattenType_Count;
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Noggit
|
||||
void blur (World* world, glm::vec3 const& cursor_pos, float dt);
|
||||
|
||||
void nextFlattenType();
|
||||
void nextFlattenMode();
|
||||
void toggleFlattenAngle();
|
||||
void toggleFlattenLock();
|
||||
void lockPos (glm::vec3 const& cursor_pos);
|
||||
|
||||
@@ -641,7 +641,8 @@ namespace Noggit
|
||||
new_obj->recalcExtents();
|
||||
|
||||
// check if pos is valid (not in an interior) wmo group
|
||||
bool is_indoor = world->isInIndoorWmoGroup(new_obj->extents);
|
||||
// bool is_indoor = world->isInIndoorWmoGroup(new_obj->extents, new_obj->transformMatrix());
|
||||
bool is_indoor = false; // TODO Disabled the indoor check until non axis aligned boxes check is implemented
|
||||
if (is_indoor)
|
||||
{
|
||||
QMessageBox::warning
|
||||
|
||||
@@ -62,6 +62,10 @@ namespace Noggit
|
||||
{
|
||||
int liquid_id = i->getInt(LiquidTypeDB::ID);
|
||||
|
||||
// filter WMO liquids
|
||||
if (liquid_id == 13 || liquid_id == 14 || liquid_id == 17 || liquid_id == 19 || liquid_id == 20)
|
||||
continue;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << liquid_id << "-" << LiquidTypeDB::getLiquidName(liquid_id);
|
||||
waterType->addItem (QString::fromUtf8(ss.str().c_str()), QVariant (liquid_id));
|
||||
|
||||
@@ -116,8 +116,18 @@ namespace Noggit
|
||||
}
|
||||
|
||||
//! \todo Only redraw stuff as told in event.
|
||||
void minimap_widget::paintEvent (QPaintEvent*)
|
||||
// called by _minimap->update()
|
||||
// \todo : massive performance drop after clicking the minimap once until moving cursor out of frame, paintEvent gets called repeatidly
|
||||
void minimap_widget::paintEvent (QPaintEvent* paint_event)
|
||||
{
|
||||
/*
|
||||
auto rectangle = paint_event->rect();
|
||||
auto left = rectangle.left();
|
||||
auto rectop = rectangle.top();
|
||||
auto recwidth = rectangle.width();
|
||||
auto recheight = rectangle.height();
|
||||
*/
|
||||
|
||||
//! \note Only take multiples of 1.0 pixels per tile.
|
||||
const int smaller_side ((qMin (rect().width(), rect().height()) / 64) * 64);
|
||||
const QRect drawing_rect (0, 0, smaller_side, smaller_side);
|
||||
@@ -248,7 +258,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 +319,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;
|
||||
@@ -351,7 +387,7 @@ namespace Noggit
|
||||
emit tile_clicked(tile);
|
||||
}
|
||||
|
||||
update();
|
||||
// update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Noggit
|
||||
void set_resizeable(bool state) { _resizeable = state; };
|
||||
|
||||
protected:
|
||||
virtual void paintEvent (QPaintEvent*) override;
|
||||
virtual void paintEvent (QPaintEvent* paint_event) override;
|
||||
virtual void mouseDoubleClickEvent (QMouseEvent*) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent*) override;
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Noggit
|
||||
)
|
||||
: QWidget(parent)
|
||||
, _brush_level(255)
|
||||
, _show_unpaintable_chunks(false)
|
||||
, _spray_size(1.0f)
|
||||
, _spray_pressure(2.0f)
|
||||
, _anim_prop(true)
|
||||
@@ -106,6 +107,16 @@ namespace Noggit
|
||||
_brush_level_spin->setSingleStep(5);
|
||||
slider_layout_right->addWidget(_brush_level_spin);
|
||||
|
||||
_show_unpaintable_chunks_cb = new QCheckBox("Show unpaintable chunks", tool_widget);
|
||||
_show_unpaintable_chunks_cb->setChecked(false);
|
||||
tool_layout->addWidget(_show_unpaintable_chunks_cb);
|
||||
|
||||
connect(_show_unpaintable_chunks_cb, &QCheckBox::toggled, [=](bool checked)
|
||||
{
|
||||
_map_view->getWorld()->renderer()->getTerrainParamsUniformBlock()->draw_paintability_overlay = checked;
|
||||
_map_view->getWorld()->renderer()->markTerrainParamsUniformBlockDirty();
|
||||
});
|
||||
|
||||
// spray
|
||||
_spray_mode_group = new QGroupBox("Spray", tool_widget);
|
||||
_spray_mode_group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||
@@ -235,6 +246,13 @@ namespace Noggit
|
||||
}
|
||||
);
|
||||
|
||||
connect(_show_unpaintable_chunks_cb, &QCheckBox::stateChanged
|
||||
, [&](int state)
|
||||
{
|
||||
_show_unpaintable_chunks = state;
|
||||
}
|
||||
);
|
||||
|
||||
connect ( _spray_size_spin, qOverload<double> (&QDoubleSpinBox::valueChanged)
|
||||
, [&] (double v)
|
||||
{
|
||||
@@ -474,6 +492,11 @@ namespace Noggit
|
||||
}
|
||||
}
|
||||
|
||||
bool texturing_tool::show_unpaintable_chunks() const
|
||||
{
|
||||
return _show_unpaintable_chunks && _texturing_mode == texturing_mode::paint;
|
||||
}
|
||||
|
||||
void texturing_tool::paint (World* world, glm::vec3 const& pos, float dt, scoped_blp_texture_reference texture)
|
||||
{
|
||||
if (TabletManager::instance()->isActive())
|
||||
@@ -579,6 +602,7 @@ namespace Noggit
|
||||
json["radius"] = _radius_slider->rawValue();
|
||||
json["brush_level"] = _brush_level_spin->value();
|
||||
json["texturing_mode"] = static_cast<int>(_texturing_mode);
|
||||
json["show_unpaintable_chunks"] = _show_unpaintable_chunks_cb->isChecked();
|
||||
|
||||
json["anim"] = _anim_prop.get();
|
||||
json["anim_speed"] = static_cast<int>(_anim_speed_prop.get());
|
||||
@@ -613,6 +637,7 @@ namespace Noggit
|
||||
_brush_level_spin->setValue(json["brush_level"].toInt());
|
||||
|
||||
tabs->setCurrentIndex(json["texturing_mode"].toInt());
|
||||
_show_unpaintable_chunks_cb->setChecked(json["show_unpaintable_chunks"].toBool());
|
||||
|
||||
_anim_prop.set(json["anim"].toBool());
|
||||
_anim_speed_prop.set(json["anim_speed"].toInt());
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace Noggit
|
||||
|
||||
float brush_radius() const;
|
||||
float hardness() const;
|
||||
bool show_unpaintable_chunks() const;
|
||||
|
||||
void set_brush_level (float level);
|
||||
|
||||
@@ -105,6 +106,7 @@ namespace Noggit
|
||||
Brush _spray_brush;
|
||||
|
||||
int _brush_level;
|
||||
bool _show_unpaintable_chunks;
|
||||
|
||||
float _spray_size;
|
||||
float _spray_pressure;
|
||||
@@ -123,6 +125,8 @@ namespace Noggit
|
||||
Noggit::Ui::Tools::UiCommon::ExtendedSlider* _pressure_slider;
|
||||
QSpinBox* _brush_level_spin;
|
||||
|
||||
QCheckBox* _show_unpaintable_chunks_cb;
|
||||
|
||||
QGroupBox* _spray_mode_group;
|
||||
QWidget* _spray_content;
|
||||
QCheckBox* _inner_radius_cb;
|
||||
|
||||
@@ -37,9 +37,13 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr<Project::NoggitProject> pro
|
||||
auto layout = new QHBoxLayout(this);
|
||||
|
||||
// Left side
|
||||
auto layout_left = new QHBoxLayout(this);
|
||||
auto layout_left = new QVBoxLayout(this);
|
||||
layout->addLayout(layout_left);
|
||||
|
||||
auto info_label = new QLabel("Left Click on the grid to add Tiles, Ctrl+click to erase, Shift+Click to add 3x3.");
|
||||
info_label->setWindowIcon(Noggit::Ui::FontAwesomeIcon(Noggit::Ui::FontAwesome::info));
|
||||
layout_left->addWidget(info_label);
|
||||
|
||||
auto scroll_minimap = new QScrollArea(this);
|
||||
|
||||
_minimap_widget = new Noggit::Ui::minimap_widget(this);
|
||||
@@ -224,6 +228,7 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr<Project::NoggitProject> pro
|
||||
_map_settings->setLayout(difficulty_settings_layout);
|
||||
|
||||
_difficulty_type = new QComboBox(_map_settings);
|
||||
_difficulty_type->setDisabled(true);
|
||||
|
||||
difficulty_settings_layout->addRow("Difficulty Index", _difficulty_type);
|
||||
|
||||
@@ -586,6 +591,23 @@ void MapCreationWizard::saveCurrentEntry()
|
||||
prompt.exec();
|
||||
return;
|
||||
}
|
||||
// prompt the user if no tile was select
|
||||
if (!_world->mapIndex.getNumExistingTiles()) // _world->mapIndex.hasAGlobalWMO()
|
||||
{
|
||||
QMessageBox prompt;
|
||||
prompt.setIcon(QMessageBox::Warning);
|
||||
prompt.setWindowTitle("Empty map");
|
||||
prompt.setText(std::string("Warning : Your map is empty.").c_str());
|
||||
prompt.setInformativeText("You didn't set any tile. To add tiles to your map click on the squares in the grid.\nDo you still want to save the empty map ?");
|
||||
prompt.setStandardButtons(QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No);
|
||||
prompt.setDefaultButton(QMessageBox::No);
|
||||
prompt.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowStaysOnTopHint);
|
||||
bool answer = prompt.exec() == QMessageBox::StandardButton::Yes;
|
||||
if (!answer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create WDT empty file for new map
|
||||
std::stringstream filename;
|
||||
@@ -710,6 +732,19 @@ void MapCreationWizard::addNewMap()
|
||||
|
||||
void MapCreationWizard::removeMap()
|
||||
{
|
||||
QMessageBox prompt;
|
||||
prompt.setIcon(QMessageBox::Warning);
|
||||
prompt.setWindowTitle("Remove Map");
|
||||
prompt.setText(std::string("Are you sure you want to remove this map ?").c_str());
|
||||
prompt.setStandardButtons(QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No);
|
||||
prompt.setDefaultButton(QMessageBox::No);
|
||||
prompt.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowStaysOnTopHint);
|
||||
bool answer = prompt.exec() == QMessageBox::StandardButton::Yes;
|
||||
if (!answer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_is_new_record && _cur_map_id >= 0)
|
||||
{
|
||||
gMapDB.removeRecord(_cur_map_id);
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace Noggit
|
||||
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void destroyFakeWorld() { if(_world) delete _world; _world = nullptr; _minimap_widget->world (nullptr); };
|
||||
|
||||
void addNewMap();
|
||||
signals:
|
||||
void map_dbc_updated();
|
||||
|
||||
@@ -148,7 +148,6 @@ namespace Noggit
|
||||
void saveCurrentEntry();
|
||||
void discardChanges();
|
||||
|
||||
void addNewMap();
|
||||
void removeMap();
|
||||
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <noggit/ui/tools/ActionHistoryNavigator/ActionHistoryNavigator.hpp>
|
||||
#include <noggit/ui/FontAwesome.hpp>
|
||||
#include <QSlider>
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
using namespace Noggit::Ui;
|
||||
using namespace Noggit::Ui::Tools::ViewToolbar::Ui;
|
||||
@@ -135,6 +136,7 @@ ViewToolbar::ViewToolbar(MapView *mapView, ViewToolbar *tb)
|
||||
// add_tool_icon(mapView, &mapView->_game_mode_camera, tr("Tile view"), FontNoggit::VIEW_MODE_2D, tb);
|
||||
addSeparator();
|
||||
|
||||
add_tool_icon(mapView, &mapView->_show_minimap_window, tr("Show Minimap"),FontNoggit::TOOL_MINIMAP_EDITOR, tb);
|
||||
add_tool_icon(mapView, &mapView->_show_detail_info_window, tr("Details info"), FontNoggit::INFO, tb);
|
||||
|
||||
// TODO : will open a panel with time controls, or use 2n toolbar
|
||||
@@ -326,6 +328,9 @@ void ViewToolbar::setCurrentMode(MapView* mapView, editing_mode mode)
|
||||
mapView->getLeftSecondaryToolbar()->hide();
|
||||
current_mode = mode;
|
||||
|
||||
QSettings settings;
|
||||
bool use_classic_ui = settings.value("classicUI", false).toBool();
|
||||
|
||||
switch (current_mode)
|
||||
{
|
||||
case editing_mode::ground:
|
||||
@@ -334,14 +339,20 @@ void ViewToolbar::setCurrentMode(MapView* mapView, editing_mode mode)
|
||||
if (_flatten_secondary_tool.size() > 0)
|
||||
{
|
||||
setupWidget(_flatten_secondary_tool);
|
||||
mapView->getLeftSecondaryToolbar()->show();
|
||||
if (!use_classic_ui)
|
||||
mapView->getLeftSecondaryToolbar()->show();
|
||||
else
|
||||
mapView->getLeftSecondaryToolbar()->hide();
|
||||
}
|
||||
break;
|
||||
case editing_mode::paint:
|
||||
if (_texture_secondary_tool.size() > 0)
|
||||
{
|
||||
setupWidget(_texture_secondary_tool);
|
||||
mapView->getLeftSecondaryToolbar()->show();
|
||||
if (!use_classic_ui)
|
||||
mapView->getLeftSecondaryToolbar()->show();
|
||||
else
|
||||
mapView->getLeftSecondaryToolbar()->hide();
|
||||
}
|
||||
break;
|
||||
case editing_mode::object:
|
||||
@@ -387,7 +398,16 @@ void ViewToolbar::add_tool_icon(MapView* mapView,
|
||||
}
|
||||
});
|
||||
|
||||
connect (view_state, &Noggit::BoolToggleProperty::changed, [action, view_state] () {
|
||||
connect (view_state, &Noggit::BoolToggleProperty::changed, [action, view_state, mapView] () {
|
||||
if (action->text() == "Game view" && view_state->get())
|
||||
{
|
||||
// hack, manually update camera when switch to game_view
|
||||
mapView->setCameraDirty();
|
||||
auto ground_pos = mapView->getWorld()->get_ground_height(mapView->getCamera()->position);
|
||||
mapView->getCamera()->position.y = ground_pos.y + 2;
|
||||
}
|
||||
|
||||
|
||||
action->setChecked(view_state->get());
|
||||
});
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace Noggit
|
||||
|
||||
void setCurrentMode(MapView* mapView, editing_mode mode);
|
||||
|
||||
editing_mode getCurrentMode() const { return current_mode; }
|
||||
|
||||
/*secondary top tool*/
|
||||
QVector<QWidgetAction*> _climb_secondary_tool;
|
||||
QVector<QWidgetAction*> _time_secondary_tool;
|
||||
|
||||
@@ -126,12 +126,17 @@ namespace Noggit::Ui::Windows
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
bool use_mysql = settings.value("project/mysql/enabled", false).toBool();
|
||||
|
||||
mysql::testConnection(true);
|
||||
bool valid_conn = false;
|
||||
if (use_mysql)
|
||||
{
|
||||
valid_conn = mysql::testConnection(true);
|
||||
}
|
||||
|
||||
if ((use_mysql && mysql::hasMaxUIDStoredDB(_world->getMapID()))
|
||||
if ((valid_conn && mysql::hasMaxUIDStoredDB(_world->getMapID()))
|
||||
|| uid_storage::hasMaxUIDStored(_world->getMapID())
|
||||
)
|
||||
{
|
||||
|
||||
_world->mapIndex.loadMaxUID();
|
||||
enterMapAt(pos, camera_pitch, camera_yaw, uid_fix_mode::none, from_bookmark);
|
||||
}
|
||||
@@ -168,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]()
|
||||
@@ -182,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)
|
||||
{
|
||||
@@ -210,6 +237,11 @@ namespace Noggit::Ui::Windows
|
||||
{
|
||||
item_widget->setHidden(true);
|
||||
}
|
||||
|
||||
if (!(widget->wmo_map() == wmo_maps))
|
||||
{
|
||||
item_widget->setHidden(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +287,10 @@ namespace Noggit::Ui::Windows
|
||||
QTabWidget* entry_points_tabs(new QTabWidget(widget));
|
||||
//entry_points_tabs->addTab(_continents_table, "Maps");
|
||||
|
||||
auto add_btn = new QPushButton("Add New Map", this);
|
||||
add_btn->setIcon(Noggit::Ui::FontAwesomeIcon(Noggit::Ui::FontAwesome::plus));
|
||||
add_btn->setAccessibleName("map_wizard_add_button");
|
||||
|
||||
/* set-up widget for seaching etc... through _continents_table */
|
||||
{
|
||||
QWidget* _first_tab = new QWidget(this);
|
||||
@@ -289,31 +325,39 @@ 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);
|
||||
_first_tab_layout->addSpacing(12);
|
||||
_first_tab_layout->addSpacing(5);
|
||||
_first_tab_layout->addWidget(_continents_table);
|
||||
_first_tab_layout->addWidget(add_btn);
|
||||
|
||||
entry_points_tabs->addTab(_first_tab, tr("Maps"));
|
||||
}
|
||||
@@ -369,18 +413,21 @@ 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));
|
||||
}
|
||||
);
|
||||
|
||||
auto right_side = new QTabWidget(this);
|
||||
_right_side = new QTabWidget(this);
|
||||
|
||||
auto minimap_holder = new QScrollArea(this);
|
||||
minimap_holder->setWidgetResizable(true);
|
||||
minimap_holder->setAlignment(Qt::AlignCenter);
|
||||
minimap_holder->setWidget(_minimap);
|
||||
|
||||
right_side->addTab(minimap_holder, "Enter map");
|
||||
_right_side->addTab(minimap_holder, "Enter map");
|
||||
minimap_holder->setAccessibleName("main_menu_minimap_holder");
|
||||
|
||||
_map_creation_wizard = new Noggit::Ui::Tools::MapCreationWizard::Ui::MapCreationWizard(_project, this);
|
||||
@@ -392,9 +439,16 @@ namespace Noggit::Ui::Windows
|
||||
}
|
||||
);
|
||||
|
||||
right_side->addTab(_map_creation_wizard, "Edit map");
|
||||
_right_side->addTab(_map_creation_wizard, "Edit map");
|
||||
|
||||
layout->addWidget(right_side);
|
||||
layout->addWidget(_right_side);
|
||||
|
||||
connect(add_btn, &QPushButton::clicked
|
||||
, [&]()
|
||||
{
|
||||
_right_side->setCurrentIndex(1);
|
||||
_map_creation_wizard->addNewMap();
|
||||
});
|
||||
|
||||
//setCentralWidget (_stack_widget);
|
||||
|
||||
|
||||
@@ -86,8 +86,9 @@ namespace Noggit::Ui::Windows
|
||||
|
||||
QListWidget* _continents_table;
|
||||
QString _filter_name;
|
||||
QTabWidget* _right_side;
|
||||
|
||||
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);
|
||||
|
||||
@@ -378,11 +378,6 @@
|
||||
<string>Wrath Of The Lich King</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Shadowlands</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
@@ -211,7 +211,7 @@ void NoggitProjectSelectionWindow::handleContextMenuProjectListItemForget(std::s
|
||||
prompt.setWindowTitle("Forget Project");
|
||||
prompt.setIcon(QMessageBox::Warning);
|
||||
prompt.setWindowFlags(Qt::WindowStaysOnTopHint);
|
||||
prompt.setText("Data on the disk will not be removed. Continue?.");
|
||||
prompt.setText("Data on the disk will not be removed, this action will only hide the project. Continue?.");
|
||||
prompt.addButton("Accept", QMessageBox::AcceptRole);
|
||||
prompt.setDefaultButton(prompt.addButton("Cancel", QMessageBox::RejectRole));
|
||||
prompt.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <QList>
|
||||
#include <filesystem>
|
||||
#include <QDesktopServices>
|
||||
|
||||
using namespace Noggit::Ui::Component;
|
||||
|
||||
@@ -72,7 +73,27 @@ void RecentProjectsComponent::buildRecentProjectsList(Noggit::Ui::Windows::Noggi
|
||||
});
|
||||
|
||||
context_menu.addAction(&action_2);
|
||||
/////
|
||||
QAction action_3("Open Project Directory", project_list_item);
|
||||
action_3.setIcon(FontAwesomeIcon(FontAwesome::folderopen).pixmap(QSize(16, 16)));
|
||||
|
||||
QObject::connect(&action_3, &QAction::triggered, [=]()
|
||||
{
|
||||
openDirectory(project_data.project_directory.toStdString());
|
||||
});
|
||||
|
||||
context_menu.addAction(&action_3);
|
||||
/////
|
||||
QAction action_4("Open WoW Client Directory", project_list_item);
|
||||
action_4.setIcon(FontAwesomeIcon(FontAwesome::gamepad).pixmap(QSize(16, 16)));
|
||||
|
||||
QObject::connect(&action_4, &QAction::triggered, [=]()
|
||||
{
|
||||
openDirectory(project->ClientPath);
|
||||
});
|
||||
|
||||
context_menu.addAction(&action_4);
|
||||
/////
|
||||
context_menu.exec(project_list_item->mapToGlobal(pos));
|
||||
});
|
||||
|
||||
@@ -84,6 +105,38 @@ void RecentProjectsComponent::buildRecentProjectsList(Noggit::Ui::Windows::Noggi
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
void RecentProjectsComponent::openDirectory(std::string const& directory_path)
|
||||
{
|
||||
if (!std::filesystem::exists(directory_path) || !std::filesystem::is_directory(directory_path))
|
||||
return;
|
||||
auto path = QString(directory_path.c_str());
|
||||
QFileInfo info(path);
|
||||
#if defined(Q_OS_WIN)
|
||||
QStringList args;
|
||||
if (!info.isDir())
|
||||
args << "/select,";
|
||||
args << QDir::toNativeSeparators(path);
|
||||
if (QProcess::startDetached("explorer", args))
|
||||
return;
|
||||
#elif defined(Q_OS_MAC)
|
||||
QStringList args;
|
||||
args << "-e";
|
||||
args << "tell application \"Finder\"";
|
||||
args << "-e";
|
||||
args << "activate";
|
||||
args << "-e";
|
||||
args << "select POSIX file \"" + path + "\"";
|
||||
args << "-e";
|
||||
args << "end tell";
|
||||
args << "-e";
|
||||
args << "return";
|
||||
if (!QProcess::execute("/usr/bin/osascript", args))
|
||||
return;
|
||||
#endif
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
|
||||
}
|
||||
|
||||
void RecentProjectsComponent::registerProjectChange(std::string const& project_path)
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace Noggit::Ui::Component
|
||||
static void buildRecentProjectsList(Noggit::Ui::Windows::NoggitProjectSelectionWindow* parent);
|
||||
static void registerProjectChange(std::string const& project_path);
|
||||
static void registerProjectRemove(std::string const& project_path);
|
||||
|
||||
private:
|
||||
static void openDirectory(std::string const& directory_path);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -194,6 +194,7 @@ namespace Noggit
|
||||
ui->_uid_cb->setChecked(_settings->value("uid_startup_check", true).toBool());
|
||||
ui->_systemWindowFrame->setChecked(_settings->value("systemWindowFrame", true).toBool());
|
||||
ui->_nativeMenubar->setChecked(_settings->value("nativeMenubar", true).toBool());
|
||||
ui->_classic_ui->setChecked(_settings->value("classicUI", false).toBool());
|
||||
ui->_additional_file_loading_log->setChecked(
|
||||
_settings->value("additional_file_loading_log", false).toBool());
|
||||
ui->_keyboard_locale->setCurrentText(_settings->value("keyboard_locale", "QWERTY").toString());
|
||||
@@ -278,6 +279,7 @@ namespace Noggit
|
||||
_settings->setValue("keyboard_locale", ui->_keyboard_locale->currentText());
|
||||
_settings->setValue("systemWindowFrame", ui->_systemWindowFrame->isChecked());
|
||||
_settings->setValue("nativeMenubar", ui->_nativeMenubar->isChecked());
|
||||
_settings->setValue("classicUI", ui->_classic_ui->isChecked());
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
_settings->setValue ("project/mysql/enabled", ui->MySQL_box->isChecked());
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="_systemWindowFrame">
|
||||
<property name="toolTip">
|
||||
<string>Turns on default system window frame instead of Noggit's styled one. Requires restart.</string>
|
||||
<string><html><head/><body><p>Turns on default system window frame instead of Noggit's styled one. Requires restart.</p><p>Warning: Can cause crash.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>System window frame</string>
|
||||
@@ -318,6 +318,46 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="_classic_ui">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Disable the new secondary toolbars and moves the settings back to the tool panels.</p><p> Requires restart.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Classic UI</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_23">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user