11#include <QDomDocument>
16#include <kpluginfactory.h>
57 QFileInfo fi(fileName);
59 QDir
d = fi.absoluteDir();
89 folderId = ¤tFolder;
92 if (!folderName.isEmpty()) {
93 pathName = folderName +
"/";
99 if (child->
visible() && child->inherits(
"KisGroupLayer")) {
109 folder.
id = *folderId;
110 folder.
name = folderName;
117 if (child->
visible() && !child->inherits(
"KisGroupLayer") && !child->inherits(
"KisMask")) {
119 QString layerBaseName = child->
name().split(
" ").first();
122 file.pathName = pathName;
123 file.baseName = layerBaseName;
124 file.layerName = child->
name();
125 file.name = folderName +
"/" + layerBaseName +
".png";
127 qreal xmin = rc.left();
128 qreal ymin = rc.top();
129 qreal xmax = rc.right();
130 qreal ymax = rc.bottom();
132 file.width = xmax - xmin;
133 file.height = ymax - ymin;
139 folder.
files.append(file);
148 if (folder.
files.size() > 0) {
159 static int boneId = 0;
160 QString groupBaseName = groupLayer->
name().split(
" ").first();
164 bone->
name = groupBaseName;
169 qreal xmin = rc.left();
170 qreal ymin = rc.top();
171 qreal xmax = rc.right();
172 qreal ymax = rc.bottom();
174 bone->
x = (xmin + xmax) / 2;
175 bone->
y = -(ymin + ymax) / 2;
176 bone->
width = xmax - xmin;
177 bone->
height = ymax - ymin;
187 bone->
localX = bone->
x - parent->x;
188 bone->
localY = bone->
y - parent->y;
201 if (child->
visible() && child->inherits(
"KisGroupLayer")) {
219 Q_FOREACH(
Bone *child, startBone->
bones) {
226 qreal boneLocalAngle = 0;
227 qreal boneLocalScaleX = 1;
229 if (bone->
bones.length() >= 1) {
232 qreal dx = childBone->
x - bone->
x;
233 qreal dy = childBone->
y - bone->
y;
234 if (qAbs(dx) > 0 || qAbs(dy) > 0) {
236 boneLocalScaleX = sqrt(dx * dx + dy * dy) / 200;
243 if (qAbs(dx) > 0 || qAbs(dy) > 0) {
245 boneLocalScaleX = sqrt(dx * dx + dy * dy) / 200;
253 for (
int i = 0; i < bone->
bones.length(); ++i) {
259 childBone->
fixLocalX = tx * cos(-boneLocalAngle) - ty * sin(-boneLocalAngle);
260 childBone->
fixLocalY = tx * sin(-boneLocalAngle) + ty * cos(-boneLocalAngle);
268 for (
int i = 0; i <
m_objects.length(); ++i) {
270 m_objects[i].fixLocalAngle -= boneLocalAngle;
271 m_objects[i].fixLocalScaleX /= boneLocalScaleX;
276 for (
int i = 0; i < bone->
bones.length(); ++i) {
284 QDomElement boneRef = scml.createElement(
"bone_ref");
285 key.appendChild(boneRef);
286 boneRef.setAttribute(
"id", bone->
id);
291 boneRef.setAttribute(
"key",
"0");
292 Q_FOREACH(
const Bone *childBone, bone->
bones) {
300 QDomElement timeline = scml.createElement(
"timeline");
301 animation.appendChild(timeline);
303 timeline.setAttribute(
"name", bone->
name);
304 timeline.setAttribute(
"object_type",
"bone");
306 QDomElement key = scml.createElement(
"key");
307 timeline.appendChild(key);
308 key.setAttribute(
"id",
"0");
309 key.setAttribute(
"spin", 0);
311 QDomElement boneEl = scml.createElement(
"bone");
312 key.appendChild(boneEl);
313 boneEl.setAttribute(
"x", QString::number(bone->
fixLocalX,
'f', 2));
314 boneEl.setAttribute(
"y", QString::number(bone->
fixLocalY,
'f', 2));
315 boneEl.setAttribute(
"angle", QString::number(bone->
fixLocalAngle,
'f', 2));
316 boneEl.setAttribute(
"scale_x", QString::number(bone->
fixLocalScaleX,
'f', 2));
317 boneEl.setAttribute(
"scale_y", QString::number(bone->
fixLocalScaleY,
'f', 2));
321 Q_FOREACH(
const Bone *childBone, bone->
bones) {
330 QDomElement root = scml.createElement(
"spriter_data");
331 scml.appendChild(root);
332 root.setAttribute(
"scml_version", 1);
333 root.setAttribute(
"generator",
"krita");
334 root.setAttribute(
"generator_version", qApp->applicationVersion());
337 QDomElement fe = scml.createElement(
"folder");
338 root.appendChild(fe);
339 fe.setAttribute(
"id", folder.
id);
340 fe.setAttribute(
"name", folder.
name);
342 QDomElement fileElement = scml.createElement(
"file");
343 fe.appendChild(fileElement);
344 fileElement.setAttribute(
"id", file.id);
345 fileElement.setAttribute(
"name", file.name);
346 fileElement.setAttribute(
"width", QString::number(file.width,
'f', 2));
347 fileElement.setAttribute(
"height", QString::number(file.height,
'f', 2));
364 QDomElement entity = scml.createElement(
"entity");
365 root.appendChild(entity);
366 entity.setAttribute(
"id",
"0");
367 entity.setAttribute(
"name", entityName);
370 QDomElement animation = scml.createElement(
"animation");
371 entity.appendChild(animation);
372 animation.setAttribute(
"id",
"0");
373 animation.setAttribute(
"name",
"default");
374 animation.setAttribute(
"length",
"1000");
375 animation.setAttribute(
"looping",
"false");
378 QDomElement mainline = scml.createElement(
"mainline");
379 animation.appendChild(mainline);
381 QDomElement key = scml.createElement(
"key");
382 mainline.appendChild(key);
383 key.setAttribute(
"id",
"0");
389 QDomElement oe = scml.createElement(
"object_ref");
391 oe.setAttribute(
"id",
object.
id);
393 oe.setAttribute(
"parent",
object.bone->id);
396 oe.setAttribute(
"key",
"0");
397 oe.setAttribute(
"z_index",
object.
id);
409 if (f.id ==
object.folderId) {
417 if (f.id ==
object.fileId) {
422 Q_ASSERT(file.id >= 0);
424 QString objectName =
"object-" + file.baseName;
426 QDomElement timeline = scml.createElement(
"timeline");
427 animation.appendChild(timeline);
429 timeline.setAttribute(
"name", objectName);
431 QDomElement key = scml.createElement(
"key");
432 timeline.appendChild(key);
433 key.setAttribute(
"id",
"0");
434 key.setAttribute(
"spin",
"0");
436 QDomElement objectEl = scml.createElement(
"object");
437 key.appendChild(objectEl);
438 objectEl.setAttribute(
"folder",
object.folderId);
439 objectEl.setAttribute(
"file",
object.fileId);
440 objectEl.setAttribute(
"x",
object.fixLocalX);
441 objectEl.setAttribute(
"y",
object.fixLocalY);
442 objectEl.setAttribute(
"angle", QString::number(
kisRadiansToDegrees(
object.fixLocalAngle),
'f', 2));
443 objectEl.setAttribute(
"scale_x", QString::number(
object.fixLocalScaleX,
'f', 2));
444 objectEl.setAttribute(
"scale_y", QString::number(
object.fixLocalScaleY,
'f', 2));
450 if (!startBone)
return 0;
453 if (startBone->
name == name) {
456 Q_FOREACH(
Bone *child, startBone->
bones) {
458 if (child->
name == name) {
473 m_image = document->savingImage();
488 if (!result.
isOk()) {
489 dbgFile <<
"There were errors encountered while using the spriter exporter.";
500 for (
int folderIndex = 0, folderCount =
m_folders.size(); folderIndex < folderCount; ++folderIndex) {
502 for (
int fileIndex = 0, fileCount = folder.
files.size(); fileIndex < fileCount; ++ fileIndex) {
505 spriterObject.
id = objectId++;
507 spriterObject.
fileId = file.id;
508 spriterObject.
x = file.x;
509 spriterObject.
y = -file.y;
514 if (file.layerName.contains(
"bone(")) {
515 int start = file.layerName.indexOf(
"bone(") + 5;
516 int end = file.layerName.indexOf(
')', start);
517 QString boneName = file.layerName.mid(start, end - start);
528 if (folder.
groupName.contains(
"bone(")) {
529 int start = folder.
groupName.indexOf(
"bone(") + 5;
530 int end = folder.
groupName.indexOf(
')', start);
531 QString boneName = folder.
groupName.mid(start, end - start);
546 spriterObject.
bone = bone;
547 spriterObject.
localX = spriterObject.
x - bone->
x;
548 spriterObject.
localY = spriterObject.
y - bone->
y;
551 spriterObject.
bone = 0;
552 spriterObject.
localX = spriterObject.
x;
553 spriterObject.
localY = spriterObject.
y;
563 if (file.layerName.contains(
"slot(")) {
564 int start = file.layerName.indexOf(
"slot(") + 5;
565 int end = file.layerName.indexOf(
')', start);
567 slot->
name = file.layerName.mid(start, end - start);
571 spriterObject.
slot = slot;
582 for (
int i = 0; i <
m_objects.size(); ++i) {
598 fillScml(scml, fi.completeBaseName());
600 bool openedHere =
false;
602 openedHere = io->open(QIODevice::WriteOnly);
609 QString towrite =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
610 if (io->write(towrite.toUtf8()) != towrite.length()) {
613 towrite = scml.toString(4).toUtf8();
614 if (io->write(towrite.toUtf8()) != towrite.length()) {
633 supportedColorModels << QPair<KoID, KoID>()
640#include "kis_spriter_export.moc"
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
static KisExportCheckRegistry * instance()
vKisAnnotationSP_it endAnnotations()
KisGroupLayerSP rootLayer() const
QRect bounds() const override
vKisAnnotationSP_it beginAnnotations()
The base class for import and export filters.
void addSupportedColorModels(QList< QPair< KoID, KoID > > supportedColorModels, const QString &name, KisExportCheckBase::Level level=KisExportCheckBase::PARTIALLY)
void addCapability(KisExportCheckBase *capability)
static bool isColorSpaceSupported(const KoColorSpace *cs)
KisImportExportErrorCode buildFile(const QString &filename, const QRect &imageRect, const qreal xRes, const qreal yRes, KisPaintDeviceSP device, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, KisPNGOptions options, KisMetaData::Store *metaData)
QRect exactBounds() const
const KoColorSpace * colorSpace() const
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
KisImportExportErrorCode parseFolder(KisGroupLayerSP parentGroup, const QString &folderName, const QString &basePath, int *folderId=0)
~KisSpriterExport() override
Bone * parseBone(const Bone *parent, KisGroupLayerSP groupLayer)
KisGroupLayerSP m_rootLayer
KisImportExportErrorCode convert(KisDocument *document, QIODevice *io, KisPropertiesConfigurationSP configuration=0) override
QList< SpriterObject > m_objects
KisSpriterExport(QObject *parent, const QVariantList &)
void fillScml(QDomDocument &scml, const QString &entityName)
KisImportExportErrorCode savePaintDevice(KisPaintDeviceSP dev, const QString &fileName)
void writeBone(const Bone *bone, QDomElement &timeline, QDomDocument &scml)
void initializeCapabilities() override
void writeBoneRef(const Bone *bone, QDomElement &mainline, QDomDocument &scml)
QList< Folder > m_folders
K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin< KritaASCCDL >();) KritaASCCDL
T kisRadiansToDegrees(T radians)
void copyBone(Bone *startBone)
Bone * findBoneByName(Bone *startBone, const QString &name)
vKisAnnotationSP::iterator vKisAnnotationSP_it
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement
KisNodeSP findNodeByName(KisNodeSP root, const QString &name)
QList< SpriterFile > files
virtual KisPaintDeviceSP projection() const =0
virtual QRect exactBounds() const
virtual bool visible(bool recursive=false) const
QRect exactBounds() const override
KisNodeSP prevSibling() const
quint32 childCount() const
KisNodeSP lastChild() const
static KoColorSpaceRegistry * instance()
bool defaultAttachmentFlag