wisp harvest and ScrollBarFrame

This commit is contained in:
Retera 2021-12-09 17:02:40 -05:00
parent 50164d8ef7
commit 84f015ef42
31 changed files with 2239 additions and 1212 deletions

View File

@ -160,6 +160,11 @@ public class CascDataSource implements DataSource {
return internalGetFile(filepath);
}
@Override
public File getDirectory(String filepath) throws IOException {
return null;
}
private File internalGetFile(final String tempFilepath) {
try {
if (this.rootFileSystem.isFile(tempFilepath) && this.rootFileSystem.isFileAvailable(tempFilepath)) {

View File

@ -47,6 +47,24 @@ public class CompoundDataSource implements DataSource {
return null;
}
@Override
public File getDirectory(String filepath) throws IOException {
try {
for (int i = this.mpqList.size() - 1; i >= 0; i--) {
final DataSource mpq = this.mpqList.get(i);
final File tempProduct = mpq.getDirectory(filepath);
if (tempProduct != null) {
return tempProduct;
}
}
}
catch (final IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
public ByteBuffer read(final String path) throws IOException {
try {

View File

@ -28,6 +28,15 @@ public interface DataSource {
*/
File getFile(String filepath) throws IOException;
/**
* Returns a directory from a FolderDataSource, otherwise returns null
*
* @param filepath
* @return
* @throws IOException
*/
File getDirectory(String filepath) throws IOException;
ByteBuffer read(String path) throws IOException;
/**

View File

@ -52,6 +52,16 @@ public class FolderDataSource implements DataSource {
return new File(this.folderPath.toString() + File.separatorChar + filepath);
}
@Override
public File getDirectory(String filepath) throws IOException {
filepath = fixFilepath(filepath);
File file = new File(this.folderPath.toString() + File.separatorChar + filepath);
if(!file.exists() || !file.isDirectory()) {
return null;
}
return file;
}
@Override
public ByteBuffer read(String path) throws IOException {
path = fixFilepath(path);

View File

@ -112,6 +112,11 @@ public class MpqDataSource implements DataSource {
return tempProduct;
}
@Override
public File getDirectory(String filepath) throws IOException {
return null;
}
@Override
public boolean has(final String filepath) {
try {

View File

@ -22,6 +22,11 @@ public class SubdirDataSource implements DataSource {
return this.dataSource.getFile(this.subdir + filepath);
}
@Override
public File getDirectory(String filepath) throws IOException {
return this.dataSource.getDirectory(this.subdir + filepath);
}
@Override
public ByteBuffer read(final String path) throws IOException {
return this.dataSource.read(this.subdir + path);

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
private UIFrame activeChild;
private Runnable onClick;
private ButtonListener buttonListener = ButtonListener.DO_NOTHING;
public GlueButtonFrame(final String name, final UIFrame parent) {
super(name, parent);
@ -66,6 +67,10 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
this.onClick = onClick;
}
public void setButtonListener(ButtonListener buttonListener) {
this.buttonListener = buttonListener;
}
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
if (this.controlBackdrop != null) {
@ -101,14 +106,20 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
@Override
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
if (this.enabled) {
this.activeChild = this.controlPushedBackdrop;
if(this.controlPushedBackdrop != null) {
this.activeChild = this.controlPushedBackdrop;
}
buttonListener.mouseDown(gameUI, uiViewport);
}
}
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
if (this.enabled) {
this.activeChild = this.controlBackdrop;
if(this.controlBackdrop != null) {
this.activeChild = this.controlBackdrop;
}
buttonListener.mouseUp(gameUI, uiViewport);
}
}
@ -139,6 +150,11 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
}
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
buttonListener.mouseDragged(rootFrame, uiViewport, x,y);
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {
@ -163,4 +179,21 @@ public class GlueButtonFrame extends AbstractRenderableFrame implements Clickabl
return super.getFrameChildUnderMouse(screenX, screenY);
}
public interface ButtonListener {
void mouseDown(GameUI gameUI, Viewport uiViewport);
void mouseUp(GameUI gameUI, Viewport uiViewport);
void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y);
ButtonListener DO_NOTHING = new ButtonListener() {
@Override
public void mouseDown(GameUI gameUI, Viewport uiViewport) {}
@Override
public void mouseUp(GameUI gameUI, Viewport uiViewport) {}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {}
};
}
}

View File

@ -15,188 +15,281 @@ import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.datamodel.TextJustify;
public class ListBoxFrame extends ControlFrame {
// TODO where are these colors in the UI definition files?
private static final Color SELECT_COLOR = Color.BLUE;
private static final Color MOUSE_OVER_HIGHLIGHT_COLOR = new Color(0.3f, 0.3f, 1.0f, 0.25f);
public class ListBoxFrame extends ControlFrame implements ScrollBarFrame.ScrollBarChangeListener {
// TODO where are these colors in the UI definition files?
private static final Color SELECT_COLOR = Color.BLUE;
private static final Color MOUSE_OVER_HIGHLIGHT_COLOR = new Color(0.3f, 0.3f, 1.0f, 0.25f);
private final List<String> listItems = new ArrayList<>();
private final List<SingleStringFrame> stringFrames = new ArrayList<>();
private BitmapFont frameFont;
private float listBoxBorder;
private int selectedIndex = -1;
private int mouseOverIndex = -1;
private final List<String> listItems = new ArrayList<>();
private final List<SingleStringFrame> stringFrames = new ArrayList<>();
private BitmapFont frameFont;
private float listBoxBorder;
private int selectedIndex = -1;
private int mouseOverIndex = -1;
private final TextureFrame selectionFrame;
private final TextureFrame mouseHighlightFrame;
private GameUI gameUI;
private Viewport viewport;
private Runnable onSelect;
private final TextureFrame selectionFrame;
private final TextureFrame mouseHighlightFrame;
private GameUI gameUI;
private Viewport viewport;
private Runnable onSelect;
private ScrollBarFrame scrollBarFrame;
public ListBoxFrame(final String name, final UIFrame parent, final Viewport viewport) {
super(name, parent);
this.listBoxBorder = GameUI.convertX(viewport, 0.01f);
this.selectionFrame = new TextureFrame(null, this, false, null);
this.mouseHighlightFrame = new TextureFrame(null, this, false, null);
final Pixmap pixmap = new Pixmap(1, 1, Format.RGBA8888);
pixmap.setColor(SELECT_COLOR);
pixmap.fill();
this.selectionFrame.setTexture(new Texture(pixmap));
final Pixmap mousePixmap = new Pixmap(1, 1, Format.RGBA8888);
mousePixmap.setColor(MOUSE_OVER_HIGHLIGHT_COLOR);
mousePixmap.fill();
this.mouseHighlightFrame.setTexture(new Texture(mousePixmap));
}
public ListBoxFrame(final String name, final UIFrame parent, final Viewport viewport) {
super(name, parent);
this.listBoxBorder = GameUI.convertX(viewport, 0.01f);
this.selectionFrame = new TextureFrame(null, this, false, null);
this.mouseHighlightFrame = new TextureFrame(null, this, false, null);
final Pixmap pixmap = new Pixmap(1, 1, Format.RGBA8888);
pixmap.setColor(SELECT_COLOR);
pixmap.fill();
this.selectionFrame.setTexture(new Texture(pixmap));
final Pixmap mousePixmap = new Pixmap(1, 1, Format.RGBA8888);
mousePixmap.setColor(MOUSE_OVER_HIGHLIGHT_COLOR);
mousePixmap.fill();
this.mouseHighlightFrame.setTexture(new Texture(mousePixmap));
}
public void setListBoxBorder(final float listBoxBorder) {
this.listBoxBorder = listBoxBorder;
}
public void setScrollBarFrame(ScrollBarFrame scrollBarFrame) {
this.scrollBarFrame = scrollBarFrame;
// TODO might be a better place to add these set points, but we definitely need them
scrollBarFrame.addSetPoint(new SetPoint(FramePoint.TOPRIGHT, this, FramePoint.TOPRIGHT, -listBoxBorder, -listBoxBorder));
scrollBarFrame.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, this, FramePoint.BOTTOMRIGHT, -listBoxBorder, listBoxBorder));
scrollBarFrame.setChangeListener(this);
}
public float getListBoxBorder() {
return this.listBoxBorder;
}
public ScrollBarFrame getScrollBarFrame() {
return scrollBarFrame;
}
public void setFrameFont(final BitmapFont frameFont) {
this.frameFont = frameFont;
}
public void setListBoxBorder(final float listBoxBorder) {
this.listBoxBorder = listBoxBorder;
}
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
this.gameUI = gameUI;
this.viewport = viewport;
super.innerPositionBounds(gameUI, viewport);
updateUI(gameUI, viewport);
}
public float getListBoxBorder() {
return this.listBoxBorder;
}
private void positionChildren(final GameUI gameUI, final Viewport viewport) {
for (final SingleStringFrame frame : this.stringFrames) {
frame.positionBounds(gameUI, viewport);
}
this.selectionFrame.positionBounds(gameUI, viewport);
this.mouseHighlightFrame.positionBounds(gameUI, viewport);
}
public void setFrameFont(final BitmapFont frameFont) {
this.frameFont = frameFont;
}
@Override
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
super.internalRender(batch, baseFont, glyphLayout);
this.selectionFrame.render(batch, baseFont, glyphLayout);
this.mouseHighlightFrame.render(batch, baseFont, glyphLayout);
for (final SingleStringFrame frame : this.stringFrames) {
frame.render(batch, baseFont, glyphLayout);
}
}
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
this.gameUI = gameUI;
this.viewport = viewport;
super.innerPositionBounds(gameUI, viewport);
updateUI(gameUI, viewport);
}
public void addItem(final String item, final GameUI gameUI, final Viewport viewport) {
this.listItems.add(item);
updateUI(gameUI, viewport);
}
private void positionChildren(final GameUI gameUI, final Viewport viewport) {
for (final SingleStringFrame frame : this.stringFrames) {
frame.positionBounds(gameUI, viewport);
}
this.selectionFrame.positionBounds(gameUI, viewport);
this.mouseHighlightFrame.positionBounds(gameUI, viewport);
if (scrollBarFrame != null) {
this.scrollBarFrame.positionBounds(gameUI, viewport);
}
}
public void setItems(final List<String> items, final GameUI gameUI, final Viewport viewport) {
this.listItems.clear();
this.listItems.addAll(items);
updateUI(gameUI, viewport);
}
@Override
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
super.internalRender(batch, baseFont, glyphLayout);
this.selectionFrame.render(batch, baseFont, glyphLayout);
this.mouseHighlightFrame.render(batch, baseFont, glyphLayout);
for (final SingleStringFrame frame : this.stringFrames) {
frame.render(batch, baseFont, glyphLayout);
}
if (scrollBarFrame != null) {
scrollBarFrame.render(batch, baseFont, glyphLayout);
}
}
public void removeItem(final String item, final GameUI gameUI, final Viewport viewport) {
this.listItems.remove(item);
updateUI(gameUI, viewport);
}
public void addItem(final String item, final GameUI gameUI, final Viewport viewport) {
this.listItems.add(item);
updateUI(gameUI, viewport);
}
public void removeItem(final int index, final GameUI gameUI, final Viewport viewport) {
this.listItems.remove(index);
updateUI(gameUI, viewport);
}
public void setItems(final List<String> items, final GameUI gameUI, final Viewport viewport) {
this.listItems.clear();
this.listItems.addAll(items);
updateUI(gameUI, viewport);
}
public void setSelectedIndex(final int selectedIndex) {
this.selectedIndex = selectedIndex;
}
public void removeItem(final String item, final GameUI gameUI, final Viewport viewport) {
this.listItems.remove(item);
updateUI(gameUI, viewport);
}
public int getSelectedIndex() {
return this.selectedIndex;
}
public void removeItem(final int index, final GameUI gameUI, final Viewport viewport) {
this.listItems.remove(index);
updateUI(gameUI, viewport);
}
private void updateUI(final GameUI gameUI, final Viewport viewport) {
this.stringFrames.clear();
SingleStringFrame prev = null;
int i = 0;
boolean foundSelected = false;
boolean foundMouseOver = false;
for (final String string : this.listItems) {
final boolean selected = (i == this.selectedIndex);
final boolean mousedOver = (i == this.mouseOverIndex);
final SingleStringFrame stringFrame = new SingleStringFrame("LISTY" + i++, this, Color.WHITE,
TextJustify.LEFT, TextJustify.MIDDLE, this.frameFont);
stringFrame.setText(string);
stringFrame.setWidth(this.renderBounds.width - (this.listBoxBorder * 2));
stringFrame.setHeight(this.frameFont.getLineHeight());
if (prev != null) {
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, prev, FramePoint.BOTTOMLEFT, 0, 0));
}
else {
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, this.listBoxBorder,
-this.listBoxBorder));
}
this.stringFrames.add(stringFrame);
prev = stringFrame;
if (selected) {
this.selectionFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
this.selectionFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
foundSelected = true;
}
else if (mousedOver) {
this.mouseHighlightFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
this.mouseHighlightFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
foundMouseOver = true;
}
}
this.selectionFrame.setVisible(foundSelected);
this.mouseHighlightFrame.setVisible(foundMouseOver);
positionChildren(gameUI, viewport);
}
public void setSelectedIndex(final int selectedIndex) {
this.selectedIndex = selectedIndex;
}
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
int index = 0;
for (final SingleStringFrame stringFrame : this.stringFrames) {
if (stringFrame.getRenderBounds().contains(screenX, screenY)) {
this.selectedIndex = index;
}
index++;
}
updateUI(this.gameUI, this.viewport);
if (this.onSelect != null) {
this.onSelect.run();
}
return this;
}
return super.touchDown(screenX, screenY, button);
}
public int getSelectedIndex() {
return this.selectedIndex;
}
@Override
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
int index = 0;
int mouseOverIndex = -1;
for (final SingleStringFrame stringFrame : this.stringFrames) {
if (stringFrame.getRenderBounds().contains(screenX, screenY)) {
mouseOverIndex = index;
}
index++;
}
if (this.mouseOverIndex != mouseOverIndex) {
this.mouseOverIndex = mouseOverIndex;
updateUI(this.gameUI, this.viewport);
}
}
return super.getFrameChildUnderMouse(screenX, screenY);
}
public String getSelectedItem() {
if(selectedIndex < 0 || selectedIndex >= listItems.size()) {
return null;
}
return listItems.get(selectedIndex);
}
public void setOnSelect(final Runnable onSelect) {
this.onSelect = onSelect;
}
private void updateUI(final GameUI gameUI, final Viewport viewport) {
SingleStringFrame prev = null;
boolean foundSelected = false;
boolean foundMouseOver = false;
int numStringFrames = (int)(Math.floor( (renderBounds.height - listBoxBorder*2) / (frameFont.getLineHeight()) ));
int scrollOffset = computeScrollOffset(numStringFrames);
if(numStringFrames != stringFrames.size()) {
this.stringFrames.clear();
for(int stringFrameIndex = 0; stringFrameIndex < numStringFrames; stringFrameIndex++) {
final int index = stringFrameIndex + scrollOffset;
final boolean selected = (index == this.selectedIndex);
final boolean mousedOver = (index == this.mouseOverIndex);
final SingleStringFrame stringFrame = new SingleStringFrame("LISTY" + index, this, Color.WHITE,
TextJustify.LEFT, TextJustify.MIDDLE, this.frameFont);
if(index < listItems.size()) {
stringFrame.setText(listItems.get(index));
}
stringFrame.setWidth(this.renderBounds.width - (this.listBoxBorder * 2));
stringFrame.setHeight(this.frameFont.getLineHeight());
if (prev != null) {
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, prev, FramePoint.BOTTOMLEFT, 0, 0));
} else {
stringFrame.addSetPoint(new SetPoint(FramePoint.TOPLEFT, this, FramePoint.TOPLEFT, this.listBoxBorder,
-this.listBoxBorder));
}
this.stringFrames.add(stringFrame);
prev = stringFrame;
if (selected) {
this.selectionFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
this.selectionFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
foundSelected = true;
} else if (mousedOver) {
this.mouseHighlightFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
this.mouseHighlightFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
foundMouseOver = true;
}
}
} else {
for(int stringFrameIndex = 0; stringFrameIndex < numStringFrames; stringFrameIndex++) {
final int index = stringFrameIndex + scrollOffset;
final boolean selected = (index == this.selectedIndex);
final boolean mousedOver = (index == this.mouseOverIndex);
SingleStringFrame stringFrame = stringFrames.get(stringFrameIndex);
if(index < listItems.size()) {
stringFrame.setText(listItems.get(index));
}
if (selected) {
this.selectionFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
this.selectionFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
foundSelected = true;
} else if (mousedOver) {
this.mouseHighlightFrame
.addSetPoint(new SetPoint(FramePoint.TOPLEFT, stringFrame, FramePoint.TOPLEFT, 0, 0));
this.mouseHighlightFrame
.addSetPoint(new SetPoint(FramePoint.BOTTOMRIGHT, stringFrame, FramePoint.BOTTOMRIGHT, 0, 0));
foundMouseOver = true;
}
}
}
this.selectionFrame.setVisible(foundSelected);
this.mouseHighlightFrame.setVisible(foundMouseOver);
positionChildren(gameUI, viewport);
}
private int computeScrollOffset(int numStringFrames) {
int scrollOffset;
if(scrollBarFrame != null && listItems.size() > numStringFrames){
scrollOffset = (int)Math.ceil(((100 - scrollBarFrame.getValue()) / 100f) * (listItems.size() - numStringFrames));
} else {
scrollOffset = 0;
}
return scrollOffset;
}
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
if(scrollBarFrame!=null) {
UIFrame sliderFrameChildUnderMouse = scrollBarFrame.touchDown(screenX, screenY, button);
if (sliderFrameChildUnderMouse != null) {
return sliderFrameChildUnderMouse;
}
}
int index = 0;
for (final SingleStringFrame stringFrame : this.stringFrames) {
if (stringFrame.getRenderBounds().contains(screenX, screenY)) {
this.selectedIndex = index + computeScrollOffset(stringFrames.size());
}
index++;
}
updateUI(this.gameUI, this.viewport);
if (this.onSelect != null) {
this.onSelect.run();
}
return this;
}
return super.touchDown(screenX, screenY, button);
}
@Override
public UIFrame touchUp(float screenX, float screenY, int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
if (scrollBarFrame != null) {
UIFrame sliderFrameChildUnderMouse = scrollBarFrame.touchDown(screenX, screenY, button);
if (sliderFrameChildUnderMouse != null) {
return sliderFrameChildUnderMouse;
}
}
}
return super.touchUp(screenX, screenY, button);
}
@Override
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
if(scrollBarFrame!=null) {
UIFrame sliderFrameChildUnderMouse = scrollBarFrame.getFrameChildUnderMouse(screenX, screenY);
if (sliderFrameChildUnderMouse != null) {
return sliderFrameChildUnderMouse;
}
}
int index = 0;
int mouseOverIndex = -1;
for (final SingleStringFrame stringFrame : this.stringFrames) {
if (stringFrame.getRenderBounds().contains(screenX, screenY)) {
mouseOverIndex = index;
}
index++;
}
if (this.mouseOverIndex != mouseOverIndex) {
this.mouseOverIndex = mouseOverIndex + computeScrollOffset(stringFrames.size());
updateUI(this.gameUI, this.viewport);
}
}
return super.getFrameChildUnderMouse(screenX, screenY);
}
public void setOnSelect(final Runnable onSelect) {
this.onSelect = onSelect;
}
@Override
public void onChange(GameUI gameUI, Viewport uiViewport, int newValue) {
updateUI(gameUI, uiViewport);
}
}

View File

@ -0,0 +1,261 @@
package com.etheller.warsmash.parsers.fdf.frames;
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.utils.viewport.Viewport;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.ClickableFrame;
public class ScrollBarFrame extends AbstractRenderableFrame implements ClickableFrame {
private UIFrame controlBackdrop;
private UIFrame incButtonFrame;
private UIFrame decButtonFrame;
private UIFrame thumbButtonFrame;
private int scrollValuePercent = 50;
private ScrollBarChangeListener changeListener = ScrollBarChangeListener.DO_NOTHING;
public ScrollBarFrame(final String name, final UIFrame parent, boolean vertical) {
super(name, parent);
}
public void setControlBackdrop(final UIFrame controlBackdrop) {
this.controlBackdrop = controlBackdrop;
}
public void setIncButtonFrame(UIFrame incButtonFrame) {
this.incButtonFrame = incButtonFrame;
((GlueButtonFrame)incButtonFrame).setButtonListener(new GlueButtonFrame.ButtonListener() {
@Override
public void mouseDown(GameUI gameUI, Viewport uiViewport) {
}
@Override
public void mouseUp(GameUI gameUI, Viewport uiViewport) {
setValue(gameUI, uiViewport, scrollValuePercent+10);
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
});
}
public void setDecButtonFrame(UIFrame decButtonFrame) {
this.decButtonFrame = decButtonFrame;
((GlueButtonFrame)decButtonFrame).setButtonListener(new GlueButtonFrame.ButtonListener() {
@Override
public void mouseDown(GameUI gameUI, Viewport uiViewport) {
}
@Override
public void mouseUp(GameUI gameUI, Viewport uiViewport) {
setValue(gameUI, uiViewport, scrollValuePercent-10);
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
});
}
public void setThumbButtonFrame(UIFrame thumbButtonFrame) {
if (this.thumbButtonFrame instanceof GlueButtonFrame) {
((GlueButtonFrame) this.thumbButtonFrame).setButtonListener(GlueButtonFrame.ButtonListener.DO_NOTHING);
}
this.thumbButtonFrame = thumbButtonFrame;
if (thumbButtonFrame instanceof GlueButtonFrame) {
GlueButtonFrame frame = (GlueButtonFrame) thumbButtonFrame;
frame.setButtonListener(new GlueButtonFrame.ButtonListener() {
@Override
public void mouseDown(GameUI gameUI, Viewport uiViewport) {
}
@Override
public void mouseUp(GameUI gameUI, Viewport uiViewport) {
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
ScrollBarFrame.this.mouseDragged(rootFrame, uiViewport, x, y);
}
});
}
}
private float getMaxThumbButtonTravelDistance() {
return renderBounds.height - thumbButtonFrame.getAssignedHeight() - incButtonFrame.getAssignedHeight() - decButtonFrame.getAssignedHeight();
}
public void setValue(GameUI gameUI, Viewport uiViewport, int percent) {
this.scrollValuePercent = Math.min(100,Math.max(0,percent));
updateThumbButtonPoint();
changeListener.onChange(gameUI, uiViewport, this.scrollValuePercent);
positionBounds(gameUI, uiViewport);
}
public int getValue() {
return scrollValuePercent;
}
public void updateThumbButtonPoint() {
float newYValue = scrollValuePercent / 100f * getMaxThumbButtonTravelDistance();
thumbButtonFrame.addSetPoint(new SetPoint(FramePoint.BOTTOM, decButtonFrame, FramePoint.TOP, 0, newYValue));
}
@Override
protected void innerPositionBounds(final GameUI gameUI, final Viewport viewport) {
if (this.controlBackdrop != null) {
this.controlBackdrop.positionBounds(gameUI, viewport);
}
if (this.incButtonFrame != null) {
this.incButtonFrame.positionBounds(gameUI, viewport);
}
if (this.decButtonFrame != null) {
this.decButtonFrame.positionBounds(gameUI, viewport);
}
updateThumbButtonPoint();
if (this.thumbButtonFrame != null) {
this.thumbButtonFrame.positionBounds(gameUI, viewport);
}
}
@Override
protected void internalRender(final SpriteBatch batch, final BitmapFont baseFont, final GlyphLayout glyphLayout) {
if (this.controlBackdrop != null) {
controlBackdrop.render(batch, baseFont, glyphLayout);
}
if (this.incButtonFrame != null) {
this.incButtonFrame.render(batch, baseFont, glyphLayout);
}
if (this.decButtonFrame != null) {
this.decButtonFrame.render(batch, baseFont, glyphLayout);
}
if (this.thumbButtonFrame != null) {
this.thumbButtonFrame.render(batch, baseFont, glyphLayout);
}
}
@Override
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
}
@Override
public void mouseUp(final GameUI gameUI, final Viewport uiViewport) {
}
@Override
public void mouseEnter(final GameUI gameUI, final Viewport uiViewport) {
}
@Override
public void mouseExit(final GameUI gameUI, final Viewport uiViewport) {
}
@Override
public void onClick(final int button) {
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
float maxThumbButtonTravelDistance = getMaxThumbButtonTravelDistance();
int newScrollValuePercent = Math.min(100,Math.max(0,(int)((y - renderBounds.y - decButtonFrame.getAssignedHeight() - thumbButtonFrame.getAssignedHeight()/2) / maxThumbButtonTravelDistance * 100)));
if(newScrollValuePercent != scrollValuePercent) {
setValue(rootFrame, uiViewport, newScrollValuePercent);
positionBounds(rootFrame, uiViewport);
}
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
UIFrame frameChildUnderMouse = thumbButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = incButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = decButtonFrame.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = controlBackdrop.touchUp(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
return this;
}
return super.touchUp(screenX, screenY, button);
}
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
UIFrame frameChildUnderMouse = thumbButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = incButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = decButtonFrame.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = controlBackdrop.touchDown(screenX, screenY, button);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
return this;
}
return super.touchDown(screenX, screenY, button);
}
@Override
public UIFrame getFrameChildUnderMouse(final float screenX, final float screenY) {
if (isVisible() && this.renderBounds.contains(screenX, screenY)) {
UIFrame frameChildUnderMouse = thumbButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = incButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = decButtonFrame.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
frameChildUnderMouse = controlBackdrop.getFrameChildUnderMouse(screenX, screenY);
if (frameChildUnderMouse != null) {
return frameChildUnderMouse;
}
return this;
}
return super.getFrameChildUnderMouse(screenX, screenY);
}
public void setChangeListener(ScrollBarChangeListener changeListener) {
this.changeListener = changeListener;
}
public interface ScrollBarChangeListener {
void onChange(GameUI gameUI, Viewport uiViewport, int newValue);
ScrollBarChangeListener DO_NOTHING = new ScrollBarChangeListener() {
@Override
public void onChange(GameUI gameUI, Viewport uiViewport, int newValue) {
}
};
}
}

View File

@ -170,6 +170,11 @@ public class SimpleButtonFrame extends AbstractRenderableFrame implements Clicka
}
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
if (isVisible() && this.enabled && this.renderBounds.contains(screenX, screenY)) {

View File

@ -144,6 +144,11 @@ public class War3Map implements DataSource {
return this.dataSource.getFile(filepath);
}
@Override
public File getDirectory(String filepath) throws IOException {
return this.dataSource.getDirectory(filepath);
}
@Override
public boolean has(final String filepath) {
return this.dataSource.has(filepath);

View File

@ -536,8 +536,10 @@ public class MdxComplexInstance extends ModelInstance {
}
final MdxModel model = (MdxModel) this.model;
for (final GenericGroup group : model.opaqueGroups) {
group.render(this, this.scene.camera.viewProjectionMatrix);
if(additiveOverrideMeshMode) {
for (final GenericGroup group : model.opaqueGroups) {
group.render(this, this.scene.camera.viewProjectionMatrix);
}
}
for (final GenericGroup group : model.translucentGroups) {
group.render(this, this.scene.camera.viewProjectionMatrix);

View File

@ -21,6 +21,7 @@ import java.util.function.Consumer;
import javax.imageio.ImageIO;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderComponent;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;
@ -836,6 +837,34 @@ public class War3MapViewer extends AbstractMdxModelViewer {
spawnEffectOnUnit(unit, abilityUI.getTargetArt(0));
}
@Override
public SimulationRenderComponent createSpellEffectOverDestructable(CUnit source, CDestructable target, War3ID alias, float artAttachmentHeight) {
final AbilityUI abilityUI = War3MapViewer.this.abilityDataUI.getUI(alias);
String effectPath = abilityUI.getTargetArt(0);
RenderDestructable renderDestructable = War3MapViewer.this.destructableToRenderPeer.get(target);
final MdxModel spawnedEffectModel = loadModelMdx(effectPath);
if (spawnedEffectModel != null) {
final MdxComplexInstance modelInstance = (MdxComplexInstance) spawnedEffectModel
.addInstance();
modelInstance.setTeamColor(simulation.getPlayer(source.getPlayerIndex()).getColor());
modelInstance.setLocation(renderDestructable.getX(), renderDestructable.getY(), renderDestructable.getZ() + artAttachmentHeight);
modelInstance.setScene(War3MapViewer.this.worldScene);
final RenderSpellEffect renderAttackInstant = new RenderSpellEffect(modelInstance,
War3MapViewer.this,
0,
RenderSpellEffect.STAND_ONLY);
renderAttackInstant.setAnimations(RenderSpellEffect.STAND_ONLY, false);
War3MapViewer.this.projectiles.add(renderAttackInstant);
return new SimulationRenderComponent() {
@Override
public void remove() {
renderAttackInstant.setAnimations(RenderSpellEffect.DEATH_ONLY, true);
}
};
}
return null;
}
@Override
public void spawnUnitReadySound(final CUnit trainedUnit) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(trainedUnit);
@ -898,6 +927,28 @@ public class War3MapViewer extends AbstractMdxModelViewer {
}
}
@Override
public void loopAbilitySoundEffect(CUnit caster, War3ID alias) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(caster);
final AbilityUI abilityUi = War3MapViewer.this.abilityDataUI.getUI(alias);
if (abilityUi.getEffectSoundLooped() != null) {
War3MapViewer.this.uiSounds.getSound(abilityUi.getEffectSoundLooped()).play(
War3MapViewer.this.worldScene.audioContext, renderPeer.getX(), renderPeer.getY(),
renderPeer.getZ());
}
}
@Override
public void stopAbilitySoundEffect(CUnit caster, War3ID alias) {
final RenderUnit renderPeer = War3MapViewer.this.unitToRenderPeer.get(caster);
final AbilityUI abilityUi = War3MapViewer.this.abilityDataUI.getUI(alias);
if (abilityUi.getEffectSoundLooped() != null) {
// TODO below this probably stops all instances of the sound, which is silly
// and busted. Would be better to keep a notion of sound instance
War3MapViewer.this.uiSounds.getSound(abilityUi.getEffectSoundLooped()).stop();
}
}
@Override
public void unitPreferredSelectionReplacement(final CUnit oldUnit, final CUnit newUnit) {
final RenderUnit oldRenderPeer = War3MapViewer.this.unitToRenderPeer.get(oldUnit);

View File

@ -13,10 +13,13 @@ import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
public class RenderSpellEffect implements RenderEffect {
public static final PrimaryTag[] DEFAULT_ANIMATION_QUEUE = { PrimaryTag.BIRTH, PrimaryTag.STAND, PrimaryTag.DEATH };
public static final PrimaryTag[] STAND_ONLY = { PrimaryTag.STAND };
public static final PrimaryTag[] DEATH_ONLY = { PrimaryTag.DEATH };
private final MdxComplexInstance modelInstance;
private final PrimaryTag[] animationQueue;
private PrimaryTag[] animationQueue;
private int animationQueueIndex;
private final List<Sequence> sequences;
private boolean killWhenDone = true;
public RenderSpellEffect(final MdxComplexInstance modelInstance, final War3MapViewer war3MapViewer, final float yaw,
final PrimaryTag[] animationQueue) {
@ -33,11 +36,17 @@ public class RenderSpellEffect implements RenderEffect {
@Override
public boolean updateAnimations(final War3MapViewer war3MapViewer, final float deltaTime) {
playNextAnimation();
final boolean everythingDone = this.animationQueueIndex >= this.animationQueue.length;
if (everythingDone) {
war3MapViewer.worldScene.removeInstance(this.modelInstance);
if(killWhenDone) {
final boolean everythingDone = this.animationQueueIndex >= this.animationQueue.length;
if (everythingDone) {
war3MapViewer.worldScene.removeInstance(this.modelInstance);
}
return everythingDone;
} else {
animationQueueIndex = 0;
playNextAnimation();;
return false;
}
return everythingDone;
}
private void playNextAnimation() {
@ -50,4 +59,10 @@ public class RenderSpellEffect implements RenderEffect {
this.animationQueueIndex++;
}
}
public void setAnimations(PrimaryTag[] animations, boolean killWhenDone) {
animationQueue = animations;
animationQueueIndex = 0;
this.killWhenDone = killWhenDone;
}
}

View File

@ -2,14 +2,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;
import java.util.*;
import com.badlogic.gdx.math.Rectangle;
import com.etheller.interpreter.ast.scope.GlobalScope;
@ -49,6 +42,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.timers.CTimer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.JassGameEventsWar3;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CPlayerSlotState;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderComponent;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandErrorListener;
@ -87,6 +81,7 @@ public class CSimulation implements CPlayerAPI {
private final List<TimeOfDayVariableEvent> timeOfDayVariableEvents = new ArrayList<>();
private boolean timeOfDaySuspended;
private boolean daytime;
private Set<CDestructable> ownedTreeSet = new HashSet<>();
public CSimulation(final War3MapConfig config, final DataTable miscData, final MutableObjectData parsedUnitData,
final MutableObjectData parsedItemData, final MutableObjectData parsedDestructableData,
@ -121,7 +116,7 @@ public class CSimulation implements CPlayerAPI {
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CBasePlayer configPlayer = config.getPlayer(i);
final War3MapConfigStartLoc startLoc = config.getStartLoc(configPlayer.getStartLocationIndex());
final CRace defaultRace = CRace.NIGHTELF;
final CRace defaultRace = CRace.ORC;
final CPlayer newPlayer = new CPlayer(defaultRace, new float[] { startLoc.getX(), startLoc.getY() },
configPlayer);
if (WarsmashConstants.LOCAL_TEMP_TEST_ALL_PLAYERS_PLAYING) {
@ -524,6 +519,14 @@ public class CSimulation implements CPlayerAPI {
this.simulationRenderController.spawnAbilitySoundEffect(caster, alias);
}
public void unitLoopSoundEffectEvent(final CUnit caster, final War3ID alias) {
this.simulationRenderController.loopAbilitySoundEffect(caster, alias);
}
public void unitStopSoundEffectEvent(final CUnit caster, final War3ID alias) {
this.simulationRenderController.stopAbilitySoundEffect(caster, alias);
}
public void unitPreferredSelectionReplacement(final CUnit unit, final CUnit newUnit) {
this.simulationRenderController.unitPreferredSelectionReplacement(unit, newUnit);
}
@ -564,6 +567,22 @@ public class CSimulation implements CPlayerAPI {
cItem.setLife(this, 0);
}
public SimulationRenderComponent createSpellEffectOverDestructable(CUnit source, CDestructable target, War3ID alias, float artAttachmentHeight) {
return simulationRenderController.createSpellEffectOverDestructable(source, target, alias, artAttachmentHeight);
}
public void tagTreeOwned(CDestructable target) {
ownedTreeSet.add(target);
}
public void untagTreeOwned(CDestructable target) {
ownedTreeSet.remove(target);
}
public boolean isTreeOwned(CDestructable tree) {
return ownedTreeSet.contains(tree);
}
private static final class TimeOfDayVariableEvent extends VariableEvent {
private final GlobalScope globalScope;

View File

@ -0,0 +1,155 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.AbstractGenericSingleIconActiveAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorWispHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
import java.util.EnumSet;
public class CAbilityWispHarvest extends AbstractGenericSingleIconActiveAbility {
public static final EnumSet<CTargetType> TREE_ALIVE_TYPE_ONLY = EnumSet.of(CTargetType.TREE, CTargetType.ALIVE);
private int lumberPerInterval;
private float artAttachmentHeight;
private float castRange;
private float periodicIntervalLength;
private int periodicIntervalLengthTicks;
private CBehaviorWispHarvest behaviorWispHarvest;
public CAbilityWispHarvest(final int handleId, final War3ID alias, final int lumberPerInterval, float artAttachmentHeight,
float castRange, final float periodicIntervalLength) {
super(handleId, alias);
this.lumberPerInterval = lumberPerInterval;
this.artAttachmentHeight = artAttachmentHeight;
this.castRange = castRange;
this.periodicIntervalLength = periodicIntervalLength;
this.periodicIntervalLengthTicks = (int)(periodicIntervalLength / WarsmashConstants.SIMULATION_STEP_TIME);
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
this.behaviorWispHarvest = new CBehaviorWispHarvest(unit, this);
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public void onTick(final CSimulation game, final CUnit unit) {
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return this.behaviorWispHarvest.reset(target);
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
return caster.pollNextOrderBehavior(game);
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return caster.pollNextOrderBehavior(game);
}
@Override
public int getBaseOrderId() {
return isToggleOn() ? OrderIds.returnresources : OrderIds.wispharvest;
}
@Override
public boolean isToggleOn() {
return false;
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.useOk();
}
@Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
if (target instanceof CDestructable) {
if (target.canBeTargetedBy(game, unit, TREE_ALIVE_TYPE_ONLY)) {
receiver.targetOk(target);
}
else {
receiver.mustTargetResources();
}
}
else {
receiver.mustTargetResources();
}
}
@Override
protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId,
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
innerCheckCanTarget(game, unit, orderId, target, receiver);
}
@Override
protected void innerCheckCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanSmartTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
if ((orderId == OrderIds.returnresources) && isToggleOn()) {
receiver.targetOk(null);
}
else {
receiver.orderIdNotAccepted();
}
}
public float getArtAttachmentHeight() {
return artAttachmentHeight;
}
public float getPeriodicIntervalLength() {
return periodicIntervalLength;
}
public int getPeriodicIntervalLengthTicks() {
return periodicIntervalLengthTicks;
}
public int getLumberPerInterval() {
return lumberPerInterval;
}
public float getCastRange() {
return castRange;
}
@Override
public void onCancelFromQueue(final CSimulation game, final CUnit unit, final int orderId) {
}
}

View File

@ -0,0 +1,39 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl;
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeWispHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeWispHarvestLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
import java.util.EnumSet;
import java.util.List;
public class CAbilityTypeDefinitionWispHarvest extends AbstractCAbilityTypeDefinition<CAbilityTypeWispHarvestLevelData>
implements CAbilityTypeDefinition {
protected static final War3ID LUMBER_PER_INTERVAL = War3ID.fromString("Wha1");
// protected static final War3ID MAYBE_UNUSED = War3ID.fromString("Wha2");
protected static final War3ID ART_ATTACHMENT_HEIGHT = War3ID.fromString("Wha3");
@Override
protected CAbilityTypeWispHarvestLevelData createLevelData(final MutableGameObject abilityEditorData, final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
final int lumberPerInterval = abilityEditorData.getFieldAsInteger(LUMBER_PER_INTERVAL, level);
final float artAttachmentHeight = abilityEditorData.getFieldAsFloat(ART_ATTACHMENT_HEIGHT, level);
final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level);
final float duration = abilityEditorData.getFieldAsFloat(DURATION, level);
return new CAbilityTypeWispHarvestLevelData(targetsAllowedAtLevel, lumberPerInterval, artAttachmentHeight,
castRange, duration);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeWispHarvestLevelData> levelData) {
return new CAbilityTypeWispHarvest(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,25 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityWispHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import java.util.List;
public class CAbilityTypeWispHarvest extends CAbilityType<CAbilityTypeWispHarvestLevelData> {
public CAbilityTypeWispHarvest(final War3ID alias, final War3ID code,
final List<CAbilityTypeWispHarvestLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeWispHarvestLevelData levelData = getLevelData(0);
return new CAbilityWispHarvest(handleId, getAlias(), levelData.getLumberPerInterval(), levelData.getArtAttachmentHeight(),
levelData.getCastRange(), levelData.getDuration());
}
}

View File

@ -0,0 +1,39 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
import java.util.EnumSet;
public class CAbilityTypeWispHarvestLevelData extends CAbilityTypeLevelData {
private final int lumberPerInterval;
private final float artAttachmentHeight;
private final float castRange;
private final float duration;
public CAbilityTypeWispHarvestLevelData(final EnumSet<CTargetType> targetsAllowed, final int lumberPerInterval,
float artAttachmentHeight, final float castRange, final float duration) {
super(targetsAllowed);
this.lumberPerInterval = lumberPerInterval;
this.artAttachmentHeight = artAttachmentHeight;
this.castRange = castRange;
this.duration = duration;
}
public int getLumberPerInterval() {
return lumberPerInterval;
}
public float getArtAttachmentHeight() {
return artAttachmentHeight;
}
public float getCastRange() {
return this.castRange;
}
public float getDuration() {
return this.duration;
}
}

View File

@ -9,6 +9,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityWispHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor;

View File

@ -0,0 +1,154 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityWispHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderComponent;
public class CBehaviorWispHarvest extends CAbstractRangedBehavior {
private int lastIncomeTick;
private final CAbilityWispHarvest abilityWispHarvest;
private boolean harvesting = false;
private SimulationRenderComponent spellEffectOverDestructable;
public CBehaviorWispHarvest(CUnit unit, CAbilityWispHarvest abilityWispHarvest) {
super(unit);
this.abilityWispHarvest = abilityWispHarvest;
}
public CBehaviorWispHarvest reset(final CWidget target) {
innerReset(target, false);
return this;
}
@Override
protected CBehavior update(CSimulation simulation, boolean withinFacingWindow) {
if(target.getX() != unit.getX() || target.getY() != unit.getY()) {
unit.setX(target.getX(), simulation.getWorldCollision(), simulation.getRegionManager());
unit.setY(target.getY(), simulation.getWorldCollision(), simulation.getRegionManager());
simulation.unitRepositioned(unit); // dont interpolate, instant jump
}
int gameTurnTick = simulation.getGameTurnTick();
if (gameTurnTick - lastIncomeTick >= abilityWispHarvest.getPeriodicIntervalLengthTicks()) {
lastIncomeTick = gameTurnTick;
final CPlayer player = simulation.getPlayer(this.unit.getPlayerIndex());
player.setLumber(player.getLumber() + this.abilityWispHarvest.getLumberPerInterval());
simulation.unitGainResourceEvent(this.unit, ResourceType.LUMBER,
abilityWispHarvest.getLumberPerInterval());
}
if(!harvesting) {
onStartHarvesting(simulation);
harvesting = true;
}
return this;
}
private void onStartHarvesting(CSimulation simulation) {
unit.getUnitAnimationListener().addSecondaryTag(AnimationTokens.SecondaryTag.LUMBER);
simulation.unitLoopSoundEffectEvent(unit, abilityWispHarvest.getAlias());
// TODO maybe use visitor instead of cast
spellEffectOverDestructable = simulation.createSpellEffectOverDestructable(this.unit, (CDestructable) this.target, abilityWispHarvest.getAlias(), abilityWispHarvest.getArtAttachmentHeight());
simulation.tagTreeOwned((CDestructable)target);
}
private void onStopHarvesting(CSimulation simulation) {
unit.getUnitAnimationListener().removeSecondaryTag(AnimationTokens.SecondaryTag.LUMBER);
simulation.unitStopSoundEffectEvent(unit, abilityWispHarvest.getAlias());
simulation.untagTreeOwned((CDestructable)target);
// TODO maybe use visitor instead of cast
if(spellEffectOverDestructable != null) {
spellEffectOverDestructable.remove();
spellEffectOverDestructable = null;
}
}
@Override
protected CBehavior updateOnInvalidTarget(CSimulation simulation) {
if (this.target instanceof CDestructable) {
// wood
if(harvesting) {
onStopHarvesting(simulation);
harvesting = false;
}
final CDestructable nearestTree = findNearestTree(this.unit, this.abilityWispHarvest,
simulation, this.unit);
if (nearestTree != null) {
return reset(nearestTree);
}
}
return this.unit.pollNextOrderBehavior(simulation);
}
@Override
protected boolean checkTargetStillValid(CSimulation simulation) {
if(this.target instanceof CDestructable) {
if(!harvesting && simulation.isTreeOwned((CDestructable)this.target)) {
return false;
}
}
return this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
}
@Override
protected void resetBeforeMoving(CSimulation simulation) {
if(harvesting) {
onStopHarvesting(simulation);
harvesting = false;
}
}
@Override
public boolean isWithinRange(CSimulation simulation) {
return this.unit.canReach(this.target, 0);
}
@Override
public void endMove(CSimulation game, boolean interrupted) {
}
@Override
public void begin(CSimulation game) {
}
@Override
public void end(CSimulation game, boolean interrupted) {
if(harvesting) {
onStopHarvesting(game);
harvesting = false;
}
}
@Override
public int getHighlightOrderId() {
return OrderIds.wispharvest;
}
public static CDestructable findNearestTree(final CUnit worker, final CAbilityWispHarvest abilityHarvest,
final CSimulation simulation, final CWidget toObject) {
CDestructable nearestMine = null;
double nearestMineDistance = abilityHarvest.getCastRange()*abilityHarvest.getCastRange();
for (final CDestructable unit : simulation.getDestructables()) {
if (!unit.isDead()
&& !simulation.isTreeOwned(unit)
&& unit.canBeTargetedBy(simulation, worker, CAbilityWispHarvest.TREE_ALIVE_TYPE_ONLY)) {
final double distance = unit.distanceSquaredNoCollision(toObject);
if (distance < nearestMineDistance) {
nearestMineDistance = distance;
nearestMine = unit;
}
}
}
return nearestMine;
}
}

View File

@ -10,22 +10,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityGeneric;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionChannelTest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionCoupleInstant;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionHarvestLumber;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionHumanRepair;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionInvulnerable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemAttackBonus;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemDefenseBonus;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemHeal;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemLifeBonus;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemPermanentStatGain;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionItemStatBonus;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.*;
public class CAbilityData {
@ -44,6 +29,7 @@ public class CAbilityData {
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Agld"), new CAbilityTypeDefinitionGoldMine());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Artn"), new CAbilityTypeDefinitionReturnResources());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Ahar"), new CAbilityTypeDefinitionHarvest());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Awha"), new CAbilityTypeDefinitionWispHarvest());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Ahrl"), new CAbilityTypeDefinitionHarvestLumber());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("ANcl"), new CAbilityTypeDefinitionChannelTest());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("AInv"), new CAbilityTypeDefinitionInventory());

View File

@ -0,0 +1,5 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
public interface SimulationRenderComponent {
void remove();
}

View File

@ -67,10 +67,15 @@ public interface SimulationRenderController {
void spawnAbilitySoundEffect(CUnit caster, War3ID alias);
void loopAbilitySoundEffect(CUnit caster, War3ID alias);
void stopAbilitySoundEffect(CUnit caster, War3ID alias);
void unitPreferredSelectionReplacement(CUnit unit, CUnit newUnit);
void heroRevived(CUnit trainedUnit);
void heroDeathEvent(CUnit cUnit);
SimulationRenderComponent createSpellEffectOverDestructable(CUnit source, CDestructable target, War3ID alias, float artAttachmentHeight);
}

View File

@ -171,6 +171,11 @@ public class CommandCardIcon extends AbstractRenderableFrame implements Clickabl
}
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
@Override
public void mouseDown(final GameUI gameUI, final Viewport uiViewport) {
this.iconFrame.setWidth(this.defaultWidth * 0.95f);

View File

@ -1,9 +1,11 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
@ -25,15 +27,7 @@ import com.etheller.warsmash.networking.WarsmashClientSendingOrderListener;
import com.etheller.warsmash.networking.WarsmashClientWriter;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.datamodel.FramePoint;
import com.etheller.warsmash.parsers.fdf.frames.EditBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.GlueButtonFrame;
import com.etheller.warsmash.parsers.fdf.frames.GlueTextButtonFrame;
import com.etheller.warsmash.parsers.fdf.frames.ListBoxFrame;
import com.etheller.warsmash.parsers.fdf.frames.SetPoint;
import com.etheller.warsmash.parsers.fdf.frames.SimpleFrame;
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
import com.etheller.warsmash.parsers.fdf.frames.StringFrame;
import com.etheller.warsmash.parsers.fdf.frames.UIFrame;
import com.etheller.warsmash.parsers.fdf.frames.*;
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
import com.etheller.warsmash.parsers.w3x.War3Map;
import com.etheller.warsmash.parsers.w3x.w3i.War3MapW3i;
@ -57,6 +51,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.CampaignMenuData;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.CampaignMenuUI;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.menu.CampaignMission;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.sound.KeyedSounds;
import javafx.scene.control.ScrollBar;
public class MenuUI {
private static final Vector2 screenCoordsVector = new Vector2();
@ -475,6 +470,39 @@ public class MenuUI {
// Create skirmish UI
this.skirmish = this.rootFrame.createFrame("Skirmish", this.rootFrame, 0, 0);
this.skirmish.setVisible(false);
GlueTextButtonFrame playGameButton = (GlueTextButtonFrame)this.rootFrame.getFrameByName("PlayGameButton", 0);
SimpleFrame mapListContainer = (SimpleFrame)this.rootFrame.getFrameByName("MapListContainer", 0);
final ListBoxFrame mapListBox = (ListBoxFrame) this.rootFrame.createFrameByType("LISTBOX", "MapListBox",
mapListContainer, "WITHCHILDREN", 0);
mapListBox.setSetAllPoints(true);
mapListBox.setFrameFont(profileListText.getFrameFont());
Collection<String> listfile = dataSource.getListfile();
for(String file: listfile) {
if((file.toLowerCase().endsWith(".w3x") || file.toLowerCase().endsWith(".w3m")) && !file.contains("/") && !file.contains("\\")) {
mapListBox.addItem(file, this.rootFrame, this.uiViewport);
}
}
mapListContainer.add(mapListBox);
playGameButton.setOnClick(new Runnable() {
@Override
public void run() {
String selectedItem = mapListBox.getSelectedItem();
if(selectedItem!=null) {
MenuUI.this.campaignMenu.setVisible(false);
MenuUI.this.campaignBackButton.setVisible(false);
MenuUI.this.missionSelectFrame.setVisible(false);
MenuUI.this.campaignSelectFrame.setVisible(false);
MenuUI.this.campaignWarcraftIIILogo.setVisible(false);
MenuUI.this.campaignRootMenuUI.setVisible(false);
MenuUI.this.currentMissionSelectMenuUI.setVisible(false);
MenuUI.this.skirmish.setVisible(false);
MenuUI.this.glueSpriteLayerTopLeft.setSequence("SinglePlayerSkirmish Birth");
MenuUI.this.glueSpriteLayerTopRight.setSequence("SinglePlayerSkirmish Birth");
MenuUI.this.mapFilepathToStart = selectedItem;
}
}
});
this.skirmishCancelButton = (GlueTextButtonFrame) this.rootFrame.getFrameByName("CancelButton", 0);
this.skirmishCancelButton.setOnClick(new Runnable() {
@ -1015,7 +1043,11 @@ public class MenuUI {
}
public boolean touchDragged(final int screenX, final int screenY, final float worldScreenY, final int pointer) {
mouseMoved(screenX, screenY, worldScreenY);
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
if(this.mouseDownUIFrame != null) {
this.mouseDownUIFrame.mouseDragged(this.rootFrame, this.uiViewport, screenCoordsVector.x, screenCoordsVector.y);
}
return false;
}
@ -1030,9 +1062,7 @@ public class MenuUI {
}
if (mousedUIFrame instanceof ClickableFrame) {
this.mouseOverUIFrame = (ClickableFrame) mousedUIFrame;
if (this.mouseOverUIFrame != null) {
this.mouseOverUIFrame.mouseEnter(this.rootFrame, this.uiViewport);
}
this.mouseOverUIFrame.mouseEnter(this.rootFrame, this.uiViewport);
}
else {
this.mouseOverUIFrame = null;

View File

@ -87,6 +87,11 @@ public class MultiSelectionIcon extends AbstractRenderableFrame implements Click
this.clickListener.multiSelectIconClicked(this.queueIconIndexId);
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
@Override
public void setWidth(final float width) {
this.defaultWidth = width;

View File

@ -74,6 +74,11 @@ public class QueueIcon extends AbstractRenderableFrame implements ClickableActio
this.clickListener.queueIconClicked(this.queueIconIndexId);
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
@Override
public void setWidth(final float width) {
this.defaultWidth = width;

View File

@ -14,4 +14,6 @@ public interface ClickableFrame extends UIFrame {
void mouseExit(final GameUI gameUI, final Viewport uiViewport);
void onClick(int button);
void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y);
}

View File

@ -91,6 +91,11 @@ public class CampaignButtonUI extends AbstractUIFrame implements ClickableFrame
this.buttonArt.onClick(button);
}
@Override
public void mouseDragged(GameUI rootFrame, Viewport uiViewport, float x, float y) {
}
public void setHeaderText(final StringFrame headerText) {
this.headerText = headerText;
this.defaultHeaderColor = headerText.getColor();