Libgdx Screenshot method not working - libgdx

A couple of weeks ago I implemented this method https://github.com/libgdx/libgdx/wiki/Take-a-Screenshot
And it worked great with libgdx 1.3.1 . Now though I upgraded to 1.6.0 and it have stopped working.
When the method is executed it freezes. I have it implemented on a button, and it gets stuck in "downclick" and nothing more happens.
private void saveScreenshot() {
try{
FileHandle fh;
do{
fh = new FileHandle(files.getLocalStoragePath() + "screenshot" + ".png");
}while(fh.exists());
Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 130, true);
PixmapIO.writePNG(fh, pixmap);
pixmap.dispose();
System.out.println("Path:" + fh.toString());
}catch(Exception e) {
}
}
private Pixmap getScreenshot(int x, int y, int w, int h, boolean yDown){
final Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(x, y, w, h);
w = pixmap.getWidth();
h = pixmap.getHeight();
if(yDown) {
ByteBuffer pixels = pixmap.getPixels();
int numBytes = w * h * 4;
byte[] lines = new byte[numBytes];
int numBytesPerLine = w * 4;
for (int i = 0; i < h; i++) {
pixels.position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
pixels.clear();
pixels.put(lines);
}
return pixmap;
}
btnArrow.addListener(new ChangeListener() {
//photoshop "save" and "back" on arrow/back image to clarify.
#Override
public void changed(ChangeEvent event, Actor actor) {
saveScreenshot();
sharePhoto();
}
});
I share the image to facebook aswell. And this method is in AndroidLauncher of course and is passed through an interface. And here I fetch the screenshot:
public void sharePhoto() {
Matrix matrix = new Matrix();
String filePath = (files.getLocalStoragePath() + "screenshot" + ".png");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
Bitmap rotateBit = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
//Starts sharing process
SharePhoto photo = new SharePhoto.Builder()
.setBitmap(rotateBit)
.build();
SharePhotoContent content = new SharePhotoContent.Builder()
.addPhoto(photo)
.build();
share.show(content);
}
So what I believe may be the issue is libgdx have done changes on Pixmap class or Bitmap class of some sort. Since sharing a link through facebook on that button works fine.
I also printed the path as you can see in saveScreenshot() and it returns this
selinux_android_setcategory: no category for userid: 0, path: /data/data/com.sparc.tormt.android/lib

Is it stuck because this is an infinite loop if the file already exists:
do {
fh = new FileHandle(files.getLocalStoragePath() + "screenshot" + ".png");
} while(fh.exists());

Related

Editing a function within mousePressed

I'm a beginner working with Processing trying to create a moving cloud sketch. They are to appear on mouseClick, and horizontally move across the screen.
void mousePressed() {
int newCloud {
xpos: mouseX;
ypos: mouseY;
}
clouds.push(newCloud);
}
Here is the area I'm unable to fix, trying to work out the mousePressed part.
and here is my full code! It seems a simple fix but I've tried a bunch of ways rewriting it without succsess.
int[] clouds;
int cloudx;
int cloudy;
int xpos, ypos;
void setup() {
size(600, 600);
int cloudx=mouseX;
int cloudy=mouseY;
}
void draw() {
background(100);
for (int i = 0; i < clouds.length; i++) {
int[] currentObj = clouds[i];
cloud(currentObj.xpos, currentObj.ypos, currentObj.size);
currentObj.xpos += 0.5;
currentObj.ypos += random(-0.5, 0.5);
if (clouds[i].xpos > width+20) {
clouds.splice(i, 1);
}
}
}
void makeCloud (int x, int y){
fill(250);
noStroke();
ellipse(x, y, 70, 50);
ellipse(x + 10, y + 10, 70, 50);
ellipse(x - 20, y + 10, 70, 50);
}
void mousePressed() {
int newCloud {
xpos: mouseX;
ypos: mouseY;
}
clouds.push(newCloud);
}
I had tried to make a new function, though the clouds wouldnt show, I also tried calling the makeCloud function though i know I need to be updating within this new function. Overall, I need help with how to write this statement for newCloud in the mousePressed function.
Your code is irreparable for many reasons.
int[] clouds; will create a reference for Array of single integers, not objects,
void makeCloud (int x, int y){...}, will just draw some ellipses,
clouds.splice(i, 1); inside an Array will not work at all,
This is a working reconstruction of Your problem:
ArrayList<Cloud> clouds = new ArrayList<Cloud>();
void setup() {
size(600, 600);
}
void draw() {
background(100);
drawClouds(clouds);
removeExcessClouds(clouds);
}
/**
** Cloud class
**/
class Cloud {
float xPos;
float yPos;
Cloud(float x, float y) {
xPos = x;
yPos = y;
}
void draw() {
fill(250);
noStroke();
ellipse(xPos, yPos, 70, 50);
ellipse(xPos + 10, yPos + 10, 70, 50);
ellipse(xPos - 20, yPos + 10, 70, 50);
}
void positionUpdate(float deltaX) {
xPos += deltaX;
yPos += random(-0.5, 0.5);
}
}
void drawClouds(ArrayList<Cloud> cds) {
float wind = 0.5;
for (Cloud cd : clouds) {
cd.draw();
cd.positionUpdate(wind);
}
}
void removeExcessClouds(ArrayList<Cloud> cds) {
int cdAmount = clouds.size();
for (int i = 0; i<cdAmount; i++) {
if (clouds.get(i).xPos > width+20) {
clouds.remove(i);
cdAmount = clouds.size();
}
}
}
void mousePressed() {
clouds.add(new Cloud(mouseX, mouseY));
println(mouseX + ", " + mouseY + " : " + clouds.size());
}
Note:
global List initiation:
ArrayList clouds = new ArrayList();
List proper iteration:
for (Cloud cd : clouds) { foo(cd); }
draw method inside a Cloud,
passing values when calling methods.
So, now You can iterate over a List of Objects, and call a draw method inside each Cloud.
As said in the other answer, you will need to refactor your code to use objects.
This looks like an atempt at a JS object literal - Java doesn't use them.
int newCloud {
xpos: mouseX;
ypos: mouseY;
}
You need to instance a Class:
Cloud myCloud = new Cloud(0,5); // You create a new variable of the Cloud type and initialize it with a new Cloud object (essentially calling the constructor)
class Cloud{
int posX, posY;
Cloud(int px, int py){ // This is called a constuctor and its the way a new instance is created
this.posX = px;
this.posY = py;
}
}
Than for the array of clouds you need an ArrayList of Clouds:
ArrayList<Cloud> clouds = new ArrayList<Cloud>();
in the mousePressed event you than just add the new cloud to the arraylist:
clouds.add(myCloud);

Trying to understand code in the PolygonSprite.java library file

I am trying to execute this piece of code in my game.
public void draw(Batch batch, float parentAlpha){
PolygonRegion polyReg = new PolygonRegion(connectorTextureRegion, getVertices(), getTriangles());
polygonSprite.setRegion(polyReg);
polygonSprite.draw((PolygonSpriteBatch)batch);
}
In general, it works well but sometimes I'm getting an ArrayIndexOutOfBounds exception caused by the setRegion line. If I dive into the methods code, it fails at the first line in the for loop.
public void setRegion (PolygonRegion region) {
this.region = region;
float[] regionVertices = region.vertices;
float[] textureCoords = region.textureCoords;
if (vertices == null || regionVertices.length != vertices.length) vertices = new float[(regionVertices.length / 2) * 5];
// Set the color and UVs in this sprite's vertices.
float floatColor = color.toFloatBits();
float[] vertices = this.vertices;
for (int i = 0, v = 2, n = regionVertices.length; i < n; i += 2, v += 5) {
vertices[v] = floatColor;
vertices[v + 1] = textureCoords[i];
vertices[v + 2] = textureCoords[i + 1];
}
dirty = true;
}
Now let me know if I'm wrong, but I feel like there might be an issue with the if condition. Why are we checking for this?
regionVertices.length != vertices.length
Whenever I get the exception, it's because the length of the region vertices array and the length of the sprite vertices array are equal.

Capture Screen in libGdx

I want to capture screen in libGdx . I use this code for my problem. On Desktop it work . But when I run on my android , I can't find image capture screen. How can I fix it? Thanks for reading my question.
public class ScreenshotFactory {
private static int counter = 1;
public static void saveScreenshot() {
try {
FileHandle fh;
do {
if (Gdx.app.getType() == ApplicationType.Desktop)
Infor.linkScreenShot = "D://chupngoc" + counter + ".png";
else
Infor.linkScreenShot = Gdx.files.getExternalStoragePath()
+ counter + ".png";
Infor.nameImage = counter + ".png";
fh = new FileHandle(Infor.linkScreenShot);
counter++;
} while (fh.exists());
Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight(), true);
PixmapIO.writePNG(fh, pixmap);
pixmap.dispose();
} catch (Exception e) {
}
}
private static Pixmap getScreenshot(int x, int y, int w, int h,
boolean yDown) {
Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1);
final Pixmap pixmap1 = new Pixmap(w, h, Format.RGBA8888);
ByteBuffer pixels1 = pixmap1.getPixels();
Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE,
pixels1);
Pixmap pixmap = pixmap1;
if (yDown) {
// Flip the pixmap upside down
ByteBuffer pixels = pixmap.getPixels();
int numBytes = w * h * 4;
byte[] lines = new byte[numBytes];
int numBytesPerLine = w * 4;
for (int i = 0; i < h; i++) {
pixels.position((h - i - 1) * numBytesPerLine);
pixels.get(lines, i * numBytesPerLine, numBytesPerLine);
}
pixels.clear();
pixels.put(lines);
}
return pixmap;
}
}
Your problem lies here...
fh = new FileHandle(Infor.linkScreenShot);
This way of creating a FileHandle is for the desktop only and will not work on Android.
You should create a file using Gdx.files.external instead...
fh = Gdx.files.external(Infor.linkScreenShot);

