Added: #2478 Simple editor - remembering last frame / timeline

This commit is contained in:
Jindra Petřík
2025-07-07 00:13:05 +02:00
parent 0ac9ec748c
commit 574cf1c848
8 changed files with 227 additions and 48 deletions
@@ -42,7 +42,7 @@ public class EasyPanel extends JPanel {
tabSwitcher.addTabSwitchedListener(new TabSwitchedListener<SWF>() {
@Override
public void tabSwitched(SWF value) {
easySwfPanel.setTimelined(value);
easySwfPanel.setSwf(value);
}
});
}
@@ -20,6 +20,8 @@ import com.jpexs.decompiler.flash.DefineBeforeUsageFixer;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.configuration.CustomConfigurationKeys;
import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration;
import com.jpexs.decompiler.flash.easygui.properties.panels.DocumentPropertiesPanel;
import com.jpexs.decompiler.flash.easygui.properties.panels.InstancePropertiesPanel;
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
@@ -134,7 +136,8 @@ public class EasySwfPanel extends JPanel {
setTimelined(stagePanel.getTimelined(), false);
}
});
} else {
timelinePanel.setFrame(stagePanel.getFrame(), stagePanel.getSelectedDepths());
}
}
@@ -427,7 +430,15 @@ public class EasySwfPanel extends JPanel {
closeTimelineButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setTimelined(timelined.getSwf());
SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(timelined.getSwf());
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_DEPTHS, new ArrayList<>());
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_FRAMES, new ArrayList<>());
String firstParentFrame = conf.getCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_FIRST_PARENT_FRAME, "1");
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_FRAME, firstParentFrame);
setTimelined(timelined.getSwf());
}
});
@@ -458,7 +469,7 @@ public class EasySwfPanel extends JPanel {
}
transformPanel.setVisible(!depths.isEmpty());
updatePropertiesPanel();
updatePropertiesPanel();
}
});
@@ -593,6 +604,23 @@ public class EasySwfPanel extends JPanel {
return rightTabbedPane.getSelectedIndex() == 2;
}
public void setSwf(SWF swf) {
Timelined tim = swf;
if (swf != null) {
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf);
if (conf != null) {
int timId = Integer.parseInt(conf.getCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_TIMELINE, "-1"));
if (timId > -1) {
CharacterTag ct = swf.getCharacter(timId);
if (ct != null && ct instanceof Timelined) {
tim = (Timelined) ct;
}
}
}
}
setTimelined(tim);
}
public void setTimelined(Timelined timelined) {
setTimelined(timelined, true);
}
@@ -616,21 +644,10 @@ public class EasySwfPanel extends JPanel {
instancePropertiesPanel.update();
textInstancePropertiesPanel.update();
} else {
SWF swf = timelined.getSwf();
SWF swf = timelined.getSwf();
documentPropertiesPanel.setSwf(swf);
libraryTreeTable.setSwf(swf);
libraryPreviewPanel.clearAll();
if (updateStage) {
stagePanel.setTimelined(timelined, swf, 0, true, true, true, true, true, false, true, true, true);
if (timelined instanceof CharacterTag) {
stagePanel.setGuidesCharacter(swf, ((CharacterTag) timelined).getCharacterId());
} else {
stagePanel.setGuidesCharacter(swf, -1);
}
stagePanel.pause();
stagePanel.gotoFrame(0);
}
timelinePanel.setTimelined(timelined);
if (timelined instanceof SWF) {
timelineLabel.setText(EasyStrings.translate("timeline.main"));
closeTimelineButton.setVisible(false);
@@ -639,6 +656,23 @@ public class EasySwfPanel extends JPanel {
timelineLabel.setText(EasyStrings.translate("timeline.item").replace("%item%", nameResolver.getTagName((Tag) timelined)));
closeTimelineButton.setVisible(true);
}
timelinePanel.setTimelined(timelined); //tohle se volá blbě rekurzivně!!!
if (updateStage) {
stagePanel.setTimelined(timelined, swf, 0, true, true, true, true, true, false, true, true, true);
if (timelined instanceof CharacterTag) {
stagePanel.setGuidesCharacter(swf, ((CharacterTag) timelined).getCharacterId());
} else {
stagePanel.setGuidesCharacter(swf, -1);
}
stagePanel.pause();
//stagePanel.gotoFrame(0);
}
if (updateStage) {
//timelinePanel.getTimelineBodyPanel().frameSelect(0, 0);
}
instancePropertiesPanel.update();
textInstancePropertiesPanel.update();
}
@@ -494,11 +494,11 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
}
public void depthSelect(int depth) {
frameSelect(getFirstFrame(), Arrays.asList(depth));
frameSelect(getFirstFrame(), Arrays.asList(depth), true);
}
public void depthsSelect(List<Integer> depths) {
frameSelect(getFirstFrame(), depths);
frameSelect(getFirstFrame(), depths, true);
}
public int getFirstFrame() {
@@ -515,7 +515,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
return cursor.iterator().next().y;
}
public void rectSelect(int frame, int depth, int endFrame, int endDepth) {
private void rectSelect(int frame, int depth, int endFrame, int endDepth) {
int x1 = Math.min(frame, endFrame);
int x2 = Math.max(frame, endFrame);
int y1 = Math.min(depth, endDepth);
@@ -550,11 +550,11 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
fireFrameSelected(frame, depths);
}
public void frameSelect(int frame, int depth) {
frameSelect(frame, Arrays.asList(depth));
public void frameSelect(int frame, int depth, boolean notify) {
frameSelect(frame, Arrays.asList(depth), notify);
}
public void frameSelect(int frame, List<Integer> depths) {
public void frameSelect(int frame, List<Integer> depths, boolean notify) {
/*if (cursor != null && cursor.width == 1 && cursor.height == 1 && (cursor.contains(frame, depth) || (depth == -1 && cursor.contains(frame, cursor.y)))) {
return;
}
@@ -582,7 +582,9 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
this.depth = depths.isEmpty() ? 0 : depths.get(0);
this.endFrame = frame;
*/
fireFrameSelected(frame, depths);
if (notify) {
fireFrameSelected(frame, depths);
}
}
private void fireFrameSelected(int frame, List<Integer> depths) {
@@ -626,7 +628,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
fireFrameSelected(frame, newDepths);
} else {
if (!(cursor != null && cursor.contains(p) && SwingUtilities.isRightMouseButton(e))) {
frameSelect(p.x, Arrays.asList(p.y));
frameSelect(p.x, Arrays.asList(p.y), true);
}
}
requestFocusInWindow();
@@ -838,7 +840,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
timelined.resetTimeline();
Point firstCursor = orderedCursor.iterator().next();
frameSelect(firstCursor.x, firstCursor.y);
frameSelect(firstCursor.x, firstCursor.y, true);
timeline = timelined.getTimeline();
refresh();
@@ -1275,22 +1277,22 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
switch (e.getKeyCode()) {
case 37: //left
if (firstCursorItem.x > 0) {
frameSelect(firstCursorItem.x - 1, firstCursorItem.y);
frameSelect(firstCursorItem.x - 1, firstCursorItem.y, true);
}
break;
case 39: //right
if (firstCursorItem.x < timeline.getFrameCount() - 1) {
frameSelect(firstCursorItem.x + 1, firstCursorItem.y);
frameSelect(firstCursorItem.x + 1, firstCursorItem.y, true);
}
break;
case 38: //up
if (firstCursorItem.y > 0) {
frameSelect(firstCursorItem.x, firstCursorItem.y - 1);
frameSelect(firstCursorItem.x, firstCursorItem.y - 1, true);
}
break;
case 40: //down
if (firstCursorItem.y < timeline.getMaxDepth()) {
frameSelect(firstCursorItem.x, firstCursorItem.y + 1);
frameSelect(firstCursorItem.x, firstCursorItem.y + 1, true);
}
break;
}
@@ -16,7 +16,10 @@
*/
package com.jpexs.decompiler.flash.easygui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.configuration.CustomConfigurationKeys;
import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration;
import com.jpexs.decompiler.flash.gui.FasterScrollPane;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
@@ -124,7 +127,7 @@ public class TimelinePanel extends JPanel {
@Override
public void frameSelected(int frame, List<Integer> depths) {
ftimeline.frameSelect(frame, depths);
ftimeline.frameSelect(frame, depths, true);
}
});
}
@@ -158,11 +161,13 @@ public class TimelinePanel extends JPanel {
}
public void setFrame(int frame, int depth) {
timelineBodyPanel.frameSelect(frame, depth);
timePanel.frameSelect(frame);
timelineBodyPanel.frameSelect(frame, depth, false);
}
public void setFrame(int frame, List<Integer> depths) {
timelineBodyPanel.frameSelect(frame, depths);
timePanel.frameSelect(frame);
timelineBodyPanel.frameSelect(frame, depths, false);
}
public void refresh() {
@@ -187,7 +192,20 @@ public class TimelinePanel extends JPanel {
timelineBodyPanel.setTimeline(timelined.getTimeline());
depthPanel.setTimeline(timelined.getTimeline());
timePanel.setTimeline(timelined.getTimeline());
timelineBodyPanel.frameSelect(0, 0);
SWF swf = timelined.getSwf();
SwfSpecificCustomConfiguration conf = swf == null ? null : Configuration.getSwfSpecificCustomConfiguration(swf);
int frame = conf == null ? 0 : Integer.parseInt(conf.getCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_FRAME, "1")) - 1;
timePanel.frameSelect(frame);
timelineBodyPanel.frameSelect(frame, 0, false);
}
}
public TimelineBodyPanel getTimelineBodyPanel() {
return timelineBodyPanel;
}
}
@@ -1776,19 +1776,9 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
if (e.getClickCount() == 2 && selectionMode && !transformSelectionMode) {
DepthState ds = depthStateUnderCursor;
if (ds != null) {
CharacterTag cht = ds.getCharacter();
if (cht instanceof Timelined) {
synchronized (lock) {
parentTimelineds.add(timelined);
parentDepths.add(ds.depth);
parentFrames.add(ds.frame.frame);
timelined = (Timelined) cht;
selectedDepths.clear();
frame = 0;
}
fireMediaDisplayStateChanged();
}
if (ds != null) {
openDepth(frame, ds.depth);
//gotoFrame(1);
}
return;
@@ -4757,7 +4747,7 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
this.timelined = drawable;
this.parentTimelineds.clear();
this.parentFrames.clear();
this.parentDepths.clear();
this.parentDepths.clear();
centerImage();
this.swf = swf;
zoomAvailable = allowZoom;
@@ -4814,6 +4804,20 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
this.showObjectsUnderCursor = showObjectsUnderCursor;
this.registrationPointPosition = RegistrationPointPosition.CENTER;
iconPanel.calcRect();
if (selectionMode) {
SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf);
int chid = -1;
if (timelined instanceof CharacterTag) {
chid = ((CharacterTag) timelined).getCharacterId();
}
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_TIMELINE, "" + chid);
loadOpenedDepths();
}
clearGuidesInternal();
setNoGuidesCharacter();
@@ -6258,11 +6262,19 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
if (frame < 1) {
frame = 1;
}
this.autoPlayed = true;
this.frame = frame - 1;
this.prevFrame = -1;
if (selectionMode) {
SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(timelined.getSwf());
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_FRAME, "" + frame);
}
stopInternal();
redraw();
fireMediaDisplayStateChanged();
}
@@ -6544,4 +6556,90 @@ public final class ImagePanel extends JPanel implements MediaDisplay {
return timelined;
}
}
public void loadOpenedDepths() {
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf);
if (conf != null) {
int chid = -1;
if (!parentTimelineds.isEmpty()) {
Timelined firstTimelined = parentTimelineds.get(0);
if (firstTimelined instanceof CharacterTag) {
chid = ((CharacterTag) firstTimelined).getCharacterId();
}
} else {
if (timelined instanceof CharacterTag) {
chid = ((CharacterTag) timelined).getCharacterId();
}
}
int lastChid = Integer.parseInt(conf.getCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_TIMELINE, "-1"));
if (lastChid != chid) {
return;
}
List<String> parentDepths = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_DEPTHS);
List<String> parentFrames = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_FRAMES);
while (parentFrames.size() < parentDepths.size()) {
parentFrames.add("0");
}
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_DEPTHS, new ArrayList<>());
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_FRAMES, new ArrayList<>());
int frame = Integer.parseInt(conf.getCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_FRAME, "1"));
for (int i = 0; i < parentDepths.size(); i++) {
openDepth(Integer.parseInt(parentFrames.get(i)), Integer.parseInt(parentDepths.get(i)));
}
gotoFrame(frame);
} else {
gotoFrame(1);
}
}
public void openDepth(int frame, int depth) {
Timelined tim = timelined;
if (tim == null) {
return;
}
if (tim.getTimeline().getFrame(frame) == null) {
return;
}
DepthState ds = tim.getTimeline().getFrame(frame).layers.get(depth);
if (ds != null) {
CharacterTag cht = ds.getCharacter();
if (cht instanceof Timelined) {
int newFrame = 0;
synchronized (lock) {
parentTimelineds.add(timelined);
parentDepths.add(ds.depth);
parentFrames.add(ds.frame.frame);
timelined = (Timelined) cht;
selectedDepths.clear();
int time = ds.time;
newFrame = time % timelined.getFrameCount();
if (timelined instanceof ButtonTag) {
newFrame = ButtonTag.FRAME_UP;
}
frame = newFrame;
SWF swf = parentTimelineds.get(0).getSwf();
SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf);
if (parentTimelineds.size() == 1) {
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_FIRST_PARENT_FRAME, "" + (ds.frame.frame + 1));
}
List<String> parentDepths = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_DEPTHS);
parentDepths.add("" + ds.depth);
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_DEPTHS, parentDepths);
List<String> parentFrames = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_FRAMES);
parentFrames.add("" + ds.frame.frame);
conf.setCustomData(CustomConfigurationKeys.KEY_EASY_LAST_SELECTED_PARENT_FRAMES, parentFrames);
}
gotoFrame(newFrame + 1);
fireMediaDisplayStateChanged();
}
}
}
}