Skip to content
This repository has been archived by the owner on Mar 14, 2024. It is now read-only.

Commit

Permalink
The most significant changes involve the refactoring of the `RecordFX…
Browse files Browse the repository at this point in the history
…` class and the modification of the `ExporterController` class. In `RecordFX`, the `savePool` has been changed from a `LinkedBlockingQueue` of `Runnable` to an `ArrayBlockingQueue` of `Runnable`. The `Record` method now adds a new `Task` to the `savePool` instead of a `Runnable`. The `Exit` method now also clears the `savePool` and resets the `counter` to 0. The `encodeFX` method has been changed to use an `ArrayBlockingQueue` of `Thread` instead of an `ArrayList`. The `savePNG` method has been split into `toPixmap` and `writePNG` methods. In `ExporterController`, the `RB_Sequence` method now sets `Main.sequence` to `Byte.MAX_VALUE` instead of `Deflater.BEST_COMPRESSION`.

List of changes:

1. The version number in both the English and Chinese README files has been updated from 2.0.0 to 2.1.0.
2. In `RecordFX.java`, the import statement for `java.util.ArrayList` has been removed and replaced with `java.util.concurrent.ArrayBlockingQueue` and `java.util.zip.Deflater`.
3. The `RecordFX` class has been significantly refactored. The `savePool` has been changed from a `LinkedBlockingQueue` of `Runnable` to an `ArrayBlockingQueue` of `Runnable`. The `Record` method now adds a new `Task` to the `savePool` instead of a `Runnable`. The `Exit` method now also clears the `savePool` and resets the `counter` to 0.
4. The `encodeFX` method in `RecordFX` has been changed to use an `ArrayBlockingQueue` of `Thread` instead of an `ArrayList`. The method now polls from the `savePool` and `threads` instead of iterating over them.
5. The `savePNG` method in `RecordFX` has been split into `toPixmap` and `writePNG` methods. The `toPixmap` method creates a `Pixmap` from a `PixelReader`, and the `writePNG` method writes the `Pixmap` to a file and disposes of it. A new `Task` class has been added that implements `Runnable` and uses the `toPixmap` and `writePNG` methods.
6. In `ExporterController.java`, the import statement for `java.util.zip.Deflater` has been removed. The `RB_Sequence` method now sets `Main.sequence` to `Byte.MAX_VALUE` instead of `Deflater.BEST_COMPRESSION`.
  • Loading branch information
Aloento committed Jan 20, 2024
1 parent b7f37a6 commit 35f8620
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 33 deletions.
2 changes: 1 addition & 1 deletion README-Eng.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A tool to load and export Spine animations
**Java 21** required
Pixel Buffers support required
Exporting MOV requires FFmpeg
Current version: 2.0.0
Current version: 2.1.0

