diff --git a/src/noggit/MapHeaders.h b/src/noggit/MapHeaders.h index 592b80df..5bc86fe0 100755 --- a/src/noggit/MapHeaders.h +++ b/src/noggit/MapHeaders.h @@ -2,7 +2,9 @@ #pragma once +#include #include +#include 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 extents; //uint16_t flags; uint16_t flags; uint16_t doodadSet; diff --git a/src/noggit/map_index.cpp b/src/noggit/map_index.cpp index 039735b2..6b6619b4 100755 --- a/src/noggit/map_index.cpp +++ b/src/noggit/map_index.cpp @@ -1,5 +1,6 @@ // This file is part of Noggit3, licensed under GNU General Public License (version 3). +#include #include #include #include @@ -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(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) diff --git a/src/noggit/map_index.hpp b/src/noggit/map_index.hpp index 486c5ce0..8ff7e76f 100755 --- a/src/noggit/map_index.hpp +++ b/src/noggit/map_index.hpp @@ -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); diff --git a/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.cpp b/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.cpp index 61c3cc16..c96ebbc8 100755 --- a/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.cpp +++ b/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -121,135 +122,11 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr 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); - auto map_settings_layout = new QFormLayout(map_settings_widget); - - _directory = new QLineEdit(_map_settings); - map_settings_layout->addRow("Map directory:", _directory); - - _is_big_alpha = new QCheckBox(this); - map_settings_layout->addRow("Big alpha:", _is_big_alpha); - _is_big_alpha->setChecked(true); - - _sort_by_size_cat = new QCheckBox(this); - map_settings_layout->addRow("Sort models", _sort_by_size_cat); - _sort_by_size_cat->setChecked(true); - _sort_by_size_cat->setToolTip("Sorts models based on their size on save. May help increase loading speed of the map."); - - - _instance_type = new QComboBox(_map_settings); - _instance_type->addItem("None"); - _instance_type->setItemData(0, QVariant(0)); - - _instance_type->addItem("Instance"); - _instance_type->setItemData(1, QVariant(1)); - - _instance_type->addItem("Raid"); - _instance_type->setItemData(2, QVariant(2)); - - _instance_type->addItem("Battleground"); - _instance_type->setItemData(3, QVariant(3)); - - _instance_type->addItem("Arena"); - _instance_type->setItemData(4, QVariant(4)); - - map_settings_layout->addRow("Map type:",_instance_type); - - _map_name = new LocaleDBCEntry(_map_settings); - map_settings_layout->addRow("Map name:",_map_name); - - _area_table_id = new QSpinBox(_map_settings); - map_settings_layout->addRow("Area ID:",_area_table_id); - _area_table_id->setMaximum(std::numeric_limits::max()); - - _map_desc_alliance = new LocaleDBCEntry(_map_settings); - map_settings_layout->addRow("Description (Alliance):",_map_desc_alliance); - - _map_desc_horde = new LocaleDBCEntry(_map_settings); - map_settings_layout->addRow("Description (Horde):",_map_desc_horde); - - _loading_screen = new QSpinBox(_map_settings); - map_settings_layout->addRow("Loading screen:",_loading_screen); - _loading_screen->setMaximum(std::numeric_limits::max()); - - _minimap_icon_scale = new QDoubleSpinBox(_map_settings); - map_settings_layout->addRow("Minimap icon scale:",_minimap_icon_scale); - - _corpse_map_id->setCurrentText("None"); - map_settings_layout->addRow("Corpse map:",_corpse_map_id); - - _corpse_x = new QDoubleSpinBox(_map_settings); - map_settings_layout->addRow("Corpse X:",_corpse_x); - _corpse_x->setMinimum(-17066.66656); // map size - _corpse_x->setMaximum(17066.66656); - - _corpse_y = new QDoubleSpinBox(_map_settings); - map_settings_layout->addRow("Corpse Y:",_corpse_y); - _corpse_y->setMinimum(-17066.66656); // map size - _corpse_y->setMaximum(17066.66656); - - _time_of_day_override = new QSpinBox(_map_settings); - _time_of_day_override->setMinimum(-1); - _time_of_day_override->setMaximum(2880); // Time Values from 0 to 2880 where each number represents a half minute from midnight to midnight - _time_of_day_override->setValue(-1); - - map_settings_layout->addRow("Daytime override:",_time_of_day_override); - - _expansion_id = new QComboBox(_map_settings); - - _expansion_id->addItem("Classic"); - _expansion_id->setItemData(0, QVariant(0)); - - _expansion_id->addItem("Burning Crusade"); - _expansion_id->setItemData(1, QVariant(1)); - - _expansion_id->addItem("Wrath of the Lich King"); - _expansion_id->setItemData(2, QVariant(2)); - - map_settings_layout->addRow("Expansion:",_expansion_id); - - _raid_offset = new QSpinBox(_map_settings); - _raid_offset->setMaximum(std::numeric_limits::max()); - map_settings_layout->addRow("Raid offset:",_raid_offset); - - _max_players = new QSpinBox(_map_settings); - _max_players->setMaximum(std::numeric_limits::max()); - map_settings_layout->addRow("Max players:",_max_players); - - // difficulty tab - auto difficulty_settings_layout = new QFormLayout(map_difficulty_widget); - _map_settings->setLayout(difficulty_settings_layout); - - _difficulty_type = new QComboBox(_map_settings); - _difficulty_type->setDisabled(true); - - difficulty_settings_layout->addRow("Difficulty Index", _difficulty_type); - - _difficulty_req_message = new LocaleDBCEntry(_map_settings); - _difficulty_req_message->setDisabled(true); // disable them until they're actually saveable, only "display" it for now - difficulty_settings_layout->addRow("Requirement Message", _difficulty_req_message); - - _difficulty_raid_duration = new QSpinBox(_map_settings); - _difficulty_raid_duration->setDisabled(true); - _difficulty_raid_duration->setRange(0, 7); - difficulty_settings_layout->addRow("Instance Duration(days)", _difficulty_raid_duration); - - _difficulty_max_players = new QSpinBox(_map_settings); - _difficulty_max_players->setDisabled(true); - difficulty_settings_layout->addRow("Max Players", _difficulty_max_players); - - _difficulty_string = new QLineEdit(_map_settings); - _difficulty_string->setDisabled(true); - difficulty_settings_layout->addRow("Difficulty String", _difficulty_string); - - difficulty_settings_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + createMapSettingsTab(); + createDifficultyTab(); + createWmoEntryTab(); // Bottom row auto bottom_row_wgt = new QWidget(layout_right_holder); @@ -327,7 +204,7 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr pro if (!_world->mapIndex.hasTile(TileIndex(x_final, y_final))) { - if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier)) + if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && !_wmoEntryTab.disableTerrain->isChecked()) { _world->mapIndex.addTile(TileIndex(x_final, y_final)); } @@ -349,7 +226,7 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr pro if (!_world->mapIndex.hasTile(TileIndex(x, y))) { - if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier)) + if (!QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && !_wmoEntryTab.disableTerrain->isChecked()) { _world->mapIndex.addTile(TileIndex(x, y)); } @@ -366,6 +243,315 @@ MapCreationWizard::MapCreationWizard(std::shared_ptr pro } +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); + map_settings_layout->addRow("Map directory:", _directory); + + _is_big_alpha = new QCheckBox(this); + map_settings_layout->addRow("Big alpha:", _is_big_alpha); + _is_big_alpha->setChecked(true); + + _sort_by_size_cat = new QCheckBox(this); + map_settings_layout->addRow("Sort models", _sort_by_size_cat); + _sort_by_size_cat->setChecked(true); + _sort_by_size_cat->setToolTip("Sorts models based on their size on save. May help increase loading speed of the map."); + + + _instance_type = new QComboBox(_map_settings); + _instance_type->addItem("None"); + _instance_type->setItemData(0, QVariant(0)); + + _instance_type->addItem("Instance"); + _instance_type->setItemData(1, QVariant(1)); + + _instance_type->addItem("Raid"); + _instance_type->setItemData(2, QVariant(2)); + + _instance_type->addItem("Battleground"); + _instance_type->setItemData(3, QVariant(3)); + + _instance_type->addItem("Arena"); + _instance_type->setItemData(4, QVariant(4)); + + map_settings_layout->addRow("Map type:", _instance_type); + + _map_name = new LocaleDBCEntry(_map_settings); + map_settings_layout->addRow("Map name:", _map_name); + + _area_table_id = new QSpinBox(_map_settings); + map_settings_layout->addRow("Area ID:", _area_table_id); + _area_table_id->setMaximum(std::numeric_limits::max()); + + _map_desc_alliance = new LocaleDBCEntry(_map_settings); + map_settings_layout->addRow("Description (Alliance):", _map_desc_alliance); + + _map_desc_horde = new LocaleDBCEntry(_map_settings); + map_settings_layout->addRow("Description (Horde):", _map_desc_horde); + + _loading_screen = new QSpinBox(_map_settings); + map_settings_layout->addRow("Loading screen:", _loading_screen); + _loading_screen->setMaximum(std::numeric_limits::max()); + + _minimap_icon_scale = new QDoubleSpinBox(_map_settings); + map_settings_layout->addRow("Minimap icon scale:", _minimap_icon_scale); + + _corpse_map_id->setCurrentText("None"); + map_settings_layout->addRow("Corpse map:", _corpse_map_id); + + _corpse_x = new QDoubleSpinBox(_map_settings); + map_settings_layout->addRow("Corpse X:", _corpse_x); + _corpse_x->setMinimum(-17066.66656); // map size + _corpse_x->setMaximum(17066.66656); + + _corpse_y = new QDoubleSpinBox(_map_settings); + map_settings_layout->addRow("Corpse Y:", _corpse_y); + _corpse_y->setMinimum(-17066.66656); // map size + _corpse_y->setMaximum(17066.66656); + + _time_of_day_override = new QSpinBox(_map_settings); + _time_of_day_override->setMinimum(-1); + _time_of_day_override->setMaximum(2880); // Time Values from 0 to 2880 where each number represents a half minute from midnight to midnight + _time_of_day_override->setValue(-1); + + map_settings_layout->addRow("Daytime override:", _time_of_day_override); + + _expansion_id = new QComboBox(_map_settings); + + _expansion_id->addItem("Classic"); + _expansion_id->setItemData(0, QVariant(0)); + + _expansion_id->addItem("Burning Crusade"); + _expansion_id->setItemData(1, QVariant(1)); + + _expansion_id->addItem("Wrath of the Lich King"); + _expansion_id->setItemData(2, QVariant(2)); + + map_settings_layout->addRow("Expansion:", _expansion_id); + + _raid_offset = new QSpinBox(_map_settings); + _raid_offset->setMaximum(std::numeric_limits::max()); + map_settings_layout->addRow("Raid offset:", _raid_offset); + + _max_players = new QSpinBox(_map_settings); + _max_players->setMaximum(std::numeric_limits::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"); + + auto difficulty_settings_layout = new QFormLayout(map_difficulty_widget); + _map_settings->setLayout(difficulty_settings_layout); + + _difficulty_type = new QComboBox(_map_settings); + _difficulty_type->setDisabled(true); + + difficulty_settings_layout->addRow("Difficulty Index", _difficulty_type); + + _difficulty_req_message = new LocaleDBCEntry(_map_settings); + _difficulty_req_message->setDisabled(true); // disable them until they're actually saveable, only "display" it for now + difficulty_settings_layout->addRow("Requirement Message", _difficulty_req_message); + + _difficulty_raid_duration = new QSpinBox(_map_settings); + _difficulty_raid_duration->setDisabled(true); + _difficulty_raid_duration->setRange(0, 7); + difficulty_settings_layout->addRow("Instance Duration(days)", _difficulty_raid_duration); + + _difficulty_max_players = new QSpinBox(_map_settings); + _difficulty_max_players->setDisabled(true); + difficulty_settings_layout->addRow("Max Players", _difficulty_max_players); + + _difficulty_string = new QLineEdit(_map_settings); + _difficulty_string->setDisabled(true); + difficulty_settings_layout->addRow("Difficulty String", _difficulty_string); + + difficulty_settings_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); +} + +void MapCreationWizard::createWmoEntryTab() +{ + 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); + + _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()) + { + 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); + + _wmoEntryTab.nameId = new QSpinBox(_map_settings); + _wmoEntryTab.nameId->setDisabled(true); + _wmoEntryTab.nameId->setMinimum(std::numeric_limits::min()); + _wmoEntryTab.nameId->setMaximum(std::numeric_limits::max()); + connect(_wmoEntryTab.nameId, static_cast(&QSpinBox::valueChanged), [=](int value) { + _wmoEntryTab.wmoEntry.nameID = value; + }); + layout->addRow("Name Id:", _wmoEntryTab.nameId); + + _wmoEntryTab.uniqueId = new QSpinBox(_map_settings); + _wmoEntryTab.uniqueId->setDisabled(true); + _wmoEntryTab.uniqueId->setMinimum(std::numeric_limits::min()); + _wmoEntryTab.uniqueId->setMaximum(std::numeric_limits::max()); + connect(_wmoEntryTab.uniqueId, static_cast(&QSpinBox::valueChanged), [=](int value) { + _wmoEntryTab.wmoEntry.uniqueID = value; + }); + layout->addRow("Unique Id:", _wmoEntryTab.uniqueId); + + _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); + + _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); + + _wmoEntryTab.flags = new QSpinBox(_map_settings); + _wmoEntryTab.flags->setDisabled(true); + _wmoEntryTab.flags->setMinimum(std::numeric_limits::min()); + _wmoEntryTab.flags->setMaximum(std::numeric_limits::max()); + connect(_wmoEntryTab.flags, static_cast(&QSpinBox::valueChanged), [=](int value) { + _wmoEntryTab.wmoEntry.flags = static_cast(value); + }); + layout->addRow("Flags:", _wmoEntryTab.flags); + + _wmoEntryTab.doodadSet = new QComboBox(_map_settings); + _wmoEntryTab.doodadSet->setDisabled(true); + connect(_wmoEntryTab.doodadSet, &QComboBox::currentTextChanged, [=](QString) + { + _wmoEntryTab.wmoEntry.doodadSet = _wmoEntryTab.doodadSet->currentIndex(); + }); + layout->addRow("Doodad Set:", _wmoEntryTab.doodadSet); + + _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); +} + +void MapCreationWizard::populateWmoEntryTab() +{ + _wmoEntryTab.disableTerrain->setChecked(_world->mapIndex.hasAGlobalWMO()); + if (!_world->mapIndex.hasAGlobalWMO()) + { + _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 + { + _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); + } +} + +void MapCreationWizard::populateDoodadSet(WMOInstance& instance) +{ + QSignalBlocker const doodadsetblocker(_wmoEntryTab.doodadSet); + _wmoEntryTab.doodadSet->clear(); + + QStringList doodadsetnames; + for (auto& doodad_set : instance.wmo->doodadsets) + { + doodadsetnames.append(doodad_set.name); + } + _wmoEntryTab.doodadSet->insertItems(0, doodadsetnames); + _wmoEntryTab.doodadSet->setCurrentIndex(instance.doodadset()); +} + +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() { if (_instance_type->itemData(_instance_type->currentIndex()).toInt() == 1 && _difficulty_max_players->value() == 5) // dungeon @@ -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 diff --git a/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.hpp b/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.hpp index 31138ac5..7630dbfd 100755 --- a/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.hpp +++ b/src/noggit/ui/tools/MapCreationWizard/Ui/MapCreationWizard.hpp @@ -26,6 +26,10 @@ namespace Noggit { + namespace Ui + { + class Vector3fWidget; + } namespace Ui::Tools::MapCreationWizard::Ui { @@ -98,7 +102,22 @@ namespace Noggit void map_dbc_updated(int new_map = 0); private: - std::shared_ptr _project; + 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; Noggit::Ui::minimap_widget* _minimap_widget; int _selected_map; QGroupBox* _map_settings; @@ -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); }; } } diff --git a/src/noggit/ui/widgets/Vector3Widget.cpp b/src/noggit/ui/widgets/Vector3Widget.cpp new file mode 100644 index 00000000..fdeea018 --- /dev/null +++ b/src/noggit/ui/widgets/Vector3Widget.cpp @@ -0,0 +1,87 @@ +// This file is part of Noggit3, licensed under GNU General Public License (version 3). +#include "Vector3Widget.hpp" +#include + +#include +#include +#include + +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(_xSpinbox->value()), + static_cast(_ySpinbox->value()), + static_cast(_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(_xSpinbox->value()), + static_cast(_ySpinbox->value()), + static_cast(_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(_xSpinbox->value()), + static_cast(_ySpinbox->value()), + static_cast(_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]); + } +} diff --git a/src/noggit/ui/widgets/Vector3Widget.hpp b/src/noggit/ui/widgets/Vector3Widget.hpp new file mode 100644 index 00000000..e37f5f71 --- /dev/null +++ b/src/noggit/ui/widgets/Vector3Widget.hpp @@ -0,0 +1,39 @@ +// This file is part of Noggit3, licensed under GNU General Public License (version 3). +#pragma once + +#include + +#include + +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; + }; +} \ No newline at end of file diff --git a/src/noggit/ui/windows/noggitWindow/NoggitWindow.cpp b/src/noggit/ui/windows/noggitWindow/NoggitWindow.cpp index 1a26980c..d7981384 100755 --- a/src/noggit/ui/windows/noggitWindow/NoggitWindow.cpp +++ b/src/noggit/ui/windows/noggitWindow/NoggitWindow.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -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))); }