Added: Simple editor - Button timeline header

This commit is contained in:
Jindra Petřík
2025-05-17 17:55:51 +02:00
parent b8c67a2bc3
commit dd49a7e73b
6 changed files with 106 additions and 62 deletions
@@ -31,7 +31,6 @@ import com.jpexs.decompiler.flash.timeline.Frame;
import com.jpexs.decompiler.flash.timeline.Timeline;
import com.jpexs.decompiler.flash.timeline.Timelined;
import com.jpexs.decompiler.flash.types.BUTTONRECORD;
import com.jpexs.helpers.Helper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
@@ -52,7 +51,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -76,7 +74,11 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
private Timeline timeline;
public static final int FRAME_WIDTH = 8;
private static final int FRAME_WIDTH = 8;
private static final int BUTTON_FRAME_WIDTH = 40;
private static final int MARKER_SIZE = 4;
public static final int FRAME_HEIGHT = 18;
@@ -223,6 +225,20 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
});
}
public static int getFrameWidthForTimeline(Timeline timeline) {
if (timeline == null) {
return FRAME_WIDTH;
}
if (timeline.timelined instanceof ButtonTag) {
return BUTTON_FRAME_WIDTH;
}
return FRAME_WIDTH;
}
public int getFrameWidth() {
return getFrameWidthForTimeline(timeline);
}
@Override
protected void paintComponent(Graphics g1) {
@@ -232,18 +248,20 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(getBackgroundColor());
g.fillRect(0, 0, getWidth(), getHeight());
g.fillRect(0, 0, getWidth(), getHeight());
if (timeline == null) {
return;
}
int frameWidth = getFrameWidth();
Set<Integer> emptyFrames = new LinkedHashSet<>();
if (timeline.timelined instanceof ButtonTag) {
emptyFrames = ((ButtonTag) timeline.timelined).getEmptyFrames();
frameWidth = BUTTON_FRAME_WIDTH;
}
Rectangle clip = g.getClipBounds();
int frameWidth = FRAME_WIDTH;
int frameHeight = FRAME_HEIGHT;
int start_f = clip.x / frameWidth;
int start_d = clip.y / frameHeight;
@@ -285,14 +303,14 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
Frame fr = timeline.getFrame(f);
if (fr != null && !fr.actions.isEmpty()) {
if (firstAction) {
drawBlock(g, getEmptyFrameColor(), 0, 0, f, BlockType.EMPTY);
drawBlock(g, getEmptyFrameColor(), 0, 0, f, BlockType.EMPTY, frameWidth);
}
int f2 = f + 1;
while (f2 <= max_f && timeline.getFrame(f2) != null && timeline.getFrame(f2).actions.isEmpty()) {
f2++;
}
drawBlock(g, getEmptyFrameColor(), 0, f, f2 - f, BlockType.EMPTY);
drawBlock(g, getEmptyFrameColor(), 0, f, f2 - f, BlockType.EMPTY, frameWidth);
g.setColor(A_COLOR);
g.setFont(getFont().deriveFont(FONT_SIZE));
g.drawString("a", f * frameWidth + frameWidth / 2 - awidth / 2, frameHeight / 2);
@@ -322,11 +340,11 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
for (int f = start_f2; f <= end_f2; f++) {
DepthState fl = timeline.getFrame(f).layers.get(d);
if (emptyFrames.contains(f)) {
fl = null;
}
boolean motionTween = fl == null ? false : fl.motionTween;
DepthState flNext = f < max_f ? timeline.getFrame(f + 1).layers.get(d) : null;
@@ -372,7 +390,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
blockType = shapeTween ? BlockType.SHAPE_TWEEN : motionTween ? BlockType.MOTION_TWEEN : BlockType.NORMAL;
}
drawBlock(g, backColor, d, draw_f, num_frames, blockType);
drawBlock(g, backColor, d, draw_f, num_frames, blockType, frameWidth);
}
}
@@ -383,8 +401,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
}
}
private void drawBlock(Graphics2D g, Color backColor, int depth, int frame, int num_frames, BlockType blockType) {
int frameWidth = FRAME_WIDTH;
private void drawBlock(Graphics2D g, Color backColor, int depth, int frame, int num_frames, BlockType blockType, int frameWidth) {
int frameHeight = FRAME_HEIGHT;
for (int n = frame; n < frame + num_frames; n++) {
@@ -429,9 +446,9 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
g.setColor(KEY_COLOR);
}
if (blockType == BlockType.EMPTY) {
g.drawOval(frame * frameWidth + frameWidth / 4, depth * frameHeight + frameHeight * 3 / 4 - frameWidth / 2 / 2, frameWidth / 2, frameWidth / 2);
g.drawOval(frame * frameWidth + frameWidth / 2 - MARKER_SIZE / 2, depth * frameHeight + frameHeight * 3 / 4 - MARKER_SIZE / 2, MARKER_SIZE, MARKER_SIZE);
} else {
g.fillOval(frame * frameWidth + frameWidth / 4, depth * frameHeight + frameHeight * 3 / 4 - frameWidth / 2 / 2, frameWidth / 2, frameWidth / 2);
g.fillOval(frame * frameWidth + frameWidth / 2 - MARKER_SIZE / 2, depth * frameHeight + frameHeight * 3 / 4 - MARKER_SIZE / 2, MARKER_SIZE, MARKER_SIZE);
}
if (num_frames > 1) {
@@ -442,7 +459,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
g.setColor(KEY_COLOR);
}
if (isTween) {
g.fillOval(endFrame * frameWidth + frameWidth / 4, depth * frameHeight + frameHeight * 3 / 4 - frameWidth / 2 / 2, frameWidth / 2, frameWidth / 2);
g.fillOval(endFrame * frameWidth + frameWidth / 2 - MARKER_SIZE / 2, depth * frameHeight + frameHeight * 3 / 4 - MARKER_SIZE / 2, MARKER_SIZE, MARKER_SIZE);
} else {
if (cursor != null && cursor.contains(new Point(endFrame, depth))) {
@@ -450,13 +467,13 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
} else {
g.setColor(STOP_COLOR);
}
g.fillRect(endFrame * frameWidth + frameWidth / 4, depth * frameHeight + frameHeight / 2 - 2, frameWidth / 2, frameHeight / 2);
g.fillRect(endFrame * frameWidth + frameWidth / 2 - MARKER_SIZE / 2, depth * frameHeight + frameHeight / 2 - 2, MARKER_SIZE, frameHeight / 2);
if (cursor != null && cursor.contains(new Point(endFrame, depth))) {
g.setBackground(getSelectedColorText());
} else {
g.setColor(STOP_BORDER_COLOR);
}
g.drawRect(endFrame * frameWidth + frameWidth / 4, depth * frameHeight + frameHeight / 2 - 2, frameWidth / 2, frameHeight / 2);
g.drawRect(endFrame * frameWidth + frameWidth / 2 - MARKER_SIZE / 2, depth * frameHeight + frameHeight / 2 - 2, MARKER_SIZE, frameHeight / 2);
}
for (int n = frame + 1; n < frame + num_frames; n++) {
@@ -580,7 +597,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
return;
}
Point p = e.getPoint();
p.x = p.x / FRAME_WIDTH;
p.x = p.x / getFrameWidth();
p.y = p.y / FRAME_HEIGHT;
/*if (p.x >= timeline.getFrameCount()) {
p.x = timeline.getFrameCount() - 1;
@@ -624,7 +641,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
DepthState ds = fr == null ? null : fr.layers.get(depth);
Set<Integer> emptyFrames = new LinkedHashSet<>();
if (timeline.timelined instanceof ButtonTag) {
emptyFrames = ((ButtonTag) timeline.timelined).getEmptyFrames();
emptyFrames = ((ButtonTag) timeline.timelined).getEmptyFrames();
}
boolean thisEmpty = emptyFrames.contains(frame) || ds == null || ds.getCharacter() == null;
boolean previousEmpty = true;
@@ -724,7 +741,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
if (rec != null) {
rec.setFrame(nf, false);
}
for(int i = nf + 1; i < button.getFrameCount(); i++) {
for (int i = nf + 1; i < button.getFrameCount(); i++) {
rec = button.getButtonRecordAt(i, nd, false);
if (rec != null) {
rec.setFrame(i - 1, true);
@@ -817,7 +834,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
}
}
}
timelined.resetTimeline();
Point firstCursor = orderedCursor.iterator().next();
@@ -874,22 +891,22 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
continue;
}
ds.key = true;
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
BUTTONRECORD rec = button.getButtonRecordAt(nf, nd, false);
if (rec != null) {
BUTTONRECORD rec2 = new BUTTONRECORD(rec.getSwf(), rec.getTag());
rec2.fromPlaceObject(rec.toPlaceObject());
for(int i = nf; i < button.getFrameCount(); i++) {
for (int i = nf; i < button.getFrameCount(); i++) {
rec2.setFrame(i, rec.hasFrame(i));
rec.setFrame(i, false);
}
button.getRecords().add(rec2);
}
continue;
}
}
PlaceObjectTypeTag place;
try {
place = (PlaceObjectTypeTag) ds.placeObjectTag.cloneTag();
@@ -977,14 +994,14 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
}
}
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
ButtonTag button = (ButtonTag) timelined;
BUTTONRECORD rec = button.getButtonRecordAt(nonEmptyFrame, fdepth, false);
BUTTONRECORD rec2 = new BUTTONRECORD(rec.getSwf(), rec.getTag());
rec2.fromPlaceObject(rec.toPlaceObject());
rec2.setFrame(fframe, true);
button.getRecords().add(rec2);
} else {
} else {
PlaceObjectTypeTag place;
try {
place = (PlaceObjectTypeTag) ds.placeObjectTag.cloneTag();
@@ -1042,13 +1059,12 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
int nf = p.x;
int nd = p.y;
if (nf >= timelined.getFrameCount()) {
if (timelined instanceof ButtonTag) {
if (timelined instanceof ButtonTag) {
continue;
}
}
ReadOnlyTagList tags = timelined.getTags();
for (int i = tags.size() - 1; i >= 0; i--) {
Tag t = tags.get(i);
@@ -1094,7 +1110,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
boolean somethingAfter = false;
Set<Integer> emptyFrames = new LinkedHashSet<>();
if (timelined instanceof ButtonTag) {
if (timelined instanceof ButtonTag) {
emptyFrames = ((ButtonTag) timelined).getEmptyFrames();
}
for (int f = nf + 1; f < timeline.getFrameCount(); f++) {
@@ -1112,8 +1128,8 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
if (!empty || somethingAfter) {
int moveFrameCount = somethingAfter ? 1 : nf - f;
for (int mf = 0; mf < moveFrameCount; mf++) {
if (timelined instanceof ButtonTag) {
if (timelined instanceof ButtonTag) {
ButtonTag button = (ButtonTag) timelined;
if (!somethingAfter) {
BUTTONRECORD rec = button.getButtonRecordAt(f, nd, true);
@@ -1129,7 +1145,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
}
button.packRecords();
continue;
}
}
int pos = timelined.indexOfTag(timeline.getFrame(f).showFrameTag);
ReadOnlyTagList tags = timelined.getTags();
@@ -1293,9 +1309,9 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
public Rectangle getFrameBounds(int frame, int depth) {
Rectangle rect = new Rectangle();
rect.width = FRAME_WIDTH;
rect.width = getFrameWidth();
rect.height = FRAME_HEIGHT;
rect.x = frame * FRAME_WIDTH;
rect.x = frame * getFrameWidth();
rect.y = depth * FRAME_HEIGHT;
return rect;
}
@@ -1303,7 +1319,7 @@ public class TimelineBodyPanel extends JPanel implements MouseListener, KeyListe
public void refresh() {
int frameCount = timeline == null ? 0 : timeline.getFrameCount();
int maxDepth = timeline == null ? 0 : timeline.getMaxDepth();
Dimension dim = new Dimension(FRAME_WIDTH * frameCount + 1, FRAME_HEIGHT * (maxDepth + 1 /*actions*/ + 1 /*one additional*/));
Dimension dim = new Dimension(getFrameWidth() * frameCount + 1, FRAME_HEIGHT * (maxDepth + 1 /*actions*/ + 1 /*one additional*/));
setSize(dim);
setPreferredSize(dim);
}