Update with simple status bar

This commit is contained in:
Retera 2020-11-13 23:12:39 -05:00
parent 632576323c
commit 2b3e5bdf4a
12 changed files with 2888 additions and 2673 deletions

View File

@ -130,7 +130,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
this.viewer.enableAudio();
}
try {
this.viewer.loadMap(this.warsmashIni.get("Map").getField("FilePath"));
this.viewer.loadMap(this.warsmashIni.get("Map").getField("FilePath"), 0);
}
catch (final IOException e) {
throw new RuntimeException(e);
@ -222,7 +222,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
cameraRatesElement.getFieldFloatValue("FOV"), cameraRatesElement.getFieldFloatValue("Rotation"),
cameraRatesElement.getFieldFloatValue("Distance"), cameraRatesElement.getFieldFloatValue("Forward"),
cameraRatesElement.getFieldFloatValue("Strafe"));
this.meleeUI = new MeleeUI(this.codebase, this.uiViewport, fontGenerator, this.uiScene, portraitScene,
this.meleeUI = new MeleeUI(this.viewer.mapMpq, this.uiViewport, fontGenerator, this.uiScene, portraitScene,
cameraPresets, cameraRates, this.viewer, new RootFrameListener() {
@Override
public void onCreate(final GameUI rootFrame) {

View File

@ -30,6 +30,7 @@ import com.etheller.warsmash.parsers.fdf.frames.AbstractUIFrame;
import com.etheller.warsmash.parsers.fdf.frames.FilterModeTextureFrame;
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
import com.etheller.warsmash.parsers.fdf.frames.SimpleStatusBarFrame;
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
@ -104,16 +105,31 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
catch (final IOException e) {
throw new RuntimeException(e);
}
// TODO eliminate duplicate read of skin TXT!!
if (dataSource.has("war3mapSkin.txt")) {
try (InputStream miscDataTxtStream = dataSource.getResourceAsStream("war3mapSkin.txt")) {
skinsTable.readTXT(miscDataTxtStream, true);
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
// final Element main = skinsTable.get("Main");
// final String skinsField = main.getField("Skins");
// final String[] skins = skinsField.split(",");
final Element defaultSkin = skinsTable.get("Default");
final Element userSkin = skinsTable.get(skin);
final Element customSkin = skinsTable.get("CustomSkin");
for (final String key : defaultSkin.keySet()) {
if (!userSkin.hasField(key)) {
userSkin.setField(key, defaultSkin.getField(key));
}
}
if (customSkin != null) {
for (final String key : customSkin.keySet()) {
userSkin.setField(key, customSkin.getField(key));
}
}
return userSkin;
}
@ -125,16 +141,31 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
catch (final IOException e) {
throw new RuntimeException(e);
}
// TODO eliminate duplicate read of skin TXT!!
if (dataSource.has("war3mapSkin.txt")) {
try (InputStream miscDataTxtStream = dataSource.getResourceAsStream("war3mapSkin.txt")) {
skinsTable.readTXT(miscDataTxtStream, true);
}
catch (final IOException e) {
throw new RuntimeException(e);
}
}
final Element main = skinsTable.get("Main");
final String skinsField = main.getField("Skins");
final String[] skins = skinsField.split(",");
final Element defaultSkin = skinsTable.get("Default");
final Element userSkin = skinsTable.get(skins[skinIndex]);
final Element customSkin = skinsTable.get("CustomSkin");
for (final String key : defaultSkin.keySet()) {
if (!userSkin.hasField(key)) {
userSkin.setField(key, defaultSkin.getField(key));
}
}
if (customSkin != null) {
for (final String key : customSkin.keySet()) {
userSkin.setField(key, customSkin.getField(key));
}
}
return userSkin;
}
@ -252,6 +283,17 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
}
inflatedFrame = simpleFrame;
}
else if ("SIMPLESTATUSBAR".equals(frameDefinition.getFrameType())) {
final boolean decorateFileNames = frameDefinition.has("DecorateFileNames")
|| ((parentDefinitionIfAvailable != null)
&& parentDefinitionIfAvailable.has("DecorateFileNames"));
final SimpleStatusBarFrame simpleStatusBarFrame = new SimpleStatusBarFrame(frameDefinition.getName(),
parent, decorateFileNames);
for (final FrameDefinition childDefinition : frameDefinition.getInnerFrames()) {
simpleStatusBarFrame.add(inflate(childDefinition, simpleStatusBarFrame, frameDefinition));
}
inflatedFrame = simpleStatusBarFrame;
}
else if ("SPRITE".equals(frameDefinition.getFrameType())) {
final SpriteFrame spriteFrame = new SpriteFrame(frameDefinition.getName(), parent, this.uiScene,
viewport2);
@ -448,6 +490,10 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
}
public Scene getUiScene() {
return uiScene;
return this.uiScene;
}
public FrameTemplateEnvironment getTemplates() {
return this.templates;
}
}

View File

@ -0,0 +1,39 @@
package com.etheller.warsmash.parsers.fdf.frames;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.datamodel.Vector4Definition;
public class SimpleStatusBarFrame extends AbstractUIFrame {
private final boolean decorateFileNames;
private final TextureFrame barFrame;
private final TextureFrame borderFrame;
public SimpleStatusBarFrame(final String name, final UIFrame parent, final boolean decorateFileNames) {
super(name, parent);
this.decorateFileNames = decorateFileNames;
this.barFrame = new TextureFrame(name + "Bar", this, decorateFileNames, new Vector4Definition(0, 1, 0, 1));
this.borderFrame = new TextureFrame(name + "Border", this, decorateFileNames,
new Vector4Definition(0, 1, 0, 1));
this.borderFrame.setSetAllPoints(true);
this.barFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, 0, 0));
this.barFrame.addSetPoint(new SetPoint(FramePoint.BOTTOMLEFT, this, FramePoint.BOTTOMLEFT, 0, 0));
add(this.barFrame);
add(this.borderFrame);
}
public boolean isDecorateFileNames() {
return this.decorateFileNames;
}
public void setValue(final float value) {
this.barFrame.setWidth(this.renderBounds.width * value);
}
public TextureFrame getBarFrame() {
return this.barFrame;
}
public TextureFrame getBorderFrame() {
return this.borderFrame;
}
}

