mirror of
https://github.com/OMGeeky/andors-trail.git
synced 2026-01-20 10:31:28 +01:00
Added missing top layer to worldmap thumbnails rendering.
This commit is contained in:
@@ -1,317 +1,318 @@
|
||||
package com.gpl.rpg.AndorsTrail.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.activity.DisplayWorldMapActivity;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.MapLayer;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class WorldMapController {
|
||||
|
||||
private static final int WORLDMAP_SCREENSHOT_TILESIZE = 8;
|
||||
public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE;
|
||||
|
||||
public static void updateWorldMap(final WorldContext world, final Resources res) {
|
||||
updateWorldMap(world, world.model.currentMap, world.model.currentTileMap, world.tileManager.currentMapTiles, res);
|
||||
}
|
||||
|
||||
private static void updateWorldMap(
|
||||
final WorldContext world,
|
||||
final PredefinedMap map,
|
||||
final LayeredTileMap mapTiles,
|
||||
final TileCollection cachedTiles,
|
||||
final Resources res) {
|
||||
final String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(map.name);
|
||||
if (worldMapSegmentName == null) return;
|
||||
|
||||
if (!shouldUpdateWorldMap(map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
|
||||
|
||||
(new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... arg0) {
|
||||
final MapRenderer renderer = new MapRenderer(world, map, mapTiles, cachedTiles);
|
||||
try {
|
||||
updateCachedBitmap(map, renderer);
|
||||
updateWorldMapSegment(res, world, worldMapSegmentName);
|
||||
world.maps.worldMapRequiresUpdate = false;
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("WorldMapController: Updated worldmap segment " + worldMapSegmentName + " for map " + map.name);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
L.log("Error creating worldmap file for map " + map.name + " : " + e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
||||
private static boolean shouldUpdateWorldMap(PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
|
||||
if (forceUpdate) return true;
|
||||
if (!map.visited) return true;
|
||||
File file = getFileForMap(map, false);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
file = getCombinedWorldMapFile(worldMapSegmentName);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void updateCachedBitmap(PredefinedMap map, MapRenderer renderer) throws IOException {
|
||||
ensureWorldmapDirectoryExists();
|
||||
|
||||
File file = getFileForMap(map, false);
|
||||
if (file.exists()) return;
|
||||
|
||||
Bitmap image = renderer.drawMap();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
image.compress(Bitmap.CompressFormat.PNG, 70, fos);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
image.recycle();
|
||||
L.log("WorldMapController: Wrote " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
private static final class MapRenderer {
|
||||
private final PredefinedMap map;
|
||||
private final LayeredTileMap mapTiles;
|
||||
private final TileCollection cachedTiles;
|
||||
private final int tileSize;
|
||||
private final float scale;
|
||||
private final Paint mPaint = new Paint();
|
||||
|
||||
public MapRenderer(final WorldContext world, final PredefinedMap map, final LayeredTileMap mapTiles, final TileCollection cachedTiles) {
|
||||
this.map = map;
|
||||
this.mapTiles = mapTiles;
|
||||
this.cachedTiles = cachedTiles;
|
||||
this.tileSize = world.tileManager.tileSize;
|
||||
this.scale = (float) WORLDMAP_SCREENSHOT_TILESIZE / world.tileManager.tileSize;
|
||||
mapTiles.setColorFilter(mPaint);
|
||||
}
|
||||
|
||||
public Bitmap drawMap() {
|
||||
Bitmap image = Bitmap.createBitmap(map.size.width * WORLDMAP_SCREENSHOT_TILESIZE, map.size.height * WORLDMAP_SCREENSHOT_TILESIZE, Config.RGB_565);
|
||||
image.setDensity(Bitmap.DENSITY_NONE);
|
||||
Canvas canvas = new Canvas(image);
|
||||
canvas.scale(scale, scale);
|
||||
|
||||
synchronized (cachedTiles) {
|
||||
drawMapLayer(canvas, mapTiles.currentLayout.layerGround);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerObjects);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerAbove);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private void tryDrawMapLayer(Canvas canvas, final MapLayer layer) {
|
||||
if (layer != null) drawMapLayer(canvas, layer);
|
||||
}
|
||||
|
||||
private void drawMapLayer(Canvas canvas, final MapLayer layer) {
|
||||
int py = 0;
|
||||
for (int y = 0; y < map.size.height; ++y, py += tileSize) {
|
||||
int px = 0;
|
||||
for (int x = 0; x < map.size.width; ++x, px += tileSize) {
|
||||
final int tile = layer.tiles[x][y];
|
||||
if (tile == 0) continue;
|
||||
cachedTiles.drawTile(canvas, tile, px, py, mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureWorldmapDirectoryExists() throws IOException {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File dir = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
dir = new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
|
||||
File noMediaFile = new File(dir, ".nomedia");
|
||||
if (!noMediaFile.exists()) noMediaFile.createNewFile();
|
||||
}
|
||||
public static boolean fileForMapExists(PredefinedMap map) {
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
return getPngFile(map.name + '.' + map.lastSeenLayoutHash).exists();
|
||||
}
|
||||
return getPngFile(map.name).exists();
|
||||
}
|
||||
private static File getFileForMap(PredefinedMap map, boolean verifyFileExists) {
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
File fileWithHash = getPngFile(map.name + '.' + map.lastSeenLayoutHash);
|
||||
if (!verifyFileExists) return fileWithHash;
|
||||
else if (fileWithHash.exists()) return fileWithHash;
|
||||
}
|
||||
return getPngFile(map.name);
|
||||
}
|
||||
private static File getPngFile(String fileName) {
|
||||
return new File(getWorldmapDirectory(), fileName + ".png");
|
||||
}
|
||||
private static File getWorldmapDirectory() {
|
||||
File dir = Environment.getExternalStorageDirectory();
|
||||
dir = new File(dir, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
return new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
}
|
||||
public static File getCombinedWorldMapFile(String segmentName) {
|
||||
return new File(getWorldmapDirectory(), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
|
||||
}
|
||||
|
||||
private static String getWorldMapSegmentAsHtml(Resources res, WorldContext world, String segmentName) {
|
||||
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
|
||||
|
||||
Map<String, File> displayedMapFilenamesPerMapName = new HashMap<String, File>(segment.maps.size());
|
||||
Coord offsetWorldmapTo = new Coord(999999, 999999);
|
||||
for (WorldMapSegmentMap map : segment.maps.values()) {
|
||||
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
|
||||
if (predefinedMap == null) continue;
|
||||
if (!predefinedMap.visited) continue;
|
||||
File f = WorldMapController.getFileForMap(predefinedMap, true);
|
||||
if (!f.exists()) continue;
|
||||
displayedMapFilenamesPerMapName.put(map.mapName, f);
|
||||
|
||||
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
|
||||
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
|
||||
}
|
||||
|
||||
Coord bottomRight = new Coord(0, 0);
|
||||
|
||||
StringBuilder mapsAsHtml = new StringBuilder(1000);
|
||||
for (WorldMapSegmentMap segmentMap : segment.maps.values()) {
|
||||
File f = displayedMapFilenamesPerMapName.get(segmentMap.mapName);
|
||||
if (f == null) continue;
|
||||
|
||||
Size size = getMapSize(segmentMap, world);
|
||||
mapsAsHtml
|
||||
.append("<img src=\"")
|
||||
.append(f.getName())
|
||||
.append("\" id=\"")
|
||||
.append(segmentMap.mapName)
|
||||
.append("\" style=\"width:")
|
||||
.append(size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; height:")
|
||||
.append(size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; left:")
|
||||
.append((segmentMap.worldPosition.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; top:")
|
||||
.append((segmentMap.worldPosition.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px;\" />");
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append('\n');
|
||||
|
||||
bottomRight.x = Math.max(bottomRight.x, segmentMap.worldPosition.x + size.width);
|
||||
bottomRight.y = Math.max(bottomRight.y, segmentMap.worldPosition.y + size.height);
|
||||
}
|
||||
Size worldmapSegmentSize = new Size(
|
||||
(bottomRight.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
|
||||
,(bottomRight.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
|
||||
);
|
||||
|
||||
StringBuilder namedAreasAsHtml = new StringBuilder(500);
|
||||
for (NamedWorldMapArea area : segment.namedAreas.values()) {
|
||||
CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapFilenamesPerMapName.keySet());
|
||||
if (r == null) continue;
|
||||
namedAreasAsHtml
|
||||
.append("<div class=\"namedarea ")
|
||||
.append(area.type)
|
||||
.append("\" style=\"width:")
|
||||
.append(r.size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; line-height:")
|
||||
.append(r.size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; left:")
|
||||
.append((r.topLeft.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; top:")
|
||||
.append((r.topLeft.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px;\"><span>")
|
||||
.append(area.name)
|
||||
.append("</span></div>");
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append('\n');
|
||||
}
|
||||
|
||||
return res.getString(R.string.worldmap_template)
|
||||
.replace("{{maps}}", mapsAsHtml.toString())
|
||||
.replace("{{areas}}", namedAreasAsHtml.toString())
|
||||
.replace("{{sizex}}", Integer.toString(worldmapSegmentSize.width))
|
||||
.replace("{{sizey}}", Integer.toString(worldmapSegmentSize.height))
|
||||
.replace("{{offsetx}}", Integer.toString(offsetWorldmapTo.x * WorldMapController.WORLDMAP_DISPLAY_TILESIZE))
|
||||
.replace("{{offsety}}", Integer.toString(offsetWorldmapTo.y * WorldMapController.WORLDMAP_DISPLAY_TILESIZE));
|
||||
}
|
||||
|
||||
private static Size getMapSize(WorldMapSegmentMap map, WorldContext world) {
|
||||
return world.maps.findPredefinedMap(map.mapName).size;
|
||||
}
|
||||
|
||||
private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Set<String> displayedMapNames) {
|
||||
Coord topLeft = null;
|
||||
Coord bottomRight = null;
|
||||
|
||||
for (String mapName : area.mapNames) {
|
||||
if (!displayedMapNames.contains(mapName)) continue;
|
||||
WorldMapSegmentMap map = segment.maps.get(mapName);
|
||||
Size size = getMapSize(map, world);
|
||||
if (topLeft == null) {
|
||||
topLeft = new Coord(map.worldPosition);
|
||||
} else {
|
||||
topLeft.x = Math.min(topLeft.x, map.worldPosition.x);
|
||||
topLeft.y = Math.min(topLeft.y, map.worldPosition.y);
|
||||
}
|
||||
if (bottomRight == null) {
|
||||
bottomRight = new Coord(map.worldPosition.x + size.width, map.worldPosition.y + size.height);
|
||||
} else {
|
||||
bottomRight.x = Math.max(bottomRight.x, map.worldPosition.x + size.width);
|
||||
bottomRight.y = Math.max(bottomRight.y, map.worldPosition.y + size.height);
|
||||
}
|
||||
}
|
||||
if (topLeft == null) return null;
|
||||
return new CoordRect(topLeft, new Size(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y));
|
||||
}
|
||||
|
||||
private static void updateWorldMapSegment(Resources res, WorldContext world, String segmentName) throws IOException {
|
||||
String mapAsHtml = getWorldMapSegmentAsHtml(res, world, segmentName);
|
||||
File outputFile = getCombinedWorldMapFile(segmentName);
|
||||
PrintWriter pw = new PrintWriter(outputFile);
|
||||
pw.write(mapAsHtml);
|
||||
pw.close();
|
||||
}
|
||||
|
||||
public static boolean displayWorldMap(Context context, WorldContext world) {
|
||||
String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(world.model.currentMap.name);
|
||||
if (worldMapSegmentName == null) {
|
||||
Toast.makeText(context, context.getResources().getString(R.string.display_worldmap_not_available), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, DisplayWorldMapActivity.class);
|
||||
intent.putExtra("worldMapSegmentName", worldMapSegmentName);
|
||||
context.startActivity(intent);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
package com.gpl.rpg.AndorsTrail.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
|
||||
import com.gpl.rpg.AndorsTrail.R;
|
||||
import com.gpl.rpg.AndorsTrail.activity.DisplayWorldMapActivity;
|
||||
import com.gpl.rpg.AndorsTrail.context.WorldContext;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.LayeredTileMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.MapLayer;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.PredefinedMap;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.NamedWorldMapArea;
|
||||
import com.gpl.rpg.AndorsTrail.model.map.WorldMapSegment.WorldMapSegmentMap;
|
||||
import com.gpl.rpg.AndorsTrail.resource.tiles.TileCollection;
|
||||
import com.gpl.rpg.AndorsTrail.util.Coord;
|
||||
import com.gpl.rpg.AndorsTrail.util.CoordRect;
|
||||
import com.gpl.rpg.AndorsTrail.util.L;
|
||||
import com.gpl.rpg.AndorsTrail.util.Size;
|
||||
|
||||
public final class WorldMapController {
|
||||
|
||||
private static final int WORLDMAP_SCREENSHOT_TILESIZE = 8;
|
||||
public static final int WORLDMAP_DISPLAY_TILESIZE = WORLDMAP_SCREENSHOT_TILESIZE;
|
||||
|
||||
public static void updateWorldMap(final WorldContext world, final Resources res) {
|
||||
updateWorldMap(world, world.model.currentMap, world.model.currentTileMap, world.tileManager.currentMapTiles, res);
|
||||
}
|
||||
|
||||
private static void updateWorldMap(
|
||||
final WorldContext world,
|
||||
final PredefinedMap map,
|
||||
final LayeredTileMap mapTiles,
|
||||
final TileCollection cachedTiles,
|
||||
final Resources res) {
|
||||
final String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(map.name);
|
||||
if (worldMapSegmentName == null) return;
|
||||
|
||||
if (!shouldUpdateWorldMap(map, worldMapSegmentName, world.maps.worldMapRequiresUpdate)) return;
|
||||
|
||||
(new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... arg0) {
|
||||
final MapRenderer renderer = new MapRenderer(world, map, mapTiles, cachedTiles);
|
||||
try {
|
||||
updateCachedBitmap(map, renderer);
|
||||
updateWorldMapSegment(res, world, worldMapSegmentName);
|
||||
world.maps.worldMapRequiresUpdate = false;
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
|
||||
L.log("WorldMapController: Updated worldmap segment " + worldMapSegmentName + " for map " + map.name);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
L.log("Error creating worldmap file for map " + map.name + " : " + e.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
||||
private static boolean shouldUpdateWorldMap(PredefinedMap map, String worldMapSegmentName, boolean forceUpdate) {
|
||||
if (forceUpdate) return true;
|
||||
if (!map.visited) return true;
|
||||
File file = getFileForMap(map, false);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
file = getCombinedWorldMapFile(worldMapSegmentName);
|
||||
if (!file.exists()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void updateCachedBitmap(PredefinedMap map, MapRenderer renderer) throws IOException {
|
||||
ensureWorldmapDirectoryExists();
|
||||
|
||||
File file = getFileForMap(map, false);
|
||||
if (file.exists()) return;
|
||||
|
||||
Bitmap image = renderer.drawMap();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
image.compress(Bitmap.CompressFormat.PNG, 70, fos);
|
||||
fos.flush();
|
||||
fos.close();
|
||||
image.recycle();
|
||||
L.log("WorldMapController: Wrote " + file.getAbsolutePath());
|
||||
}
|
||||
|
||||
private static final class MapRenderer {
|
||||
private final PredefinedMap map;
|
||||
private final LayeredTileMap mapTiles;
|
||||
private final TileCollection cachedTiles;
|
||||
private final int tileSize;
|
||||
private final float scale;
|
||||
private final Paint mPaint = new Paint();
|
||||
|
||||
public MapRenderer(final WorldContext world, final PredefinedMap map, final LayeredTileMap mapTiles, final TileCollection cachedTiles) {
|
||||
this.map = map;
|
||||
this.mapTiles = mapTiles;
|
||||
this.cachedTiles = cachedTiles;
|
||||
this.tileSize = world.tileManager.tileSize;
|
||||
this.scale = (float) WORLDMAP_SCREENSHOT_TILESIZE / world.tileManager.tileSize;
|
||||
mapTiles.setColorFilter(mPaint);
|
||||
}
|
||||
|
||||
public Bitmap drawMap() {
|
||||
Bitmap image = Bitmap.createBitmap(map.size.width * WORLDMAP_SCREENSHOT_TILESIZE, map.size.height * WORLDMAP_SCREENSHOT_TILESIZE, Config.RGB_565);
|
||||
image.setDensity(Bitmap.DENSITY_NONE);
|
||||
Canvas canvas = new Canvas(image);
|
||||
canvas.scale(scale, scale);
|
||||
|
||||
synchronized (cachedTiles) {
|
||||
drawMapLayer(canvas, mapTiles.currentLayout.layerGround);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerObjects);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerAbove);
|
||||
tryDrawMapLayer(canvas, mapTiles.currentLayout.layerTop);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private void tryDrawMapLayer(Canvas canvas, final MapLayer layer) {
|
||||
if (layer != null) drawMapLayer(canvas, layer);
|
||||
}
|
||||
|
||||
private void drawMapLayer(Canvas canvas, final MapLayer layer) {
|
||||
int py = 0;
|
||||
for (int y = 0; y < map.size.height; ++y, py += tileSize) {
|
||||
int px = 0;
|
||||
for (int x = 0; x < map.size.width; ++x, px += tileSize) {
|
||||
final int tile = layer.tiles[x][y];
|
||||
if (tile == 0) continue;
|
||||
cachedTiles.drawTile(canvas, tile, px, py, mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureWorldmapDirectoryExists() throws IOException {
|
||||
File root = Environment.getExternalStorageDirectory();
|
||||
File dir = new File(root, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
dir = new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
if (!dir.exists()) dir.mkdir();
|
||||
|
||||
File noMediaFile = new File(dir, ".nomedia");
|
||||
if (!noMediaFile.exists()) noMediaFile.createNewFile();
|
||||
}
|
||||
public static boolean fileForMapExists(PredefinedMap map) {
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
return getPngFile(map.name + '.' + map.lastSeenLayoutHash).exists();
|
||||
}
|
||||
return getPngFile(map.name).exists();
|
||||
}
|
||||
private static File getFileForMap(PredefinedMap map, boolean verifyFileExists) {
|
||||
if (map.lastSeenLayoutHash.length() > 0) {
|
||||
File fileWithHash = getPngFile(map.name + '.' + map.lastSeenLayoutHash);
|
||||
if (!verifyFileExists) return fileWithHash;
|
||||
else if (fileWithHash.exists()) return fileWithHash;
|
||||
}
|
||||
return getPngFile(map.name);
|
||||
}
|
||||
private static File getPngFile(String fileName) {
|
||||
return new File(getWorldmapDirectory(), fileName + ".png");
|
||||
}
|
||||
private static File getWorldmapDirectory() {
|
||||
File dir = Environment.getExternalStorageDirectory();
|
||||
dir = new File(dir, Constants.FILENAME_SAVEGAME_DIRECTORY);
|
||||
return new File(dir, Constants.FILENAME_WORLDMAP_DIRECTORY);
|
||||
}
|
||||
public static File getCombinedWorldMapFile(String segmentName) {
|
||||
return new File(getWorldmapDirectory(), Constants.FILENAME_WORLDMAP_HTMLFILE_PREFIX + segmentName + Constants.FILENAME_WORLDMAP_HTMLFILE_SUFFIX);
|
||||
}
|
||||
|
||||
private static String getWorldMapSegmentAsHtml(Resources res, WorldContext world, String segmentName) {
|
||||
WorldMapSegment segment = world.maps.worldMapSegments.get(segmentName);
|
||||
|
||||
Map<String, File> displayedMapFilenamesPerMapName = new HashMap<String, File>(segment.maps.size());
|
||||
Coord offsetWorldmapTo = new Coord(999999, 999999);
|
||||
for (WorldMapSegmentMap map : segment.maps.values()) {
|
||||
PredefinedMap predefinedMap = world.maps.findPredefinedMap(map.mapName);
|
||||
if (predefinedMap == null) continue;
|
||||
if (!predefinedMap.visited) continue;
|
||||
File f = WorldMapController.getFileForMap(predefinedMap, true);
|
||||
if (!f.exists()) continue;
|
||||
displayedMapFilenamesPerMapName.put(map.mapName, f);
|
||||
|
||||
offsetWorldmapTo.x = Math.min(offsetWorldmapTo.x, map.worldPosition.x);
|
||||
offsetWorldmapTo.y = Math.min(offsetWorldmapTo.y, map.worldPosition.y);
|
||||
}
|
||||
|
||||
Coord bottomRight = new Coord(0, 0);
|
||||
|
||||
StringBuilder mapsAsHtml = new StringBuilder(1000);
|
||||
for (WorldMapSegmentMap segmentMap : segment.maps.values()) {
|
||||
File f = displayedMapFilenamesPerMapName.get(segmentMap.mapName);
|
||||
if (f == null) continue;
|
||||
|
||||
Size size = getMapSize(segmentMap, world);
|
||||
mapsAsHtml
|
||||
.append("<img src=\"")
|
||||
.append(f.getName())
|
||||
.append("\" id=\"")
|
||||
.append(segmentMap.mapName)
|
||||
.append("\" style=\"width:")
|
||||
.append(size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; height:")
|
||||
.append(size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; left:")
|
||||
.append((segmentMap.worldPosition.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; top:")
|
||||
.append((segmentMap.worldPosition.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px;\" />");
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) mapsAsHtml.append('\n');
|
||||
|
||||
bottomRight.x = Math.max(bottomRight.x, segmentMap.worldPosition.x + size.width);
|
||||
bottomRight.y = Math.max(bottomRight.y, segmentMap.worldPosition.y + size.height);
|
||||
}
|
||||
Size worldmapSegmentSize = new Size(
|
||||
(bottomRight.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
|
||||
,(bottomRight.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE
|
||||
);
|
||||
|
||||
StringBuilder namedAreasAsHtml = new StringBuilder(500);
|
||||
for (NamedWorldMapArea area : segment.namedAreas.values()) {
|
||||
CoordRect r = determineNamedAreaBoundary(area, segment, world, displayedMapFilenamesPerMapName.keySet());
|
||||
if (r == null) continue;
|
||||
namedAreasAsHtml
|
||||
.append("<div class=\"namedarea ")
|
||||
.append(area.type)
|
||||
.append("\" style=\"width:")
|
||||
.append(r.size.width * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; line-height:")
|
||||
.append(r.size.height * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; left:")
|
||||
.append((r.topLeft.x - offsetWorldmapTo.x) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px; top:")
|
||||
.append((r.topLeft.y - offsetWorldmapTo.y) * WorldMapController.WORLDMAP_DISPLAY_TILESIZE)
|
||||
.append("px;\"><span>")
|
||||
.append(area.name)
|
||||
.append("</span></div>");
|
||||
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) namedAreasAsHtml.append('\n');
|
||||
}
|
||||
|
||||
return res.getString(R.string.worldmap_template)
|
||||
.replace("{{maps}}", mapsAsHtml.toString())
|
||||
.replace("{{areas}}", namedAreasAsHtml.toString())
|
||||
.replace("{{sizex}}", Integer.toString(worldmapSegmentSize.width))
|
||||
.replace("{{sizey}}", Integer.toString(worldmapSegmentSize.height))
|
||||
.replace("{{offsetx}}", Integer.toString(offsetWorldmapTo.x * WorldMapController.WORLDMAP_DISPLAY_TILESIZE))
|
||||
.replace("{{offsety}}", Integer.toString(offsetWorldmapTo.y * WorldMapController.WORLDMAP_DISPLAY_TILESIZE));
|
||||
}
|
||||
|
||||
private static Size getMapSize(WorldMapSegmentMap map, WorldContext world) {
|
||||
return world.maps.findPredefinedMap(map.mapName).size;
|
||||
}
|
||||
|
||||
private static CoordRect determineNamedAreaBoundary(NamedWorldMapArea area, WorldMapSegment segment, WorldContext world, Set<String> displayedMapNames) {
|
||||
Coord topLeft = null;
|
||||
Coord bottomRight = null;
|
||||
|
||||
for (String mapName : area.mapNames) {
|
||||
if (!displayedMapNames.contains(mapName)) continue;
|
||||
WorldMapSegmentMap map = segment.maps.get(mapName);
|
||||
Size size = getMapSize(map, world);
|
||||
if (topLeft == null) {
|
||||
topLeft = new Coord(map.worldPosition);
|
||||
} else {
|
||||
topLeft.x = Math.min(topLeft.x, map.worldPosition.x);
|
||||
topLeft.y = Math.min(topLeft.y, map.worldPosition.y);
|
||||
}
|
||||
if (bottomRight == null) {
|
||||
bottomRight = new Coord(map.worldPosition.x + size.width, map.worldPosition.y + size.height);
|
||||
} else {
|
||||
bottomRight.x = Math.max(bottomRight.x, map.worldPosition.x + size.width);
|
||||
bottomRight.y = Math.max(bottomRight.y, map.worldPosition.y + size.height);
|
||||
}
|
||||
}
|
||||
if (topLeft == null) return null;
|
||||
return new CoordRect(topLeft, new Size(bottomRight.x - topLeft.x, bottomRight.y - topLeft.y));
|
||||
}
|
||||
|
||||
private static void updateWorldMapSegment(Resources res, WorldContext world, String segmentName) throws IOException {
|
||||
String mapAsHtml = getWorldMapSegmentAsHtml(res, world, segmentName);
|
||||
File outputFile = getCombinedWorldMapFile(segmentName);
|
||||
PrintWriter pw = new PrintWriter(outputFile);
|
||||
pw.write(mapAsHtml);
|
||||
pw.close();
|
||||
}
|
||||
|
||||
public static boolean displayWorldMap(Context context, WorldContext world) {
|
||||
String worldMapSegmentName = world.maps.getWorldMapSegmentNameForMap(world.model.currentMap.name);
|
||||
if (worldMapSegmentName == null) {
|
||||
Toast.makeText(context, context.getResources().getString(R.string.display_worldmap_not_available), Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, DisplayWorldMapActivity.class);
|
||||
intent.putExtra("worldMapSegmentName", worldMapSegmentName);
|
||||
context.startActivity(intent);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user