diff --git a/build.gradle b/build.gradle index 36b7f391..9a2bb232 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ plugins { group 'org.magmaOffenburg' version '1.0-SNAPSHOT' +mainClassName = 'org.magmaoffenburg.roboviz.MainKt' subprojects { apply plugin: 'java' @@ -42,5 +43,3 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' } - -mainClassName = 'org.magmaoffenburg.roboviz.MainKt' diff --git a/src/main/java/rv/Configuration.java b/src/main/java/rv/Configuration.java deleted file mode 100644 index 11b7e5c9..00000000 --- a/src/main/java/rv/Configuration.java +++ /dev/null @@ -1,764 +0,0 @@ -/* - * Copyright 2011 RoboViz - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package rv; - -import java.awt.Color; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map.Entry; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import kotlin.Pair; - -/** - * Configuration parameters for RoboViz startup - * - * @author Justin Stoecker - */ -public class Configuration -{ - private static final String CONFIG_FILE_NAME = "config.txt"; - private ArrayList> configList = new ArrayList<>(); - private static final String REGEX_LINE = "^[^#\\t\\n\\r].*:.*"; - - private static String getConfigFilePath() - { - String userConfig = System.getProperty("user.home") + "/.roboviz/" + CONFIG_FILE_NAME; - if (new File(userConfig).exists()) - return userConfig; - return CONFIG_FILE_NAME; - } - - public class Graphics - { - public boolean useBloom = false; - public boolean usePhong = false; - public boolean useShadows = false; - public boolean useSoftShadows = false; - public boolean useStereo = false; - public boolean useVsync = true; - public boolean useFsaa = false; - public boolean centerFrame = true; - public boolean isMaximized = false; - public boolean saveFrameState = true; - public int fsaaSamples = 4; - public int targetFPS = 60; - public int firstPersonFOV = 120; - public int thirdPersonFOV = 80; - public int frameWidth = 1024; - public int frameHeight = 768; - public int frameX = 0; - public int frameY = 0; - public int shadowResolution = 1024; - - private void read() - { - useBloom = getBool("Bloom"); - usePhong = getBool("Phong"); - useShadows = getBool("Shadows"); - useSoftShadows = getBool("Soft Shadows"); - shadowResolution = getInt("Shadow Resolution"); - useStereo = getBool("Stereo 3D"); - useVsync = getBool("V-Sync"); - useFsaa = getBool("FSAA"); - fsaaSamples = getInt("FSAA Samples"); - targetFPS = getInt("Target FPS"); - firstPersonFOV = getInt("First Person FOV"); - thirdPersonFOV = getInt("Third Person FOV"); - frameWidth = getInt("Frame Width"); - frameHeight = getInt("Frame Height"); - frameX = getInt("Frame X"); - frameY = getInt("Frame Y"); - centerFrame = getBool("Center Frame"); - isMaximized = getBool("Frame Maximized"); - saveFrameState = getBool("Save Frame State"); - } - - private void write(List lines) - { - writeVal(lines, "Bloom", useBloom); - writeVal(lines, "Phong", usePhong); - writeVal(lines, "Shadows", useShadows); - writeVal(lines, "Soft Shadows", useSoftShadows); - writeVal(lines, "Shadow Resolution", shadowResolution); - writeVal(lines, "Stereo 3D", useStereo); - writeVal(lines, "V-Sync", useVsync); - writeVal(lines, "FSAA", useFsaa); - writeVal(lines, "FSAA Samples", fsaaSamples); - writeVal(lines, "Target FPS", targetFPS); - writeVal(lines, "First Person FOV", firstPersonFOV); - writeVal(lines, "Third Person FOV", thirdPersonFOV); - writeVal(lines, "Frame Width", frameWidth); - writeVal(lines, "Frame Height", frameHeight); - writeVal(lines, "Frame X", frameX); - writeVal(lines, "Frame Y", frameY); - writeVal(lines, "Center Frame", centerFrame); - writeVal(lines, "Frame Maximized", isMaximized); - writeVal(lines, "Save Frame State", saveFrameState); - } - - public boolean equals(Graphics other) - { - boolean equal = true; - - equal &= this.useBloom == other.useBloom; - equal &= this.usePhong == other.usePhong; - equal &= this.useShadows == other.useShadows; - equal &= this.useSoftShadows == other.useSoftShadows; - equal &= this.useStereo == other.useStereo; - equal &= this.useVsync == other.useVsync; - equal &= this.useFsaa == other.useFsaa; - equal &= this.centerFrame == other.centerFrame; - equal &= this.isMaximized == other.isMaximized; - equal &= this.saveFrameState == other.saveFrameState; - equal &= this.fsaaSamples == other.fsaaSamples; - equal &= this.targetFPS == other.targetFPS; - equal &= this.firstPersonFOV == other.firstPersonFOV; - equal &= this.thirdPersonFOV == other.thirdPersonFOV; - equal &= this.frameWidth == other.frameWidth; - equal &= this.frameHeight == other.frameHeight; - equal &= this.frameX == other.frameX; - equal &= this.frameY == other.frameY; - equal &= this.shadowResolution == other.shadowResolution; - - return equal; - } - - @Override - public Graphics clone() - { - Graphics clone = new Graphics(); - clone.useBloom = this.useBloom; - clone.usePhong = this.usePhong; - clone.useShadows = this.useShadows; - clone.useSoftShadows = this.useSoftShadows; - clone.useStereo = this.useStereo; - clone.useVsync = this.useVsync; - clone.useFsaa = this.useFsaa; - clone.centerFrame = this.centerFrame; - clone.isMaximized = this.isMaximized; - clone.saveFrameState = this.saveFrameState; - clone.fsaaSamples = this.fsaaSamples; - clone.targetFPS = this.targetFPS; - clone.firstPersonFOV = this.firstPersonFOV; - clone.thirdPersonFOV = this.thirdPersonFOV; - clone.frameWidth = this.frameWidth; - clone.frameHeight = this.frameHeight; - clone.frameX = this.frameX; - clone.frameY = this.frameY; - clone.shadowResolution = this.shadowResolution; - - return clone; - } - } - - public class OverlayVisibility - { - public boolean serverSpeed = true; - public boolean foulOverlay = true; - public boolean fieldOverlay = false; - public boolean numberOfPlayers = false; - public boolean playerIDs = false; - - private void read() - { - serverSpeed = getBool("Server Speed"); - foulOverlay = getBool("Foul Overlay"); - fieldOverlay = getBool("Field Overlay"); - numberOfPlayers = getBool("Number of Players"); - playerIDs = getBool("Player IDs"); - } - - private void write(List lines) - { - writeVal(lines, "Server Speed", serverSpeed); - writeVal(lines, "Foul Overlay", foulOverlay); - writeVal(lines, "Field Overlay", fieldOverlay); - writeVal(lines, "Number of Players", numberOfPlayers); - writeVal(lines, "Player IDs", playerIDs); - } - - public boolean equals(OverlayVisibility other) - { - boolean equal = true; - - equal &= this.serverSpeed == other.serverSpeed; - equal &= this.foulOverlay == other.foulOverlay; - equal &= this.fieldOverlay == other.fieldOverlay; - equal &= this.numberOfPlayers == other.numberOfPlayers; - equal &= this.playerIDs == other.playerIDs; - - return equal; - } - - @Override - public OverlayVisibility clone() - { - OverlayVisibility clone = new OverlayVisibility(); - clone.serverSpeed = this.serverSpeed; - clone.foulOverlay = this.foulOverlay; - clone.fieldOverlay = this.fieldOverlay; - clone.numberOfPlayers = this.numberOfPlayers; - clone.playerIDs = this.playerIDs; - - return clone; - } - } - - public class Networking - { - public boolean autoConnect = true; - public List> servers; - public String defaultServerHost = "localhost"; - public int defaultServerPort = 3200; - public int listenPort = 32769; - public int autoConnectDelay = 1000; - - private String overriddenServerHost = null; - private Integer overriddenServerPort = null; - - private void read() - { - autoConnect = getBool("Auto-Connect"); - autoConnectDelay = getInt("Auto-Connect Delay"); - listenPort = getInt("Drawing Port"); - - String defaultServerString = getString("Default Server"); - Pair defaultServerPair = decodePair(defaultServerString); - defaultServerHost = defaultServerPair.getFirst(); - defaultServerPort = Integer.decode(defaultServerPair.getSecond()); - - servers = new LinkedList<>(); - List serverValues = getAllValues("Server"); - for (String serverValue : serverValues) { - Pair decodedServer = decodePair(serverValue); - servers.add(new Pair<>(decodedServer.getFirst(), Integer.decode(decodedServer.getSecond()))); - } - if (servers.size() == 0) { - servers.add(new Pair<>(defaultServerHost, defaultServerPort)); - } else { - // Remove duplicates (if existing) - servers = servers.stream().distinct().collect(Collectors.toList()); - } - } - - private void write(List lines) - { - writeVal(lines, "Auto-Connect", autoConnect); - writeVal(lines, "Auto-Connect Delay", autoConnectDelay); - writeVal(lines, "Default Server", encodePairWithoutFormatting(defaultServerHost, "" + defaultServerPort)); - writeVal(lines, "Drawing Port", listenPort); - - List encodedServers = - servers.stream() - .distinct() - .map(server - -> encodePairWithoutFormatting(server.getFirst(), server.getSecond().toString())) - .collect(Collectors.toList()); - writeValList(lines, "Server", encodedServers); - } - - public boolean equals(Networking other) - { - boolean equal = true; - - equal &= this.autoConnect == other.autoConnect; - equal &= this.defaultServerHost.equals(other.defaultServerHost); - equal &= this.defaultServerPort == other.defaultServerPort; - equal &= this.listenPort == other.listenPort; - equal &= this.autoConnectDelay == other.autoConnectDelay; - - equal &= this.servers.size() == other.servers.size(); - for (Pair server : this.servers) { - equal &= other.servers.contains(server); - } - - return equal; - } - - @Override - public Networking clone() - { - Networking clone = new Networking(); - clone.autoConnect = this.autoConnect; - clone.defaultServerHost = this.defaultServerHost; - clone.defaultServerPort = this.defaultServerPort; - clone.listenPort = this.listenPort; - clone.autoConnectDelay = this.autoConnectDelay; - - clone.servers = new LinkedList<>(); - for (Pair server : this.servers) { - clone.servers.add(new Pair<>(server.getFirst(), server.getSecond())); - } - - return clone; - } - - public void overrideServer(String serverHost, Integer serverPort) - { - if (serverHost != null) { - this.overriddenServerHost = serverHost; - } else { - this.overriddenServerHost = defaultServerHost; - } - - if (serverPort != null) { - this.overriddenServerPort = serverPort; - } else { - this.overriddenServerPort = defaultServerPort; - } - } - - public String getOverriddenServerHost() - { - return overriddenServerHost; - } - - public Integer getOverriddenServerPort() - { - return overriddenServerPort; - } - } - - public class General - { - public boolean recordLogs = false; - public String logfileDirectory = null; - public String lookAndFeel = "javax.swing.plaf.nimbus.NimbusLookAndFeel"; - - private void read() - { - recordLogs = getBool("Record Logfiles"); - logfileDirectory = getString("Logfile Directory"); - lookAndFeel = getString("Look and Feel"); - } - - private void write(List lines) - { - writeVal(lines, "Record Logfiles", recordLogs); - writeVal(lines, "Logfile Directory", logfileDirectory); - writeVal(lines, "Look and Feel", lookAndFeel); - } - - public boolean equals(General other) - { - boolean equal = true; - - equal &= this.recordLogs == other.recordLogs; - equal &= this.logfileDirectory.equals(other.logfileDirectory); - equal &= this.lookAndFeel.equals(other.lookAndFeel); - - return equal; - } - - @Override - public General clone() - { - General clone = new General(); - clone.recordLogs = this.recordLogs; - clone.logfileDirectory = this.logfileDirectory; - clone.lookAndFeel = this.lookAndFeel; - - return clone; - } - } - - public class TeamColors - { - public final HashMap colorByTeamName = new HashMap<>(); - public final Color defaultLeftColor = new Color(0x2626ff); - public final Color defaultRightColor = new Color(0xff2626); - - private void read() - { - List teamColors = getAllValues("Team Color"); - for (String teamColor : teamColors) { - Pair decodedTeamColor = decodePair(teamColor); - colorByTeamName.put( - decodedTeamColor.getFirst(), new Color(Integer.decode(decodedTeamColor.getSecond()))); - } - - // Add default colors (if not present) - if (!colorByTeamName.containsKey("")) { - colorByTeamName.put("", defaultLeftColor); - } - if (!colorByTeamName.containsKey("")) { - colorByTeamName.put("", defaultRightColor); - } - } - - private void write(List lines) - { - List encodedTeamNames = - colorByTeamName.entrySet() - .stream() - .map(teamColor - -> encodePairWithoutFormatting(teamColor.getKey(), - String.format("0x%06x", teamColor.getValue().getRGB() & 0xFFFFFF))) - .collect(Collectors.toList()); - - writeValList(lines, "Team Color", encodedTeamNames); - } - - public boolean equals(TeamColors other) - { - boolean equal = true; - - equal &= this.colorByTeamName.size() == other.colorByTeamName.size(); - for (Entry entry : this.colorByTeamName.entrySet()) { - String key = entry.getKey(); - if (entry.getValue() != null) { - equal &= entry.getValue().equals(other.colorByTeamName.get(key)); - } else { - equal &= other.colorByTeamName.get(key) == null; - } - } - - return equal; - } - - @Override - public TeamColors clone() - { - TeamColors clone = new TeamColors(); - - for (Entry entry : this.colorByTeamName.entrySet()) { - clone.colorByTeamName.put(entry.getKey(), entry.getValue()); - } - - return clone; - } - } - - // Original configuration read from config file - private Graphics originalGraphics = new Graphics(); - private OverlayVisibility originalOverlayVisibility = new OverlayVisibility(); - private Networking originalNetworking = new Networking(); - private General originalGeneral = new General(); - private TeamColors originalTeamColors = new TeamColors(); - - // Current configuration - public final Graphics graphics = new Graphics(); - public final OverlayVisibility overlayVisibility = new OverlayVisibility(); - public final Networking networking = new Networking(); - public final General general = new General(); - public final TeamColors teamColors = new TeamColors(); - - private boolean checkLine(String line) - { - return (line.trim().length() > 0 && !line.startsWith("#")); - } - - private String getValue(String key) - { - Pair valuePair = configList.stream().filter(it -> it.getFirst().equals(key)).findFirst().get(); - - if (valuePair != null) { - return valuePair.getSecond(); - } else { - return ""; - } - } - - private List getAllValues(String key) - { - return configList.stream() - .filter(it -> it.getFirst().equals(key)) - .map(it -> it.getSecond()) - .collect(Collectors.toList()); - } - - private boolean getBool(String key) - { - return Boolean.parseBoolean(getValue(key)); - } - - private int getInt(String key) - { - return Integer.parseInt(getValue(key)); - } - - private String getString(String key) - { - return getValue(key); - } - - private static Pair decodePair(String pair) throws IndexOutOfBoundsException - { - String val1 = pair.substring(0, pair.indexOf(":")).trim(); - String val2 = pair.substring(pair.indexOf(":") + 1).trim(); - return new Pair<>(val1, val2); - } - - private static String encodePairWithoutFormatting(String val1, String val2) - { - return val1 + ":" + val2; - } - - private static String escapeRegexCharacters(String unescaped) - { - String escaped = unescaped.replace("\\", "\\\\"); - escaped = escaped.replace(".", "\\."); - escaped = escaped.replace("*", "\\*"); - return escaped; - } - - private static void writeConfigLine(List configLines, String name, String newString) - { - name = escapeRegexCharacters(name); - - // Replace existing line - for (String line : configLines) { - if (line.matches("^" + name + " *:.*$")) { - configLines.set(configLines.indexOf(line), newString); - return; - } - } - - // Name not existing in config file - configLines.add(newString); - } - - private static void writeValList(List configLines, String name, List newStrings) - { - name = escapeRegexCharacters(name); - - // Replace existing lines - int i = 0; - for (String newString : newStrings) { - String line = formatProperty('s', name, newString); - boolean replaced = false; - while (!replaced) { - if (i < configLines.size()) { - // Line existing - if (configLines.get(i).matches("^" + name + " *:.*$")) { - configLines.set(i, line); - replaced = true; - } - } else { - // No more matching lines existing - configLines.add(line); - replaced = true; - } - i++; - } - } - - // Delete leftover old values - while (i < configLines.size()) { - if (configLines.get(i).matches("^" + name + " *:.*$")) { - configLines.remove(i); - } else { - i++; - } - } - } - - private static void writeVal(List configLines, String name, int value) - { - writeConfigLine(configLines, name, formatProperty('d', name, value)); - } - - private static void writeVal(List configLines, String name, boolean value) - { - writeConfigLine(configLines, name, formatProperty('b', name, value)); - } - - private static void writeVal(List configLines, String name, String value) - { - writeConfigLine(configLines, name, formatProperty('s', name, value)); - } - - private static String join(Collection data, String separator) - { - StringBuilder sb = new StringBuilder(); - boolean first = true; - for (String item : data) { - if (!first || (first = false)) - sb.append(separator); - sb.append(item); - } - return sb.toString(); - } - - private static String formatProperty(char type, String name, Object value) - { - return String.format("%-20s : %" + type, name, value); - } - - private static String getNewline() - { - return System.getProperty("line.separator"); - } - - public boolean didChange() - { - return !(graphics.equals(originalGraphics) && overlayVisibility.equals(originalOverlayVisibility) && - networking.equals(originalNetworking) && general.equals(originalGeneral) && - teamColors.equals(originalTeamColors)); - } - - /** - * Sorts the lines which will be written to the config file. - * This prevents parameters apprearing more than once (e.g. "Server") from being spread over the whole document. - */ - private static void sortLines(List lines) - { - int sameParameters; - for (int i = 0; i < lines.size(); i += sameParameters + 1) { - sameParameters = 0; - - String iLine = lines.get(i); - if (!iLine.matches(REGEX_LINE)) { - // Not a key-value line - continue; - } - - Pair iParsedLine = decodePair(iLine); - - for (int j = i + 1; j < lines.size(); j++) { - String jLine = lines.get(j); - if (!jLine.matches(REGEX_LINE)) { - // Not a key-value line - continue; - } - - Pair jParsedLine = decodePair(jLine); - - if (jParsedLine.getFirst().equals(iParsedLine.getFirst())) { - // Move line up to the first one of its kind - sameParameters++; - Collections.rotate(lines.subList(i + sameParameters, j + 1), 1); - } - } - } - } - - private void setCurrentStateAsOriginal() - { - originalGraphics = graphics.clone(); - originalOverlayVisibility = overlayVisibility.clone(); - originalNetworking = networking.clone(); - originalGeneral = general.clone(); - originalTeamColors = teamColors.clone(); - } - - private void readLines(File file, Consumer action) - { - try (Stream stream = Files.lines(Paths.get(file.getAbsolutePath()))) { - stream.forEach(action); - } catch (NoSuchFileException nf) { - System.err.println("Could not find config file"); - nf.printStackTrace(); - System.exit(1); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - } - - public void write() - { - if (!didChange()) { - // Doesn't need to be saved if nothing changed - return; - } - - File configFile = new File(getConfigFilePath()); - - // Read configuration including comments - List lines = new LinkedList(); - readLines(configFile, line -> lines.add(line)); - - graphics.write(lines); - overlayVisibility.write(lines); - networking.write(lines); - general.write(lines); - teamColors.write(lines); - sortLines(lines); - - // Write modified configuration file back - BufferedWriter out = null; - try { - out = new BufferedWriter(new FileWriter(configFile)); - out.write(join(lines, getNewline())); - setCurrentStateAsOriginal(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (out != null) { - try { - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - private Configuration read(File file) - { - // parse the configuration file - readLines(file, line -> { - if (checkLine(line)) { - try { - Pair parsedLine = decodePair(line); - configList.add(parsedLine); - } catch (IndexOutOfBoundsException e) { - // Line doesn't contain a colon - System.err.println("\"" + line + "\" is not a valid key-value pair."); - } - } - }); - - // read the parsed data - try { - graphics.read(); - overlayVisibility.read(); - networking.read(); - general.read(); - teamColors.read(); - - setCurrentStateAsOriginal(); - } catch (Exception e) { - System.err.println( - "Error reading values from config file '" + file + - "'. The configuration file might be corrupt or incompatible with this version of RoboViz, try resetting it."); - System.exit(1); - } - - return this; - } - - public static Configuration loadFromFile() - { - return new Configuration().read(new File(getConfigFilePath())); - } -} diff --git a/src/main/java/rv/comm/NetworkManager.java b/src/main/java/rv/comm/NetworkManager.java index 6d3a1170..7dc8d2ca 100644 --- a/src/main/java/rv/comm/NetworkManager.java +++ b/src/main/java/rv/comm/NetworkManager.java @@ -19,8 +19,8 @@ import java.net.SocketException; import org.magmaoffenburg.roboviz.Main; +import org.magmaoffenburg.roboviz.configuration.Config.Networking; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration; import rv.comm.drawing.DrawComm; import rv.comm.rcssserver.ServerComm; @@ -44,14 +44,14 @@ public ServerComm getServer() return serverComm; } - public void init(Configuration config) + public void init() { try { - agentComm = new DrawComm(config.networking.listenPort); + agentComm = new DrawComm(Networking.INSTANCE.getListenPort()); } catch (SocketException e) { e.printStackTrace(); } - serverComm = new ServerComm(ViewRenderer.Companion.getWorld(), config, Main.Companion.getMode()); + serverComm = new ServerComm(ViewRenderer.Companion.getWorld(), Main.Companion.getMode()); if (agentComm != null) { agentComm.addListener(serverComm); } diff --git a/src/main/java/rv/comm/rcssserver/LogPlayer.java b/src/main/java/rv/comm/rcssserver/LogPlayer.java index cf7c2eee..e3c08bdf 100644 --- a/src/main/java/rv/comm/rcssserver/LogPlayer.java +++ b/src/main/java/rv/comm/rcssserver/LogPlayer.java @@ -24,8 +24,8 @@ import javax.swing.JFileChooser; import javax.swing.JFrame; import jsgl.math.Maths; +import org.magmaoffenburg.roboviz.configuration.Config.General; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration; import rv.comm.rcssserver.ILogfileReader.LogfileListener; import rv.comm.rcssserver.LogAnalyzerThread.Goal; import rv.util.StringUtil; @@ -53,7 +53,6 @@ public interface StateChangeListener { /** time within which to jump over goals for nicer stepping during playback */ private static final float GOAL_STEP_THRESHOLD_SECONDS = 3f; - private final Configuration config; private ILogfileReader logfile; private LogRunnerThread logRunner; private LogAnalyzerThread logAnalyzer; @@ -76,10 +75,8 @@ public interface StateChangeListener { * @param world * reference to the world model */ - public LogPlayer(File file, WorldModel world, Configuration config) + public LogPlayer(File file, WorldModel world) { - this.config = config; - playing = false; parser = new MessageParser(world); @@ -351,7 +348,7 @@ private void setPlaying(boolean playing) public void openFileDialog(JFrame parent) { JFileChooser fileChooser = new FileChooser(); - String logfileDirectory = config.general.logfileDirectory; + String logfileDirectory = General.INSTANCE.getLogfileDirectory(); if (logfileDirectory != null && !logfileDirectory.isEmpty()) { fileChooser.setCurrentDirectory(new File(logfileDirectory)); } diff --git a/src/main/java/rv/comm/rcssserver/ServerComm.java b/src/main/java/rv/comm/rcssserver/ServerComm.java index 614cedf8..36d407dd 100644 --- a/src/main/java/rv/comm/rcssserver/ServerComm.java +++ b/src/main/java/rv/comm/rcssserver/ServerComm.java @@ -31,8 +31,9 @@ import java.util.concurrent.CopyOnWriteArrayList; import javax.swing.Timer; import jsgl.math.vector.Vec3f; +import org.magmaoffenburg.roboviz.configuration.Config.General; +import org.magmaoffenburg.roboviz.configuration.Config.Networking; import org.magmaoffenburg.roboviz.util.DataTypes; -import rv.Configuration; import rv.comm.drawing.DrawComm.DrawCommListener; import rv.ui.DebugInfo; import rv.world.WorldModel; @@ -176,23 +177,21 @@ private void writeToLogfile(String msg) logfileOutput.write("\n"); } - public ServerComm(WorldModel world, Configuration config, DataTypes.Mode viewerMode) + public ServerComm(WorldModel world, DataTypes.Mode viewerMode) { this.world = world; - Configuration.Networking net = config.networking; - - if (net.getOverriddenServerHost() != null && net.getOverriddenServerPort() != null) { - serverHost = net.getOverriddenServerHost(); - serverPort = net.getOverriddenServerPort(); - } else { - serverHost = net.servers.get(0).getFirst(); - serverPort = net.servers.get(0).getSecond(); - } +// if (Networking.INSTANCE.getOverriddenServerHost() != null && Networking.INSTANCE.getOverriddenServerPort() != null) { + serverHost = Networking.INSTANCE.getOverriddenServerHost(); + serverPort = Networking.INSTANCE.getOverriddenServerPort(); +// } else { +// serverHost = Networking.INSTANCE.getServers().get(0).getFirst(); +// serverPort = Networking.INSTANCE.getServers().get(0).getSecond(); +// } // automatically attempt connection with server while not connected - if (net.autoConnect) { - autoConnectTimer = new Timer(net.autoConnectDelay, e -> { + if (Networking.INSTANCE.getAutoConnect()) { + autoConnectTimer = new Timer(Networking.INSTANCE.getAutoConnectDelay(), e -> { if (socket == null) { connect(serverHost, serverPort); } @@ -201,8 +200,8 @@ public ServerComm(WorldModel world, Configuration config, DataTypes.Mode viewerM autoConnectTimer.start(); } - recordLogs = viewerMode != DataTypes.Mode.LOGFILE && config.general.recordLogs; - logfileDirectory = config.general.logfileDirectory; + recordLogs = viewerMode != DataTypes.Mode.LOGFILE && General.INSTANCE.getRecordLogs(); + logfileDirectory = General.INSTANCE.getLogfileDirectory(); } private void setupNewLogfile() diff --git a/src/main/java/rv/content/ContentManager.java b/src/main/java/rv/content/ContentManager.java index c6962a42..20229bd7 100644 --- a/src/main/java/rv/content/ContentManager.java +++ b/src/main/java/rv/content/ContentManager.java @@ -38,7 +38,7 @@ import jsgl.jogl.model.ObjMaterialLibrary; import jsgl.jogl.model.ObjMeshImporter; import jsgl.math.vector.Vec3f; -import rv.Configuration; +import org.magmaoffenburg.roboviz.configuration.Config.TeamColors; import rv.comm.rcssserver.GameState; import rv.comm.rcssserver.scenegraph.Node; import rv.comm.rcssserver.scenegraph.SceneGraph; @@ -76,7 +76,7 @@ public void run() } } - private final Configuration.TeamColors config; + private final TeamColors config; private Mesh.RenderMode meshRenderMode = Mesh.RenderMode.IMMEDIATE; private Texture2D whiteTexture; @@ -125,7 +125,7 @@ public synchronized Model getModel(String name) return model; } - public ContentManager(Configuration.TeamColors config) + public ContentManager(TeamColors config) { this.config = config; } @@ -300,12 +300,12 @@ public void gsPlayStateChanged(GameState gs) // if team name changed, update the materials String teamNameLeft = gs.getTeamLeft(); if (!Objects.equals(teamNameLeft, this.teamNameLeft)) { - updateTeamColor(teamNameLeft, "matLeft", config.defaultLeftColor); + updateTeamColor(teamNameLeft, "matLeft", config.getDefaultLeft()); this.teamNameLeft = teamNameLeft; } String teamNameRight = gs.getTeamRight(); if (!Objects.equals(teamNameRight, this.teamNameRight)) { - updateTeamColor(teamNameRight, "matRight", config.defaultRightColor); + updateTeamColor(teamNameRight, "matRight", config.getDefaultRight()); this.teamNameRight = teamNameRight; } } @@ -313,7 +313,7 @@ public void gsPlayStateChanged(GameState gs) private void updateTeamColor(String teamName, String materialName, Color defaultColor) { ObjMaterial mat = getMaterial(materialName); - Color color = config.colorByTeamName.get(teamName); + Color color = config.getByTeamNames().get(teamName); if (color == null) { color = defaultColor; } diff --git a/src/main/java/rv/effects/Bloom.java b/src/main/java/rv/effects/Bloom.java index 2876f22e..8be8c952 100644 --- a/src/main/java/rv/effects/Bloom.java +++ b/src/main/java/rv/effects/Bloom.java @@ -25,7 +25,7 @@ import jsgl.jogl.Uniform; import jsgl.jogl.view.Viewport; import jsgl.math.Gaussian; -import rv.Configuration; +import org.magmaoffenburg.roboviz.configuration.Config; import rv.util.WindowResizeEvent; import rv.util.WindowResizeListener; import rv.content.ContentManager; @@ -68,7 +68,7 @@ public Bloom() { } - public boolean init(GL2 gl, Viewport screen, ContentManager cm, Configuration.Graphics config) + public boolean init(GL2 gl, Viewport screen, ContentManager cm, Config.Graphics config) { luminosityShader = cm.loadShader(gl, "luminosity"); if (luminosityShader == null) { @@ -109,11 +109,11 @@ public boolean init(GL2 gl, Viewport screen, ContentManager cm, Configuration.Gr return true; } - private void abortInit(GL2 gl, String error, Configuration.Graphics config) + private void abortInit(GL2 gl, String error, Config.Graphics config) { System.err.println("Bloom: " + error); dispose(gl); - config.useBloom = false; + config.setUseBloom(false); } /** diff --git a/src/main/java/rv/effects/EffectManager.java b/src/main/java/rv/effects/EffectManager.java index 1329270b..5253c371 100644 --- a/src/main/java/rv/effects/EffectManager.java +++ b/src/main/java/rv/effects/EffectManager.java @@ -23,7 +23,7 @@ import jsgl.jogl.light.DirLight; import jsgl.jogl.view.Viewport; import jsgl.math.vector.Vec3f; -import rv.Configuration; +import org.magmaoffenburg.roboviz.configuration.Config.Graphics; import rv.content.ContentManager; import rv.world.rendering.GLHelper; import rv.world.rendering.ShadowMapRenderer; @@ -50,7 +50,7 @@ public ShadowMapRenderer getShadowRenderer() return shadowRenderer; } - public void init(GL2 gl, Viewport screen, Configuration.Graphics config, ContentManager cm) + public void init(GL2 gl, Viewport screen, Graphics config, ContentManager cm) { // configure sun Vec3f lightPos = new Vec3f(-11, 10, 9); @@ -58,7 +58,7 @@ public void init(GL2 gl, Viewport screen, Configuration.Graphics config, Content DirLight light = new DirLight(lightDir); LightShadowVolume sun = new LightShadowVolume(light, lightPos, new Vec3f(0, 0, 0), Vec3f.unitY(), 40, 40, 40); - if (config.useBloom) { + if (config.getUseBloom()) { bloom = new Bloom(); boolean success = bloom.init(gl, screen, cm, config); if (!success) @@ -67,7 +67,7 @@ public void init(GL2 gl, Viewport screen, Configuration.Graphics config, Content // viewer.addWindowResizeListener(bloom); // not needed windowResized is called in Renderer.reshape } - if (config.useShadows) { + if (config.getUseShadows()) { shadowRenderer = new ShadowMapRenderer(sun); if (!shadowRenderer.init(gl, config, cm)) shadowRenderer = null; diff --git a/src/main/java/rv/ui/screens/LiveGameScreen.java b/src/main/java/rv/ui/screens/LiveGameScreen.java index e7019af2..1f3acde6 100644 --- a/src/main/java/rv/ui/screens/LiveGameScreen.java +++ b/src/main/java/rv/ui/screens/LiveGameScreen.java @@ -20,9 +20,9 @@ import java.awt.event.MouseEvent; import jsgl.math.vector.Vec3f; import org.magmaoffenburg.roboviz.MainWindow; -import org.magmaoffenburg.roboviz.configuration.ConfigurationController; +import org.magmaoffenburg.roboviz.configuration.Config.Networking; +import org.magmaoffenburg.roboviz.configuration.Config.OverlayVisibility; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration; import rv.comm.rcssserver.GameState; import rv.comm.rcssserver.ServerComm; import rv.comm.rcssserver.ServerSpeedBenchmarker; @@ -52,10 +52,10 @@ public LiveGameScreen() } @Override - protected void loadOverlayVisibilities(Configuration.OverlayVisibility config) + protected void loadOverlayVisibilities() { - super.loadOverlayVisibilities(config); - gameStateOverlay.setShowServerSpeed(config.serverSpeed); + super.loadOverlayVisibilities(); + gameStateOverlay.setShowServerSpeed(OverlayVisibility.INSTANCE.getServerSpeed()); } private ServerComm getServer() @@ -102,7 +102,7 @@ private String getConnectionMessage() // "stopped" if (gameState.isInitialized() && Math.abs(gameState.getTime() - gameState.getHalfTime()) < 0.1) return "Waiting for second half..."; - else if (ConfigurationController.INSTANCE.getConfig().networking.autoConnect) + else if (Networking.INSTANCE.getAutoConnect()) return "Trying to connect to " + server + "..."; else return "Press C to connect to " + server + "."; diff --git a/src/main/java/rv/ui/screens/ViewerScreenBase.java b/src/main/java/rv/ui/screens/ViewerScreenBase.java index 74aba2f3..209484a8 100644 --- a/src/main/java/rv/ui/screens/ViewerScreenBase.java +++ b/src/main/java/rv/ui/screens/ViewerScreenBase.java @@ -19,10 +19,10 @@ import jsgl.jogl.view.Viewport; import jsgl.math.BoundingBox; import jsgl.math.vector.Vec3f; -import org.magmaoffenburg.roboviz.configuration.ConfigurationController; +import org.magmaoffenburg.roboviz.configuration.Config.Graphics; +import org.magmaoffenburg.roboviz.configuration.Config.OverlayVisibility; import org.magmaoffenburg.roboviz.rendering.CameraController; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration; import rv.comm.drawing.BufferedSet; import rv.comm.drawing.annotations.AgentAnnotation; import rv.comm.drawing.annotations.Annotation; @@ -97,23 +97,23 @@ public ViewerScreenBase() Font font = new Font("Arial", Font.BOLD, 16); tr = new BorderTextRenderer(font, true, false); - Configuration.Graphics config = ConfigurationController.INSTANCE.getGraphics(); - firstPersonFOV = config.firstPersonFOV; - thirdPersonFOV = config.thirdPersonFOV; + Graphics config = Graphics.INSTANCE; + firstPersonFOV = config.getFirstPersonFOV(); + thirdPersonFOV = config.getThirdPersonFOV(); ViewRenderer.world.getGameState().addListener(this); ViewRenderer.world.addSelectionChangeListener(this); // viewer.addWindowResizeListener(this); // TODO - loadOverlayVisibilities(ConfigurationController.INSTANCE.getConfig().overlayVisibility); + loadOverlayVisibilities(); } - protected void loadOverlayVisibilities(Configuration.OverlayVisibility config) + protected void loadOverlayVisibilities() { - fieldOverlay.setVisible(config.fieldOverlay); - foulListOverlay.setVisible(config.foulOverlay); - setShowNumPlayers(config.numberOfPlayers); - if (config.playerIDs) + fieldOverlay.setVisible(OverlayVisibility.INSTANCE.getFieldOverlay()); + foulListOverlay.setVisible(OverlayVisibility.INSTANCE.getFoulOverlay()); + setShowNumPlayers(OverlayVisibility.INSTANCE.getNumberOfPlayers()); + if (OverlayVisibility.INSTANCE.getPlayerIDs()) agentOverheadType = AgentOverheadType.IDS; } diff --git a/src/main/java/rv/world/Team.java b/src/main/java/rv/world/Team.java index 79b374dc..81a23451 100644 --- a/src/main/java/rv/world/Team.java +++ b/src/main/java/rv/world/Team.java @@ -21,7 +21,7 @@ import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; import jsgl.jogl.model.ObjMaterial; -import rv.Configuration; +import org.magmaoffenburg.roboviz.configuration.Config.TeamColors; import rv.comm.rcssserver.GameState; import rv.comm.rcssserver.GameState.GameStateChangeListener; import rv.comm.rcssserver.ISceneGraphItem; @@ -44,7 +44,7 @@ public class Team implements ISceneGraphItem, GameStateChangeListener public static final int MAX_AGENTS = 11; - private final Configuration.TeamColors config; + private final TeamColors config; private final ContentManager content; private final Color defaultColor; private final int id; @@ -100,7 +100,7 @@ public void setName(String name) this.name = name; - Color color = config.colorByTeamName.get(name); + Color color = config.getByTeamNames().get(name); if (color == null) { color = defaultColor; } @@ -112,7 +112,7 @@ public void setScore(int score) this.score = score; } - public Team(Color defaultColor, int id, ContentManager content, Configuration.TeamColors config) + public Team(Color defaultColor, int id, ContentManager content, TeamColors config) { this.defaultColor = defaultColor; this.id = id; diff --git a/src/main/java/rv/world/WorldModel.java b/src/main/java/rv/world/WorldModel.java index f016523a..08d648f9 100644 --- a/src/main/java/rv/world/WorldModel.java +++ b/src/main/java/rv/world/WorldModel.java @@ -25,9 +25,9 @@ import jsgl.jogl.light.LightModel; import jsgl.math.vector.Matrix; import jsgl.math.vector.Vec3f; +import org.magmaoffenburg.roboviz.configuration.Config.TeamColors; import org.magmaoffenburg.roboviz.rendering.CameraController; import org.magmaoffenburg.roboviz.util.DataTypes; -import rv.Configuration; import rv.comm.rcssserver.GameState; import rv.comm.rcssserver.ISceneGraphItem; import rv.comm.rcssserver.scenegraph.SceneGraph; @@ -55,7 +55,6 @@ public interface SelectionChangeListener { private final GameState gameState = new GameState(); private SceneGraph sceneGraph = null; private ContentManager cm; - private Configuration config; private final ArrayList sgItems = new ArrayList<>(); @@ -184,10 +183,9 @@ public Team getRightTeam() return rightTeam; } - public void init(GL glObj, ContentManager cm, Configuration config, DataTypes.Mode mode) + public void init(GL glObj, ContentManager cm, DataTypes.Mode mode) { this.cm = cm; - this.config = config; GL2 gl = glObj.getGL2(); field = new Field(cm.getModel("models/newfield.obj"), cm); @@ -223,10 +221,10 @@ private void initTeams() sgItems.remove(rightTeam); } - Configuration.TeamColors teamColors = config.teamColors; - leftTeam = new Team(teamColors.defaultLeftColor, Team.LEFT, cm, teamColors); + TeamColors teamColors = TeamColors.INSTANCE; + leftTeam = new Team(teamColors.getDefaultLeft(), Team.LEFT, cm, teamColors); gameState.addListener(leftTeam); - rightTeam = new Team(teamColors.defaultRightColor, Team.RIGHT, cm, teamColors); + rightTeam = new Team(teamColors.getDefaultRight(), Team.RIGHT, cm, teamColors); gameState.addListener(rightTeam); sgItems.add(leftTeam); @@ -319,7 +317,7 @@ public void dispose(GL gl) public synchronized void reset() { gameState.reset(); - if (cm != null && config != null) + if (cm != null) initTeams(); setSceneGraph(null); } diff --git a/src/main/java/rv/world/rendering/BasicSceneRenderer.java b/src/main/java/rv/world/rendering/BasicSceneRenderer.java index e48c2e3b..95587991 100644 --- a/src/main/java/rv/world/rendering/BasicSceneRenderer.java +++ b/src/main/java/rv/world/rendering/BasicSceneRenderer.java @@ -21,8 +21,8 @@ import java.util.ArrayList; import java.util.List; import jsgl.math.vector.Matrix; +import org.magmaoffenburg.roboviz.configuration.Config; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration; import rv.comm.drawing.Drawings; import rv.comm.rcssserver.scenegraph.StaticMeshNode; import rv.content.ContentManager; @@ -40,7 +40,7 @@ public class BasicSceneRenderer implements SceneRenderer private final List suppressedMeshes = new ArrayList<>(); @Override - public boolean init(GL2 gl2, Configuration.Graphics conf, ContentManager cm) + public boolean init(GL2 gl2, Config.Graphics conf, ContentManager cm) { this.content = cm; diff --git a/src/main/java/rv/world/rendering/PhongWorldRenderer.java b/src/main/java/rv/world/rendering/PhongWorldRenderer.java index 1682b311..512d2629 100644 --- a/src/main/java/rv/world/rendering/PhongWorldRenderer.java +++ b/src/main/java/rv/world/rendering/PhongWorldRenderer.java @@ -22,8 +22,8 @@ import java.util.List; import jsgl.jogl.ShaderProgram; import jsgl.math.vector.Matrix; +import org.magmaoffenburg.roboviz.configuration.Config; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration.Graphics; import rv.comm.drawing.Drawings; import rv.comm.rcssserver.scenegraph.StaticMeshNode; import rv.content.ContentManager; @@ -43,18 +43,18 @@ public class PhongWorldRenderer implements SceneRenderer private final List suppressedMeshes = new ArrayList<>(); @Override - public boolean init(GL2 gl, Graphics graphics, ContentManager cm) + public boolean init(GL2 gl, Config.Graphics graphics, ContentManager cm) { this.content = cm; shader = cm.loadShader(gl, "phong"); if (shader == null) { - graphics.usePhong = false; + graphics.setUsePhong(false); System.err.println("Phong shader failed to load!"); } if (shader == null) { - graphics.usePhong = false; + graphics.setUsePhong(false); return false; } diff --git a/src/main/java/rv/world/rendering/SceneRenderer.java b/src/main/java/rv/world/rendering/SceneRenderer.java index 92af01a0..d5b1f519 100644 --- a/src/main/java/rv/world/rendering/SceneRenderer.java +++ b/src/main/java/rv/world/rendering/SceneRenderer.java @@ -18,7 +18,7 @@ import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2; -import rv.Configuration; +import org.magmaoffenburg.roboviz.configuration.Config; import rv.comm.drawing.Drawings; import rv.content.ContentManager; import rv.world.WorldModel; @@ -34,7 +34,7 @@ public interface SceneRenderer { * * @return true if initialization successful */ - boolean init(GL2 gl, Configuration.Graphics conf, ContentManager cm); + boolean init(GL2 gl, Config.Graphics conf, ContentManager cm); /** * Renders world model scene to currently bound frame buffer according to this renderer's diff --git a/src/main/java/rv/world/rendering/ShadowMapRenderer.java b/src/main/java/rv/world/rendering/ShadowMapRenderer.java index 31162979..1496d915 100644 --- a/src/main/java/rv/world/rendering/ShadowMapRenderer.java +++ b/src/main/java/rv/world/rendering/ShadowMapRenderer.java @@ -28,8 +28,7 @@ import jsgl.math.Gaussian; import jsgl.math.vector.Matrix; import jsgl.math.vector.Vec3f; -import rv.Configuration; -import rv.Configuration.Graphics; +import org.magmaoffenburg.roboviz.configuration.Config; import rv.comm.drawing.Drawings; import rv.comm.rcssserver.scenegraph.StaticMeshNode; import rv.content.ContentManager; @@ -184,11 +183,11 @@ private FrameBufferObject createBlurFBO(GL2 gl) return fbo; } - private boolean abortInit(GL2 gl, String error, Configuration.Graphics config) + private boolean abortInit(GL2 gl, String error, Config.Graphics config) { System.err.println("Shadow Map: " + error); dispose(gl); - config.useShadows = false; + config.setUseShadows(false); return false; } @@ -301,12 +300,12 @@ public void dispose(GL gl) } @Override - public boolean init(GL2 gl, Graphics conf, ContentManager cm) + public boolean init(GL2 gl, Config.Graphics conf, ContentManager cm) { this.content = cm; - this.useBlur = conf.useSoftShadows; + this.useBlur = conf.getUseSoftShadows(); - texWidth = texHeight = conf.shadowResolution; + texWidth = texHeight = conf.getShadowResolution(); // generate FBOs shadowFBO = createShadowFBO(gl); diff --git a/src/main/java/rv/world/rendering/VSMPhongWorldRenderer.java b/src/main/java/rv/world/rendering/VSMPhongWorldRenderer.java index f6ef5df3..1837735d 100644 --- a/src/main/java/rv/world/rendering/VSMPhongWorldRenderer.java +++ b/src/main/java/rv/world/rendering/VSMPhongWorldRenderer.java @@ -21,8 +21,8 @@ import java.util.ArrayList; import java.util.List; import jsgl.math.vector.Matrix; +import org.magmaoffenburg.roboviz.configuration.Config; import org.magmaoffenburg.roboviz.rendering.ViewRenderer; -import rv.Configuration.Graphics; import rv.comm.drawing.Drawings; import rv.comm.rcssserver.scenegraph.StaticMeshNode; import rv.content.ContentManager; @@ -54,13 +54,13 @@ public VSMPhongWorldRenderer(EffectManager effects) } @Override - public boolean init(GL2 gl, Graphics graphics, ContentManager cm) + public boolean init(GL2 gl, Config.Graphics graphics, ContentManager cm) { this.content = cm; shader = VSMPhongShader.create(gl); if (shader == null) { - graphics.useShadows = false; + graphics.setUseShadows(false); return false; } diff --git a/src/main/kotlin/org/magmaoffenburg/roboviz/Main.kt b/src/main/kotlin/org/magmaoffenburg/roboviz/Main.kt index 983f86fb..54e3ec23 100644 --- a/src/main/kotlin/org/magmaoffenburg/roboviz/Main.kt +++ b/src/main/kotlin/org/magmaoffenburg/roboviz/Main.kt @@ -1,6 +1,6 @@ package org.magmaoffenburg.roboviz -import org.magmaoffenburg.roboviz.configuration.ConfigurationController +import org.magmaoffenburg.roboviz.configuration.Config import org.magmaoffenburg.roboviz.etc.LookAndFeelController import org.magmaoffenburg.roboviz.rendering.ViewRenderer import org.magmaoffenburg.roboviz.util.DataTypes @@ -14,10 +14,12 @@ class Main { } fun main(args: Array) { - // TODO parse parameters + // parse parameters and config + // TODO --logMode, --logFile, --drawingFilter + Config(args) // set Look and Feel - LookAndFeelController.setLookAndFeel(ConfigurationController.general.lookAndFeel) + LookAndFeelController.setLookAndFeel(Config.General.lookAndFeel) // create MainWindow EventQueue.invokeLater(::createAndShowGUI) @@ -28,4 +30,4 @@ private fun createAndShowGUI() { mainWindow.isVisible = true ViewRenderer() // create the Renderer -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/magmaoffenburg/roboviz/MainWindow.kt b/src/main/kotlin/org/magmaoffenburg/roboviz/MainWindow.kt index a2ba35a9..b8d11a12 100644 --- a/src/main/kotlin/org/magmaoffenburg/roboviz/MainWindow.kt +++ b/src/main/kotlin/org/magmaoffenburg/roboviz/MainWindow.kt @@ -3,7 +3,7 @@ package org.magmaoffenburg.roboviz import com.jogamp.opengl.GLCapabilities import com.jogamp.opengl.GLProfile import com.jogamp.opengl.awt.GLCanvas -import org.magmaoffenburg.roboviz.configuration.ConfigurationController +import org.magmaoffenburg.roboviz.configuration.Config import org.magmaoffenburg.roboviz.menus.CameraMenu import org.magmaoffenburg.roboviz.menus.ConnectionMenu import org.magmaoffenburg.roboviz.menus.ServerMenu @@ -13,7 +13,6 @@ import rv.comm.rcssserver.ServerComm import java.awt.BorderLayout import java.awt.Dimension import java.awt.event.KeyEvent -import java.awt.event.KeyListener import javax.imageio.ImageIO import javax.swing.JFrame import javax.swing.JMenuBar @@ -23,7 +22,7 @@ import javax.swing.JMenuBar */ class MainWindow : JFrame(), ServerComm.ServerChangeListener { - private val windowTitle = "RoboViz-Kt ${Main.version}" + private val windowTitle = "RoboVizKt ${Main.version}" companion object { lateinit var instance: MainWindow @@ -87,10 +86,10 @@ class MainWindow : JFrame(), ServerComm.ServerChangeListener { val glCapabilities = GLCapabilities(glProfile) // set glCapabilities according to config - glCapabilities.stereo = ConfigurationController.graphics.useStereo - if (ConfigurationController.graphics.useFsaa) { + glCapabilities.stereo = Config.Graphics.useStereo + if (Config.Graphics.useFsaa) { glCapabilities.sampleBuffers = true - glCapabilities.numSamples = ConfigurationController.graphics.fsaaSamples + glCapabilities.numSamples = Config.Graphics.fsaaSamples } glCanvas = GLCanvas(glCapabilities) diff --git a/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/Config.kt b/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/Config.kt new file mode 100644 index 00000000..404b182a --- /dev/null +++ b/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/Config.kt @@ -0,0 +1,215 @@ +package org.magmaoffenburg.roboviz.configuration + +import java.awt.Color +import java.io.File + +/** + * To support multiple Team colors and servers without breaking existing + * Config files, "Server :" and "Team Color" are SuperKeys. The ConfigParser can + * get all lines starting with a SuperKey. The raw SuperKeys are trimmed to only + * contain one space. + */ +class Config(args: Array) { + + private val localPath = "config.txt" + private val globalPath = System.getProperty("user.home") + "/.roboviz/config.txt" + + private val parser = ConfigParser() + private val filePath = if (File(globalPath).exists()) globalPath else localPath + + init { + parser.parseArgs(args) + parser.parseFile(filePath) + + try { + read() + } catch (ex: Exception) { + System.err.println("Error reading parsed values. The configuration file might be corrupt or incompatible with this version of RoboViz, try resetting it.") + } + +// Networking.servers.add( +// Pair("localhost", 3400) +// ) +// +// write() +// parser.writeFile(filePath) + } + + object General { + var recordLogs = false + var logfileDirectory = "" + var lookAndFeel = "javax.swing.plaf.nimbus.NimbusLookAndFeel" + } + + object Graphics { + var useBloom = false + var usePhong = false + var useShadows = false + var useSoftShadows = false + var shadowResolution = 1024 + var useStereo = false + var useVsync = true + var useFsaa = false + var fsaaSamples = 4 + var targetFPS = 60 + var firstPersonFOV = 120 + var thirdPersonFOV = 80 + + var frameWidth = 1024 + var frameHeight = 768 + var frameX = 0 + var frameY = 0 + + var centerFrame = true + var isMaximized = false + var saveFrameState = true + } + + object Networking { + var autoConnect = true + var autoConnectDelay = 1000 + var listenPort = 32769 + + var servers = arrayListOf>() + var defaultServerHost = "localhost" + var defaultServerPort = 3200 + + var overriddenServerHost = defaultServerHost + var overriddenServerPort = defaultServerPort + } + + object OverlayVisibility { + var serverSpeed = true + var foulOverlay = true + var fieldOverlay = false + var numberOfPlayers = false + var playerIDs = false + } + + object TeamColors { + val byTeamNames = hashMapOf() + val defaultLeft = Color(0x2626ff) + val defaultRight = Color(0xff2626) + } + + /** + * set object variables to values from parser + */ + private fun read() { + // General + General.recordLogs = parser.getValue("Record Logfiles").toBoolean() + General.logfileDirectory = parser.getValue("Logfile Directory") + General.lookAndFeel = parser.getValue("Look and Feel") + + // Graphics + Graphics.useBloom = parser.getValue("Bloom").toBoolean() + Graphics.usePhong = parser.getValue("Phong").toBoolean() + Graphics.useShadows = parser.getValue("Shadows").toBoolean() + Graphics.useSoftShadows = parser.getValue("Soft Shadows").toBoolean() + Graphics.shadowResolution = parser.getValue("Shadow Resolution").toInt() + Graphics.useStereo = parser.getValue("Stereo 3D").toBoolean() + Graphics.useVsync = parser.getValue("V-Sync").toBoolean() + Graphics.useFsaa = parser.getValue("FSAA").toBoolean() + Graphics.fsaaSamples = parser.getValue("FSAA Samples").toInt() + Graphics.targetFPS = parser.getValue("Target FPS").toInt() + Graphics.firstPersonFOV = parser.getValue("First Person FOV").toInt() + Graphics.thirdPersonFOV = parser.getValue("Third Person FOV").toInt() + + Graphics.frameWidth = parser.getValue("Frame Width").toInt() + Graphics.frameHeight = parser.getValue("Frame Height").toInt() + Graphics.frameX = parser.getValue("Frame X").toInt() + Graphics.frameY = parser.getValue("Frame Y").toInt() + Graphics.centerFrame = parser.getValue("Center Frame").toBoolean() + Graphics.isMaximized = parser.getValue("Frame Maximized").toBoolean() + Graphics.saveFrameState = parser.getValue("Save Frame State").toBoolean() + + // Networking + Networking.autoConnect = parser.getValue("Auto-Connect").toBoolean() + Networking.autoConnectDelay = parser.getValue("Auto-Connect Delay").toInt() + Networking.listenPort = parser.getValue("Drawing Port").toInt() + + parser.getValueSuperKey("Server :").forEach { + Networking.servers.add(Pair(it.value.substringBefore(":"), it.value.substringAfter(":").toInt())) + } + Networking.defaultServerHost = parser.getValue("Default Server").substringBefore(":") + Networking.defaultServerPort = parser.getValue("Default Server").substringAfter(":").toInt() + + // OverlayVisibility + OverlayVisibility.serverSpeed = parser.getValue("Server Speed").toBoolean() + OverlayVisibility.foulOverlay = parser.getValue("Foul Overlay").toBoolean() + OverlayVisibility.fieldOverlay = parser.getValue("Field Overlay").toBoolean() + OverlayVisibility.numberOfPlayers = parser.getValue("Number of Players").toBoolean() + OverlayVisibility.playerIDs = parser.getValue("Player IDs").toBoolean() + + // TeamColors + parser.getValueSuperKey("Team Color").forEach { + TeamColors.byTeamNames[it.key] = Color(Integer.decode(it.value)) + } + + // Args + Networking.overriddenServerHost = parser.argsList.firstOrNull { + it.first == "serverHost" + }?.second ?: Networking.defaultServerHost + Networking.overriddenServerPort = parser.argsList.firstOrNull { + it.first == "serverPort" + }?.second?.toInt() ?: Networking.defaultServerPort + } + + /** + * set parser list to object variable values + */ + private fun write() { + // general + parser.setValue("Record Logfiles", General.recordLogs.toString()) + parser.setValue("Logfile Directory", General.logfileDirectory) + parser.setValue("Look and Feel", General.lookAndFeel) + + // Graphics + parser.setValue("Bloom", Graphics.useBloom.toString()) + parser.setValue("Phong", Graphics.usePhong.toString()) + parser.setValue("Shadows", Graphics.useShadows.toString()) + parser.setValue("Soft Shadows", Graphics.useSoftShadows.toString()) + parser.setValue("Shadow Resolution", Graphics.shadowResolution.toString()) + parser.setValue("Stereo 3D", Graphics.useStereo.toString()) + parser.setValue("V-Sync", Graphics.useVsync.toString()) + parser.setValue("FSAA", Graphics.useFsaa.toString()) + parser.setValue("FSAA Samples", Graphics.fsaaSamples.toString()) + parser.setValue("Target FPS", Graphics.targetFPS.toString()) + parser.setValue("First Person FOV", Graphics.firstPersonFOV.toString()) + parser.setValue("Third Person FOV", Graphics.thirdPersonFOV.toString()) + + parser.setValue("Frame Width", Graphics.frameWidth.toString()) + parser.setValue("Frame Height", Graphics.frameHeight.toString()) + parser.setValue("Frame X", Graphics.frameX.toString()) + parser.setValue("Frame Y", Graphics.frameY.toString()) + parser.setValue("Center Frame", Graphics.centerFrame.toString()) + parser.setValue("Frame Maximized", Graphics.isMaximized.toString()) + parser.setValue("Save Frame State", Graphics.saveFrameState.toString()) + + // Networking + parser.setValue("Auto-Connect", Networking.autoConnect.toString()) + parser.setValue("Auto-Connect Delay", Networking.autoConnectDelay.toString()) + parser.setValue("Drawing Port", Networking.listenPort.toString()) + + Networking.servers.forEach { + val key = "Server : ${it.first}:${it.second}" + val value = "${it.first}:${it.second}" + parser.setValue(key, value) + } + parser.setValue("Drawing Port", Networking.listenPort.toString()) + parser.setValue("Default Server", "${Networking.defaultServerHost}:${Networking.defaultServerPort}") + + // OverlayVisibility + parser.setValue("Server Speed", OverlayVisibility.serverSpeed.toString()) + parser.setValue("Foul Overlay", OverlayVisibility.foulOverlay.toString()) + parser.setValue("Field Overlay", OverlayVisibility.fieldOverlay.toString()) + parser.setValue("Number of Players", OverlayVisibility.numberOfPlayers.toString()) + parser.setValue("Player IDs", OverlayVisibility.playerIDs.toString()) + + // team colors + TeamColors.byTeamNames.forEach { + parser.setValue(it.key, "0x${Integer.toHexString(it.value.rgb and 0xFFFFFF)}") + } + } + +} diff --git a/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/ConfigParser.kt b/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/ConfigParser.kt new file mode 100644 index 00000000..9210c1fa --- /dev/null +++ b/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/ConfigParser.kt @@ -0,0 +1,138 @@ +package org.magmaoffenburg.roboviz.configuration + +import java.io.File + +class ConfigParser { + + val argsList = arrayListOf>() + val fileMap = hashMapOf() + + /** + * parse the args into a ArrayList, delimiter is "=" + */ + fun parseArgs(args: Array): List> { + argsList.clear() + + args.forEach { arg -> + if (arg.startsWith("--")) { + argsList.add(Pair(arg.substring(2).substringBefore("="), arg.substringAfter("="))) + } + } + + return argsList + } + + /** + * parse the config file into a HashMap, delimiter is ":" + */ + fun parseFile(path: String): HashMap { + fileMap.clear() + + File(path).forEachLine { line -> + if (line.trim().isNotEmpty() && !line.startsWith("#")) { + val pair = when { + line.startsWith("Team Color") -> { + val superKey = line.substringBefore(":").trim() + val key = line.substringBeforeLast(":").replaceBefore(":", "$superKey ") + val value = line.substringAfterLast(":") + + Pair(key.trim(), value.trim()) + } + line.substringBefore(":").trim() == "Server" -> { + val key = "${line.substringBefore(":").trim()} : ${line.substringAfter(":").trim()}" + val value = line.substringAfter(":").trim() + Pair(key, value) + } + else -> { + Pair(line.substringBefore(":").trim(), line.substringAfter(":").trim()) + } + } + + fileMap[pair.first] = pair.second + } + } + + return fileMap + } + + /** + * write the stored variables into the config file + */ + fun writeFile(path: String) { + val configFile = File(path) + + // read raw file + val rawFileList = configFile.readLines().toMutableList() + + fileMap.forEach { pair -> + when { + pair.key.startsWith("Team Color") -> { + val superKey = pair.key.replace("Team Color", "Team Color".padEnd(20)) + val index = rawFileList.indexOfFirst { line -> + line.startsWith(superKey) + } + rawFileList[index] = "$superKey:${pair.value}" + } + pair.key.startsWith("Server :") -> { + // only new servers will be added, existing servers can't be edited since there is no unique ID + val newLine = pair.key.replace("Server", "Server".padEnd(20)) + val index = rawFileList.indexOfFirst { line -> + line.startsWith(newLine) + } + + if (index >= 0) { + rawFileList[index] = newLine + } else { + // add a new server + val addIndex = rawFileList.indexOfLast { line -> + line.startsWith("${"Server".padEnd(20)} :") + } + rawFileList.add(addIndex + 1, newLine) + } + } + else -> { + val index = rawFileList.indexOfFirst { line -> + line.startsWith("${pair.key.padEnd(20)} :") + } + rawFileList[index] = "${pair.key.padEnd(20)} : ${pair.value}" + } + } + } + + val sb = StringBuilder() + rawFileList.forEach { line -> + sb.append(line) + sb.append("\n") + } + configFile.writeText(sb.toString()) + } + + /** + * get the value of a key + */ + fun getValue(key: String): String { + return if (fileMap.containsKey(key)) { + fileMap[key]!! + } else { + System.err.println("The key \"$key\" does not exist!") + "" + } + } + + /** + * set the value of a key + */ + fun setValue(key: String, value: String) { + fileMap[key] = value + } + + /** + * get all key value pairs, where the key starts with the superKey + */ + fun getValueSuperKey(superKey: String): List> { + return fileMap.filter { + it.key.startsWith(superKey) + }.entries.toList() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/ConfigurationController.kt b/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/ConfigurationController.kt deleted file mode 100644 index 383671f9..00000000 --- a/src/main/kotlin/org/magmaoffenburg/roboviz/configuration/ConfigurationController.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.magmaoffenburg.roboviz.configuration - -import rv.Configuration - -object ConfigurationController { - - val config: Configuration = Configuration.loadFromFile() - - val general: Configuration.General = config.general - val graphics: Configuration.Graphics = config.graphics - val networking: Configuration.Networking = config.networking - val overlayVisibility: Configuration.OverlayVisibility = config.overlayVisibility - val teamColors: Configuration.TeamColors = config.teamColors - -} \ No newline at end of file diff --git a/src/main/kotlin/org/magmaoffenburg/roboviz/rendering/ViewRenderer.kt b/src/main/kotlin/org/magmaoffenburg/roboviz/rendering/ViewRenderer.kt index 64fbe93f..9425f710 100644 --- a/src/main/kotlin/org/magmaoffenburg/roboviz/rendering/ViewRenderer.kt +++ b/src/main/kotlin/org/magmaoffenburg/roboviz/rendering/ViewRenderer.kt @@ -18,10 +18,9 @@ import jsgl.jogl.view.Camera3D import jsgl.jogl.view.Viewport import org.magmaoffenburg.roboviz.Main import org.magmaoffenburg.roboviz.MainWindow -import org.magmaoffenburg.roboviz.configuration.ConfigurationController -import org.magmaoffenburg.roboviz.configuration.ConfigurationController.graphics +import org.magmaoffenburg.roboviz.configuration.Config.Graphics +import org.magmaoffenburg.roboviz.configuration.Config.TeamColors import org.magmaoffenburg.roboviz.util.DataTypes -import rv.Configuration import rv.comm.NetworkManager import rv.comm.drawing.Drawings import rv.comm.rcssserver.LogPlayer @@ -89,13 +88,13 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he glInfo = GLInfo(gl) - contentManager = ContentManager(ConfigurationController.teamColors) + contentManager = ContentManager(TeamColors) if (!contentManager.init(drawable, glInfo)) { System.err.println("Problems loading resource files!") } world = WorldModel() - world.init(gl, contentManager, ConfigurationController.config, Main.mode) + world.init(gl, contentManager, Main.mode) drawings = Drawings() @@ -106,14 +105,14 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he activeScreen = if (Main.mode == DataTypes.Mode.LIVE) { netManager = NetworkManager() - netManager.init(ConfigurationController.config) + netManager.init() netManager.server.addChangeListener(world.gameState) netManager.server.addChangeListener(MainWindow.instance) LiveGameScreen() } else { if (!isInitialized) { val helperFile = File("") // - logPlayer = LogPlayer(helperFile, world, ConfigurationController.config) + logPlayer = LogPlayer(helperFile, world) //logPlayer.addListener(this) // TODO //logfileChanged() } else logPlayer.setWorldModel(world) @@ -121,7 +120,7 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he } activeScreen.setEnabled(MainWindow.glCanvas, true) - gl?.let { initEffects(gl, graphics) } + gl?.let { initEffects(gl, Graphics) } if (isInitialized && oldSceneGraph != null) { world.sceneGraph = oldSceneGraph @@ -161,12 +160,12 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he // Renderer.render() synchronized(world) { val gl2 = drawable.gl.gL2 - if (graphics.useShadows) { + if (Graphics.useShadows) { val shadowRenderer = effectManager.shadowRenderer shadowRenderer.render(gl2, world, drawings) } - if (graphics.useStereo) { + if (Graphics.useStereo) { vantage?.applyLeft(gl2, glu, screen) gl2?.glDrawBuffer(GL2.GL_BACK_LEFT) gl2?.glClear(GL.GL_COLOR_BUFFER_BIT or GL.GL_DEPTH_BUFFER_BIT) @@ -203,7 +202,7 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he override fun reshape(drawable: GLAutoDrawable?, x: Int, y: Int, width: Int, height: Int) { super.reshape(drawable, x, y, width, height) - if (graphics.useBloom || graphics.useShadows) { + if (Graphics.useBloom || Graphics.useShadows) { sceneFBO?.dispose(drawable!!.gl) msSceneFBO?.dispose(drawable!!.gl) genFBO(drawable!!.gl.gL2, screen) @@ -226,7 +225,7 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he * This is the former Renderer.init() * Initialize effects (FSAA, Bool, VSync) */ - private fun initEffects(gl: GL, graphics: Configuration.Graphics) { + private fun initEffects(gl: GL, graphics: Graphics) { val supportAAFBO = glInfo.extSupported("GL_EXT_framebuffer_multisample") && glInfo.extSupported("GL_EXT_framebuffer_blit") if (graphics.useFsaa && !supportAAFBO) println("Warning: no support for FSAA while bloom enabled") @@ -252,12 +251,12 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he private fun selectRenderer(gl: GL2, cm: ContentManager) { while (sceneRenderer == null) { sceneRenderer = when { - graphics.useShadows -> VSMPhongWorldRenderer(effectManager) - graphics.usePhong -> PhongWorldRenderer() + Graphics.useShadows -> VSMPhongWorldRenderer(effectManager) + Graphics.usePhong -> PhongWorldRenderer() else -> BasicSceneRenderer() } - if (!sceneRenderer!!.init(gl, graphics, cm)) { + if (!sceneRenderer!!.init(gl, Graphics, cm)) { System.err.println("Could not initialize $sceneRenderer") sceneRenderer = null } @@ -274,7 +273,7 @@ class ViewRenderer : GLProgram(MainWindow.instance.width, MainWindow.instance.he } private fun drawScene(gl: GL2) { - if (graphics.useBloom) { + if (Graphics.useBloom) { if (msSceneFBO != null) { msSceneFBO!!.bind(gl) msSceneFBO!!.clear(gl)