/*
Copyright (C) 2001, 2007 United States Government as represented by
the Administrator of the National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.view;
import gov.nasa.worldwind.View;
import gov.nasa.worldwind.ViewStateIterator;
import gov.nasa.worldwind.WWObjectImpl;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.Matrix;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.Logging;
import javax.media.opengl.GL;
/**
* @author dcollins
* @version $Id: AbstractView.java 4994 2008-04-09 18:15:52Z dcollins $
*/
public abstract class AbstractView extends WWObjectImpl implements View
{
private boolean detectCollisions = true;
private boolean hadCollisions;
private ViewStateIterator viewStateIterator;
public boolean isDetectCollisions()
{
return this.detectCollisions;
}
public void setDetectCollisions(boolean detectCollisions)
{
this.detectCollisions = detectCollisions;
}
public boolean hadCollisions()
{
boolean result = this.hadCollisions;
this.hadCollisions = false;
return result;
}
// TODO
// Separate control should be provided over whether the View will detect collisions
// which reports through hadCollisions() and flagHadCollisions(),
// and whether the View will resolve collisions itself,
// something along the lines of isResolveCollisions.
// At the same time, flagHadCollisions() should be made part of the public View interface.
protected void flagHadCollisions()
{
this.hadCollisions = true;
}
public void stopMovement()
{
forceStopStateIterators();
firePropertyChange(VIEW_STOPPED, null, this);
}
public void apply(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (dc.getGL() == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGLIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (dc.getGlobe() == null)
{
String message = Logging.getMessage("layers.AbstractLayer.NoGlobeSpecifiedInDrawingContext");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
updateStateIterator();
doApply(dc);
}
protected abstract void doApply(DrawContext dc);
public Matrix pushReferenceCenter(DrawContext dc, Vec4 referenceCenter)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (dc.getGL() == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGLIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
if (referenceCenter == null)
{
String message = Logging.getMessage("nullValue.PointIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
Matrix modelview = getModelviewMatrix();
// Compute a new model-view matrix with origin at referenceCenter.
Matrix matrix = null;
if (modelview != null)
matrix = modelview.multiply(Matrix.fromTranslation(referenceCenter));
GL gl = dc.getGL();
// Store the current matrix-mode state.
int[] matrixMode = new int[1];
gl.glGetIntegerv(GL.GL_MATRIX_MODE, matrixMode, 0);
if (matrixMode[0] != GL.GL_MODELVIEW)
gl.glMatrixMode(GL.GL_MODELVIEW);
// Push and load a new model-view matrix to the current OpenGL context held by 'dc'.
gl.glPushMatrix();
if (matrix != null)
{
double[] matrixArray = new double[16];
matrix.toArray(matrixArray, 0, false);
gl.glLoadMatrixd(matrixArray, 0);
}
// Restore matrix-mode state.
if (matrixMode[0] != GL.GL_MODELVIEW)
gl.glMatrixMode(matrixMode[0]);
return matrix;
}
public void popReferenceCenter(DrawContext dc)
{
if (dc == null)
{
String message = Logging.getMessage("nullValue.DrawContextIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (dc.getGL() == null)
{
String message = Logging.getMessage("nullValue.DrawingContextGLIsNull");
Logging.logger().severe(message);
throw new IllegalStateException(message);
}
GL gl = dc.getGL();
// Store the current matrix-mode state.
int[] matrixMode = new int[1];
gl.glGetIntegerv(GL.GL_MATRIX_MODE, matrixMode, 0);
// Pop a model-view matrix off the current OpenGL context held by 'dc'.
if (matrixMode[0] != GL.GL_MODELVIEW)
gl.glMatrixMode(GL.GL_MODELVIEW);
// Pop the top model-view matrix.
gl.glPopMatrix();
// Restore matrix-mode state.
if (matrixMode[0] != GL.GL_MODELVIEW)
gl.glMatrixMode(matrixMode[0]);
}
public void applyStateIterator(ViewStateIterator viewStateIterator)
{
ViewStateIterator oldIterator = this.viewStateIterator;
this.viewStateIterator = viewStateIterator;
if (this.viewStateIterator != null)
{
this.viewStateIterator = this.viewStateIterator.coalesceWith(this, oldIterator);
firePropertyChange(AVKey.VIEW, null, this);
}
}
public boolean hasStateIterator()
{
return this.viewStateIterator != null;
}
public void stopStateIterators()
{
forceStopStateIterators();
}
private void updateStateIterator()
{
if (this.viewStateIterator != null)
{
if (this.viewStateIterator.hasNextState(this))
{
this.viewStateIterator.nextState(this);
firePropertyChange(AVKey.VIEW, null, this);
}
else
{
forceStopStateIterators();
firePropertyChange(AVKey.VIEW_QUIET, null, this);
}
}
}
private void forceStopStateIterators()
{
this.viewStateIterator = null;
}
}