/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions 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 the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.ui.hud;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Stack;
import org.jagatoo.input.InputSystem;
import org.jagatoo.input.devices.Mouse;
import org.jagatoo.input.devices.components.ControllerAxis;
import org.jagatoo.input.devices.components.ControllerButton;
import org.jagatoo.input.devices.components.DeviceComponent;
import org.jagatoo.input.devices.components.DigitalDeviceComponent;
import org.jagatoo.input.devices.components.Key;
import org.jagatoo.input.devices.components.Keys;
import org.jagatoo.input.devices.components.MouseButton;
import org.jagatoo.input.devices.components.MouseButtons;
import org.jagatoo.util.arrays.ArrayUtils;
import org.openmali.types.twodee.Dim2f;
import org.openmali.types.twodee.ExtSized2i;
import org.openmali.types.twodee.Sized2fRO;
import org.openmali.types.twodee.Sized2i;
import org.openmali.types.twodee.Sized2iRO;
import org.openmali.types.twodee.util.ResizeListener2i;
import org.openmali.vecmath2.Point2f;
import org.openmali.vecmath2.Point2i;
import org.openmali.vecmath2.Tuple2f;
import org.openmali.vecmath2.Tuple2i;
import org.xith3d.loop.UpdatingThread.TimingMode;
import org.xith3d.loop.opscheduler.OperationScheduler;
import org.xith3d.loop.opscheduler.impl.OperationSchedulerImpl;
import org.xith3d.render.ForegroundRenderPass;
import org.xith3d.render.RenderPassConfig;
import org.xith3d.render.preprocessing.sorting.CustomRenderBinSorter;
import org.xith3d.scenegraph.BranchGroup;
import org.xith3d.scenegraph.Node;
import org.xith3d.scenegraph.SceneGraph;
import org.xith3d.scenegraph.Texture2D;
import org.xith3d.scenegraph.View.CameraMode;
import org.xith3d.ui.hud.base.Widget;
import org.xith3d.ui.hud.base.WidgetContainer;
import org.xith3d.ui.hud.base.Window;
import org.xith3d.ui.hud.base.__HUD_base_PrivilegedAccess;
import org.xith3d.ui.hud.contextmenu.ContextMenu;
import org.xith3d.ui.hud.listeners.HUDPickMissedListener;
import org.xith3d.ui.hud.listeners.WidgetContainerListener;
import org.xith3d.ui.hud.listeners.WidgetInputListener;
import org.xith3d.ui.hud.theming.FallbackTheme;
import org.xith3d.ui.hud.theming.WidgetTheme;
import org.xith3d.ui.hud.utils.Cursor;
import org.xith3d.ui.hud.utils.CursorSet;
import org.xith3d.ui.hud.utils.DefaultDropShadowFactory;
import org.xith3d.ui.hud.utils.DefaultToolTipFactory;
import org.xith3d.ui.hud.utils.DropShadowFactory;
import org.xith3d.ui.hud.utils.HUDPickResult;
import org.xith3d.ui.hud.utils.HUDTextureUtils;
import org.xith3d.ui.hud.utils.TileMode;
import org.xith3d.ui.hud.utils.ToolTipFactory;
import org.xith3d.ui.hud.utils.WidgetZIndexGroup;
import org.xith3d.ui.hud.utils.HUDPickResult.HUDPickReason;
import org.xith3d.ui.hud.widgets.Dialog;
import org.xith3d.ui.hud.widgets.Image;
import org.xith3d.ui.hud.widgets.Panel;
/**
* This is a 3D HUD implementation. A HUD can contain WidgetContainers and Widgets.
*
* @author Marvin Froehlich (aka Qudus)
*/
public class HUD
{
public static enum FocusMoveDirection
{
UP,
LEFT,
RIGHT,
DOWN,
NEXT,
;
}
/**
* Since the inner size of a decorated Canvas3D window is not correct
* before the first frame, the HUD size needs to be updated after the
* first frame.
*
* @author Marvin Froehlich (aka Qudus)
*/
private class HUDCanvas3DConnection implements ResizeListener2i
{
public void onObjectResized( Sized2i object, int oldWidth, int oldHeight, int newWidth, int newHeight )
{
HUD.this.setSize( newWidth, newHeight, -1f, -1f );
fixRenderPass();
}
}
public static final int WINDOW_BASE_Z_INDEX = (int)Short.MAX_VALUE + 2;
public static final int POPUP_Z_INDEX = Integer.MAX_VALUE - 100;
public static final int TOOLTIP_Z_INDEX = Integer.MAX_VALUE - 90;
public static final int CROSSHAIR_Z_INDEX = (int)Short.MAX_VALUE + 1;
public static final int CURSOR_Z_INDEX = Integer.MAX_VALUE - 1;
private ForegroundRenderPass renderPass = null;
private final BranchGroup branchGroup;
private Dim2f size;
private HUDCanvas3DConnection canvasConnection = null;
private HUDInputSystemConnection inputSystemConnection = null;
private Dim2f resolution = null;
private final HUDCoordinatesConverter coordinatesConverter = new HUDCoordinatesConverter( this );
private WidgetContainer contentPane;
private final ArrayList<Window> windows = new ArrayList<Window>();
private final WidgetZIndexGroup framesZIGroup = new WidgetZIndexGroup( 1 );
private final Stack<Dialog> dialogs = new Stack<Dialog>();
private Widget currentVolatilePopup = null;
private Widget currentVolatilePopupAssembly = null;
private final Tuple2f lastMousePos;
private CursorSet cursorSet = null;
private Cursor.Type currentCursorType = Cursor.Type.POINTER1;
private Cursor currentCursor = null;
private Image cursorImage = null;
private Image crosshairImage = null;
private int crosshairHotspotX = -2, crosshairHotspotY = -2;
private Widget currentHoveredWidget = null;
private Widget currentFocusedWidget = null;
private Widget mouseBoundWidget = null;
private final ArrayList<HUDPickResult> pickedWidgets = new ArrayList< HUDPickResult >();
private final ArrayList<WidgetContainerListener> globalContainerListeners = new ArrayList<WidgetContainerListener>( 1 );
private final ArrayList<WidgetInputListener> globalInputListeners = new ArrayList<WidgetInputListener>( 1 );
private final ArrayList<HUDPickMissedListener> pickMissedListeners = new ArrayList<HUDPickMissedListener>( 1 );
private final ArrayList<Integer> pickMissedMasks = new ArrayList<Integer>( 1 );
private ContextMenu contextMenu = null;
private ContextMenu currentlyDisplayedContextMenu = null;
private boolean useVoidContextMenu = true;
private ToolTipFactory tooltipFactory = new DefaultToolTipFactory();
private Widget currentlyTooltippedWidget = null;
private Point2i tooltipStartPoint = new Point2i();
private Widget currentlyDisplayedTooltipWidget = null;
private DropShadowFactory dropshadowFactory = new DefaultDropShadowFactory();
private final OperationScheduler opScheduler = new OperationSchedulerImpl();
private transient static WidgetTheme theme = null;
private DeviceComponent[] focusMoveUpAccessors = new DeviceComponent[] { Keys.UP };
private DeviceComponent[] focusMoveLeftAccessors = new DeviceComponent[] { Keys.LEFT };
private DeviceComponent[] focusMoveRightAccessors = new DeviceComponent[] { Keys.RIGHT };
private DeviceComponent[] focusMoveDownAccessors = new DeviceComponent[] { Keys.DOWN };
private DeviceComponent[] focusMoveNextAccessors = new DeviceComponent[] { Keys.TAB };
private final void fixRenderPass()
{
renderPass.getConfig().setScreenScale( getWidth() / 2.0f );
renderPass.getConfig().setCenterOfView( new Point2f( -getWidth() / 2.0f, getHeight() / 2.0f ) );
}
private final ForegroundRenderPass createRenderPass( BranchGroup bg )
{
this.renderPass = ForegroundRenderPass.createParallel( bg );
final RenderPassConfig passConfig = renderPass.getConfig();
passConfig.setCameraMode( CameraMode.VIEW_FIXED );
passConfig.setOpaqueSorter( new CustomRenderBinSorter() );
passConfig.setTransparentSorter( new CustomRenderBinSorter() );
passConfig.setFrontClipDistance( -1.0f );
passConfig.setBackClipDistance( +1.0f );
//passConfig.setFieldOfView( fov );
fixRenderPass();
//renderPass.setClipperEnabled( false );
renderPass.setScissorEnabled( true );
//renderPass.setFrustumCullingEnabled( false );
return ( renderPass );
}
/**
* Walks up the Scenegraph to the root BranchGroup. If there is one the
* assotiated RenderPass is searched for and returned.
* If this HUD is not attached to a BranchGroup or the BranchGroup
* is not assitiated with a RenderPass they are created.
*
* @return the RenderPass to add to the Renderer or Xith3DEnvironment
*/
public final ForegroundRenderPass getRenderPass()
{
if ( this.renderPass == null )
{
this.renderPass = createRenderPass( branchGroup );
}
return ( this.renderPass );
}
/**
* {@inheritDoc}
*/
public final BranchGroup getSGGroup()
{
return ( branchGroup );
}
/**
* {@inheritDoc}
*/
public final void detach()
{
BranchGroup bg = getSGGroup();
if ( bg == null )
return;
SceneGraph sg = bg.getSceneGraph();
if ( sg == null )
return;
sg.removeHUD( this );
}
/**
* {@inheritDoc}
*/
public void setName( String name )
{
getSGGroup().setName( name );
}
/**
* {@inheritDoc}
*/
public final String getName()
{
return ( getSGGroup().getName() );
}
/**
* Sets the WidgetTheme to use for default textures and some default properties
*
* @param theme the new WidgetTheme to use
*/
public static void setTheme( WidgetTheme theme )
{
HUD.theme = theme;
}
/**
* Sets the built-in WidgetTheme to use for default textures and some default properties
*
* @param theme the new WidgetTheme to use
*/
public static void setTheme( String theme ) throws IOException
{
HUD.theme = new WidgetTheme( theme );
}
/**
* @return the WidgetTheme to use for default textures and some default properties
*/
public static final WidgetTheme getTheme()
{
if ( HUD.theme == null )
{
final String THEME_NAME = "GTK";
try
{
HUD.theme = new WidgetTheme( THEME_NAME );
}
catch ( IOException e )
{
System.err.println( "WARNING: Theme \"" + THEME_NAME + "\" could not get loaded. Using Fallback-Theme" );
HUD.theme = new FallbackTheme();
}
}
return ( HUD.theme );
}
/**
* Adds a new HUDPickMissedListener to be notified of a pick event, that
* didn't hit any Widget.
*
* @see HUDPickReason#getMaskValue()
*
* @param mask a bitmask to define, which {@link HUDPickReason}s cause the listener to be notified.
* @param l
*/
public void addPickMissedListener( int mask, HUDPickMissedListener l )
{
this.pickMissedListeners.add( l );
this.pickMissedMasks.add( mask );
}
/**
* Removes a HUDPickMissedListener.
*
* @param l
*/
public void removePickMissedListener( HUDPickMissedListener l )
{
int index = pickMissedListeners.indexOf( l );
if ( index < 0 )
return;
this.pickMissedListeners.remove( index );
this.pickMissedMasks.remove( index );
}
/**
* Adds a new WidgetInputListener to be notified of global widget input events.
*
* @param l
*/
public void addGlobalInputListener( WidgetInputListener l )
{
this.globalInputListeners.add( l );
}
/**
* Removes a global WidgetInputListener.
*
* @param l
*/
public void removeGlobalInputListener( WidgetInputListener l )
{
this.globalInputListeners.remove( l );
}
/**
* Adds a new WidgetContainerListener to be notified of global widget container events.
*
* @param l
*/
public void addGlobalContainerListener( WidgetContainerListener l )
{
this.globalContainerListeners.add( l );
}
/**
* Removes a global WidgetContainerListener.
*
* @param l
*/
public void removeGlobalContainerListener( WidgetContainerListener l )
{
this.globalContainerListeners.remove( l );
}
/**
* Unfocusses all Widgets.
*/
public void disposeFocus()
{
if ( currentFocusedWidget != null )
__HUD_base_PrivilegedAccess.onFocusLost( currentFocusedWidget );
currentFocusedWidget = null;
}
/**
* Sets the whole HUD visible/invisible.
*
* @param visible
*/
public void setVisible( boolean visible )
{
this.getSGGroup().setRenderable( visible );
}
/**
* Gets, if the whole HUD is visible/invisible.
*
* @return the whole HUD's visibility.
*/
public final boolean isVisible()
{
return ( this.getSGGroup().isRenderable() );
}
/**
* Sets all Widgets' transparency.
*
* @param transparency
*/
public void setTransparency( float transparency )
{
for ( int i = 0; i < windows.size(); i++ )
{
windows.get( i ).setTransparency( transparency );
}
contentPane.setTransparency( transparency, true );
}
/**
* Gets the content pane's transparency.
*
* @return the transparency.
*/
public final float getTransparency()
{
return ( contentPane.getTransparency() );
}
/**
* @return this HUD's width
*/
public final float getWidth()
{
if ( size != null )
return ( size.getWidth() );
return ( -1.0f );
}
/**
* @return this HUD's height
*/
public final float getHeight()
{
if ( size != null )
return ( size.getHeight() );
return ( -1.0f );
}
/**
* {@inheritDoc}
*/
public final float getAspect()
{
//if ( getHeight() == 0f )
// return ( 0f );
return ( getWidth() / getHeight() );
}
/**
* @return this HUD's size
*/
public final Sized2fRO getSize()
{
return ( size );
}
/**
* Returns whether a custom resolution is defined on the hud.
*
* @return whether a custom resolution is defined on the hud.
*/
public final boolean hasCustomResolution()
{
return ( resolution != null );
}
/**
* {@inheritDoc}
*/
public final float getResX()
{
if ( resolution == null )
return ( getWidth() );
return ( resolution.getWidth() );
}
/**
* {@inheritDoc}
*/
public final float getResY()
{
if ( resolution == null )
return ( getHeight() );
return ( resolution.getHeight() );
}
/**
* {@inheritDoc}
*/
public final Tuple2f getResolution()
{
return ( new Tuple2f( getResX(), getResY() ) );
}
/**
* {@inheritDoc}
*/
public final float getResAspect()
{
if ( getResY() == 0f )
return ( 0f );
return ( getResX() / getResY() );
}
/**
* Returns a converter utility to convert from different coorcinate spaces.
*
* @return a converter utility to convert from different coorcinate spaces.
*/
public final HUDCoordinatesConverter getCoordinatesConverter()
{
return ( coordinatesConverter );
}
/**
* {@inheritDoc}
*/
public void update()
{
contentPane.update();
for ( int i = 0; i < windows.size(); i++ )
{
windows.get( i ).update();
}
if ( currentVolatilePopup != null )
currentVolatilePopup.update();
if ( currentlyDisplayedTooltipWidget != null )
currentlyDisplayedTooltipWidget.update();
}
/**
* Resizes this HUD's coordinate system to the given width and height.
*
* @param resX the new width of this HUD's coordinate system
* @param resY the new height of this HUD's coordinate system
* @param forced
*/
protected boolean setSize( float resX, float resY, boolean forced )
{
final boolean result = true;
boolean contentPaneHasFullSize = ( contentPane.getWidth() == this.getResX() ) && ( contentPane.getHeight() == this.getResY() );
if ( ( resY >= 0f ) && ( resY >= 0f ) )
{
this.resolution = new Dim2f( resX, resY );
}
if ( contentPaneHasFullSize )
{
contentPane.setSize( this.getResX(), this.getResY() );
}
update();
return ( result );
}
/**
* Resizes this HUD's coordinate system to the given width and height.
*
* @param resX the new width of this HUD's coordinate system
* @param resY the new height of this HUD's coordinate system
*/
public final HUD setSize( float resX, float resY )
{
setSize( resX, resY, false );
return ( this );
}
/**
* Resizes this HUD's coordinate system to the given width and height.
*
* @param resolution the new resolution of this HUD's coordinate system
*/
public final HUD setSize( Sized2fRO resolution )
{
return ( setSize( resolution.getWidth(), resolution.getHeight() ) );
}
/**
* Resizes this HUD's coordinate system to the given width and height.
*
* @param resolution the new resolution of this HUD's coordinate system
*/
public final HUD setSize( Tuple2f resolution )
{
return ( setSize( resolution.getX(), resolution.getY() ) );
}
/**
* Creates a new coordinate system on the HUD.
* It doesn't actually resize the HUD.
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resX the view width of the coordinate system
* @param resY the view height of the coordinate system
*/
public final void setSize( int canvasWidth, int canvasHeight, float resX, float resY )
{
if ( this.size == null )
this.size = new Dim2f();
this.size.set( canvasWidth, (float)canvasHeight );
//final boolean result = ( ( this.resolution == null ) || ( this.resolution.getWidth() != resX ) || ( this.resolution.getHeight() != resY ) );
setSize( resX, resY );
this.update();
//return ( result );
}
/**
* Creates a new coordinate system on the HUD.
* It doesn't actually resize the HUD.
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the view width of the coordinate system
* @param resY the view height of the coordinate system
*/
public final void setSize( Sized2iRO canvas, float resX, float resY )
{
setSize( canvas.getWidth(), canvas.getHeight(), resX, resY );
}
/**
* Creates a new coordinate system on the HUD.
* It doesn't actually resize the HUD.
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resolution the resolution of the coordinate system
*/
public final void setSize( int canvasWidth, int canvasHeight, Sized2fRO resolution )
{
if ( resolution != null )
setSize( canvasWidth, canvasHeight, resolution.getWidth(), resolution.getHeight() );
else
setSize( canvasWidth, canvasHeight, -1f, -1f );
}
/**
* Creates a new coordinate system on the HUD.
* It doesn't actually resize the HUD.
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resolution the resolution of the coordinate system
*/
public final void setSize( Sized2iRO canvas, Sized2fRO resolution )
{
if ( resolution != null )
setSize( canvas, resolution.getWidth(), resolution.getHeight() );
else
setSize( canvas, -1f, -1f );
}
/**
* Creates a new coordinate system on the HUD.
* It doesn't actually resize the HUD.
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
*/
public final void setSize( int canvasWidth, int canvasHeight )
{
setSize( canvasWidth, canvasHeight, canvasWidth, canvasHeight );
}
/**
* Creates a new coordinate system on the HUD.
* It doesn't actually resize the HUD.
*
* @param canvas the canvas to take the resolution and aspect from
*/
public final void setSize( Sized2iRO canvas )
{
setSize( canvas, (Sized2fRO)null );
}
public final void setWidth( float width )
{
setSize( width, getResX() );
}
public final void setHeight( float height )
{
setSize( getResX(), height );
}
/**
* {@inheritDoc}
*/
public Window addWindow( Window window, float locX, float locY )
{
if ( window.getHUD() != null )
{
throw new Error( "This Widget is already added to the HUD." );
}
int maxZIndex = WINDOW_BASE_Z_INDEX - 1;
for ( int i = 0; i < windows.size(); i++ )
{
final Window wnd = windows.get( i );
if ( wnd.getZIndex() > maxZIndex )
maxZIndex = wnd.getZIndex();
}
window.setZIndex( maxZIndex + 1 );
framesZIGroup.add( window );
windows.add( window );
currentFocusedWidget = window;
if ( inputSystemConnection != null )
inputSystemConnection.nextAcceptedMouseEventTime = System.currentTimeMillis() + 200L;
if ( window instanceof Dialog )
{
dialogs.push( (Dialog)window );
}
window.setLocation( locX, locY );
__HUD_base_PrivilegedAccess.setHUD( this, window );
branchGroup.addChild( __HUD_base_PrivilegedAccess.getSGNode( window ) );
for ( int i = 0; i < globalContainerListeners.size(); i++ )
{
globalContainerListeners.get( i ).onWidgetAttachedToHUD( window, this );
}
return ( window );
}
/**
* {@inheritDoc}
*/
public final Window addWindow( Window window )
{
return ( addWindow( window, window.getLeft(), window.getTop() ) );
}
/**
* {@inheritDoc}
*/
public final Window addWindowCentered( Window window )
{
float posUpperLeftX = ( this.getResX() - window.getWidth() ) / 2.0f;
float posUpperLeftY = ( this.getResY() - window.getHeight() ) / 2.0f;
posUpperLeftX = Math.round( posUpperLeftX );
posUpperLeftY = Math.round( posUpperLeftY );
return ( addWindow( window, posUpperLeftX, posUpperLeftY ) );
}
/**
* {@inheritDoc}
*/
public void removeWindow( Window window )
{
if ( window.getHUD() != this )
throw new Error( "the given Widget is not held in this Container." );
branchGroup.removeChild( __HUD_base_PrivilegedAccess.getSGNode( window ) );
if ( window instanceof Dialog )
{
dialogs.remove( window );
}
windows.remove( window );
framesZIGroup.remove( window );
__HUD_base_PrivilegedAccess.setHUD( null, window );
for ( int i = 0; i < globalContainerListeners.size(); i++ )
{
globalContainerListeners.get( i ).onWidgetDetachedFromHUD( window, this );
}
}
/**
* Adds an internally managed widget.
*
* @param widget
* @param locX use -1 for center
* @param locY use -1 for center
* @param zIndex
*/
private void addInternalWidget( Widget widget, float locX, float locY, int zIndex )
{
if ( ( widget.getContainer() != null ) || ( widget.getHUD() != null ) )
{
throw new Error( "This Widget is already added to the HUD." );
}
if ( locX < 0f )
locX = Math.round( ( this.getResX() - widget.getWidth() ) / 2.0f );
if ( locY < 0f )
locY = Math.round( ( this.getResY() - widget.getHeight() ) / 2.0f );
widget.setLocation( locX, locY );
widget.setZIndex( zIndex );
__HUD_base_PrivilegedAccess.setHUD( this, widget );
branchGroup.addChild( __HUD_base_PrivilegedAccess.getSGNode( widget ) );
}
void addVolatilePopup( Widget widget, Widget assembly, float locX, float locY )
{
if ( !widget.isHeavyWeight() )
throw new IllegalArgumentException( "A volatile popup must be heavyweight." );
if ( currentVolatilePopup != null )
{
removeVolatilePopup();
}
addInternalWidget( widget, locX, locY, POPUP_Z_INDEX );
this.currentVolatilePopup = widget;
this.currentVolatilePopupAssembly = assembly;
}
void removeVolatilePopup()
{
removeInternalWidget( currentVolatilePopup );
currentVolatilePopup = null;
currentVolatilePopupAssembly = null;
}
final Widget getCurrentVolatilePopup()
{
return ( currentVolatilePopup );
}
private void removeInternalWidget( Widget widget )
{
if ( ( widget.getContainer() != null ) || ( widget.getHUD() != this ) )
throw new Error( "the given Widget is not held in this Container." );
branchGroup.removeChild( __HUD_base_PrivilegedAccess.getSGNode( widget ) );
__HUD_base_PrivilegedAccess.setHUD( null, widget );
}
/**
* Sets the content pane, where all other Widgets (except for windows) must be added to.
*
* @param contentPane
*/
public void setContentPane( WidgetContainer contentPane )
{
if ( contentPane == null )
throw new IllegalArgumentException( "contentPane must not be null." );
if ( contentPane == this.contentPane )
return;
if ( this.contentPane != null )
removeInternalWidget( this.contentPane );
addInternalWidget( contentPane, contentPane.getLeft(), contentPane.getTop(), 0 );
this.contentPane = contentPane;
}
/**
* Returns the content pane, where all other Widgets (except for windows) must be added to.
*
* @return the content pane, where all other Widgets (except for windows) must be added to.
*/
public final WidgetContainer getContentPane()
{
return ( contentPane );
}
/**
* @return the currently visible dialog, if any or null
*/
private final Dialog getCurrentDialog()
{
for ( int i = dialogs.size() - 1; i >= 0; i-- )
{
Dialog dialog = dialogs.get( i );
if ( dialog.isVisible() && ( dialog.getHUD() != null ) )
{
return ( dialogs.get( i ) );
}
}
return ( null );
}
Widget focus( Widget widget )
{
final Widget cfw = currentFocusedWidget;
if ( widget instanceof WidgetContainer )
{
// We need to check, if the container is a content pane of a window.
if ( ( (WidgetContainer)widget ).isContentPane() )
widget = ( (WidgetContainer)widget ).getParentWindow();
}
if ( ( cfw == widget ) || !widget.isFocussable() )
return ( cfw );
if ( currentFocusedWidget != null )
__HUD_base_PrivilegedAccess.onFocusLost( currentFocusedWidget );
currentFocusedWidget = widget;
__HUD_base_PrivilegedAccess.onFocusGained( currentFocusedWidget );
return ( cfw );
}
final Widget getCurrentFocusedWidget( boolean getLeaf )
{
final Widget cfw = currentFocusedWidget;
if ( getLeaf )
{
if ( ( cfw != null ) && ( cfw instanceof WidgetContainer ) )
{
final Widget cfw2 = ( (WidgetContainer)cfw ).getCurrentFocusedWidget( getLeaf );
if ( cfw2 != null )
return ( cfw2 );
return ( cfw );
}
}
return ( cfw );
}
private final Widget getCurrentFocusedWidget()
{
return ( getCurrentFocusedWidget( false ) );
}
final Widget getCurrentHoveredWidget( boolean getLeaf )
{
final Widget chw = currentHoveredWidget;
if ( getLeaf )
{
if ( ( chw != null ) && ( chw instanceof WidgetContainer ) )
{
final Widget chw2 = ( (WidgetContainer)chw ).getCurrentHoveredWidget( getLeaf );
if ( chw2 != null )
return ( chw2 );
return ( chw );
}
}
return ( chw );
}
private final Widget getCurrentHoveredWidget()
{
return ( currentHoveredWidget );
}
/**
* Bind mouse movement to a Widget.
* onMouseMoved will be called on this Widget,
* even if the mouse is not over it.
*
* @param widget the Widget to bind
*/
void bindMouseMovement( Widget widget )
{
mouseBoundWidget = widget;
}
private final Widget getCurrentMouseBoundWidget()
{
return ( mouseBoundWidget );
}
/**
* Sets the {@link ToolTipFactory} to be used to generate tooltip-Widgets.
*
* @param ttf
*/
public void setToolTipFactory( ToolTipFactory ttf )
{
this.tooltipFactory = ttf;
}
/**
* @return the {@link ToolTipFactory} to be used to generate tooltip-Widgets.
*/
public final ToolTipFactory getToolTipFactory()
{
return ( tooltipFactory );
}
private void disposeToolTip()
{
if ( currentlyDisplayedTooltipWidget == null )
return;
removeInternalWidget( currentlyDisplayedTooltipWidget );
currentlyDisplayedTooltipWidget = null;
currentlyTooltippedWidget = null;
}
private void displayToolTipIfNeeded( Widget leafHoveredWidget, int canvasX, int canvasY )
{
if ( !leafHoveredWidget.hasToolTip() || ( getToolTipFactory() == null ) )
return;
if ( leafHoveredWidget == currentlyTooltippedWidget )
return;
Widget tooltip = __HUD_base_PrivilegedAccess.getCachedToolTipWidget( leafHoveredWidget );
if ( tooltip == null )
{
tooltip = getToolTipFactory().createToolTip( leafHoveredWidget.getToolTip() );
if ( tooltip == null )
{
throw new Error( "ToolTipFactory " + getToolTipFactory().getClass() + " returns null. This is illegal!" );
}
if ( !tooltip.isHeavyWeight() )
{
throw new Error( "A tooltip must be heavyweight!" );
}
__HUD_base_PrivilegedAccess.setCachedToolTipWidget( leafHoveredWidget, tooltip );
}
disposeToolTip();
this.currentlyDisplayedTooltipWidget = tooltip;
Tuple2f buffer = Tuple2f.fromPool();
coordinatesConverter.getLocationPixels2HUD( canvasX, canvasY, buffer );
final float posX = buffer.getX();
final float posY = buffer.getY();
Tuple2f.toPool( buffer );
addInternalWidget( tooltip, posX, posY, TOOLTIP_Z_INDEX );
currentlyTooltippedWidget = leafHoveredWidget;
tooltipStartPoint.set( canvasX, canvasY );
}
/**
* Sets the {@link DropShadowFactory} to be used to render drop shadows.
*
* @param ttf
*/
public void setDropShadowFactory( DropShadowFactory dsf )
{
this.dropshadowFactory = dsf;
}
/**
* @return the {@link DropShadowFactory} to be used to render drop shadows.
*/
public final DropShadowFactory getDropShadowFactory()
{
return ( dropshadowFactory );
}
/**
* {@inheritDoc}
*/
public void setContextMenu( ContextMenu contextMenu )
{
if ( contextMenu == this.contextMenu )
{
return;
}
if ( this.contextMenu != null )
{
this.contextMenu.setHUD( null );
}
this.contextMenu = contextMenu;
contextMenu.setHUD( this );
}
/**
* {@inheritDoc}
*/
public ContextMenu getContextMenu()
{
return ( contextMenu );
}
/**
* Defines, if a ContextMenu is used, if the mouse was clicked in the empty
* space (where no Widget is displayed).
*
* @param use
*/
public void setUseVoidContextMenu( boolean use )
{
this.useVoidContextMenu = use;
}
/**
* @return if a ContextMenu is used, if the mouse was clicked in the empty
* space (where no Widget is displayed).
*/
public final boolean useVoidContextMenu()
{
return ( useVoidContextMenu );
}
private void popUpContextMenu( ContextMenu contextMenu, float posX, float posY )
{
if ( contextMenu == null )
return;
contextMenu.popUp( posX, posY );
}
private void checkPopupMenu( HUDPickResult pickResult, MouseButton button, float posX, float posY, HUDPickReason pickReason )
{
Widget pickedWidget = ( pickResult == null ) ? null : pickResult.getLeafResult().getWidget();
ContextMenu contextMenu = null;
if ( pickedWidget != null )
{
contextMenu = pickedWidget.getContextMenu();
}
if ( contextMenu == null )
{
contextMenu = this.getContextMenu();
}
if ( contextMenu != null )
{
if ( currentlyDisplayedContextMenu != null )
{
if ( ( pickedWidget != null ) || ( useVoidContextMenu() ) )
{
if ( pickedWidget != currentlyDisplayedContextMenu.getMenuItemsContainer() )
{
if ( button == MouseButtons.RIGHT_BUTTON )
{
if ( contextMenu != currentlyDisplayedContextMenu )
{
currentlyDisplayedContextMenu.popUp( false );
currentlyDisplayedContextMenu = null;
}
if ( pickReason == HUDPickReason.BUTTON_RELEASED )
{
popUpContextMenu( contextMenu, posX, posY );
this.currentlyDisplayedContextMenu = contextMenu;
}
}
else
{
if ( ( pickResult == null ) || ( pickResult.getWidget() != contextMenu.getMenuItemsContainer() ) )
{
currentlyDisplayedContextMenu.popUp( false );
currentlyDisplayedContextMenu = null;
}
}
}
}
}
else if ( ( button == MouseButtons.RIGHT_BUTTON ) && ( pickReason == HUDPickReason.BUTTON_RELEASED ) )
{
if ( ( pickedWidget != null ) || useVoidContextMenu() )
{
popUpContextMenu( contextMenu, posX, posY );
this.currentlyDisplayedContextMenu = contextMenu;
}
}
}
else if ( currentlyDisplayedContextMenu != null )
{
currentlyDisplayedContextMenu.popUp( false );
currentlyDisplayedContextMenu = null;
}
}
private Widget pick( int canvasX, int canvasY, HUDPickReason pickReason, MouseButton button, long when, long meta, int flags )
{
HUDPickResult tmpHPR = null;
HUDPickResult topMost = null;
pickedWidgets.clear();
/*
if ( ( topMost == null ) && ( currentlyDisplayedTooltipWidget != null ) )
{
tmpHPR = __HUD_base_PrivilegedAccess.pick( currentlyDisplayedTooltipWidget, canvasX, canvasY, pickReason, button, when, meta, flags | HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL | HUDPickResult.HUD_PICK_FLAG_EVENTS_SUPPRESSED );
if ( tmpHPR != null )
{
pickedWidgets.add( tmpHPR );
topMost = tmpHPR;
}
}
*/
if ( ( topMost == null ) && ( getCurrentVolatilePopup() != null ) )
{
tmpHPR = __HUD_base_PrivilegedAccess.pick( getCurrentVolatilePopup(), canvasX, canvasY, pickReason, button, when, meta, flags );
if ( tmpHPR != null )
{
pickedWidgets.add( tmpHPR );
topMost = tmpHPR;
}
}
Dialog currDialog = getCurrentDialog();
if ( topMost == null )
{
if ( currDialog != null )
{
if ( currDialog.isPickable() )
{
tmpHPR = __HUD_base_PrivilegedAccess.pick( currDialog, canvasX, canvasY, pickReason, button, when, meta, flags );
if ( tmpHPR != null )
{
pickedWidgets.add( tmpHPR );
topMost = tmpHPR;
}
}
}
else
{
// check, if there's a Window under the cursor
for ( int i = 0; i < windows.size(); i++ )
{
final Window window = windows.get( i );
if ( window.isVisible() && window.isPickable() )
{
//tmpHPR = __HUD_base_PrivilegedAccess.pick( window, canvasX, canvasY, pickReason, button, when, meta, flags | HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL | HUDPickResult.HUD_PICK_FLAG_EVENTS_SUPPRESSED );
tmpHPR = __HUD_base_PrivilegedAccess.pick( window, canvasX, canvasY, pickReason, button, when, meta, flags | HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL );
if ( tmpHPR != null )
{
pickedWidgets.add( tmpHPR );
if ( ( topMost == null ) || ( topMost.compareTo( tmpHPR ) <= 0 ) )
{
topMost = tmpHPR;
}
}
}
}
if ( ( topMost == null ) && contentPane.isVisible() && contentPane.isPickable() )
{
tmpHPR = __HUD_base_PrivilegedAccess.pick( contentPane, canvasX, canvasY, pickReason, button, when, meta, flags );
if ( tmpHPR != null )
{
pickedWidgets.add( tmpHPR );
topMost = tmpHPR;
}
}
}
}
final boolean justTest = ( flags & HUDPickResult.HUD_PICK_FLAG_JUST_TEST_AND_DO_NOTHING ) == HUDPickResult.HUD_PICK_FLAG_JUST_TEST_AND_DO_NOTHING;
final boolean isInternal = justTest || ( flags & HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL ) != 0;
final boolean eventsSuppressed = justTest || ( flags & HUDPickResult.HUD_PICK_FLAG_EVENTS_SUPPRESSED ) != 0;
if ( !justTest && ( currentHoveredWidget != null ) && ( ( topMost == null ) || ( currentHoveredWidget != topMost.getWidget() ) ) )
{
// How can this be??? But we will check it to avoid problems...
if ( currentHoveredWidget.getHUD() != null )
{
__HUD_base_PrivilegedAccess.onMouseExited( currentHoveredWidget, true, false );
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseExited( getCurrentHoveredWidget( true ), true, false );
}
}
currentHoveredWidget = null;
}
final Tuple2f locP = Tuple2f.fromPool();
getCoordinatesConverter().getLocationPixels2HUD( canvasX, canvasY, locP );
float pickXHUD = locP.getX();
float pickYHUD = locP.getY();
Tuple2f.toPool( locP );
if ( ( topMost != null ) && isInternal && !eventsSuppressed )
{
for ( int i = 0; i < pickedWidgets.size(); i++ )
{
final HUDPickResult hpr = pickedWidgets.get( i );
final Widget pickedWidget = hpr.getWidget();
final boolean isTopMost = ( pickedWidget == topMost.getWidget() ); // && topMost.isLeafResult();
boolean hasFocus = ( pickedWidget == getCurrentFocusedWidget() );
float pickXHUD_ = pickXHUD - pickedWidget.getLeft();
float pickYHUD_ = pickYHUD - pickedWidget.getTop();
switch ( pickReason )
{
case BUTTON_PRESSED:
if ( isTopMost )
{
if ( currentFocusedWidget != pickedWidget )
{
focus( pickedWidget );
hasFocus = true;
}
}
__HUD_base_PrivilegedAccess.onMouseButtonPressed( pickedWidget, button, pickXHUD_, pickYHUD_, when, meta, isTopMost, hasFocus );
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseButtonPressed( hpr.getLeafResult().getWidget(), button, pickXHUD_, pickYHUD_, when, meta, isTopMost, hasFocus );
}
break;
case BUTTON_RELEASED:
__HUD_base_PrivilegedAccess.onMouseButtonReleased( pickedWidget, button, pickXHUD_, pickYHUD_, when, meta, isTopMost, hasFocus );
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseButtonReleased( hpr.getLeafResult().getWidget(), button, pickXHUD_, pickYHUD_, when, meta, isTopMost, hasFocus );
}
break;
case MOUSE_MOVED:
__HUD_base_PrivilegedAccess.onMouseMoved( pickedWidget, pickXHUD_, pickYHUD_, (int)meta, when, isTopMost, hasFocus );
if ( ( currentHoveredWidget == null ) && isTopMost )
{
currentHoveredWidget = pickedWidget;
__HUD_base_PrivilegedAccess.onMouseEntered( currentHoveredWidget, isTopMost, hasFocus );
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseEntered( getCurrentHoveredWidget( true ), isTopMost, hasFocus );
}
}
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseMoved( hpr.getLeafResult().getWidget(), pickXHUD_, pickYHUD_, (int)meta, when, isTopMost, hasFocus );
}
break;
case MOUSE_STOPPED:
//__HUD_base_PrivilegedAccess.onMouseStopped( pickedWidget, pickXHUD_, pickYHUD_, when, isTopMost, hasFocus );
if ( isTopMost )
{
displayToolTipIfNeeded( hpr.getLeafResult().getWidget(), canvasX, canvasY );
}
/*
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseStopped( hpr.getLeafResult().getWidget(), pickXHUD_, pickYHUD_, when, isTopMost, hasFocus );
}
*/
break;
case MOUSE_WHEEL_MOVED_UP:
__HUD_base_PrivilegedAccess.onMouseWheelMoved( pickedWidget, +1, ( meta != 0L ), pickXHUD_, pickYHUD_, when, isTopMost );
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseWheelMoved( hpr.getLeafResult().getWidget(), +1, ( meta != 0L ), pickXHUD_, pickYHUD_, when, isTopMost );
}
break;
case MOUSE_WHEEL_MOVED_DOWN:
__HUD_base_PrivilegedAccess.onMouseWheelMoved( pickedWidget, -1, ( meta != 0L ), pickXHUD_, pickYHUD_, when, isTopMost );
for ( int j = 0; j < globalInputListeners.size(); j++ )
{
globalInputListeners.get( j ).onMouseWheelMoved( hpr.getLeafResult().getWidget(), -1, ( meta != 0L ), pickXHUD_, pickYHUD_, when, isTopMost );
}
break;
}
}
}
if ( !justTest )
{
// notify pick-missed listeners in case...
if ( pickedWidgets.size() == 0 )
{
if ( !eventsSuppressed )
{
if ( currDialog == null )
{
for ( int i = 0; i < pickMissedListeners.size(); i++ )
{
if ( ( pickMissedMasks.get( i ) & pickReason.getMaskValue() ) > 0 )
pickMissedListeners.get( i ).onHUDPickMissed( button, canvasX, canvasY, pickReason, when, meta );
}
}
}
checkPopupMenu( null, button, pickXHUD, pickYHUD, pickReason );
}
// change the Cursor texture, if necessary...
if ( topMost != null )
{
final Cursor.Type newCursorType = topMost.getInheritedCursorType();
if ( newCursorType != currentCursorType )
{
if ( ( newCursorType != null ) || ( currentCursorType != null ) )
{
if ( newCursorType == null )
setCursorInternal( getCursorSet().get( Cursor.Type.POINTER1 ), Cursor.Type.POINTER1, false );
else
setCursorInternal( getCursorSet().get( newCursorType ), newCursorType, false );
}
}
if ( ( pickReason == HUDPickReason.BUTTON_PRESSED ) || ( pickReason == HUDPickReason.BUTTON_RELEASED ) )
{
checkPopupMenu( topMost, button, pickXHUD, pickYHUD, pickReason );
}
}
else if ( currentCursorType != Cursor.Type.POINTER1 )
{
setCursorInternal( getCursorSet().get( Cursor.Type.POINTER1 ), Cursor.Type.POINTER1, false );
}
}
if ( topMost != null )
{
if ( pickReason == HUDPickReason.BUTTON_PRESSED )
{
if ( ( getCurrentVolatilePopup() != null ) && ( topMost.getWidget() != getCurrentVolatilePopup() ) && ( topMost.getLeafResult().getWidget() != currentVolatilePopupAssembly ) )
{
removeVolatilePopup();
}
}
}
else if ( ( pickReason == HUDPickReason.BUTTON_PRESSED ) && ( getCurrentVolatilePopup() != null ) )
{
removeVolatilePopup();
}
Widget topmostWidget = ( topMost != null ) ? topMost.getWidget() : null;
for ( int i = 0; i < pickedWidgets.size(); i++ )
{
HUDPickResult.toPool( pickedWidgets.get( i ) );
}
pickedWidgets.clear();
return ( topmostWidget );
}
void onMouseButtonPressed( MouseButton button, int x, int y, long when, long lastWhen )
{
pick( x, y, HUDPickReason.BUTTON_PRESSED, button, when, lastWhen, HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL );
}
void onMouseButtonReleased( MouseButton button, int x, int y, long when, long lastWhen )
{
if ( getCurrentMouseBoundWidget() == null )
{
pick( x, y, HUDPickReason.BUTTON_RELEASED, button, when, lastWhen, HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL );
}
else
{
final Tuple2f locP = Tuple2f.fromPool();
//getCoordinatesConverter().getLocationPixels2HUD( x, y, locP );
__HUD_base_PrivilegedAccess.getLocationPixels2HUD_( mouseBoundWidget, x, y, locP );
float pickXHUD = locP.getX();
float pickYHUD = locP.getY();
Tuple2f.toPool( locP );
Widget mbw = mouseBoundWidget;
mouseBoundWidget = null;
__HUD_base_PrivilegedAccess.onMouseButtonReleased( mbw, button, pickXHUD, pickYHUD, when, lastWhen, true, mbw.isFocussable() );
}
}
void onMouseMoved( int x, int y, int buttonsState, long when, long lastWhen )
{
if ( currentlyDisplayedTooltipWidget != null )
{
Widget tmp = currentlyDisplayedTooltipWidget;
currentlyDisplayedTooltipWidget = null;
Widget pr = pick( x, y, HUDPickReason.MOUSE_MOVED, null, when, lastWhen, HUDPickResult.HUD_PICK_FLAG_JUST_TEST_AND_DO_NOTHING );
currentlyDisplayedTooltipWidget = tmp;
if ( ( pr == null ) || ( pr != currentlyDisplayedTooltipWidget ) )
{
final int minMoveX = (int)( this.getWidth() / 16f );
final int minMoveY = (int)( this.getHeight() / 12f );
if ( ( Math.abs( x - tooltipStartPoint.getX() ) > minMoveX ) || ( Math.abs( y - tooltipStartPoint.getY() ) > minMoveY ) )
{
disposeToolTip();
}
}
}
lastMousePos.set( x * getResX() / getWidth(), y * getResY() / getHeight() );
if ( ( cursorImage != null ) && ( currentCursor != null ) )
{
if ( __HUD_base_PrivilegedAccess.getSGNode( cursorImage ).getParent() == null )
{
branchGroup.addChild( __HUD_base_PrivilegedAccess.getSGNode( cursorImage ) );
__HUD_base_PrivilegedAccess.setHUD( this, cursorImage );
}
float zpx = currentCursor.getZeroPointX() * getResX() / getWidth();
float zpy = currentCursor.getZeroPointY() * getResY() / getHeight();
cursorImage.setLocation( lastMousePos.getX() - zpx, lastMousePos.getY() - zpy );
}
Widget mouseBound = getCurrentMouseBoundWidget();
if ( ( mouseBound != null ) && ( getCurrentHoveredWidget() != mouseBound ) )
{
final Tuple2f locP = Tuple2f.fromPool();
//getCoordinatesConverter().getLocationPixels2HUD( x, y, locP );
__HUD_base_PrivilegedAccess.getLocationPixels2HUD_( mouseBound, x, y, locP );
float pickXHUD = locP.getX();
float pickYHUD = locP.getY();
Tuple2f.toPool( locP );
__HUD_base_PrivilegedAccess.onMouseMoved( mouseBound, pickXHUD, pickYHUD, buttonsState, when, true, mouseBound.hasFocus() );
}
else
{
pick( x, y, HUDPickReason.MOUSE_MOVED, null, when, (long)buttonsState, HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL );
}
}
void onMouseStopped( int x, int y, int buttonsState, long when )
{
if ( currentHoveredWidget != null )
{
final Tuple2f locP = Tuple2f.fromPool();
getCoordinatesConverter().getLocationPixels2HUD( x, y, locP );
float pickXHUD = locP.getX();
float pickYHUD = locP.getY();
Tuple2f.toPool( locP );
__HUD_base_PrivilegedAccess.onMouseStopped( currentHoveredWidget, pickXHUD, pickYHUD, when, true, currentHoveredWidget.hasFocus() );
}
/*Widget pickedWidget = */pick( x, y, HUDPickReason.MOUSE_STOPPED, null, when, buttonsState, HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL );
/*
if ( pickedWidget == null )
{
displayToolTipIfNeeded( null, x, y );
}
*/
}
void onMouseWheelMoved( int wheelDelta, int x, int y, long when, boolean isPageMove )
{
final HUDPickReason pickReason;
if ( wheelDelta > 0 )
pickReason = HUDPickReason.MOUSE_WHEEL_MOVED_UP;
else if ( wheelDelta < 0 )
pickReason = HUDPickReason.MOUSE_WHEEL_MOVED_DOWN;
else
pickReason = null;
if ( pickReason != null )
pick( x, y, pickReason, null, when, isPageMove ? 1L : 0L, HUDPickResult.HUD_PICK_FLAG_IS_INTERNAL );
}
void onKeyPressed( Key key, int modifierMask, long when )
{
if ( currentFocusedWidget != null )
{
__HUD_base_PrivilegedAccess.onKeyPressed( currentFocusedWidget, key, modifierMask, when );
if ( !globalInputListeners.isEmpty() )
{
Widget leafFocussedWidget = getCurrentFocusedWidget( true );
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onKeyPressed( leafFocussedWidget, key, modifierMask, when );
}
}
}
}
void onKeyReleased( Key key, int modifierMask, long when )
{
if ( currentFocusedWidget != null )
{
__HUD_base_PrivilegedAccess.onKeyReleased( currentFocusedWidget, key, modifierMask, when );
if ( !globalInputListeners.isEmpty() )
{
Widget leafFocussedWidget = getCurrentFocusedWidget( true );
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onKeyReleased( leafFocussedWidget, key, modifierMask, when );
}
}
}
}
void onKeyTyped( char keyChar, int modifierMask, long when )
{
if ( currentFocusedWidget != null )
{
__HUD_base_PrivilegedAccess.onKeyTyped( currentFocusedWidget, keyChar, modifierMask, when );
if ( !globalInputListeners.isEmpty() )
{
Widget leafFocussedWidget = getCurrentFocusedWidget( true );
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onKeyTyped( leafFocussedWidget, keyChar, modifierMask, when );
}
}
}
}
void onControllerButtonPressed( ControllerButton button, long when )
{
final Widget currentFocusedWidget = getCurrentFocusedWidget( true );
if ( currentFocusedWidget != null )
{
__HUD_base_PrivilegedAccess.onControllerButtonPressed( currentFocusedWidget, button, when );
if ( !globalInputListeners.isEmpty() )
{
Widget leafFocussedWidget = getCurrentFocusedWidget( true );
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onControllerButtonPressed( leafFocussedWidget, button, when );
}
}
}
}
void onControllerButtonReleased( ControllerButton button, long when )
{
final Widget currentFocusedWidget = getCurrentFocusedWidget( true );
if ( currentFocusedWidget != null )
{
__HUD_base_PrivilegedAccess.onControllerButtonReleased( currentFocusedWidget, button, when );
if ( !globalInputListeners.isEmpty() )
{
Widget leafFocussedWidget = getCurrentFocusedWidget( true );
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onControllerButtonReleased( leafFocussedWidget, button, when );
}
}
}
}
void onControllerAxisChanged( ControllerAxis axis, float axisDelta, long when )
{
final Widget currentFocusedWidget = getCurrentFocusedWidget( true );
if ( currentFocusedWidget != null )
{
__HUD_base_PrivilegedAccess.onControllerAxisChanged( currentFocusedWidget, axis, (int)( axisDelta * axis.getScale() ), when );
if ( !globalInputListeners.isEmpty() )
{
Widget leafFocussedWidget = getCurrentFocusedWidget( true );
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onControllerAxisChanged( leafFocussedWidget, axis, axisDelta, when );
}
}
}
}
void onInputStateChanged( DeviceComponent comp, int delta, int state, long when )
{
final Widget leafFocussedWidget = getCurrentFocusedWidget( true );
if ( leafFocussedWidget == null )
return;
__HUD_base_PrivilegedAccess.onInputStateChanged( leafFocussedWidget, comp, delta, state, when, true, true );
boolean doFocusManagement = true;
if ( comp instanceof DigitalDeviceComponent )
{
if ( delta <= 0 )
doFocusManagement = false;
}
/*
else if ( comp instanceof MouseWheel )
{
//delta = Math.abs( delta );
}
*/
else
{
doFocusManagement = false;
}
if ( doFocusManagement && ( leafFocussedWidget.getContainer() != null ) && ( !__HUD_base_PrivilegedAccess.widgetBlocksFocusMoveDeviceComponent( leafFocussedWidget, comp ) ) )
{
FocusMoveDirection fmd = null;
if ( ( fmd == null ) && ( focusMoveUpAccessors != null ) )
{
for ( int i = 0; i < focusMoveUpAccessors.length; i++ )
{
if ( focusMoveUpAccessors[ i ] == comp )
{
fmd = FocusMoveDirection.UP;
break;
}
}
}
if ( ( fmd == null ) && ( focusMoveDownAccessors != null ) )
{
for ( int i = 0; i < focusMoveDownAccessors.length; i++ )
{
if ( focusMoveDownAccessors[ i ] == comp )
{
fmd = FocusMoveDirection.DOWN;
break;
}
}
}
if ( ( fmd == null ) && ( focusMoveLeftAccessors != null ) )
{
for ( int i = 0; i < focusMoveLeftAccessors.length; i++ )
{
if ( focusMoveLeftAccessors[ i ] == comp )
{
fmd = FocusMoveDirection.LEFT;
break;
}
}
}
if ( ( fmd == null ) && ( focusMoveRightAccessors != null ) )
{
for ( int i = 0; i < focusMoveRightAccessors.length; i++ )
{
if ( focusMoveRightAccessors[ i ] == comp )
{
fmd = FocusMoveDirection.RIGHT;
break;
}
}
}
if ( ( fmd == null ) && ( focusMoveNextAccessors != null ) )
{
for ( int i = 0; i < focusMoveNextAccessors.length; i++ )
{
if ( focusMoveNextAccessors[ i ] == comp )
{
fmd = FocusMoveDirection.NEXT;
break;
}
}
}
if ( ( fmd != null ) && ( leafFocussedWidget.getContainer() != null ) )
{
__HUD_base_PrivilegedAccess.moveFocus( leafFocussedWidget.getContainer(), fmd );
}
}
for ( int i = 0; i < globalInputListeners.size(); i++ )
{
globalInputListeners.get( i ).onInputStateChanged( leafFocussedWidget, comp, delta, state, when, true, true );
}
}
/**
* Binds a DeviceComponent to this HUD, that works as a focus-move-accessor
* for a given direction.
*
* @param comp
* @param direction
*/
public void bindFocusMoveAccessor( DeviceComponent comp, FocusMoveDirection direction )
{
DeviceComponent[] accessors;
switch ( direction )
{
case UP:
accessors = focusMoveUpAccessors;
break;
case DOWN:
accessors = focusMoveDownAccessors;
break;
case LEFT:
accessors = focusMoveLeftAccessors;
break;
case RIGHT:
accessors = focusMoveRightAccessors;
break;
case NEXT:
accessors = focusMoveNextAccessors;
break;
default:
throw new Error( "Unsupported direction " + direction );
}
if ( ( accessors == null ) || ( accessors.length == 0 ) )
{
accessors = new DeviceComponent[] { comp };
}
else
{
DeviceComponent[] newArray = new DeviceComponent[ accessors.length + 1 ];
System.arraycopy( accessors, 0, newArray, 0, accessors.length );
newArray[ newArray.length - 1 ] = comp;
accessors = newArray;
}
switch ( direction )
{
case UP:
focusMoveUpAccessors = accessors;
break;
case DOWN:
focusMoveDownAccessors = accessors;
break;
case LEFT:
focusMoveLeftAccessors = accessors;
break;
case RIGHT:
focusMoveRightAccessors = accessors;
break;
case NEXT:
focusMoveNextAccessors = accessors;
break;
}
}
/**
* Unbinds a focus-move-accessor DeviceComponent from this HUD for a given direction.
*
* @param comp
* @param direction
*/
public void unbindFocusMoveAccessor( DeviceComponent comp, FocusMoveDirection direction )
{
DeviceComponent[] accessors;
switch ( direction )
{
case UP:
accessors = focusMoveUpAccessors;
break;
case DOWN:
accessors = focusMoveDownAccessors;
break;
case LEFT:
accessors = focusMoveLeftAccessors;
break;
case RIGHT:
accessors = focusMoveRightAccessors;
break;
case NEXT:
accessors = focusMoveNextAccessors;
break;
default:
throw new Error( "Unsupported direction " + direction );
}
if ( accessors == null )
{
return;
}
final int index = ArrayUtils.indexOf( accessors, comp, true );
if ( index < 0 )
{
return;
}
if ( accessors.length == 1 )
{
accessors = null;
return;
}
DeviceComponent[] newArray = new DeviceComponent[ accessors.length - 1 ];
System.arraycopy( accessors, 0, newArray, 0, index );
System.arraycopy( accessors, index + 1, newArray, index, accessors.length - index - 1 );
accessors = newArray;
switch ( direction )
{
case UP:
focusMoveUpAccessors = accessors;
break;
case DOWN:
focusMoveDownAccessors = accessors;
break;
case LEFT:
focusMoveLeftAccessors = accessors;
break;
case RIGHT:
focusMoveRightAccessors = accessors;
break;
case NEXT:
focusMoveNextAccessors = accessors;
break;
}
}
/**
* Sets the CursorSet with standard cursor types.
*
* @param cursorSet
*/
public void setCursorSet( CursorSet cursorSet )
{
if ( cursorSet == null )
throw new IllegalArgumentException( "cursorSet cannot be null." );
this.cursorSet = cursorSet;
}
/**
* @return the CursorManager to manager the standard cursor types.
*/
public final CursorSet getCursorSet()
{
if ( this.cursorSet == null )
{
this.cursorSet = getTheme().getCursorSet();
}
return ( cursorSet );
}
/**
* Sets the {@link Cursor} for the mouse cursor.<br>
* Use <i>null</i> for cursor to remove the cursor.
*
* @param cursor the new cursor for the cursor Image (or null for no cursor)
* @param type
*/
private final void setCursorInternal( Cursor cursor, Cursor.Type type, boolean allowDetach )
{
if ( cursor != null )
{
float texWidth = cursor.getTexture().getOriginalWidth() * getResX() / getWidth();
float texHeight = cursor.getTexture().getOriginalHeight() * getResY() / getHeight();
Dim2f tmp = Dim2f.fromPool();
getCoordinatesConverter().getSizePixels2HUD( cursor.getZeroPointX(), cursor.getZeroPointY(), tmp );
float zpx = tmp.getWidth();
float zpy = tmp.getHeight();
Dim2f.toPool( tmp );
if ( this.cursorImage == null )
{
cursorImage = new Image( true, texWidth, texHeight, cursor.getTexture(), TileMode.TILE_BOTH );
cursorImage.setLocation( lastMousePos.getX() - zpx, lastMousePos.getY() - zpy );
cursorImage.setZIndex( CURSOR_Z_INDEX );
branchGroup.addChild( __HUD_base_PrivilegedAccess.getSGNode( cursorImage ) );
__HUD_base_PrivilegedAccess.setHUD( this, cursorImage );
}
else
{
if ( cursorImage.getTexture() != cursor.getTexture() )
cursorImage.setTexture( cursor.getTexture() );
if ( ( cursorImage.getWidth() != texWidth ) || ( cursorImage.getHeight() != texHeight ) )
{
cursorImage.setSize( texWidth, texHeight );
}
cursorImage.setLocation( lastMousePos.getX() - zpx, lastMousePos.getY() - zpy );
}
cursorImage.setVisible( true );
currentCursorType = type;
currentCursor = cursor;
}
else if ( allowDetach )
{
if ( __HUD_base_PrivilegedAccess.getSGNode( cursorImage ).getParent() != null )
__HUD_base_PrivilegedAccess.getSGNode( cursorImage ).detach();
__HUD_base_PrivilegedAccess.setHUD( null, cursorImage );
cursorImage = null;
currentCursorType = null;
currentCursor = null;
}
else
{
if ( cursorImage != null )
{
cursorImage.setVisible( false );
}
}
}
/**
* This is a convenience- and backwards-compatiblity-method to set the {@link Cursor}.
* This sets the Cursor.Type#POINTER1 entry in the current {@link CursorSet}.
*
* @param pointer1 the new Cursor to use for pointer1 (or null for no cursor)
*/
public void setCursor( Cursor pointer1 )
{
getCursorSet().setPointer1( pointer1 );
if ( currentCursorType == Cursor.Type.POINTER1 )
{
setCursorInternal( pointer1, Cursor.Type.POINTER1, true );
}
}
/**
* This is a convenience- and backwards-compatiblity-method to set the {@link Cursor}.
* This sets the Cursor.Type#POINTER1 entry in the current {@link CursorSet}.
*
* @param pointer1 the new Cursor to use for pointer1 (or null for no cursor)
*/
public void setCursor( String pointer1 )
{
if ( getCursorSet().getPointer1() == null )
getCursorSet().setPointer1( new Cursor( pointer1 ) );
else
getCursorSet().getPointer1().setTexture( pointer1 );
if ( currentCursorType == Cursor.Type.POINTER1 )
{
setCursorInternal( getCursorSet().getPointer1(), Cursor.Type.POINTER1, true );
}
}
/**
* Sets the cursor's visibility.<br>
* If no cursor image has been set, this call will have no effect!
*
* @param visible
*/
public void setCursorVisible( boolean visible )
{
if ( cursorImage != null )
cursorImage.setVisible( visible );
}
/**
* @return the cursor's current visibility.
*/
public final boolean isCursorVisible()
{
if ( cursorImage == null )
return ( false );
return ( cursorImage.isVisible() );
}
private void setCrosshairLocation( Image crosshairImage, int hotspotX, int hotspotY, float imgWidth, float imgHeight )
{
if ( ( hotspotX < 0 ) || ( hotspotY < 0 ) )
{
final float posX = ( getResX() - imgWidth ) / 2.0f;
final float posY = ( getResY() - imgHeight ) / 2.0f;
crosshairImage.setLocation( posX, posY );
}
else
{
Dim2f tmp = Dim2f.fromPool();
getCoordinatesConverter().getSizePixels2HUD( hotspotX, hotspotY, tmp );
float posX = ( getResX() - imgWidth ) / 2.0f + hotspotX;
float posY = ( getResY() - imgHeight ) / 2.0f + hotspotY;
Dim2f.toPool( tmp );
crosshairImage.setLocation( posX, posY );
}
this.crosshairHotspotX = hotspotX;
this.crosshairHotspotY = hotspotY;
}
/**
* Sets the Texture for the crosshair.<br>
* Use <i>null</i> for texture to remove the crosshair.
*
* @param texture the new texture for the crosshair Image (or null for no crosshair)
* @param hotspotX texture-relative location of the crossheir's hotspot (x)
* @param hotspotY texture-relative location of the crossheir's hotspot (y)
*/
public void setCrosshair( Texture2D texture, int hotspotX, int hotspotY )
{
if ( texture != null )
{
Dim2f tmp = Dim2f.fromPool();
getCoordinatesConverter().getSizePixels2HUD( HUDTextureUtils.getTextureWidth( texture ), HUDTextureUtils.getTextureHeight( texture ), tmp );
float imgWidth = tmp.getWidth();
float imgHeight = tmp.getHeight();
Dim2f.toPool( tmp );
if ( this.crosshairImage == null )
{
crosshairImage = new Image( true, imgWidth, imgHeight, texture, TileMode.TILE_BOTH );
crosshairImage.setZIndex( CROSSHAIR_Z_INDEX );
setCrosshairLocation( crosshairImage, hotspotX, hotspotY, imgWidth, imgHeight );
branchGroup.addChild( __HUD_base_PrivilegedAccess.getSGNode( crosshairImage ) );
__HUD_base_PrivilegedAccess.setHUD( this, crosshairImage );
}
else
{
crosshairImage.setTexture( texture );
if ( ( crosshairImage.getWidth() != imgWidth ) || ( crosshairImage.getHeight() != imgHeight ) )
{
crosshairImage.setSize( imgWidth, imgHeight );
setCrosshairLocation( crosshairImage, hotspotX, hotspotY, imgWidth, imgHeight );
}
else if ( ( hotspotX != this.crosshairHotspotX ) || ( hotspotY != this.crosshairHotspotY ) )
{
setCrosshairLocation( crosshairImage, hotspotX, hotspotY, imgWidth, imgHeight );
}
}
}
else
{
if ( __HUD_base_PrivilegedAccess.getSGNode( crosshairImage ).getParent() != null )
branchGroup.removeChild( __HUD_base_PrivilegedAccess.getSGNode( crosshairImage ) );
crosshairImage = null;
}
}
/**
* Sets the Texture for the crosshair.<br>
* Use <i>null</i> for texture to remove the crosshair.
*
* @param texture the new texture for the crosshair Image (or null for no crosshair)
* @param hotspot texture-relative location of the crossheir's hotspot
*/
public final void setCrosshair( Texture2D texture, Tuple2i hotspot )
{
setCrosshair( texture, hotspot.getX(), hotspot.getY() );
}
/**
* Sets the Texture for the corsshair. The texture MUST support an alpha channel.<br>
* Use <i>null</i> for texture to remove the crosshair.
*
* @param texture the new texture for the crosshair Image (or null for no crosshair)
* @param hotspotX texture-relative location of the crossheir's hotspot (x)
* @param hotspotY texture-relative location of the crossheir's hotspot (y)
*/
public final void setCrosshair( String texture, int hotspotX, int hotspotY )
{
setCrosshair( HUDTextureUtils.getTexture( texture, true ), hotspotX, hotspotY );
}
/**
* Sets the Texture for the corsshair. The texture MUST support an alpha channel.<br>
* Use <i>null</i> for texture to remove the crosshair.
*
* @param texture the new texture for the crosshair Image (or null for no crosshair)
* @param hotspot texture-relative location of the crossheir's hotspot
*/
public final void setCrosshair( String texture, Tuple2i hotspot )
{
setCrosshair( texture, hotspot.getX(), hotspot.getY() );
}
/**
* Sets the Texture for the crosshair.<br>
* Use <i>null</i> for texture to remove the crosshair.
*
* @param texture the new texture for the crosshair Image (or null for no crosshair)
*/
public final void setCrosshair( Texture2D texture )
{
setCrosshair( texture, -1, -1 );
}
/**
* Sets the Texture for the corsshair. The texture MUST support an alpha channel.<br>
* Use <i>null</i> for texture to remove the crosshair.
*
* @param texture the new texture for the crosshair Image (or null for no crosshair)
*/
public final void setCrosshair( String texture )
{
setCrosshair( texture, -1, -1 );
}
/**
* Sets the crosshair's visibility.<br>
* If no crosshair image has been set, this call will have no effect!
*
* @param visible
*/
public void setCrosshairVisible( boolean visible )
{
if ( crosshairImage != null )
crosshairImage.setVisible( visible );
}
/**
* @return the crosshair's current visibility.
*/
public final boolean isCrosshairVisible()
{
if ( crosshairImage == null )
return ( false );
return ( crosshairImage.isVisible() );
}
/**
* @return this HUD's OperationScheduler
*/
public final OperationScheduler getOperationScheduler()
{
return ( opScheduler );
}
final void updateOperations( long nanoGameTime, long nanoFrameTime )
{
opScheduler.update( nanoGameTime, nanoFrameTime, TimingMode.NANOSECONDS );
}
/**
* Connects this HUD to the given Sized2i instance (e.g. a Canvas3D)
* and listenes for its resized event.
*
* @param canvas
*/
public void connect( ExtSized2i canvas )
{
if ( isConnected() )
return;
this.canvasConnection = new HUDCanvas3DConnection();
canvas.addResizeListener( canvasConnection );
// when the HUD is first added to the scenegraph, the Widgets need to be updated.
update();
}
/**
* Connects this HUD to the given InputSystem.
*
* @param inputSystem
*/
public void connect( InputSystem inputSystem )
{
if ( inputSystem != null )
{
this.inputSystemConnection = new HUDInputSystemConnection( this );
inputSystem.addInputListener( inputSystemConnection );
inputSystem.addInputStateListener( inputSystemConnection );
if ( inputSystem.hasMouse() )
{
final Mouse mouse = inputSystem.getMouse();
lastMousePos.set( mouse.getCurrentX(), mouse.getCurrentY() );
mouse.addMouseStopListener( inputSystemConnection );
}
}
}
/**
* Disconnects this HUD from the given Sized2i instance (e.g. a Canvas3D)
* and does not listen for its resized event anymore.
*
* @param canvas
*/
public void disconnect( ExtSized2i canvas )
{
if ( canvasConnection != null )
{
canvas.removeResizeListener( canvasConnection );
canvasConnection = null;
}
}
/**
* Disconnects this HUD from the given InputSystem.
*
* @param inputSystem
*/
public void disconnect( InputSystem inputSystem )
{
if ( ( inputSystem != null ) && ( inputSystemConnection != null ) )
{
inputSystem.removeInputListener( inputSystemConnection );
inputSystem.removeInputStateListener( inputSystemConnection );
if ( inputSystem.hasMouse() )
{
final Mouse mouse = inputSystem.getMouse();
mouse.removeMouseStopListener( inputSystemConnection );
}
this.inputSystemConnection = null;
}
}
/**
* @return if the HUD is currently connected with the {@link SceneGraph}.
*/
public final boolean isConnected()
{
return ( canvasConnection != null );
}
protected WidgetContainer createDefaultContentPane( boolean heavyWeight, float resX, float resY )
{
Panel p = new Panel( heavyWeight, resX, resY, null, null );
p.setClippingEnabled( false );
p.setName( "HUD ContentPane" );
return ( p );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resolution the resolution of the coordinate system
* @param contentPane
* @param createHeavyWeightContentPane
*/
protected HUD( int canvasWidth, int canvasHeight, Sized2fRO resolution, WidgetContainer contentPane, boolean createHeavyWeightContentPane )
{
super();
Node.pushGlobalIgnoreBounds( true );
this.branchGroup = new BranchGroup();
Node.popGlobalIgnoreBounds();
float resX = ( resolution == null ) ? canvasWidth : resolution.getWidth();
float resY = ( resolution == null ) ? canvasHeight: resolution.getHeight();
if ( contentPane == null )
setContentPane( createDefaultContentPane( createHeavyWeightContentPane, resX, resY ) );
else
setContentPane( contentPane );
setSize( canvasWidth, canvasHeight, resolution );
this.lastMousePos = new Tuple2f( getResX() / 2f, getResY() / 2f );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resolution the resolution of the coordinate system
* @param contentPane
*/
public HUD( int canvasWidth, int canvasHeight, Sized2fRO resolution, WidgetContainer contentPane )
{
this( canvasWidth, canvasHeight, resolution, contentPane, true );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resolution the resolution of the coordinate system
*/
public HUD( int canvasWidth, int canvasHeight, Sized2fRO resolution )
{
this( canvasWidth, canvasHeight, resolution, null );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resX the new width of the coordinate system
* @param resY the new height of the coordinate system
*/
public HUD( int canvasWidth, int canvasHeight, float resX, float resY )
{
this( canvasWidth, canvasHeight, new Dim2f( resX, resY ) );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resX the new width of the coordinate system
* @param resY the new height of the coordinate system
* @param contentPane
*/
public HUD( int canvasWidth, int canvasHeight, float resX, float resY, WidgetContainer contentPane )
{
this( canvasWidth, canvasHeight, new Dim2f( resX, resY ), contentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resolution the resolution of the coordinate system
*/
public HUD( Sized2iRO canvas, Sized2fRO resolution )
{
this( canvas.getWidth(), canvas.getHeight(), resolution );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resolution the resolution of the coordinate system
* @param contentPane
*/
public HUD( Sized2iRO canvas, Sized2fRO resolution, WidgetContainer contentPane )
{
this( canvas.getWidth(), canvas.getHeight(), resolution, contentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the x-resolution of the coordinate system. The y-resolution is calculateed by (resX / canvasAspect).
*/
public HUD( Sized2iRO canvas, float resX )
{
this( canvas.getWidth(), canvas.getHeight(), resX, resX / canvas.getAspect() );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the x-resolution of the coordinate system. The y-resolution is calculateed by (resX / canvasAspect).
* @param createHeavyWeightContentPane
*/
public HUD( Sized2iRO canvas, float resX, boolean createHeavyWeightContentPane )
{
this( canvas.getWidth(), canvas.getHeight(), new Dim2f( resX, resX / canvas.getAspect() ), null, createHeavyWeightContentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the x-resolution of the coordinate system. The y-resolution is calculateed by (resX / canvasAspect).
* @param contentPane
*/
public HUD( Sized2iRO canvas, float resX, WidgetContainer contentPane )
{
this( canvas.getWidth(), canvas.getHeight(), resX, resX / canvas.getAspect(), contentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resX the x-resolution of the coordinate system. The y-resolution is calculateed by (resX / canvasAspect).
*/
public HUD( int canvasWidth, int canvasHeight, float resX )
{
this( canvasWidth, canvasHeight, new Dim2f( resX, resX / ( (float)canvasWidth / (float)canvasHeight ) ) );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
* @param resX the x-resolution of the coordinate system. The y-resolution is calculateed by (resX / canvasAspect).
* @param contentPane
*/
public HUD( int canvasWidth, int canvasHeight, float resX, WidgetContainer contentPane )
{
this( canvasWidth, canvasHeight, new Dim2f( resX, resX / ( (float)canvasWidth / (float)canvasHeight ) ), contentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the new width of the coordinate system
* @param resY the new height of the coordinate system
*/
public HUD( Sized2iRO canvas, float resX, float resY )
{
this( canvas, new Dim2f( resX, resY ) );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the new width of the coordinate system
* @param resY the new height of the coordinate system
* @param createHeavyWeightContentPane
*/
public HUD( Sized2iRO canvas, float resX, float resY, boolean createHeavyWeightContentPane )
{
this( canvas.getWidth(), canvas.getHeight(), new Dim2f( resX, resY ), null, createHeavyWeightContentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the aspect ratio from
* @param resX the new width of the coordinate system
* @param resY the new height of the coordinate system
* @param contentPane
*/
public HUD( Sized2iRO canvas, float resX, float resY, WidgetContainer contentPane )
{
this( canvas, new Dim2f( resX, resY ), contentPane );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvasWidth the width of the Canvas3D to take the resolution and aspect from
* @param canvasHeight the width of the Canvas3D to take the resolution and aspect from
*/
public HUD( int canvasWidth, int canvasHeight )
{
this( canvasWidth, canvasHeight, (Sized2fRO)null );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the resolution and aspect ratio from
*/
public HUD( Sized2iRO canvas )
{
this( canvas, (Sized2fRO)null );
}
/**
* Creates a new HUD with a coordinate system with the given width and height
*
* @param canvas the Canvas3D to take the resolution and aspect ratio from
*/
public HUD( Sized2iRO canvas, boolean createHeavyWeightContentPane )
{
this( canvas.getWidth(), canvas.getHeight(), (Sized2fRO)null, null, createHeavyWeightContentPane );
}
}