Added #2100 Copy/paste frames (same SWF only)

This commit is contained in:
Jindra Petřík
2023-11-08 23:14:40 +01:00
parent 191eae40c5
commit 12a8a67c6f
17 changed files with 1537 additions and 108 deletions

View File

@@ -4574,4 +4574,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
}
return uninitializedAs2ClassTraits;
}
@Override
public SWF getSwf() {
return this;
}
}

View File

@@ -261,7 +261,7 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
if (swf.getCyclicCharacters().contains(r.characterId)) {
continue;
}
DepthState layer = new DepthState(swf, null);
DepthState layer = new DepthState(swf, null, null);
layer.colorTransForm = r.colorTransform;
layer.blendMode = r.blendMode;
layer.filters = r.filterList;
@@ -272,16 +272,16 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
}
if (r.buttonStateUp) {
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false));
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, frameUp, false));
}
if (r.buttonStateDown) {
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false));
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, frameDown, false));
}
if (r.buttonStateOver) {
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false));
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, frameOver, false));
}
if (r.buttonStateHitTest) {
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false));
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, frameHit, false));
}
}

View File

@@ -251,7 +251,7 @@ public class DefineButtonTag extends ButtonTag implements ASMSourceContainer {
if (swf.getCyclicCharacters().contains(r.characterId)) {
continue;
}
DepthState layer = new DepthState(swf, null);
DepthState layer = new DepthState(swf, null, null);
layer.colorTransForm = clrTrans;
layer.blendMode = r.blendMode;
layer.filters = r.filterList;
@@ -262,16 +262,16 @@ public class DefineButtonTag extends ButtonTag implements ASMSourceContainer {
}
if (r.buttonStateUp) {
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, false));
frameUp.layers.put(r.placeDepth, new DepthState(layer, frameUp, frameUp, false));
}
if (r.buttonStateDown) {
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, false));
frameDown.layers.put(r.placeDepth, new DepthState(layer, frameDown, frameDown, false));
}
if (r.buttonStateOver) {
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, false));
frameOver.layers.put(r.placeDepth, new DepthState(layer, frameOver, frameOver, false));
}
if (r.buttonStateHitTest) {
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, false));
frameHit.layers.put(r.placeDepth, new DepthState(layer, frameHit, frameHit, false));
}
}

View File

