Update to support red and green status under buildings

This commit is contained in:
Retera 2020-11-27 20:45:21 -05:00
parent 94d5d51f93
commit b60233a5a2
9 changed files with 178 additions and 76 deletions

View File

@ -2,7 +2,7 @@ package com.etheller.warsmash.viewer5;
import com.etheller.warsmash.viewer5.handlers.ResourceHandler;
public abstract class Texture extends HandlerResource<ResourceHandler> {
public abstract class Texture extends HandlerResource<ResourceHandler> implements ViewerTextureRenderable {
public Texture(final ModelViewer viewer, final String extension, final PathSolver pathSolver, final String fetchUrl,
final ResourceHandler handler) {
@ -17,8 +17,10 @@ public abstract class Texture extends HandlerResource<ResourceHandler> {
public abstract int getHeight();
@Override
public abstract int getGlTarget();
@Override
public abstract int getGlHandle();
public abstract void setWrapS(final boolean wrapS);

View File

@ -0,0 +1,29 @@
package com.etheller.warsmash.viewer5;
import com.badlogic.gdx.graphics.Texture;
public interface ViewerTextureRenderable {
// TODO bind method makes more sense here
int getGlTarget();
int getGlHandle();
class GdxViewerTextureRenderable implements ViewerTextureRenderable {
private final com.badlogic.gdx.graphics.Texture gdxTexture;
public GdxViewerTextureRenderable(final Texture texture) {
this.gdxTexture = texture;
}
@Override
public int getGlTarget() {
return this.gdxTexture.glTarget;
}
@Override
public int getGlHandle() {
return this.gdxTexture.getTextureObjectHandle();
}
}
}

View File

@ -9,7 +9,7 @@ import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.etheller.warsmash.util.RenderMathUtils;
import com.etheller.warsmash.viewer5.Texture;
import com.etheller.warsmash.viewer5.ViewerTextureRenderable;
/**
* TODO this is copied from RivSoft stuff.
@ -22,7 +22,7 @@ import com.etheller.warsmash.viewer5.Texture;
*/
public class SplatModel {
private static final int MAX_VERTICES = 65000;
private final Texture texture;
private final ViewerTextureRenderable texture;
private final List<Batch> batches;
public final float[] color;
private final List<float[]> locations;
@ -30,8 +30,9 @@ public class SplatModel {
private final boolean unshaded;
private final boolean noDepthTest;
public SplatModel(final GL30 gl, final Texture texture, final List<float[]> locations, final float[] centerOffset,
final List<Consumer<SplatMover>> unitMapping, final boolean unshaded, final boolean noDepthTest) {
public SplatModel(final GL30 gl, final ViewerTextureRenderable texture, final List<float[]> locations,
final float[] centerOffset, final List<Consumer<SplatMover>> unitMapping, final boolean unshaded,
final boolean noDepthTest) {
this.texture = texture;
this.unshaded = unshaded;
this.noDepthTest = noDepthTest;
@ -245,9 +246,9 @@ public class SplatModel {
return this.noDepthTest;
}
public SplatMover add(final float x, final float y, final float w, final float h, final float zDepthUpward,
public SplatMover add(final float x, final float y, final float x2, final float y2, final float zDepthUpward,
final float[] centerOffset) {
this.locations.add(new float[] { x, y, w, h, zDepthUpward });
this.locations.add(new float[] { x, y, x2, y2, zDepthUpward });
final SplatMover splatMover;
if (this.splatInstances != null) {
splatMover = new SplatMover(this);

View File

@ -910,8 +910,14 @@ public class War3MapViewer extends ModelViewer {
buildingPathingPixelMap = getBuildingPathingPixelMap(row);
if (buildingPathingPixelMap != null) {
unitX = Math.round(unitX / 64f) * 64f;
unitY = Math.round(unitY / 64f) * 64f;
unitX = (float) Math.floor(unitX / 64f) * 64f;
unitY = (float) Math.floor(unitY / 64f) * 64f;
if (((buildingPathingPixelMap.getWidth() / 2) % 2) == 1) {
unitX += 32f;
}
if (((buildingPathingPixelMap.getHeight() / 2) % 2) == 1) {
unitY += 32f;
}
pathingInstance = this.terrain.pathingGrid.blitRemovablePathingOverlayTexture(unitX, unitY,
(int) Math.toDegrees(unitAngle), buildingPathingPixelMap);
}

View File

@ -141,91 +141,37 @@ public class PathingGrid {
short anyPathingTypeWithUnit = 0;
if (cWorldCollision.intersectsAnythingOtherThan(pathingMapRectangle, unitToExcludeFromCollisionChecks,
MovementType.AMPHIBIOUS)) {
System.out.println("intersects amph unit");
anyPathingTypesInRegion |= PathingFlags.UNBUILDABLE | PathingFlags.UNWALKABLE | PathingFlags.UNSWIMABLE;
anyPathingTypeWithUnit |= PathingFlags.UNBUILDABLE | PathingFlags.UNWALKABLE | PathingFlags.UNSWIMABLE;
}
if (cWorldCollision.intersectsAnythingOtherThan(pathingMapRectangle, unitToExcludeFromCollisionChecks,
MovementType.FLOAT)) {
System.out.println("intersects float unit");
anyPathingTypesInRegion |= PathingFlags.UNSWIMABLE;
anyPathingTypeWithUnit |= PathingFlags.UNSWIMABLE;
}
if (cWorldCollision.intersectsAnythingOtherThan(pathingMapRectangle, unitToExcludeFromCollisionChecks,
MovementType.FLY)) {
System.out.println("intersects fly unit");
anyPathingTypesInRegion |= PathingFlags.UNFLYABLE;
anyPathingTypeWithUnit |= PathingFlags.UNFLYABLE;
}
if (cWorldCollision.intersectsAnythingOtherThan(pathingMapRectangle, unitToExcludeFromCollisionChecks,
MovementType.FOOT)) {
System.out.println("intersects foot unit");
anyPathingTypesInRegion |= PathingFlags.UNBUILDABLE | PathingFlags.UNWALKABLE;
anyPathingTypeWithUnit |= PathingFlags.UNBUILDABLE | PathingFlags.UNWALKABLE;
}
pathingTypesFillingRegion &= anyPathingTypeWithUnit;
for (final CBuildingPathingType pathingType : preventPathingTypes) {
switch (pathingType) {
case BLIGHTED:
throw new IllegalArgumentException("Blight pathing check system is Not Yet Implemented");
case UNAMPH:
if (PathingFlags.isPathingFlag(anyPathingTypesInRegion, PathingFlags.UNWALKABLE)
&& PathingFlags.isPathingFlag(anyPathingTypesInRegion, PathingFlags.UNSWIMABLE)) {
return false;
}
break;
case UNBUILDABLE:
if (PathingFlags.isPathingFlag(anyPathingTypesInRegion, PathingFlags.UNBUILDABLE)) {
return false;
}
break;
case UNFLOAT:
if (PathingFlags.isPathingFlag(anyPathingTypesInRegion, PathingFlags.UNSWIMABLE)) {
return false;
}
break;
case UNFLYABLE:
if (PathingFlags.isPathingFlag(anyPathingTypesInRegion, PathingFlags.UNFLYABLE)) {
return false;
}
break;
case UNWALKABLE:
if (PathingFlags.isPathingFlag(anyPathingTypesInRegion, PathingFlags.UNWALKABLE)) {
return false;
}
break;
default:
break;
if (PathingFlags.isPathingFlag(anyPathingTypesInRegion, pathingType)) {
return false;
}
}
for (final CBuildingPathingType pathingType : requirePathingTypes) {
switch (pathingType) {
case BLIGHTED:
throw new IllegalArgumentException("Blight pathing check system is Not Yet Implemented");
case UNAMPH:
if (!PathingFlags.isPathingFlag(pathingTypesFillingRegion, PathingFlags.UNWALKABLE)
|| !PathingFlags.isPathingFlag(pathingTypesFillingRegion, PathingFlags.UNSWIMABLE)) {
return false;
}
break;
case UNBUILDABLE:
if (!PathingFlags.isPathingFlag(pathingTypesFillingRegion, PathingFlags.UNBUILDABLE)) {
return false;
}
break;
case UNFLOAT:
if (!PathingFlags.isPathingFlag(pathingTypesFillingRegion, PathingFlags.UNSWIMABLE)) {
return false;
}
break;
case UNFLYABLE:
if (!PathingFlags.isPathingFlag(pathingTypesFillingRegion, PathingFlags.UNFLYABLE)) {
return false;
}
break;
case UNWALKABLE:
if (!PathingFlags.isPathingFlag(pathingTypesFillingRegion, PathingFlags.UNWALKABLE)) {
return false;
}
break;
default:
break;
if (!PathingFlags.isPathingFlag(pathingTypesFillingRegion, pathingType)) {
return false;
}
}
return true;
@ -383,6 +329,26 @@ public class PathingGrid {
return (pathingValue & flag) != 0;
}
public static boolean isPathingFlag(final short pathingValue, final CBuildingPathingType pathingType) {
switch (pathingType) {
case BLIGHTED:
throw new IllegalArgumentException("Blight pathing check system is Not Yet Implemented");
case UNAMPH:
return PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNWALKABLE)
&& PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNSWIMABLE);
case UNBUILDABLE:
return PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNBUILDABLE);
case UNFLOAT:
return PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNSWIMABLE);
case UNFLYABLE:
return PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNFLYABLE);
case UNWALKABLE:
return PathingFlags.isPathingFlag(pathingValue, PathingFlags.UNWALKABLE);
default:
return false;
}
}
private PathingFlags() {
}
}

View File

@ -190,6 +190,9 @@ public class CWorldCollision {
@Override
public boolean onIntersect(final CUnit intersectingObject) {
if (intersectingObject.isHidden()) {
return false;
}
return (intersectingObject != this.firstUnit) && (intersectingObject != this.secondUnit);
}
}
@ -208,6 +211,9 @@ public class CWorldCollision {
@Override
public boolean onIntersect(final CUnit intersectingObject) {
if (intersectingObject.isHidden()) {
return false;
}
if (this.done) {
return true;
}

View File

@ -1,5 +1,6 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.awt.image.BufferedImage;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
@ -41,6 +42,18 @@ public class CAbilityOrcBuild extends AbstractCAbilityBuild {
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
final BufferedImage buildingPathingPixelMap = game.getUnitData().getUnitType(new War3ID(orderId))
.getBuildingPathingPixelMap();
if (buildingPathingPixelMap != null) {
point.x = (float) Math.floor(point.x / 64f) * 64f;
point.y = (float) Math.floor(point.y / 64f) * 64f;
if (((buildingPathingPixelMap.getWidth() / 2) % 2) == 1) {
point.x += 32f;
}
if (((buildingPathingPixelMap.getHeight() / 2) % 2) == 1) {
point.y += 32f;
}
}
return this.buildBehavior.reset(point, orderId, getBaseOrderId());
}

View File

@ -44,7 +44,6 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CBuildingPa
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
public class CUnitData {
private static final War3ID RALLY_RAWCODE = War3ID.fromString("ARal");
private static final War3ID MANA_INITIAL_AMOUNT = War3ID.fromString("umpi");
private static final War3ID MANA_MAXIMUM = War3ID.fromString("umpm");
private static final War3ID HIT_POINT_MAXIMUM = War3ID.fromString("uhpm");

View File

@ -11,11 +11,15 @@ import javax.imageio.ImageIO;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Blending;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
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.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
@ -43,6 +47,7 @@ import com.etheller.warsmash.util.RenderMathUtils;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.Scene;
import com.etheller.warsmash.viewer5.ViewerTextureRenderable;
import com.etheller.warsmash.viewer5.handlers.mdx.Attachment;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxComplexInstance;
import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
@ -54,6 +59,7 @@ 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;
import com.etheller.warsmash.viewer5.handlers.w3x.SplatModel.SplatMover;
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
@ -61,6 +67,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraPreset;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraRates;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.GameCameraManager;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.PortraitCameraManager;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.PathingFlags;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
@ -101,6 +108,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CodeKeyType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttackMissileSplash;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CBuildingPathingType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayerUnitOrderListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.BooleanAbilityTargetCheckReceiver;
@ -113,6 +121,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.QueueIconListener;
public class MeleeUI
implements CUnitStateListener, CommandButtonListener, CommandCardCommandListener, QueueIconListener {
private static final String BUILDING_PATHING_PREVIEW_KEY = "buildingPathingPreview";
public static final float DEFAULT_COMMAND_CARD_ICON_WIDTH = 0.039f;
public static final float DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH = 0.037f;
private static final int COMMAND_CARD_WIDTH = 4;
@ -192,6 +201,11 @@ public class MeleeUI
private MdxComplexInstance cursorModelInstance = null;
private MdxComplexInstance rallyPointInstance = null;
private BufferedImage cursorModelPathing;
private Pixmap cursorModelUnderneathPathingRedGreenPixmap;
private Texture cursorModelUnderneathPathingRedGreenPixmapTexture;
private PixmapTextureData cursorModelUnderneathPathingRedGreenPixmapTextureData;
private SplatModel cursorModelUnderneathPathingRedGreenSplatModel;
private CUnitType cursorBuildingUnitType;
private SplatMover placementCursor = null;
private final CursorTargetSetupVisitor cursorTargetSetupVisitor;
@ -632,11 +646,15 @@ public class MeleeUI
this.cursorModelInstance = null;
this.cursorFrame.setVisible(true);
}
else if (this.placementCursor != null) {
if (this.placementCursor != null) {
this.placementCursor.destroy(Gdx.gl30, this.war3MapViewer.terrain.centerOffset);
this.placementCursor = null;
this.cursorFrame.setVisible(true);
}
if (this.cursorModelUnderneathPathingRedGreenSplatModel != null) {
this.war3MapViewer.terrain.removeSplatBatchModel(BUILDING_PATHING_PREVIEW_KEY);
this.cursorModelUnderneathPathingRedGreenSplatModel = null;
}
if (down) {
if (left) {
this.cursorFrame.setSequence("Scroll Down Left");
@ -832,6 +850,7 @@ public class MeleeUI
if (MeleeUI.this.cursorModelInstance == null) {
final MutableObjectData unitData = viewer.getAllObjectData().getUnits();
final War3ID buildingTypeId = new War3ID(MeleeUI.this.activeCommandOrderId);
MeleeUI.this.cursorBuildingUnitType = viewer.simulation.getUnitData().getUnitType(buildingTypeId);
final String unitModelPath = viewer.getUnitModelPath(unitData.get(buildingTypeId));
final MdxModel model = (MdxModel) viewer.load(unitModelPath, viewer.mapPathSolver, viewer.solverParams);
MeleeUI.this.cursorModelInstance = (MdxComplexInstance) model.addInstance();
@ -843,14 +862,75 @@ public class MeleeUI
viewer.simulation.getGameplayConstants().getBuildingAngle()));
MeleeUI.this.cursorModelInstance.setAnimationSpeed(0f);
justLoaded = true;
final CUnitType buildingUnitType = viewer.simulation.getUnitData().getUnitType(buildingTypeId);
final CUnitType buildingUnitType = MeleeUI.this.cursorBuildingUnitType;
MeleeUI.this.cursorModelPathing = buildingUnitType.getBuildingPathingPixelMap();
if (MeleeUI.this.cursorModelPathing != null) {
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap = new Pixmap(
MeleeUI.this.cursorModelPathing.getWidth(), MeleeUI.this.cursorModelPathing.getHeight(),
Format.RGBA8888);
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.setBlending(Blending.None);
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTextureData = new PixmapTextureData(
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap, Format.RGBA8888, false, false);
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTexture = new Texture(
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTextureData);
final ViewerTextureRenderable greenPixmap = new ViewerTextureRenderable.GdxViewerTextureRenderable(
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTexture);
MeleeUI.this.cursorModelUnderneathPathingRedGreenSplatModel = new SplatModel(Gdx.gl30, greenPixmap,
new ArrayList<>(), viewer.terrain.centerOffset, new ArrayList<>(), true, false);
MeleeUI.this.cursorModelUnderneathPathingRedGreenSplatModel.color[3] = 0.20f;
}
}
viewer.getClickLocation(clickLocationTemp, this.baseMouseX, Gdx.graphics.getHeight() - this.baseMouseY);
if (MeleeUI.this.cursorModelPathing != null) {
clickLocationTemp.x = Math.round(clickLocationTemp.x / 64f) * 64f;
clickLocationTemp.y = Math.round(clickLocationTemp.y / 64f) * 64f;
clickLocationTemp.x = (float) Math.floor(clickLocationTemp.x / 64f) * 64f;
clickLocationTemp.y = (float) Math.floor(clickLocationTemp.y / 64f) * 64f;
if (((MeleeUI.this.cursorModelPathing.getWidth() / 2) % 2) == 1) {
clickLocationTemp.x += 32f;
}
if (((MeleeUI.this.cursorModelPathing.getHeight() / 2) % 2) == 1) {
clickLocationTemp.y += 32f;
}
clickLocationTemp.z = viewer.terrain.getGroundHeight(clickLocationTemp.x, clickLocationTemp.y);
final float halfRenderWidth = MeleeUI.this.cursorModelPathing.getWidth() * 16;
final float halfRenderHeight = MeleeUI.this.cursorModelPathing.getHeight() * 16;
for (int i = 0; i < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getWidth(); i++) {
for (int j = 0; j < MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getHeight(); j++) {
boolean blocked = false;
final short pathing = viewer.simulation.getPathingGrid().getPathing(
(clickLocationTemp.x + (i * 32)) - halfRenderWidth,
(clickLocationTemp.y + (j * 32)) - halfRenderHeight);
for (final CBuildingPathingType preventedType : MeleeUI.this.cursorBuildingUnitType
.getPreventedPathingTypes()) {
if (PathingFlags.isPathingFlag(pathing, preventedType)) {
blocked = true;
}
}
for (final CBuildingPathingType requiredType : MeleeUI.this.cursorBuildingUnitType
.getRequiredPathingTypes()) {
if (!PathingFlags.isPathingFlag(pathing, requiredType)) {
blocked = true;
}
}
final int color = blocked ? Color.rgba8888(1, 0, 0, 1.0f) : Color.rgba8888(0, 1, 0, 1.0f);
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.drawPixel(i,
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmap.getHeight() - 1 - j, color);
}
}
MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTexture
.load(MeleeUI.this.cursorModelUnderneathPathingRedGreenPixmapTextureData);
if (justLoaded) {
viewer.terrain.addSplatBatchModel(BUILDING_PATHING_PREVIEW_KEY,
MeleeUI.this.cursorModelUnderneathPathingRedGreenSplatModel);
MeleeUI.this.placementCursor = MeleeUI.this.cursorModelUnderneathPathingRedGreenSplatModel.add(
clickLocationTemp.x - halfRenderWidth, clickLocationTemp.y - halfRenderHeight,
clickLocationTemp.x + halfRenderWidth, clickLocationTemp.y + halfRenderHeight, 10,
viewer.terrain.centerOffset);
}
MeleeUI.this.placementCursor.setLocation(clickLocationTemp.x, clickLocationTemp.y,
viewer.terrain.centerOffset);
}
MeleeUI.this.cursorModelInstance.setLocation(clickLocationTemp);
SequenceUtils.randomSequence(MeleeUI.this.cursorModelInstance, PrimaryTag.STAND);