TestUI and FDFTest as well as small jass updates

This commit is contained in:
Retera 2021-12-09 17:04:58 -05:00
parent 38f67af599
commit f54b74ba0f
12 changed files with 1360 additions and 281 deletions

View File

@ -0,0 +1,868 @@
package com.etheller.warsmash;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.util.DataSourceFileHandle;
import com.etheller.warsmash.util.ImageUtils;
import com.etheller.warsmash.util.StringBundle;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.Camera;
import com.etheller.warsmash.viewer5.CanvasProvider;
import com.etheller.warsmash.viewer5.Model;
import com.etheller.warsmash.viewer5.ModelInstance;
import com.etheller.warsmash.viewer5.ModelViewer;
import com.etheller.warsmash.viewer5.PathSolver;
import com.etheller.warsmash.viewer5.RenderBatch;
import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.SolvedPath;
import com.etheller.warsmash.viewer5.TextureMapper;
import com.etheller.warsmash.viewer5.handlers.ModelHandler;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxHandler;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
import com.etheller.warsmash.viewer5.handlers.mdx.Sequence;
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.TestUI;
public class WarsmashGdxFDFTestRenderScreen implements InputProcessor, Screen, SingleModelScreen {
private static final boolean ENABLE_AUDIO = true;
private DataSource codebase;
private MdxViewer viewer;
private MdxModel model;
private CameraManager cameraManager;
private final Rectangle tempRect = new Rectangle();
// libGDX stuff
private OrthographicCamera uiCamera;
private SpriteBatch batch;
private Viewport uiViewport;
private GlyphLayout glyphLayout;
private final DataTable warsmashIni;
private Scene uiScene;
private Texture solidGreenTexture;
private TestUI menuUI;
private final WarsmashGdxMultiScreenGame game;
private Music currentMusic;
private boolean hasPlayedStandHack = false;
private boolean loaded = false;
private final String finalFileToLoad;
public WarsmashGdxFDFTestRenderScreen(final DataTable warsmashIni, final WarsmashGdxMultiScreenGame game,
final String finalFileToLoad) {
this.warsmashIni = warsmashIni;
this.game = game;
this.finalFileToLoad = finalFileToLoad;
}
@Override
public void show() {
if (!this.loaded) {
this.loaded = true;
final ByteBuffer tempByteBuffer = ByteBuffer.allocateDirect(4);
tempByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
final IntBuffer temp = tempByteBuffer.asIntBuffer();
//
Gdx.gl30.glGenVertexArrays(1, temp);
WarsmashGdxGame.VAO = temp.get(0);
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
System.err.println("Renderer: " + renderer);
this.codebase = WarsmashGdxMapScreen.parseDataSources(this.warsmashIni);
this.viewer = new MdxViewer(this.codebase, this.game, Vector3.Zero);
this.viewer.addHandler(new MdxHandler());
this.viewer.enableAudio();
this.scene = this.viewer.addSimpleScene();
this.scene.enableAudio();
this.uiScene = this.viewer.addSimpleScene();
this.uiScene.alpha = true;
if (ENABLE_AUDIO) {
this.uiScene.enableAudio();
}
final int width = Gdx.graphics.getWidth();
final int height = Gdx.graphics.getHeight();
this.glyphLayout = new GlyphLayout();
// Constructs a new OrthographicCamera, using the given viewport width and
// height
// Height is multiplied by aspect ratio.
this.uiCamera = new OrthographicCamera();
int aspect3By4Width;
int aspect3By4Height;
if (width < ((height * 4) / 3)) {
aspect3By4Width = width;
aspect3By4Height = (width * 3) / 4;
}
else {
aspect3By4Width = (height * 4) / 3;
aspect3By4Height = height;
}
this.uiViewport = new FitViewport(aspect3By4Width, aspect3By4Height, this.uiCamera);
this.uiViewport.update(width, height);
this.uiCamera.position.set(this.getMinWorldWidth() / 2, this.getMinWorldHeight() / 2, 0);
this.uiCamera.update();
this.batch = new SpriteBatch();
this.solidGreenTexture = ImageUtils.getAnyExtensionTexture(this.viewer.dataSource,
"ReplaceableTextures\\TeamColor\\TeamColor06.blp");
this.cameraManager = new CameraManager();
this.cameraManager.setupCamera(this.scene);
System.out.println("Loaded");
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1);
final DataTable musicSLK = new DataTable(StringBundle.EMPTY);
final String musicSLKPath = "UI\\SoundInfo\\Music.SLK";
if (this.viewer.dataSource.has(musicSLKPath)) {
try (InputStream miscDataTxtStream = this.viewer.dataSource.getResourceAsStream(musicSLKPath)) {
musicSLK.readSLK(miscDataTxtStream);
}
catch (final IOException e) {
e.printStackTrace();
}
}
this.menuUI = new TestUI(this.viewer.dataSource, this.uiViewport, this.uiScene, this.viewer, this.game,
this, this.warsmashIni, new RootFrameListener() {
@Override
public void onCreate(final GameUI rootFrame) {
// WarsmashGdxMapGame.this.viewer.setGameUI(rootFrame);
if (WarsmashConstants.ENABLE_MUSIC) {
final String musicField = rootFrame
.getSkinField("GlueMusic_V" + WarsmashConstants.GAME_VERSION);
final String[] musics = musicField.split(";");
String musicPath = musics[(int) (Math.random() * musics.length)];
if (musicSLK.get(musicPath) != null) {
musicPath = musicSLK.get(musicPath).getField("FileNames");
}
final String[] moreSplitMusics = musicPath.split(",");
final String finalMusicPath = moreSplitMusics[(int) (Math.random()
* moreSplitMusics.length)];
final Music music = Gdx.audio.newMusic(new DataSourceFileHandle(
WarsmashGdxFDFTestRenderScreen.this.viewer.dataSource, finalMusicPath));
// music.setVolume(0.2f);
music.setLooping(true);
music.play();
WarsmashGdxFDFTestRenderScreen.this.currentMusic = music;
}
WarsmashGdxFDFTestRenderScreen.this
.singleModelScene(WarsmashGdxFDFTestRenderScreen.this.scene,
War3MapViewer.mdx(rootFrame.getSkinField(
"GlueSpriteLayerBackground_V" + WarsmashConstants.GAME_VERSION)),
"Stand");
WarsmashGdxFDFTestRenderScreen.this.modelCamera = WarsmashGdxFDFTestRenderScreen.this.mainModel.cameras
.get(0);
}
}, this.finalFileToLoad);
final ModelInstance libgdxContentInstance = new LibGDXContentLayerModel(null, this.viewer, "",
PathSolver.DEFAULT, "").addInstance();
libgdxContentInstance.setLocation(0f, 0f, -0.5f);
libgdxContentInstance.setScene(this.uiScene);
this.menuUI.main();
this.updateUIScene();
this.resize(width, height);
}
Gdx.input.setInputProcessor(this);
if (this.currentMusic != null) {
this.currentMusic.play();
}
}
private float getMinWorldWidth() {
if (this.uiViewport instanceof ExtendViewport) {
return ((ExtendViewport) this.uiViewport).getMinWorldWidth();
}
return this.uiViewport.getWorldWidth();
}
private float getMinWorldHeight() {
if (this.uiViewport instanceof ExtendViewport) {
return ((ExtendViewport) this.uiViewport).getMinWorldHeight();
}
return this.uiViewport.getWorldHeight();
}
private void updateUIScene() {
this.tempRect.x = this.uiViewport.getScreenX();
this.tempRect.y = this.uiViewport.getScreenY();
this.tempRect.width = this.uiViewport.getScreenWidth();
this.tempRect.height = this.uiViewport.getScreenHeight();
this.uiScene.camera.viewport(this.tempRect);
final float worldWidth = this.uiViewport.getWorldWidth();
final float worldHeight = this.uiViewport.getWorldHeight();
final float xScale = worldWidth / this.getMinWorldWidth();
final float yScale = worldHeight / this.getMinWorldHeight();
final float uiSceneWidth = 0.8f * xScale;
final float uiSceneHeight = 0.6f * yScale;
final float uiSceneX = (0.8f - uiSceneWidth) / 2;
final float uiSceneY = (0.6f - uiSceneHeight) / 2;
this.uiScene.camera.ortho(uiSceneX, uiSceneWidth + uiSceneX, uiSceneY, uiSceneHeight + uiSceneY, -1024f, 1024);
}
private void makeDruidSquare(final Scene scene) {
final MdxModel model2 = (MdxModel) this.viewer.load("units\\nightelf\\druidoftheclaw\\druidoftheclaw.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
this.makePerfectSquare(scene, model2, 15);
}
private void singleAcolyteScene(final Scene scene) {
final MdxModel model2 = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx", new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
instance3.setScene(scene);
int animIndex = 0;
for (final Sequence s : model2.getSequences()) {
if (s.getName().toLowerCase().startsWith("stand work")) {
animIndex = model2.getSequences().indexOf(s);
}
}
instance3.setSequence(animIndex);
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
}
private void singleModelScene(final Scene scene, final String path, final String animName) {
final MdxModel model2 = (MdxModel) this.viewer.load(path, new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
instance3.setScene(scene);
int animIndex = 0;
for (final Sequence s : model2.getSequences()) {
if (s.getName().toLowerCase().startsWith(animName)) {
animIndex = model2.getSequences().indexOf(s);
break;
}
}
instance3.setSequence(animIndex);
instance3.setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP);
this.mainInstance = instance3;
this.mainModel = model2;
}
@Override
public void setModel(final String path) {
if (this.mainInstance != null) {
this.mainInstance.detach();
}
if (path == null) {
this.modelCamera = null;
this.mainInstance = null;
this.mainModel = null;
}
else {
this.singleModelScene(this.scene, War3MapViewer.mdx(path), "birth");
WarsmashGdxFDFTestRenderScreen.this.modelCamera = WarsmashGdxFDFTestRenderScreen.this.mainModel.cameras
.get(0);
// this hack is because we only have the queued animation system in RenderWidget
// which is stupid and back and needs to get moved to the model instance
// itself... our model instance class is a
// hacky replica of a model viewer tool with a bunch of irrelevant loop type
// settings instead of what it should be
this.hasPlayedStandHack = false;
}
}
private void acolytesHarvestingScene(final Scene scene) {
final MdxModel acolyteModel = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxModel mineEffectModel = (MdxModel) this.viewer
.load("abilities\\spells\\undead\\undeadmine\\undeadminecircle.mdx", new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
for (int i = 0; i < 5; i++) {
final MdxComplexInstance acolyteInstance = (MdxComplexInstance) acolyteModel.addInstance(0);
acolyteInstance.setScene(scene);
int animIndex = i % acolyteModel.getSequences().size();
for (final Sequence s : acolyteModel.getSequences()) {
if (s.getName().toLowerCase().startsWith("stand work")) {
animIndex = acolyteModel.getSequences().indexOf(s);
}
}
acolyteInstance.setSequence(animIndex);
acolyteInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
final double angle = ((Math.PI * 2) / 5) * i;
acolyteInstance.localLocation.x = (float) Math.cos(angle) * 256;
acolyteInstance.localLocation.y = (float) Math.sin(angle) * 256;
acolyteInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle + Math.PI));
final MdxComplexInstance effectInstance = (MdxComplexInstance) mineEffectModel.addInstance(0);
effectInstance.setScene(scene);
effectInstance.setSequence(1);
effectInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
effectInstance.localLocation.x = (float) Math.cos(angle) * 256;
effectInstance.localLocation.y = (float) Math.sin(angle) * 256;
effectInstance.localRotation.setFromAxisRad(0, 0, 1, (float) angle);
}
final MdxModel mineModel = (MdxModel) this.viewer.load("buildings\\undead\\hauntedmine\\hauntedmine.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxComplexInstance mineInstance = (MdxComplexInstance) mineModel.addInstance(0);
mineInstance.setScene(scene);
mineInstance.setSequence(2);
mineInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
}
private void acolytesHarvestingSceneJoke2(final Scene scene) {
final MdxModel acolyteModel = (MdxModel) this.viewer.load("units\\undead\\acolyte\\acolyte.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxModel mineEffectModel = (MdxModel) this.viewer
.load("abilities\\spells\\undead\\undeadmine\\undeadminecircle.mdx", new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
for (int i = 0; i < 5; i++) {
final MdxComplexInstance acolyteInstance = (MdxComplexInstance) acolyteModel.addInstance(0);
acolyteInstance.setScene(scene);
int animIndex = i % acolyteModel.getSequences().size();
for (final Sequence s : acolyteModel.getSequences()) {
if (s.getName().toLowerCase().startsWith("stand work")) {
animIndex = acolyteModel.getSequences().indexOf(s);
}
}
acolyteInstance.setSequence(animIndex);
acolyteInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
final double angle = ((Math.PI * 2) / 5) * i;
acolyteInstance.localLocation.x = (float) Math.cos(angle) * 256;
acolyteInstance.localLocation.y = (float) Math.sin(angle) * 256;
acolyteInstance.localRotation.setFromAxisRad(0, 0, 1, (float) (angle + Math.PI));
final MdxComplexInstance effectInstance = (MdxComplexInstance) mineEffectModel.addInstance(0);
effectInstance.setScene(scene);
effectInstance.setSequence(1);
effectInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
effectInstance.localLocation.x = (float) Math.cos(angle) * 256;
effectInstance.localLocation.y = (float) Math.sin(angle) * 256;
effectInstance.localRotation.setFromAxisRad(0, 0, 1, (float) angle);
}
final MdxModel mineModel = (MdxModel) this.viewer.load("units\\orc\\spiritwolf\\spiritwolf.mdx",
new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxComplexInstance mineInstance = (MdxComplexInstance) mineModel.addInstance(0);
mineInstance.setScene(scene);
mineInstance.setSequence(0);
mineInstance.localScale.x = 2;
mineInstance.localScale.y = 2;
mineInstance.localScale.z = 2;
mineInstance.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
final MdxModel mineModel2 = (MdxModel) this.viewer
.load("abilities\\spells\\undead\\unsummon\\unsummontarget.mdx", new PathSolver() {
@Override
public SolvedPath solve(final String src, final Object solverParams) {
return new SolvedPath(src, src.substring(src.lastIndexOf('.')), true);
}
}, null);
final MdxComplexInstance mineInstance2 = (MdxComplexInstance) mineModel2.addInstance(0);
mineInstance2.setScene(scene);
mineInstance2.setSequence(0);
mineInstance2.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
}
private void makeFourHundred(final Scene scene, final MdxModel model2) {
for (int i = 0; i < 400; i++) {
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
instance3.localLocation.x = ((i % 20) - 10) * 128;
instance3.localLocation.y = ((i / 20) - 10) * 128;
instance3.setScene(scene);
final int animIndex = i % model2.getSequences().size();
instance3.setSequence(animIndex);
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
}
}
private void makePerfectSquare(final Scene scene, final MdxModel model2, final int n) {
final int n2 = n * n;
for (int i = 0; i < n2; i++) {
final MdxComplexInstance instance3 = (MdxComplexInstance) model2.addInstance(0);
instance3.localLocation.x = ((i % n) - (n / 2)) * 128;
instance3.localLocation.y = ((i / n) - (n / 2)) * 128;
instance3.setScene(scene);
final int animIndex = i % model2.getSequences().size();
instance3.setSequence(animIndex);
instance3.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
}
}
public static void bindDefaultVertexArray() {
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
}
private final int frame = 0;
private MdxComplexInstance mainInstance;
private MdxModel mainModel;
private com.etheller.warsmash.viewer5.handlers.mdx.Camera modelCamera;
private final float[] cameraPositionTemp = new float[3];
private final float[] cameraTargetTemp = new float[3];
private final boolean firstFrame = true;
private Scene scene;
@Override
public void render(final float delta) {
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
final float deltaTime = Gdx.graphics.getDeltaTime();
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
this.cameraManager.updateCamera();
this.menuUI.update(deltaTime);
if ((this.mainInstance != null) && this.mainInstance.sequenceEnded
&& (((this.mainModel.getSequences().get(this.mainInstance.sequence).getFlags() & 0x1) == 0)
|| !this.hasPlayedStandHack)) {
SequenceUtils.randomStandSequence(this.mainInstance);
this.hasPlayedStandHack = true;
}
this.viewer.updateAndRender();
Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST);
Gdx.gl30.glDisable(GL30.GL_CULL_FACE);
this.viewer.webGL.useShaderProgram(null);
Gdx.gl30.glActiveTexture(GL30.GL_TEXTURE0);
}
@Override
public void dispose() {
this.menuUI.dispose();
}
@Override
public void resize(final int width, final int height) {
this.tempRect.width = width;
this.tempRect.height = height;
final float fourThirdsHeight = (this.tempRect.height * 4) / 3;
if (fourThirdsHeight < this.tempRect.width) {
final float dx = this.tempRect.width - fourThirdsHeight;
this.tempRect.width = fourThirdsHeight;
this.tempRect.x = dx / 2;
}
else {
final float threeFourthsWidth = (this.tempRect.width * 3) / 4;
if (threeFourthsWidth < this.tempRect.height) {
final float dy = this.tempRect.height - threeFourthsWidth;
this.tempRect.height = threeFourthsWidth;
this.tempRect.y = dy;
}
}
this.cameraManager.camera.viewport(this.tempRect);
// super.resize(width, height);
this.uiViewport.update(width, height);
this.uiCamera.position.set(this.getMinWorldWidth() / 2, this.getMinWorldHeight() / 2, 0);
this.menuUI.resize();
this.updateUIScene();
}
class CameraManager {
private CanvasProvider canvas;
private Camera camera;
private float moveSpeed;
private float rotationSpeed;
private float zoomFactor;
private float horizontalAngle;
private float verticalAngle;
private float distance;
private Vector3 position;
private Vector3 target;
private Vector3 worldUp;
private Vector3 vecHeap;
private Vector3 vecHeap2;
private Quaternion quatHeap;
private Quaternion quatHeap2;
// An orbit camera setup example.
// Left mouse button controls the orbit itself.
// The right mouse button allows to move the camera and the point it's looking
// at on the XY plane.
// Scrolling zooms in and out.
private void setupCamera(final Scene scene) {
this.canvas = scene.viewer.canvas;
this.camera = scene.camera;
this.moveSpeed = 2;
this.rotationSpeed = (float) (Math.PI / 180);
this.zoomFactor = 0.1f;
this.horizontalAngle = (float) (Math.PI / 2);
this.verticalAngle = (float) (Math.PI / 4);
this.distance = 500;
this.position = new Vector3();
this.target = new Vector3(0, 0, 50);
this.worldUp = new Vector3(0, 0, 1);
this.vecHeap = new Vector3();
this.vecHeap2 = new Vector3();
this.quatHeap = new Quaternion();
this.quatHeap2 = new Quaternion();
this.updateCamera();
// cameraUpdate();
}
private void updateCamera() {
// Limit the vertical angle so it doesn't flip.
// Since the camera uses a quaternion, flips don't matter to it, but this feels
// better.
this.verticalAngle = (float) Math.min(Math.max(0.01, this.verticalAngle), Math.PI - 0.01);
this.quatHeap.idt();
this.quatHeap.setFromAxisRad(0, 0, 1, this.horizontalAngle);
this.quatHeap2.idt();
this.quatHeap2.setFromAxisRad(1, 0, 0, this.verticalAngle);
this.quatHeap.mul(this.quatHeap2);
this.position.set(0, 0, 1);
this.quatHeap.transform(this.position);
this.position.scl(this.distance);
this.position = this.position.add(this.target);
if (WarsmashGdxFDFTestRenderScreen.this.modelCamera != null) {
WarsmashGdxFDFTestRenderScreen.this.modelCamera.getPositionTranslation(
WarsmashGdxFDFTestRenderScreen.this.cameraPositionTemp,
WarsmashGdxFDFTestRenderScreen.this.mainInstance.sequence,
WarsmashGdxFDFTestRenderScreen.this.mainInstance.frame,
WarsmashGdxFDFTestRenderScreen.this.mainInstance.counter);
WarsmashGdxFDFTestRenderScreen.this.modelCamera.getTargetTranslation(
WarsmashGdxFDFTestRenderScreen.this.cameraTargetTemp,
WarsmashGdxFDFTestRenderScreen.this.mainInstance.sequence,
WarsmashGdxFDFTestRenderScreen.this.mainInstance.frame,
WarsmashGdxFDFTestRenderScreen.this.mainInstance.counter);
this.position.set(WarsmashGdxFDFTestRenderScreen.this.modelCamera.position);
this.target.set(WarsmashGdxFDFTestRenderScreen.this.modelCamera.targetPosition);
// this.vecHeap2.set(this.target);
// this.vecHeap2.sub(this.position);
// this.vecHeap.set(this.vecHeap2);
// this.vecHeap.crs(this.worldUp);
// this.vecHeap.crs(this.vecHeap2);
// this.vecHeap.nor();
// this.vecHeap.scl(this.camera.rect.height / 2f);
// this.position.add(this.vecHeap);
this.position.add(WarsmashGdxFDFTestRenderScreen.this.cameraPositionTemp[0],
WarsmashGdxFDFTestRenderScreen.this.cameraPositionTemp[1],
WarsmashGdxFDFTestRenderScreen.this.cameraPositionTemp[2]);
this.target.add(WarsmashGdxFDFTestRenderScreen.this.cameraTargetTemp[0],
WarsmashGdxFDFTestRenderScreen.this.cameraTargetTemp[1],
WarsmashGdxFDFTestRenderScreen.this.cameraTargetTemp[2]);
this.camera.perspective(WarsmashGdxFDFTestRenderScreen.this.modelCamera.fieldOfView * 0.6f,
this.camera.rect.width / this.camera.rect.height,
WarsmashGdxFDFTestRenderScreen.this.modelCamera.nearClippingPlane,
WarsmashGdxFDFTestRenderScreen.this.modelCamera.farClippingPlane);
}
else {
this.camera.perspective(70, this.camera.getAspect(), 100, 5000);
}
this.camera.moveToAndFace(this.position, this.target, this.worldUp);
}
// private void cameraUpdate() {
//
// }
}
public DataSource getCodebase() {
return this.codebase;
}
@Override
public boolean keyDown(final int keycode) {
return this.menuUI.keyDown(keycode);
}
@Override
public boolean keyUp(final int keycode) {
return this.menuUI.keyUp(keycode);
}
@Override
public boolean keyTyped(final char character) {
return this.menuUI.keyTyped(character);
}
@Override
public boolean touchDown(final int screenX, final int screenY, final int pointer, final int button) {
final float worldScreenY = this.game.getHeight() - screenY;
if (this.menuUI.touchDown(screenX, screenY, worldScreenY, button)) {
return false;
}
return false;
}
@Override
public boolean touchUp(final int screenX, final int screenY, final int pointer, final int button) {
final float worldScreenY = this.game.getHeight() - screenY;
if (this.menuUI.touchUp(screenX, screenY, worldScreenY, button)) {
return false;
}
return false;
}
@Override
public boolean touchDragged(final int screenX, final int screenY, final int pointer) {
final float worldScreenY = this.game.getHeight() - screenY;
if (this.menuUI.touchDragged(screenX, screenY, worldScreenY, pointer)) {
return false;
}
return false;
}
@Override
public boolean mouseMoved(final int screenX, final int screenY) {
final float worldScreenY = this.game.getHeight() - screenY;
if (this.menuUI.mouseMoved(screenX, screenY, worldScreenY)) {
return false;
}
return false;
}
@Override
public boolean scrolled(final int amount) {
// TODO Auto-generated method stub
return false;
}
private void renderLibGDXContent() {
Gdx.gl30.glDisable(GL30.GL_SCISSOR_TEST);
Gdx.gl30.glDisable(GL30.GL_CULL_FACE);
this.viewer.webGL.useShaderProgram(null);
Gdx.gl30.glActiveTexture(GL30.GL_TEXTURE0);
this.uiViewport.apply();
this.batch.setProjectionMatrix(this.uiCamera.combined);
this.batch.begin();
this.menuUI.render(this.batch, this.glyphLayout);
this.batch.end();
Gdx.gl30.glEnable(GL30.GL_SCISSOR_TEST);
Gdx.gl30.glBindVertexArray(WarsmashGdxGame.VAO);
}
private class LibGDXContentLayerModelInstance extends ModelInstance {
public LibGDXContentLayerModelInstance(final Model model) {
super(model);
}
@Override
public void updateAnimations(final float dt) {
}
@Override
public void clearEmittedObjects() {
}
@Override
protected void updateLights(final Scene scene2) {
}
@Override
public void renderOpaque(final Matrix4 mvp) {
}
@Override
public void renderTranslucent() {
WarsmashGdxFDFTestRenderScreen.this.renderLibGDXContent();
}
@Override
public void load() {
}
@Override
protected RenderBatch getBatch(final TextureMapper textureMapper2) {
throw new UnsupportedOperationException("NOT API");
}
@Override
public void setReplaceableTexture(final int replaceableTextureId, final String replaceableTextureFile) {
}
@Override
public boolean isBatched() {
return super.isBatched();
}
@Override
protected void removeLights(final Scene scene2) {
// TODO Auto-generated method stub
}
}
private class LibGDXContentLayerModel extends Model {
public LibGDXContentLayerModel(final ModelHandler handler, final ModelViewer viewer, final String extension,
final PathSolver pathSolver, final String fetchUrl) {
super(handler, viewer, extension, pathSolver, fetchUrl);
this.ok = true;
}
@Override
protected ModelInstance createInstance(final int type) {
return new LibGDXContentLayerModelInstance(this);
}
@Override
protected void lateLoad() {
}
@Override
protected void load(final InputStream src, final Object options) {
}
@Override
protected void error(final Exception e) {
}
}
@Override
public void hide() {
if (this.currentMusic != null) {
this.currentMusic.stop();
}
this.menuUI.hide();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
}

View File

@ -1,206 +1,35 @@
package com.etheller.warsmash.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption;
import com.google.common.io.Files;
import com.hiveworkshop.rms.parsers.mdlx.MdlxAttachment;
import com.hiveworkshop.rms.parsers.mdlx.MdlxBone;
import com.hiveworkshop.rms.parsers.mdlx.MdlxExtent;
import com.hiveworkshop.rms.parsers.mdlx.MdlxGeoset;
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer;
import com.hiveworkshop.rms.parsers.mdlx.MdlxLayer.FilterMode;
import com.hiveworkshop.rms.parsers.mdlx.MdlxLight;
import com.hiveworkshop.rms.parsers.mdlx.MdlxLight.Type;
import com.hiveworkshop.rms.parsers.mdlx.MdlxMaterial;
import com.hiveworkshop.rms.parsers.mdlx.MdlxModel;
import com.hiveworkshop.rms.parsers.mdlx.MdlxParticleEmitter;
import com.hiveworkshop.rms.parsers.mdlx.MdlxSequence;
import com.hiveworkshop.rms.parsers.mdlx.MdlxTexture;
import com.hiveworkshop.rms.parsers.mdlx.util.MdxUtils;
public class Test {
public static void main(final String[] args) {
final Pattern pattern = Pattern.compile("^\\[(.+?)\\]");
final Matcher matcher = pattern.matcher("[boat] // ocean");
if (matcher.matches()) {
final String name = matcher.group(1).trim().toLowerCase();
System.out.println(name);
final File mdxFile = new File("C:\\Users\\micro\\Downloads\\DrunkSnake\\NagaTridentyr.mdx");
final File mdlFile = new File("C:\\Users\\micro\\Downloads\\DrunkSnake\\NagaTridentyr.mdl");
try (FileInputStream stream = new FileInputStream(mdxFile)) {
final MdlxModel mdlx = MdxUtils.loadMdlx(stream);
final ByteBuffer mdl = mdlx.saveMdl();
try (FileChannel outChannel = FileChannel.open(mdlFile.toPath(), StandardOpenOption.CREATE,
StandardOpenOption.WRITE)) {
outChannel.write(mdl);
}
}
else {
System.out.println("no match");
}
// Quadtree<String> myQT = new Quadtree<>(new Rectangle(-, y, width, height))
final MdlxModel model = new MdlxModel();
upExtent(model.extent);
MdlxSequence sequence = new MdlxSequence();
sequence.name = "Stand";
sequence.interval = new long[] { 333, 332 };
upExtent(sequence.extent);
model.sequences.add(sequence);
sequence = new MdlxSequence();
sequence.name = "Stand";
sequence.interval = new long[] { 333, 332 };
upExtent(sequence.extent);
model.sequences.add(sequence);
sequence.name = "Stand";
sequence.interval = new long[] { 334, 333 };
upExtent(sequence.extent);
model.sequences.add(sequence);
sequence.name = "Stand";
sequence.interval = new long[] { 331, 330 };
upExtent(sequence.extent);
model.sequences.add(sequence);
MdlxGeoset mdlxGeoset = new MdlxGeoset();
upExtent(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.vertices = new float[] { -128f, -128f, 0f, 128f, -128f, 0f, 128f, 128f, 0f, -128f, 128f, 0f };
mdlxGeoset.vertexGroups = new short[] { 0, 0, 0, 0 };
mdlxGeoset.normals = new float[] { 0, 0, 1, 0, 128f, 1, 0, 0, Float.NaN, 0, 0, 1 };
mdlxGeoset.faceTypeGroups = new long[] { 1, 0 };
mdlxGeoset.faces = new int[] { 0, 1, 2, 3 };
mdlxGeoset.faceGroups = new long[] { 2, 2 };
mdlxGeoset.materialId = 0;
mdlxGeoset.matrixGroups = new long[] { 3 };
mdlxGeoset.matrixIndices = new long[] { 0, 1, 2 };
mdlxGeoset.uvSets = new float[][] { { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f } };
model.geosets.add(mdlxGeoset);
final int n = 3600;
mdlxGeoset = new MdlxGeoset();
upExtent(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.sequenceExtents.add(mdlxGeoset.extent);
mdlxGeoset.vertices = new float[(n + 1) * 3];
for (int i = 1; i <= n; i++) {
final float distance = 4000;
final float down = (float) ((((((i / 360) % 10) + 1) / 10f) * Math.PI) / 2);
final float around = (float) (((i % 360) / 360f) * Math.PI * 2);
final float xyRad = (float) (Math.sin(down) * distance);
final float z = (float) (Math.cos(down) * distance);
mdlxGeoset.vertices[i * 3] = (float) (Math.cos(around) * xyRad);
mdlxGeoset.vertices[(i * 3) + 1] = (float) (Math.sin(around) * xyRad);
mdlxGeoset.vertices[(i * 3) + 2] = z;
}
mdlxGeoset.vertexGroups = new short[(n + 1)];
mdlxGeoset.normals = new float[(n + 1) * 3];
mdlxGeoset.faceTypeGroups = new long[n];
Arrays.fill(mdlxGeoset.faceTypeGroups, 1);
mdlxGeoset.faces = new int[n * 2];
for (int i = 0; i < n; i++) {
mdlxGeoset.faces[(i * 2) + 1] = i + 1;
}
mdlxGeoset.faceGroups = new long[n];
Arrays.fill(mdlxGeoset.faceGroups, 2);
mdlxGeoset.materialId = 0;
mdlxGeoset.matrixGroups = new long[] { 3 };
mdlxGeoset.matrixIndices = new long[] { 0, 1, 2 };
mdlxGeoset.uvSets = new float[][] { { 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f } };
model.geosets.add(mdlxGeoset);
final MdlxTexture texture = new MdlxTexture();
texture.setPath("Textures\\white.blp");
model.textures.add(texture);
final MdlxMaterial material = new MdlxMaterial();
final MdlxLayer layer = new MdlxLayer();
layer.alpha = 1.0f;
layer.textureId = 0;
layer.filterMode = FilterMode.NONE;
material.layers.add(layer);
model.materials.add(material);
final MdlxBone stupid1 = makeStupidBone("Bone_A");
stupid1.setObjectId(0);
stupid1.setParentId(-1);
model.bones.add(stupid1);
final MdlxBone stupid2 = makeStupidBone("Bone_B");
stupid2.setObjectId(1);
stupid1.setParentId(-1);
model.bones.add(stupid2);
final MdlxBone stupid3 = makeStupidBone("Bone_C");
stupid2.setObjectId(2);
stupid1.setParentId(-1);
model.bones.add(stupid3);
final MdlxLight light = new MdlxLight();
light.ambientColor[0] = -5;
light.ambientColor[1] = 0;
light.ambientColor[2] = Float.MAX_VALUE;
light.ambientIntensity = Float.MAX_VALUE;
light.intensity = Float.MAX_VALUE;
light.attenuation[0] = Float.MAX_VALUE;
light.attenuation[1] = Float.MAX_VALUE;
light.color[0] = -5;
light.color[1] = -5;
light.color[2] = Float.MAX_VALUE;
light.type = Type.OMNIDIRECTIONAL;
light.name = "#!@$!@#$";
light.objectId = 3;
light.parentId = -1;
model.lights.add(light);
final MdlxAttachment attachment = new MdlxAttachment();
attachment.setObjectId(4);
attachment.setParentId(-1);
attachment.setName("!@#$");
// attachment.setPath("war3mapImport\\stupidFan.mdl");
model.attachments.add(attachment);
final MdlxParticleEmitter mdlxParticleEmitter = new MdlxParticleEmitter();
mdlxParticleEmitter.emissionRate = 99999;
mdlxParticleEmitter.flags |= 0x8000;
mdlxParticleEmitter.lifeSpan = 99999;
mdlxParticleEmitter.name = "ATCH";
mdlxParticleEmitter.objectId = 5;
mdlxParticleEmitter.parentId = -1;
mdlxParticleEmitter.path = "Doodads\\Cinematic\\ArthasIllidanFight\\ArthasIllidanFight.mdl";
model.particleEmitters.add(mdlxParticleEmitter);
model.pivotPoints.add(new float[] { 0, 0, 0 });
model.pivotPoints.add(new float[] { 0, 0, 0 });
model.pivotPoints.add(new float[] { 0, 0, 0 });
model.pivotPoints.add(new float[] { 0, 0, 0 });
model.pivotPoints.add(new float[] { 0, 0, 0 });
model.pivotPoints.add(new float[] { 0, 0, 0 });
final ByteBuffer mdxBuffer = model.saveMdx();
try {
Files.write(mdxBuffer.array(), new File("C:\\Temp\\doomball.mdx"));
catch (final FileNotFoundException e) {
e.printStackTrace();
}
catch (final IOException e) {
e.printStackTrace();
}
}
private static void upExtent(final MdlxExtent extent) {
extent.boundsRadius = Float.MAX_VALUE;
extent.max[0] = Float.MAX_VALUE;
extent.max[1] = Float.MAX_VALUE;
extent.max[2] = Float.MAX_VALUE;
extent.min[0] = -Float.MAX_VALUE;
extent.min[1] = -Float.MAX_VALUE;
extent.min[2] = -Float.MAX_VALUE;
}
private static MdlxBone makeStupidBone(final String name) {
final MdlxBone stupid1 = new MdlxBone();
stupid1.setName(name);
stupid1.setGeosetId(-1);
stupid1.setGeosetAnimationId(-1);
return stupid1;
}
}

View File

@ -114,7 +114,7 @@ public abstract class SkeletalNode extends GenericNode {
computedRotation = rotationHeap;
computedRotation.set(this.parent.inverseWorldRotation);
if(scene!=null) {
if (scene != null) {
// TODO null scene is stupid, and happens rarely
computedRotation.mul(scene.camera.inverseRotation);
}
@ -194,6 +194,9 @@ public abstract class SkeletalNode extends GenericNode {
RenderMathUtils.mul(computedRotation, computedRotation, rotationHeap2);
}
else if (this.dontInheritRotation) {
RenderMathUtils.mul(computedRotation, this.parent.inverseWorldRotation, computedRotation);
}
}
if (!Float.isNaN(blendTimeRatio) && (blendTimeRatio > 0)) {

View File

@ -56,8 +56,8 @@ public class GenericObject extends AnimatedObject implements GenericIndexed {
final int flags = object.getFlags();
this.dontInheritTranslation = flags & 0x1;
this.dontInheritRotation = flags & 0x2;
this.dontInheritScaling = flags & 0x4;
this.dontInheritScaling = flags & 0x2;
this.dontInheritRotation = flags & 0x4;
this.billboarded = flags & 0x8;
this.billboardedX = flags & 0x10;
this.billboardedY = flags & 0x20;

View File

@ -234,7 +234,7 @@ public class MdxComplexInstance extends ModelInstance {
}
private void initNode(final MdxNode[] nodes, final SkeletalNode node, final GenericObject genericObject) {
initNode(nodes, node, genericObject, null);
this.initNode(nodes, node, genericObject, null);
}
/**
@ -251,7 +251,10 @@ public class MdxComplexInstance extends ModelInstance {
node.parent = nodes[genericObject.parentId];
}
/// TODO: single-axis billboarding
node.dontInheritTranslation = genericObject.dontInheritTranslation > 0;
node.dontInheritScaling = genericObject.dontInheritScaling > 0;
node.dontInheritRotation = genericObject.dontInheritRotation > 0;
if (genericObject.billboarded != 0) {
node.billboarded = true;
}
@ -573,11 +576,13 @@ public class MdxComplexInstance extends ModelInstance {
final long animEnd = interval[1] - 1;
if (this.floatingFrame >= animEnd) {
boolean sequenceRestarted = false;
if ((this.sequenceLoopMode == SequenceLoopMode.ALWAYS_LOOP)
|| ((this.sequenceLoopMode == SequenceLoopMode.MODEL_LOOP) && (sequence.getFlags() == 0))) {
this.floatingFrame = this.frame = (int) interval[0]; // TODO not cast
this.resetEventEmitters();
sequenceRestarted = true;
}
else if (this.sequenceLoopMode == SequenceLoopMode.LOOP_TO_NEXT_ANIMATION) { // faux queued animation
// mode
@ -590,6 +595,7 @@ public class MdxComplexInstance extends ModelInstance {
this.sequenceEnded = false;
this.resetEventEmitters();
this.forced = true;
sequenceRestarted = true;
}
else {
this.floatingFrame = this.frame = (int) animEnd; // TODO not cast
@ -597,10 +603,10 @@ public class MdxComplexInstance extends ModelInstance {
this.allowParticleSpawn = false;
}
if (this.sequenceLoopMode == SequenceLoopMode.NEVER_LOOP_AND_HIDE_WHEN_DONE) {
hide();
this.hide();
}
this.sequenceEnded = true;
this.sequenceEnded = !sequenceRestarted;
}
else {
this.sequenceEnded = false;
@ -800,7 +806,7 @@ public class MdxComplexInstance extends ModelInstance {
}
public boolean intersectRayBounds(final Ray ray, final Vector3 intersection) {
return CollisionShape.intersectRayBounds(getBounds(), this.worldMatrix, ray, intersection);
return CollisionShape.intersectRayBounds(this.getBounds(), this.worldMatrix, ray, intersection);
}
/**
@ -824,7 +830,7 @@ public class MdxComplexInstance extends ModelInstance {
intersected = true;
}
}
return intersected || (!this.hasAnyUnselectableMesh && intersectRayBounds(ray, intersection));
return intersected || (!this.hasAnyUnselectableMesh && this.intersectRayBounds(ray, intersection));
}
/**

View File

@ -384,9 +384,9 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
this.selectionCircleScaleFactor = selectionCircleData.getFieldFloatValue("ScaleFactor");
this.imageWalkableZOffset = selectionCircleData.getFieldValue("ImageWalkableZOffset");
this.selectionCircleColorFriend = parseColor(selectionCircleData, "ColorFriend");
this.selectionCircleColorNeutral = parseColor(selectionCircleData, "ColorNeutral");
this.selectionCircleColorEnemy = parseColor(selectionCircleData, "ColorEnemy");
this.selectionCircleColorFriend = this.parseColor(selectionCircleData, "ColorFriend");
this.selectionCircleColorNeutral = this.parseColor(selectionCircleData, "ColorNeutral");
this.selectionCircleColorEnemy = this.parseColor(selectionCircleData, "ColorEnemy");
this.uiSoundsTable = new DataTable(worldEditStrings);
try (InputStream miscDataTxtStream = this.dataSource.getResourceAsStream("UI\\SoundInfo\\UISounds.slk")) {
@ -410,10 +410,10 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public GenericResource loadMapGeneric(final String path, final FetchDataTypeName dataType,
final LoadGenericCallback callback) {
if (this.mapMpq == null) {
return loadGeneric(path, dataType, callback);
return this.loadGeneric(path, dataType, callback);
}
else {
return loadGeneric(path, dataType, callback, this.dataSource);
return this.loadGeneric(path, dataType, callback, this.dataSource);
}
}
@ -506,9 +506,9 @@ public class War3MapViewer extends AbstractMdxModelViewer {
catch (final MPQException e) {
throw new RuntimeException(e);
}
setDataSource(tilesetSource);
this.setDataSource(tilesetSource);
this.worldEditStrings = new WorldEditStrings(this.dataSource);
loadSLKs(this.worldEditStrings);
this.loadSLKs(this.worldEditStrings);
this.solverParams.tileset = Character.toLowerCase(tileset);
@ -530,7 +530,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
this.worldScene.grid = new Grid(centerOffset[0], centerOffset[1], (mapSize[0] * 128) - 128,
(mapSize[1] * 128) - 128, 16 * 128, 16 * 128);
final MdxModel confirmation = (MdxModel) load("UI\\Feedback\\Confirmation\\Confirmation.mdx",
final MdxModel confirmation = (MdxModel) this.load("UI\\Feedback\\Confirmation\\Confirmation.mdx",
PathSolver.DEFAULT, null);
this.confirmationInstance = (MdxComplexInstance) confirmation.addInstance();
this.confirmationInstance.setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP_AND_HIDE_WHEN_DONE);
@ -573,8 +573,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final CAttackProjectile simulationAttackProjectile = new CAttackProjectile(x, y,
projectileSpeed, target, source, damage, unitAttack, bounceIndex, attackListener);
final MdxModel model = (MdxModel) load(missileArt, War3MapViewer.this.mapPathSolver,
War3MapViewer.this.solverParams);
final MdxModel model = (MdxModel) War3MapViewer.this.load(missileArt,
War3MapViewer.this.mapPathSolver, War3MapViewer.this.solverParams);
final MdxComplexInstance modelInstance = (MdxComplexInstance) model.addInstance();
modelInstance.setTeamColor(source.getPlayerIndex());
modelInstance.setScene(War3MapViewer.this.worldScene);
@ -619,8 +619,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final float height = War3MapViewer.this.terrain.getGroundHeight(targetX, targetY)
+ target.getFlyHeight() + target.getImpactZ();
final MdxModel model = (MdxModel) load(missileArt, War3MapViewer.this.mapPathSolver,
War3MapViewer.this.solverParams);
final MdxModel model = (MdxModel) War3MapViewer.this.load(missileArt,
War3MapViewer.this.mapPathSolver, War3MapViewer.this.solverParams);
final MdxComplexInstance modelInstance = (MdxComplexInstance) model.addInstance();
modelInstance.setTeamColor(source.getPlayerIndex());
SequenceUtils.randomBirthSequence(modelInstance);
@ -633,7 +633,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public void spawnDamageSound(final CWidget damagedDestructable, final String weaponSound,
final String armorType) {
final RenderWidget damagedWidget = getRenderPeer(damagedDestructable);
final RenderWidget damagedWidget = War3MapViewer.this.getRenderPeer(damagedDestructable);
if (damagedWidget == null) {
return;
}
@ -711,15 +711,18 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public CUnit createUnit(final CSimulation simulation, final War3ID typeId, final int playerIndex,
final float x, final float y, final float facing) {
return (CUnit) createNewUnit(War3MapViewer.this.allObjectData, typeId, x, y, playerIndex,
playerIndex, (float) Math.toRadians(facing));
return (CUnit) War3MapViewer.this.createNewUnit(War3MapViewer.this.allObjectData, typeId, x, y,
playerIndex, playerIndex, (float) Math.toRadians(facing));
}
@Override
public CDestructable createDestructable(final War3ID typeId, final float x, final float y,
final float facing, final float scale, final int variation) {
return createDestructableZ(typeId, x, y, Math.max(getWalkableRenderHeight(x, y),
War3MapViewer.this.terrain.getGroundHeight(x, y)), facing, scale, variation);
return this
.createDestructableZ(typeId, x, y,
Math.max(War3MapViewer.this.getWalkableRenderHeight(x, y),
War3MapViewer.this.terrain.getGroundHeight(x, y)),
facing, scale, variation);
}
@Override
@ -728,16 +731,16 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final MutableGameObject row = War3MapViewer.this.allObjectData.getDestructibles().get(typeId);
final float[] location3d = { x, y, z };
final float[] scale3d = { scale, scale, scale };
final RenderDestructable newDestructable = createNewDestructable(typeId, row, variation,
location3d, (float) Math.toRadians(facing), (short) 100, scale3d);
final RenderDestructable newDestructable = War3MapViewer.this.createNewDestructable(typeId, row,
variation, location3d, (float) Math.toRadians(facing), (short) 100, scale3d);
return newDestructable.getSimulationDestructable();
}
@Override
public CItem createItem(final CSimulation simulation, final War3ID typeId, final float x,
final float y) {
return (CItem) createNewUnit(War3MapViewer.this.allObjectData, typeId, x, y, -1, -1,
(float) Math.toRadians(
return (CItem) War3MapViewer.this.createNewUnit(War3MapViewer.this.allObjectData, typeId, x, y,
-1, -1, (float) Math.toRadians(
War3MapViewer.this.simulation.getGameplayConstants().getBuildingAngle()));
}
@ -762,7 +765,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final AbilityUI heroUI = War3MapViewer.this.abilityDataUI.getUI(ABILITY_HERO_RAWCODE);
final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(source);
final String heroLevelUpArt = heroUI.getCasterArt(0);
spawnFxOnOrigin(renderUnit, heroLevelUpArt);
War3MapViewer.this.spawnFxOnOrigin(renderUnit, heroLevelUpArt);
}
@Override
@ -773,7 +776,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
renderUnit.instance.setVertexAlpha(1.0f);
final CPlayer player = War3MapViewer.this.simulation.getPlayer(source.getPlayerIndex());
final String heroReviveArt = reviveUI.getTargetArt(player.getRace().ordinal());
spawnFxOnOrigin(renderUnit, heroReviveArt);
War3MapViewer.this.spawnFxOnOrigin(renderUnit, heroReviveArt);
final MutableGameObject row = War3MapViewer.this.allObjectData.getUnits()
.get(source.getTypeId());
@ -815,7 +818,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public void spawnEffectOnUnit(final CUnit unit, final String effectPath) {
final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(unit);
final MdxModel spawnedEffectModel = (MdxModel) load(mdx(effectPath), PathSolver.DEFAULT, null);
final MdxModel spawnedEffectModel = (MdxModel) War3MapViewer.this.load(mdx(effectPath),
PathSolver.DEFAULT, null);
if (spawnedEffectModel != null) {
final MdxComplexInstance modelInstance = (MdxComplexInstance) spawnedEffectModel
.addInstance();
@ -834,7 +838,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
@Override
public void spawnSpellEffectOnUnit(final CUnit unit, final War3ID alias) {
final AbilityUI abilityUI = War3MapViewer.this.abilityDataUI.getUI(alias);
spawnEffectOnUnit(unit, abilityUI.getTargetArt(0));
this.spawnEffectOnUnit(unit, abilityUI.getTargetArt(0));
}
@Override
@ -916,13 +920,13 @@ public class War3MapViewer extends AbstractMdxModelViewer {
throw new IllegalStateException("transcription of JS has not loaded a map and has no JS async promises");
}
loadSounds();
this.loadSounds();
this.terrain.createWaves();
}
public void spawnFxOnOrigin(final RenderUnit renderUnit, final String heroLevelUpArt) {
final MdxModel heroLevelUpModel = loadModel(heroLevelUpArt);
final MdxModel heroLevelUpModel = this.loadModel(heroLevelUpArt);
if (heroLevelUpModel != null) {
final MdxComplexInstance modelInstance = (MdxComplexInstance) heroLevelUpModel.addInstance();
modelInstance.setTeamColor(renderUnit.playerIndex);
@ -952,11 +956,11 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
protected BufferedImage getDestructablePathingPixelMap(final MutableGameObject row) {
return loadPathingTexture(row.getFieldAsString(DESTRUCTABLE_PATHING, 0));
return this.loadPathingTexture(row.getFieldAsString(DESTRUCTABLE_PATHING, 0));
}
protected BufferedImage getDestructablePathingDeathPixelMap(final MutableGameObject row) {
return loadPathingTexture(row.getFieldAsString(DESTRUCTABLE_PATHING_DEATH, 0));
return this.loadPathingTexture(row.getFieldAsString(DESTRUCTABLE_PATHING_DEATH, 0));
}
private void loadSounds() {
@ -1003,8 +1007,8 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final float facingRadians = doodad.getAngle();
final short lifePercent = doodad.getLife();
final float[] scale = doodad.getScale();
createDestructableOrDoodad(doodadId, modifications, doodadVariation, location, facingRadians, lifePercent,
scale);
this.createDestructableOrDoodad(doodadId, modifications, doodadVariation, location, facingRadians,
lifePercent, scale);
}
// Cliff/Terrain doodads.
@ -1072,7 +1076,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
private void createDoodad(final MutableGameObject row, final int doodadVariation, final float[] location,
final float facingRadians, final float[] scale) {
final MdxModel model = getDoodadModel(doodadVariation, row);
final MdxModel model = this.getDoodadModel(doodadVariation, row);
final float maxPitch = row.readSLKTagFloat("maxPitch");
final float maxRoll = row.readSLKTagFloat("maxRoll");
final float defScale = row.readSLKTagFloat("defScale");
@ -1088,7 +1092,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
BuildingShadow destructableShadow = null;
RemovablePathingMapInstance destructablePathing = null;
RemovablePathingMapInstance destructablePathingDeath = null;
final MdxModel model = getDoodadModel(doodadVariation, row);
final MdxModel model = this.getDoodadModel(doodadVariation, row);
final float maxPitch = row.readSLKTagFloat("maxPitch");
final float maxRoll = row.readSLKTagFloat("maxRoll");
@ -1097,7 +1101,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
destructableShadow = this.terrain.addShadow(shadowString, location[0], location[1]);
}
final BufferedImage destructablePathingPixelMap = getDestructablePathingPixelMap(row);
final BufferedImage destructablePathingPixelMap = this.getDestructablePathingPixelMap(row);
if (destructablePathingPixelMap != null) {
destructablePathing = this.terrain.pathingGrid.createRemovablePathingOverlayTexture(location[0],
location[1], (int) Math.toDegrees(facingRadians), destructablePathingPixelMap);
@ -1105,7 +1109,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
destructablePathing.add();
}
}
final BufferedImage destructablePathingDeathPixelMap = getDestructablePathingDeathPixelMap(row);
final BufferedImage destructablePathingDeathPixelMap = this.getDestructablePathingDeathPixelMap(row);
if (destructablePathingDeathPixelMap != null) {
destructablePathingDeath = this.terrain.pathingGrid.createRemovablePathingOverlayTexture(location[0],
location[1], (int) Math.toDegrees(facingRadians), destructablePathingDeathPixelMap);
@ -1127,7 +1131,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
if (row.readSLKTagBoolean("walkable")) {
final float angle = facingRadians;
final BoundingBox boundingBox = model.bounds.getBoundingBox();
final Rectangle renderDestructableBounds = getRotatedBoundingBox(x, y, angle, boundingBox);
final Rectangle renderDestructableBounds = this.getRotatedBoundingBox(x, y, angle, boundingBox);
this.walkableObjectsTree.add((MdxComplexInstance) renderDestructable.instance, renderDestructableBounds);
renderDestructable.walkableBounds = renderDestructableBounds;
}
@ -1143,11 +1147,11 @@ public class War3MapViewer extends AbstractMdxModelViewer {
if (row == null) {
row = modifications.getDestructibles().get(doodadId);
if (row != null) {
createNewDestructable(doodadId, row, doodadVariation, location, facingRadians, lifePercent, scale);
this.createNewDestructable(doodadId, row, doodadVariation, location, facingRadians, lifePercent, scale);
}
}
else {
createDoodad(row, doodadVariation, location, facingRadians, scale);
this.createDoodad(row, doodadVariation, location, facingRadians, scale);
}
}
@ -1249,7 +1253,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final float unitAngle = unit.getAngle();
final int editorConfigHitPointPercent = unit.getHitpoints();
final CWidget widgetCreated = createNewUnit(modifications, unitId, unitX, unitY, playerIndex,
final CWidget widgetCreated = this.createNewUnit(modifications, unitId, unitX, unitY, playerIndex,
customTeamColor, unitAngle);
if (widgetCreated instanceof CUnit) {
final CUnit unitCreated = (CUnit) widgetCreated;
@ -1338,9 +1342,9 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
else {
type = WorldEditorDataType.UNITS;
path = getUnitModelPath(row);
path = this.getUnitModelPath(row);
buildingPathingPixelMap = getBuildingPathingPixelMap(row);
buildingPathingPixelMap = this.getBuildingPathingPixelMap(row);
if (buildingPathingPixelMap != null) {
unitX = (float) Math.floor(unitX / 64f) * 64f;
unitY = (float) Math.floor(unitY / 64f) * 64f;
@ -1426,7 +1430,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
if (path != null) {
final String unitSpecialArtPath = row.getFieldAsString(UNIT_SPECIAL, 0);
MdxModel specialArtModel;
if (unitSpecialArtPath != null) {
if ((unitSpecialArtPath != null) && !unitSpecialArtPath.isEmpty()) {
try {
specialArtModel = (MdxModel) this.load(mdx(unitSpecialArtPath), this.mapPathSolver,
this.solverParams);
@ -1452,7 +1456,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final float angle = (float) Math.toDegrees(unitAngle);
final CUnit simulationUnit = this.simulation.internalCreateUnit(row.getAlias(), playerIndex, unitX,
unitY, angle, buildingPathingPixelMap, pathingInstance);
final RenderUnitTypeData typeData = getUnitTypeData(unitId, row);
final RenderUnitTypeData typeData = this.getUnitTypeData(unitId, row);
if (!typeData.isAllowCustomTeamColor() || (customTeamColor == -1)) {
if (typeData.getTeamColor() != -1) {
customTeamColor = typeData.getTeamColor();
@ -1461,7 +1465,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
customTeamColor = playerIndex;
}
}
final float unitZ = Math.max(getWalkableRenderHeight(unitX, unitY),
final float unitZ = Math.max(this.getWalkableRenderHeight(unitX, unitY),
War3MapViewer.this.terrain.getGroundHeight(unitX, unitY)) + simulationUnit.getFlyHeight();
final RenderUnit renderUnit = new RenderUnit(this, model, row, unitX, unitY, unitZ, customTeamColor,
soundset, portraitModel, simulationUnit, typeData, specialArtModel, buildingShadowInstance,
@ -1498,7 +1502,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
else {
final CItem simulationItem = this.simulation.internalCreateItem(row.getAlias(), unitX, unitY);
final float unitZ = Math.max(getWalkableRenderHeight(unitX, unitY),
final float unitZ = Math.max(this.getWalkableRenderHeight(unitX, unitY),
War3MapViewer.this.terrain.getGroundHeight(unitX, unitY));
final RenderItem renderItem = new RenderItem(this, model, row, unitX, unitY, unitZ, unitAngle, soundset,
portraitModel, simulationItem);
@ -1542,7 +1546,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
private BufferedImage getBuildingPathingPixelMap(final MutableGameObject row) {
final String pathingTexture = row.getFieldAsString(UNIT_PATHING, 0);
final BufferedImage buildingPathingPixelMap = loadPathingTexture(pathingTexture);
final BufferedImage buildingPathingPixelMap = this.loadPathingTexture(pathingTexture);
return buildingPathingPixelMap;
}
@ -1663,7 +1667,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
if (this.anyReady) {
final Scene worldScene = this.worldScene;
startFrame();
this.startFrame();
worldScene.startFrame();
if (DEBUG_DEPTH > 0) {
worldScene.renderOpaque(this.dynamicShadowManager, this.webGL);
@ -1728,7 +1732,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
public void doSelectUnit(final List<RenderWidget> units) {
deselect();
this.deselect();
if (units.isEmpty()) {
return;
}
@ -1798,7 +1802,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final String filePath = path.substring(2);
final String allyKey = path.substring(0, 2);
final Splat locations = entry.getValue();
final SplatModel model = new SplatModel(Gdx.gl30, (Texture) load(filePath, PathSolver.DEFAULT, null),
final SplatModel model = new SplatModel(Gdx.gl30, (Texture) this.load(filePath, PathSolver.DEFAULT, null),
locations.locations, this.terrain.centerOffset, locations.unitMapping, true, false, true);
switch (allyKey) {
case "e:":
@ -1905,7 +1909,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final String filePath = path.substring(2);
final String allyKey = path.substring(0, 2);
final Splat locations = entry.getValue();
final SplatModel model = new SplatModel(Gdx.gl30, (Texture) load(filePath, PathSolver.DEFAULT, null),
final SplatModel model = new SplatModel(Gdx.gl30, (Texture) this.load(filePath, PathSolver.DEFAULT, null),
locations.locations, this.terrain.centerOffset, locations.unitMapping, true, false, true);
switch (allyKey) {
case "e:":
@ -1947,7 +1951,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
out.set(this.walkablesIntersectionFinder.intersection);
}
else {
out.z = Math.max(getWalkableRenderHeight(out.x, out.y), this.terrain.getGroundHeight(out.x, out.y));
out.z = Math.max(this.getWalkableRenderHeight(out.x, out.y), this.terrain.getGroundHeight(out.x, out.y));
}
}
@ -1962,7 +1966,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
public RenderWidget rayPickUnit(final float x, final float y) {
return rayPickUnit(x, y, CWidgetFilterFunction.ACCEPT_ALL);
return this.rayPickUnit(x, y, CWidgetFilterFunction.ACCEPT_ALL);
}
public RenderWidget rayPickUnit(final float x, final float y, final CWidgetFilterFunction filter) {
@ -2113,15 +2117,15 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
public void setDayNightModels(final String terrainDNCFile, final String unitDNCFile) {
final MdxModel terrainDNCModel = (MdxModel) load(mdx(terrainDNCFile), PathSolver.DEFAULT, null);
final MdxModel terrainDNCModel = (MdxModel) this.load(mdx(terrainDNCFile), PathSolver.DEFAULT, null);
this.dncTerrain = (MdxComplexInstance) terrainDNCModel.addInstance();
this.dncTerrain.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
this.dncTerrain.setSequence(0);
final MdxModel unitDNCModel = (MdxModel) load(mdx(unitDNCFile), PathSolver.DEFAULT, null);
final MdxModel unitDNCModel = (MdxModel) this.load(mdx(unitDNCFile), PathSolver.DEFAULT, null);
this.dncUnit = (MdxComplexInstance) unitDNCModel.addInstance();
this.dncUnit.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
this.dncUnit.setSequence(0);
final MdxModel targetDNCModel = (MdxModel) load(
final MdxModel targetDNCModel = (MdxModel) this.load(
mdx("Environment\\DNC\\DNCLordaeron\\DNCLordaeronTarget\\DNCLordaeronTarget.mdl"), PathSolver.DEFAULT,
null);
this.dncTarget = (MdxComplexInstance) targetDNCModel.addInstance();
@ -2161,7 +2165,7 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
public MdxModel loadModel(final String path) {
return (MdxModel) load(mdx(path), PathSolver.DEFAULT, null);
return (MdxModel) this.load(mdx(path), PathSolver.DEFAULT, null);
}
@Override
@ -2332,11 +2336,31 @@ public class War3MapViewer extends AbstractMdxModelViewer {
final String attachPointName) {
if (targetWidget instanceof CUnit) {
final RenderUnit renderUnit = War3MapViewer.this.unitToRenderPeer.get(targetWidget);
final MdxModel spawnedEffectModel = (MdxModel) load(mdx(modelName), PathSolver.DEFAULT, null);
final MdxModel spawnedEffectModel = (MdxModel) this.load(mdx(modelName), PathSolver.DEFAULT, null);
if (spawnedEffectModel != null) {
final MdxComplexInstance modelInstance = (MdxComplexInstance) spawnedEffectModel.addInstance();
modelInstance.setTeamColor(renderUnit.playerIndex);
modelInstance.setLocation(renderUnit.location);
{
final MdxModel model = (MdxModel) renderUnit.instance.model;
int index = -1;
for (int i = 0; i < model.attachments.size(); i++) {
final Attachment attachment = model.attachments.get(i);
if (attachment.getName().startsWith(attachPointName)) {
index = i;
break;
}
}
if (index != -1) {
modelInstance.detach();
final MdxNode attachment = renderUnit.instance.getAttachment(index);
modelInstance.setParent(attachment);
modelInstance.setLocation(0, 0, 0);
}
else {
// TODO This is not consistent with War3, is it? Should look nice though.
modelInstance.setLocation(renderUnit.location);
}
}
modelInstance.setScene(War3MapViewer.this.worldScene);
final RenderSpellEffect renderAttackInstant = new RenderSpellEffect(modelInstance, War3MapViewer.this,
(float) Math.toRadians(renderUnit.getSimulationUnit().getFacing()),

View File

@ -24,17 +24,20 @@ public class RenderSpellEffect implements RenderEffect {
this.animationQueue = animationQueue;
final MdxModel model = (MdxModel) this.modelInstance.model;
this.sequences = model.getSequences();
this.modelInstance.setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP);
this.modelInstance.setSequenceLoopMode(SequenceLoopMode.MODEL_LOOP);
this.modelInstance.localRotation.setFromAxisRad(0, 0, 1, yaw);
this.modelInstance.sequenceEnded = true;
playNextAnimation();
this.playNextAnimation();
}
@Override
public boolean updateAnimations(final War3MapViewer war3MapViewer, final float deltaTime) {
playNextAnimation();
this.playNextAnimation();
final boolean everythingDone = this.animationQueueIndex >= this.animationQueue.length;
if (everythingDone) {
if (this.modelInstance.parent != null) {
this.modelInstance.setParent(null);
}
war3MapViewer.worldScene.removeInstance(this.modelInstance);
}
return everythingDone;

View File

@ -0,0 +1,315 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
import java.io.IOException;
import java.io.InputStream;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.SingleModelScreen;
import com.etheller.warsmash.WarsmashGdxMultiScreenGame;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.custom.WTS;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.util.WorldEditStrings;
import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxViewer;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.FocusableFrame;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.sound.KeyedSounds;
public class TestUI {
private static final Vector2 screenCoordsVector = new Vector2();
private static boolean ENABLE_NOT_YET_IMPLEMENTED_BUTTONS = false;
private final DataSource dataSource;
private final Scene uiScene;
private final Viewport uiViewport;
private final MdxViewer viewer;
private final RootFrameListener rootFrameListener;
private final float widthRatioCorrection;
private final float heightRatioCorrection;
private GameUI rootFrame;
private SpriteFrame cursorFrame;
private ClickableFrame mouseDownUIFrame;
private ClickableFrame mouseOverUIFrame;
private FocusableFrame focusUIFrame;
private WorldEditStrings worldEditStrings;
private DataTable uiSoundsTable;
private KeyedSounds uiSounds;
private final WarsmashGdxMultiScreenGame screenManager;
private final DataTable warsmashIni;
private final SingleModelScreen menuScreen;
private UIFrame main;
private final String customTOC;
public TestUI(final DataSource dataSource, final Viewport uiViewport, final Scene uiScene, final MdxViewer viewer,
final WarsmashGdxMultiScreenGame screenManager, final SingleModelScreen menuScreen,
final DataTable warsmashIni, final RootFrameListener rootFrameListener, final String customTOC) {
this.dataSource = dataSource;
this.uiViewport = uiViewport;
this.uiScene = uiScene;
this.viewer = viewer;
this.screenManager = screenManager;
this.menuScreen = menuScreen;
this.warsmashIni = warsmashIni;
this.rootFrameListener = rootFrameListener;
this.customTOC = customTOC;
this.widthRatioCorrection = this.getMinWorldWidth() / 1600f;
this.heightRatioCorrection = this.getMinWorldHeight() / 1200f;
}
public float getHeightRatioCorrection() {
return this.heightRatioCorrection;
}
/**
* Called "main" because this was originally written in JASS so that maps could
* override it, and I may convert it back to the JASS at some point.
*/
public void main() {
// =================================
// Load skins and templates
// =================================
this.rootFrame = new GameUI(this.dataSource, GameUI.loadSkin(this.dataSource, WarsmashConstants.GAME_VERSION),
this.uiViewport, this.uiScene, this.viewer, 0, WTS.DO_NOTHING);
this.rootFrameListener.onCreate(this.rootFrame);
try {
this.rootFrame.loadTOCFile(this.customTOC);
}
catch (final IOException exc) {
throw new IllegalStateException(this.customTOC);
}
// Create main menu
this.main = this.rootFrame.createFrame("Main", this.rootFrame, 0, 0);
this.cursorFrame = (SpriteFrame) this.rootFrame.createFrameByType("SPRITE", "SmashCursorFrame", this.rootFrame,
"", 0);
this.rootFrame.setSpriteFrameModel(this.cursorFrame, this.rootFrame.getSkinField("Cursor"));
this.cursorFrame.setSequence("Normal");
this.cursorFrame.setZDepth(-1.0f);
if (WarsmashConstants.CATCH_CURSOR) {
Gdx.input.setCursorCatched(true);
}
// position all
this.rootFrame.positionBounds(this.rootFrame, this.uiViewport);
this.loadSounds();
}
private static String getStringWithWTS(final WTS wts, String string) {
if (string.startsWith("TRIGSTR_")) {
string = wts.get(Integer.parseInt(string.substring(8)));
}
return string;
}
public void resize() {
}
public void render(final SpriteBatch batch, final GlyphLayout glyphLayout) {
final BitmapFont font = this.rootFrame.getFont();
final BitmapFont font20 = this.rootFrame.getFont20();
font.setColor(Color.YELLOW);
final String fpsString = "FPS: " + Gdx.graphics.getFramesPerSecond();
glyphLayout.setText(font, fpsString);
font.draw(batch, fpsString, (this.getMinWorldWidth() - glyphLayout.width) / 2,
1100 * this.heightRatioCorrection);
this.rootFrame.render(batch, font20, glyphLayout);
}
private float getMinWorldWidth() {
if (this.uiViewport instanceof ExtendViewport) {
return ((ExtendViewport) this.uiViewport).getMinWorldWidth();
}
return this.uiViewport.getWorldWidth();
}
private float getMinWorldHeight() {
if (this.uiViewport instanceof ExtendViewport) {
return ((ExtendViewport) this.uiViewport).getMinWorldHeight();
}
return this.uiViewport.getWorldHeight();
}
public void update(final float deltaTime) {
if ((this.focusUIFrame != null) && !this.focusUIFrame.isVisibleOnScreen()) {
this.setFocusFrame(this.getNextFocusFrame());
}
final int baseMouseX = Gdx.input.getX();
int mouseX = baseMouseX;
final int baseMouseY = Gdx.input.getY();
int mouseY = baseMouseY;
final int minX = this.uiViewport.getScreenX();
final int maxX = minX + this.uiViewport.getScreenWidth();
final int minY = this.uiViewport.getScreenY();
final int maxY = minY + this.uiViewport.getScreenHeight();
mouseX = Math.max(minX, Math.min(maxX, mouseX));
mouseY = Math.max(minY, Math.min(maxY, mouseY));
if (Gdx.input.isCursorCatched()) {
if (WarsmashConstants.CATCH_CURSOR) {
Gdx.input.setCursorPosition(mouseX, mouseY);
}
}
screenCoordsVector.set(mouseX, mouseY);
this.uiViewport.unproject(screenCoordsVector);
this.cursorFrame.setFramePointX(FramePoint.LEFT, screenCoordsVector.x);
this.cursorFrame.setFramePointY(FramePoint.BOTTOM, screenCoordsVector.y);
this.cursorFrame.setSequence("Normal");
}
private FocusableFrame getNextFocusFrame() {
return this.rootFrame.getNextFocusFrame();
}
public boolean touchDown(final int screenX, final int screenY, final float worldScreenY, final int button) {
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
final UIFrame clickedUIFrame = this.rootFrame.touchDown(screenCoordsVector.x, screenCoordsVector.y, button);
if (clickedUIFrame != null) {
if (clickedUIFrame instanceof ClickableFrame) {
this.mouseDownUIFrame = (ClickableFrame) clickedUIFrame;
this.mouseDownUIFrame.mouseDown(this.rootFrame, this.uiViewport);
}
if (clickedUIFrame instanceof FocusableFrame) {
final FocusableFrame clickedFocusableFrame = (FocusableFrame) clickedUIFrame;
if (clickedFocusableFrame.isFocusable()) {
this.setFocusFrame(clickedFocusableFrame);
}
}
}
return false;
}
private void setFocusFrame(final FocusableFrame clickedFocusableFrame) {
if (this.focusUIFrame != null) {
this.focusUIFrame.onFocusLost();
}
this.focusUIFrame = clickedFocusableFrame;
if (this.focusUIFrame != null) {
this.focusUIFrame.onFocusGained();
}
}
public boolean touchUp(final int screenX, final int screenY, final float worldScreenY, final int button) {
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
final UIFrame clickedUIFrame = this.rootFrame.touchUp(screenCoordsVector.x, screenCoordsVector.y, button);
if (this.mouseDownUIFrame != null) {
if (clickedUIFrame == this.mouseDownUIFrame) {
this.mouseDownUIFrame.onClick(button);
this.uiSounds.getSound("GlueScreenClick").play(this.uiScene.audioContext, 0, 0, 0);
}
this.mouseDownUIFrame.mouseUp(this.rootFrame, this.uiViewport);
}
this.mouseDownUIFrame = null;
return false;
}
public boolean touchDragged(final int screenX, final int screenY, final float worldScreenY, final int pointer) {
this.mouseMoved(screenX, screenY, worldScreenY);
return false;
}
public boolean mouseMoved(final int screenX, final int screenY, final float worldScreenY) {
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
final UIFrame mousedUIFrame = this.rootFrame.getFrameChildUnderMouse(screenCoordsVector.x,
screenCoordsVector.y);
if (mousedUIFrame != this.mouseOverUIFrame) {
if (this.mouseOverUIFrame != null) {
this.mouseOverUIFrame.mouseExit(this.rootFrame, this.uiViewport);
}
if (mousedUIFrame instanceof ClickableFrame) {
this.mouseOverUIFrame = (ClickableFrame) mousedUIFrame;
if (this.mouseOverUIFrame != null) {
this.mouseOverUIFrame.mouseEnter(this.rootFrame, this.uiViewport);
}
}
else {
this.mouseOverUIFrame = null;
}
}
return false;
}
private void loadSounds() {
this.worldEditStrings = new WorldEditStrings(this.dataSource);
this.uiSoundsTable = new DataTable(this.worldEditStrings);
try {
try (InputStream miscDataTxtStream = this.dataSource.getResourceAsStream("UI\\SoundInfo\\UISounds.slk")) {
this.uiSoundsTable.readSLK(miscDataTxtStream);
}
try (InputStream miscDataTxtStream = this.dataSource
.getResourceAsStream("UI\\SoundInfo\\AmbienceSounds.slk")) {
this.uiSoundsTable.readSLK(miscDataTxtStream);
}
}
catch (final IOException e) {
e.printStackTrace();
}
this.uiSounds = new KeyedSounds(this.uiSoundsTable, this.dataSource);
}
public KeyedSounds getUiSounds() {
return this.uiSounds;
}
public void hide() {
}
public void dispose() {
if (this.rootFrame != null) {
this.rootFrame.dispose();
}
}
public boolean keyDown(final int keycode) {
if (this.focusUIFrame != null) {
this.focusUIFrame.keyDown(keycode);
}
return false;
}
public boolean keyUp(final int keycode) {
if (this.focusUIFrame != null) {
this.focusUIFrame.keyUp(keycode);
}
return false;
}
public boolean keyTyped(final char character) {
if (this.focusUIFrame != null) {
this.focusUIFrame.keyTyped(character);
}
return false;
}
}

View File

@ -37,19 +37,19 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
this.parentId = reader.readInt32();
this.flags = reader.readInt32();
readTimelines(reader, size - 96);
this.readTimelines(reader, size - 96);
}
@Override
public void writeMdx(final BinaryWriter writer, final int version) {
writer.writeUInt32(getGenericByteLength(version));
writer.writeUInt32(this.getGenericByteLength(version));
writer.writeWithNulls(this.name, 80);
writer.writeInt32(this.objectId);
writer.writeInt32(this.parentId);
writer.writeInt32(this.flags);
for (final MdlxTimeline<?> timeline : this.timelines) {
if (isGeneric(timeline)) {
if (this.isGeneric(timeline)) {
timeline.writeMdx(writer);
}
}
@ -57,7 +57,7 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
public void writeNonGenericAnimationChunks(final BinaryWriter writer) {
for (final MdlxTimeline<?> timeline : this.timelines) {
if (!isGeneric(timeline)) {
if (!this.isGeneric(timeline)) {
timeline.writeMdx(writer);
}
}
@ -65,7 +65,7 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
protected final Iterable<String> readMdlGeneric(final MdlTokenInputStream stream) {
this.name = stream.read();
return () -> new WrappedMdlTokenIterator(readAnimatedBlock(stream), MdlxGenericObject.this, stream);
return () -> new WrappedMdlTokenIterator(this.readAnimatedBlock(stream), MdlxGenericObject.this, stream);
}
public void writeGenericHeader(final MdlTokenOutputStream stream) {
@ -95,7 +95,7 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
stream.writeFlag(MdlUtils.TOKEN_CAMERA_ANCHORED);
}
if ((this.flags & 0x2) != 0) {
if ((this.flags & 0x4) != 0) {
stream.writeFlag(MdlUtils.TOKEN_DONT_INHERIT + " { " + MdlUtils.TOKEN_ROTATION + " }");
}
@ -103,22 +103,22 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
stream.writeFlag(MdlUtils.TOKEN_DONT_INHERIT + " { " + MdlUtils.TOKEN_TRANSLATION + " }");
}
if ((this.flags & 0x4) != 0) {
if ((this.flags & 0x2) != 0) {
stream.writeFlag(MdlUtils.TOKEN_DONT_INHERIT + " { " + MdlUtils.TOKEN_SCALING + " }");
}
}
public void writeGenericTimelines(final MdlTokenOutputStream stream) {
writeTimeline(stream, AnimationMap.KGTR);
writeTimeline(stream, AnimationMap.KGRT);
writeTimeline(stream, AnimationMap.KGSC);
this.writeTimeline(stream, AnimationMap.KGTR);
this.writeTimeline(stream, AnimationMap.KGRT);
this.writeTimeline(stream, AnimationMap.KGSC);
}
public long getGenericByteLength(final int version) {
long size = 96;
for (final MdlxTimeline<?> timeline : this.timelines) {
if (isGeneric(timeline)) {
if (this.isGeneric(timeline)) {
size += timeline.getByteLength();
}
}
@ -186,7 +186,7 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
@Override
public boolean hasNext() {
if (this.delegate.hasNext()) {
this.next = read();
this.next = this.read();
this.hasLoaded = true;
return this.next != null;
}
@ -196,7 +196,7 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
@Override
public String next() {
if (!this.hasLoaded) {
this.next = read();
this.next = this.read();
}
this.hasLoaded = false;
return this.next;
@ -242,13 +242,13 @@ public abstract class MdlxGenericObject extends MdlxAnimatedObject {
for (final String subToken : this.stream.readBlock()) {
switch (subToken) {
case MdlUtils.TOKEN_ROTATION:
this.updatingObject.flags |= 0x2;
this.updatingObject.flags |= 0x4;
break;
case MdlUtils.TOKEN_TRANSLATION:
this.updatingObject.flags |= 0x1;
break;
case MdlUtils.TOKEN_SCALING:
this.updatingObject.flags |= 0x0;
this.updatingObject.flags |= 0x2;
break;
}
}

View File

@ -13,6 +13,7 @@ import java.io.PrintStream;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.openal.AL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL31;
import org.lwjgl.opengl.GL32;
@ -24,6 +25,7 @@ import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl.LwjglNativesLoader;
import com.etheller.warsmash.WarsmashGdxFDFTestRenderScreen;
import com.etheller.warsmash.WarsmashGdxMenuScreen;
import com.etheller.warsmash.WarsmashGdxMultiScreenGame;
import com.etheller.warsmash.audio.OpenALSound;
@ -104,11 +106,17 @@ public class DesktopLauncher {
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
final WarsmashGdxMenuScreen menuScreen = new WarsmashGdxMenuScreen(warsmashIni,
warsmashGdxMultiScreenGame);
warsmashGdxMultiScreenGame.setScreen(menuScreen);
if (finalFileToLoad != null) {
menuScreen.startMap(finalFileToLoad);
if ((finalFileToLoad != null) && finalFileToLoad.toLowerCase().endsWith(".toc")) {
warsmashGdxMultiScreenGame.setScreen(new WarsmashGdxFDFTestRenderScreen(warsmashIni,
warsmashGdxMultiScreenGame, finalFileToLoad));
}
else {
final WarsmashGdxMenuScreen menuScreen = new WarsmashGdxMenuScreen(warsmashIni,
warsmashGdxMultiScreenGame);
warsmashGdxMultiScreenGame.setScreen(menuScreen);
if (finalFileToLoad != null) {
menuScreen.startMap(finalFileToLoad);
}
}
}
});
@ -188,7 +196,7 @@ public class DesktopLauncher {
@Override
public AudioContext createContext(final boolean world) {
Listener listener;
if (world) {
if (world && AL.isCreated()) {
listener = new Listener() {
private float x;
private float y;

View File

@ -1,5 +1,8 @@
package com.etheller.interpreter.ast;
import java.util.Collections;
import java.util.List;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
@ -8,6 +11,11 @@ import org.antlr.v4.runtime.Recognizer;
import com.etheller.interpreter.JassLexer;
import com.etheller.interpreter.JassParser;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.JassValue;
import com.etheller.interpreter.ast.value.visitor.StringJassValueVisitor;
import com.etheller.interpreter.ast.visitors.JassProgramVisitor;
public class JassRunner {
@ -19,8 +27,19 @@ public class JassRunner {
return;
}
final JassProgramVisitor jassProgramVisitor = new JassProgramVisitor();
jassProgramVisitor.getJassNativeManager().createNative("BJDebugMsg", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
for (final JassValue argument : arguments) {
System.out.println(argument.visit(StringJassValueVisitor.getInstance()));
}
return null;
}
});
for (final String arg : args) {
try {
jassProgramVisitor.setCurrentFileName(arg);
final JassLexer lexer = new JassLexer(CharStreams.fromFileName(arg));
final JassParser parser = new JassParser(new CommonTokenStream(lexer));
parser.addErrorListener(new BaseErrorListener() {
@ -41,10 +60,13 @@ public class JassRunner {
}
});
jassProgramVisitor.visit(parser.program());
} catch (final Exception e) {
}
catch (final Exception e) {
e.printStackTrace();
}
}
jassProgramVisitor.getGlobals().getFunctionByName("main").call(Collections.emptyList(),
jassProgramVisitor.getGlobals(), null);
}
}

View File

@ -3,6 +3,7 @@ package com.etheller.interpreter.ast.expression;
import java.util.ArrayList;
import java.util.List;
import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.LocalScope;
@ -23,7 +24,7 @@ public class FunctionCallJassExpression implements JassExpression {
final TriggerExecutionScope triggerScope) {
final JassFunction functionByName = globalScope.getFunctionByName(this.functionName);
if (functionByName == null) {
throw new RuntimeException("Undefined function: " + this.functionName);
throw new JassException(globalScope, "Undefined function: " + this.functionName, new RuntimeException());
}
final List<JassValue> evaluatedExpressions = new ArrayList<>();
for (final JassExpression expr : this.arguments) {
@ -34,7 +35,7 @@ public class FunctionCallJassExpression implements JassExpression {
return functionByName.call(evaluatedExpressions, globalScope, triggerScope);
}
catch (final Exception exc) {
throw new RuntimeException("Function call by name failed for name: " + this.functionName, exc);
throw new JassException(globalScope, "Function call by name failed for name: " + this.functionName, exc);
}
}