/**
* @file GMXFileReader.java
* @brief Class implementing a GMX file reader.
*
* @section License
*
* Copyright (C) 2013-2015 Robert B. Colton
* This file is a part of the LateralGM IDE.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
package org.lateralgm.file;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import javax.imageio.ImageIO;
import javax.swing.JProgressBar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.lateralgm.components.impl.ResNode;
import org.lateralgm.file.ProjectFile.ResourceHolder;
import org.lateralgm.file.iconio.ICOFile;
import org.lateralgm.main.LGM;
import org.lateralgm.main.Util;
import org.lateralgm.messages.Messages;
import org.lateralgm.resources.Background;
import org.lateralgm.resources.Background.PBackground;
import org.lateralgm.resources.Constants;
import org.lateralgm.resources.Extension;
import org.lateralgm.resources.ExtensionPackages;
import org.lateralgm.resources.Font;
import org.lateralgm.resources.Font.PFont;
import org.lateralgm.resources.GameInformation;
import org.lateralgm.resources.GameInformation.PGameInformation;
import org.lateralgm.resources.GameSettings;
import org.lateralgm.resources.GameSettings.PGameSettings;
import org.lateralgm.resources.GmObject;
import org.lateralgm.resources.GmObject.PGmObject;
import org.lateralgm.resources.Include;
import org.lateralgm.resources.Path;
import org.lateralgm.resources.Path.PPath;
import org.lateralgm.resources.Resource;
import org.lateralgm.resources.Room;
import org.lateralgm.resources.Room.PRoom;
import org.lateralgm.resources.Script;
import org.lateralgm.resources.Script.PScript;
import org.lateralgm.resources.Shader;
import org.lateralgm.resources.Shader.PShader;
import org.lateralgm.resources.Sound;
import org.lateralgm.resources.Sound.PSound;
import org.lateralgm.resources.Sprite;
import org.lateralgm.resources.Sprite.PSprite;
import org.lateralgm.resources.Timeline;
import org.lateralgm.resources.library.LibAction;
import org.lateralgm.resources.library.LibArgument;
import org.lateralgm.resources.library.LibManager;
import org.lateralgm.resources.sub.Action;
import org.lateralgm.resources.sub.ActionContainer;
import org.lateralgm.resources.sub.Argument;
import org.lateralgm.resources.sub.BackgroundDef;
import org.lateralgm.resources.sub.BackgroundDef.PBackgroundDef;
import org.lateralgm.resources.sub.Constant;
import org.lateralgm.resources.sub.Event;
import org.lateralgm.resources.sub.GlyphMetric;
import org.lateralgm.resources.sub.GlyphMetric.PGlyphMetric;
import org.lateralgm.resources.sub.Instance;
import org.lateralgm.resources.sub.Instance.PInstance;
import org.lateralgm.resources.sub.MainEvent;
import org.lateralgm.resources.sub.Moment;
import org.lateralgm.resources.sub.PathPoint;
import org.lateralgm.resources.sub.ShapePoint;
import org.lateralgm.resources.sub.Tile;
import org.lateralgm.resources.sub.Tile.PTile;
import org.lateralgm.resources.sub.View;
import org.lateralgm.resources.sub.View.PView;
import org.lateralgm.util.PropertyMap;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;
// TODO: Possibly rewrite from a DOM parser to a SAX parser,
// because SAX is light weight faster and uses less memory,
// DOM reads the whole thing into memory and then parses it.
// There is a downside to SAX such as incompatibility with UTF-8
public final class GMXFileReader
{
public static final String STUPID_SHADER_MARKER =
"//######################_==_YOYO_SHADER_MARKER_==_######################@~"; //$NON-NLS-1$
private static DocumentBuilderFactory documentBuilderFactory;
private static DocumentBuilder documentBuilder;
private GMXFileReader()
{
}
static Queue<PostponedRef> postpone = new LinkedList<PostponedRef>();
static interface PostponedRef
{
boolean invoke();
}
static class DefaultPostponedRef<K extends Enum<K>> implements PostponedRef
{
ResourceList<?> list;
String name;
PropertyMap<K> p;
K key;
DefaultPostponedRef(ResourceList<?> list, PropertyMap<K> p, K key, String name)
{
this.list = list;
this.p = p;
this.key = key;
this.name = name;
}
public boolean invoke()
{
Resource<?,?> temp = list.get(name);
if (temp != null) p.put(key,temp.reference);
return temp != null;
}
}
private static Document parseDocumentUnchecked(ProjectFile f, String path) throws GmFormatException
{
Document doc = null;
try
{
doc = documentBuilder.parse(path);
}
catch (SAXException e)
{
throw new GmFormatException(f, "failed to parse: " + path, e);
}
catch (IOException e)
{
throw new GmFormatException(f, "failed to read: " + path, e);
}
return doc;
}
private static Document parseDocumentChecked(ProjectFile f, String path)
{
Document doc = null;
try
{
doc = parseDocumentUnchecked(f, path);
}
catch (GmFormatException e)
{
LGM.showDefaultExceptionHandler(e);
}
return doc;
}
//Workaround for Parameter limit
private static class ProjectFileContext
{
ProjectFile f;
Document in;
RefList<Timeline> timeids;
RefList<GmObject> objids;
RefList<Room> rmids;
public ProjectFileContext(ProjectFile f, Document d, RefList<Timeline> timeids,
RefList<GmObject> objids, RefList<Room> rmids)
{
this.f = f;
this.in = d;
this.timeids = timeids;
this.objids = objids;
this.rmids = rmids;
}
public ProjectFileContext copy()
{
return new ProjectFileContext(f,in,timeids,objids,rmids);
}
}
private static GmFormatException versionError(ProjectFile f, String error, String res, int ver)
{
return versionError(f,error,res,0,ver);
}
private static GmFormatException versionError(ProjectFile f, String error, String res, int i,
int ver)
{
return new GmFormatException(f,Messages.format(
"ProjectFileReader.ERROR_UNSUPPORTED",Messages.format(//$NON-NLS-1$
"ProjectFileReader." + error,Messages.getString("LGM." + res),i),ver)); //$NON-NLS-1$ //$NON-NLS-2$
}
public static void readProjectFile(InputStream stream, ProjectFile file, URI uri, ResNode root)
throws GmFormatException
{
readProjectFile(stream,file,uri,root,null);
}
public static void readProjectFile(InputStream stream, ProjectFile file, URI uri, ResNode root,
Charset forceCharset) throws GmFormatException
{
file.format = ProjectFile.FormatFlavor.getVersionFlavor(1200); // GMX will have version numbers in the future
if (documentBuilderFactory == null)
documentBuilderFactory = DocumentBuilderFactory.newInstance();
if (documentBuilder == null)
try
{
documentBuilder = documentBuilderFactory.newDocumentBuilder();
}
catch (ParserConfigurationException e1)
{
throw new GmFormatException(file,e1);
}
RefList<Timeline> timeids = new RefList<Timeline>(Timeline.class); // timeline ids
RefList<GmObject> objids = new RefList<GmObject>(GmObject.class); // object ids
RefList<Room> rmids = new RefList<Room>(Room.class); // room id
long startTime = System.currentTimeMillis();
try
{
Document document = GMXFileReader.parseDocumentUnchecked(file, uri.toString());
ProjectFileContext c = new ProjectFileContext(file,document,timeids,objids,rmids);
JProgressBar progressBar = LGM.getProgressDialogBar();
progressBar.setMaximum(160);
LGM.setProgressTitle(Messages.getString("ProgressDialog.GMX_LOADING")); //$NON-NLS-1$
LGM.setProgress(0,Messages.getString("ProgressDialog.SPRITES")); //$NON-NLS-1$
readSprites(c,root);
LGM.setProgress(10,Messages.getString("ProgressDialog.SOUNDS")); //$NON-NLS-1$
readSounds(c,root);
LGM.setProgress(20,Messages.getString("ProgressDialog.BACKGROUNDS")); //$NON-NLS-1$
readBackgrounds(c,root);
LGM.setProgress(30,Messages.getString("ProgressDialog.PATHS")); //$NON-NLS-1$
readPaths(c,root);
LGM.setProgress(40,Messages.getString("ProgressDialog.SCRIPTS")); //$NON-NLS-1$
readScripts(c,root);
LGM.setProgress(50,Messages.getString("ProgressDialog.SHADERS")); //$NON-NLS-1$
readShaders(c,root);
LGM.setProgress(60,Messages.getString("ProgressDialog.FONTS")); //$NON-NLS-1$
readFonts(c,root);
LGM.setProgress(70,Messages.getString("ProgressDialog.TIMELINES")); //$NON-NLS-1$
readTimelines(c,root);
LGM.setProgress(80,Messages.getString("ProgressDialog.OBJECTS")); //$NON-NLS-1$
readGmObjects(c,root);
LGM.setProgress(90,Messages.getString("ProgressDialog.ROOMS")); //$NON-NLS-1$
readRooms(c,root);
LGM.setProgress(100,Messages.getString("ProgressDialog.INCLUDEFILES")); //$NON-NLS-1$
readIncludedFiles(c,root);
LGM.setProgress(110,Messages.getString("ProgressDialog.EXTENSIONS")); //$NON-NLS-1$
readExtensions(c,root);
LGM.setProgress(120,Messages.getString("ProgressDialog.CONSTANTS")); //$NON-NLS-1$
readDefaultConstants(c,root);
LGM.setProgress(130,Messages.getString("ProgressDialog.GAMEINFORMATION")); //$NON-NLS-1$
readGameInformation(c,root);
LGM.setProgress(140,Messages.getString("ProgressDialog.SETTINGS")); //$NON-NLS-1$
readConfigurations(c,root);
LGM.setProgress(150,Messages.getString("ProgressDialog.PACKAGES")); //$NON-NLS-1$
readPackages(c,root);
LGM.setProgress(160,Messages.getString("ProgressDialog.POSTPONED")); //$NON-NLS-1$
// All resources read, now we can invoke our postponed references.
for (PostponedRef i : postpone)
i.invoke();
LGM.setProgress(160,Messages.getString("ProgressDialog.FINISHED")); //$NON-NLS-1$
System.out.println(Messages.format("ProjectFileReader.LOADTIME",System.currentTimeMillis() //$NON-NLS-1$
- startTime));
}
catch (Exception e)
{
if ((e instanceof GmFormatException)) throw (GmFormatException) e;
throw new GmFormatException(file,e);
}
finally
{
try
{
if (stream != null)
{
stream.close();
stream = null;
}
}
catch (IOException ex)
{
String key = Messages.getString("GmFileReader.ERROR_CLOSEFAILED"); //$NON-NLS-1$
throw new GmFormatException(file,key);
}
}
}
private static void readConfigurations(ProjectFileContext c, ResNode root)
{
Document in = c.in;
NodeList configNodes = in.getElementsByTagName("Configs").item(0).getChildNodes(); //$NON-NLS-1$
// clear the old/default ones
c.f.gameSettings.clear();
for (int i = 0; i < configNodes.getLength(); i++)
{
Node cNode = configNodes.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
if (cname.toLowerCase().equals("configs")) //$NON-NLS-1$
{
continue;
}
else if (cname.toLowerCase().equals("config")) //$NON-NLS-1$
{
GameSettings gSet = new GameSettings();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
gSet.setName(fileName);
c.f.gameSettings.add(gSet);
PropertyMap<PGameSettings> pSet = gSet.properties;
String path = c.f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document setdoc = GMXFileReader.parseDocumentChecked(c.f, path + ".config.gmx"); //$NON-NLS-1$
if (setdoc == null) continue;
pSet.put(
PGameSettings.START_FULLSCREEN,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_fullscreen").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.ALLOW_WINDOW_RESIZE,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_sizeable").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.ALWAYS_ON_TOP,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_stayontop").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.ABORT_ON_ERROR,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_aborterrors").item(0).getTextContent())); //$NON-NLS-1$
// TODO: This value is stored using the Windows native dialog's name for the color value, ie
// "clBlack" or "clWhite" meaning black and white respectively. If the user chooses a custom
// defined color in the dialog, then the value is in the hexadecimal form "$HHHHHHHH" using
// a dollar sign instead of a hash sign as a normal hex color value does in other places in
// the same configuration file.
// This will not be compatible if they ever try to port their IDE to other platforms.
//gSet.put(PGameSettings.COLOR_OUTSIDE_ROOM, Integer.parseInt(setdoc.getElementsByTagName("option_windowcolor").item(0).getTextContent()));
pSet.put(
PGameSettings.DISABLE_SCREENSAVERS,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_noscreensaver").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.DISPLAY_CURSOR,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_showcursor").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.DISPLAY_ERRORS,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_displayerrors").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.DONT_DRAW_BORDER,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_noborder").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.DONT_SHOW_BUTTONS,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_nobuttons").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.ERROR_ON_ARGS,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_argumenterrors").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.FREEZE_ON_LOSE_FOCUS,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_freeze").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.COLOR_DEPTH,
ProjectFile.GS_DEPTHS[Integer.parseInt(setdoc.getElementsByTagName("option_colordepth").item( //$NON-NLS-1$
0).getTextContent())]);
pSet.put(
PGameSettings.FREQUENCY,
ProjectFile.GS_FREQS[Integer.parseInt(setdoc.getElementsByTagName("option_frequency").item( //$NON-NLS-1$
0).getTextContent())]);
pSet.put(
PGameSettings.RESOLUTION,
ProjectFile.GS_RESOLS[Integer.parseInt(setdoc.getElementsByTagName("option_resolution").item( //$NON-NLS-1$
0).getTextContent())]);
pSet.put(
PGameSettings.SET_RESOLUTION,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_changeresolution").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.GAME_PRIORITY,
ProjectFile.GS_PRIORITIES[Integer.parseInt(setdoc.getElementsByTagName(
"option_priority").item(0).getTextContent())]); //$NON-NLS-1$
// For some odd reason these two settings are combined together.
// 2147483649 - Both
// 2147483648 - Software Vertex Processing only
// 1 - Synchronization Only
// 0 - None
long syncvertex = Long.parseLong(setdoc.getElementsByTagName("option_sync_vertex").item(0).getTextContent()); //$NON-NLS-1$
gSet.put(PGameSettings.USE_SYNCHRONIZATION,(syncvertex == 2147483649L || syncvertex == 1));
pSet.put(PGameSettings.FORCE_SOFTWARE_VERTEX_PROCESSING,
(syncvertex == 2147483649L || syncvertex == 2147483648L));
pSet.put(
PGameSettings.LET_ESC_END_GAME,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_closeesc").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.INTERPOLATE,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_interpolate").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(PGameSettings.SCALING,
Integer.parseInt(setdoc.getElementsByTagName("option_scale").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.TREAT_CLOSE_AS_ESCAPE,
Boolean.parseBoolean(setdoc.getElementsByTagName("option_closeesc").item(0).getTextContent())); //$NON-NLS-1$
String changed = setdoc.getElementsByTagName("option_lastchanged").item(0).getTextContent(); //$NON-NLS-1$
if (changed != "")
{
pSet.put(PGameSettings.LAST_CHANGED,Double.parseDouble(changed));
}
// TODO: Could not find these properties in GMX
//gSet.put(PGameSettings.BACK_LOAD_BAR,
// Boolean.parseBoolean(setdoc.getElementsByTagName("option_stayontop").item(0).getTextContent()));
//gSet.put(PGameSettings.FRONT_LOAD_BAR,
// Boolean.parseBoolean(setdoc.getElementsByTagName("option_showcursor").item(0).getTextContent()));
String icopath = c.f.getDirectory() + '/'
+ setdoc.getElementsByTagName("option_windows_game_icon").item(0).getTextContent(); //$NON-NLS-1$
try
{
pSet.put(PGameSettings.GAME_ICON,new ICOFile(icopath));
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "failed to read: " + icopath, e));
}
pSet.put(PGameSettings.GAME_ID,
Integer.parseInt(setdoc.getElementsByTagName("option_gameid").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.GAME_GUID,
HexBin.decode(setdoc.getElementsByTagName("option_gameguid").item(0).getTextContent().replace( //$NON-NLS-1$
"-","").replace("{","").replace("}","")));
pSet.put(PGameSettings.AUTHOR,
setdoc.getElementsByTagName("option_author").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(PGameSettings.VERSION,
setdoc.getElementsByTagName("option_version").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(PGameSettings.INFORMATION,
setdoc.getElementsByTagName("option_information").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(PGameSettings.COMPANY,
setdoc.getElementsByTagName("option_version_company").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(PGameSettings.COPYRIGHT,
setdoc.getElementsByTagName("option_version_copyright").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(PGameSettings.DESCRIPTION,
setdoc.getElementsByTagName("option_version_description").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(PGameSettings.PRODUCT,
setdoc.getElementsByTagName("option_version_product").item(0).getTextContent()); //$NON-NLS-1$
pSet.put(
PGameSettings.VERSION_BUILD,
Integer.parseInt(setdoc.getElementsByTagName("option_version_build").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.VERSION_MAJOR,
Integer.parseInt(setdoc.getElementsByTagName("option_version_major").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.VERSION_MINOR,
Integer.parseInt(setdoc.getElementsByTagName("option_version_minor").item(0).getTextContent())); //$NON-NLS-1$
pSet.put(
PGameSettings.VERSION_RELEASE,
Integer.parseInt(setdoc.getElementsByTagName("option_version_release").item(0).getTextContent())); //$NON-NLS-1$
Node cnstNode = setdoc.getElementsByTagName("ConfigConstants").item(0); //$NON-NLS-1$
// If there is a constant section
if (cnstNode != null)
{
NodeList cnstsList = cnstNode.getChildNodes();
boolean found = false;
for (int ic = 0; ic < cnstsList.getLength(); ic++)
{
cnstNode = cnstsList.item(ic);
String cnstName = cnstNode.getNodeName();
if (cnstName.toLowerCase().equals("#text")) //$NON-NLS-1$
{
continue;
}
else if (cnstName.toLowerCase().equals("constants")) //$NON-NLS-1$
{
found = true;
break;
}
}
if (found) readConstants(gSet.constants,cnstNode);
}
}
}
ResNode node = new ResNode("Game Settings",ResNode.STATUS_SECONDARY,GameSettings.class,null);
root.add(node);
}
private static void iterateSprites(ProjectFileContext c, NodeList sprList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < sprList.getLength(); i++)
{
Node cNode = sprList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("sprites")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Sprite.class,null);
node.add(rnode);
iterateSprites(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("sprite")) //$NON-NLS-1$
{
Sprite spr = f.resMap.getList(Sprite.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
spr.setName(fileName);
rnode = new ResNode(spr.getName(),ResNode.STATUS_SECONDARY,Sprite.class,spr.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document sprdoc = GMXFileReader.parseDocumentChecked(f, path + ".sprite.gmx"); //$NON-NLS-1$
if (sprdoc == null) continue;
spr.put(PSprite.ORIGIN_X,
Integer.parseInt(sprdoc.getElementsByTagName("xorig").item(0).getTextContent())); //$NON-NLS-1$
spr.put(PSprite.ORIGIN_Y,
Integer.parseInt(sprdoc.getElementsByTagName("yorigin").item(0).getTextContent())); //$NON-NLS-1$
spr.put(
PSprite.SHAPE,
ProjectFile.SPRITE_MASK_SHAPE[Integer.parseInt(sprdoc.getElementsByTagName("colkind").item( //$NON-NLS-1$
0).getTextContent())]);
spr.put(PSprite.SEPARATE_MASK,
Integer.parseInt(sprdoc.getElementsByTagName("sepmasks").item(0).getTextContent()) != 0); //$NON-NLS-1$
spr.put(
PSprite.BB_MODE,
ProjectFile.SPRITE_BB_MODE[Integer.parseInt(sprdoc.getElementsByTagName("bboxmode").item( //$NON-NLS-1$
0).getTextContent())]);
spr.put(PSprite.BB_LEFT,
Integer.parseInt(sprdoc.getElementsByTagName("bbox_left").item(0).getTextContent())); //$NON-NLS-1$
spr.put(PSprite.BB_RIGHT,
Integer.parseInt(sprdoc.getElementsByTagName("bbox_right").item(0).getTextContent())); //$NON-NLS-1$
spr.put(PSprite.BB_TOP,
Integer.parseInt(sprdoc.getElementsByTagName("bbox_top").item(0).getTextContent())); //$NON-NLS-1$
spr.put(PSprite.BB_BOTTOM,
Integer.parseInt(sprdoc.getElementsByTagName("bbox_bottom").item(0).getTextContent())); //$NON-NLS-1$
spr.put(PSprite.ALPHA_TOLERANCE,
Integer.parseInt(sprdoc.getElementsByTagName("coltolerance").item(0).getTextContent())); //$NON-NLS-1$
spr.put(PSprite.TILE_HORIZONTALLY,
Integer.parseInt(sprdoc.getElementsByTagName("HTile").item(0).getTextContent()) != 0); //$NON-NLS-1$
spr.put(PSprite.TILE_VERTICALLY,
Integer.parseInt(sprdoc.getElementsByTagName("VTile").item(0).getTextContent()) != 0); //$NON-NLS-1$
// TODO: Read texture groups
spr.put(PSprite.FOR3D,
Integer.parseInt(sprdoc.getElementsByTagName("For3D").item(0).getTextContent()) != 0); //$NON-NLS-1$
// TODO: Just extra metadata stored in the GMX by studio
//int width = Integer.parseInt(sprdoc.getElementsByTagName("width").item(0).getTextContent());
//int height = Integer.parseInt(sprdoc.getElementsByTagName("height").item(0).getTextContent());
// iterate and load the sprites subimages
NodeList frList = sprdoc.getElementsByTagName("frame"); //$NON-NLS-1$
path = f.getDirectory() + "/sprites/"; //$NON-NLS-1$
for (int ii = 0; ii < frList.getLength(); ii++)
{
Node fnode = frList.item(ii);
BufferedImage img = null;
File imgfile = new File(path + Util.getPOSIXPath(fnode.getTextContent()));
if (imgfile.exists())
{
try
{
img = ImageIO.read(imgfile);
spr.subImages.add(img);
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "failed to read: " + imgfile.getAbsolutePath(), e));
}
}
}
}
}
}
private static void readSprites(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Sprite.class),ResNode.STATUS_PRIMARY,
Sprite.class,null);
root.add(node);
NodeList sprList = in.getElementsByTagName("sprites"); //$NON-NLS-1$
if (sprList.getLength() > 0)
{
sprList = sprList.item(0).getChildNodes();
}
else
{
return;
}
iterateSprites(c,sprList,node);
}
private static void iterateSounds(ProjectFileContext c, NodeList sndList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < sndList.getLength(); i++)
{
Node cNode = sndList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("sounds")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Sound.class,null);
node.add(rnode);
iterateSounds(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("sound")) //$NON-NLS-1$
{
Sound snd = f.resMap.getList(Sound.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
snd.setName(fileName);
rnode = new ResNode(snd.getName(),ResNode.STATUS_SECONDARY,Sound.class,snd.reference);
node.add(rnode);
snd.setNode(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document snddoc = GMXFileReader.parseDocumentChecked(f, path + ".sound.gmx"); //$NON-NLS-1$
if (snddoc == null) continue;
snd.put(PSound.FILE_NAME,snddoc.getElementsByTagName("origname").item(0).getTextContent()); //$NON-NLS-1$
// GMX uses double nested tags for volume, bit rate, sample rate, type, and bit depth
// There is a special clause here, every one of those tags after volume, the nested
// tag is singular, where its parent is plural.
NodeList nl = snddoc.getElementsByTagName("volume"); //$NON-NLS-1$
snd.put(PSound.VOLUME,Double.parseDouble(nl.item(nl.getLength() - 1).getTextContent()));
snd.put(PSound.PAN,
Double.parseDouble(snddoc.getElementsByTagName("pan").item(0).getTextContent())); //$NON-NLS-1$
snd.put(PSound.BIT_RATE,
Integer.parseInt(snddoc.getElementsByTagName("bitRate").item(0).getTextContent())); //$NON-NLS-1$
snd.put(PSound.SAMPLE_RATE,
Integer.parseInt(snddoc.getElementsByTagName("sampleRate").item(0).getTextContent())); //$NON-NLS-1$
int sndtype = Integer.parseInt(snddoc.getElementsByTagName("type").item(0).getTextContent()); //$NON-NLS-1$
snd.put(PSound.TYPE, ProjectFile.SOUND_TYPE[sndtype]);
snd.put(PSound.BIT_DEPTH,
Integer.parseInt(snddoc.getElementsByTagName("bitDepth").item(0).getTextContent())); //$NON-NLS-1$
snd.put(PSound.PRELOAD,
Integer.parseInt(snddoc.getElementsByTagName("preload").item(0).getTextContent()) != 0); //$NON-NLS-1$
snd.put(PSound.COMPRESSED,
Integer.parseInt(snddoc.getElementsByTagName("compressed").item(0).getTextContent()) != 0); //$NON-NLS-1$
snd.put(PSound.STREAMED,
Integer.parseInt(snddoc.getElementsByTagName("streamed").item(0).getTextContent()) != 0); //$NON-NLS-1$
snd.put(PSound.DECOMPRESS_ON_LOAD,
Integer.parseInt(snddoc.getElementsByTagName("uncompressOnLoad").item(0).getTextContent()) != 0); //$NON-NLS-1$
int sndkind = Integer.parseInt(snddoc.getElementsByTagName("kind").item(0).getTextContent()); //$NON-NLS-1$
snd.put(PSound.KIND,ProjectFile.SOUND_KIND[sndkind]);
snd.put(PSound.FILE_TYPE,snddoc.getElementsByTagName("extension").item(0).getTextContent()); //$NON-NLS-1$
NodeList data = snddoc.getElementsByTagName("data"); //$NON-NLS-1$
if (data.item(0) != null)
{
String fname = data.item(0).getTextContent();
snd.data = Util.readBinaryFile(f.getDirectory() + "/sound/audio/" + fname); //$NON-NLS-1$
}
}
}
}
private static void readSounds(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Sound.class),ResNode.STATUS_PRIMARY,
Sound.class,null);
root.add(node);
NodeList sndList = in.getElementsByTagName("sounds"); //$NON-NLS-1$
if (sndList.getLength() > 0)
{
sndList = sndList.item(0).getChildNodes();
}
else
{
return;
}
iterateSounds(c,sndList,node);
}
private static void iterateBackgrounds(ProjectFileContext c, NodeList bkgList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < bkgList.getLength(); i++)
{
Node cNode = bkgList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("backgrounds")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Background.class,null);
node.add(rnode);
iterateBackgrounds(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("background")) //$NON-NLS-1$
{
Background bkg = f.resMap.getList(Background.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
bkg.setName(fileName);
rnode = new ResNode(bkg.getName(),ResNode.STATUS_SECONDARY,Background.class,bkg.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document bkgdoc = GMXFileReader.parseDocumentChecked(f, path + ".background.gmx"); //$NON-NLS-1$
if (bkgdoc == null) continue;
bkg.put(PBackground.USE_AS_TILESET,
Integer.parseInt(bkgdoc.getElementsByTagName("istileset").item(0).getTextContent()) != 0); //$NON-NLS-1$
bkg.put(PBackground.TILE_WIDTH,
Integer.parseInt(bkgdoc.getElementsByTagName("tilewidth").item(0).getTextContent())); //$NON-NLS-1$
bkg.put(PBackground.TILE_HEIGHT,
Integer.parseInt(bkgdoc.getElementsByTagName("tileheight").item(0).getTextContent())); //$NON-NLS-1$
bkg.put(PBackground.H_OFFSET,
Integer.parseInt(bkgdoc.getElementsByTagName("tilexoff").item(0).getTextContent())); //$NON-NLS-1$
bkg.put(PBackground.V_OFFSET,
Integer.parseInt(bkgdoc.getElementsByTagName("tileyoff").item(0).getTextContent())); //$NON-NLS-1$
bkg.put(PBackground.H_SEP,
Integer.parseInt(bkgdoc.getElementsByTagName("tilehsep").item(0).getTextContent())); //$NON-NLS-1$
bkg.put(PBackground.V_SEP,
Integer.parseInt(bkgdoc.getElementsByTagName("tilevsep").item(0).getTextContent())); //$NON-NLS-1$
bkg.put(PBackground.TILE_HORIZONTALLY,
Integer.parseInt(bkgdoc.getElementsByTagName("HTile").item(0).getTextContent()) != 0); //$NON-NLS-1$
bkg.put(PBackground.TILE_VERTICALLY,
Integer.parseInt(bkgdoc.getElementsByTagName("VTile").item(0).getTextContent()) != 0); //$NON-NLS-1$
// TODO: Read texture groups
bkg.put(PBackground.FOR3D,
Integer.parseInt(bkgdoc.getElementsByTagName("For3D").item(0).getTextContent()) != 0); //$NON-NLS-1$
// NOTE: Just extra metadata stored in the GMX by studio
//int width = Integer.parseInt(bkgdoc.getElementsByTagName("width").item(0).getTextContent());
//int height = Integer.parseInt(bkgdoc.getElementsByTagName("height").item(0).getTextContent());
path = f.getDirectory() + "/background/"; //$NON-NLS-1$
Node fnode = bkgdoc.getElementsByTagName("data").item(0); //$NON-NLS-1$
BufferedImage img = null;
File imgfile = new File(path + Util.getPOSIXPath(fnode.getTextContent()));
if (imgfile.exists())
{
try
{
img = ImageIO.read(imgfile);
bkg.setBackgroundImage(img);
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "failed to read: " + imgfile.getAbsolutePath(), e));
}
}
}
}
}
private static void readBackgrounds(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Background.class),
ResNode.STATUS_PRIMARY,Background.class,null);
root.add(node);
NodeList bkgList = in.getElementsByTagName("backgrounds"); //$NON-NLS-1$
if (bkgList.getLength() > 0)
{
bkgList = bkgList.item(0).getChildNodes();
}
else
{
return;
}
iterateBackgrounds(c,bkgList,node);
}
private static void iteratePaths(ProjectFileContext c, NodeList pthList, ResNode node)
{
final ProjectFile f = c.f;
for (int i = 0; i < pthList.getLength(); i++)
{
Node cNode = pthList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("paths")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Path.class,null);
node.add(rnode);
iteratePaths(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("path")) //$NON-NLS-1$
{
final Path pth = f.resMap.getList(Path.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
pth.setName(fileName);
rnode = new ResNode(pth.getName(),ResNode.STATUS_SECONDARY,Path.class,pth.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document pthdoc = GMXFileReader.parseDocumentChecked(f, path + ".path.gmx"); //$NON-NLS-1$
if (pthdoc == null) continue;
pth.put(PPath.SMOOTH,
Integer.parseInt(pthdoc.getElementsByTagName("kind").item(0).getTextContent()) != 0); //$NON-NLS-1$
pth.put(PPath.PRECISION,
Integer.parseInt(pthdoc.getElementsByTagName("precision").item(0).getTextContent())); //$NON-NLS-1$
pth.put(PPath.CLOSED,
Integer.parseInt(pthdoc.getElementsByTagName("closed").item(0).getTextContent()) != 0); //$NON-NLS-1$
final int backroom = Integer.parseInt(pthdoc.getElementsByTagName("backroom").item(0).getTextContent()); //$NON-NLS-1$
if (backroom >= 0)
{
PostponedRef pr = new PostponedRef()
{
public boolean invoke()
{
ResourceList<Room> list = f.resMap.getList(Room.class);
if (list == null)
{
return false;
}
Room rmn = list.getUnsafe(backroom);
if (rmn == null)
{
return false;
}
pth.put(PPath.BACKGROUND_ROOM,rmn.reference);
return true;
}
};
postpone.add(pr);
}
pth.put(PPath.SNAP_X,
Integer.parseInt(pthdoc.getElementsByTagName("hsnap").item(0).getTextContent())); //$NON-NLS-1$
pth.put(PPath.SNAP_Y,
Integer.parseInt(pthdoc.getElementsByTagName("vsnap").item(0).getTextContent())); //$NON-NLS-1$
// iterate and add each path point
NodeList frList = pthdoc.getElementsByTagName("point"); //$NON-NLS-1$
for (int ii = 0; ii < frList.getLength(); ii++)
{
Node fnode = frList.item(ii);
String[] coords = fnode.getTextContent().split(","); //$NON-NLS-1$
pth.points.add(new PathPoint(Integer.parseInt(coords[0]),Integer.parseInt(coords[1]),
Integer.parseInt(coords[2])));
}
}
}
}
private static void readPaths(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Path.class),ResNode.STATUS_PRIMARY,
Path.class,null);
root.add(node);
NodeList pthList = in.getElementsByTagName("paths"); //$NON-NLS-1$
if (pthList.getLength() > 0)
{
pthList = pthList.item(0).getChildNodes();
}
else
{
return;
}
iteratePaths(c,pthList,node);
}
private static void iterateScripts(ProjectFileContext c, NodeList scrList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < scrList.getLength(); i++)
{
Node cNode = scrList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("scripts")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Script.class,null);
node.add(rnode);
iterateScripts(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("script")) //$NON-NLS-1$
{
Script scr = f.resMap.getList(Script.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
scr.setName(fileName.substring(0,fileName.lastIndexOf('.')));
rnode = new ResNode(scr.getName(),ResNode.STATUS_SECONDARY,Script.class,scr.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
try (BufferedReader reader = new BufferedReader(new FileReader(path)))
{
String code = ""; //$NON-NLS-1$
String line = reader.readLine();
if (line == null) continue;
if (line.startsWith("#define")) //$NON-NLS-1$
{
line = reader.readLine();
if (line == null) continue;
}
do
{
if (line.startsWith("#define")) //$NON-NLS-1$
{
scr.put(PScript.CODE,code);
code = ""; //$NON-NLS-1$
scr = f.resMap.getList(Script.class).add();
scr.setName(line.substring(8, line.length()));
rnode = new ResNode(scr.getName(),ResNode.STATUS_SECONDARY,Script.class,scr.reference);
node.add(rnode);
}
else
code += line + '\n';
}
while ((line = reader.readLine()) != null);
scr.put(PScript.CODE,code);
}
catch (FileNotFoundException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "file not found: " + path, e));
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "unable to read file: " + path, e));
}
}
}
}
private static void readScripts(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Script.class),ResNode.STATUS_PRIMARY,
Script.class,null);
root.add(node);
NodeList scrList = in.getElementsByTagName("scripts"); //$NON-NLS-1$
if (scrList.getLength() > 0)
{
scrList = scrList.item(0).getChildNodes();
}
else
{
return;
}
iterateScripts(c,scrList,node);
}
private static void iterateShaders(ProjectFileContext c, NodeList shrList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < shrList.getLength(); i++)
{
Node cNode = shrList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("shaders")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Shader.class,null);
node.add(rnode);
iterateScripts(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("shader")) //$NON-NLS-1$
{
Shader shr = f.resMap.getList(Shader.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
shr.setName(fileName.substring(0,fileName.lastIndexOf('.')));
rnode = new ResNode(shr.getName(),ResNode.STATUS_SECONDARY,Shader.class,shr.reference);
node.add(rnode);
shr.put(PShader.TYPE,cNode.getAttributes().item(0).getTextContent());
String code = ""; //$NON-NLS-1$
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
try (BufferedReader reader = new BufferedReader(new FileReader(path)))
{
String line = ""; //$NON-NLS-1$
while ((line = reader.readLine()) != null)
{
code += line + '\n';
}
}
catch (FileNotFoundException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "file not found: " + path, e));
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "unable to read file: " + path, e));
}
String[] splitcode = code.split(STUPID_SHADER_MARKER);
shr.put(PShader.VERTEX,splitcode[0]);
shr.put(PShader.FRAGMENT,splitcode[1]);
}
}
}
private static void readShaders(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Shader.class),ResNode.STATUS_PRIMARY,
Shader.class,null);
root.add(node);
NodeList shrList = in.getElementsByTagName("shaders"); //$NON-NLS-1$
if (shrList.getLength() > 0)
{
shrList = shrList.item(0).getChildNodes();
}
else
{
return;
}
iterateShaders(c,shrList,node);
}
private static void iterateFonts(ProjectFileContext c, NodeList fntList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < fntList.getLength(); i++)
{
Node cNode = fntList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("fonts")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Font.class,null);
node.add(rnode);
iterateFonts(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("font")) //$NON-NLS-1$
{
Font fnt = f.resMap.getList(Font.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
fnt.setName(fileName);
rnode = new ResNode(fnt.getName(),ResNode.STATUS_SECONDARY,Font.class,fnt.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document fntdoc = GMXFileReader.parseDocumentChecked(f, path + ".font.gmx"); //$NON-NLS-1$
if (fntdoc == null) continue;
fnt.put(PFont.FONT_NAME,fntdoc.getElementsByTagName("name").item(0).getTextContent()); //$NON-NLS-1$
fnt.put(PFont.SIZE,
Integer.parseInt(fntdoc.getElementsByTagName("size").item(0).getTextContent())); //$NON-NLS-1$
fnt.put(PFont.BOLD,
Integer.parseInt(fntdoc.getElementsByTagName("bold").item(0).getTextContent()) != 0); //$NON-NLS-1$
fnt.put(PFont.ITALIC,
Integer.parseInt(fntdoc.getElementsByTagName("italic").item(0).getTextContent()) != 0); //$NON-NLS-1$
fnt.put(PFont.CHARSET,
Integer.parseInt(fntdoc.getElementsByTagName("charset").item(0).getTextContent())); //$NON-NLS-1$
fnt.put(PFont.ANTIALIAS,
Integer.parseInt(fntdoc.getElementsByTagName("aa").item(0).getTextContent())); //$NON-NLS-1$
NodeList ranges = fntdoc.getElementsByTagName("range0"); //$NON-NLS-1$
for (int item = 0; item < ranges.getLength(); item++)
{
String[] range = ranges.item(item).getTextContent().split(","); //$NON-NLS-1$
fnt.addRange(Integer.parseInt(range[0]),Integer.parseInt(range[1]));
}
NodeList glyphs = fntdoc.getElementsByTagName("glyph"); //$NON-NLS-1$
for (int item = 0; item < glyphs.getLength(); item++)
{
NamedNodeMap attribs = glyphs.item(item).getAttributes();
GlyphMetric gm = fnt.addGlyph();
gm.properties.put(PGlyphMetric.CHARACTER,
Integer.parseInt(attribs.getNamedItem("character").getTextContent())); //$NON-NLS-1$
gm.properties.put(PGlyphMetric.X,
Integer.parseInt(attribs.getNamedItem("x").getTextContent())); //$NON-NLS-1$
gm.properties.put(PGlyphMetric.Y,
Integer.parseInt(attribs.getNamedItem("y").getTextContent())); //$NON-NLS-1$
gm.properties.put(PGlyphMetric.W,
Integer.parseInt(attribs.getNamedItem("w").getTextContent())); //$NON-NLS-1$
gm.properties.put(PGlyphMetric.H,
Integer.parseInt(attribs.getNamedItem("h").getTextContent())); //$NON-NLS-1$
gm.properties.put(PGlyphMetric.SHIFT,
Integer.parseInt(attribs.getNamedItem("shift").getTextContent())); //$NON-NLS-1$
gm.properties.put(PGlyphMetric.OFFSET,
Integer.parseInt(attribs.getNamedItem("offset").getTextContent())); //$NON-NLS-1$
}
}
}
}
private static void readFonts(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Font.class),ResNode.STATUS_PRIMARY,
Font.class,null);
root.add(node);
NodeList fntList = in.getElementsByTagName("fonts"); //$NON-NLS-1$
if (fntList.getLength() > 0)
{
fntList = fntList.item(0).getChildNodes();
}
else
{
return;
}
iterateFonts(c,fntList,node);
}
private static void iterateTimelines(ProjectFileContext c, NodeList tmlList, ResNode node)
{
ProjectFile f = c.f;
for (int i = 0; i < tmlList.getLength(); i++)
{
Node cNode = tmlList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("timelines")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Timeline.class,null);
node.add(rnode);
}
else if (cname.equals("timeline")) //$NON-NLS-1$
{
//ResourceReference<Timeline> r = c.timeids.get(i); //includes ID
//Timeline tml = r.get();
//f.resMap.getList(Timeline.class).add(tml);
Timeline tml = f.resMap.getList(Timeline.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
tml.setName(fileName);
rnode = new ResNode(tml.getName(),ResNode.STATUS_SECONDARY,Timeline.class,tml.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document tmldoc = GMXFileReader.parseDocumentChecked(f, path + ".timeline.gmx"); //$NON-NLS-1$
if (tmldoc == null) continue;
//Iterate the moments and load the actions
NodeList frList = tmldoc.getElementsByTagName("entry"); //$NON-NLS-1$
for (int ii = 0; ii < frList.getLength(); ii++)
{
Node fnode = frList.item(ii);
Moment mom = tml.addMoment();
NodeList children = fnode.getChildNodes();
for (int x = 0; x < children.getLength(); x++)
{
Node cnode = children.item(x);
if (cnode.getNodeName().equals("#text")) //$NON-NLS-1$
{
continue;
}
else if (cnode.getNodeName().equals("step")) //$NON-NLS-1$
{
mom.stepNo = Integer.parseInt(cnode.getTextContent());
}
else if (cnode.getNodeName().equals("event")) //$NON-NLS-1$
{
readActions(c,mom,"INTIMELINEACTION",i,mom.stepNo,cnode.getChildNodes()); //$NON-NLS-1$
}
}
}
}
iterateTimelines(c,cNode.getChildNodes(),rnode);
}
}
private static void readTimelines(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Timeline.class),ResNode.STATUS_PRIMARY,
Timeline.class,null);
root.add(node);
NodeList tmlList = in.getElementsByTagName("timelines"); //$NON-NLS-1$
if (tmlList.getLength() > 0)
{
tmlList = tmlList.item(0).getChildNodes();
}
else
{
return;
}
iterateTimelines(c,tmlList,node);
}
private static void iterateGmObjects(ProjectFileContext c, NodeList objList, ResNode node)
{
final ProjectFile f = c.f;
for (int i = 0; i < objList.getLength(); i++)
{
Node cNode = objList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("objects")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
GmObject.class,null);
node.add(rnode);
iterateGmObjects(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("object")) //$NON-NLS-1$
{
//ResourceReference<GmObject> r = c.objids.get(int); //includes ID
//final GmObject obj = r.get();
//f.resMap.getList(GmObject.class).add(obj);
final GmObject obj = f.resMap.getList(GmObject.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
obj.setName(fileName);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document objdoc = GMXFileReader.parseDocumentChecked(f, path + ".object.gmx"); //$NON-NLS-1$
if (objdoc == null) continue;
final String sprname = objdoc.getElementsByTagName("spriteName").item(0).getTextContent(); //$NON-NLS-1$
if (!sprname.equals("<undefined>"))
{
postpone.add(new DefaultPostponedRef(f.resMap.getList(Sprite.class), obj.properties, PGmObject.SPRITE, sprname));
}
else
{
obj.put(PGmObject.SPRITE,null);
}
final String mskname = objdoc.getElementsByTagName("maskName").item(0).getTextContent(); //$NON-NLS-1$
if (!mskname.equals("<undefined>"))
{
postpone.add(new DefaultPostponedRef(f.resMap.getList(Sprite.class), obj.properties, PGmObject.MASK, mskname));
}
else
{
obj.put(PGmObject.MASK,null);
}
final String parname = objdoc.getElementsByTagName("parentName").item(0).getTextContent(); //$NON-NLS-1$
if (!parname.equals("<undefined>") && !parname.equals("self"))
{
postpone.add(new DefaultPostponedRef(f.resMap.getList(GmObject.class), obj.properties, PGmObject.PARENT, parname));
}
else
{
obj.put(PGmObject.PARENT,null);
}
obj.put(PGmObject.SOLID,
Integer.parseInt(objdoc.getElementsByTagName("solid").item(0).getTextContent()) != 0); //$NON-NLS-1$
obj.put(PGmObject.VISIBLE,
Integer.parseInt(objdoc.getElementsByTagName("visible").item(0).getTextContent()) != 0); //$NON-NLS-1$
obj.put(PGmObject.DEPTH,
Integer.parseInt(objdoc.getElementsByTagName("depth").item(0).getTextContent())); //$NON-NLS-1$
obj.put(
PGmObject.PERSISTENT,
Integer.parseInt(objdoc.getElementsByTagName("persistent").item(0).getTextContent()) != 0); //$NON-NLS-1$
// Now that properties are loaded iterate the events and load the actions
NodeList frList = objdoc.getElementsByTagName("event"); //$NON-NLS-1$
for (int ii = 0; ii < frList.getLength(); ii++)
{
Node fnode = frList.item(ii);
final Event ev = new Event();
ev.mainId = Integer.parseInt(fnode.getAttributes().getNamedItem("eventtype").getTextContent()); //$NON-NLS-1$
MainEvent me = obj.mainEvents.get(ev.mainId);
me.events.add(0,ev);
if (ev.mainId == MainEvent.EV_COLLISION)
{
final String colname = fnode.getAttributes().getNamedItem("ename").getTextContent(); //$NON-NLS-1$
PostponedRef pr = new PostponedRef()
{
public boolean invoke()
{
ResourceList<GmObject> list = f.resMap.getList(GmObject.class);
if (list == null)
{
return false;
}
GmObject col = list.get(colname);
if (col == null)
{
return false;
}
ev.other = col.reference;
return true;
}
};
postpone.add(pr);
}
else
{
ev.id = Integer.parseInt(fnode.getAttributes().getNamedItem("enumb").getTextContent()); //$NON-NLS-1$
}
readActions(c,ev,"INOBJECTACTION",i,ii * 1000 + ev.id,fnode.getChildNodes()); //$NON-NLS-1$
}
obj.put(
PGmObject.PHYSICS_OBJECT,
Integer.parseInt(objdoc.getElementsByTagName("PhysicsObject").item(0).getTextContent()) != 0); //$NON-NLS-1$
obj.put(
PGmObject.PHYSICS_SENSOR,
Integer.parseInt(objdoc.getElementsByTagName("PhysicsObjectSensor").item(0).getTextContent()) != 0); //$NON-NLS-1$
int shapekind = Integer.parseInt(objdoc.getElementsByTagName("PhysicsObjectShape").item(0).getTextContent()); //$NON-NLS-1$
obj.put(PGmObject.PHYSICS_SHAPE,ProjectFile.PHYSICS_SHAPE[shapekind]);
obj.put(
PGmObject.PHYSICS_DENSITY,
Double.parseDouble(objdoc.getElementsByTagName("PhysicsObjectDensity").item(0).getTextContent())); //$NON-NLS-1$
obj.put(
PGmObject.PHYSICS_RESTITUTION,
Double.parseDouble(objdoc.getElementsByTagName("PhysicsObjectRestitution").item(0).getTextContent())); //$NON-NLS-1$
obj.put(
PGmObject.PHYSICS_GROUP,
Integer.parseInt(objdoc.getElementsByTagName("PhysicsObjectGroup").item(0).getTextContent())); //$NON-NLS-1$
obj.put(
PGmObject.PHYSICS_DAMPING_LINEAR,
Double.parseDouble(objdoc.getElementsByTagName("PhysicsObjectLinearDamping").item(0).getTextContent())); //$NON-NLS-1$
obj.put(
PGmObject.PHYSICS_DAMPING_ANGULAR,
Double.parseDouble(objdoc.getElementsByTagName("PhysicsObjectAngularDamping").item(0).getTextContent())); //$NON-NLS-1$
// TODO: Some versions of the format did not have all of the physics properties.
Node fNode = objdoc.getElementsByTagName("PhysicsObjectFriction").item(0); //$NON-NLS-1$
if (fNode != null)
{
obj.put(PGmObject.PHYSICS_FRICTION,Double.parseDouble(fNode.getTextContent()));
obj.put(
PGmObject.PHYSICS_AWAKE,
Integer.parseInt(objdoc.getElementsByTagName("PhysicsObjectAwake").item(0).getTextContent()) != 0); //$NON-NLS-1$
obj.put(
PGmObject.PHYSICS_KINEMATIC,
Integer.parseInt(objdoc.getElementsByTagName("PhysicsObjectKinematic").item(0).getTextContent()) != 0); //$NON-NLS-1$
}
NodeList pointNodes = objdoc.getElementsByTagName("point"); //$NON-NLS-1$
for (int p = 0; p < pointNodes.getLength(); p++)
{
String[] coords = pointNodes.item(p).getTextContent().split(","); //$NON-NLS-1$
obj.shapePoints.add(new ShapePoint(Integer.parseInt(coords[0]),
Integer.parseInt(coords[1])));
}
rnode = new ResNode(obj.getName(),ResNode.STATUS_SECONDARY,GmObject.class,obj.reference);
node.add(rnode);
}
}
}
private static void readGmObjects(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ProjectFile f = c.f;
ResNode node = new ResNode("Objects",ResNode.STATUS_PRIMARY,GmObject.class,null); //$NON-NLS-1$
root.add(node);
NodeList objList = in.getElementsByTagName("objects"); //$NON-NLS-1$
if (objList.getLength() > 0)
{
objList = objList.item(0).getChildNodes();
}
else
{
return;
}
iterateGmObjects(c,objList,node);
f.resMap.getList(GmObject.class).lastId = objList.getLength() - 1;
}
private static void iterateRooms(ProjectFileContext c, NodeList rmnList, ResNode node)
{
final ProjectFile f = c.f;
for (int i = 0; i < rmnList.getLength(); i++)
{
Node cNode = rmnList.item(i);
String cname = cNode.getNodeName();
if (cname.equals("#text")) //$NON-NLS-1$
{
continue;
}
ResNode rnode = null;
if (cname.equals("rooms")) //$NON-NLS-1$
{
rnode = new ResNode(cNode.getAttributes().item(0).getTextContent(),ResNode.STATUS_GROUP,
Room.class,null);
node.add(rnode);
iterateRooms(c,cNode.getChildNodes(),rnode);
}
else if (cname.equals("room")) //$NON-NLS-1$
{
//ResourceReference<Room> r = c.rmids.get(i); //includes ID
//Room rmn = r.get();
//f.resMap.getList(Room.class).add(rmn);
Room rmn = f.resMap.getList(Room.class).add();
String fileName = new File(Util.getPOSIXPath(cNode.getTextContent())).getName();
rmn.setName(fileName);
rnode = new ResNode(rmn.getName(),ResNode.STATUS_SECONDARY,Room.class,rmn.reference);
node.add(rnode);
String path = f.getDirectory() + '/' + Util.getPOSIXPath(cNode.getTextContent());
Document rmndoc = GMXFileReader.parseDocumentChecked(f, path + ".room.gmx"); //$NON-NLS-1$
if (rmndoc == null) continue;
String caption = rmndoc.getElementsByTagName("caption").item(0).getTextContent(); //$NON-NLS-1$
rmn.put(PRoom.CAPTION,caption);
NodeList cnodes = rmndoc.getElementsByTagName("room").item(0).getChildNodes(); //$NON-NLS-1$
for (int x = 0; x < cnodes.getLength(); x++)
{
Node pnode = cnodes.item(x);
String pname = pnode.getNodeName();
if (pname.equals("#text")) //$NON-NLS-1$
{
continue;
}
else if (pname.equals("caption")) //$NON-NLS-1$
{
rmn.put(PRoom.CAPTION,pnode.getTextContent());
}
else if (pname.equals("width")) //$NON-NLS-1$
{
rmn.put(PRoom.WIDTH,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("height")) //$NON-NLS-1$
{
rmn.put(PRoom.HEIGHT,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("vsnap")) //$NON-NLS-1$
{
rmn.put(PRoom.SNAP_Y,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("hsnap")) //$NON-NLS-1$
{
rmn.put(PRoom.SNAP_X,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("isometric")) //$NON-NLS-1$
{
rmn.put(PRoom.ISOMETRIC,Integer.parseInt(pnode.getTextContent()) != 0);
}
else if (pname.equals("speed")) //$NON-NLS-1$
{
rmn.put(PRoom.SPEED,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("persistent")) //$NON-NLS-1$
{
rmn.put(PRoom.PERSISTENT,Integer.parseInt(pnode.getTextContent()) != 0);
}
else if (pname.equals("colour")) //$NON-NLS-1$
{
int col = Integer.parseInt(pnode.getTextContent());
rmn.put(PRoom.BACKGROUND_COLOR,Util.convertGmColor(col));
}
else if (pname.equals("showcolour")) //$NON-NLS-1$
{
rmn.put(PRoom.DRAW_BACKGROUND_COLOR,Integer.parseInt(pnode.getTextContent()) != 0);
}
else if (pname.equals("code")) //$NON-NLS-1$
{
rmn.put(PRoom.CREATION_CODE,pnode.getTextContent());
}
else if (pname.equals("enableViews")) //$NON-NLS-1$
{
rmn.put(PRoom.VIEWS_ENABLED,Integer.parseInt(pnode.getTextContent()) != 0);
}
else if (pname.equals("clearViewBackground")) //$NON-NLS-1$
{
rmn.put(PRoom.VIEWS_CLEAR,Integer.parseInt(pnode.getTextContent()) != 0);
}
else if (pname.equals("makerSettings")) //$NON-NLS-1$
{
NodeList msnodes = pnode.getChildNodes();
for (int y = 0; y < msnodes.getLength(); y++)
{
Node mnode = msnodes.item(y);
String mname = mnode.getNodeName();
if (mname.equals("#text")) //$NON-NLS-1$
{
continue;
}
else if (mname.equals("isSet")) //$NON-NLS-1$
{
rmn.put(PRoom.REMEMBER_WINDOW_SIZE,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("w")) //$NON-NLS-1$
{
rmn.put(PRoom.EDITOR_WIDTH,Integer.parseInt(mnode.getTextContent()));
}
else if (mname.equals("h")) //$NON-NLS-1$
{
rmn.put(PRoom.EDITOR_HEIGHT,Integer.parseInt(mnode.getTextContent()));
}
else if (mname.equals("showGrid")) //$NON-NLS-1$
{
rmn.put(PRoom.SHOW_GRID,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("showObjects")) //$NON-NLS-1$
{
rmn.put(PRoom.SHOW_OBJECTS,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("showTiles")) //$NON-NLS-1$
{
rmn.put(PRoom.SHOW_TILES,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("showBackgrounds")) //$NON-NLS-1$
{
rmn.put(PRoom.SHOW_BACKGROUNDS,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("showForegrounds")) //$NON-NLS-1$
{
rmn.put(PRoom.SHOW_FOREGROUNDS,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("showViews")) //$NON-NLS-1$
{
rmn.put(PRoom.SHOW_VIEWS,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("deleteUnderlyingObj")) //$NON-NLS-1$
{
rmn.put(PRoom.DELETE_UNDERLYING_OBJECTS,
Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("deleteUnderlyingTiles")) //$NON-NLS-1$
{
rmn.put(PRoom.DELETE_UNDERLYING_TILES,Integer.parseInt(mnode.getTextContent()) != 0);
}
else if (mname.equals("page")) //$NON-NLS-1$
{
rmn.put(PRoom.CURRENT_TAB,Integer.parseInt(mnode.getTextContent()));
}
else if (mname.equals("xoffset")) //$NON-NLS-1$
{
rmn.put(PRoom.SCROLL_BAR_X,Integer.parseInt(mnode.getTextContent()));
}
else if (mname.equals("yoffset")) //$NON-NLS-1$
{
rmn.put(PRoom.SCROLL_BAR_Y,Integer.parseInt(mnode.getTextContent()));
}
}
}
else if (pname.equals("backgrounds")) //$NON-NLS-1$
{
NodeList bgnodes = pnode.getChildNodes();
int bkgnum = 0;
for (int y = 0; y < bgnodes.getLength(); y++)
{
Node bnode = bgnodes.item(y);
String bname = bnode.getNodeName();
if (bname.equals("#text")) //$NON-NLS-1$
{
continue;
}
final BackgroundDef bkg = rmn.backgroundDefs.get(bkgnum);
bkgnum += 1;
bkg.properties.put(
PBackgroundDef.VISIBLE,
Integer.parseInt(bnode.getAttributes().getNamedItem("visible").getTextContent()) != 0); //$NON-NLS-1$
final String bkgname = bnode.getAttributes().getNamedItem("name").getTextContent(); //$NON-NLS-1$
postpone.add(new DefaultPostponedRef(f.resMap.getList(Background.class), bkg.properties, PBackgroundDef.BACKGROUND, bkgname));
bkg.properties.put(
PBackgroundDef.FOREGROUND,
Integer.parseInt(bnode.getAttributes().getNamedItem("foreground").getTextContent()) != 0); //$NON-NLS-1$
bkg.properties.put(
PBackgroundDef.TILE_HORIZ,
Integer.parseInt(bnode.getAttributes().getNamedItem("htiled").getTextContent()) != 0); //$NON-NLS-1$
bkg.properties.put(
PBackgroundDef.TILE_VERT,
Integer.parseInt(bnode.getAttributes().getNamedItem("vtiled").getTextContent()) != 0); //$NON-NLS-1$
bkg.properties.put(
PBackgroundDef.STRETCH,
Integer.parseInt(bnode.getAttributes().getNamedItem("stretch").getTextContent()) != 0); //$NON-NLS-1$
bkg.properties.put(PBackgroundDef.H_SPEED,
Integer.parseInt(bnode.getAttributes().getNamedItem("hspeed").getTextContent())); //$NON-NLS-1$
bkg.properties.put(PBackgroundDef.V_SPEED,
Integer.parseInt(bnode.getAttributes().getNamedItem("vspeed").getTextContent())); //$NON-NLS-1$
bkg.properties.put(PBackgroundDef.X,
Integer.parseInt(bnode.getAttributes().getNamedItem("x").getTextContent())); //$NON-NLS-1$
bkg.properties.put(PBackgroundDef.Y,
Integer.parseInt(bnode.getAttributes().getNamedItem("y").getTextContent())); //$NON-NLS-1$
}
}
else if (pname.equals("views")) //$NON-NLS-1$
{
NodeList vinodes = pnode.getChildNodes();
int viewnum = 0;
for (int y = 0; y < vinodes.getLength(); y++)
{
Node vnode = vinodes.item(y);
String vname = vnode.getNodeName();
if (vname.equals("#text")) //$NON-NLS-1$
{
continue;
}
final View vw = rmn.views.get(viewnum);
viewnum += 1;
vw.properties.put(
PView.VISIBLE,
Integer.parseInt(vnode.getAttributes().getNamedItem("visible").getTextContent()) != 0); //$NON-NLS-1$
final String objname = vnode.getAttributes().getNamedItem("objName").getTextContent(); //$NON-NLS-1$
postpone.add(new DefaultPostponedRef(f.resMap.getList(GmObject.class), vw.properties, PView.OBJECT, objname));
vw.properties.put(PView.SPEED_H,
Integer.parseInt(vnode.getAttributes().getNamedItem("hspeed").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.SPEED_V,
Integer.parseInt(vnode.getAttributes().getNamedItem("vspeed").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.BORDER_H,
Integer.parseInt(vnode.getAttributes().getNamedItem("hborder").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.BORDER_V,
Integer.parseInt(vnode.getAttributes().getNamedItem("vborder").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.PORT_H,
Integer.parseInt(vnode.getAttributes().getNamedItem("hport").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.PORT_W,
Integer.parseInt(vnode.getAttributes().getNamedItem("wport").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.PORT_X,
Integer.parseInt(vnode.getAttributes().getNamedItem("xport").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.PORT_Y,
Integer.parseInt(vnode.getAttributes().getNamedItem("yport").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.VIEW_H,
Integer.parseInt(vnode.getAttributes().getNamedItem("hview").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.VIEW_W,
Integer.parseInt(vnode.getAttributes().getNamedItem("wview").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.VIEW_X,
Integer.parseInt(vnode.getAttributes().getNamedItem("xview").getTextContent())); //$NON-NLS-1$
vw.properties.put(PView.VIEW_Y,
Integer.parseInt(vnode.getAttributes().getNamedItem("yview").getTextContent())); //$NON-NLS-1$
}
}
else if (pname.equals("instances")) //$NON-NLS-1$
{
NodeList insnodes = pnode.getChildNodes();
for (int y = 0; y < insnodes.getLength(); y++)
{
Node inode = insnodes.item(y);
String iname = inode.getNodeName();
if (iname.equals("#text")) //$NON-NLS-1$
{
continue;
}
else if (iname.equals("instance") && inode.getAttributes().getLength() > 0) //$NON-NLS-1$
{
Instance inst = rmn.addInstance();
// TODO: Replace this with DelayedRef
String objname = inode.getAttributes().getNamedItem("objName").getTextContent(); //$NON-NLS-1$
// because of the way this is set up, sprites must be loaded before objects
GmObject temp = f.resMap.getList(GmObject.class).get(objname);
if (temp != null) inst.properties.put(PInstance.OBJECT,temp.reference);
NamedNodeMap attribs = inode.getAttributes();
int xx = Integer.parseInt(attribs.getNamedItem("x").getNodeValue()); //$NON-NLS-1$
int yy = Integer.parseInt(attribs.getNamedItem("y").getNodeValue()); //$NON-NLS-1$
double sx = Double.parseDouble(attribs.getNamedItem("scaleX").getNodeValue()); //$NON-NLS-1$
double sy = Double.parseDouble(attribs.getNamedItem("scaleY").getNodeValue()); //$NON-NLS-1$
// Read the color blending
if (attribs.getNamedItem("colour") != null) //$NON-NLS-1$
{
long col = Long.parseLong(attribs.getNamedItem("colour").getNodeValue()); //$NON-NLS-1$
Color color = Util.convertInstanceColorWithAlpha((int) col);
inst.setColor(color);
inst.setAlpha(color.getAlpha());
}
double rot = Double.parseDouble(attribs.getNamedItem("rotation").getNodeValue()); //$NON-NLS-1$
inst.properties.put(PInstance.NAME, inode.getAttributes().getNamedItem("name").getNodeValue()); //$NON-NLS-1$
// NOTE: Because LGM still supports GMK, we attempt to preserve the ID which Studio
// will remove if it saves over the GMX, so see if the "id" attribute we added is
// there otherwise make up a new ID.
Node idNode = inode.getAttributes().getNamedItem("id"); //$NON-NLS-1$
int instid;
if (idNode != null) {
instid = Integer.parseInt(idNode.getNodeValue());
if (instid > f.lastInstanceId) {
f.lastInstanceId = instid;
}
} else {
instid = ++f.lastInstanceId;
}
inst.properties.put(PInstance.ID, instid);
inst.setPosition(new Point(xx,yy));
inst.setScale(new Point2D.Double(sx,sy));
inst.setRotation(rot);
inst.setCreationCode(inode.getAttributes().getNamedItem("code").getNodeValue()); //$NON-NLS-1$
inst.setLocked(Integer.parseInt(inode.getAttributes().getNamedItem("locked").getNodeValue()) != 0); //$NON-NLS-1$
}
}
}
else if (pname.equals("tiles")) //$NON-NLS-1$
{
NodeList tinodes = pnode.getChildNodes();
for (int p = 0; p < tinodes.getLength(); p++)
{
Node tnode = tinodes.item(p);
String tname = tnode.getNodeName();
if (tname.equals("#text")) //$NON-NLS-1$
{
continue;
}
final Tile tile = new Tile(rmn);
NamedNodeMap attribs = tnode.getAttributes();
tile.setPosition(new Point(
Integer.parseInt(attribs.getNamedItem("x").getTextContent()), //$NON-NLS-1$
Integer.parseInt(attribs.getNamedItem("y").getTextContent()))); //$NON-NLS-1$
final String bkgname = tnode.getAttributes().getNamedItem("bgName").getTextContent(); //$NON-NLS-1$
postpone.add(new DefaultPostponedRef(f.resMap.getList(Background.class), tile.properties, PTile.BACKGROUND, bkgname));
tile.properties.put(PTile.NAME, attribs.getNamedItem("name").getNodeValue()); //$NON-NLS-1$
int tileid = Integer.parseInt(attribs.getNamedItem("id").getTextContent()); //$NON-NLS-1$
if (tileid > f.lastTileId) {
f.lastTileId = tileid;
}
tile.properties.put(PTile.ID,tileid);
tile.setBackgroundPosition(new Point(
Integer.parseInt(attribs.getNamedItem("xo").getTextContent()), //$NON-NLS-1$
Integer.parseInt(attribs.getNamedItem("yo").getTextContent()))); //$NON-NLS-1$
tile.setSize(new Dimension(
Integer.parseInt(attribs.getNamedItem("w").getTextContent()), //$NON-NLS-1$
Integer.parseInt(attribs.getNamedItem("h").getTextContent()))); //$NON-NLS-1$
tile.setDepth(Integer.parseInt(attribs.getNamedItem("depth").getTextContent())); //$NON-NLS-1$
tile.setLocked(Integer.parseInt(attribs.getNamedItem("locked").getTextContent()) != 0); //$NON-NLS-1$
double sx = Double.parseDouble(attribs.getNamedItem("scaleX").getNodeValue()); //$NON-NLS-1$
double sy = Double.parseDouble(attribs.getNamedItem("scaleY").getNodeValue()); //$NON-NLS-1$
tile.setScale(new Point2D.Double(sx,sy));
tile.setColor(Long.parseLong(attribs.getNamedItem("colour").getNodeValue())); //$NON-NLS-1$
rmn.tiles.add(tile);
}
}
else if (pname.equals("PhysicsWorld")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_WORLD,Integer.parseInt(pnode.getTextContent()) != 0);
}
else if (pname.equals("PhysicsWorldTop")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_TOP,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("PhysicsWorldLeft")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_LEFT,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("PhysicsWorldRight")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_RIGHT,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("PhysicsWorldBottom")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_BOTTOM,Integer.parseInt(pnode.getTextContent()));
}
else if (pname.equals("PhysicsWorldGravityX")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_GRAVITY_X,Double.parseDouble(pnode.getTextContent()));
}
else if (pname.equals("PhysicsWorldGravityY")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_GRAVITY_Y,Double.parseDouble(pnode.getTextContent()));
}
else if (pname.equals("PhysicsWorldPixToMeters")) //$NON-NLS-1$
{
rmn.put(PRoom.PHYSICS_PIXTOMETERS,Double.parseDouble(pnode.getTextContent()));
}
}
}
}
}
private static void readRooms(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Room.class), ResNode.STATUS_PRIMARY,
Room.class, null);
root.add(node);
NodeList rmnList = in.getElementsByTagName("rooms"); //$NON-NLS-1$
if (rmnList.getLength() > 0)
{
rmnList = rmnList.item(0).getChildNodes();
}
else
{
return;
}
iterateRooms(c,rmnList,node);
}
private static void readIncludedFiles(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Include.class), ResNode.STATUS_PRIMARY,
Include.class, null);
root.add(node);
NodeList incList = in.getElementsByTagName("includes"); //$NON-NLS-1$
if (incList.getLength() > 0)
{
incList = incList.item(0).getChildNodes();
}
else
{
return;
}
//iterateIncludes(c, incList, node);
}
private static void readPackages(ProjectFileContext c, ResNode root)
{
//iteratePackages(c, extList, node);
ExtensionPackages extpkgs = c.f.extPackages;
ResNode node = new ResNode(Resource.kindNamesPlural.get(ExtensionPackages.class),
ResNode.STATUS_SECONDARY,ExtensionPackages.class,extpkgs.reference);
root.add(node);
}
private static void readExtensions(ProjectFileContext c, ResNode root)
{
Document in = c.in;
ResNode node = new ResNode(Resource.kindNamesPlural.get(Extension.class),
ResNode.STATUS_PRIMARY,ExtensionPackages.class,null);
root.add(node);
NodeList extList = in.getElementsByTagName("extensions"); //$NON-NLS-1$
if (extList.getLength() > 0)
{
extList = extList.item(0).getChildNodes();
}
else
{
return;
}
//iterateExtensions(c, extList, node);
}
private static void readConstants(Constants cnsts, Node node)
{
if (node == null) return;
int count = Integer.valueOf(node.getAttributes().getNamedItem("number").getNodeValue()); //$NON-NLS-1$
List<Constant> newList = new ArrayList<Constant>(count);
NodeList cnstNodes = node.getChildNodes();
for (int i = 0; i < cnstNodes.getLength(); i++)
{
Node cnstNode = cnstNodes.item(i);
if (!cnstNode.getNodeName().equals("constant")) //$NON-NLS-1$
{
continue;
}
String name = cnstNode.getAttributes().getNamedItem("name").getTextContent(); //$NON-NLS-1$
String value = cnstNode.getTextContent();
newList.add(new Constant(name,value));
}
cnsts.constants = newList;
}
private static void readDefaultConstants(ProjectFileContext c, ResNode root)
{
readConstants(c.f.defaultConstants,c.in.getElementsByTagName("constants").item(0)); //$NON-NLS-1$
ResNode node = new ResNode("Constants",ResNode.STATUS_SECONDARY,Constants.class,null); //$NON-NLS-1$
root.add(node);
}
private static void readGameInformation(ProjectFileContext c, ResNode root)
{
Document in = c.in;
GameInformation gameInfo = c.f.gameInfo;
NodeList rtfNodes = in.getElementsByTagName("rtf"); //$NON-NLS-1$
if (rtfNodes.getLength() == 0)
{
return;
}
Node rtfNode = rtfNodes.item(rtfNodes.getLength() - 1);
String path = c.f.getDirectory() + '/' + Util.getPOSIXPath(rtfNode.getTextContent());
String text = ""; //$NON-NLS-1$
try (BufferedReader reader = new BufferedReader(new FileReader(path)))
{
String line = ""; //$NON-NLS-1$
while ((line = reader.readLine()) != null)
{
text += line + '\n';
}
}
catch (FileNotFoundException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "file not found: " + path, e));
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(new GmFormatException(c.f, "unable to read file: " + path, e));
}
gameInfo.put(PGameInformation.TEXT,text);
ResNode node = new ResNode(Resource.kindNamesPlural.get(GameInformation.class),
ResNode.STATUS_SECONDARY,GameInformation.class,gameInfo.reference);
root.add(node);
}
private static void readActions(ProjectFileContext c, ActionContainer container, String errorKey,
int format1, int format2, NodeList actList)
{
final ProjectFile f = c.f;
for (int i = 0; i < actList.getLength(); i++)
{
Node actNode = actList.item(i);
if (actNode.getNodeName().equals("#text")) //$NON-NLS-1$
{
continue;
}
int libid = 0;
int actid = 0;
byte kind = 0;
boolean userelative = false;
boolean isquestion = false;
boolean isquestiontrue = false;
boolean isrelative = false;
boolean useapplyto = false;
byte exectype = 0;
String appliesto = ""; //$NON-NLS-1$
String functionname = ""; // execInfo for if the action just calls an action function //$NON-NLS-1$
String codestring = ""; // execInfo for if the action executes code //$NON-NLS-1$
Argument[] args = null;
LibAction la = null;
NodeList propList = actNode.getChildNodes();
for (int ii = 0; ii < propList.getLength(); ii++)
{
Node prop = propList.item(ii);
if (prop.getNodeName().equals("#text")) //$NON-NLS-1$
{
continue;
}
if (prop.getNodeName().equals("libid")) //$NON-NLS-1$
{
libid = Integer.parseInt(prop.getTextContent());
}
else if (prop.getNodeName().equals("id")) //$NON-NLS-1$
{
actid = Integer.parseInt(prop.getTextContent());
}
else if (prop.getNodeName().equals("kind")) //$NON-NLS-1$
{
kind = Byte.parseByte(prop.getTextContent());
}
else if (prop.getNodeName().equals("userelative")) //$NON-NLS-1$
{
userelative = Integer.parseInt(prop.getTextContent()) != 0;
}
else if (prop.getNodeName().equals("relative")) //$NON-NLS-1$
{
isrelative = Integer.parseInt(prop.getTextContent()) != 0;
}
else if (prop.getNodeName().equals("isquestion")) //$NON-NLS-1$
{
isquestion = Integer.parseInt(prop.getTextContent()) != 0;
}
else if (prop.getNodeName().equals("isnot")) //$NON-NLS-1$
{
isquestiontrue = Integer.parseInt(prop.getTextContent()) != 0;
}
else if (prop.getNodeName().equals("useapplyto")) //$NON-NLS-1$
{
useapplyto = Integer.parseInt(prop.getTextContent()) != 0;
}
else if (prop.getNodeName().equals("exetype")) //$NON-NLS-1$
{
exectype = Byte.parseByte(prop.getTextContent());
}
else if (prop.getNodeName().equals("whoName")) //$NON-NLS-1$
{
appliesto = prop.getTextContent();
}
else if (prop.getNodeName().equals("functionname")) //$NON-NLS-1$
{
functionname = prop.getTextContent();
}
else if (prop.getNodeName().equals("codestring")) //$NON-NLS-1$
{
codestring = prop.getTextContent();
}
else if (prop.getNodeName().equals("arguments")) //$NON-NLS-1$
{
NodeList targList = prop.getChildNodes();
List<Node> argList = new ArrayList<Node>();
for (int x = 0; x < targList.getLength(); x++)
{
Node arg = targList.item(x);
if (!arg.getNodeName().equals("#text")) //$NON-NLS-1$
{
argList.add(arg);
}
}
args = new Argument[argList.size()];
for (int x = 0; x < argList.size(); x++)
{
Node arg = argList.get(x);
if (arg.getNodeName().equals("#text")) //$NON-NLS-1$
{
continue;
}
args[x] = new Argument((byte) 0);
NodeList argproplist = arg.getChildNodes();
for (int xx = 0; xx < argproplist.getLength(); xx++)
{
Node argprop = argproplist.item(xx);
if (prop.getNodeName().equals("#text")) //$NON-NLS-1$
{
continue;
}
final String proptext = argprop.getTextContent();
final Argument argument = args[x];
if (argprop.getNodeName().equals("kind")) //$NON-NLS-1$
{
argument.kind = Byte.parseByte(argprop.getTextContent());
}
else if (argprop.getNodeName().equals("string")) //$NON-NLS-1$
{
argument.setVal(proptext);
}
else
{
Class<? extends Resource<?,?>> kindc = Argument.getResourceKind(argument.kind);
if (kindc != null && Resource.class.isAssignableFrom(kindc)) try
{
PostponedRef pr = new PostponedRef()
{
public boolean invoke()
{
ResourceHolder<?> rh = f.resMap.get(Argument.getResourceKind(argument.kind));
if (rh == null)
{
return false;
}
Resource<?,?> temp = null;
if (rh instanceof ResourceList<?>)
temp = ((ResourceList<?>) rh).get(proptext);
else
temp = rh.getResource();
if (temp != null) argument.setRes(temp.reference);
argument.setVal(proptext);
return temp != null;
}
};
postpone.add(pr);
}
catch (NumberFormatException e)
{
// Trying to ref a resource without a valid id number?
// Fallback to strval (already set)
}
}
}
}
}
}
la = LibManager.getLibAction(libid,actid);
boolean unknownLib = la == null;
// The libAction will have a null parent, among other things
if (unknownLib)
{
la = new LibAction();
la.id = actid;
la.parentId = libid;
la.actionKind = kind;
// TODO: Maybe make this more agnostic?
if (la.actionKind == Action.ACT_CODE)
{
la = LibManager.codeAction;
}
else
{
la.allowRelative = userelative;
la.question = isquestion;
la.canApplyTo = useapplyto;
la.execType = exectype;
if (la.execType == Action.EXEC_FUNCTION) la.execInfo = functionname;
if (la.execType == Action.EXEC_CODE) la.execInfo = codestring;
}
if (args != null)
{
la.libArguments = new LibArgument[args.length];
for (int b = 0; b < args.length; b++)
{
LibArgument argument = new LibArgument();
argument.kind = args[b].kind;
la.libArguments[b] = argument;
}
}
}
final Action act = container.addAction(la);
if (appliesto.equals("self")) //$NON-NLS-1$
{
act.setAppliesTo(GmObject.OBJECT_SELF);
}
else if (appliesto.equals("other")) //$NON-NLS-1$
{
act.setAppliesTo(GmObject.OBJECT_OTHER);
}
else
{
final String objname = appliesto;
PostponedRef pr = new PostponedRef()
{
public boolean invoke()
{
ResourceList<GmObject> list = f.resMap.getList(GmObject.class);
if (list == null)
{
return false;
}
GmObject obj = list.get(objname);
if (obj == null)
{
return false;
}
act.setAppliesTo(obj.reference);
return true;
}
};
postpone.add(pr);
}
act.setRelative(isrelative);
if (args != null && args.length > 0)
{
act.setArguments(args);
}
act.setNot(isquestiontrue);
}
}
}