/** * Copyright (C) 2009-2014 Cars and Tracks Development Project (CTDP). * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package net.ctdp.rfdynhud.widgets.standard.revmeter; import java.io.IOException; import net.ctdp.rfdynhud.properties.AbstractPropertiesKeeper; import net.ctdp.rfdynhud.properties.ImageProperty; import net.ctdp.rfdynhud.properties.IntProperty; import net.ctdp.rfdynhud.properties.PropertiesContainer; import net.ctdp.rfdynhud.properties.PropertyLoader; import net.ctdp.rfdynhud.render.ImageTemplate; import net.ctdp.rfdynhud.render.TransformableTexture; import net.ctdp.rfdynhud.util.PropertyWriter; import net.ctdp.rfdynhud.util.RFDHLog; import net.ctdp.rfdynhud.util.SubTextureCollector; import net.ctdp.rfdynhud.widgets.base.widget.Widget; import org.jagatoo.logging.Log; public class ShiftLight { private static final String[] default_shift_light_on_images = { "standard/shiftlight_on_red.png", "standard/shiftlight_on_orange.png", "standard/shiftlight_on_yellow.png", "standard/shiftlight_on_lightgreen.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", "standard/shiftlight_on_green.png", }; public static final ShiftLight DEFAULT_SHIFT_LIGHT1 = new ShiftLight( null, 1 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT2 = new ShiftLight( null, 2 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT3 = new ShiftLight( null, 3 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT4 = new ShiftLight( null, 4 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT5 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT6 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT7 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT8 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT9 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT10 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT11 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT12 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT13 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT14 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT15 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT16 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT17 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT18 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT19 = new ShiftLight( null, 5 ); public static final ShiftLight DEFAULT_SHIFT_LIGHT20 = new ShiftLight( null, 5 ); private final RevMeterWidget widget; private final int indexOneBased; private final ImageProperty imageNameOff; private final ImageProperty imageNameOn; private final IntProperty posX; private final IntProperty posY; private final IntProperty height; final IntProperty activationRPM; private TransformableTexture textureOff = null; private TransformableTexture textureOn = null; public void resetTextures() { this.textureOff = null; this.textureOn = null; } /** * * @param imageChanged * @param deltaScaleX * @param deltaScaleY */ public void onBackgroundChanged( boolean imageChanged, float deltaScaleX, float deltaScaleY ) { resetTextures(); posX.setIntValue( Math.round( posX.getIntValue() * deltaScaleX ) ); posY.setIntValue( Math.round( posY.getIntValue() * deltaScaleY ) ); height.setIntValue( Math.round( height.getIntValue() * deltaScaleY ) ); } private final boolean isOffStatePartOfBackground() { return ( imageNameOff.getValue().equals( "" ) ); } public void loadTextures( boolean isEditorMode, SubTextureCollector collector ) { if ( !isOffStatePartOfBackground() ) { try { ImageTemplate it = imageNameOff.getImage(); if ( it == null ) { textureOff = null; return; } float scale = widget.getBackground().getScaleY(); int w, h; if ( height.getIntValue() == 0 ) { w = Math.round( it.getBaseWidth() * scale ); h = Math.round( it.getBaseHeight() * scale ); } else { h = Math.round( height.getFloatValue() * scale ); w = Math.round( h * it.getBaseAspect() ); } if ( ( textureOff == null ) || ( textureOff.getWidth() != w ) || ( textureOff.getHeight() != h ) ) { textureOff = TransformableTexture.getOrCreate( w, h, TransformableTexture.DEFAULT_PIXEL_PERFECT_POSITIONING, textureOff, isEditorMode ); it.drawScaled( 0, 0, w, h, textureOff.getTexture(), true ); } collector.add( textureOff ); } catch ( Throwable t ) { Log.exception( Widget.LOG_CHANNEL, t ); return; } } else { textureOff = null; } try { ImageTemplate it = imageNameOn.getImage(); if ( it == null ) { textureOn = null; return; } if ( isOffStatePartOfBackground() ) { int w, h; if ( height.getIntValue() == 0 ) { w = Math.round( it.getBaseWidth() * widget.getBackground().getScaleX() ); h = Math.round( it.getBaseHeight() * widget.getBackground().getScaleY() ); } else { h = Math.round( height.getFloatValue() * widget.getBackground().getScaleY() ); w = Math.round( h * it.getBaseAspect() ); } if ( ( textureOn == null ) || ( textureOn.getWidth() != w ) || ( textureOn.getHeight() != h * 2 ) ) { textureOn = TransformableTexture.getOrCreate( w, h * 2, TransformableTexture.DEFAULT_PIXEL_PERFECT_POSITIONING, textureOn, isEditorMode ); // TODO: Move this code to drawBackground() of RevMeterWidget! if ( widget.getBackgroundProperty().getBackgroundType().isImage() ) { ImageTemplate it0 = widget.getBackgroundProperty().getImageValue(); it0.drawScaled( posX.getIntValue(), posY.getIntValue(), it.getBaseWidth(), it.getBaseHeight(), 0, 0, w, h, textureOn.getTexture(), false ); it0.drawScaled( posX.getIntValue(), posY.getIntValue(), it.getBaseWidth(), it.getBaseHeight(), 0, h, w, h, textureOn.getTexture(), false ); } else if ( widget.getBackgroundProperty().getBackgroundType().isColor() ) { textureOn.getTexture().clear( widget.getBackground().getColor(), true, null ); } it.drawScaled( 0, 0, w, h, textureOn.getTexture(), false ); } } else { float scale = widget.getBackground().getScaleY(); int w, h; if ( height.getIntValue() == 0 ) { w = Math.round( it.getBaseWidth() * scale ); h = Math.round( it.getBaseHeight() * scale ); } else { h = Math.round( height.getFloatValue() * scale ); w = Math.round( h * it.getBaseAspect() ); } if ( ( textureOn == null ) || ( textureOn.getWidth() != w ) || ( textureOn.getHeight() != h ) ) { textureOn = TransformableTexture.getOrCreate( w, h, TransformableTexture.DEFAULT_PIXEL_PERFECT_POSITIONING, textureOn, isEditorMode ); it.drawScaled( 0, 0, w, h, textureOn.getTexture(), true ); } } collector.add( textureOn ); } catch ( Throwable t ) { RFDHLog.exception( t ); return; } } public int writeTexturesToArray( TransformableTexture[] array, int offset ) { if ( textureOff != null ) array[offset++] = textureOff; if ( textureOn != null ) array[offset++] = textureOn; return ( offset ); } public void updateTextures( float rpm, float maxRPM, float backgroundScaleX, float backgroundScaleY ) { boolean isOn = ( rpm >= maxRPM + activationRPM.getIntValue() ); if ( isOffStatePartOfBackground() ) { if ( textureOn != null ) { if ( isOn ) { textureOn.setClipRect( 0, 0, textureOn.getWidth(), textureOn.getHeight() / 2, true ); textureOn.setTranslation( Math.round( posX.getIntValue() * backgroundScaleX ), Math.round( posY.getIntValue() * backgroundScaleY ) ); } else { textureOn.setClipRect( 0, textureOn.getHeight() / 2, textureOn.getWidth(), textureOn.getHeight() / 2, true ); textureOn.setTranslation( Math.round( posX.getIntValue() * backgroundScaleX ), Math.round( posY.getIntValue() * backgroundScaleY ) - textureOn.getHeight() / 2 ); } } } else { if ( isOn ) { if ( textureOn != null ) { textureOn.setClipRect( 0, 0, textureOn.getWidth(), textureOn.getHeight(), true ); textureOn.setTranslation( Math.round( posX.getIntValue() * backgroundScaleX ), Math.round( posY.getIntValue() * backgroundScaleY ) ); textureOn.setVisible( true ); } if ( textureOff != null ) textureOff.setVisible( false ); } else { if ( textureOff != null ) { textureOff.setClipRect( 0, 0, textureOff.getWidth(), textureOff.getHeight(), true ); textureOff.setTranslation( Math.round( posX.getIntValue() * backgroundScaleX ), Math.round( posY.getIntValue() * backgroundScaleY ) ); textureOff.setVisible( true ); } if ( textureOn != null ) textureOn.setVisible( false ); } } } public void saveProperties( PropertyWriter writer ) throws IOException { AbstractPropertiesKeeper.setKeeper( imageNameOff, widget ); AbstractPropertiesKeeper.setKeeper( imageNameOn, widget ); writer.writeProperty( imageNameOff, "The name of the shift light image for \"off\" state." ); writer.writeProperty( imageNameOn, "The name of the shift light image for \"on\" state." ); writer.writeProperty( posX, "The x-offset in background image pixels for the shift light image." ); writer.writeProperty( posY, "The y-offset in background image pixels for the shift light image." ); writer.writeProperty( height, "The height in background image pixels for the shift light image" ); writer.writeProperty( activationRPM, "The RPM (rounds per minute) to subtract from the maximum for the level to display shoft light on" ); } public boolean loadProperty( PropertyLoader loader ) { AbstractPropertiesKeeper.setKeeper( imageNameOff, widget ); AbstractPropertiesKeeper.setKeeper( imageNameOn, widget ); if ( loader.loadProperty( imageNameOff ) ) return ( true ); if ( loader.loadProperty( imageNameOn ) ) return ( true ); if ( loader.loadProperty( posX ) ) return ( true ); if ( loader.loadProperty( posY ) ) return ( true ); if ( loader.loadProperty( height ) ) return ( true ); if ( loader.loadProperty( activationRPM ) ) return ( true ); return ( false ); } /** * * @param propsCont * @param forceAll */ public void getProperties( PropertiesContainer propsCont, boolean forceAll ) { AbstractPropertiesKeeper.setKeeper( imageNameOff, widget ); AbstractPropertiesKeeper.setKeeper( imageNameOn, widget ); propsCont.addGroup( "Shift Light " + indexOneBased ); propsCont.addProperty( imageNameOff ); propsCont.addProperty( imageNameOn ); propsCont.addProperty( posX ); propsCont.addProperty( posY ); propsCont.addProperty( height ); propsCont.addProperty( activationRPM ); } public ShiftLight( RevMeterWidget widget, int indexOneBased ) { this.widget = widget; this.indexOneBased = indexOneBased; this.imageNameOff = new ImageProperty( "shiftLightImageNameOff" + indexOneBased, "imageNameOff", "standard/shiftlight_off.png", false, true ) { @Override protected void onValueChanged( String oldValue, String newValue ) { textureOff = null; } }; this.imageNameOn = new ImageProperty( "shiftLightImageNameOn" + indexOneBased, "imageNameOn", default_shift_light_on_images[indexOneBased - 1] ) { @Override protected void onValueChanged( String oldValue, String newValue ) { textureOn = null; } }; this.posX = new IntProperty( "shiftLightPosX" + indexOneBased, "posX", 625 - 32 * ( indexOneBased - 1 ) ) { @Override protected void onValueChanged( Integer oldValue, int newValue ) { resetTextures(); } }; this.posY = new IntProperty( "shiftLightPosY" + indexOneBased, "posY", 42 ) { @Override protected void onValueChanged( Integer oldValue, int newValue ) { resetTextures(); } }; this.height = new IntProperty( "shiftLightHeight" + indexOneBased, "height", 0, 0, 1000, false ) { @Override protected void onValueChanged( Integer oldValue, int newValue ) { resetTextures(); } }; this.activationRPM = new IntProperty( "shiftLightRPM" + indexOneBased, "activationRPM", 100 - 250 * indexOneBased, -5000, 0, false ); } }