Compare commits

...

20 Commits

Author SHA1 Message Date
Zukero
1a70f87897 v0.4.7 ! 2016-08-10 18:03:11 +02:00
Zukero
c07fb4ddf3 Implemented all colorfilters in TMXMapEditor, thanks to the new
MatrixComposite that really emulates the ColorMatrixColorFilter of
Android ! Hi-fidelity filter emulation !
2016-08-10 16:20:48 +02:00
Zukero
1458fb0aaa Bug fix for the map's "outside" property that wasn't handled properly.
Added support for the new "colorfilter" map property. Due to Java2D
having no correct color filter support, only the "blackXX" values can be
previwed. "bw" and "invert" cannot, the performance cost was simply way
too high.
2016-08-08 16:31:38 +02:00
Zukero
57b8209b26 v0.4.6 ! Oh so many bugfixes... 2016-07-21 16:39:55 +02:00
Zukero
a7224755ff Fixed NPE in KeyArea creation. Rest areas can be renamed. 2016-07-19 18:49:42 +02:00
Zukero
e97168c62e v0.4.5 complete with packaging. 2016-07-19 17:57:02 +02:00
Zukero
1e8dd405c3 Addedchanges to match new datamodel in AT. Notably, ability to disable a
Map Object Group in a new game in a map, and the associated rewards
((de)activateMapObjectGroup) in dialogues that replace
(de)activateMapChangeArea.
2016-07-19 17:37:54 +02:00
Zukero
830e9de56b v0.4.5 to cope with changes to spawnareas definition in game code.
replaced gcode references by github repo.
2016-07-18 18:55:16 +02:00
Zukero
2a06002b51 Updated packaging for v0.4.4 2016-01-05 14:22:18 +01:00
Zukero
84b1b6a7eb v0.4.4 !
- Projects can now use either loadresources.xml or
loadresources_debug.xml, or none (as before). This must be selected at
project creation and cannot be changed.
- NPC and Items comparators now include both the source and altered
version of elements present in both.
- Spritesheets view should now be better laid out, as insets were not
taken into account, thus cropping a few pixels right and down.
2016-01-05 14:15:23 +01:00
Zukero
f924c481f8 v0.4.3 ! Only a bugfix on JSON import. 2016-01-01 22:59:20 +01:00
Zukero
ed004f5cfc v0.4.2 ! 2015-10-30 14:09:28 +01:00
Zukero
12ca21b9e4 Added "active" setting for SpawnAreas. Added cool tooltip to
DialogueGraphView
2015-10-30 14:02:38 +01:00
Zukero
f5c454807c Small bug fixes (started ignoring case for Spawn Group lookup, like in
the game; avoid NPE in Dialogue parser).
2015-10-30 12:50:03 +01:00
Zukero
6118fc39d8 Changed (enhanced ?) UI for Map replacement activation in simulator.
Added cool tooltip on the Map replacement simulator showing tiles used
for Ground, Objects and Above layers, as well as coordinates, taking the
active replacements into account.
2015-10-28 16:47:42 +01:00
Zukero
7d5a5008bd v0.4.1 packaging done. 2015-10-27 17:24:30 +01:00
Zukero
56b7ab4b92 v0.4.1 ! Now with ReplaceArea support and simulation tool ! 2015-10-27 17:14:15 +01:00
Zukero
0776bc4109 Added replace areas support in model (to preserve contents on map
saving)
2015-08-12 17:59:28 +02:00
Zukero
c870be2d1f Fixed missing attributes in TMX file loading and writing (sizes in
tilesets).
Added a fancy logo in the workspace selector... could look better
though.
2015-08-12 15:14:30 +02:00
Zukero
1c90d47bdf Update eclipse project's classpath. 2015-08-11 17:38:15 +02:00
46 changed files with 2199 additions and 194 deletions

View File

