how to write GameObject position in the Scene to json file? - json

on Clicking the button, I m loading the function WriteJsonForLevel(). I have placed three GameObject with the tag name "RedCoin" and I want to write the position of the GameObject to a JSON file. I can get the position of the object, but it's all overwritten. I can only see the last GameObject position (i.e the completion of the loop)
public List<GameObject> levelObjects;
public string level;
public Vector3 pos;
// Start is called before the first frame update
void Start()
{
levelObjects = new List<GameObject>();
}
// Update is called once per frame
void Update()
{
}
public void WritejsonForAll()
{
WriteJsonForLevel();
}
public void WriteJsonForLevel()
{
/* FileStream fs = new FileStream(Application.dataPath + "/sample.json",FileMode.Create);
StreamWriter writer= new StreamWriter(fs);*/
GameObject[] coinObjRed = GameObject.FindGameObjectsWithTag("RedCoin");
putAllObjectInList(coinObjRed);
}
public void putAllObjectInList(GameObject[] p)
{
string path = Application.dataPath + "/text.json";
foreach (GameObject q in p)
{
levelObjects.Add(q);
}
for (int i = 0; i < levelObjects.Count; i++)
{
GameObject lvlObj = levelObjects[i];
Vector3 pos = lvlObj.transform.position;
string posOutput = JsonUtility.ToJson(pos);
File.WriteAllText(path,posOutput);
Debug.Log("position:" + posOutput);
}
}
}

You are using WriteAllText which will overwrite the file every time it is called. As it is overwriting each time it is in the loop, it will only write the last object to the file as every other previous write is overwritten. I would consider making a serialized class of data, assigning the data to it, converting it to a JSON string then saving that.
// stores individual locations for saving
[System.Serializable]
public class IndividualLocation
{
public IndividualLocation(Vector3 pos)
{
xPos = pos.x;
yPos = pos.y;
zPos = pos.z;
}
public float xPos;
public float yPos;
public float zPos;
}
// stores all game locations for saving
[System.Serializable]
public class AllGameLocations
{
public List<IndividualLocation> Locations = new List<IndividualLocation>();
}
public void PutAllObjectInList(in GameObject[] p)
{
string path = Application.dataPath + "/text.json";
// create a new object to write to
AllGameLocations data = new AllGameLocations();
// iterate the objects adding each to our structure
foreach(GameObject obj in p)
{
data.Locations.Add(new IndividualLocation(obj.transform.position));
}
// now that the data is filled, write out to the file
File.WriteAllText(path, JsonUtility.ToJson(AllGameLocations));
}
If you need a snippet on how to load the data properly I can add one.
Edit: Here is a load snippet
public void LoadJSONObject()
{
string path = Application.dataPath + "/text.json";
// if the file path or name does not exist
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Debug.LogWarning("File or path does not exist! " + path);
return
}
// load in the save data as byte array
byte[] jsonDataAsBytes = null;
try
{
jsonDataAsBytes = File.ReadAllBytes(path);
Debug.Log("<color=green>Loaded all data from: </color>" + path);
}
catch (Exception e)
{
Debug.LogWarning("Failed to load data from: " + path);
Debug.LogWarning("Error: " + e.Message);
return;
}
if (jsonDataAsBytes == null)
return;
// convert the byte array to json
string jsonData;
// convert the byte array to json
jsonData = Encoding.ASCII.GetString(jsonDataAsBytes);
// convert to the specified object type
AllGameLocations returnedData;
JsonUtility.FromJsonOverwrite<AllGameLocations>(jsonData, AllGameLocations);
// use returnedData as a normal object now
float firstObjectX = returnedData.Locations[0].xPos;
}
}
Let me know if the Load works, just typed it up untested. Added some error handling as well to assure data exists and the load properly works.

Related

Accessing nested JSON in Processing