View File

@ -9,9 +9,9 @@ public class AudioBufferSource {
}
public void start(final int value) {
public void start(final int value, final float volume, final float pitch) {
if (this.buffer != null) {
this.buffer.play(1);
this.buffer.play(volume, pitch, 0.0f);
}
}
}

View File

@ -22,328 +22,348 @@ import com.etheller.warsmash.viewer5.Texture;
import com.etheller.warsmash.viewer5.handlers.EmitterObject;
public class EventObjectEmitterObject extends GenericObject implements EmitterObject {
private static final class LoadGenericSoundCallback implements LoadGenericCallback {
private final String filename;
private static final class LoadGenericSoundCallback implements LoadGenericCallback {
private final String filename;
public LoadGenericSoundCallback(final String filename) {
this.filename = filename;
}
public LoadGenericSoundCallback(final String filename) {
this.filename = filename;
}
@Override
public Object call(final InputStream data) {
final FileHandle temp = new FileHandle(this.filename) {
@Override
public InputStream read() {
return data;
}
@Override
public Object call(final InputStream data) {
final FileHandle temp = new FileHandle(this.filename) {
@Override
public InputStream read() {
return data;
}
;
};
if (data != null) {
return Gdx.audio.newSound(temp);
} else {
System.err.println("Warning: missing sound file: " + this.filename);
return null;
}
}
}
;
};
if (data != null) {
return Gdx.audio.newSound(temp);
}
else {
System.err.println("Warning: missing sound file: " + this.filename);
return null;
}
}
}
private static final LoadGenericCallback mappedDataCallback = new LoadGenericCallback() {
private static final LoadGenericCallback mappedDataCallback = new LoadGenericCallback() {
@Override
public Object call(final InputStream data) {
final StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(data, "utf-8"))) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append("\n");
}
} catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (final IOException e) {
throw new RuntimeException(e);
}
return new MappedData(stringBuilder.toString());
}
};
@Override
public Object call(final InputStream data) {
final StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(data, "utf-8"))) {
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append("\n");
}
}
catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
catch (final IOException e) {
throw new RuntimeException(e);
}
return new MappedData(stringBuilder.toString());
}
};
private int geometryEmitterType = -1;
public final String type;
private final String id;
public final long[] keyFrames;
private long globalSequence = -1;
private final long[] defval = {1};
public MdxModel internalModel;
public Texture internalTexture;
public float[][] colors;
public float[] intervalTimes;
public float scale;
public int columns;
public int rows;
public float lifeSpan;
public int blendSrc;
public int blendDst;
public float[][] intervals;
public float distanceCutoff;
private float maxDistance;
public float minDistance;
private float pitch;
private float pitchVariance;
private float volume;
public List<Sound> decodedBuffers = new ArrayList<>();
/**
* If this is an SPL/UBR emitter object, ok will be set to true if the tables
* are loaded.
* <p>
* This is because, like the other geometry emitters, it is fine to use them
* even if the textures don't load.
* <p>
* The particles will simply be black.
*/
private boolean ok = false;
private int geometryEmitterType = -1;
public final String type;
private final String id;
public final long[] keyFrames;
private long globalSequence = -1;
private final long[] defval = { 1 };
public MdxModel internalModel;
public Texture internalTexture;
public float[][] colors;
public float[] intervalTimes;
public float scale;
public int columns;
public int rows;
public float lifeSpan;
public int blendSrc;
public int blendDst;
public float[][] intervals;
public float distanceCutoff;
private float maxDistance;
public float minDistance;
public float pitch;
public float pitchVariance;
public float volume;
public List<Sound> decodedBuffers = new ArrayList<>();
/**
* If this is an SPL/UBR emitter object, ok will be set to true if the tables
* are loaded.
* <p>
* This is because, like the other geometry emitters, it is fine to use them
* even if the textures don't load.
* <p>
* The particles will simply be black.
*/
private boolean ok = false;
public EventObjectEmitterObject(final MdxModel model,
final com.etheller.warsmash.parsers.mdlx.EventObject eventObject, final int index) {
super(model, eventObject, index);
public EventObjectEmitterObject(final MdxModel model,
final com.etheller.warsmash.parsers.mdlx.EventObject eventObject, final int index) {
super(model, eventObject, index);
final ModelViewer viewer = model.viewer;
final String name = eventObject.getName();
String type = name.substring(0, 3);
final String id = name.substring(4);
final ModelViewer viewer = model.viewer;
final String name = eventObject.getName();
String type = name.substring(0, 3);
final String id = name.substring(4);
// Same thing
if ("FPT".equals(type)) {
type = "SPL";
}
// Same thing
if ("FPT".equals(type)) {
type = "SPL";
}
if ("SPL".equals(type)) {
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPLAT;
} else if ("UBR".equals(type)) {
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_UBERSPLAT;
} else if ("SPN".equals(type)) {
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPN;
}
if ("SPL".equals(type)) {
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPLAT;
}
else if ("UBR".equals(type)) {
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_UBERSPLAT;
}
else if ("SPN".equals(type)) {
this.geometryEmitterType = GeometryEmitterFuncs.EMITTER_SPN;
}
this.type = type;
this.id = id;
this.keyFrames = eventObject.getKeyFrames();
this.type = type;
this.id = id;
this.keyFrames = eventObject.getKeyFrames();
final int globalSequenceId = eventObject.getGlobalSequenceId();
if (globalSequenceId != -1) {
this.globalSequence = model.getGlobalSequences().get(globalSequenceId);
}
final int globalSequenceId = eventObject.getGlobalSequenceId();
if (globalSequenceId != -1) {
this.globalSequence = model.getGlobalSequences().get(globalSequenceId);
}
final List<GenericResource> tables = new ArrayList<>();
final PathSolver pathSolver = model.pathSolver;
final Object solverParams = model.solverParams;
final List<GenericResource> tables = new ArrayList<>();
final PathSolver pathSolver = model.pathSolver;
final Object solverParams = model.solverParams;
if ("SPN".equals(type)) {
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SpawnData.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
} else if ("SPL".equals(type)) {
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SplatData.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
} else if ("UBR".equals(type)) {
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\UberSplatData.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
} else if ("SND".equals(type)) {
if (!model.reforged) {
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimLookups.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
}
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
} else {
// Units\Critters\BlackStagMale\BlackStagMale.mdx has an event object named
// "Point01".
return;
}
if ("SPN".equals(type)) {
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SpawnData.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
}
else if ("SPL".equals(type)) {
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\SplatData.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
}
else if ("UBR".equals(type)) {
tables.add(viewer.loadGeneric(pathSolver.solve("Splats\\UberSplatData.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
}
else if ("SND".equals(type)) {
if (!model.reforged) {
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimLookups.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
}
tables.add(viewer.loadGeneric(pathSolver.solve("UI\\SoundInfo\\AnimSounds.slk", solverParams).finalSrc,
FetchDataTypeName.SLK, mappedDataCallback));
}
else {
// Units\Critters\BlackStagMale\BlackStagMale.mdx has an event object named
// "Point01".
return;
}
// TODO I am scrapping some async stuff with promises here from the JS and
// calling load
this.load(tables);
}
// TODO I am scrapping some async stuff with promises here from the JS and
// calling load
this.load(tables);
}
private float getFloat(final MappedDataRow row, final String name) {
final Float x = (Float) row.get(name);
if (x == null) {
return Float.NaN;
} else {
return x.floatValue();
}
}
private float getFloat(final MappedDataRow row, final String name) {
final Float x = (Float) row.get(name);
if (x == null) {
return Float.NaN;
}
else {
return x.floatValue();
}
}
private int getInt(final MappedDataRow row, final String name) {
return getInt(row, name, Integer.MIN_VALUE);
}
private int getInt(final MappedDataRow row, final String name) {
return getInt(row, name, Integer.MIN_VALUE);
}
private int getInt(final MappedDataRow row, final String name, final int defaultValue) {
final Number x = (Number) row.get(name);
if (x == null) {
return defaultValue;
} else {
return x.intValue();
}
}
private int getInt(final MappedDataRow row, final String name, final int defaultValue) {
final Number x = (Number) row.get(name);
if (x == null) {
return defaultValue;
}
else {
return x.intValue();
}
}
private void load(final List<GenericResource> tables) {
final MappedData firstTable = (MappedData) tables.get(0).data;
if (firstTable == null) {
return;
}
final MappedDataRow row = firstTable.getRow(this.id.trim());
private void load(final List<GenericResource> tables) {
final MappedData firstTable = (MappedData) tables.get(0).data;
if (firstTable == null) {
return;
}
final MappedDataRow row = firstTable.getRow(this.id.trim());
if (row != null) {
final MdxModel model = this.model;
final ModelViewer viewer = model.viewer;
final PathSolver pathSolver = model.pathSolver;
if (row != null) {
final MdxModel model = this.model;
final ModelViewer viewer = model.viewer;
final PathSolver pathSolver = model.pathSolver;
if ("SPN".equals(this.type)) {
this.internalModel = (MdxModel) viewer.load(((String) row.get("Model")).replace(".mdl", ".mdx"),
pathSolver, model.solverParams);
if ("SPN".equals(this.type)) {
this.internalModel = (MdxModel) viewer.load(((String) row.get("Model")).replace(".mdl", ".mdx"),
pathSolver, model.solverParams);
if (this.internalModel != null) {
// TODO javascript async code removed here
if (this.internalModel != null) {
// TODO javascript async code removed here
// this.internalModel.whenLoaded((model) => this.ok = model.ok)
this.ok = this.internalModel.ok;
}
} else if ("SPL".equals(this.type) || "UBR".equals(this.type)) {
final String texturesExt = model.reforged ? ".dds" : ".blp";
this.ok = this.internalModel.ok;
}
}
else if ("SPL".equals(this.type) || "UBR".equals(this.type)) {
final String texturesExt = model.reforged ? ".dds" : ".blp";
this.internalTexture = (Texture) viewer.load(
"ReplaceableTextures\\Splats\\" + row.get("file") + texturesExt, pathSolver,
model.solverParams);
this.internalTexture = (Texture) viewer.load(
"ReplaceableTextures\\Splats\\" + row.get("file") + texturesExt, pathSolver,
model.solverParams);
this.scale = getFloat(row, "Scale");
this.colors = new float[][]{
{getFloat(row, "StartR"), getFloat(row, "StartG"), getFloat(row, "StartB"),
getFloat(row, "StartA")},
{getFloat(row, "MiddleR"), getFloat(row, "MiddleG"), getFloat(row, "MiddleB"),
getFloat(row, "MiddleA")},
{getFloat(row, "EndR"), getFloat(row, "EndG"), getFloat(row, "EndB"),
getFloat(row, "EndA")}};
this.scale = getFloat(row, "Scale");
this.colors = new float[][] {
{ getFloat(row, "StartR"), getFloat(row, "StartG"), getFloat(row, "StartB"),
getFloat(row, "StartA") },
{ getFloat(row, "MiddleR"), getFloat(row, "MiddleG"), getFloat(row, "MiddleB"),
getFloat(row, "MiddleA") },
{ getFloat(row, "EndR"), getFloat(row, "EndG"), getFloat(row, "EndB"),
getFloat(row, "EndA") } };
if ("SPL".equals(this.type)) {
this.columns = getInt(row, "Columns");
this.rows = getInt(row, "Rows");
this.lifeSpan = getFloat(row, "Lifespan") + getFloat(row, "Decay");
this.intervalTimes = new float[]{getFloat(row, "Lifespan"), getFloat(row, "Decay")};
this.intervals = new float[][]{
{getFloat(row, "UVLifespanStart"), getFloat(row, "UVLifespanEnd"),
getFloat(row, "LifespanRepeat")},
{getFloat(row, "UVDecayStart"), getFloat(row, "UVDecayEnd"),
getFloat(row, "DecayRepeat")},};
} else {
this.columns = 1;
this.rows = 1;
this.lifeSpan = getFloat(row, "BirthTime") + getFloat(row, "PauseTime") + getFloat(row, "Decay");
this.intervalTimes = new float[]{getFloat(row, "BirthTime"), getFloat(row, "PauseTime"),
getFloat(row, "Decay")};
}
if ("SPL".equals(this.type)) {
this.columns = getInt(row, "Columns");
this.rows = getInt(row, "Rows");
this.lifeSpan = getFloat(row, "Lifespan") + getFloat(row, "Decay");
this.intervalTimes = new float[] { getFloat(row, "Lifespan"), getFloat(row, "Decay") };
this.intervals = new float[][] {
{ getFloat(row, "UVLifespanStart"), getFloat(row, "UVLifespanEnd"),
getFloat(row, "LifespanRepeat") },
{ getFloat(row, "UVDecayStart"), getFloat(row, "UVDecayEnd"),
getFloat(row, "DecayRepeat") }, };
}
else {
this.columns = 1;
this.rows = 1;
this.lifeSpan = getFloat(row, "BirthTime") + getFloat(row, "PauseTime") + getFloat(row, "Decay");
this.intervalTimes = new float[] { getFloat(row, "BirthTime"), getFloat(row, "PauseTime"),
getFloat(row, "Decay") };
}
final int[] blendModes = FilterMode
.emitterFilterMode(com.etheller.warsmash.parsers.mdlx.ParticleEmitter2.FilterMode
.fromId(getInt(row, "BlendMode")));
final int[] blendModes = FilterMode
.emitterFilterMode(com.etheller.warsmash.parsers.mdlx.ParticleEmitter2.FilterMode
.fromId(getInt(row, "BlendMode")));
this.blendSrc = blendModes[0];
this.blendDst = blendModes[1];
this.blendSrc = blendModes[0];
this.blendDst = blendModes[1];
this.ok = true;
} else if ("SND".equals(this.type)) {
// Only load sounds if audio is enabled.
// This is mostly to save on bandwidth and loading time, especially when loading
// full maps.
if (viewer.audioEnabled) {
final MappedData animSounds = (MappedData) tables.get(1).data;
this.ok = true;
}
else if ("SND".equals(this.type)) {
// Only load sounds if audio is enabled.
// This is mostly to save on bandwidth and loading time, especially when loading
// full maps.
if (viewer.audioEnabled) {
final MappedData animSounds = (MappedData) tables.get(1).data;
final MappedDataRow animSoundsRow = animSounds.getRow((String) row.get("SoundLabel"));
final MappedDataRow animSoundsRow = animSounds.getRow((String) row.get("SoundLabel"));
if (animSoundsRow != null) {
this.distanceCutoff = getFloat(animSoundsRow, "DistanceCutoff");
this.maxDistance = getFloat(animSoundsRow, "MaxDistance");
this.minDistance = getFloat(animSoundsRow, "MinDistance");
this.pitch = getFloat(animSoundsRow, "Pitch");
this.pitchVariance = getFloat(animSoundsRow, "PitchVariance");
this.volume = getFloat(animSoundsRow, "Volume");
if (animSoundsRow != null) {
this.distanceCutoff = getFloat(animSoundsRow, "DistanceCutoff");
this.maxDistance = getFloat(animSoundsRow, "MaxDistance");
this.minDistance = getFloat(animSoundsRow, "MinDistance");
this.pitch = getFloat(animSoundsRow, "Pitch");
this.pitchVariance = getFloat(animSoundsRow, "PitchVariance");
this.volume = getFloat(animSoundsRow, "Volume") / 127f;
final String[] fileNames = ((String) animSoundsRow.get("FileNames")).split(",");
final GenericResource[] resources = new GenericResource[fileNames.length];
for (int i = 0; i < fileNames.length; i++) {
final String path = ((String) animSoundsRow.get("DirectoryBase")) + fileNames[i];
try {
final String pathString = pathSolver.solve(path, model.solverParams).finalSrc;
final GenericResource genericResource = viewer.loadGeneric(pathString,
FetchDataTypeName.ARRAY_BUFFER, new LoadGenericSoundCallback(pathString));
if (genericResource == null) {
System.err.println("Null sound: " + fileNames[i]);
}
resources[i] = genericResource;
} catch (final Exception exc) {
System.err.println("Failed to load sound: " + path);
exc.printStackTrace();
}
}
final String[] fileNames = ((String) animSoundsRow.get("FileNames")).split(",");
final GenericResource[] resources = new GenericResource[fileNames.length];
for (int i = 0; i < fileNames.length; i++) {
final String path = ((String) animSoundsRow.get("DirectoryBase")) + fileNames[i];
try {
final String pathString = pathSolver.solve(path, model.solverParams).finalSrc;
final GenericResource genericResource = viewer.loadGeneric(pathString,
FetchDataTypeName.ARRAY_BUFFER, new LoadGenericSoundCallback(pathString));
if (genericResource == null) {
System.err.println("Null sound: " + fileNames[i]);
}
resources[i] = genericResource;
}
catch (final Exception exc) {
System.err.println("Failed to load sound: " + path);
exc.printStackTrace();
}
}
// TODO JS async removed
for (final GenericResource resource : resources) {
if (resource != null) {
this.decodedBuffers.add((Sound) resource.data);
}
}
this.ok = true;
}
}
} else {
System.err.println("Unknown event object type: " + this.type + this.id);
}
} else {
System.err.println("Unknown event object ID: " + this.type + this.id);
}
}
// TODO JS async removed
for (final GenericResource resource : resources) {
if (resource != null) {
this.decodedBuffers.add((Sound) resource.data);
}
}
this.ok = true;
}
}
}
else {
System.err.println("Unknown event object type: " + this.type + this.id);
}
}
else {
System.err.println("Unknown event object ID: " + this.type + this.id);
}
}
public int getValue(final long[] out, final MdxComplexInstance instance) {
if (this.globalSequence != -1) {
public int getValue(final long[] out, final MdxComplexInstance instance) {
if (this.globalSequence != -1) {
return this.getValueAtTime(out, instance.counter % this.globalSequence, 0, this.globalSequence);
} else if (instance.sequence != -1) {
final long[] interval = this.model.getSequences().get(instance.sequence).getInterval();
return this.getValueAtTime(out, instance.counter % this.globalSequence, 0, this.globalSequence);
}
else if (instance.sequence != -1) {
final long[] interval = this.model.getSequences().get(instance.sequence).getInterval();
return this.getValueAtTime(out, instance.frame, interval[0], interval[1]);
} else {
out[0] = this.defval[0];
return this.getValueAtTime(out, instance.frame, interval[0], interval[1]);
}
else {
out[0] = this.defval[0];
return -1;
}
}
return -1;
}
}
public int getValueAtTime(final long[] out, final long frame, final long start, final long end) {
if ((frame >= start) && (frame <= end)) {
for (int i = this.keyFrames.length - 1; i > -1; i--) {
if (this.keyFrames[i] < start) {
out[0] = 0;
public int getValueAtTime(final long[] out, final long frame, final long start, final long end) {
if ((frame >= start) && (frame <= end)) {
for (int i = this.keyFrames.length - 1; i > -1; i--) {
if (this.keyFrames[i] < start) {
out[0] = 0;
return i;
} else if (this.keyFrames[i] <= frame) {
out[0] = 1;
return i;
}
else if (this.keyFrames[i] <= frame) {
out[0] = 1;
return i;
}
}
}
return i;
}
}
}
out[0] = 0;
out[0] = 0;
return -1;
}
return -1;
}
@Override
public boolean ok() {
return this.ok;
}
@Override
public boolean ok() {
return this.ok;
}
@Override
public int getGeometryEmitterType() {
return this.geometryEmitterType;
}
@Override
public int getGeometryEmitterType() {
return this.geometryEmitterType;
}
}

View File

@ -47,7 +47,9 @@ public class EventObjectSnd extends EmittedObject<MdxComplexInstance, EventObjec
source.connect(panner);
// Make a sound.
source.start(0);
source.start(0, emitterObject.volume,
(emitterObject.pitch + ((float) Math.random() * emitterObject.pitchVariance * 2))
- emitterObject.pitchVariance);
}
}

