Allow editing WMO only maps

This commit is contained in:
DennisWG
2024-09-08 17:50:34 +00:00
committed by T1ti
parent 619bc0b0bb
commit 52298c338d
8 changed files with 515 additions and 136 deletions

View File

@@ -2,7 +2,9 @@
#pragma once
#include <glm/vec3.hpp>
#include <cstdint>
#include <array>
union mcnk_flags
{
@@ -114,7 +116,7 @@ struct ENTRY_MODF
uint32_t uniqueID;
float pos[3];
float rot[3];
float extents[2][3];
std::array<glm::vec3, 2> extents;
//uint16_t flags;
uint16_t flags;
uint16_t doodadSet;

View File

@@ -1,5 +1,6 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include <math/coordinates.hpp>
#include <noggit/AsyncLoader.h>
#include <noggit/MapChunk.h>
#include <noggit/MapTile.h>
@@ -160,6 +161,7 @@ MapIndex::MapIndex (const std::string &pBasename, int map_id, World* world,
assert(fourcc == 'MODF');
theFile.read(&wmoEntry, sizeof(ENTRY_MODF));
math::to_client(wmoEntry.pos);
}
// -----------------------------------------------------
@@ -245,6 +247,11 @@ void MapIndex::save()
{
// MWMO
// {
// the game requires the path to be zero terminated!
if(globalWMOName[globalWMOName.size() - 1] != '\0')
{
globalWMOName += '\0';
}
wdtFile.Extend(8);
SetChunkHeader(wdtFile, curPos, 'MWMO', static_cast<int>(globalWMOName.size()));
curPos += 8;
@@ -259,7 +266,9 @@ void MapIndex::save()
SetChunkHeader(wdtFile, curPos, 'MODF', sizeof(ENTRY_MODF));
curPos += 8;
wdtFile.Insert(curPos, sizeof(ENTRY_MODF), (char*)&wmoEntry);
auto entry = wmoEntry;
math::to_server(entry.pos);
wdtFile.Insert(curPos, sizeof(ENTRY_MODF), (char*)&entry);
curPos += sizeof(ENTRY_MODF);
// }
}
@@ -540,7 +549,7 @@ void MapIndex::saveChanged (World* world, bool save_unloaded)
}
}
bool MapIndex::hasAGlobalWMO()
bool MapIndex::hasAGlobalWMO() const
{
return mHasAGlobalWMO;
}
@@ -1193,6 +1202,20 @@ void MapIndex::removeTile(const TileIndex &tile)
changed = true;
}
void MapIndex::addGlobalWmo(std::string path, ENTRY_MODF entry)
{
mHasAGlobalWMO = true;
globalWMOName = std::move(path);
wmoEntry = std::move(entry);
}
void MapIndex::removeGlobalWmo()
{
mHasAGlobalWMO = false;
globalWMOName.clear();
wmoEntry = {};
}
unsigned MapIndex::getNumExistingTiles()
{
if (_n_existing_tiles >= 0)

View File

@@ -213,7 +213,7 @@ public:
void markOnDisc(const TileIndex& tile, bool mto);
bool isTileExternal(const TileIndex& tile) const;
bool hasAGlobalWMO();
bool hasAGlobalWMO() const;
bool hasTile(const TileIndex& index) const;
bool tileAwaitingLoading(const TileIndex& tile) const;
bool tileLoaded(const TileIndex& tile) const;
@@ -241,6 +241,9 @@ public:
void saveMaxUID();
void loadMaxUID();
void addGlobalWmo(std::string path, ENTRY_MODF entry);
void removeGlobalWmo();
void addTile(const TileIndex& tile);
void removeTile(const TileIndex& tile);

View File

@@ -4,6 +4,7 @@
#include <noggit/ui/FontAwesome.hpp>
#include <noggit/ui/windows/noggitWindow/NoggitWindow.hpp>
#include <noggit/ui/widgets/Vector3Widget.hpp>
#include <noggit/project/CurrentProject.hpp>
#include <blizzard-database-library/include/structures/Types.h>
#include <noggit/MapView.h>
@@ -121,14 +122,132 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr<Project::NoggitProject> pro
_tabs = new QTabWidget(_map_settings);
auto map_settings_widget(new QWidget(this));
auto map_difficulty_widget(new QWidget(this));
_tabs->addTab(map_settings_widget, "Map Settings");
_tabs->addTab(map_difficulty_widget, "Map Difficulty Settings");
box_map_settings_layout->addWidget(_tabs);
createMapSettingsTab();
createDifficultyTab();
createWmoEntryTab();
// Bottom row
auto bottom_row_wgt = new QWidget(layout_right_holder);
auto btn_row_layout = new QHBoxLayout(layout_right_holder);
bottom_row_wgt->setLayout(btn_row_layout);
btn_row_layout->setAlignment(Qt::AlignRight);
auto save_btn = new QPushButton("Save", this);
auto discard_btn = new QPushButton("Discard", this);
btn_row_layout->addWidget(save_btn);
btn_row_layout->addWidget(discard_btn);
save_btn->setAccessibleName("map_wizard_save_button");
discard_btn->setAccessibleName("map_wizard_discard_button");
layout_right->addWidget(bottom_row_wgt);
// Connections
connect(save_btn, &QPushButton::clicked
,[&] ()
{
saveCurrentEntry();
});
connect(discard_btn, &QPushButton::clicked
,[&] ()
{
discardChanges();
});
connect(add_btn, &QPushButton::clicked
,[&] ()
{
addNewMap();
});
connect(remove_btn, &QPushButton::clicked
,[&] ()
{
removeMap();
});
_connection = connect(reinterpret_cast<Noggit::Ui::Windows::NoggitWindow*>(parent),
QOverload<int>::of(&Noggit::Ui::Windows::NoggitWindow::mapSelected)
, [&] (int index)
{
selectMap(index);
}
);
connect(_difficulty_type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
selectMapDifficulty();
});
// Selection
QObject::connect
( _minimap_widget, &Noggit::Ui::minimap_widget::tile_clicked
, [this] (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)
{
int x_final = x + i;
int y_final = y + j;
if (x_final < 0 || x_final > 63 || y_final < 0 || y_final > 63)
continue;
if (!_world->mapIndex.hasTile(TileIndex(x_final, y_final)))
{
if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && !_wmoEntryTab.disableTerrain->isChecked())
{
_world->mapIndex.addTile(TileIndex(x_final, y_final));
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.removeTile(TileIndex(x_final, y_final));
}
}
}
}
else
{
int x = tile.x();
int y = tile.y();
if (x < 0 || x > 63 || y < 0 || y > 63)
return;
if (!_world->mapIndex.hasTile(TileIndex(x, y)))
{
if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && !_wmoEntryTab.disableTerrain->isChecked())
{
_world->mapIndex.addTile(TileIndex(x, y));
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.removeTile(TileIndex(x, y));
}
}
update();
}
);
}
void MapCreationWizard::createMapSettingsTab()
{
auto map_settings_widget(new QWidget(this));
_tabs->addTab(map_settings_widget, "Map Settings");
auto map_settings_layout = new QFormLayout(map_settings_widget);
_directory = new QLineEdit(_map_settings);
@@ -222,8 +341,13 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr<Project::NoggitProject> pro
_max_players = new QSpinBox(_map_settings);
_max_players->setMaximum(std::numeric_limits<std::int32_t>::max());
map_settings_layout->addRow("Max players:", _max_players);
}
void MapCreationWizard::createDifficultyTab()
{
auto map_difficulty_widget(new QWidget(this));
_tabs->addTab(map_difficulty_widget, "Map Difficulty Settings");
// difficulty tab
auto difficulty_settings_layout = new QFormLayout(map_difficulty_widget);
_map_settings->setLayout(difficulty_settings_layout);
@@ -250,120 +374,182 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr<Project::NoggitProject> pro
difficulty_settings_layout->addRow("Difficulty String", _difficulty_string);
difficulty_settings_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding));
}
// Bottom row
auto bottom_row_wgt = new QWidget(layout_right_holder);
auto btn_row_layout = new QHBoxLayout(layout_right_holder);
bottom_row_wgt->setLayout(btn_row_layout);
btn_row_layout->setAlignment(Qt::AlignRight);
auto save_btn = new QPushButton("Save", this);
auto discard_btn = new QPushButton("Discard", this);
btn_row_layout->addWidget(save_btn);
btn_row_layout->addWidget(discard_btn);
save_btn->setAccessibleName("map_wizard_save_button");
discard_btn->setAccessibleName("map_wizard_discard_button");
layout_right->addWidget(bottom_row_wgt);
// Connections
connect(save_btn, &QPushButton::clicked
,[&] ()
void MapCreationWizard::createWmoEntryTab()
{
saveCurrentEntry();
auto wmo_widget(new QWidget(this));
_tabs->addTab(wmo_widget, "WMO Entry");
auto layout = new QFormLayout(wmo_widget);
_map_settings->setLayout(layout);
_wmoEntryTab.disableTerrain = new QCheckBox(_map_settings);
_wmoEntryTab.disableTerrain->setChecked(false);
connect(_wmoEntryTab.disableTerrain, &QCheckBox::toggled, [=](bool state) {
_wmoEntryTab.wmoPath->setDisabled(!state);
// Is there any value in exposing these?
//_wmoEntryTab.nameId->setDisabled(!state);
//_wmoEntryTab.uniqueId->setDisabled(!state);
_wmoEntryTab.position->setDisabled(!state);
_wmoEntryTab.rotation->setDisabled(!state);
//_wmoEntryTab.flags->setDisabled(!state);
_wmoEntryTab.doodadSet->setDisabled(!state);
_wmoEntryTab.nameSet->setDisabled(!state);
});
layout->addRow("WMO only (disable terrain):", _wmoEntryTab.disableTerrain);
connect(discard_btn, &QPushButton::clicked
,[&] ()
_wmoEntryTab.wmoPath = new QLineEdit(_map_settings);
_wmoEntryTab.wmoPath->setDisabled(true);
auto defaultStylesheet = _wmoEntryTab.wmoPath->styleSheet();
connect(_wmoEntryTab.wmoPath, &QLineEdit::textChanged, [=](QString text) {
if (!_wmoEntryTab.disableTerrain->isChecked())
{
discardChanges();
return;
}
_world->mWmoFilename = text.toStdString();
WMOInstance wmo{ _world->mWmoFilename, _world->getRenderContext() };
wmo.wmo->wait_until_loaded();
if (!wmo.finishedLoading() || wmo.wmo->loading_failed())
{
_wmoEntryTab.wmoPath->setStyleSheet("QLineEdit { background-color : red; }");
return;
}
_wmoEntryTab.wmoEntry.extents = wmo.getExtents();
_wmoEntryTab.wmoPath->setStyleSheet(defaultStylesheet);
populateDoodadSet(wmo);
populateNameSet(wmo);
});
layout->addRow("Path:", _wmoEntryTab.wmoPath);
connect(add_btn, &QPushButton::clicked
,[&] ()
{
addNewMap();
_wmoEntryTab.nameId = new QSpinBox(_map_settings);
_wmoEntryTab.nameId->setDisabled(true);
_wmoEntryTab.nameId->setMinimum(std::numeric_limits<std::int32_t>::min());
_wmoEntryTab.nameId->setMaximum(std::numeric_limits<std::int32_t>::max());
connect(_wmoEntryTab.nameId, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int value) {
_wmoEntryTab.wmoEntry.nameID = value;
});
layout->addRow("Name Id:", _wmoEntryTab.nameId);
connect(remove_btn, &QPushButton::clicked
,[&] ()
{
removeMap();
_wmoEntryTab.uniqueId = new QSpinBox(_map_settings);
_wmoEntryTab.uniqueId->setDisabled(true);
_wmoEntryTab.uniqueId->setMinimum(std::numeric_limits<std::int32_t>::min());
_wmoEntryTab.uniqueId->setMaximum(std::numeric_limits<std::int32_t>::max());
connect(_wmoEntryTab.uniqueId, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int value) {
_wmoEntryTab.wmoEntry.uniqueID = value;
});
layout->addRow("Unique Id:", _wmoEntryTab.uniqueId);
_connection = connect(reinterpret_cast<Noggit::Ui::Windows::NoggitWindow*>(parent),
QOverload<int>::of(&Noggit::Ui::Windows::NoggitWindow::mapSelected)
, [&] (int index)
{
selectMap(index);
}
);
connect(_difficulty_type, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
selectMapDifficulty();
_wmoEntryTab.position = new Vector3fWidget(_map_settings);
_wmoEntryTab.position->setDisabled(true);
connect(_wmoEntryTab.position, &Vector3fWidget::valueChanged , [=](glm::vec3 const& value) {
_wmoEntryTab.wmoEntry.pos[0] = value.x;
_wmoEntryTab.wmoEntry.pos[1] = value.y;
_wmoEntryTab.wmoEntry.pos[2] = value.z;
});
layout->addRow("Position:", _wmoEntryTab.position);
// Selection
_wmoEntryTab.rotation = new Vector3fWidget(_map_settings);
_wmoEntryTab.rotation->setDisabled(true);
connect(_wmoEntryTab.rotation, &Vector3fWidget::valueChanged, [=](glm::vec3 const& value) {
_wmoEntryTab.wmoEntry.rot[0] = value.x;
_wmoEntryTab.wmoEntry.rot[1] = value.y;
_wmoEntryTab.wmoEntry.rot[2] = value.z;
});
layout->addRow("Rotation:", _wmoEntryTab.rotation);
QObject::connect
( _minimap_widget, &Noggit::Ui::minimap_widget::tile_clicked
, [this] (QPoint tile)
{
if (QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier))
{
int x = tile.x() - 1;
int y = tile.y() - 1;
_wmoEntryTab.flags = new QSpinBox(_map_settings);
_wmoEntryTab.flags->setDisabled(true);
_wmoEntryTab.flags->setMinimum(std::numeric_limits<std::uint16_t>::min());
_wmoEntryTab.flags->setMaximum(std::numeric_limits<std::uint16_t>::max());
connect(_wmoEntryTab.flags, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [=](int value) {
_wmoEntryTab.wmoEntry.flags = static_cast<uint16_t>(value);
});
layout->addRow("Flags:", _wmoEntryTab.flags);
for (int i = 0; i < 3; ++i)
_wmoEntryTab.doodadSet = new QComboBox(_map_settings);
_wmoEntryTab.doodadSet->setDisabled(true);
connect(_wmoEntryTab.doodadSet, &QComboBox::currentTextChanged, [=](QString)
{
for (int j = 0; j < 3; ++j)
{
int x_final = x + i;
int y_final = y + j;
_wmoEntryTab.wmoEntry.doodadSet = _wmoEntryTab.doodadSet->currentIndex();
});
layout->addRow("Doodad Set:", _wmoEntryTab.doodadSet);
if (x_final < 0 || x_final > 63 || y_final < 0 || y_final > 63)
continue;
_wmoEntryTab.nameSet = new QComboBox(_map_settings);
_wmoEntryTab.nameSet->setDisabled(true);
connect(_wmoEntryTab.nameSet, &QComboBox::currentTextChanged, [=](QString)
{
_wmoEntryTab.wmoEntry.nameSet = _wmoEntryTab.nameSet->currentIndex();
});
layout->addRow("Name set:", _wmoEntryTab.nameSet);
}
if (!_world->mapIndex.hasTile(TileIndex(x_final, y_final)))
void MapCreationWizard::populateWmoEntryTab()
{
if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
_wmoEntryTab.disableTerrain->setChecked(_world->mapIndex.hasAGlobalWMO());
if (!_world->mapIndex.hasAGlobalWMO())
{
_world->mapIndex.addTile(TileIndex(x_final, y_final));
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.removeTile(TileIndex(x_final, y_final));
}
}
}
_wmoEntryTab.wmoPath->clear();
_wmoEntryTab.nameId->clear();
_wmoEntryTab.uniqueId->clear();
_wmoEntryTab.position->clear();
_wmoEntryTab.rotation->clear();
_wmoEntryTab.flags->clear();
_wmoEntryTab.doodadSet->clear();
_wmoEntryTab.nameSet->clear();
}
else
{
int x = tile.x();
int y = tile.y();
_wmoEntryTab.wmoPath->setText(QString::fromStdString(_world->mWmoFilename));
_wmoEntryTab.wmoEntry = _world->mWmoEntry;
_wmoEntryTab.nameId->setValue(_wmoEntryTab.wmoEntry.nameID);
_wmoEntryTab.uniqueId->setValue(_wmoEntryTab.wmoEntry.uniqueID);
_wmoEntryTab.position->setValue(_wmoEntryTab.wmoEntry.pos);
_wmoEntryTab.rotation->setValue(_wmoEntryTab.wmoEntry.rot);
_wmoEntryTab.flags->setValue(_wmoEntryTab.wmoEntry.flags);
_wmoEntryTab.doodadSet->setCurrentIndex(_wmoEntryTab.wmoEntry.doodadSet);
_wmoEntryTab.nameSet->setCurrentIndex(_wmoEntryTab.wmoEntry.nameSet);
}
}
if (x < 0 || x > 63 || y < 0 || y > 63)
return;
if (!_world->mapIndex.hasTile(TileIndex(x, y)))
void MapCreationWizard::populateDoodadSet(WMOInstance& instance)
{
if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
QSignalBlocker const doodadsetblocker(_wmoEntryTab.doodadSet);
_wmoEntryTab.doodadSet->clear();
QStringList doodadsetnames;
for (auto& doodad_set : instance.wmo->doodadsets)
{
_world->mapIndex.addTile(TileIndex(x, y));
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
_world->mapIndex.removeTile(TileIndex(x, y));
doodadsetnames.append(doodad_set.name);
}
_wmoEntryTab.doodadSet->insertItems(0, doodadsetnames);
_wmoEntryTab.doodadSet->setCurrentIndex(instance.doodadset());
}
update();
void MapCreationWizard::populateNameSet(WMOInstance& instance)
{
// get names from WMOAreatable, if no name, get from areatable
// if no areatable, we have to get the terrain's area
QSignalBlocker const namesetblocker(_wmoEntryTab.nameSet);
_wmoEntryTab.nameSet->clear();
auto wmoid = instance.wmo->WmoId;
auto setnames = gWMOAreaTableDB.getWMOAreaNames(wmoid);
QStringList namesetnames;
for (auto& area_name : setnames)
{
if (area_name.empty())
{
auto chunk = _world->getChunkAt(instance.pos);
namesetnames.append(gAreaDB.getAreaFullName(chunk->getAreaID()).c_str());
}
else
namesetnames.append(area_name.c_str());
}
);
_wmoEntryTab.nameSet->insertItems(0, namesetnames);
_wmoEntryTab.nameSet->setCurrentIndex(instance.mNameset);
}
std::string MapCreationWizard::getDifficultyString()
@@ -518,6 +704,8 @@ void MapCreationWizard::selectMap(int map_id)
_project->ClientDatabase->UnloadTable("MapDifficulty");
_difficulty_type->setCurrentIndex(0);
selectMapDifficulty();
populateWmoEntryTab();
}
void MapCreationWizard::selectMapDifficulty()
@@ -633,6 +821,14 @@ void MapCreationWizard::saveCurrentEntry()
_world->mapIndex.setBigAlpha(_is_big_alpha->isChecked());
_world->setBasename(_directory->text().toStdString());
_world->mapIndex.set_sort_models_by_size_class(_sort_by_size_cat->isChecked());
if (_wmoEntryTab.disableTerrain->isChecked())
{
_world->mapIndex.addGlobalWmo(_wmoEntryTab.wmoPath->text().toStdString(), _wmoEntryTab.wmoEntry);
}
else
{
_world->mapIndex.removeGlobalWmo();
}
_world->mapIndex.saveChanged(_world, true);
_world->mapIndex.save(); // save wdt file

View File

@@ -26,6 +26,10 @@
namespace Noggit
{
namespace Ui
{
class Vector3fWidget;
}
namespace Ui::Tools::MapCreationWizard::Ui
{
@@ -98,6 +102,21 @@ namespace Noggit
void map_dbc_updated(int new_map = 0);
private:
struct WmoEntryTab
{
QCheckBox* disableTerrain = nullptr;
QLineEdit* wmoPath = nullptr;
QSpinBox* nameId = nullptr;
QSpinBox* uniqueId = nullptr;
Vector3fWidget* position = nullptr;
Vector3fWidget* rotation = nullptr;
QSpinBox* flags = nullptr;
QComboBox* doodadSet = nullptr;
QComboBox* nameSet = nullptr;
ENTRY_MODF wmoEntry;
};
std::shared_ptr<Project::NoggitProject> _project;
Noggit::Ui::minimap_widget* _minimap_widget;
int _selected_map;
@@ -139,6 +158,8 @@ namespace Noggit
QSpinBox* _difficulty_max_players;
QLineEdit* _difficulty_string;
WmoEntryTab _wmoEntryTab;
World* _world = nullptr;
bool _is_new_record = false;
@@ -156,6 +177,13 @@ namespace Noggit
void removeMap();
void createMapSettingsTab();
void createDifficultyTab();
void createWmoEntryTab();
void populateWmoEntryTab();
void populateDoodadSet(WMOInstance& instance);
void populateNameSet(WMOInstance& instance);
};
}
}

View File

@@ -0,0 +1,87 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#include "Vector3Widget.hpp"
#include <noggit/MapHeaders.h>
#include <QLabel>
#include <QDoubleSpinBox>
#include <QHBoxLayout>
namespace Noggit::Ui
{
Vector3fWidget::Vector3fWidget(QWidget* parent)
: QWidget(parent)
{
constexpr int spacing = 8;
_layout = new QHBoxLayout(this);
_layout->setContentsMargins(0, 0, 0, 0);
_layout->setSpacing(0);
_xLabel = new QLabel("X", this);
_xLabel->setStyleSheet("QLabel { background-color : red; color : white; }");
_xLabel->setMaximumWidth(14);
_xLabel->setAlignment(Qt::AlignCenter);
_layout->addWidget(_xLabel);
_xSpinbox = new QDoubleSpinBox(this);
_xSpinbox->setMinimum(0);
_xSpinbox->setMaximum(ZEROPOINT * 2);
connect(_xSpinbox, &QDoubleSpinBox::textChanged, [=](auto) {
emit valueChanged({
static_cast<float>(_xSpinbox->value()),
static_cast<float>(_ySpinbox->value()),
static_cast<float>(_zSpinbox->value()) });
});
_layout->addWidget(_xSpinbox);
_layout->addSpacing(spacing);
_yLabel = new QLabel("Y", this);
_yLabel->setStyleSheet("QLabel { background-color : green; color : white; }");
_yLabel->setMaximumWidth(14);
_yLabel->setAlignment(Qt::AlignCenter);
_layout->addWidget(_yLabel);
_ySpinbox = new QDoubleSpinBox(this);
_ySpinbox->setMinimum(0);
_ySpinbox->setMaximum(ZEROPOINT * 2);
connect(_ySpinbox, &QDoubleSpinBox::textChanged, [=](auto) {
emit valueChanged({
static_cast<float>(_xSpinbox->value()),
static_cast<float>(_ySpinbox->value()),
static_cast<float>(_zSpinbox->value()) });
});
_layout->addWidget(_ySpinbox);
_layout->addSpacing(spacing);
_zLabel = new QLabel("Z", this);
_zLabel->setStyleSheet("QLabel { background-color : blue; color : white; }");
_zLabel->setMaximumWidth(14);
_zLabel->setAlignment(Qt::AlignCenter);
_layout->addWidget(_zLabel);
_zSpinbox = new QDoubleSpinBox(this);
_zSpinbox->setMinimum(0);
_zSpinbox->setMaximum(ZEROPOINT * 2);
connect(_zSpinbox, &QDoubleSpinBox::textChanged, [=](auto) {
emit valueChanged({
static_cast<float>(_xSpinbox->value()),
static_cast<float>(_ySpinbox->value()),
static_cast<float>(_zSpinbox->value()) });
});
_layout->addWidget(_zSpinbox);
}
void Vector3fWidget::clear()
{
_xSpinbox->clear();
_ySpinbox->clear();
_zSpinbox->clear();
}
void Vector3fWidget::setValue(float value[3])
{
_xSpinbox->setValue(value[0]);
_ySpinbox->setValue(value[1]);
_zSpinbox->setValue(value[2]);
}
}

View File

@@ -0,0 +1,39 @@
// This file is part of Noggit3, licensed under GNU General Public License (version 3).
#pragma once
#include <glm/vec3.hpp>
#include <QWidget>
class QLabel;
class QHBoxLayout;
class QDoubleSpinBox;
namespace Noggit::Ui
{
class Vector3fWidget : public QWidget
{
Q_OBJECT
public:
Vector3fWidget(QWidget* parent = nullptr);
void clear();
void setValue(float value[3]);
signals:
void valueChanged(glm::vec3 const& value);
private:
glm::vec3 _vector = {};
QHBoxLayout* _layout = nullptr;
QLabel* _xLabel = nullptr;
QLabel* _yLabel = nullptr;
QLabel* _zLabel = nullptr;
QDoubleSpinBox* _xSpinbox = nullptr;
QDoubleSpinBox* _ySpinbox = nullptr;
QDoubleSpinBox* _zSpinbox = nullptr;
};
}

View File

@@ -20,6 +20,7 @@
#include <noggit/ui/windows/noggitWindow/components/BuildMapListComponent.hpp>
#include <noggit/application/Utils.hpp>
#include <noggit/application/NoggitApplication.hpp>
#include <math/coordinates.hpp>
#include <BlizzardDatabase.h>
#include <QtGui/QCloseEvent>
#include <QtWidgets/QHBoxLayout>
@@ -211,12 +212,12 @@ namespace Noggit::Ui::Windows
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;
pos = { _world->mWmoEntry.pos[0], _world->mWmoEntry.pos[1], _world->mWmoEntry.pos[2] };
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)));
camera_pitch = -math::degrees(math::radians(std::asin(dz / distance)));
}