I need to extract 3 values from a JSON file. I just managed to get all data but I can't separate them.
The file looks like this:
{
"motionAndDeviceRelated":{
"mOrientation":[0,0,0],
"mLocalVelocity":[0,0,0],
"mWorldVelocity":[0,0,0],
"mAngularVelocity":[0,0,0],
"mLocalAcceleration":[0,0,0],
"mWorldAcceleration":[0,0,0],
"mExtentsCentre":[0,0,0]
}
}
I need to extract in float variables data from mLocalAcceleration.
import http.requests.*;
JSONObject json;
void setup() {
size(600,600);
}
void draw() {
// actually returns something instead of throwing an error, which is progress
long t = System.currentTimeMillis();
GetRequest get = new GetRequest("http://" + "localhost:8180/crest2/v1/api?motionDeviceRelated=true&formatted=true");
get.send();
JSONObject json = parseJSONObject(get.getContent());
println(json);
println(System.currentTimeMillis() - t);
loop();
}
Here is the code that works:
`import http.requests.*;
JSONObject json;
float x;
float y;
float z;
void setup() {
size(800,800);
}
void draw() {
long t = System.currentTimeMillis();
GetRequest get = new GetRequest("http://" + "localhost:8180/crest2/v1/api?motionDeviceRelated=true&formatted=true");
get.send();
JSONObject json = parseJSONObject(get.getContent());
JSONObject motion = json.getJSONObject("motionAndDeviceRelated");
JSONArray acc = motion.getJSONArray("mWorldAcceleration");
x = acc.getFloat(0);
z = acc.getFloat(1);
y = acc.getFloat(2);
println(System.currentTimeMillis() - t);
loop();
}`

Outputting data to JSON file csharp (unity)

