Compare commits

...

7 Commits

Author SHA1 Message Date
Zukero
8d8a1e122e v0.6.3 released! 2017-07-26 23:49:16 +02:00
Zukero
fe62c05b4b Fixed many bugs in the TMX Maps management. Added the
removeQuestProgress dialogue reward type. Initiallized the GDEVisitor
class to help with finding dependencies (through the Beanshell console
only for now).
2017-07-26 15:50:50 +02:00
Zukero
f93d03dbd3 Deleting a TMX Map also removes it from created/altered worldmaps, and
marks these as modified.
2017-07-25 19:16:35 +02:00
Zukero
7eb5c7c208 Fixed NPC editor bug where inflicted actor conditions weren't managed
correctly.
Fixed Worldmap saving and deletion (mostly the * management was crap)
Fixed multi-selection deletion.
2017-07-25 17:01:31 +02:00
Zukero
e04c3ee2fd v0.6.2 released! Redesigned WorldMap editor. Many new UI features. Fixed
Trainer.
2017-05-05 15:07:50 +02:00
Zukero
38a1e90aad Redesigned Worldmap editor. Better UI & support for town labels.
Searchable map list that mirrors the on-map selection.
2017-05-04 14:27:38 +02:00
Zukero
83d459021b Simple bug fix that broke the NPC icon selection window. 2017-04-21 15:55:15 +02:00
25 changed files with 1325 additions and 316 deletions

View File

@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="res"/>
<classpathentry kind="src" path="hacked-libtiled"/>
<classpathentry kind="src" path="siphash-zackehh/src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/jide-oss.jar"/>
<classpathentry kind="lib" path="lib/json_simple-1.1.jar"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<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/bsh-2.0b4.jar"/>
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.3.jar"/>
<classpathentry kind="lib" path="lib/jsoup-1.10.2.jar" sourcepath="lib/jsoup-1.10.2-sources.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="res"/>
<classpathentry kind="src" path="hacked-libtiled"/>
<classpathentry kind="src" path="siphash-zackehh/src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/jide-oss.jar"/>
<classpathentry kind="lib" path="lib/json_simple-1.1.jar"/>
<classpathentry kind="lib" path="lib/junit-4.10.jar"/>
<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/bsh-2.0b4.jar"/>
<classpathentry kind="lib" path="lib/jsoup-1.10.2.jar" sourcepath="lib/jsoup-1.10.2-sources.jar"/>
<classpathentry kind="lib" path="lib/AndorsTrainer_v0.1.4.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jardesc>
<jar path="ATContentStudio/ATCS_v0.6.1.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ATContentStudio/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/>
<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
<sealing sealJar="false">
<packagesToSeal/>
<packagesToUnSeal/>
</sealing>
</manifest>
<selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false">
<javaElement handleIdentifier="=ATContentStudio/siphash-zackehh\/src\/main\/java"/>
<javaElement handleIdentifier="=ATContentStudio/res"/>
<javaElement handleIdentifier="=ATContentStudio/src"/>
<javaElement handleIdentifier="=ATContentStudio/hacked-libtiled"/>
</selectedElements>
</jardesc>
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
<jardesc>
<jar path="ATCS/ATCS_v0.6.3.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ATCS/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/>
<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
<sealing sealJar="false">
<packagesToSeal/>
<packagesToUnSeal/>
</sealing>
</manifest>
<selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false">
<javaElement handleIdentifier="=ATCS/res"/>
<javaElement handleIdentifier="=ATCS/src"/>
<javaElement handleIdentifier="=ATCS/siphash-zackehh\/src\/main\/java"/>
<javaElement handleIdentifier="=ATCS/hacked-libtiled"/>
</selectedElements>
</jardesc>

View File

@@ -111,11 +111,14 @@ public class Map implements Iterable<MapLayer>
public MapLayer addLayer(MapLayer layer) {
layer.setMap(this);
layers.add(layer);
if (layer instanceof TileLayer) {
tileLayers.add((TileLayer) layer);
layers.add(layer);
} else if (layer instanceof ObjectGroup) {
layers.insertElementAt(layer, objectGroups.size());
objectGroups.add((ObjectGroup) layer);
} else {
layers.add(layer);
}
return layer;
}

View File

