Layer *VariantToMapConverter::toLayer(const QVariant &variant) { const QVariantMap variantMap = variant.toMap(); Layer *layer = nullptr; if (variantMap[QLatin1String("type")] == QLatin1String("tilelayer")) layer = toTileLayer(variantMap); else if (variantMap[QLatin1String("type")] == QLatin1String("objectgroup")) layer = toObjectGroup(variantMap); else if (variantMap[QLatin1String("type")] == QLatin1String("imagelayer")) layer = toImageLayer(variantMap); else if (variantMap[QLatin1String("type")] == QLatin1String("group")) layer = toGroupLayer(variantMap); if (layer) { layer->setProperties(extractProperties(variantMap)); const QPointF offset(variantMap[QLatin1String("offsetx")].toDouble(), variantMap[QLatin1String("offsety")].toDouble()); layer->setOffset(offset); } return layer; }
Map *VariantToMapConverter::toMap(const QVariant &variant, const QDir &mapDir) { mGidMapper.clear(); mMapDir = mapDir; const QVariantMap variantMap = variant.toMap(); const QString orientationString = variantMap[QLatin1String("orientation")].toString(); Map::Orientation orientation = orientationFromString(orientationString); if (orientation == Map::Unknown) { mError = tr("Unsupported map orientation: \"%1\"") .arg(orientationString); return nullptr; } const QString staggerAxisString = variantMap[QLatin1String("staggeraxis")].toString(); Map::StaggerAxis staggerAxis = staggerAxisFromString(staggerAxisString); const QString staggerIndexString = variantMap[QLatin1String("staggerindex")].toString(); Map::StaggerIndex staggerIndex = staggerIndexFromString(staggerIndexString); const QString renderOrderString = variantMap[QLatin1String("renderorder")].toString(); Map::RenderOrder renderOrder = renderOrderFromString(renderOrderString); const int nextObjectId = variantMap[QLatin1String("nextobjectid")].toInt(); QScopedPointer<Map> map(new Map(orientation, variantMap[QLatin1String("width")].toInt(), variantMap[QLatin1String("height")].toInt(), variantMap[QLatin1String("tilewidth")].toInt(), variantMap[QLatin1String("tileheight")].toInt())); map->setHexSideLength(variantMap[QLatin1String("hexsidelength")].toInt()); map->setStaggerAxis(staggerAxis); map->setStaggerIndex(staggerIndex); map->setRenderOrder(renderOrder); if (nextObjectId) map->setNextObjectId(nextObjectId); mMap = map.data(); map->setProperties(extractProperties(variantMap)); const QString bgColor = variantMap[QLatin1String("backgroundcolor")].toString(); if (!bgColor.isEmpty() && QColor::isValidColor(bgColor)) map->setBackgroundColor(QColor(bgColor)); const auto tilesetVariants = variantMap[QLatin1String("tilesets")].toList(); for (const QVariant &tilesetVariant : tilesetVariants) { SharedTileset tileset = toTileset(tilesetVariant); if (!tileset) return nullptr; map->addTileset(tileset); } const auto layerVariants = variantMap[QLatin1String("layers")].toList(); for (const QVariant &layerVariant : layerVariants) { Layer *layer = toLayer(layerVariant); if (!layer) return nullptr; map->addLayer(layer); } // Try to load the tileset images auto tilesets = map->tilesets(); for (SharedTileset &tileset : tilesets) { if (!tileset->imageSource().isEmpty() && tileset->fileName().isEmpty()) tileset->loadImage(); } return map.take(); }
ObjectGroup *VariantToMapConverter::toObjectGroup(const QVariantMap &variantMap) { typedef QScopedPointer<ObjectGroup> ObjectGroupPtr; ObjectGroupPtr objectGroup(new ObjectGroup(variantMap[QLatin1String("name")].toString(), variantMap[QLatin1String("x")].toInt(), variantMap[QLatin1String("y")].toInt())); const qreal opacity = variantMap[QLatin1String("opacity")].toReal(); const bool visible = variantMap[QLatin1String("visible")].toBool(); objectGroup->setOpacity(opacity); objectGroup->setVisible(visible); objectGroup->setColor(variantMap.value(QLatin1String("color")).value<QColor>()); const QString drawOrderString = variantMap.value(QLatin1String("draworder")).toString(); if (!drawOrderString.isEmpty()) { objectGroup->setDrawOrder(drawOrderFromString(drawOrderString)); if (objectGroup->drawOrder() == ObjectGroup::UnknownOrder) { mError = tr("Invalid draw order: %1").arg(drawOrderString); return nullptr; } } const auto objectVariants = variantMap[QLatin1String("objects")].toList(); for (const QVariant &objectVariant : objectVariants) { const QVariantMap objectVariantMap = objectVariant.toMap(); const QString name = objectVariantMap[QLatin1String("name")].toString(); const QString type = objectVariantMap[QLatin1String("type")].toString(); const int id = objectVariantMap[QLatin1String("id")].toInt(); const int gid = objectVariantMap[QLatin1String("gid")].toInt(); const qreal x = objectVariantMap[QLatin1String("x")].toReal(); const qreal y = objectVariantMap[QLatin1String("y")].toReal(); const qreal width = objectVariantMap[QLatin1String("width")].toReal(); const qreal height = objectVariantMap[QLatin1String("height")].toReal(); const qreal rotation = objectVariantMap[QLatin1String("rotation")].toReal(); const QPointF pos(x, y); const QSizeF size(width, height); MapObject *object = new MapObject(name, type, pos, size); object->setId(id); object->setRotation(rotation); if (gid) { bool ok; object->setCell(mGidMapper.gidToCell(gid, ok)); if (const Tile *tile = object->cell().tile()) { const QSizeF &tileSize = tile->size(); if (width == 0) object->setWidth(tileSize.width()); if (height == 0) object->setHeight(tileSize.height()); } } if (objectVariantMap.contains(QLatin1String("visible"))) object->setVisible(objectVariantMap[QLatin1String("visible")].toBool()); object->setProperties(extractProperties(objectVariantMap)); objectGroup->addObject(object); const QVariant polylineVariant = objectVariantMap[QLatin1String("polyline")]; const QVariant polygonVariant = objectVariantMap[QLatin1String("polygon")]; const QVariant textVariant = objectVariantMap[QLatin1String("text")]; if (polygonVariant.isValid()) { object->setShape(MapObject::Polygon); object->setPolygon(toPolygon(polygonVariant)); } if (polylineVariant.isValid()) { object->setShape(MapObject::Polyline); object->setPolygon(toPolygon(polylineVariant)); } if (objectVariantMap.contains(QLatin1String("ellipse"))) object->setShape(MapObject::Ellipse); if (textVariant.isValid()) { object->setTextData(toTextData(textVariant.toMap())); object->setShape(MapObject::Text); } } return objectGroup.take(); }
SharedTileset VariantToMapConverter::toTileset(const QVariant &variant) { const QVariantMap variantMap = variant.toMap(); const int firstGid = variantMap[QLatin1String("firstgid")].toInt(); // Handle external tilesets const QVariant sourceVariant = variantMap[QLatin1String("source")]; if (!sourceVariant.isNull()) { QString source = resolvePath(mMapDir, sourceVariant); QString error; SharedTileset tileset = TilesetManager::instance()->loadTileset(source, &error); if (!tileset) { // Insert a placeholder to allow the map to load tileset = Tileset::create(QFileInfo(source).completeBaseName(), 32, 32); tileset->setFileName(source); tileset->setLoaded(false); } else { mGidMapper.insert(firstGid, tileset.data()); } return tileset; } const QString name = variantMap[QLatin1String("name")].toString(); const int tileWidth = variantMap[QLatin1String("tilewidth")].toInt(); const int tileHeight = variantMap[QLatin1String("tileheight")].toInt(); const int spacing = variantMap[QLatin1String("spacing")].toInt(); const int margin = variantMap[QLatin1String("margin")].toInt(); const QVariantMap tileOffset = variantMap[QLatin1String("tileoffset")].toMap(); const QVariantMap grid = variantMap[QLatin1String("grid")].toMap(); const int tileOffsetX = tileOffset[QLatin1String("x")].toInt(); const int tileOffsetY = tileOffset[QLatin1String("y")].toInt(); const int columns = tileOffset[QLatin1String("columns")].toInt(); const QString bgColor = variantMap[QLatin1String("backgroundcolor")].toString(); if (tileWidth <= 0 || tileHeight <= 0 || (firstGid == 0 && !mReadingExternalTileset)) { mError = tr("Invalid tileset parameters for tileset '%1'").arg(name); return SharedTileset(); } SharedTileset tileset(Tileset::create(name, tileWidth, tileHeight, spacing, margin)); tileset->setTileOffset(QPoint(tileOffsetX, tileOffsetY)); tileset->setColumnCount(columns); if (!grid.isEmpty()) { const QString orientation = grid[QLatin1String("orientation")].toString(); const QSize gridSize(grid[QLatin1String("width")].toInt(), grid[QLatin1String("height")].toInt()); tileset->setOrientation(Tileset::orientationFromString(orientation)); if (!gridSize.isEmpty()) tileset->setGridSize(gridSize); } if (!bgColor.isEmpty() && QColor::isValidColor(bgColor)) tileset->setBackgroundColor(QColor(bgColor)); QVariant imageVariant = variantMap[QLatin1String("image")]; if (!imageVariant.isNull()) { const int imageWidth = variantMap[QLatin1String("imagewidth")].toInt(); const int imageHeight = variantMap[QLatin1String("imageheight")].toInt(); ImageReference imageRef; imageRef.source = resolvePath(mMapDir, imageVariant); imageRef.size = QSize(imageWidth, imageHeight); tileset->setImageReference(imageRef); } const QString trans = variantMap[QLatin1String("transparentcolor")].toString(); if (!trans.isEmpty() && QColor::isValidColor(trans)) tileset->setTransparentColor(QColor(trans)); tileset->setProperties(extractProperties(variantMap)); // Read terrains QVariantList terrainsVariantList = variantMap[QLatin1String("terrains")].toList(); for (int i = 0; i < terrainsVariantList.count(); ++i) { QVariantMap terrainMap = terrainsVariantList[i].toMap(); Terrain *terrain = tileset->addTerrain(terrainMap[QLatin1String("name")].toString(), terrainMap[QLatin1String("tile")].toInt()); terrain->setProperties(extractProperties(terrainMap)); } // Read tiles (everything except their properties) const QVariantMap tilesVariantMap = variantMap[QLatin1String("tiles")].toMap(); QVariantMap::const_iterator it = tilesVariantMap.constBegin(); for (; it != tilesVariantMap.end(); ++it) { bool ok; const int tileId = it.key().toInt(); if (tileId < 0) { mError = tr("Invalid (negative) tile id: %1").arg(tileId); return SharedTileset(); } Tile *tile = tileset->findOrCreateTile(tileId); const QVariantMap tileVar = it.value().toMap(); tile->setType(tileVar[QLatin1String("type")].toString()); QList<QVariant> terrains = tileVar[QLatin1String("terrain")].toList(); if (terrains.count() == 4) { for (int i = 0; i < 4; ++i) { int terrainId = terrains.at(i).toInt(&ok); if (ok && terrainId >= 0 && terrainId < tileset->terrainCount()) tile->setCornerTerrainId(i, terrainId); } } float probability = tileVar[QLatin1String("probability")].toFloat(&ok); if (ok) tile->setProbability(probability); imageVariant = tileVar[QLatin1String("image")]; if (!imageVariant.isNull()) { QString imagePath = resolvePath(mMapDir, imageVariant); tileset->setTileImage(tile, QPixmap(imagePath), imagePath); } QVariantMap objectGroupVariant = tileVar[QLatin1String("objectgroup")].toMap(); if (!objectGroupVariant.isEmpty()) tile->setObjectGroup(toObjectGroup(objectGroupVariant)); QVariantList frameList = tileVar[QLatin1String("animation")].toList(); if (!frameList.isEmpty()) { QVector<Frame> frames(frameList.size()); for (int i = frameList.size() - 1; i >= 0; --i) { const QVariantMap frameVariantMap = frameList[i].toMap(); Frame &frame = frames[i]; frame.tileId = frameVariantMap[QLatin1String("tileid")].toInt(); frame.duration = frameVariantMap[QLatin1String("duration")].toInt(); } tile->setFrames(frames); } } // Read tile properties QVariantMap propertiesVariantMap = variantMap[QLatin1String("tileproperties")].toMap(); QVariantMap propertyTypesVariantMap = variantMap[QLatin1String("tilepropertytypes")].toMap(); for (it = propertiesVariantMap.constBegin(); it != propertiesVariantMap.constEnd(); ++it) { const int tileId = it.key().toInt(); const QVariant propertiesVar = it.value(); const QVariant propertyTypesVar = propertyTypesVariantMap.value(it.key()); const Properties properties = toProperties(propertiesVar, propertyTypesVar); tileset->findOrCreateTile(tileId)->setProperties(properties); } if (!mReadingExternalTileset) mGidMapper.insert(firstGid, tileset.data()); return tileset; }
bool SGFNode::makeNode(string sb) { // separate property string string propertyString; char c='\0'; int insideSBracket=0; // read properties up to first '(' or ';' // allowing '(' ')' inside '[' ']' for(int i=0;i<sb.length();i++) { c = sb.at(i); if(!insideSBracket && c=='[') insideSBracket++; else if(c==']' && (!(i>0&&sb.at(i-1)=='\\'))) insideSBracket--; if (insideSBracket==0) { if (c=='(' || c==';' || c==')') { propertyString = sb.substr(0, i); sb.erase(0, i); break; } } } // extract properties if(!extractProperties(propertyString)) { string message = "Bad node: "; message+=propertyString; message+="\n"; LogWriter::printerr(message, "SGF"); return false; } /* SGFNode* node; try { node = new SGFNode(); } catch(exception& e) { cerr << e.what(); return false; }*/ SGFNode node; if (c=='(') { string pb; int bcount, i; char b; while (c=='(') { // remove up to matching ')' from sb // and put into pb bcount = 0; insideSBracket = 0; for(i=0;i<sb.length();i++) { // WARNING: Don't count '(' or ')' inside comments! // and check for escaped ']' i.e. "C[This is some comment \](blah blah) ]" b = sb.at(i); if(!insideSBracket && b=='[') insideSBracket++; else if(b==']' && (!(i>0&&sb.at(i-1)=='\\'))) { insideSBracket--; // error check if(insideSBracket<0) { // The stupid program that wrote this sgf // has not escaped a ']' inside a comment insideSBracket = 0; // NOTE: We should really just quit parsing this sgf // and say's it's got an invalid node string message = "Bad node (mismatched brackets '[', ']'): "; message+=sb.substr(0, i); message+="\n"; LogWriter::printerr(message, "SGF"); return false; } } if(!insideSBracket) { if(b=='(') bcount++; else if(b==')' && bcount<=1) break; else if(b==')') bcount--; } } // remove '(;' from start by starting after it //pb = *(new string(sb.substr(2, i).trim())); pb = string(sb.substr(2, i)); sb.erase(0, i); if (pb.length()>0) { // run make node if(!node.makeNode(pb)) return false; // add as child addChild(node); } // see whats next c = sb.at(0); } } else if (c==';') { // copy all sb from after ';' to end string pb = string(sb.substr(1)); //pb.deleteCharAt(pb.length()-1); if (pb.length()>0) { // make sure this isn't the end of a variation // or an empty node e.g. '(;W[pp];B[pl];)' if(pb.at(0)!=')') { // run make node if(!node.makeNode(pb)) return false; // add as child addChild(node); } } } return true; }