| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 |
- #include "map_data.h"
- #include <QFile>
- #include <QJsonDocument>
- namespace MapEditor {
- MapData::MapData(QObject *parent) : QObject(parent) { clear(); }
- void MapData::clear() {
- m_name = "New Map";
- m_description.clear();
- m_coordSystem = "grid";
- m_maxTroopsPerPlayer = 2000;
- m_grid = GridSettings{100, 100, 1.0F};
- m_terrain.clear();
- m_firecamps.clear();
- m_linearElements.clear();
- m_structures.clear();
- m_biome = QJsonObject();
- m_camera = QJsonObject();
- m_spawns = QJsonArray();
- m_victory = QJsonObject();
- m_rain = QJsonObject();
- m_undoStack.clear();
- m_redoStack.clear();
- setModified(false);
- emit dataChanged();
- emit undoRedoChanged();
- }
- void MapData::setName(const QString &name) {
- if (m_name != name) {
- m_name = name;
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::setGrid(const GridSettings &grid) {
- m_grid = grid;
- setModified(true);
- emit dataChanged();
- }
- void MapData::setModified(bool modified) {
- if (m_modified != modified) {
- m_modified = modified;
- emit modifiedChanged(modified);
- }
- }
- void MapData::executeCommand(std::unique_ptr<Command> cmd) {
- if (!cmd) {
- return;
- }
- cmd->execute();
- m_undoStack.push_back(std::move(cmd));
- m_redoStack.clear();
- setModified(true);
- emit undoRedoChanged();
- }
- void MapData::undo() {
- if (m_undoStack.empty()) {
- return;
- }
- auto cmd = std::move(m_undoStack.back());
- m_undoStack.pop_back();
- cmd->undo();
- m_redoStack.push_back(std::move(cmd));
- setModified(true);
- emit dataChanged();
- emit undoRedoChanged();
- }
- void MapData::redo() {
- if (m_redoStack.empty()) {
- return;
- }
- auto cmd = std::move(m_redoStack.back());
- m_redoStack.pop_back();
- cmd->execute();
- m_undoStack.push_back(std::move(cmd));
- setModified(true);
- emit dataChanged();
- emit undoRedoChanged();
- }
- bool MapData::loadFromJson(const QString &filePath) {
- QFile file(filePath);
- if (!file.open(QIODevice::ReadOnly)) {
- return false;
- }
- QByteArray data = file.readAll();
- file.close();
- QJsonParseError error;
- QJsonDocument doc = QJsonDocument::fromJson(data, &error);
- if (error.error != QJsonParseError::NoError) {
- return false;
- }
- QJsonObject root = doc.object();
- m_name = root["name"].toString("Untitled Map");
- m_description = root["description"].toString();
- m_coordSystem = root["coordSystem"].toString("grid");
- m_maxTroopsPerPlayer = root["maxTroopsPerPlayer"].toInt(2000);
- if (root.contains("grid")) {
- QJsonObject gridObj = root["grid"].toObject();
- m_grid.width = gridObj["width"].toInt(100);
- m_grid.height = gridObj["height"].toInt(100);
- m_grid.tileSize = static_cast<float>(gridObj["tileSize"].toDouble(1.0));
- }
- m_biome = root["biome"].toObject();
- m_camera = root["camera"].toObject();
- m_spawns = root["spawns"].toArray();
- m_victory = root["victory"].toObject();
- m_rain = root["rain"].toObject();
- m_terrain.clear();
- m_firecamps.clear();
- m_linearElements.clear();
- m_structures.clear();
- if (root.contains("terrain")) {
- parseTerrainArray(root["terrain"].toArray());
- }
- if (root.contains("firecamps")) {
- parseFirecampsArray(root["firecamps"].toArray());
- }
- if (root.contains("rivers")) {
- parseRiversArray(root["rivers"].toArray());
- }
- if (root.contains("roads")) {
- parseRoadsArray(root["roads"].toArray());
- }
- if (root.contains("bridges")) {
- parseBridgesArray(root["bridges"].toArray());
- }
- if (root.contains("spawns")) {
- parseStructuresFromSpawns(root["spawns"].toArray());
- }
- m_undoStack.clear();
- m_redoStack.clear();
- setModified(false);
- emit dataChanged();
- emit undoRedoChanged();
- return true;
- }
- bool MapData::saveToJson(const QString &filePath) const {
- QJsonObject root;
- root["name"] = m_name;
- if (!m_description.isEmpty()) {
- root["description"] = m_description;
- }
- root["coordSystem"] = m_coordSystem;
- root["maxTroopsPerPlayer"] = m_maxTroopsPerPlayer;
- QJsonObject gridObj;
- gridObj["width"] = m_grid.width;
- gridObj["height"] = m_grid.height;
- gridObj["tileSize"] = static_cast<double>(m_grid.tileSize);
- root["grid"] = gridObj;
- if (!m_biome.isEmpty()) {
- root["biome"] = m_biome;
- }
- if (!m_camera.isEmpty()) {
- root["camera"] = m_camera;
- }
- if (!m_victory.isEmpty()) {
- root["victory"] = m_victory;
- }
- if (!m_rain.isEmpty()) {
- root["rain"] = m_rain;
- }
- QJsonArray terrainArr = terrainToJson();
- if (!terrainArr.isEmpty()) {
- root["terrain"] = terrainArr;
- }
- QJsonArray firecampsArr = firecampsToJson();
- if (!firecampsArr.isEmpty()) {
- root["firecamps"] = firecampsArr;
- }
- QJsonArray riversArr = riversToJson();
- if (!riversArr.isEmpty()) {
- root["rivers"] = riversArr;
- }
- QJsonArray roadsArr = roadsToJson();
- if (!roadsArr.isEmpty()) {
- root["roads"] = roadsArr;
- }
- QJsonArray bridgesArr = bridgesToJson();
- if (!bridgesArr.isEmpty()) {
- root["bridges"] = bridgesArr;
- }
- QJsonArray spawnsArr = structuresToSpawnsJson();
- for (const auto &spawn : m_spawns) {
- QJsonObject spawnObj = spawn.toObject();
- QString type = spawnObj["type"].toString();
- if (type != "barracks" && type != "village") {
- spawnsArr.append(spawn);
- }
- }
- if (!spawnsArr.isEmpty()) {
- root["spawns"] = spawnsArr;
- }
- QJsonDocument doc(root);
- QFile file(filePath);
- if (!file.open(QIODevice::WriteOnly)) {
- return false;
- }
- file.write(doc.toJson(QJsonDocument::Indented));
- file.close();
- return true;
- }
- void MapData::parseTerrainArray(const QJsonArray &arr) {
- for (const auto &val : arr) {
- QJsonObject obj = val.toObject();
- TerrainElement elem;
- elem.type = obj["type"].toString();
- elem.x = static_cast<float>(obj["x"].toDouble());
- elem.z = static_cast<float>(obj["z"].toDouble());
- elem.radius = static_cast<float>(obj["radius"].toDouble(10.0));
- elem.width = static_cast<float>(obj["width"].toDouble(10.0));
- elem.depth = static_cast<float>(obj["depth"].toDouble(10.0));
- elem.height = static_cast<float>(obj["height"].toDouble(3.0));
- elem.rotation = static_cast<float>(obj["rotation"].toDouble(0.0));
- elem.entrances = obj["entrances"].toArray();
- QStringList knownKeys = {"type", "x", "z", "radius", "width",
- "depth", "height", "rotation", "entrances"};
- for (const QString &key : obj.keys()) {
- if (!knownKeys.contains(key)) {
- elem.extraFields[key] = obj[key];
- }
- }
- m_terrain.append(elem);
- }
- }
- void MapData::parseFirecampsArray(const QJsonArray &arr) {
- for (const auto &val : arr) {
- QJsonObject obj = val.toObject();
- FirecampElement elem;
- elem.x = static_cast<float>(obj["x"].toDouble());
- elem.z = static_cast<float>(obj["z"].toDouble());
- elem.intensity = static_cast<float>(obj["intensity"].toDouble(1.0));
- elem.radius = static_cast<float>(obj["radius"].toDouble(3.0));
- QStringList knownKeys = {"x", "z", "intensity", "radius"};
- for (const QString &key : obj.keys()) {
- if (!knownKeys.contains(key)) {
- elem.extraFields[key] = obj[key];
- }
- }
- m_firecamps.append(elem);
- }
- }
- void MapData::parseRiversArray(const QJsonArray &arr) {
- for (const auto &val : arr) {
- QJsonObject obj = val.toObject();
- LinearElement elem;
- elem.type = "river";
- QJsonArray startArr = obj["start"].toArray();
- QJsonArray endArr = obj["end"].toArray();
- if (startArr.size() >= 2 && endArr.size() >= 2) {
- elem.start = QVector2D(static_cast<float>(startArr[0].toDouble()),
- static_cast<float>(startArr[1].toDouble()));
- elem.end = QVector2D(static_cast<float>(endArr[0].toDouble()),
- static_cast<float>(endArr[1].toDouble()));
- }
- elem.width = static_cast<float>(obj["width"].toDouble(3.0));
- QStringList knownKeys = {"start", "end", "width"};
- for (const QString &key : obj.keys()) {
- if (!knownKeys.contains(key)) {
- elem.extraFields[key] = obj[key];
- }
- }
- m_linearElements.append(elem);
- }
- }
- void MapData::parseRoadsArray(const QJsonArray &arr) {
- for (const auto &val : arr) {
- QJsonObject obj = val.toObject();
- LinearElement elem;
- elem.type = "road";
- QJsonArray startArr = obj["start"].toArray();
- QJsonArray endArr = obj["end"].toArray();
- if (startArr.size() >= 2 && endArr.size() >= 2) {
- elem.start = QVector2D(static_cast<float>(startArr[0].toDouble()),
- static_cast<float>(startArr[1].toDouble()));
- elem.end = QVector2D(static_cast<float>(endArr[0].toDouble()),
- static_cast<float>(endArr[1].toDouble()));
- }
- elem.width = static_cast<float>(obj["width"].toDouble(3.0));
- elem.style = obj["style"].toString("default");
- QStringList knownKeys = {"start", "end", "width", "style"};
- for (const QString &key : obj.keys()) {
- if (!knownKeys.contains(key)) {
- elem.extraFields[key] = obj[key];
- }
- }
- m_linearElements.append(elem);
- }
- }
- void MapData::parseBridgesArray(const QJsonArray &arr) {
- for (const auto &val : arr) {
- QJsonObject obj = val.toObject();
- LinearElement elem;
- elem.type = "bridge";
- QJsonArray startArr = obj["start"].toArray();
- QJsonArray endArr = obj["end"].toArray();
- if (startArr.size() >= 2 && endArr.size() >= 2) {
- elem.start = QVector2D(static_cast<float>(startArr[0].toDouble()),
- static_cast<float>(startArr[1].toDouble()));
- elem.end = QVector2D(static_cast<float>(endArr[0].toDouble()),
- static_cast<float>(endArr[1].toDouble()));
- }
- elem.width = static_cast<float>(obj["width"].toDouble(4.0));
- elem.height = static_cast<float>(obj["height"].toDouble(0.5));
- QStringList knownKeys = {"start", "end", "width", "height"};
- for (const QString &key : obj.keys()) {
- if (!knownKeys.contains(key)) {
- elem.extraFields[key] = obj[key];
- }
- }
- m_linearElements.append(elem);
- }
- }
- QJsonArray MapData::terrainToJson() const {
- QJsonArray arr;
- for (const auto &elem : m_terrain) {
- QJsonObject obj;
- obj["type"] = elem.type;
- obj["x"] = static_cast<double>(elem.x);
- obj["z"] = static_cast<double>(elem.z);
- if (elem.type == "hill") {
- bool hasCustomDimensions = (elem.width != 10.0F && elem.width > 0.0F) ||
- (elem.depth != 10.0F && elem.depth > 0.0F);
- if (hasCustomDimensions) {
- if (elem.width > 0.0F) {
- obj["width"] = static_cast<double>(elem.width);
- }
- if (elem.depth > 0.0F) {
- obj["depth"] = static_cast<double>(elem.depth);
- }
- } else if (elem.radius > 0.0F) {
- obj["radius"] = static_cast<double>(elem.radius);
- }
- } else {
- obj["radius"] = static_cast<double>(elem.radius);
- }
- obj["height"] = static_cast<double>(elem.height);
- if (elem.rotation != 0.0F) {
- obj["rotation"] = static_cast<double>(elem.rotation);
- }
- if (!elem.entrances.isEmpty()) {
- obj["entrances"] = elem.entrances;
- }
- for (const QString &key : elem.extraFields.keys()) {
- obj[key] = elem.extraFields[key];
- }
- arr.append(obj);
- }
- return arr;
- }
- QJsonArray MapData::firecampsToJson() const {
- QJsonArray arr;
- for (const auto &elem : m_firecamps) {
- QJsonObject obj;
- obj["x"] = static_cast<double>(elem.x);
- obj["z"] = static_cast<double>(elem.z);
- obj["intensity"] = static_cast<double>(elem.intensity);
- obj["radius"] = static_cast<double>(elem.radius);
- for (const QString &key : elem.extraFields.keys()) {
- obj[key] = elem.extraFields[key];
- }
- arr.append(obj);
- }
- return arr;
- }
- QJsonArray MapData::riversToJson() const {
- QJsonArray arr;
- for (const auto &elem : m_linearElements) {
- if (elem.type != "river") {
- continue;
- }
- QJsonObject obj;
- obj["start"] = QJsonArray{static_cast<double>(elem.start.x()),
- static_cast<double>(elem.start.y())};
- obj["end"] = QJsonArray{static_cast<double>(elem.end.x()),
- static_cast<double>(elem.end.y())};
- obj["width"] = static_cast<double>(elem.width);
- for (const QString &key : elem.extraFields.keys()) {
- obj[key] = elem.extraFields[key];
- }
- arr.append(obj);
- }
- return arr;
- }
- QJsonArray MapData::roadsToJson() const {
- QJsonArray arr;
- for (const auto &elem : m_linearElements) {
- if (elem.type != "road") {
- continue;
- }
- QJsonObject obj;
- obj["start"] = QJsonArray{static_cast<double>(elem.start.x()),
- static_cast<double>(elem.start.y())};
- obj["end"] = QJsonArray{static_cast<double>(elem.end.x()),
- static_cast<double>(elem.end.y())};
- obj["width"] = static_cast<double>(elem.width);
- obj["style"] = elem.style.isEmpty() ? "default" : elem.style;
- for (const QString &key : elem.extraFields.keys()) {
- obj[key] = elem.extraFields[key];
- }
- arr.append(obj);
- }
- return arr;
- }
- QJsonArray MapData::bridgesToJson() const {
- QJsonArray arr;
- for (const auto &elem : m_linearElements) {
- if (elem.type != "bridge") {
- continue;
- }
- QJsonObject obj;
- obj["start"] = QJsonArray{static_cast<double>(elem.start.x()),
- static_cast<double>(elem.start.y())};
- obj["end"] = QJsonArray{static_cast<double>(elem.end.x()),
- static_cast<double>(elem.end.y())};
- obj["width"] = static_cast<double>(elem.width);
- obj["height"] = static_cast<double>(elem.height);
- for (const QString &key : elem.extraFields.keys()) {
- obj[key] = elem.extraFields[key];
- }
- arr.append(obj);
- }
- return arr;
- }
- void MapData::addTerrainElement(const TerrainElement &element) {
- m_terrain.append(element);
- setModified(true);
- emit dataChanged();
- }
- void MapData::updateTerrainElement(int index, const TerrainElement &element) {
- if (index >= 0 && index < m_terrain.size()) {
- m_terrain[index] = element;
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::removeTerrainElement(int index) {
- if (index >= 0 && index < m_terrain.size()) {
- m_terrain.removeAt(index);
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::addFirecamp(const FirecampElement &element) {
- m_firecamps.append(element);
- setModified(true);
- emit dataChanged();
- }
- void MapData::updateFirecamp(int index, const FirecampElement &element) {
- if (index >= 0 && index < m_firecamps.size()) {
- m_firecamps[index] = element;
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::removeFirecamp(int index) {
- if (index >= 0 && index < m_firecamps.size()) {
- m_firecamps.removeAt(index);
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::addLinearElement(const LinearElement &element) {
- m_linearElements.append(element);
- setModified(true);
- emit dataChanged();
- }
- void MapData::updateLinearElement(int index, const LinearElement &element) {
- if (index >= 0 && index < m_linearElements.size()) {
- m_linearElements[index] = element;
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::removeLinearElement(int index) {
- if (index >= 0 && index < m_linearElements.size()) {
- m_linearElements.removeAt(index);
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::addStructure(const StructureElement &element) {
- m_structures.append(element);
- setModified(true);
- emit dataChanged();
- }
- void MapData::updateStructure(int index, const StructureElement &element) {
- if (index >= 0 && index < m_structures.size()) {
- m_structures[index] = element;
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::removeStructure(int index) {
- if (index >= 0 && index < m_structures.size()) {
- m_structures.removeAt(index);
- setModified(true);
- emit dataChanged();
- }
- }
- void MapData::parseStructuresFromSpawns(const QJsonArray &arr) {
- for (const auto &val : arr) {
- QJsonObject obj = val.toObject();
- QString type = obj["type"].toString();
- if (type == "barracks" || type == "village") {
- StructureElement elem;
- elem.type = type;
- elem.x = static_cast<float>(obj["x"].toDouble());
- elem.z = static_cast<float>(obj["z"].toDouble());
- elem.playerId = obj["playerId"].toInt(0);
- elem.maxPopulation = obj["maxPopulation"].toInt(150);
- elem.nation = obj["nation"].toString();
- QStringList knownKeys = {"type", "x", "z", "playerId",
- "maxPopulation", "nation"};
- for (const QString &key : obj.keys()) {
- if (!knownKeys.contains(key)) {
- elem.extraFields[key] = obj[key];
- }
- }
- m_structures.append(elem);
- }
- }
- }
- QJsonArray MapData::structuresToSpawnsJson() const {
- QJsonArray arr;
- for (const auto &elem : m_structures) {
- QJsonObject obj;
- obj["type"] = elem.type;
- obj["x"] = static_cast<double>(elem.x);
- obj["z"] = static_cast<double>(elem.z);
- if (elem.playerId > 0) {
- obj["playerId"] = elem.playerId;
- }
- obj["maxPopulation"] = elem.maxPopulation;
- if (!elem.nation.isEmpty()) {
- obj["nation"] = elem.nation;
- }
- for (const QString &key : elem.extraFields.keys()) {
- obj[key] = elem.extraFields[key];
- }
- arr.append(obj);
- }
- return arr;
- }
- } // namespace MapEditor
|