/**
* 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.timing;
import java.awt.Font;
import java.io.IOException;
import java.util.Arrays;
import net.ctdp.rfdynhud.gamedata.Laptime;
import net.ctdp.rfdynhud.gamedata.LiveGameData;
import net.ctdp.rfdynhud.gamedata.ScoringInfo;
import net.ctdp.rfdynhud.gamedata.SessionType;
import net.ctdp.rfdynhud.gamedata.VehicleScoringInfo;
import net.ctdp.rfdynhud.properties.BooleanProperty;
import net.ctdp.rfdynhud.properties.ColorProperty;
import net.ctdp.rfdynhud.properties.IntProperty;
import net.ctdp.rfdynhud.properties.PropertiesContainer;
import net.ctdp.rfdynhud.properties.PropertyLoader;
import net.ctdp.rfdynhud.render.DrawnString;
import net.ctdp.rfdynhud.render.DrawnString.Alignment;
import net.ctdp.rfdynhud.render.DrawnStringFactory;
import net.ctdp.rfdynhud.render.TextureImage2D;
import net.ctdp.rfdynhud.util.PropertyWriter;
import net.ctdp.rfdynhud.util.SubTextureCollector;
import net.ctdp.rfdynhud.util.TimingUtil;
import net.ctdp.rfdynhud.valuemanagers.Clock;
import net.ctdp.rfdynhud.values.BoolValue;
import net.ctdp.rfdynhud.values.IntValue;
import net.ctdp.rfdynhud.values.LongValue;
import net.ctdp.rfdynhud.widgets.base.widget.Widget;
import net.ctdp.rfdynhud.widgets.standard._util.StandardWidgetSet;
/**
* The {@link TimingWidget} displays lap- and sector times and gaps.
*
* @author Marvin Froehlich (CTDP)
*/
public class TimingWidget extends Widget
{
private final BooleanProperty displayAbsFastest = new BooleanProperty( "displayAbsFastest", true );
private final BooleanProperty displayOwnFastest = new BooleanProperty( "displayOwnFastest", true );
private final BooleanProperty cumulativeSectors = new BooleanProperty( "cumulativeSectors", false );
private final BooleanProperty forceCurrentCumulSectors = new BooleanProperty( "forceCurrentCumulSectors", "forceCurrCumulSects", true );
private final IntProperty lastLapDisplayDelay = new IntProperty( "lastLapDisplayDelay", 10000, -100, Integer.MAX_VALUE ); // ten seconds
private final ColorProperty slowerColor = new ColorProperty( "slowerColor", "#FF7248" );
private final ColorProperty fasterColor = new ColorProperty( "fasterColor", "#6AFF3D" );
private DrawnString absFastestLapHeaderString = null;
private DrawnString absFastestLapDriverString = null;
private DrawnString absSector1String = null;
private DrawnString absSector2String = null;
private DrawnString absSector3String = null;
private DrawnString absFastestLapString = null;
private DrawnString ownFastestLapHeaderString = null;
private DrawnString ownSector1String = null;
private DrawnString ownSector2String = null;
private DrawnString ownSector3String = null;
private DrawnString ownFastestLapString = null;
private DrawnString currLapHeaderString = null;
private DrawnString currSector1String = null;
private DrawnString currSector2String = null;
private DrawnString currSector3String = null;
private DrawnString currLapString = null;
private final IntValue leaderID = new IntValue();
private int oldAbsFastestLap = -1;
private boolean absFLValid = false;
private int oldOwnFastestLap = -1;
private boolean ownFLValid = false;
private final BoolValue currLapValid = new BoolValue();
private float lastLapDisplayTime = -1f;
private float gapOFSec1 = 0f;
private boolean gapOFSec1Valid = false;
private float gapOFSec2 = 0f;
private boolean gapOFSec2Valid = false;
private float gapOFSec3 = 0f;
private boolean gapOFSec3Valid = false;
private float gapOFLap = 0f;
private float gapAFSec1 = 0f;
private boolean gapAFSec1Valid = false;
private float gapAFSec2 = 0f;
private boolean gapAFSec2Valid = false;
private float gapAFSec3 = 0f;
private boolean gapAFSec3Valid = false;
private float gapAFLap = 0f;
private final java.awt.Color[] fontColors = new java.awt.Color[ 5 ];
private Laptime delayedAbsFastestLap = null;
private Laptime delayedOwnFastestLap = null;
private boolean delayedAbsFastestIsOwn = false;
private int colPadding = 10;
private final LongValue scoringInfoUpdateID = new LongValue();
private final String[][] oldClStrings = new String[ 4 ][ 0 ];
public TimingWidget()
{
super( StandardWidgetSet.INSTANCE, StandardWidgetSet.WIDGET_PACKAGE_TIMING, 24.0625f, 30.083334f );
}
@Override
public void prepareForMenuItem()
{
super.prepareForMenuItem();
colPadding = 1;
getFontProperty().setFont( "Dialog", Font.PLAIN, 3, false, true );
}
/**
* {@inheritDoc}
*/
@Override
public void saveProperties( PropertyWriter writer ) throws IOException
{
super.saveProperties( writer );
writer.writeProperty( displayAbsFastest, "Display the absolute fastest lap part of the Widget?" );
writer.writeProperty( displayOwnFastest, "Display your own fastest lap part of the Widget?" );
writer.writeProperty( cumulativeSectors, "Display the second sector as a sum?" );
writer.writeProperty( forceCurrentCumulSectors, "Display the second sector as a sum even if the others not?" );
writer.writeProperty( lastLapDisplayDelay, "The time for which the last driven lap will keepbeing displayed (in milliseconds)." );
writer.writeProperty( slowerColor, "The font color to use for positive gaps." );
writer.writeProperty( fasterColor, "The font color to use for negative gaps." );
}
/**
* {@inheritDoc}
*/
@Override
public void loadProperty( PropertyLoader loader )
{
super.loadProperty( loader );
if ( loader.loadProperty( displayAbsFastest ) );
else if ( loader.loadProperty( displayOwnFastest ) );
else if ( loader.loadProperty( cumulativeSectors ) );
else if ( loader.loadProperty( forceCurrentCumulSectors ) );
else if ( loader.loadProperty( lastLapDisplayDelay ) );
else if ( loader.loadProperty( slowerColor ) );
else if ( loader.loadProperty( fasterColor ) );
}
/**
* {@inheritDoc}
*/
@Override
public void getProperties( PropertiesContainer propsCont, boolean forceAll )
{
super.getProperties( propsCont, forceAll );
propsCont.addGroup( "Misc" );
propsCont.addProperty( displayAbsFastest );
propsCont.addProperty( displayOwnFastest );
propsCont.addProperty( cumulativeSectors );
propsCont.addProperty( forceCurrentCumulSectors );
propsCont.addProperty( lastLapDisplayDelay );
propsCont.addProperty( slowerColor );
propsCont.addProperty( fasterColor );
}
/**
* {@inheritDoc}
*/
@Override
public void onSessionStarted( SessionType sessionType, LiveGameData gameData, boolean isEditorMode )
{
super.onSessionStarted( sessionType, gameData, isEditorMode );
leaderID.reset();
oldAbsFastestLap = -1;
oldOwnFastestLap = -1;
absFLValid = false;
ownFLValid = false;
currLapValid.reset( true );
}
/**
* {@inheritDoc}
*/
@Override
public void onCockpitEntered( LiveGameData gameData, boolean isEditorMode )
{
super.onCockpitEntered( gameData, isEditorMode );
currLapValid.reset( true );
lastLapDisplayTime = -1f;
scoringInfoUpdateID.reset( true );
}
/**
* {@inheritDoc}
*/
@Override
public void onPitsExited( LiveGameData gameData, boolean isEditorMode )
{
super.onPitsExited( gameData, isEditorMode );
currLapValid.reset( true );
}
/**
* {@inheritDoc}
*/
@Override
public void onLapStarted( VehicleScoringInfo vsi, LiveGameData gameData, boolean isEditorMode )
{
super.onLapStarted( vsi, gameData, isEditorMode );
if ( vsi == gameData.getScoringInfo().getViewedVehicleScoringInfo() )
{
if ( vsi.getStintLength() < 1.9f )
{
lastLapDisplayTime = -1f;
}
else if ( lastLapDisplayDelay.getIntValue() < 0 )
{
if ( vsi.getLaptime( vsi.getLapsCompleted() ) == null ) // Should not be possible, but it happens!
lastLapDisplayTime = -1f;
else
lastLapDisplayTime = vsi.getLapStartTime() + ( vsi.getLaptime( vsi.getLapsCompleted() ).getSector1() * -lastLapDisplayDelay.getIntValue() / 100f );
}
else
{
lastLapDisplayTime = vsi.getLapStartTime() + ( lastLapDisplayDelay.getIntValue() / 1000f );
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected Boolean onVehicleControlChanged( VehicleScoringInfo viewedVSI, LiveGameData gameData, boolean isEditorMode )
{
Boolean result = super.onVehicleControlChanged( viewedVSI, gameData, isEditorMode );
lastLapDisplayTime = -1f;
scoringInfoUpdateID.reset( true );
leaderID.reset();
return ( result );
}
/**
* {@inheritDoc}
*/
@Override
protected void initSubTextures( LiveGameData gameData, boolean isEditorMode, int widgetInnerWidth, int widgetInnerHeight, SubTextureCollector collector )
{
}
/**
* {@inheritDoc}
*/
@Override
protected void initialize( LiveGameData gameData, boolean isEditorMode, DrawnStringFactory dsf, TextureImage2D texture, int width, int height )
{
final java.awt.Font font = getFont();
final boolean fontAntiAliased = isFontAntiAliased();
final java.awt.Color fontColor = getFontColor();
final int left1 = 2;
final int left2 = left1 + 10;
int top = -2;
final int sectionGap = 7;
DrawnString yRel = null;
if ( displayAbsFastest.getBooleanValue() )
{
absFastestLapHeaderString = dsf.newDrawnString( "absFastestLapHeaderString", left1, top, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
absFastestLapDriverString = dsf.newDrawnString( "absFastestLapDriverString", null, absFastestLapHeaderString, left2, top, Alignment.LEFT, false, font, fontAntiAliased, fontColor, Loc.abs_fastest_header_prefix + ": ", null );
absSector1String = dsf.newDrawnString( "absSector1String", null, absFastestLapDriverString, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
absSector2String = dsf.newDrawnString( "absSector2String", null, absSector1String, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
if ( !cumulativeSectors.getBooleanValue() )
{
absSector3String = dsf.newDrawnString( "absSector3String", null, absSector2String, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
yRel = absSector3String;
}
else
{
absSector3String = null;
yRel = absSector2String;
}
absFastestLapString = dsf.newDrawnString( "absFastestLapString", null, yRel, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
yRel = absFastestLapString;
top = sectionGap;
}
else
{
absFastestLapHeaderString = null;
absFastestLapDriverString = null;
absSector1String = null;
absSector2String = null;
absSector3String = null;
absFastestLapString = null;
//yRel = null;
}
if ( displayOwnFastest.getBooleanValue() )
{
ownFastestLapHeaderString = dsf.newDrawnString( "ownFastestLapHeaderString", null, yRel, left1, top, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
ownSector1String = dsf.newDrawnString( "ownSector1String", null, ownFastestLapHeaderString, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
ownSector2String = dsf.newDrawnString( "ownSector2String", null, ownSector1String, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
if ( !cumulativeSectors.getBooleanValue() )
{
ownSector3String = dsf.newDrawnString( "ownSector3String", null, ownSector2String, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
yRel = ownSector3String;
}
else
{
ownSector3String = null;
yRel = ownSector2String;
}
ownFastestLapString = dsf.newDrawnString( "ownFastestLapString", null, yRel, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
yRel = ownFastestLapString;
}
else
{
ownFastestLapHeaderString = null;
ownSector1String = null;
ownSector2String = null;
ownSector3String = null;
ownFastestLapString = null;
//yRel = null;
}
if ( displayAbsFastest.getBooleanValue() || displayOwnFastest.getBooleanValue() )
{
currLapHeaderString = dsf.newDrawnString( "currLapHeaderString", null, yRel, left1, sectionGap, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
yRel = currLapHeaderString;
}
else
{
currLapHeaderString = null;
}
currSector1String = dsf.newDrawnString( "currSector1String", null, yRel, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
currSector2String = dsf.newDrawnString( "currSector2String", null, currSector1String, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
if ( !cumulativeSectors.getBooleanValue() && !forceCurrentCumulSectors.getBooleanValue() )
{
currSector3String = dsf.newDrawnString( "currSector3String", null, currSector2String, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
yRel = currSector3String;
}
else
{
currSector3String = null;
yRel = currSector2String;
}
currLapString = dsf.newDrawnString( "currLapString", null, yRel, left2, 0, Alignment.LEFT, false, font, fontAntiAliased, fontColor );
fontColors[0] = getFontColor();
fontColors[1] = getFontColor();
fontColors[2] = getFontColor();
fontColors[3] = getFontColor();
fontColors[4] = getFontColor();
}
/**
* {@inheritDoc}
*/
@Override
protected void drawWidget( Clock clock, boolean needsCompleteRedraw, LiveGameData gameData, boolean isEditorMode, TextureImage2D texture, int offsetX, int offsetY, int width, int height )
{
ScoringInfo scoringInfo = gameData.getScoringInfo();
scoringInfoUpdateID.update( scoringInfo.getUpdateId() );
VehicleScoringInfo myVSI = scoringInfo.getViewedVehicleScoringInfo();
VehicleScoringInfo afVSI = scoringInfo.getFastestLapVSI();
boolean absFastestIsSecond = false;
if ( afVSI == myVSI )
{
if ( scoringInfo.getSecondFastestLapVSI() != null )
{
afVSI = scoringInfo.getSecondFastestLapVSI();
absFastestIsSecond = true;
}
}
if ( isEditorMode && ( afVSI == myVSI ) )
{
// Just to get differences...
if ( afVSI == scoringInfo.getLeadersVehicleScoringInfo() )
afVSI = scoringInfo.getVehicleScoringInfo( 1 );
else
afVSI = scoringInfo.getLeadersVehicleScoringInfo();
}
Laptime afLaptime = afVSI.getFastestLaptime();
if ( displayAbsFastest.getBooleanValue() )
{
// absolute fastest lap
Laptime lt = afVSI.getFastestLaptime();
float lap = ( lt == null ) ? -1f : lt.getLapTime();
boolean lv = ( lap > 0f );
String leaderName = lv ? afVSI.getDriverName() : "";
leaderID.update( lv ? scoringInfo.getFastestLapVSI().getDriverId() : -1 );
if ( needsCompleteRedraw || leaderID.hasChanged() )
{
if ( absFastestIsSecond )
absFastestLapHeaderString.draw( offsetX, offsetY, Loc.abs_second_fastest_prefix + ":", texture );
else
absFastestLapHeaderString.draw( offsetX, offsetY, Loc.abs_fastest_prefix + ":", texture );
absFastestLapDriverString.draw( offsetX, offsetY, leaderName, texture );
}
int lap_ = Math.round( lap * 10000f );
if ( needsCompleteRedraw || ( lap_ != oldAbsFastestLap ) || ( lv != absFLValid ) )
{
oldAbsFastestLap = lap_;
absFLValid = lv;
if ( absFLValid )
{
float sec1 = ( afLaptime != null ) ? afLaptime.getSector1() : -1f;
float sec2 = ( afLaptime != null ) ? afLaptime.getSector2( cumulativeSectors.getBooleanValue() ) : -1f;
float sec3 = ( afLaptime != null ) ? ( cumulativeSectors.getBooleanValue() ? sec2 + afLaptime.getSector3() : afLaptime.getSector3() ) : -1f;
int cols = 3;
String[][] s = new String[4][cols];
int[] colWidths = new int[cols];
final Alignment[] aligns = { Alignment.RIGHT, Alignment.LEFT, Alignment.RIGHT };
s[0][0] = Loc.timing_sector1_prefix + ":";
s[0][1] = null;
if ( sec1 > 0f )
s[0][2] = TimingUtil.getTimeAsLaptimeString( sec1 );
else
s[0][2] = "-:--.---";
s[1][0] = Loc.timing_sector2_prefix + ":";
s[1][1] = null;
if ( sec2 > 0f )
s[1][2] = TimingUtil.getTimeAsLaptimeString( sec2 );
else
s[1][2] = "-:--.---";
if ( !cumulativeSectors.getBooleanValue() )
{
s[2][0] = Loc.timing_sector3_prefix + ":";
s[2][1] = null;
if ( sec3 > 0f )
s[2][2] = TimingUtil.getTimeAsLaptimeString( sec3 );
else
s[2][2] = "-:--.---";
}
else
{
s[2][0] = null;
s[2][1] = null;
s[2][2] = "";
}
s[3][0] = Loc.timing_lap_prefix + ":";
s[3][1] = null;
s[3][2] = TimingUtil.getTimeAsLaptimeString( lap );
absSector1String.getMaxColWidths( s[0], aligns, colPadding, colWidths );
absSector2String.getMaxColWidths( s[1], aligns, colPadding, colWidths );
if ( !cumulativeSectors.getBooleanValue() )
absSector3String.getMaxColWidths( s[2], aligns, colPadding, colWidths );
absFastestLapString.getMaxColWidths( s[3], aligns, colPadding, colWidths );
absSector1String.drawColumns( offsetX, offsetY, s[0], aligns, colPadding, colWidths, texture );
absSector2String.drawColumns( offsetX, offsetY, s[1], aligns, colPadding, colWidths, texture );
if ( !cumulativeSectors.getBooleanValue() )
absSector3String.drawColumns( offsetX, offsetY, s[2], aligns, colPadding, colWidths, texture );
absFastestLapString.drawColumns( offsetX, offsetY, s[3], aligns, colPadding, colWidths, texture );
}
else
{
absSector1String.draw( offsetX, offsetY, "-:--.---", texture );
absSector2String.draw( offsetX, offsetY, "-:--.---", texture );
if ( !cumulativeSectors.getBooleanValue() )
absSector3String.draw( offsetX, offsetY, "-:--.---", texture );
absFastestLapString.draw( offsetX, offsetY, "-:--.---", texture );
}
}
}
if ( displayOwnFastest.getBooleanValue() )
{
// own fastest lap
Laptime laptime = myVSI.getFastestLaptime();
float lap = myVSI.getBestLapTime();
if ( needsCompleteRedraw )
{
ownFastestLapHeaderString.draw( offsetX, offsetY, Loc.own_fastest_prefix + ":", texture );
}
int lap_ = Math.round( lap * 10000f );
boolean lv = ( lap > 0f );
if ( needsCompleteRedraw || ( lap_ != oldOwnFastestLap ) || ( lv != ownFLValid ) )
{
oldOwnFastestLap = lap_;
ownFLValid = lv;
if ( ownFLValid )
{
boolean displayCumul = cumulativeSectors.getBooleanValue();
float afSec1 = ( afLaptime != null ) ? afLaptime.getSector1() : -1f; //afVSI.getBestSector1();
float afSec2 = ( afLaptime != null ) ? afLaptime.getSector2( displayCumul ) : -1f; //afVSI.getBestSector2( displayCumul );
float afSec3 = ( afLaptime != null ) ? ( displayCumul ? afSec2 + afLaptime.getSector3() : afLaptime.getSector3() ) : -1f; //displayCumul ? afSec2 + afVSI.getBestSector3() : afVSI.getBestSector3();
float afLap = ( afLaptime != null ) ? afLaptime.getLapTime() : -1f;// afVSI.getBestLapTime();
float sec1 = ( laptime != null ) ? laptime.getSector1() : -1f; //vsi.getBestSector1();
float sec2 = ( laptime != null ) ? laptime.getSector2( displayCumul ) : -1f; //vsi.getBestSector2( displayCumul );
float sec3 = ( laptime != null ) ? ( displayCumul ? sec2 + laptime.getSector3() : laptime.getSector3() ) : -1f; //displayCumul ? sec2 + vsi.getBestSector3() : vsi.getBestSector3();
final boolean dispGapToAbs = ( displayAbsFastest.getBooleanValue() && ( myVSI != afVSI ) );
int cols = dispGapToAbs ? 4 : 3;
String[][] s = new String[4][cols];
int[] colWidths = new int[cols];
final Alignment[] aligns = ( myVSI != afVSI ) ? new Alignment[] { Alignment.RIGHT, Alignment.LEFT, Alignment.RIGHT, Alignment.RIGHT } : new Alignment[] { Alignment.RIGHT, Alignment.LEFT, Alignment.RIGHT };
java.awt.Color sfColor1 = getFontColor();
s[0][0] = Loc.timing_sector1_prefix + ":";
s[0][1] = null;
if ( sec1 > 0f )
s[0][2] = TimingUtil.getTimeAsLaptimeString( sec1 );
else
s[0][2] = "-:--.---";
if ( dispGapToAbs )
{
if ( afSec1 < 0f )
{
s[0][3] = null;
}
else if ( sec1 > 0f )
{
s[0][3] = "(" + TimingUtil.getTimeAsGapString( sec1 - afSec1 ) + ")";
sfColor1 = ( sec1 - afSec1 < 0f )? fasterColor.getColor() : slowerColor.getColor();
}
else
{
s[0][3] = null;
}
}
java.awt.Color sfColor2 = getFontColor();
s[1][0] = Loc.timing_sector2_prefix + ":";
s[1][1] = null;
if ( sec2 > 0f )
s[1][2] = TimingUtil.getTimeAsLaptimeString( sec2 );
else
s[1][2] = "-:--.---";
if ( dispGapToAbs )
{
if ( afSec2 < 0f )
{
s[1][3] = null;
}
else if ( sec2 > 0f )
{
s[1][3] = "(" + TimingUtil.getTimeAsGapString( sec2 - afSec2 ) + ")";
sfColor2 = ( sec2 - afSec2 < 0f )? fasterColor.getColor() : slowerColor.getColor();
}
else
{
s[1][3] = null;
}
}
java.awt.Color sfColor3 = getFontColor();
if ( !displayCumul )
{
s[2][0] = Loc.timing_sector3_prefix + ":";
s[2][1] = null;
if ( sec3 > 0f )
s[2][2] = TimingUtil.getTimeAsLaptimeString( sec3 );
else
s[2][2] = "-:--.---";
if ( dispGapToAbs )
{
if ( afSec3 < 0f )
{
s[2][3] = null;
}
else if ( sec3 > 0f )
{
s[2][3] = "(" + TimingUtil.getTimeAsGapString( sec3 - afSec3 ) + ")";
sfColor3 = ( sec3 - afSec3 < 0f )? fasterColor.getColor() : slowerColor.getColor();
}
else
{
s[2][3] = null;
}
}
}
else
{
s[2][0] = null;
s[2][1] = null;
s[2][2] = "";
if ( dispGapToAbs )
s[2][3] = "";
}
java.awt.Color sfColorL = getFontColor();
s[3][0] = Loc.timing_lap_prefix + ":";
s[3][1] = null;
s[3][2] = TimingUtil.getTimeAsLaptimeString( lap );
if ( dispGapToAbs )
{
if ( afLap > 0f )
{
s[3][3] = "(" + TimingUtil.getTimeAsGapString( lap - afLap ) + ")";
sfColorL = ( lap - afLap < 0f )? fasterColor.getColor() : slowerColor.getColor();
}
else
{
s[3][3] = null;
}
}
ownSector1String.getMaxColWidths( s[0], aligns, colPadding, colWidths );
ownSector2String.getMaxColWidths( s[1], aligns, colPadding, colWidths );
if ( !displayCumul )
ownSector3String.getMaxColWidths( s[2], aligns, colPadding, colWidths );
ownFastestLapString.getMaxColWidths( s[3], aligns, colPadding, colWidths );
fontColors[3] = sfColor1;
ownSector1String.drawColumns( offsetX, offsetY, s[0], aligns, colPadding, colWidths, fontColors, texture );
fontColors[3] = sfColor2;
ownSector2String.drawColumns( offsetX, offsetY, s[1], aligns, colPadding, colWidths, fontColors, texture );
fontColors[3] = sfColor3;
if ( !displayCumul )
ownSector3String.drawColumns( offsetX, offsetY, s[2], aligns, colPadding, colWidths, fontColors, texture );
fontColors[3] = sfColorL;
ownFastestLapString.drawColumns( offsetX, offsetY, s[3], aligns, colPadding, colWidths, fontColors, texture );
}
else
{
ownSector1String.draw( offsetX, offsetY, "-:--.---", texture );
ownSector2String.draw( offsetX, offsetY, "-:--.---", texture );
if ( !cumulativeSectors.getBooleanValue() )
ownSector3String.draw( offsetX, offsetY, "-:--.---", texture );
ownFastestLapString.draw( offsetX, offsetY, "-:--.---", texture );
}
}
}
{
// current lap
if ( needsCompleteRedraw && ( currLapHeaderString != null ) )
{
currLapHeaderString.draw( offsetX, offsetY, Loc.current_prefix + ":", texture );
}
Laptime ownFastestLaptime = myVSI.getFastestLaptime();
float lap = myVSI.getCurrentLaptime();
currLapValid.update( lap > 0f );
if ( isEditorMode || ( ( lap > 0f ) && ( myVSI.getLapsCompleted() >= myVSI.getStintStartLap() ) ) )
if ( needsCompleteRedraw || clock.c() || ( clock.c() && ( currLapValid.hasChanged( false ) ) ) )
{
currLapValid.setUnchanged();
final boolean isDelaying = isEditorMode || ( scoringInfo.getSessionTime() <= lastLapDisplayTime );
final boolean isDelaying2 = !isEditorMode && isDelaying;
final boolean absFastestIsOwn = isDelaying ? delayedAbsFastestIsOwn : ( myVSI == afVSI );
final short sector = myVSI.getSector();
final boolean displayCumul = cumulativeSectors.getBooleanValue() || forceCurrentCumulSectors.getBooleanValue();
float afSec1 = isDelaying2 ? ( delayedAbsFastestLap != null ? delayedAbsFastestLap.getSector1() : -1f ) : ( afLaptime != null ) ? afLaptime.getSector1(): -1f; //afVSI.getBestSector1();
float afSec2 = isDelaying2 ? ( delayedAbsFastestLap != null ? delayedAbsFastestLap.getSector2( displayCumul ) : -1f ) : ( afLaptime != null ) ? afLaptime.getSector2( displayCumul ): -1f; //afVSI.getBestSector2( displayCumul );
float afSec3 = isDelaying2 ? ( delayedAbsFastestLap != null ? delayedAbsFastestLap.getSector3() : -1f ) : ( displayCumul ? ( delayedAbsFastestLap != null ? afSec2 + delayedAbsFastestLap.getSector3() : -1f ) : ( afLaptime != null ? afLaptime.getSector3() : -1f ) );
float afLap = isDelaying2 ? ( delayedAbsFastestLap != null ? delayedAbsFastestLap.getLapTime() : -1f ) : ( afLaptime != null ? afLaptime.getLapTime() : -1f );
Laptime ofLaptime = myVSI.getFastestLaptime();
float ofSec1 = isDelaying2 ? ( delayedOwnFastestLap != null ? delayedOwnFastestLap.getSector1() : -1f ) : ( ownFastestLaptime != null ? ownFastestLaptime.getSector1() : -1f );
float ofSec2 = isDelaying2 ? ( delayedOwnFastestLap != null ? delayedOwnFastestLap.getSector2( displayCumul ) : -1f ) : ( ownFastestLaptime != null ? ownFastestLaptime.getSector2( displayCumul ) : -1f );
float ofSec3 = isDelaying2 ? ( delayedOwnFastestLap != null ? delayedOwnFastestLap.getSector3() : -1f ) : ( displayCumul ? ( delayedOwnFastestLap != null ? ofSec2 + delayedOwnFastestLap.getSector3() : -1f ) : ( ofLaptime != null ? ofLaptime.getSector3() : -1f ) );
float ofLap = isDelaying2 ? ( delayedOwnFastestLap != null ? delayedOwnFastestLap.getLapTime() : -1f ) : ( ofLaptime != null ? ofLaptime.getLapTime() : -1f );
float sec1 = isDelaying ? myVSI.getLastSector1() : myVSI.getCurrentSector1();
float sec2 = isDelaying ? myVSI.getLastSector2( displayCumul ) : myVSI.getCurrentSector2( displayCumul );
float sec3 = isDelaying ? myVSI.getLastSector3() : ( ( sec2 > 0f ) ? ( displayCumul ? lap : lap - sec2 ) : -1f );
if ( isDelaying )
{
lap = myVSI.getLastLapTime();
}
boolean afValid = afLap > 0f;
boolean ofValid = ofLap > 0f;
final boolean dispOwnFastest = displayOwnFastest.getBooleanValue() || ( !displayAbsFastest.getBooleanValue() && !displayOwnFastest.getBooleanValue() );
final boolean dispAbsFastest = displayAbsFastest.getBooleanValue() || ( !displayAbsFastest.getBooleanValue() && !displayOwnFastest.getBooleanValue() );
int cols = 3 + ( dispOwnFastest ? 1 : 0 ) + ( dispAbsFastest ? 1 : 0 );
String[][] s = new String[4][cols];
int[] colWidths = new int[cols];
final Alignment[] aligns = new Alignment[ cols ];
aligns[0] = Alignment.RIGHT;
aligns[1] = Alignment.LEFT;
for ( int i = 2; i < aligns.length; i++ )
aligns[i] = Alignment.RIGHT;
if ( !isDelaying || isEditorMode )
{
gapOFSec1 = sec1 - ofSec1;
gapOFSec1Valid = ( ofSec1 > 0f );
gapOFSec2 = sec2 - ofSec2;
gapOFSec2Valid = ( ofSec2 > 0f );
gapOFSec3 = sec3 - ofSec3;
gapOFSec3Valid = ( ofSec3 > 0f );
gapOFLap = lap - ofLap;
gapAFSec1 = sec1 - afSec1;
gapAFSec1Valid = ( afSec1 > 0f );
gapAFSec2 = sec2 - afSec2;
gapAFSec2Valid = ( afSec2 > 0f );
gapAFSec3 = sec3 - afSec3;
gapAFSec3Valid = ( afSec3 > 0f );
gapAFLap = lap - afLap;
delayedAbsFastestLap = afLaptime;
delayedOwnFastestLap = ofLaptime;
delayedAbsFastestIsOwn = ( afVSI == myVSI );
}
else
{
gapOFLap = lap - ofLap;
gapAFLap = lap - afLap;
}
java.awt.Color[] sfColor1 = new java.awt.Color[] { getFontColor(), getFontColor() };
s[0][0] = Loc.timing_sector1_prefix + ":";
s[0][1] = null;
if ( sec1 > 0f )
{
s[0][2] = TimingUtil.getTimeAsLaptimeString( sec1 );
if ( !isEditorMode && ( sector == 1 ) && !isDelaying )
{
if ( cols >= 4 )
s[0][3] = null;
if ( cols >= 5 )
s[0][4] = null;
}
else
{
int ii = 3;
if ( dispOwnFastest )
{
if ( ofValid && gapOFSec1Valid )
{
sfColor1[ii - 3] = ( gapOFSec1 < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[0][ii] = "(" + TimingUtil.getTimeAsGapString( gapOFSec1 ) + ")";
}
else
s[0][ii] = "--.---";
ii++;
}
if ( dispAbsFastest )
{
if ( afValid && !absFastestIsOwn )
{
if ( gapAFSec1Valid )
{
sfColor1[ii - 3] = ( gapAFSec1 < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[0][ii] = "(" + TimingUtil.getTimeAsGapString( gapAFSec1 ) + ")";
}
else
s[0][ii] = "--.---";
}
else
s[0][ii] = null;
ii++;
}
}
}
else
{
s[0][2] = "--.---";
if ( cols >= 4 )
s[0][3] = null;
if ( cols >= 5 )
s[0][4] = null;
}
java.awt.Color[] sfColor2 = new java.awt.Color[] { getFontColor(), getFontColor() };
s[1][0] = Loc.timing_sector2_prefix + ":";
s[1][1] = null;
if ( sec2 > 0f )
{
s[1][2] = TimingUtil.getTimeAsLaptimeString( sec2 );
if ( !isEditorMode && ( sector == 2 ) && !isDelaying )
{
if ( cols >= 4 )
s[1][3] = null;
if ( cols >= 5 )
s[1][4] = null;
}
else
{
int ii = 3;
if ( dispOwnFastest )
{
if ( ofValid && gapOFSec2Valid )
{
sfColor2[ii - 3] = ( gapOFSec2 < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[1][ii] = "(" + TimingUtil.getTimeAsGapString( gapOFSec2 ) + ")";
}
else
s[1][ii] = "--.---";
ii++;
}
if ( dispAbsFastest )
{
if ( afValid && !absFastestIsOwn )
{
if ( gapAFSec2Valid )
{
sfColor2[ii - 3] = ( gapAFSec2 < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[1][ii] = "(" + TimingUtil.getTimeAsGapString( gapAFSec2 ) + ")";
}
else
s[1][ii] = "--.---";
}
else
s[1][4] = null;
ii++;
}
}
}
else
{
s[1][2] = "--.---";
if ( cols >= 4 )
s[1][3] = null;
if ( cols >= 5 )
s[1][4] = null;
}
java.awt.Color[] sfColor3 = new java.awt.Color[] { getFontColor(), getFontColor() };
s[2][0] = Loc.timing_sector3_prefix + ":";
s[2][1] = null;
if ( !displayCumul )
{
if ( sec3 > 0f )
{
s[2][2] = TimingUtil.getTimeAsLaptimeString( sec3 );
if ( !isEditorMode && ( sector == 3 ) && !isDelaying )
{
if ( cols >= 4 )
s[2][3] = null;
if ( cols >= 5 )
s[2][4] = null;
}
else
{
int ii = 3;
if ( dispOwnFastest )
{
if ( ofValid && gapOFSec3Valid )
{
sfColor3[ii - 3] = ( gapOFSec3 < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[2][ii] = "(" + TimingUtil.getTimeAsGapString( gapOFSec3 ) + ")";
}
else
s[2][ii] = "--.---";
ii++;
}
if ( dispAbsFastest )
{
if ( afValid && !absFastestIsOwn )
{
if ( gapAFSec3Valid )
{
sfColor3[ii - 3] = ( gapAFSec3 < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[2][ii] = "(" + TimingUtil.getTimeAsGapString( gapAFSec3 ) + ")";
}
else
s[2][ii] = "--.---";
}
else
s[2][ii] = null;
ii++;
}
}
}
else
{
s[2][2] = "--.---";
if ( cols >= 4 )
s[2][3] = null;
if ( cols >= 5 )
s[2][4] = null;
}
}
else
{
s[2][2] = null;
if ( cols >= 4 )
s[2][3] = null;
if ( cols >= 5 )
s[2][4] = null;
}
java.awt.Color[] sfColorL = new java.awt.Color[] { getFontColor(), getFontColor() };
s[3][0] = Loc.timing_lap_prefix + ":";
s[3][1] = null;
if ( isEditorMode || ( ( lap > 0f ) && ( myVSI.getLapsCompleted() >= myVSI.getStintStartLap() ) ) )
{
s[3][2] = TimingUtil.getTimeAsLaptimeString( lap );
if ( isDelaying )
{
int ii = 3;
if ( dispOwnFastest )
{
if ( ofValid )
{
sfColorL[ii - 3] = ( gapOFLap < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[3][ii] = "(" + TimingUtil.getTimeAsGapString( gapOFLap ) + ")";
}
else
s[3][ii] = "--.---";
ii++;
}
if ( dispAbsFastest )
{
if ( afValid && !absFastestIsOwn )
{
sfColorL[ii - 3] = ( gapAFLap < 0f ) ? fasterColor.getColor() : slowerColor.getColor();
s[3][ii] = "(" + TimingUtil.getTimeAsGapString( gapAFLap ) + ")";
}
else
s[3][ii] = null;
ii++;
}
}
else
{
if ( cols >= 4 )
s[3][3] = null;
if ( cols >= 5 )
s[3][4] = null;
}
}
else
{
s[3][2] = "-:--.---";
if ( cols >= 4 )
s[3][3] = null;
if ( cols >= 5 )
s[3][4] = null;
}
currSector1String.getMaxColWidths( s[0], aligns, colPadding, colWidths );
currSector2String.getMaxColWidths( s[1], aligns, colPadding, colWidths );
if ( !displayCumul )
currSector3String.getMaxColWidths( s[2], aligns, colPadding, colWidths );
String s31 = s[3][2];
s[3][2] = TimingUtil.getTimeAsLaptimeString( 90.0f );
currLapString.getMaxColWidths( s[3], aligns, colPadding, colWidths );
s[3][2] = s31;
if ( oldClStrings[0].length != s[0].length )
oldClStrings[0] = new String[ s[0].length ];
if ( needsCompleteRedraw || !Arrays.equals( s[0], oldClStrings[0] ) )
{
System.arraycopy( s[0], 0, oldClStrings[0], 0, s[0].length );
fontColors[3] = sfColor1[0];
fontColors[4] = sfColor1[1];
currSector1String.drawColumns( offsetX, offsetY, s[0], aligns, colPadding, colWidths, fontColors, texture );
}
if ( oldClStrings[1].length != s[1].length )
oldClStrings[1] = new String[ s[1].length ];
if ( needsCompleteRedraw || !Arrays.equals( s[1], oldClStrings[1] ) )
{
System.arraycopy( s[1], 0, oldClStrings[1], 0, s[1].length );
fontColors[3] = sfColor2[0];
fontColors[4] = sfColor2[1];
currSector2String.drawColumns( offsetX, offsetY, s[1], aligns, colPadding, colWidths, fontColors, texture );
}
if ( !displayCumul )
{
if ( oldClStrings[2].length != s[2].length )
oldClStrings[2] = new String[ s[2].length ];
if ( needsCompleteRedraw || !Arrays.equals( s[2], oldClStrings[2] ) )
{
System.arraycopy( s[2], 0, oldClStrings[2], 0, s[2].length );
fontColors[3] = sfColor3[0];
fontColors[4] = sfColor3[1];
currSector3String.drawColumns( offsetX, offsetY, s[2], aligns, colPadding, colWidths, fontColors, texture );
}
}
if ( oldClStrings[3].length != s[3].length )
oldClStrings[3] = new String[ s[3].length ];
if ( needsCompleteRedraw || !Arrays.equals( s[3], oldClStrings[3] ) )
{
System.arraycopy( s[3], 0, oldClStrings[3], 0, s[3].length );
fontColors[3] = sfColorL[0];
fontColors[4] = sfColorL[1];
currLapString.drawColumns( offsetX, offsetY, s[3], aligns, colPadding, colWidths, fontColors, texture );
}
}
}
}
}