From 6a14c761ad6a59054b724c5cebbcfb2ea3cda68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 10 Dec 2022 16:06:19 +0100 Subject: [PATCH] Fixed Classnames in PlaceObject --- CHANGELOG.md | 1 + .../src/com/jpexs/decompiler/flash/SWF.java | 19 +++++- .../flash/exporters/FrameExporter.java | 10 +-- .../decompiler/flash/timeline/DepthState.java | 21 ++++++- .../decompiler/flash/timeline/Timeline.java | 63 ++++++++++++------- .../decompiler/flash/gui/ImagePanel.java | 12 ++-- .../flash/gui/timeline/TimelineBodyPanel.java | 7 ++- 7 files changed, 93 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94960a37c..013935175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ All notable changes to this project will be documented in this file. - Clone tag - Hide freetransform button in readonly mode - Maintain export name/class on imported tags +- Classnames in PlaceObject ### Changed - Quick search needs minimum of 3 characters diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 600045a68..12d1c3c20 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -391,12 +391,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { @Internal private Map importedTagToExportNameMapping = new HashMap<>(); - + @Internal + private Map classToCharacter = new HashMap<>(); + private static final DecompilerPool decompilerPool = new DecompilerPool(); @Internal private AbcIndexing abcIndex; - + private static AbcIndexing playerGlobalAbcIndex; private static AbcIndexing airGlobalAbcIndex; @@ -738,6 +740,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { public CharacterTag getCharacter(int characterId) { return getCharacters().get(characterId); } + + public CharacterTag getCharacterByClass(String className) { + if (!classToCharacter.containsKey(className)) { + return null; + } + int charId = classToCharacter.get(className); + return getCharacter(charId); + } public String getExportName(int characterId) { CharacterTag characterTag = getCharacters().get(characterId); @@ -1867,6 +1877,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } } } + + classToCharacter.clear(); + for (int ch:classes.keySet()) { + classToCharacter.put(classes.get(ch), ch); + } } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index 5472cd9e9..99dcffa74 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -737,14 +737,14 @@ public class FrameExporter { continue; } DepthState layer = frameObj.layers.get(i); - if (!timeline.swf.getCharacters().containsKey(layer.characterId)) { - continue; - } if (!layer.isVisible) { continue; } - CharacterTag character = timeline.swf.getCharacter(layer.characterId); + CharacterTag character = layer.getCharacter(); + if (character == null) { + continue; + } Matrix placeMatrix = new Matrix(layer.matrix); placeMatrix.scaleX /= unitDivisor; @@ -793,7 +793,7 @@ public class FrameExporter { + ctrans.getRedMulti() + "," + ctrans.getGreenMulti() + "," + ctrans.getBlueMulti() + "," + ctrans.getAlphaMulti() + "))"; } - result.append("\t\t\tplace(\"").append(SWF.getTypePrefix(character)).append(layer.characterId).append("\",canvas,ctx,[").append(placeMatrix.scaleX).append(",") + result.append("\t\t\tplace(\"").append(SWF.getTypePrefix(character)).append(layer.getCharacter().getCharacterId()).append("\",canvas,ctx,[").append(placeMatrix.scaleX).append(",") .append(placeMatrix.rotateSkew0).append(",") .append(placeMatrix.rotateSkew1).append(",") .append(placeMatrix.scaleY).append(",") diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java index 48fdf7776..0adbd00e7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/DepthState.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; import com.jpexs.decompiler.flash.tags.PlaceObject3Tag; import com.jpexs.decompiler.flash.tags.PlaceObject4Tag; import com.jpexs.decompiler.flash.tags.PlaceObjectTag; +import com.jpexs.decompiler.flash.tags.base.CharacterTag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.types.CLIPACTIONS; import com.jpexs.decompiler.flash.types.CXFORM; @@ -45,6 +46,8 @@ public class DepthState { public MATRIX matrix; public String instanceName; + + public String className; public ColorTransform colorTransForm; @@ -103,6 +106,7 @@ public class DepthState { matrix = obj.matrix; instanceName = obj.instanceName; colorTransForm = obj.colorTransForm; + className = obj.className; cacheAsBitmap = obj.cacheAsBitmap; blendMode = obj.blendMode; filters = obj.filters; @@ -142,10 +146,23 @@ public class DepthState { return new PlaceObject2Tag(swf, false, depth, characterId, matrix, cxForm, ratio, instanceName, clipDepth, clipActions); } else if (minPlaceObjectNum == 3) { CXFORMWITHALPHA cxForm = colorTransForm == null ? null : new CXFORMWITHALPHA(colorTransForm); - return new PlaceObject3Tag(swf, false, depth, null/*todo: className*/, characterId, matrix, cxForm, ratio, instanceName, clipDepth, filters, blendMode, cacheAsBitmap ? 1 : 0, isVisible ? 1 : 0, backGroundColor, clipActions, hasImage); + return new PlaceObject3Tag(swf, false, depth, className, characterId, matrix, cxForm, ratio, instanceName, clipDepth, filters, blendMode, cacheAsBitmap ? 1 : 0, isVisible ? 1 : 0, backGroundColor, clipActions, hasImage); } CXFORMWITHALPHA cxForm = colorTransForm == null ? null : new CXFORMWITHALPHA(colorTransForm); - return new PlaceObject4Tag(swf, false, depth, null/*todo: className*/, characterId, matrix, cxForm, ratio, instanceName, clipDepth, filters, blendMode, cacheAsBitmap ? 1 : 0, isVisible ? 1 : 0, backGroundColor, clipActions, null, hasImage); + return new PlaceObject4Tag(swf, false, depth, className, characterId, matrix, cxForm, ratio, instanceName, clipDepth, filters, blendMode, cacheAsBitmap ? 1 : 0, isVisible ? 1 : 0, backGroundColor, clipActions, null, hasImage); + } + + public CharacterTag getCharacter() { + if (characterId == -1) { + + if (className != null) { + return swf.getCharacterByClass(className); + } + + return null; + } + + return swf.getCharacter(characterId); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 74edefc3e..ecff4bf4a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -81,6 +81,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.Stack; import org.w3c.dom.Element; @@ -328,6 +329,18 @@ public class Timeline { fl.characterId = -1; } } + String className = po.getClassName(); + if (className != null) { + fl.className = className; + character = swf.getCharacterByClass(className); + if (character instanceof DefineSpriteTag) { + if (swf.getCyclicCharacters().contains(characterId)) { + fl.className = null; + } + } + } + + if (po.flagMove()) { MATRIX matrix2 = po.getMatrix(); if (matrix2 != null) { @@ -341,6 +354,11 @@ public class Timeline { if (colorTransForm2 != null) { fl.colorTransForm = colorTransForm2; } + + String className2 = po.getClassName(); + if (className2 != null) { + fl.className = className2; + } CLIPACTIONS clipActions2 = po.getClipActions(); if (clipActions2 != null) { @@ -420,14 +438,15 @@ public class Timeline { private synchronized void detectTweens() { for (int d = 1; d <= maxDepth; d++) { int characterId = -1; + String charClassName = null; int len = 0; for (int f = 0; f <= frames.size(); f++) { DepthState ds = f >= frames.size() ? null : frames.get(f).layers.get(d); - if (ds != null && characterId != -1 && ds.characterId == characterId) { + if (ds != null && (characterId != -1 || charClassName != null) && (ds.characterId == characterId && Objects.equals(ds.className, charClassName))) { len++; } else { - if (characterId != -1) { + if (characterId != -1 || charClassName != null) { int startPos = f - len; List matrices = new ArrayList<>(len); for (int k = 0; k < len; k++) { @@ -450,6 +469,7 @@ public class Timeline { } characterId = ds == null ? -1 : ds.characterId; + charClassName = ds == null ? null : ds.className; } } } @@ -573,13 +593,12 @@ public class Timeline { Frame frameObj = getFrame(frame); for (int depth : frameObj.layers.keySet()) { DepthState layer = frameObj.layers.get(depth); - if (layer.characterId != -1) { - if (!swf.getCharacters().containsKey(layer.characterId)) { - continue; - } - usedCharacters.add(layer.characterId); - swf.getCharacter(layer.characterId).getNeededCharactersDeep(usedCharacters); + CharacterTag ch = layer.getCharacter(); + if (ch == null) { + continue; } + usedCharacters.add(ch.getCharacterId()); + ch.getNeededCharactersDeep(usedCharacters); } } @@ -1035,14 +1054,14 @@ public class Timeline { continue; } DepthState layer = frameObj.layers.get(i); - if (!swf.getCharacters().containsKey(layer.characterId)) { - continue; - } if (!layer.isVisible) { continue; } - CharacterTag character = swf.getCharacter(layer.characterId); + CharacterTag character = layer.getCharacter(); + if (character == null) { + continue; + } Matrix layerMatrix = new Matrix(layer.matrix); Matrix mat = transformation.concatenate(layerMatrix); @@ -1187,14 +1206,14 @@ public class Timeline { continue; } DepthState layer = frameObj.layers.get(i); - if (!swf.getCharacters().containsKey(layer.characterId)) { - continue; - } if (!layer.isVisible) { continue; } - CharacterTag character = swf.getCharacter(layer.characterId); + CharacterTag character =layer.getCharacter(); + if (character == null) { + continue; + } ColorTransform clrTrans = colorTransform; if (layer.colorTransForm != null && layer.blendMode <= 1) { // Normal blend mode @@ -1277,7 +1296,7 @@ public class Timeline { for (int d = maxDepth; d >= 0; d--) { DepthState ds = fr.layers.get(d); if (ds != null) { - CharacterTag c = swf.getCharacter(ds.characterId); + CharacterTag c = ds.getCharacter(); if (c instanceof Timelined) { int frameCount = ((Timelined) c).getTimeline().frames.size(); if (frameCount == 0) { @@ -1322,7 +1341,7 @@ public class Timeline { if (!layer.isVisible) { continue; } - CharacterTag character = swf.getCharacter(layer.characterId); + CharacterTag character = layer.getCharacter(); if (character instanceof DrawableTag) { DrawableTag drawable = (DrawableTag) character; Matrix m = transformation.concatenate(new Matrix(layer.matrix)); @@ -1383,13 +1402,13 @@ public class Timeline { continue; } DepthState layer = frameObj.layers.get(i); - if (!swf.getCharacters().containsKey(layer.characterId)) { - continue; - } if (!layer.isVisible) { continue; } - CharacterTag character = swf.getCharacter(layer.characterId); + CharacterTag character = layer.getCharacter(); + if (character == null) { + continue; + } if (character instanceof DrawableTag) { DrawableTag drawable = (DrawableTag) character; if (!drawable.isSingleFrame()) { diff --git a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java index 9bc40ef1d..67f968c7b 100644 --- a/src/com/jpexs/decompiler/flash/gui/ImagePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/ImagePanel.java @@ -317,7 +317,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } if (ds != null) { - CharacterTag cht = swf.getCharacter(ds.characterId); + CharacterTag cht = ds.getCharacter(); if (cht != null) { if (cht instanceof DrawableTag) { RECT rect = timelined.getRect(); @@ -359,7 +359,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } if (ds != null) { - CharacterTag cht = swf.getCharacter(ds.characterId); + CharacterTag cht = ds.getCharacter(); if (cht != null) { if (cht instanceof DrawableTag) { DrawableTag dt = (DrawableTag) cht; @@ -1400,7 +1400,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } DepthState ds = f.layers.get(selectedDepth); if (ds != null) { - CharacterTag cht = timelined.getTimeline().swf.getCharacter(ds.characterId); + CharacterTag cht = ds.getCharacter(); if (cht != null) { debugLabel.setText(cht.getName()); } @@ -1943,7 +1943,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } if (ds != null) { - CharacterTag cht = swf.getCharacter(ds.characterId); + CharacterTag cht = ds.getCharacter(); if (cht != null) { if (cht instanceof DrawableTag) { DrawableTag dt = (DrawableTag) cht; @@ -1971,7 +1971,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } if (ds != null) { - CharacterTag cht = swf.getCharacter(ds.characterId); + CharacterTag cht = ds.getCharacter(); if (cht != null) { if (cht instanceof DrawableTag) { DrawableTag dt = (DrawableTag) cht; @@ -2365,7 +2365,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay { } first = false; - CharacterTag c = swf.getCharacter(ds.characterId); + CharacterTag c = ds.getCharacter(); ret.append(c.toString()); if (ds.depth > 0) { ret.append(" "); diff --git a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java index ff70f8b65..de63a5461 100644 --- a/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/timeline/TimelineBodyPanel.java @@ -36,6 +36,7 @@ import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.swing.JPanel; import org.pushingpixels.substance.api.ColorSchemeAssociationKind; import org.pushingpixels.substance.api.ComponentState; @@ -201,7 +202,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe for (; start_f2 >= 1; start_f2--) { DepthState ds = timeline.getFrame(start_f2 - 1).layers.get(d); if (((dsStart == null) != (ds == null)) - || (ds != null && dsStart.characterId != ds.characterId)) { + || (ds != null && (dsStart.characterId != ds.characterId || !Objects.equals(dsStart.className, ds.className)))) { break; } } @@ -213,7 +214,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe DepthState flNext = f < max_f ? timeline.getFrame(f + 1).layers.get(d) : null; DepthState flPrev = f > 0 ? timeline.getFrame(f - 1).layers.get(d) : null; - CharacterTag cht = fl == null ? null : timeline.swf.getCharacter(fl.characterId); + CharacterTag cht = fl == null ? null : fl.getCharacter(); boolean shapeTween = cht != null && (cht instanceof MorphShapeTag); boolean motionTweenStart = !motionTween && (flNext != null && flNext.motionTween); boolean motionTweenEnd = !motionTween && (flPrev != null && flPrev.motionTween); @@ -230,7 +231,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe if (fl == null) { for (; f + 1 < timeline.getFrameCount(); f++) { fl = timeline.getFrame(f + 1).layers.get(d); - if (fl != null && fl.characterId != -1) { + if (fl != null && fl.getCharacter() != null) { break; }