/*
* Copyright 2013 Hannes Janetzek
*
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.oscim.gdx;
import org.oscim.layers.TileGridLayer;
import org.oscim.layers.tile.buildings.BuildingLayer;
import org.oscim.layers.tile.vector.VectorTileLayer;
import org.oscim.layers.tile.vector.labeling.LabelLayer;
import org.oscim.map.Layers;
import org.oscim.map.Map;
import org.oscim.renderer.MapRenderer;
import org.oscim.theme.VtmThemes;
import org.oscim.tiling.TileSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.Timer.Task;
public abstract class GdxMap implements ApplicationListener {
final static Logger log = LoggerFactory.getLogger(GdxMap.class);
protected final Map mMap;
private final MapAdapter mMapAdapter;
VectorTileLayer mMapLayer;
private final MapRenderer mMapRenderer;
public GdxMap() {
mMap = mMapAdapter = new MapAdapter();
mMapRenderer = new MapRenderer(mMap);
}
protected void initDefaultLayers(TileSource tileSource, boolean tileGrid, boolean labels,
boolean buildings) {
Layers layers = mMap.layers();
if (tileSource != null) {
mMapLayer = mMap.setBaseMap(tileSource);
mMap.setTheme(VtmThemes.DEFAULT);
if (buildings)
layers.add(new BuildingLayer(mMap, mMapLayer));
if (labels)
layers.add(new LabelLayer(mMap, mMapLayer));
}
if (tileGrid)
layers.add(new TileGridLayer(mMap));
}
@Override
public void create() {
Gdx.graphics.setContinuousRendering(false);
Gdx.app.setLogLevel(Application.LOG_DEBUG);
int w = Gdx.graphics.getWidth();
int h = Gdx.graphics.getHeight();
mMap.viewport().setScreenSize(w, h);
mMapRenderer.onSurfaceCreated();
mMapRenderer.onSurfaceChanged(w, h);
InputMultiplexer mux = new InputMultiplexer();
mux.addProcessor(new InputHandler(this));
//mux.addProcessor(new GestureDetector(20, 0.5f, 2, 0.05f,
// new MapController(mMap)));
mux.addProcessor(new MotionHandler(mMap));
Gdx.input.setInputProcessor(mux);
createLayers();
}
protected void createLayers() {
mMap.layers().add(new TileGridLayer(mMap));
}
@Override
public void dispose() {
}
@Override
public void render() {
if (!mMapAdapter.needsRedraw())
return;
mMapRenderer.onDrawFrame();
}
@Override
public void resize(int w, int h) {
mMap.viewport().setScreenSize(w, h);
mMapRenderer.onSurfaceChanged(w, h);
mMap.render();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
protected boolean onKeyDown(int keycode) {
return false;
}
public Map getMap() {
return mMap;
}
static class MapAdapter extends Map {
boolean mRenderRequest;
@Override
public int getWidth() {
return Gdx.graphics.getWidth();
}
@Override
public int getHeight() {
return Gdx.graphics.getHeight();
}
@Override
public void updateMap(boolean forceRender) {
if (!mWaitRedraw) {
mWaitRedraw = true;
Gdx.app.postRunnable(mRedrawRequest);
}
}
@Override
public void render() {
mRenderRequest = true;
if (mClearMap)
updateMap(false);
else
Gdx.graphics.requestRendering();
}
@Override
public boolean post(Runnable runnable) {
Gdx.app.postRunnable(runnable);
return true;
}
@Override
public boolean postDelayed(final Runnable action, long delay) {
Timer.schedule(new Task() {
@Override
public void run() {
action.run();
}
}, delay / 1000f);
return true;
}
/**
* Update all Layers on Main thread.
*
* @param forceRedraw
* also render frame FIXME (does nothing atm)
*/
private void redrawMapInternal(boolean forceRedraw) {
updateLayers();
mRenderRequest = true;
Gdx.graphics.requestRendering();
}
/* private */boolean mWaitRedraw;
private final Runnable mRedrawRequest = new Runnable() {
@Override
public void run() {
mWaitRedraw = false;
redrawMapInternal(false);
}
};
public boolean needsRedraw() {
if (!mRenderRequest)
return false;
mRenderRequest = false;
return true;
}
}
}