/** * 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.menusystem.menus.settings; import java.util.ArrayList; import java.util.HashMap; import org.jagatoo.input.devices.components.DeviceComponent; import org.jagatoo.input.devices.components.Key; import org.jagatoo.input.devices.components.MouseButton; import org.jagatoo.input.devices.components.MouseButtons; import org.jagatoo.input.managers.InputBindingsManager; import org.jagatoo.input.managers.InputBindingsSet; import org.openmali.vecmath2.Colorf; import org.xith3d.input.FirstPersonInputHandler; import org.xith3d.input.modules.fpih.FPIHInputAction; import org.xith3d.input.modules.fpih.FPIHInputBindingsManager; import org.xith3d.ui.hud.base.Widget; import org.xith3d.ui.hud.borders.ColoredBorder; import org.xith3d.ui.hud.layout.FillLayout; import org.xith3d.ui.hud.layout.GridLayout; import org.xith3d.ui.hud.layout.LayoutManager; import org.xith3d.ui.hud.listeners.WidgetInputAdapter; import org.xith3d.ui.hud.listeners.WidgetInputListener; import org.xith3d.ui.hud.listeners.WidgetMouseAdapter; import org.xith3d.ui.hud.listeners.WidgetMouseListener; import org.xith3d.ui.hud.menusystem.menus.MenuBase; import org.xith3d.ui.hud.utils.HUDFont; import org.xith3d.ui.hud.widgets.Label; import org.xith3d.ui.hud.widgets.Panel; import org.xith3d.ui.text2d.TextAlignment; /** * This is a settings menu for the {@link FirstPersonInputHandler}'s input bindings. * * @author Marvin Froehlich (aka Qudus) */ public class FPIHInputBindingsSettingsMenu extends MenuBase { public static final String NAME = FPIHInputBindingsSettingsMenu.class.getSimpleName(); private final HashMap< FPIHInputAction, Label[] > actionLabelMap = new HashMap< FPIHInputAction, Label[] >(); private final HashMap< Label, FPIHInputAction > labelActionMap = new HashMap< Label, FPIHInputAction >(); private final InputBindingsManager< FPIHInputAction > inputBindings = new InputBindingsManager< FPIHInputAction >( FPIHInputAction.values().length ); private Label bindingQuery; private Label lastClickedLabel = null; public void setBinding( DeviceComponent comp, FPIHInputAction action, InputBindingsSet set ) { FPIHInputAction bound = inputBindings.getBoundAction( comp ); if ( bound != null ) { Label[] boundLabels = actionLabelMap.get( bound ); if ( boundLabels[ 0 ].getText().equals( comp.getName() ) ) boundLabels[ 0 ].setText( "" ); else if ( boundLabels[ 1 ].getText().equals( comp.getName() ) ) boundLabels[ 1 ].setText( "" ); } final Label targetLabel; if ( set == InputBindingsSet.PRIMARY ) targetLabel = actionLabelMap.get( action )[ 0 ]; else //if ( set == BindingSet.SECONDARY ) targetLabel = actionLabelMap.get( action )[ 1 ]; inputBindings.bind( comp, action, set ); targetLabel.setText( comp.getLocalizedName() ); } public void resetBinding( FPIHInputAction action, InputBindingsSet set ) { if ( inputBindings.unbind( action ) != null ) { final Label targetLabel; if ( set == InputBindingsSet.PRIMARY ) targetLabel = actionLabelMap.get( action )[ 0 ]; else //if ( set == BindingSet.SECONDARY ) targetLabel = actionLabelMap.get( action )[ 1 ]; targetLabel.setText( "" ); } } public FPIHInputAction getBinding( DeviceComponent comp ) { return ( inputBindings.getBoundAction( comp ) ); } public DeviceComponent getBoundComponent( FPIHInputAction action, InputBindingsSet set ) { return ( inputBindings.getBoundComponent( action, set ) ); } public void clearBindings() { inputBindings.unbindAll(); for ( Label label: labelActionMap.keySet() ) { label.setText( "" ); } } public void setBindings( InputBindingsManager< FPIHInputAction > inputBindings ) { clearBindings(); for ( FPIHInputAction action: FPIHInputAction.values() ) { for ( InputBindingsSet set: InputBindingsSet.values() ) { final DeviceComponent comp = inputBindings.getBoundComponent( action, set ); if ( comp != null ) { setBinding( comp, action, set ); } } } } public InputBindingsManager< FPIHInputAction > getBindings() { return ( inputBindings ); } private WidgetInputListener bindingSetListener = new WidgetInputAdapter() { private final void handleInput( DeviceComponent comp ) { bindingQuery.removeInputListener( bindingSetListener ); if ( lastClickedLabel == null ) return; bindingQuery.setClickable( false ); bindingQuery.setPickable( false ); bindingQuery.setVisible( false ); final FPIHInputAction action = labelActionMap.get( lastClickedLabel ); setBinding( comp, action, (InputBindingsSet)lastClickedLabel.getUserObject() ); getMenuGroup().fireOnSettingChanged( FPIHInputBindingsSettingsMenu.this, "key_binding", comp.getName() + "=>" + action ); lastClickedLabel = null; } @Override public void onKeyPressed( Widget widget, Key key, int modifierMask, long when ) { handleInput( key ); } @Override public void onMouseWheelMoved( Widget widget, int delta, boolean isPageMove, float x, float y, long when, boolean isTopMost ) { if ( delta > 0 ) handleInput( MouseButtons.WHEEL_UP ); else if ( delta < 0 ) handleInput( MouseButtons.WHEEL_DOWN ); } }; private WidgetMouseListener bindingInputListener = new WidgetMouseAdapter() { @Override public void onMouseButtonReleased( Widget widget, MouseButton button, float x, float y, long when, long lastWhen, boolean isTopMost, boolean hasFocus ) { lastClickedLabel = (Label)widget; if ( ( lastWhen != -1L ) && ( ( when - lastWhen ) < 300000000L ) ) { float parentLeft = 0f; float parentTop = 0f; float parentResX = 0f; float parentResY = 0f; if ( widget.getContainer() != null ) { parentLeft = widget.getContainer().getLeft(); parentTop = widget.getContainer().getTop(); parentResX = widget.getContainer().getResX(); parentResY = widget.getContainer().getResY(); } else if ( widget.getHUD() != null ) { parentResX = widget.getHUD().getResX(); parentResY = widget.getHUD().getResY(); } bindingQuery.setLocation( parentLeft + 2f, parentTop + 2f ); bindingQuery.setSize( parentResX - 4f, parentResY - 4f ); bindingQuery.setClickable( true ); bindingQuery.setPickable( true ); bindingQuery.setVisible( true ); bindingQuery.setFocussable( true ); bindingQuery.requestFocus(); bindingQuery.addInputListener( bindingSetListener ); } } }; private ArrayList< Widget > earlyWidgets; /** * Applies the {@link FirstPersonInputHandler}'s relevant config to this config menu. * * @param fpih */ public void applyConfig( FirstPersonInputHandler fpih ) { setBindings( fpih.getBindingsManager() ); } /** * Reads the relevant config from this config menu * and applies it to the {@link FirstPersonInputHandler}. * * @param fpih * @param clearFPIHBefore */ public void extractConfig( FirstPersonInputHandler fpih, boolean clearFPIHBefore ) { fpih.getBindingsManager().set( inputBindings, clearFPIHBefore ); } /** * {@inheritDoc} */ @Override protected void initWidgets() { if ( earlyWidgets != null ) { for ( int i = 0; i < earlyWidgets.size(); i++ ) { addWidget( earlyWidgets.get( i ) ); } earlyWidgets = null; } } private Panel createMiniPanel( float height, int borderBottom, int borderRight, int borderTop, int borderLeft, Colorf backgroundColor ) { Panel panel = new Panel( 200f, height, backgroundColor ); panel.setLayout( new FillLayout() ); panel.setBorder( new ColoredBorder( borderBottom, borderRight, borderTop, borderLeft, Colorf.DARK_GRAY ) ); return ( panel ); } private void addHeaderLine( HUDFont font ) { Panel panel1 = createMiniPanel( 30f, 1, 1, 1, 1, null ); Label label1 = new Label( 0f, 0f, "Command", font, Colorf.BLACK, TextAlignment.CENTER_LEFT ); label1.setPadding( 0, 3, 0, 3 ); panel1.addWidget( label1 ); earlyWidgets.add( panel1 ); Panel panel2 = createMiniPanel( 30f, 1, 1, 1, 0, null ); Label label2 = new Label( 0f, 0f, "Key 1", font, Colorf.BLACK, TextAlignment.CENTER_CENTER ); panel2.addWidget( label2 ); earlyWidgets.add( panel2 ); Panel panel3 = createMiniPanel( 30f, 1, 1, 1, 0, null ); Label label3 = new Label( 0f, 0f, "Key 2", font, Colorf.BLACK, TextAlignment.CENTER_CENTER ); panel3.addWidget( label3 ); earlyWidgets.add( panel3 ); Panel panel4 = createMiniPanel( 5f, 0, 1, 0, 1, null ); earlyWidgets.add( panel4 ); Panel panel5 = createMiniPanel( 5f, 0, 1, 0, 0, null ); earlyWidgets.add( panel5 ); Panel panel6 = createMiniPanel( 5f, 0, 1, 0, 0, null ); earlyWidgets.add( panel6 ); } private void addBindingLine( String caption, FPIHInputAction action, HUDFont font ) { final int borderTop = ( actionLabelMap.size() == 0 ) ? 1: 0; Panel panel1 = createMiniPanel( 30f, 1, 1, borderTop, 1, null ); Label label1 = new Label( 1f, 1f, caption, font, Colorf.BLACK, TextAlignment.CENTER_LEFT ); label1.setPadding( 0, 3, 0, 3 ); panel1.addWidget( label1 ); earlyWidgets.add( panel1 ); Panel panel2 = createMiniPanel( 30f, 1, 1, borderTop, 0, Colorf.BLACK ); Label label2 = new Label( 1f, 1f, "", font, Colorf.WHITE, TextAlignment.CENTER_CENTER ); label2.setUserObject( InputBindingsSet.PRIMARY ); label2.addMouseListener( bindingInputListener ); panel2.addWidget( label2 ); earlyWidgets.add( panel2 ); Panel panel3 = createMiniPanel( 30f, 1, 1, borderTop, 0, Colorf.BLACK ); Label label3 = new Label( 1f, 1f, "", font, Colorf.WHITE, TextAlignment.CENTER_CENTER ); label3.setUserObject( InputBindingsSet.SECONDARY ); label3.addMouseListener( bindingInputListener ); panel3.addWidget( label3 ); earlyWidgets.add( panel3 ); actionLabelMap.put( action, new Label[] { label2, label3 } ); labelActionMap.put( label2, action ); labelActionMap.put( label3, action ); } public FPIHInputBindingsSettingsMenu( float width, float height ) { super( width, height, FPIHInputBindingsSettingsMenu.NAME, new String[] { "save" } ); this.setLayout( new GridLayout( 0, 3, 0f, 0f, 10f, 10f, 10f, 10f ) ); HUDFont font = HUDFont.getFont( "Verdana", HUDFont.PLAIN, 12 ); earlyWidgets = new ArrayList< Widget >(); addHeaderLine( font.derive( HUDFont.BOLD ) ); addBindingLine( FPIHInputAction.WALK_FORWARD.getLocalizedText(), FPIHInputAction.WALK_FORWARD, font ); addBindingLine( FPIHInputAction.WALK_BACKWARD.getLocalizedText(), FPIHInputAction.WALK_BACKWARD, font ); addBindingLine( FPIHInputAction.STRAFE_LEFT.getLocalizedText(), FPIHInputAction.STRAFE_LEFT, font ); addBindingLine( FPIHInputAction.STRAFE_RIGHT.getLocalizedText(), FPIHInputAction.STRAFE_RIGHT, font ); addBindingLine( FPIHInputAction.TURN_LEFT.getLocalizedText(), FPIHInputAction.TURN_LEFT, font ); addBindingLine( FPIHInputAction.TURN_RIGHT.getLocalizedText(), FPIHInputAction.TURN_RIGHT, font ); addBindingLine( FPIHInputAction.AIM_UP.getLocalizedText(), FPIHInputAction.AIM_UP, font ); addBindingLine( FPIHInputAction.AIM_DOWN.getLocalizedText(), FPIHInputAction.AIM_DOWN, font ); addBindingLine( FPIHInputAction.JUMP.getLocalizedText(), FPIHInputAction.JUMP, font ); addBindingLine( FPIHInputAction.CROUCH.getLocalizedText(), FPIHInputAction.CROUCH, font ); addBindingLine( FPIHInputAction.DISCRETE_ZOOM_IN.getLocalizedText(), FPIHInputAction.DISCRETE_ZOOM_IN, font ); addBindingLine( FPIHInputAction.DISCRETE_ZOOM_OUT.getLocalizedText(), FPIHInputAction.DISCRETE_ZOOM_OUT, font ); addBindingLine( FPIHInputAction.ZOOM_IN.getLocalizedText(), FPIHInputAction.ZOOM_IN, font ); addBindingLine( FPIHInputAction.ZOOM_OUT.getLocalizedText(), FPIHInputAction.ZOOM_OUT, font ); this.bindingQuery = new Label( 0f, 0f, "PRESS_KEY", font.derive( HUDFont.BOLD ), Colorf.GREEN, TextAlignment.CENTER_CENTER ); this.bindingQuery.setZIndex( 10 ); bindingQuery.setBackgroundColor( Colorf.BLACK ); this.addWidget( bindingQuery, 100f, 100f, LayoutManager.IGNORED_BY_LAYOUT ); bindingQuery.setVisible( false ); bindingQuery.setClickable( false ); bindingQuery.setPickable( false ); // Apply default settings... setBindings( FPIHInputBindingsManager.DEFAULT_BINDINGS ); } public FPIHInputBindingsSettingsMenu( float width ) { this( width, 0f ); setMinimalHeight(); } }