use of org.pepsoft.worldpainter.MixedMaterial.Row in project WorldPainter by Captain-Chaos.
the class MixedMaterialTest method testBlobs.
@Test
public void testBlobs() {
try {
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new InternalError("VM does not support mandatory encoding UTF-8");
}
MixedMaterial mixedMaterial = new MixedMaterial("Test", new Row[] { new Row(DIRT, 400, 1.0f), new Row(GRAVEL, 300, 1.0f), new Row(STONE, 200, 1.0f), new Row(SOUL_SAND, 100, 1.0f) }, -1, null);
long[] buckets = new long[256];
for (int x = 0; x < 500; x++) {
for (int y = 0; y < 500; y++) {
for (int z = 0; z < 256; z++) {
Material material = mixedMaterial.getMaterial(0, x, y, z);
Assert.assertTrue(material == DIRT || material == GRAVEL || material == STONE || material == SOUL_SAND);
buckets[material.blockType]++;
}
}
System.out.println(x);
}
long total = 500L * 500L * 256L;
int dirtPerMillage = (int) (buckets[BLK_DIRT] * 1000L / total);
int gravelPerMillage = (int) (buckets[BLK_GRAVEL] * 1000L / total);
int stonePerMillage = (int) (buckets[BLK_STONE] * 1000L / total);
int soulSandPerMillage = (int) (buckets[BLK_SOUL_SAND] * 1000L / total);
System.out.println("Total blocks tested: " + total);
System.out.println("Dirt: " + dirtPerMillage + "‰");
System.out.println("Gravel: " + gravelPerMillage + "‰");
System.out.println("Stone: " + stonePerMillage + "‰");
System.out.println("Soul sand: " + soulSandPerMillage + "‰");
}
use of org.pepsoft.worldpainter.MixedMaterial.Row in project WorldPainter by Captain-Chaos.
the class MixedMaterialTableModel method setValueAt.
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if ((rows.length == 1) && (columnIndex == COLUMN_OCCURRENCE) && (mode != Mode.LAYERED)) {
throw new IllegalArgumentException("Uneditable cell");
}
Row row = rows[rowIndex];
switch(columnIndex) {
case COLUMN_BLOCK_ID:
row = new Row(Material.get((Integer) aValue, row.material.data), row.occurrence, row.scale);
break;
case COLUMN_DATA_VALUE:
row = new Row(Material.get(row.material.blockType, (Integer) aValue), row.occurrence, row.scale);
break;
case COLUMN_OCCURRENCE:
int oldOccurrence = row.occurrence;
int maxValue = 1001 - rows.length;
int occurrence = Math.min((Integer) aValue, maxValue);
if (occurrence == oldOccurrence) {
return;
}
row = new Row(row.material, occurrence, row.scale);
break;
case COLUMN_SCALE:
row = new Row(row.material, row.occurrence, (Integer) aValue / 100f);
break;
default:
throw new IndexOutOfBoundsException("columnIndex " + columnIndex);
}
rows[rowIndex] = row;
TableModelEvent event = new TableModelEvent(this, rowIndex, rowIndex, columnIndex);
fireEvent(event);
}
use of org.pepsoft.worldpainter.MixedMaterial.Row in project WorldPainter by Captain-Chaos.
the class MixedMaterialTableModel method removeMaterial.
public void removeMaterial(int rowIndex) {
if (rows.length == 1) {
throw new IllegalArgumentException("Can't remove last row");
}
Row oldRow = rows[rowIndex];
Row[] oldRows = rows;
rows = new Row[rows.length - 1];
System.arraycopy(oldRows, 0, rows, 0, rowIndex);
System.arraycopy(oldRows, rowIndex + 1, rows, rowIndex, rows.length - rowIndex);
if (mode != Mode.LAYERED) {
float factor = (float) 1000 / (1000 - oldRow.occurrence);
int remaining = 1000;
for (int i = 0; i < rows.length; i++) {
if (i < rows.length - 1) {
int newOccurrence = MathUtils.clamp(1, (int) (rows[i].occurrence * factor + 0.5f), 999);
rows[i] = new Row(rows[i].material, newOccurrence, rows[i].scale);
remaining -= newOccurrence;
} else {
rows[i] = new Row(rows[i].material, remaining, rows[i].scale);
}
}
}
TableModelEvent event = new TableModelEvent(this);
fireEvent(event);
}
use of org.pepsoft.worldpainter.MixedMaterial.Row in project WorldPainter by Captain-Chaos.
the class MixedMaterialTableModel method setMode.
public void setMode(Mode mode) {
if (mode != this.mode) {
Mode previousMode = this.mode;
this.mode = mode;
if (mode == Mode.LAYERED) {
for (int i = 0; i < rows.length; i++) {
rows[i] = new Row(rows[i].material, Math.max(rows[i].occurrence / 100, 3), rows[i].scale);
}
COLUMN_NAMES[COLUMN_OCCURRENCE] = "Thickness";
} else {
if (previousMode == Mode.LAYERED) {
int total = 0;
for (Row row : rows) {
total += row.occurrence;
}
int remaining = 1000;
for (int i = 0; i < rows.length; i++) {
if (i < rows.length - 1) {
int newOccurrence = rows[i].occurrence * 1000 / total;
rows[i] = new Row(rows[i].material, newOccurrence, rows[i].scale);
remaining -= newOccurrence;
} else {
rows[i] = new Row(rows[i].material, remaining, rows[i].scale);
}
}
}
COLUMN_NAMES[COLUMN_OCCURRENCE] = "Occurrence (in ‰)";
}
TableModelEvent event = new TableModelEvent(this, TableModelEvent.HEADER_ROW);
fireEvent(event);
}
}
use of org.pepsoft.worldpainter.MixedMaterial.Row in project WorldPainter by Captain-Chaos.
the class MixedMaterialTableModel method normalise.
/**
* Adjusts the occurrences, if necessary, so that they total one thousand
* while keeping their proportions the same.
*/
public void normalise() {
int total = 0;
for (Row row : rows) {
total += row.occurrence;
}
if (total != 1000) {
float ratio = 1000f / total;
total = 0;
for (int i = 0; i < rows.length; i++) {
if (i < (rows.length - 1)) {
rows[i] = new Row(rows[i].material, Math.max((int) (rows[i].occurrence * ratio + 0.5f), 1), rows[i].scale);
} else {
rows[i] = new Row(rows[i].material, Math.max(1000 - total, 1), rows[i].scale);
}
total += rows[i].occurrence;
}
while (total > 1000) {
// This can happen if one or more rows have had to be rounded up
// because they would have otherwise been zero. This crude
// algorithm keeps stealing from the highest row (where the
// relative effect will be the smallest) until the total is 1000
int highestRowOccurrence = -1, highestRowIndex = -1;
for (int i = 0; i < rows.length; i++) {
if (rows[i].occurrence > highestRowOccurrence) {
highestRowOccurrence = rows[i].occurrence;
highestRowIndex = i;
}
}
rows[highestRowIndex] = new Row(rows[highestRowIndex].material, rows[highestRowIndex].occurrence - 1, rows[highestRowIndex].scale);
total--;
}
fireEvent(new TableModelEvent(this, 0, rows.length - 1, COLUMN_OCCURRENCE));
}
}
Aggregations