@@ -31,7 +31,9 @@ import com.jpexs.decompiler.flash.types.MATRIX;
import com.jpexs.decompiler.flash.types.RGBA;
import com.jpexs.decompiler.flash.types.filters.FILTER;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -77,6 +79,8 @@ public class DepthState {
private final SWF swf;
public Frame frame;
public Frame placeFrame;
public PlaceObjectTypeTag placeObjectTag;
@@ -94,14 +98,16 @@ public class DepthState {
return lastInstanceId.addAndGet(1);
}
public DepthState(SWF swf, Frame frame) {
public DepthState(SWF swf, Frame frame, Frame placeFrame) {
this.swf = swf;
this.frame = frame;
this.placeFrame = placeFrame;
this.instanceId = getNewInstanceId();
}
public DepthState(DepthState obj, Frame frame, boolean sameInstance) {
public DepthState(DepthState obj, Frame frame, Frame placeFrame, boolean sameInstance) {
this.frame = frame;
this.placeFrame = placeFrame;
swf = obj.swf;
characterId = obj.characterId;
matrix = obj.matrix;
@@ -166,4 +172,87 @@ public class DepthState {
return swf.getCharacter(characterId);
}
@Override
public int hashCode() {
int hash = 7;
hash = 29 * hash + this.depth;
hash = 29 * hash + this.characterId;
hash = 29 * hash + Objects.hashCode(this.matrix);
hash = 29 * hash + Objects.hashCode(this.instanceName);
hash = 29 * hash + Objects.hashCode(this.className);
hash = 29 * hash + Objects.hashCode(this.colorTransForm);
hash = 29 * hash + (this.cacheAsBitmap ? 1 : 0);
hash = 29 * hash + this.blendMode;
hash = 29 * hash + Objects.hashCode(this.filters);
hash = 29 * hash + (this.isVisible ? 1 : 0);
hash = 29 * hash + Objects.hashCode(this.backGroundColor);
hash = 29 * hash + Objects.hashCode(this.clipActions);
hash = 29 * hash + Arrays.hashCode(this.amfData);
hash = 29 * hash + this.ratio;
hash = 29 * hash + this.clipDepth;
hash = 29 * hash + this.time;
hash = 29 * hash + (this.hasImage ? 1 : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DepthState other = (DepthState) obj;
if (this.depth != other.depth) {
return false;
}
if (this.characterId != other.characterId) {
return false;
}
if (this.cacheAsBitmap != other.cacheAsBitmap) {
return false;
}
if (this.blendMode != other.blendMode) {
return false;
}
if (this.isVisible != other.isVisible) {
return false;
}
if (this.ratio != other.ratio) {
return false;
}
if (this.clipDepth != other.clipDepth) {
return false;
}
if (this.hasImage != other.hasImage) {
return false;
}
if (!Objects.equals(this.instanceName, other.instanceName)) {
return false;
}
if (!Objects.equals(this.className, other.className)) {
return false;
}
if (!Objects.equals(this.matrix, other.matrix)) {
return false;
}
if (!Objects.equals(this.colorTransForm, other.colorTransForm)) {
return false;
}
if (!Objects.equals(this.filters, other.filters)) {
return false;
}
if (!Objects.equals(this.backGroundColor, other.backGroundColor)) {
return false;
}
if (!Objects.equals(this.clipActions, other.clipActions)) {
return false;
}
return Arrays.equals(this.amfData, other.amfData);
}
}

View File

@@ -41,6 +41,9 @@ import java.util.TreeMap;
*/
public class Frame implements TreeItem, Exportable {
/**
* Zero based frame index
*/
public final int frame;
public TreeMap<Integer, DepthState> layers = new TreeMap<>();
@@ -67,9 +70,9 @@ public class Frame implements TreeItem, Exportable {
public boolean layersChanged;
public String label = null;
public List<String> labels = new ArrayList<>();
public boolean namedAnchor = false;
public List<Boolean> namedAnchors = new ArrayList<>();
public Frame(Timeline timeline, int frame) {
this.timeline = timeline;
@@ -82,7 +85,7 @@ public class Frame implements TreeItem, Exportable {
backgroundColor = obj.backgroundColor;
timeline = obj.timeline;
for (int depth : obj.layers.keySet()) {
layers.put(depth, new DepthState(obj.layers.get(depth), this, true));
layers.put(depth, new DepthState(obj.layers.get(depth), this, obj.layers.get(depth).placeFrame, true));
}
//Do not copy sounds
}

View File

@@ -144,6 +144,11 @@ public class Timeline {
return frames;
}
/**
*
* @param index 0-based frame index
* @return
*/
public synchronized Frame getFrame(int index) {
ensureInitialized();
if (index >= frames.size()) {
@@ -296,9 +301,10 @@ public class Timeline {
}
if (t instanceof FrameLabelTag) {
frame.label = ((FrameLabelTag) t).getLabelName();
frame.namedAnchor = ((FrameLabelTag) t).isNamedAnchor();
labelToFrame.put(frame.label, frames.size());
String labelName = ((FrameLabelTag) t).getLabelName();
frame.labels.add(labelName);
frame.namedAnchors.add(((FrameLabelTag) t).isNamedAnchor());
labelToFrame.put(labelName, frames.size());
} else if (t instanceof StartSoundTag) {
frame.sounds.add(((StartSoundTag) t).soundId);
frame.soundClasses.add(null);
@@ -314,11 +320,12 @@ public class Timeline {
int depth = po.getDepth();
DepthState fl = frame.layers.get(depth);
if (fl == null) {
frame.layers.put(depth, fl = new DepthState(swf, frame));
frame.layers.put(depth, fl = new DepthState(swf, frame, frame));
fl.depth = depth;
}
frame.layersChanged = true;
fl.placeObjectTag = po;
fl.placeFrame = frame;
fl.minPlaceObjectNum = Math.max(fl.minPlaceObjectNum, po.getPlaceObjectNum());
boolean wasEmpty = fl.characterId == -1 && fl.className == null;

View File

@@ -17,6 +17,7 @@
package com.jpexs.decompiler.flash.timeline;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
@@ -26,6 +27,8 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag;
*/
public interface Timelined extends BoundedTag {
public SWF getSwf();
public Timeline getTimeline();
public void resetTimeline();