diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a1c2a23
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a3191c5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Noah Ortega
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/NMSVRScreenshotFix.java b/NMSVRScreenshotFix.java
new file mode 100644
index 0000000..264f2fd
--- /dev/null
+++ b/NMSVRScreenshotFix.java
@@ -0,0 +1,287 @@
+
+package nmsvrscreenshotfix;
+
+import java.io.IOException;
+import java.io.File;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+import java.awt.Graphics2D;
+import static java.lang.Character.isLetterOrDigit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Iterates through every image in the executable's folder and if applicable,
+ * creates a copy of it with an aspect ratio to 1:1
+ * @author Noah Ortega
+ */
+public class NMSVRScreenshotFix {
+
+ public static void main(String[] args) {
+ LogicController.getInstance();
+ }
+}
+
+class LogicController {
+
+ public boolean isExecuting = false;
+ public boolean canceled = false;
+
+ private int totalFiles;
+ private int converted;
+ private BufferedImage curImage;
+
+ public String sourcePath;
+ public String resultPath;
+
+ public boolean shouldRename = true;
+ public boolean renameNewFile = true;
+ public String addToFile = "_fix";
+ public boolean addAsPrefix = false;
+
+ ProgramUI myUI;
+
+ //singleton
+ private static LogicController sharedController = null;
+ private LogicController() {
+ launchUI();
+ sourcePath = System.getProperty("user.dir");
+ resultPath = System.getProperty("user.dir");
+ }
+ public static LogicController getInstance() {
+ if(sharedController == null) {
+ sharedController = new LogicController();
+ }
+ return sharedController;
+ }
+
+
+ private void launchUI() {
+ /* Set the Nimbus look and feel */
+ //
+ /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
+ * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
+ */
+ try {
+ for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
+ if ("Nimbus".equals(info.getName())) {
+ javax.swing.UIManager.setLookAndFeel(info.getClassName());
+ break;
+ }
+ }
+ } catch (ClassNotFoundException ex) {
+ java.util.logging.Logger.getLogger(ProgramUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (InstantiationException ex) {
+ java.util.logging.Logger.getLogger(ProgramUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (IllegalAccessException ex) {
+ java.util.logging.Logger.getLogger(ProgramUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ } catch (javax.swing.UnsupportedLookAndFeelException ex) {
+ java.util.logging.Logger.getLogger(ProgramUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ }
+ //
+ //
+ //
+ //
+
+ /* Create and display the form */
+ java.awt.EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ myUI = new ProgramUI();
+ myUI.setVisible(true);
+ }
+ });
+ }
+
+ /**
+ * Iterates through the files in the directory, validates files before
+ * allowing resizing.
+ */
+ public void execute() {
+ System.out.println("starting");
+ isExecuting = true;
+ canceled = false;
+ myUI.updateProgressBar(0);
+ converted = 0;
+
+ File sourceFolder = new File(sourcePath); //file of originals
+ File destFolder = new File(resultPath); //destination files
+
+ File[] folderContents = sourceFolder.listFiles();
+ totalFiles = folderContents.length;
+ File curFile;
+
+
+ for (int fileIndex = 0; fileIndex < totalFiles && !canceled; fileIndex++) {
+ curFile = folderContents[fileIndex];
+ if (!folderContents[fileIndex].isDirectory() && isImage(curFile.getPath())) {
+ System.out.println(fileIndex);
+ //System.out.println(curFile.getPath());
+ try {
+ curImage = ImageIO.read(folderContents[fileIndex]);
+ if (shouldResize(curImage.getWidth(), curImage.getHeight())) {
+ squish(curFile);
+ converted++;
+ }
+ }
+ catch (IOException ex) {
+ System.err.println(">> Caught IOException on '" + curFile.getPath() + "':\n " + ex.getMessage());
+ }
+ }
+ myUI.updateProgressBar((fileIndex + 1)*100/totalFiles);
+ }
+ if(canceled) {myUI.cancelPopup(converted);}
+ else {myUI.successPopup(converted);}
+
+ isExecuting = false;
+ System.out.println("finished");
+ }
+
+ /**
+ * Resizes an image to a 1:1 aspect ratio by changing the width
+ * @param originalFile Path of the original input image
+ * @throws java.io.IOException
+ *
+ * based on code by Nam Ha Minh from article "How to resize images in Java"
+ * https://www.codejava.net/java-se/graphics/how-to-resize-images-in-java
+ */
+ private void squish(File originalFile) throws IOException {
+ int newWidth = curImage.getHeight();
+ int height = curImage.getHeight();
+ // creates output image
+ BufferedImage outputImage = new BufferedImage(newWidth, height, curImage.getType());
+
+ // scales the input image to the output image
+ Graphics2D g2d = outputImage.createGraphics();
+ g2d.drawImage(curImage, 0, 0, newWidth, height, null);
+ g2d.dispose();
+
+ int fileDotIndex = originalFile.getName().lastIndexOf('.');
+ String formatName = originalFile.getName().substring(fileDotIndex + 1);
+
+ File newFile = new File(resultPath +"/"+ originalFile.getName());
+ if(shouldRename) {
+ if (renameNewFile) {
+ newFile = modifyFilePath(resultPath,originalFile.getName());
+ }
+ else {
+ originalFile.renameTo(modifyFilePath(sourcePath,originalFile.getName()));
+ }
+ }
+ // write to output file
+ ImageIO.write(outputImage, formatName, newFile);
+
+ System.out.println(">> Converted");
+ }
+
+ public void cancelExecution() {
+ canceled = true;
+ }
+
+ public String getCurrentBehavior() {
+ String behavior = "";
+ if(!shouldRename && (sourcePath.equals(resultPath))) {
+ behavior += "• Replacing originals with converted screenshots";
+ }
+ else {
+ behavior += "• Making copies of converted screenshots";
+ }
+
+ behavior +="\n";
+ if(shouldRename) {
+ if(addAsPrefix) {
+ behavior += "• Adding prefix ";
+ }
+ else {
+ behavior += "• Adding suffix ";
+ }
+ behavior += "\""+addToFile+"\" to ";
+ if(renameNewFile) {
+ behavior += "converted image";
+ }
+ else {
+ behavior += "original image";
+ }
+ behavior += "\n";
+ behavior += "• " + getExampleRename();
+ }
+ return behavior;
+ }
+
+ private String getRename(String oldName) {
+ int dotIndex = oldName.lastIndexOf('.');
+
+ String name = oldName.substring(0, dotIndex);
+ String ext = oldName.substring(dotIndex);
+
+ return addAsPrefix ? (addToFile+name+ext) : (name+addToFile+ext);
+ }
+
+ private String getExampleRename() {
+ String exampleName = renameNewFile ? "converted.png" : "original.png";
+ return ("Ex: \"" + exampleName + "\" -> \"" + getRename(exampleName) +"\"");
+ }
+
+ private File modifyFilePath(String parentPath, String fileName) {
+ return (new File(parentPath + "/" + getRename(fileName)));
+ }
+
+ /**
+ * Determines if a file is a basic image type
+ * @param path file path of image
+ * @return true if extension is png jpg or jpeg
+ */
+ private boolean isImage(String path) {
+ //extention of file, from file after final period
+ int dotIndex = path.lastIndexOf('.');
+ String extension = (dotIndex == -1) ? "no extension" : path.substring(dotIndex + 1);
+ extension = extension.toLowerCase();
+ return (extension.equals("png") || extension.equals("jpg") || extension.equals("jpeg"));
+ }
+
+ /**
+ * Determines if an image should be resized based on criteria:
+ * - width must be greater than height
+ * @param width image width
+ * @param height image height
+ * @return true if image matches criteria
+ */
+ private boolean shouldResize(int width, int height) {
+ if (width == height) {
+ System.out.println(">> Already 1:1 aspect ratio");
+ return false;
+ } else if (width < height) {
+ System.out.println(">> Height is greater than width");
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * For generating the path of the output image
+ * @param inputPath Path of the original input image
+ * @param dotIndex the index of the dot in the input path
+ * @return the final output path
+ */
+ public String generateOutputPath(String inputPath, int dotIndex) {
+
+ return inputPath.substring(0, dotIndex) + addToFile + inputPath.substring(dotIndex);
+ }
+
+ public boolean isValidAddition(String phrase) {
+
+ for (int charIndex = 0; charIndex < phrase.length(); charIndex++) {
+ char curChar = phrase.charAt(charIndex);
+ if(!isLetterOrDigit(curChar)) {
+ if(curChar != '_' && curChar != '-') {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean hasValidDirectoryPaths() {
+ return((new File(sourcePath)).isDirectory() && (new File(resultPath)).isDirectory());
+ }
+}
\ No newline at end of file
diff --git a/ProgramUI.form b/ProgramUI.form
new file mode 100644
index 0000000..d6418a2
--- /dev/null
+++ b/ProgramUI.form
@@ -0,0 +1,210 @@
+
+
+
diff --git a/ProgramUI.java b/ProgramUI.java
new file mode 100644
index 0000000..41ca483
--- /dev/null
+++ b/ProgramUI.java
@@ -0,0 +1,278 @@
+
+package nmsvrscreenshotfix;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+
+
+public class ProgramUI extends javax.swing.JFrame {
+
+ LogicController controller = LogicController.getInstance();
+
+ public ProgramUI() {
+ initComponents();
+ resultFolderField.setText(controller.resultPath);
+ sourceFolderField.setText(controller.sourcePath);
+ behaviorTextArea.setText(controller.getCurrentBehavior());
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ jPanel3 = new javax.swing.JPanel();
+ jLabel2 = new javax.swing.JLabel();
+ jLabel1 = new javax.swing.JLabel();
+ jLabel3 = new javax.swing.JLabel();
+ sourceFolderField = new javax.swing.JTextField();
+ sourceFolderButton = new javax.swing.JButton();
+ resultFolderField = new javax.swing.JTextField();
+ resultFolderButton = new javax.swing.JButton();
+ jScrollPane2 = new javax.swing.JScrollPane();
+ behaviorTextArea = new javax.swing.JTextArea();
+ settingsButton = new javax.swing.JButton();
+ executeButton = new javax.swing.JButton();
+ progressBar = new javax.swing.JProgressBar();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setTitle("NMS VR Screenshot Fix");
+ setResizable(false);
+
+ jLabel2.setText("Source Folder:");
+
+ jLabel1.setText("Behavior:");
+ jLabel1.setVerticalAlignment(javax.swing.SwingConstants.TOP);
+
+ jLabel3.setText("Result Folder:");
+
+ sourceFolderField.setText("err");
+ sourceFolderField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ sourceFolderFieldActionPerformed(evt);
+ }
+ });
+
+ sourceFolderButton.setText("...");
+ sourceFolderButton.setMaximumSize(new java.awt.Dimension(22, 22));
+ sourceFolderButton.setMinimumSize(new java.awt.Dimension(22, 22));
+ sourceFolderButton.setPreferredSize(new java.awt.Dimension(32, 32));
+ sourceFolderButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ sourceFolderButtonActionPerformed(evt);
+ }
+ });
+
+ resultFolderField.setText("err");
+ resultFolderField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ resultFolderFieldActionPerformed(evt);
+ }
+ });
+
+ resultFolderButton.setText("...");
+ resultFolderButton.setMaximumSize(new java.awt.Dimension(22, 22));
+ resultFolderButton.setMinimumSize(new java.awt.Dimension(22, 22));
+ resultFolderButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ resultFolderButtonActionPerformed(evt);
+ }
+ });
+
+ behaviorTextArea.setEditable(false);
+ behaviorTextArea.setColumns(20);
+ behaviorTextArea.setLineWrap(true);
+ behaviorTextArea.setRows(5);
+ behaviorTextArea.setText("• Make copies of converted screenshots\n• Add prefix \" new_\" to the new image\n• Ex: \"image.png\" -> \"new_image.png\"\n");
+ jScrollPane2.setViewportView(behaviorTextArea);
+
+ settingsButton.setText("Behavior Settings");
+ settingsButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ settingsButtonActionPerformed(evt);
+ }
+ });
+
+ executeButton.setText("Execute");
+ executeButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ executeButtonActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
+ jPanel3.setLayout(jPanel3Layout);
+ jPanel3Layout.setHorizontalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
+ .addComponent(executeButton)
+ .addComponent(jLabel3)
+ .addComponent(jLabel2)
+ .addComponent(jLabel1))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 318, Short.MAX_VALUE)
+ .addComponent(settingsButton)
+ .addComponent(sourceFolderField)
+ .addComponent(resultFolderField)
+ .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(sourceFolderButton, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(resultFolderButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGap(273, 273, 273))
+ );
+ jPanel3Layout.setVerticalGroup(
+ jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel3Layout.createSequentialGroup()
+ .addGap(23, 23, 23)
+ .addComponent(sourceFolderButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(sourceFolderField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))))
+ .addGap(17, 17, 17)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(resultFolderButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(resultFolderField, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(settingsButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(executeButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addGap(12, 12, 12))
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, 462, javax.swing.GroupLayout.PREFERRED_SIZE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void executeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_executeButtonActionPerformed
+ if(controller.isExecuting) {
+ controller.cancelExecution();
+ toggleUI();
+ }
+ else {
+ controller.sourcePath = sourceFolderField.getText();
+ controller.resultPath = resultFolderField.getText();
+ if (controller.hasValidDirectoryPaths()) {
+ controller.execute();
+ toggleUI();
+ }
+ else {
+ JOptionPane.showMessageDialog(this,
+ "One of the paths appears to not be a valid folder","Error",
+ JOptionPane.WARNING_MESSAGE);
+ }
+ }
+ }//GEN-LAST:event_executeButtonActionPerformed
+
+ private void toggleUI() {
+ boolean shouldEnable = !controller.isExecuting;
+ settingsButton.setEnabled(shouldEnable);
+ sourceFolderField.setEnabled(shouldEnable);
+ sourceFolderButton.setEnabled(shouldEnable);
+ resultFolderField.setEnabled(shouldEnable);
+ resultFolderButton.setEnabled(shouldEnable);
+
+ if(controller.isExecuting) {executeButton.setText("cancel");}
+ else {executeButton.setText("execute");}
+ }
+
+ private void settingsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_settingsButtonActionPerformed
+ new SettingsUI(this,true).setVisible(true);
+ behaviorTextArea.setText(controller.getCurrentBehavior());
+ }//GEN-LAST:event_settingsButtonActionPerformed
+
+ private void sourceFolderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sourceFolderButtonActionPerformed
+ JFileChooser jfc = new JFileChooser();
+ jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int optionCode = jfc.showSaveDialog(null);
+
+ if (optionCode == JFileChooser.APPROVE_OPTION) {
+ controller.sourcePath = jfc.getSelectedFile().getAbsolutePath();
+ sourceFolderField.setText(controller.sourcePath);
+ behaviorTextArea.setText(controller.getCurrentBehavior());
+ }
+ }//GEN-LAST:event_sourceFolderButtonActionPerformed
+
+ private void resultFolderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultFolderButtonActionPerformed
+ JFileChooser jfc = new JFileChooser();
+ jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int optionCode = jfc.showSaveDialog(null);
+
+ if (optionCode == JFileChooser.APPROVE_OPTION) {
+ controller.resultPath = jfc.getSelectedFile().getAbsolutePath();
+ resultFolderField.setText(controller.resultPath);
+ behaviorTextArea.setText(controller.getCurrentBehavior());
+ }
+ }//GEN-LAST:event_resultFolderButtonActionPerformed
+
+ private void sourceFolderFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sourceFolderFieldActionPerformed
+ controller.sourcePath = sourceFolderField.getText();
+ behaviorTextArea.setText(controller.getCurrentBehavior());
+ }//GEN-LAST:event_sourceFolderFieldActionPerformed
+
+ private void resultFolderFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resultFolderFieldActionPerformed
+ controller.resultPath = resultFolderField.getText();
+ behaviorTextArea.setText(controller.getCurrentBehavior());
+ }//GEN-LAST:event_resultFolderFieldActionPerformed
+
+ public void updateProgressBar(int value) {
+ progressBar.setValue(value);
+ }
+
+ public void successPopup(int value) {
+ JOptionPane.showMessageDialog(this,
+ ("Converted " + value + " images successfully."),"Complete",
+ JOptionPane.INFORMATION_MESSAGE);
+ progressBar.setValue(0);
+ }
+
+ public void cancelPopup(int value) {
+ JOptionPane.showMessageDialog(this,
+ "Converted " + value + " files before canceling.","Canceled",
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JTextArea behaviorTextArea;
+ private javax.swing.JButton executeButton;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel3;
+ private javax.swing.JPanel jPanel3;
+ private javax.swing.JScrollPane jScrollPane2;
+ private javax.swing.JProgressBar progressBar;
+ private javax.swing.JButton resultFolderButton;
+ private javax.swing.JTextField resultFolderField;
+ private javax.swing.JButton settingsButton;
+ private javax.swing.JButton sourceFolderButton;
+ private javax.swing.JTextField sourceFolderField;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1985832
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# NMS-VR-Screenshot-Fix
+ By default, No Man's Sky VR takes screenshots that appear stretched. By changing their aspect ratio to 1:1 the shots look much more natural. To automate this solution, this program makes 1:1 aspect ratio copies of images.
diff --git a/SettingsUI.form b/SettingsUI.form
new file mode 100644
index 0000000..a6803d6
--- /dev/null
+++ b/SettingsUI.form
@@ -0,0 +1,267 @@
+
+
+
diff --git a/SettingsUI.java b/SettingsUI.java
new file mode 100644
index 0000000..1372f11
--- /dev/null
+++ b/SettingsUI.java
@@ -0,0 +1,327 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package nmsvrscreenshotfix;
+
+import java.awt.Component;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+/**
+ *
+ * @author midli
+ */
+public class SettingsUI extends javax.swing.JDialog {
+
+ LogicController controller = LogicController.getInstance();
+
+
+ public SettingsUI(java.awt.Frame parent, boolean modal) {
+ super(parent, modal);
+ initComponents();
+
+ if(controller.shouldRename) {renameButton.setSelected(true);}
+ else {dontRenameButton.setSelected(true);}
+ if(controller.renameNewFile) {renameNewButton.setSelected(true);}
+ else {renameOriginalButton.setSelected(true);}
+ addTextField.setText(controller.addToFile);
+ if(controller.addAsPrefix) {prefixButton.setSelected(true);}
+ else {suffixButton.setSelected(true);}
+
+ if(dontRenameButton.isSelected()) {disableRenamePanel(newFileSettings);}
+
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ replaceOrCopyGroup = new javax.swing.ButtonGroup();
+ renameWhichGroup = new javax.swing.ButtonGroup();
+ prefixOrSuffix = new javax.swing.ButtonGroup();
+ jPanel1 = new javax.swing.JPanel();
+ dontRenameButton = new javax.swing.JRadioButton();
+ renameButton = new javax.swing.JRadioButton();
+ jLabel1 = new javax.swing.JLabel();
+ jSeparator1 = new javax.swing.JSeparator();
+ ConfirmButton = new javax.swing.JButton();
+ newFileSettings = new javax.swing.JPanel();
+ renameNewButton = new javax.swing.JRadioButton();
+ renameOriginalButton = new javax.swing.JRadioButton();
+ jLabel6 = new javax.swing.JLabel();
+ jLabel7 = new javax.swing.JLabel();
+ prefixButton = new javax.swing.JRadioButton();
+ suffixButton = new javax.swing.JRadioButton();
+ jLabel8 = new javax.swing.JLabel();
+ addTextField = new javax.swing.JTextField();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setTitle("Settings");
+ setModal(true);
+ setResizable(false);
+
+ replaceOrCopyGroup.add(dontRenameButton);
+ dontRenameButton.setText("Keep Same Names");
+ dontRenameButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ dontRenameButtonActionPerformed(evt);
+ }
+ });
+
+ replaceOrCopyGroup.add(renameButton);
+ renameButton.setText("Edit File Names");
+ renameButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ renameButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel1.setText("Rename files?");
+
+ ConfirmButton.setText("confirm");
+ ConfirmButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ ConfirmButtonActionPerformed(evt);
+ }
+ });
+
+ renameWhichGroup.add(renameNewButton);
+ renameNewButton.setText("Converted File");
+ renameNewButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ renameNewButtonActionPerformed(evt);
+ }
+ });
+
+ renameWhichGroup.add(renameOriginalButton);
+ renameOriginalButton.setText("Original File");
+ renameOriginalButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ renameOriginalButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel6.setText("Rename which file?");
+
+ jLabel7.setText("Add as a prefix or suffix?");
+
+ prefixOrSuffix.add(prefixButton);
+ prefixButton.setText("Add Prefix");
+ prefixButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ prefixButtonActionPerformed(evt);
+ }
+ });
+
+ prefixOrSuffix.add(suffixButton);
+ suffixButton.setText("Add Suffix");
+ suffixButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ suffixButtonActionPerformed(evt);
+ }
+ });
+
+ jLabel8.setText("Text to be added:");
+
+ addTextField.setText("_new");
+ addTextField.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ addTextFieldActionPerformed(evt);
+ }
+ });
+
+ javax.swing.GroupLayout newFileSettingsLayout = new javax.swing.GroupLayout(newFileSettings);
+ newFileSettings.setLayout(newFileSettingsLayout);
+ newFileSettingsLayout.setHorizontalGroup(
+ newFileSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, newFileSettingsLayout.createSequentialGroup()
+ .addGroup(newFileSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jLabel7)
+ .addComponent(jLabel8)
+ .addComponent(jLabel6)
+ .addComponent(renameOriginalButton)
+ .addComponent(prefixButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(newFileSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(renameNewButton)
+ .addComponent(suffixButton))
+ .addGap(35, 35, 35))
+ .addGroup(newFileSettingsLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(addTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addContainerGap(23, Short.MAX_VALUE))
+ );
+ newFileSettingsLayout.setVerticalGroup(
+ newFileSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, newFileSettingsLayout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(jLabel6)
+ .addGap(2, 2, 2)
+ .addGroup(newFileSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(renameOriginalButton)
+ .addComponent(renameNewButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jLabel8)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(addTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(jLabel7)
+ .addGap(4, 4, 4)
+ .addGroup(newFileSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
+ .addComponent(prefixButton)
+ .addComponent(suffixButton))
+ .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ );
+
+ javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+ jPanel1.setLayout(jPanel1Layout);
+ jPanel1Layout.setHorizontalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGap(27, 27, 27)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 321, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGap(6, 6, 6)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
+ .addComponent(jLabel1)
+ .addComponent(newFileSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addComponent(dontRenameButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(renameButton)
+ .addGap(35, 35, 35))))))
+ .addGroup(jPanel1Layout.createSequentialGroup()
+ .addGap(145, 145, 145)
+ .addComponent(ConfirmButton)))
+ .addContainerGap(20, Short.MAX_VALUE))
+ );
+ jPanel1Layout.setVerticalGroup(
+ jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
+ .addGap(20, 20, 20)
+ .addComponent(jLabel1)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(dontRenameButton)
+ .addComponent(renameButton))
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(newFileSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(ConfirmButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addContainerGap())
+ );
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+ getContentPane().setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ );
+
+ pack();
+ }// //GEN-END:initComponents
+
+ private void dontRenameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dontRenameButtonActionPerformed
+ disableRenamePanel(newFileSettings);
+ controller.shouldRename = false;
+ }//GEN-LAST:event_dontRenameButtonActionPerformed
+
+ private void renameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renameButtonActionPerformed
+ enableRenamePanel(newFileSettings);
+ controller.shouldRename = true;
+ }//GEN-LAST:event_renameButtonActionPerformed
+
+ private void ConfirmButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ConfirmButtonActionPerformed
+ if (controller.isValidAddition(addTextField.getText())) {
+ controller.addToFile = addTextField.getText();
+ this.setVisible(false);
+ }
+ else {
+ JOptionPane.showMessageDialog(this,
+ "Text can only contain alphanumeric characters, '_' and '-'.","Error",
+ JOptionPane.WARNING_MESSAGE);
+ }
+ }//GEN-LAST:event_ConfirmButtonActionPerformed
+
+ private void renameNewButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renameNewButtonActionPerformed
+ controller.renameNewFile = true;
+ }//GEN-LAST:event_renameNewButtonActionPerformed
+
+ private void prefixButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_prefixButtonActionPerformed
+ controller.addAsPrefix = true;
+ }//GEN-LAST:event_prefixButtonActionPerformed
+
+ private void addTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTextFieldActionPerformed
+ // no action
+ }//GEN-LAST:event_addTextFieldActionPerformed
+
+ private void renameOriginalButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_renameOriginalButtonActionPerformed
+ controller.renameNewFile = false;
+ }//GEN-LAST:event_renameOriginalButtonActionPerformed
+
+ private void suffixButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_suffixButtonActionPerformed
+ controller.addAsPrefix = false;
+ }//GEN-LAST:event_suffixButtonActionPerformed
+
+ private void disableRenamePanel(JPanel panel){
+ panel.setEnabled(false);
+ Component[] components = panel.getComponents();
+
+ for (Component component : components) {
+ if (component instanceof JPanel) {
+ disableRenamePanel((JPanel) component);
+ }
+ component.setEnabled(false);
+ }
+ }
+
+ private void enableRenamePanel(JPanel panel){
+ panel.setEnabled(true);
+ Component[] components = panel.getComponents();
+
+ for (Component component : components) {
+ if (component instanceof JPanel) {
+ disableRenamePanel((JPanel) component);
+ }
+ component.setEnabled(true);
+ }
+ }
+
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton ConfirmButton;
+ private javax.swing.JTextField addTextField;
+ private javax.swing.JRadioButton dontRenameButton;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel6;
+ private javax.swing.JLabel jLabel7;
+ private javax.swing.JLabel jLabel8;
+ private javax.swing.JPanel jPanel1;
+ private javax.swing.JSeparator jSeparator1;
+ private javax.swing.JPanel newFileSettings;
+ private javax.swing.JRadioButton prefixButton;
+ private javax.swing.ButtonGroup prefixOrSuffix;
+ private javax.swing.JRadioButton renameButton;
+ private javax.swing.JRadioButton renameNewButton;
+ private javax.swing.JRadioButton renameOriginalButton;
+ private javax.swing.ButtonGroup renameWhichGroup;
+ private javax.swing.ButtonGroup replaceOrCopyGroup;
+ private javax.swing.JRadioButton suffixButton;
+ // End of variables declaration//GEN-END:variables
+}