@@ -181,7 +181,12 @@ public class TMXMapWriter
firstgid += tileset.getMaxTileId() + 1;
}
for (MapLayer layer : map) {
for (MapLayer layer : map.getTileLayers()) {
writeMapLayer(layer, w, wp);
}
for (MapLayer layer : map.getObjectGroup()) {
if (map.getTileLayers().contains(layer)) continue;
writeMapLayer(layer, w, wp);
}
firstGidPerTileset = null;

BIN
itemScroll.xcf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,7 +1,7 @@
!include MUI2.nsh
!define VERSION "0.6.1"
!define TRAINER_VERSION "0.1.3"
!define VERSION "0.6.3"
!define TRAINER_VERSION "0.1.4"
!define JAVA_BIN "javaw"
Name "Andor's Trail Content Studio v${VERSION}"

View File

@@ -24,7 +24,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.6.1";
public static final String APP_VERSION = "v0.6.3";
public static boolean STARTED = false;
public static StudioFrame frame = null;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -670,7 +670,7 @@ public class Project implements ProjectTreeNode, Serializable {
public Spritesheet getSpritesheet(int index) {
if (index < createdContent.gameSprites.spritesheets.size()) {
return createdContent.gameSprites.spritesheets.get(index);
} else if (index < getQuestCount()){
} else if (index < getSpritesheetCount()){
return getSpritesheet(baseContent.gameSprites.spritesheets.get(index - createdContent.gameSprites.spritesheets.size()).id);
}
return null;

View File

@@ -54,6 +54,7 @@ public class Dialogue extends JSONElement {
public enum RewardType {
questProgress,
removeQuestProgress,
dropList,
skillIncrease,
actorCondition,
@@ -264,6 +265,7 @@ public class Dialogue extends JSONElement {
reward.reward_obj = proj.getItem(reward.reward_obj_id);
break;
case questProgress:
case removeQuestProgress:
reward.reward_obj = proj.getQuest(reward.reward_obj_id);
if (reward.reward_obj != null && reward.reward_value != null) {
QuestStage stage = ((Quest)reward.reward_obj).getStage(reward.reward_value);

View File

@@ -12,7 +12,7 @@ import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
public class ReplaceArea extends MapObject {
public Requirement requirement = null;
public boolean oldSchoolRequirement = true;
public boolean oldSchoolRequirement = false;
public List<ReplaceArea.Replacement> replacements = null;
@@ -26,14 +26,12 @@ public class ReplaceArea extends MapObject {
// requireType = Requirement.RequirementType.questProgress.toString();
requireValue = fields[1];
requireId = fields[0];
oldSchoolRequirement = true;
} /*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
@@ -45,6 +43,7 @@ public class ReplaceArea extends MapObject {
for (Object s : obj.getProperties().keySet()) {
if (!TMXMap.isPaintedLayerName(s.toString())) continue;
if (replacements == null) replacements = new ArrayList<ReplaceArea.Replacement>();
replacements.add(new Replacement(s.toString(), obj.getProperties().getProperty(s.toString())));
}

View File

@@ -273,11 +273,12 @@ public class TMXMap extends GameDataElement {
public void save() {
if (writable) {
String xml = toXml();
try {
//TODO: check in fileutils, to test the workspace's filesystem once at startup, and figure out how many of these can occur, instead of hard-coded '2'
dismissNextChangeNotif += 2;
FileWriter w = new FileWriter(tmxFile);
w.write(toXml());
w.write(xml);
w.close();
this.state = State.saved;
changedOnDisk = false;

View File

@@ -35,6 +35,7 @@ import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.GameSource.Type;
import com.gpl.rpg.atcontentstudio.model.Project;
@@ -222,6 +223,7 @@ public class Worldmap extends ArrayList<WorldmapSegment> implements ProjectTreeN
for (WorldmapSegment segment : this) {
root.appendChild(segment.toXmlElement(doc));
segment.state = GameDataElement.State.saved;
}
saveDocToFile(doc, worldmapFile);

View File

@@ -24,6 +24,7 @@ import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.SaveEvent;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
@@ -32,6 +33,8 @@ public class WorldmapSegment extends GameDataElement {
private static final long serialVersionUID = 2658610076889592723L;
public static final String TEMP_LABEL_KEY = "ATCS_INTERNAL_TEMPORARY_KEY_FOR_LABEL";
public int segmentX;
public int segmentY;
public Map<String, Point> mapLocations = new LinkedHashMap<String, Point>();
@@ -102,8 +105,28 @@ public class WorldmapSegment extends GameDataElement {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
boolean modified = false;
if (newOne == null && writable) {
//A referenced map may have been deleted.
if (mapLocations.containsKey(oldOne.id)) {
mapLocations.remove(oldOne.id);
modified = true;
}
for (String label : labelledMaps.keySet()) {
if (labelledMaps.get(label).contains(oldOne.id)) {
labelledMaps.get(label).remove(oldOne.id);
modified = true;
}
}
}
oldOne.removeBacklink(this);
if(newOne != null) newOne.addBacklink(this);
if (modified) {
this.state = GameDataElement.State.modified;
childrenChanged(new ArrayList<ProjectTreeNode>());
}
}
@Override
@@ -154,6 +177,7 @@ public class WorldmapSegment extends GameDataElement {
map.setAttribute("x", Integer.toString(mapLocations.get(s).x + segmentX));
map.setAttribute("y", Integer.toString(mapLocations.get(s).y + segmentY));
for (String label : labelledMaps.keySet()) {
if (TEMP_LABEL_KEY.equals(label)) continue;
if (labelledMaps.get(label).contains(s)) {
map.setAttribute("area", label);
}
@@ -161,7 +185,9 @@ public class WorldmapSegment extends GameDataElement {
element.appendChild(map);
}
for (NamedArea area : labels.values()) {
for (String key : labels.keySet()) {
if (TEMP_LABEL_KEY.equals(key)) continue;
NamedArea area = labels.get(key);
Element namedArea = doc.createElement("namedarea");
namedArea.setAttribute("id", area.id);
namedArea.setAttribute("name", area.name);

View File

@@ -227,6 +227,10 @@ public class DefaultIcons {
public static Image getCreateTileLayerImage() { return getImage(CREATE_TILE_LAYER_RES); }
public static Image getCreateTileLayerIcon() { return getIcon(CREATE_TILE_LAYER_RES); }
private static String LABEL_RES = "/com/gpl/rpg/atcontentstudio/img/label.png";
public static Image getLabelImage() { return getImage(LABEL_RES); }
public static Image getLabelIcon() { return getIcon(LABEL_RES); }
private static String ZOOM_RES = "/com/gpl/rpg/atcontentstudio/img/zoom.png";
public static Image getZoomImage() { return getImage(ZOOM_RES); }
public static Image getZoomIcon() { return getIcon(ZOOM_RES); }

View File

@@ -140,14 +140,14 @@ public class ProjectsTree extends JPanel {
projectsTree.addTreeSelectionListener(new TreeSelectionListener() {
@Override
public void valueChanged(TreeSelectionEvent e) {
List<TreePath> newPaths = new ArrayList<TreePath>();
for (TreePath path : e.getPaths()) {
if (e.isAddedPath(path)) newPaths.add(path);
}
// List<TreePath> newPaths = new ArrayList<TreePath>();
// for (TreePath path : e.getPaths()) {
// if (e.isAddedPath(path)) newPaths.add(path);
// }
if (e.getPath() == null) {
ATContentStudio.frame.actions.selectionChanged(null, newPaths.toArray(new TreePath[newPaths.size()]));
ATContentStudio.frame.actions.selectionChanged(null, projectsTree.getSelectionPaths());
} else {
ATContentStudio.frame.actions.selectionChanged((ProjectTreeNode) e.getPath().getLastPathComponent(), newPaths.toArray(new TreePath[newPaths.size()]));
ATContentStudio.frame.actions.selectionChanged((ProjectTreeNode) e.getPath().getLastPathComponent(), projectsTree.getSelectionPaths());
}
}
});

View File

@@ -31,8 +31,12 @@ import com.gpl.rpg.atcontentstudio.model.Workspace;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory;
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
import com.gpl.rpg.atcontentstudio.model.maps.Worldmap;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
import com.gpl.rpg.atcontentstudio.model.saves.SavedGamesSet;
import com.gpl.rpg.atcontentstudio.model.tools.writermode.WriterModeData;
import com.gpl.rpg.atcontentstudio.model.tools.writermode.WriterModeDataSet;
@@ -122,19 +126,45 @@ public class WorkspaceActions {
ATContentStudio.frame.closeEditor(element);
element.childrenRemoved(new ArrayList<ProjectTreeNode>());
if (element instanceof JSONElement) {
@SuppressWarnings("unchecked")
GameDataCategory<JSONElement> category = (GameDataCategory<JSONElement>) element.getParent();
category.remove(element);
if (impactedCategories.get(category) == null) {
impactedCategories.put(category, new HashSet<File>());
if (element.getParent() instanceof GameDataCategory<?>) {
@SuppressWarnings("unchecked")
GameDataCategory<JSONElement> category = (GameDataCategory<JSONElement>) element.getParent();
category.remove(element);
if (impactedCategories.get(category) == null) {
impactedCategories.put(category, new HashSet<File>());
}
GameDataElement newOne = element.getProject().getGameDataElement(((JSONElement)element).getClass(), element.id);
if (element instanceof Quest) {
for (QuestStage oldStage : ((Quest) element).stages) {
QuestStage newStage = newOne != null ? ((Quest) newOne).getStage(oldStage.progress) : null;
for (GameDataElement backlink : oldStage.getBacklinks()) {
backlink.elementChanged(oldStage, newStage);
}
}
}
for (GameDataElement backlink : element.getBacklinks()) {
backlink.elementChanged(element, newOne);
}
impactedCategories.get(category).add(((JSONElement) element).jsonFile);
}
impactedCategories.get(category).add(((JSONElement) element).jsonFile);
} else if (element instanceof TMXMap) {
TMXMapSet parent = (TMXMapSet) element.getParent();
parent.tmxMaps.remove(element);
((TMXMap)element).delete();
GameDataElement newOne = element.getProject().getMap(element.id);
for (GameDataElement backlink : element.getBacklinks()) {
backlink.elementChanged(element, newOne);
}
} else if (element instanceof WriterModeData) {
WriterModeDataSet parent = (WriterModeDataSet) element.getParent();
parent.writerModeDataList.remove(element);
} else if (element instanceof WorldmapSegment) {
if (element.getParent() instanceof Worldmap) {
((Worldmap)element.getParent()).remove(element);
element.save();
for (GameDataElement backlink : element.getBacklinks()) {
backlink.elementChanged(element, element.getProject().getWorldmapSegment(element.id));
}
}
}
}
new Thread() {
@@ -165,20 +195,52 @@ public class WorkspaceActions {
@Override
public void run() {
node.childrenRemoved(new ArrayList<ProjectTreeNode>());
if (node.getParent() instanceof GameDataCategory<?>) {
((GameDataCategory<?>)node.getParent()).remove(node);
List<SaveEvent> events = node.attemptSave();
if (events == null || events.isEmpty()) {
node.save();
} else {
new SaveItemsWizard(events, null).setVisible(true);
if (node instanceof JSONElement) {
if (node.getParent() instanceof GameDataCategory<?>) {
((GameDataCategory<?>)node.getParent()).remove(node);
List<SaveEvent> events = node.attemptSave();
if (events == null || events.isEmpty()) {
node.save();
} else {
new SaveItemsWizard(events, null).setVisible(true);
}
GameDataElement newOne = node.getProject().getGameDataElement(((JSONElement)node).getClass(), node.id);
if (node instanceof Quest) {
for (QuestStage oldStage : ((Quest) node).stages) {
QuestStage newStage = newOne != null ? ((Quest) newOne).getStage(oldStage.progress) : null;
for (GameDataElement backlink : oldStage.getBacklinks()) {
backlink.elementChanged(oldStage, newStage);
}
}
}
for (GameDataElement backlink : node.getBacklinks()) {
backlink.elementChanged(node, newOne);
}
}
// ((GameDataCategory<?>)node.getParent()).remove(node);
// List<SaveEvent> events = node.attemptSave();
// if (events == null || events.isEmpty()) {
// node.save();
// } else {
// new SaveItemsWizard(events, null).setVisible(true);
// }
} else if (node instanceof TMXMap) {
TMXMapSet parent = (TMXMapSet) node.getParent();
parent.tmxMaps.remove(node);
((TMXMap)node).delete();
GameDataElement newOne = node.getProject().getMap(node.id);
for (GameDataElement backlink : node.getBacklinks()) {
backlink.elementChanged(node, newOne);
}
} else if (node instanceof WriterModeData) {
WriterModeDataSet parent = (WriterModeDataSet) node.getParent();
parent.writerModeDataList.remove(node);
} else if (node instanceof WorldmapSegment) {
if (node.getParent() instanceof Worldmap) {
((Worldmap)node.getParent()).remove(node);
node.save();
for (GameDataElement backlink : node.getBacklinks()) {
backlink.elementChanged(node, node.getProject().getWorldmapSegment(node.id));
}
}
}
}
}.start();
@@ -192,12 +254,9 @@ public class WorkspaceActions {
for (TreePath selected : selectedPaths) {
if (selected.getLastPathComponent() instanceof GameDataElement && ((GameDataElement)selected.getLastPathComponent()).writable) {
elementsToDelete.add((GameDataElement) selected.getLastPathComponent());
multiMode = true;
} else {
multiMode = false;
break;
}
}
multiMode = elementsToDelete.size() > 1;
putValue(Action.NAME, "Delete all selected elements");
setEnabled(multiMode);
} else if (selectedNode instanceof GameDataElement && ((GameDataElement)selectedNode).writable) {

View File

@@ -417,6 +417,7 @@ public class DialogueEditor extends JSONElementEditor {
rewardObj = addItemBox(pane, ((Dialogue)target).getProject(), "Item: ", (Item) reward.reward_obj, writable, listener);
rewardValue = addIntegerField(pane, "Quantity: ", reward.reward_value, false, writable, listener);
break;
case removeQuestProgress:
case questProgress:
rewardMap = null;
rewardObjId = null;
@@ -826,6 +827,10 @@ public class DialogueEditor extends JSONElementEditor {
label.setText("Give quest progress "+rewardObjDesc+":"+reward.reward_value);
if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon()));
break;
case removeQuestProgress:
label.setText("Removes 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()));

View File

@@ -606,7 +606,7 @@ public class NPCEditor extends JSONElementEditor {
hitEffect.ap_boost_max = (Integer) value;
updateHit = true;
} else if (source == hitSourceConditionsList) {
//TODO
updateHit = true;
} else if (source == sourceConditionBox) {
if (selectedHitEffectSourceCondition.condition != null) {
selectedHitEffectSourceCondition.condition.removeBacklink(npc);
@@ -629,7 +629,7 @@ public class NPCEditor extends JSONElementEditor {
selectedHitEffectSourceCondition.chance = (Double) value;
hitSourceConditionsListModel.itemChanged(selectedHitEffectSourceCondition);
} else if (source == hitTargetConditionsList) {
//TODO
updateHit = true;
} else if (source == targetConditionBox) {
if (selectedHitEffectTargetCondition.condition != null) {
selectedHitEffectTargetCondition.condition.removeBacklink(npc);

View File

@@ -260,7 +260,12 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
addTileLayer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
layerListModel.addObject(new tiled.core.TileLayer());
tiled.core.TileLayer layer = new tiled.core.TileLayer(map.tmxMap.getWidth(), map.tmxMap.getHeight());
layerListModel.addObject(layer);
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addObjectGroup = new JButton(new ImageIcon(DefaultIcons.getCreateObjectGroupIcon()));
@@ -270,6 +275,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
layerListModel.addObject(new tiled.core.ObjectGroup());
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
deleteLayer = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
@@ -279,6 +288,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
layerListModel.removeObject(selectedLayer);
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
JPanel layersButtonsPane = new JPanel();
@@ -363,6 +376,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newMapchange(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addSpawn = new JButton(new ImageIcon(DefaultIcons.getCreateSpawnareaIcon()));
@@ -372,6 +389,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newSpawnArea(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addRest = new JButton(new ImageIcon(DefaultIcons.getCreateRestIcon()));
@@ -381,6 +402,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newRest(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addKey = new JButton(new ImageIcon(DefaultIcons.getCreateKeyIcon()));
@@ -390,6 +415,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newKey(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addReplace = new JButton(new ImageIcon(DefaultIcons.getCreateReplaceIcon()));
@@ -399,6 +428,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newReplace(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addScript = new JButton(new ImageIcon(DefaultIcons.getCreateScriptIcon()));
@@ -408,6 +441,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newScript(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addContainer = new JButton(new ImageIcon(DefaultIcons.getCreateContainerIcon()));
@@ -417,6 +454,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newContainer(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
addSign = new JButton(new ImageIcon(DefaultIcons.getCreateSignIcon()));
@@ -426,6 +467,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.addObject(MapObject.newSign(new tiled.core.MapObject(0, 0, 32, 32), map));
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
deleteObject = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
@@ -435,6 +480,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@Override
public void actionPerformed(ActionEvent e) {
groupObjectsListModel.removeObject(selectedMapObject);
map.state = GameDataElement.State.modified;
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
targetUpdated();
}
});
@@ -514,6 +563,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
} else if (selected instanceof ReplaceArea) {
//Replace areas only use questProgress requirements ATM
//requirementTypeCombo = addEnumValueBox(pane, "Requirement type: ", Requirement.RequirementType.values(), ((ReplaceArea)selected).requirement.type, ((TMXMap)target).writable, listener);
areaField = addTextField(pane, "Area ID: ", ((ReplaceArea)selected).name, ((TMXMap)target).writable, listener);
requirementParamsPane = new JPanel();
requirementParamsPane.setLayout(new JideBoxLayout(requirementParamsPane, JideBoxLayout.PAGE_AXIS, 6));
pane.add(requirementParamsPane, JideBoxLayout.FIX);
@@ -1593,6 +1643,9 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
public void targetUpdated() {
this.name = ((TMXMap)target).getDesc();
updateMessage();
updateXmlViewText(((TMXMap)target).toXml());
tmxViewer.repaint();
tmxViewer.revalidate();
}
@@ -1682,6 +1735,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
ATContentStudio.frame.closeEditor(map);
map.childrenRemoved(new ArrayList<ProjectTreeNode>());
map.delete();
GameDataElement newOne = map.getProject().getMap(map.id);
for (GameDataElement backlink : map.getBacklinks()) {
backlink.elementChanged(map, newOne);
}
}
});
savePane.add(delete, JideBoxLayout.FIX);
@@ -2005,11 +2062,9 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
if (modified) {
if (map.state != GameDataElement.State.modified) {
map.state = GameDataElement.State.modified;
TMXMapEditor.this.name = map.getDesc();
map.childrenChanged(new ArrayList<ProjectTreeNode>());
ATContentStudio.frame.editorChanged(TMXMapEditor.this);
}
updateXmlViewText(map.toXml());
}
}
}

View File

@@ -1,33 +1,47 @@
package com.gpl.rpg.atcontentstudio.ui.map;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import com.gpl.rpg.atcontentstudio.ATContentStudio;
import com.gpl.rpg.atcontentstudio.Notification;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
@@ -35,16 +49,16 @@ import com.gpl.rpg.atcontentstudio.model.SaveEvent;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.Worldmap;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment.NamedArea;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
import com.gpl.rpg.atcontentstudio.ui.Editor;
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
import com.gpl.rpg.atcontentstudio.ui.SaveItemsWizard;
import com.gpl.rpg.atcontentstudio.ui.WorldmapLabelEditionWizard;
import com.jidesoft.swing.ComboBoxSearchable;
import com.jidesoft.swing.JideBoxLayout;
import com.jidesoft.swing.JideTabbedPane;
import com.jidesoft.swing.ListSearchable;
public class WorldMapEditor extends Editor {
public class WorldMapEditor extends Editor implements FieldUpdateListener {
private static final long serialVersionUID = -8358238912588729094L;
@@ -56,18 +70,35 @@ public class WorldMapEditor extends Editor {
public enum EditMode {
moveViewSelect,
moveMaps,
deleteMaps,
addMap,
editLabelCoverage
addMap
}
public String mapBeingAddedID = null;
public String selectedLabel = null;
WorldMapView mapView = null;
WorldmapSegment.NamedArea selectedLabel = null;
MapSegmentMapsListModel msmListModel = null;
ListSelectionModel msmListSelectionModel = null;
MapSegmentLabelsListModel mslListModel = null;
MapSegmentLabelMapsListModel mslmListModel = null;
ListSelectionModel mslmListSelectionModel = null;
ListModel<TMXMap> currentSelectionListModel = null;
ListSelectionModel currentSelectionSelectionModel = null;
ListModel<TMXMap> currentHighlightListModel = null;
JList<TMXMap> mapsShown;
JList<WorldmapSegment.NamedArea> labelList;
JTextField labelIdField;
JTextField labelNameField;
JTextField labelTypeField;
public WorldMapEditor(WorldmapSegment worldmap) {
target = worldmap;
this.name = worldmap.id;
this.name = worldmap.getDesc();
this.icon = new ImageIcon(worldmap.getIcon());
setLayout(new BorderLayout());
@@ -86,8 +117,10 @@ public class WorldMapEditor extends Editor {
@Override
public void targetUpdated() {
// TODO Auto-generated method stub
this.name = ((GameDataElement)target).getDesc();
updateMessage();
updateXmlViewText(((WorldmapSegment)target).toXml());
mapView.updateFromModel();
}
public JPanel getXmlEditorPane() {
@@ -128,10 +161,6 @@ public class WorldMapEditor extends Editor {
zoomSliderPane.add(zoomSlider, JideBoxLayout.VARY);
zoomSliderPane.add(new JLabel(new ImageIcon(DefaultIcons.getZoomIcon())), JideBoxLayout.FIX);
final JRadioButton editLabelCoverage = new JRadioButton("Edit label coverage");
final JButton editLabel = new JButton("Edit map label");
final JButton createLabel = new JButton("Create map label");
final JButton deleteLabel = new JButton("Delete map label");
if (target.writable) {
JPanel mapToolsPane = new JPanel();
@@ -143,9 +172,6 @@ public class WorldMapEditor extends Editor {
JRadioButton moveMaps = new JRadioButton("Move selected map(s)");
mapToolsGroup.add(moveMaps);
mapToolsPane.add(moveMaps, JideBoxLayout.FIX);
JRadioButton deleteMaps = new JRadioButton("Delete maps");
mapToolsGroup.add(deleteMaps);
mapToolsPane.add(deleteMaps, JideBoxLayout.FIX);
JRadioButton addMap = new JRadioButton("Add map");
mapToolsGroup.add(addMap);
mapToolsPane.add(addMap, JideBoxLayout.FIX);
@@ -176,22 +202,6 @@ public class WorldMapEditor extends Editor {
moveView.setSelected(true);
pane.add(mapToolsPane, JideBoxLayout.FIX);
JPanel labelToolsPane = new JPanel();
labelToolsPane.setLayout(new JideBoxLayout(labelToolsPane, JideBoxLayout.LINE_AXIS));
mapToolsGroup.add(editLabelCoverage);
editLabelCoverage.setEnabled(false);
labelToolsPane.add(editLabelCoverage, JideBoxLayout.FIX);
editLabel.setEnabled(false);
labelToolsPane.add(editLabel, JideBoxLayout.FIX);
deleteLabel.setEnabled(false);
labelToolsPane.add(deleteLabel, JideBoxLayout.FIX);
createLabel.setEnabled(false);
labelToolsPane.add(createLabel, JideBoxLayout.FIX);
labelToolsPane.add(new JPanel(), JideBoxLayout.VARY);
pane.add(labelToolsPane, JideBoxLayout.FIX);
moveView.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -220,20 +230,6 @@ public class WorldMapEditor extends Editor {
}
});
deleteMaps.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
editMode = EditMode.deleteMaps;
mapBox.setEnabled(false);
if (mapBeingAddedID != null) {
mapView.mapLocations.remove(mapBeingAddedID);
mapBeingAddedID = null;
mapView.revalidate();
mapView.repaint();
}
}
});
addMap.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -268,109 +264,27 @@ public class WorldMapEditor extends Editor {
}
});
editLabelCoverage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
editMode = EditMode.editLabelCoverage;
mapBox.setEnabled(false);
mapView.selected.clear();
mapView.selected.addAll(((WorldmapSegment)target).labelledMaps.get(selectedLabel));
if (mapBeingAddedID != null) {
mapView.mapLocations.remove(mapBeingAddedID);
mapBeingAddedID = null;
}
mapView.revalidate();
mapView.repaint();
}
});
editLabelCoverage.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.DESELECTED) {
WorldmapSegment map = (WorldmapSegment)target;
if (map.labelledMaps.get(selectedLabel) != null) {
map.labelledMaps.get(selectedLabel).clear();
} else {
map.labelledMaps.put(selectedLabel, new ArrayList<String>());
}
for (String s : mapView.selected) {
map.labelledMaps.get(selectedLabel).add(s);
}
notifyModelModified();
mapView.revalidate();
mapView.repaint();
}
}
});
editLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mapView.selected.clear();
mapView.selected.addAll(((WorldmapSegment)target).labelledMaps.get(selectedLabel));
mapView.revalidate();
mapView.repaint();
WorldmapLabelEditionWizard wiz = new WorldmapLabelEditionWizard(worldmap, worldmap.labels.get(selectedLabel));
wiz.addCreationListener(new WorldmapLabelEditionWizard.CreationCompletedListener() {
@Override
public void labelCreated(NamedArea created) {
if (!created.id.equals(selectedLabel)) {
worldmap.labelledMaps.put(created.id, worldmap.labelledMaps.get(selectedLabel));
worldmap.labelledMaps.remove(selectedLabel);
worldmap.labels.put(created.id, created);
worldmap.labels.remove(selectedLabel);
selectedLabel = created.id;
notifyModelModified();
mapView.revalidate();
mapView.repaint();
}
}
});
wiz.setVisible(true);
}
});
deleteLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
worldmap.labelledMaps.remove(selectedLabel);
worldmap.labels.remove(selectedLabel);
selectedLabel = null;
notifyModelModified();
mapView.revalidate();
mapView.repaint();
}
});
createLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
WorldmapLabelEditionWizard wiz = new WorldmapLabelEditionWizard(worldmap);
wiz.addCreationListener(new WorldmapLabelEditionWizard.CreationCompletedListener() {
@Override
public void labelCreated(NamedArea created) {
worldmap.labelledMaps.put(created.id, new ArrayList<String>());
worldmap.labelledMaps.get(created.id).addAll(mapView.selected);
notifyModelModified();
mapView.revalidate();
mapView.repaint();
}
});
wiz.setVisible(true);
}
});
}
JPanel mapZoomPane = new JPanel();
mapZoomPane.setLayout(new BorderLayout());
mapZoomPane.add(zoomSliderPane, BorderLayout.WEST);
mapZoomPane.add(mapScroller, BorderLayout.CENTER);
pane.add(mapZoomPane, JideBoxLayout.VARY);
JPanel mapPropsPane = new JPanel();
buildMapPropsPane(mapPropsPane, worldmap);
setCurrentSelectionModel(msmListModel, msmListSelectionModel);
final JSplitPane mapAndPropsSplitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, mapZoomPane, mapPropsPane);
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
mapAndPropsSplitter.setDividerLocation(0.8d);
}
});
pane.add(mapAndPropsSplitter, JideBoxLayout.VARY);
zoomSlider.addChangeListener(new ChangeListener() {
@Override
@@ -410,39 +324,29 @@ public class WorldMapEditor extends Editor {
break;
}
}
if (editMode == EditMode.moveViewSelect || editMode == EditMode.editLabelCoverage) {
if (editMode == EditMode.moveViewSelect) {
if (selectedMap == null) return;
if (e.getButton() == MouseEvent.BUTTON1) {
if (e.isControlDown() || e.isShiftDown()) {
if (mapView.selected.contains(selectedMap)) {
if (editMode != EditMode.editLabelCoverage || mapView.selected.size() > 1) {
mapView.selected.remove(selectedMap);
mapSelectionChanged();
if (mapView.getSelectedMapsIDs().contains(selectedMap)) {
if (mapView.getSelectedMapsIDs().size() > 1) {
removeFromSelection(selectedMap);
// mapView.selected.remove(selectedMap);
update = true;
}
} else {
mapView.selected.add(selectedMap);
mapSelectionChanged();
addToSelection(selectedMap);
// mapView.selected.add(selectedMap);
update = true;
}
} else {
mapView.selected.clear();
mapView.selected.add(selectedMap);
mapSelectionChanged();
clearSelection();
// mapView.selected.clear();
addToSelection(selectedMap);
// mapView.selected.add(selectedMap);
update = true;
}
if (e.getClickCount() == 2) {
ATContentStudio.frame.openEditor(worldmap.getProject().getMap(selectedMap));
}
}
} else if (editMode == EditMode.deleteMaps) {
worldmap.mapLocations.remove(selectedMap);
worldmap.labels.remove(selectedMap);
mapView.selected.remove(selectedMap);
mapSelectionChanged();
mapView.updateFromModel();
notifyModelModified();
update = true;
} else if (editMode == EditMode.addMap && mapBeingAddedID != null) {
if (e.getButton() == MouseEvent.BUTTON1) {
mapView.recomputeSize();
@@ -452,10 +356,9 @@ public class WorldMapEditor extends Editor {
update = true;
mapBeingAddedID = null;
}
if (update) {
mapView.revalidate();
mapView.repaint();
}
// if (update) {
// validateSelection();
// }
}
@Override
@@ -515,7 +418,7 @@ public class WorldMapEditor extends Editor {
mapDeltaX -= mapDeltaX % WorldMapView.TILE_SIZE;
mapDeltaY -= mapDeltaY % WorldMapView.TILE_SIZE;
for (String s : mapView.selected) {
for (String s : mapView.getSelectedMapsIDs()) {
mapView.mapLocations.get(s).x = (worldmap.mapLocations.get(s).x * WorldMapView.TILE_SIZE) + mapDeltaX;
mapView.mapLocations.get(s).y = (worldmap.mapLocations.get(s).y * WorldMapView.TILE_SIZE) + mapDeltaY;
}
@@ -531,54 +434,441 @@ public class WorldMapEditor extends Editor {
}
}
public void mapSelectionChanged() {
if (mapView.selected.isEmpty()) {
editLabelCoverage.setEnabled(false);
editLabel.setEnabled(false);
createLabel.setEnabled(false);
selectedLabel = null;
} else {
String label = null;
boolean multiLabel = false;
for (String map : mapView.selected) {
for (String existingLabel : ((WorldmapSegment)target).labelledMaps.keySet()) {
if (((WorldmapSegment)target).labelledMaps.get(existingLabel).contains(map)) {
if (label != null && !label.equals(existingLabel)) {
multiLabel = true;
}
label = existingLabel;
}
}
}
if (multiLabel) {
editLabelCoverage.setEnabled(false);
editLabel.setEnabled(false);
createLabel.setEnabled(false);
deleteLabel.setEnabled(false);
selectedLabel = null;
} else if (label != null) {
editLabelCoverage.setEnabled(true);
editLabel.setEnabled(true);
deleteLabel.setEnabled(true);
createLabel.setEnabled(false);
selectedLabel = label;
} else {
editLabelCoverage.setEnabled(false);
editLabel.setEnabled(false);
deleteLabel.setEnabled(false);
createLabel.setEnabled(true);
selectedLabel = null;
}
}
}
};
mapView.addMouseListener(mouseListener);
mapView.addMouseMotionListener(mouseListener);
mapView.addMapClickListener(new WorldMapView.MapClickListener() {
@Override
public void mapClicked(MouseEvent e, TMXMap m) {
if (e.getClickCount() == 2) {
ATContentStudio.frame.openEditor(m);
}
}
@Override
public void mapChangeClicked(MouseEvent e, TMXMap m, TMXMap changeTarget) {
if (e.getClickCount() == 2) {
ATContentStudio.frame.openEditor(changeTarget);
}
}
@Override
public void backgroundClicked(MouseEvent e) {
}
});
return pane;
}
private void buildMapPropsPane(JPanel mapPropsPane, final WorldmapSegment worldmap) {
JideTabbedPane tabPane = new JideTabbedPane(JideTabbedPane.TOP);
JPanel mapListPane = new JPanel();
mapListPane.setLayout(new JideBoxLayout(mapListPane, JideBoxLayout.PAGE_AXIS));
mapListPane.add(new JLabel("Maps shown here"), JideBoxLayout.FIX);
msmListModel = new MapSegmentMapsListModel(worldmap);
mapsShown = new JList<TMXMap>(msmListModel);
mapsShown.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
msmListSelectionModel = mapsShown.getSelectionModel();
mapsShown.setCellRenderer(new MapCellRenderer());
new ListSearchable(mapsShown) {
@Override
protected String convertElementToString(Object object) {
return ((TMXMap)object).id;
}
};
mapListPane.add(new JScrollPane(mapsShown), JideBoxLayout.VARY);
mapsShown.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
ATContentStudio.frame.openEditor(mapsShown.getSelectedValue());
ATContentStudio.frame.selectInTree(mapsShown.getSelectedValue());
}
}
});
mapsShown.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
ATContentStudio.frame.openEditor(mapsShown.getSelectedValue());
ATContentStudio.frame.selectInTree(mapsShown.getSelectedValue());
}
}
});
mapsShown.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
setCurrentSelectionModel(msmListModel, msmListSelectionModel);
}
});
tabPane.addTab("Map list", mapListPane);
final JPanel labelEditPane = new JPanel();
labelEditPane.setLayout(new JideBoxLayout(labelEditPane, JideBoxLayout.PAGE_AXIS));
labelEditPane.add(new JLabel("Labels on the worldmap"), JideBoxLayout.FIX);
mslListModel = new MapSegmentLabelsListModel(worldmap);
labelList = new JList<WorldmapSegment.NamedArea>(mslListModel);
labelList.setCellRenderer(new MapLabelCellRenderer());
labelList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
labelEditPane.add(new JScrollPane(labelList), JideBoxLayout.FLEXIBLE);
JPanel labelListButtonsPane = new JPanel();
labelListButtonsPane.setLayout(new JideBoxLayout(labelListButtonsPane, JideBoxLayout.LINE_AXIS));
final JButton createLabel = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
labelListButtonsPane.add(createLabel, JideBoxLayout.FIX);
final JButton deleteLabel = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
labelListButtonsPane.add(deleteLabel, JideBoxLayout.FIX);
labelListButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
labelEditPane.add(labelListButtonsPane, JideBoxLayout.FIX);
final JPanel labelParametersPane = new JPanel();
labelEditPane.add(labelParametersPane, JideBoxLayout.FLEXIBLE);
labelList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
selectedLabel = labelList.getSelectedValue();
updateLabelParamsPane(labelParametersPane, worldmap);
labelEditPane.revalidate();
labelEditPane.repaint();
}
});
createLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
WorldmapSegment.NamedArea creation = new WorldmapSegment.NamedArea(null, null, null);
worldmap.labels.put(WorldmapSegment.TEMP_LABEL_KEY, creation);
worldmap.labelledMaps.put(WorldmapSegment.TEMP_LABEL_KEY, new ArrayList<String>());
mslListModel.listChanged();
labelList.setSelectedValue(creation, true);
}
});
deleteLabel.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (selectedLabel.id != null) {
worldmap.labelledMaps.remove(selectedLabel.id);
worldmap.labels.remove(selectedLabel.id);
} else {
worldmap.labelledMaps.remove(WorldmapSegment.TEMP_LABEL_KEY);
worldmap.labels.remove(WorldmapSegment.TEMP_LABEL_KEY);
}
labelList.clearSelection();
mslListModel.listChanged();
notifyModelModified();
}
});
tabPane.addTab("Labels", labelEditPane);
mapPropsPane.setLayout(new BorderLayout());
mapPropsPane.add(tabPane, BorderLayout.CENTER);
}
private void updateLabelParamsPane(JPanel labelParametersPane, final WorldmapSegment worldmap) {
labelParametersPane.removeAll();
if (selectedLabel == null) {
setCurrentHighlightModel(null);
return;
}
labelParametersPane.setLayout(new JideBoxLayout(labelParametersPane, JideBoxLayout.PAGE_AXIS));
labelIdField = addTextField(labelParametersPane, "Internal ID: ", selectedLabel.id, worldmap.writable, this);
labelNameField = addTranslatableTextField(labelParametersPane, "Name: ", selectedLabel.name, worldmap.writable, this);
labelTypeField = addTextField(labelParametersPane, "Type: ", selectedLabel.type, worldmap.writable, this);
labelParametersPane.add(new JLabel("Label covers the following maps"), JideBoxLayout.FIX);
mslmListModel = new MapSegmentLabelMapsListModel(worldmap, selectedLabel);
final JList<TMXMap> labelCoverageList = new JList<TMXMap>(mslmListModel);
labelCoverageList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
mslmListSelectionModel = labelCoverageList.getSelectionModel();
labelCoverageList.setCellRenderer(new MapCellRenderer());
labelParametersPane.add(new JScrollPane(labelCoverageList), JideBoxLayout.VARY);
labelCoverageList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
setCurrentHighlightModel(mslmListModel);
}
});
JPanel labelCoverageButtonsPane = new JPanel();
labelCoverageButtonsPane.setLayout(new JideBoxLayout(labelCoverageButtonsPane, JideBoxLayout.LINE_AXIS));
JButton addCoverage = new JButton("Add on-map selection");
labelCoverageButtonsPane.add(addCoverage, JideBoxLayout.FIX);
JButton replaceCoverage = new JButton("Replace by on-map selection");
labelCoverageButtonsPane.add(replaceCoverage, JideBoxLayout.FIX);
JButton removeFromCoverage = new JButton("Remove selected in list");
labelCoverageButtonsPane.add(removeFromCoverage, JideBoxLayout.FIX);
labelCoverageButtonsPane.add(new JPanel(), JideBoxLayout.VARY);
addCoverage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (selectedLabel == null) return;
String labelId = selectedLabel.id;
if (labelId == null) labelId = WorldmapSegment.TEMP_LABEL_KEY;
List<String> currentCoverage = worldmap.labelledMaps.get(labelId);
if (currentCoverage == null) {
worldmap.labelledMaps.put(labelId, new ArrayList<String>());
currentCoverage = worldmap.labelledMaps.get(labelId);
}
for (int i = 0; i < msmListModel.getSize(); i++) {
if (msmListSelectionModel.isSelectedIndex(i)) {
if (!currentCoverage.contains(msmListModel.getElementAt(i).id)) {
currentCoverage.add(msmListModel.getElementAt(i).id);
}
}
}
mslmListModel.listChanged();
repaintMap();
}
});
replaceCoverage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (selectedLabel == null) return;
String labelId = selectedLabel.id;
if (labelId == null) labelId = WorldmapSegment.TEMP_LABEL_KEY;
List<String> currentCoverage = worldmap.labelledMaps.get(labelId);
if (currentCoverage == null) {
worldmap.labelledMaps.put(labelId, new ArrayList<String>());
currentCoverage = worldmap.labelledMaps.get(labelId);
} else {
currentCoverage.clear();
}
for (int i = 0; i < msmListModel.getSize(); i++) {
if (msmListSelectionModel.isSelectedIndex(i)) {
if (!currentCoverage.contains(msmListModel.getElementAt(i).id)) {
currentCoverage.add(msmListModel.getElementAt(i).id);
}
}
}
mslmListModel.listChanged();
repaintMap();
}
});
removeFromCoverage.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (selectedLabel == null) return;
String labelId = selectedLabel.id;
if (labelId == null) labelId = WorldmapSegment.TEMP_LABEL_KEY;
List<String> currentCoverage = worldmap.labelledMaps.get(labelId);
if (currentCoverage == null) return;
List<String> toRemove = new ArrayList<String>();
for (int i = 0; i < mslmListModel.getSize(); i++) {
if (mslmListSelectionModel.isSelectedIndex(i)) {
if (currentCoverage.contains(mslmListModel.getElementAt(i).id)) {
toRemove.add(mslmListModel.getElementAt(i).id);
}
}
}
currentCoverage.removeAll(toRemove);
mslmListModel.listChanged();
repaintMap();
}
});
labelParametersPane.add(labelCoverageButtonsPane, JideBoxLayout.FIX);
setCurrentHighlightModel(mslmListModel);
}
public class MapSegmentMapsListModel implements ListModel<TMXMap> {
WorldmapSegment segment;
public MapSegmentMapsListModel(WorldmapSegment segment) {
this.segment = segment;
}
@Override
public int getSize() {
return segment.mapLocations.size();
}
@Override
public TMXMap getElementAt(int index) {
return segment.getProject().getMap(((String)segment.mapLocations.keySet().toArray()[index]));
}
public void listChanged() {
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize() - 1));
}
}
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 MapSegmentLabelMapsListModel implements ListModel<TMXMap> {
WorldmapSegment segment;
WorldmapSegment.NamedArea area;
public MapSegmentLabelMapsListModel(WorldmapSegment segment, WorldmapSegment.NamedArea area) {
this.segment = segment;
this.area = area;
}
@Override
public int getSize() {
if (area.id == null) return segment.labelledMaps.get(WorldmapSegment.TEMP_LABEL_KEY).size();
return segment.labelledMaps.get(area.id).size();
}
@Override
public TMXMap getElementAt(int index) {
if (area.id == null) return segment.getProject().getMap(segment.labelledMaps.get(WorldmapSegment.TEMP_LABEL_KEY).get(index));
return segment.getProject().getMap(segment.labelledMaps.get(area.id).get(index));
}
public void listChanged() {
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize() - 1));
}
}
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 MapSegmentLabelsListModel implements ListModel<WorldmapSegment.NamedArea> {
WorldmapSegment segment;
public MapSegmentLabelsListModel(WorldmapSegment segment) {
this.segment = segment;
}
@Override
public int getSize() {
return segment.labels.values().size();
}
@Override
public WorldmapSegment.NamedArea getElementAt(int index) {
return new ArrayList<WorldmapSegment.NamedArea>(segment.labels.values()).get(index);
}
public void listChanged() {
for (ListDataListener l : listeners) {
l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, 0, getSize() - 1));
}
}
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 static class MapCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 6819681566800482793L;
public MapCellRenderer() {
super();
}
@SuppressWarnings("rawtypes")
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null) {
label.setText("None");
} else {
label.setText(((GameDataElement)value).getDesc());
if (((GameDataElement)value).getIcon() == null) {
Notification.addError("Unable to find icon for "+((GameDataElement)value).getDesc());
} else {
label.setIcon(new ImageIcon(((GameDataElement)value).getIcon()));
}
}
return label;
}
}
public static class MapLabelCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 6819681566800482793L;
public MapLabelCellRenderer() {
super();
}
@SuppressWarnings("rawtypes")
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null) {
label.setText("None");
} else {
WorldmapSegment.NamedArea area = (WorldmapSegment.NamedArea) value;
if (area.id != null) {
label.setText(area.name+" ("+area.id+")");
label.setIcon(new ImageIcon(DefaultIcons.getLabelIcon()));
} else {
label.setText("Incomplete Label. Enter an ID.");
label.setIcon(new ImageIcon(DefaultIcons.getNullifyIcon()));
}
}
return label;
}
}
public JPanel createButtonPane(final WorldmapSegment node) {
final JButton gdeIcon = new JButton(new ImageIcon(DefaultIcons.getUIMapImage()));
JPanel savePane = new JPanel();
@@ -721,14 +1011,108 @@ public class WorldMapEditor extends Editor {
public void pushToModel() {
mapView.pushToModel();
msmListModel.listChanged();
notifyModelModified();
updateXmlViewText(((WorldmapSegment)target).toXml());
}
public void notifyModelModified() {
target.state = GameDataElement.State.modified;
this.name = ((WorldmapSegment)target).getDesc();
target.childrenChanged(new ArrayList<ProjectTreeNode>());
}
ListSelectionListener activeSelectionListSelectionListener = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
repaintMap();
};
};
private void setCurrentSelectionModel(ListModel<TMXMap> listModel, ListSelectionModel listSelectionModel) {
if (currentSelectionSelectionModel != null) {
currentSelectionSelectionModel.removeListSelectionListener(activeSelectionListSelectionListener);
}
currentSelectionListModel = listModel;
currentSelectionSelectionModel = listSelectionModel;
mapView.selectedListModel = listModel;
mapView.selectedSelectionModel = listSelectionModel;
currentSelectionSelectionModel.addListSelectionListener(activeSelectionListSelectionListener);
repaintMap();
}
private void setCurrentHighlightModel(ListModel<TMXMap> listModel) {
mapView.highlightedListModel = listModel;
repaintMap();
}
public void clearSelection() {
currentSelectionSelectionModel.clearSelection();
}
public void addToSelection(String mapId) {
if (mapId == null) return;
int index = -1;
for (int i = 0; i < currentSelectionListModel.getSize(); i++) {
if (currentSelectionListModel.getElementAt(i).id.equals(mapId)) {
index = i;
break;
}
}
currentSelectionSelectionModel.addSelectionInterval(index, index);
}
public void removeFromSelection(String mapId) {
if (mapId == null) return;
int index = -1;
for (int i = 0; i < currentSelectionListModel.getSize(); i++) {
if (currentSelectionListModel.getElementAt(i).id.equals(mapId)) {
index = i;
break;
}
}
currentSelectionSelectionModel.removeSelectionInterval(index, index);
}
public void repaintMap() {
mapView.revalidate();
mapView.repaint();
}
@Override
public void valueChanged(JComponent source, Object value) {
WorldmapSegment worldmap = (WorldmapSegment)target;
boolean changed = false;
if (source == labelIdField) {
List<String> coverage;
if (selectedLabel.id != null) {
coverage = worldmap.labelledMaps.get(selectedLabel.id);
worldmap.labelledMaps.remove(selectedLabel.id);
worldmap.labels.remove(selectedLabel.id);
} else {
coverage = worldmap.labelledMaps.get(WorldmapSegment.TEMP_LABEL_KEY);
worldmap.labels.remove(WorldmapSegment.TEMP_LABEL_KEY);
}
selectedLabel.id = (String) value;
if (value != null) {
worldmap.labelledMaps.put(selectedLabel.id, coverage);
worldmap.labels.put(selectedLabel.id, selectedLabel);
}
mslListModel.listChanged();
changed = true;
} else if (source == labelNameField) {
selectedLabel.name = (String) value;
mslListModel.listChanged();
changed = true;
repaintMap();
} else if (source == labelTypeField) {
selectedLabel.type = (String) value;
changed = true;
}
if (changed) {
notifyModelModified();
updateXmlViewText(worldmap.toXml());
}
}
}

View File

@@ -7,10 +7,14 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;
@@ -20,14 +24,21 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.JComponent;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.Scrollable;
import javax.swing.ToolTipManager;
import tiled.view.MapRenderer;
import tiled.view.OrthogonalRenderer;
import com.gpl.rpg.atcontentstudio.model.Project;
import com.gpl.rpg.atcontentstudio.model.maps.MapChange;
import com.gpl.rpg.atcontentstudio.model.maps.MapObject;
import com.gpl.rpg.atcontentstudio.model.maps.MapObjectGroup;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
@@ -46,26 +57,140 @@ public class WorldMapView extends JComponent implements Scrollable {
public Map<String, Rectangle> mapLocations = new LinkedHashMap<String, Rectangle>();
public ListSelectionModel selectedSelectionModel = null;
public ListModel<TMXMap> selectedListModel = null;
public Set<String> selected = new HashSet<String>();
public ListModel<TMXMap> highlightedListModel = null;
public float zoomLevel = 0.1f;
int sizeX = 0, sizeY = 0;
int offsetX = 0, offsetY = 0;
static final Color selectOutlineColor = new Color(255, 0, 0);
static final Stroke selectOutlineStroke = new BasicStroke(4f);
static final Color highlightOutlineColor = Color.CYAN;
static final Stroke highlightOutlineStroke = new BasicStroke(4f);
static final Color mapIdLabelOutlineColor = Color.BLACK;
static final Stroke thinLabelOutlineStroke = new BasicStroke(1.5f);
static final Stroke labelOutlineStroke = new BasicStroke(3f);
public WorldMapView(WorldmapSegment worldmap) {
this.worldmap = worldmap;
this.proj = worldmap.getProject();
updateFromModel();
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
String selectedMap = null;
boolean update = false;
int x = (int) (e.getX() / zoomLevel);
int y = (int) (e.getY() / zoomLevel);
for (String s : mapLocations.keySet()) {
if (mapLocations.get(s).contains(x, y)) {
selectedMap = s;
break;
}
}
if (selectedMap != null) {
x = x - mapLocations.get(selectedMap).x;
y = y - mapLocations.get(selectedMap).y;
//Look for a mapchange there
TMXMap map = proj.getMap(selectedMap);
boolean mapchangeFound = false;
for (MapObjectGroup group : map.groups) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof MapChange) {
if (x >= obj.x && x < obj.x + obj.w && y >= obj.y && y < obj.y + obj.h) {
String mapId = ((MapChange)obj).map != null ? ((MapChange)obj).map.id : ((MapChange)obj).map_id;
mapChangeClicked(e, proj.getMap(selectedMap), proj.getMap(mapId));
mapchangeFound = true;
}
}
}
}
if (!mapchangeFound) {
mapClicked(e, WorldMapView.this.worldmap.getProject().getMap(selectedMap));
}
} else {
backgroundClicked(e);
}
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
String selectedMap = null;
int x = (int) (e.getX() / zoomLevel);
int y = (int) (e.getY() / zoomLevel);
for (String s : mapLocations.keySet()) {
if (mapLocations.get(s).contains(x, y)) {
selectedMap = s;
break;
}
}
if (selectedMap != null) {
//Reuse x,y to indicate to tile-within-the-map coordinates.
x = x - mapLocations.get(selectedMap).x;
y = y - mapLocations.get(selectedMap).y;
//Look for a mapchange there
TMXMap map = proj.getMap(selectedMap);
boolean mapchangeFound = false;
for (MapObjectGroup group : map.groups) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof MapChange) {
if (x >= obj.x && x < obj.x + obj.w && y >= obj.y && y < obj.y + obj.h) {
String mapId = ((MapChange)obj).map != null ? ((MapChange)obj).map.id : ((MapChange)obj).map_id;
setToolTipText(selectedMap+"->"+mapId);
mapchangeFound = true;
}
}
}
}
if (!mapchangeFound) {
setToolTipText(selectedMap);
}
ToolTipManager.sharedInstance().registerComponent(WorldMapView.this);
ToolTipManager.sharedInstance().setEnabled(true);
} else {
ToolTipManager.sharedInstance().setEnabled(false);
ToolTipManager.sharedInstance().unregisterComponent(WorldMapView.this);
setToolTipText(null);
}
}
});
}
@Override
public Point getToolTipLocation(MouseEvent event) {
return event.getPoint();
}
private void paintOnGraphics(Graphics2D g2) {
g2.setPaint(new Color(100, 100, 100));
g2.fillRect(0, 0, sizeX, sizeY);
g2.setPaint(new Color(255, 0, 0));
g2.setStroke(new BasicStroke(4));
g2.setPaint(selectOutlineColor);
g2.setStroke(selectOutlineStroke);
Font areaNameFont = g2.getFont();
areaNameFont = areaNameFont.deriveFont(70f).deriveFont(Font.BOLD);
Font mapIdFont = g2.getFont();
mapIdFont = mapIdFont.deriveFont(50f).deriveFont(Font.BOLD);
g2.setFont(mapIdFont);
FontMetrics mifm = g2.getFontMetrics();
int mapIdLabelHeight = mifm.getHeight();
for (String s : mapLocations.keySet()) {
int x = mapLocations.get(s).x;
@@ -83,8 +208,8 @@ public class WorldMapView extends JComponent implements Scrollable {
if (layer instanceof tiled.core.TileLayer && layer.isVisible()) {
if (layer.getName().equalsIgnoreCase("walkable")) continue;
renderer.paintTileLayer(g2, (tiled.core.TileLayer) layer);
} else if (layer instanceof tiled.core.ObjectGroup && layer.isVisible()) {
// paintObjectGroup(g2, map, (tiled.core.ObjectGroup) layer);
} else if (layer instanceof tiled.core.ObjectGroup) {
paintObjectGroup(g2, map, (tiled.core.ObjectGroup) layer);
}
}
if (map.colorFilter != null) {
@@ -93,39 +218,119 @@ public class WorldMapView extends JComponent implements Scrollable {
MapColorFilters.applyColorfilter(map.colorFilter, g2);
g2.setClip(oldClip);
}
if (selected.contains(s)) {
g2.drawRect(0, 0, map.tmxMap.getWidth() * TILE_SIZE, map.tmxMap.getHeight() * TILE_SIZE);
}
g2.translate(-x, -y);
}
if (highlightedListModel != null) {
outlineFromListModel(g2, highlightedListModel, null, highlightOutlineColor, highlightOutlineStroke, mapIdFont, mapIdLabelHeight);
}
Font f = g2.getFont();
f = f.deriveFont(70f).deriveFont(Font.BOLD);
g2.setFont(f);
g2.setStroke(new BasicStroke(3));
if (selectedListModel != null && selectedSelectionModel != null) {
outlineFromListModel(g2, selectedListModel, selectedSelectionModel, selectOutlineColor, selectOutlineStroke, mapIdFont, mapIdLabelHeight);
}
g2.setStroke(labelOutlineStroke);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setFont(areaNameFont);
FontMetrics fm = g2.getFontMetrics();
FontRenderContext frc = g2.getFontRenderContext();
for (String s : worldmap.labels.keySet()) {
String label = worldmap.labels.get(s).name;
Rectangle areaCovered = new Rectangle(0, 0, -1, -1);
for (String map : worldmap.labelledMaps.get(s)) {
areaCovered.add(mapLocations.get(map));
if (label != null) {
Rectangle areaCovered = new Rectangle(0, 0, -1, -1);
for (String map : worldmap.labelledMaps.get(s)) {
areaCovered.add(mapLocations.get(map));
}
Rectangle2D stringBounds = fm.getStringBounds(label, g2);
GlyphVector gv = areaNameFont.createGlyphVector(frc, label);
g2.setColor(Color.WHITE);
g2.fill(gv.getOutline((int)(areaCovered.getCenterX() - stringBounds.getCenterX()), (int)(areaCovered.getCenterY() - stringBounds.getCenterY())));
g2.setColor(Color.BLACK);
g2.draw(gv.getOutline((int)(areaCovered.getCenterX() - stringBounds.getCenterX()), (int)(areaCovered.getCenterY() - stringBounds.getCenterY())));
}
Rectangle2D stringBounds = fm.getStringBounds(label, g2);
GlyphVector gv = f.createGlyphVector(frc, label);
g2.setColor(Color.WHITE);
g2.fill(gv.getOutline((int)(areaCovered.getCenterX() - stringBounds.getCenterX()), (int)(areaCovered.getCenterY() - stringBounds.getCenterY())));
g2.setColor(Color.BLACK);
g2.draw(gv.getOutline((int)(areaCovered.getCenterX() - stringBounds.getCenterX()), (int)(areaCovered.getCenterY() - stringBounds.getCenterY())));
}
}
private void paintObjectGroup(Graphics2D g2d, TMXMap map, tiled.core.ObjectGroup layer) {
for (MapObjectGroup group : map.groups) {
if (group.tmxGroup == layer) {
for (MapObject object : group.mapObjects) {
if (object instanceof MapChange) {
// Only show mapchange areas pointing to maps not shown in this worldmap
if (((MapChange)object).map != null && !mapLocations.containsKey(((MapChange)object).map.id)) {
drawObject(object, g2d, new Color(20, 20, 190));
}
}
}
break;
}
}
}
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 void outlineFromListModel(Graphics2D g2, ListModel<TMXMap> listModel, ListSelectionModel selectionModel, Color outlineColor, Stroke outlineStroke, Font mapIdFont, int mapIdLabelHeight) {
for (int i =0; i<listModel.getSize(); i++) {
//No selection model ? We want to highlight the whole list.
if (selectionModel == null || selectionModel.isSelectedIndex(i)) {
TMXMap map = listModel.getElementAt(i);
int x = mapLocations.get(map.id).x;
int y = mapLocations.get(map.id).y;
g2.translate(x, y);
GlyphVector gv = mapIdFont.createGlyphVector(g2.getFontRenderContext(), map.id);
g2.setStroke(outlineStroke);
g2.setColor(outlineColor);
g2.drawRect(0, 0, map.tmxMap.getWidth() * TILE_SIZE, map.tmxMap.getHeight() * TILE_SIZE);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(thinLabelOutlineStroke);
g2.fill(gv.getOutline(8, 8 + mapIdLabelHeight));
g2.setColor(mapIdLabelOutlineColor);
g2.draw(gv.getOutline(8, 8 + mapIdLabelHeight));
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
g2.translate(-x, -y);
}
}
}
public List<String> getSelectedMapsIDs() {
List<String> result = new ArrayList<String>();
for (int i =0; i<selectedListModel.getSize(); i++) {
if (selectedSelectionModel.isSelectedIndex(i)) {
TMXMap map = selectedListModel.getElementAt(i);
result.add(map.id);
}
}
return result;
}
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g.create();
@@ -140,6 +345,35 @@ public class WorldMapView extends JComponent implements Scrollable {
}
public interface MapClickListener {
public void mapClicked(MouseEvent e, TMXMap m);
public void mapChangeClicked(MouseEvent e, TMXMap m, TMXMap changeTarget);
public void backgroundClicked(MouseEvent e);
}
private List<MapClickListener> listeners = new CopyOnWriteArrayList<MapClickListener>();
public void addMapClickListener(MapClickListener l) {
listeners.add(l);
}
public void removeMapClickListener(MapClickListener l) {
listeners.remove(l);
}
private void mapClicked(MouseEvent e, TMXMap m) {
for (MapClickListener l : listeners) l.mapClicked(e, m);
}
private void mapChangeClicked(MouseEvent e, TMXMap m, TMXMap changeTarget) {
for (MapClickListener l : listeners) l.mapChangeClicked(e, m, changeTarget);
}
private void backgroundClicked(MouseEvent e) {
for (MapClickListener l : listeners) l.backgroundClicked(e);
}
// private boolean paintObjectGroup(Graphics2D g2d, TMXMap map, tiled.core.ObjectGroup layer) {
// boolean paintSelected = false;
// for (MapObjectGroup group : map.groups) {
@@ -262,6 +496,9 @@ public class WorldMapView extends JComponent implements Scrollable {
public void pushToModel() {
worldmap.segmentX = offsetX / TILE_SIZE;
worldmap.segmentY = offsetY / TILE_SIZE;
for (String id : worldmap.mapLocations.keySet()) {
worldmap.getProject().getMap(id).removeBacklink(worldmap);
}
worldmap.mapLocations.clear();
for (String s : mapLocations.keySet()) {
int x = mapLocations.get(s).x / TILE_SIZE;
@@ -270,6 +507,10 @@ public class WorldMapView extends JComponent implements Scrollable {
worldmap.mapLocations.put(s, new Point(x, y));
}
for (String id : worldmap.mapLocations.keySet()) {
worldmap.getProject().getMap(id).addBacklink(worldmap);
}
List<String> toRemove = new ArrayList<String>();
for (String s : worldmap.labels.keySet()) {
if (!mapLocations.containsKey(s)) {

View File

@@ -0,0 +1,223 @@
package com.gpl.rpg.atcontentstudio.ui.tools;
import java.util.ArrayList;
import java.util.List;
import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.GameSource;
import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition;
import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue;
import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist;
import com.gpl.rpg.atcontentstudio.model.gamedata.Item;
import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest;
import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.model.maps.ContainerArea;
import com.gpl.rpg.atcontentstudio.model.maps.KeyArea;
import com.gpl.rpg.atcontentstudio.model.maps.MapChange;
import com.gpl.rpg.atcontentstudio.model.maps.MapObject;
import com.gpl.rpg.atcontentstudio.model.maps.MapObjectGroup;
import com.gpl.rpg.atcontentstudio.model.maps.ReplaceArea;
import com.gpl.rpg.atcontentstudio.model.maps.RestArea;
import com.gpl.rpg.atcontentstudio.model.maps.ScriptArea;
import com.gpl.rpg.atcontentstudio.model.maps.SignArea;
import com.gpl.rpg.atcontentstudio.model.maps.SpawnArea;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
public class GDEVisitor {
public static List<GameDataElement> findDependencies(GameDataElement origin, boolean includeSource) {
List<GameDataElement> visited = new ArrayList<GameDataElement>();
visit(origin, visited, includeSource);
return visited;
}
private static void visit(GameDataElement element, List<GameDataElement> visited, boolean includeSource) {
if (element == null) return;
if (visited.contains(element)) return;
if (!(includeSource || element.getDataType() != GameSource.Type.source)) return;
visited.add(element);
element.link();
if (element instanceof ActorCondition) {
visitActorCondition((ActorCondition)element, visited, includeSource);
} else if (element instanceof Dialogue) {
visitDialogue((Dialogue)element, visited, includeSource);
} else if (element instanceof Droplist) {
visitDroplist((Droplist)element, visited, includeSource);
} else if (element instanceof Item) {
visitItem((Item)element, visited, includeSource);
} else if (element instanceof ItemCategory) {
visitItemCategory((ItemCategory)element, visited, includeSource);
} else if (element instanceof NPC) {
visitNPC((NPC)element, visited, includeSource);
} else if (element instanceof Quest) {
visitQuest((Quest)element, visited, includeSource);
} else if (element instanceof TMXMap) {
visitTMXMap((TMXMap)element, visited, includeSource);
} else if (element instanceof Spritesheet) {
visitSpritesheet((Spritesheet)element, visited, includeSource);
}
}
private static void visitActorCondition(ActorCondition element, List<GameDataElement> visited, boolean includeSource) {
if (element.icon_id != null) visit(element.getProject().getSpritesheet(element.icon_id.split(":")[0]), visited, includeSource);
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitDialogue(Dialogue element, List<GameDataElement> visited, boolean includeSource) {
visit(element.switch_to_npc, visited, includeSource);
if (element.replies != null) {
for (Dialogue.Reply reply : element.replies) {
visit(reply.next_phrase, visited, includeSource);
if (reply.requirements != null) {
for (Requirement req : reply.requirements) {
visit(req.required_obj, visited, includeSource);
}
}
}
}
if (element.rewards != null) {
for (Dialogue.Reward reward : element.rewards) {
visit(reward.reward_obj, visited, includeSource);
visit(reward.map, visited, includeSource);
}
}
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitDroplist(Droplist element, List<GameDataElement> visited, boolean includeSource) {
if (element.dropped_items != null) {
for (Droplist.DroppedItem droppedItem : element.dropped_items) {
visit(droppedItem.item, visited, includeSource);
}
}
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitItem(Item element, List<GameDataElement> visited, boolean includeSource) {
visit(element.category, visited, includeSource);
if (element.icon_id != null) visit(element.getProject().getSpritesheet(element.icon_id.split(":")[0]), visited, includeSource);
if (element.equip_effect != null && element.equip_effect.conditions != null) {
for (Item.ConditionEffect condEffect : element.equip_effect.conditions) {
visit(condEffect.condition, visited, includeSource);
}
}
if (element.hit_effect != null) {
if (element.hit_effect.conditions_source != null) {
for (Item.ConditionEffect condEffect : element.hit_effect.conditions_source) {
visit(condEffect.condition, visited, includeSource);
}
}
if (element.hit_effect.conditions_target != null) {
for (Item.ConditionEffect condEffect : element.hit_effect.conditions_target) {
visit(condEffect.condition, visited, includeSource);
}
}
}
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitItemCategory(ItemCategory element, List<GameDataElement> visited, boolean includeSource) {
//Nothing to visit
}
private static void visitNPC(NPC element, List<GameDataElement> visited, boolean includeSource) {
visit(element.dialogue, visited, includeSource);
visit(element.droplist, visited, includeSource);
if (element.icon_id != null) visit(element.getProject().getSpritesheet(element.icon_id.split(":")[0]), visited, includeSource);
if (element.hit_effect != null) {
if (element.hit_effect.conditions_source != null) {
for (NPC.TimedConditionEffect condEffect : element.hit_effect.conditions_source) {
visit(condEffect.condition, visited, includeSource);
}
}
if (element.hit_effect.conditions_target != null) {
for (NPC.TimedConditionEffect condEffect : element.hit_effect.conditions_target) {
visit(condEffect.condition, visited, includeSource);
}
}
}
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitQuest(Quest element, List<GameDataElement> visited, boolean includeSource) {
//Nothing to visit
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitTMXMap(TMXMap element, List<GameDataElement> visited, boolean includeSource) {
// TODO Auto-generated method stub
if (element.groups != null) {
for (MapObjectGroup group : element.groups) {
if (group.mapObjects != null) {
for (MapObject obj : group.mapObjects) {
if (obj instanceof ContainerArea) {
visit(((ContainerArea)obj).droplist, visited, includeSource);
} else if (obj instanceof KeyArea) {
visit(((KeyArea)obj).dialogue, visited, includeSource);
if (((KeyArea)obj).requirement != null) {
visit(((KeyArea)obj).requirement.required_obj, visited, includeSource);
}
} else if (obj instanceof MapChange) {
visit(((MapChange)obj).map, visited, includeSource);
} else if (obj instanceof ReplaceArea) {
if (((ReplaceArea)obj).requirement != null) {
visit(((ReplaceArea)obj).requirement.required_obj, visited, includeSource);
}
} else if (obj instanceof RestArea) {
//Nothing to visit
} else if (obj instanceof ScriptArea) {
visit(((ScriptArea)obj).dialogue, visited, includeSource);
} else if (obj instanceof SignArea) {
visit(((SignArea)obj).dialogue, visited, includeSource);
} else if (obj instanceof SpawnArea) {
if (((SpawnArea)obj).spawnGroup != null) {
for (NPC npc : ((SpawnArea)obj).spawnGroup) {
visit(npc, visited, includeSource);
}
}
}
}
}
}
}
for (GameDataElement backlink : element.getBacklinks()) {
visit(backlink, visited, includeSource);
}
}
private static void visitSpritesheet(Spritesheet element, List<GameDataElement> visited, boolean includeSource) {
//Nothing to visit
//Not even the backlinks. Makes no sense.
}
}