Add to stage tag order fix.

This commit is contained in:
Jindra Petřík
2024-10-06 09:40:05 +02:00
parent 3dd6e6fad8
commit 875b9c17d3
9 changed files with 146 additions and 23 deletions

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.VideoFrameTag;
import com.jpexs.decompiler.flash.tags.base.CharacterIdTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.base.RemoveTag;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* This class fixes SWF that all CharacterTags (and attached CharacterIdTags)
* are placed before their usage.
* @author JPEXS
*/
public class DefineBeforeUsageFixer {
public boolean fixDefineBeforeUsage(SWF swf) {
ReadOnlyTagList tags = swf.getTags();
Set<Integer> walkedCharacters = new HashSet<>();
boolean changed = false;
for (int i = 0; i < tags.size(); i++) {
Tag t = tags.get(i);
Set<Integer> needed = new LinkedHashSet<>();
t.getNeededCharactersDeep(needed);
for (int chId : needed) {
if (walkedCharacters.contains(chId)) {
continue;
}
walkedCharacters.add(chId);
CharacterTag ch = swf.getCharacter(chId);
if (ch != null) {
int defineIndex = tags.indexOf(ch);
int usageIndex = i;
if (usageIndex < defineIndex) {
i += moveCharacter(swf, i, chId);
changed = true;
}
}
}
}
return changed;
}
private int moveCharacter(SWF swf, int usageIndex, int characterId) {
int i = 0;
for (int j = 0; j < swf.getTags().size(); j++) {
Tag t2 = swf.getTags().get(j);
if ((t2 instanceof CharacterIdTag)
&& !(t2 instanceof PlaceObjectTypeTag)
&& !(t2 instanceof RemoveTag)
&& !(t2 instanceof VideoFrameTag)) {
CharacterIdTag chit = (CharacterIdTag) t2;
if (chit.getCharacterId() == characterId) {
swf.removeTag(j);
swf.addTag(usageIndex + i, (Tag) chit);
i++;
}
}
}
return i;
}
}

View File

@@ -1613,7 +1613,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param characters Map of characterId to CharacterTag
* @param characterIdTags Map of characterId to list of CharacterIdTags
*/
private void parseCharacters(Iterable<Tag> list, Map<Integer, DefineExternalImage2> externalImages2, Map<Integer, CharacterTag> characters, Map<Integer, List<CharacterIdTag>> characterIdTags) {
private synchronized void parseCharacters(Iterable<Tag> list, Map<Integer, DefineExternalImage2> externalImages2, Map<Integer, CharacterTag> characters, Map<Integer, List<CharacterIdTag>> characterIdTags) {
Iterator<Tag> iterator = list.iterator();
while (iterator.hasNext()) {
Tag t = iterator.next();
@@ -5068,7 +5068,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param removeDependencies Remove dependencies?
* @param listener Listener to call after removing each of character.
*/
public void removeTags(Collection<Tag> tags, boolean removeDependencies, TagRemoveListener listener) {
public synchronized void removeTags(Collection<Tag> tags, boolean removeDependencies, TagRemoveListener listener) {
Set<Timelined> timelineds = new HashSet<>();
for (Tag tag : tags) {
Timelined timelined = tag.getTimelined();
@@ -5091,7 +5091,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param index Index of tag
*/
@Override
public void removeTag(int index) {
public synchronized void removeTag(int index) {
setModified(true);
tags.remove(index);
updateCharacters();
@@ -5103,10 +5103,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param tag Tag
*/
@Override
public void removeTag(Tag tag) {
public synchronized void removeTag(Tag tag) {
setModified(true);
tags.remove(tag);
updateCharacters();
readOnlyTags = null;
}
/**
@@ -5116,13 +5117,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param removeDependencies Remove dependencies?
* @param listener Listener to call after removing each of character.
*/
public void removeTag(Tag tag, boolean removeDependencies, TagRemoveListener listener) {
public synchronized void removeTag(Tag tag, boolean removeDependencies, TagRemoveListener listener) {
Timelined timelined = tag.getTimelined();
removeTagInternal(timelined, tag, removeDependencies, listener);
resetTimelines(timelined);
updateCharacters();
clearImageCache();
clearShapeCache();
readOnlyTags = null;
}
/**
@@ -5161,7 +5163,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @return Tags
*/
@Override
public ReadOnlyTagList getTags() {
public synchronized ReadOnlyTagList getTags() {
if (readOnlyTags == null) {
readOnlyTags = new ReadOnlyTagList(tags);
}
@@ -5175,10 +5177,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param tag Tag
*/
@Override
public void addTag(Tag tag) {
public synchronized void addTag(Tag tag) {
setModified(true);
tags.add(tag);
updateCharacters();
readOnlyTags = null;
}
/**
@@ -5188,10 +5191,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @param tag Tag
*/
@Override
public void addTag(int index, Tag tag) {
public synchronized void addTag(int index, Tag tag) {
setModified(true);
tags.add(index, tag);
updateCharacters();
readOnlyTags = null;
}
/**
@@ -5201,7 +5205,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
* @return Index or -1 when not found
*/
@Override
public int indexOfTag(Tag tag) {
public synchronized int indexOfTag(Tag tag) {
return tags.indexOf(tag);
}

View File

@@ -326,7 +326,7 @@ public class DefineSpriteTag extends DrawableTag implements Timelined {
}
@Override
public ReadOnlyTagList getTags() {
public synchronized ReadOnlyTagList getTags() {
if (readOnlyTags == null) {
readOnlyTags = new ReadOnlyTagList(subTags);
}
@@ -335,31 +335,31 @@ public class DefineSpriteTag extends DrawableTag implements Timelined {
}
@Override
public void removeTag(int index) {
public synchronized void removeTag(int index) {
setModified(true);
subTags.remove(index);
}
@Override
public void removeTag(Tag tag) {
public synchronized void removeTag(Tag tag) {
setModified(true);
subTags.remove(tag);
}
@Override
public void addTag(Tag tag) {
public synchronized void addTag(Tag tag) {
setModified(true);
subTags.add(tag);
}
@Override
public void addTag(int index, Tag tag) {
public synchronized void addTag(int index, Tag tag) {
setModified(true);
subTags.add(index, tag);
}
@Override
public int indexOfTag(Tag tag) {
public synchronized int indexOfTag(Tag tag) {
return subTags.indexOf(tag);
}

View File

@@ -486,7 +486,7 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim
}
@Override
public ReadOnlyTagList getTags() {
public synchronized ReadOnlyTagList getTags() {
initTimeline();
return tags;
}

View File

@@ -188,7 +188,7 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
protected abstract void initTimeline(Timeline timeline);
@Override
public ReadOnlyTagList getTags() {
public synchronized ReadOnlyTagList getTags() {
return ReadOnlyTagList.EMPTY;
}

View File

@@ -449,7 +449,8 @@ public class Timeline {
boolean newFrameNeeded = false;
scenes = new ArrayList<>();
Scene prevScene = null;
for (Tag t : timelined.getTags()) {
List<Tag> tagList = timelined.getTags().toArrayList();
for (Tag t : tagList) {
newFrameNeeded = true;
boolean isNested = ShowFrameTag.isNestedTagType(t.getId());
if (isNested) {