File indexing completed on 2024-12-22 04:15:55
0001 /* 0002 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_spriter_export.h" 0008 0009 #include <QApplication> 0010 #include <QCheckBox> 0011 #include <QDomDocument> 0012 #include <QFileInfo> 0013 #include <QSlider> 0014 #include <QDir> 0015 0016 #include <kpluginfactory.h> 0017 0018 #include <KoColorSpaceConstants.h> 0019 #include <KoColorSpaceRegistry.h> 0020 0021 #include <KisExportCheckRegistry.h> 0022 #include <KisImportExportManager.h> 0023 0024 #include <KisDocument.h> 0025 #include <kis_group_layer.h> 0026 #include <kis_image.h> 0027 #include <kis_layer.h> 0028 #include <kis_node.h> 0029 #include <kis_painter.h> 0030 #include <kis_paint_layer.h> 0031 #include <kis_shape_layer.h> 0032 #include <kis_file_layer.h> 0033 #include <kis_clone_layer.h> 0034 #include <kis_generator_layer.h> 0035 #include <kis_adjustment_layer.h> 0036 #include <KisPart.h> 0037 #include <kis_types.h> 0038 #include <kis_png_converter.h> 0039 #include <kis_global.h> // for KisDegreesToRadians 0040 #include <kis_fast_math.h> 0041 #include <math.h> 0042 #include <kis_dom_utils.h> 0043 #include <kis_layer_utils.h> 0044 0045 K_PLUGIN_FACTORY_WITH_JSON(KisSpriterExportFactory, "krita_spriter_export.json", registerPlugin<KisSpriterExport>();) 0046 0047 KisSpriterExport::KisSpriterExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) 0048 { 0049 } 0050 0051 KisSpriterExport::~KisSpriterExport() 0052 { 0053 } 0054 0055 KisImportExportErrorCode KisSpriterExport::savePaintDevice(KisPaintDeviceSP dev, const QString &fileName) 0056 { 0057 QFileInfo fi(fileName); 0058 0059 QDir d = fi.absoluteDir(); 0060 d.mkpath(d.path()); 0061 QRect rc = m_image->bounds().intersected(dev->exactBounds()); 0062 0063 if (!KisPNGConverter::isColorSpaceSupported(dev->colorSpace())) { 0064 dev = new KisPaintDevice(*dev.data()); 0065 dev->convertTo(KoColorSpaceRegistry::instance()->rgb8()); 0066 } 0067 0068 KisPNGOptions options; 0069 options.forceSRGB = true; 0070 0071 vKisAnnotationSP_it beginIt = m_image->beginAnnotations(); 0072 vKisAnnotationSP_it endIt = m_image->endAnnotations(); 0073 0074 KisPNGConverter converter(0); 0075 KisImportExportErrorCode res = converter.buildFile(fileName, rc, m_image->xRes(), m_image->yRes(), dev, beginIt, endIt, options, 0); 0076 0077 return res; 0078 } 0079 0080 KisImportExportErrorCode KisSpriterExport::parseFolder(KisGroupLayerSP parentGroup, const QString &folderName, const QString &basePath, int *folderId) 0081 { 0082 // qDebug() << "parseFolder: parent" << parentGroup->name() 0083 // << "folderName" << folderName 0084 // << "basepath" << basePath; 0085 0086 int currentFolder=0; 0087 if(folderId == 0) 0088 { 0089 folderId = ¤tFolder; 0090 } 0091 QString pathName; 0092 if (!folderName.isEmpty()) { 0093 pathName = folderName + "/"; 0094 } 0095 0096 0097 KisNodeSP child = parentGroup->lastChild(); 0098 while (child) { 0099 if (child->visible() && child->inherits("KisGroupLayer")) { 0100 KisImportExportErrorCode res = parseFolder(qobject_cast<KisGroupLayer*>(child.data()), child->name().split(" ").first(), basePath + "/" + pathName, folderId); 0101 if (!res.isOk()) { 0102 return res; 0103 } 0104 } 0105 child = child->prevSibling(); 0106 } 0107 0108 Folder folder; 0109 folder.id = *folderId; 0110 folder.name = folderName; 0111 folder.groupName = parentGroup->name(); 0112 0113 int fileId = 0; 0114 child = parentGroup->lastChild(); 0115 0116 while (child) { 0117 if (child->visible() && !child->inherits("KisGroupLayer") && !child->inherits("KisMask")) { 0118 QRectF rc = m_image->bounds().intersected(child->exactBounds()); 0119 QString layerBaseName = child->name().split(" ").first(); 0120 SpriterFile file; 0121 file.id = fileId++; 0122 file.pathName = pathName; 0123 file.baseName = layerBaseName; 0124 file.layerName = child->name(); 0125 file.name = folderName + "/" + layerBaseName + ".png"; 0126 0127 qreal xmin = rc.left(); 0128 qreal ymin = rc.top(); 0129 qreal xmax = rc.right(); 0130 qreal ymax = rc.bottom(); 0131 0132 file.width = xmax - xmin; 0133 file.height = ymax - ymin; 0134 file.x = xmin; 0135 file.y = ymin; 0136 //qDebug() << "Created file" << file.id << file.name << file.pathName << file.baseName << file.width << file.height << file.layerName; 0137 KisImportExportErrorCode result = savePaintDevice(child->projection(), basePath + file.name); 0138 if (result.isOk()) { 0139 folder.files.append(file); 0140 } else { 0141 return result; 0142 } 0143 } 0144 0145 child = child->prevSibling(); 0146 } 0147 0148 if (folder.files.size() > 0) { 0149 //qDebug() << "Adding folder" << folder.id << folder.name << folder.groupName << folder.files.length(); 0150 m_folders.append(folder); 0151 (*folderId)++; 0152 } 0153 0154 return ImportExportCodes::OK; 0155 } 0156 0157 Bone *KisSpriterExport::parseBone(const Bone *parent, KisGroupLayerSP groupLayer) 0158 { 0159 static int boneId = 0; 0160 QString groupBaseName = groupLayer->name().split(" ").first(); 0161 Bone *bone = new Bone; 0162 bone->id = boneId++; 0163 bone->parentBone = parent; 0164 bone->name = groupBaseName; 0165 0166 if (m_boneLayer) { 0167 QRectF rc = m_image->bounds().intersected(m_boneLayer->exactBounds()); 0168 0169 qreal xmin = rc.left(); 0170 qreal ymin = rc.top(); 0171 qreal xmax = rc.right(); 0172 qreal ymax = rc.bottom(); 0173 0174 bone->x = (xmin + xmax) / 2; 0175 bone->y = -(ymin + ymax) / 2; 0176 bone->width = xmax - xmin; 0177 bone->height = ymax - ymin; 0178 } 0179 else { 0180 bone->x = 0.0; 0181 bone->y = 0.0; 0182 bone->width = 0.0; 0183 bone->height = 0.0; 0184 } 0185 0186 if (parent) { 0187 bone->localX = bone->x - parent->x; 0188 bone->localY = bone->y - parent->y; 0189 } 0190 else { 0191 bone->localX = bone->x; 0192 bone->localY = bone->y; 0193 } 0194 0195 bone->localAngle = 0.0; 0196 bone->localScaleX = 1.0; 0197 bone->localScaleY = 1.0; 0198 0199 KisNodeSP child = groupLayer->lastChild(); 0200 while (child) { 0201 if (child->visible() && child->inherits("KisGroupLayer")) { 0202 bone->bones.append(parseBone(bone, qobject_cast<KisGroupLayer*>(child.data()))); 0203 } 0204 child = child->prevSibling(); 0205 } 0206 0207 //qDebug() << "Created bone" << bone->id << "with" << bone->bones.size() << "bones"; 0208 return bone; 0209 } 0210 0211 void copyBone(Bone *startBone) 0212 { 0213 startBone->fixLocalX = startBone->localX; 0214 startBone->fixLocalY = startBone->localY; 0215 startBone->fixLocalAngle = startBone->localAngle; 0216 startBone->fixLocalScaleX= startBone->localScaleX; 0217 startBone->fixLocalScaleY= startBone->localScaleY; 0218 0219 Q_FOREACH(Bone *child, startBone->bones) { 0220 copyBone(child); 0221 } 0222 } 0223 0224 void KisSpriterExport::fixBone(Bone *bone) 0225 { 0226 qreal boneLocalAngle = 0; 0227 qreal boneLocalScaleX = 1; 0228 0229 if (bone->bones.length() >= 1) { 0230 // if a bone has one or more children, point at first child 0231 Bone *childBone = bone->bones[0]; 0232 qreal dx = childBone->x - bone->x; 0233 qreal dy = childBone->y - bone->y; 0234 if (qAbs(dx) > 0 || qAbs(dy) > 0) { 0235 boneLocalAngle = KisFastMath::atan2(dy, dx); 0236 boneLocalScaleX = sqrt(dx * dx + dy * dy) / 200; 0237 } 0238 } 0239 else if (bone->parentBone) { 0240 // else, if bone has parent, point away from parent 0241 qreal dx = bone->x - bone->parentBone->x; 0242 qreal dy = bone->y - bone->parentBone->y; 0243 if (qAbs(dx) > 0 || qAbs(dy) > 0) { 0244 boneLocalAngle = KisFastMath::atan2(dy, dx); 0245 boneLocalScaleX = sqrt(dx * dx + dy * dy) / 200; 0246 } 0247 } 0248 // adjust bone angle 0249 bone->fixLocalAngle += boneLocalAngle; 0250 bone->fixLocalScaleX *= boneLocalScaleX; 0251 0252 // rotate all the child bones back to world position 0253 for (int i = 0; i < bone->bones.length(); ++i) { 0254 Bone *childBone = bone->bones[i]; 0255 0256 qreal tx = childBone->fixLocalX; 0257 qreal ty = childBone->fixLocalY; 0258 0259 childBone->fixLocalX = tx * cos(-boneLocalAngle) - ty * sin(-boneLocalAngle); 0260 childBone->fixLocalY = tx * sin(-boneLocalAngle) + ty * cos(-boneLocalAngle); 0261 0262 childBone->fixLocalX /= boneLocalScaleX; 0263 childBone->fixLocalAngle -= boneLocalAngle; 0264 childBone->fixLocalScaleX /= boneLocalScaleX; 0265 } 0266 0267 // rotate all the child objects back to world position 0268 for (int i = 0; i < m_objects.length(); ++i) { 0269 if (m_objects[i].bone == bone) { 0270 m_objects[i].fixLocalAngle -= boneLocalAngle; 0271 m_objects[i].fixLocalScaleX /= boneLocalScaleX; 0272 } 0273 } 0274 0275 // process all child bones 0276 for (int i = 0; i < bone->bones.length(); ++i) { 0277 fixBone(bone->bones[i]); 0278 } 0279 } 0280 0281 void KisSpriterExport::writeBoneRef(const Bone *bone, QDomElement &key, QDomDocument &scml) 0282 { 0283 if (!bone) return; 0284 QDomElement boneRef = scml.createElement("bone_ref"); 0285 key.appendChild(boneRef); 0286 boneRef.setAttribute("id", bone->id); 0287 if (bone->parentBone) { 0288 boneRef.setAttribute("parent", bone->parentBone->id); 0289 } 0290 boneRef.setAttribute("timeline", m_timelineid++); 0291 boneRef.setAttribute("key", "0"); 0292 Q_FOREACH(const Bone *childBone, bone->bones) { 0293 writeBoneRef(childBone, key, scml); 0294 } 0295 } 0296 0297 void KisSpriterExport::writeBone(const Bone *bone, QDomElement &animation, QDomDocument &scml) 0298 { 0299 if (!bone) return; 0300 QDomElement timeline = scml.createElement("timeline"); 0301 animation.appendChild(timeline); 0302 timeline.setAttribute("id", m_timelineid); 0303 timeline.setAttribute("name", bone->name); 0304 timeline.setAttribute("object_type", "bone"); 0305 0306 QDomElement key = scml.createElement("key"); 0307 timeline.appendChild(key); 0308 key.setAttribute("id", "0"); 0309 key.setAttribute("spin", 0); 0310 0311 QDomElement boneEl = scml.createElement("bone"); 0312 key.appendChild(boneEl); 0313 boneEl.setAttribute("x", QString::number(bone->fixLocalX, 'f', 2)); 0314 boneEl.setAttribute("y", QString::number(bone->fixLocalY, 'f', 2)); 0315 boneEl.setAttribute("angle", QString::number(bone->fixLocalAngle, 'f', 2)); 0316 boneEl.setAttribute("scale_x", QString::number(bone->fixLocalScaleX, 'f', 2)); 0317 boneEl.setAttribute("scale_y", QString::number(bone->fixLocalScaleY, 'f', 2)); 0318 0319 m_timelineid++; 0320 0321 Q_FOREACH(const Bone *childBone, bone->bones) { 0322 writeBone(childBone, animation, scml); 0323 } 0324 } 0325 0326 void KisSpriterExport::fillScml(QDomDocument &scml, const QString &entityName) 0327 { 0328 //qDebug() << "Creating scml" << entityName; 0329 0330 QDomElement root = scml.createElement("spriter_data"); 0331 scml.appendChild(root); 0332 root.setAttribute("scml_version", 1); 0333 root.setAttribute("generator", "krita"); 0334 root.setAttribute("generator_version", qApp->applicationVersion()); 0335 0336 Q_FOREACH(const Folder &folder, m_folders) { 0337 QDomElement fe = scml.createElement("folder"); 0338 root.appendChild(fe); 0339 fe.setAttribute("id", folder.id); 0340 fe.setAttribute("name", folder.name); 0341 Q_FOREACH(const SpriterFile &file, folder.files) { 0342 QDomElement fileElement = scml.createElement("file"); 0343 fe.appendChild(fileElement); 0344 fileElement.setAttribute("id", file.id); 0345 fileElement.setAttribute("name", file.name); 0346 fileElement.setAttribute("width", QString::number(file.width, 'f', 2)); 0347 fileElement.setAttribute("height", QString::number(file.height, 'f', 2)); 0348 // qreal pivotX=0; 0349 // qreal pivotY=1; 0350 // Q_FOREACH(const SpriterObject &object, m_objects) { 0351 // if(file.id == object.fileId) 0352 // { 0353 // pivotX = (0.0 -(object.fixLocalX / file.width)); 0354 // pivotY = (1.0 -(object.fixLocalY / file.height)); 0355 // break; 0356 // } 0357 // } 0358 // fileElement.setAttribute("pivot_x", QString::number(pivotX, 'f', 2)); 0359 // fileElement.setAttribute("pivot_y", QString::number(pivotY, 'f', 2)); 0360 } 0361 } 0362 0363 // entity 0364 QDomElement entity = scml.createElement("entity"); 0365 root.appendChild(entity); 0366 entity.setAttribute("id", "0"); 0367 entity.setAttribute("name", entityName); 0368 0369 // entity/animation 0370 QDomElement animation = scml.createElement("animation"); 0371 entity.appendChild(animation); 0372 animation.setAttribute("id", "0"); 0373 animation.setAttribute("name", "default"); 0374 animation.setAttribute("length", "1000"); 0375 animation.setAttribute("looping", "false"); 0376 0377 // entity/animation/mainline 0378 QDomElement mainline = scml.createElement("mainline"); 0379 animation.appendChild(mainline); 0380 0381 QDomElement key = scml.createElement("key"); 0382 mainline.appendChild(key); 0383 key.setAttribute("id", "0"); 0384 0385 m_timelineid = 0; 0386 writeBoneRef(m_rootBone, key, scml); 0387 0388 Q_FOREACH(const SpriterObject &object, m_objects) { 0389 QDomElement oe = scml.createElement("object_ref"); 0390 key.appendChild(oe); 0391 oe.setAttribute("id", object.id); 0392 if (object.bone) { 0393 oe.setAttribute("parent", object.bone->id); 0394 } 0395 oe.setAttribute("timeline", m_timelineid++); 0396 oe.setAttribute("key", "0"); 0397 oe.setAttribute("z_index", object.id); 0398 } 0399 0400 // entity/animation/timeline 0401 m_timelineid = 0; 0402 if (m_rootBone) { 0403 writeBone(m_rootBone, animation, scml); 0404 } 0405 0406 Q_FOREACH(const SpriterObject &object, m_objects) { 0407 Folder folder; 0408 Q_FOREACH(const Folder & f, m_folders) { 0409 if (f.id == object.folderId) { 0410 folder = f; 0411 break; 0412 } 0413 } 0414 SpriterFile file; 0415 file.id = -1; 0416 Q_FOREACH(const SpriterFile &f, folder.files) { 0417 if (f.id == object.fileId) { 0418 file = f; 0419 break; 0420 } 0421 } 0422 Q_ASSERT(file.id >= 0); 0423 0424 QString objectName = "object-" + file.baseName; 0425 0426 QDomElement timeline = scml.createElement("timeline"); 0427 animation.appendChild(timeline); 0428 timeline.setAttribute("id", m_timelineid++); 0429 timeline.setAttribute("name", objectName); 0430 0431 QDomElement key = scml.createElement("key"); 0432 timeline.appendChild(key); 0433 key.setAttribute("id", "0"); 0434 key.setAttribute("spin", "0"); 0435 0436 QDomElement objectEl = scml.createElement("object"); 0437 key.appendChild(objectEl); 0438 objectEl.setAttribute("folder", object.folderId); 0439 objectEl.setAttribute("file", object.fileId); 0440 objectEl.setAttribute("x", object.fixLocalX); 0441 objectEl.setAttribute("y", object.fixLocalY); 0442 objectEl.setAttribute("angle", QString::number(kisRadiansToDegrees(object.fixLocalAngle), 'f', 2)); 0443 objectEl.setAttribute("scale_x", QString::number(object.fixLocalScaleX, 'f', 2)); 0444 objectEl.setAttribute("scale_y", QString::number(object.fixLocalScaleY, 'f', 2)); 0445 } 0446 } 0447 0448 Bone *findBoneByName(Bone *startBone, const QString &name) 0449 { 0450 if (!startBone) return 0; 0451 //qDebug() << "findBoneByName" << name << "starting with" << startBone->name; 0452 0453 if (startBone->name == name) { 0454 return startBone; 0455 } 0456 Q_FOREACH(Bone *child, startBone->bones) { 0457 //qDebug() << "looking for" << name << "found" << child->name; 0458 if (child->name == name) { 0459 return child; 0460 } 0461 Bone *grandChild = findBoneByName(child, name); 0462 if (grandChild){ 0463 return grandChild; 0464 } 0465 } 0466 return 0; 0467 } 0468 0469 KisImportExportErrorCode KisSpriterExport::convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP /*configuration*/) 0470 { 0471 QFileInfo fi(filename()); 0472 0473 m_image = document->savingImage(); 0474 0475 if (m_image->rootLayer()->childCount() == 0) { 0476 return ImportExportCodes::Failure; 0477 } 0478 0479 KisGroupLayerSP root = m_image->rootLayer(); 0480 0481 m_boneLayer = qobject_cast<KisLayer*>(KisLayerUtils::findNodeByName(root,"bone").data()); 0482 //qDebug() << "Found boneLayer" << m_boneLayer; 0483 0484 m_rootLayer= qobject_cast<KisGroupLayer*>(KisLayerUtils::findNodeByName(root,"root").data()); 0485 //qDebug() << "Fond rootLayer" << m_rootLayer; 0486 0487 KisImportExportErrorCode result = parseFolder(m_image->rootLayer(), "", fi.absolutePath()); 0488 if (!result.isOk()) { 0489 dbgFile << "There were errors encountered while using the spriter exporter."; 0490 return result; 0491 } 0492 0493 m_rootBone = 0; 0494 0495 if (m_rootLayer) { 0496 m_rootBone = parseBone(0, m_rootLayer); 0497 } 0498 // Generate objects 0499 int objectId = 0; 0500 for (int folderIndex = 0, folderCount = m_folders.size(); folderIndex < folderCount; ++folderIndex) { 0501 Folder folder = m_folders[folderCount - 1 - folderIndex]; 0502 for (int fileIndex = 0, fileCount = folder.files.size(); fileIndex < fileCount; ++ fileIndex) { 0503 SpriterFile file = folder.files[fileCount - 1 - fileIndex]; 0504 SpriterObject spriterObject; 0505 spriterObject.id = objectId++; 0506 spriterObject.folderId = folder.id; 0507 spriterObject.fileId = file.id; 0508 spriterObject.x = file.x; 0509 spriterObject.y = -file.y; 0510 Bone *bone = 0; 0511 0512 //qDebug() << "file layername" << file.layerName; 0513 // layer.name format: "base_name bone(bone_name) slot(slot_name)" 0514 if (file.layerName.contains("bone(")) { 0515 int start = file.layerName.indexOf("bone(") + 5; 0516 int end = file.layerName.indexOf(')', start); 0517 QString boneName = file.layerName.mid(start, end - start); 0518 bone = findBoneByName(m_rootBone, boneName); 0519 } 0520 0521 0522 // layer.name format: "base_name" 0523 if (!bone && m_rootBone) { 0524 bone = findBoneByName(m_rootBone, file.layerName); 0525 } 0526 // group.name format: "base_name bone(bone_name)" 0527 if (!bone && m_rootBone) { 0528 if (folder.groupName.contains("bone(")) { 0529 int start = folder.groupName.indexOf("bone(") + 5; 0530 int end = folder.groupName.indexOf(')', start); 0531 QString boneName = folder.groupName.mid(start, end - start); 0532 bone = findBoneByName(m_rootBone, boneName); 0533 } 0534 0535 // group.name format: "base_name" 0536 if (!bone) { 0537 bone = findBoneByName(m_rootBone, folder.groupName); 0538 } 0539 } 0540 0541 if (!bone) { 0542 bone = m_rootBone; 0543 } 0544 0545 if (bone) { 0546 spriterObject.bone = bone; 0547 spriterObject.localX = spriterObject.x - bone->x; 0548 spriterObject.localY = spriterObject.y - bone->y; 0549 } 0550 else { 0551 spriterObject.bone = 0; 0552 spriterObject.localX = spriterObject.x; 0553 spriterObject.localY = spriterObject.y; 0554 } 0555 0556 spriterObject.localAngle = 0; 0557 spriterObject.localScaleX = 1.0; 0558 spriterObject.localScaleY = 1.0; 0559 0560 SpriterSlot *slot = 0; 0561 0562 // layer.name format: "base_name bone(bone_name) slot(slot_name)" 0563 if (file.layerName.contains("slot(")) { 0564 int start = file.layerName.indexOf("slot(") + 5; 0565 int end = file.layerName.indexOf(')', start); 0566 slot = new SpriterSlot(); 0567 slot->name = file.layerName.mid(start, end - start); 0568 slot->defaultAttachmentFlag = file.layerName.contains("*"); 0569 } 0570 0571 spriterObject.slot = slot; 0572 0573 // qDebug() << "Created object" << spriterObject.id << spriterObject.folderId 0574 // << spriterObject.fileId << spriterObject.x << spriterObject.y 0575 // << spriterObject.localX << spriterObject.localY; 0576 0577 m_objects.append(spriterObject); 0578 } 0579 } 0580 0581 // Copy object transforms 0582 for (int i = 0; i < m_objects.size(); ++i) { 0583 m_objects[i].fixLocalX = m_objects[i].localX; 0584 m_objects[i].fixLocalY = m_objects[i].localY; 0585 m_objects[i].fixLocalAngle = m_objects[i].localAngle; 0586 m_objects[i].fixLocalScaleX = m_objects[i].localScaleX; 0587 m_objects[i].fixLocalScaleY = m_objects[i].localScaleY; 0588 } 0589 0590 // Calculate bone angles 0591 if (m_rootBone) { 0592 copyBone(m_rootBone); 0593 fixBone(m_rootBone); 0594 } 0595 0596 // Generate scml 0597 QDomDocument scml; 0598 fillScml(scml, fi.completeBaseName()); 0599 0600 bool openedHere = false; 0601 if (!io->isOpen()) { 0602 openedHere = io->open(QIODevice::WriteOnly); 0603 if (!openedHere) { 0604 // unsuccessful open 0605 return ImportExportCodes::NoAccessToWrite; 0606 } 0607 } 0608 0609 QString towrite = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 0610 if (io->write(towrite.toUtf8()) != towrite.length()) { 0611 return ImportExportCodes::ErrorWhileWriting; 0612 } 0613 towrite = scml.toString(4).toUtf8(); 0614 if (io->write(towrite.toUtf8()) != towrite.length()) { 0615 return ImportExportCodes::ErrorWhileWriting; 0616 } 0617 0618 delete m_rootBone; 0619 0620 if (openedHere) { 0621 // FIXME: causes crash... 0622 //io->close(); 0623 } 0624 0625 return ImportExportCodes::OK; 0626 } 0627 0628 void KisSpriterExport::initializeCapabilities() 0629 { 0630 addCapability(KisExportCheckRegistry::instance()->get("MultiLayerCheck")->create(KisExportCheckBase::SUPPORTED)); 0631 addCapability(KisExportCheckRegistry::instance()->get("LayerOpacityCheck")->create(KisExportCheckBase::PARTIALLY)); 0632 QList<QPair<KoID, KoID> > supportedColorModels; 0633 supportedColorModels << QPair<KoID, KoID>() 0634 << QPair<KoID, KoID>(RGBAColorModelID, Integer8BitsColorDepthID); 0635 addSupportedColorModels(supportedColorModels, "Spriter"); 0636 } 0637 0638 0639 0640 #include "kis_spriter_export.moc"