![霜叶](https://i0.hdslb.com/bfs/album/[email protected] "明日方舟 - 霜叶")

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
需要 **Java 21 21 21**
需要 像素缓冲区支持
导出 MOV 需要 FFmpeg
当前版本:2.0.0
当前版本:2.1.0

![霜叶](https://i0.hdslb.com/bfs/album/[email protected] "明日方舟 - 霜叶")

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>to.aloen</groupId>
<artifactId>SuperSpineViewer</artifactId>
<version>2.0.0</version>
<version>2.1.0</version>
<repositories>
<repository>
<id>sonatype</id>
Expand Down
92 changes: 64 additions & 28 deletions src/main/java/to/aloen/ssv/RecordFX.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,34 @@
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.zip.Deflater;

public abstract class RecordFX {
private static final LinkedBlockingQueue<Runnable> savePool = new LinkedBlockingQueue<>();
private static final LinkedBlockingQueue<Runnable> savePool = new LinkedBlockingQueue<>() {{
for (int i = 0; i < (Runtime.getRuntime().availableProcessors() + 1) / 2; i++) {
Thread.startVirtualThread(() -> {
while (true) {
try {
take().run();
} catch (InterruptedException ignored) {
}
}
});
}
}};

private static String fileName;

private static short counter;

private static short items;

public static void Record(PixelReader image) {
public static void Record(final PixelReader image) {
if (Spine.percent < 1) {
counter++;
savePool.add(() -> savePNG(image, counter));
savePool.add(new Task(image, counter++));
// System.out.println(STR."捕获:\{counter}\t\{Spine.percent}");
} else {
Main.recording = false;
Expand All @@ -48,8 +59,11 @@ public static void Exit() {
Main.recording = false;
Spine.speed.set(1);
Spine.isPlay.set(false);
savePool.clear();

counter = 0;
items = 0;

System.out.println("强制停止");
System.gc();
}
Expand Down Expand Up @@ -90,16 +104,14 @@ private static void encodeFX() {
Platform.runLater(() -> Main.progressBar.setProgress(-1));
System.out.println("请求:停止录制");

ArrayList<Thread> threads = new ArrayList<>();
ArrayBlockingQueue<Thread> threads = new ArrayBlockingQueue<>(savePool.size());

for (Runnable runnable : savePool)
threads.add(Thread.startVirtualThread(runnable));
while (!savePool.isEmpty())
threads.add(Thread.startVirtualThread(savePool.poll()));

savePool.clear();

for (Thread thread : threads)
while (!threads.isEmpty())
try {
thread.join();
threads.poll().join();
} catch (InterruptedException ignored) {
}

Expand All @@ -117,25 +129,49 @@ private static void encodeFX() {
});
}

private static void savePNG(PixelReader image, short index) {
Pixmap pixmap = new Pixmap(Main.width, Main.height, Pixmap.Format.RGBA8888) {{
for (int h = 0; h < Main.height; h++) {
for (int w = 0; w < Main.width; w++) {
int argb = image.getArgb(w, h);
drawPixel(w, h, (argb << 8) | (argb >>> 24));
}
private static Pixmap toPixmap(final PixelReader image) {
final Pixmap pixmap = new Pixmap(Main.width, Main.height, Pixmap.Format.RGBA8888);

for (int h = 0; h < Main.height; h++) {
for (int w = 0; w < Main.width; w++) {
int argb = image.getArgb(w, h);
pixmap.drawPixel(w, h, (argb << 8) | (argb >>> 24));
}
}};
}

PixmapIO.writePNG(Gdx.files.absolute(
STR."\{Main.outPath}\{fileName}_Sequence\{File.separator}\{fileName}_\{index}.png"),
pixmap, Main.sequence, true
);
return pixmap;
}

private static void writePNG(final Pixmap pixmap, final short index) {
try {
PixmapIO.writePNG(Gdx.files.absolute(
STR."\{Main.outPath}\{fileName}_Sequence\{File.separator}\{fileName}_\{index}.png"),
pixmap, Deflater.NO_COMPRESSION, true
);
} finally {
pixmap.dispose();

var percent = (double) items++ / counter;
Platform.runLater(() -> Main.progressBar.setProgress(percent));
// System.out.println(STR."保存:\{index}");
}
}

var percent = (double) items++ / counter;
Platform.runLater(() -> Main.progressBar.setProgress(percent));
private static class Task implements Runnable {
private final short counter;

pixmap.dispose();
// System.out.println(STR."保存:\{index}");
private PixelReader image;

private Task(PixelReader image, short counter) {
this.image = image;
this.counter = counter;
}

@Override
public void run() {
final Pixmap pixmap = toPixmap(image);
image = null;
writePNG(pixmap, counter);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.zip.Deflater;

public class ExporterController implements Initializable {
@FXML
Expand Down Expand Up @@ -134,7 +133,7 @@ void RB_MOV() {

@FXML
void RB_Sequence() {
Main.sequence = Deflater.BEST_COMPRESSION;
Main.sequence = Byte.MAX_VALUE;
}

@FXML
Expand Down

0 comments on commit 35f8620

Please sign in to comment.