116 lines
5.4 KiB
Java
116 lines
5.4 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.logging.LogUtils
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.client;
|
|
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
|
import com.mojang.blaze3d.platform.NativeImage;
|
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.textures.GpuTexture;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.File;
|
|
import java.util.function.Consumer;
|
|
import net.minecraft.ChatFormatting;
|
|
import net.minecraft.network.chat.ClickEvent;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.MutableComponent;
|
|
import net.minecraft.util.ARGB;
|
|
import net.minecraft.util.Util;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class Screenshot {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
public static final String SCREENSHOT_DIR = "screenshots";
|
|
|
|
public static void grab(File workDir, RenderTarget target, Consumer<Component> callback) {
|
|
Screenshot.grab(workDir, null, target, 1, callback);
|
|
}
|
|
|
|
public static void grab(File workDir, @Nullable String forceName, RenderTarget target, int downscaleFactor, Consumer<Component> callback) {
|
|
Screenshot.takeScreenshot(target, downscaleFactor, image -> {
|
|
File picDir = new File(workDir, SCREENSHOT_DIR);
|
|
picDir.mkdir();
|
|
File file = forceName == null ? Screenshot.getFile(picDir) : new File(picDir, forceName);
|
|
Util.ioPool().execute(() -> {
|
|
try (NativeImage nativeImage = image;){
|
|
image.writeToFile(file);
|
|
MutableComponent component = Component.literal(file.getName()).withStyle(ChatFormatting.UNDERLINE).withStyle(s -> s.withClickEvent(new ClickEvent.OpenFile(file.getAbsoluteFile())));
|
|
callback.accept(Component.translatable("screenshot.success", component));
|
|
}
|
|
catch (Exception e) {
|
|
LOGGER.warn("Couldn't save screenshot", (Throwable)e);
|
|
callback.accept(Component.translatable("screenshot.failure", e.getMessage()));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
public static void takeScreenshot(RenderTarget target, Consumer<NativeImage> callback) {
|
|
Screenshot.takeScreenshot(target, 1, callback);
|
|
}
|
|
|
|
public static void takeScreenshot(RenderTarget target, int downscaleFactor, Consumer<NativeImage> callback) {
|
|
int width = target.width;
|
|
int height = target.height;
|
|
GpuTexture sourceTexture = target.getColorTexture();
|
|
if (sourceTexture == null) {
|
|
throw new IllegalStateException("Tried to capture screenshot of an incomplete framebuffer");
|
|
}
|
|
if (width % downscaleFactor != 0 || height % downscaleFactor != 0) {
|
|
throw new IllegalArgumentException("Image size is not divisible by downscale factor");
|
|
}
|
|
GpuBuffer buffer = RenderSystem.getDevice().createBuffer(() -> "Screenshot buffer", 9, width * height * sourceTexture.getFormat().pixelSize());
|
|
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
|
|
RenderSystem.getDevice().createCommandEncoder().copyTextureToBuffer(sourceTexture, buffer, 0, () -> {
|
|
try (GpuBuffer.MappedView read = commandEncoder.mapBuffer(buffer, true, false);){
|
|
int outputHeight = height / downscaleFactor;
|
|
int outputWidth = width / downscaleFactor;
|
|
NativeImage image = new NativeImage(outputWidth, outputHeight, false);
|
|
for (int y = 0; y < outputHeight; ++y) {
|
|
for (int x = 0; x < outputWidth; ++x) {
|
|
if (downscaleFactor == 1) {
|
|
int argb = read.data().getInt((x + y * width) * sourceTexture.getFormat().pixelSize());
|
|
image.setPixelABGR(x, height - y - 1, argb | 0xFF000000);
|
|
continue;
|
|
}
|
|
int red = 0;
|
|
int green = 0;
|
|
int blue = 0;
|
|
for (int i = 0; i < downscaleFactor; ++i) {
|
|
for (int j = 0; j < downscaleFactor; ++j) {
|
|
int argb = read.data().getInt((x * downscaleFactor + i + (y * downscaleFactor + j) * width) * sourceTexture.getFormat().pixelSize());
|
|
red += ARGB.red(argb);
|
|
green += ARGB.green(argb);
|
|
blue += ARGB.blue(argb);
|
|
}
|
|
}
|
|
int sampleCount = downscaleFactor * downscaleFactor;
|
|
image.setPixelABGR(x, outputHeight - y - 1, ARGB.color(255, red / sampleCount, green / sampleCount, blue / sampleCount));
|
|
}
|
|
}
|
|
callback.accept(image);
|
|
}
|
|
buffer.close();
|
|
}, 0);
|
|
}
|
|
|
|
private static File getFile(File picDir) {
|
|
String name = Util.getFilenameFormattedDateTime();
|
|
int count = 1;
|
|
File file;
|
|
while ((file = new File(picDir, name + (String)(count == 1 ? "" : "_" + count) + ".png")).exists()) {
|
|
++count;
|
|
}
|
|
return file;
|
|
}
|
|
}
|
|
|