getRenderingExceptions()
{
return this.renderingExceptions;
}
+ @Override
public ScreenCreditController getScreenCreditController()
{
return screenCreditController;
}
+ @Override
public void setScreenCreditController(ScreenCreditController screenCreditController)
{
this.screenCreditController = screenCreditController;
}
/** {@inheritDoc} */
+ @Override
public GLRuntimeCapabilities getGLRuntimeCapabilities()
{
return this.glRuntimeCaps;
}
/** {@inheritDoc} */
+ @Override
public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
{
if (capabilities == null)
@@ -411,6 +440,7 @@ public void setDeferOrderedRendering(boolean deferOrderedRendering)
this.deferOrderedRendering = deferOrderedRendering;
}
+ @Override
public int repaint()
{
this.frameTime = System.currentTimeMillis();
@@ -635,8 +665,8 @@ protected void preRender(DrawContext dc)
protected void pickTerrain(DrawContext dc)
{
- if (dc.isPickingMode() && dc.getVisibleSector() != null && dc.getSurfaceGeometry() != null &&
- dc.getSurfaceGeometry().size() > 0)
+ if (dc.isPickingMode() && dc.getVisibleSector() != null && dc.getSurfaceGeometry() != null
+ && dc.getSurfaceGeometry().size() > 0)
{
this.pickPoints.clear();
if (dc.getPickPoint() != null)
@@ -757,7 +787,10 @@ else if (pol != null && pol.size() > 1)
// used to cull the number of colors that the draw context must consider with identifying the unique
// pick colors in the specified screen rectangle.
if (minAndMaxColorCodes == null)
- minAndMaxColorCodes = new int[] {colorCode, colorCode};
+ minAndMaxColorCodes = new int[]
+ {
+ colorCode, colorCode
+ };
else
{
if (minAndMaxColorCodes[0] > colorCode)
@@ -809,8 +842,8 @@ protected void pick(DrawContext dc)
this.lastPickedObjects = new PickedObjectList(dc.getPickedObjects());
this.lastObjectsInPickRect = new PickedObjectList(dc.getObjectsInPickRectangle());
- if (this.isDeepPickEnabled() &&
- (this.lastPickedObjects.hasNonTerrainObjects() || this.lastObjectsInPickRect.hasNonTerrainObjects()))
+ if (this.isDeepPickEnabled()
+ && (this.lastPickedObjects.hasNonTerrainObjects() || this.lastObjectsInPickRect.hasNonTerrainObjects()))
{
this.doDeepPick(dc);
}
@@ -957,8 +990,8 @@ protected void draw(DrawContext dc)
dc.setOrderedRenderingMode(false);
// Draw the diagnostic displays.
- if (dc.getSurfaceGeometry() != null && dc.getModel() != null && (dc.getModel().isShowWireframeExterior() ||
- dc.getModel().isShowWireframeInterior() || dc.getModel().isShowTessellationBoundingVolumes()))
+ if (dc.getSurfaceGeometry() != null && dc.getModel() != null && (dc.getModel().isShowWireframeExterior()
+ || dc.getModel().isShowWireframeInterior() || dc.getModel().isShowTessellationBoundingVolumes()))
{
Model model = dc.getModel();
@@ -994,7 +1027,6 @@ protected void draw(DrawContext dc)
*
* @param dc the relevant DrawContext
*/
- @SuppressWarnings({"UNUSED_SYMBOL", "UnusedDeclaration"})
protected void checkGLErrors(DrawContext dc)
{
GL gl = dc.getGL();
@@ -1010,7 +1042,6 @@ protected void checkGLErrors(DrawContext dc)
//**************************************************************//
//******************** Ordered Surface Renderable ************//
//**************************************************************//
-
protected void preRenderOrderedSurfaceRenderables(DrawContext dc)
{
if (dc.getOrderedSurfaceRenderables().isEmpty())
@@ -1125,9 +1156,9 @@ protected void drawCompositeSurfaceObjects(DrawContext dc)
if (tileCount == 0)
return;
- int attributeMask =
- GL2.GL_COLOR_BUFFER_BIT // For alpha test enable, blend enable, alpha func, blend func, blend ref.
- | GL2.GL_POLYGON_BIT; // For cull face enable, cull face, polygon mode.
+ int attributeMask
+ = GL2.GL_COLOR_BUFFER_BIT // For alpha test enable, blend enable, alpha func, blend func, blend ref.
+ | GL2.GL_POLYGON_BIT; // For cull face enable, cull face, polygon mode.
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
OGLStackHandler ogsh = new OGLStackHandler();
diff --git a/src/gov/nasa/worldwind/SceneController.java b/src/gov/nasa/worldwind/SceneController.java
index 2cbf20ee7b..7b93ad2664 100644
--- a/src/gov/nasa/worldwind/SceneController.java
+++ b/src/gov/nasa/worldwind/SceneController.java
@@ -128,7 +128,7 @@ public interface SceneController extends WWObject, Disposable
double getFrameTime();
/**
- * Specifies the current pick point in AWT screen coordinates, or null to indicate that there is no
+ * Specifies the current pick point in GL surface screen coordinates, or null to indicate that there is no
* pick point. Each frame, this scene controller determines which objects are drawn at the pick point and places
* them in a PickedObjectList. This list can be accessed by calling {@link #getPickedObjectList()}.
*
@@ -140,7 +140,7 @@ public interface SceneController extends WWObject, Disposable
void setPickPoint(Point pickPoint);
/**
- * Returns the current pick point in AWT screen coordinates.
+ * Returns the current pick point in GL surface coordinates.
*
* @return the current pick point, or null if no pick point is current.
*
@@ -149,7 +149,7 @@ public interface SceneController extends WWObject, Disposable
Point getPickPoint();
/**
- * Specifies the current pick rectangle in AWT screen coordinates, or null to indicate that there is no
+ * Specifies the current pick rectangle in GL surface coordinates, or null to indicate that there is no
* pick rectangle. Each frame, this scene controller determines which objects intersect the pick rectangle and
* places them in a PickedObjectList. This list can be accessed by calling {@link #getObjectsInPickRectangle()}.
*
@@ -161,7 +161,7 @@ public interface SceneController extends WWObject, Disposable
void setPickRectangle(Rectangle pickRect);
/**
- * Returns the current pick rectangle in AWT screen coordinates.
+ * Returns the current pick rectangle in GL surface coordinates.
*
* @return the current pick rectangle, or null if no pick rectangle is current.
*
diff --git a/src/gov/nasa/worldwind/WorldWindowImpl.java b/src/gov/nasa/worldwind/WorldWindowImpl.java
index 51da668096..d375bcba25 100644
--- a/src/gov/nasa/worldwind/WorldWindowImpl.java
+++ b/src/gov/nasa/worldwind/WorldWindowImpl.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is 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.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -28,7 +28,6 @@
package gov.nasa.worldwind;
-import com.jogamp.nativewindow.ScalableSurface;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.cache.*;
import gov.nasa.worldwind.event.*;
@@ -68,6 +67,7 @@ public WorldWindowImpl()
* Causes resources used by the WorldWindow to be freed. The WorldWindow cannot be used once this method is
* called. An OpenGL context for the window must be current.
*/
+ @Override
public void shutdown()
{
WorldWind.getDataFileStore().removePropertyChangeListener(this);
@@ -104,6 +104,7 @@ public void shutdown()
sc.dispose();
}
+ @Override
public GpuResourceCache getGpuResourceCache()
{
return this.gpuResourceCache;
@@ -115,6 +116,7 @@ public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
this.sceneController.setGpuResourceCache(this.gpuResourceCache);
}
+ @Override
public void setModel(Model model)
{
// model can be null, that's ok - it indicates no model.
@@ -122,11 +124,13 @@ public void setModel(Model model)
this.sceneController.setModel(model);
}
+ @Override
public Model getModel()
{
return this.sceneController != null ? this.sceneController.getModel() : null;
}
+ @Override
public void setView(View view)
{
// view can be null, that's ok - it indicates no view.
@@ -134,22 +138,26 @@ public void setView(View view)
this.sceneController.setView(view);
}
+ @Override
public View getView()
{
return this.sceneController != null ? this.sceneController.getView() : null;
}
+ @Override
public void setModelAndView(Model model, View view)
{
this.setModel(model);
this.setView(view);
}
+ @Override
public SceneController getSceneController()
{
return this.sceneController;
}
+ @Override
public void setSceneController(SceneController sc)
{
if (sc != null && this.getSceneController() != null)
@@ -160,30 +168,36 @@ public void setSceneController(SceneController sc)
this.sceneController = sc;
}
+ @Override
public InputHandler getInputHandler()
{
return this.inputHandler;
}
+ @Override
public void setInputHandler(InputHandler inputHandler)
{
this.inputHandler = inputHandler;
}
+ @Override
public void redraw()
{
}
+ @Override
public void redrawNow()
{
}
+ @Override
public void setPerFrameStatisticsKeys(Set keys)
{
if (this.sceneController != null)
this.sceneController.setPerFrameStatisticsKeys(keys);
}
+ @Override
public Collection getPerFrameStatistics()
{
if (this.sceneController == null || this.sceneController.getPerFrameStatistics() == null)
@@ -192,16 +206,19 @@ public Collection getPerFrameStatistics()
return this.sceneController.getPerFrameStatistics();
}
+ @Override
public PickedObjectList getObjectsAtCurrentPosition()
{
return null;
}
+ @Override
public PickedObjectList getObjectsInSelectionBox()
{
return null;
}
+ @Override
public Position getCurrentPosition()
{
if (this.sceneController == null)
@@ -243,11 +260,13 @@ protected PickedObjectList getCurrentBoxSelection()
return pol != null && pol.size() > 0 ? pol : null;
}
+ @Override
public void addRenderingListener(RenderingListener listener)
{
this.eventListeners.add(RenderingListener.class, listener);
}
+ @Override
public void removeRenderingListener(RenderingListener listener)
{
this.eventListeners.remove(RenderingListener.class, listener);
@@ -261,11 +280,13 @@ protected void callRenderingListeners(RenderingEvent event)
}
}
+ @Override
public void addPositionListener(PositionListener listener)
{
this.eventListeners.add(PositionListener.class, listener);
}
+ @Override
public void removePositionListener(PositionListener listener)
{
this.eventListeners.remove(PositionListener.class, listener);
@@ -275,6 +296,7 @@ protected void callPositionListeners(final PositionEvent event)
{
EventQueue.invokeLater(new Runnable()
{
+ @Override
public void run()
{
for (PositionListener listener : eventListeners.getListeners(PositionListener.class))
@@ -285,11 +307,13 @@ public void run()
});
}
+ @Override
public void addSelectListener(SelectListener listener)
{
this.eventListeners.add(SelectListener.class, listener);
}
+ @Override
public void removeSelectListener(SelectListener listener)
{
this.eventListeners.remove(SelectListener.class, listener);
@@ -299,6 +323,7 @@ protected void callSelectListeners(final SelectEvent event)
{
EventQueue.invokeLater(new Runnable()
{
+ @Override
public void run()
{
for (SelectListener listener : eventListeners.getListeners(SelectListener.class))
@@ -309,11 +334,13 @@ public void run()
});
}
+ @Override
public void addRenderingExceptionListener(RenderingExceptionListener listener)
{
this.eventListeners.add(RenderingExceptionListener.class, listener);
}
+ @Override
public void removeRenderingExceptionListener(RenderingExceptionListener listener)
{
this.eventListeners.remove(RenderingExceptionListener.class, listener);
@@ -323,6 +350,7 @@ protected void callRenderingExceptionListeners(final Throwable exception)
{
EventQueue.invokeLater(new Runnable()
{
+ @Override
public void run()
{
for (RenderingExceptionListener listener : eventListeners.getListeners(
@@ -341,32 +369,4 @@ public static GpuResourceCache createGpuResourceCache()
long cacheSize = Configuration.getLongValue(AVKey.TEXTURE_CACHE_SIZE, FALLBACK_TEXTURE_CACHE_SIZE);
return new BasicGpuResourceCache((long) (0.8 * cacheSize), cacheSize);
}
-
- /**
- * Configures JOGL's surface pixel scaling on the specified
- * ScalableSurface to ensure backward compatibility with
- * WorldWind applications developed prior to JOGL pixel scaling's
- * introduction.This method is used by GLCanvas and
- * GLJPanel to effectively disable JOGL's surface pixel scaling
- * by requesting a 1:1 scale.
- * Since v2.2.0, JOGL defaults to using high-dpi pixel scales where
- * possible. This causes WorldWind screen elements such as placemarks, the
- * compass, the world map, the view controls, and the scale bar (plus many
- * more) to appear smaller than they are intended to on screen. The high-dpi
- * default also has the effect of degrading WorldWind rendering performance.
- *
- * @param surface The surface to configure.
- */
- public static void configureIdentityPixelScale(ScalableSurface surface)
- {
- if (surface == null)
- {
- String message = Logging.getMessage("nullValue.SurfaceIsNull");
- Logging.logger().severe(message);
- throw new IllegalArgumentException(message);
- }
-
- float[] identityScale = new float[] {ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE};
- surface.setSurfaceScale(identityScale);
- }
}
diff --git a/src/gov/nasa/worldwind/animation/MoveToDoubleAnimator.java b/src/gov/nasa/worldwind/animation/MoveToDoubleAnimator.java
index 68305c6b3a..aa999bd25a 100644
--- a/src/gov/nasa/worldwind/animation/MoveToDoubleAnimator.java
+++ b/src/gov/nasa/worldwind/animation/MoveToDoubleAnimator.java
@@ -1,84 +1,86 @@
/*
- * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
- * Administrator of the National Aeronautics and Space Administration.
+ * Copyright 2006-2009, 2017, 2020 United States Government,
+ * as represented by the Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
- * The NASA World Wind Java (WWJ) platform is 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
- *
+ *
+ * The NASA World Wind Java (WWJ) platform is 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.
- *
- * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
- * software:
- *
+ *
+ * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source software:
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
- * JOGL – Licensed under Berkeley Software Distribution (BSD)
+ * JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
- * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
- * notices and licenses PDF found in code directory.
+ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
+ * notices and licenses PDF found in the code directory.
*/
package gov.nasa.worldwind.animation;
import gov.nasa.worldwind.util.PropertyAccessor;
/**
- * Animates the value to the specified end position, using the specified smoothing, until the value is within the
- * specified minEpsilon of the end value. For each frame the animator interpolates between the current value and the
- * target(end) value using (1.0-smoothing) as the interpolant, until the difference between the current
- * value and the target(end) value is less than the minEpsilon value.
+ * Animates a double value toward a specified end position using a smoothing factor.
+ * The animation continues until the current value is within a defined {@code minEpsilon}
+ * distance of the end value.
+ *
+ * For each frame, the animator interpolates between the current value and the target value
+ * using {@code (1.0 - smoothing)} as the interpolation factor, until the absolute difference
+ * between the two is less than {@code minEpsilon}.
+ *
*
* @author jym
* @version $Id: MoveToDoubleAnimator.java 1171 2013-02-11 21:45:02Z dcollins $
*/
-public class MoveToDoubleAnimator extends DoubleAnimator
-{
+public class MoveToDoubleAnimator extends DoubleAnimator {
+
/**
- * The amount of delta between the end value and the current value that is required to stop the animation. Defaults
- * to .001.
+ * The minimum difference between the end value and the current value required
+ * to stop the animation. Defaults to {@code 0.001}.
*/
protected double minEpsilon = 1e-3;
- /** The amount of smoothing. A number between 0 and 1. The higher the number the greater the smoothing. */
- protected double smoothing = .9;
/**
- * Construct a {@link MoveToDoubleAnimator}
+ * The smoothing factor, a number between 0 and 1.
+ * Higher values produce smoother, slower movement.
+ */
+ protected double smoothing = 0.9;
+
+ /**
+ * Constructs a {@link MoveToDoubleAnimator}.
*
- * @param end The target value, the value to animate to.
- * @param smoothing The smoothing factor. A number between 0 and 1. The higher the number the greater the
- * smoothing.
- * @param propertyAccessor The accessor used to access the animated value.
+ * @param end The target value to animate toward.
+ * @param smoothing The smoothing factor (0–1). Higher means smoother/slower.
+ * @param propertyAccessor The accessor used to get and set the animated value.
*/
- public MoveToDoubleAnimator(
- Double end, double smoothing,
- PropertyAccessor.DoubleAccessor propertyAccessor)
- {
+ public MoveToDoubleAnimator(Double end, double smoothing,
+ PropertyAccessor.DoubleAccessor propertyAccessor) {
super(null, 0, end, propertyAccessor);
this.interpolator = null;
this.smoothing = smoothing;
}
/**
- * Construct a {@link MoveToDoubleAnimator}
+ * Constructs a {@link MoveToDoubleAnimator}.
*
- * @param end The target value, the value to animate to.
- * @param smoothing smoothing The smoothing factor. A number between 0 and 1. The higher the number the
- * greater the smoothing.
- * @param minEpsilon The minimum difference between the current value and the target value that triggers the
- * end of the animation. Defaults to .001.
- * @param propertyAccessor The double accessor used to access the animated value.
+ * @param end The target value to animate toward.
+ * @param smoothing The smoothing factor (0–1). Higher means smoother/slower.
+ * @param minEpsilon The minimum difference between the current value and target
+ * value that triggers the end of the animation.
+ * @param propertyAccessor The accessor used to get and set the animated value.
*/
- public MoveToDoubleAnimator(
- Double end, double smoothing, double minEpsilon,
- PropertyAccessor.DoubleAccessor propertyAccessor)
- {
+ public MoveToDoubleAnimator(Double end, double smoothing, double minEpsilon,
+ PropertyAccessor.DoubleAccessor propertyAccessor) {
super(null, 0, end, propertyAccessor);
this.interpolator = null;
this.smoothing = smoothing;
@@ -86,31 +88,34 @@ public MoveToDoubleAnimator(
}
/**
- * Set the value to the next value in the animation. This interpolates between the current value and the target
- * value using 1.0-smoothing as the interpolant.
+ * Advances the animation to the next frame.
+ *
+ * Interpolates between the current value and the target value using
+ * {@code (1.0 - smoothing)} as the interpolation factor.
+ *
*/
- public void next()
- {
- if (hasNext())
+ public void next() {
+ if (hasNext()) {
set(1.0 - smoothing);
+ }
}
/**
- * Get the next value using the given interpolantto perform a linear interplation. between the current value and the
- * target(end) value.
+ * Computes the next interpolated double value based on the given interpolant.
+ * Performs linear interpolation between the current and target values.
*
- * @param interpolant The inerpolant to be used to perform the interpolation. A number between 0 and 1.
- *
- * @return the interpolated value.
+ * @param interpolant The interpolation factor (0–1).
+ * @return The interpolated value, or {@code null} if the animation has stopped.
*/
- public Double nextDouble(double interpolant)
- {
- double newValue = (1 - interpolant) * propertyAccessor.getDouble() + interpolant * this.end;
- if (Math.abs(newValue - propertyAccessor.getDouble()) < minEpsilon)
- {
+ public Double nextDouble(double interpolant) {
+ double currentValue = propertyAccessor.getDouble();
+ double newValue = (1 - interpolant) * currentValue + interpolant * this.end;
+
+ if (Math.abs(newValue - currentValue) < minEpsilon) {
this.stop();
- return (null);
+ return null;
}
+
return newValue;
}
}
diff --git a/src/gov/nasa/worldwind/awt/AWTInputHandler.java b/src/gov/nasa/worldwind/awt/AWTInputHandler.java
index 3697849cdc..4915cd6d77 100644
--- a/src/gov/nasa/worldwind/awt/AWTInputHandler.java
+++ b/src/gov/nasa/worldwind/awt/AWTInputHandler.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is 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.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -57,6 +57,7 @@ public class AWTInputHandler extends WWObjectImpl
protected boolean forceRedrawOnMousePressed = Configuration.getBooleanValue(AVKey.REDRAW_ON_MOUSE_PRESSED, false);
protected javax.swing.Timer hoverTimer = new javax.swing.Timer(600, new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent actionEvent)
{
if (AWTInputHandler.this.pickMatches(AWTInputHandler.this.hoverObjects))
@@ -75,6 +76,7 @@ public AWTInputHandler()
{
}
+ @Override
public void dispose()
{
this.hoverTimer.stop();
@@ -91,6 +93,7 @@ public void dispose()
this.objectsAtButtonPress = null;
}
+ @Override
public void setEventSource(WorldWindow newWorldWindow)
{
if (newWorldWindow != null && !(newWorldWindow instanceof Component))
@@ -139,6 +142,7 @@ public void setEventSource(WorldWindow newWorldWindow)
this.selectListener = new SelectListener()
{
+ @Override
public void selected(SelectEvent event)
{
if (event.getEventAction().equals(SelectEvent.ROLLOVER))
@@ -160,16 +164,19 @@ public void removeHoverSelectListener()
this.wwd.removeSelectListener(selectListener);
}
+ @Override
public WorldWindow getEventSource()
{
return this.wwd;
}
+ @Override
public void setHoverDelay(int delay)
{
this.hoverTimer.setDelay(delay);
}
+ @Override
public int getHoverDelay()
{
return this.hoverTimer.getDelay();
@@ -250,22 +257,25 @@ protected void setObjectsAtButtonPress(PickedObjectList objectsAtButtonPress)
this.objectsAtButtonPress = objectsAtButtonPress;
}
+ @Override
public boolean isForceRedrawOnMousePressed()
{
return forceRedrawOnMousePressed;
}
+ @Override
public void setForceRedrawOnMousePressed(boolean forceRedrawOnMousePressed)
{
this.forceRedrawOnMousePressed = forceRedrawOnMousePressed;
}
-/*
+
+ /*
public ViewInputHandler getViewInputHandler()
{
return viewInputHandler;
}
- */
-
+ */
+ @Override
public void keyTyped(KeyEvent keyEvent)
{
if (this.wwd == null)
@@ -286,6 +296,7 @@ public void keyTyped(KeyEvent keyEvent)
}
}
+ @Override
public void keyPressed(KeyEvent keyEvent)
{
if (this.wwd == null)
@@ -306,6 +317,7 @@ public void keyPressed(KeyEvent keyEvent)
}
}
+ @Override
public void keyReleased(KeyEvent keyEvent)
{
if (this.wwd == null)
@@ -326,7 +338,48 @@ public void keyReleased(KeyEvent keyEvent)
}
}
- public void mouseClicked(final MouseEvent mouseEvent)
+ /**
+ * Construct a mouse event with GL surface screen coordinates
+ * @param e
+ * @return
+ */
+ private MouseEvent glMouseEvent(MouseEvent awtMouseEvent)
+ {
+ int[] GLmousePt = wwd.getSceneController().getDrawContext().awtPointToGLpoint(awtMouseEvent.getPoint());
+ MouseEvent e = new MouseEvent(awtMouseEvent.getComponent(), awtMouseEvent.getID(),
+ awtMouseEvent.getWhen(), awtMouseEvent.getModifiersEx(),
+ GLmousePt[0], GLmousePt[1], awtMouseEvent.getClickCount(), awtMouseEvent.isPopupTrigger(),
+ awtMouseEvent.getButton());
+
+ if (awtMouseEvent.isConsumed()) // needed in case this method is overridden by a subclass
+ e.consume();
+
+ return e;
+ }
+
+ /**
+ * Construct a mouse wheel event with GL surface screen coordinates
+ * @param e
+ * @return
+ */
+ private MouseWheelEvent glMouseWheelEvent(MouseWheelEvent awtEv)
+ {
+ int[] GLmousePt = wwd.getSceneController().getDrawContext().awtPointToGLpoint(awtEv.getPoint());
+ MouseWheelEvent e = new MouseWheelEvent(awtEv.getComponent(), awtEv.getID(),
+ awtEv.getWhen(), awtEv.getModifiersEx(),
+ GLmousePt[0], GLmousePt[1], awtEv.getXOnScreen(), awtEv.getYOnScreen(),
+ awtEv.getClickCount(), awtEv.isPopupTrigger(),
+ awtEv.getScrollType(), awtEv.getScrollAmount(),
+ awtEv.getWheelRotation(), awtEv.getPreciseWheelRotation());
+
+ if (awtEv.isConsumed()) // needed in case this method is overridden by a subclass
+ e.consume();
+
+ return e;
+ }
+
+ @Override
+ public void mouseClicked(final MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
@@ -338,10 +391,11 @@ public void mouseClicked(final MouseEvent mouseEvent)
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
PickedObjectList pickedObjects = this.wwd.getObjectsAtCurrentPosition();
@@ -350,24 +404,26 @@ public void mouseClicked(final MouseEvent mouseEvent)
if (pickedObjects != null && pickedObjects.getTopPickedObject() != null
&& !pickedObjects.getTopPickedObject().isTerrain())
{
- // Something is under the cursor, so it's deemed "selected".
+ Point awtPt = awtMouseEvent.getPoint(); // AWT screen coordinates
+
+ // Something is under the cursor, so it's deemed "selected".
if (MouseEvent.BUTTON1 == mouseEvent.getButton())
{
if (mouseEvent.getClickCount() <= 1)
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.LEFT_CLICK,
- mouseEvent, pickedObjects));
+ awtPt, mouseEvent, pickedObjects));
}
else
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.LEFT_DOUBLE_CLICK,
- mouseEvent, pickedObjects));
+ awtPt, mouseEvent, pickedObjects));
}
}
else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.RIGHT_CLICK,
- mouseEvent, pickedObjects));
+ awtPt, mouseEvent, pickedObjects));
}
this.wwd.getView().firePropertyChange(AVKey.VIEW, null, this.wwd.getView());
@@ -381,20 +437,22 @@ else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
}
}
- public void mousePressed(MouseEvent mouseEvent)
+ @Override
+ public void mousePressed(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
// Determine if the mouse point has changed since the last mouse move event. This can happen if user switches to
// another window, moves the mouse, and then switches back to the WorldWind window.
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
boolean mousePointChanged = !mouseEvent.getPoint().equals(this.mousePoint);
this.mousePoint = mouseEvent.getPoint();
@@ -416,16 +474,18 @@ public void mousePressed(MouseEvent mouseEvent)
if (this.objectsAtButtonPress != null && objectsAtButtonPress.getTopPickedObject() != null
&& !this.objectsAtButtonPress.getTopPickedObject().isTerrain())
{
+ Point awtPt = awtMouseEvent.getPoint(); // AWT screen coordinates
+
// Something is under the cursor, so it's deemed "selected".
if (MouseEvent.BUTTON1 == mouseEvent.getButton())
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.LEFT_PRESS,
- mouseEvent, this.objectsAtButtonPress));
+ awtPt, mouseEvent, this.objectsAtButtonPress));
}
else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
{
this.callSelectListeners(new SelectEvent(this.wwd, SelectEvent.RIGHT_PRESS,
- mouseEvent, this.objectsAtButtonPress));
+ awtPt, mouseEvent, this.objectsAtButtonPress));
}
// Initiate a repaint.
@@ -448,18 +508,20 @@ else if (MouseEvent.BUTTON3 == mouseEvent.getButton())
}
}
- public void mouseReleased(MouseEvent mouseEvent)
+ @Override
+ public void mouseReleased(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.mousePoint = mouseEvent.getPoint();
this.callMouseReleasedListeners(mouseEvent);
if (!mouseEvent.isConsumed())
@@ -470,36 +532,40 @@ public void mouseReleased(MouseEvent mouseEvent)
this.cancelDrag();
}
- public void mouseEntered(MouseEvent mouseEvent)
+ @Override
+ public void mouseEntered(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.callMouseEnteredListeners(mouseEvent);
this.wwd.getView().getViewInputHandler().mouseEntered(mouseEvent);
this.cancelHover();
this.cancelDrag();
}
- public void mouseExited(MouseEvent mouseEvent)
+ @Override
+ public void mouseExited(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.callMouseExitedListeners(mouseEvent);
this.wwd.getView().getViewInputHandler().mouseExited(mouseEvent);
@@ -514,16 +580,18 @@ public void mouseExited(MouseEvent mouseEvent)
this.cancelDrag();
}
- public void mouseDragged(MouseEvent mouseEvent)
+ @Override
+ public void mouseDragged(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
return;
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
Point prevMousePoint = this.mousePoint;
this.mousePoint = mouseEvent.getPoint();
this.callMouseDraggedListeners(mouseEvent);
@@ -536,8 +604,9 @@ public void mouseDragged(MouseEvent mouseEvent)
&& !pickedObjects.getTopPickedObject().isTerrain()))
{
this.isDragging = true;
- DragSelectEvent selectEvent = new DragSelectEvent(this.wwd, SelectEvent.DRAG, mouseEvent, pickedObjects,
- prevMousePoint);
+ DragSelectEvent selectEvent = new DragSelectEvent(this.wwd, SelectEvent.DRAG,
+ awtMouseEvent.getPoint(), mouseEvent,
+ pickedObjects, prevMousePoint);
this.callSelectListeners(selectEvent);
// If no listener consumed the event, then cancel the drag.
@@ -562,18 +631,20 @@ public void mouseDragged(MouseEvent mouseEvent)
}
}
- public void mouseMoved(MouseEvent mouseEvent)
+ @Override
+ public void mouseMoved(MouseEvent awtMouseEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseEvent == null)
+ if (awtMouseEvent == null)
{
return;
}
+ MouseEvent mouseEvent = glMouseEvent(awtMouseEvent);
this.mousePoint = mouseEvent.getPoint();
this.callMouseMovedListeners(mouseEvent);
@@ -590,24 +661,27 @@ public void mouseMoved(MouseEvent mouseEvent)
}
}
- public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent)
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent awtMouseWheelEvent)
{
if (this.wwd == null)
{
return;
}
- if (mouseWheelEvent == null)
+ if (awtMouseWheelEvent == null)
{
return;
}
+ MouseWheelEvent mouseWheelEvent = glMouseWheelEvent(awtMouseWheelEvent);
this.callMouseWheelMovedListeners(mouseWheelEvent);
if (!mouseWheelEvent.isConsumed())
this.wwd.getView().getViewInputHandler().mouseWheelMoved(mouseWheelEvent);
}
+ @Override
public void focusGained(FocusEvent focusEvent)
{
if (this.wwd == null)
@@ -623,6 +697,7 @@ public void focusGained(FocusEvent focusEvent)
this.wwd.getView().getViewInputHandler().focusGained(focusEvent);
}
+ @Override
public void focusLost(FocusEvent focusEvent)
{
if (this.wwd == null)
@@ -651,10 +726,10 @@ protected void doHover(boolean reset)
PickedObject hover = this.hoverObjects.getTopPickedObject();
PickedObject last = pickedObjects.getTopPickedObject();
- Object oh = hover == null ? null : hover.getObject() != null ? hover.getObject() :
- hover.getParentLayer() != null ? hover.getParentLayer() : null;
- Object ol = last == null ? null : last.getObject() != null ? last.getObject() :
- last.getParentLayer() != null ? last.getParentLayer() : null;
+ Object oh = hover == null ? null : hover.getObject() != null ? hover.getObject()
+ : hover.getParentLayer() != null ? hover.getParentLayer() : null;
+ Object ol = last == null ? null : last.getObject() != null ? last.getObject()
+ : last.getParentLayer() != null ? last.getParentLayer() : null;
if (oh != null && ol != null && oh.equals(ol))
{
return; // object picked is the hover object. don't do anything but wait for the timer to expire.
@@ -720,17 +795,19 @@ protected void cancelDrag()
if (this.isDragging)
{
this.callSelectListeners(new DragSelectEvent(this.wwd, SelectEvent.DRAG_END, null,
- this.objectsAtButtonPress, this.mousePoint));
+ null, this.objectsAtButtonPress, this.mousePoint));
}
this.isDragging = false;
}
+ @Override
public void addSelectListener(SelectListener listener)
{
this.eventListeners.add(SelectListener.class, listener);
}
+ @Override
public void removeSelectListener(SelectListener listener)
{
this.eventListeners.remove(SelectListener.class, listener);
@@ -744,41 +821,49 @@ protected void callSelectListeners(SelectEvent event)
}
}
+ @Override
public void addKeyListener(KeyListener listener)
{
this.eventListeners.add(KeyListener.class, listener);
}
+ @Override
public void removeKeyListener(KeyListener listener)
{
this.eventListeners.remove(KeyListener.class, listener);
}
+ @Override
public void addMouseListener(MouseListener listener)
{
this.eventListeners.add(MouseListener.class, listener);
}
+ @Override
public void removeMouseListener(MouseListener listener)
{
this.eventListeners.remove(MouseListener.class, listener);
}
+ @Override
public void addMouseMotionListener(MouseMotionListener listener)
{
this.eventListeners.add(MouseMotionListener.class, listener);
}
+ @Override
public void removeMouseMotionListener(MouseMotionListener listener)
{
this.eventListeners.remove(MouseMotionListener.class, listener);
}
+ @Override
public void addMouseWheelListener(MouseWheelListener listener)
{
this.eventListeners.add(MouseWheelListener.class, listener);
}
+ @Override
public void removeMouseWheelListener(MouseWheelListener listener)
{
this.eventListeners.remove(MouseWheelListener.class, listener);
@@ -872,6 +957,7 @@ protected void callMouseExitedListeners(MouseEvent event)
}
}
+ @Override
public void propertyChange(PropertyChangeEvent event)
{
if (this.wwd == null)
@@ -889,8 +975,8 @@ public void propertyChange(PropertyChangeEvent event)
return;
}
- if (event.getPropertyName().equals(AVKey.VIEW) &&
- (event.getSource() == this.getWorldWindow().getSceneController()))
+ if (event.getPropertyName().equals(AVKey.VIEW)
+ && (event.getSource() == this.getWorldWindow().getSceneController()))
{
this.wwd.getView().getViewInputHandler().setWorldWindow(this.wwd);
}
diff --git a/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java b/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java
index b0783cd1f4..012457796b 100644
--- a/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java
+++ b/src/gov/nasa/worldwind/awt/AbstractViewInputHandler.java
@@ -954,7 +954,7 @@ public double computeDragSlope(Point point1, Point point2, Vec4 vec1, Vec4 vec2)
return slope - 1.0;
}
- protected static Point constrainToSourceBounds(Point point, Object source)
+ protected static Point constrainToSourceBounds(Point point, WorldWindow source)
{
if (point == null)
return null;
@@ -962,19 +962,24 @@ protected static Point constrainToSourceBounds(Point point, Object source)
if (!(source instanceof Component))
return point;
- Component c = (Component) source;
+ // source.getHeight(), source.getWidth() are AWT coords height,
+ // but the 'point' is MouseEvent GL surface coords.
+ // Clamp to GL viewport size.
+ int glWidth = source.getView().getViewport().width;
+ int glHeight = source.getView().getViewport().height;
int x = (int) point.getX();
if (x < 0)
x = 0;
- if (x > c.getWidth())
- x = c.getWidth();
+ if (x >= glWidth)
+ x = glWidth - 1;
int y = (int) point.getY();
if (y < 0)
y = 0;
- if (y > c.getHeight())
- y = c.getHeight();
+
+ if (y >= glHeight)
+ y = glHeight - 1;
return new Point(x, y);
}
diff --git a/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java b/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java
index e7af6f0ca6..2008517ca6 100644
--- a/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java
+++ b/src/gov/nasa/worldwind/awt/BasicViewInputHandler.java
@@ -219,10 +219,10 @@ public boolean inputActionPerformed(KeyEventState keys, String target,
Point movement = ViewUtil.subtract(point, lastPoint);
int headingInput = movement.x;
- int pitchInput = movement.y;
+ int pitchInput = -movement.y;
Point totalMovement = ViewUtil.subtract(point, mouseDownPoint);
int totalHeadingInput = totalMovement.x;
- int totalPitchInput = totalMovement.y;
+ int totalPitchInput = -totalMovement.y;
ViewInputAttributes.DeviceAttributes deviceAttributes =
getAttributes().getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE);
@@ -258,16 +258,16 @@ public boolean inputActionPerformed(AbstractViewInputHandler inputHandler,
return false;
}
+ // 'mouseEvent' is in GL surface coords, (0,0) in lower left of canvas
+ // Make down mouse movement increase the pitch.
Point movement = ViewUtil.subtract(point, lastPoint);
int headingInput = movement.x;
- int pitchInput = movement.y;
+ int pitchInput = -movement.y;
if (mouseDownPoint == null)
mouseDownPoint = lastPoint;
Point totalMovement = ViewUtil.subtract(point, mouseDownPoint);
int totalHeadingInput = totalMovement.x;
- int totalPitchInput = totalMovement.y;
-
-
+ int totalPitchInput = -totalMovement.y;
ViewInputAttributes.DeviceAttributes deviceAttributes =
getAttributes().getDeviceAttributes(ViewInputAttributes.DEVICE_MOUSE);
diff --git a/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java b/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java
index 8a9942751b..3fb63c14ba 100644
--- a/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java
+++ b/src/gov/nasa/worldwind/awt/WorldWindowGLCanvas.java
@@ -94,7 +94,6 @@ public WorldWindowGLCanvas()
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -132,7 +131,6 @@ public WorldWindowGLCanvas(WorldWindow shareWith)
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -172,7 +170,6 @@ public WorldWindowGLCanvas(WorldWindow shareWith, java.awt.GraphicsDevice device
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -216,7 +213,6 @@ public WorldWindowGLCanvas(WorldWindow shareWith, java.awt.GraphicsDevice device
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -227,7 +223,8 @@ public WorldWindowGLCanvas(WorldWindow shareWith, java.awt.GraphicsDevice device
}
}
- public void propertyChange(PropertyChangeEvent evt)
+ @Override
+ public void propertyChange(PropertyChangeEvent evt)
{
if(this.wwd == evt.getSource())
this.firePropertyChange(evt);
@@ -237,7 +234,8 @@ public void propertyChange(PropertyChangeEvent evt)
this.shutdown();
}
- public void shutdown()
+ @Override
+ public void shutdown()
{
WorldWind.removePropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
this.wwd.shutdown();
@@ -267,12 +265,14 @@ protected void createDefaultInputHandler()
this.setInputHandler((InputHandler) WorldWind.createConfigurationComponent(AVKey.INPUT_HANDLER_CLASS_NAME));
}
- public InputHandler getInputHandler()
+ @Override
+ public InputHandler getInputHandler()
{
return this.wwd.getInputHandler();
}
- public void setInputHandler(InputHandler inputHandler)
+ @Override
+ public void setInputHandler(InputHandler inputHandler)
{
if (this.wwd.getInputHandler() != null)
this.wwd.getInputHandler().setEventSource(null); // remove this window as a source of events
@@ -282,153 +282,182 @@ public void setInputHandler(InputHandler inputHandler)
inputHandler.setEventSource(this);
}
- public SceneController getSceneController()
+ @Override
+ public SceneController getSceneController()
{
return this.wwd.getSceneController();
}
- public void setSceneController(SceneController sceneController)
+ @Override
+ public void setSceneController(SceneController sceneController)
{
this.wwd.setSceneController(sceneController);
}
- public GpuResourceCache getGpuResourceCache()
+ @Override
+ public GpuResourceCache getGpuResourceCache()
{
return this.wwd.getGpuResourceCache();
}
- public void redraw()
+ @Override
+ public void redraw()
{
this.repaint();
}
- public void redrawNow()
+ @Override
+ public void redrawNow()
{
this.wwd.redrawNow();
}
- public void setModel(Model model)
+ @Override
+ public void setModel(Model model)
{
// null models are permissible
this.wwd.setModel(model);
}
- public Model getModel()
+ @Override
+ public Model getModel()
{
return this.wwd.getModel();
}
- public void setView(View view)
+ @Override
+ public void setView(View view)
{
// null views are permissible
if (view != null)
this.wwd.setView(view);
}
- public View getView()
+ @Override
+ public View getView()
{
return this.wwd.getView();
}
- public void setModelAndView(Model model, View view)
+ @Override
+ public void setModelAndView(Model model, View view)
{ // null models/views are permissible
this.setModel(model);
this.setView(view);
}
- public void addRenderingListener(RenderingListener listener)
+ @Override
+ public void addRenderingListener(RenderingListener listener)
{
this.wwd.addRenderingListener(listener);
}
- public void removeRenderingListener(RenderingListener listener)
+ @Override
+ public void removeRenderingListener(RenderingListener listener)
{
this.wwd.removeRenderingListener(listener);
}
- public void addSelectListener(SelectListener listener)
+ @Override
+ public void addSelectListener(SelectListener listener)
{
this.wwd.getInputHandler().addSelectListener(listener);
this.wwd.addSelectListener(listener);
}
- public void removeSelectListener(SelectListener listener)
+ @Override
+ public void removeSelectListener(SelectListener listener)
{
this.wwd.getInputHandler().removeSelectListener(listener);
this.wwd.removeSelectListener(listener);
}
- public void addPositionListener(PositionListener listener)
+ @Override
+ public void addPositionListener(PositionListener listener)
{
this.wwd.addPositionListener(listener);
}
- public void removePositionListener(PositionListener listener)
+ @Override
+ public void removePositionListener(PositionListener listener)
{
this.wwd.removePositionListener(listener);
}
- public void addRenderingExceptionListener(RenderingExceptionListener listener)
+ @Override
+ public void addRenderingExceptionListener(RenderingExceptionListener listener)
{
this.wwd.addRenderingExceptionListener(listener);
}
- public void removeRenderingExceptionListener(RenderingExceptionListener listener)
+ @Override
+ public void removeRenderingExceptionListener(RenderingExceptionListener listener)
{
this.wwd.removeRenderingExceptionListener(listener);
}
- public Position getCurrentPosition()
+ @Override
+ public Position getCurrentPosition()
{
return this.wwd.getCurrentPosition();
}
- public PickedObjectList getObjectsAtCurrentPosition()
+ @Override
+ public PickedObjectList getObjectsAtCurrentPosition()
{
return this.wwd.getSceneController() != null ? this.wwd.getSceneController().getPickedObjectList() : null;
}
- public PickedObjectList getObjectsInSelectionBox()
+ @Override
+ public PickedObjectList getObjectsInSelectionBox()
{
return this.wwd.getSceneController() != null ? this.wwd.getSceneController().getObjectsInPickRectangle() : null;
}
- public Object setValue(String key, Object value)
+ @Override
+ public Object setValue(String key, Object value)
{
return this.wwd.setValue(key, value);
}
- public AVList setValues(AVList avList)
+ @Override
+ public AVList setValues(AVList avList)
{
return this.wwd.setValues(avList);
}
- public Object getValue(String key)
+ @Override
+ public Object getValue(String key)
{
return this.wwd.getValue(key);
}
- public Collection getValues()
+ @Override
+ public Collection getValues()
{
return this.wwd.getValues();
}
- public Set> getEntries()
+ @Override
+ public Set> getEntries()
{
return this.wwd.getEntries();
}
- public String getStringValue(String key)
+ @Override
+ public String getStringValue(String key)
{
return this.wwd.getStringValue(key);
}
- public boolean hasKey(String key)
+ @Override
+ public boolean hasKey(String key)
{
return this.wwd.hasKey(key);
}
- public Object removeKey(String key)
+ @Override
+ public Object removeKey(String key)
{
return this.wwd.removeKey(key);
}
@@ -463,28 +492,53 @@ public void firePropertyChange(String propertyName, Object oldValue, Object newV
super.firePropertyChange(propertyName, oldValue, newValue);
}
- public void firePropertyChange(PropertyChangeEvent propertyChangeEvent)
+ @Override
+ public void firePropertyChange(PropertyChangeEvent propertyChangeEvent)
{
this.wwd.firePropertyChange(propertyChangeEvent);
}
- public AVList copy()
+ @Override
+ public AVList copy()
{
return this.wwd.copy();
}
- public AVList clearList()
+ @Override
+ public AVList clearList()
{
return this.wwd.clearList();
}
- public void setPerFrameStatisticsKeys(Set keys)
+ @Override
+ public void setPerFrameStatisticsKeys(Set keys)
{
this.wwd.setPerFrameStatisticsKeys(keys);
}
- public Collection getPerFrameStatistics()
+ @Override
+ public Collection getPerFrameStatistics()
{
return this.wwd.getPerFrameStatistics();
}
+
+ /**
+ * @return current mouse pointer position in GL surface screen coordinates.
+ */
+ @Override
+ public Point getMousePosition() throws HeadlessException {
+ Point mpos = super.getMousePosition();
+ int [] awtPt = { mpos.x, mpos.y };
+
+ if (wwd.getContext() == null) return mpos;
+
+ GLDrawable drawable = wwd.getContext().getGLDrawable();
+ if (drawable == null) return mpos;
+
+ // Convert to GL surface coordinates
+ int [] glSurfacePt = drawable.getNativeSurface().convertToPixelUnits(awtPt);
+ int glSurfaceHeight = drawable.getSurfaceHeight();
+ glSurfacePt[1] = glSurfaceHeight - glSurfacePt[1] - 1;
+ return new Point(glSurfacePt[0], glSurfacePt[1]);
+ }
}
diff --git a/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java b/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java
index 5630b5b874..0b2a37322c 100644
--- a/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java
+++ b/src/gov/nasa/worldwind/awt/WorldWindowGLJPanel.java
@@ -93,7 +93,6 @@ public WorldWindowGLJPanel()
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -131,7 +130,6 @@ public WorldWindowGLJPanel(WorldWindow shareWith)
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
@@ -175,7 +173,6 @@ public WorldWindowGLJPanel(WorldWindow shareWith, GLCapabilities capabilities,
this.createView();
this.createDefaultInputHandler();
WorldWind.addPropertyChangeListener(WorldWind.SHUTDOWN_EVENT, this);
- WorldWindowImpl.configureIdentityPixelScale(this);
this.wwd.endInitialization();
}
catch (Exception e)
diff --git a/src/gov/nasa/worldwind/drag/DragContext.java b/src/gov/nasa/worldwind/drag/DragContext.java
index 6623902e88..935f2c31b4 100644
--- a/src/gov/nasa/worldwind/drag/DragContext.java
+++ b/src/gov/nasa/worldwind/drag/DragContext.java
@@ -41,16 +41,16 @@
public class DragContext
{
/**
- * In accordance with the AWT screen coordinates the top left point of the window is the origin.
+ * In accordance with the GL surface coordinates the top left point of the window is the origin.
*/
protected Point point;
/**
- * In accordance with the AWT screen coordinates the top left point of the window is the origin. This point is the
+ * In accordance with the GL surface coordinates the top left point of the window is the origin. This point is the
* previous screen point.
*/
protected Point previousPoint;
/**
- * In accordance with the AWT screen coordinates the top left point of the window is the origin. This point refers
+ * In accordance with the GL surface coordinates the top left point of the window is the origin. This point refers
* to the initial point of the drag event.
*/
protected Point initialPoint;
@@ -81,9 +81,9 @@ public DragContext()
}
/**
- * Returns the current screen point with the origin at the top left corner of the window.
+ * Returns the current GL surface point with the origin at the top left corner of the window.
*
- * @return the current screen point.
+ * @return the current GL surface point.
*/
public Point getPoint()
{
@@ -91,9 +91,9 @@ public Point getPoint()
}
/**
- * Set the {@link DragContext} current screen point.
+ * Set the {@link DragContext} current GL surface point.
*
- * @param point the point to assign to the current screen point.
+ * @param point the point to assign to the current GL surface point.
*
* @throws IllegalArgumentException if the point is null.
*/
@@ -110,7 +110,7 @@ public void setPoint(Point point)
}
/**
- * Returns the previous screen point with the origin at the top left corner of the window.
+ * Returns the previous GL surface point with the origin at the top left corner of the window.
*
* @return the previous point.
*/
@@ -120,9 +120,9 @@ public Point getPreviousPoint()
}
/**
- * Set the {@link DragContext} previous screen point.
+ * Set the {@link DragContext} previous GL surface point.
*
- * @param previousPoint the screen point to assign to the previous screen point.
+ * @param previousPoint the GL surface point to assign to the previous screen point.
*
* @throws IllegalArgumentException if the previousPoint is null.
*/
@@ -139,10 +139,10 @@ public void setPreviousPoint(Point previousPoint)
}
/**
- * Returns the initial screen point with the origin at the top left corner of the window. The initial point is the
- * screen point at the initiation of the drag event.
+ * Returns the initial GL surface point with the origin at the top left corner of the window. The initial point is the
+ * GL surface point at the initiation of the drag event.
*
- * @return the initial screen point.
+ * @return the initial GL surface point.
*/
public Point getInitialPoint()
{
@@ -150,9 +150,9 @@ public Point getInitialPoint()
}
/**
- * Set the {@link DragContext} initial screen point.
+ * Set the {@link DragContext} initial GL surface point.
*
- * @param initialPoint the screen point to assign to the initial screen point.
+ * @param initialPoint the GL surface point to assign to the initial screen point.
*
* @throws IllegalArgumentException if the initialPoint is null.
*/
diff --git a/src/gov/nasa/worldwind/drag/DraggableSupport.java b/src/gov/nasa/worldwind/drag/DraggableSupport.java
index 3a5e7b52a5..7af85f8eb6 100644
--- a/src/gov/nasa/worldwind/drag/DraggableSupport.java
+++ b/src/gov/nasa/worldwind/drag/DraggableSupport.java
@@ -428,9 +428,7 @@ protected Vec4 computeScreenOffsetFromReferencePosition(Position dragObjectRefer
Vec4 screenPointOffset = new Vec4(
dragContext.getInitialPoint().getX() - dragObjectScreenPoint.getX(),
- dragContext.getInitialPoint().getY() - (
- dragContext.getView().getViewport().getHeight()
- - dragObjectScreenPoint.getY() - 1.0)
+ dragContext.getInitialPoint().getY() - dragObjectScreenPoint.getY()
);
return screenPointOffset;
diff --git a/src/gov/nasa/worldwind/event/DragSelectEvent.java b/src/gov/nasa/worldwind/event/DragSelectEvent.java
index fcd36fe33a..c694b58f1b 100644
--- a/src/gov/nasa/worldwind/event/DragSelectEvent.java
+++ b/src/gov/nasa/worldwind/event/DragSelectEvent.java
@@ -42,10 +42,11 @@ public class DragSelectEvent extends SelectEvent
{
private final java.awt.Point previousPickPoint;
- public DragSelectEvent(Object source, String eventAction, MouseEvent mouseEvent, PickedObjectList pickedObjects,
- java.awt.Point previousPickPoint)
+ public DragSelectEvent(Object source, String eventAction, java.awt.Point awtPt, MouseEvent mouseEvent,
+ PickedObjectList pickedObjects,
+ java.awt.Point previousPickPoint)
{
- super(source, eventAction, mouseEvent, pickedObjects);
+ super(source, eventAction, awtPt, mouseEvent, pickedObjects);
this.previousPickPoint = previousPickPoint;
}
diff --git a/src/gov/nasa/worldwind/event/SelectEvent.java b/src/gov/nasa/worldwind/event/SelectEvent.java
index ac07024c64..1804356111 100644
--- a/src/gov/nasa/worldwind/event/SelectEvent.java
+++ b/src/gov/nasa/worldwind/event/SelectEvent.java
@@ -65,7 +65,6 @@
* @author tag
* @version $Id: SelectEvent.java 1171 2013-02-11 21:45:02Z dcollins $
*/
-@SuppressWarnings({"StringEquality"})
public class SelectEvent extends WWEvent
{
/** The user clicked the left mouse button while the cursor was over picked object. */
@@ -96,24 +95,26 @@ public class SelectEvent extends WWEvent
* The user has selected one or more of objects using a selection box. A box rollover event is generated every frame
* if one or more objects intersect the box, in which case the event's pickedObjects list contain the selected
* objects. A box rollover event is generated once when the selection becomes empty, in which case the event's
- * pickedObjects is null. In either case, the event's pickRect contains the selection box bounds in AWT
- * screen coordinates.
+ * pickedObjects is null. In either case, the event's pickRect contains the
+ * selection box bounds in GL surface coordinates.
*/
public static final String BOX_ROLLOVER = "gov.nasa.worldwind.SelectEvent.BoxRollover";
private final String eventAction;
- private final Point pickPoint;
- private final Rectangle pickRect;
- private final MouseEvent mouseEvent;
+ private final Point pickPoint; // GL surface coordinates
+ private final Rectangle pickRect; // GL surface coordinates
+ private final MouseEvent mouseEvent; // GL surface coordinates
+ private final Point awtMousePt; // AWT screen coordinates
private final PickedObjectList pickedObjects;
- public SelectEvent(Object source, String eventAction, MouseEvent mouseEvent, PickedObjectList pickedObjects)
+ public SelectEvent(Object source, String eventAction, Point awtPt, MouseEvent mouseEvent, PickedObjectList pickedObjects)
{
super(source);
this.eventAction = eventAction;
this.pickPoint = mouseEvent != null ? mouseEvent.getPoint() : null;
this.pickRect = null;
this.mouseEvent = mouseEvent;
+ this.awtMousePt = awtPt;
this.pickedObjects = pickedObjects;
}
@@ -124,6 +125,7 @@ public SelectEvent(Object source, String eventAction, Point pickPoint, PickedObj
this.pickPoint = pickPoint;
this.pickRect = null;
this.mouseEvent = null;
+ this.awtMousePt = null;
this.pickedObjects = pickedObjects;
}
@@ -134,6 +136,7 @@ public SelectEvent(Object source, String eventAction, Rectangle pickRectangle, P
this.pickPoint = null;
this.pickRect = pickRectangle;
this.mouseEvent = null;
+ this.awtMousePt = null;
this.pickedObjects = pickedObjects;
}
@@ -151,6 +154,10 @@ public String getEventAction()
return this.eventAction != null ? this.eventAction : "gov.nasa.worldwind.SelectEvent.UnknownEventAction";
}
+ public Point getAwtMousePt() {
+ return awtMousePt;
+ }
+
public Point getPickPoint()
{
return this.pickPoint;
diff --git a/src/gov/nasa/worldwind/geom/LatLon.java b/src/gov/nasa/worldwind/geom/LatLon.java
index acc1e29a7b..30e3385205 100644
--- a/src/gov/nasa/worldwind/geom/LatLon.java
+++ b/src/gov/nasa/worldwind/geom/LatLon.java
@@ -1272,6 +1272,7 @@ public static boolean locationsCrossDateLine(Iterable extends LatLon> location
LatLon pos = null;
for (LatLon posNext : locations)
{
+ if (posNext == null) break;
if (pos != null)
{
// A segment cross the line if end pos have different longitude signs
diff --git a/src/gov/nasa/worldwind/geom/Sector.java b/src/gov/nasa/worldwind/geom/Sector.java
index 5b1e73092c..9a38490d96 100644
--- a/src/gov/nasa/worldwind/geom/Sector.java
+++ b/src/gov/nasa/worldwind/geom/Sector.java
@@ -284,6 +284,7 @@ public static Sector boundingSector(Iterable extends LatLon> locations) {
double maxLon = Angle.NEG180.getDegrees();
for (LatLon p : locations) {
+ if (p == null) break;
double lat = p.getLatitude().getDegrees();
if (lat < minLat) {
minLat = lat;
diff --git a/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java b/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java
index 479cf7fbe6..d5ccf17d09 100644
--- a/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java
+++ b/src/gov/nasa/worldwind/globes/EllipsoidalGlobe.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is 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.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -132,7 +132,10 @@ public Globe getGlobe()
return this.globe;
}
- @SuppressWarnings({"RedundantIfStatement"})
+ @SuppressWarnings(
+ {
+ "RedundantIfStatement"
+ })
@Override
public boolean equals(Object o)
{
@@ -145,8 +148,8 @@ public boolean equals(Object o)
if (Double.compare(stateKey.verticalExaggeration, verticalExaggeration) != 0)
return false;
- if (elevationModel != null ? !elevationModel.equals(stateKey.elevationModel) :
- stateKey.elevationModel != null)
+ if (elevationModel != null ? !elevationModel.equals(stateKey.elevationModel)
+ : stateKey.elevationModel != null)
return false;
if (globe != null ? !globe.equals(stateKey.globe) : stateKey.globe != null)
return false;
@@ -238,7 +241,6 @@ public double getRadiusAt(Angle latitude, Angle longitude)
// observing that the length of the ellipsoidal point at the specified latitude and longitude indicates the
// radius at that location. The formula for the length of the ellipsoidal point was then converted into the
// simplified form below.
-
double sinLat = Math.sin(latitude.radians);
double rpm = this.equatorialRadius / Math.sqrt(1.0 - this.es * sinLat * sinLat);
@@ -294,7 +296,10 @@ public double[] getMinAndMaxElevations(Angle latitude, Angle longitude)
}
return this.elevationModel != null ? this.elevationModel.getExtremeElevations(latitude, longitude)
- : new double[] {0, 0};
+ : new double[]
+ {
+ 0, 0
+ };
}
public double[] getMinAndMaxElevations(Sector sector)
@@ -306,7 +311,10 @@ public double[] getMinAndMaxElevations(Sector sector)
throw new IllegalArgumentException(message);
}
- return this.elevationModel != null ? this.elevationModel.getExtremeElevations(sector) : new double[] {0, 0};
+ return this.elevationModel != null ? this.elevationModel.getExtremeElevations(sector) : new double[]
+ {
+ 0, 0
+ };
}
public Extent getExtent()
@@ -347,7 +355,6 @@ protected Intersection[] intersect(Line line, double equRadius, double polRadius
return null;
// Taken from Lengyel, 2Ed., Section 5.2.3, page 148.
-
double m = equRadius / polRadius; // "ratio of the x semi-axis length to the y semi-axis length"
double n = 1d; // "ratio of the x semi-axis length to the z semi-axis length"
double m2 = m * m;
@@ -373,16 +380,25 @@ protected Intersection[] intersect(Line line, double equRadius, double polRadius
if (discriminant == 0)
{
Vec4 p = line.getPointAt((-b - discriminantRoot) / (2 * a));
- return new Intersection[] {new Intersection(p, true)};
+ return new Intersection[]
+ {
+ new Intersection(p, true)
+ };
}
else // (discriminant > 0)
{
Vec4 near = line.getPointAt((-b - discriminantRoot) / (2 * a));
Vec4 far = line.getPointAt((-b + discriminantRoot) / (2 * a));
if (c >= 0) // Line originates outside the Globe.
- return new Intersection[] {new Intersection(near, false), new Intersection(far, false)};
+ return new Intersection[]
+ {
+ new Intersection(near, false), new Intersection(far, false)
+ };
else // Line originates inside the Globe.
- return new Intersection[] {new Intersection(far, false)};
+ return new Intersection[]
+ {
+ new Intersection(far, false)
+ };
}
}
@@ -492,7 +508,10 @@ public double[] getElevations(Sector sector, List extends LatLon> latLons, dou
double[] elevations)
{
if (this.elevationModel == null)
- return new double[] {0};
+ return new double[]
+ {
+ 0
+ };
double[] resolution = this.elevationModel.getElevations(sector, latLons, targetResolution, elevations);
@@ -508,6 +527,16 @@ public double[] getElevations(Sector sector, List extends LatLon> latLons, dou
return resolution;
}
+ /**
+ * Get the EGM96 offset class for this globe.
+ *
+ * @return The EGM96 offset class for this globe.
+ */
+ public EGM96 getEGM96()
+ {
+ return this.egm96;
+ }
+
public double getElevation(Angle latitude, Angle longitude)
{
if (latitude == null || longitude == null)
@@ -909,7 +938,8 @@ protected Vec4 geodeticToEllipsoidal(Angle latitude, Angle longitude, double met
double cosLon = Math.cos(longitude.radians);
double sinLon = Math.sin(longitude.radians);
- double rpm = // getRadius (in meters) of vertical in prime meridian
+ double rpm
+ = // getRadius (in meters) of vertical in prime meridian
this.equatorialRadius / Math.sqrt(1.0 - this.es * sinLat * sinLat);
double x = (rpm + metersElevation) * cosLat * sinLon;
@@ -1035,7 +1065,6 @@ protected void geodeticToCartesian(Sector sector, int numLat, int numLon, double
//
// return Position.fromRadians(lat, lon, elevation);
// }
-
/**
* Compute the geographic position to corresponds to a Cartesian point.
*
@@ -1059,7 +1088,10 @@ protected Position cartesianToGeodetic(Vec4 cart)
*
* @see #geodeticToEllipsoidal(gov.nasa.worldwind.geom.Angle, gov.nasa.worldwind.geom.Angle, double)
*/
- @SuppressWarnings({"SuspiciousNameCombination"})
+ @SuppressWarnings(
+ {
+ "SuspiciousNameCombination"
+ })
protected Position ellipsoidalToGeodetic(Vec4 cart)
{
// Contributed by Nathan Kronenfeld. Integrated 1/24/2011. Brings this calculation in line with Vermeille's
@@ -1370,4 +1402,4 @@ public static ElevationModel makeElevationModel(String key, String defaultValue)
Object configSource = Configuration.getStringValue(key, defaultValue);
return (ElevationModel) BasicFactory.create(AVKey.ELEVATION_MODEL_FACTORY, configSource);
}
-}
\ No newline at end of file
+}
diff --git a/src/gov/nasa/worldwind/layers/CompassLayer.java b/src/gov/nasa/worldwind/layers/CompassLayer.java
index 2c4bcb7cf8..0116a3fcf6 100644
--- a/src/gov/nasa/worldwind/layers/CompassLayer.java
+++ b/src/gov/nasa/worldwind/layers/CompassLayer.java
@@ -67,17 +67,20 @@ public class CompassLayer extends AbstractLayer
protected class OrderedIcon implements OrderedRenderable
{
- public double getDistanceFromEye()
+ @Override
+ public double getDistanceFromEye()
{
return 0;
}
- public void pick(DrawContext dc, Point pickPoint)
+ @Override
+ public void pick(DrawContext dc, Point pickPoint)
{
CompassLayer.this.draw(dc);
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
CompassLayer.this.draw(dc);
}
@@ -295,7 +298,8 @@ public void setLocationOffset(Vec4 locationOffset)
this.locationOffset = locationOffset;
}
- protected void doRender(DrawContext dc)
+ @Override
+ protected void doRender(DrawContext dc)
{
if (dc.isContinuous2DGlobe() && this.frameStampForDrawing == dc.getFrameTimeStamp())
return;
@@ -305,7 +309,8 @@ protected void doRender(DrawContext dc)
this.frameStampForDrawing = dc.getFrameTimeStamp();
}
- protected void doPick(DrawContext dc, Point pickPoint)
+ @Override
+ protected void doPick(DrawContext dc, Point pickPoint)
{
if (dc.isContinuous2DGlobe() && this.frameStampForPicking == dc.getFrameTimeStamp())
return;
@@ -414,7 +419,7 @@ protected void draw(DrawContext dc)
Vec4 center = new Vec4(locationSW.x + width * scale / 2, locationSW.y + height * scale / 2,
0);
double px = dc.getPickPoint().x - center.x;
- double py = viewport.getHeight() - dc.getPickPoint().y - center.y;
+ double py = dc.getPickPoint().y - center.y;
Angle pickHeading = Angle.fromRadians(Math.atan2(px, py));
pickHeading = pickHeading.degrees >= 0 ? pickHeading : pickHeading.addDegrees(360);
po.setValue("Heading", pickHeading);
diff --git a/src/gov/nasa/worldwind/layers/ScalebarLayer.java b/src/gov/nasa/worldwind/layers/ScalebarLayer.java
index 03f495b886..6cfd8af978 100644
--- a/src/gov/nasa/worldwind/layers/ScalebarLayer.java
+++ b/src/gov/nasa/worldwind/layers/ScalebarLayer.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
diff --git a/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java b/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java
index d675ad6699..149ab8c2eb 100644
--- a/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java
+++ b/src/gov/nasa/worldwind/layers/TerrainProfileLayer.java
@@ -37,6 +37,8 @@
import gov.nasa.worldwind.view.orbit.OrbitView;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.beans.PropertyChangeEvent;
@@ -148,7 +150,6 @@ public TerrainProfileLayer() {
*
* @return true if the profile graph is minimized.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean getIsMinimized() {
return this.isMinimized;
}
@@ -171,7 +172,6 @@ public void setIsMinimized(boolean state) {
*
* @return true if the profile graph is maximized.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean getIsMaximized() {
return this.isMaximized;
}
@@ -262,7 +262,6 @@ public double getOpacity() {
*
* @return the graphic-to-viewport scale factor.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public double getToViewportScale() {
return toViewportScale;
}
@@ -275,7 +274,6 @@ public double getToViewportScale() {
*
* @param toViewportScale the graphic to viewport scale factor.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setToViewportScale(double toViewportScale) {
this.toViewportScale = toViewportScale;
}
@@ -305,7 +303,6 @@ public void setPosition(String position) {
*
* @return the screen location of the graph center if set (can be null).
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Point getLocationCenter() {
return this.locationCenter;
}
@@ -325,7 +322,6 @@ public void setLocationCenter(Point point) {
*
* @return the location offset. Will be null if no offset has been specified.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Vec4 getLocationOffset() {
return locationOffset;
}
@@ -349,7 +345,6 @@ public void setLocationOffset(Vec4 locationOffset) {
*
* @return the layer's resize behavior.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public String getResizeBehavior() {
return resizeBehavior;
}
@@ -365,7 +360,6 @@ public String getResizeBehavior() {
*
* @param resizeBehavior the desired resize behavior
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setResizeBehavior(String resizeBehavior) {
this.resizeBehavior = resizeBehavior;
}
@@ -384,7 +378,6 @@ public void setBorderWidth(int borderWidth) {
this.borderWidth = borderWidth;
}
- @SuppressWarnings({"UnusedDeclaration"})
public String getUnit() {
return this.unit;
}
@@ -503,7 +496,6 @@ public double getProfileLenghtFactor() {
*
* @return the profile start position lat/lon.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public LatLon getStartLatLon() {
return this.startLatLon;
}
@@ -527,7 +519,6 @@ public void setStartLatLon(LatLon latLon) {
*
* @return the profile end position lat/lon.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public LatLon getEndLatLon() {
return this.endLatLon;
}
@@ -551,7 +542,6 @@ public void setEndLatLon(LatLon latLon) {
*
* @return the number of elevation samples in the profile.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public int getSamples() {
return this.samples;
}
@@ -561,7 +551,6 @@ public int getSamples() {
*
* @param number the number of elevation samples in the profile.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setSamples(int number) {
this.samples = Math.abs(number);
}
@@ -589,7 +578,6 @@ public void setZeroBased(boolean state) {
*
* @return the object position the graph follows.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Position getObjectPosition() {
return this.objectPosition;
}
@@ -609,7 +597,6 @@ public void setObjectPosition(Position pos) {
*
* @return the object heading the graph follows.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Angle getObjectHeading() {
return this.objectHeading;
}
@@ -629,7 +616,6 @@ public void setObjectHeading(Angle heading) {
*
* @return the path positions that the profile follows.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public List extends LatLon> getPathPositions() {
return this.pathPositions;
}
@@ -708,7 +694,6 @@ public void setPathType(String pathType) {
*
* @return the Path used to render the profile line on the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Path getProfileLine() {
return this.selectionShape;
}
@@ -718,7 +703,6 @@ public Path getProfileLine() {
*
* @return the Path used to render the picked position on the terrain.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public Path getPickedLine() {
return this.selectionShape;
}
@@ -728,7 +712,6 @@ public Path getPickedLine() {
*
* @return true is the profile line is displayed over the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean isShowProfileLine() {
return this.showProfileLine;
}
@@ -747,7 +730,6 @@ public void setShowProfileLine(boolean state) {
*
* @return true if the picked line is displayed over the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public boolean isShowPickedLine() {
return this.showPickedLine;
}
@@ -757,7 +739,6 @@ public boolean isShowPickedLine() {
*
* @param state if the picked line should be displayed over the ground.
*/
- @SuppressWarnings({"UnusedDeclaration"})
public void setShowPickedLine(boolean state) {
this.showPickedLine = state;
}
@@ -986,6 +967,7 @@ protected void drawGraph(DrawContext dc, Dimension dimension) {
(byte) this.color.getBlue(), (byte) 100);
gl.glBegin(GL2.GL_TRIANGLE_STRIP);
for (i = 0; i < this.samples; i++) {
+ if (this.positions[i] == null) break;
x = i * lengthStep * stepX;
y = (this.positions[i].getElevation() - min) * stepY;
gl.glVertex3d(x, 0, 0);
@@ -997,6 +979,7 @@ protected void drawGraph(DrawContext dc, Dimension dimension) {
gl.glColor4d(colorRGB[0], colorRGB[1], colorRGB[2], this.getOpacity());
gl.glBegin(GL2.GL_LINE_STRIP);
for (i = 0; i < this.samples; i++) {
+ if (this.positions[i] == null) break;
x = i * lengthStep * stepX;
y = (this.positions[i].getElevation() - min) * stepY;
gl.glVertex3d(x, y, 0);
@@ -1274,12 +1257,11 @@ protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimensio
this.pickedSample = -1;
Point pickPoint = dc.getPickPoint();
if (pickPoint != null && this.positions != null && !this.follow.equals(FOLLOW_CURSOR)) {
- Rectangle viewport = dc.getView().getViewport();
// Check if pickpoint is inside the graph
if (pickPoint.getX() >= locationSW.getX()
&& pickPoint.getX() < locationSW.getX() + mapSize.width
- && viewport.height - pickPoint.getY() >= locationSW.getY()
- && viewport.height - pickPoint.getY() < locationSW.getY() + mapSize.height) {
+ && pickPoint.getY() >= locationSW.getY()
+ && pickPoint.getY() < locationSW.getY() + mapSize.height) {
// Find sample - Note: only works when graph expends over the full width
int sample = (int) (((double) (pickPoint.getX() - locationSW.getX()) / mapSize.width) * this.samples);
if (sample >= 0 && sample < this.samples) {
diff --git a/src/gov/nasa/worldwind/layers/TiledImageLayer.java b/src/gov/nasa/worldwind/layers/TiledImageLayer.java
index 67fba48604..1a19ce23e7 100644
--- a/src/gov/nasa/worldwind/layers/TiledImageLayer.java
+++ b/src/gov/nasa/worldwind/layers/TiledImageLayer.java
@@ -39,6 +39,8 @@
import javax.imageio.ImageIO;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.xml.xpath.XPath;
import java.awt.image.*;
import java.io.*;
diff --git a/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java b/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java
index 35b79f478e..5f1c3fb356 100644
--- a/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java
+++ b/src/gov/nasa/worldwind/layers/ViewControlsSelectListener.java
@@ -496,7 +496,7 @@ protected Angle computePanHeading(OrbitView view, ScreenAnnotation control)
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
- double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
+ double py = lastPickPoint.y - center.y;
Angle heading = view.getHeading().add(Angle.fromRadians(Math.atan2(px, py)));
heading = heading.degrees >= 0 ? heading : heading.addDegrees(360);
return heading;
@@ -508,7 +508,7 @@ protected Angle computePanAmount(Globe globe, OrbitView view, ScreenAnnotation c
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
double px = lastPickPoint.x - center.x;
- double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
+ double py = lastPickPoint.y - center.y;
double pickDistance = Math.sqrt(px * px + py * py);
double pickDistanceFactor = Math.min(pickDistance / 10, 5);
@@ -547,7 +547,7 @@ protected Angle computeLookPitch(OrbitView view, ScreenAnnotation control, doubl
// Compute last pick point 'pitch' relative to look control center on y
double size = control.getAttributes().getSize().width * control.getAttributes().getScale();
Vec4 center = new Vec4(control.getScreenPoint().x, control.getScreenPoint().y + size / 2, 0);
- double py = view.getViewport().getHeight() - lastPickPoint.y - center.y;
+ double py = lastPickPoint.y - center.y;
double pickDistanceFactor = Math.min(Math.abs(py) / 3000, 5) * Math.signum(py);
// New pitch
Angle pitch = view.getPitch().add(Angle.fromRadians(pitchStep * pickDistanceFactor));
diff --git a/src/gov/nasa/worldwind/layers/WorldMapLayer.java b/src/gov/nasa/worldwind/layers/WorldMapLayer.java
index 5d8c84f534..151d8b451b 100644
--- a/src/gov/nasa/worldwind/layers/WorldMapLayer.java
+++ b/src/gov/nasa/worldwind/layers/WorldMapLayer.java
@@ -700,11 +700,11 @@ protected Position computePickPosition(DrawContext dc, Vec4 locationSW, Dimensio
// Check if pickpoint is inside the map
if (pickPoint.getX() >= locationSW.getX()
&& pickPoint.getX() < locationSW.getX() + mapSize.width
- && viewport.height - pickPoint.getY() >= locationSW.getY()
- && viewport.height - pickPoint.getY() < locationSW.getY() + mapSize.height)
+ && pickPoint.getY() >= locationSW.getY()
+ && pickPoint.getY() < locationSW.getY() + mapSize.height)
{
double lon = (pickPoint.getX() - locationSW.getX()) / mapSize.width * 360 - 180;
- double lat = (viewport.height - pickPoint.getY() - locationSW.getY()) / mapSize.height * 180 - 90;
+ double lat = (pickPoint.getY() - locationSW.getY()) / mapSize.height * 180 - 90;
double pickAltitude = 1000e3;
pickPosition = new Position(Angle.fromDegrees(lat), Angle.fromDegrees(lon), pickAltitude);
}
diff --git a/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java b/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java
index 9ba7c0ff76..9d6f527329 100644
--- a/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java
+++ b/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java
@@ -38,6 +38,8 @@
import javax.imageio.ImageIO;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
diff --git a/src/gov/nasa/worldwind/pick/PickSupport.java b/src/gov/nasa/worldwind/pick/PickSupport.java
index de36c75420..002107ce1e 100644
--- a/src/gov/nasa/worldwind/pick/PickSupport.java
+++ b/src/gov/nasa/worldwind/pick/PickSupport.java
@@ -135,7 +135,7 @@ public PickedObject getTopObject(DrawContext dc, Point pickPoint)
* objects are currently registered with this PickSupport.
*
* @param dc the draw context which receives the picked object.
- * @param pickPoint the point in AWT screen coordinates.
+ * @param pickPoint the point in GL surface coordinates.
* @param layer the layer associated with the picked object.
*
* @return the picked object added to the draw context, or null if no picked object is drawn at the
@@ -166,11 +166,11 @@ public PickedObject resolvePick(DrawContext dc, Point pickPoint, Layer layer)
}
/**
- * Adds a picked object registered with this PickSupport that is drawn at the specified point in AWT screen
+ * Adds a picked object registered with this PickSupport that is drawn at the specified point in GL surface
* coordinates (if one exists) to the draw context's list of picked objects.
*
* @param dc the draw context which receives the picked object.
- * @param pickPoint the point in AWT screen coordinates.
+ * @param pickPoint the point in GL surface coordinates.
* @param layer the layer associated with the picked object.
*
* @return the picked object added to the draw context, or null if no picked object is drawn at the
@@ -195,7 +195,7 @@ protected PickedObject doResolvePick(DrawContext dc, Point pickPoint, Layer laye
* screen coordinates (if any) to the draw context's list of picked objects.
*
* @param dc the draw context which receives the picked objects.
- * @param pickRect the rectangle in AWT screen coordinates.
+ * @param pickRect the rectangle in GL surface coordinates.
* @param layer the layer associated with the picked objects.
*/
protected void doResolvePick(DrawContext dc, Rectangle pickRect, Layer layer)
@@ -226,7 +226,7 @@ protected void doResolvePick(DrawContext dc, Rectangle pickRect, Layer layer)
}
/**
- * Returns the framebuffer RGB color for a point in AWT screen coordinates, formatted as a pick color code. The red,
+ * Returns the framebuffer RGB color for a point in GL surface coordinates, formatted as a pick color code. The red,
* green, and blue components are each stored as an 8-bit unsigned integer, and packed into bits 0-23 of the
* returned integer as follows: bits 16-23 are red, bits 8-15 are green, and bits 0-7 are blue. This format is
* consistent with the RGB integers used to create the pick colors.
@@ -235,7 +235,7 @@ protected void doResolvePick(DrawContext dc, Rectangle pickRect, Layer layer)
* outside the draw context's drawable area.
*
* @param dc the draw context to return a color for.
- * @param pickPoint the point to return a color for, in AWT screen coordinates.
+ * @param pickPoint the point to return a color for, in GL surface coordinates.
*
* @return the RGB color corresponding to the specified point.
*/
diff --git a/src/gov/nasa/worldwind/render/AbstractAnnotation.java b/src/gov/nasa/worldwind/render/AbstractAnnotation.java
index 25cb16b38f..72d1571bfc 100644
--- a/src/gov/nasa/worldwind/render/AbstractAnnotation.java
+++ b/src/gov/nasa/worldwind/render/AbstractAnnotation.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
/**
@@ -462,7 +464,6 @@ protected void drawTopLevelAnnotation(DrawContext dc, int x, int y, int width, i
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void applyScreenTransform(DrawContext dc, int x, int y, int width, int height, double scale)
{
double finalScale = scale * this.computeScale(dc);
@@ -475,7 +476,6 @@ protected void applyScreenTransform(DrawContext dc, int x, int y, int width, int
gl.glTranslated(-width / 2, 0, 0);
}
- @SuppressWarnings({"UnusedDeclaration"})
protected double computeScale(DrawContext dc)
{
double scale = this.attributes.getScale();
@@ -489,7 +489,6 @@ protected double computeScale(DrawContext dc)
return scale;
}
- @SuppressWarnings({"UnusedDeclaration"})
protected double computeOpacity(DrawContext dc)
{
double opacity = this.attributes.getOpacity();
@@ -616,7 +615,6 @@ protected void drawBackgroundImage(DrawContext dc, int width, int height, double
this.doDrawBackgroundTexture(dc, width, height, opacity, pickPosition, texture);
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void doDrawBackgroundTexture(DrawContext dc, int width, int height, double opacity, Position pickPosition,
WWTexture texture)
{
@@ -660,7 +658,6 @@ protected void doDrawBackgroundTexture(DrawContext dc, int width, int height, do
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void applyBackgroundTextureState(DrawContext dc, int width, int height, double opacity,
WWTexture texture)
{
@@ -721,7 +718,6 @@ protected void transformImageCoordsToBackgroundImageCoords(DrawContext dc, WWTex
* @param texture the texture to transform from Annotation background image coordinates to Annotation geometry
* coordinates.
*/
- @SuppressWarnings({"UnusedDeclaration"})
protected void transformBackgroundImageCoordsToAnnotationCoords(DrawContext dc, int width, int height,
WWTexture texture)
{
@@ -750,7 +746,6 @@ protected void transformBackgroundImageCoordsToAnnotationCoords(DrawContext dc,
//******************** Border Rendering **********************//
//**************************************************************//
- @SuppressWarnings({"UnusedDeclaration"})
protected void drawBorder(DrawContext dc, int width, int height, double opacity, Position pickPosition)
{
if (this.getAttributes().getBorderWidth() <= 0)
@@ -813,8 +808,7 @@ protected void drawText(DrawContext dc, int width, int height, double opacity, P
return;
java.awt.Rectangle screenInsetBounds = this.transformByModelview(dc, insetBounds);
- java.awt.Point glPickPoint = this.glPointFromAWTPoint(dc, dc.getPickPoint());
- if (!screenInsetBounds.contains(glPickPoint))
+ if (!screenInsetBounds.contains(dc.getPickPoint()))
return;
}
@@ -897,7 +891,6 @@ protected void drawPlainText(DrawContext dc, int x, int y, int lineHeight, doubl
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void drawHTML(DrawContext dc, int x, int y, int lineHeight, double opacity, Object pickObject,
Position pickPosition, String text)
{
@@ -941,14 +934,12 @@ protected void drawChildren(DrawContext dc, int width, int height, double opacit
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void doDrawChildren(DrawContext dc, java.awt.Rectangle bounds, double opacity, Position pickPosition)
{
this.layoutManager.setPickSupport(this.pickSupport);
this.layoutManager.drawAnnotations(dc, bounds, this.childList, opacity, pickPosition);
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void beginDrawChildren(DrawContext dc, java.awt.Rectangle bounds)
{
this.layoutManager.beginDrawAnnotations(dc, bounds);
@@ -1051,15 +1042,6 @@ protected java.awt.Rectangle transformByModelview(DrawContext dc, java.awt.Recta
return new java.awt.Rectangle((int) origin.x, (int) origin.y, (int) size.x, (int) size.y);
}
- protected java.awt.Point glPointFromAWTPoint(DrawContext dc, java.awt.Point awtPoint)
- {
- if (dc.getView() == null || dc.getView().getViewport() == null)
- return null;
-
- java.awt.Rectangle viewport = dc.getView().getViewport();
- return new java.awt.Point(awtPoint.x, viewport.height - awtPoint.y - 1);
- }
-
//**************************************************************//
//******************** Text Utilities ************************//
//**************************************************************//
diff --git a/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java b/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java
index 9c77cd54fc..a4d6b2bd29 100644
--- a/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java
+++ b/src/gov/nasa/worldwind/render/AbstractBrowserBalloon.java
@@ -1731,7 +1731,7 @@ protected void drawResizeControl(DrawContext dc, OrderedBrowserBalloon obb)
// Compute the screen rectangle in AWT coordinates (origin top left).
Rectangle awtScreenRect = new Rectangle(obb.screenRect.x,
- dc.getView().getViewport().height - obb.screenRect.y - obb.screenRect.height,
+ obb.screenRect.y - obb.screenRect.height,
obb.screenRect.width, obb.screenRect.height);
Color color = dc.getUniquePickColor();
diff --git a/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java b/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java
index 81faf5ce86..394e81e879 100644
--- a/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java
+++ b/src/gov/nasa/worldwind/render/DeclutteringTextRenderer.java
@@ -36,6 +36,8 @@
import com.jogamp.opengl.*;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.gl2.GLUgl2;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.io.IOException;
diff --git a/src/gov/nasa/worldwind/render/DrawContext.java b/src/gov/nasa/worldwind/render/DrawContext.java
index 750955b933..c6e8567a5e 100644
--- a/src/gov/nasa/worldwind/render/DrawContext.java
+++ b/src/gov/nasa/worldwind/render/DrawContext.java
@@ -345,14 +345,14 @@ public interface DrawContext extends WWObject, Disposable
Color getClearColor();
/**
- * Returns the framebuffer RGB color for a point in AWT screen coordinates, formatted as a pick color code. The red,
+ * Returns the framebuffer RGB color for a point in GL surface coordinates, formatted as a pick color code. The red,
* green, and blue components are each stored as an 8-bit unsigned integer, and packed into bits 0-23 of the
* returned integer as follows: bits 16-23 are red, bits 8-15 are green, and bits 0-7 are blue. This format is
* consistent with the RGB integers used to create the pick colors in getUniquePickColor.
*
* This returns 0 if the point contains the clear color, or is outside this draw context's drawable area.
*
- * @param point the point to return a color for, in AWT screen coordinates.
+ * @param point the point to return a color for, in GL surface coordinates.
*
* @return the RGB color corresponding to the specified point.
*
@@ -361,7 +361,7 @@ public interface DrawContext extends WWObject, Disposable
int getPickColorAtPoint(Point point);
/**
- * Returns an array of the unique framebuffer RGB colors within a rectangle in AWT screen coordinates, formatted as
+ * Returns an array of the unique framebuffer RGB colors within a rectangle in GL surface coordinates, formatted as
* pick color codes. The red, green, and blue components are each stored as an 8-bit unsigned integer, and packed
* into bits 0-23 of the returned integers as follows: bits 16-23 are red, bits 8-15 are green, and bits 0-7 are
* blue. This format is consistent with the RGB integers used to create the pick colors in getUniquePickColor.
@@ -376,7 +376,7 @@ public interface DrawContext extends WWObject, Disposable
* the colors that must be considered by this method and the caller. When specified, these integers must be
* formatted exactly as the integers this method returns.
*
- * @param rectangle the rectangle to return unique colors for, in AWT screen coordinates.
+ * @param rectangle the rectangle to return unique colors for, in GL surface coordinates.
* @param minAndMaxColorCodes an two element array representing the minimum and maximum RGB colors to return. May be
* null to specify that all color codes must be returned.
*
@@ -502,7 +502,7 @@ public interface DrawContext extends WWObject, Disposable
SurfaceTileRenderer getGeographicSurfaceTileRenderer();
/**
- * Returns the current pick point in AWT screen coordinates.
+ * Returns the current pick point in GL surface coordinates.
*
* @return the current pick point, or null if no pick point is available.
*
@@ -511,7 +511,7 @@ public interface DrawContext extends WWObject, Disposable
Point getPickPoint();
/**
- * Specifies the current pick point in AWT screen coordinates, or null to indicate that there is no
+ * Specifies the current pick point in GL surface coordinates, or null to indicate that there is no
* pick point. During each pick traversal, layers determine if their contents are drawn at the pick point. If so,
* layers add each unique picked object to a PickedObjectList on this draw context by calling {@link
* #addPickedObject(gov.nasa.worldwind.pick.PickedObject)}. This list can be accessed by calling {@link
@@ -525,7 +525,7 @@ public interface DrawContext extends WWObject, Disposable
void setPickPoint(Point pickPoint);
/**
- * Returns the current pick rectangle in AWT screen coordinates.
+ * Returns the current pick rectangle in GL surface coordinates.
*
* @return the current pick rectangle, or null if no pick rectangle is current.
*
@@ -534,7 +534,7 @@ public interface DrawContext extends WWObject, Disposable
Rectangle getPickRectangle();
/**
- * Specifies the current pick rectangle in AWT screen coordinates, or null to indicate that there is no
+ * Specifies the current pick rectangle in GL surface coordinates, or null to indicate that there is no
* pick rectangle. During each pick traversal, layers determine if their contents intersect the pick rectangle. If
* so, layers add each unique picked object to a PickedObjectList on this draw context by calling {@link
* #addObjectInPickRectangle(gov.nasa.worldwind.pick.PickedObject)}. This is list can be accessed by calling {@link
@@ -1046,4 +1046,16 @@ public interface DrawContext extends WWObject, Disposable
boolean is2DGlobe();
boolean isContinuous2DGlobe();
+
+ /**
+ * Convert AWT effective screen location to GL surface location using DPI scaling.
+ */
+ int [] awtPointToGLpoint(Point pt);
+
+ /**
+ * Convert GL surface coordinate point to AWT device point using DPI scaling.
+ * @param glPoint
+ * @return
+ */
+ public Point glPointToAwtPoint(Point glPoint);
}
diff --git a/src/gov/nasa/worldwind/render/DrawContextImpl.java b/src/gov/nasa/worldwind/render/DrawContextImpl.java
index 4c3cf88c92..c24100b162 100644
--- a/src/gov/nasa/worldwind/render/DrawContextImpl.java
+++ b/src/gov/nasa/worldwind/render/DrawContextImpl.java
@@ -87,15 +87,15 @@ public class DrawContextImpl extends WWObjectImpl implements DrawContext
protected boolean pickingMode = false;
protected boolean deepPickingMode = false;
/**
- * Indicates the current pick point in AWT screen coordinates, or null to indicate that there is no
+ * Indicates the current pick point in GL screen coordinates, or null to indicate that there is no
* pick point. Initially null.
*/
- protected Point pickPoint = null;
+ private Point pickPoint = null;
/**
- * Indicates the current pick rectangle in AWT screen coordinates, or null to indicate that there is no
+ * Indicates the current pick rectangle in GL screen coordinates, or null to indicate that there is no
* pick rectangle. Initially null.
*/
- protected Rectangle pickRect = null;
+ private Rectangle pickRect = null;
protected boolean isOrderedRenderingMode = false;
protected boolean preRenderMode = false;
protected Point viewportCenterScreenPoint = null;
@@ -154,7 +154,8 @@ public OrderedRenderableEntry(OrderedRenderable orderedRenderable, double distan
protected PriorityQueue orderedRenderables =
new PriorityQueue(100, new Comparator()
{
- public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
+ @Override
+ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
{
double eA = orA.distanceFromEye;
double eB = orB.distanceFromEye;
@@ -171,47 +172,56 @@ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
*
* @throws com.jogamp.opengl.GLException - If an OpenGL context is not current when this method is called.
*/
- public void dispose()
+ @Override
+ public void dispose()
{
this.geographicSurfaceTileRenderer.dispose();
}
- public final GL getGL()
+ @Override
+ public final GL getGL()
{
return this.getGLContext().getGL();
}
- public final GLU getGLU()
+ @Override
+ public final GLU getGLU()
{
return this.glu;
}
- public final GLContext getGLContext()
+ @Override
+ public final GLContext getGLContext()
{
return this.glContext;
}
- public final int getDrawableHeight()
+ @Override
+ public final int getDrawableHeight()
{
return this.getGLDrawable().getSurfaceHeight();
}
- public final int getDrawableWidth()
+ @Override
+ public final int getDrawableWidth()
{
return this.getGLDrawable().getSurfaceWidth();
}
- public final GLDrawable getGLDrawable()
+ @Override
+ public final GLDrawable getGLDrawable()
{
return this.getGLContext().getGLDrawable();
}
- public GLRuntimeCapabilities getGLRuntimeCapabilities()
+ @Override
+ public GLRuntimeCapabilities getGLRuntimeCapabilities()
{
return this.glRuntimeCaps;
}
- public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
+ @Override
+ public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
{
if (capabilities == null)
{
@@ -223,7 +233,8 @@ public void setGLRuntimeCapabilities(GLRuntimeCapabilities capabilities)
this.glRuntimeCaps = capabilities;
}
- public final void initialize(GLContext glContext)
+ @Override
+ public final void initialize(GLContext glContext)
{
if (glContext == null)
{
@@ -252,7 +263,8 @@ public final void initialize(GLContext glContext)
this.currentLayer = null;
}
- public final void setModel(Model model)
+ @Override
+ public final void setModel(Model model)
{
this.model = model;
if (this.model == null)
@@ -263,53 +275,63 @@ public final void setModel(Model model)
this.globe = g;
}
- public final Model getModel()
+ @Override
+ public final Model getModel()
{
return this.model;
}
- public final LayerList getLayers()
+ @Override
+ public final LayerList getLayers()
{
return this.model.getLayers();
}
- public final Sector getVisibleSector()
+ @Override
+ public final Sector getVisibleSector()
{
return this.visibleSector;
}
- public final void setVisibleSector(Sector s)
+ @Override
+ public final void setVisibleSector(Sector s)
{
// don't check for null - it is possible that no globe is active, no view is active, no sectors visible, etc.
this.visibleSector = s;
}
- public void setSurfaceGeometry(SectorGeometryList surfaceGeometry)
+ @Override
+ public void setSurfaceGeometry(SectorGeometryList surfaceGeometry)
{
this.surfaceGeometry = surfaceGeometry;
}
- public SectorGeometryList getSurfaceGeometry()
+ @Override
+ public SectorGeometryList getSurfaceGeometry()
{
return surfaceGeometry;
}
- public final Globe getGlobe()
+ @Override
+ public final Globe getGlobe()
{
return this.globe != null ? this.globe : this.model.getGlobe();
}
- public final void setView(View view)
+ @Override
+ public final void setView(View view)
{
this.view = view;
}
- public final View getView()
+ @Override
+ public final View getView()
{
return this.view;
}
- public final void setGLContext(GLContext glContext)
+ @Override
+ public final void setGLContext(GLContext glContext)
{
if (glContext == null)
{
@@ -321,27 +343,32 @@ public final void setGLContext(GLContext glContext)
this.glContext = glContext;
}
- public final double getVerticalExaggeration()
+ @Override
+ public final double getVerticalExaggeration()
{
return verticalExaggeration;
}
- public final void setVerticalExaggeration(double verticalExaggeration)
+ @Override
+ public final void setVerticalExaggeration(double verticalExaggeration)
{
this.verticalExaggeration = verticalExaggeration;
}
- public GpuResourceCache getTextureCache()
+ @Override
+ public GpuResourceCache getTextureCache()
{
return this.gpuResourceCache;
}
- public GpuResourceCache getGpuResourceCache()
+ @Override
+ public GpuResourceCache getGpuResourceCache()
{
return this.gpuResourceCache;
}
- public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
+ @Override
+ public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
{
if (gpuResourceCache == null)
{
@@ -353,12 +380,14 @@ public void setGpuResourceCache(GpuResourceCache gpuResourceCache)
this.gpuResourceCache = gpuResourceCache;
}
- public TextRendererCache getTextRendererCache()
+ @Override
+ public TextRendererCache getTextRendererCache()
{
return textRendererCache;
}
- public void setTextRendererCache(TextRendererCache textRendererCache)
+ @Override
+ public void setTextRendererCache(TextRendererCache textRendererCache)
{
if (textRendererCache == null)
{
@@ -370,12 +399,14 @@ public void setTextRendererCache(TextRendererCache textRendererCache)
this.textRendererCache = textRendererCache;
}
- public AnnotationRenderer getAnnotationRenderer()
+ @Override
+ public AnnotationRenderer getAnnotationRenderer()
{
return annotationRenderer;
}
- public void setAnnotationRenderer(AnnotationRenderer ar)
+ @Override
+ public void setAnnotationRenderer(AnnotationRenderer ar)
{
if (ar == null)
{
@@ -386,57 +417,68 @@ public void setAnnotationRenderer(AnnotationRenderer ar)
annotationRenderer = ar;
}
- public LightingModel getStandardLightingModel()
+ @Override
+ public LightingModel getStandardLightingModel()
{
return standardLighting;
}
- public void setStandardLightingModel(LightingModel standardLighting)
+ @Override
+ public void setStandardLightingModel(LightingModel standardLighting)
{
this.standardLighting = standardLighting;
}
- public Point getPickPoint()
+ @Override
+ public Point getPickPoint()
{
return this.pickPoint;
}
- public void setPickPoint(Point pickPoint)
+ @Override
+ public void setPickPoint(Point pickPoint)
{
- this.pickPoint = pickPoint;
+ this.pickPoint = pickPoint;
}
- public Rectangle getPickRectangle()
+ @Override
+ public Rectangle getPickRectangle()
{
return this.pickRect;
}
- public void setPickRectangle(Rectangle pickRect)
+ @Override
+ public void setPickRectangle(Rectangle pickRect)
{
this.pickRect = pickRect;
}
- public Point getViewportCenterScreenPoint()
+ @Override
+ public Point getViewportCenterScreenPoint()
{
return viewportCenterScreenPoint;
}
- public void setViewportCenterScreenPoint(Point viewportCenterScreenPoint)
+ @Override
+ public void setViewportCenterScreenPoint(Point viewportCenterScreenPoint)
{
this.viewportCenterScreenPoint = viewportCenterScreenPoint;
}
- public Position getViewportCenterPosition()
+ @Override
+ public Position getViewportCenterPosition()
{
return viewportCenterPosition;
}
- public void setViewportCenterPosition(Position viewportCenterPosition)
+ @Override
+ public void setViewportCenterPosition(Position viewportCenterPosition)
{
this.viewportCenterPosition = viewportCenterPosition;
}
- public void addPickedObjects(PickedObjectList pickedObjects)
+ @Override
+ public void addPickedObjects(PickedObjectList pickedObjects)
{
if (pickedObjects == null)
{
@@ -457,7 +499,8 @@ public void addPickedObjects(PickedObjectList pickedObjects)
}
}
- public void addPickedObject(PickedObject pickedObject)
+ @Override
+ public void addPickedObject(PickedObject pickedObject)
{
if (null == pickedObject)
{
@@ -472,17 +515,20 @@ public void addPickedObject(PickedObject pickedObject)
this.pickedObjects.add(pickedObject);
}
- public PickedObjectList getPickedObjects()
+ @Override
+ public PickedObjectList getPickedObjects()
{
return this.pickedObjects;
}
- public PickedObjectList getObjectsInPickRectangle()
+ @Override
+ public PickedObjectList getObjectsInPickRectangle()
{
return this.objectsInPickRect;
}
- public void addObjectInPickRectangle(PickedObject pickedObject)
+ @Override
+ public void addObjectInPickRectangle(PickedObject pickedObject)
{
if (pickedObject == null)
{
@@ -494,7 +540,8 @@ public void addObjectInPickRectangle(PickedObject pickedObject)
this.objectsInPickRect.add(pickedObject);
}
- public Color getUniquePickColor()
+ @Override
+ public Color getUniquePickColor()
{
this.uniquePickNumber++;
@@ -512,7 +559,8 @@ public Color getUniquePickColor()
return new Color(this.uniquePickNumber, true); // has alpha
}
- public Color getUniquePickColorRange(int count)
+ @Override
+ public Color getUniquePickColorRange(int count)
{
if (count < 1)
return null;
@@ -532,13 +580,15 @@ public Color getUniquePickColorRange(int count)
return new Color(range.location, true); // return a pointer to the beginning of the requested range
}
- public Color getClearColor()
+ @Override
+ public Color getClearColor()
{
return this.clearColor;
}
/** {@inheritDoc} */
- public int getPickColorAtPoint(Point point)
+ @Override
+ public int getPickColorAtPoint(Point point)
{
if (point == null)
{
@@ -547,10 +597,8 @@ public int getPickColorAtPoint(Point point)
throw new IllegalArgumentException(msg);
}
- // Translate the point from AWT screen coordinates to OpenGL screen coordinates.
- Rectangle viewport = this.getView().getViewport();
int x = point.x;
- int y = viewport.height - point.y - 1;
+ int y = point.y;
// Read the framebuffer color at the specified point in OpenGL screen coordinates as a 24-bit RGB value.
if (this.pixelColors == null || this.pixelColors.capacity() < 3)
@@ -566,7 +614,8 @@ public int getPickColorAtPoint(Point point)
}
/** {@inheritDoc} */
- public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorCodes)
+ @Override
+ public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorCodes)
{
if (rectangle == null)
{
@@ -577,10 +626,7 @@ public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorC
Rectangle viewport = this.getView().getViewport();
- // Transform the rectangle from AWT screen coordinates to OpenGL screen coordinates and compute its intersection
- // with the viewport. Transformation to GL coordinates must be done prior to computing the intersection, because
- // the viewport is in GL coordinates. The resultant rectangle represents the area that's valid to read from GL.
- Rectangle r = new Rectangle(rectangle.x, viewport.height - rectangle.y - 1, rectangle.width, rectangle.height);
+ Rectangle r = new Rectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
r = r.intersection(viewport);
if (r.isEmpty()) // Return null if the rectangle is empty.
@@ -641,52 +687,62 @@ public int[] getPickColorsInRectangle(Rectangle rectangle, int[] minAndMaxColorC
return array;
}
- public boolean isPickingMode()
+ @Override
+ public boolean isPickingMode()
{
return this.pickingMode;
}
- public void enablePickingMode()
+ @Override
+ public void enablePickingMode()
{
this.pickingMode = true;
}
- public void disablePickingMode()
+ @Override
+ public void disablePickingMode()
{
this.pickingMode = false;
}
- public boolean isDeepPickingEnabled()
+ @Override
+ public boolean isDeepPickingEnabled()
{
return this.deepPickingMode;
}
- public void setDeepPickingEnabled(boolean tf)
+ @Override
+ public void setDeepPickingEnabled(boolean tf)
{
this.deepPickingMode = tf;
}
- public boolean isPreRenderMode()
+ @Override
+ public boolean isPreRenderMode()
{
return preRenderMode;
}
- public void setPreRenderMode(boolean preRenderMode)
+ @Override
+ public void setPreRenderMode(boolean preRenderMode)
{
this.preRenderMode = preRenderMode;
}
- public boolean isOrderedRenderingMode()
+ @Override
+ public boolean isOrderedRenderingMode()
{
return this.isOrderedRenderingMode;
}
- public void setOrderedRenderingMode(boolean tf)
+ @Override
+ public void setOrderedRenderingMode(boolean tf)
{
this.isOrderedRenderingMode = tf;
}
- public DeclutteringTextRenderer getDeclutteringTextRenderer()
+ @Override
+ public DeclutteringTextRenderer getDeclutteringTextRenderer()
{
return declutteringTextRenderer;
}
@@ -703,7 +759,8 @@ public boolean isContinuous2DGlobe()
return this.globe instanceof Globe2D && ((Globe2D) this.getGlobe()).isContinuous();
}
- public void addOrderedRenderable(OrderedRenderable orderedRenderable)
+ @Override
+ public void addOrderedRenderable(OrderedRenderable orderedRenderable)
{
if (null == orderedRenderable)
{
@@ -716,7 +773,8 @@ public void addOrderedRenderable(OrderedRenderable orderedRenderable)
}
/** {@inheritDoc} */
- public void addOrderedRenderable(OrderedRenderable orderedRenderable, boolean isBehind)
+ @Override
+ public void addOrderedRenderable(OrderedRenderable orderedRenderable, boolean isBehind)
{
if (null == orderedRenderable)
{
@@ -734,14 +792,16 @@ public void addOrderedRenderable(OrderedRenderable orderedRenderable, boolean is
new OrderedRenderableEntry(orderedRenderable, eyeDistance, System.nanoTime(), this));
}
- public OrderedRenderable peekOrderedRenderables()
+ @Override
+ public OrderedRenderable peekOrderedRenderables()
{
OrderedRenderableEntry ore = this.orderedRenderables.peek();
return ore != null ? ore.or : null;
}
- public OrderedRenderable pollOrderedRenderables()
+ @Override
+ public OrderedRenderable pollOrderedRenderables()
{
OrderedRenderableEntry ore = this.orderedRenderables.poll();
@@ -810,7 +870,8 @@ public ClutterFilter getClutterFilter()
return this.clutterFilter;
}
- public void applyClutterFilter()
+ @Override
+ public void applyClutterFilter()
{
if (this.getClutterFilter() == null)
return;
@@ -826,7 +887,8 @@ public void applyClutterFilter()
// Sort the declutterables front-to-back.
Collections.sort(declutterableArray, new Comparator()
{
- public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
+ @Override
+ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
{
double eA = orA.distanceFromEye;
double eB = orB.distanceFromEye;
@@ -854,7 +916,8 @@ public int compare(OrderedRenderableEntry orA, OrderedRenderableEntry orB)
}
/** {@inheritDoc} */
- public void addOrderedSurfaceRenderable(OrderedRenderable orderedRenderable)
+ @Override
+ public void addOrderedSurfaceRenderable(OrderedRenderable orderedRenderable)
{
if (orderedRenderable == null)
{
@@ -867,7 +930,8 @@ public void addOrderedSurfaceRenderable(OrderedRenderable orderedRenderable)
}
/** {@inheritDoc} */
- public Queue getOrderedSurfaceRenderables()
+ @Override
+ public Queue getOrderedSurfaceRenderables()
{
return this.orderedSurfaceRenderables;
}
@@ -903,7 +967,8 @@ public Queue getOrderedSurfaceRenderables()
// }
// }
- public void drawUnitQuad()
+ @Override
+ public void drawUnitQuad()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -915,7 +980,8 @@ public void drawUnitQuad()
gl.glEnd();
}
- public void drawUnitQuad(TextureCoords texCoords)
+ @Override
+ public void drawUnitQuad(TextureCoords texCoords)
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -931,7 +997,8 @@ public void drawUnitQuad(TextureCoords texCoords)
gl.glEnd();
}
- public void drawUnitQuadOutline()
+ @Override
+ public void drawUnitQuadOutline()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -943,7 +1010,8 @@ public void drawUnitQuadOutline()
gl.glEnd();
}
- public void drawNormals(float length, FloatBuffer vBuf, FloatBuffer nBuf)
+ @Override
+ public void drawNormals(float length, FloatBuffer vBuf, FloatBuffer nBuf)
{
if (vBuf == null || nBuf == null)
return;
@@ -971,7 +1039,8 @@ public void drawNormals(float length, FloatBuffer vBuf, FloatBuffer nBuf)
gl.glEnd();
}
- public Vec4 getPointOnTerrain(Angle latitude, Angle longitude)
+ @Override
+ public Vec4 getPointOnTerrain(Angle latitude, Angle longitude)
{
if (latitude == null || longitude == null)
{
@@ -997,28 +1066,33 @@ public Vec4 getPointOnTerrain(Angle latitude, Angle longitude)
return null;
}
- public SurfaceTileRenderer getGeographicSurfaceTileRenderer()
+ @Override
+ public SurfaceTileRenderer getGeographicSurfaceTileRenderer()
{
return this.geographicSurfaceTileRenderer;
}
- public Collection getPerFrameStatistics()
+ @Override
+ public Collection getPerFrameStatistics()
{
return this.perFrameStatistics;
}
- public void setPerFrameStatisticsKeys(Set statKeys, Collection stats)
+ @Override
+ public void setPerFrameStatisticsKeys(Set statKeys, Collection stats)
{
this.perFrameStatisticsKeys = statKeys;
this.perFrameStatistics = stats;
}
- public Set getPerFrameStatisticsKeys()
+ @Override
+ public Set getPerFrameStatisticsKeys()
{
return perFrameStatisticsKeys;
}
- public void setPerFrameStatistic(String key, String displayName, Object value)
+ @Override
+ public void setPerFrameStatistic(String key, String displayName, Object value)
{
if (this.perFrameStatistics == null || this.perFrameStatisticsKeys == null)
return;
@@ -1041,7 +1115,8 @@ public void setPerFrameStatistic(String key, String displayName, Object value)
this.perFrameStatistics.add(new PerformanceStatistic(key, displayName, value));
}
- public void setPerFrameStatistics(Collection stats)
+ @Override
+ public void setPerFrameStatistics(Collection stats)
{
if (stats == null)
{
@@ -1059,17 +1134,20 @@ public void setPerFrameStatistics(Collection stats)
}
}
- public long getFrameTimeStamp()
+ @Override
+ public long getFrameTimeStamp()
{
return this.frameTimestamp;
}
- public void setFrameTimeStamp(long frameTimeStamp)
+ @Override
+ public void setFrameTimeStamp(long frameTimeStamp)
{
this.frameTimestamp = frameTimeStamp;
}
- public List getVisibleSectors(double[] resolutions, long timeLimit, Sector sector)
+ @Override
+ public List getVisibleSectors(double[] resolutions, long timeLimit, Sector sector)
{
if (resolutions == null)
{
@@ -1106,19 +1184,22 @@ else if (this.visibleSectors.getSectorSize() == resolutions[resolutions.length -
return this.visibleSectors.getSectors();
}
- public void setCurrentLayer(Layer layer)
+ @Override
+ public void setCurrentLayer(Layer layer)
{
this.currentLayer = layer;
}
- public Layer getCurrentLayer()
+ @Override
+ public Layer getCurrentLayer()
{
return this.currentLayer;
}
protected LinkedHashMap credits = new LinkedHashMap();
- public void addScreenCredit(ScreenCredit credit)
+ @Override
+ public void addScreenCredit(ScreenCredit credit)
{
if (credit == null)
{
@@ -1130,27 +1211,32 @@ public void addScreenCredit(ScreenCredit credit)
this.credits.put(credit, this.frameTimestamp);
}
- public Map getScreenCredits()
+ @Override
+ public Map getScreenCredits()
{
return this.credits;
}
- public int getRedrawRequested()
+ @Override
+ public int getRedrawRequested()
{
return redrawRequested;
}
- public void setRedrawRequested(int redrawRequested)
+ @Override
+ public void setRedrawRequested(int redrawRequested)
{
this.redrawRequested = redrawRequested;
}
- public PickPointFrustumList getPickFrustums()
+ @Override
+ public PickPointFrustumList getPickFrustums()
{
return this.pickFrustumList;
}
- public void setPickPointFrustumDimension(Dimension dim)
+ @Override
+ public void setPickPointFrustumDimension(Dimension dim)
{
if (dim == null)
{
@@ -1169,25 +1255,20 @@ public void setPickPointFrustumDimension(Dimension dim)
this.pickPointFrustumDimension = new Dimension(dim);
}
- public Dimension getPickPointFrustumDimension()
+ @Override
+ public Dimension getPickPointFrustumDimension()
{
return this.pickPointFrustumDimension;
}
- public void addPickPointFrustum()
+ @Override
+ public void addPickPointFrustum()
{
//Compute the current picking frustum
if (getPickPoint() != null)
{
- Rectangle viewport = getView().getViewport();
-
- double viewportWidth = viewport.getWidth() <= 0.0 ? 1.0 : viewport.getWidth();
- double viewportHeight = viewport.getHeight() <= 0.0 ? 1.0 : viewport.getHeight();
-
- //Get the pick point and translate screen center to zero
Point ptCenter = new Point(getPickPoint());
- ptCenter.y = (int) viewportHeight - ptCenter.y;
- ptCenter.translate((int) (-viewportWidth / 2), (int) (-viewportHeight / 2));
+ ptCenter.translate(-viewportCenterScreenPoint.x, -viewportCenterScreenPoint.y);
//Number of pixels around pick point to include in frustum
int offsetX = pickPointFrustumDimension.width / 2;
@@ -1199,7 +1280,9 @@ public void addPickPointFrustum()
//Compute the distance to the near plane in screen coordinates
double width = getView().getFieldOfView().tanHalfAngle() * getView().getNearClipDistance();
- double x = width / (viewportWidth / 2.0);
+ double viewportWidth = getView().getViewport().getWidth();
+ if (viewportWidth <= 0.0) viewportWidth = 1.0;
+ double x = width / (viewportWidth/2);
double screenDist = getView().getNearClipDistance() / x;
//Create the four vectors that define the top-left, top-right, bottom-left, and bottom-right vectors
@@ -1213,10 +1296,10 @@ public void addPickPointFrustum()
getView().getNearClipDistance(), getView().getFarClipDistance());
//Create the screen rectangle associated with this frustum
- Rectangle rectScreen = new Rectangle(getPickPoint().x - offsetX,
- (int) viewportHeight - getPickPoint().y - offsetY,
- pickPointFrustumDimension.width,
- pickPointFrustumDimension.height);
+ Rectangle rectScreen = new Rectangle(getPickPoint().x - offsetX + 1,
+ getPickPoint().y - offsetY - 1,
+ pickPointFrustumDimension.width,
+ pickPointFrustumDimension.height);
//Transform the frustum to Model Coordinates
Matrix modelviewTranspose = getView().getModelviewMatrix().getTranspose();
@@ -1227,24 +1310,21 @@ public void addPickPointFrustum()
}
}
- public void addPickRectangleFrustum()
+ @Override
+ public void addPickRectangleFrustum()
{
// Do nothing if the pick rectangle is either null or has zero dimension.
if (this.getPickRectangle() == null || this.getPickRectangle().isEmpty())
return;
- View view = this.getView();
-
- Rectangle viewport = view.getViewport();
- double viewportWidth = viewport.getWidth() <= 0.0 ? 1.0 : viewport.getWidth();
- double viewportHeight = viewport.getHeight() <= 0.0 ? 1.0 : viewport.getHeight();
-
- // Get the pick rectangle, transform it from AWT screen coordinates to OpenGL screen coordinates, then translate
+ // Get the pick rectangle, transform it from GL surface coordinates to OpenGL screen coordinates, then translate
// it such that the screen's center is at the origin.
Rectangle pr = new Rectangle(this.getPickRectangle());
- pr.y = (int) viewportHeight - pr.y;
- pr.translate((int) (-viewportWidth / 2), (int) (-viewportHeight / 2));
+ pr.translate(-viewportCenterScreenPoint.x, -viewportCenterScreenPoint.y);
+ double viewportWidth = view.getViewport().getWidth();
+ if (viewportWidth <= 0.0) viewportWidth = 1.0;
+
// Create the four vectors that define the top-left, top-right, bottom-left, and bottom-right corners of the
// pick rectangle in screen coordinates.
double screenDist = viewportWidth / (2 * view.getFieldOfView().tanHalfAngle());
@@ -1265,22 +1345,24 @@ public void addPickRectangleFrustum()
// Create the screen rectangle in OpenGL screen coordinates associated with this frustum. We translate the
// specified pick rectangle from AWT coordinates to GL coordinates by inverting the y axis.
Rectangle screenRect = new Rectangle(this.getPickRectangle());
- screenRect.y = (int) viewportHeight - screenRect.y;
this.pickFrustumList.add(new PickPointFrustum(frustum, screenRect));
}
- public Collection getRenderingExceptions()
+ @Override
+ public Collection getRenderingExceptions()
{
return this.renderingExceptions;
}
- public void setRenderingExceptions(Collection exceptions)
+ @Override
+ public void setRenderingExceptions(Collection exceptions)
{
this.renderingExceptions = exceptions;
}
- public void addRenderingException(Throwable t)
+ @Override
+ public void addRenderingException(Throwable t)
{
// If the renderingExceptions Collection is non-null, it's used as the data structure that accumulates rendering
// exceptions. Otherwise this DrawContext ignores all rendering exceptions passed to this method.
@@ -1297,7 +1379,8 @@ public void addRenderingException(Throwable t)
this.renderingExceptions.add(t);
}
- public void pushProjectionOffest(Double offset)
+ @Override
+ public void pushProjectionOffest(Double offset)
{
// Modify the projection transform to shift the depth values slightly toward the camera in order to
// ensure the lines are selected during depth buffering.
@@ -1313,7 +1396,8 @@ public void pushProjectionOffest(Double offset)
gl.glLoadMatrixf(pm, 0);
}
- public void popProjectionOffest()
+ @Override
+ public void popProjectionOffest()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
@@ -1325,7 +1409,8 @@ public void popProjectionOffest()
public static final float DEFAULT_DEPTH_OFFSET_FACTOR = 1f;
public static final float DEFAULT_DEPTH_OFFSET_UNITS = 1f;
- public void drawOutlinedShape(OutlinedShape renderer, Object shape)
+ @Override
+ public void drawOutlinedShape(OutlinedShape renderer, Object shape)
{
// Draw the outlined shape using a multiple pass algorithm. The motivation for this algorithm is twofold:
//
@@ -1433,7 +1518,8 @@ public void drawOutlinedShape(OutlinedShape renderer, Object shape)
}
}
- public void beginStandardLighting()
+ @Override
+ public void beginStandardLighting()
{
if (this.standardLighting != null)
{
@@ -1442,7 +1528,8 @@ public void beginStandardLighting()
}
}
- public void endStandardLighting()
+ @Override
+ public void endStandardLighting()
{
if (this.standardLighting != null)
{
@@ -1450,7 +1537,8 @@ public void endStandardLighting()
}
}
- public boolean isSmall(Extent extent, int numPixels)
+ @Override
+ public boolean isSmall(Extent extent, int numPixels)
{
return extent != null && extent.getDiameter() <= numPixels * this.getView().computePixelSizeAtDistance(
// burkey couldnt we make this minimum dimension
@@ -1458,29 +1546,34 @@ public boolean isSmall(Extent extent, int numPixels)
extent.getCenter())); // -- so box could return small when one dim is narrow?
} // i see really skinny telephone poles that dont need to be rendered at distance but are tall
- public Terrain getTerrain()
+ @Override
+ public Terrain getTerrain()
{
return this.terrain;
}
- public Vec4 computeTerrainPoint(Angle lat, Angle lon, double offset)
+ @Override
+ public Vec4 computeTerrainPoint(Angle lat, Angle lon, double offset)
{
return this.getTerrain().getSurfacePoint(lat, lon, offset);
}
protected Terrain terrain = new Terrain()
{
- public Globe getGlobe()
+ @Override
+ public Globe getGlobe()
{
return DrawContextImpl.this.getGlobe();
}
- public double getVerticalExaggeration()
+ @Override
+ public double getVerticalExaggeration()
{
return DrawContextImpl.this.getVerticalExaggeration();
}
- public Vec4 getSurfacePoint(Position position)
+ @Override
+ public Vec4 getSurfacePoint(Position position)
{
if (position == null)
{
@@ -1504,7 +1597,8 @@ public Vec4 getSurfacePoint(Position position)
return pt;
}
- public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset)
+ @Override
+ public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset)
{
if (latitude == null || longitude == null)
{
@@ -1529,7 +1623,8 @@ public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset
return pt;
}
- public Intersection[] intersect(Position pA, Position pB)
+ @Override
+ public Intersection[] intersect(Position pA, Position pB)
{
SectorGeometryList sectorGeometry = DrawContextImpl.this.getSurfaceGeometry();
if (sectorGeometry == null)
@@ -1544,7 +1639,8 @@ public Intersection[] intersect(Position pA, Position pB)
return sectorGeometry.intersect(new Line(ptA, ptB.subtract3(ptA)));
}
- public Intersection[] intersect(Position pA, Position pB, int altitudeMode)
+ @Override
+ public Intersection[] intersect(Position pA, Position pB, int altitudeMode)
{
if (pA == null || pB == null)
{
@@ -1570,7 +1666,8 @@ else if (altitudeMode == WorldWind.CLAMP_TO_GROUND)
return this.intersect(new Position(pA, altitudeA), new Position(pB, altitudeB));
}
- public Double getElevation(LatLon location)
+ @Override
+ public Double getElevation(LatLon location)
{
if (location == null)
{
@@ -1589,25 +1686,29 @@ public Double getElevation(LatLon location)
}
};
- public void restoreDefaultBlending()
+ @Override
+ public void restoreDefaultBlending()
{
this.getGL().glBlendFunc(GL.GL_ONE, GL.GL_ZERO);
this.getGL().glDisable(GL.GL_BLEND);
}
- public void restoreDefaultCurrentColor()
+ @Override
+ public void restoreDefaultCurrentColor()
{
GL2 gl = this.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
gl.glColor4f(1, 1, 1, 1);
}
- public void restoreDefaultDepthTesting()
+ @Override
+ public void restoreDefaultDepthTesting()
{
this.getGL().glEnable(GL.GL_DEPTH_TEST);
this.getGL().glDepthMask(true);
}
- public Vec4 computePointFromPosition(Position position, int altitudeMode)
+ @Override
+ public Vec4 computePointFromPosition(Position position, int altitudeMode)
{
if (position == null)
{
@@ -1636,4 +1737,32 @@ else if (altitudeMode == WorldWind.RELATIVE_TO_GROUND)
return point;
}
+
+ /** {@inheritDoc} */
+ @Override
+ public int [] awtPointToGLpoint(Point pt) {
+ if (pt == null) return null;
+
+ int [] awtPt = { pt.x, pt.y };
+ if (glContext == null) return awtPt;
+
+ GLDrawable drawable = glContext.getGLDrawable();
+ if (drawable == null) return awtPt;
+
+ // Convert to GL surface coordinates
+ int [] glSurfacePt = drawable.getNativeSurface().convertToPixelUnits(awtPt);
+ int glSurfaceHeight = drawable.getSurfaceHeight();
+ glSurfacePt[1] = glSurfaceHeight-1 - glSurfacePt[1];
+ return glSurfacePt;
+ }
+
+ public Point glPointToAwtPoint(Point glPoint) {
+ GLDrawable drawable = glContext.getGLDrawable();
+ if (drawable == null) return glPoint;
+
+ final int viewportHeight = getView().getViewport().height;
+ int [] glPt = { glPoint.x, viewportHeight-1 - glPoint.y };
+ getGLDrawable().getNativeSurface().convertToWindowUnits(glPt);
+ return new Point(glPt[0], glPt[1]);
+ }
}
diff --git a/src/gov/nasa/worldwind/render/GeographicTextRenderer.java b/src/gov/nasa/worldwind/render/GeographicTextRenderer.java
index a362b387dc..d3aa21fa5d 100644
--- a/src/gov/nasa/worldwind/render/GeographicTextRenderer.java
+++ b/src/gov/nasa/worldwind/render/GeographicTextRenderer.java
@@ -38,6 +38,8 @@
import com.jogamp.opengl.*;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.gl2.GLUgl2;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.io.IOException;
diff --git a/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java b/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java
index d8677398b8..201b35eb64 100644
--- a/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java
+++ b/src/gov/nasa/worldwind/render/MultiLineTextRenderer.java
@@ -33,6 +33,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwind/render/Path.java b/src/gov/nasa/worldwind/render/Path.java
index dbb8d5fef5..a72fa785a4 100644
--- a/src/gov/nasa/worldwind/render/Path.java
+++ b/src/gov/nasa/worldwind/render/Path.java
@@ -569,7 +569,7 @@ public PickedObject getTopObject(DrawContext dc, Point pickPoint) {
* AVKey.ORDINAL_LIST.
*
* @param dc the draw context which receives the picked objects.
- * @param pickRect the rectangle in AWT screen coordinates.
+ * @param pickRect the rectangle in GL surface coordinates.
* @param layer the layer associated with the picked objects.
*/
@SuppressWarnings({"unchecked"})
diff --git a/src/gov/nasa/worldwind/render/PointPlacemark.java b/src/gov/nasa/worldwind/render/PointPlacemark.java
index 93c6e2d5c8..9ac04e0b57 100644
--- a/src/gov/nasa/worldwind/render/PointPlacemark.java
+++ b/src/gov/nasa/worldwind/render/PointPlacemark.java
@@ -40,6 +40,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.xml.stream.*;
import java.awt.*;
import java.awt.geom.*;
diff --git a/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java b/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java
index 82dbae6710..863a50d62c 100644
--- a/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java
+++ b/src/gov/nasa/worldwind/render/ScreenAnnotationBalloon.java
@@ -68,7 +68,8 @@ public ScreenAnnotationBalloon(String text, Point point)
}
/** {@inheritDoc} */
- protected ScreenAnnotation createAnnotation()
+ @Override
+ protected ScreenAnnotation createAnnotation()
{
ScreenAnnotation annotation = new ScreenAnnotation(this.getDecodedText(), this.screenPoint);
@@ -79,22 +80,22 @@ protected ScreenAnnotation createAnnotation()
}
/** {@inheritDoc} */
- protected ScreenAnnotation getAnnotation()
+ @Override
+ protected ScreenAnnotation getAnnotation()
{
return this.annotation;
}
/** {@inheritDoc} */
- protected void computePosition(DrawContext dc)
+ @Override
+ protected void computePosition(DrawContext dc)
{
- Rectangle viewport = dc.getView().getViewport();
-
- int y = (int) viewport.getHeight() - this.screenPoint.y - 1;
- this.getAnnotation().setScreenPoint(new Point(this.screenPoint.x, y));
+ this.getAnnotation().setScreenPoint(new Point(this.screenPoint));
}
/** {@inheritDoc} */
- public void setScreenLocation(Point point)
+ @Override
+ public void setScreenLocation(Point point)
{
if (point == null)
{
@@ -107,7 +108,8 @@ public void setScreenLocation(Point point)
}
/** {@inheritDoc} */
- public Point getScreenLocation()
+ @Override
+ public Point getScreenLocation()
{
return this.screenPoint;
}
diff --git a/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java b/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java
index f90914b995..65d1660ca4 100644
--- a/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java
+++ b/src/gov/nasa/worldwind/render/ScreenBrowserBalloon.java
@@ -82,13 +82,15 @@ protected OrderedBrowserBalloon createOrderedRenderable()
}
/** {@inheritDoc} */
- public Point getScreenLocation()
+ @Override
+ public Point getScreenLocation()
{
return this.screenLocation;
}
/** {@inheritDoc} */
- public void setScreenLocation(Point point)
+ @Override
+ public void setScreenLocation(Point point)
{
if (point == null)
{
@@ -111,7 +113,8 @@ public void setScreenLocation(Point point)
*
* @param dc the current draw context.
*/
- protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
+ @Override
+ protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
{
this.screenOffset = null;
obb.screenRect = null;
@@ -130,12 +133,11 @@ protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
// bottom left). Note: The screen offset denotes how to place the screen reference point relative to the frame.
// For example, an offset of (-10, -10) in pixels places the reference point below and to the left of the frame.
// Since the screen reference point is fixed, the frame appears to move relative to the reference point.
- int y = dc.getView().getViewport().height - this.screenLocation.y;
- obb.screenRect = new Rectangle(this.screenLocation.x - this.screenOffset.x, y - this.screenOffset.y,
+ obb.screenRect = new Rectangle(this.screenLocation.x - this.screenOffset.x, this.screenLocation.y - this.screenOffset.y,
size.width, size.height);
// Compute the screen extent as the rectangle containing the balloon's screen rectangle and its screen point.
obb.screenExtent = new Rectangle(obb.screenRect);
- obb.screenExtent.add(this.screenLocation.x, y);
+ obb.screenExtent.add(this.screenLocation.x, this.screenLocation.y);
// Compute the pickable screen extent as the screen extent, plus the width of the balloon's pickable outline.
// This extent is used during picking to ensure that the balloon's outline is pickable when it exceeds the
// balloon's screen extent.
@@ -147,7 +149,8 @@ protected void computeBalloonPoints(DrawContext dc, OrderedBrowserBalloon obb)
}
/** {@inheritDoc} */
- protected void setupDepthTest(DrawContext dc, OrderedBrowserBalloon obb)
+ @Override
+ protected void setupDepthTest(DrawContext dc, OrderedBrowserBalloon obb)
{
dc.getGL().glDisable(GL.GL_DEPTH_TEST);
}
diff --git a/src/gov/nasa/worldwind/render/ScreenCredit.java b/src/gov/nasa/worldwind/render/ScreenCredit.java
index e4a38a4d03..3e4c0533e6 100644
--- a/src/gov/nasa/worldwind/render/ScreenCredit.java
+++ b/src/gov/nasa/worldwind/render/ScreenCredit.java
@@ -47,6 +47,4 @@ public interface ScreenCredit extends Renderable
void setLink(String link);
String getLink();
-
- public void pick(DrawContext dc, java.awt.Point pickPoint);
}
diff --git a/src/gov/nasa/worldwind/render/ScreenCreditController.java b/src/gov/nasa/worldwind/render/ScreenCreditController.java
index aa2ae11949..d060ecc0e4 100644
--- a/src/gov/nasa/worldwind/render/ScreenCreditController.java
+++ b/src/gov/nasa/worldwind/render/ScreenCreditController.java
@@ -70,7 +70,8 @@ public ScreenCreditController(WorldWindow wwd)
wwd.addSelectListener(this);
}
- public void dispose()
+ @Override
+ public void dispose()
{
wwd.removeSelectListener(this);
if (wwd.getSceneController() == this)
@@ -87,7 +88,7 @@ public void setEnabled(boolean enabled)
this.enabled = enabled;
}
- public void pick(DrawContext dc, Point pickPoint)
+ public void pick(DrawContext dc, @SuppressWarnings("unused") Point pickPoint)
{
if (dc == null)
{
@@ -113,13 +114,13 @@ public void pick(DrawContext dc, Point pickPoint)
Rectangle viewport = new Rectangle(x, y, creditWidth, creditHeight);
credit.setViewport(viewport);
- credit.pick(dc, pickPoint);
x += (separation + creditWidth);
}
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc == null)
{
@@ -136,7 +137,7 @@ public void render(DrawContext dc)
Set> credits = dc.getScreenCredits().entrySet();
- int y = dc.getView().getViewport().height - (bottomMargin + creditHeight / 2);
+ int y = bottomMargin + creditHeight / 2;
int x = leftMargin + creditWidth / 2;
for (Map.Entry entry : credits)
@@ -156,7 +157,8 @@ public void render(DrawContext dc)
}
}
- public void selected(SelectEvent event)
+ @Override
+ public void selected(SelectEvent event)
{
if (event.getMouseEvent() != null && event.getMouseEvent().isConsumed())
return;
diff --git a/src/gov/nasa/worldwind/render/ScreenImage.java b/src/gov/nasa/worldwind/render/ScreenImage.java
index 69c33b5cb7..488d283002 100644
--- a/src/gov/nasa/worldwind/render/ScreenImage.java
+++ b/src/gov/nasa/worldwind/render/ScreenImage.java
@@ -78,13 +78,6 @@ public class ScreenImage extends WWObjectImpl implements Renderable, Exportable
* is computed in computeOffsets and used in draw Initially null.
*/
protected Point screenLocation;
- /**
- * Indicates the location of this screen image in the viewport (on the screen) in AWT coordinates. This property is
- * assigned in setScreenLocation and computeOffsets. In computeOffsets, this
- * is computed by converting the screenLocation from OpenGL coordinates to AWT coordinates. Initially
- * null.
- */
- protected Point awtScreenLocation;
protected double dx;
protected double dy;
protected Layer pickLayer;
@@ -122,7 +115,7 @@ public void render(DrawContext dc)
*/
public Point getScreenLocation()
{
- return this.awtScreenLocation;
+ return this.screenLocation;
}
/**
@@ -136,7 +129,7 @@ public Point getScreenLocation()
public Point getScreenLocation(DrawContext dc)
{
this.computeOffsets(dc);
- return this.awtScreenLocation;
+ return this.screenLocation;
}
/**
@@ -151,17 +144,16 @@ public Point getScreenLocation(DrawContext dc)
*/
public void setScreenLocation(Point screenLocation)
{
- // Use units PIXELS for the X screen offset, and and INSET_PIXELS for the Y screen offset. The Offset is in
- // OpenGL coordinates with the origin in the lower-left corner, but the Point is in AWT coordinates with the
- // origin in the upper-left corner. This offset translates the origin from the lower-left to the upper-left
- // corner.
- this.screenOffset = new Offset(screenLocation.getX(), screenLocation.getY(), AVKey.PIXELS, AVKey.INSET_PIXELS);
+ // Use units PIXELS for the X screen offset, and and PIXELS for the Y screen offset. The Offset is in
+ // OpenGL coordinates with the origin in the lower-left corner, as is the Point. This offset
+ // translates the origin from the lower-left to the upper-left corner.
+ this.screenOffset = new Offset(screenLocation.getX(), screenLocation.getY(), AVKey.PIXELS, AVKey.PIXELS);
this.imageOffset = new Offset(0.5, 0.5, AVKey.FRACTION, AVKey.FRACTION);
// Set cached screen location to the initial screen location so that it can be retrieved if getScreenLocation()
// is called before the image is rendered. This maintains backward compatibility with the previous behavior of
// ScreenImage.
- this.awtScreenLocation = new Point(screenLocation);
+ this.screenLocation = new Point(screenLocation);
}
/**
@@ -544,12 +536,7 @@ else if (this.getImageSource() == null) // If no image source is set, draw a rec
{
this.screenLocation = new Point(viewportWidth / 2, viewportHeight / 2);
}
-
- // Convert the screen location from OpenGL to AWT coordinates and store the result in awtScreenLocation. The
- // awtScreenLocation property is used in getScreenLocation to indicate the screen location in AWT
- // coordinates.
- this.awtScreenLocation = new Point(this.screenLocation.x, viewportHeight - this.screenLocation.y);
-
+
Point.Double overlayPoint;
if (this.imageOffset != null)
overlayPoint = this.imageOffset.computeOffset(this.width, this.height, null, null);
diff --git a/src/gov/nasa/worldwind/render/SurfaceText.java b/src/gov/nasa/worldwind/render/SurfaceText.java
index bdb5490b3a..74386e9aae 100644
--- a/src/gov/nasa/worldwind/render/SurfaceText.java
+++ b/src/gov/nasa/worldwind/render/SurfaceText.java
@@ -36,6 +36,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.util.Arrays;
diff --git a/src/gov/nasa/worldwind/render/TextRenderer.java b/src/gov/nasa/worldwind/render/TextRenderer.java
deleted file mode 100644
index 7ed52bbb85..0000000000
--- a/src/gov/nasa/worldwind/render/TextRenderer.java
+++ /dev/null
@@ -1,2095 +0,0 @@
-/*
- * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
- * Administrator of the National Aeronautics and Space Administration.
- * All rights reserved.
- *
- * The NASA World Wind Java (WWJ) platform is 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.
- *
- * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
- * software:
- *
- * Jackson Parser – Licensed under Apache 2.0
- * GDAL – Licensed under MIT
- * JOGL – Licensed under Berkeley Software Distribution (BSD)
- * Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
- * A complete listing of 3rd Party software notices and licenses included in
- * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
- * notices and licenses PDF found in code directory.
- */
-/*
- * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright (c) 2010 JogAmp Community. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistribution of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistribution in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of Sun Microsystems, Inc. or the names of
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
- * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
- * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
- * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
- * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
- * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
- * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
- * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
- * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
- * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
- * You acknowledge that this software is not designed or intended for use
- * in the design, construction, operation or maintenance of any nuclear
- * facility.
- *
- * Sun gratefully acknowledges that this software was originally authored
- * and developed by Kenneth Bradley Russell and Christopher John Kline.
- */
-/**
- * @version $Id: TextRenderer.java 2387 2014-10-15 20:25:02Z tgaskins $
- */
-
-package gov.nasa.worldwind.render;
-
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.opengl.GLExtensions;
-import com.jogamp.opengl.util.FPSAnimator;
-import com.jogamp.opengl.util.awt.TextureRenderer;
-import com.jogamp.opengl.util.packrect.*;
-import com.jogamp.opengl.util.texture.TextureCoords;
-import jogamp.opengl.Debug;
-
-import com.jogamp.opengl.*;
-import com.jogamp.opengl.awt.GLCanvas;
-import com.jogamp.opengl.glu.GLU;
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.font.*;
-import java.awt.geom.*;
-import java.nio.*;
-import java.text.CharacterIterator;
-import java.util.*;
-import java.util.List;
-
-// For debugging purposes
-
-
-/** Renders bitmapped Java 2D text into an OpenGL window with high
- performance, full Unicode support, and a simple API. Performs
- appropriate caching of text rendering results in an OpenGL texture
- internally to avoid repeated font rasterization. The caching is
- completely automatic, does not require any user intervention, and
- has no visible controls in the public API.
-
- Using the {@link TextRenderer TextRenderer} is simple. Add a
- "TextRenderer renderer;" field to your {@link
- com.jogamp.opengl.GLEventListener GLEventListener}. In your {@link
- com.jogamp.opengl.GLEventListener#init init} method, add:
-
-
- renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 36));
-
-
- In the {@link com.jogamp.opengl.GLEventListener#display display} method of your
- {@link com.jogamp.opengl.GLEventListener GLEventListener}, add:
-
- renderer.beginRendering(drawable.getWidth(), drawable.getHeight());
- // optionally set the color
- renderer.setColor(1.0f, 0.2f, 0.2f, 0.8f);
- renderer.draw("Text to draw", xPosition, yPosition);
- // ... more draw commands, color changes, etc.
- renderer.endRendering();
-
-
- Unless you are sharing textures and display lists between OpenGL
- contexts, you do not need to call the {@link #dispose dispose}
- method of the TextRenderer; the OpenGL resources it uses
- internally will be cleaned up automatically when the OpenGL
- context is destroyed.
-
- Note that the TextRenderer may cause the vertex and texture
- coordinate array buffer bindings to change, or to be unbound. This
- is important to note if you are using Vertex Buffer Objects (VBOs)
- in your application.
-
- Internally, the renderer uses a rectangle packing algorithm to
- pack both glyphs and full Strings' rendering results (which are
- variable size) onto a larger OpenGL texture. The internal backing
- store is maintained using a {@link
- com.jogamp.opengl.util.awt.TextureRenderer TextureRenderer}. A least
- recently used (LRU) algorithm is used to discard previously
- rendered strings; the specific algorithm is undefined, but is
- currently implemented by flushing unused Strings' rendering
- results every few hundred rendering cycles, where a rendering
- cycle is defined as a pair of calls to {@link #beginRendering
- beginRendering} / {@link #endRendering endRendering}.
-
- @author John Burkey
- @author Kenneth Russell
-*/
-public class TextRenderer {
- private static final boolean DEBUG;
-
- static {
- Debug.initSingleton();
- DEBUG = Debug.isPropertyDefined("jogl.debug.TextRenderer", true);
- }
-
- // These are occasionally useful for more in-depth debugging
- private static boolean DISABLE_GLYPH_CACHE = false;
- private static final boolean DRAW_BBOXES = false;
- static
- {
- String arg = System.getProperty("gov.nasa.worldwind.textrender.useglyphcache");
- if (arg != null && arg.toLowerCase().startsWith("f"))
- DISABLE_GLYPH_CACHE = true;
- }
-
- static final int kSize = 256;
-
- // Every certain number of render cycles, flush the strings which
- // haven't been used recently
- private static final int CYCLES_PER_FLUSH = 100;
-
- // The amount of vertical dead space on the backing store before we
- // force a compaction
- private static final float MAX_VERTICAL_FRAGMENTATION = 0.7f;
- static final int kQuadsPerBuffer = 100;
- static final int kCoordsPerVertVerts = 3;
- static final int kCoordsPerVertTex = 2;
- static final int kVertsPerQuad = 4;
- static final int kTotalBufferSizeVerts = kQuadsPerBuffer * kVertsPerQuad;
- static final int kTotalBufferSizeCoordsVerts = kQuadsPerBuffer * kVertsPerQuad * kCoordsPerVertVerts;
- static final int kTotalBufferSizeCoordsTex = kQuadsPerBuffer * kVertsPerQuad * kCoordsPerVertTex;
- static final int kTotalBufferSizeBytesVerts = kTotalBufferSizeCoordsVerts * 4;
- static final int kTotalBufferSizeBytesTex = kTotalBufferSizeCoordsTex * 4;
- static final int kSizeInBytes_OneVertices_VertexData = kCoordsPerVertVerts * 4;
- static final int kSizeInBytes_OneVertices_TexData = kCoordsPerVertTex * 4;
- private final Font font;
- private final boolean antialiased;
- private final boolean useFractionalMetrics;
-
- // Whether we're attempting to use automatic mipmap generation support
- private boolean mipmap;
- private RectanglePacker packer;
- private boolean haveMaxSize;
- private final RenderDelegate renderDelegate;
- private TextureRenderer cachedBackingStore;
- private Graphics2D cachedGraphics;
- private FontRenderContext cachedFontRenderContext;
- private final Map stringLocations = new HashMap();
- private final GlyphProducer mGlyphProducer;
-
- private int numRenderCycles;
-
- // Need to keep track of whether we're in a beginRendering() /
- // endRendering() cycle so we can re-enter the exact same state if
- // we have to reallocate the backing store
- private boolean inBeginEndPair;
- private boolean isOrthoMode;
- private int beginRenderingWidth;
- private int beginRenderingHeight;
- private boolean beginRenderingDepthTestDisabled;
-
- // For resetting the color after disposal of the old backing store
- private boolean haveCachedColor;
- private float cachedR;
- private float cachedG;
- private float cachedB;
- private float cachedA;
- private Color cachedColor;
- private boolean needToResetColor;
-
- // For debugging only
- private Frame dbgFrame;
-
- // Debugging purposes only
- private boolean debugged;
- Pipelined_QuadRenderer mPipelinedQuadRenderer;
-
- //emzic: added boolean flag
- private boolean useVertexArrays = true;
-
- //emzic: added boolean flag
- private boolean isExtensionAvailable_GL_VERSION_1_5;
- private boolean checkFor_isExtensionAvailable_GL_VERSION_1_5;
-
- // Whether GL_LINEAR filtering is enabled for the backing store
- private boolean smoothing = true;
-
- /** Creates a new TextRenderer with the given font, using no
- antialiasing or fractional metrics, and the default
- RenderDelegate. Equivalent to TextRenderer(font, false,
- false).
-
- @param font the font to render with
- */
- public TextRenderer(Font font) {
- this(font, false, false, null, false);
- }
-
- /** Creates a new TextRenderer with the given font, using no
- antialiasing or fractional metrics, and the default
- RenderDelegate. If mipmap is true, attempts to use
- OpenGL's automatic mipmap generation for better smoothing when
- rendering the TextureRenderer's contents at a distance.
- Equivalent to TextRenderer(font, false, false).
-
- @param font the font to render with
- @param mipmap whether to attempt use of automatic mipmap generation
- */
- public TextRenderer(Font font, boolean mipmap) {
- this(font, false, false, null, mipmap);
- }
-
- /** Creates a new TextRenderer with the given Font, specified font
- properties, and default RenderDelegate. The
- antialiased and useFractionalMetrics
- flags provide control over the same properties at the Java 2D
- level. No mipmap support is requested. Equivalent to
- TextRenderer(font, antialiased, useFractionalMetrics,
- null).
-
- @param font the font to render with
- @param antialiased whether to use antialiased fonts
- @param useFractionalMetrics whether to use fractional font
- metrics at the Java 2D level
- */
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics) {
- this(font, antialiased, useFractionalMetrics, null, false);
- }
-
- /** Creates a new TextRenderer with the given Font, specified font
- properties, and given RenderDelegate. The
- antialiased and useFractionalMetrics
- flags provide control over the same properties at the Java 2D
- level. The renderDelegate provides more control
- over the text rendered. No mipmap support is requested.
-
- @param font the font to render with
- @param antialiased whether to use antialiased fonts
- @param useFractionalMetrics whether to use fractional font
- metrics at the Java 2D level
- @param renderDelegate the render delegate to use to draw the
- text's bitmap, or null to use the default one
- */
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics, RenderDelegate renderDelegate) {
- this(font, antialiased, useFractionalMetrics, renderDelegate, false);
- }
-
- /** Creates a new TextRenderer with the given Font, specified font
- properties, and given RenderDelegate. The
- antialiased and useFractionalMetrics
- flags provide control over the same properties at the Java 2D
- level. The renderDelegate provides more control
- over the text rendered. If mipmap is true, attempts
- to use OpenGL's automatic mipmap generation for better smoothing
- when rendering the TextureRenderer's contents at a distance.
-
- @param font the font to render with
- @param antialiased whether to use antialiased fonts
- @param useFractionalMetrics whether to use fractional font
- metrics at the Java 2D level
- @param renderDelegate the render delegate to use to draw the
- text's bitmap, or null to use the default one
- @param mipmap whether to attempt use of automatic mipmap generation
- */
- public TextRenderer(Font font, boolean antialiased,
- boolean useFractionalMetrics, RenderDelegate renderDelegate,
- boolean mipmap) {
- this.font = font;
- this.antialiased = antialiased;
- this.useFractionalMetrics = useFractionalMetrics;
- this.mipmap = mipmap;
-
- // FIXME: consider adjusting the size based on font size
- // (it will already automatically resize if necessary)
- packer = new RectanglePacker(new Manager(), kSize, kSize);
-
- if (renderDelegate == null) {
- renderDelegate = new DefaultRenderDelegate();
- }
-
- this.renderDelegate = renderDelegate;
-
- mGlyphProducer = new GlyphProducer(font.getNumGlyphs());
- }
-
- /**
- * Returns the bounding rectangle of the given String, assuming it was rendered at the origin.See
- * {@link #getBounds(CharSequence) getBounds(CharSequence)}.
- *
- * @param str The string.
- * @return The bounding rectangle for str.
- */
- public Rectangle2D getBounds(String str) {
- return getBounds((CharSequence) str);
- }
-
- /**
- * Returns the bounding rectangle of the given CharSequence, assuming it was rendered at the origin.The coordinate
- * system of the returned rectangle is Java 2D's, with increasing Y coordinates in the downward direction.The
- * relative coordinate (0, 0) in the returned rectangle corresponds to the baseline of the leftmost character of the
- * rendered string, in similar fashion to the results returned by, for example,
- * {@link java.awt.font.GlyphVector#getVisualBounds}. Most applications will use only the width and height of the
- * returned Rectangle for the purposes of centering or justifying the String. It is not specified which Java 2D
- * bounds ({@link
- * java.awt.font.GlyphVector#getVisualBounds getVisualBounds},
- * {@link java.awt.font.GlyphVector#getPixelBounds getPixelBounds}, etc.) the returned bounds correspond to,
- * although every effort is made to ensure an accurate bound.
- *
- * @param str The string.
- * @return The bounds of the string.
- */
- public Rectangle2D getBounds(CharSequence str) {
- // FIXME: this should be more optimized and use the glyph cache
- Rect r = stringLocations.get(str);
-
- if (r != null) {
- TextData data = (TextData) r.getUserData();
-
- // Reconstitute the Java 2D results based on the cached values
- return new Rectangle2D.Double(-data.origin().x, -data.origin().y,
- r.w(), r.h());
- }
-
- // Must return a Rectangle compatible with the layout algorithm --
- // must be idempotent
- return normalize(renderDelegate.getBounds(str, font,
- getFontRenderContext()));
- }
-
- /**
- * Returns the Font this renderer is using.
- *
- * @return The Font.
- */
- public Font getFont() {
- return font;
- }
-
- /**
- * * Returns a FontRenderContext which can be used for external text-related size computations.This object should be
- * considered transient and may become invalidated between
- * {@link #beginRendering beginRendering} / {@link #endRendering endRendering} pairs.
- *
- * @return A FontRenderContext.
- */
- public FontRenderContext getFontRenderContext() {
- if (cachedFontRenderContext == null) {
- cachedFontRenderContext = getGraphics2D().getFontRenderContext();
- }
-
- return cachedFontRenderContext;
- }
-
- /** Begins rendering with this {@link TextRenderer TextRenderer}
- into the current OpenGL drawable, pushing the projection and
- modelview matrices and some state bits and setting up a
- two-dimensional orthographic projection with (0, 0) as the
- lower-left coordinate and (width, height) as the upper-right
- coordinate. Binds and enables the internal OpenGL texture
- object, sets the texture environment mode to GL_MODULATE, and
- changes the current color to the last color set with this
- TextRenderer via {@link #setColor setColor}. This method
- disables the depth test and is equivalent to
- beginRendering(width, height, true).
-
- @param width the width of the current on-screen OpenGL drawable
- @param height the height of the current on-screen OpenGL drawable
- @throws com.jogamp.opengl.GLException If an OpenGL context is not current when this method is called
- */
- public void beginRendering(int width, int height) throws GLException {
- beginRendering(width, height, true);
- }
-
- /** Begins rendering with this {@link TextRenderer TextRenderer}
- into the current OpenGL drawable, pushing the projection and
- modelview matrices and some state bits and setting up a
- two-dimensional orthographic projection with (0, 0) as the
- lower-left coordinate and (width, height) as the upper-right
- coordinate. Binds and enables the internal OpenGL texture
- object, sets the texture environment mode to GL_MODULATE, and
- changes the current color to the last color set with this
- TextRenderer via {@link #setColor setColor}. Disables the depth
- test if the disableDepthTest argument is true.
-
- @param width the width of the current on-screen OpenGL drawable
- @param height the height of the current on-screen OpenGL drawable
- @param disableDepthTest whether to disable the depth test
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void beginRendering(int width, int height, boolean disableDepthTest)
- throws GLException {
- beginRendering(true, width, height, disableDepthTest);
- }
-
- /** Begins rendering of 2D text in 3D with this {@link TextRenderer
- TextRenderer} into the current OpenGL drawable. Assumes the end
- user is responsible for setting up the modelview and projection
- matrices, and will render text using the {@link #draw3D draw3D}
- method. This method pushes some OpenGL state bits, binds and
- enables the internal OpenGL texture object, sets the texture
- environment mode to GL_MODULATE, and changes the current color
- to the last color set with this TextRenderer via {@link
- #setColor setColor}.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void begin3DRendering() throws GLException {
- beginRendering(false, 0, 0, false);
- }
-
- /** Changes the current color of this TextRenderer to the supplied
- one. The default color is opaque white.
-
- @param color the new color to use for rendering text
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void setColor(Color color) throws GLException {
- boolean noNeedForFlush = (haveCachedColor && (cachedColor != null) &&
- color.equals(cachedColor));
-
- if (!noNeedForFlush) {
- flushGlyphPipeline();
- }
-
- getBackingStore().setColor(color);
- haveCachedColor = true;
- cachedColor = color;
- }
-
- /** Changes the current color of this TextRenderer to the supplied
- one, where each component ranges from 0.0f - 1.0f. The alpha
- component, if used, does not need to be premultiplied into the
- color channels as described in the documentation for {@link
- com.jogamp.opengl.util.texture.Texture Texture}, although
- premultiplied colors are used internally. The default color is
- opaque white.
-
- @param r the red component of the new color
- @param g the green component of the new color
- @param b the blue component of the new color
- @param a the alpha component of the new color, 0.0f = completely
- transparent, 1.0f = completely opaque
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void setColor(float r, float g, float b, float a)
- throws GLException {
- boolean noNeedForFlush = (haveCachedColor && (cachedColor == null) &&
- (r == cachedR) && (g == cachedG) && (b == cachedB) &&
- (a == cachedA));
-
- if (!noNeedForFlush) {
- flushGlyphPipeline();
- }
-
- getBackingStore().setColor(r, g, b, a);
- haveCachedColor = true;
- cachedR = r;
- cachedG = g;
- cachedB = b;
- cachedA = a;
- cachedColor = null;
- }
-
- /** Draws the supplied CharSequence at the desired location using
- the renderer's current color. The baseline of the leftmost
- character is at position (x, y) specified in OpenGL coordinates,
- where the origin is at the lower-left of the drawable and the Y
- coordinate increases in the upward direction.
-
- @param str the string to draw
- @param x the x coordinate at which to draw
- @param y the y coordinate at which to draw
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void draw(CharSequence str, int x, int y) throws GLException {
- draw3D(str, x, y, 0, 1);
- }
-
- /**
- * * Draws the supplied String at the desired location using the renderer's current color.See
- * {@link #draw(CharSequence, int, int) draw(CharSequence, int, int)}.
- *
- * @param str The string to draw.
- * @param x The desired x location.
- * @param y The desired y location.
- */
- public void draw(String str, int x, int y) throws GLException {
- draw3D(str, x, y, 0, 1);
- }
-
- /** Draws the supplied CharSequence at the desired 3D location using
- the renderer's current color. The baseline of the leftmost
- character is placed at position (x, y, z) in the current
- coordinate system.
-
- @param str the string to draw
- @param x the x coordinate at which to draw
- @param y the y coordinate at which to draw
- @param z the z coordinate at which to draw
- @param scaleFactor a uniform scale factor applied to the width and height of the drawn rectangle
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void draw3D(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- internal_draw3D(str, x, y, z, scaleFactor);
- }
-
- /**
- * * Draws the supplied String at the desired 3D location using the renderer's current color.See {@link #draw3D(CharSequence, float, float, float, float) draw3D(CharSequence, float, float,
- * float, float)}.
- *
- * @param str The string to draw.
- * @param x The x location.
- * @param y The y location.
- * @param z The z location.
- * @param scaleFactor The scale factor.
- */
- public void draw3D(String str, float x, float y, float z, float scaleFactor) {
- internal_draw3D(str, x, y, z, scaleFactor);
- }
-
- /**
- * Returns the pixel width of the given character.
- *
- * @param inChar The character to measure.
- * @return The pixel width.
- */
- public float getCharWidth(char inChar) {
- return mGlyphProducer.getGlyphPixelWidth(inChar);
- }
-
- /** Causes the TextRenderer to flush any internal caches it may be
- maintaining and draw its rendering results to the screen. This
- should be called after each call to draw() if you are setting
- OpenGL state such as the modelview matrix between calls to
- draw(). */
- public void flush() {
- flushGlyphPipeline();
- }
-
- /** Ends a render cycle with this {@link TextRenderer TextRenderer}.
- Restores the projection and modelview matrices as well as
- several OpenGL state bits. Should be paired with {@link
- #beginRendering beginRendering}.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void endRendering() throws GLException {
- endRendering(true);
- }
-
- /** Ends a 3D render cycle with this {@link TextRenderer TextRenderer}.
- Restores several OpenGL state bits. Should be paired with {@link
- #begin3DRendering begin3DRendering}.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void end3DRendering() throws GLException {
- endRendering(false);
- }
-
- /** Disposes of all resources this TextRenderer is using. It is not
- valid to use the TextRenderer after this method is called.
-
- @throws GLException If an OpenGL context is not current when this method is called
- */
- public void dispose() throws GLException {
- packer.dispose();
- packer = null;
- cachedBackingStore = null;
- cachedGraphics = null;
- cachedFontRenderContext = null;
-
- if (dbgFrame != null) {
- dbgFrame.dispose();
- }
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- private static Rectangle2D preNormalize(Rectangle2D src) {
- // Need to round to integer coordinates
- // Also give ourselves a little slop around the reported
- // bounds of glyphs because it looks like neither the visual
- // nor the pixel bounds works perfectly well
- int minX = (int) Math.floor(src.getMinX()) - 1;
- int minY = (int) Math.floor(src.getMinY()) - 1;
- int maxX = (int) Math.ceil(src.getMaxX()) + 1;
- int maxY = (int) Math.ceil(src.getMaxY()) + 1;
- return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
- }
-
-
- private Rectangle2D normalize(Rectangle2D src) {
- // Give ourselves a boundary around each entity on the backing
- // store in order to prevent bleeding of nearby Strings due to
- // the fact that we use linear filtering
-
- // NOTE that this boundary is quite heuristic and is related
- // to how far away in 3D we may view the text --
- // heuristically, 1.5% of the font's height
- int boundary = (int) Math.max(1, 0.015 * font.getSize());
-
- return new Rectangle2D.Double((int) Math.floor(src.getMinX() - boundary),
- (int) Math.floor(src.getMinY() - boundary),
- (int) Math.ceil(src.getWidth() + 2 * boundary),
- (int) Math.ceil(src.getHeight()) + 2 * boundary);
- }
-
- private TextureRenderer getBackingStore() {
- TextureRenderer renderer = (TextureRenderer) packer.getBackingStore();
-
- if (renderer != cachedBackingStore) {
- // Backing store changed since last time; discard any cached Graphics2D
- if (cachedGraphics != null) {
- cachedGraphics.dispose();
- cachedGraphics = null;
- cachedFontRenderContext = null;
- }
-
- cachedBackingStore = renderer;
- }
-
- return cachedBackingStore;
- }
-
- private Graphics2D getGraphics2D() {
- TextureRenderer renderer = getBackingStore();
-
- if (cachedGraphics == null) {
- cachedGraphics = renderer.createGraphics();
-
- // Set up composite, font and rendering hints
- cachedGraphics.setComposite(AlphaComposite.Src);
- cachedGraphics.setColor(Color.WHITE);
- cachedGraphics.setFont(font);
- cachedGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
- (antialiased ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON
- : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF));
- cachedGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
- (useFractionalMetrics
- ? RenderingHints.VALUE_FRACTIONALMETRICS_ON
- : RenderingHints.VALUE_FRACTIONALMETRICS_OFF));
- }
-
- return cachedGraphics;
- }
-
- private void beginRendering(boolean ortho, int width, int height,
- boolean disableDepthTestForOrtho) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- if (DEBUG && !debugged) {
- debug(gl);
- }
-
- inBeginEndPair = true;
- isOrthoMode = ortho;
- beginRenderingWidth = width;
- beginRenderingHeight = height;
- beginRenderingDepthTestDisabled = disableDepthTestForOrtho;
-
- if (ortho) {
- getBackingStore().beginOrthoRendering(width, height,
- disableDepthTestForOrtho);
- } else {
- getBackingStore().begin3DRendering();
- }
-
- // Push client attrib bits used by the pipelined quad renderer
- gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS);
-
- if (!haveMaxSize) {
- // Query OpenGL for the maximum texture size and set it in the
- // RectanglePacker to keep it from expanding too large
- int[] sz = new int[1];
- gl.glGetIntegerv(GL2.GL_MAX_TEXTURE_SIZE, sz, 0);
- packer.setMaxSize(sz[0], sz[0]);
- haveMaxSize = true;
- }
-
- if (needToResetColor && haveCachedColor) {
- if (cachedColor == null) {
- getBackingStore().setColor(cachedR, cachedG, cachedB, cachedA);
- } else {
- getBackingStore().setColor(cachedColor);
- }
-
- needToResetColor = false;
- }
-
- // Disable future attempts to use mipmapping if TextureRenderer
- // doesn't support it
- if (mipmap && !getBackingStore().isUsingAutoMipmapGeneration()) {
- if (DEBUG) {
- System.err.println("Disabled mipmapping in TextRenderer");
- }
-
- mipmap = false;
- }
- }
-
- /**
- * emzic: here the call to glBindBuffer crashes on certain graphicscard/driver combinations
- * this is why the ugly try-catch block has been added, which falls back to the old textrenderer
- *
- * @param ortho
- * @throws GLException
- */
- private void endRendering(boolean ortho) throws GLException {
- flushGlyphPipeline();
-
- inBeginEndPair = false;
-
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- // Pop client attrib bits used by the pipelined quad renderer
- gl.glPopClientAttrib();
-
- // The OpenGL spec is unclear about whether this changes the
- // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER
- // binding
- if (getUseVertexArrays() && is15Available(gl)) {
- try {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- } catch (Exception e) {
- isExtensionAvailable_GL_VERSION_1_5 = false;
- }
- }
-
- if (ortho) {
- getBackingStore().endOrthoRendering();
- } else {
- getBackingStore().end3DRendering();
- }
-
- if (++numRenderCycles >= CYCLES_PER_FLUSH) {
- numRenderCycles = 0;
-
- if (DEBUG) {
- System.err.println("Clearing unused entries in endRendering()");
- }
-
- clearUnusedEntries();
- }
- }
-
- private void clearUnusedEntries() {
- final java.util.List deadRects = new ArrayList();
-
- // Iterate through the contents of the backing store, removing
- // text strings that haven't been used recently
- packer.visit(new RectVisitor() {
- @Override
- public void visit(Rect rect) {
- TextData data = (TextData) rect.getUserData();
-
- if (data.used()) {
- data.clearUsed();
- } else {
- deadRects.add(rect);
- }
- }
- });
-
- for (Rect r : deadRects) {
- packer.remove(r);
- stringLocations.remove(((TextData) r.getUserData()).string());
-
- int unicodeToClearFromCache = ((TextData) r.getUserData()).unicodeID;
-
- if (unicodeToClearFromCache > 0) {
- mGlyphProducer.clearCacheEntry(unicodeToClearFromCache);
- }
-
- // if (DEBUG) {
- // Graphics2D g = getGraphics2D();
- // g.setComposite(AlphaComposite.Clear);
- // g.fillRect(r.x(), r.y(), r.w(), r.h());
- // g.setComposite(AlphaComposite.Src);
- // }
- }
-
- // If we removed dead rectangles this cycle, try to do a compaction
- float frag = packer.verticalFragmentationRatio();
-
- if (!deadRects.isEmpty() && (frag > MAX_VERTICAL_FRAGMENTATION)) {
- if (DEBUG) {
- System.err.println(
- "Compacting TextRenderer backing store due to vertical fragmentation " +
- frag);
- }
-
- packer.compact();
- }
-
- if (DEBUG) {
- getBackingStore().markDirty(0, 0, getBackingStore().getWidth(),
- getBackingStore().getHeight());
- }
- }
-
- private void internal_draw3D(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- for (Glyph glyph : mGlyphProducer.getGlyphs(str)) {
- float advance = glyph.draw3D(x, y, z, scaleFactor);
- x += advance * scaleFactor;
- }
- }
-
- private void flushGlyphPipeline() {
- if (mPipelinedQuadRenderer != null) {
- mPipelinedQuadRenderer.draw();
- }
- }
-
- private void draw3D_ROBUST(CharSequence str, float x, float y, float z,
- float scaleFactor) {
- String curStr;
- if (str instanceof String) {
- curStr = (String) str;
- } else {
- curStr = str.toString();
- }
-
- // Look up the string on the backing store
- Rect rect = stringLocations.get(curStr);
-
- if (rect == null) {
- // Rasterize this string and place it on the backing store
- Graphics2D g = getGraphics2D();
- Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(curStr, font, getFontRenderContext()));
- Rectangle2D bbox = normalize(origBBox);
- Point origin = new Point((int) -bbox.getMinX(),
- (int) -bbox.getMinY());
- rect = new Rect(0, 0, (int) bbox.getWidth(),
- (int) bbox.getHeight(),
- new TextData(curStr, origin, origBBox, -1));
-
- packer.add(rect);
- stringLocations.put(curStr, rect);
-
- // Re-fetch the Graphics2D in case the addition of the rectangle
- // caused the old backing store to be thrown away
- g = getGraphics2D();
-
- // OK, should now have an (x, y) for this rectangle; rasterize
- // the String
- int strx = rect.x() + origin.x;
- int stry = rect.y() + origin.y;
-
- // Clear out the area we're going to draw into
- g.setComposite(AlphaComposite.Clear);
- g.fillRect(rect.x(), rect.y(), rect.w(), rect.h());
- g.setComposite(AlphaComposite.Src);
-
- // Draw the string
- renderDelegate.draw(g, curStr, strx, stry);
-
- if (DRAW_BBOXES) {
- TextData data = (TextData) rect.getUserData();
- // Draw a bounding box on the backing store
- g.drawRect(strx - data.origOriginX(),
- stry - data.origOriginY(),
- (int) data.origRect().getWidth(),
- (int) data.origRect().getHeight());
- g.drawRect(strx - data.origin().x,
- stry - data.origin().y,
- rect.w(),
- rect.h());
- }
-
- // Mark this region of the TextureRenderer as dirty
- getBackingStore().markDirty(rect.x(), rect.y(), rect.w(),
- rect.h());
- }
-
- // OK, now draw the portion of the backing store to the screen
- TextureRenderer renderer = getBackingStore();
-
- // NOTE that the rectangles managed by the packer have their
- // origin at the upper-left but the TextureRenderer's origin is
- // at its lower left!!!
- TextData data = (TextData) rect.getUserData();
- data.markUsed();
-
- Rectangle2D origRect = data.origRect();
-
- // Align the leftmost point of the baseline to the (x, y, z) coordinate requested
- renderer.draw3DRect(x - (scaleFactor * data.origOriginX()),
- y - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY())), z,
- rect.x() + (data.origin().x - data.origOriginX()),
- renderer.getHeight() - rect.y() - (int) origRect.getHeight() -
- (data.origin().y - data.origOriginY()),
- (int) origRect.getWidth(), (int) origRect.getHeight(), scaleFactor);
- }
-
- //----------------------------------------------------------------------
- // Debugging functionality
- //
- private void debug(GL gl) {
- dbgFrame = new Frame("TextRenderer Debug Output");
-
- GLCanvas dbgCanvas = new GLCanvas(new GLCapabilities(gl.getGLProfile()));
- dbgCanvas.setSharedContext(GLContext.getCurrent());
- dbgCanvas.addGLEventListener(new DebugListener(gl, dbgFrame));
- dbgFrame.add(dbgCanvas);
-
- final FPSAnimator anim = new FPSAnimator(dbgCanvas, 10);
- dbgFrame.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- // Run this on another thread than the AWT event queue to
- // make sure the call to Animator.stop() completes before
- // exiting
- new Thread(new Runnable() {
- @Override
- public void run() {
- anim.stop();
- }
- }).start();
- }
- });
- dbgFrame.setSize(kSize, kSize);
- dbgFrame.setVisible(true);
- anim.start();
- debugged = true;
- }
-
- /** Class supporting more full control over the process of rendering
- the bitmapped text. Allows customization of whether the backing
- store text bitmap is full-color or intensity only, the size of
- each individual rendered text rectangle, and the contents of
- each individual rendered text string. The default implementation
- of this interface uses an intensity-only texture, a
- closely-cropped rectangle around the text, and renders text
- using the color white, which is modulated by the set color
- during the rendering process. */
- public static interface RenderDelegate {
- /**
- * Indicates whether the backing store of this TextRenderer should be intensity-only (the default) or
- * full-color.
- *
- * @return whether or not intensity only is on.
- */
- public boolean intensityOnly();
-
- /**
- * Computes the bounds of the given String relative to the origin.
- *
- * @param str The string to process.
- * @param font The font to use.
- * @param frc The render context to use.
- * @return The bounds given the parameters.
- */
- public Rectangle2D getBounds(String str, Font font,
- FontRenderContext frc);
-
- /**
- * Computes the bounds of the given character sequence relative to the origin.
- *
- * @param str The string to process.
- * @param font The font to use.
- * @param frc The render context to use.
- * @return The bounds given the parameters.
- */
- public Rectangle2D getBounds(CharSequence str, Font font,
- FontRenderContext frc);
-
- /**
- * Computes the bounds of the given GlyphVector, already assumed to have been created for a particular Font,
- * relative to the origin.
- *
- * @param gv The string to process.
- * @param frc The render context to use.
- * @return The bounds given the parameters.
- */
- public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc);
-
- /**
- * * Render the passed character sequence at the designated location using the supplied Graphics2D instance.The
- * surrounding region will already have been cleared to the RGB color (0, 0, 0) with zero alpha.The initial
- * drawing context of the passed Graphics2D will be set to use AlphaComposite.Src, the color white, the Font
- * specified in the TextRenderer's constructor, and the rendering hints specified in the TextRenderer
- * constructor.Changes made by the end user may be visible in successive calls to this method, but are not
- * guaranteed to be preserved.Implementors of this method should reset the Graphics2D's state to that desired
- * each time this method is called, in particular those states which are not the defaults.
- *
- * @param graphics The canvas to draw on.
- * @param str The string to draw.
- * @param x The x location.
- * @param y The y location.
- */
- public void draw(Graphics2D graphics, String str, int x, int y);
-
- /**
- * * Render the passed GlyphVector at the designated location using the supplied Graphics2D instance.The
- * surrounding region will already have been cleared to the RGB color (0, 0, 0) with zero alpha.The initial
- * drawing context of the passed Graphics2D will be set to use AlphaComposite.Src, the color white, the Font
- * specified in the TextRenderer's constructor, and the rendering hints specified in the TextRenderer
- * constructor.Changes made by the end user may be visible in successive calls to this method, but are not
- * guaranteed to be preserved.Implementors of this method should reset the Graphics2D's state to that desired
- * each time this method is called, in particular those states which are not the defaults.
- *
- * @param graphics The canvas to draw on.
- * @param str The string to draw.
- * @param x The x location.
- * @param y The y location.
- */
- public void drawGlyphVector(Graphics2D graphics, GlyphVector str,
- int x, int y);
- }
-
- private static class CharSequenceIterator implements CharacterIterator {
- CharSequence mSequence;
- int mLength;
- int mCurrentIndex;
-
- CharSequenceIterator() {
- }
-
- CharSequenceIterator(CharSequence sequence) {
- initFromCharSequence(sequence);
- }
-
- public void initFromCharSequence(CharSequence sequence) {
- mSequence = sequence;
- mLength = mSequence.length();
- mCurrentIndex = 0;
- }
-
- @Override
- public char last() {
- mCurrentIndex = Math.max(0, mLength - 1);
-
- return current();
- }
-
- @Override
- public char current() {
- if ((mLength == 0) || (mCurrentIndex >= mLength)) {
- return CharacterIterator.DONE;
- }
-
- return mSequence.charAt(mCurrentIndex);
- }
-
- @Override
- public char next() {
- mCurrentIndex++;
-
- return current();
- }
-
- @Override
- public char previous() {
- mCurrentIndex = Math.max(mCurrentIndex - 1, 0);
-
- return current();
- }
-
- @Override
- public char setIndex(int position) {
- mCurrentIndex = position;
-
- return current();
- }
-
- @Override
- public int getBeginIndex() {
- return 0;
- }
-
- @Override
- public int getEndIndex() {
- return mLength;
- }
-
- @Override
- public int getIndex() {
- return mCurrentIndex;
- }
-
- @Override
- public Object clone() {
- CharSequenceIterator iter = new CharSequenceIterator(mSequence);
- iter.mCurrentIndex = mCurrentIndex;
-
- return iter;
- }
-
- @Override
- public char first() {
- if (mLength == 0) {
- return CharacterIterator.DONE;
- }
-
- mCurrentIndex = 0;
-
- return current();
- }
- }
-
- // Data associated with each rectangle of text
- static class TextData {
- // Back-pointer to String this TextData describes, if it
- // represents a String rather than a single glyph
- private final String str;
-
- // If this TextData represents a single glyph, this is its
- // unicode ID
- int unicodeID;
-
- // The following must be defined and used VERY precisely. This is
- // the offset from the upper-left corner of this rectangle (Java
- // 2D coordinate system) at which the string must be rasterized in
- // order to fit within the rectangle -- the leftmost point of the
- // baseline.
- private final Point origin;
-
- // This represents the pre-normalized rectangle, which fits
- // within the rectangle on the backing store. We keep a
- // one-pixel border around entries on the backing store to
- // prevent bleeding of adjacent letters when using GL_LINEAR
- // filtering for rendering. The origin of this rectangle is
- // equivalent to the origin above.
- private final Rectangle2D origRect;
-
- private boolean used; // Whether this text was used recently
-
- TextData(String str, Point origin, Rectangle2D origRect, int unicodeID) {
- this.str = str;
- this.origin = origin;
- this.origRect = origRect;
- this.unicodeID = unicodeID;
- }
-
- String string() {
- return str;
- }
-
- Point origin() {
- return origin;
- }
-
- // The following three methods are used to locate the glyph
- // within the expanded rectangle coming from normalize()
- int origOriginX() {
- return (int) -origRect.getMinX();
- }
-
- int origOriginY() {
- return (int) -origRect.getMinY();
- }
-
- Rectangle2D origRect() {
- return origRect;
- }
-
- boolean used() {
- return used;
- }
-
- void markUsed() {
- used = true;
- }
-
- void clearUsed() {
- used = false;
- }
- }
-
- class Manager implements BackingStoreManager {
- private Graphics2D g;
-
- @Override
- public Object allocateBackingStore(int w, int h) {
- // FIXME: should consider checking Font's attributes to see
- // whether we're likely to need to support a full RGBA backing
- // store (i.e., non-default Paint, foreground color, etc.), but
- // for now, let's just be more efficient
- TextureRenderer renderer;
-
- if (renderDelegate.intensityOnly()) {
- renderer = TextureRenderer.createAlphaOnlyRenderer(w, h, mipmap);
- } else {
- renderer = new TextureRenderer(w, h, true, mipmap);
- }
- renderer.setSmoothing(smoothing);
-
- if (DEBUG) {
- System.err.println(" TextRenderer allocating backing store " +
- w + " x " + h);
- }
-
- return renderer;
- }
-
- @Override
- public void deleteBackingStore(Object backingStore) {
- ((TextureRenderer) backingStore).dispose();
- }
-
- @Override
- public boolean preExpand(Rect cause, int attemptNumber) {
- // Only try this one time; clear out potentially obsolete entries
- // NOTE: this heuristic and the fact that it clears the used bit
- // of all entries seems to cause cycling of entries in some
- // situations, where the backing store becomes small compared to
- // the amount of text on the screen (see the TextFlow demo) and
- // the entries continually cycle in and out of the backing
- // store, decreasing performance. If we added a little age
- // information to the entries, and only cleared out entries
- // above a certain age, this behavior would be eliminated.
- // However, it seems the system usually stabilizes itself, so
- // for now we'll just keep things simple. Note that if we don't
- // clear the used bit here, the backing store tends to increase
- // very quickly to its maximum size, at least with the TextFlow
- // demo when the text is being continually re-laid out.
- if (attemptNumber == 0) {
- if (DEBUG) {
- System.err.println(
- "Clearing unused entries in preExpand(): attempt number " +
- attemptNumber);
- }
-
- if (inBeginEndPair) {
- // Draw any outstanding glyphs
- flush();
- }
-
- clearUnusedEntries();
-
- return true;
- }
-
- return false;
- }
-
- @Override
- public boolean additionFailed(Rect cause, int attemptNumber) {
- // Heavy hammer -- might consider doing something different
- packer.clear();
- stringLocations.clear();
- mGlyphProducer.clearAllCacheEntries();
-
- if (DEBUG) {
- System.err.println(
- " *** Cleared all text because addition failed ***");
- }
-
- if (attemptNumber == 0) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public boolean canCompact() {
- return true;
- }
-
- @Override
- public void beginMovement(Object oldBackingStore, Object newBackingStore) {
- // Exit the begin / end pair if necessary
- if (inBeginEndPair) {
- // Draw any outstanding glyphs
- flush();
-
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- // Pop client attrib bits used by the pipelined quad renderer
- gl.glPopClientAttrib();
-
- // The OpenGL spec is unclear about whether this changes the
- // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER
- // binding
- if (getUseVertexArrays() && is15Available(gl)) {
- try {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
- } catch (Exception e) {
- isExtensionAvailable_GL_VERSION_1_5 = false;
- }
- }
-
- if (isOrthoMode) {
- ((TextureRenderer) oldBackingStore).endOrthoRendering();
- } else {
- ((TextureRenderer) oldBackingStore).end3DRendering();
- }
- }
-
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
- g = newRenderer.createGraphics();
- }
-
- @Override
- public void move(Object oldBackingStore, Rect oldLocation,
- Object newBackingStore, Rect newLocation) {
- TextureRenderer oldRenderer = (TextureRenderer) oldBackingStore;
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
-
- if (oldRenderer == newRenderer) {
- // Movement on the same backing store -- easy case
- g.copyArea(oldLocation.x(), oldLocation.y(), oldLocation.w(),
- oldLocation.h(), newLocation.x() - oldLocation.x(),
- newLocation.y() - oldLocation.y());
- } else {
- // Need to draw from the old renderer's image into the new one
- Image img = oldRenderer.getImage();
- g.drawImage(img, newLocation.x(), newLocation.y(),
- newLocation.x() + newLocation.w(),
- newLocation.y() + newLocation.h(), oldLocation.x(),
- oldLocation.y(), oldLocation.x() + oldLocation.w(),
- oldLocation.y() + oldLocation.h(), null);
- }
- }
-
- @Override
- public void endMovement(Object oldBackingStore, Object newBackingStore) {
- g.dispose();
-
- // Sync the whole surface
- TextureRenderer newRenderer = (TextureRenderer) newBackingStore;
- newRenderer.markDirty(0, 0, newRenderer.getWidth(),
- newRenderer.getHeight());
-
- // Re-enter the begin / end pair if necessary
- if (inBeginEndPair) {
- if (isOrthoMode) {
- ((TextureRenderer) newBackingStore).beginOrthoRendering(beginRenderingWidth,
- beginRenderingHeight, beginRenderingDepthTestDisabled);
- } else {
- ((TextureRenderer) newBackingStore).begin3DRendering();
- }
-
- // Push client attrib bits used by the pipelined quad renderer
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS);
-
- if (haveCachedColor) {
- if (cachedColor == null) {
- ((TextureRenderer) newBackingStore).setColor(cachedR,
- cachedG, cachedB, cachedA);
- } else {
- ((TextureRenderer) newBackingStore).setColor(cachedColor);
- }
- }
- } else {
- needToResetColor = true;
- }
- }
- }
-
- public static class DefaultRenderDelegate implements RenderDelegate {
- @Override
- public boolean intensityOnly() {
- return true;
- }
-
- @Override
- public Rectangle2D getBounds(CharSequence str, Font font,
- FontRenderContext frc) {
- return getBounds(font.createGlyphVector(frc,
- new CharSequenceIterator(str)),
- frc);
- }
-
- @Override
- public Rectangle2D getBounds(String str, Font font,
- FontRenderContext frc) {
- return getBounds(font.createGlyphVector(frc, str), frc);
- }
-
- @Override
- public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc) {
- return gv.getVisualBounds();
- }
-
- @Override
- public void drawGlyphVector(Graphics2D graphics, GlyphVector str,
- int x, int y) {
- graphics.drawGlyphVector(str, x, y);
- }
-
- @Override
- public void draw(Graphics2D graphics, String str, int x, int y) {
- graphics.drawString(str, x, y);
- }
- }
-
- //----------------------------------------------------------------------
- // Glyph-by-glyph rendering support
- //
-
- // A temporary to prevent excessive garbage creation
- private final char[] singleUnicode = new char[1];
-
- /** A Glyph represents either a single unicode glyph or a
- substring of characters to be drawn. The reason for the dual
- behavior is so that we can take in a sequence of unicode
- characters and partition them into runs of individual glyphs,
- but if we encounter complex text and/or unicode sequences we
- don't understand, we can render them using the
- string-by-string method.
-
- Glyphs need to be able to re-upload themselves to the backing
- store on demand as we go along in the render sequence.
- */
-
- class Glyph {
- // If this Glyph represents an individual unicode glyph, this
- // is its unicode ID. If it represents a String, this is -1.
- private int unicodeID;
- // If the above field isn't -1, then these fields are used.
- // The glyph code in the font
- private int glyphCode;
- // The GlyphProducer which created us
- private GlyphProducer producer;
- // The advance of this glyph
- private float advance;
- // The GlyphVector for this single character; this is passed
- // in during construction but cleared during the upload
- // process
- private GlyphVector singleUnicodeGlyphVector;
- // The rectangle of this glyph on the backing store, or null
- // if it has been cleared due to space pressure
- private Rect glyphRectForTextureMapping;
- // If this Glyph represents a String, this is the sequence of
- // characters
- private String str;
- // Whether we need a valid advance when rendering this string
- // (i.e., whether it has other single glyphs coming after it)
- private boolean needAdvance;
-
- // Creates a Glyph representing an individual Unicode character
- public Glyph(int unicodeID,
- int glyphCode,
- float advance,
- GlyphVector singleUnicodeGlyphVector,
- GlyphProducer producer) {
- this.unicodeID = unicodeID;
- this.glyphCode = glyphCode;
- this.advance = advance;
- this.singleUnicodeGlyphVector = singleUnicodeGlyphVector;
- this.producer = producer;
- }
-
- // Creates a Glyph representing a sequence of characters, with
- // an indication of whether additional single glyphs are being
- // rendered after it
- public Glyph(String str, boolean needAdvance) {
- this.str = str;
- this.needAdvance = needAdvance;
- }
-
- /** Returns this glyph's unicode ID */
- public int getUnicodeID() {
- return unicodeID;
- }
-
- /** Returns this glyph's (font-specific) glyph code */
- public int getGlyphCode() {
- return glyphCode;
- }
-
- /** Returns the advance for this glyph */
- public float getAdvance() {
- return advance;
- }
-
- /** Draws this glyph and returns the (x) advance for this glyph */
- public float draw3D(float inX, float inY, float z, float scaleFactor) {
- if (str != null) {
- draw3D_ROBUST(str, inX, inY, z, scaleFactor);
- if (!needAdvance) {
- return 0;
- }
- // Compute and return the advance for this string
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), str);
- float totalAdvance = 0;
- for (int i = 0; i < gv.getNumGlyphs(); i++) {
- totalAdvance += gv.getGlyphMetrics(i).getAdvance();
- }
- return totalAdvance;
- }
-
- // This is the code path taken for individual glyphs
- if (glyphRectForTextureMapping == null) {
- upload();
- }
-
- try {
- if (mPipelinedQuadRenderer == null) {
- mPipelinedQuadRenderer = new Pipelined_QuadRenderer();
- }
-
- TextureRenderer renderer = getBackingStore();
- // Handles case where NPOT texture is used for backing store
- TextureCoords wholeImageTexCoords = renderer.getTexture().getImageTexCoords();
- float xScale = wholeImageTexCoords.right();
- float yScale = wholeImageTexCoords.bottom();
-
- Rect rect = glyphRectForTextureMapping;
- TextData data = (TextData) rect.getUserData();
- data.markUsed();
-
- Rectangle2D origRect = data.origRect();
-
- float x = inX - (scaleFactor * data.origOriginX());
- float y = inY - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY()));
-
- int texturex = rect.x() + (data.origin().x - data.origOriginX());
- int texturey = renderer.getHeight() - rect.y() - (int) origRect.getHeight() -
- (data.origin().y - data.origOriginY());
- int width = (int) origRect.getWidth();
- int height = (int) origRect.getHeight();
-
- float tx1 = xScale * texturex / renderer.getWidth();
- float ty1 = yScale * (1.0f -
- ((float) texturey / (float) renderer.getHeight()));
- float tx2 = xScale * (texturex + width) / renderer.getWidth();
- float ty2 = yScale * (1.0f -
- ((float) (texturey + height) / (float) renderer.getHeight()));
-
- mPipelinedQuadRenderer.glTexCoord2f(tx1, ty1);
- mPipelinedQuadRenderer.glVertex3f(x, y, z);
- mPipelinedQuadRenderer.glTexCoord2f(tx2, ty1);
- mPipelinedQuadRenderer.glVertex3f(x + (width * scaleFactor), y,
- z);
- mPipelinedQuadRenderer.glTexCoord2f(tx2, ty2);
- mPipelinedQuadRenderer.glVertex3f(x + (width * scaleFactor),
- y + (height * scaleFactor), z);
- mPipelinedQuadRenderer.glTexCoord2f(tx1, ty2);
- mPipelinedQuadRenderer.glVertex3f(x,
- y + (height * scaleFactor), z);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return advance;
- }
-
- /** Notifies this glyph that it's been cleared out of the cache */
- public void clear() {
- glyphRectForTextureMapping = null;
- }
-
- private void upload() {
- GlyphVector gv = getGlyphVector();
- Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(gv, getFontRenderContext()));
- Rectangle2D bbox = normalize(origBBox);
- Point origin = new Point((int) -bbox.getMinX(),
- (int) -bbox.getMinY());
- Rect rect = new Rect(0, 0, (int) bbox.getWidth(),
- (int) bbox.getHeight(),
- new TextData(null, origin, origBBox, unicodeID));
- packer.add(rect);
- glyphRectForTextureMapping = rect;
- Graphics2D g = getGraphics2D();
- // OK, should now have an (x, y) for this rectangle; rasterize
- // the glyph
- int strx = rect.x() + origin.x;
- int stry = rect.y() + origin.y;
-
- // Clear out the area we're going to draw into
- g.setComposite(AlphaComposite.Clear);
- g.fillRect(rect.x(), rect.y(), rect.w(), rect.h());
- g.setComposite(AlphaComposite.Src);
-
- // Draw the string
- renderDelegate.drawGlyphVector(g, gv, strx, stry);
-
- if (DRAW_BBOXES) {
- TextData data = (TextData) rect.getUserData();
- // Draw a bounding box on the backing store
- g.drawRect(strx - data.origOriginX(),
- stry - data.origOriginY(),
- (int) data.origRect().getWidth(),
- (int) data.origRect().getHeight());
- g.drawRect(strx - data.origin().x,
- stry - data.origin().y,
- rect.w(),
- rect.h());
- }
-
- // Mark this region of the TextureRenderer as dirty
- getBackingStore().markDirty(rect.x(), rect.y(), rect.w(),
- rect.h());
- // Re-register ourselves with our producer
- producer.register(this);
- }
-
- private GlyphVector getGlyphVector() {
- GlyphVector gv = singleUnicodeGlyphVector;
- if (gv != null) {
- singleUnicodeGlyphVector = null; // Don't need this anymore
- return gv;
- }
- singleUnicode[0] = (char) unicodeID;
- return font.createGlyphVector(getFontRenderContext(), singleUnicode);
- }
- }
-
- class GlyphProducer {
- final int undefined = -2;
- FontRenderContext fontRenderContext;
- List glyphsOutput = new ArrayList();
- HashMap fullGlyphVectorCache = new HashMap();
- HashMap glyphMetricsCache = new HashMap();
- // The mapping from unicode character to font-specific glyph ID
- int[] unicodes2Glyphs;
- // The mapping from glyph ID to Glyph
- Glyph[] glyphCache;
- // We re-use this for each incoming string
- CharSequenceIterator iter = new CharSequenceIterator();
-
- GlyphProducer(int fontLengthInGlyphs) {
- unicodes2Glyphs = new int[512];
- glyphCache = new Glyph[fontLengthInGlyphs];
- clearAllCacheEntries();
- }
-
- public List getGlyphs(CharSequence inString) {
- glyphsOutput.clear();
- GlyphVector fullRunGlyphVector;
- fullRunGlyphVector = fullGlyphVectorCache.get(inString.toString());
- if (fullRunGlyphVector == null) {
- iter.initFromCharSequence(inString);
- fullRunGlyphVector = font.createGlyphVector(getFontRenderContext(), iter);
- fullGlyphVectorCache.put(inString.toString(), fullRunGlyphVector);
- }
- boolean complex = (fullRunGlyphVector.getLayoutFlags() != 0);
- if (complex || DISABLE_GLYPH_CACHE) {
- // Punt to the robust version of the renderer
- glyphsOutput.add(new Glyph(inString.toString(), false));
- return glyphsOutput;
- }
-
- int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs();
- int i = 0;
- while (i < lengthInGlyphs) {
- Character letter = CharacterCache.valueOf(inString.charAt(i));
- GlyphMetrics metrics = glyphMetricsCache.get(letter);
- if (metrics == null) {
- metrics = fullRunGlyphVector.getGlyphMetrics(i);
- glyphMetricsCache.put(letter, metrics);
- }
- Glyph glyph = getGlyph(inString, metrics, i);
- if (glyph != null) {
- glyphsOutput.add(glyph);
- i++;
- } else {
- // Assemble a run of characters that don't fit in
- // the cache
- StringBuilder buf = new StringBuilder();
- while (i < lengthInGlyphs &&
- getGlyph(inString, fullRunGlyphVector.getGlyphMetrics(i), i) == null) {
- buf.append(inString.charAt(i++));
- }
- glyphsOutput.add(new Glyph(buf.toString(),
- // Any more glyphs after this run?
- i < lengthInGlyphs));
- }
- }
- return glyphsOutput;
- }
-
- public void clearCacheEntry(int unicodeID) {
- int glyphID = unicodes2Glyphs[unicodeID];
- if (glyphID != undefined) {
- Glyph glyph = glyphCache[glyphID];
- if (glyph != null) {
- glyph.clear();
- }
- glyphCache[glyphID] = null;
- }
- unicodes2Glyphs[unicodeID] = undefined;
- }
-
- public void clearAllCacheEntries() {
- for (int i = 0; i < unicodes2Glyphs.length; i++) {
- clearCacheEntry(i);
- }
- }
-
- public void register(Glyph glyph) {
- unicodes2Glyphs[glyph.getUnicodeID()] = glyph.getGlyphCode();
- glyphCache[glyph.getGlyphCode()] = glyph;
- }
-
- public float getGlyphPixelWidth(char unicodeID) {
- Glyph glyph = getGlyph(unicodeID);
- if (glyph != null) {
- return glyph.getAdvance();
- }
-
- // Have to do this the hard / uncached way
- singleUnicode[0] = unicodeID;
- GlyphVector gv = font.createGlyphVector(fontRenderContext,
- singleUnicode);
- return gv.getGlyphMetrics(0).getAdvance();
- }
-
- // Returns a glyph object for this single glyph. Returns null
- // if the unicode or glyph ID would be out of bounds of the
- // glyph cache.
- private Glyph getGlyph(CharSequence inString,
- GlyphMetrics glyphMetrics,
- int index) {
- char unicodeID = inString.charAt(index);
-
- if (unicodeID >= unicodes2Glyphs.length) {
- return null;
- }
-
- int glyphID = unicodes2Glyphs[unicodeID];
- if (glyphID != undefined) {
- return glyphCache[glyphID];
- }
-
- // Must fabricate the glyph
- singleUnicode[0] = unicodeID;
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
- return getGlyph(unicodeID, gv, glyphMetrics);
- }
-
- // It's unclear whether this variant might produce less
- // optimal results than if we can see the entire GlyphVector
- // for the incoming string
- private Glyph getGlyph(int unicodeID) {
- if (unicodeID >= unicodes2Glyphs.length) {
- return null;
- }
-
- int glyphID = unicodes2Glyphs[unicodeID];
- if (glyphID != undefined) {
- return glyphCache[glyphID];
- }
- singleUnicode[0] = (char) unicodeID;
- GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode);
- return getGlyph(unicodeID, gv, gv.getGlyphMetrics(0));
- }
-
- private Glyph getGlyph(int unicodeID,
- GlyphVector singleUnicodeGlyphVector,
- GlyphMetrics metrics) {
- int glyphCode = singleUnicodeGlyphVector.getGlyphCode(0);
- // Have seen huge glyph codes (65536) coming out of some fonts in some Unicode situations
- if (glyphCode >= glyphCache.length) {
- return null;
- }
- Glyph glyph = new Glyph(unicodeID,
- glyphCode,
- metrics.getAdvance(),
- singleUnicodeGlyphVector,
- this);
- register(glyph);
- return glyph;
- }
- }
-
- private static class CharacterCache {
- private CharacterCache() {
- }
-
- static final Character CACHE[] = new Character[127 + 1];
-
- static {
- for (int i = 0; i < CACHE.length; i++) {
- CACHE[i] = (char) i;
- }
- }
-
- public static Character valueOf(char c) {
- if (c <= 127) { // must cache
- return CharacterCache.CACHE[c];
- }
- return c;
- }
- }
-
- class Pipelined_QuadRenderer {
- int mOutstandingGlyphsVerticesPipeline = 0;
- FloatBuffer mTexCoords;
- FloatBuffer mVertCoords;
- boolean usingVBOs;
- int mVBO_For_ResuableTileVertices;
- int mVBO_For_ResuableTileTexCoords;
-
- Pipelined_QuadRenderer() {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- mVertCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsVerts);
- mTexCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsTex);
-
- usingVBOs = getUseVertexArrays() && is15Available(gl);
-
- if (usingVBOs) {
- try {
- int[] vbos = new int[2];
- gl.glGenBuffers(2, IntBuffer.wrap(vbos));
-
- mVBO_For_ResuableTileVertices = vbos[0];
- mVBO_For_ResuableTileTexCoords = vbos[1];
-
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileVertices);
- gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesVerts,
- null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
-
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileTexCoords);
- gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesTex,
- null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline
- } catch (Exception e) {
- isExtensionAvailable_GL_VERSION_1_5 = false;
- usingVBOs = false;
- }
- }
- }
-
- public void glTexCoord2f(float v, float v1) {
- mTexCoords.put(v);
- mTexCoords.put(v1);
- }
-
- public void glVertex3f(float inX, float inY, float inZ) {
- mVertCoords.put(inX);
- mVertCoords.put(inY);
- mVertCoords.put(inZ);
-
- mOutstandingGlyphsVerticesPipeline++;
-
- if (mOutstandingGlyphsVerticesPipeline >= kTotalBufferSizeVerts) {
- this.draw();
- }
- }
-
- private void draw() {
- if (useVertexArrays) {
- drawVertexArrays();
- } else {
- drawIMMEDIATE();
- }
- }
-
- private void drawVertexArrays() {
- if (mOutstandingGlyphsVerticesPipeline > 0) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
-
- TextureRenderer renderer = getBackingStore();
- renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
-
- mVertCoords.rewind();
- mTexCoords.rewind();
-
- gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
-
- if (usingVBOs) {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileVertices);
- gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0,
- mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_VertexData,
- mVertCoords); // upload only the new stuff
- gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0);
- } else {
- gl.glVertexPointer(3, GL2.GL_FLOAT, 0, mVertCoords);
- }
-
- gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
-
- if (usingVBOs) {
- gl.glBindBuffer(GL2.GL_ARRAY_BUFFER,
- mVBO_For_ResuableTileTexCoords);
- gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0,
- mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_TexData,
- mTexCoords); // upload only the new stuff
- gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, 0);
- } else {
- gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, mTexCoords);
- }
-
- gl.glDrawArrays(GL2.GL_QUADS, 0,
- mOutstandingGlyphsVerticesPipeline);
-
- mVertCoords.rewind();
- mTexCoords.rewind();
- mOutstandingGlyphsVerticesPipeline = 0;
- }
- }
-
- private void drawIMMEDIATE() {
- if (mOutstandingGlyphsVerticesPipeline > 0) {
- TextureRenderer renderer = getBackingStore();
- renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious?
-
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glBegin(GL2.GL_QUADS);
-
- try {
- int numberOfQuads = mOutstandingGlyphsVerticesPipeline / 4;
- mVertCoords.rewind();
- mTexCoords.rewind();
-
- for (int i = 0; i < numberOfQuads; i++) {
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
-
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
-
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
-
- gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get());
- gl.glVertex3f(mVertCoords.get(), mVertCoords.get(),
- mVertCoords.get());
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- gl.glEnd();
- mVertCoords.rewind();
- mTexCoords.rewind();
- mOutstandingGlyphsVerticesPipeline = 0;
- }
- }
- }
- }
-
- class DebugListener implements GLEventListener {
- private GLU glu;
- private Frame frame;
-
- DebugListener(GL gl, Frame frame) {
- this.glu = GLU.createGLU(gl);
- this.frame = frame;
- }
-
- @Override
- public void display(GLAutoDrawable drawable) {
- GL2 gl = GLContext.getCurrentGL().getGL2();
- gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT);
-
- if (packer == null) {
- return;
- }
-
- TextureRenderer rend = getBackingStore();
- final int w = rend.getWidth();
- final int h = rend.getHeight();
- rend.beginOrthoRendering(w, h);
- rend.drawOrthoRect(0, 0);
- rend.endOrthoRendering();
-
- if ((frame.getWidth() != w) || (frame.getHeight() != h)) {
- EventQueue.invokeLater(new Runnable() {
- @Override
- public void run() {
- frame.setSize(w, h);
- }
- });
- }
- }
-
- @Override
- public void dispose(GLAutoDrawable drawable) {
- glu=null;
- frame=null;
- }
-
- // Unused methods
- @Override
- public void init(GLAutoDrawable drawable) {
- }
-
- @Override
- public void reshape(GLAutoDrawable drawable, int x, int y, int width,
- int height) {
- }
-
- public void displayChanged(GLAutoDrawable drawable,
- boolean modeChanged, boolean deviceChanged) {
- }
- }
-
- /**
- * Sets whether vertex arrays are being used internally for rendering, or whether text is rendered using the OpenGL
- * immediate mode commands.This is provided as a concession for certain graphics cards which have poor vertex array
- * performance. Defaults to true.
- *
- * @param useVertexArrays The desired value.
- */
- public void setUseVertexArrays(boolean useVertexArrays) {
- this.useVertexArrays = useVertexArrays;
- }
-
- /**
- * Indicates whether vertex arrays are being used internally for
- * rendering, or whether text is rendered using the OpenGL
- * immediate mode commands.Defaults to true.
- * @return whether userVertexArrays is on or off.
- */
- public final boolean getUseVertexArrays() {
- return useVertexArrays;
- }
-
- /**
- * Sets whether smoothing (i.e., GL_LINEAR filtering) is enabled in the backing TextureRenderer of this
- * TextRenderer.A few graphics cards do not behave well when this is enabled, resulting in fuzzy text. Defaults to
- * true.
- *
- * @param smoothing The new smoothing setting.
- */
- public void setSmoothing(boolean smoothing) {
- this.smoothing = smoothing;
- getBackingStore().setSmoothing(smoothing);
- }
-
- /**
- * Indicates whether smoothing is enabled in the backing TextureRenderer of this TextRenderer.A few graphics cards
- * do not behave well when this is enabled, resulting in fuzzy text. Defaults to true.
- *
- * @return The current smoothing setting.
- */
- public boolean getSmoothing() {
- return smoothing;
- }
-
- private boolean is15Available(GL gl) {
- if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) {
- isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable(GLExtensions.VERSION_1_5);
- checkFor_isExtensionAvailable_GL_VERSION_1_5 = true;
- }
- return isExtensionAvailable_GL_VERSION_1_5;
- }
-}
diff --git a/src/gov/nasa/worldwind/render/TextRendererCache.java b/src/gov/nasa/worldwind/render/TextRendererCache.java
index 5f670f784e..82a710bbe6 100644
--- a/src/gov/nasa/worldwind/render/TextRendererCache.java
+++ b/src/gov/nasa/worldwind/render/TextRendererCache.java
@@ -27,6 +27,8 @@
*/
package gov.nasa.worldwind.render;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import gov.nasa.worldwind.Disposable;
import gov.nasa.worldwind.util.Logging;
diff --git a/src/gov/nasa/worldwind/render/ToolTipRenderer.java b/src/gov/nasa/worldwind/render/ToolTipRenderer.java
index b9e4b7af0f..13fb44fb69 100644
--- a/src/gov/nasa/worldwind/render/ToolTipRenderer.java
+++ b/src/gov/nasa/worldwind/render/ToolTipRenderer.java
@@ -30,6 +30,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
diff --git a/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java b/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java
index af167bd955..7c410ec413 100644
--- a/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java
+++ b/src/gov/nasa/worldwind/symbology/AbstractTacticalSymbol.java
@@ -28,6 +28,7 @@
package gov.nasa.worldwind.symbology;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.*;
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
import gov.nasa.worldwind.*;
diff --git a/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java b/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java
index d24b0dcfb9..0837534eaa 100644
--- a/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java
+++ b/src/gov/nasa/worldwind/symbology/TacticalGraphicLabel.java
@@ -37,6 +37,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
diff --git a/src/gov/nasa/worldwind/terrain/RectangularTessellator.java b/src/gov/nasa/worldwind/terrain/RectangularTessellator.java
index 869e99424a..07ea6ba500 100644
--- a/src/gov/nasa/worldwind/terrain/RectangularTessellator.java
+++ b/src/gov/nasa/worldwind/terrain/RectangularTessellator.java
@@ -39,6 +39,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.nio.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwind/util/EGM2008.java b/src/gov/nasa/worldwind/util/EGM2008.java
new file mode 100644
index 0000000000..f8e64d9900
--- /dev/null
+++ b/src/gov/nasa/worldwind/util/EGM2008.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The NASA World Wind Java (WWJ) platform is 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.
+ *
+ * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
+ * software:
+ *
+ * Jackson Parser – Licensed under Apache 2.0
+ * GDAL – Licensed under MIT
+ * JOGL – Licensed under Berkeley Software Distribution (BSD)
+ * Gluegen – Licensed under Berkeley Software Distribution (BSD)
+ *
+ * A complete listing of 3rd Party software notices and licenses included in
+ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
+ * notices and licenses PDF found in code directory.
+ */
+
+package gov.nasa.worldwind.util;
+
+import gov.nasa.worldwind.cache.BasicMemoryCache;
+import gov.nasa.worldwind.geom.Angle;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.net.URL;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+public class EGM2008
+{
+ public static final int N_ROW_MARKERS = 2; // The beginning and end of each row of latitude data is a flag of some sort
+ public static final int N_LONGITUDE_COLS = 8640 + N_ROW_MARKERS; // Number of float32s in a row of data in the data file.
+ public static final int N_LATITUDE_ROWS = 4321; // Number of rows.
+ public static final double GRID_RESOLUTION = 2.5d / 60d; // 2.5 minute grid
+ public static final double CELL_AREA = GRID_RESOLUTION * GRID_RESOLUTION;
+ protected static final long CACHE_SIZE = EGM2008.N_LONGITUDE_COLS * 4 * 45 * 15; // Cache 15 degrees worth of offsets.
+ public static final int N_LAT_ROW_BYTES = N_LONGITUDE_COLS * 4; // Offsets are float32
+
+ protected String offsetsFilePath;
+ protected BufferWrapper deltas;
+ protected final BasicMemoryCache offsetCache;
+
+ protected class GridCell
+ {
+ public double x1;
+ public double y1;
+ public double x2;
+ public double y2;
+
+ public GridCell(double x1, double y1)
+ {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x1 + EGM2008.GRID_RESOLUTION;
+ this.y2 = y1 + EGM2008.GRID_RESOLUTION;
+ }
+
+ public GridCell()
+ {
+ this(0, 0);
+ }
+
+ public GridCell intersect(GridCell that)
+ {
+ GridCell intersection = new GridCell();
+ intersection.x1 = Math.max(this.x1, that.x1);
+ intersection.x2 = Math.min(this.x2, that.x2);
+ intersection.y1 = Math.max(this.y1, that.y1);
+ intersection.y2 = Math.min(this.y2, that.y2);
+ return intersection;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%5.2f,%5.2f,%5.2f,%5.2f", x1, y1, x2, y2);
+ }
+
+ public double area()
+ {
+ return (this.x2 - this.x1) * (this.y2 - this.y1);
+ }
+ }
+
+ /**
+ * Allows the retrieval of geoid offsets from the EGM2008 2.5 Minute Interpolation Grid sourced from the
+ * National Geospatial-Intelligence Agency Office of Geomatics (https://earth-info.nga.mil/).
+ *
+ * The EGM2008 data path. This data file is not included in the SDK due to its size. The data may be downloaded here:
+ * https://builds.worldwind.arc.nasa.gov/artifactory/EGM2008-Data/egm2008_25.dat
+ *
+ * @param offsetsFilePath a path pointing to a file with the geoid offsets.
+ */
+ public EGM2008(String offsetsFilePath)
+ {
+ if (offsetsFilePath == null)
+ {
+ String msg = Logging.getMessage("nullValue.PathIsNull");
+ Logging.logger().severe(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ File test = new File(offsetsFilePath);
+ if (test.exists())
+ {
+ this.offsetsFilePath = offsetsFilePath;
+ }
+ else
+ {
+ Class c = EGM2008.class;
+ URL url = c.getResource("/" + offsetsFilePath);
+ if (url != null)
+ {
+ test = WWIO.getFileForLocalAddress(url);
+ this.offsetsFilePath = test.getAbsolutePath();
+ }
+ else
+ {
+ this.offsetsFilePath = null;
+ }
+ }
+ this.offsetCache = new BasicMemoryCache((EGM2008.CACHE_SIZE * 8) / 10, EGM2008.CACHE_SIZE);
+ this.offsetCache.setName(EGM2008.class.getName());
+ }
+
+ public float getOffset(Angle lat, Angle lon) throws IOException
+ {
+ return this.getOffset((float) lat.degrees, (float) lon.degrees);
+ }
+
+ public int getLatRow(double lat)
+ {
+ // Compute the row in the data file corresponding to a given latitude.
+ // Latitude row zero in the data corresponds to 90 degrees latitude (north pole) and increases southward
+ // Longitude column zero in the data corresponds to 0 degrees of longitude and increases eastward
+ float lat180 = 90f - (float) lat;
+ return (int) Math.floor(lat180 / EGM2008.GRID_RESOLUTION);
+ }
+
+ public int getLonCol(double lon)
+ {
+ // Compute the column in the data file corresponding to a given latitude and longitude.
+ // Latitude row zero in the data corresponds to 90 degrees latitude (north pole) and increases southward
+ // Longitude column zero in the data corresponds to 0 degrees of longitude and increases eastward
+ float lon360 = (float) lon;
+ if (lon < 0)
+ {
+ lon360 = lon360 + 360;
+ }
+ return (int) Math.floor(lon360 / EGM2008.GRID_RESOLUTION);
+ }
+
+ public float[][] getLatRows(int latRow) throws IOException
+ {
+ int[] interpRowIndices =
+ {
+ latRow, latRow + 1
+ };
+ float[][] latDataArray = new float[2][];
+ boolean retrievalRequired = false;
+ for (int i = 0; i < interpRowIndices.length; i++)
+ {
+ if (interpRowIndices[i] < EGM2008.N_LATITUDE_ROWS)
+ {
+ float[] latData = (float[]) this.offsetCache.getObject(interpRowIndices[i]);
+ latDataArray[i] = latData;
+ if (latData == null)
+ {
+ retrievalRequired = true;
+ }
+ }
+ }
+ if (retrievalRequired)
+ {
+ try (RandomAccessFile offsetFile = new RandomAccessFile(this.offsetsFilePath, "r"))
+ {
+ for (int i = 0; i < interpRowIndices.length; i++)
+ {
+ if (interpRowIndices[i] < EGM2008.N_LATITUDE_ROWS && latDataArray[i] == null)
+ {
+ offsetFile.seek(interpRowIndices[i] * EGM2008.N_LAT_ROW_BYTES);
+ byte[] latByteData = new byte[EGM2008.N_LAT_ROW_BYTES];
+ offsetFile.read(latByteData);
+ ByteBuffer latByteBuffer = ByteBuffer.wrap(latByteData).order(ByteOrder.LITTLE_ENDIAN);
+ FloatBuffer latFloatBuffer = latByteBuffer.asFloatBuffer();
+ float[] latData = new float[EGM2008.N_LONGITUDE_COLS];
+ latFloatBuffer.get(latData);
+ this.offsetCache.add(interpRowIndices[i], latData, EGM2008.N_LAT_ROW_BYTES);
+ latDataArray[i] = latData;
+ }
+ }
+ }
+ }
+ return latDataArray;
+ }
+
+ public float getOffset(double lat, double lon) throws IOException
+ {
+ if (this.offsetsFilePath == null)
+ {
+ return 0f;
+ }
+ int latRow = this.getLatRow(lat);
+ int lonCol = this.getLonCol(lon);
+
+ float[][] latDataArray = getLatRows(latRow);
+
+ float baseOffset = latDataArray[0][lonCol + EGM2008.N_ROW_MARKERS / 2];
+ if (latDataArray[1] == null)
+ {
+ return baseOffset;
+ }
+
+ // Interpolate with surrounding offset cells
+ float lat180 = 90f - (float) lat;
+ float lon360 = (float) lon;
+ if (lon < 0)
+ {
+ lon360 = lon360 + 360;
+ }
+ GridCell offsetCell = new GridCell(lon360, lat180);
+ double baseLat = ((double) latRow) * EGM2008.GRID_RESOLUTION;
+ double baseLon = ((double) lonCol) * EGM2008.GRID_RESOLUTION;
+ float interpOffset = 0;
+ for (int x = 0; x < 2; x++)
+ {
+ double cellLon = baseLon + ((double) x) * EGM2008.GRID_RESOLUTION;
+ for (int y = 0; y < 2; y++)
+ {
+ float cellOffset = latDataArray[y][lonCol + EGM2008.N_ROW_MARKERS / 2 + x];
+ double cellLat = baseLat + ((double) y) * EGM2008.GRID_RESOLUTION;
+ GridCell interpCell = new GridCell(cellLon, cellLat);
+ GridCell intersection = offsetCell.intersect(interpCell);
+ interpOffset += cellOffset * (intersection.area() / EGM2008.CELL_AREA);
+ }
+ }
+ return interpOffset;
+ }
+
+ public boolean isEGMDataAvailable()
+ {
+ return this.offsetsFilePath != null;
+ }
+}
diff --git a/src/gov/nasa/worldwind/util/OGLTextRenderer.java b/src/gov/nasa/worldwind/util/OGLTextRenderer.java
index 271568cc94..a5b77a291d 100644
--- a/src/gov/nasa/worldwind/util/OGLTextRenderer.java
+++ b/src/gov/nasa/worldwind/util/OGLTextRenderer.java
@@ -27,6 +27,8 @@
*/
package gov.nasa.worldwind.util;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import gov.nasa.worldwind.render.*;
/**
diff --git a/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java b/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java
index e41b6a8100..0d785e5e3f 100644
--- a/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java
+++ b/src/gov/nasa/worldwind/util/PlacemarkClutterFilter.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwind.render.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwind/util/layertree/LayerTree.java b/src/gov/nasa/worldwind/util/layertree/LayerTree.java
index 0b4ee0937a..ca504bb616 100644
--- a/src/gov/nasa/worldwind/util/layertree/LayerTree.java
+++ b/src/gov/nasa/worldwind/util/layertree/LayerTree.java
@@ -27,6 +27,8 @@
*/
package gov.nasa.worldwind.util.layertree;
+import java.awt.Point;
+
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.render.Offset;
import gov.nasa.worldwind.util.Logging;
@@ -87,11 +89,11 @@ public LayerTree(LayerTreeModel model)
* Creates a new LayerTree with an empty LayerTreeModel and the specified screen
* location.
*
- * @param offset the screen location of the tree's upper left corner, relative to the screen's upper left corner.
+ * @param offset the screen location of the tree's lower left corner, relative to the screen's lower left corner.
*
* @throws IllegalArgumentException if offset is null.
*/
- public LayerTree(Offset offset)
+ public LayerTree(Point offset)
{
if (offset == null)
{
@@ -107,12 +109,12 @@ public LayerTree(Offset offset)
* Creates a new LayerTree with the specified model and the specified screen location.
*
* @param model the tree model to use.
- * @param offset the screen location of the tree's upper left corner, relative to the screen's upper left corner.
+ * @param offset the screen location of the tree's lower left corner, relative to the screen's lower left corner. (GL surface pixels)
*
* @throws IllegalArgumentException if model is null, or if offset is
* null.
*/
- public LayerTree(LayerTreeModel model, Offset offset)
+ public LayerTree(LayerTreeModel model, Point offset)
{
if (model == null)
{
@@ -139,7 +141,7 @@ public LayerTree(LayerTreeModel model, Offset offset)
* @param model this tree's model to use, or null to create a new LayerTreeModel.
* @param offset the screen location of this tree's upper left corner, or null to use the default.
*/
- protected void initialize(LayerTreeModel model, Offset offset)
+ protected void initialize(LayerTreeModel model, Point offset)
{
if (model == null)
model = this.createTreeModel();
@@ -167,10 +169,10 @@ protected LayerTreeModel createTreeModel()
*
* @return new TreeLayout.
*/
- protected TreeLayout createTreeLayout(Offset offset)
+ protected TreeLayout createTreeLayout(Point offset)
{
if (offset == null)
- offset = DEFAULT_OFFSET;
+ offset = new Point(DEFAULT_OFFSET.getX().intValue(), DEFAULT_OFFSET.getY().intValue());
BasicTreeLayout layout = new BasicTreeLayout(this, offset);
layout.getFrame().setFrameTitle(DEFAULT_FRAME_TITLE);
@@ -196,7 +198,8 @@ protected TreeLayout createTreeLayout(Offset offset)
}
/** {@inheritDoc} */
- public LayerTreeModel getModel()
+ @Override
+ public LayerTreeModel getModel()
{
return (LayerTreeModel) super.getModel();
}
diff --git a/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java b/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java
index 8bb6c85172..d9325e46f8 100644
--- a/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java
+++ b/src/gov/nasa/worldwind/util/tree/BasicTreeLayout.java
@@ -28,6 +28,7 @@
package gov.nasa.worldwind.util.tree;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.TextureCoords;
import gov.nasa.worldwind.WWObjectImpl;
import gov.nasa.worldwind.avlist.AVKey;
@@ -160,7 +161,7 @@ public BasicTreeLayout(Tree tree)
*/
public BasicTreeLayout(Tree tree, int x, int y)
{
- this(tree, new Offset((double) x, (double) y, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this(tree, new Point(x, y));
}
/**
@@ -170,7 +171,7 @@ public BasicTreeLayout(Tree tree, int x, int y)
* @param screenLocation The location of the upper left corner of the tree frame. The offset is interpreted relative
* to the lower left corner of the screen.
*/
- public BasicTreeLayout(Tree tree, Offset screenLocation)
+ public BasicTreeLayout(Tree tree, Point screenLocation)
{
this.tree = tree;
this.frame = this.createFrame();
@@ -186,7 +187,8 @@ public BasicTreeLayout(Tree tree, Offset screenLocation)
// events between TreeLayout and Tree.
this.tree.addPropertyChangeListener(new PropertyChangeListener()
{
- public void propertyChange(PropertyChangeEvent propertyChangeEvent)
+ @Override
+ public void propertyChange(PropertyChangeEvent propertyChangeEvent)
{
// Ignore events originated by this TreeLayout, and repaint events. There is no need to recompute the
// tree layout just because a repaint was triggered.
@@ -341,7 +343,8 @@ public void setDrawNodeStateSymbol(boolean drawNodeStateSymbol)
}
/** {@inheritDoc} */
- public long getUpdateTime()
+ @Override
+ public long getUpdateTime()
{
return this.updateTime;
}
@@ -364,7 +367,8 @@ protected ScrollFrame createFrame()
*
* @return Size of the rendered tree.
*/
- public Dimension getSize(DrawContext dc, Dimension frameSize)
+ @Override
+ public Dimension getSize(DrawContext dc, Dimension frameSize)
{
this.updateAttributes(dc);
@@ -472,7 +476,8 @@ protected boolean mustDisplayNode(TreeNode node, int level)
}
/** {@inheritDoc} */
- public void preRender(DrawContext dc)
+ @Override
+ public void preRender(DrawContext dc)
{
// Adjust scroll position if an application has requested that the layout scroll to make a node visible.
this.scrollToNode(dc);
@@ -481,7 +486,8 @@ public void preRender(DrawContext dc)
}
/** {@inheritDoc} */
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
this.frame.render(dc);
}
@@ -514,7 +520,8 @@ protected synchronized void scrollToNode(DrawContext dc)
}
/** {@inheritDoc} */
- public void renderScrollable(DrawContext dc, Point location, Dimension frameSize, Rectangle clipBounds)
+ @Override
+ public void renderScrollable(DrawContext dc, Point location, Dimension frameSize, Rectangle clipBounds)
{
TreeModel model = this.tree.getModel();
TreeNode root = model.getRoot();
@@ -1321,7 +1328,8 @@ protected Rectangle findNodeBounds(TreeNode needle, TreeNode haystack, DrawConte
}
/** {@inheritDoc} */
- public synchronized void makeVisible(TreePath path)
+ @Override
+ public synchronized void makeVisible(TreePath path)
{
TreeNode node = this.tree.getNode(path);
if (node == null)
@@ -1345,7 +1353,7 @@ public synchronized void makeVisible(TreePath path)
*
* @return Screen location, measured in pixels from the upper left corner of the screen.
*/
- public Offset getScreenLocation()
+ public Point getScreenLocation()
{
return this.frame.getScreenLocation();
}
@@ -1356,19 +1364,21 @@ public Offset getScreenLocation()
*
* @param screenLocation New screen location.
*/
- public void setScreenLocation(Offset screenLocation)
+ public void setScreenLocation(Point screenLocation)
{
frame.setScreenLocation(screenLocation);
}
/** {@inheritDoc} */
- public TreeAttributes getAttributes()
+ @Override
+ public TreeAttributes getAttributes()
{
return this.normalAttributes;
}
/** {@inheritDoc} */
- public void setAttributes(TreeAttributes attributes)
+ @Override
+ public void setAttributes(TreeAttributes attributes)
{
if (attributes == null)
{
@@ -1464,7 +1474,8 @@ public boolean isHighlighted()
*
* @param highlighted True if the tree should be highlighted.
*/
- public void setHighlighted(boolean highlighted)
+ @Override
+ public void setHighlighted(boolean highlighted)
{
this.highlighted = highlighted;
}
diff --git a/src/gov/nasa/worldwind/util/tree/DragControl.java b/src/gov/nasa/worldwind/util/tree/DragControl.java
index ac0b8e0e28..8f6edace36 100644
--- a/src/gov/nasa/worldwind/util/tree/DragControl.java
+++ b/src/gov/nasa/worldwind/util/tree/DragControl.java
@@ -101,7 +101,7 @@ else if (event.isDragEnd())
/**
* Called when a drag begins. This implementation saves the first drag point to {@link #dragRefPoint}.
*
- * @param point Point at which dragging started.
+ * @param point Point at which dragging started (GL surface pixels)
*/
protected void beginDrag(Point point)
{
@@ -111,7 +111,7 @@ protected void beginDrag(Point point)
/**
* Called for each point within a drag action.
*
- * @param point Current drag point.
+ * @param point Current drag point. (GL surface pixels)
*/
protected abstract void drag(Point point);
diff --git a/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java b/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java
index 69f3f26776..fcfb13b54d 100644
--- a/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java
+++ b/src/gov/nasa/worldwind/util/tree/FrameResizeControl.java
@@ -28,13 +28,11 @@
package gov.nasa.worldwind.util.tree;
-import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.AbstractResizeHotSpot;
import java.awt.*;
import java.awt.event.*;
-import java.awt.geom.*;
/**
* A screen control for resizing a frame. This class handles the resize input events, but does does not actually draw
@@ -89,15 +87,15 @@ protected void setSize(Dimension newSize)
@Override
protected Point getScreenPoint()
{
- Point2D point2D = this.frame.getScreenPoint();
- return new Point((int)point2D.getX(), (int)point2D.getY());
+ Point point = this.frame.getScreenLocation();
+ return new Point(point);
}
/** {@inheritDoc} */
@Override
protected void setScreenPoint(Point newPoint)
{
- this.frame.setScreenLocation(new Offset(newPoint.getX(), newPoint.getY(), AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this.frame.setScreenLocation(newPoint);
}
/** {@inheritDoc} */
@@ -113,7 +111,8 @@ protected Dimension getMinimumSize()
*
* @param event The event to handle.
*/
- public void mouseWheelMoved(MouseWheelEvent event)
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent event)
{
if (event == null || event.isConsumed())
return;
diff --git a/src/gov/nasa/worldwind/util/tree/ScrollBar.java b/src/gov/nasa/worldwind/util/tree/ScrollBar.java
index 431a8084a5..a973053661 100644
--- a/src/gov/nasa/worldwind/util/tree/ScrollBar.java
+++ b/src/gov/nasa/worldwind/util/tree/ScrollBar.java
@@ -683,7 +683,8 @@ public boolean isAutoScrolling()
*
* @param dc the DrawContext to be used
*/
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc.getFrameTimeStamp() != this.frameNumber)
{
@@ -1110,7 +1111,9 @@ protected void beginDrag(Point point)
this.dragRefValue = this.scrollBar.getValue();
}
- protected void drag(Point point)
+ /** {@inheritDoc} */
+ @Override
+ protected void drag(Point point)
{
int delta;
int adjustment;
@@ -1118,7 +1121,10 @@ protected void drag(Point point)
if (AVKey.VERTICAL.equals(scrollBar.getOrientation()))
{
- delta = point.y - this.dragRefPoint.y;
+ // scroll bar zero position is at the top in GL surface coordinates.
+ // 'point' will be in GL surface coordinates, so moving the mouse
+ // towards the bottom of the screen yields a smaller y value.
+ delta = this.dragRefPoint.y - point.y;
screenDimension = this.scrollBar.scrollBounds.height - this.scrollBar.getMinScrollKnobSize();
}
else
diff --git a/src/gov/nasa/worldwind/util/tree/ScrollFrame.java b/src/gov/nasa/worldwind/util/tree/ScrollFrame.java
index ebb1d63c6e..057fd378fa 100644
--- a/src/gov/nasa/worldwind/util/tree/ScrollFrame.java
+++ b/src/gov/nasa/worldwind/util/tree/ScrollFrame.java
@@ -28,6 +28,7 @@
package gov.nasa.worldwind.util.tree;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.*;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.AVKey;
@@ -98,7 +99,7 @@ public class ScrollFrame extends DragControl implements PreRenderable, Renderabl
protected Scrollable contents;
/** Indicates the location of the upper left corner of the frame. */
- protected Offset screenLocation;
+ protected Point screenLocation;
/** Indicates whether or not to draw a title bar in the frame. Default is true. */
protected boolean drawTitleBar = true;
@@ -209,11 +210,6 @@ public class ScrollFrame extends DragControl implements PreRenderable, Renderabl
protected long frameNumber = -1;
/** Indicates that the frame must be regenerated because the size or attributes have changed. */
protected boolean mustRecomputeFrameGeometry = true;
- /**
- * Indicates the location of the upper left corner of the frame, in AWT coordinates (origin at the upper left corner
- * of the screen.
- */
- protected Point2D awtScreenPoint;
/** Bounds of the full frame. */
protected Rectangle frameBounds;
/** Bounds of the frame inside the frame border. */
@@ -262,7 +258,7 @@ public ScrollFrame()
*/
public ScrollFrame(int x, int y)
{
- this(new Offset((double) x, (double) y, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this(new Point(x, y));
}
/**
@@ -270,7 +266,7 @@ public ScrollFrame(int x, int y)
*
* @param screenLocation initial location of the upper left corner of the frame.
*/
- public ScrollFrame(Offset screenLocation)
+ public ScrollFrame(Point screenLocation)
{
super(null);
this.setScreenLocation(screenLocation);
@@ -628,43 +624,32 @@ public Rectangle getBounds(DrawContext dc)
{
this.updateBounds(dc);
- return new Rectangle((int) this.awtScreenPoint.getX(), (int) this.awtScreenPoint.getY(), this.frameSize.width,
+ return new Rectangle(screenLocation.x, screenLocation.y, this.frameSize.width,
this.frameSize.height);
}
/**
- * Get the location of the upper left corner of the tree, measured in screen coordinates with the origin at the
- * upper left corner of the screen.
+ * Get the location of the lower left corner of the tree, measured in screen
+ * coordinates with the origin at the lower left corner of the screen.
*
- * @return Screen location, measured in pixels from the upper left corner of the screen.
+ * @return Screen location, measured in GL surface pixels from the lower left corner of the screen.
*/
- public Offset getScreenLocation()
+ public Point getScreenLocation()
{
return this.screenLocation;
}
/**
- * Set the location of the upper left corner of the tree, measured in screen coordinates with the origin at the
- * upper left corner of the screen.
+ * Set the location of the lower left corner of the tree, measured in GL surface coordinates
+ * with the origin at the lower left corner of the screen.
*
* @param screenLocation New screen location.
*/
- public void setScreenLocation(Offset screenLocation)
+ public void setScreenLocation(Point screenLocation)
{
this.screenLocation = screenLocation;
}
- /**
- * Get the location of the upper left corner of the frame, measured from the upper left corner of the screen.
- *
- * @return The location of the upper left corner of the frame. This method will return null until the has been
- * rendered.
- */
- protected Point2D getScreenPoint()
- {
- return this.awtScreenPoint;
- }
-
/**
* Indicates the frame attributes used to draw the frame when it is not highlighted.
*
@@ -1043,9 +1028,10 @@ protected int computeTileTextureDimension(Dimension frameSize, Dimension content
}
/** {@inheritDoc} */
- public void preRender(DrawContext dc)
+ @Override
+ public void preRender(DrawContext dc)
{
- Offset screenLocation = this.getScreenLocation();
+ Point screenLocation = this.getScreenLocation();
if (screenLocation == null)
return;
@@ -1057,8 +1043,7 @@ public void preRender(DrawContext dc)
Point pickPoint = dc.getPickPoint();
if (pickPoint != null)
{
- int glY = dc.getView().getViewport().height - pickPoint.y;
- this.setHighlighted(this.pickBounds.contains(new Point(pickPoint.x, glY)));
+ this.setHighlighted(this.pickBounds.contains(pickPoint));
}
this.determineActiveAttributes();
@@ -1078,9 +1063,10 @@ public void preRender(DrawContext dc)
}
/** {@inheritDoc} */
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
- Offset screenLocation = this.getScreenLocation();
+ Point screenLocation = this.getScreenLocation();
if (screenLocation == null || this.frameBounds == null)
return;
@@ -1244,26 +1230,23 @@ public void updateBounds(DrawContext dc)
if (!this.frameSize.equals(previousFrameSize))
this.mustRecomputeFrameGeometry = true;
- // Compute point in OpenGL coordinates
- Point2D upperLeft = this.screenLocation.computeOffset(viewport.width, viewport.height, 1.0, 1.0);
-
- this.awtScreenPoint = new Point((int) upperLeft.getX(), (int) (viewport.height - upperLeft.getY()));
+ // Set frame bounds
+ this.frameBounds = new Rectangle(screenLocation.x, screenLocation.y,
+ this.frameSize.width, this.frameSize.height);
- this.frameBounds = new Rectangle((int) upperLeft.getX(), (int) upperLeft.getY() - this.frameSize.height,
- this.frameSize.width, this.frameSize.height);
-
- // Compute the pickable screen extent as the frame extent, plus the width of the frame's pickable outline.
- // This extent is used during picking to ensure that the frame's outline is pickable when it exceeds the
- // frame's screen extent.
+ // Compute the pickable screen extent in GL surface coordinates as the frame extent,
+ // plus the width of the frame's pickable outline.
+ // This extent is used during picking to ensure that the frame's outline is pickable
+ // when it exceeds the frame's screen extent.
this.pickBounds = new Rectangle(
this.frameBounds.x - this.borderPickWidth / 2,
this.frameBounds.y - this.borderPickWidth / 2,
this.frameBounds.width + this.borderPickWidth,
this.frameBounds.height + this.borderPickWidth);
- this.innerBounds = new Rectangle((int) upperLeft.getX() + this.frameBorder,
- (int) upperLeft.getY() - frameSize.height + this.frameBorder, frameSize.width - this.frameBorder * 2,
- frameSize.height - this.frameBorder * 2);
+ this.innerBounds = new Rectangle(frameBounds.x + this.frameBorder,
+ frameBounds.y + this.frameBorder, frameSize.width - this.frameBorder * 2,
+ frameSize.height - this.frameBorder * 2);
// If the content size has yet not been computed, compute it now.
if (contentSize == null)
@@ -2269,18 +2252,17 @@ protected void beginDrag(Point point)
{
if (this.isEnableMove())
{
- Point2D location = this.awtScreenPoint;
- this.dragRefPoint = new Point((int) location.getX() - point.x, (int) location.getY() - point.y);
+ this.dragRefPoint = new Point( screenLocation.x - point.x, screenLocation.y - point.y);
}
}
- public void drag(Point point)
+ @Override
+ public void drag(Point point)
{
if (this.isEnableMove())
{
- double x = point.x + this.dragRefPoint.x;
- double y = point.y + this.dragRefPoint.y;
- this.setScreenLocation(new Offset(x, y, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ Point pt = new Point(point.x + this.dragRefPoint.x, point.y + this.dragRefPoint.y);
+ this.setScreenLocation(pt);
}
}
@@ -2293,8 +2275,8 @@ public void selected(SelectEvent event)
super.selected(event);
// Minimize the frame if the title bar was double clicked.
- Rectangle titleBarBounds = new Rectangle((int) this.awtScreenPoint.getX() + this.frameBorder,
- (int) this.awtScreenPoint.getY() + this.frameBorder * 2, this.innerBounds.width, this.titleBarHeight);
+ Rectangle titleBarBounds = new Rectangle(this.screenLocation.x + this.frameBorder,
+ this.screenLocation.y + this.frameBorder * 2, this.innerBounds.width, this.titleBarHeight);
if (event.isLeftDoubleClick())
{
@@ -2475,7 +2457,8 @@ class TextureTile implements Comparable
* @return -1 if this tile was accessed less recently than that tile, 0 if the access times are the same, or 1
* if this tile was accessed more recently.
*/
- public int compareTo(TextureTile that)
+ @Override
+ public int compareTo(TextureTile that)
{
if (that == null)
{
diff --git a/src/gov/nasa/worldwind/view/BasicView.java b/src/gov/nasa/worldwind/view/BasicView.java
index 2857760067..22809dbe66 100644
--- a/src/gov/nasa/worldwind/view/BasicView.java
+++ b/src/gov/nasa/worldwind/view/BasicView.java
@@ -591,7 +591,7 @@ public void goTo(Position position, double distance)
public Line computeRayFromScreenPoint(double x, double y)
{
return ViewUtil.computeRayFromScreenPoint(this, x, y,
- this.modelview, this.projection, this.viewport);
+ this.modelview, this.projection);
}
public Position computePositionFromScreenPoint(double x, double y)
diff --git a/src/gov/nasa/worldwind/view/ViewUtil.java b/src/gov/nasa/worldwind/view/ViewUtil.java
index e2dbd2d988..dbd8d97c68 100644
--- a/src/gov/nasa/worldwind/view/ViewUtil.java
+++ b/src/gov/nasa/worldwind/view/ViewUtil.java
@@ -536,7 +536,7 @@ public static Angle normalizedRoll(Angle unnormalizedRoll)
}
public static Line computeRayFromScreenPoint(View view, double x, double y,
- Matrix modelview, Matrix projection, java.awt.Rectangle viewport)
+ Matrix modelview, Matrix projection)
{
if (modelview == null || projection == null)
{
@@ -544,12 +544,6 @@ public static Line computeRayFromScreenPoint(View view, double x, double y,
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
- if (viewport == null)
- {
- String message = Logging.getMessage("nullValue.RectangleIsNull");
- Logging.logger().severe(message);
- throw new IllegalArgumentException(message);
- }
// Compute a ray originating from the view, and passing through the screen point (x, y).
//
@@ -566,9 +560,8 @@ public static Line computeRayFromScreenPoint(View view, double x, double y,
if (eye == null)
return null;
- double yInGLCoords = viewport.height - y - 1;
- Vec4 a = view.unProject(new Vec4(x, yInGLCoords, 0, 0));
- Vec4 b = view.unProject(new Vec4(x, yInGLCoords, 1, 0));
+ Vec4 a = view.unProject(new Vec4(x, y, 0, 0));
+ Vec4 b = view.unProject(new Vec4(x, y, 1, 0));
if (a == null || b == null)
return null;
diff --git a/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java b/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java
index f429cc0b49..3d622eda72 100644
--- a/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java
+++ b/src/gov/nasa/worldwind/view/orbit/OrbitViewInputHandler.java
@@ -159,7 +159,6 @@ protected void onMoveTo(Position focalPosition, ViewInputAttributes.DeviceAttrib
}
}
- @SuppressWarnings("UnusedParameters")
protected void onMoveTo2D(Position focalPosition, ViewInputAttributes.DeviceAttributes deviceAttributes,
ViewInputAttributes.ActionAttributes actionAttribs)
{
@@ -314,7 +313,6 @@ protected void onHorizontalTranslateRel(Angle forwardChange, Angle sideChange,
}
}
- @SuppressWarnings("UnusedParameters")
protected void onHorizontalTranslate2D(double forwardInput, double sideInput,
double totalForwardInput, double totalSideInput,
ViewInputAttributes.DeviceAttributes deviceAttributes,
@@ -335,9 +333,9 @@ protected void onHorizontalTranslate2D(double forwardInput, double sideInput,
Point p1 = constrainToSourceBounds(this.getMouseDownPoint(), this.getWorldWindow());
Point p2 = constrainToSourceBounds(this.getMousePoint(), this.getWorldWindow());
Line ray1 = ViewUtil.computeRayFromScreenPoint(orbitView, p1.x, p1.y, this.mouseDownModelview,
- this.mouseDownProjection, this.mouseDownViewport);
+ this.mouseDownProjection);
Line ray2 = ViewUtil.computeRayFromScreenPoint(orbitView, p2.x, p2.y, this.mouseDownModelview,
- this.mouseDownProjection, this.mouseDownViewport);
+ this.mouseDownProjection);
// Compute a model coordinate plane passing through the position under the cursor when the mouse button was
// pressed. Fall back to a plane normal to the globe if the cursor was off the globe.
@@ -400,7 +398,6 @@ protected void onResetHeading(ViewInputAttributes.ActionAttributes actionAttribs
*
* @param actionAttribs input that caused the change.
*/
- @SuppressWarnings("UnusedParameters")
protected void onResetRoll(ViewInputAttributes.ActionAttributes actionAttribs)
{
View view = this.getView();
diff --git a/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java b/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java
index de6ad819d8..23dc2412e0 100644
--- a/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java
+++ b/src/gov/nasa/worldwindx/applications/antenna/AntennaAxes.java
@@ -37,6 +37,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.xml.stream.*;
import java.awt.*;
import java.io.IOException;
diff --git a/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java b/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java
index 5455ebed9f..3503bd4c49 100644
--- a/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java
+++ b/src/gov/nasa/worldwindx/applications/sar/render/TrackSegmentInfo.java
@@ -34,6 +34,8 @@
import gov.nasa.worldwindx.applications.sar.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
/**
diff --git a/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java b/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java
index 9444f7228d..b99607e25a 100644
--- a/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java
+++ b/src/gov/nasa/worldwindx/applications/sar/segmentplane/SegmentPlaneRenderer.java
@@ -40,6 +40,8 @@
import gov.nasa.worldwind.util.*;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import java.awt.*;
import java.nio.*;
import java.util.*;
diff --git a/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java b/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java
index 53e831a7c2..c8bf39e19a 100644
--- a/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java
+++ b/src/gov/nasa/worldwindx/applications/worldwindow/core/ToolTipAnnotation.java
@@ -98,7 +98,7 @@ protected void doRenderNow(DrawContext dc)
protected Point adjustDrawPointToViewport(Point point, Rectangle bounds, Rectangle viewport)
{
int x = point.x;
- int y = (int) viewport.getHeight() - point.y - 1;
+ int y = point.y;
if (x + this.getOffsetX() + bounds.getWidth() > viewport.getWidth())
x = (int) (viewport.getWidth() - bounds.getWidth()) - 1 - this.getOffsetX();
diff --git a/src/gov/nasa/worldwindx/examples/Annotations.java b/src/gov/nasa/worldwindx/examples/Annotations.java
index cd0e8972dc..866ba403c6 100644
--- a/src/gov/nasa/worldwindx/examples/Annotations.java
+++ b/src/gov/nasa/worldwindx/examples/Annotations.java
@@ -38,6 +38,8 @@
import gov.nasa.worldwindx.examples.util.PowerOfTwoPaddedImage;
import com.jogamp.opengl.*;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
import javax.swing.*;
import javax.swing.Box;
import javax.swing.border.*;
diff --git a/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java b/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java
index c432b47db4..9ace62fed7 100644
--- a/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java
+++ b/src/gov/nasa/worldwindx/examples/ContextMenusOnShapes.java
@@ -72,7 +72,6 @@ public void selected(SelectEvent event) {
}
}
- @SuppressWarnings({"UnusedDeclaration"})
protected void highlight(SelectEvent event, Object o) {
if (this.lastPickedPlacemark == o) {
return; // same thing selected
@@ -110,7 +109,7 @@ protected void showContextMenu(SelectEvent event) {
}
ContextMenu menu = new ContextMenu((Component) event.getSource(), menuInfo);
- menu.show(event.getMouseEvent());
+ menu.show(event.getAwtMousePt());
}
}
}
@@ -145,7 +144,7 @@ protected void makeMenuItems() {
}
}
- public void show(final MouseEvent event) {
+ public void show(final Point screenPt) {
JPopupMenu popup = new JPopupMenu();
popup.add(this.menuTitleItem);
@@ -156,7 +155,7 @@ public void show(final MouseEvent event) {
popup.add(subMenu);
}
- popup.show(sourceComponent, event.getX(), event.getY());
+ popup.show(sourceComponent, (int)screenPt.getX(), (int)screenPt.getY());
}
}
diff --git a/src/gov/nasa/worldwindx/examples/EGM2008Offsets.java b/src/gov/nasa/worldwindx/examples/EGM2008Offsets.java
new file mode 100644
index 0000000000..f2b403ca0d
--- /dev/null
+++ b/src/gov/nasa/worldwindx/examples/EGM2008Offsets.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
+ * Administrator of the National Aeronautics and Space Administration.
+ * All rights reserved.
+ *
+ * The NASA World Wind Java (WWJ) platform is 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.
+ *
+ * NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
+ * software:
+ *
+ * Jackson Parser – Licensed under Apache 2.0
+ * GDAL – Licensed under MIT
+ * JOGL – Licensed under Berkeley Software Distribution (BSD)
+ * Gluegen – Licensed under Berkeley Software Distribution (BSD)
+ *
+ * A complete listing of 3rd Party software notices and licenses included in
+ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
+ * notices and licenses PDF found in code directory.
+ */
+package gov.nasa.worldwindx.examples;
+
+import gov.nasa.worldwind.Model;
+import gov.nasa.worldwind.avlist.AVKey;
+import gov.nasa.worldwind.geom.LatLon;
+import gov.nasa.worldwind.geom.Position;
+import gov.nasa.worldwind.geom.Sector;
+import gov.nasa.worldwind.globes.Earth;
+import gov.nasa.worldwind.globes.Globe;
+import gov.nasa.worldwind.layers.RenderableLayer;
+import gov.nasa.worldwind.render.PointPlacemark;
+import gov.nasa.worldwind.util.EGM2008;
+import java.awt.Dimension;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import javax.swing.SwingUtilities;
+
+/**
+ * Shows how to apply EGM2008 offsets to Earth elevations.
+ *
+ * This EGM2008 data file is not included in the SDK due to its size. The data may be downloaded here:
+ * https://builds.worldwind.arc.nasa.gov/artifactory/EGM2008-Data/egm2008_25.dat
+ *
+ * This example looks for the EGM2008 data in the WorldWind src/config folder by default.
+ */
+public class EGM2008Offsets extends ApplicationTemplate
+{
+ public static class AppFrame extends ApplicationTemplate.AppFrame
+ {
+ /**
+ * Attempt to retrieve the best elevations for a specified list of locations. The elevations returned are the best currently
+ * available for the data set and the area bounding the locations. Since the necessary elevation data might not
+ * be in memory at the time of the call, this method iterates until the necessary elevation data is in memory
+ * and can be used to determine the locations elevations.
+ *
+ * @param locations a list of locations to determine elevations for
+ */
+ public void loadBestElevations(ArrayList locations)
+ {
+ Globe globe = this.getWwd().getModel().getGlobe();
+ ArrayList sectors = new ArrayList<>();
+ ArrayList> locationsList = new ArrayList<>();
+ double delta = 0.0001;
+ for (LatLon ll : locations)
+ {
+ double lat = ll.latitude.degrees;
+ double lon = ll.longitude.degrees;
+ sectors.add(Sector.fromDegrees(lat, lat + delta, lon, lon + delta));
+ ArrayList sectorLocations = new ArrayList<>();
+ sectorLocations.add(ll);
+ sectorLocations.add(LatLon.fromDegrees(lat + delta, lon + delta));
+ locationsList.add(sectorLocations);
+ }
+
+ double[] targetResolutions = new double[sectors.size()];
+ double[] actualResolutions = new double[sectors.size()];
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ targetResolutions[i] = globe.getElevationModel().getBestResolution(sectors.get(i));
+ }
+ boolean resolutionsAchieved = false;
+ double[] elevations = new double[2];
+ while (!resolutionsAchieved)
+ {
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ actualResolutions[i] = globe.getElevations(sectors.get(i), locationsList.get(i), targetResolutions[i], elevations);
+ }
+
+ resolutionsAchieved = true;
+ for (int i = 0, len = actualResolutions.length; i < len && resolutionsAchieved; i++)
+ {
+ resolutionsAchieved = actualResolutions[i] <= targetResolutions[i];
+ }
+ if (!resolutionsAchieved)
+ {
+ try
+ {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public AppFrame()
+ {
+ Model m = this.wwjPanel.getWwd().getModel();
+ Earth earth = (Earth) m.getGlobe();
+ final RenderableLayer layer = new RenderableLayer();
+ double[] locations = new double[]
+ {
+ 37.0, -119.0,
+ 36.0, -117.016667,
+ 89.0, 0.0,
+ -80.0, 0.0,
+ -90.0, 0.0
+ };
+ EGM2008 egm2008Offsets = new EGM2008("config/egm2008_25.dat");
+ boolean egmAvailable = egm2008Offsets.isEGMDataAvailable();
+ if (!egmAvailable)
+ {
+ System.out.println("*** EGM 2008 data not available.");
+ }
+
+ // Run the elevation query in a separate thread to avoid locking up the user interface
+ Thread t = new Thread(() ->
+ {
+ ArrayList elevLocations = new ArrayList<>();
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ elevLocations.add(LatLon.fromDegrees(locations[i], locations[i + 1]));
+ }
+
+ loadBestElevations(elevLocations);
+
+ try
+ {
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ Position pos = Position.fromDegrees(locations[i], locations[i + 1], 0);
+ PointPlacemark placemark = new PointPlacemark(pos);
+ String label = String.format("lat: %7.4f, lon: %7.4f", locations[i], locations[i + 1]);
+ float egmOffset = egm2008Offsets.getOffset(pos.latitude, pos.longitude);
+ double elevation = earth.getElevation(pos.latitude, pos.longitude);
+ if (egmAvailable)
+ {
+ placemark.setValue(AVKey.DISPLAY_NAME, String.format("EGM2008 Offset: %7.4f\nEllipsoid elevation:%7.4f\nEGM2008 Adjusted elevation: %7.4f",
+ egmOffset, elevation, elevation - egmOffset));
+ }
+ else
+ {
+ placemark.setValue(AVKey.DISPLAY_NAME, String.format("EGM2008 Offset: N/A\nEllipsoid elevation:%7.4f\nEGM2008 Adjusted elevation: N/A",
+ elevation));
+ }
+ placemark.setLabelText(label);
+ layer.addRenderable(placemark);
+ }
+ }
+ catch (IOException iex)
+ {
+ iex.printStackTrace();
+ }
+
+ SwingUtilities.invokeLater(() ->
+ {
+ System.out.println("Elevations retrieved");
+ getWwd().redraw();
+ });
+ });
+ t.start();
+
+ try
+ {
+ // Test offsets for some coordinates
+ float lat = 47;
+ float lon = -94;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 37;
+ lon = -119;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ // Try previous coordinates to verify caching
+ lat = 47;
+ lon = -94;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 37;
+ lon = -119;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 47.02f;
+ lon = -94.02f;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ float gridResolution = (float) EGM2008.GRID_RESOLUTION;
+ lat = 47 + gridResolution;
+ lon = -94 - gridResolution;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 36.0f;
+ lon = -117.0f;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ lat = 36.0f;
+ lon = -117.041666666667f;
+ System.out.println(lat + "," + lon + "," + egm2008Offsets.getOffset(lat, lon));
+
+ System.out.println();
+ }
+ catch (IOException iex)
+ {
+ iex.printStackTrace();
+ }
+
+ this.wwjPanel.toolTipController.setAnnotationSize(new Dimension(500, 0));
+ insertBeforeCompass(getWwd(), layer);
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ ApplicationTemplate.start("WorldWind EGM2008 Offsets", AppFrame.class);
+ }
+}
diff --git a/src/gov/nasa/worldwindx/examples/EGM96Offsets.java b/src/gov/nasa/worldwindx/examples/EGM96Offsets.java
index a64d11b1bc..39b7adf6b0 100644
--- a/src/gov/nasa/worldwindx/examples/EGM96Offsets.java
+++ b/src/gov/nasa/worldwindx/examples/EGM96Offsets.java
@@ -2,39 +2,50 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is 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.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
*/
-
package gov.nasa.worldwindx.examples;
import gov.nasa.worldwind.Model;
+import gov.nasa.worldwind.avlist.AVKey;
+import gov.nasa.worldwind.geom.LatLon;
+import gov.nasa.worldwind.geom.Position;
+import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.globes.Earth;
+import gov.nasa.worldwind.globes.Globe;
+import gov.nasa.worldwind.layers.RenderableLayer;
+import gov.nasa.worldwind.render.PointPlacemark;
+import gov.nasa.worldwind.util.EGM96;
+import java.awt.Dimension;
import java.io.IOException;
+import java.util.ArrayList;
+import javax.swing.SwingUtilities;
/**
* Shows how to apply EGM96 offsets to the Earth.
+ *
* @author tag
* @version $Id: EGM96Offsets.java 1501 2013-07-11 15:59:11Z tgaskins $
*/
@@ -42,17 +53,118 @@ public class EGM96Offsets extends ApplicationTemplate
{
public static class AppFrame extends ApplicationTemplate.AppFrame
{
+ /**
+ * Attempt to retrieve the best elevations for a specified list of locations. The elevations returned are the best currently
+ * available for the data set and the area bounding the locations. Since the necessary elevation data might not
+ * be in memory at the time of the call, this method iterates until the necessary elevation data is in memory
+ * and can be used to determine the locations elevations.
+ *
+ * @param locations a list of locations to determine elevations for
+ */
+ public void loadBestElevations(ArrayList locations)
+ {
+ Globe globe = this.getWwd().getModel().getGlobe();
+ ArrayList sectors = new ArrayList<>();
+ ArrayList> locationsList = new ArrayList<>();
+ double delta = 0.0001;
+ for (LatLon ll : locations)
+ {
+ double lat = ll.latitude.degrees;
+ double lon = ll.longitude.degrees;
+ sectors.add(Sector.fromDegrees(lat, lat + delta, lon, lon + delta));
+ ArrayList sectorLocations = new ArrayList<>();
+ sectorLocations.add(ll);
+ sectorLocations.add(LatLon.fromDegrees(lat + delta, lon + delta));
+ locationsList.add(sectorLocations);
+ }
+
+ double[] targetResolutions = new double[sectors.size()];
+ double[] actualResolutions = new double[sectors.size()];
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ targetResolutions[i] = globe.getElevationModel().getBestResolution(sectors.get(i));
+ }
+ boolean resolutionsAchieved = false;
+ double[] elevations = new double[2];
+ while (!resolutionsAchieved)
+ {
+ for (int i = 0, len = sectors.size(); i < len; i++)
+ {
+ actualResolutions[i] = globe.getElevations(sectors.get(i), locationsList.get(i), targetResolutions[i], elevations);
+ }
+
+ resolutionsAchieved = true;
+ for (int i = 0, len = actualResolutions.length; i < len && resolutionsAchieved; i++)
+ {
+ resolutionsAchieved = actualResolutions[i] <= targetResolutions[i];
+ }
+ if (!resolutionsAchieved)
+ {
+ try
+ {
+ Thread.sleep(200);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
public AppFrame()
{
Model m = this.wwjPanel.getWwd().getModel();
+ Earth earth = (Earth) m.getGlobe();
try
{
- ((Earth) m.getGlobe()).applyEGMA96Offsets("config/EGM96.dat");
+ earth.applyEGMA96Offsets("config/EGM96.dat");
}
catch (IOException e)
{
e.printStackTrace();
}
+ final RenderableLayer layer = new RenderableLayer();
+ double[] locations = new double[]
+ {
+ 37.0, -119.0,
+ 36.0, -117.016667,
+ 89.0, 0.0,
+ -80.0, 0.0,
+ -90.0, 0.0
+ };
+ Thread t = new Thread(() ->
+ {
+ ArrayList elevLocations = new ArrayList<>();
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ elevLocations.add(LatLon.fromDegrees(locations[i], locations[i + 1]));
+ }
+
+ loadBestElevations(elevLocations);
+
+ EGM96 egm96Offsets = earth.getEGM96();
+ for (int i = 0; i < locations.length; i += 2)
+ {
+ Position pos = Position.fromDegrees(locations[i], locations[i + 1], 0);
+ PointPlacemark placemark = new PointPlacemark(pos);
+ String label = String.format("lat: %7.4f, lon: %7.4f", locations[i], locations[i + 1]);
+ placemark.setValue(AVKey.DISPLAY_NAME, String.format("EGM96 Offset: %7.4f\nEGM96 Adjusted elevation: %7.4f",
+ egm96Offsets.getOffset(pos.latitude, pos.longitude),
+ earth.getElevation(pos.latitude, pos.longitude)));
+ placemark.setLabelText(label);
+ layer.addRenderable(placemark);
+ }
+ SwingUtilities.invokeLater(() ->
+ {
+ System.out.println("Elevations retrieved");
+ getWwd().redraw();
+ });
+ });
+ t.start();
+
+ this.wwjPanel.toolTipController.setAnnotationSize(new Dimension(500, 0));
+ insertBeforeCompass(getWwd(), layer);
}
}
diff --git a/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java b/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java
index 85d358249b..69b42dfc81 100644
--- a/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java
+++ b/src/gov/nasa/worldwindx/examples/analytics/AnalyticSurfaceLegend.java
@@ -37,6 +37,8 @@
import java.text.Format;
import java.util.ArrayList;
+import com.jogamp.opengl.util.awt.TextRenderer;
+
/**
* @author dcollins
* @version $Id: AnalyticSurfaceLegend.java 2053 2014-06-10 20:16:57Z tgaskins $
@@ -158,7 +160,8 @@ public int getHeight(DrawContext dc)
return this.screenImage.getImageHeight(dc);
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc == null)
{
@@ -225,27 +228,32 @@ public static AnalyticSurfaceLegend.LabelAttributes createLegendLabelAttributes(
{
return new AnalyticSurfaceLegend.LabelAttributes()
{
- public double getValue()
+ @Override
+ public double getValue()
{
return value;
}
- public String getText()
+ @Override
+ public String getText()
{
return text;
}
- public Font getFont()
+ @Override
+ public Font getFont()
{
return font;
}
- public Color getColor()
+ @Override
+ public Color getColor()
{
return color;
}
- public Point2D getOffset()
+ @Override
+ public Point2D getOffset()
{
return new Point2D.Double(xOffset, yOffset);
}
@@ -320,18 +328,16 @@ protected void drawLabel(DrawContext dc, LabelAttributes attr, double x, double
tr.beginRendering(viewport.width, viewport.height);
try
{
- double yInGLCoords = viewport.height - y - 1;
-
// Draw the text outline, in a contrasting color.
tr.setColor(WWUtil.computeContrastingColor(color));
- tr.draw(text, (int) x - 1, (int) yInGLCoords - 1);
- tr.draw(text, (int) x + 1, (int) yInGLCoords - 1);
- tr.draw(text, (int) x + 1, (int) yInGLCoords + 1);
- tr.draw(text, (int) x - 1, (int) yInGLCoords + 1);
+ tr.draw(text, (int) x - 1, (int) y - 1);
+ tr.draw(text, (int) x + 1, (int) y - 1);
+ tr.draw(text, (int) x + 1, (int) y + 1);
+ tr.draw(text, (int) x - 1, (int) y + 1);
// Draw the text over its outline, in the specified color.
tr.setColor(color);
- tr.draw(text, (int) x, (int) yInGLCoords);
+ tr.draw(text, (int) x, (int) y);
}
finally
{
@@ -411,7 +417,8 @@ public LabelRenderable(AnalyticSurfaceLegend legend, LabelAttributes attr, doubl
this.orderedLabel = new OrderedLabel(legend, attr, x, y, halign, valign);
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
dc.addOrderedRenderable(this.orderedLabel);
}
@@ -437,17 +444,20 @@ public OrderedLabel(AnalyticSurfaceLegend legend, LabelAttributes attr, double x
this.valign = valign;
}
- public double getDistanceFromEye()
+ @Override
+ public double getDistanceFromEye()
{
return 0;
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
this.legend.drawLabel(dc, this.attr, this.x, this.y, this.halign, this.valign);
}
- public void pick(DrawContext dc, Point pickPoint)
+ @Override
+ public void pick(DrawContext dc, Point pickPoint)
{
// Intentionally left blank.
}
diff --git a/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java b/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java
index 12b60e1fa9..759426f6f4 100644
--- a/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java
+++ b/src/gov/nasa/worldwindx/examples/kml/KMLViewer.java
@@ -37,7 +37,6 @@
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.ogc.kml.*;
import gov.nasa.worldwind.ogc.kml.impl.KMLController;
-import gov.nasa.worldwind.render.Offset;
import gov.nasa.worldwind.util.*;
import javax.swing.*;
@@ -76,7 +75,7 @@ public AppFrame()
// Add the on-screen layer tree, refreshing model with the WorldWindow's current layer list. We
// intentionally refresh the tree's model before adding the layer that contains the tree itself. This
// prevents the tree's layer from being displayed in the tree itself.
- this.layerTree = new LayerTree(new Offset(20d, 160d, AVKey.PIXELS, AVKey.INSET_PIXELS));
+ this.layerTree = new LayerTree(new Point(20, 160));
this.layerTree.getModel().refresh(this.getWwd().getModel().getLayers());
// Set up a layer to display the on-screen layer tree in the WorldWindow. This layer is not displayed in
@@ -119,7 +118,8 @@ protected void addDocumentLayer(KMLRoot document)
// Set up to receive SSLHandshakeExceptions that occur during resource retrieval.
WorldWind.getRetrievalService().setSSLExceptionListener(new RetrievalService.SSLExceptionListener()
{
- public void onException(Throwable e, String path)
+ @Override
+ public void onException(Throwable e, String path)
{
System.out.println(path);
System.out.println(e);
@@ -164,14 +164,16 @@ protected void addKMLLayer(KMLRoot kmlRoot)
// we ensure that the network link tree view appearance is consistent with the KML specification.
layerNode.addPropertyChangeListener(AVKey.RETRIEVAL_STATE_SUCCESSFUL, new PropertyChangeListener()
{
- public void propertyChange(final PropertyChangeEvent event)
+ @Override
+ public void propertyChange(final PropertyChangeEvent event)
{
if (event.getSource() instanceof KMLNetworkLinkTreeNode)
{
// Manipulate the tree on the EDT.
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
((KMLNetworkLinkTreeNode) event.getSource()).expandOpenContainers(layerTree);
getWwd().redraw();
@@ -213,7 +215,8 @@ public WorkerThread(Object kmlSource, AppFrame appFrame)
* If loading the KML source fails, this prints the exception and its stack trace to the standard error stream,
* but otherwise does nothing.
*/
- public void run()
+ @Override
+ public void run()
{
try
{
@@ -226,7 +229,8 @@ public void run()
final KMLRoot finalKMLRoot = kmlRoot;
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
appFrame.addKMLLayer(finalKMLRoot);
}
@@ -287,7 +291,8 @@ protected static void makeMenu(final AppFrame appFrame)
JMenuItem openFileMenuItem = new JMenuItem(new AbstractAction("Open File...")
{
- public void actionPerformed(ActionEvent actionEvent)
+ @Override
+ public void actionPerformed(ActionEvent actionEvent)
{
try
{
@@ -311,7 +316,8 @@ public void actionPerformed(ActionEvent actionEvent)
JMenuItem openURLMenuItem = new JMenuItem(new AbstractAction("Open URL...")
{
- public void actionPerformed(ActionEvent actionEvent)
+ @Override
+ public void actionPerformed(ActionEvent actionEvent)
{
try
{
@@ -334,6 +340,7 @@ public void actionPerformed(ActionEvent actionEvent)
public static void main(String[] args)
{
//noinspection UnusedDeclaration
- final AppFrame af = (AppFrame) start("WorldWind KML Viewer", AppFrame.class);
+ @SuppressWarnings("unused")
+ final AppFrame af = (AppFrame) start("WorldWind KML Viewer", AppFrame.class);
}
}
diff --git a/src/gov/nasa/worldwindx/examples/util/BalloonController.java b/src/gov/nasa/worldwindx/examples/util/BalloonController.java
index f1708c1e95..ccd2c2abd9 100644
--- a/src/gov/nasa/worldwindx/examples/util/BalloonController.java
+++ b/src/gov/nasa/worldwindx/examples/util/BalloonController.java
@@ -163,6 +163,19 @@ public void setBalloonOffset(int balloonOffset)
//*********************** Event handling *****************************//
//********************************************************************//
+ /**
+ * Construct a mouse event with GL surface screen coordinates
+ * @param e
+ * @return
+ */
+ private MouseEvent glMouseEvent(MouseEvent awtMouseEvent) {
+ int[] GLmousePt = wwd.getSceneController().getDrawContext().awtPointToGLpoint(awtMouseEvent.getPoint());
+ MouseEvent e = new MouseEvent(awtMouseEvent.getComponent(), awtMouseEvent.getID(),
+ awtMouseEvent.getWhen(), awtMouseEvent.getModifiersEx(),
+ awtMouseEvent.getClickCount(), GLmousePt[0], GLmousePt[1], awtMouseEvent.isPopupTrigger(),
+ awtMouseEvent.getButton());
+ return e;
+ }
/**
* Handle a mouse click. If the top picked object has a balloon attached to it the balloon will be made visible. A
* balloon may be attached to a KML feature, or to any picked object though {@link AVKey#BALLOON}.
@@ -170,11 +183,13 @@ public void setBalloonOffset(int balloonOffset)
* @param e Mouse event
*/
@Override
- public void mouseClicked(MouseEvent e)
+ public void mouseClicked(MouseEvent awtEv)
{
- if (e == null || e.isConsumed())
+ if (awtEv == null || awtEv.isConsumed())
return;
+ MouseEvent e = glMouseEvent(awtEv);
+
// Implementation note: handle the balloon with a mouse listener instead of a select listener so that the balloon
// can be turned off if the user clicks on the terrain.
try
@@ -219,6 +234,9 @@ public void mouseClicked(MouseEvent e)
// Wrap the handler in a try/catch to keep exceptions from bubbling up
Logging.logger().warning(ex.getMessage() != null ? ex.getMessage() : ex.toString());
}
+
+ if (e.isConsumed())
+ awtEv.consume();
}
@Override
@@ -248,7 +266,8 @@ else if (this.resizeController != null && !this.resizeController.isResizing())
}
}
- @SuppressWarnings("deprecation")
+ @Override
+ @SuppressWarnings("deprecation")
public void selected(SelectEvent event)
{
if (event == null || event.isConsumed()
@@ -984,8 +1003,7 @@ protected void showBalloon(Balloon balloon, Position position)
Vec4 screenVec4 = this.wwd.getView().project(
this.wwd.getModel().getGlobe().computePointFromPosition(position));
- Point screenPoint = new Point((int) screenVec4.x,
- (int) (this.wwd.getView().getViewport().height - screenVec4.y));
+ Point screenPoint = new Point((int) screenVec4.x, (int) screenVec4.y);
// If the balloon is attached to the screen rather than the globe, move it to the
// current point. Otherwise move it to the position under the current point.
@@ -1327,8 +1345,7 @@ protected Point getBalloonPointForScreenOverlay(KMLScreenOverlay overlay)
Rectangle viewport = this.wwd.getView().getViewport();
Point2D point2D = offset.computeOffset(viewport.width, viewport.height, 1d, 1d);
- int y = (int) point2D.getY();
- return new Point((int) point2D.getX(), viewport.height - y);
+ return new Point((int) point2D.getX(), (int) point2D.getY());
}
/**
@@ -1504,7 +1521,8 @@ public DocumentRetrievalTask(String url, KMLRoot context, String featureRef, lon
* gov.nasa.worldwind.ogc.kml.KMLRoot, String)}. If an exception occurs, or the timeout is exceeded, schedule a
* callback on the EDT to {@link BalloonController#onDocumentFailed(String, Exception)}
*/
- public void run()
+ @Override
+ public void run()
{
KMLRoot root = null;
@@ -1544,7 +1562,8 @@ else if (docSource != null)
final KMLRoot pinnedRoot = root; // Final ref that can be accessed by anonymous class
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
BalloonController.this.onDocumentLoaded(docUrl, pinnedRoot, featureRef);
}
@@ -1558,7 +1577,8 @@ public void run()
// Schedule a callback on the EDT to report the error to the BalloonController
SwingUtilities.invokeLater(new Runnable()
{
- public void run()
+ @Override
+ public void run()
{
BalloonController.this.onDocumentFailed(docUrl, e);
}
diff --git a/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java b/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java
index 57dd7465f2..24a72f8714 100644
--- a/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java
+++ b/src/gov/nasa/worldwindx/examples/util/LayerManagerLayer.java
@@ -644,7 +644,7 @@ protected void drag(SelectEvent event)
Point cursorOffset = new Point(event.getMouseEvent().getPoint().x - this.dragRefCursorPoint.x,
event.getMouseEvent().getPoint().y - this.dragRefCursorPoint.y);
Point targetPoint = new Point(this.dragRefPoint.x + cursorOffset.x,
- this.dragRefPoint.y - cursorOffset.y);
+ this.dragRefPoint.y + cursorOffset.y);
this.moveTo(targetPoint);
event.consume();
}
diff --git a/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java b/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java
index ec266fd0b8..b6a42bdbbd 100644
--- a/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java
+++ b/src/gov/nasa/worldwindx/examples/util/ScreenSelector.java
@@ -163,8 +163,8 @@ public void endSelection(Point point)
maxX = this.startPoint.x;
}
- // Compute the selection's extremes along the y axis. The selection is defined in AWT screen coordinates, so
- // the origin is in the upper left corner and the y axis points down.
+ // Compute the selection's extremes along the y axis. The selection is defined in GL surface coordinates, so
+ // the origin is in the lower left corner and the y axis points up.
double minY, maxY;
if (this.startPoint.y < this.endPoint.y)
{
@@ -185,7 +185,7 @@ public void endSelection(Point point)
if (minY == maxY && minX < maxX)
minY = maxY - 1;
- this.rect.setRect(minX, maxY, maxX - minX, maxY - minY);
+ this.rect.setRect(minX, minY, maxX - minX, maxY - minY);
}
public void clearSelection()
@@ -215,17 +215,20 @@ public void setBorderColor(Color color)
this.borderColor = color;
}
- public double getDistanceFromEye()
+ @Override
+ public double getDistanceFromEye()
{
return 0; // Screen rectangle is drawn on top of other ordered renderables, except other screen objects.
}
- public void pick(DrawContext dc, Point pickPoint)
+ @Override
+ public void pick(DrawContext dc, Point pickPoint)
{
// Intentionally left blank. SelectionRectangle is not pickable.
}
- public void render(DrawContext dc)
+ @Override
+ public void render(DrawContext dc)
{
if (dc == null)
{
@@ -270,7 +273,7 @@ protected void drawOrderedRenderable(DrawContext dc)
gl.glOrtho(0, viewport.getWidth(), 0, viewport.getHeight(), -1, 1); // l, r, b, t, n, f
this.BEogsh.pushModelviewIdentity(gl);
gl.glTranslated(0.5, 0.5, 0.0);
- gl.glTranslated(selection.getX(), viewport.getHeight() - selection.getY(), 0);
+ gl.glTranslated(selection.getX(), selection.getY(), 0);
gl.glScaled(selection.getWidth() - 1, selection.getHeight() - 1, 1);
// Disable the depth test and enable blending so this screen rectangle appears on top of the existing
@@ -460,12 +463,14 @@ protected void sendMessage(Message message)
}
}
- public void mouseClicked(MouseEvent mouseEvent)
+ @Override
+ public void mouseClicked(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse clicked events.
}
- public void mousePressed(MouseEvent mouseEvent)
+ @Override
+ public void mousePressed(MouseEvent mouseEvent)
{
if (mouseEvent == null) // Ignore null events.
return;
@@ -478,7 +483,8 @@ public void mousePressed(MouseEvent mouseEvent)
mouseEvent.consume(); // Consume the mouse event to prevent the view from responding to it.
}
- public void mouseReleased(MouseEvent mouseEvent)
+ @Override
+ public void mouseReleased(MouseEvent mouseEvent)
{
if (mouseEvent == null) // Ignore null events.
return;
@@ -491,17 +497,20 @@ public void mouseReleased(MouseEvent mouseEvent)
mouseEvent.consume(); // Consume the mouse event to prevent the view from responding to it.
}
- public void mouseEntered(MouseEvent mouseEvent)
+ @Override
+ public void mouseEntered(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse entered events.
}
- public void mouseExited(MouseEvent mouseEvent)
+ @Override
+ public void mouseExited(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse exited events.
}
- public void mouseDragged(MouseEvent mouseEvent)
+ @Override
+ public void mouseDragged(MouseEvent mouseEvent)
{
if (mouseEvent == null) // Ignore null events.
return;
@@ -513,7 +522,8 @@ public void mouseDragged(MouseEvent mouseEvent)
mouseEvent.consume(); // Consume the mouse event to prevent the view from responding to it.
}
- public void mouseMoved(MouseEvent mouseEvent)
+ @Override
+ public void mouseMoved(MouseEvent mouseEvent)
{
// Intentionally left blank. ScreenSelector does not respond to mouse moved events.
}
@@ -530,8 +540,7 @@ protected void selectionStarted(MouseEvent mouseEvent)
this.sendMessage(new Message(SELECTION_STARTED, this));
}
- @SuppressWarnings({"UnusedParameters"})
- protected void selectionEnded(MouseEvent mouseEvent)
+ protected void selectionEnded(@SuppressWarnings("unused") MouseEvent mouseEvent)
{
this.selectionRect.clearSelection();
this.getWwd().getSceneController().setPickRectangle(null);
@@ -577,19 +586,20 @@ protected Point limitPointToWorldWindow(Point point)
int x = point.x;
if (x < viewport.x)
x = viewport.x;
- if (x > viewport.x + viewport.width)
- x = viewport.x + viewport.width;
+ if (x >= viewport.x + viewport.width)
+ x = viewport.x + viewport.width - 1;
int y = point.y;
if (y < viewport.y)
y = viewport.y;
- if (y > viewport.y + viewport.height)
- y = viewport.y + viewport.height;
+ if (y >= viewport.y + viewport.height)
+ y = viewport.y + viewport.height - 1;
return new Point(x, y);
}
- public void selected(SelectEvent event)
+ @Override
+ public void selected(SelectEvent event)
{
try
{
diff --git a/src/gov/nasa/worldwindx/examples/util/StatusLayer.java b/src/gov/nasa/worldwindx/examples/util/StatusLayer.java
index 9544a97cee..76f9d4c6e5 100644
--- a/src/gov/nasa/worldwindx/examples/util/StatusLayer.java
+++ b/src/gov/nasa/worldwindx/examples/util/StatusLayer.java
@@ -27,6 +27,7 @@
*/
package gov.nasa.worldwindx.examples.util;
+import com.jogamp.opengl.util.awt.TextRenderer;
import com.jogamp.opengl.util.texture.*;
import gov.nasa.worldwind.*;
import gov.nasa.worldwind.event.*;
diff --git a/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java b/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java
index 5113946db4..ab47aad371 100644
--- a/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java
+++ b/src/gov/nasa/worldwindx/examples/util/ToolTipAnnotation.java
@@ -116,7 +116,7 @@ protected void doRenderNow(DrawContext dc)
protected Point adjustDrawPointToViewport(Point point, Rectangle bounds, Rectangle viewport)
{
int x = point.x;
- int y = (int) viewport.getHeight() - point.y - 1;
+ int y = point.y;
if (x + this.getOffsetX() + bounds.getWidth() > viewport.getWidth())
x = (int) (viewport.getWidth() - bounds.getWidth()) - 1 - this.getOffsetX();
diff --git a/src/gov/nasa/worldwindx/examples/util/ToolTipController.java b/src/gov/nasa/worldwindx/examples/util/ToolTipController.java
index 0cadd531d9..05e58a7e63 100644
--- a/src/gov/nasa/worldwindx/examples/util/ToolTipController.java
+++ b/src/gov/nasa/worldwindx/examples/util/ToolTipController.java
@@ -2,25 +2,25 @@
* Copyright 2006-2009, 2017, 2020 United States Government, as represented by the
* Administrator of the National Aeronautics and Space Administration.
* All rights reserved.
- *
+ *
* The NASA World Wind Java (WWJ) platform is 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.
- *
+ *
* NASA World Wind Java (WWJ) also contains the following 3rd party Open Source
* software:
- *
+ *
* Jackson Parser – Licensed under Apache 2.0
* GDAL – Licensed under MIT
* JOGL – Licensed under Berkeley Software Distribution (BSD)
* Gluegen – Licensed under Berkeley Software Distribution (BSD)
- *
+ *
* A complete listing of 3rd Party software notices and licenses included in
* NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party
* notices and licenses PDF found in code directory.
@@ -34,6 +34,7 @@
import gov.nasa.worldwindx.examples.ApplicationTemplate;
import gov.nasa.worldwind.layers.*;
import gov.nasa.worldwind.util.*;
+import java.awt.Dimension;
/**
* Controls display of tool tips on picked objects. Any shape implementing {@link AVList} can participate. Shapes
@@ -52,6 +53,7 @@ public class ToolTipController implements SelectListener, Disposable
protected Object lastHoverObject;
protected AnnotationLayer layer;
protected ToolTipAnnotation annotation;
+ protected Dimension annotationSize = null;
/**
* Create a controller for a specified {@link WorldWindow} that displays tool tips on hover and/or rollover.
@@ -84,6 +86,16 @@ public ToolTipController(WorldWindow wwd)
this.wwd.addSelectListener(this);
}
+ public Dimension getAnnotationSize()
+ {
+ return this.annotationSize;
+ }
+
+ public void setAnnotationSize(Dimension value)
+ {
+ this.annotationSize = value;
+ }
+
public void dispose()
{
this.wwd.removeSelectListener(this);
@@ -91,14 +103,14 @@ public void dispose()
protected String getHoverText(SelectEvent event)
{
- return event.getTopObject() != null && event.getTopObject() instanceof AVList ?
- ((AVList) event.getTopObject()).getStringValue(this.hoverKey) : null;
+ return event.getTopObject() != null && event.getTopObject() instanceof AVList
+ ? ((AVList) event.getTopObject()).getStringValue(this.hoverKey) : null;
}
protected String getRolloverText(SelectEvent event)
{
- return event.getTopObject() != null && event.getTopObject() instanceof AVList ?
- ((AVList) event.getTopObject()).getStringValue(this.rolloverKey) : null;
+ return event.getTopObject() != null && event.getTopObject() instanceof AVList
+ ? ((AVList) event.getTopObject()).getStringValue(this.rolloverKey) : null;
}
public void selected(SelectEvent event)
@@ -167,6 +179,7 @@ protected void showToolTip(SelectEvent event, String text)
else
{
annotation = new ToolTipAnnotation(text);
+ annotation.getAttributes().setSize(this.annotationSize);
}
if (layer == null)