Added: Simple editor - edit parameters of items inside buttons

This commit is contained in:
Jindra Petřík
2025-05-17 13:38:53 +02:00
parent 5683544d35
commit 5fecb497b4
7 changed files with 187 additions and 23 deletions

View File

@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
### Added
- "Starting Flash content debugger" in status bar when debugging starts
- Simple editor - edit parameters of items inside buttons
### Fixed
- Resize export dialogs labels to match localized strings

View File

@@ -200,6 +200,9 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
@Override
public RECT getRect(Set<BoundedTag> added) {
if (swf == null) {
return null;
}
Cache<CharacterTag, RECT> cache = swf == null ? null : swf.getRectCache();
RECT ret = cache == null ? null : cache.get(this);
if (ret != null) {
@@ -267,6 +270,8 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
layer.filters = r.filterList;
layer.matrix = r.placeMatrix;
layer.characterId = r.characterId;
layer.depth = r.placeDepth;
if (r.placeDepth > maxDepth) {
maxDepth = r.placeDepth;
}
@@ -313,7 +318,7 @@ public class DefineButton2Tag extends ButtonTag implements ASMSourceContainer {
@Override
public void setFrameCount(int frameCount) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override

View File

@@ -48,22 +48,22 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
/**
* Frame up
*/
public static int FRAME_UP = 0;
public static final int FRAME_UP = 0;
/**
* Frame over
*/
public static int FRAME_OVER = 1;
public static final int FRAME_OVER = 1;
/**
* Frame down
*/
public static int FRAME_DOWN = 2;
public static final int FRAME_DOWN = 2;
/**
* Frame hit test
*/
public static int FRAME_HITTEST = 3;
public static final int FRAME_HITTEST = 3;
private transient Timeline timeline;
@@ -85,12 +85,14 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
/**
* Gets button records.
*
* @return Button records
*/
public abstract List<BUTTONRECORD> getRecords();
/**
* Checks if the button is tracked as a menu.
*
* @return True if the button is tracked as a menu, otherwise false
*/
public abstract boolean trackAsMenu();
@@ -134,6 +136,7 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
/**
* Gets the sounds.
*
* @return Sounds
*/
public DefineButtonSoundTag getSounds() {
@@ -184,6 +187,7 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
/**
* Initializes the timeline.
*
* @param timeline Timeline
*/
protected abstract void initTimeline(Timeline timeline);
@@ -244,4 +248,115 @@ public abstract class ButtonTag extends DrawableTag implements Timelined {
record.setModified(value);
}
}
public BUTTONRECORD getButtonRecordAt(int frame, int depth, boolean addIfNotExists) {
for (BUTTONRECORD rec : getRecords()) {
if (rec.placeDepth != depth) {
continue;
}
switch (frame) {
case FRAME_UP:
if (rec.buttonStateUp) {
return rec;
}
break;
case FRAME_OVER:
if (rec.buttonStateOver) {
return rec;
}
break;
case FRAME_DOWN:
if (rec.buttonStateDown) {
return rec;
}
break;
case FRAME_HITTEST:
if (rec.buttonStateHitTest) {
return rec;
}
break;
}
}
if (addIfNotExists) {
BUTTONRECORD newRecord = new BUTTONRECORD(swf, this);
switch (frame) {
case FRAME_UP:
newRecord.buttonStateUp = true;
break;
case FRAME_OVER:
newRecord.buttonStateOver = true;
break;
case FRAME_DOWN:
newRecord.buttonStateDown = true;
break;
case FRAME_HITTEST:
newRecord.buttonStateHitTest = true;
break;
}
getRecords().add(newRecord);
return newRecord;
}
return null;
}
public void setRecordFromPlaceObject(int frame, PlaceObjectTypeTag placeTag) {
BUTTONRECORD selectedRecord = null;
List<BUTTONRECORD> records = getRecords();
loopRecords:
for (BUTTONRECORD rec : records) {
if (rec.placeDepth != placeTag.getDepth()) {
continue;
}
switch (frame) {
case FRAME_UP:
if (rec.buttonStateUp) {
selectedRecord = rec;
break loopRecords;
}
break;
case FRAME_OVER:
if (rec.buttonStateOver) {
selectedRecord = rec;
break loopRecords;
}
break;
case FRAME_DOWN:
if (rec.buttonStateDown) {
selectedRecord = rec;
break loopRecords;
}
break;
case FRAME_HITTEST:
if (rec.buttonStateHitTest) {
selectedRecord = rec;
break loopRecords;
}
break;
}
}
if (selectedRecord == null) {
selectedRecord = new BUTTONRECORD(swf, this);
switch (frame) {
case FRAME_UP:
selectedRecord.buttonStateUp = true;
break;
case FRAME_OVER:
selectedRecord.buttonStateOver = true;
break;
case FRAME_DOWN:
selectedRecord.buttonStateDown = true;
break;
case FRAME_HITTEST:
selectedRecord.buttonStateHitTest = true;
break;
}
records.add(selectedRecord);
}
selectedRecord.fromPlaceObject(placeTag);
}
}

View File

@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.tags.DefineButtonTag;
import com.jpexs.decompiler.flash.tags.PlaceObject3Tag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.treeitems.Openable;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.types.annotations.Conditional;
@@ -210,6 +211,18 @@ public class BUTTONRECORD implements Serializable, TreeItem, HasSwfAndTag, HasCh
this.characterId = characterId;
}
public void fromPlaceObject(PlaceObjectTypeTag placeObject) {
placeDepth = placeObject.getDepth();
characterId = placeObject.getCharacterId();
ColorTransform importedColorTrans = placeObject.getColorTransform();
colorTransform = importedColorTrans == null ? null : new CXFORMWITHALPHA(placeObject.getColorTransform());
placeMatrix = placeObject.getMatrix();
blendMode = placeObject.getBlendMode();
buttonHasBlendMode = blendMode > 0;
filterList = placeObject.getFilters();
buttonHasFilterList = filterList != null && !filterList.isEmpty();
}
/**
* Converts this BUTTONRECORD to a place tag.
* @return Place tag

View File

@@ -49,6 +49,7 @@ import com.jpexs.decompiler.flash.timeline.DepthState;
import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.treeitems.Openable;
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
import com.jpexs.decompiler.flash.types.MATRIX;
import java.awt.BorderLayout;
import java.awt.CardLayout;
@@ -187,13 +188,19 @@ public class EasySwfPanel extends JPanel {
for (int i = 0; i < depths.size(); i++) {
int depth = depths.get(i);
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
wasModified.add(ds.placeObjectTag.isModified());
wasModified.add(ds.placeObjectTag == null ? false : ds.placeObjectTag.isModified());
Matrix contMat = newMatrix.concatenate(new Matrix(fpreviousMatrices.get(i)));
ds.placeObjectTag.setMatrix(contMat.toMATRIX());
ds.placeObjectTag.setPlaceFlagHasMatrix(newMatrix != null);
ds.placeObjectTag.setModified(true);
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
BUTTONRECORD rec = button.getButtonRecordAt(frame, depth, true);
rec.placeMatrix = contMat.toMATRIX();
} else {
ds.placeObjectTag.setMatrix(contMat.toMATRIX());
ds.placeObjectTag.setPlaceFlagHasMatrix(newMatrix != null);
ds.placeObjectTag.setModified(true);
}
}
timelined.resetTimeline();
stagePanel.repaint();
@@ -216,10 +223,16 @@ public class EasySwfPanel extends JPanel {
for (int i = 0; i < depths.size(); i++) {
int depth = depths.get(i);
DepthState ds = stagePanel.getTimelined().getTimeline().getFrame(frame).layers.get(depth);
ds.placeObjectTag.setMatrix(fpreviousMatrices.get(i));
ds.placeObjectTag.setPlaceFlagHasMatrix(fpreviousMatrices != null);
if (!wasModified.get(i)) {
ds.placeObjectTag.setModified(false);
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
BUTTONRECORD rec = button.getButtonRecordAt(frame, depth, true);
rec.placeMatrix = fpreviousMatrices.get(i);
} else {
ds.placeObjectTag.setMatrix(fpreviousMatrices.get(i));
ds.placeObjectTag.setPlaceFlagHasMatrix(fpreviousMatrices != null);
if (ds.placeObjectTag != null && !wasModified.get(i)) {
ds.placeObjectTag.setModified(false);
}
}
}
stagePanel.getTimelined().resetTimeline();
@@ -675,7 +688,11 @@ public class EasySwfPanel extends JPanel {
if (ds == null) {
ret.add(null);
} else {
ret.add(ds.placeObjectTag);
if (ds.placeObjectTag == null) {
ret.add(ds.toPlaceObjectTag(ds.depth));
} else {
ret.add(ds.placeObjectTag);
}
}
}
return ret;

View File

@@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.gui.PopupButton;
import com.jpexs.decompiler.flash.gui.RegistrationPointPosition;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.ViewMessages;
import com.jpexs.decompiler.flash.tags.base.ButtonTag;
import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag;
import com.jpexs.decompiler.flash.tags.converters.PlaceObjectTypeConverter;
import com.jpexs.decompiler.flash.timeline.DepthState;
@@ -1093,13 +1094,20 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
for (int i = 0; i < fdepths.size(); i++) {
PlaceObjectTypeTag placeObjectBefore = placeObjectsBefore.get(i);
PlaceObjectTypeTag placeObjectAfter = placeObjectsAfter.get(i);
int index = timelined.indexOfTag(placeObjectBefore);
timelined.removeTag(index);
timelined.addTag(index, placeObjectAfter);
timelined.setModified(true);
if (!(timelined instanceof ButtonTag)) {
int index = timelined.indexOfTag(placeObjectBefore);
timelined.removeTag(index);
timelined.addTag(index, placeObjectAfter);
timelined.setModified(true);
}
DepthState depthStateBefore = depthStatesBefore.get(i);
doPlaceOperation(placeObjectAfter, depthStateBefore);
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
button.setRecordFromPlaceObject(fframe, placeObjectAfter);
}
}
timelined.resetTimeline();
@@ -1113,9 +1121,14 @@ public class InstancePropertiesPanel extends AbstractPropertiesPanel {
for (int i = 0; i < placeObjectsAfter.size(); i++) {
PlaceObjectTypeTag placeObjectAfter = placeObjectsAfter.get(i);
PlaceObjectTypeTag placeObjectBefore = placeObjectsBefore.get(i);
int index = timelined.indexOfTag(placeObjectAfter);
timelined.removeTag(index);
timelined.addTag(index, placeObjectBefore);
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
button.setRecordFromPlaceObject(fframe, placeObjectBefore);
} else {
int index = timelined.indexOfTag(placeObjectAfter);
timelined.removeTag(index);
timelined.addTag(index, placeObjectBefore);
}
}
if (!timelinedModifiedBefore) {
timelined.setModified(false);

View File

@@ -5394,7 +5394,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
} else {
depthStateUnderCursor = null;
}
if (showObjectsUnderCursor && autoPlayed) {
boolean first = true;
for (int i = renderContext.stateUnderCursor.size() - 1; i >= 0; i--) {