diff --git a/CHANGELOG.md b/CHANGELOG.md index b779bf5f9..4478c0381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. but new `spacing "x" NN` and `spacingpair "x" "y" NN` prefix so now texts are more readable and searchable - [#2333] Changing Shape tag type (DefineShape, DefineShape2, ...) +- Changing PlaceObject tag type (PlaceObject, PlaceObject2, ...) ### Fixed - [#2319] AS3 Compound assignments problems in some cases diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/converters/PlaceObjectTypeConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/converters/PlaceObjectTypeConverter.java new file mode 100644 index 000000000..06e3119ee --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/converters/PlaceObjectTypeConverter.java @@ -0,0 +1,289 @@ +/* + * 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.tags.converters; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.amf.amf3.Amf3Value; +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.PlaceObjectTypeTag; +import com.jpexs.decompiler.flash.types.CLIPACTIONS; +import com.jpexs.decompiler.flash.types.CXFORM; +import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; +import com.jpexs.decompiler.flash.types.ColorTransform; +import com.jpexs.decompiler.flash.types.MATRIX; +import com.jpexs.decompiler.flash.types.filters.FILTER; +import com.jpexs.helpers.Helper; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class PlaceObjectTypeConverter { + + /** + * Gets minimum PlaceObject type number (PlaceObject, PlaceObject2, ...) + * to cover all features that passed placeTag has + * @param placeTag PlaceObject tag + * @return Minimum type number + */ + public int getMinPlaceNum(PlaceObjectTypeTag placeTag) { + int minPlaceNum = 1; + if (placeTag.flagMove()) { + minPlaceNum = 2; + } + if (placeTag.getMatrix() == null) { + minPlaceNum = 2; + } + if (placeTag.getColorTransform() instanceof CXFORMWITHALPHA) { + minPlaceNum = 2; + } + if (placeTag.getClipDepth() > -1) { + minPlaceNum = 2; + } + if (placeTag.getName() != null) { + minPlaceNum = 2; + } + if (placeTag.getRatio() > -1) { + minPlaceNum = 2; + } + if (placeTag.getClassName() != null) { + minPlaceNum = 3; + } + if (placeTag.getBackgroundColor() != null) { + minPlaceNum = 3; + } + if (placeTag.getBitmapCache() != null) { + minPlaceNum = 3; + } + if (placeTag.getBlendMode() > 0) { + minPlaceNum = 3; + } + if (placeTag.getFilters() != null && !placeTag.getFilters().isEmpty()) { + minPlaceNum = 3; + } + if (placeTag.getVisible() != null) { + minPlaceNum = 3; + } + if (placeTag.getAmfData() != null) { + minPlaceNum = 4; + } + return minPlaceNum; + } + + /** + * Converts versions of PlaceObject tag (PlaceObject, PlaceObject2, ...) + * @param sourcePlaceTag Source place tag + * @param targetSWF Target SWF + * @param targetPlaceNum Target place type number + * @return Place object of target type + */ + public PlaceObjectTypeTag convertTagType(PlaceObjectTypeTag sourcePlaceTag, SWF targetSWF, int targetPlaceNum) { + ColorTransform colorTransform = sourcePlaceTag.getColorTransform(); + CLIPACTIONS clipActions = sourcePlaceTag.getClipActions(); + MATRIX matrix = sourcePlaceTag.getMatrix(); + Integer bitmapCache = sourcePlaceTag.getBitmapCache(); + List filters = sourcePlaceTag.getFilters(); + Integer visible = sourcePlaceTag.getVisible(); + Amf3Value amfData = sourcePlaceTag.getAmfData(); + switch(targetPlaceNum) { + case 1: + PlaceObjectTag place1 = new PlaceObjectTag(targetSWF); + place1.characterId = sourcePlaceTag.getCharacterId(); + if (colorTransform != null) { + place1.colorTransform = new CXFORM(colorTransform); + } + place1.depth = sourcePlaceTag.getDepth(); + if (matrix != null) { + place1.matrix = new MATRIX(matrix); + } else { + place1.matrix = new MATRIX(); + } + + return place1; + case 2: + PlaceObject2Tag place2 = new PlaceObject2Tag(targetSWF); + place2.placeFlagMove = sourcePlaceTag.flagMove(); + place2.characterId = sourcePlaceTag.getCharacterId(); + if (place2.characterId != -1) { + place2.placeFlagHasCharacter = true; + } + if (clipActions != null) { + place2.clipActions = Helper.deepCopy(clipActions); + place2.placeFlagHasClipActions = true; + } + place2.clipDepth = sourcePlaceTag.getClipDepth(); + if (place2.clipDepth > -1) { + place2.placeFlagHasClipDepth = true; + } + if (colorTransform != null) { + place2.colorTransform = new CXFORMWITHALPHA(colorTransform); + place2.placeFlagHasColorTransform = true; + } + place2.depth = sourcePlaceTag.getDepth(); + if (matrix != null) { + place2.matrix = new MATRIX(matrix); + place2.placeFlagHasMatrix = true; + } + place2.name = sourcePlaceTag.getInstanceName(); + if (place2.name != null) { + place2.placeFlagHasName = true; + } + place2.ratio = sourcePlaceTag.getRatio(); + if (place2.ratio > -1) { + place2.placeFlagHasRatio = true; + } + return place2; + case 3: + PlaceObject3Tag place3 = new PlaceObject3Tag(targetSWF); + place3.placeFlagMove = sourcePlaceTag.flagMove(); + place3.characterId = sourcePlaceTag.getCharacterId(); + if (place3.characterId != -1) { + place3.placeFlagHasCharacter = true; + } + if (clipActions != null) { + place3.clipActions = Helper.deepCopy(clipActions); + place3.placeFlagHasClipActions = true; + } + place3.clipDepth = sourcePlaceTag.getClipDepth(); + if (place3.clipDepth > -1) { + place3.placeFlagHasClipDepth = true; + } + if (colorTransform != null) { + place3.colorTransform = new CXFORMWITHALPHA(colorTransform); + place3.placeFlagHasColorTransform = true; + } + place3.depth = sourcePlaceTag.getDepth(); + if (matrix != null) { + place3.matrix = new MATRIX(matrix); + place3.placeFlagHasMatrix = true; + } + place3.name = sourcePlaceTag.getInstanceName(); + if (place3.name != null) { + place3.placeFlagHasName = true; + } + place3.ratio = sourcePlaceTag.getRatio(); + if (place3.ratio > -1) { + place3.placeFlagHasRatio = true; + } + place3.className = sourcePlaceTag.getClassName(); + if (place3.className != null) { + place3.placeFlagHasClassName = true; + } + place3.backgroundColor = sourcePlaceTag.getBackgroundColor(); + if (place3.backgroundColor != null) { + place3.placeFlagOpaqueBackground = true; + } + if (bitmapCache != null) { + place3.bitmapCache = bitmapCache; + place3.placeFlagHasCacheAsBitmap = true; + } + place3.blendMode = sourcePlaceTag.getBlendMode(); + if (place3.blendMode > 0) { + place3.placeFlagHasBlendMode = true; + } + if (filters != null && !filters.isEmpty()) { + place3.surfaceFilterList = Helper.deepCopy(filters); + place3.placeFlagHasFilterList = true; + } + if (visible != null) { + place3.visible = visible; + place3.placeFlagHasVisible = true; + } + return place3; + case 4: + PlaceObject4Tag place4 = new PlaceObject4Tag(targetSWF); + place4.placeFlagMove = sourcePlaceTag.flagMove(); + place4.characterId = sourcePlaceTag.getCharacterId(); + if (place4.characterId != -1) { + place4.placeFlagHasCharacter = true; + } + if (clipActions != null) { + place4.clipActions = Helper.deepCopy(clipActions); + place4.placeFlagHasClipActions = true; + } + place4.clipDepth = sourcePlaceTag.getClipDepth(); + if (place4.clipDepth > -1) { + place4.placeFlagHasClipDepth = true; + } + if (colorTransform != null) { + place4.colorTransform = new CXFORMWITHALPHA(colorTransform); + place4.placeFlagHasColorTransform = true; + } + place4.depth = sourcePlaceTag.getDepth(); + if (matrix != null) { + place4.matrix = new MATRIX(matrix); + place4.placeFlagHasMatrix = true; + } + place4.name = sourcePlaceTag.getInstanceName(); + if (place4.name != null) { + place4.placeFlagHasName = true; + } + place4.ratio = sourcePlaceTag.getRatio(); + if (place4.ratio > -1) { + place4.placeFlagHasRatio = true; + } + place4.className = sourcePlaceTag.getClassName(); + if (place4.className != null) { + place4.placeFlagHasClassName = true; + } + place4.backgroundColor = sourcePlaceTag.getBackgroundColor(); + if (place4.backgroundColor != null) { + place4.placeFlagOpaqueBackground = true; + } + if (bitmapCache != null) { + place4.bitmapCache = bitmapCache; + place4.placeFlagHasCacheAsBitmap = true; + } + place4.blendMode = sourcePlaceTag.getBlendMode(); + if (place4.blendMode > 0) { + place4.placeFlagHasBlendMode = true; + } + if (filters != null && !filters.isEmpty()) { + place4.surfaceFilterList = Helper.deepCopy(filters); + place4.placeFlagHasFilterList = true; + } + if (visible != null) { + place4.visible = visible; + place4.placeFlagHasVisible = true; + } + if (amfData != null) { + place4.amfData = Helper.deepCopy(amfData); + } + return place4; + default: + throw new IllegalArgumentException("PlaceNum must be between 1 and 4. Provided: " + targetPlaceNum); + } + } + + /** + * Converts versions of PlaceObject tag (PlaceObject, PlaceObject2, ...) + * and place result in the position where original tag was. + * @param placeTag Place tag + * @param targetPlaceNum Target place num + */ + public PlaceObjectTypeTag convertTagType(PlaceObjectTypeTag placeTag, int targetPlaceNum) { + PlaceObjectTypeTag converted = convertTagType(placeTag, placeTag.getSwf(), targetPlaceNum); + converted.setTimelined(placeTag.getTimelined()); + placeTag.getTimelined().replaceTag(placeTag, converted); + placeTag.getTimelined().resetTimeline(); + return converted; + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/ConvertPlaceObjectTypeDialog.java b/src/com/jpexs/decompiler/flash/gui/ConvertPlaceObjectTypeDialog.java new file mode 100644 index 000000000..4844b8660 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/ConvertPlaceObjectTypeDialog.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010-2024 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 . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.tags.converters.ShapeTypeConverter; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JRadioButton; + +/** + * + * @author JPEXS + */ +public class ConvertPlaceObjectTypeDialog extends AppDialog { + + private List radios = new ArrayList<>(); + + private int result = 0; + + public ConvertPlaceObjectTypeDialog(Window owner, int currentPlaceObjectNum, int min) { + super(owner); + setTitle(translate("dialog.title")); + JPanel radioPanel = new JPanel(); + radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS)); + ButtonGroup radioGroup = new ButtonGroup(); + + JButton okButton = new JButton(translate("button.ok")); + + for (int i = 1; i <= 4; i++) { + String text = "PlaceObject" + (i > 1 ? "" + i : ""); + if (i == min) { + text += " " + translate("minimum"); + } + text += " - " + translate("place" + i); + JRadioButton radio = new JRadioButton(text); + radio.setAlignmentX(Component.LEFT_ALIGNMENT); + if (i == currentPlaceObjectNum) { + radio.setSelected(true); + } + final int fi = i; + radio.addActionListener(new ActionListener(){ + @Override + public void actionPerformed(ActionEvent e) { + okButton.setEnabled(fi != currentPlaceObjectNum); + } + }); + radioPanel.add(radio); + radioGroup.add(radio); + radios.add(radio); + } + + Container cnt = getContentPane(); + cnt.setLayout(new BorderLayout()); + + cnt.add(radioPanel, BorderLayout.CENTER); + + JPanel buttonsPanel = new JPanel(new FlowLayout()); + + + okButton.setEnabled(false); + okButton.addActionListener(this::okButtonActionPerformed); + JButton cancelButton = new JButton(translate("button.cancel")); + cancelButton.addActionListener(this::cancelButtonActionPerformed); + buttonsPanel.add(okButton); + buttonsPanel.add(cancelButton); + + cnt.add(buttonsPanel, BorderLayout.SOUTH); + pack(); + View.centerScreen(this); + View.setWindowIcon(this, "placeobject"); + setModal(true); + } + + private void okButtonActionPerformed(ActionEvent evt) { + result = 0; + for (int i = 0; i < radios.size(); i++) { + if (radios.get(i).isSelected()) { + result = i + 1; + break; + } + } + setVisible(false); + } + + private void cancelButtonActionPerformed(ActionEvent evt) { + setVisible(false); + } + + public int getResult() { + return result; + } + + public int showDialog() { + setVisible(true); + return result; + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/ConvertShapeTypeDialog.java b/src/com/jpexs/decompiler/flash/gui/ConvertShapeTypeDialog.java index 118d6fb31..1939bb5d5 100644 --- a/src/com/jpexs/decompiler/flash/gui/ConvertShapeTypeDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/ConvertShapeTypeDialog.java @@ -16,8 +16,6 @@ */ package com.jpexs.decompiler.flash.gui; -import com.jpexs.decompiler.flash.tags.base.ShapeTag; -import com.jpexs.decompiler.flash.tags.converters.ShapeTypeConverter; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; @@ -52,7 +50,6 @@ public class ConvertShapeTypeDialog extends AppDialog { JButton okButton = new JButton(translate("button.ok")); - ShapeTypeConverter converter = new ShapeTypeConverter(); for (int i = 1; i <= 4; i++) { String text = "DefineShape" + (i > 1 ? "" + i : ""); if (i < minForced) { diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ConvertPlaceObjectTypeDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/ConvertPlaceObjectTypeDialog.properties new file mode 100644 index 000000000..4c700ef9c --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/locales/ConvertPlaceObjectTypeDialog.properties @@ -0,0 +1,27 @@ +# Copyright (C) 2024 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 . + +dialog.title = Convert place object type + +place1 = colortransform, depth, character id, matrix +place2 = flag move, clip actions, clip depth, colortransform with alpha, name, ratio +place3 = class name, background color, bitmap cache, blend mode, filters, visible +place4 = AMF data + +minimum = (Minimum) +unsupported = (Unsupported) + +button.ok = OK +button.cancel = Cancel \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ConvertPlaceObjectTypeDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/ConvertPlaceObjectTypeDialog_cs.properties new file mode 100644 index 000000000..d9ffa90d1 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/locales/ConvertPlaceObjectTypeDialog_cs.properties @@ -0,0 +1,27 @@ +# Copyright (C) 2024 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 . + +dialog.title = Konvertovat typ place objektu + +place1 = colortransform, depth, character id, matrix +place2 = flag move, clip actions, clip depth, colortransform s pr\u016fhlednost\u00ed, name, ratio +place3 = class name, background color, bitmap cache, blend mode, filtry, visible +place4 = AMF data + +minimum = (Minimum) +unsupported = (Nepodporov\u00e1no) + +button.ok = OK +button.cancel = Storno \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 971edfa7b..b65b3f8ba 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1004,4 +1004,5 @@ work.exporting.vsCode = Exporting VS Code menu.file.export.vsCode = Export to VS Code #after 21.1.0 -contextmenu.convertShapeType = Convert shape type \ No newline at end of file +contextmenu.convertShapeType = Convert shape type +contextmenu.convertPlaceObjectType = Convert place object type \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 4a0656455..5b76a04ac 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -986,4 +986,5 @@ work.exporting.vsCode = Exportuji VS Code menu.file.export.vsCode = Exportovat do VS Code #after 21.1.0 -contextmenu.convertShapeType = Konvertovat typ tvaru \ No newline at end of file +contextmenu.convertShapeType = Konvertovat typ tvaru +contextmenu.convertPlaceObjectType = Konvertovat typ place objektu \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 30e3a96c7..8d256b051 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -42,6 +42,7 @@ import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.AsLinkageDialog; import com.jpexs.decompiler.flash.gui.ClipboardType; import com.jpexs.decompiler.flash.gui.CollectDepthAsSpritesDialog; +import com.jpexs.decompiler.flash.gui.ConvertPlaceObjectTypeDialog; import com.jpexs.decompiler.flash.gui.ConvertShapeTypeDialog; import com.jpexs.decompiler.flash.gui.Main; import com.jpexs.decompiler.flash.gui.MainPanel; @@ -104,6 +105,7 @@ import com.jpexs.decompiler.flash.tags.base.RemoveTag; import com.jpexs.decompiler.flash.tags.base.ShapeTag; import com.jpexs.decompiler.flash.tags.base.SoundTag; import com.jpexs.decompiler.flash.tags.base.TextTag; +import com.jpexs.decompiler.flash.tags.converters.PlaceObjectTypeConverter; import com.jpexs.decompiler.flash.tags.converters.ShapeTypeConverter; import com.jpexs.decompiler.flash.tags.gfx.ExporterInfo; import com.jpexs.decompiler.flash.timeline.AS2Package; @@ -340,6 +342,8 @@ public class TagTreeContextMenu extends JPopupMenu { private JMenuItem collectDepthAsSpritesMenuItem; private JMenuItem convertShapeTypeMenuItem; + + private JMenuItem convertPlaceObjectTypeMenuItem; private List items = new ArrayList<>(); @@ -543,6 +547,11 @@ public class TagTreeContextMenu extends JPopupMenu { convertShapeTypeMenuItem.addActionListener(this::convertShapeTypeActionPerformed); convertShapeTypeMenuItem.setIcon(View.getIcon("shape16")); add(convertShapeTypeMenuItem); + + convertPlaceObjectTypeMenuItem = new JMenuItem(mainPanel.translate("contextmenu.convertPlaceObjectType")); + convertPlaceObjectTypeMenuItem.addActionListener(this::convertPlaceObjectTypeActionPerformed); + convertPlaceObjectTypeMenuItem.setIcon(View.getIcon("placeobject16")); + add(convertPlaceObjectTypeMenuItem); addSeparator(); @@ -1075,9 +1084,11 @@ public class TagTreeContextMenu extends JPopupMenu { } boolean allSelectedIsShape = true; + boolean allSelectedIsPlaceObject = true; if (items.isEmpty()) { allSelectedIsShape = false; + allSelectedIsPlaceObject = false; } for (TreeItem item : items) { @@ -1085,6 +1096,9 @@ public class TagTreeContextMenu extends JPopupMenu { if (!(item instanceof ShapeTag)) { allSelectedIsShape = false; } + if (!(item instanceof PlaceObjectTypeTag)) { + allSelectedIsPlaceObject = false; + } if (item instanceof Tag) { Tag tag = (Tag) item; @@ -1236,6 +1250,7 @@ public class TagTreeContextMenu extends JPopupMenu { replaceWithTagMenuItem.setVisible(false); replaceRefsWithTagMenuItem.setVisible(false); convertShapeTypeMenuItem.setVisible(false); + convertPlaceObjectTypeMenuItem.setVisible(false); abcExplorerMenuItem.setVisible(false); cleanAbcMenuItem.setVisible(false); rawEditMenuItem.setVisible(false); @@ -1662,6 +1677,10 @@ public class TagTreeContextMenu extends JPopupMenu { if (allSelectedIsShape) { convertShapeTypeMenuItem.setVisible(true); } + + if (allSelectedIsPlaceObject) { + convertPlaceObjectTypeMenuItem.setVisible(true); + } moveTagToMenu.removeAll(); moveTagToWithDependenciesMenu.removeAll(); @@ -2619,6 +2638,46 @@ public class TagTreeContextMenu extends JPopupMenu { mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), sh.getSwf().getCharacter(sh.getCharacterId())); } } + + private void convertPlaceObjectTypeActionPerformed(ActionEvent evt) { + List itemr = getSelectedItems(); + if (itemr.isEmpty()) { + return; + } + int currentPlaceObjectNum = 0; + int min = 0; + + PlaceObjectTypeConverter converter = new PlaceObjectTypeConverter(); + + + if (itemr.size() == 1) { + PlaceObjectTypeTag sh = (PlaceObjectTypeTag) itemr.get(0); + currentPlaceObjectNum = sh.getPlaceObjectNum(); + min = converter.getMinPlaceNum(sh); + } + + ConvertPlaceObjectTypeDialog dialog = new ConvertPlaceObjectTypeDialog(Main.getDefaultDialogsOwner(), currentPlaceObjectNum, min); + + int placeNum = dialog.showDialog(); + + if (placeNum == 0) { + return; + } + + PlaceObjectTypeTag lastConverted = null; + for (TreeItem item : itemr) { + PlaceObjectTypeTag pl = (PlaceObjectTypeTag) item; + if (pl.getPlaceObjectNum()== placeNum) { + continue; + } + lastConverted = converter.convertTagType(pl, placeNum); + } + + mainPanel.refreshTree(); + if (itemr.size() == 1) { + mainPanel.setTagTreeSelectedNode(mainPanel.getCurrentTree(), lastConverted); + } + } private void replaceRefsWithTagActionPerformed(ActionEvent evt) { TreeItem itemr = getCurrentItem();