v0.4.1 ! Now with ReplaceArea support and simulation tool !

This commit is contained in:
Zukero
2015-10-27 17:14:15 +01:00
parent 0776bc4109
commit 56b7ab4b92
10 changed files with 924 additions and 22 deletions

View File

@@ -90,4 +90,5 @@ public class OrthogonalRenderer implements MapRenderer
g.translate(-bounds.x * tileWidth, -bounds.y * tileHeight);
}
}

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.1";
public static boolean STARTED = false;
public static StudioFrame frame = 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,6 +30,9 @@ 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);
@@ -59,6 +63,7 @@ public class KeyArea extends MapObject {
dialogue = (Dialogue) newOne;
newOne.addBacklink(parentMap);
}
requirement.elementChanged(oldOne, newOne);
}
@Override
@@ -69,16 +74,34 @@ 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 {
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

@@ -2,28 +2,61 @@ 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 Map<String, String> replacedLayers = null;
public List<ReplaceArea.Replacement> replacements = null;
public ReplaceArea(tiled.core.MapObject obj) {
// 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 (replacedLayers == null) replacedLayers = new LinkedHashMap<String, String>();
replacedLayers.put(s.toString(), obj.getProperties().getProperty(s.toString()));
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
@@ -33,16 +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) {
if (replacedLayers != null) {
for(String s : replacedLayers.keySet())
tmxObject.getProperties().setProperty(s, replacedLayers.get(s));
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

@@ -33,6 +33,12 @@ 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 File tmxFile = null;
public tiled.core.Map tmxMap = null;
public Set<Spritesheet> usedSpritesheets = null;
@@ -335,4 +341,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

@@ -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;
@@ -103,6 +117,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

@@ -18,15 +18,20 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
@@ -36,6 +41,8 @@ import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
@@ -45,6 +52,12 @@ import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
@@ -79,6 +92,7 @@ import com.gpl.rpg.atcontentstudio.model.maps.SpawnArea;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.ui.BooleanBasedCheckBox;
import com.gpl.rpg.atcontentstudio.ui.CollapsiblePanel;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.ui.Editor;
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
@@ -139,6 +153,15 @@ public class TMXMapEditor extends Editor {
private JSpinner requirementValue;
private BooleanBasedCheckBox requirementNegated;
private JList replacementsList;
private ReplacementsListModel replacementsListModel;
private ReplaceArea.Replacement selectedReplacement;
private JButton addReplacement;
private JButton deleteReplacement;
private JPanel replacementEditPane;
private JComboBox sourceLayer;
private JComboBox targetLayer;
private TMXViewer tmxViewer;
public TMXMapEditor(TMXMap map) {
@@ -156,12 +179,16 @@ public class TMXMapEditor extends Editor {
JScrollPane tmxScroller = new JScrollPane(getTmxEditorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane xmlScroller = new JScrollPane(getXmlEditorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane replScroller = new JScrollPane(getReplacementSimulatorPane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
xmlScroller.getVerticalScrollBar().setUnitIncrement(16);
editorTabsHolder.add("TMX", tmxScroller);
editorTabsHolder.add("XML", xmlScroller);
editorTabsHolder.add("Replacements", replScroller);
}
public JPanel getTmxEditorPane() {
final TMXMap map = (TMXMap) target;
final FieldUpdateListener listener = new MapFieldUpdater();
@@ -453,7 +480,60 @@ public class TMXMapEditor extends Editor {
});
pane.add(tACPane, JideBoxLayout.FIX);
} else if (selected instanceof ReplaceArea) {
//TODO replace area edition
//Replace areas only use questProgress requirements ATM
//requirementTypeCombo = addEnumValueBox(pane, "Requirement type: ", Requirement.RequirementType.values(), ((ReplaceArea)selected).requirement.type, ((TMXMap)target).writable, listener);
requirementParamsPane = new JPanel();
requirementParamsPane.setLayout(new JideBoxLayout(requirementParamsPane, JideBoxLayout.PAGE_AXIS, 6));
pane.add(requirementParamsPane, JideBoxLayout.FIX);
updateRequirementParamsPane(requirementParamsPane, ((ReplaceArea)selected).requirement, listener);
CollapsiblePanel replacementListPane = new CollapsiblePanel("Replacements");
replacementListPane.setLayout(new JideBoxLayout(replacementListPane, JideBoxLayout.PAGE_AXIS));
replacementsListModel = new ReplacementsListModel((ReplaceArea) selected);
replacementsList = new JList(replacementsListModel);
replacementsList.setCellRenderer(new ReplacementsListRenderer((ReplaceArea) selected));
replacementListPane.add(new JScrollPane(replacementsList), JideBoxLayout.VARY);
JPanel replacementListButtonsPane = new JPanel();
replacementListButtonsPane.setLayout(new JideBoxLayout(replacementListButtonsPane, JideBoxLayout.LINE_AXIS));
addReplacement = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
replacementListButtonsPane.add(addReplacement, JideBoxLayout.FIX);
addReplacement.setEnabled(((TMXMap)target).writable);
addReplacement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
replacementsListModel.addObject(null, null);
}
});
deleteReplacement = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
replacementListButtonsPane.add(deleteReplacement, JideBoxLayout.FIX);
deleteReplacement.setEnabled(false);
deleteReplacement.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
replacementsListModel.removeObject(selectedReplacement);
}
});
replacementListButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
replacementListPane.add(replacementListButtonsPane, JideBoxLayout.FIX);
replacementEditPane = new JPanel();
replacementListPane.add(replacementEditPane, JideBoxLayout.FIX);
pane.add(new JScrollPane(replacementListPane), JideBoxLayout.VARY);
replacementsList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedReplacement = (ReplaceArea.Replacement)replacementsList.getSelectedValue();
updateReplacementsEditPane(replacementEditPane, (ReplaceArea)selected, selectedReplacement, listener);
deleteReplacement.setEnabled(((TMXMap)target).writable);
}
});
} else if (selected instanceof RestArea) {
pane.add(new JLabel("Rest areas have no parameters"), JideBoxLayout.FIX);
} else if (selected instanceof ScriptArea) {
@@ -553,6 +633,37 @@ public class TMXMapEditor extends Editor {
pane.repaint();
}
public void updateReplacementsEditPane(JPanel pane, ReplaceArea area, ReplaceArea.Replacement replacement, final FieldUpdateListener listener) {
boolean writable = ((TMXMap)target).writable;
pane.removeAll();
sourceLayer = new JComboBox<String>(new ReplacementsLayersComboModel(area, true, replacement.sourceLayer));
targetLayer = new JComboBox<String>(new ReplacementsLayersComboModel(area, false, replacement.targetLayer));
sourceLayer.setEnabled(writable);
targetLayer.setEnabled(writable);
sourceLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
listener.valueChanged(sourceLayer, sourceLayer.getModel().getSelectedItem());
}
});
targetLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
listener.valueChanged(targetLayer, targetLayer.getModel().getSelectedItem());
}
});
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.LINE_AXIS));
pane.add(new JLabel("Replace "), JideBoxLayout.FIX);
pane.add(sourceLayer, JideBoxLayout.FIX);
pane.add(new JLabel(" by "), JideBoxLayout.FIX);
pane.add(targetLayer, JideBoxLayout.FIX);
pane.add(new JPanel(), JideBoxLayout.VARY);
}
public JPanel getXmlEditorPane() {
JPanel pane = new JPanel();
pane.setLayout(new JideBoxLayout(pane, JideBoxLayout.PAGE_AXIS, 6));
@@ -569,6 +680,214 @@ public class TMXMapEditor extends Editor {
editorPane.setText(text);
}
public JPanel getReplacementSimulatorPane() {
JPanel replacementSimulator = new JPanel();
replacementSimulator.setLayout(new JideBoxLayout(replacementSimulator, JideBoxLayout.PAGE_AXIS));
final JCheckBox walkableVisibleBox = new JCheckBox("Show \""+TMXMap.WALKABLE_LAYER_NAME+"\" layer.");
JPanel areasActivationPane = new JPanel();
areasActivationPane.setLayout(new JideBoxLayout(areasActivationPane, JideBoxLayout.LINE_AXIS));
TreeModel areasTreeModel = new ReplaceAreasActivationTreeModel();
final JTree areasTree = new JTree(areasTreeModel);
areasTree.setEditable(false);
areasTree.setRootVisible(false);
areasTree.setCellRenderer(new ReplaceAreasActivationTreeCellRenderer());
areasActivationPane.add(new JScrollPane(areasTree), JideBoxLayout.FIX);
final JToggleButton activate = new JToggleButton("Activate ReplaceArea(s)");
areasActivationPane.add(activate, JideBoxLayout.VARY);
final TMXReplacementViewer viewer = new TMXReplacementViewer((TMXMap)target);
replacementSimulator.add(walkableVisibleBox, JideBoxLayout.FIX);
replacementSimulator.add(areasActivationPane, JideBoxLayout.FIX);
replacementSimulator.add(viewer, JideBoxLayout.VARY);
walkableVisibleBox.setSelected(true);
walkableVisibleBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
viewer.showWalkable = walkableVisibleBox.isSelected();
viewer.revalidate();
viewer.repaint();
}
});
activate.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (areasTree.getSelectionPaths() == null) return;
for (TreePath paths : areasTree.getSelectionPaths()) {
Object target = paths.getLastPathComponent();
if (target instanceof ReplaceArea) {
viewer.activeReplacements.put((ReplaceArea) target, activate.isSelected());
viewer.updateLayers();
viewer.revalidate();
viewer.repaint();
} else if (target instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)target).mapObjects) {
if (obj instanceof ReplaceArea) {
viewer.activeReplacements.put((ReplaceArea) obj, activate.isSelected());
}
viewer.updateLayers();
viewer.revalidate();
viewer.repaint();
}
}
}
}
});
areasTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
if (areasTree.getSelectionPaths() == null) return;
for (TreePath paths : areasTree.getSelectionPaths()) {
Object target = paths.getLastPathComponent();
if (target instanceof ReplaceArea) {
activate.setSelected(viewer.activeReplacements.get((ReplaceArea) target));
} else if (target instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)target).mapObjects) {
activate.setSelected(true);
if (obj instanceof ReplaceArea) {
if (!viewer.activeReplacements.get((ReplaceArea) obj)) {
activate.setSelected(false);
}
}
}
}
}
}
});
return replacementSimulator;
}
public class ReplaceAreasActivationTreeModel implements TreeModel {
@Override
public Object getRoot() {
return target;
}
@Override
public Object getChild(Object parent, int index) {
int i = index;
if (parent instanceof TMXMap) {
for (MapObjectGroup group : ((TMXMap)parent).groups) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof ReplaceArea) {
if (i == 0) return group;
i--;
break;
}
}
}
} else if (parent instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)parent).mapObjects) {
if (obj instanceof ReplaceArea) {
if (i == 0) return obj;
i--;
}
}
}
return null;
}
@Override
public int getChildCount(Object parent) {
int count = 0;
if (parent instanceof TMXMap) {
for (MapObjectGroup group : ((TMXMap)parent).groups) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof ReplaceArea) {
count++;
break;
}
}
}
} else if (parent instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)parent).mapObjects) {
if (obj instanceof ReplaceArea) {
count++;
}
}
}
return count;
}
@Override
public boolean isLeaf(Object node) {
return node instanceof ReplaceArea;
}
@Override
public void valueForPathChanged(TreePath path, Object newValue) {
// TODO Auto-generated method stub
}
@Override
public int getIndexOfChild(Object parent, Object child) {
int index = 0;
if (parent instanceof TMXMap) {
for (MapObjectGroup group : ((TMXMap)parent).groups) {
if (group == child) return index;
for (MapObject obj : group.mapObjects) {
if (obj instanceof ReplaceArea) {
index++;
break;
}
}
}
} else if (parent instanceof MapObjectGroup) {
for (MapObject obj : ((MapObjectGroup)parent).mapObjects) {
if (obj == child) return index;
if (obj instanceof ReplaceArea) {
index++;
}
}
}
return index;
}
List<TreeModelListener> listeners = new LinkedList<TreeModelListener>();
@Override
public void addTreeModelListener(TreeModelListener l) {
listeners.add(l);
}
@Override
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(l);
}
}
public class ReplaceAreasActivationTreeCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 3988638353699460533L;
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
Component c = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (c instanceof JLabel) {
JLabel label = (JLabel)c;
if (value instanceof MapObjectGroup) {
label.setText(((MapObjectGroup)value).name);
label.setIcon(new ImageIcon(DefaultIcons.getObjectLayerIcon()));
} else if (value instanceof ReplaceArea) {
label.setText(((ReplaceArea)value).name);
label.setIcon(new ImageIcon(DefaultIcons.getReplaceIcon()));
}
}
return c;
}
}
public static JList addTMXMapSpritesheetsList(JPanel pane, TMXMap tmxMap) {
final JList list = new JList(new TMXMapSpritesheetsListModel(tmxMap));
list.addMouseListener(new MouseAdapter() {
@@ -672,6 +991,139 @@ public class TMXMapEditor extends Editor {
}
}
public class ReplacementsListModel implements ListModel {
public ReplaceArea area;
public ReplacementsListModel(ReplaceArea area) {
this.area = area;
}
@Override
public int getSize() {
if (area.replacements == null) return 0;
return area.replacements.size();
}
@Override
public Object getElementAt(int index) {
if (index < 0 || index > getSize()) return null;
if (area.replacements == null) return null;
return area.replacements.get(index);
}
public void objectChanged(ReplaceArea.Replacement repl) {
int index = area.replacements.indexOf(repl);
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index));
}
}
public void addObject(String source, String target) {
ReplaceArea.Replacement repl = area.addReplacement(source, target);
int index = area.replacements.indexOf(repl);
for (ListDataListener l : listeners) {
l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
}
}
public void removeObject(ReplaceArea.Replacement repl) {
int index = area.replacements.indexOf(repl);
area.removeReplacement(repl);
for (ListDataListener l : listeners) {
l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index));
}
}
List<ListDataListener> listeners = new ArrayList<ListDataListener>();
@Override
public void addListDataListener(ListDataListener l) {
listeners.add(l);
}
@Override
public void removeListDataListener(ListDataListener l) {
listeners.remove(l);
}
}
public class ReplacementsListRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = -6182599528961565957L;
public ReplaceArea area;
public ReplacementsListRenderer(ReplaceArea area) {
super();
this.area = area;
}
@Override
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 label = (JLabel)c;
ReplaceArea.Replacement repl = (ReplaceArea.Replacement)value;
label.setText(repl.sourceLayer+" -> "+repl.targetLayer);
}
return c;
}
}
public class ReplacementsLayersComboModel implements ComboBoxModel<String> {
ReplaceArea area;
boolean modelForSource = false;
public List<String> availableLayers = new LinkedList<String>();
public String selected;
public ReplacementsLayersComboModel(ReplaceArea area, boolean modelForSource, String selected) {
this.area = area;
this.modelForSource = modelForSource;
this.selected = selected;
availableLayers.add(null);
for (tiled.core.MapLayer layer : ((TMXMap)target).tmxMap.getLayers()) {
if (layer instanceof tiled.core.TileLayer) {
if (modelForSource && !TMXMap.isPaintedLayerName(layer.getName())) {
continue;
}
if (modelForSource && area.hasReplacementFor(layer.getName()) && !layer.getName().equals(selected)) {
continue;
}
availableLayers.add(layer.getName());
}
}
}
@Override
public String getElementAt(int index) {
return availableLayers.get(index);
}
@Override
public Object getSelectedItem() {
return selected;
}
@Override
public int getSize() {
return availableLayers.size();
}
List<ListDataListener> listeners = new ArrayList<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 = (String)anItem;
}
}
public class MapObjectsListModel implements ListModel {
public MapObjectGroup group;
@@ -1373,6 +1825,7 @@ public class TMXMapEditor extends Editor {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.changeType((Requirement.RequirementType)requirementTypeCombo.getSelectedItem());
updateRequirementParamsPane(requirementParamsPane, area.requirement, this);
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == requirementObj) {
if (selectedMapObject instanceof KeyArea) {
@@ -1383,24 +1836,56 @@ public class TMXMapEditor extends Editor {
} else {
area.requirement.required_obj_id = null;
}
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.required_obj = (GameDataElement) value;
if (area.requirement.required_obj != null) {
area.requirement.required_obj_id = area.requirement.required_obj.id;
} else {
area.requirement.required_obj_id = null;
}
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == requirementObjId) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.required_obj_id = (String) value;
area.requirement.required_obj = null;
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.required_obj_id = (String) value;
area.requirement.required_obj = null;
}
} else if (source == requirementValue) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.required_value = (Integer) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.required_value = (Integer) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
} else if (source == requirementNegated) {
if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject;
area.requirement.negated = (Boolean) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject;
area.requirement.negated = (Boolean) value;
if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
}
}
} else if (source == sourceLayer) {
selectedReplacement.sourceLayer = (String)value;
replacementsListModel.objectChanged(selectedReplacement);
groupObjectsListModel.objectChanged(selectedMapObject);
} else if (source == targetLayer) {
selectedReplacement.targetLayer = (String)value;
replacementsListModel.objectChanged(selectedReplacement);
groupObjectsListModel.objectChanged(selectedMapObject);
}
if (modified) {
if (map.state != GameDataElement.State.modified) {
map.state = GameDataElement.State.modified;
@@ -1433,5 +1918,204 @@ public class TMXMapEditor extends Editor {
message.repaint();
}
public class TMXReplacementViewer extends JPanel implements Scrollable {
private static final long serialVersionUID = 2845032142029325865L;
private TMXMap map;
public ReplaceArea highlighted = null;
public boolean showWalkable = true;
private OrthogonalRenderer renderer;
private String groundName, objectsName, aboveName, walkableName;
private Map<String, tiled.core.TileLayer> layersByName = new LinkedHashMap<String, tiled.core.TileLayer>();
private tiled.core.TileLayer ground, objects, above, walkable;
private Map<String, List<ReplaceArea>> replacementsForLayer = new LinkedHashMap<String, List<ReplaceArea>>();
public Map<ReplaceArea, Boolean> activeReplacements = new LinkedHashMap<ReplaceArea, Boolean>();
public TMXReplacementViewer(final TMXMap map) {
this.map = map;
renderer = createRenderer(map.tmxMap);
init();
setPreferredSize(renderer.getMapSize());
setOpaque(true);
}
public void init() {
groundName = objectsName = aboveName = walkableName = null;
layersByName.clear();
ground = objects = above = walkable = null;
replacementsForLayer.clear();
for (tiled.core.MapLayer layer : map.tmxMap.getLayers()) {
if (layer instanceof tiled.core.TileLayer) {
layersByName.put(layer.getName(), (tiled.core.TileLayer)layer);
if (TMXMap.GROUND_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
groundName = layer.getName();
} else if (TMXMap.OBJECTS_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
objectsName = layer.getName();
} else if (TMXMap.ABOVE_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
aboveName = layer.getName();
} else if (TMXMap.WALKABLE_LAYER_NAME.equalsIgnoreCase(layer.getName())) {
walkableName = layer.getName();
}
}
}
for (MapObjectGroup group : map.groups) {
for (MapObject object : group.mapObjects) {
if (object instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea)object;
if (!activeReplacements.containsKey(area)) {
activeReplacements.put(area, true);
}
for (ReplaceArea.Replacement repl : area.replacements) {
if (replacementsForLayer.get(repl.sourceLayer) == null) {
replacementsForLayer.put(repl.sourceLayer, new LinkedList<ReplaceArea>());
}
replacementsForLayer.get(repl.sourceLayer).add(area);
}
}
}
}
updateLayers();
}
public void updateLayers() {
ground = mergeReplacements(groundName);
objects = mergeReplacements(objectsName);
above = mergeReplacements(aboveName);
walkable = mergeReplacements(walkableName);
}
private tiled.core.TileLayer mergeReplacements(String layerName) {
tiled.core.TileLayer merged = null;
if (layerName != null && layersByName.get(layerName) != null) {
tiled.core.TileLayer original = layersByName.get(layerName);
merged = new tiled.core.TileLayer(original.getBounds());
merged.copyFrom(original);
if (replacementsForLayer.containsKey(layerName)) {
for (ReplaceArea area : replacementsForLayer.get(layerName)) {
if (activeReplacements.get(area)) {
String targetName = null;
for (ReplaceArea.Replacement repl : area.replacements) {
if (layerName.equals(repl.sourceLayer)) {
targetName = repl.targetLayer;
}
}
if (targetName != null) {
for (int x = area.x / 32; x < (area.x + area.w) / 32; x++) {
for (int y = area.y / 32; y < (area.y + area.h) / 32; y++) {
merged.setTileAt(x, y, layersByName.get(targetName).getTileAt(x, y));
}
}
}
}
}
}
}
return merged;
}
public void setHighlight(ReplaceArea selected) {
highlighted = selected;
invalidate();
}
public void paintComponent(Graphics g) {
final Graphics2D g2d = (Graphics2D) g.create();
final Rectangle clip = g2d.getClipBounds();
// Draw a gray background
g2d.setPaint(new Color(100, 100, 100));
g2d.fill(clip);
// Draw each tile map layer
if (ground != null) {
renderer.paintTileLayer(g2d, ground);
}
if (objects != null) {
renderer.paintTileLayer(g2d, objects);
}
if (above != null) {
renderer.paintTileLayer(g2d, above);
}
if (walkable != null && showWalkable) {
renderer.paintTileLayer(g2d, walkable);
}
if (highlighted != null) {
drawObject(highlighted, g2d, new Color(190, 20, 20));
}
g2d.dispose();
}
private void drawObject(MapObject object, Graphics2D g2d, Color color) {
g2d.setPaint(color);
g2d.drawRect(object.x+1, object.y+1, object.w-3, object.h-3);
g2d.drawRect(object.x+2, object.y+2, object.w-5, object.h-5);
g2d.setPaint(color.darker().darker());
g2d.drawLine(object.x, object.y + object.h - 1, object.x + object.w - 1, object.y + object.h - 1);
g2d.drawLine(object.x + object.w - 1, object.y, object.x + object.w - 1, object.y + object.h - 1);
g2d.drawLine(object.x + 3, object.y + 3, object.x + object.w - 4, object.y + 3);
g2d.drawLine(object.x + 3, object.y + 3, object.x + 3, object.y + object.h - 4);
g2d.setPaint(color.brighter().brighter().brighter());
g2d.drawLine(object.x, object.y, object.x + object.w - 1, object.y);
g2d.drawLine(object.x, object.y, object.x, object.y + object.h - 1);
g2d.drawLine(object.x + 3, object.y + object.h - 4, object.x + object.w - 4, object.y + object.h - 4);
g2d.drawLine(object.x + object.w - 4, object.y + 3, object.x + object.w - 4, object.y + object.h - 4);
Image img = object.getIcon();
g2d.setColor(new Color(255, 255, 255, 120));
g2d.fillRect(object.x + 2, object.y + 2, img.getWidth(null), img.getHeight(null));
g2d.drawImage(object.getIcon(), object.x + 2, object.y + 2, null);
}
private OrthogonalRenderer createRenderer(tiled.core.Map map) {
return new OrthogonalRenderer(map);
}
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
public int getScrollableUnitIncrement(Rectangle visibleRect,
int orientation, int direction) {
if (orientation == SwingConstants.HORIZONTAL)
return ((TMXMap)target).tmxMap.getTileWidth();
else
return ((TMXMap)target).tmxMap.getTileHeight();
}
public int getScrollableBlockIncrement(Rectangle visibleRect,
int orientation, int direction) {
if (orientation == SwingConstants.HORIZONTAL) {
final int tileWidth = ((TMXMap)target).tmxMap.getTileWidth();
return (visibleRect.width / tileWidth - 1) * tileWidth;
} else {
final int tileHeight = ((TMXMap)target).tmxMap.getTileHeight();
return (visibleRect.height / tileHeight - 1) * tileHeight;
}
}
public boolean getScrollableTracksViewportWidth() {
return false;
}
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
}

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,18 @@ 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;
}
private JPanel buildSegmentTab(final WorldmapSegment worldmap) {
JPanel pane = new JPanel();