Windows Store apps do not support WPF's <InkCanvas>

I am working on an application which can take input thru touch screen using mouse or stylus.. Found that <InkCanvas> works really great for me, but Windows Store app project does not recognize/support <InkCanvas> tag.
Does any came across similar kind of requirement and scenario.
Any suggestion.
Of course, one of them is but it is not as flexible as <InkCanvas>
Use this control in xaml like: <ctrl:InkCanvas x:Name="inkCanvas" />
Don't forget to reference 'ctrl' like: xmlns:ctrl="using:MyAppNamespace"
using System;
using System.Collections.Generic;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
namespace MyAppNamespace
{
public class InkCanvas : Canvas
{
InkManager m_InkManager = new Windows.UI.Input.Inking.InkManager();
private uint m_PenId;
private uint _touchID;
private Point _previousContactPt;
private Point currentContactPt;
private double x1;
private double y1;
private double x2;
private double y2;
private Color m_CurrentDrawingColor = Colors.Black;
private double m_CurrentDrawingSize = 4;
public List<InkStroke> Strokes { get { return m_InkManager.GetStrokes().ToList(); } }
public InkCanvas()
{
m_InkManager.Mode = Windows.UI.Input.Inking.InkManipulationMode.Inking;
SetDefaults(m_CurrentDrawingSize, m_CurrentDrawingColor);
this.PointerPressed += new PointerEventHandler(OnCanvasPointerPressed);
this.PointerMoved += new PointerEventHandler(OnCanvasPointerMoved);
this.PointerReleased += new PointerEventHandler(OnCanvasPointerReleased);
this.PointerExited += new PointerEventHandler(OnCanvasPointerReleased);
}
public void Clear()
{
this.Children.Clear();
var strokes = m_InkManager.GetStrokes();
for (int i = 0; i < strokes.Count; i++)
strokes[i].Selected = true;
m_InkManager.DeleteSelected();
}
public async Task<byte[]> GetBytes()
{
var bytes = new byte[0];
if (Strokes.Count > 0)
{
var tempFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(Guid.NewGuid().ToString() + ".jpg");
var writeStream = await tempFile.OpenAsync(FileAccessMode.ReadWrite);
await m_InkManager.SaveAsync(writeStream);
await writeStream.FlushAsync();
var reader = new DataReader(writeStream.GetInputStreamAt(0));
bytes = new byte[writeStream.Size];
await reader.LoadAsync((uint)writeStream.Size);
reader.ReadBytes(bytes);
reader.DetachStream();
await tempFile.DeleteAsync();
}
return bytes;
}
public async Task<BitmapImage> GetBitmapImage()
{
var bitmapImage = new BitmapImage();
var bytes = await GetBytes();
if (bytes.Length > 0)
{
using (var stream = new InMemoryRandomAccessStream())
{
// For AsBuffer manually add [ using System.Runtime.InteropServices.WindowsRuntime ];
await stream.WriteAsync(bytes.AsBuffer());
stream.Seek(0);
bitmapImage.SetSource(stream);
}
}
return bitmapImage;
}
#region Pointer Event Handlers
public void OnCanvasPointerReleased(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == m_PenId)
{
Windows.UI.Input.PointerPoint pt = e.GetCurrentPoint(this);
// Pass the pointer information to the InkManager.
m_InkManager.ProcessPointerUp(pt);
}
else if (e.Pointer.PointerId == _touchID)
{
// Process touch input
}
_touchID = 0;
m_PenId = 0;
e.Handled = true;
}
private void OnCanvasPointerMoved(object sender, PointerRoutedEventArgs e)
{
if (e.Pointer.PointerId == m_PenId)
{
PointerPoint pt = e.GetCurrentPoint(this);
// Render a red line on the canvas as the pointer moves.
// Distance() is an application-defined function that tests
// whether the pointer has moved far enough to justify
// drawing a new line.
currentContactPt = pt.Position;
x1 = _previousContactPt.X;
y1 = _previousContactPt.Y;
x2 = currentContactPt.X;
y2 = currentContactPt.Y;
var color = m_CurrentDrawingColor;
var size = m_CurrentDrawingSize;
if (Distance(x1, y1, x2, y2) > 2.0)
{
Line line = new Line()
{
X1 = x1,
Y1 = y1,
X2 = x2,
Y2 = y2,
StrokeThickness = size,
Stroke = new SolidColorBrush(color)
};
_previousContactPt = currentContactPt;
// Draw the line on the canvas by adding the Line object as
// a child of the Canvas object.
this.Children.Add(line);
}
// Pass the pointer information to the InkManager.
m_InkManager.ProcessPointerUpdate(pt);
}
else if (e.Pointer.PointerId == _touchID)
{
// Process touch input
}
}
private double Distance(double x1, double y1, double x2, double y2)
{
double d = 0;
d = Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2));
return d;
}
public void OnCanvasPointerPressed(object sender, PointerRoutedEventArgs e)
{
// Get information about the pointer location.
PointerPoint pt = e.GetCurrentPoint(this);
_previousContactPt = pt.Position;
// Accept input only from a pen or mouse with the left button pressed.
PointerDeviceType pointerDevType = e.Pointer.PointerDeviceType;
if (pointerDevType == PointerDeviceType.Pen ||
pointerDevType == PointerDeviceType.Mouse &&
pt.Properties.IsLeftButtonPressed)
{
// Pass the pointer information to the InkManager.
m_InkManager.ProcessPointerDown(pt);
m_PenId = pt.PointerId;
e.Handled = true;
}
else if (pointerDevType == PointerDeviceType.Touch)
{
// Process touch input
}
}
#endregion
#region Mode Functions
// Change the color and width in the default (used for new strokes) to the values
// currently set in the current context.
private void SetDefaults(double strokeSize, Color color)
{
var newDrawingAttributes = new InkDrawingAttributes();
newDrawingAttributes.Size = new Size(strokeSize, strokeSize);
newDrawingAttributes.Color = color;
newDrawingAttributes.FitToCurve = true;
m_InkManager.SetDefaultDrawingAttributes(newDrawingAttributes);
this.Background = new SolidColorBrush(Colors.White);
}
#endregion
}
}
You use the InkManager class in WinRT instead of WPF's InkCanvas. I think you might need to use your own Canvas control with some Shapes (Polyline?) and handle the Pointer~ events yourself, but I haven't done it myself so I can't say for sure.