I can't figure out how to output a complex data type to JSON.
I constructed a data type which basically holds smaller data types, I have also assigned the data types to new data types so they all seem to have a reference. I have looked into outputting complex data but don't seem to be able to find a problem similar to mine. I will consider appending data but this method will be much simpler if I can output the data type successfully.
Save Data Code
[System.Serializable]
public class SaveData
{
public MapData mapData;
}
[System.Serializable]
public class TileData
{
public List<BlockData> blockData;
}
[System.Serializable]
public class BlockData
{
public Vector3 blockPosition;
public string blockName;
public float blockOrientation;
public int blockLayer;
}
[System.Serializable]
public class MapData
{
public List<TileData> tileData;
}
Get Map Data Method
SaveData GetMapData()
{
mapHeight += mapStartY;
maplength += mapStartX;
int tileCounter = 0;
MapData mapData = new MapData();
SaveData saveData = new SaveData();
List<TileData> tileList = new List<TileData>();
for (float r = mapStartY; r < mapHeight; r++)
{
for(float c = mapStartX; c < maplength; c++)
{
Vector2 currentPosition = new Vector2(c * (blocksize)-(blocksize/2), blocksize * r -(blocksize/2));
GameObject[] currentTile = getObjectID.RayDetectAll(currentPosition);
if (currentTile!= null)
{
//adds a tiledata list here if the tile is occupied.
TileData tileData = new TileData();
//adds a list of blocks here.
List<BlockData> blocks = new List<BlockData>();
for (int i = 0; i < currentTile.Length; i++)
{
BlockData blockData = new BlockData();
GameObject currentBlock = currentTile[i];
blockData.blockPosition = currentBlock.transform.position;
blockData.blockName = currentBlock.name;
blockData.blockOrientation = currentBlock.transform.eulerAngles.z;
blockData.blockLayer = currentBlock.GetComponent<SpriteRenderer>().sortingOrder;
//adds a blockdata to the blocks list
blocks.Add(blockData);
Debug.LogWarning(blockData.blockName);
}
//need to assign tile data and add a new one to the list
tileList.Add(tileData);
//assins the blocks to tile data block data list
tileData.blockData = blocks;
}
else
{
//Debug.LogWarning("warning! no objects found on tile: " + currentPosition);
}
tileCounter++;
}
}
'''
I want the file to output all the data so that i can read the data and reassign it. Right now it outputs the data wrong.
Generally I think this is something that would be commented, but I can't comment yet.
If all you want is to convert an object to Json, could you use JsonUtility.ToJson() as described here?
just to let people know I devised a new method which counted an array of all tiles and assigned it to a data type with an array in it. It managed to load from this format.

Is there in JSON function which dumps JSON array of dictionary into tab separated text files

I have an JSON array as defined below:-
[
{"Name":"Ayush","Age":24,"Job":"Developer"},
{"Name":"Monika","Age":23,"Job":"Developer"},
{"Name":"Chinmay","Age":23,"Job":"Developer"}
]
I want to dump this into text file in following format:-
Name Age Job
Ayush 24 Developer
Monika 23 Developer
Chinmay 23 Developer
Is there any C# function to accomplish the above? If not, how can i achieve it with minimum memory consumption?
Thanks in advance
There is no such built-in function. You may achieve this by reading JTokens from input stream using JsonTextReader and writing their values into another stream. Stream input and output ensures minimal memory footprint.
using (var inputStream = File.OpenRead("input.json"))
using (var streamReader = new StreamReader(inputStream))
using (var jsonTextReader = new JsonTextReader(streamReader))
using (var outputStream = File.OpenWrite("output.csv"))
using (var streamWriter = new StreamWriter(outputStream))
{
var firstItem = true;
while (jsonTextReader.Read())
{
if (jsonTextReader.TokenType == JsonToken.StartObject)
{
var jObject = JObject.ReadFrom(jsonTextReader);
if (firstItem)
{
streamWriter.WriteLine(string.Join("\t",
jObject.Children().Select(c => (c as JProperty).Name)));
firstItem = false;
}
streamWriter.WriteLine(string.Join("\t",
jObject.Values().Select(t => t.ToString())));
}
}
}
Demo: https://dotnetfiddle.net/2fCRa6. (I used MemoryStream and Console instead of input and output file streams in this demo since .NET Fiddle does not allow file IO, but the idea is the same.)
You can create a class with Name, Age and Job as properties.
public class Info{
public string Name { get; set; }
public int Age { get; set; }
public string Job { get; set; }
}
Then in another function use we can use System.Web.Script.Serialization class(to use this class make sure you have referenced System.Web.Extensions in project references). Once done we can use JavaScriptSerializer class and get list of objects from the json data. Then we can iterate over each item and add it two our file with a tab as a delimeter.
public static void WriteDetailsInFile(string jsonData)
{
var list = new JavaScriptSerializer().Deserialize<List<Info>>(jsonData);
using (var streamWriter = File.AppendText("D:MyFile.txt"))
{
streamWriter.WriteLine("Name\tAge\tJob");
foreach (var item in list)
{
streamWriter.WriteLine(item.Name + "\t" + item.Age + "\t" + item.Job);
}
}
}
//driver
public static void Main()
{
string data = #"[
{ ""Name"":""Ayush"",""Age"":24,""Job"":""Developer""},
{ ""Name"":""Monika"",""Age"":23,""Job"":""Developer""},
{ ""Name"":""Chinmay"",""Age"":23,""Job"":""Developer""}
]";
WriteDetailsInFile(data);
}

Storing short[] in a file using Libgdx filehandle

I record some audio using libgdx AudioRecorder which return short[]. I think I´ve converted it into byte[] instead so it can be stored in a file cause I need the audio to be able to playback anytime.
Here´s some variables I use:
final int samples = 44100;
boolean isMono = true;
final short[] data = new short[samples * 5];
final AudioRecorder recorder = Gdx.audio.newAudioRecorder(samples, isMono);
final AudioDevice player = Gdx.audio.newAudioDevice(samples, isMono);
And here I start and play the audio, also I think I´ve converted the short[] into byte[] , correct me if Im wrong.
public void startRecord(){
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Record start:");
recorder.read(data, 0, data.length);
recorder.dispose();
ShortBuffer buffer = BufferUtils.newShortBuffer(2);
buffer.put(data[1]);
}
}).start();
}
public void playRecorded(){
new Thread(new Runnable() {
#Override
public void run() {
player.writeSamples(data, 0, data.length);
player.dispose();
}
}).start();
}
Here´s an example on how I´ve stored byte[] before. But I can´t implement this teqhnique on this method. Bare in mind I need it to be a libgdx solution.
public void onImagePicked(final InputStream stream) {
loading = "Loading";
pending = executor.submit(new AsyncTask<Pixmap>() {
#Override
public Pixmap call() throws Exception {
StreamUtils.copyStream(stream, file.write(false));
final byte[] bytes = file.readBytes();
final Pixmap pix = new Pixmap(bytes, 0, bytes.length);
return pix;
}
});
}
Hi it is actually very simple. You can convert a byte array to short like this:
// get all bytes
byte[] temp = ...
// create short with half the length (short = 2 bytes)
short[] data = new short[temp.length / 2];
// cast a byte array to short array
ByteBuffer.wrap(temp).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(data);
//data now has the short array in it
You can convert a short array to byte like this:
// audio data
short[] data = ...;
//create a byte array to hold the data passed (short = 2 bytes)
byte[] temp = new byte[data.length * 2];
// cast a short array to byte array
ByteBuffer.wrap(temp).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(data);
// temp now has the byte array
Sample project
I created a sample project in github that you can clone to see how this works.
Sample project here
However this is the Game class for the sample project if you only want to take a quick look at it:
package com.leonziyo.recording;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.AudioDevice;
import com.badlogic.gdx.audio.AudioRecorder;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.GdxRuntimeException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class MainGame extends ApplicationAdapter {
boolean recordTurn = true;
final int samples = 44100;
boolean isMono = true, recording = false, playing = false;
#Override
public void create () {}
#Override
public void render () {
/*Changing the color just to know when it is done recording or playing audio (optional)*/
if(recording)
Gdx.gl.glClearColor(1, 0, 0, 1);
else if(playing)
Gdx.gl.glClearColor(0, 1, 0, 1);
else
Gdx.gl.glClearColor(0, 0, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// We trigger recording and playing with touch for simplicity
if(Gdx.input.justTouched()) {
if(recordTurn)
recordToFile("sound.bin", 3); //pass file name and number of seconds to record
else
playFile("sound.bin"); //file name to play
recordTurn = !recordTurn;
}
}
#Override
public void dispose() {
}
private void recordToFile(final String filename, final int seconds) {
//Start a new thread to do the recording, because it will block and render won't be called if done in the main thread
new Thread(new Runnable() {
#Override
public void run() {
try {
recording = true;
short[] data = new short[samples * seconds];
AudioRecorder recorder = Gdx.audio.newAudioRecorder(samples, isMono);
recorder.read(data, 0, data.length);
recorder.dispose();
saveAudioToFile(data, filename);
}
catch(GdxRuntimeException e) {
Gdx.app.log("test", e.getMessage());
}
finally {
recording = false;
}
}
}).start();
}
private void playFile(final String filename) {
//Start a new thread to play the file, because it will block and render won't be called if done in the main thread
new Thread(new Runnable() {
#Override
public void run() {
try {
playing = true;
short[] data = getAudioDataFromFile(filename); //get audio data from file
AudioDevice device = Gdx.audio.newAudioDevice(samples, isMono);
device.writeSamples(data, 0, data.length);
device.dispose();
}
catch(GdxRuntimeException e) {
Gdx.app.log("test", e.getMessage());
}
finally {
playing = false;
}
}
}).start();
}
private short[] getAudioDataFromFile(String filename) {
FileHandle file = Gdx.files.local(filename);
byte[] temp = file.readBytes(); // get all bytes from file
short[] data = new short[temp.length / 2]; // create short with half the length (short = 2 bytes)
ByteBuffer.wrap(temp).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(data); // cast a byte array to short array
return data;
}
private void saveAudioToFile(short[] data, String filename) {
byte[] temp = new byte[data.length * 2]; //create a byte array to hold the data passed (short = 2 bytes)
ByteBuffer.wrap(temp).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(data); // cast a short array to byte array
FileHandle file = Gdx.files.local(filename);
file.writeBytes(temp, false); //save bytes to file
}
}
Don't forget to add permission in case you are writing to external storage and permission for audio recording:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Facing issues while printing on Dot Matrix Printer

I am developing a desktop application in java swing; in which I need to take a bill print on dot matrix printer, the print will be having name, address and table which will be having item, qty, price…etc, which should be printed as per their x, y positions on paper, font stored in database .
But in print there is issue of overlapping/attaching letters if I use the following code:
class BillPrint implements ActionListener, Printable
{
PrintMngt PM=new PrintMngt();
public int print(Graphics gx, PageFormat pf, int page) throws PrinterException {
if (page>0){return NO_SUCH_PAGE;}
Graphics2D g = (Graphics2D)gx; //Cast to Graphics2D object
g.translate(pf.getImageableX(), pf.getImageableY());
Vector<Vector<Object>> data =PM.getvarientDetail(printID);
for (int i = 0; i <data.size(); i++) {
if(data.get(i).get(3).toString().equalsIgnoreCase("DYNAMIC"))
{
String bill_no=textField_Trans.getText();
int TblH,TblL;
Vector<String> Tbl_HL=PM.getTblHieghtNoLline(printID);
//PRINT_ID0, QUERY_STATIC1, OBJECT_NAME2, QUERY_TYPE3, X4, Y5, WIDTH6,
//ALIGN7, FONT8, F_SIZE9, F_STYLE10, SECTION11, LOOPES_NO12, OBJ_FORMAT13, VARIANT_ID14
TblH=Integer.parseInt(Tbl_HL.get(0).toString());
TblL=Integer.parseInt(Tbl_HL.get(1).toString());
int x=Integer.parseInt(data.get(i).get(4).toString());
int y=Integer.parseInt(data.get(i).get(5).toString());
String fName=data.get(i).get(8).toString();
int fSize=Integer.parseInt(data.get(i).get(9).toString());
String fStyle=data.get(i).get(10).toString();
Font font=null;
if(fStyle.equalsIgnoreCase("Plain"))
{
font = new Font(fName,Font.PLAIN, fSize);
}
else if(fStyle.equalsIgnoreCase("Bold"))
{
font = new Font(fName,Font.BOLD, fSize);
}
else if(fStyle.equalsIgnoreCase("Italic"))
{
font = new Font(fName,Font.ITALIC, fSize);
}
else if(fStyle.equalsIgnoreCase("Bold Italic"))
{
font = new Font(fName,Font.BOLD+ Font.ITALIC, fSize);
}
System.out.println("Myqry"+data.get(i).get(1).toString());
Vector<String> Query_Static=PM.getQuery_Static(data.get(i).get(1).toString(),bill_no);
for (int j = NoOfProd; j < Query_Static.size(); j++) {
g.drawString(Query_Static.get(j).toString(),x,y);
y=y+TblH/TblL;
g.setFont(font);
}
}
}
return PAGE_EXISTS; //Page exists (offsets start at zero!)
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
int ProductCnt= PM.getNoProduct(textField_Trans.getText().toString());//no. of products under given billno
int TableLine=PM.getTblNoLline(printID);//no. of lines to print
System.out.println("No of TableLines="+TableLine);
System.out.println("No of Product="+ProductCnt);
for (int i = 0; i <(TableLine/ProductCnt); i++)
{
job.print();
NoOfProd=NoOfProd+TableLine;
}
NoOfProd=0;
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}//end actionPerformed
}//end BillPrint
I have also tried with writing data to .txt file and then printing it. Here output is proper i.e letters are not overlapping , but here in this method I m not able to give proper positions for my data. Following method I used for this:
private void printData(){
File output = new File("E:\\PrintFile1.txt");
output.setWritable(true);
String billNo="B1000", patient = "ABC";
try
{
BufferedWriter out = new BufferedWriter(new FileWriter(output));
out.write(billNo + "\n");
out.write(patient + "\n" );
out.write("\n");
out.write("\n");
out.close();
}
catch (java.io.IOException e)
{
System.out.println("Failed to write Output");
}
FileInputStream textStream = null;
try
{
textStream = new FileInputStream("E:\\PrintFile1.txt");
}
catch (java.io.FileNotFoundException e)
{
System.out.println("Error trying to find the print file.");
}
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
Doc mydoc = new SimpleDoc(textStream, flavor, null);
PrintService printer = PrintServiceLookup.lookupDefaultPrintService();
DocPrintJob printJob = printer.createPrintJob();
try
{
printJob.print(mydoc, null);
}
catch (javax.print.PrintException e)
{
JOptionPane.showMessageDialog(this, "Error occured while attempting to print.", "Error!", JOptionPane.ERROR_MESSAGE);
}
}
Basically for the issue in the letters i just add one space for each character in the string
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
public class Print implements Printable {
/* Just add one space for all charaters */
String numero = "Numero Nro :";
String numeroreplace = numero.replaceAll(".(?=.)", "$0 ");
public Print() {
super();
}
/* The font for you string */
public int print(Graphics g,PageFormat pf, int page) throws PrinterException{
Font textFont = new Font(Font.SANS_SERIF,Font.PLAIN,8);
/* To set the position, you can use for or while if u need it. */
g.setFont(textFont);
g.drawString(numeroreplace,350,150);
}
}
Finally you need to copy all this code just add one space for all characters in code.
Note : you must be call from yor main program.