diff options
author | Loren <47842483+sornerol@users.noreply.github.com> | 2022-07-06 11:42:40 -0500 |
---|---|---|
committer | rafa_99 <raroma09@gmail.com> | 2022-07-10 21:24:13 +0100 |
commit | b8f4accb0da92aa786c0da1d22fcf307aa11d618 (patch) | |
tree | ef13df016ed93fc0a9837110fea1816f29628a30 | |
parent | c96c5028316877a8a764da7fdba4b56904e393d5 (diff) |
Batch randomization (#477)
6 files changed, 619 insertions, 30 deletions
diff --git a/src/com/sneed/pkrandom/BatchRandomizationSettings.java b/src/com/sneed/pkrandom/BatchRandomizationSettings.java new file mode 100644 index 0000000..97ae6f2 --- /dev/null +++ b/src/com/sneed/pkrandom/BatchRandomizationSettings.java @@ -0,0 +1,126 @@ +package com.sneed.pkrandom; + +/*----------------------------------------------------------------------------*/ +/*-- BatchRandomizationSettings.java - handles functionality related to --*/ +/*-- batch randomization. --*/ +/*-- --*/ +/*-- Part of "Universal Pokemon Randomizer ZX" by the UPR-ZX team --*/ +/*-- Originally part of "Universal Pokemon Randomizer" by sneed --*/ +/*-- Pokemon and any associated names and the like are --*/ +/*-- trademark and (C) Nintendo 1996-2020. --*/ +/*-- --*/ +/*-- The custom code written here is licensed under the terms of the GPL: --*/ +/*-- --*/ +/*-- This program is free software: you can redistribute it and/or modify --*/ +/*-- it under the terms of the GNU General Public License as published by --*/ +/*-- the Free Software Foundation, either version 3 of the License, or --*/ +/*-- (at your option) any later version. --*/ +/*-- --*/ +/*-- This program is distributed in the hope that it will be useful, --*/ +/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/ +/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/ +/*-- GNU General Public License for more details. --*/ +/*-- --*/ +/*-- You should have received a copy of the GNU General Public License --*/ +/*-- along with this program. If not, see <http://www.gnu.org/licenses/>. --*/ +/*----------------------------------------------------------------------------*/ + +import java.util.StringJoiner; + +public class BatchRandomizationSettings implements Cloneable { + private Boolean batchRandomizationEnabled; + private Boolean generateLogFile; + private Boolean autoAdvanceStartingIndex; + private Integer numberOfRandomizedROMs; + private Integer startingIndex; + private String fileNamePrefix; + private String outputDirectory; + + public BatchRandomizationSettings() { + batchRandomizationEnabled = false; + generateLogFile = false; + autoAdvanceStartingIndex = true; + numberOfRandomizedROMs = 10; + startingIndex = 0; + fileNamePrefix = "random"; + outputDirectory = SysConstants.ROOT_PATH; + } + + public boolean isBatchRandomizationEnabled() { + return batchRandomizationEnabled; + } + + public void setBatchRandomizationEnabled(boolean batchRandomizationEnabled) { + this.batchRandomizationEnabled = batchRandomizationEnabled; + } + + public boolean shouldGenerateLogFile() { + return generateLogFile; + } + + public void setGenerateLogFile(boolean generateLogFile) { + this.generateLogFile = generateLogFile; + } + + public boolean shouldAutoAdvanceStartingIndex() { + return autoAdvanceStartingIndex; + } + + public void setAutoAdvanceStartingIndex(boolean autoAdvanceStartingIndex) { + this.autoAdvanceStartingIndex = autoAdvanceStartingIndex; + } + + public int getNumberOfRandomizedROMs() { + return numberOfRandomizedROMs; + } + + public void setNumberOfRandomizedROMs(int numberOfRandomizedROMs) { + this.numberOfRandomizedROMs = numberOfRandomizedROMs; + } + + public int getStartingIndex() { + return startingIndex; + } + + public void setStartingIndex(int startingIndex) { + this.startingIndex = startingIndex; + } + + public String getFileNamePrefix() { + return fileNamePrefix; + } + + public void setFileNamePrefix(String fileNamePrefix) { + this.fileNamePrefix = fileNamePrefix; + } + + public String getOutputDirectory() { + return outputDirectory; + } + + public void setOutputDirectory(String outputDirectory) { + this.outputDirectory = outputDirectory; + } + + @Override + public String toString() { + StringJoiner sj = new StringJoiner(SysConstants.LINE_SEP); + sj.add("batchrandomization.enabled=" + batchRandomizationEnabled.toString()); + sj.add("batchrandomization.generatelogfiles=" + generateLogFile.toString()); + sj.add("batchrandomization.autoadvanceindex=" + autoAdvanceStartingIndex.toString()); + sj.add("batchrandomization.numberofrandomizedroms=" + numberOfRandomizedROMs.toString()); + sj.add("batchrandomization.startingindex=" + startingIndex.toString()); + sj.add("batchrandomization.filenameprefix=" + fileNamePrefix); + sj.add("batchrandomization.outputdirectory=" + outputDirectory); + return sj.toString(); + } + + @Override + public BatchRandomizationSettings clone() { + try { + return (BatchRandomizationSettings) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} diff --git a/src/com/sneed/pkrandom/newgui/BatchRandomizationSettingsDialog.form b/src/com/sneed/pkrandom/newgui/BatchRandomizationSettingsDialog.form new file mode 100644 index 0000000..37c712e --- /dev/null +++ b/src/com/sneed/pkrandom/newgui/BatchRandomizationSettingsDialog.form @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="UTF-8"?> +<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.sneed.pkrandom.newgui.BatchRandomizationSettingsDialog"> + <grid id="6cce1" binding="mainPanel" layout-manager="GridBagLayout"> + <constraints> + <xy x="48" y="54" width="615" height="250"/> + </constraints> + <properties> + <minimumSize width="615" height="250"/> + <preferredSize width="615" height="250"/> + </properties> + <border type="none"/> + <children> + <grid id="94766" layout-manager="GridBagLayout"> + <constraints> + <grid row="7" column="1" row-span="1" col-span="3" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <maximumSize width="200" height="50"/> + <minimumSize width="200" height="50"/> + <preferredSize width="200" height="50"/> + </properties> + <border type="none"/> + <children> + <component id="e7465" class="javax.swing.JButton" binding="okButton"> + <constraints> + <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <maximumSize width="100" height="30"/> + <minimumSize width="100" height="30"/> + <preferredSize width="100" height="30"/> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.okButton.text"/> + </properties> + </component> + <component id="5723f" class="javax.swing.JButton" binding="cancelButton"> + <constraints> + <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="1.0"/> + </constraints> + <properties> + <maximumSize width="100" height="30"/> + <minimumSize width="100" height="30"/> + <opaque value="false"/> + <preferredSize width="100" height="30"/> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.cancelButton.text"/> + </properties> + </component> + </children> + </grid> + <hspacer id="46ba8"> + <constraints> + <grid row="0" column="0" row-span="8" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> + <gridbag weightx="1.0" weighty="0.0"/> + </constraints> + </hspacer> + <hspacer id="57384"> + <constraints> + <grid row="0" column="4" row-span="8" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> + <gridbag weightx="1.0" weighty="0.0"/> + </constraints> + </hspacer> + <component id="59655" class="javax.swing.JLabel"> + <constraints> + <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="1.0" weighty="0.0"/> + </constraints> + <properties> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.startingIndexLabel.text"/> + </properties> + </component> + <component id="c81ca" class="javax.swing.JTextField" binding="fileNamePrefixTextField"> + <constraints> + <grid row="4" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="0" indent="0" use-parent-layout="false"> + <preferred-size width="150" height="-1"/> + </grid> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <margin top="2" left="6" bottom="2" right="6"/> + <maximumSize width="160" height="30"/> + <minimumSize width="160" height="30"/> + <preferredSize width="160" height="30"/> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.fileNamePrefixTextBox.toolTipText"/> + </properties> + </component> + <component id="a4367" class="javax.swing.JLabel"> + <constraints> + <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="1.0" weighty="0.0"/> + </constraints> + <properties> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.fileNamePrefixLabel.text"/> + </properties> + </component> + <component id="e86c2" class="javax.swing.JLabel"> + <constraints> + <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="1.0" weighty="0.0"/> + </constraints> + <properties> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.numberOfRandomizedROMsLabel.text"/> + </properties> + </component> + <component id="3ee4c" class="javax.swing.JSpinner" binding="startingIndexSpinner"> + <constraints> + <grid row="1" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.startingIndexSpinner.toolTipText"/> + </properties> + </component> + <component id="76f06" class="javax.swing.JSpinner" binding="numberOfRandomizedROMsSpinner"> + <constraints> + <grid row="2" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.numberOfRandomizedROMsSpinner.toolTipText"/> + </properties> + </component> + <component id="f8d94" class="javax.swing.JCheckBox" binding="enableBatchRandomizationCheckBox"> + <constraints> + <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="9" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <alignmentY value="0.5"/> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.enableCheckBox.text"/> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.enableCheckBox.toolTipText"/> + </properties> + </component> + <component id="33deb" class="javax.swing.JButton" binding="chooseDirectoryButton"> + <constraints> + <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.5" weighty="0.0"/> + </constraints> + <properties> + <alignmentY value="0.0"/> + <inheritsPopupMenu value="true"/> + <label value="Output directory..."/> + <maximumSize width="165" height="30"/> + <minimumSize width="165" height="30"/> + <preferredSize width="165" height="30"/> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.outputDirectoryButton.text"/> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.outputDirectoryButton.toolTipText"/> + </properties> + </component> + <component id="52169" class="javax.swing.JLabel" binding="outputDirectoryLabel"> + <constraints> + <grid row="3" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="1.0" weighty="0.0"/> + </constraints> + <properties> + <maximumSize width="350" height="16"/> + <minimumSize width="350" height="16"/> + <preferredSize width="350" height="16"/> + <text value=""/> + </properties> + </component> + <component id="2d8de" class="javax.swing.JCheckBox" binding="generateLogFilesCheckBox"> + <constraints> + <grid row="6" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.generateLogFilesCheckBox.text"/> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.generateLogFilesCheckBox.toolTipText"/> + </properties> + </component> + <component id="ebf20" class="javax.swing.JCheckBox" binding="autoAdvanceIndexCheckBox"> + <constraints> + <grid row="5" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + <properties> + <text resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.autoAdvanceIndexCheckBox.text"/> + <toolTipText resource-bundle="com/sneed/pkrandom/newgui/Bundle" key="BatchRandomizationSettingsDialog.autoAdvanceIndexCheckBox.toolTipText"/> + </properties> + </component> + <hspacer id="ff006"> + <constraints> + <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> + <gridbag weightx="0.0" weighty="0.0"/> + </constraints> + </hspacer> + </children> + </grid> +</form> diff --git a/src/com/sneed/pkrandom/newgui/BatchRandomizationSettingsDialog.java b/src/com/sneed/pkrandom/newgui/BatchRandomizationSettingsDialog.java new file mode 100644 index 0000000..13e12e5 --- /dev/null +++ b/src/com/sneed/pkrandom/newgui/BatchRandomizationSettingsDialog.java @@ -0,0 +1,145 @@ +package com.sneed.pkrandom.newgui; + +/*----------------------------------------------------------------------------*/ +/*-- BatchRandomizationSettingsDialog.java - a dialog for configuring --*/ +/*-- batch randomization settings --*/ +/*-- --*/ +/*-- Part of "Universal Pokemon Randomizer ZX" by the UPR-ZX team --*/ +/*-- Originally part of "Universal Pokemon Randomizer" by sneed --*/ +/*-- Pokemon and any associated names and the like are --*/ +/*-- trademark and (C) Nintendo 1996-2020. --*/ +/*-- --*/ +/*-- The custom code written here is licensed under the terms of the GPL: --*/ +/*-- --*/ +/*-- This program is free software: you can redistribute it and/or modify --*/ +/*-- it under the terms of the GNU General Public License as published by --*/ +/*-- the Free Software Foundation, either version 3 of the License, or --*/ +/*-- (at your option) any later version. --*/ +/*-- --*/ +/*-- This program is distributed in the hope that it will be useful, --*/ +/*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/ +/*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/ +/*-- GNU General Public License for more details. --*/ +/*-- --*/ +/*-- You should have received a copy of the GNU General Public License --*/ +/*-- along with this program. If not, see <http://www.gnu.org/licenses/>. --*/ +/*----------------------------------------------------------------------------*/ + +import com.sneed.pkrandom.BatchRandomizationSettings; + +import javax.swing.*; +import java.awt.event.*; +import java.io.File; + +public class BatchRandomizationSettingsDialog extends JDialog { + private JPanel mainPanel; + private JButton okButton; + private JButton cancelButton; + private JCheckBox enableBatchRandomizationCheckBox; + private JSpinner numberOfRandomizedROMsSpinner; + private JSpinner startingIndexSpinner; + private JTextField fileNamePrefixTextField; + private JCheckBox generateLogFilesCheckBox; + private JCheckBox autoAdvanceIndexCheckBox; + private JButton chooseDirectoryButton; + private JLabel outputDirectoryLabel; + + private JFileChooser outputDirectoryFileChooser; + + private final BatchRandomizationSettings currentSettings; + + public BatchRandomizationSettings getCurrentSettings() { + return this.currentSettings; + } + + public BatchRandomizationSettingsDialog(JFrame parent, BatchRandomizationSettings currentSettings) { + super(parent, true); + add(mainPanel); + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/sneed/pkrandom/newgui/Bundle"); + setTitle(bundle.getString("BatchRandomizationSettingsDialog.title")); + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + getRootPane().setDefaultButton(okButton); + + this.currentSettings = currentSettings.clone(); + + initializeControls(); + setLocationRelativeTo(parent); + pack(); + setVisible(true); + } + + private void onOK() { + updateSettings(); + setVisible(false); + } + + private void onCancel() { + // add your code here if necessary + setVisible(false); + } + + private void initializeControls() { + outputDirectoryFileChooser = new JFileChooser(); + okButton.addActionListener(e -> onOK()); + cancelButton.addActionListener(e -> onCancel()); + + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + onCancel(); + } + }); + mainPanel.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + SpinnerNumberModel numberOfRandomizedROMsModel = new SpinnerNumberModel(1,1, Integer.MAX_VALUE, 1); + numberOfRandomizedROMsSpinner.setModel(numberOfRandomizedROMsModel); + + SpinnerNumberModel startingIndexModel = new SpinnerNumberModel(1,0, Integer.MAX_VALUE, 1); + startingIndexSpinner.setModel(startingIndexModel); + + chooseDirectoryButton.addActionListener(e -> { + int selectionResult = outputDirectoryFileChooser.showDialog(this, "Select"); + if (selectionResult == JFileChooser.APPROVE_OPTION) { + outputDirectoryFileChooser.setCurrentDirectory(outputDirectoryFileChooser.getSelectedFile()); + outputDirectoryLabel.setText(outputDirectoryFileChooser.getSelectedFile().getAbsolutePath()); + } + }); + setInitialControlValues(); + setControlsEnabled(currentSettings.isBatchRandomizationEnabled()); + } + + private void setInitialControlValues() { + enableBatchRandomizationCheckBox.setSelected(currentSettings.isBatchRandomizationEnabled()); + generateLogFilesCheckBox.setSelected(currentSettings.shouldGenerateLogFile()); + autoAdvanceIndexCheckBox.setSelected(currentSettings.shouldAutoAdvanceStartingIndex()); + numberOfRandomizedROMsSpinner.setValue(currentSettings.getNumberOfRandomizedROMs()); + startingIndexSpinner.setValue(currentSettings.getStartingIndex()); + fileNamePrefixTextField.setText(currentSettings.getFileNamePrefix()); + outputDirectoryLabel.setText(currentSettings.getOutputDirectory()); + outputDirectoryFileChooser.setCurrentDirectory(new File(currentSettings.getOutputDirectory())); + outputDirectoryFileChooser.setSelectedFile(new File(currentSettings.getOutputDirectory())); + outputDirectoryFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + enableBatchRandomizationCheckBox.addActionListener(a -> setControlsEnabled(enableBatchRandomizationCheckBox.isSelected())); + } + + private void setControlsEnabled(boolean enabled) { + numberOfRandomizedROMsSpinner.setEnabled(enabled); + startingIndexSpinner.setEnabled(enabled); + fileNamePrefixTextField.setEnabled(enabled); + generateLogFilesCheckBox.setEnabled(enabled); + autoAdvanceIndexCheckBox.setEnabled(enabled); + chooseDirectoryButton.setEnabled(enabled); + } + + private void updateSettings() { + currentSettings.setBatchRandomizationEnabled(enableBatchRandomizationCheckBox.isSelected()); + currentSettings.setGenerateLogFile(generateLogFilesCheckBox.isSelected()); + currentSettings.setAutoAdvanceStartingIndex(autoAdvanceIndexCheckBox.isSelected()); + currentSettings.setNumberOfRandomizedROMs((Integer) numberOfRandomizedROMsSpinner.getValue()); + currentSettings.setStartingIndex((Integer) startingIndexSpinner.getValue()); + currentSettings.setFileNamePrefix(fileNamePrefixTextField.getText()); + currentSettings.setOutputDirectory(outputDirectoryFileChooser.getSelectedFile().getAbsolutePath()); + } +} diff --git a/src/com/sneed/pkrandom/newgui/Bundle.properties b/src/com/sneed/pkrandom/newgui/Bundle.properties index 72d7737..6bff613 100644 --- a/src/com/sneed/pkrandom/newgui/Bundle.properties +++ b/src/com/sneed/pkrandom/newgui/Bundle.properties @@ -390,6 +390,7 @@ GUI.romSupportPrefix=Support: GUI.processFailed=There was an unhandled exception trying to process your ROM.\nA log file containing some details has been saved to %s.\nPlease include this file in any bug reports you do. GUI.processFailedNoLog=There was an unhandled exception trying to process your ROM. GUI.raceModeRequirements=You can't use Race Mode without randomizing either the wild Pokemon or the trainer Pokemon.\nReview this and try again. +GUI.batchRandomizationRequirements=You have enabled both Race Mode and Batch Randomization. These options can't be used together.\nDisable one of these options and try again. GUI.pokeLimitNotChosen=You enabled the option to limit the Pokemon that appear, but didn't choose any to allow.\nSelect some by clicking on the "Limit Pokemon" button and try again. GUI.presetFailTrainerClasses=Can't use this preset because you have a different set of random trainer class names to the creator.\nHave them make you a rndp file instead. GUI.presetFailTrainerNames=Can't use this preset because you have a different set of random trainer names to the creator.\nHave them make you a rndp file instead. @@ -428,6 +429,8 @@ GUI.miscTweaksPanel.toolTipText= GUI.miscTweaksPanel.text= GUI.gameMascotLabel.toolTipText= GUI.gameMascotLabel.text= +GUI.batchRandomizationMenuItem.text=Batch Randomization Settings +GUI.batchRandomizationProgress=Saving %d of %d Log.InvalidRomLoaded=The ROM you loaded is not a clean, official ROM.\nRandomizing ROM hacks or bad ROM dumps is not supported and may cause issues.\n GenerationLimitDialog.includePokemonHeader.text=Include Pokemon from: GenerationLimitDialog.relatedPokemonHeader.text=... and related Pokemon from: @@ -631,4 +634,20 @@ GUI.tpEliteFourUniquePokemonCheckBox.text=Pokemon League Has Unique Pokemon: GUI.tpEliteFourUniquePokemonCheckBox.toolTipText=<html>Enabling this setting will ensure that Pokemon League Trainers (Elite Four, Champions and BW1 N/Ghetsis) <br />are given the specified number of unique Pokemon that will not appear on any other Trainer.<br />The Elite Four Trainers' highest level Pokemon are the ones that will be unique;<br/>in the case of a level tie, it will be the Pokemon further back in the party.<br />Does not apply to postgame Pokemon League battles. GUI.tpBetterMovesetsCheckBox.text=Better Movesets GUI.tpBetterMovesetsCheckBox.toolTipText=<html>Attempts to give Trainer Pokemon better movesets by including TM moves/tutor moves/egg moves/pre-evolution moves,<br />and picking moves that synergize with the Pokemon's ability/stats/other moves. - +BatchRandomizationSettingsDialog.title=Batch Randomization Settings +BatchRandomizationSettingsDialog.enableCheckBox.text=Enable batch randomization +BatchRandomizationSettingsDialog.enableCheckBox.toolTipText=If selected, generate the number of randomized ROMs specified. +BatchRandomizationSettingsDialog.startingIndexLabel.text=Starting index +BatchRandomizationSettingsDialog.startingIndexSpinner.toolTipText=Starting index for the first generated ROM. +BatchRandomizationSettingsDialog.numberOfRandomizedROMsLabel.text=Number of randomized ROMs +BatchRandomizationSettingsDialog.numberOfRandomizedROMsSpinner.toolTipText=Number of ROMs to generate in a single batch. +BatchRandomizationSettingsDialog.outputDirectoryButton.text=Output directory... +BatchRandomizationSettingsDialog.outputDirectoryButton.toolTipText=Choose the output directory for your randomized ROMs. +BatchRandomizationSettingsDialog.fileNamePrefixLabel.text=File name prefix +BatchRandomizationSettingsDialog.fileNamePrefixTextBox.toolTipText=File name prefix for the generated ROMs. +BatchRandomizationSettingsDialog.autoAdvanceIndexCheckBox.text=Automatically advance index after batch +BatchRandomizationSettingsDialog.autoAdvanceIndexCheckBox.toolTipText=If selected, the starting index will be automatically updated to the next index after a batch is run. +BatchRandomizationSettingsDialog.generateLogFilesCheckBox.text=Generate log files +BatchRandomizationSettingsDialog.generateLogFilesCheckBox.toolTipText=If selected, save logs for the randomized ROMs. +BatchRandomizationSettingsDialog.okButton.text=OK +BatchRandomizationSettingsDialog.cancelButton.text=Cancel
\ No newline at end of file diff --git a/src/com/sneed/pkrandom/newgui/NewRandomizerGUI.java b/src/com/sneed/pkrandom/newgui/NewRandomizerGUI.java index 40c1313..82ca2c2 100644 --- a/src/com/sneed/pkrandom/newgui/NewRandomizerGUI.java +++ b/src/com/sneed/pkrandom/newgui/NewRandomizerGUI.java @@ -326,6 +326,7 @@ public class NewRandomizerGUI { private JMenuItem customNamesEditorMenuItem; private JMenuItem loadGetSettingsMenuItem; private JMenuItem keepOrUnloadGameAfterRandomizingMenuItem; + private JMenuItem batchRandomizationMenuItem; private ImageIcon emptyIcon = new ImageIcon(getClass().getResource("/com/sneed/pkrandom/newgui/emptyIcon.png")); private boolean haveCheckedCustomNames, unloadGameOnSuccess; @@ -336,6 +337,8 @@ public class NewRandomizerGUI { private final int TRAINER_UNCHANGED = 0, TRAINER_RANDOM = 1, TRAINER_RANDOM_EVEN = 2, TRAINER_RANDOM_EVEN_MAIN = 3, TRAINER_TYPE_THEMED = 4, TRAINER_TYPE_THEMED_ELITE4_GYMS = 5; + private BatchRandomizationSettings batchRandomizationSettings; + public NewRandomizerGUI() { ToolTipManager.sharedInstance().setInitialDelay(400); ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE); @@ -520,6 +523,7 @@ public class NewRandomizerGUI { enableOrDisableSubControls(); } }); + batchRandomizationMenuItem.addActionListener(e -> batchRandomizationSettingsDialog()); } private void showInitialPopup() { @@ -640,6 +644,10 @@ public class NewRandomizerGUI { keepOrUnloadGameAfterRandomizingMenuItem.setText(bundle.getString("GUI.unloadGameAfterRandomizingMenuItem.text")); } settingsMenu.add(keepOrUnloadGameAfterRandomizingMenuItem); + + batchRandomizationMenuItem = new JMenuItem(); + batchRandomizationMenuItem.setText(bundle.getString("GUI.batchRandomizationMenuItem.text")); + settingsMenu.add(batchRandomizationMenuItem); } private void loadROM() { @@ -723,6 +731,10 @@ public class NewRandomizerGUI { if (romHandler == null) { return; // none loaded } + if (raceModeCheckBox.isSelected() && batchRandomizationSettings.isBatchRandomizationEnabled()) { + JOptionPane.showMessageDialog(frame, bundle.getString("GUI.batchRandomizationRequirements")); + return; + } if (raceModeCheckBox.isSelected() && isTrainerSetting(TRAINER_UNCHANGED) && wpUnchangedRadioButton.isSelected()) { JOptionPane.showMessageDialog(frame, bundle.getString("GUI.raceModeRequirements")); return; @@ -736,7 +748,10 @@ public class NewRandomizerGUI { romSaveChooser.setSelectedFile(null); boolean allowed = false; File fh = null; - if (outputType == SaveType.FILE) { + if (batchRandomizationSettings.isBatchRandomizationEnabled() && outputType != SaveType.INVALID) { + allowed = true; + } + else if (outputType == SaveType.FILE) { romSaveChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); int returnVal = romSaveChooser.showSaveDialog(frame); if (returnVal == JFileChooser.APPROVE_OPTION) { @@ -764,19 +779,78 @@ public class NewRandomizerGUI { } if (allowed && fh != null) { - // Get a seed - long seed = RandomSource.pickSeed(); - // Apply it - RandomSource.seed(seed); - presetMode = false; + saveRandomizedRom(outputType, fh); + } else if (allowed && batchRandomizationSettings.isBatchRandomizationEnabled()) { + int numberOfRandomizedROMs = batchRandomizationSettings.getNumberOfRandomizedROMs(); + int startingIndex = batchRandomizationSettings.getStartingIndex(); + int endingIndex = startingIndex + numberOfRandomizedROMs; + final String progressTemplate = bundle.getString("GUI.batchRandomizationProgress"); + OperationDialog batchProgressDialog = new OperationDialog(String.format(progressTemplate, 0, numberOfRandomizedROMs), frame, true); + SwingWorker swingWorker = new SwingWorker<Void, Void>() { + int i; - try { - CustomNamesSet cns = FileFunctions.getCustomNames(); - performRandomization(fh.getAbsolutePath(), seed, cns, outputType == SaveType.DIRECTORY); - } catch (IOException ex) { - JOptionPane.showMessageDialog(frame, bundle.getString("GUI.cantLoadCustomNames")); - } + @Override + protected Void doInBackground() { + frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + SwingUtilities.invokeLater(() -> batchProgressDialog.setVisible(true)); + for (i = startingIndex; i < endingIndex; i++) { + String fileName = batchRandomizationSettings.getOutputDirectory() + + File.separator + + batchRandomizationSettings.getFileNamePrefix() + + i; + if (outputType == SaveType.FILE) { + fileName += '.' + romHandler.getDefaultExtension(); + } + File rom = new File(fileName); + if (outputType == SaveType.DIRECTORY) { + rom.mkdirs(); + } + int currentRomNumber = i - startingIndex + 1; + + SwingUtilities.invokeLater( + () -> batchProgressDialog.setLoadingLabelText(String.format(progressTemplate, + currentRomNumber, + numberOfRandomizedROMs)) + ); + saveRandomizedRom(outputType, rom); + } + return null; + } + + @Override + protected void done() { + super.done(); + if (batchRandomizationSettings.shouldAutoAdvanceStartingIndex()) { + batchRandomizationSettings.setStartingIndex(i); + attemptWriteConfig(); + } + SwingUtilities.invokeLater(() -> batchProgressDialog.setVisible(false)); + JOptionPane.showMessageDialog(frame, bundle.getString("GUI.randomizationDone")); + if (unloadGameOnSuccess) { + romHandler = null; + initialState(); + } else { + reinitializeRomHandler(false); + } + frame.setCursor(null); + } + }; + swingWorker.execute(); + } + } + private void saveRandomizedRom(SaveType outputType, File fh) { + // Get a seed + long seed = RandomSource.pickSeed(); + // Apply it + RandomSource.seed(seed); + presetMode = false; + + try { + CustomNamesSet cns = FileFunctions.getCustomNames(); + performRandomization(fh.getAbsolutePath(), seed, cns, outputType == SaveType.DIRECTORY); + } catch (IOException ex) { + JOptionPane.showMessageDialog(frame, bundle.getString("GUI.cantLoadCustomNames")); } } @@ -848,6 +922,7 @@ public class NewRandomizerGUI { private void performRandomization(final String filename, final long seed, CustomNamesSet customNames, boolean saveAsDirectory) { final Settings settings = createSettingsFromState(customNames); final boolean raceMode = settings.isRaceMode(); + final boolean batchRandomization = batchRandomizationSettings.isBatchRandomizationEnabled() && !presetMode; // Setup verbose log final ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream log; @@ -863,7 +938,7 @@ public class NewRandomizerGUI { final AtomicInteger finishedCV = new AtomicInteger(0); opDialog = new OperationDialog(bundle.getString("GUI.savingText"), frame, true); Thread t = new Thread(() -> { - SwingUtilities.invokeLater(() -> opDialog.setVisible(true)); + SwingUtilities.invokeLater(() -> opDialog.setVisible(!batchRandomization)); boolean succeededSave = false; try { romHandler.setLog(verboseLog); @@ -893,19 +968,22 @@ public class NewRandomizerGUI { JOptionPane.showMessageDialog(frame, String.format(bundle.getString("GUI.raceModeCheckValuePopup"), finishedCV.get())); - } else { + } else if (batchRandomization && batchRandomizationSettings.shouldGenerateLogFile()) { + try { + saveLogFile(filename, out); + } catch (IOException e) { + JOptionPane.showMessageDialog(frame, + bundle.getString("GUI.logSaveFailed")); + return; + } + } else if (!batchRandomization) { int response = JOptionPane.showConfirmDialog(frame, bundle.getString("GUI.saveLogDialog.text"), bundle.getString("GUI.saveLogDialog.title"), JOptionPane.YES_NO_OPTION); if (response == JOptionPane.YES_OPTION) { try { - FileOutputStream fos = new FileOutputStream(filename + ".log"); - fos.write(0xEF); - fos.write(0xBB); - fos.write(0xBF); - fos.write(out); - fos.close(); + saveLogFile(filename, out); } catch (IOException e) { JOptionPane.showMessageDialog(frame, bundle.getString("GUI.logSaveFailed")); @@ -923,9 +1001,9 @@ public class NewRandomizerGUI { romHandler = null; initialState(); } else { - reinitializeRomHandler(); + reinitializeRomHandler(false); } - } else { + } else if (!batchRandomization) { // Compile a config string try { String configString = getCurrentSettings().toString(); @@ -941,7 +1019,7 @@ public class NewRandomizerGUI { romHandler = null; initialState(); } else { - reinitializeRomHandler(); + reinitializeRomHandler(false); } } }); @@ -954,6 +1032,10 @@ public class NewRandomizerGUI { } }); t.start(); + if (batchRandomization) { + t.join(); + reinitializeRomHandler(true); + } } catch (Exception ex) { attemptToLogException(ex, "GUI.saveFailed", "GUI.saveFailedNoLog", settings.toString(), Long.toString(seed)); if (verboseLog != null) { @@ -962,6 +1044,15 @@ public class NewRandomizerGUI { } } + private void saveLogFile(String filename, byte[] out) throws IOException { + FileOutputStream fos = new FileOutputStream(filename + ".log"); + fos.write(0xEF); + fos.write(0xBB); + fos.write(0xBF); + fos.write(out); + fos.close(); + } + private void presetLoader() { PresetLoadDialog pld = new PresetLoadDialog(this,frame); if (pld.isCompleted()) { @@ -1209,17 +1300,24 @@ public class NewRandomizerGUI { JOptionPane.showMessageDialog(frame, messages); } - // This is only intended to be used with the "Keep Game Loaded After Randomizing" setting; it assumes that - // the game has already been loaded once, and we just need to reload the same game to reinitialize the - // RomHandler. Don't use this for other purposes unless you know what you're doing. - private void reinitializeRomHandler() { + private void batchRandomizationSettingsDialog() { + BatchRandomizationSettingsDialog dlg = new BatchRandomizationSettingsDialog(frame, batchRandomizationSettings); + batchRandomizationSettings = dlg.getCurrentSettings(); + attemptWriteConfig(); + } + + // This is only intended to be used with the "Keep Game Loaded After Randomizing" setting or between randomization + // iterations when batch randomization is enabled. It assumes that the game has already been loaded once, and we just need + // to reload the same game to reinitialize the RomHandler. Don't use this for other purposes unless you know what + // you're doing. + private void reinitializeRomHandler(boolean batchRandomization) { String currentFN = this.romHandler.loadedFilename(); for (RomHandler.Factory rhf : checkHandlers) { if (rhf.isLoadable(currentFN)) { this.romHandler = rhf.create(RandomSource.instance()); opDialog = new OperationDialog(bundle.getString("GUI.loadingText"), frame, true); Thread t = new Thread(() -> { - SwingUtilities.invokeLater(() -> opDialog.setVisible(true)); + SwingUtilities.invokeLater(() -> opDialog.setVisible(!batchRandomization)); try { this.romHandler.loadRom(currentFN); if (gameUpdates.containsKey(this.romHandler.getROMCode())) { @@ -1233,7 +1331,13 @@ public class NewRandomizerGUI { }); }); t.start(); - + if (batchRandomization) { + try { + t.join(); + } catch(InterruptedException ex) { + attemptToLogException(ex, "GUI.loadFailed", "GUI.loadFailedNoLog", null, null); + } + } return; } } diff --git a/src/com/sneed/pkrandom/newgui/OperationDialog.java b/src/com/sneed/pkrandom/newgui/OperationDialog.java index 52e6008..2a2a1b2 100644 --- a/src/com/sneed/pkrandom/newgui/OperationDialog.java +++ b/src/com/sneed/pkrandom/newgui/OperationDialog.java @@ -59,6 +59,10 @@ public class OperationDialog extends javax.swing.JDialog { setLocationRelativeTo(parent); } + public void setLoadingLabelText(String text) { + loadingLabel.setText(text); + } + /* @formatter:off */ /** * This method is called from within the constructor to initialize the form. |