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

This commit is contained in:
Jindra Petřík
2023-12-30 18:06:08 +01:00
parent 191eae40c5
commit 12a8a67c6f
17 changed files with 1537 additions and 108 deletions
@@ -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);
}
}
@@ -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
}
@@ -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;
@@ -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();