
com.ardor3d.example.PropertiesGameSettings Maven / Gradle / Ivy
/**
* Copyright (c) 2008-2012 Ardor Labs, Inc.
*
* This file is part of Ardor3D.
*
* Ardor3D is free software: you can redistribute it and/or modify it
* under the terms of its license which may be found in the accompanying
* LICENSE file or at .
*/
package com.ardor3d.example;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.ardor3d.util.Ardor3dException;
import com.ardor3d.util.resource.ResourceLocatorTool;
/**
* PropertiesGameSettings
handles loading and saving a properties file that defines the display settings. A
* property file is identified during creation of the object. The properties file should have the following format:
*
*
* <CODE>
* FREQ=60
* RENDERER=LWJGL
* WIDTH=1280
* HEIGHT=1024
* DEPTH=32
* FULLSCREEN=false
* </CODE>
*
*/
public class PropertiesGameSettings {
private static final Logger logger = Logger.getLogger(PropertiesGameSettings.class.getName());
/**
* The default width, used if there is a problem with the properties file.
*/
static int DEFAULT_WIDTH = 640;
/**
* The default height, used if there is a problem with the properties file.
*/
static int DEFAULT_HEIGHT = 480;
/**
* The default depth, used if there is a problem with the properties file.
*/
static int DEFAULT_DEPTH = 16;
/**
* The default frequency, used if there is a problem with the properties file.
*/
static int DEFAULT_FREQUENCY = 60;
/**
* The default fullscreen flag, used if there is a problem with the properties file.
*/
static boolean DEFAULT_FULLSCREEN = false;
/**
* The default renderer flag, used if there is a problem with the properties file.
*/
static String DEFAULT_RENDERER = "LWJGL";
static boolean DEFAULT_VERTICAL_SYNC = true;
static int DEFAULT_DEPTH_BITS = 8;
static int DEFAULT_ALPHA_BITS = 0;
static int DEFAULT_STENCIL_BITS = 0;
static int DEFAULT_SAMPLES = 0;
static boolean DEFAULT_MUSIC = true;
static boolean DEFAULT_SFX = true;
static int DEFAULT_FRAMERATE = -1;
protected boolean isNew = true;
// These are all objects so it is very clear when they have been
// explicitly set.
protected static Integer defaultWidth = null;
protected static Integer defaultHeight = null;
protected static Integer defaultDepth = null;
protected static Integer defaultFrequency = null;
protected static Boolean defaultFullscreen = null;
protected static String defaultRenderer = null;
protected static Boolean defaultVerticalSync = null;
protected static Integer defaultDepthBits = null;
protected static Integer defaultAlphaBits = null;
protected static Integer defaultStencilBits = null;
protected static Integer defaultSamples = null;
protected static Boolean defaultMusic = null;
protected static Boolean defaultSFX = null;
protected static Integer defaultFramerate = null;
protected static String defaultSettingsWidgetImage = null;
private static boolean defaultsAssigned = false;
// property object
private final Properties prop;
// the file that contains our properties.
private final String filename;
private static boolean dfltsInitted = false;
/**
* Constructor creates the PropertiesGameSettings
object for use.
*
* @param personalFilename
* the properties file to use, read from filesystem. Must not be null.
* @param dfltsFilename
* the properties file to use, read from CLASSPATH. Null to not seek any runtime defaults file.
* @throws Ardor3dException
* if the personalFilename is null.
*/
public PropertiesGameSettings(final String personalFilename, final String dfltsFilename) {
if (null == personalFilename) {
throw new Ardor3dException("Must give a valid filename");
}
if (!dfltsInitted) {
dfltsInitted = true;
// default* setting values are static, therefore, regardless of
// how many GameSettings we instantiate, the defaults are
// assigned only once.
assignDefaults(dfltsFilename);
}
filename = personalFilename;
isNew = !(new File(filename).isFile());
prop = new Properties();
load();
}
public void clear() {
prop.clear();
}
/**
* get
takes an arbitrary string as a key and returns any value associated with it, null if none.
*
* @param key
* the key to use for data retrieval.
* @return the string associated with the key, null if none.
*/
public String get(final String key) {
return prop.getProperty(key);
}
public String get(final String name, final String defaultValue) {
final String value = get(name);
return (value == null) ? defaultValue : value;
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public int getAlphaBits() {
final String s = prop.getProperty("ALPHA_BITS");
return (s == null) ? defaultAlphaBits : Integer.parseInt(s);
}
public boolean getBoolean(final String name, final boolean defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : Boolean.parseBoolean(stringValue);
}
public byte[] getByteArray(final String name, final byte[] defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : stringValue.getBytes();
}
/**
* This is only getting the "default" value, which may not be changed by end-users.
*/
public String getDefaultSettingsWidgetImage() {
return defaultSettingsWidgetImage;
}
/**
* getDepth
returns the depth as read from the properties file. If the properties file does not contain
* depth or was not read properly, the default depth is returned.
*
* @return the depth determined by the properties file, or the default.
*/
public int getDepth() {
final String d = prop.getProperty("DEPTH");
if (null == d) {
return defaultDepth;
}
return Integer.parseInt(d);
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public int getDepthBits() {
final String s = prop.getProperty("DEPTH_BITS");
return (s == null) ? defaultDepthBits : Integer.parseInt(s);
}
public double getDouble(final String name, final double defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : Double.parseDouble(stringValue);
}
public float getFloat(final String name, final float defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : Float.parseFloat(stringValue);
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public int getFramerate() {
final String s = prop.getProperty("FRAMERATE");
return (s == null) ? defaultFramerate : Integer.parseInt(s);
}
/**
* getFrequency
returns the frequency of the monitor as read from the properties file. If the
* properties file does not contain frequency or was not read properly the default frequency is returned.
*
* @return the frequency determined by the properties file, or the default.
*/
public int getFrequency() {
final String f = prop.getProperty("FREQ");
if (null == f) {
return defaultFrequency;
}
return Integer.parseInt(f);
}
/**
* Legacy method.
*
* @deprecated Use method isFullscreen instead.
* @see #isFullscreen()
*/
@Deprecated
public boolean getFullscreen() {
return isFullscreen();
}
/**
* getHeight
returns the height as read from the properties file. If the properties file does not
* contain height or was not read properly, the default height is returned.
*
* @return the height determined by the properties file, or the default.
*/
public int getHeight() {
final String h = prop.getProperty("HEIGHT");
if (null == h) {
return defaultHeight;
}
return Integer.parseInt(h);
}
public int getInt(final String name, final int defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : Integer.parseInt(stringValue);
}
public long getLong(final String name, final long defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : Long.parseLong(stringValue);
}
public Object getObject(final String name, final Object defaultValue) {
final String stringValue = get(name);
return (stringValue == null) ? defaultValue : stringValue;
}
/**
*
* getRenderer
returns the requested rendering API, or the default.
*
* @return the rendering API or the default.
*/
public String getRenderer() {
final String renderer = prop.getProperty("RENDERER");
if (null == renderer) {
return defaultRenderer;
}
return renderer;
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public int getSamples() {
final String s = prop.getProperty("SAMPLES");
return (s == null) ? defaultSamples : Integer.parseInt(s);
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public int getStencilBits() {
final String s = prop.getProperty("STENCIL_BITS");
return (s == null) ? defaultStencilBits : Integer.parseInt(s);
}
/**
* getWidth
returns the width as read from the properties file. If the properties file does not contain
* width or was not read properly, the default width is returned.
*
* @return the width determined by the properties file, or the default.
*/
public int getWidth() {
final String w = prop.getProperty("WIDTH");
if (null == w) {
return defaultWidth;
}
return Integer.parseInt(w);
}
/**
* isFullscreen
returns the fullscreen flag as read from the properties file. If the properties file
* does not contain the fullscreen flag or was not read properly, the default value is returned.
*
* @return the fullscreen flag determined by the properties file, or the default.
*/
public boolean isFullscreen() {
final String f = prop.getProperty("FULLSCREEN");
if (null == f) {
return defaultFullscreen;
}
return Boolean.valueOf(prop.getProperty("FULLSCREEN"));
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public boolean isMusic() {
final String s = prop.getProperty("MUSIC");
return (s == null) ? defaultMusic : Boolean.parseBoolean(s);
}
public boolean isNew() {
return isNew;
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public boolean isSFX() {
final String s = prop.getProperty("SFX");
return (s == null) ? defaultSFX : Boolean.parseBoolean(s);
}
/**
* If the properties file does not contain the setting or was not read properly, the default value is returned.
*
* @throws InternalError
* in all cases
*/
public boolean isVerticalSync() {
final String s = prop.getProperty("VERTICAL_SYNC");
return (s == null) ? defaultVerticalSync : Boolean.parseBoolean(s);
}
/**
* load
attempts to load the properties file defined during instantiation and put all properties in the
* table. If there is a problem loading or reading the file, false is returned. If all goes well, true is returned.
*
* @return the success of the load, true indicated success and false indicates failure.
*/
public boolean load() {
FileInputStream fin = null;
try {
fin = new FileInputStream(filename);
} catch (final FileNotFoundException e) {
logger.warning("Could not load properties. Creating a new one.");
return false;
}
try {
prop.load(fin);
fin.close();
} catch (final IOException e) {
logger.warning("Could not load properties. Creating a new one.");
return false;
}
// confirm that the properties file has all the data we need.
if (null == prop.getProperty("WIDTH") || null == prop.getProperty("HEIGHT")
|| null == prop.getProperty("DEPTH") || null == prop.getProperty("FULLSCREEN")) {
logger.warning("Properties file not complete.");
return false;
}
logger.finer("Read properties");
return true;
}
/**
* Removes specified property, if present.
*/
public void remove(final String name) {
prop.remove(name);
}
/**
* Persists current property mappings to designated file, overwriting if file already present.
*
* @throws IOException
* for I/O failures
*/
public void save() throws IOException {
final FileOutputStream fout = new FileOutputStream(filename);
prop.store(fout, "Game Settings written by " + getClass().getName() + " at " + new java.util.Date());
fout.close();
logger.finer("Saved properties");
}
/**
* save(int, int, int, int, boolean, String)
overwrites the properties file with the given parameters.
*
* @param width
* the width of the resolution.
* @param height
* the height of the resolution.
* @param depth
* the bits per pixel.
* @param freq
* the frequency of the monitor.
* @param fullscreen
* use fullscreen or not.
* @deprecated
* @return true if save was successful, false otherwise.
*/
@Deprecated
public boolean save(final int width, final int height, final int depth, final int freq, final boolean fullscreen,
final String renderer) {
prop.clear();
setWidth(width);
setHeight(height);
setDepth(depth);
setFrequency(freq);
setFullscreen(fullscreen);
setRenderer(renderer);
try {
save();
} catch (final IOException e) {
logger.warning("Could not save properties: " + e);
return false;
}
return true;
}
/**
* Sets a property.
*/
public void set(final String name, final String value) {
prop.setProperty(name, value);
}
/**
* @throws InternalError
* in all cases
*/
public void setAlphaBits(final int alphaBits) {
setInt("ALPHA_BITS", alphaBits);
}
/**
* @see #set(String, String)
* @throws RuntimeSetting
* for IO failure
*/
public void setBoolean(final String name, final boolean value) {
set(name, Boolean.toString(value));
}
/**
* @see #set(String, String)
* @throws RuntimeSetting
* for IO failure
*/
public void setByteArray(final String name, final byte[] value) {
set(name, new String(value));
}
public void setDepth(final int depth) {
setInt("DEPTH", depth);
}
/**
* @throws InternalError
* in all cases
*/
public void setDepthBits(final int depthBits) {
setInt("DEPTH_BITS", depthBits);
}
/**
* @see #set(String, String)
* @throws RuntimeSetting
* for IO failure
*/
public void setDouble(final String name, final double value) {
set(name, Double.toString(value));
}
/**
* @see #set(String, String)
* @throws RuntimeSetting
* for IO failure
*/
public void setFloat(final String name, final float value) {
set(name, Float.toString(value));
}
/**
* @throws InternalError
* in all cases
*/
public void setFramerate(final int framerate) {
setInt("FRAMERATE", framerate);
}
public void setFrequency(final int freq) {
setInt("FREQ", freq);
}
public void setFullscreen(final boolean fullscreen) {
setBoolean("FULLSCREEN", fullscreen);
}
public void setHeight(final int height) {
setInt("HEIGHT", height);
}
/**
* @see #set(String, String)
* @throws RuntimeSetting
* for IO failure
*/
public void setInt(final String name, final int value) {
set(name, Integer.toString(value));
}
public void setIsNew(final boolean isNew) {
this.isNew = isNew;
}
/**
* @see #set(String, String)
* @throws RuntimeSetting
* for IO failure
*/
public void setLong(final String name, final long value) {
set(name, Long.toString(value));
}
/**
* @throws InternalError
* in all cases
*/
public void setMusic(final boolean music) {
setBoolean("MUSIC", music);
}
/**
* Not implemented. Properties can not store an arbitrary Object in human-readable format. Use set(String, String)
* instead.
*
* @see #set(String, String)
* @throws InternalError
* in all cases
*/
public void setObject(final String name, final Object value) {
throw new InternalError(getClass().getName() + " Can't store arbitrary objects. "
+ "If there is a toString() method for your Object, and it is " + "Properties-compatible, use "
+ getClass().getName() + ".set(String, String).");
}
public void setRenderer(final String renderer) {
set("RENDERER", renderer);
}
/**
* @throws InternalError
* in all cases
*/
public void setSamples(final int samples) {
setInt("SAMPLES", samples);
}
/**
* @throws InternalError
* in all cases
*/
public void setSFX(final boolean sfx) {
setBoolean("SFX", sfx);
}
/**
* @throws InternalError
* in all cases
*/
public void setStencilBits(final int stencilBits) {
setInt("STENCIL_BITS", stencilBits);
}
/**
* @throws InternalError
* in all cases
*/
public void setVerticalSync(final boolean verticalSync) {
setBoolean("VERTICAL_SYNC", verticalSync);
}
public void setWidth(final int width) {
setInt("WIDTH", width);
}
/**
* save() method which throws only a RuntimeExceptin.
*
* @throws RuntimeSetting
* for IO failure
* @see #save()
*/
public void wrappedSave() {
try {
save();
} catch (final IOException ioe) {
logger.log(Level.WARNING, "Failed to persist properties", ioe);
throw new RuntimeException(ioe);
}
}
/**
* Sets default* static variables according to GameSettings.DEFAULT_* values and an optional .properties file. Note
* that we are talking about defaults here, not user-specific settings.
*
* This method should be called once the game name is known to the subclass. To override any default with your
* subclass (as opposed to by using a .properties file), just set the static variable before or after calling this
* method (before or after depends on the precedence you want among programmatic and declarative DEFAULT_*, default*
* settings).
*
* Add new setting names by making your own method which does its own thing and calls
* AbstractGameSettings.assignDefaults(propfilename).
*
* Property file paths are relative to CLASSPATH element roots.
*
* @param propFileName
* Properties file read as CLASSPATH resource. If you give null, no properties file will be loaded.
*/
protected static void assignDefaults(final String propFileName) {
if (defaultsAssigned) {
logger.fine("Skipping repeat invocation of assignDefaults()");
return;
}
logger.fine("Initializing static default* setting variables");
// hansen.playground.logging.LoggerInformation.getInfo();
// System.exit(0);
defaultsAssigned = true;
if (defaultWidth == null) {
defaultWidth = Integer.valueOf(DEFAULT_WIDTH);
}
if (defaultHeight == null) {
defaultHeight = Integer.valueOf(DEFAULT_HEIGHT);
}
if (defaultDepth == null) {
defaultDepth = Integer.valueOf(DEFAULT_DEPTH);
}
if (defaultFrequency == null) {
defaultFrequency = Integer.valueOf(DEFAULT_FREQUENCY);
}
if (defaultFullscreen == null) {
defaultFullscreen = Boolean.valueOf(DEFAULT_FULLSCREEN);
}
if (defaultRenderer == null) {
defaultRenderer = DEFAULT_RENDERER;
}
if (defaultVerticalSync == null) {
defaultVerticalSync = Boolean.valueOf(DEFAULT_VERTICAL_SYNC);
}
if (defaultDepthBits == null) {
defaultDepthBits = Integer.valueOf(DEFAULT_DEPTH_BITS);
}
if (defaultAlphaBits == null) {
defaultAlphaBits = Integer.valueOf(DEFAULT_ALPHA_BITS);
}
if (defaultStencilBits == null) {
defaultStencilBits = Integer.valueOf(DEFAULT_STENCIL_BITS);
}
if (defaultSamples == null) {
defaultSamples = Integer.valueOf(DEFAULT_SAMPLES);
}
if (defaultMusic == null) {
defaultMusic = Boolean.valueOf(DEFAULT_MUSIC);
}
if (defaultSFX == null) {
defaultSFX = Boolean.valueOf(DEFAULT_SFX);
}
if (defaultFramerate == null) {
defaultFramerate = Integer.valueOf(DEFAULT_FRAMERATE);
}
InputStream istream = null;
if (propFileName != null) {
istream = ResourceLocatorTool.getClassPathResourceAsStream(PropertiesGameSettings.class, propFileName);
}
if (istream == null) {
logger.fine("No customization properties file found");
return;
}
logger.fine("Customizing defaults according to '" + propFileName + "'");
final Properties p = new Properties();
try {
p.load(istream);
} catch (final IOException ioe) {
logger.log(Level.WARNING, "Failed to load customizations from '" + propFileName
+ "'. Continuing without customizations.", ioe);
return;
}
Integer i;
String s;
Boolean b;
i = loadInteger("DEFAULT_WIDTH", p);
if (i != null) {
defaultWidth = i.intValue();
}
i = loadInteger("DEFAULT_HEIGHT", p);
if (i != null) {
defaultHeight = i.intValue();
}
i = loadInteger("DEFAULT_DEPTH", p);
if (i != null) {
defaultDepth = i.intValue();
}
i = loadInteger("DEFAULT_FREQUENCY", p);
if (i != null) {
defaultFrequency = i.intValue();
}
b = loadBoolean("DEFAULT_FULLSCREEN", p);
if (b != null) {
defaultFullscreen = b.booleanValue();
}
s = p.getProperty("DEFAULT_RENDERER");
if (s != null) {
defaultRenderer = s;
}
b = loadBoolean("DEFAULT_VERTICAL_SYNC", p);
if (b != null) {
defaultVerticalSync = b.booleanValue();
}
i = loadInteger("DEFAULT_DEPTH_BITS", p);
if (i != null) {
defaultDepthBits = i.intValue();
}
i = loadInteger("DEFAULT_ALPHA_BITS", p);
if (i != null) {
defaultAlphaBits = i.intValue();
}
i = loadInteger("DEFAULT_STENCIL_BITS", p);
if (i != null) {
defaultStencilBits = i.intValue();
}
i = loadInteger("DEFAULT_SAMPLES", p);
if (i != null) {
defaultSamples = i.intValue();
}
b = loadBoolean("DEFAULT_MUSIC", p);
if (b != null) {
defaultMusic = b.booleanValue();
}
b = loadBoolean("DEFAULT_SFX", p);
if (b != null) {
defaultSFX = b.booleanValue();
}
i = loadInteger("DEFAULT_FRAMERATE", p);
if (i != null) {
defaultFramerate = i.intValue();
}
s = p.getProperty("SETTINGS_WIDGET_IMAGE");
if (s != null) {
defaultSettingsWidgetImage = s;
}
}
public static Boolean loadBoolean(final String name, final Properties props) {
final String s = props.getProperty(name);
if (s == null) {
return null;
}
return Boolean.valueOf(s);
}
public static Integer loadInteger(final String name, final Properties props) {
final String s = props.getProperty(name);
if (s == null) {
return null;
}
try {
return Integer.valueOf(s);
} catch (final NumberFormatException nfe) {
}
logger.warning("Malformatted value in game properties file: " + s);
return null;
}
/**
* @param inName
* Must be non-null
* @return normalized name. All lower-case with no shell meta-characters.
*/
protected static String normalizeName(final String inName) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < inName.length(); i++) {
final char c = inName.charAt(i);
sb.append((Character.isLetter(c) || Character.isDigit(c) || c == '-' || c == '_') ? c : '_');
}
return sb.toString().toUpperCase();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy