mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 20:39:10 +00:00
Main concept working
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.ListSelectionModel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class CollectDepthAsSpritesDialogue extends AppDialog {
|
||||
|
||||
private final JButton okButton = new JButton(translate("button.ok"));
|
||||
|
||||
private final JButton cancelButton = new JButton(translate("button.cancel"));
|
||||
|
||||
private final JList<Integer> depthsList;
|
||||
|
||||
private final JCheckBox replaceCheckBox;
|
||||
|
||||
private final JCheckBox offsetCheckBox;
|
||||
|
||||
private int result = ERROR_OPTION;
|
||||
|
||||
public CollectDepthAsSpritesDialogue(Window owner) {
|
||||
super(owner);
|
||||
setSize(400, 150);
|
||||
setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
|
||||
Container cnt = getContentPane();
|
||||
cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS));
|
||||
cnt.add(new JLabel(translate("collect.depths")));
|
||||
|
||||
depthsList = new JList<>();
|
||||
depthsList.setVisibleRowCount(7);
|
||||
depthsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
|
||||
JScrollPane listScroller = new FasterScrollPane(depthsList);
|
||||
listScroller.setPreferredSize(new Dimension(400, 200));
|
||||
cnt.add(listScroller);
|
||||
|
||||
replaceCheckBox = new JCheckBox(translate("collect.replace"));
|
||||
cnt.add(replaceCheckBox);
|
||||
|
||||
offsetCheckBox = new JCheckBox(translate("collect.offset"));
|
||||
cnt.add(offsetCheckBox);
|
||||
|
||||
JPanel panButtons = new JPanel(new FlowLayout());
|
||||
okButton.addActionListener(this::okButtonActionPerformed);
|
||||
cancelButton.addActionListener(this::cancelButtonActionPerformed);
|
||||
panButtons.add(okButton);
|
||||
panButtons.add(cancelButton);
|
||||
|
||||
add(panButtons, BorderLayout.SOUTH);
|
||||
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
View.setWindowIcon(this);
|
||||
setTitle(translate("dialog.title"));
|
||||
getRootPane().setDefaultButton(okButton);
|
||||
pack();
|
||||
View.centerScreen(this);
|
||||
}
|
||||
|
||||
private void okButtonActionPerformed(ActionEvent evt) {
|
||||
result = OK_OPTION;
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
private void cancelButtonActionPerformed(ActionEvent evt) {
|
||||
result = CANCEL_OPTION;
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
public List<Integer> getDepths() {
|
||||
if (result == ERROR_OPTION) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return depthsList.getSelectedValuesList();
|
||||
}
|
||||
|
||||
public boolean getReplace() {
|
||||
return replaceCheckBox.isSelected();
|
||||
}
|
||||
|
||||
public boolean getOffset() {
|
||||
return offsetCheckBox.isSelected();
|
||||
}
|
||||
|
||||
public int showDialog(Collection<Integer> depths) {
|
||||
depthsList.setListData(depths.toArray(new Integer[depths.size()]));
|
||||
depthsList.setVisibleRowCount(7);
|
||||
setVisible(true);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2010-2016 JPEXS
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
dialog.title = Collect options
|
||||
collect.depths = Depths to collect:
|
||||
collect.replace = Replace original tags with sprite
|
||||
collect.offset = Offset top left corner to (0,0)
|
||||
|
||||
button.ok = OK
|
||||
button.cancel = Cancel
|
||||
@@ -1256,4 +1256,5 @@ node.scenes = scenes
|
||||
contextmenu.showInFramesFolder = Show in frames folder
|
||||
|
||||
#after 20.1.0
|
||||
contextmenu.collapseAll = Collapse all
|
||||
contextmenu.collapseAll = Collapse all
|
||||
contextmenu.collectDepthAsSprites = Collect items at same depth as sprites
|
||||
@@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration;
|
||||
import com.jpexs.decompiler.flash.gui.AppDialog;
|
||||
import com.jpexs.decompiler.flash.gui.AppStrings;
|
||||
import com.jpexs.decompiler.flash.gui.ClipboardType;
|
||||
import com.jpexs.decompiler.flash.gui.CollectDepthAsSpritesDialogue;
|
||||
import com.jpexs.decompiler.flash.gui.Main;
|
||||
import com.jpexs.decompiler.flash.gui.MainPanel;
|
||||
import com.jpexs.decompiler.flash.gui.ReplaceCharacterDialog;
|
||||
@@ -118,6 +119,7 @@ import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD;
|
||||
import com.jpexs.decompiler.flash.types.CLIPACTIONS;
|
||||
import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA;
|
||||
import com.jpexs.decompiler.flash.types.HasCharacterId;
|
||||
import com.jpexs.decompiler.flash.types.MATRIX;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
@@ -143,6 +145,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
@@ -308,6 +311,8 @@ public class TagTreeContextMenu extends JPopupMenu {
|
||||
|
||||
private JMenuItem replaceWithGifMenuItem;
|
||||
|
||||
private JMenuItem collectDepthAsSpritesItem;
|
||||
|
||||
private List<TreeItem> items = new ArrayList<>();
|
||||
|
||||
private static final int KIND_TAG_MOVETO = 0;
|
||||
@@ -637,6 +642,10 @@ public class TagTreeContextMenu extends JPopupMenu {
|
||||
pasteInsideMenuItem.addActionListener(this::pasteInsideActionPerformed);
|
||||
add(pasteInsideMenuItem);
|
||||
|
||||
collectDepthAsSpritesItem = new JMenuItem(mainPanel.translate("contextmenu.collectDepthAsSprites"));
|
||||
collectDepthAsSpritesItem.addActionListener(this::collectDepthAsSprites);
|
||||
add(collectDepthAsSpritesItem);
|
||||
|
||||
applyUnpackerMenu = new JMenu(mainPanel.translate("contextmenu.applyUnpacker"));
|
||||
applyUnpackerMenu.setIcon(View.getIcon("openinside16"));
|
||||
|
||||
@@ -1083,6 +1092,14 @@ public class TagTreeContextMenu extends JPopupMenu {
|
||||
}
|
||||
}
|
||||
|
||||
boolean allSelectedIsFrame = true;
|
||||
for (TreeItem item : items) {
|
||||
if (!(item instanceof Frame)) {
|
||||
allSelectedIsFrame = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasExportableNodes = tree.hasExportableNodes();
|
||||
|
||||
expandRecursiveMenuItem.setVisible(false);
|
||||
@@ -1140,6 +1157,7 @@ public class TagTreeContextMenu extends JPopupMenu {
|
||||
pasteAfterMenuItem.setVisible(false);
|
||||
pasteBeforeMenuItem.setVisible(false);
|
||||
pasteInsideMenuItem.setVisible(false);
|
||||
collectDepthAsSpritesItem.setVisible(allSelectedIsFrame && allSelectedSameParent);
|
||||
applyUnpackerMenu.setVisible(false);
|
||||
openSWFInsideTagMenuItem.setVisible(false);
|
||||
addAs12ScriptMenuItem.setVisible(false);
|
||||
@@ -4088,6 +4106,146 @@ public class TagTreeContextMenu extends JPopupMenu {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectDepthAsSprites(ActionEvent e) {
|
||||
List<TreeItem> frames = getSelectedItems();
|
||||
Timelined timelined = ((Frame) frames.get(0)).timeline.timelined;
|
||||
SWF swf = timelined instanceof SWF ? (SWF) timelined : ((DefineSpriteTag) timelined).getSwf();
|
||||
|
||||
Set<Integer> originalDepths = new HashSet<>();
|
||||
|
||||
for (TreeItem item : frames) {
|
||||
Frame f = (Frame) item;
|
||||
for (Tag t : f.innerTags) {
|
||||
if (t instanceof RemoveTag) {
|
||||
originalDepths.add(((RemoveTag) t).getDepth());
|
||||
} else if (t instanceof PlaceObjectTypeTag) {
|
||||
originalDepths.add(((PlaceObjectTypeTag) t).getDepth());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CollectDepthAsSpritesDialogue dialog = new CollectDepthAsSpritesDialogue(Main.getDefaultDialogsOwner());
|
||||
|
||||
if (dialog.showDialog(originalDepths) == CollectDepthAsSpritesDialogue.OK_OPTION) {
|
||||
List<Integer> depths = dialog.getDepths();
|
||||
boolean replace = dialog.getReplace();
|
||||
boolean offset = dialog.getOffset();
|
||||
|
||||
Map<Integer, DefineSpriteTag> sprites = new HashMap<>();
|
||||
for (int d : depths) {
|
||||
DefineSpriteTag sprite = new DefineSpriteTag(swf);
|
||||
sprite.frameCount = frames.size();
|
||||
|
||||
for (int i = 0; i < frames.size(); i++) {
|
||||
Tag showFrame = new ShowFrameTag(swf);
|
||||
showFrame.setTimelined(sprite);
|
||||
sprite.addTag(showFrame);
|
||||
}
|
||||
|
||||
swf.addTag(sprite);
|
||||
sprites.put(d, sprite);
|
||||
}
|
||||
|
||||
try {
|
||||
for (int i = frames.size() - 1; i > -1; i--) {
|
||||
Frame f = (Frame) frames.get(i);
|
||||
for (int j = 0; j < f.innerTags.size(); j++) {
|
||||
Tag t = f.innerTags.get(j);
|
||||
|
||||
int depth = -1;
|
||||
if (t instanceof RemoveTag) {
|
||||
depth = ((RemoveTag) t).getDepth();
|
||||
} else if (t instanceof PlaceObjectTypeTag) {
|
||||
depth = ((PlaceObjectTypeTag) t).getDepth();
|
||||
}
|
||||
|
||||
if (depth != -1) {
|
||||
DefineSpriteTag sprite = sprites.get(depth);
|
||||
Tag clone = t.cloneTag();
|
||||
clone.setTimelined(sprite);
|
||||
sprite.addTag(i, clone);
|
||||
|
||||
if (replace) {
|
||||
f.innerTags.remove(t);
|
||||
t.getTimelined().removeTag(t);
|
||||
swf.removeTag(t);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Frame first = (Frame) frames.get(0);
|
||||
|
||||
for (Entry<Integer, DefineSpriteTag> entry : sprites.entrySet()) {
|
||||
DefineSpriteTag sprite = entry.getValue();
|
||||
|
||||
if (offset || replace) {
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
|
||||
for (Tag t : sprite.getTags()) {
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
PlaceObjectTypeTag placeTag = (PlaceObjectTypeTag) t;
|
||||
MATRIX m = placeTag.getMatrix();
|
||||
|
||||
if (m != null) {
|
||||
if (m.translateX < minX) {
|
||||
minX = m.translateX;
|
||||
}
|
||||
|
||||
if (m.translateY < minY) {
|
||||
minY = m.translateY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
for (Tag t : sprite.getTags()) {
|
||||
if (t instanceof PlaceObjectTypeTag) {
|
||||
PlaceObjectTypeTag placeTag = (PlaceObjectTypeTag) t;
|
||||
MATRIX m = placeTag.getMatrix();
|
||||
|
||||
if (m != null) {
|
||||
m.translateX -= minX;
|
||||
m.translateY -= minY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (replace) {
|
||||
PlaceObject3Tag place = new PlaceObject3Tag(swf);
|
||||
place.placeFlagHasCharacter = true;
|
||||
place.characterId = sprite.getCharacterId();
|
||||
place.depth = entry.getKey();
|
||||
if (offset) {
|
||||
place.placeFlagHasMatrix = true;
|
||||
place.placeFlagMove = true;
|
||||
place.matrix = new MATRIX();
|
||||
place.matrix.translateX = minX;
|
||||
place.matrix.translateY = minY;
|
||||
}
|
||||
|
||||
place.setTimelined(first.timeline.timelined);
|
||||
first.innerTags.add(place);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
swf.updateCharacters();
|
||||
if(replace) {
|
||||
swf.computeDependentCharacters();
|
||||
swf.computeDependentFrames();
|
||||
}
|
||||
mainPanel.refreshTree(swf);
|
||||
} catch (InterruptedException | IOException ex) {
|
||||
Logger.getLogger(TagTreeContextMenu.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param items
|
||||
@@ -4852,7 +5010,7 @@ public class TagTreeContextMenu extends JPopupMenu {
|
||||
}
|
||||
}
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(fileName)) {
|
||||
try ( FileOutputStream fos = new FileOutputStream(fileName)) {
|
||||
container.getABC().saveTo(fos);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user