/** * 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.gamedata; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import net.ctdp.rfdynhud.editor.EditorPresets; import net.ctdp.rfdynhud.gamedata.ProfileInfo.MeasurementUnits; import net.ctdp.rfdynhud.gamedata.ProfileInfo.MeasurementUnits.Convert; import net.ctdp.rfdynhud.gamedata.ProfileInfo.SpeedUnits; import net.ctdp.rfdynhud.util.RFDHLog; /** * * @author Marvin Froehlich (CTDP) */ public abstract class WeatherInfo { private final LiveGameData gameData; private boolean updatedInTimeScope = false; private long updateId = 0L; private long updateTimestamp = -1L; public static interface WeatherInfoUpdateListener extends LiveGameData.GameDataUpdateListener { public void onWeatherInfoUpdated( LiveGameData gameData, boolean isEditorMode ); } private WeatherInfoUpdateListener[] updateListeners = null; public void registerListener( WeatherInfoUpdateListener l ) { if ( updateListeners == null ) { updateListeners = new WeatherInfoUpdateListener[] { l }; } else { for ( int i = 0; i < updateListeners.length; i++ ) { if ( updateListeners[i] == l ) return; } WeatherInfoUpdateListener[] tmp = new WeatherInfoUpdateListener[ updateListeners.length + 1 ]; System.arraycopy( updateListeners, 0, tmp, 0, updateListeners.length ); updateListeners = tmp; updateListeners[updateListeners.length - 1] = l; } gameData.registerDataUpdateListener( l ); } public void unregisterListener( WeatherInfoUpdateListener l ) { if ( updateListeners == null ) return; int index = -1; for ( int i = 0; i < updateListeners.length; i++ ) { if ( updateListeners[i] == l ) { index = i; break; } } if ( index < 0 ) return; if ( updateListeners.length == 1 ) { updateListeners = null; return; } WeatherInfoUpdateListener[] tmp = new WeatherInfoUpdateListener[ updateListeners.length - 1 ]; if ( index > 0 ) System.arraycopy( updateListeners, 0, tmp, 0, index ); if ( index < updateListeners.length - 1 ) System.arraycopy( updateListeners, index + 1, tmp, index, updateListeners.length - index - 1 ); updateListeners = tmp; gameData.unregisterDataUpdateListener( l ); } public abstract void readFromStream( InputStream in, EditorPresets editorPresets ) throws IOException; /** * Read default values. This is usually done in editor mode. * * @param editorPresets <code>null</code> in non editor mode */ public abstract void loadDefaultValues( EditorPresets editorPresets ); public abstract void writeToStream( OutputStream out ) throws IOException; /** * * @param userObject (could be an instance of {@link EditorPresets}), if in editor mode * @param timestamp */ protected void prepareDataUpdate( Object userObject, long timestamp ) { } /** * * @param userObject (could be an instance of {@link EditorPresets}), if in editor mode * @param timestamp */ protected abstract void updateDataImpl( Object userObject, long timestamp ); protected void applyEditorPresets( EditorPresets editorPresets ) { if ( editorPresets == null ) return; } /** * @param userObject (could be an instance of {@link EditorPresets}), if in editor mode * @param timestamp */ protected void onDataUpdatedImpl( Object userObject, long timestamp ) { } /** * @param userObject (could be an instance of {@link EditorPresets}), if in editor mode * @param timestamp */ protected final void onDataUpdated( Object userObject, long timestamp ) { try { this.updatedInTimeScope = true; this.updateId++; this.updateTimestamp = timestamp; if ( userObject instanceof EditorPresets ) applyEditorPresets( (EditorPresets)userObject ); if ( updateListeners != null ) { for ( int i = 0; i < updateListeners.length; i++ ) { try { updateListeners[i].onWeatherInfoUpdated( gameData, userObject instanceof EditorPresets ); } catch ( Throwable t ) { RFDHLog.exception( t ); } } } onDataUpdatedImpl( userObject, timestamp ); } catch ( Throwable t ) { RFDHLog.exception( t ); } } protected void updateData( Object userObject, long timestamp ) { //if ( gameData.getProfileInfo().isValid() ) { prepareDataUpdate( userObject, timestamp ); updateDataImpl( userObject, timestamp ); onDataUpdated( userObject, timestamp ); } } /** * @param timestamp * @param isEditorMode */ final void onSessionStarted( long timestamp, boolean isEditorMode ) { this.updatedInTimeScope = false; } /** * * @param timestamp */ final void onSessionEnded( long timestamp ) { this.updatedInTimeScope = false; } /** * * @param timestamp */ final void onCockpitEntered( long timestamp ) { this.updatedInTimeScope = true; } /** * * @param timestamp */ final void onCockpitExited( long timestamp ) { this.updatedInTimeScope = false; } /** * Gets, whether the last update of these data has been done while in running session resp. cockpit mode. * @return whether the last update of these data has been done while in running session resp. cockpit mode. */ public final boolean isUpdatedInTimeScope() { return ( updatedInTimeScope ); } /** * Gets whether this data has been updated in the current session. * * @return whether this data has been updated in the current session. */ public final boolean isValid() { return ( updateId > 0L ); } /** * Gets an ID, that in incremented every time, this {@link WeatherInfo} object is filled with new data from the game. * * @return an ID, that in incremented every time, this {@link WeatherInfo} object is filled with new data from the game. */ public final long getUpdateId() { return ( updateId ); } /** * Gets the system nano time for the last data update. * * @return the system nano time for the last data update. */ public final long getUpdateTimestamp() { return ( updateTimestamp ); } /** * Gets cloud darkness? 0.0-1.0 * * @return cloud darkness? 0.0-1.0 */ public abstract float getCloudDarkness(); /** * Gets raining severity 0.0-1.0 * * @return raining severity 0.0-1.0 */ public abstract float getRainingSeverity(); /** * Gets ambient temperature (Kelvin) * * @return ambient temperature (Kelvin) */ public abstract float getAmbientTemperatureK(); // return ( data.getAmbientTemperature() - Convert.ZERO_KELVIN ); /** * Gets ambient temperature (Celsius) * * @return ambient temperature (Celsius) */ public final float getAmbientTemperatureC() { return ( getAmbientTemperatureK() + Convert.ZERO_KELVIN ); } /** * Gets ambient temperature (Fahrenheit) * * @return ambient temperature (Fahrenheit) */ public final float getAmbientTemperatureF() { return ( Convert.celsius2Fahrehheit( getAmbientTemperatureC() ) ); } /** * Gets ambient temperature (PLR selected units) * * @return ambient temperature (PLR selected units) */ public final float getAmbientTemperature() { if ( gameData.getProfileInfo().getMeasurementUnits() == MeasurementUnits.IMPERIAL ) return ( getAmbientTemperatureF() ); return ( getAmbientTemperatureC() ); } /** * Gets track temperature (Kelvin) * * @return track temperature (Kelvin) */ public abstract float getTrackTemperatureK(); // return ( data.getTrackTemperature() - Convert.ZERO_KELVIN ); /** * Gets track temperature (Celsius) * * @return track temperature (Celsius) */ public final float getTrackTemperatureC() { return ( getTrackTemperatureK() + Convert.ZERO_KELVIN ); } /** * Gets track temperature (Fahrenheit) * * @return track temperature (Fahrenheit) */ public final float getTrackTemperatureF() { return ( Convert.celsius2Fahrehheit( getTrackTemperatureC() ) ); } /** * Gets track temperature (PLR selected units) * * @return track temperature (PLR selected units) */ public final float getTrackTemperature() { if ( gameData.getProfileInfo().getMeasurementUnits() == MeasurementUnits.IMPERIAL ) return ( getTrackTemperatureF() ); return ( getTrackTemperatureC() ); } /** * Gets wind speed in m/sec. * * @param speed output buffer * * @return the input buffer back again. */ public abstract TelemVect3 getWindSpeedMS( TelemVect3 speed ); /** * Gets wind speed in km/h. * * @param speed output buffer * * @return the input buffer back again. */ public final TelemVect3 getWindSpeedKmh( TelemVect3 speed ) { speed = getWindSpeedMS( speed ); speed.x *= SpeedUnits.Convert.MS_TO_KMH; speed.y *= SpeedUnits.Convert.MS_TO_KMH; speed.z *= SpeedUnits.Convert.MS_TO_KMH; return ( speed ); } /** * Gets wind speed in mi/h. * * @param speed output buffer * * @return the input buffer back again. */ public final TelemVect3 getWindSpeedMih( TelemVect3 speed ) { speed = getWindSpeedMS( speed ); speed.x *= SpeedUnits.Convert.MS_TO_MIH; speed.y *= SpeedUnits.Convert.MS_TO_MIH; speed.z *= SpeedUnits.Convert.MS_TO_MIH; return ( speed ); } /** * Gets wind speed in km/h or mi/h depending on PLR settings. * * @param speed output buffer * * @return the input buffer back again. */ public final TelemVect3 getWindSpeed( TelemVect3 speed ) { if ( gameData.getProfileInfo().getSpeedUnits() == SpeedUnits.MIH ) return ( getWindSpeedMih( speed ) ); return ( getWindSpeedKmh( speed ) ); } /** * Gets wetness on main path 0.0-1.0 * * @return wetness on main path 0.0-1.0 */ public abstract float getOnPathWetness(); /** * Gets wetness off main path 0.0-1.0 * * @return wetness off main path 0.0-1.0 */ public abstract float getOffPathWetness(); protected WeatherInfo( LiveGameData gameData ) { this.gameData = gameData; } }