@@ -10,7 +10,7 @@
<classpathentry kind="lib" path="lib/prefuse.jar"/>
<classpathentry kind="lib" path="lib/rsyntaxtextarea.jar"/>
<classpathentry kind="lib" path="lib/ui.jar"/>
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.1.jar"/>
<classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.2.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -29,6 +29,7 @@
package tiled.core;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Properties;
/**
@@ -36,7 +37,7 @@ import java.util.Properties;
*/
public class Tile
{
private Image image;
private BufferedImage image;
private int id = -1;
private Properties properties;
private TileSet tileset;
@@ -76,7 +77,7 @@ public class Tile
*
* @param i the new image of the tile
*/
public void setImage(Image i) {
public void setImage(BufferedImage i) {
image = i;
}
@@ -133,7 +134,7 @@ public class Tile
*
* @return Image
*/
public Image getImage() {
public BufferedImage getImage() {
if (tileset != null && tileset.sheet != null) return tileset.sheet.getImage(getId());
return image;
}

View File

@@ -74,6 +74,7 @@ public class TileSet implements Iterable<Tile>
private Color transparentColor;
private Image tileSetImage;
public Spritesheet sheet = null;
public Rectangle sheetDimensions;
/**
* Default constructor
@@ -120,8 +121,10 @@ public class TileSet implements Iterable<Tile>
importTileBitmap(buffered, cutter);
}
public void loadFromProject(String name, TMXMap tmxMap) {
public void loadFromProject(String name, TMXMap tmxMap, int tileWidth, int tileHeight) {
sheet = tmxMap.getProject().getSpritesheet(name);
tileDimensions.width = tileWidth;
tileDimensions.height = tileHeight;
int i = 0;
Image tileImage = sheet.getImage(i);
while (tileImage != null) {
@@ -158,7 +161,7 @@ public class TileSet implements Iterable<Tile>
tilesPerRow = basicTileCutter.getTilesPerRow();
}
Image tileImage = cutter.getNextTile();
BufferedImage tileImage = cutter.getNextTile();
while (tileImage != null) {
Tile tile = new Tile();
tile.setImage(tileImage);
@@ -217,7 +220,7 @@ public class TileSet implements Iterable<Tile>
tileDimensions = new Rectangle(tileCutter.getTileDimensions());
int id = 0;
Image tileImage = tileCutter.getNextTile();
BufferedImage tileImage = tileCutter.getNextTile();
while (tileImage != null) {
Tile tile = getTile(id);
tile.setImage(tileImage);

View File

@@ -30,6 +30,8 @@ package tiled.io;
import java.awt.Color;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
@@ -222,9 +224,9 @@ public class TMXMapReader
return o;
}
private Image unmarshalImage(Node t, String baseDir) throws IOException
private BufferedImage unmarshalImage(Node t, String baseDir) throws IOException
{
Image img = null;
BufferedImage img = null;
String source = getAttributeValue(t, "source");
@@ -252,7 +254,7 @@ public class TMXMapReader
// size, somehow makes drawing of the tiles a lot
// faster on various systems (seen on Linux, Windows
// and MacOS X).
img = img.getScaledInstance(
img = (BufferedImage) img.getScaledInstance(
img.getWidth(null), img.getHeight(null),
Image.SCALE_FAST);
}
@@ -382,7 +384,10 @@ public class TMXMapReader
// case.
if (tmxMap.getProject().getSpritesheet(name) != null) {
set.loadFromProject(name, tmxMap);
set.loadFromProject(name, tmxMap, tileWidth, tileHeight);
set.sheetDimensions = new Rectangle();
set.sheetDimensions.width = getAttribute(child, "width", 0);
set.sheetDimensions.height = getAttribute(child, "height", 0);
} else {
@@ -530,7 +535,7 @@ public class TMXMapReader
Node child = children.item(i);
if ("image".equalsIgnoreCase(child.getNodeName())) {
int id = getAttribute(child, "id", -1);
Image img = unmarshalImage(child, baseDir);
BufferedImage img = unmarshalImage(child, baseDir);
tile.setImage(img);
} else if ("animation".equalsIgnoreCase(child.getNodeName())) {
// TODO: fill this in once TMXMapWriter is complete

View File

@@ -257,7 +257,11 @@ public class TMXMapWriter
if (tileBitmapFile != null) {
w.startElement("image");
w.writeAttribute("source", getRelativePath(wp, tileBitmapFile));
if (set.sheetDimensions != null) {
w.writeAttribute("width", set.sheetDimensions.width);
w.writeAttribute("height", set.sheetDimensions.height);
}
Color trans = set.getTransparentColor();
if (trans != null) {
w.writeAttribute("trans", Integer.toHexString(

View File

@@ -64,7 +64,7 @@ public class BasicTileCutter implements TileCutter
this.image = image;
}
public Image getNextTile() {
public BufferedImage getNextTile() {
if (nextY + tileHeight + tileMargin <= image.getHeight()) {
BufferedImage tile =
image.getSubimage(nextX, nextY, tileWidth, tileHeight);

View File

@@ -48,7 +48,7 @@ public interface TileCutter
* @return the next tile image, or <code>null</code> when no more tile
* images are available
*/
public Image getNextTile();
public BufferedImage getNextTile();
/**
* Resets the tile cutter so that the next call to <code>getNextTile</code>

View File

@@ -30,6 +30,7 @@ package tiled.view;
import tiled.core.TileLayer;
import java.awt.*;
import java.awt.image.BufferedImageOp;
/**
* An interface defining methods to render a map.
@@ -50,5 +51,5 @@ public interface MapRenderer
* @param g the graphics context to paint to
* @param layer the layer to paint
*/
public void paintTileLayer(Graphics2D g, TileLayer layer);
public void paintTileLayer(Graphics2D g, TileLayer layer, BufferedImageOp filter);
}

View File

@@ -32,6 +32,8 @@ import tiled.core.Tile;
import tiled.core.TileLayer;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
/**
* The orthogonal map renderer. This is the most basic map renderer, dealing
@@ -51,7 +53,7 @@ public class OrthogonalRenderer implements MapRenderer
map.getHeight() * map.getTileHeight());
}
public void paintTileLayer(Graphics2D g, TileLayer layer) {
public void paintTileLayer(Graphics2D g, TileLayer layer, BufferedImageOp filter ) {
final Rectangle clip = g.getClipBounds();
final int tileWidth = map.getTileWidth();
final int tileHeight = map.getTileHeight();
@@ -74,15 +76,17 @@ public class OrthogonalRenderer implements MapRenderer
final Tile tile = layer.getTileAt(x, y);
if (tile == null)
continue;
final Image image = tile.getImage();
final BufferedImage image = tile.getImage();
if (image == null)
continue;
g.drawImage(
image,
filter,
x * tileWidth,
(y + 1) * tileHeight - image.getHeight(null),
null);
(y + 1) * tileHeight - image.getHeight(null));
}
}
@@ -90,4 +94,5 @@ public class OrthogonalRenderer implements MapRenderer
g.translate(-bounds.x * tileWidth, -bounds.y * tileHeight);
}
}

View File

@@ -1 +1 @@
start "" "javaw.exe" -Xmx512M -cp "lib\jide-oss.jar;lib\ui.jar;lib\junit-4.10.jar;lib\json_simple-1.1.jar;lib\rsyntaxtextarea.jar;lib\prefuse.jar;lib\ATCS_v0.4.0.jar;lib\AndorsTrainer_v0.1.2.jar;lib\bsh-2.0b4.jar" com.gpl.rpg.atcontentstudio.ATContentStudio
start "" "javaw.exe" -Xmx512M -cp "lib\ATCS_v0.4.7.jar;lib\jide-oss.jar;lib\ui.jar;lib\junit-4.10.jar;lib\json_simple-1.1.jar;lib\rsyntaxtextarea.jar;lib\prefuse.jar;lib\AndorsTrainer_v0.1.2.jar;lib\bsh-2.0b4.jar" com.gpl.rpg.atcontentstudio.ATContentStudio

View File

@@ -1,2 +1,2 @@
#!/bin/bash
java -Xmx512M -cp lib/AndorsTrainer_v0.1.2.jar:lib/ATCS_v0.4.0.jar:lib/prefuse.jar:lib/json_simple-1.1.jar:lib/jide-oss.jar:lib/ui.jar:lib/junit-4.10.jar:lib/rsyntaxtextarea.jar:lib/bsh-2.0b4.jar com.gpl.rpg.atcontentstudio.ATContentStudio
java -Xmx512M -cp lib/AndorsTrainer_v0.1.2.jar:lib/ATCS_v0.4.7.jar:lib/prefuse.jar:lib/json_simple-1.1.jar:lib/jide-oss.jar:lib/ui.jar:lib/junit-4.10.jar:lib/rsyntaxtextarea.jar:lib/bsh-2.0b4.jar com.gpl.rpg.atcontentstudio.ATContentStudio

View File

@@ -1 +1 @@
start "" "D:\Programs\jdk1.6.0_24\\bin\javaw.exe" -Xmx512M -cp "lib\jide-oss.jar;lib\ui.jar;lib\junit-4.10.jar;lib\json_simple-1.1.jar;lib\rsyntaxtextarea.jar;lib\ATCS_v0.0.4.jar;lib\AndorsTrainer_V0.1.2.jar" com.gpl.rpg.atcontentstudio.ATContentStudio
start "" "javaw.exe" -Xmx512M -cp "lib\ATCS_v0.4.6.jar;lib\jide-oss.jar;lib\ui.jar;lib\junit-4.10.jar;lib\json_simple-1.1.jar;lib\rsyntaxtextarea.jar;lib\prefuse.jar;lib\AndorsTrainer_v0.1.2.jar;lib\bsh-2.0b4.jar" com.gpl.rpg.atcontentstudio.ATContentStudio

View File

@@ -1,6 +1,6 @@
!include MUI2.nsh
!define VERSION "0.4.0"
!define VERSION "0.4.7"
!define JAVA_BIN "java"
Name "Andor's Trail Content Studio v${VERSION}"

View File

@@ -18,7 +18,7 @@ import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector;
public class ATContentStudio {
public static final String APP_NAME = "Andor's Trail Content Studio";
public static final String APP_VERSION = "v0.4.0";
public static final String APP_VERSION = "v0.4.7";
public static boolean STARTED = false;
public static StudioFrame frame = null;

View File

@@ -2,13 +2,29 @@ package com.gpl.rpg.atcontentstudio.model;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.gpl.rpg.atcontentstudio.model.Project.ResourceSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
import com.gpl.rpg.atcontentstudio.model.maps.Worldmap;
@@ -21,6 +37,9 @@ public class GameSource implements ProjectTreeNode, Serializable {
private static final long serialVersionUID = -1512979360971918158L;
public static final String DEFAULT_REL_PATH_FOR_GAME_RESOURCE = "res"+File.separator+"values"+File.separator+"loadresources.xml";
public static final String DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE = "res"+File.separator+"values"+File.separator+"loadresources_debug.xml";
public transient GameDataSet gameData;
public transient TMXMapSet gameMaps;
public transient SpriteSheetSet gameSprites;
@@ -39,6 +58,8 @@ public class GameSource implements ProjectTreeNode, Serializable {
public transient Project parent = null;
public transient Map<String, List<String>> referencedSourceFiles = null;
public GameSource(File folder, Project parent) {
this.parent = parent;
this.baseFolder = folder;
@@ -59,6 +80,12 @@ public class GameSource implements ProjectTreeNode, Serializable {
}
public void initData() {
if (type == Type.source) {
if (parent.sourceSetToUse == ResourceSet.gameData || parent.sourceSetToUse == ResourceSet.debugData) {
referencedSourceFiles = new LinkedHashMap<String, List<String>>();
readResourceList();
}
}
this.gameData = new GameDataSet(this);
this.gameMaps = new TMXMapSet(this);
this.gameSprites = new SpriteSheetSet(this);
@@ -70,6 +97,58 @@ public class GameSource implements ProjectTreeNode, Serializable {
v.add(worldmap);
}
public void readResourceList() {
File xmlFile = null;
if (parent.sourceSetToUse == ResourceSet.gameData) {
xmlFile = new File(baseFolder, DEFAULT_REL_PATH_FOR_GAME_RESOURCE);
} else if (parent.sourceSetToUse == ResourceSet.debugData) {
xmlFile = new File(baseFolder, DEFAULT_REL_PATH_FOR_DEBUG_RESOURCE);
} else {
return;
}
if (!xmlFile.exists()) return;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc;
try {
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource insrc = new InputSource(new FileInputStream(xmlFile));
// insrc.setSystemId("http://worldmap/");
insrc.setEncoding("UTF-8");
doc = builder.parse(insrc);
Element root = (Element) doc.getElementsByTagName("resources").item(0);
if (root != null) {
NodeList arraysList = root.getElementsByTagName("array");
if (arraysList != null) {
for (int i = 0; i < arraysList.getLength(); i++) {
Element arrayNode = (Element) arraysList.item(i);
String name = arrayNode.getAttribute("name");
List<String> arrayContents = new LinkedList<String>();
NodeList arrayItems = arrayNode.getElementsByTagName("item");
if (arrayItems != null) {
for (int j = 0; j < arrayItems.getLength(); j++) {
arrayContents.add(((Element)arrayItems.item(j)).getTextContent());
}
referencedSourceFiles.put(name, arrayContents);
}
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public Enumeration<ProjectTreeNode> children() {
return v.getNonEmptyElements();

View File

@@ -73,10 +73,19 @@ public class Project implements ProjectTreeNode, Serializable {
public transient Workspace parent;
public Properties knownSpritesheetsProperties = null;
public static enum ResourceSet {
gameData,
debugData,
allFiles
}
public ResourceSet sourceSetToUse = ResourceSet.allFiles;
public Project(Workspace w, String name, File source) {
public Project(Workspace w, String name, File source, ResourceSet sourceSet) {
this.parent = w;
this.name = name;
this.sourceSetToUse = sourceSet;
//CREATE PROJECT
baseFolder = new File(w.baseFolder, name+File.separator);
@@ -220,6 +229,10 @@ public class Project implements ProjectTreeNode, Serializable {
}
}
if (sourceSetToUse == null) {
sourceSetToUse = ResourceSet.allFiles;
}
// long l = new Date().getTime();
baseContent.refreshTransients(this);
// l = new Date().getTime() - l;
@@ -477,6 +490,21 @@ public class Project implements ProjectTreeNode, Serializable {
return null;
}
public int getItemCountIncludingAltered() {
return createdContent.gameData.items.size() + alteredContent.gameData.items.size() + baseContent.gameData.items.size();
}
public Item getItemIncludingAltered(int index) {
if (index < createdContent.gameData.items.size()) {
return createdContent.gameData.items.get(index);
} else if (index < createdContent.gameData.items.size() + alteredContent.gameData.items.size()){
return alteredContent.gameData.items.get(index - createdContent.gameData.items.size());
} else if (index < getItemCountIncludingAltered()) {
return baseContent.gameData.items.get(index - (createdContent.gameData.items.size() + alteredContent.gameData.items.size()));
}
return null;
}
public int getItemIndex(Item item) {
if (item.getDataType() == GameSource.Type.created) {
return createdContent.gameData.items.getIndex(item);
@@ -522,6 +550,13 @@ public class Project implements ProjectTreeNode, Serializable {
return gde;
}
public NPC getNPCIgnoreCase(String id) {
NPC gde = createdContent.gameData.getNPCIgnoreCase(id);
if (gde == null) gde = alteredContent.gameData.getNPCIgnoreCase(id);
if (gde == null) gde = baseContent.gameData.getNPCIgnoreCase(id);
return gde;
}
public int getNPCCount() {
return createdContent.gameData.npcs.size() + baseContent.gameData.npcs.size();
}
@@ -535,6 +570,21 @@ public class Project implements ProjectTreeNode, Serializable {
return null;
}
public int getNPCCountIncludingAltered() {
return createdContent.gameData.npcs.size() + alteredContent.gameData.npcs.size() + baseContent.gameData.npcs.size();
}
public NPC getNPCIncludingAltered(int index) {
if (index < createdContent.gameData.npcs.size()) {
return createdContent.gameData.npcs.get(index);
} else if (index < createdContent.gameData.npcs.size() + alteredContent.gameData.npcs.size()){
return alteredContent.gameData.npcs.get(index - createdContent.gameData.npcs.size());
} else if (index < getNPCCountIncludingAltered()) {
return baseContent.gameData.npcs.get(index - (createdContent.gameData.npcs.size() + alteredContent.gameData.npcs.size()));
}
return null;
}
public int getNPCIndex(NPC npc) {
if (npc.getDataType() == GameSource.Type.created) {
return createdContent.gameData.npcs.getIndex(npc);
@@ -747,13 +797,13 @@ public class Project implements ProjectTreeNode, Serializable {
}
existingNode.getBacklinks().clear();
node.writable = true;
node.state = GameDataElement.State.created;
alteredContent.gameData.addElement(node);
node.link();
node.state = GameDataElement.State.created;
} else {
createdContent.gameData.addElement(node);
node.state = GameDataElement.State.created;
node.link();
node.state = GameDataElement.State.created;
}
fireElementAdded(node, getNodeIndex(node));
}
@@ -833,7 +883,7 @@ public class Project implements ProjectTreeNode, Serializable {
int index = -1;
while (--i >= 0) {
NPC npc = getNPC(i);
if (spawngroup_id.equals(npc.spawngroup_id)) {
if (spawngroup_id.equalsIgnoreCase(npc.spawngroup_id)) {
for (NPC present : result) {
if (present.id.equals(npc.id)) {
alreadyAdded = true;
@@ -851,7 +901,7 @@ public class Project implements ProjectTreeNode, Serializable {
}
if (result.isEmpty()) {
//Fallback case. A single NPC does not declare a spawn group, but is referred by its ID in maps' spawn areas.
NPC npc = getNPC(spawngroup_id);
NPC npc = getNPCIgnoreCase(spawngroup_id);
if (npc != null) result.add(npc);
}
return result;

View File

@@ -146,7 +146,7 @@ public class Workspace implements ProjectTreeNode, Serializable {
}
public static void createProject(final String projectName, final File gameSourceFolder) {
public static void createProject(final String projectName, final File gameSourceFolder, final Project.ResourceSet sourceSet) {
WorkerDialog.showTaskMessage("Creating project "+projectName+"...", ATContentStudio.frame, new Runnable() {
@Override
public void run() {
@@ -154,7 +154,7 @@ public class Workspace implements ProjectTreeNode, Serializable {
Notification.addError("A project named "+projectName+" already exists in this workspace.");
return;
}
Project p = new Project(activeWorkspace, projectName, gameSourceFolder);
Project p = new Project(activeWorkspace, projectName, gameSourceFolder, sourceSet);
activeWorkspace.projects.add(p);
activeWorkspace.projectsName.add(projectName);
activeWorkspace.projectsOpenByName.put(projectName, p.open);

View File

@@ -63,8 +63,8 @@ public class Dialogue extends JSONElement {
spawnAll,
removeSpawnArea,
deactivateSpawnArea,
activateMapChangeArea,
deactivateMapChangeArea
activateMapObjectGroup,
deactivateMapObjectGroup
}
}
@@ -171,7 +171,7 @@ public class Dialogue extends JSONElement {
requirement.parent = this;
if (requirementJson.get("requireType") != null) requirement.type = RequirementType.valueOf((String) requirementJson.get("requireType"));
requirement.required_obj_id = (String) requirementJson.get("requireID");
requirement.required_value = JSONElement.getInteger(Integer.parseInt(requirementJson.get("value").toString()));
if (requirementJson.get("value") != null) requirement.required_value = JSONElement.getInteger(Integer.parseInt(requirementJson.get("value").toString()));
if (requirementJson.get("negate") != null) requirement.negated = (Boolean) requirementJson.get("negate");
requirement.state = State.parsed;
reply.requirements.add(requirement);
@@ -242,8 +242,8 @@ public class Dialogue extends JSONElement {
for (Reward reward : rewards) {
if (reward.reward_obj_id != null) {
switch (reward.type) {
case activateMapChangeArea:
case deactivateMapChangeArea:
case activateMapObjectGroup:
case deactivateMapObjectGroup:
case spawnAll:
case removeSpawnArea:
case deactivateSpawnArea:

View File

@@ -154,7 +154,7 @@ public class GameDataCategory<E extends JSONElement> extends ArrayList<E> implem
dataToSave.add(element.toJson());
}
}
if (dataToSave.isEmpty()) {
if (dataToSave.isEmpty() && jsonFile.exists()) {
if (jsonFile.delete()) {
Notification.addSuccess("File "+jsonFile.getAbsolutePath()+" deleted.");
} else {

View File

@@ -13,6 +13,7 @@ import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.Project.ResourceSet;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SavedSlotCollection;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
@@ -25,6 +26,17 @@ public class GameDataSet implements ProjectTreeNode, Serializable {
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res"+File.separator+"raw"+File.separator;
public static final String DEFAULT_REL_PATH_IN_PROJECT = "json"+File.separator;
public static final String GAME_AC_ARRAY_NAME = "loadresource_actorconditions";
public static final String GAME_DIALOGUES_ARRAY_NAME = "loadresource_conversationlists";
public static final String GAME_DROPLISTS_ARRAY_NAME = "loadresource_droplists";
public static final String GAME_ITEMS_ARRAY_NAME = "loadresource_items";
public static final String GAME_ITEMCAT_ARRAY_NAME = "loadresource_itemcategories";
public static final String GAME_NPC_ARRAY_NAME = "loadresource_monsters";
public static final String GAME_QUESTS_ARRAY_NAME = "loadresource_quests";
public static final String DEBUG_SUFFIX = "_debug";
public static final String RESOURCE_PREFIX = "@raw/";
public static final String FILENAME_SUFFIX = ".json";
public File baseFolder;
public GameDataCategory<ActorCondition> actorConditions;
@@ -67,7 +79,87 @@ public class GameDataSet implements ProjectTreeNode, Serializable {
v.add(quests);
//Start parsing to populate categories' content.
if (parent.type != GameSource.Type.referenced) {
if (parent.type == GameSource.Type.source && (parent.parent.sourceSetToUse == ResourceSet.debugData || parent.parent.sourceSetToUse == ResourceSet.gameData)) {
String suffix = (parent.parent.sourceSetToUse == ResourceSet.debugData) ? DEBUG_SUFFIX : "";
if (parent.referencedSourceFiles.get(GAME_AC_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_AC_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
ActorCondition.fromJson(f, actorConditions);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_DIALOGUES_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_DIALOGUES_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Dialogue.fromJson(f, dialogues);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_DROPLISTS_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_DROPLISTS_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Droplist.fromJson(f, droplists);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_ITEMS_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_ITEMS_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Item.fromJson(f, items);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_ITEMCAT_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_ITEMCAT_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
ItemCategory.fromJson(f, itemCategories);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_NPC_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_NPC_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
NPC.fromJson(f, npcs);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
if (parent.referencedSourceFiles.get(GAME_QUESTS_ARRAY_NAME+suffix) != null) {
for (String resource : parent.referencedSourceFiles.get(GAME_QUESTS_ARRAY_NAME+suffix)) {
File f = new File(baseFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
Quest.fromJson(f, quests);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
} else if (parent.type != GameSource.Type.referenced) {
for (File f : baseFolder.listFiles()) {
if (f.getName().startsWith("actorconditions_")) {
ActorCondition.fromJson(f, actorConditions);
@@ -212,6 +304,16 @@ public class GameDataSet implements ProjectTreeNode, Serializable {
return null;
}
public NPC getNPCIgnoreCase(String id) {
if (npcs == null) return null;
for (NPC gde : npcs) {
if (id.equalsIgnoreCase(gde.id)){
return gde;
}
}
return null;
}
public Quest getQuest(String id) {
if (quests == null) return null;
for (Quest gde : quests) {

View File

@@ -496,6 +496,8 @@ public class Item extends JSONElement {
itemJson.put("id", this.id);
if (this.icon_id != null) itemJson.put("iconID", this.icon_id);
if (this.name != null) itemJson.put("name", this.name);
if(this.display_type != null) itemJson.put("displaytype", this.display_type.toString());
if (this.has_manual_price != null) itemJson.put("hasManualPrice", this.has_manual_price);
if (this.base_market_cost != null) itemJson.put("baseMarketCost", this.base_market_cost);
if (this.category != null) {

View File

@@ -12,6 +12,7 @@ public class KeyArea extends MapObject {
public String dialogue_id = null;
public Dialogue dialogue = null;
public Requirement requirement = null;
public boolean oldSchoolRequirement = true;
public KeyArea(tiled.core.MapObject obj) {
dialogue_id = obj.getProperties().getProperty("phrase");
@@ -29,9 +30,12 @@ public class KeyArea extends MapObject {
requireType = fields[0];
requireId = fields[1];
}
oldSchoolRequirement = true;
} else {
oldSchoolRequirement = false;
}
requirement = new Requirement();
requirement.type = Requirement.RequirementType.valueOf(requireType);
if (requireType != null) requirement.type = Requirement.RequirementType.valueOf(requireType);
requirement.required_obj_id = requireId;
if (requireValue != null) requirement.required_value = Integer.parseInt(requireValue);
requirement.state = GameDataElement.State.parsed;
@@ -59,6 +63,7 @@ public class KeyArea extends MapObject {
dialogue = (Dialogue) newOne;
newOne.addBacklink(parentMap);
}
requirement.elementChanged(oldOne, newOne);
}
@Override
@@ -69,16 +74,36 @@ public class KeyArea extends MapObject {
tmxObject.getProperties().setProperty("phrase", dialogue_id);
}
if (requirement != null) {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
tmxObject.setName(requirement.required_obj_id+":"+Integer.toString(requirement.required_value));
} else {
if (requirement.type != null) {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
}
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
}
}
}
}
public void updateNameFromRequirementChange() {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
name = requirement.required_obj_id+":"+Integer.toString(requirement.required_value);
} else if (oldSchoolRequirement) {
int i = 0;
String futureName = requirement.type.toString() + "#" + Integer.toString(i);
while (parentMap.getMapObject(futureName) != null) {
i++;
futureName = requirement.type.toString() + "#" + Integer.toString(i);
}
this.name = futureName;
}
}
}

View File

@@ -94,6 +94,7 @@ public abstract class MapObject {
public abstract void savePropertiesInTmxObject(tiled.core.MapObject tmxObject);
public static MapObject newMapchange(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Mapchange");
MapObject result = new MapChange(obj);
result.type = Types.mapchange;
initObj(result, obj, parentMap);
@@ -101,6 +102,7 @@ public abstract class MapObject {
}
public static MapObject newSpawnArea(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Spawnarea");
MapObject result = new SpawnArea(obj);
result.type = Types.spawn;
initObj(result, obj, parentMap);
@@ -108,6 +110,7 @@ public abstract class MapObject {
}
public static MapObject newRest(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Rest");
MapObject result = new RestArea(obj);
result.type = Types.rest;
initObj(result, obj, parentMap);
@@ -115,6 +118,7 @@ public abstract class MapObject {
}
public static MapObject newKey(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Key");
MapObject result = new KeyArea(obj);
result.type = Types.key;
initObj(result, obj, parentMap);
@@ -122,6 +126,7 @@ public abstract class MapObject {
}
public static MapObject newReplace(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Replace");
MapObject result = new ReplaceArea(obj);
result.type = Types.replace;
initObj(result, obj, parentMap);
@@ -129,6 +134,7 @@ public abstract class MapObject {
}
public static MapObject newScript(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Script");
MapObject result = new ScriptArea(obj);
result.type = Types.script;
initObj(result, obj, parentMap);
@@ -136,6 +142,7 @@ public abstract class MapObject {
}
public static MapObject newContainer(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Container");
MapObject result = new ContainerArea(obj);
result.type = Types.container;
initObj(result, obj, parentMap);
@@ -143,6 +150,7 @@ public abstract class MapObject {
}
public static MapObject newSign(tiled.core.MapObject obj, TMXMap parentMap) {
if (obj.getName() == null) obj.setName("Sign");
MapObject result = new SignArea(obj);
result.type = Types.sign;
initObj(result, obj, parentMap);

View File

@@ -13,12 +13,18 @@ public class MapObjectGroup {
public String name;
public boolean visible;
public List<MapObject> mapObjects = new ArrayList<MapObject>();
public Boolean active;
public MapObjectGroup(tiled.core.ObjectGroup layer, TMXMap map) {
this.tmxGroup = layer;
this.name = layer.getName();
this.visible = layer.isVisible();
this.parentMap = map;
if (layer.getProperties().get("active") != null) {
active = new Boolean(((String) layer.getProperties().get("active")));
} else {
active = true;
}
for (tiled.core.MapObject obj : layer.getObjectsList()) {
mapObjects.add(MapObject.buildObject(obj, map));
}
@@ -44,6 +50,9 @@ public class MapObjectGroup {
}
tmxGroup.setVisible(visible);
tmxGroup.setName(name);
if (!active) {
tmxGroup.getProperties().put("active", Boolean.toString(active));
}
for (MapObject object : mapObjects) {
tmxGroup.addObject(object.toTmxObject());
}

View File

@@ -1,21 +1,62 @@
package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class ReplaceArea extends MapObject {
public Requirement requirement = null;
public boolean oldSchoolRequirement = true;
public List<ReplaceArea.Replacement> replacements = null;
public ReplaceArea(tiled.core.MapObject obj) {
// TODO Auto-generated constructor stub
// String requireType = obj.getProperties().getProperty("requireType");
String requireId = obj.getProperties().getProperty("requireId");
String requireValue = obj.getProperties().getProperty("requireValue");
if (requireId == null) {
String[] fields = obj.getName().split(":");
if (fields.length == 2) {
// requireType = Requirement.RequirementType.questProgress.toString();
requireValue = fields[1];
requireId = fields[0];
} /*else if (fields.length == 3) {
requireValue = fields[2];
requireType = fields[0];
requireId = fields[1];
}*/
oldSchoolRequirement = true;
} else {
oldSchoolRequirement = false;
}
requirement = new Requirement();
//Replace areas only support questProgress requirements ATM
//requirement.type = Requirement.RequirementType.valueOf(requireType);
requirement.type = Requirement.RequirementType.questProgress;
requirement.required_obj_id = requireId;
if (requireValue != null) requirement.required_value = Integer.parseInt(requireValue);
requirement.state = GameDataElement.State.parsed;
for (Object s : obj.getProperties().keySet()) {
if (replacements == null) replacements = new LinkedList<ReplaceArea.Replacement>();
replacements.add(new Replacement(s.toString(), obj.getProperties().getProperty(s.toString())));
}
}
@Override
public void link() {
// TODO Auto-generated method stub
requirement.parent = parentMap;
requirement.link();
}
@Override
@@ -25,14 +66,79 @@ public class ReplaceArea extends MapObject {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
// TODO Auto-generated method stub
requirement.elementChanged(oldOne, newOne);
}
public ReplaceArea.Replacement addReplacement(String source, String target) {
Replacement repl = new Replacement(source, target);
addReplacement(repl);
return repl;
}
public void addReplacement(ReplaceArea.Replacement repl) {
if (replacements == null) replacements = new LinkedList<ReplaceArea.Replacement>();
replacements.add(repl);
}
// public void removeReplacement(String source, String target) {
// replacedLayers.remove(source);
// }
public void removeReplacement(Replacement repl) {
replacements.remove(repl);
}
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
// TODO Auto-generated method stub
if (replacements != null) {
for(Replacement r : replacements)
tmxObject.getProperties().setProperty(r.sourceLayer, r.targetLayer);
}
if (requirement != null) {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
tmxObject.setName(requirement.required_obj_id+":"+Integer.toString(requirement.required_value));
} else {
tmxObject.getProperties().setProperty("requireType", requirement.type.toString());
if (requirement.required_obj != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj.id);
} else if (requirement.required_obj_id != null) {
tmxObject.getProperties().setProperty("requireId", requirement.required_obj_id);
}
if (requirement.required_value != null) {
tmxObject.getProperties().setProperty("requireValue", requirement.required_value.toString());
}
}
}
}
//Don't use yet !
public void updateNameFromRequirementChange() {
if (oldSchoolRequirement && Requirement.RequirementType.questProgress.equals(requirement.type) && (requirement.negated == null || !requirement.negated)) {
name = requirement.required_obj_id+":"+Integer.toString(requirement.required_value);
} else if (oldSchoolRequirement) {
int i = 0;
String futureName = requirement.type.toString() + "#" + Integer.toString(i);
while (parentMap.getMapObject(futureName) != null) {
i++;
futureName = requirement.type.toString() + "#" + Integer.toString(i);
}
this.name = futureName;
}
}
public class Replacement {
public String sourceLayer, targetLayer;
public Replacement(String source, String target) {
this.sourceLayer = source;
this.targetLayer = target;
}
}
public boolean hasReplacementFor(String name) {
if (name == null) return false;
for (Replacement repl : replacements) {
if (name.equalsIgnoreCase(repl.sourceLayer)) return true;
}
return false;
}
}

