mirror of https://github.com/YTVanced/VancedMicroG
320 lines
9.8 KiB
Java
320 lines
9.8 KiB
Java
/*
|
|
* Copyright 2013-2015 µg Project Team
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package org.microg.gms.maps.markup;
|
|
|
|
import android.content.Context;
|
|
import android.os.RemoteException;
|
|
|
|
import com.google.android.gms.maps.model.CircleOptions;
|
|
import com.google.android.gms.maps.model.LatLng;
|
|
import com.google.android.gms.maps.model.internal.ICircleDelegate;
|
|
|
|
import org.oscim.android.gl.AndroidGL;
|
|
import org.oscim.backend.GL20;
|
|
import org.oscim.backend.canvas.Color;
|
|
import org.oscim.core.Box;
|
|
import org.oscim.core.Point;
|
|
import org.oscim.core.Tile;
|
|
import org.oscim.layers.Layer;
|
|
import org.oscim.layers.marker.MarkerItem;
|
|
import org.oscim.map.Map;
|
|
import org.oscim.renderer.GLShader;
|
|
import org.oscim.renderer.GLState;
|
|
import org.oscim.renderer.GLViewport;
|
|
import org.oscim.renderer.LayerRenderer;
|
|
import org.oscim.renderer.MapRenderer;
|
|
|
|
import static org.oscim.core.MercatorProjection.groundResolution;
|
|
import static org.oscim.core.MercatorProjection.latitudeToY;
|
|
import static org.oscim.core.MercatorProjection.longitudeToX;
|
|
|
|
public class CircleImpl extends ICircleDelegate.Stub implements Markup {
|
|
|
|
private final String id;
|
|
private final CircleOptions options;
|
|
private final MarkupListener listener;
|
|
private CircleLayer layer;
|
|
private Point point;
|
|
private float drawRadius;
|
|
private boolean removed = false;
|
|
|
|
public CircleImpl(String id, CircleOptions options, MarkupListener listener) {
|
|
this.id = id;
|
|
this.listener = listener;
|
|
this.options = options == null ? new CircleOptions() : options;
|
|
LatLng center = this.options.getCenter();
|
|
if (center != null) {
|
|
point = new Point(longitudeToX(center.longitude), latitudeToY(center.latitude));
|
|
drawRadius = (float) (options.getRadius() / groundResolution(center.latitude, 1));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void remove() throws RemoteException {
|
|
listener.remove(this);
|
|
removed = true;
|
|
layer.setEnabled(false);
|
|
layer = null;
|
|
}
|
|
|
|
@Override
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
|
|
@Override
|
|
public void setCenter(LatLng center) throws RemoteException {
|
|
options.center(center);
|
|
point = new Point(longitudeToX(center.longitude), latitudeToY(center.latitude));
|
|
drawRadius = (float) (options.getRadius() / groundResolution(center.latitude, 1));
|
|
}
|
|
|
|
@Override
|
|
public LatLng getCenter() throws RemoteException {
|
|
return options.getCenter();
|
|
}
|
|
|
|
@Override
|
|
public void setRadius(double radius) throws RemoteException {
|
|
options.radius(radius);
|
|
if (point != null) {
|
|
this.drawRadius = (float) (options.getRadius() / groundResolution(options.getCenter().latitude, 1));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public double getRadius() throws RemoteException {
|
|
return options.getRadius();
|
|
}
|
|
|
|
@Override
|
|
public void setStrokeWidth(float width) throws RemoteException {
|
|
options.strokeWidth(width);
|
|
}
|
|
|
|
@Override
|
|
public float getStrokeWidth() throws RemoteException {
|
|
return options.getStrokeWidth();
|
|
}
|
|
|
|
@Override
|
|
public void setStrokeColor(int color) throws RemoteException {
|
|
options.strokeColor(color);
|
|
}
|
|
|
|
@Override
|
|
public int getStrokeColor() throws RemoteException {
|
|
return options.getStrokeColor();
|
|
}
|
|
|
|
@Override
|
|
public void setFillColor(int color) throws RemoteException {
|
|
options.fillColor(color);
|
|
listener.update(this);
|
|
}
|
|
|
|
@Override
|
|
public int getFillColor() throws RemoteException {
|
|
return options.getFillColor();
|
|
}
|
|
|
|
@Override
|
|
public void setZIndex(float zIndex) throws RemoteException {
|
|
options.zIndex(zIndex);
|
|
}
|
|
|
|
@Override
|
|
public float getZIndex() throws RemoteException {
|
|
return options.getZIndex();
|
|
}
|
|
|
|
@Override
|
|
public void setVisible(boolean visible) throws RemoteException {
|
|
options.visible(visible);
|
|
}
|
|
|
|
@Override
|
|
public boolean isVisible() throws RemoteException {
|
|
return options.isVisible();
|
|
}
|
|
|
|
@Override
|
|
public boolean equalsRemote(ICircleDelegate other) throws RemoteException {
|
|
return other != null && other.getId().equals(getId());
|
|
}
|
|
|
|
@Override
|
|
public int hashCodeRemote() throws RemoteException {
|
|
return id.hashCode();
|
|
}
|
|
|
|
@Override
|
|
public boolean onClick() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isValid() {
|
|
return !removed;
|
|
}
|
|
|
|
@Override
|
|
public MarkerItem getMarkerItem(Context context) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public Layer getLayer(Context context, Map map) {
|
|
if (layer == null) {
|
|
layer = new CircleLayer(map);
|
|
}
|
|
return layer;
|
|
}
|
|
|
|
@Override
|
|
public Type getType() {
|
|
return Type.LAYER;
|
|
}
|
|
|
|
private class CircleLayer extends Layer {
|
|
|
|
public CircleLayer(Map map) {
|
|
super(map);
|
|
mRenderer = new CircleRenderer();
|
|
}
|
|
|
|
private class CircleRenderer extends LayerRenderer {
|
|
private final Box bBox = new Box();
|
|
private final Point screenPoint = new Point();
|
|
private final Point indicatorPosition = new Point();
|
|
private AndroidGL GL = new AndroidGL();
|
|
|
|
private int shader;
|
|
private int vertexPosition;
|
|
private int matrixPosition;
|
|
private int phase;
|
|
private int scale;
|
|
private int direction;
|
|
private int color;
|
|
|
|
@Override
|
|
public void update(GLViewport viewport) {
|
|
if (!isEnabled()) {
|
|
setReady(false);
|
|
return;
|
|
}
|
|
|
|
if (!viewport.changed() && isReady()) return;
|
|
|
|
setReady(true);
|
|
|
|
int width = mMap.getWidth();
|
|
int height = mMap.getHeight();
|
|
|
|
// clamp location to a position that can be
|
|
// savely translated to screen coordinates
|
|
viewport.getBBox(bBox, 0);
|
|
|
|
double x = point.x;
|
|
double y = point.y;
|
|
|
|
// get position of Location in pixel relative to
|
|
// screen center
|
|
viewport.toScreenPoint(x, y, screenPoint);
|
|
|
|
x = screenPoint.x + width / 2;
|
|
y = screenPoint.y + height / 2;
|
|
|
|
viewport.fromScreenPoint(x, y, indicatorPosition);
|
|
}
|
|
|
|
@Override
|
|
public void render(GLViewport viewport) {
|
|
|
|
GLState.useProgram(shader);
|
|
GLState.blend(true);
|
|
GLState.test(false, false);
|
|
|
|
GLState.enableVertexArrays(vertexPosition, -1);
|
|
MapRenderer.bindQuadVertexVBO(vertexPosition);
|
|
|
|
float radius = (float) (drawRadius * viewport.pos.scale);
|
|
GL.uniform1f(scale, radius);
|
|
|
|
double x = indicatorPosition.x - viewport.pos.x;
|
|
double y = indicatorPosition.y - viewport.pos.y;
|
|
double tileScale = Tile.SIZE * viewport.pos.scale;
|
|
|
|
viewport.mvp.setTransScale((float) (x * tileScale), (float) (y * tileScale), 1);
|
|
viewport.mvp.multiplyMM(viewport.viewproj, viewport.mvp);
|
|
viewport.mvp.setAsUniform(matrixPosition);
|
|
GL.uniform1f(phase, 1);
|
|
GL.uniform2f(direction, 0, 0);
|
|
float alpha = Color.aToFloat(options.getFillColor());
|
|
GL.uniform4f(color,
|
|
Color.rToFloat(options.getFillColor()) * alpha,
|
|
Color.gToFloat(options.getFillColor()) * alpha,
|
|
Color.bToFloat(options.getFillColor()) * alpha,
|
|
alpha);
|
|
|
|
GL.drawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
|
|
}
|
|
|
|
@Override
|
|
public boolean setup() {
|
|
shader = GLShader.createProgram(vShaderStr, fShaderStr);
|
|
if (shader == 0)
|
|
return false;
|
|
vertexPosition = GL.getAttribLocation(shader, "a_pos");
|
|
matrixPosition = GL.getUniformLocation(shader, "u_mvp");
|
|
phase = GL.getUniformLocation(shader, "u_phase");
|
|
scale = GL.getUniformLocation(shader, "u_scale");
|
|
direction = GL.getUniformLocation(shader, "u_dir");
|
|
color = GL.getUniformLocation(shader, "u_color");
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private final static String vShaderStr = ""
|
|
+ "precision mediump float;"
|
|
+ "uniform mat4 u_mvp;"
|
|
+ "uniform float u_phase;"
|
|
+ "uniform float u_scale;"
|
|
+ "attribute vec2 a_pos;"
|
|
+ "varying vec2 v_tex;"
|
|
+ "void main() {"
|
|
+ " gl_Position = u_mvp * vec4(a_pos * u_scale * u_phase, 0.0, 1.0);"
|
|
+ " v_tex = a_pos;"
|
|
+ "}";
|
|
|
|
private final static String fShaderStr = ""
|
|
+ "precision mediump float;"
|
|
+ "varying vec2 v_tex;"
|
|
+ "uniform float u_scale;"
|
|
+ "uniform float u_phase;"
|
|
+ "uniform vec2 u_dir;"
|
|
+ "uniform vec4 u_color;"
|
|
|
|
+ "void main() {"
|
|
+ " float len = 1.0 - length(v_tex);"
|
|
+ " float a = smoothstep(0.0, 2.0 / u_scale, len);"
|
|
+ " gl_FragColor = u_color * a;"
|
|
+ "}";
|
|
}
|