void TiledMapLoader::loadObjectGroups(Map &map, rapidxml::xml_node<> &rootNode) {
		rapidxml::xml_node<> *objectGroupNode = nullptr;
		objectGroupNode = rootNode.first_node("objectgroup");
		while (objectGroupNode) {
			ObjectGroup::Ptr objectGroup(new ObjectGroup);
			XMLElement objectGroupElement(*objectGroupNode);
			objectGroup->setName(objectGroupElement.getString("name"));
			objectGroup->setDrawOrder(objectGroupElement.getString("draworder"));
			objectGroup->setWidth(objectGroupElement.getInt("width"));
			objectGroup->setHeight(objectGroupElement.getInt("height"));
			objectGroup->setVisible(objectGroupElement.getInt("visible", 1));
			objectGroup->setOpacity(objectGroupElement.getFloat("opacity", 1));
			objectGroup->parseProperties(*objectGroupNode);
			loadObjectGroupObjects(map, *objectGroup.get(), *objectGroupNode);
			map.addObjectGroup(std::move(objectGroup));
			objectGroupNode = objectGroupNode->next_sibling("objectgroup");
		}
	}
RootNode::RootNode() :
SceneNode(INVALID_GAMEOBJECT_ID, WeakBaseRenderComponentPtr(), RenderPass::RenderPass_0, &Mat4x4::Identity)
{
	m_Children.reserve(RenderPass::RenderPass_Last);

	// split children into different groups

	shared_ptr<SceneNode> staticGroup(CB_NEW SceneNode(INVALID_GAMEOBJECT_ID, WeakBaseRenderComponentPtr(), RenderPass::RenderPass_Static, &Mat4x4::Identity));
	m_Children.push_back(staticGroup);

	shared_ptr<SceneNode> objectGroup(CB_NEW SceneNode(INVALID_GAMEOBJECT_ID, WeakBaseRenderComponentPtr(), RenderPass::RenderPass_Object, &Mat4x4::Identity));
	m_Children.push_back(objectGroup);

	shared_ptr<SceneNode> skyGroup(CB_NEW SceneNode(INVALID_GAMEOBJECT_ID, WeakBaseRenderComponentPtr(), RenderPass::RenderPass_Sky, &Mat4x4::Identity));
	m_Children.push_back(skyGroup);

	shared_ptr<SceneNode> invisibleGroup(CB_NEW SceneNode(INVALID_GAMEOBJECT_ID, WeakBaseRenderComponentPtr(), RenderPass::RenderPass_NotRendered, &Mat4x4::Identity));
	m_Children.push_back(staticGroup);

}
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();
}