Trying to create a circle with VBO's - LWJGL

Im trying to create a circle in LWJGL , using VBO's and VAO , and move it using an offset , but it seems one vertex is stuck in the center of the screen . I can't figure out how to move it to the new location . Any help is appreciated , thanks !
P.S : I have already tried debugging the program , but I can't locate the faulty vertex in my array
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.*;
public class Test {
// Setup variables
private int WIDTH = 800;
private int HEIGHT = 600;
private String title = "Circle";
// Quad variables
private int vbo = 0; // Vertex Buffer Object
private int vao = 0; // Vertex Array Object
int SUBDIVISIONS = 100;
float[] vertex = new float[(SUBDIVISIONS + 1) * 4];
public Test() {
// Initialize
setupOpenGL();
setupQuad();
while (!Display.isCloseRequested()) {
loop();
Display.update();
Display.sync(60);
}
Display.destroy();
}
public void setupOpenGL() {
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.setTitle(title);
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(-1); // If error , exit program
}
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
public void setupQuad() {
float r = 0.2f;
float x;
float y;
float offSetX = 0.3f;
float offSetY = 0.3f;
vertex[0] = (float) Math.sin(Math.PI*2*0/SUBDIVISIONS) * r + offSetX;
vertex[1] = (float) Math.cos(Math.PI*2*1/SUBDIVISIONS) * r + offSetY;
for (int i = 2; i < 360; i = i + 2) {
double angle = Math.PI * 2 * i / SUBDIVISIONS;
x = (float) Math.cos(angle) * r;
vertex[i] = x + offSetX;
}
for (int i = 3; i < 360; i = i + 2) {
double angle = Math.PI * 2 * i / SUBDIVISIONS;
y = (float) Math.sin(angle) * r;
vertex[i] = y + offSetY;
}
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(vertex.length);
vertexBuffer.put(vertex);
vertexBuffer.flip();
vao = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
vbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,vertexBuffer,GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
public void loop() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL30.glBindVertexArray(vao);
GL20.glEnableVertexAttribArray(0);
// Draw the vertices
GL11.glDrawArrays(GL11.GL_TRIANGLE_FAN, 0, vertex.length / 2);
// Put everything back to default (deselect)
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
public static void main(String[] args) {
new Test();
}
}
"I think I've found the problem . I was setting the positions of only 359 vertices out of 404 vertices (nr of subdivisions + 1 times 4) . It seems the rest of the vertices were stuck at 0,0 on the screen . Allowing both FOR statements to cycle up to 404 seems to solve the problem"