use of org.pepsoft.worldpainter.Terrain in project WorldPainter by Captain-Chaos.
the class CombinedLayerPaint method apply.
@Override
public void apply(Dimension dimension, int centreX, int centreY, float dynamicLevel) {
if (brush.getRadius() == 0) {
// Special case: if the radius is 0, assume that the user wants to paint complete pixels instead of trying
// to apply the brush
applyPixel(dimension, centreX, centreY);
return;
}
final int effectiveRadius = brush.getEffectiveRadius();
final int x1 = centreX - effectiveRadius, y1 = centreY - effectiveRadius, x2 = centreX + effectiveRadius, y2 = centreY + effectiveRadius;
final int tileX1 = x1 >> TILE_SIZE_BITS, tileY1 = y1 >> TILE_SIZE_BITS, tileX2 = x2 >> TILE_SIZE_BITS, tileY2 = y2 >> TILE_SIZE_BITS;
final Terrain terrain = ((CombinedLayer) layer).getTerrain();
final int biome = ((CombinedLayer) layer).getBiome();
final boolean terrainConfigured = terrain != null;
final boolean biomeConfigured = biome != -1;
if ((tileX1 == tileX2) && (tileY1 == tileY2)) {
// The bounding box of the brush is entirely on one tile; optimize by painting directly to the tile
final Tile tile = dimension.getTileForEditing(tileX1, tileY1);
if (tile == null) {
return;
}
final int x1InTile = x1 & TILE_SIZE_MASK, y1InTile = y1 & TILE_SIZE_MASK, x2InTile = x2 & TILE_SIZE_MASK, y2InTile = y2 & TILE_SIZE_MASK;
final int tileXInWorld = tileX1 << TILE_SIZE_BITS, tileYInWorld = tileY1 << TILE_SIZE_BITS;
if (dither) {
for (int y = y1InTile; y <= y2InTile; y++) {
for (int x = x1InTile; x <= x2InTile; x++) {
final int currentValue = tile.getLayerValue(layer, x, y);
final float strength = dynamicLevel * getStrength(centreX, centreY, tileXInWorld + x, tileYInWorld + y);
if (strength != 0f) {
int targetValue = 1 + Math.round(strength * 14);
if (targetValue > currentValue) {
tile.setLayerValue(layer, x, y, targetValue);
}
if (terrainConfigured && ((strength > 0.95f) || (Math.random() < strength))) {
tile.setTerrain(x, y, terrain);
}
if (biomeConfigured && ((strength > 0.95f) || (Math.random() < strength))) {
tile.setLayerValue(Biome.INSTANCE, x, y, biome);
}
}
}
}
} else {
for (int y = y1InTile; y <= y2InTile; y++) {
for (int x = x1InTile; x <= x2InTile; x++) {
final int currentValue = tile.getLayerValue(layer, x, y);
final float strength = dynamicLevel * getStrength(centreX, centreY, tileXInWorld + x, tileYInWorld + y);
if (strength != 0f) {
int targetValue = 1 + Math.round(strength * 14);
if (targetValue > currentValue) {
tile.setLayerValue(layer, x, y, targetValue);
}
if (dynamicLevel * getFullStrength(centreX, centreY, tileXInWorld + x, tileYInWorld + y) > 0.75f) {
if (terrainConfigured) {
tile.setTerrain(x, y, terrain);
}
if (biomeConfigured) {
tile.setLayerValue(Biome.INSTANCE, x, y, biome);
}
}
}
}
}
}
} else {
// The bounding box of the brush straddles more than one tile; paint to the dimension
if (dither) {
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
final int currentValue = dimension.getLayerValueAt(layer, x, y);
final float strength = dynamicLevel * getStrength(centreX, centreY, x, y);
if (strength != 0f) {
int targetValue = 1 + Math.round(strength * 14);
if (targetValue > currentValue) {
dimension.setLayerValueAt(layer, x, y, targetValue);
}
if (terrainConfigured && ((strength > 0.95f) || (Math.random() < strength))) {
dimension.setTerrainAt(x, y, terrain);
}
if (biomeConfigured && ((strength > 0.95f) || (Math.random() < strength))) {
dimension.setLayerValueAt(Biome.INSTANCE, x, y, biome);
}
}
}
}
} else {
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
final int currentValue = dimension.getLayerValueAt(layer, x, y);
final float strength = dynamicLevel * getStrength(centreX, centreY, x, y);
if (strength != 0f) {
int targetValue = 1 + Math.round(strength * 14);
if (targetValue > currentValue) {
dimension.setLayerValueAt(layer, x, y, targetValue);
}
if (dynamicLevel * getFullStrength(centreX, centreY, x, y) > 0.75f) {
if (terrainConfigured) {
dimension.setTerrainAt(x, y, terrain);
}
if (biomeConfigured) {
dimension.setLayerValueAt(Biome.INSTANCE, x, y, biome);
}
}
}
}
}
}
}
}
use of org.pepsoft.worldpainter.Terrain in project WorldPainter by Captain-Chaos.
the class App method importLayers.
private void importLayers(String paletteName) {
Configuration config = Configuration.getInstance();
File layerDirectory = config.getLayerDirectory();
if ((layerDirectory == null) || (!layerDirectory.isDirectory())) {
layerDirectory = DesktopUtils.getDocumentsFolder();
}
File[] selectedFiles = FileUtils.selectFilesForOpen(this, "Select WorldPainter layer file(s)", layerDirectory, new FileFilter() {
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".layer");
}
@Override
public String getDescription() {
return "WorldPainter Custom Layers (*.layer)";
}
});
if (selectedFiles != null) {
boolean updateCustomTerrainButtons = false;
for (File selectedFile : selectedFiles) {
try {
try (ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(selectedFile))))) {
CustomLayer layer = (CustomLayer) in.readObject();
for (Layer existingLayer : getCustomLayers()) {
if (layer.equals(existingLayer)) {
showMessageDialog(this, "That layer is already present in the dimension.\nThe layer has not been added.", "Layer Already Present", WARNING_MESSAGE);
return;
}
}
if (paletteName != null) {
layer.setPalette(paletteName);
}
registerCustomLayer(layer, true);
if (layer instanceof CombinedLayer) {
CombinedLayer combinedLayer = (CombinedLayer) layer;
addLayersFromCombinedLayer(combinedLayer);
if (!combinedLayer.restoreCustomTerrain()) {
showMessageDialog(this, "The layer contained a Custom Terrain which could not be restored. The terrain has been reset.", "Custom Terrain Not Restored", ERROR_MESSAGE);
} else {
// Check for a custom terrain type and if necessary make
// sure it has a button
Terrain terrain = combinedLayer.getTerrain();
if ((terrain != null) && terrain.isCustom()) {
updateCustomTerrainButtons = true;
if (customMaterialButtons[terrain.getCustomTerrainIndex()] == null) {
addButtonForNewCustomTerrain(terrain.getCustomTerrainIndex(), getCustomMaterial(terrain.getCustomTerrainIndex()), false);
}
}
}
}
}
} catch (FileNotFoundException e) {
logger.error("File not found while loading file " + selectedFile, e);
showMessageDialog(this, "The specified path does not exist or is not a file", "Nonexistent File", ERROR_MESSAGE);
return;
} catch (IOException e) {
logger.error("I/O error while loading file " + selectedFile, e);
showMessageDialog(this, "I/O error occurred while reading the specified file,\nor is not a (valid) WorldPainter layer file", "I/O Error Or Invalid File", ERROR_MESSAGE);
return;
} catch (ClassNotFoundException e) {
logger.error("Class not found exception while loading file " + selectedFile, e);
showMessageDialog(this, "The specified file is not a (valid) WorldPainter layer file", "Invalid File", ERROR_MESSAGE);
return;
} catch (ClassCastException e) {
logger.error("Class cast exception while loading file " + selectedFile, e);
showMessageDialog(this, "The specified file is not a (valid) WorldPainter layer file", "Invalid File", ERROR_MESSAGE);
return;
}
}
if (updateCustomTerrainButtons) {
updateCustomTerrainButtons();
}
}
}
use of org.pepsoft.worldpainter.Terrain in project WorldPainter by Captain-Chaos.
the class App method setDimension.
public void setDimension(final Dimension dimension) {
Configuration config = Configuration.getInstance();
if (this.dimension != null) {
this.dimension.removePropertyChangeListener(this);
this.dimension.removeDimensionListener(this);
for (Tile tile : this.dimension.getTiles()) {
tile.removeListener(this);
}
Point viewPosition = view.getViewCentreInWorldCoords();
if (viewPosition != null) {
this.dimension.setLastViewPosition(viewPosition);
// in sync
if (world != null) {
Dimension oppositeDimension = null;
switch(this.dimension.getDim()) {
case DIM_NORMAL:
oppositeDimension = world.getDimension(DIM_NORMAL_CEILING);
break;
case DIM_NORMAL_CEILING:
oppositeDimension = world.getDimension(DIM_NORMAL);
break;
case DIM_NETHER:
oppositeDimension = world.getDimension(DIM_NETHER_CEILING);
break;
case DIM_NETHER_CEILING:
oppositeDimension = world.getDimension(DIM_NETHER);
break;
case DIM_END:
oppositeDimension = world.getDimension(DIM_END_CEILING);
break;
case DIM_END_CEILING:
oppositeDimension = world.getDimension(DIM_END);
break;
}
if (oppositeDimension != null) {
oppositeDimension.setLastViewPosition(viewPosition);
}
}
}
currentUndoManager.unregisterActions();
currentUndoManager = null;
// currently in use
if (!paletteManager.isEmpty()) {
List<CustomLayer> customLayers = new ArrayList<>();
boolean visibleLayersChanged = false;
for (Palette palette : paletteManager.clear()) {
palette.removePropertyChangeListener(this);
List<CustomLayer> paletteLayers = palette.getLayers();
customLayers.addAll(paletteLayers);
for (Layer layer : paletteLayers) {
if (hiddenLayers.contains(layer)) {
hiddenLayers.remove(layer);
visibleLayersChanged = true;
}
if (layer.equals(soloLayer)) {
soloLayer = null;
visibleLayersChanged = true;
}
}
dockingManager.removeFrame(palette.getDockableFrame().getKey());
}
if (visibleLayersChanged) {
updateLayerVisibility();
}
layerSoloCheckBoxes.clear();
this.dimension.setCustomLayers(customLayers);
} else {
this.dimension.setCustomLayers(emptyList());
}
layersWithNoButton.clear();
saveCustomBiomes();
}
this.dimension = dimension;
if (dimension != null) {
// NOI18N
setTitle("WorldPainter - " + world.getName() + " - " + dimension.getName());
viewSurfaceMenuItem.setSelected(dimension.getDim() == DIM_NORMAL);
viewSurfaceCeilingMenuItem.setSelected(dimension.getDim() == DIM_NORMAL_CEILING);
viewNetherMenuItem.setSelected(dimension.getDim() == DIM_NETHER);
viewNetherCeilingMenuItem.setSelected(dimension.getDim() == DIM_NETHER_CEILING);
viewEndMenuItem.setSelected(dimension.getDim() == DIM_END);
viewEndCeilingMenuItem.setSelected(dimension.getDim() == DIM_END_CEILING);
// neglected to do it automatically)
if (dimension.isFixOverlayCoords()) {
DesktopUtils.beep();
if (showConfirmDialog(this, "This world was created in an older version of WorldPainter\n" + "in which the overlay offsets were not stored correctly.\n" + "Do you want WorldPainter to fix the offsets now?\n" + "\n" + "If you already manually fixed the offsets using version 1.9.0\n" + "or 1.9.1 of WorldPainter, say no. If you're unsure, say yes.", "Fix Overlay Offset?", YES_NO_OPTION, QUESTION_MESSAGE) != NO_OPTION) {
dimension.setOverlayOffsetX(dimension.getOverlayOffsetX() + dimension.getLowestX() << TILE_SIZE_BITS);
dimension.setOverlayOffsetY(dimension.getOverlayOffsetY() + dimension.getLowestY() << TILE_SIZE_BITS);
}
dimension.setFixOverlayCoords(false);
}
view.setDimension(dimension);
view.moveTo(dimension.getLastViewPosition());
configureForPlatform();
currentUndoManager = undoManagers.get(dimension.getDim());
if (currentUndoManager == null) {
if ((!"true".equals(System.getProperty("org.pepsoft.worldpainter.disableUndo"))) && config.isUndoEnabled()) {
currentUndoManager = new UndoManager(ACTION_UNDO, ACTION_REDO, Math.max(config.getUndoLevels() + 1, 2));
} else {
// Still install an undo manager, because some operations depend
// on one level of undo being available
currentUndoManager = new UndoManager(2);
ACTION_UNDO.setEnabled(false);
ACTION_REDO.setEnabled(false);
}
currentUndoManager.setStopAtClasses(PropertyChangeListener.class, Tile.Listener.class, Biome.class, BetterAction.class);
undoManagers.put(dimension.getDim(), currentUndoManager);
dimension.register(currentUndoManager);
} else if ((!"true".equals(System.getProperty("org.pepsoft.worldpainter.disableUndo"))) && config.isUndoEnabled()) {
currentUndoManager.registerActions(ACTION_UNDO, ACTION_REDO);
}
dimension.armSavePoint();
if (threeDeeFrame != null) {
threeDeeFrame.setDimension(dimension);
}
// Add the custom object layers from the world
StringBuilder warnings = new StringBuilder();
for (CustomLayer customLayer : dimension.getCustomLayers()) {
if (customLayer.isHide()) {
layersWithNoButton.add(customLayer);
} else {
registerCustomLayer(customLayer, false);
}
if (customLayer instanceof CombinedLayer) {
if (!((CombinedLayer) customLayer).restoreCustomTerrain()) {
if (warnings.length() == 0) {
warnings.append("The Custom Terrain for one or more Combined Layer could not be restored:\n\n");
}
warnings.append(customLayer.getName()).append('\n');
} else {
// Check for a custom terrain type and if necessary make
// sure it has a button
Terrain terrain = ((CombinedLayer) customLayer).getTerrain();
if ((terrain != null) && terrain.isCustom() && (customMaterialButtons[terrain.getCustomTerrainIndex()] == null)) {
addButtonForNewCustomTerrain(terrain.getCustomTerrainIndex(), getCustomMaterial(terrain.getCustomTerrainIndex()), false);
}
}
}
}
if (warnings.length() > 0) {
warnings.append("\nThe Custom Terrain has been removed from the layer(s).");
showMessageDialog(this, warnings.toString(), "Custom Terrain(s) Not Restored", ERROR_MESSAGE);
}
// Set action states
ACTION_GRID.setSelected(view.isPaintGrid());
ACTION_CONTOURS.setSelected(view.isDrawContours());
ACTION_OVERLAY.setSelected(view.isDrawOverlay());
// TODO: make this work correctly with undo/redo, and make "inside selection" ineffective when there is no selection, to avoid confusion
// Set operation states
// if (dimension.containsOneOf(SelectionChunk.INSTANCE, SelectionBlock.INSTANCE)) {
// selectionState.setValue(true);
// } else {
// if (activeOperation instanceof CopySelectionOperation) {
// deselectTool();
// }
// selectionState.setValue(false);
// }
// Load custom biomes. But first remove any that are now regular
// biomes
List<CustomBiome> customBiomes = dimension.getCustomBiomes();
if (customBiomes != null) {
customBiomes.removeIf(customBiome -> StaticBiomeInfo.INSTANCE.isBiomePresent(customBiome.getId()));
if (customBiomes.isEmpty()) {
customBiomes = null;
}
}
programmaticChange = true;
try {
customBiomeManager.setCustomBiomes(customBiomes);
} finally {
programmaticChange = false;
}
brushOptions.setMaxHeight(dimension.getMaxHeight());
dimension.addPropertyChangeListener(this);
dimension.addDimensionListener(this);
for (Tile tile : dimension.getTiles()) {
tile.addListener(this);
}
} else {
view.setDimension(null);
// NOI18N
setTitle("WorldPainter");
// Clear action states
ACTION_GRID.setSelected(false);
ACTION_CONTOURS.setSelected(false);
ACTION_OVERLAY.setSelected(false);
// Close the 3D view
if (threeDeeFrame != null) {
threeDeeFrame.dispose();
threeDeeFrame = null;
}
// Clear status bar
locationLabel.setText(strings.getString("location-"));
heightLabel.setText(" ");
waterLabel.setText(" ");
biomeLabel.setText(" ");
materialLabel.setText(" ");
// Deselect any current operation
if (activeOperation != null) {
deselectTool();
}
// TODO: make this work correctly with undo/redo, and make "inside selection" ineffective when there is no selection, to avoid confusion
// Disable copy selection operation
// selectionState.setValue(false);
programmaticChange = true;
try {
customBiomeManager.setCustomBiomes(null);
} finally {
programmaticChange = false;
}
}
}
use of org.pepsoft.worldpainter.Terrain in project WorldPainter by Captain-Chaos.
the class NewWorldDialog method createTileFactory.
private TileFactory createTileFactory(long seed) {
final Terrain terrain = (Terrain) comboBoxSurfaceMaterial.getSelectedItem();
final int baseHeight = (Integer) spinnerTerrainLevel.getValue();
final int waterHeight = (Integer) spinnerWaterLevel.getValue();
final float range = ((Number) spinnerRange.getValue()).floatValue();
final double scale = ((Integer) spinnerScale.getValue()) / 100.0;
final boolean floodWithLava = checkBoxLava.isSelected();
final boolean beaches = checkBoxBeaches.isSelected();
final int minHeight;
int maxHeight = (Integer) comboBoxMaxHeight.getSelectedItem();
switch(dim) {
case DIM_NETHER:
case DIM_NETHER_CEILING:
minHeight = Math.max(platform.minZ, 0);
maxHeight = Math.min(maxHeight, DEFAULT_MAX_HEIGHT_NETHER);
break;
case DIM_END:
case DIM_END_CEILING:
minHeight = Math.max(platform.minZ, 0);
maxHeight = Math.min(maxHeight, DEFAULT_MAX_HEIGHT_END);
break;
default:
minHeight = platform.minZ;
break;
}
final HeightMapTileFactory tileFactory;
if ("true".equals(System.getProperty("org.pepsoft.worldpainter.fancyworlds"))) {
tileFactory = TileFactoryFactory.createFancyTileFactory(seed, terrain, minHeight, maxHeight, baseHeight, waterHeight, floodWithLava, range, scale);
} else {
// HeightMapTileFactory tileFactory = new ExperimentalTileFactory(maxHeight);
if (radioButtonHilly.isSelected()) {
tileFactory = TileFactoryFactory.createNoiseTileFactory(seed, terrain, minHeight, maxHeight, baseHeight, waterHeight, floodWithLava, beaches, range, scale);
} else {
tileFactory = TileFactoryFactory.createFlatTileFactory(seed, terrain, minHeight, maxHeight, baseHeight, waterHeight, floodWithLava, beaches);
}
if (radioButtonAdvancedTerrain.isSelected()) {
theme.setWaterHeight((Integer) spinnerWaterLevel.getValue());
theme.setBeaches(checkBoxBeaches.isSelected());
tileFactory.setTheme(theme);
}
Configuration config = Configuration.getInstance();
Dimension defaults = config.getDefaultTerrainAndLayerSettings();
if ((dim == DIM_NORMAL) && (defaults.getTileFactory() instanceof HeightMapTileFactory) && (((HeightMapTileFactory) defaults.getTileFactory()).getTheme() instanceof SimpleTheme) && (((SimpleTheme) ((HeightMapTileFactory) defaults.getTileFactory()).getTheme()).getTerrainRanges() != null) && radioButtonSimpleTerrain.isSelected()) {
final HeightMapTileFactory defaultTileFactory = (HeightMapTileFactory) defaults.getTileFactory();
final SimpleTheme defaultTheme = (SimpleTheme) defaultTileFactory.getTheme().clone();
defaultTheme.setMinMaxHeight(minHeight, maxHeight, IDENTITY);
final SortedMap<Integer, Terrain> terrainRanges = new TreeMap<>(defaultTheme.getTerrainRanges());
final int surfaceLevel = terrainRanges.headMap(waterHeight + 3).lastKey();
terrainRanges.put(surfaceLevel, terrain);
final SimpleTheme theme = (SimpleTheme) tileFactory.getTheme();
theme.setTerrainRanges(terrainRanges);
theme.setRandomise(defaultTheme.isRandomise());
} else if ((dim != DIM_NORMAL) && radioButtonSimpleTerrain.isSelected()) {
// Override the default terrain map:
SortedMap<Integer, Terrain> terrainMap = new TreeMap<>();
terrainMap.put(-1, terrain);
SimpleTheme theme = (SimpleTheme) tileFactory.getTheme();
theme.setTerrainRanges(terrainMap);
}
}
return tileFactory;
}
use of org.pepsoft.worldpainter.Terrain in project WorldPainter by Captain-Chaos.
the class TerrainRangesTableModel method sortIfNeeded.
private void sortIfNeeded() {
for (int i = 1; i < rows; i++) {
if (levels[i] < levels[i - 1]) {
SortedMap<Integer, Terrain> sortedMap = new TreeMap<>();
for (int j = 0; j < rows; j++) {
sortedMap.put(levels[j], terrains[j]);
}
int j = 0;
for (Map.Entry<Integer, Terrain> row : sortedMap.entrySet()) {
levels[j] = row.getKey();
terrains[j] = row.getValue();
j++;
}
TableModelEvent event = new TableModelEvent(this, 0, rows - 1);
for (TableModelListener listener : listeners) {
listener.tableChanged(event);
}
notifyChangeListener();
break;
}
}
}
Aggregations