/* * To change this template, choose Tools | Templates * and open the template in the editor. */ /* * ChangeHeightDialog.java * * Created on 30-jan-2012, 17:54:20 */ package org.pepsoft.worldpainter; import org.pepsoft.util.ProgressReceiver; import org.pepsoft.util.ProgressReceiver.OperationCancelled; import org.pepsoft.util.swing.ProgressDialog; import org.pepsoft.util.swing.ProgressTask; import org.pepsoft.worldpainter.heightMaps.HeightMapUtils; import org.pepsoft.worldpainter.history.HistoryEntry; import org.pepsoft.worldpainter.layers.Resources; import org.pepsoft.worldpainter.layers.exporters.ResourcesExporter.ResourcesExporterSettings; import javax.swing.*; import java.awt.*; import static org.pepsoft.minecraft.Constants.DEFAULT_MAX_HEIGHT_2; /** * * @author pepijn */ public class ChangeHeightDialog extends WorldPainterDialog { /** Creates new form ChangeHeightDialog */ public ChangeHeightDialog(java.awt.Frame parent, World2 world) { super(parent); this.world = world; initComponents(); int maxHeight = world.getMaxHeight(); labelCurrentHeight.setText(Integer.toString(maxHeight)); comboBoxNewHeight.setSelectedItem(Integer.toString(maxHeight)); getRootPane().setDefaultButton(buttonOK); setLocationRelativeTo(parent); } private void calculateDefaults() { int oldMaxHeight = world.getMaxHeight(); int newMaxHeight = Integer.parseInt((String) comboBoxNewHeight.getSelectedItem()); int defaultTranslateAmount = (newMaxHeight - oldMaxHeight) / 2; int maxTranslateAmount = newMaxHeight - 1; int minTranslateAmount = -maxTranslateAmount; spinnerTranslateAmount.setValue(defaultTranslateAmount); ((SpinnerNumberModel) spinnerTranslateAmount.getModel()).setMinimum(minTranslateAmount); ((SpinnerNumberModel) spinnerTranslateAmount.getModel()).setMaximum(maxTranslateAmount); int defaultScale = newMaxHeight * 100 / oldMaxHeight; spinnerScaleAmount.setValue(defaultScale); } private void setControlStates() { int oldMaxHeight = world.getMaxHeight(); int newMaxHeight = Integer.parseInt((String) comboBoxNewHeight.getSelectedItem()); boolean translate = checkBoxTranslate.isSelected(); boolean scale = checkBoxScale.isSelected(); buttonOK.setEnabled((oldMaxHeight != newMaxHeight) || (translate && ((Integer) spinnerTranslateAmount.getValue() != 0)) || (scale && ((Integer) spinnerScaleAmount.getValue() != 100))); spinnerTranslateAmount.setEnabled(translate); spinnerScaleAmount.setEnabled(scale); labelWarning.setVisible(newMaxHeight != DEFAULT_MAX_HEIGHT_2); } private void doResize() { int oldMaxHeight = world.getMaxHeight(); int newMaxHeight = Integer.parseInt((String) comboBoxNewHeight.getSelectedItem()); if ((newMaxHeight != oldMaxHeight) && (world.getImportedFrom() != null) && (JOptionPane.showConfirmDialog(this, "<html>This world was imported from an existing map!<br>Are you <i>sure</i> you want to change the height?<br>You will not be able to merge it back to the existing map any more!</html>", "Import from Existing Map", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION)) { return; } boolean scale = checkBoxScale.isSelected(); int scaleAmount = (Integer) spinnerScaleAmount.getValue(); boolean translate = checkBoxTranslate.isSelected(); int translateAmount = (Integer) spinnerTranslateAmount.getValue(); HeightTransform transform = HeightTransform.get(scale ? scaleAmount : 100, translate ? translateAmount : 0); resizeWorld(world, transform, newMaxHeight, this); if (newMaxHeight != oldMaxHeight) { world.addHistoryEntry(HistoryEntry.WORLD_MAX_HEIGHT_CHANGED, newMaxHeight); } if (translate) { for (Dimension dimension: world.getDimensions()) { world.addHistoryEntry(HistoryEntry.WORLD_DIMENSION_SHIFTED_VERTICALLY, dimension.getName(), translateAmount); } } } static void resizeWorld(final World2 world, final HeightTransform transform, final int newMaxHeight, final Window parent) { int tileCount = 0; for (Dimension dim: world.getDimensions()) { dim.setEventsInhibited(true); tileCount += dim.getTiles().size(); } final int finalTileCount = tileCount; try { ProgressDialog.executeTask(parent, new ProgressTask<World2>() { @Override public String getName() { return "Changing world height"; } @Override public World2 execute(ProgressReceiver progressReceiver) throws OperationCancelled { int tileNo = 0; int oldMaxHeight = world.getMaxHeight(); for (Dimension dim: world.getDimensions()) { dim.clearUndo(); dim.getTiles().forEach(org.pepsoft.worldpainter.Tile::inhibitEvents); try { for (Tile tile: dim.getTiles()) { tile.setMaxHeight(newMaxHeight, transform); tileNo++; progressReceiver.setProgress((float) tileNo / finalTileCount); } dim.setMaxHeight(newMaxHeight); TileFactory tileFactory = dim.getTileFactory(); if (tileFactory instanceof HeightMapTileFactory) { HeightMapTileFactory heightMapTileFactory = (HeightMapTileFactory) tileFactory; heightMapTileFactory.setMaxHeight(newMaxHeight, transform); float baseHeight = heightMapTileFactory.getBaseHeight(); float transposeAmount = transform.transformHeight(baseHeight) - baseHeight; heightMapTileFactory.setHeightMap(HeightMapUtils.transposeHeightMap(heightMapTileFactory.getHeightMap(), transposeAmount)); } ResourcesExporterSettings resourcesSettings = (ResourcesExporterSettings) dim.getLayerSettings(Resources.INSTANCE); if (resourcesSettings != null) { for (int blockType: resourcesSettings.getBlockTypes()) { int maxLevel = resourcesSettings.getMaxLevel(blockType); if (maxLevel == (oldMaxHeight - 1)) { maxLevel = newMaxHeight - 1; } else if (maxLevel > 1) { maxLevel = clamp(transform.transformHeight(maxLevel), newMaxHeight - 1); } resourcesSettings.setMaxLevel(blockType, maxLevel); resourcesSettings.setMaxLevel(blockType, clamp(transform.transformHeight(resourcesSettings.getMaxLevel(blockType)), newMaxHeight - 1)); } } dim.clearUndo(); dim.armSavePoint(); } finally { dim.getTiles().forEach(org.pepsoft.worldpainter.Tile::releaseEvents); } } world.setMaxHeight(newMaxHeight); return world; } }, false); } finally { for (Dimension dim: world.getDimensions()) { dim.setEventsInhibited(false); } } } private static int clamp(int level, int maxLevel) { if (level < 0) { return 0; } else if (level > maxLevel) { return maxLevel; } else { return level; } } /** 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") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); labelCurrentHeight = new javax.swing.JLabel(); comboBoxNewHeight = new javax.swing.JComboBox(); buttonCancel = new javax.swing.JButton(); buttonOK = new javax.swing.JButton(); jLabel5 = new javax.swing.JLabel(); spinnerTranslateAmount = new javax.swing.JSpinner(); label = new javax.swing.JLabel(); spinnerScaleAmount = new javax.swing.JSpinner(); jLabel7 = new javax.swing.JLabel(); checkBoxScale = new javax.swing.JCheckBox(); checkBoxTranslate = new javax.swing.JCheckBox(); jLabel6 = new javax.swing.JLabel(); jLabel8 = new javax.swing.JLabel(); labelWarning = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Change Height"); jLabel1.setText("Current height:"); jLabel2.setText("New height:"); labelCurrentHeight.setText("jLabel3"); comboBoxNewHeight.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "32", "64", "128", "256", "512", "1024", "2048" })); comboBoxNewHeight.addActionListener(this::comboBoxNewHeightActionPerformed); buttonCancel.setText("Cancel"); buttonCancel.addActionListener(this::buttonCancelActionPerformed); buttonOK.setText("OK"); buttonOK.setEnabled(false); buttonOK.addActionListener(this::buttonOKActionPerformed); jLabel5.setText("Terrain and water levels:"); spinnerTranslateAmount.setModel(new javax.swing.SpinnerNumberModel(0, -127, 127, 1)); spinnerTranslateAmount.setEnabled(false); spinnerTranslateAmount.addChangeListener(this::spinnerTranslateAmountStateChanged); label.setText("blocks"); spinnerScaleAmount.setModel(new javax.swing.SpinnerNumberModel(100, 1, 9999, 1)); spinnerScaleAmount.setEnabled(false); spinnerScaleAmount.addChangeListener(this::spinnerScaleAmountStateChanged); jLabel7.setText("%"); checkBoxScale.setText("Scale"); checkBoxScale.setToolTipText("<html>Scale the levels by the specified percentage;<br>\nlevels that are (still) too low or high will be cut off.</html>"); checkBoxScale.addChangeListener(this::checkBoxScaleStateChanged); checkBoxTranslate.setText("Shift"); checkBoxTranslate.setToolTipText("<html>Shift the levels up or down by the specified number of blocks;<br>\nnegative means down; levels which are (still) too low or high will be cut off.</html>"); checkBoxTranslate.addChangeListener(this::checkBoxTranslateStateChanged); jLabel6.setText("<html><b>Note:</b> this operation cannot be undone!</html>"); jLabel8.setText("(If both are enabled scale will be applied first, then shift.)"); labelWarning.setFont(labelWarning.getFont().deriveFont(labelWarning.getFont().getStyle() | java.awt.Font.BOLD)); labelWarning.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/pepsoft/worldpainter/icons/error.png"))); // NOI18N labelWarning.setText("Only Minecraft 1.1, with mods!"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(buttonOK) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonCancel)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel1) .addComponent(jLabel2)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(labelCurrentHeight) .addGroup(layout.createSequentialGroup() .addComponent(comboBoxNewHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(labelWarning)))) .addGroup(layout.createSequentialGroup() .addComponent(checkBoxTranslate) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(spinnerTranslateAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) .addComponent(label)) .addGroup(layout.createSequentialGroup() .addComponent(spinnerScaleAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) .addComponent(jLabel7)))) .addComponent(jLabel5) .addComponent(checkBoxScale) .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel8)) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(labelCurrentHeight)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(comboBoxNewHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(labelWarning)) .addGap(18, 18, 18) .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(checkBoxScale) .addComponent(spinnerScaleAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel7)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(checkBoxTranslate) .addComponent(spinnerTranslateAmount, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(label)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel8) .addGap(18, 18, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(buttonCancel) .addComponent(buttonOK)) .addContainerGap()) ); pack(); }// </editor-fold>//GEN-END:initComponents private void comboBoxNewHeightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboBoxNewHeightActionPerformed calculateDefaults(); setControlStates(); }//GEN-LAST:event_comboBoxNewHeightActionPerformed private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed cancel(); }//GEN-LAST:event_buttonCancelActionPerformed private void checkBoxScaleStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_checkBoxScaleStateChanged setControlStates(); }//GEN-LAST:event_checkBoxScaleStateChanged private void checkBoxTranslateStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_checkBoxTranslateStateChanged setControlStates(); }//GEN-LAST:event_checkBoxTranslateStateChanged private void buttonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOKActionPerformed doResize(); ok(); }//GEN-LAST:event_buttonOKActionPerformed private void spinnerScaleAmountStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerScaleAmountStateChanged setControlStates(); }//GEN-LAST:event_spinnerScaleAmountStateChanged private void spinnerTranslateAmountStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerTranslateAmountStateChanged setControlStates(); }//GEN-LAST:event_spinnerTranslateAmountStateChanged // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton buttonCancel; private javax.swing.JButton buttonOK; private javax.swing.JCheckBox checkBoxScale; private javax.swing.JCheckBox checkBoxTranslate; private javax.swing.JComboBox comboBoxNewHeight; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel5; private javax.swing.JLabel jLabel6; private javax.swing.JLabel jLabel7; private javax.swing.JLabel jLabel8; private javax.swing.JLabel label; private javax.swing.JLabel labelCurrentHeight; private javax.swing.JLabel labelWarning; private javax.swing.JSpinner spinnerScaleAmount; private javax.swing.JSpinner spinnerTranslateAmount; // End of variables declaration//GEN-END:variables private final World2 world; private static final long serialVersionUID = 1L; }