From b1ba7ed7045f345a3f591dba40ef84ae810c5237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 11 Aug 2025 17:30:26 +0200 Subject: [PATCH] Fixed: #2507 FLA export - Button hit test frame placing morphshapes Fixed: #2507 FLA export - Place characters over multiple button frames --- CHANGELOG.md | 3 + .../decompiler/flash/xfl/XFLConverter.java | 83 ++++++++++++------- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8862085e5..16d97f4d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,8 @@ All notable changes to this project will be documented in this file. - [#2496] Fonts - adding characters - truncating too wide advance widths - [#2498] Public traits with same name were not distinguishable - [#2503] Exporting sound streams as FLV +- [#2507] FLA export - Button hit test frame placing morphshapes +- [#2507] FLA export - Place characters over multiple button frames ### Changed - Icon of "Deobfuscation options" menu from pile of pills to medkit @@ -3966,6 +3968,7 @@ Major version of SWF to XML export changed to 2. [#2496]: https://www.free-decompiler.com/flash/issues/2496 [#2498]: https://www.free-decompiler.com/flash/issues/2498 [#2503]: https://www.free-decompiler.com/flash/issues/2503 +[#2507]: https://www.free-decompiler.com/flash/issues/2507 [#2476]: https://www.free-decompiler.com/flash/issues/2476 [#2404]: https://www.free-decompiler.com/flash/issues/2404 [#1418]: https://www.free-decompiler.com/flash/issues/1418 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index db8c19971..98a6c6719 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1627,22 +1627,29 @@ public class XFLConverter { for (BUTTONRECORD rec : records) { if (rec.placeDepth == i) { - boolean ok = false; - switch (frame) { - case 1: - ok = rec.buttonStateUp; - break; - case 2: - ok = rec.buttonStateOver; - break; - case 3: - ok = rec.buttonStateDown; - break; - case 4: - ok = rec.buttonStateHitTest; + int duration = 0; + while (frame + duration <= 4) { + boolean ok = false; + switch (frame + duration) { + case 1: + ok = rec.buttonStateUp; + break; + case 2: + ok = rec.buttonStateOver; + break; + case 3: + ok = rec.buttonStateDown; + break; + case 4: + ok = rec.buttonStateHitTest; + break; + } + if (!ok) { break; + } + duration++; } - if (!ok) { + if (duration == 0) { continue; } CXFORMWITHALPHA colorTransformAlpha = null; @@ -1659,7 +1666,7 @@ public class XFLConverter { } CharacterTag character = button.getSwf().getCharacter(rec.characterId); if (character != null) { - MATRIX matrix = rec.placeMatrix; + MATRIX matrix = rec.placeMatrix; XFLXmlWriter recCharWriter = new XFLXmlWriter(); if ((character instanceof ShapeTag) && (nonLibraryShapes.contains(character))) { @@ -1667,6 +1674,11 @@ public class XFLConverter { statusStack.pushStatus(character.toString()); convertShape(lastImportedId, characterNameMap, character.getSwf(), matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, false, false, recCharWriter); statusStack.popStatus(); + } else if (character instanceof MorphShapeTag) { //can happen for HIT_TEST frame + ShapeTag shape = ((MorphShapeTag) character).getStartShapeTag(); + statusStack.pushStatus(character.toString()); + convertShape(lastImportedId, characterNameMap, character.getSwf(), matrix, shape.getShapeNum(), shape.getShapes().shapeRecords, shape.getShapes().fillStyles, shape.getShapes().lineStyles, true, false, recCharWriter); + statusStack.popStatus(); } else if (character instanceof TextTag) { statusStack.pushStatus(character.toString()); convertText(frame, new AccessibilityBag() /*???*/, null, (TextTag) character, matrix, filters, recCharWriter, characterImportLinkageURL, lastImportedId, characterNameMap, characters); @@ -1683,25 +1695,34 @@ public class XFLConverter { convertSymbolInstance(-1, new AccessibilityBag() /*???*/, lastImportedId, characterNameMap, swf, null, matrix, colorTransformAlpha, false, blendMode, filters, true, null, null, null, character.getSwf().getCharacter(rec.characterId), flaVersion, recCharWriter); } - int duration = frame - lastFrame; - lastFrame = frame; - if (duration > 0) { - if (duration > 1) { - symbolStr.writeStartElement("DOMFrame", new String[]{ - "index", Integer.toString(frame - duration), - "duration", Integer.toString(duration - 1), - "keyMode", Integer.toString(KEY_MODE_NORMAL)}); - symbolStr.writeElementValue("elements", ""); - symbolStr.writeEndElement(); - } + int emptyDuration = frame - lastFrame - 1; + lastFrame = frame + duration - 1; + + + if (emptyDuration > 0) { symbolStr.writeStartElement("DOMFrame", new String[]{ - "index", Integer.toString(frame), - "keyMode", Integer.toString(KEY_MODE_NORMAL)}); - symbolStr.writeStartElement("elements"); - symbolStr.writeCharactersRaw(recCharWriter.toString()); - symbolStr.writeEndElement(); + "index", Integer.toString(frame - emptyDuration), + "duration", Integer.toString(emptyDuration), + "keyMode", Integer.toString(KEY_MODE_NORMAL)}); + symbolStr.writeElementValue("elements", ""); symbolStr.writeEndElement(); } + + if (duration > 1) { + symbolStr.writeStartElement("DOMFrame", new String[]{ + "index", Integer.toString(frame), + "duration", Integer.toString(duration), + "keyMode", Integer.toString(KEY_MODE_NORMAL)}); + } else { + symbolStr.writeStartElement("DOMFrame", new String[]{ + "index", Integer.toString(frame), + "keyMode", Integer.toString(KEY_MODE_NORMAL)}); + } + symbolStr.writeStartElement("elements"); + symbolStr.writeCharactersRaw(recCharWriter.toString()); + symbolStr.writeEndElement(); + symbolStr.writeEndElement(); + frame += duration - 1; } else { logger.log(Level.WARNING, "Character with id={0} was not found.", rec.characterId); }