Enhanced Tiled integration. Can now reload a map that has changed

externaly. Still some rough edges, notably the number of nitification
sto skip when saving in ATCS.
This commit is contained in:
Zukero
2017-03-01 19:02:00 +01:00
parent 061a0fa11b
commit 2a4cfb0684
10 changed files with 177 additions and 6 deletions

View File

@@ -145,8 +145,9 @@ public class Requirement extends JSONElement {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (this.required_obj == oldOne) {
oldOne.removeBacklink((GameDataElement) this.parent);
this.required_obj = newOne;
if (newOne != null) newOne.addBacklink(this);
if (newOne != null) newOne.addBacklink((GameDataElement) this.parent);
}
}
@Override

View File

@@ -29,6 +29,7 @@ public class ContainerArea extends MapObject {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == droplist) {
oldOne.removeBacklink(parentMap);
droplist = (Droplist) newOne;
newOne.addBacklink(parentMap);
}

View File

@@ -60,6 +60,7 @@ public class KeyArea extends MapObject {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
newOne.addBacklink(parentMap);
}

View File

@@ -37,6 +37,7 @@ public class MapChange extends MapObject {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == map) {
oldOne.removeBacklink(parentMap);
map = (TMXMap) newOne;
newOne.addBacklink(parentMap);
}

View File

@@ -42,6 +42,7 @@ public class ScriptArea extends MapObject {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
newOne.addBacklink(parentMap);
}

View File

@@ -31,6 +31,7 @@ public class SignArea extends MapObject {
@Override
public void elementChanged(GameDataElement oldOne, GameDataElement newOne) {
if (oldOne == dialogue) {
oldOne.removeBacklink(parentMap);
dialogue = (Dialogue) newOne;
newOne.addBacklink(parentMap);
}

View File

@@ -64,6 +64,7 @@ public class SpawnArea extends MapObject {
}
}
if (replacedIndex >= 0) {
oldOne.removeBacklink(parentMap);
spawnGroup.set(replacedIndex, (NPC) newOne);
newOne.addBacklink(parentMap);
}

View File

@@ -26,6 +26,7 @@ import com.gpl.rpg.atcontentstudio.model.Project;
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.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet;
import com.gpl.rpg.atcontentstudio.ui.DefaultIcons;
@@ -61,6 +62,8 @@ public class TMXMap extends GameDataElement {
public ColorFilter colorFilter = null;
public boolean writable = false;
public boolean changedOnDisk = false;
public int dismissNextChangeNotif = 0;
public TMXMap(TMXMapSet parent, File f) {
this.parent = parent;
@@ -270,10 +273,13 @@ public class TMXMap extends GameDataElement {
public void save() {
if (writable) {
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.close();
this.state = State.saved;
changedOnDisk = false;
Notification.addSuccess("TMX file "+tmxFile.getAbsolutePath()+" saved.");
} catch (IOException e) {
Notification.addError("Error while writing TMX file "+tmxFile.getAbsolutePath()+" : "+e.getMessage());
@@ -392,5 +398,77 @@ public class TMXMap extends GameDataElement {
ABOVE_LAYER_NAME.equalsIgnoreCase(name) ||
WALKABLE_LAYER_NAME.equalsIgnoreCase(name);
}
public void reload() {
tmxMap = null;
for (Spritesheet s : usedSpritesheets) {
s.elementChanged(this, null);
}
usedSpritesheets.clear();
for (MapObjectGroup g : groups) {
for (MapObject o : g.mapObjects) {
if (o instanceof ContainerArea) {
if (((ContainerArea)o).droplist != null) ((ContainerArea)o).droplist.elementChanged(this, null);
} else if (o instanceof KeyArea) {
if (((KeyArea)o).dialogue != null) ((KeyArea)o).dialogue.elementChanged(this, null);
if (((KeyArea)o).requirement != null && ((KeyArea)o).requirement.required_obj != null) ((KeyArea)o).requirement.required_obj.elementChanged(this, null);
} else if (o instanceof MapChange) {
if (((MapChange)o).map != null) ((MapChange)o).map.elementChanged(this, null);
} else if (o instanceof ReplaceArea) {
if (((ReplaceArea)o).requirement != null && ((ReplaceArea)o).requirement.required_obj != null) ((ReplaceArea)o).requirement.required_obj.elementChanged(this, null);
} else if (o instanceof RestArea) {
} else if (o instanceof ScriptArea) {
if (((ScriptArea)o).dialogue != null) ((ScriptArea)o).dialogue.elementChanged(this, null);
} else if (o instanceof SignArea) {
if (((SignArea)o).dialogue != null) ((SignArea)o).dialogue.elementChanged(this, null);
} else if (o instanceof SpawnArea) {
if (((SpawnArea)o).spawnGroup != null) {
for (NPC n : ((SpawnArea)o).spawnGroup) {
n.elementChanged(this, null);
}
}
}
}
}
groups.clear();
outside = null;
colorFilter = null;
state = GameDataElement.State.init;
this.link();
changedOnDisk = false;
for (MapChangedOnDiskListener l : new ArrayList<TMXMap.MapChangedOnDiskListener>(listeners)) {
l.mapReloaded();
}
}
public void mapChangedOnDisk() {
if (dismissNextChangeNotif > 0) {
dismissNextChangeNotif--;
} else {
changedOnDisk = true;
for (MapChangedOnDiskListener l : new ArrayList<TMXMap.MapChangedOnDiskListener>(listeners)) {
l.mapChanged();
}
}
}
public interface MapChangedOnDiskListener {
public void mapChanged();
public void mapReloaded();
}
private List<MapChangedOnDiskListener> listeners = new ArrayList<TMXMap.MapChangedOnDiskListener>();
public void addMapChangedOnDiskListener(MapChangedOnDiskListener l) {
listeners.add(l);
}
public void removeMapChangedOnDiskListener(MapChangedOnDiskListener l) {
listeners.remove(l);
}
}

View File

@@ -3,9 +3,14 @@ package com.gpl.rpg.atcontentstudio.model.maps;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -87,6 +92,44 @@ public class TMXMapSet implements ProjectTreeNode {
return o1.id.compareTo(o2.id);
}
});
if (source.type == GameSource.Type.created | source.type == GameSource.Type.altered) {
final Path folderPath = Paths.get(mapFolder.getAbsolutePath());
Thread watcher = new Thread("Map folder watcher for "+source.type) {
public void run() {
WatchService watchService;
while(getProject().open) {
try {
watchService = FileSystems.getDefault().newWatchService();
WatchKey watchKey = folderPath.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey wk;
validService: while(getProject().open) {
wk = watchService.take();
for (WatchEvent<?> event : wk.pollEvents()) {
Path changed = (Path) event.context();
String name = changed.getFileName().toString();
System.out.println("Changed: "+name);
String id = name.substring(0, name.length() - 4);
TMXMap map = getMap(id);
if (map != null) {
map.mapChangedOnDisk();
}
}
if(!wk.reset()) {
watchService.close();
break validService;
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
};
watcher.start();
}
}
@Override