View File

@ -22,15 +22,15 @@ public final class UnitAckSound {
private final List<Sound> sounds = new ArrayList<>();
private final float volume;
private final float pitch;
private final float pitchVariation;
private final float pitchVariance;
private final float minDistance;
private final float maxDistance;
private final float distanceCutoff;
private Sound lastPlayedSound;
public static UnitAckSound create(final DataSource dataSource, final DataTable unitAckSounds, final String soundName,
final String soundType) {
public static UnitAckSound create(final DataSource dataSource, final DataTable unitAckSounds,
final String soundName, final String soundType) {
final Element row = unitAckSounds.get(soundName + soundType);
if (row == null) {
return SILENT;
@ -40,13 +40,17 @@ public final class UnitAckSound {
if ((directoryBase.length() > 1) && !directoryBase.endsWith("\\")) {
directoryBase += "\\";
}
final float volume = row.getFieldFloatValue("Volume");
final float volume = row.getFieldFloatValue("Volume") / 127f;
final float pitch = row.getFieldFloatValue("Pitch");
final float pitchVariation = row.getFieldFloatValue("PitchVariance");
float pitchVariance = row.getFieldFloatValue("PitchVariance");
if (pitchVariance == 1.0f) {
pitchVariance = 0.0f;
}
final float minDistance = row.getFieldFloatValue("MinDistance");
final float maxDistance = row.getFieldFloatValue("MaxDistance");
final float distanceCutoff = row.getFieldFloatValue("DistanceCutoff");
final UnitAckSound sound = new UnitAckSound(volume, pitch, pitchVariation, minDistance, maxDistance, distanceCutoff);
final UnitAckSound sound = new UnitAckSound(volume, pitch, pitchVariance, minDistance, maxDistance,
distanceCutoff);
for (final String fileName : fileNames.split(",")) {
String filePath = directoryBase + fileName;
if (!filePath.toLowerCase().endsWith(".wav")) {
@ -63,7 +67,7 @@ public final class UnitAckSound {
final float maxDistance, final float distanceCutoff) {
this.volume = volume;
this.pitch = pitch;
this.pitchVariation = pitchVariation;
this.pitchVariance = pitchVariation;
this.minDistance = minDistance;
this.maxDistance = maxDistance;
this.distanceCutoff = distanceCutoff;
@ -96,7 +100,8 @@ public final class UnitAckSound {
source.connect(panner);
// Make a sound.
source.start(0);
source.start(0, this.volume,
(this.pitch + ((float) Math.random() * this.pitchVariance * 2)) - this.pitchVariance);
this.lastPlayedSound = source.buffer;
final float duration = Extensions.soundLengthExtension.getDuration(this.lastPlayedSound);
unit.lastUnitResponseEndTimeMillis = millisTime + (long) (1000 * duration);

View File

@ -22,7 +22,7 @@ public final class UnitSound {
private final List<Sound> sounds = new ArrayList<>();
private final float volume;
private final float pitch;
private final float pitchVariation;
private final float pitchVariance;
private final float minDistance;
private final float maxDistance;
private final float distanceCutoff;
@ -40,13 +40,16 @@ public final class UnitSound {
if ((directoryBase.length() > 1) && !directoryBase.endsWith("\\")) {
directoryBase += "\\";
}
final float volume = row.getFieldFloatValue("Volume");
final float volume = row.getFieldFloatValue("Volume") / 127f;
final float pitch = row.getFieldFloatValue("Pitch");
final float pitchVariation = row.getFieldFloatValue("PitchVariance");
float pitchVariance = row.getFieldFloatValue("PitchVariance");
if (pitchVariance == 1.0f) {
pitchVariance = 0.0f;
}
final float minDistance = row.getFieldFloatValue("MinDistance");
final float maxDistance = row.getFieldFloatValue("MaxDistance");
final float distanceCutoff = row.getFieldFloatValue("DistanceCutoff");
final UnitSound sound = new UnitSound(volume, pitch, pitchVariation, minDistance, maxDistance, distanceCutoff);
final UnitSound sound = new UnitSound(volume, pitch, pitchVariance, minDistance, maxDistance, distanceCutoff);
for (final String fileName : fileNames.split(",")) {
String filePath = directoryBase + fileName;
if (!filePath.toLowerCase().endsWith(".wav")) {
@ -63,7 +66,7 @@ public final class UnitSound {
final float maxDistance, final float distanceCutoff) {
this.volume = volume;
this.pitch = pitch;
this.pitchVariation = pitchVariation;
this.pitchVariance = pitchVariation;
this.minDistance = minDistance;
this.maxDistance = maxDistance;
this.distanceCutoff = distanceCutoff;
@ -112,7 +115,8 @@ public final class UnitSound {
source.connect(panner);
// Make a sound.
source.start(0);
source.start(0, this.volume,
(this.pitch + ((float) Math.random() * this.pitchVariance * 2)) - this.pitchVariance);
this.lastPlayedSound = source.buffer;
return true;
}

View File

@ -12,10 +12,13 @@ import com.etheller.warsmash.util.RenderMathUtils;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
import com.etheller.warsmash.viewer5.handlers.w3x.*;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSoundset;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
@ -64,7 +67,6 @@ public class RenderUnit {
private boolean corpse;
private boolean boneCorpse;
private final RenderUnitTypeData typeData;
public UnitSound buildSound;
public RenderUnit(final War3MapViewer map, final MdxModel model, final MutableGameObject row, final float x,
final float y, final float z, final int playerIndex, final UnitSoundset soundset,
@ -127,7 +129,6 @@ public class RenderUnit {
final float blendTime = row.getFieldAsFloat(BLEND_TIME, 0);
instance.setBlendTime(blendTime * 1000.0f);
buildSound = map.getUiSounds().getSound(row.getFieldAsString(BUILD_SOUND_LABEL, 0));
}
this.instance = instance;
@ -350,8 +351,9 @@ public class RenderUnit {
this.selectionCircle.move(dx, dy, map.terrain.centerOffset);
}
this.unitAnimationListenerImpl.update();
if(!dead && simulationUnit.isConstructing()) {
instance.setFrameByRatio(simulationUnit.getConstructionProgress() / simulationUnit.getUnitType().getBuildTime());
if (!dead && this.simulationUnit.isConstructing()) {
this.instance.setFrameByRatio(
this.simulationUnit.getConstructionProgress() / this.simulationUnit.getUnitType().getBuildTime());
}
}

View File

@ -50,6 +50,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
this.activeHighlightFrame.setVisible(false);
this.cooldownFrame.setVisible(false);
this.autocastFrame.setVisible(false);
setVisible(false);
}
else {
if (commandButton.isEnabled()) {
@ -74,6 +75,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
public void setCommandButtonData(final Texture texture, final int abilityHandleId, final int orderId,
final int autoCastOrderId, final boolean active, final boolean autoCastActive, final boolean menuButton) {
this.menuButton = menuButton;
setVisible(true);
this.iconFrame.setVisible(true);
this.activeHighlightFrame.setVisible(active);
this.cooldownFrame.setVisible(false);
@ -113,7 +115,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (this.renderBounds.contains(screenX, screenY)) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
return this;
}
return super.touchDown(screenX, screenY, button);
@ -121,7 +123,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
if (this.renderBounds.contains(screenX, screenY)) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
return this;
}
return super.touchUp(screenX, screenY, button);