package net.cis.client.game.util;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.ByteBuffer;
import javax.imageio.ImageIO;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.jme3.app.SimpleApplication;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.post.SceneProcessor;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer;
import com.jme3.util.BufferUtils;
import com.jme3.util.Screenshots;
public class ScreenRecorder implements SceneProcessor, ActionListener {
private static final Log log = LogFactory.getLog(ScreenRecorder.class);
protected final SimpleApplication theGame;
protected final ViewPort viewPort;
protected Renderer renderer = null;
protected String screenshotFolder = null;
protected static final String screenShotPrefix = "screenshot-";
protected ByteBuffer outBuf;
protected BufferedImage outImg;
protected boolean printScreenButtonDown = false;
protected boolean oneTimeScreenShot = false;
protected long lastScreenCapture = 0;
protected long fileIndex = 0;
public ScreenRecorder(SimpleApplication app, String folder)
{
this(app, folder, null, true);
}
public ScreenRecorder(SimpleApplication app, String folder, boolean registerKey)
{
this(app, folder, null, registerKey);
}
public ScreenRecorder(SimpleApplication app, String folder, ViewPort vp, boolean registerKey)
{
theGame = app;
screenshotFolder = folder;
if(screenshotFolder == null || screenshotFolder.trim().length() == 0)
screenshotFolder = "./";
if(vp == null)
viewPort = app.getRenderManager().getPostViews().get(app.getRenderManager().getPostViews().size()-1);
else
viewPort = vp;
viewPort.addProcessor(this);
if(registerKey)
registerPrintScreenForScreenshots();
}
public void registerPrintScreenForScreenshots()
{
theGame.getInputManager().addMapping("Screenshot", new KeyTrigger(KeyInput.KEY_SYSRQ));
theGame.getInputManager().addListener(this, "Screenshot");
}
public void removePrintScreenForScreenshots()
{
theGame.getInputManager().removeListener(this);
theGame.getInputManager().deleteMapping("Screenshot");
}
public void takeScreenshot()
{
oneTimeScreenShot = true;
}
protected String getNextScreenshotFileName()
{
if(!screenshotFolder.endsWith("/"))
screenshotFolder += "/";
File path = new File(screenshotFolder);
if(!path.exists())
if(!path.mkdirs())
screenshotFolder = "./";
String name = screenshotFolder + screenShotPrefix + String.format("%05d", fileIndex) + ".png";
File f = new File(name);
while(f.exists())
{
++fileIndex;
name = screenshotFolder + screenShotPrefix + String.format("%05d", fileIndex) + ".png";
f = new File(name);
}
++fileIndex;
return name;
}
@Override
public void onAction(String name, boolean isPressed, float tpf) {
takeScreenshot();
}
@Override
public void initialize(RenderManager rm, ViewPort vp) {
renderer = rm.getRenderer();
assert(vp == viewPort);
reshape(viewPort, viewPort.getCamera().getWidth(), viewPort.getCamera().getHeight());
}
@Override
public void reshape(ViewPort vp, int w, int h) {
outBuf = BufferUtils.createByteBuffer(w*h*4);
outImg = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
}
@Override
public boolean isInitialized() {
return renderer != null;
}
@Override
public void preFrame(float tpf) {
//nothing to do...
}
@Override
public void postQueue(RenderQueue rq) {
//nothing to do...
}
@Override
public void postFrame(FrameBuffer out) {
if(oneTimeScreenShot && System.currentTimeMillis() - lastScreenCapture > 500)
{
lastScreenCapture = System.currentTimeMillis();
oneTimeScreenShot = false;
renderer.readFrameBuffer(out, outBuf);
Screenshots.convertScreenShot(outBuf, outImg);
try {
String fileName = getNextScreenshotFileName();
ImageIO.write(outImg, "png", new File(fileName));
log.info("Screenshot saved to " + fileName);
} catch (Exception ex){
log.info("Error while saving screenshot", ex);
}
}
}
@Override
public void cleanup() {
removePrintScreenForScreenshots();
}
}