View File

@@ -12,6 +12,8 @@ public class SpawnArea extends MapObject {
public int quantity = 1;
public int spawnchance = 10;
public boolean active = true;
public String spawngroup_id;
public List<NPC> spawnGroup = new ArrayList<NPC>();
public SpawnArea(tiled.core.MapObject obj) {
@@ -21,12 +23,20 @@ public class SpawnArea extends MapObject {
if (obj.getProperties().getProperty("spawnchance") != null) {
this.spawnchance = Integer.parseInt(obj.getProperties().getProperty("spawnchance"));
}
if (obj.getProperties().getProperty("active") != null) {
this.active = Boolean.parseBoolean(obj.getProperties().getProperty("active"));
}
if (obj.getProperties().getProperty("spawngroup") != null) {
this.spawngroup_id = obj.getProperties().getProperty("spawngroup");
} else if (obj.getName() != null ){
this.spawngroup_id = obj.getName();
}
}
@Override
public void link() {
if (name != null) {
spawnGroup = parentMap.getProject().getSpawnGroup(name);
if (spawngroup_id != null) {
spawnGroup = parentMap.getProject().getSpawnGroup(spawngroup_id);
} else {
spawnGroup = new ArrayList<NPC>();
}
@@ -61,12 +71,18 @@ public class SpawnArea extends MapObject {
@Override
public void savePropertiesInTmxObject(tiled.core.MapObject tmxObject) {
if (spawngroup_id != null) {
tmxObject.getProperties().setProperty("spawngroup", spawngroup_id);
}
if (quantity != 1) {
tmxObject.getProperties().setProperty("quantity", Integer.toString(quantity));
}
if (spawnchance != 10) {
tmxObject.getProperties().setProperty("spawnchance", Integer.toString(spawnchance));
}
if (!this.active) {
tmxObject.getProperties().setProperty("active", Boolean.toString(active));
}
}
}

View File

@@ -33,6 +33,23 @@ public class TMXMap extends GameDataElement {
private static final long serialVersionUID = 1609502879500898837L;
public static final String GROUND_LAYER_NAME = "Ground";
public static final String OBJECTS_LAYER_NAME = "Objects";
public static final String ABOVE_LAYER_NAME = "Above";
public static final String WALKABLE_LAYER_NAME = "Walkable";
public enum ColorFilter {
black20,
black40,
black60,
black80,
invert,
bw,
redtint,
greentint,
bluetint
}
public File tmxFile = null;
public tiled.core.Map tmxMap = null;
public Set<Spritesheet> usedSpritesheets = null;
@@ -40,6 +57,7 @@ public class TMXMap extends GameDataElement {
public ProjectTreeNode parent;
public Integer outside = null;
public ColorFilter colorFilter = null;
public boolean writable = false;
@@ -56,8 +74,11 @@ public class TMXMap extends GameDataElement {
usedSpritesheets = new HashSet<Spritesheet>();
try {
tmxMap = new TMXMapReader().readMap(tmxFile.getAbsolutePath(), this);
if (tmxMap.getProperties().get("outside") != null) {
outside = new Integer(((String) tmxMap.getProperties().get("outside")));
if (tmxMap.getProperties().get("outdoors") != null) {
outside = new Integer(((String) tmxMap.getProperties().get("outdoors")));
}
if (tmxMap.getProperties().get("colorfilter") != null) {
colorFilter = ColorFilter.valueOf(((String) tmxMap.getProperties().get("colorfilter")));
}
} catch (FileNotFoundException e) {
Notification.addError("Impossible to load TMX map file "+tmxFile.getAbsolutePath());
@@ -91,8 +112,11 @@ public class TMXMap extends GameDataElement {
try {
clone.usedSpritesheets = new HashSet<Spritesheet>();
clone.tmxMap = new TMXMapReader().readMap(new StringReader(this.toXml()), clone);
if (clone.tmxMap.getProperties().get("outside") != null) {
clone.outside = new Integer(((String) clone.tmxMap.getProperties().get("outside")));
if (clone.tmxMap.getProperties().get("outdoors") != null) {
clone.outside = new Integer(((String) clone.tmxMap.getProperties().get("outdoors")));
}
if (clone.tmxMap.getProperties().get("colorfilter") != null) {
clone.colorFilter = ColorFilter.valueOf(((String) tmxMap.getProperties().get("colorfilter")));
}
for (tiled.core.MapLayer layer : clone.tmxMap.getLayers()) {
if (layer instanceof tiled.core.ObjectGroup) {
@@ -204,6 +228,17 @@ public class TMXMap extends GameDataElement {
}
public String toXml() {
if (outside != null && outside == 1) {
tmxMap.getProperties().put("outdoors", Integer.toString(outside));
} else {
tmxMap.getProperties().remove("outdoors");
}
if (colorFilter != null) {
tmxMap.getProperties().put("colorfilter", colorFilter.toString());
} else {
tmxMap.getProperties().remove("colorfilter");
}
for (MapObjectGroup group : groups) {
group.pushBackToTiledProperties();
if (!tmxMap.containsLayer(group.tmxGroup)) {
@@ -335,4 +370,24 @@ public class TMXMap extends GameDataElement {
return result;
}
public MapObject getMapObject(String name) {
MapObject result = null;
for (MapObjectGroup group : groups) {
for (MapObject obj : group.mapObjects) {
if (obj.name.equals(name)) {
result = obj;
break;
}
}
}
return result;
}
public static boolean isPaintedLayerName(String name) {
return GROUND_LAYER_NAME.equalsIgnoreCase(name) ||
OBJECTS_LAYER_NAME.equalsIgnoreCase(name) ||
ABOVE_LAYER_NAME.equalsIgnoreCase(name) ||
WALKABLE_LAYER_NAME.equalsIgnoreCase(name);
}
}

View File

@@ -10,11 +10,14 @@ import java.util.List;
import javax.swing.tree.TreeNode;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project.ResourceSet;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class TMXMapSet implements ProjectTreeNode {
@@ -22,6 +25,11 @@ public class TMXMapSet implements ProjectTreeNode {
public static final String DEFAULT_REL_PATH_IN_SOURCE = "res/xml/";
public static final String DEFAULT_REL_PATH_IN_PROJECT = "maps/";
public static final String GAME_MAPS_ARRAY_NAME = "loadresource_maps";
public static final String DEBUG_SUFFIX = "_debug";
public static final String RESOURCE_PREFIX = "@xml/";
public static final String FILENAME_SUFFIX = ".tmx";
public File mapFolder = null;
public List<TMXMap> tmxMaps;
@@ -29,7 +37,9 @@ public class TMXMapSet implements ProjectTreeNode {
public TMXMapSet(GameSource source) {
this.parent = source;
if (source.type == GameSource.Type.source) this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
if (source.type == GameSource.Type.source) {
this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_SOURCE);
}
else if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
this.mapFolder = new File(source.baseFolder, DEFAULT_REL_PATH_IN_PROJECT);
if (!this.mapFolder.exists()) {
@@ -38,7 +48,22 @@ public class TMXMapSet implements ProjectTreeNode {
}
this.tmxMaps = new ArrayList<TMXMap>();
if (this.mapFolder != null) {
if (source.type == GameSource.Type.source && (source.parent.sourceSetToUse == ResourceSet.debugData || source.parent.sourceSetToUse == ResourceSet.gameData)) {
String suffix = (source.parent.sourceSetToUse == ResourceSet.debugData) ? DEBUG_SUFFIX : "";
if (source.referencedSourceFiles.get(GAME_MAPS_ARRAY_NAME+suffix) != null) {
for (String resource : source.referencedSourceFiles.get(GAME_MAPS_ARRAY_NAME+suffix)) {
File f = new File(mapFolder, resource.replaceAll(RESOURCE_PREFIX, "")+FILENAME_SUFFIX);
if (f.exists()) {
TMXMap map = new TMXMap(this, f);
tmxMaps.add(map);
} else {
Notification.addWarn("Unable to locate resource "+resource+" in the game source for project "+getProject().name);
}
}
}
} else if (this.mapFolder != null) {
for (File f : this.mapFolder.listFiles()) {
if (f.getName().endsWith(".tmx") || f.getName().endsWith(".TMX")) {
TMXMap map = new TMXMap(this, f);

View File

@@ -11,6 +11,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -52,7 +53,7 @@ public class Worldmap extends ArrayList<WorldmapSegment> implements ProjectTreeN
public File worldmapFile;
public GameSource parent;
public Map<String, Map<String, Point>> segments = new HashMap<String, Map<String,Point>>();
public Map<String, Map<String, Point>> segments = new LinkedHashMap<String, Map<String,Point>>();
public Worldmap(GameSource gameSource) {
this.parent = gameSource;
@@ -261,6 +262,7 @@ public class Worldmap extends ArrayList<WorldmapSegment> implements ProjectTreeN
Source input = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2");
transformer.transform(input, output);
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block

View File

@@ -2,12 +2,26 @@ package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.awt.Point;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
@@ -76,7 +90,9 @@ public class WorldmapSegment extends GameDataElement {
return;
}
for (String mapName : mapLocations.keySet()) {
getProject().getMap(mapName).addBacklink(this);
if (getProject().getMap(mapName) != null) {
getProject().getMap(mapName).addBacklink(this);
}
}
}
@@ -103,6 +119,32 @@ public class WorldmapSegment extends GameDataElement {
((Worldmap)parent).save();
}
public String toXml() {
Document doc;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
doc.setXmlVersion("1.0");
Element root = doc.createElement("worldmap");
doc.appendChild(root);
root.appendChild(this.toXmlElement(doc));
Transformer transformer = TransformerFactory.newInstance().newTransformer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Result output = new StreamResult(baos);
Source input = new DOMSource(doc);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2");
transformer.transform(input, output);
return baos.toString();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
return null;
}
public Element toXmlElement(Document doc) {
Element element = doc.createElement("segment");
element.setAttribute("id", id);

View File

@@ -36,7 +36,7 @@ public class AboutEditor extends Editor {
"<br/>" +
"Play <a href=\"https://play.google.com/store/apps/details?id=com.gpl.rpg.AndorsTrail\">Andor's Trail</a> for free on your Android device.<br/>" +
"Visit <a href=\"http://andorstrail.com/\">the official forum</a> to give or receive help.<br/>" +
"Open the project's <a href=\"https://code.google.com/p/andors-trail/\">Google Code page</a> to check out the game's source code.<br/>" +
"Open the project's <a href=\"https://github.com/Zukero/andors-trail/\">GitHub project page</a> to check out the game's source code.<br/>" +
"<br/>" +
"For content creation help, make sure to use the following resources:<br/>" +
"<a href=\"http://andorstrail.com/viewtopic.php?f=6&t=4560\">The contribution guide on the forums</a><br/>" +

View File

@@ -14,6 +14,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
@@ -29,6 +30,7 @@ import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSpinner.NumberEditor;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.SpinnerNumberModel;
@@ -147,6 +149,51 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
});
return tfField;
}
public static JTextArea addTextArea(JPanel pane, String label, String initialValue, boolean editable, final FieldUpdateListener listener) {
String text= initialValue == null ? "" : initialValue.replaceAll("\\n", "\n");
JPanel tfPane = new JPanel();
tfPane.setLayout(new JideBoxLayout(tfPane, JideBoxLayout.LINE_AXIS, 6));
JLabel tfLabel = new JLabel(label);
tfPane.add(tfLabel, JideBoxLayout.FIX);
final JTextArea tfArea = new JTextArea(text);
tfArea.setEditable(editable);
tfPane.add(new JScrollPane(tfArea), JideBoxLayout.VARY);
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
tfPane.add(nullify, JideBoxLayout.FIX);
nullify.setEnabled(editable);
pane.add(tfPane, JideBoxLayout.FIX);
nullify.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tfArea.setText("");
listener.valueChanged(tfArea, null);
}
});
tfArea.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
listener.valueChanged(tfArea, tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n")));
}
@Override
public void insertUpdate(DocumentEvent e) {
listener.valueChanged(tfArea, tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n")));
}
@Override
public void changedUpdate(DocumentEvent e) {
listener.valueChanged(tfArea, tfArea.getText().replaceAll("\n", Matcher.quoteReplacement("\n")));
}
});
// tfArea.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// listener.valueChanged(tfArea, tfArea.getText().replaceAll("\n", "\\n"));
// }
// });
return tfArea;
}
// public static JSpinner addIntegerField(JPanel pane, String label, Integer initialValue, boolean allowNegatives, boolean editable) {
// return addIntegerField(pane, label, initialValue, allowNegatives, editable, nullListener);

View File

@@ -27,6 +27,7 @@ import javax.swing.event.ListDataListener;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameDataElement.State;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
@@ -293,6 +294,7 @@ public class JSONCreationWizard extends JDialog {
creation.id = idField.getText();
JSONCreationWizard.this.setVisible(false);
JSONCreationWizard.this.dispose();
creation.state = State.created;
proj.createElement(creation);
notifyCreated();
ATContentStudio.frame.selectInTree(creation);

View File

@@ -1,5 +1,6 @@
package com.gpl.rpg.atcontentstudio.ui;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
@@ -8,18 +9,26 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import javax.swing.ComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataListener;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.Project.ResourceSet;
import com.gpl.rpg.atcontentstudio.model.Workspace;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
@@ -30,7 +39,8 @@ public class ProjectCreationWizard extends JDialog {
private static final long serialVersionUID = -2854969975146867119L;
final JTextField projectNameField;
final JComboBox atSourceSelectionCombo;
final JComboBox<String> atSourceSelectionCombo;
final JComboBox<Project.ResourceSet> resourceSetToUse;
final JButton browse;
final JButton okButton;
@@ -42,7 +52,62 @@ public class ProjectCreationWizard extends JDialog {
super(ATContentStudio.frame);
setTitle("Create project");
projectNameField = new JTextField();
atSourceSelectionCombo = new JComboBox();
atSourceSelectionCombo = new JComboBox<String>();
resourceSetToUse = new JComboBox<Project.ResourceSet>(new ComboBoxModel<Project.ResourceSet>() {
Project.ResourceSet selected = Project.ResourceSet.allFiles;
@Override
public int getSize() {
return Project.ResourceSet.values().length;
}
@Override
public ResourceSet getElementAt(int index) {
return Project.ResourceSet.values()[index];
}
List<ListDataListener> listeners = new LinkedList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
@Override
public void setSelectedItem(Object anItem) {
selected = (ResourceSet) anItem;
}
@Override
public Object getSelectedItem() {
return selected;
}
});
resourceSetToUse.setRenderer(new ListCellRenderer<Project.ResourceSet>() {
@Override
public Component getListCellRendererComponent(
JList<? extends ResourceSet> list, ResourceSet value,
int index, boolean isSelected, boolean cellHasFocus) {
switch (value) {
case allFiles:
return new JLabel("All available files");
case debugData:
return new JLabel("Debug data");
case gameData:
return new JLabel("Real game data");
default:
return new JLabel();
}
}
});
browse = new JButton("Browse...");
okButton = new JButton("Ok");
cancelButton = new JButton("Cancel");
@@ -103,7 +168,7 @@ public class ProjectCreationWizard extends JDialog {
if (!Workspace.activeWorkspace.knownMapSourcesFolders.contains(atSourceFolder)) {
Workspace.activeWorkspace.knownMapSourcesFolders.add(atSourceFolder);
}
Workspace.createProject(projectNameField.getText(), atSourceFolder);
Workspace.createProject(projectNameField.getText(), atSourceFolder, (Project.ResourceSet)resourceSetToUse.getSelectedItem());
ProjectCreationWizard.this.dispose();
}
});
@@ -154,6 +219,17 @@ public class ProjectCreationWizard extends JDialog {
c.weightx = 20;
panel.add(browse, c);
c.gridy++;
c.gridx = 1;
c.gridwidth = 1;
c.weightx = 20;
panel.add(new JLabel("Resource set: "), c);
c.gridx++;
c.weightx = 80;
c.gridwidth = 2;
panel.add(resourceSetToUse, c);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new GridBagLayout());
GridBagConstraints c2 = new GridBagConstraints();

View File

@@ -370,7 +370,7 @@ public class WorkspaceActions {
}
@Override
public void putValue(String key, Object value) {
public synchronized void putValue(String key, Object value) {
PropertyChangeEvent event = new PropertyChangeEvent(this, key, values.get(key), value);
values.put(key, value);
for (PropertyChangeListener l : listeners) {
@@ -379,7 +379,7 @@ public class WorkspaceActions {
}
@Override
public void setEnabled(boolean b) {
public synchronized void setEnabled(boolean b) {
PropertyChangeEvent event = new PropertyChangeEvent(this, "enabled", isEnabled(), b);
enabled = b;
for (PropertyChangeListener l : listeners) {
@@ -395,12 +395,12 @@ public class WorkspaceActions {
private Set<PropertyChangeListener> listeners = new HashSet<PropertyChangeListener>();
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.add(listener);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
listeners.remove(listener);
}

View File

@@ -6,9 +6,12 @@ import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
@@ -108,9 +111,15 @@ public class WorkspaceSelector extends JFrame {
//Layout, labels and dialog behavior.
setTitle("Select your workspace");
JLabel logoLabel = new JLabel();
try {
logoLabel = new JLabel(new ImageIcon(ImageIO.read(WorkspaceSelector.class.getResource("/com/gpl/rpg/atcontentstudio/img/atcs_logo_banner.png"))), JLabel.CENTER);
} catch (IOException e1) {}
JPanel dialogPane = new JPanel();
dialogPane.setLayout(new BorderLayout());
dialogPane.add(logoLabel, BorderLayout.NORTH);
dialogPane.add(new JLabel("Workspace : "), BorderLayout.WEST);
dialogPane.add(combo, BorderLayout.CENTER);
dialogPane.add(browse, BorderLayout.EAST);

View File

@@ -23,6 +23,7 @@ import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
@@ -79,7 +80,7 @@ public class DialogueEditor extends JSONElementEditor {
private static final int SHOP_INDEX = 5;
private JTextField idField;
private JTextField messageField;
private JTextArea messageField;
private MyComboBox switchToNpcBox;
private RewardsListModel rewardsListModel;
@@ -127,7 +128,7 @@ public class DialogueEditor extends JSONElementEditor {
createButtonPane(pane, dialogue.getProject(), dialogue, Dialogue.class, dialogue.getImage(), null, listener);
idField = addTextField(pane, "Internal ID: ", dialogue.id, dialogue.writable, listener);
messageField = addTextField(pane, "Message: ", dialogue.message, dialogue.writable, listener);
messageField = addTextArea(pane, "Message: ", dialogue.message, dialogue.writable, listener);
switchToNpcBox = addNPCBox(pane, dialogue.getProject(), "Switch active NPC to: ", dialogue.switch_to_npc, dialogue.writable, listener);
CollapsiblePanel rewards = new CollapsiblePanel("Reaching this phrase gives the following rewards: ");
@@ -320,8 +321,13 @@ public class DialogueEditor extends JSONElementEditor {
}
if (reward.type != null) {
switch (reward.type) {
case activateMapChangeArea:
case deactivateMapChangeArea:
case activateMapObjectGroup:
case deactivateMapObjectGroup:
rewardMap = addMapBox(pane, ((Dialogue)target).getProject(), "Map Name: ", reward.map, writable, listener);
rewardObjId = addTextField(pane, "Group ID: ", reward.reward_obj_id, writable, listener);
rewardObj = null;
rewardValue = null;
break;
case deactivateSpawnArea:
case removeSpawnArea:
case spawnAll:
@@ -717,63 +723,72 @@ public class DialogueEditor extends JSONElementEditor {
JLabel label = ((JLabel)c);
Dialogue.Reward reward = (Dialogue.Reward)value;
if (reward.type != null) {
String rewardObjDesc = null;
if( reward.reward_obj != null) {
rewardObjDesc = reward.reward_obj.getDesc();
} else if (reward.reward_obj_id != null) {
rewardObjDesc = reward.reward_obj_id;
}
switch (reward.type) {
case activateMapChangeArea:
label.setText("Activate mapchange area "+rewardObjDesc+" on map "+reward.map_name);
break;
case actorCondition:
label.setText("Give actor condition "+rewardObjDesc+" for "+reward.reward_value+" turns");
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case alignmentChange:
label.setText("Change alignment for faction "+rewardObjDesc+" : "+reward.reward_value);
break;
case createTimer:
label.setText("Create timer "+rewardObjDesc);
break;
case deactivateMapChangeArea:
label.setText("Deactivate mapchange area "+rewardObjDesc+" on map "+reward.map_name);
break;
case deactivateSpawnArea:
label.setText("Deactivate spawnarea area "+rewardObjDesc+" on map "+reward.map_name);
break;
case dropList:
label.setText("Give contents of droplist "+rewardObjDesc);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case giveItem:
label.setText("Give "+reward.reward_value+" "+rewardObjDesc);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case questProgress:
label.setText("Give quest progress "+rewardObjDesc+":"+reward.reward_value);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case removeSpawnArea:
label.setText("Remove all monsters in spawnarea area "+rewardObjDesc+" on map "+reward.map_name);
break;
case skillIncrease:
label.setText("Increase skill "+rewardObjDesc+" level");
break;
case spawnAll:
label.setText("Respawn all monsters in spawnarea area "+rewardObjDesc+" on map "+reward.map_name);
break;
}
} else {
label.setText("New, undefined reward");
}
decorateRewardJLabel(label, reward);
}
return c;
}
}
public static void decorateRewardJLabel(JLabel label, Dialogue.Reward reward) {
if (reward.type != null) {
String rewardObjDesc = null;
if( reward.reward_obj != null) {
rewardObjDesc = reward.reward_obj.getDesc();
} else if (reward.reward_obj_id != null) {
rewardObjDesc = reward.reward_obj_id;
}
switch (reward.type) {
case activateMapObjectGroup:
label.setText("Activate map object group "+rewardObjDesc+" on map "+reward.map_name);
label.setIcon(new ImageIcon(DefaultIcons.getObjectLayerIcon()));
break;
case actorCondition:
label.setText("Give actor condition "+rewardObjDesc+" for "+reward.reward_value+" turns");
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case alignmentChange:
label.setText("Change alignment for faction "+rewardObjDesc+" : "+reward.reward_value);
break;
case createTimer:
label.setText("Create timer "+rewardObjDesc);
break;
case deactivateMapObjectGroup:
label.setText("Deactivate map object group "+rewardObjDesc+" on map "+reward.map_name);
label.setIcon(new ImageIcon(DefaultIcons.getObjectLayerIcon()));
break;
case deactivateSpawnArea:
label.setText("Deactivate spawnarea area "+rewardObjDesc+" on map "+reward.map_name);
label.setIcon(new ImageIcon(DefaultIcons.getNPCIcon()));
break;
case dropList:
label.setText("Give contents of droplist "+rewardObjDesc);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case giveItem:
label.setText("Give "+reward.reward_value+" "+rewardObjDesc);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case questProgress:
label.setText("Give quest progress "+rewardObjDesc+":"+reward.reward_value);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case removeSpawnArea:
label.setText("Remove all monsters in spawnarea area "+rewardObjDesc+" on map "+reward.map_name);
label.setIcon(new ImageIcon(DefaultIcons.getNPCIcon()));
break;
case skillIncrease:
label.setText("Increase skill "+rewardObjDesc+" level");
break;
case spawnAll:
label.setText("Respawn all monsters in spawnarea area "+rewardObjDesc+" on map "+reward.map_name);
label.setIcon(new ImageIcon(DefaultIcons.getNPCIcon()));
break;
}
} else {
label.setText("New, undefined reward");
}
}
public static class RepliesListModel implements ListModel {
@@ -981,19 +996,23 @@ public class DialogueEditor extends JSONElementEditor {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (c instanceof JLabel) {
((JLabel)c).setText(((Requirement)value).getDesc());
if (((Requirement)value).required_obj != null) {
if (((Requirement)value).required_obj.getIcon() != null) {
((JLabel)c).setIcon(new ImageIcon(((Requirement)value).required_obj.getIcon()));
}
} if (((Requirement)value).type == null) {
((JLabel)c).setText("New, undefined requirement.");
}
decorateRequirementJLabel((JLabel)c, (Requirement)value);
}
return c;
}
}
public static void decorateRequirementJLabel(JLabel label, Requirement req) {
label.setText(req.getDesc());
if (req.required_obj != null) {
if (req.required_obj.getIcon() != null) {
label.setIcon(new ImageIcon(req.required_obj.getIcon()));
}
} if (req.type == null) {
label.setText("New, undefined requirement.");
}
}
public class DialogueFieldUpdater implements FieldUpdateListener {
@Override
public void valueChanged(JComponent source, Object value) {
@@ -1019,6 +1038,10 @@ public class DialogueEditor extends JSONElementEditor {
} else if (source == rewardTypeCombo) {
if (selectedReward.type != value) {
selectedReward.type = (Dialogue.Reward.RewardType) value;
if (selectedReward.map != null) {
selectedReward.map.removeBacklink(dialogue);
}
selectedReward.map = null;
selectedReward.map_name = null;
selectedReward.reward_obj = null;
selectedReward.reward_obj_id = null;

View File

@@ -1,24 +1,32 @@
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import org.fife.ui.rtextarea.ColorBackgroundPainterStrategy;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
@@ -79,6 +87,7 @@ public class QuestEditor extends JSONElementEditor {
stagesTable.getColumnModel().getColumn(3).setMinWidth(130);
stagesTable.getColumnModel().getColumn(3).setMaxWidth(130);
stagesTable.setCellSelectionEnabled(true);
stagesTable.getColumnModel().getColumn(1).setCellRenderer(new MultilineCellRenderer());
stagesPane.add(new JScrollPane(stagesTable), BorderLayout.CENTER);
if (quest.writable) {
JPanel buttonPane = new JPanel();
@@ -330,6 +339,48 @@ public class QuestEditor extends JSONElementEditor {
updateJsonViewText(quest.toJsonString());
}
}
public class MultilineCellRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 6539816623608859506L;
public MultilineCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
//setOpaque(true);
}
@Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
if (isSelected) {
setForeground(stagesTable.getSelectionForeground());
setBackground(stagesTable.getSelectionBackground());
} else {
setForeground(stagesTable.getForeground());
setBackground(stagesTable.getBackground());
}
setFont(stagesTable.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (stagesTable.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(BorderFactory.createLineBorder(getBackground(), 1));
}
setText((value == null ? "" : value.toString()));
int fh = getFontMetrics(getFont()).getHeight();
// int tl = getText().length();
setSize(stagesTable.getWidth(), fh);
stagesTable.setRowHeight(row, getPreferredSize().height);
return this;
}
}

View File

@@ -1,7 +1,11 @@
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors.dialoguetree;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -9,6 +13,12 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.ToolTipManager;
import prefuse.Display;
import prefuse.Visualization;
import prefuse.action.ActionList;
@@ -42,7 +52,11 @@ import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.ui.gamedataeditors.DialogueEditor;
import com.gpl.rpg.atcontentstudio.ui.map.TMXMapEditor.TMXReplacementViewer;
import com.jidesoft.swing.JideBoxLayout;
public class DialogueGraphView extends Display {
@@ -147,6 +161,7 @@ public class DialogueGraphView extends Display {
setSize(500,500);
pan(250, 250);
setHighQuality(true);
addControlListener(new TooltipControl());
addControlListener(new DoubleClickControl());
addControlListener(new WheelZoomControl());
addControlListener(new ZoomControl());
@@ -434,6 +449,90 @@ public class DialogueGraphView extends Display {
}
}
}
class TooltipControl extends ControlAdapter {
@Override
public void itemEntered(VisualItem item, MouseEvent e) {
if (item.get(TARGET) != null) {
tooltippedItem = item;
if (!tooltipActivated) {
setToolTipText("");
ToolTipManager.sharedInstance().registerComponent(DialogueGraphView.this);
ToolTipManager.sharedInstance().setEnabled(true);
tooltipActivated = true;
}
}
}
@Override
public void itemExited(VisualItem item, MouseEvent e) {
//Hides the tooltip...
ToolTipManager.sharedInstance().setEnabled(false);
ToolTipManager.sharedInstance().unregisterComponent(DialogueGraphView.this);
tooltipActivated = false;
}
}
JToolTip tt = null;
private VisualItem tooltippedItem = null;
private VisualItem lastTTItem = null;
private boolean tooltipActivated = false;
@Override
public Point getToolTipLocation(MouseEvent event) {
return new Point(event.getX() + 5, event.getY() + 5);
}
@Override
public JToolTip createToolTip() {
if (tt == null) tt = super.createToolTip();
if (tooltippedItem == lastTTItem) {
return tt;
}
tt = super.createToolTip();
lastTTItem = tooltippedItem;
tt.setLayout(new BorderLayout());
JPanel content = new JPanel();
content.setLayout(new JideBoxLayout(content, JideBoxLayout.PAGE_AXIS));
JLabel label;
if (tooltippedItem != null) {
Object target = tooltippedItem.get(TARGET);
if (target != null) {
if (target instanceof Dialogue) {
Dialogue d = (Dialogue) target;
label = new JLabel(new ImageIcon(DefaultIcons.getDialogueIcon()));
label.setText(d.id);
content.add(label, JideBoxLayout.FIX);
if (tooltippedItem.get(REPLY) == null) {
if (d.rewards != null && !d.rewards.isEmpty()) {
for (Dialogue.Reward r : d.rewards) {
label = new JLabel();
DialogueEditor.decorateRewardJLabel(label, r);
content.add(label, JideBoxLayout.FIX);
}
}
} else {
Object replObj = tooltippedItem.get(REPLY);
if (replObj instanceof Dialogue.Reply) {
Dialogue.Reply r = (Dialogue.Reply) replObj;
if (r.requirements != null && !r.requirements.isEmpty()) {
for (Requirement req : r.requirements) {
label = new JLabel();
DialogueEditor.decorateRequirementJLabel(label, req);
content.add(label, JideBoxLayout.FIX);
}
}
}
}
}
}
}
tt.add(content, BorderLayout.CENTER);
tt.setPreferredSize(tt.getLayout().preferredLayoutSize(tt));
return tt;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,9 @@ import javax.swing.JViewport;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
@@ -46,6 +49,9 @@ public class WorldMapEditor extends Editor {
private static final long serialVersionUID = -8358238912588729094L;
private RSyntaxTextArea editorPane;
public EditMode editMode = EditMode.moveViewSelect;
public enum EditMode {
@@ -72,6 +78,10 @@ public class WorldMapEditor extends Editor {
add(editorTabsHolder, BorderLayout.CENTER);
editorTabsHolder.add("Map", buildSegmentTab(worldmap));
JScrollPane xmlScroller = new JScrollPane(getXmlEditorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
xmlScroller.getVerticalScrollBar().setUnitIncrement(16);
editorTabsHolder.add("XML", xmlScroller);
}
@Override
@@ -80,6 +90,22 @@ public class WorldMapEditor extends Editor {
}
public JPanel getXmlEditorPane() {
JPanel pane = new JPanel();
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
editorPane = new RSyntaxTextArea();
editorPane.setText(((WorldmapSegment)target).toXml());
editorPane.setEditable(false);
editorPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
pane.add(editorPane, JideBoxLayout.VARY);
return pane;
}
public void updateXmlViewText(String text) {
editorPane.setText(text);
}
private JPanel buildSegmentTab(final WorldmapSegment worldmap) {
JPanel pane = new JPanel();

View File

@@ -81,7 +81,7 @@ public class WorldMapView extends JComponent implements Scrollable {
for (tiled.core.MapLayer layer : ((TMXMap)map).tmxMap) {
if (layer instanceof tiled.core.TileLayer && layer.isVisible()) {
if (layer.getName().equalsIgnoreCase("walkable")) continue;
renderer.paintTileLayer(g2, (tiled.core.TileLayer) layer);
renderer.paintTileLayer(g2, (tiled.core.TileLayer) layer, null);
} else if (layer instanceof tiled.core.ObjectGroup && layer.isVisible()) {
// paintObjectGroup(g2, map, (tiled.core.ObjectGroup) layer);
}

View File

@@ -151,10 +151,10 @@ public class SpritesheetEditor extends Editor {
TableColumn col;
while (columns.hasMoreElements()) {
col = columns.nextElement();
col.setMinWidth(sheet.spriteWidth + 1);
col.setMaxWidth(sheet.spriteWidth + 1);
col.setMinWidth(sheet.spriteWidth + 4);
col.setMaxWidth(sheet.spriteWidth + 4);
}
spritesTable.setRowHeight(sheet.spriteHeight + 1);
spritesTable.setRowHeight(sheet.spriteHeight + 4);
pane.add(new JScrollPane(spritesTable), BorderLayout.CENTER);
}
}

View File

@@ -18,7 +18,7 @@ public class ItemsTableView extends ElementTableView {
private static final long serialVersionUID = 1474255176349837609L;
public ItemsTableView(Project proj) {
super(new ItemsTableModel(proj), "Compare "+proj.getItemCount()+" items.", new ImageIcon(DefaultIcons.getItemIcon()));
super(new ItemsTableModel(proj), "Compare "+proj.getItemCountIncludingAltered()+" items.", new ImageIcon(DefaultIcons.getItemIcon()));
}
private static class ItemsTableModel implements TableModel {
@@ -32,7 +32,7 @@ public class ItemsTableView extends ElementTableView {
@Override
public int getRowCount() {
// return proj.getItemCount() + 1;
return proj.getItemCount();
return proj.getItemCountIncludingAltered();
}
@Override
@@ -130,7 +130,7 @@ public class ItemsTableView extends ElementTableView {
// return getColumnName(columnIndex);
// }
// Item item = proj.getItem(rowIndex - 1);
Item item = proj.getItem(rowIndex);
Item item = proj.getItemIncludingAltered(rowIndex);
boolean canUse = item.category != null && item.category.action_type == ItemCategory.ActionType.use;
boolean canEquip = item.category != null && item.category.action_type == ItemCategory.ActionType.equip;
switch (columnIndex) {

View File

@@ -0,0 +1,124 @@
package com.gpl.rpg.atcontentstudio.ui.tools;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.RenderingHints;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
/**
* This Composite emulates the behaviour of Android's ColorMatrixColorFilter,
* except that you have to use this one a posteriori instead of a filtering paint.
*
* It applies a ColorMatrix to the destination pixels, regardless of potential "source" pixels.
* Once created and activated through Graphics2D.setComposite(), just paint anything over the pixels you want "filtered".
*
* Works on a per-pixel basis, no sampling of surrounding pixels, or anything.
*
* @author pochat
*
*/
public class MatrixComposite implements Composite {
final float[] matrix = new float[20];
/**
* Dismisses the source pixels. Just paint it black, or white, it only affects the dest RGB with the following formulae.
*
* R' = a*R + b*G + c*B + d*A + e;
* G' = f*R + g*G + h*B + i*A + j;
* B' = k*R + l*G + m*B + n*A + o;
* A' = p*R + q*G + r*B + s*A + t;
*
* @param matrix a flat float[20] array, giving the a..t values;
*/
public MatrixComposite(float[] matrix) {
if (matrix.length != this.matrix.length) {
throw new Error("MatrixComposite matrix must be of length "+this.matrix.length);
}
System.arraycopy(matrix, 0, this.matrix, 0, this.matrix.length);
}
@Override
public CompositeContext createContext(ColorModel srcColorModel,
ColorModel dstColorModel, RenderingHints hints) {
return new MatrixCompositeContext(this);
}
class MatrixCompositeContext implements CompositeContext {
MatrixComposite composite;
public MatrixCompositeContext(MatrixComposite composite) {
this.composite = composite;
}
@Override
public void dispose() {
}
@Override
public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
throw new IllegalStateException(
"Source and destination must store pixels as INT.");
}
int width = Math.min(src.getWidth(), dstIn.getWidth());
int height = Math.min(src.getHeight(), dstIn.getHeight());
float alpha = 1.0f;
int[] srcPixel = new int[4];
int[] dstPixel = new int[4];
int[] srcPixels = new int[width];
int[] dstPixels = new int[width];
for (int y = 0; y < height; y++) {
src.getDataElements(0, y, width, 1, srcPixels);
dstIn.getDataElements(0, y, width, 1, dstPixels);
for (int x = 0; x < width; x++) {
// pixels are stored as INT_ARGB
// our arrays are [R, G, B, A]
int pixel = srcPixels[x];
srcPixel[0] = (pixel >> 16) & 0xFF;
srcPixel[1] = (pixel >> 8) & 0xFF;
srcPixel[2] = (pixel ) & 0xFF;
srcPixel[3] = (pixel >> 24) & 0xFF;
pixel = dstPixels[x];
dstPixel[0] = (pixel >> 16) & 0xFF;
dstPixel[1] = (pixel >> 8) & 0xFF;
dstPixel[2] = (pixel ) & 0xFF;
dstPixel[3] = (pixel >> 24) & 0xFF;
int[] result = applyMatrix(matrix, dstPixel);
// mixes the result with the opacity
dstPixels[x] = ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 |
(int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
}
dstOut.setDataElements(0, y, width, 1, dstPixels);
}
}
private int[] applyMatrix(float[] matrix, int[] dstPixel) {
int[] result = new int[4];
result[0] = Math.max(0, Math.min(255, (int) (matrix[ 0] * dstPixel[0] + matrix[ 1] * dstPixel[1] + matrix[ 2] * dstPixel[2] + matrix[ 3] * dstPixel[3] + matrix[ 4]) ));
result[1] = Math.max(0, Math.min(255, (int) (matrix[ 5] * dstPixel[0] + matrix[ 6] * dstPixel[1] + matrix[ 7] * dstPixel[2] + matrix[ 8] * dstPixel[3] + matrix[ 9]) ));
result[2] = Math.max(0, Math.min(255, (int) (matrix[10] * dstPixel[0] + matrix[11] * dstPixel[1] + matrix[12] * dstPixel[2] + matrix[13] * dstPixel[3] + matrix[14]) ));
result[3] = Math.max(0, Math.min(255, (int) (matrix[15] * dstPixel[0] + matrix[16] * dstPixel[1] + matrix[17] * dstPixel[2] + matrix[18] * dstPixel[3] + matrix[19]) ));
return result;
}
}
}

View File

@@ -17,7 +17,7 @@ public class NPCsTableView extends ElementTableView {
private static final long serialVersionUID = -4196852140899079621L;
public NPCsTableView(Project proj) {
super(new NPCsTableModel(proj), "Compare "+proj.getNPCCount()+" NPCs.", new ImageIcon(DefaultIcons.getNPCIcon()));
super(new NPCsTableModel(proj), "Compare "+proj.getNPCCountIncludingAltered()+" NPCs.", new ImageIcon(DefaultIcons.getNPCIcon()));
}
private static class NPCsTableModel implements TableModel {
@@ -30,7 +30,7 @@ public class NPCsTableView extends ElementTableView {
@Override
public int getRowCount() {
return proj.getNPCCount();
return proj.getNPCCountIncludingAltered();
}
@Override
@@ -109,7 +109,7 @@ public class NPCsTableView extends ElementTableView {
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
NPC npc = proj.getNPC(rowIndex);
NPC npc = proj.getNPCIncludingAltered(rowIndex);
switch (columnIndex) {
case 0: return new ImageIcon(npc.getIcon()); // Icon
case 1: return npc.id; //ID