diff options
author | Jérémy Zurcher <jeremy@asynk.ch> | 2018-10-03 16:29:04 +0200 |
---|---|---|
committer | Jérémy Zurcher <jeremy@asynk.ch> | 2018-10-03 16:29:04 +0200 |
commit | 2f1bec6890815033211fde71e645c5a57e502a20 (patch) | |
tree | a83756b4df61e729fdbdf495c19423dc7799e269 /core/src/ch/asynk/gdx/boardgame/ui | |
parent | 977ce8e5a8f967f2ad9acc634111231e3af9ef7a (diff) | |
download | gdx-boardgame-2f1bec6890815033211fde71e645c5a57e502a20.zip gdx-boardgame-2f1bec6890815033211fde71e645c5a57e502a20.tar.gz |
tabletop -> boardgame
Diffstat (limited to 'core/src/ch/asynk/gdx/boardgame/ui')
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Alignment.java | 168 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Assembly.java | 63 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Button.java | 67 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Element.java | 116 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Label.java | 61 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Menu.java | 126 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Patch.java | 23 | ||||
-rw-r--r-- | core/src/ch/asynk/gdx/boardgame/ui/Root.java | 28 |
8 files changed, 652 insertions, 0 deletions
diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Alignment.java b/core/src/ch/asynk/gdx/boardgame/ui/Alignment.java new file mode 100644 index 0000000..67da089 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Alignment.java @@ -0,0 +1,168 @@ +package ch.asynk.gdx.boardgame.ui; + +public enum Alignment +{ + ABSOLUTE, // Root + RELATIVE, // Default + TOP_LEFT, + TOP_RIGHT, + TOP_CENTER, + MIDDLE_LEFT, + MIDDLE_RIGHT, + MIDDLE_CENTER, + BOTTOM_LEFT, + BOTTOM_RIGHT, + BOTTOM_CENTER; + + public Alignment verticalMirror() + { + switch(this) { + case TOP_LEFT: + return TOP_RIGHT; + case MIDDLE_LEFT: + return MIDDLE_RIGHT; + case BOTTOM_LEFT: + return BOTTOM_RIGHT; + case TOP_RIGHT: + return TOP_LEFT; + case MIDDLE_RIGHT: + return MIDDLE_LEFT; + case BOTTOM_RIGHT: + return BOTTOM_LEFT; + } + return this; + } + + public Alignment horizontalMirror() + { + switch(this) { + case TOP_LEFT: + return BOTTOM_LEFT; + case TOP_CENTER: + return BOTTOM_CENTER; + case TOP_RIGHT: + return BOTTOM_RIGHT; + case BOTTOM_LEFT: + return TOP_LEFT; + case BOTTOM_CENTER: + return TOP_CENTER; + case BOTTOM_RIGHT: + return TOP_RIGHT; + } + return this; + } + + public boolean isTop() + { + switch(this) { + case TOP_LEFT: + case TOP_CENTER: + case TOP_RIGHT: + return true; + } + return false; + } + + public boolean isMiddle() + { + boolean r = false; + switch(this) { + case MIDDLE_LEFT: + case MIDDLE_CENTER: + case MIDDLE_RIGHT: + return true; + } + return false; + } + + public boolean isBottom() + { + boolean r = false; + switch(this) { + case BOTTOM_LEFT: + case BOTTOM_CENTER: + case BOTTOM_RIGHT: + return true; + } + return false; + } + + public boolean isLeft() + { + boolean r = false; + switch(this) { + case TOP_LEFT: + case MIDDLE_LEFT: + case BOTTOM_LEFT: + return true; + } + return false; + } + + public boolean isRight() + { + boolean r = false; + switch(this) { + case TOP_RIGHT: + case MIDDLE_RIGHT: + case BOTTOM_RIGHT: + return true; + } + return false; + } + + public boolean isCenter() + { + switch(this) { + case TOP_CENTER: + case MIDDLE_CENTER: + case BOTTOM_CENTER: + return true; + } + return false; + } + + public float getX(Element element, float width) + { + float x = element.getInnerX(); + switch(this) { + case TOP_LEFT: + case MIDDLE_LEFT: + case BOTTOM_LEFT: + break; + case TOP_CENTER: + case MIDDLE_CENTER: + case BOTTOM_CENTER: + x += ((element.getInnerWidth() - width) / 2); + break; + case TOP_RIGHT: + case MIDDLE_RIGHT: + case BOTTOM_RIGHT: + x += (element.getInnerWidth() - width); + break; + } + return x; + } + + public float getY(Element element, float height) + { + float y = element.getInnerY(); + switch(this) { + case TOP_LEFT: + case TOP_CENTER: + case TOP_RIGHT: + y += (element.getInnerHeight() - height); + break; + case MIDDLE_LEFT: + case MIDDLE_CENTER: + case MIDDLE_RIGHT: + y += ((element.getInnerHeight() - height) / 2); + break; + case BOTTOM_LEFT: + case BOTTOM_CENTER: + case BOTTOM_RIGHT: + break; + } + return y; + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Assembly.java b/core/src/ch/asynk/gdx/boardgame/ui/Assembly.java new file mode 100644 index 0000000..c603383 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Assembly.java @@ -0,0 +1,63 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +import ch.asynk.gdx.boardgame.util.IterableSet; + +public abstract class Assembly extends Element +{ + private IterableSet<Element> children; + private Element touched; + + public Assembly(int c) + { + this.children = new IterableSet<Element>(c); + } + + public void add(Element e) + { + if (children.add(e)) { + e.setParent(this); + } + } + + public void remove(Element e) + { + if (children.remove(e)) { + e.setParent(null); + } + } + + public Element touched() + { + return touched; + } + + @Override public boolean touch(float x, float y) + { + for (Element e : children) + if (e.touch(x, y)) { + touched = e; + return true; + } + touched = null; + return false; + } + + @Override public void taint() + { + children.forEach( c -> c.taint() ); + } + + @Override public void draw(Batch batch) + { + if (tainted) computeGeometry(); + children.forEach( c -> c.draw(batch) ); + } + + @Override public void drawDebug(ShapeRenderer debugShapes) + { + children.forEach( c -> c.drawDebug(debugShapes) ); + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Button.java b/core/src/ch/asynk/gdx/boardgame/ui/Button.java new file mode 100644 index 0000000..9bc1149 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Button.java @@ -0,0 +1,67 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; + +public class Button extends Patch +{ + private Label label; + private float spacing; // for label alignment; + + public Button(BitmapFont font, NinePatch patch) + { + this(font, patch, 0); + } + + public Button(BitmapFont font, NinePatch patch, float padding) + { + this(font, patch, padding, 0); + } + + public Button(BitmapFont font, NinePatch patch, float padding, float spacing) + { + super(patch); + this.padding = padding; + this.spacing = spacing; + label = new Label(font); + label.setParent(this); + label.setAlignment(Alignment.MIDDLE_CENTER); + } + + public void write(String text) + { + label.write(text); + this.tainted = true; // might impact Button's geometry + } + + public void setLabelAlignment(Alignment alignment) + { + label.setAlignment(alignment); + } + + @Override public void computeGeometry() + { + float dd = 2 * (padding + spacing); + label.computeGeometry(); // update dimensions + rect.width = label.getWidth() + dd; + rect.height = label.getHeight() + dd; + super.computeGeometry(); + label.computeGeometry(); // update position + } + + @Override public void draw(Batch batch) + { + if (!visible) return; + if (tainted) computeGeometry(); + super.draw(batch); + label.draw(batch); + } + + @Override public void drawDebug(ShapeRenderer debugShapes) + { + super.drawDebug(debugShapes); + label.drawDebug(debugShapes); + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Element.java b/core/src/ch/asynk/gdx/boardgame/ui/Element.java new file mode 100644 index 0000000..25f38eb --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Element.java @@ -0,0 +1,116 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Rectangle; + +import ch.asynk.gdx.boardgame.Drawable; +import ch.asynk.gdx.boardgame.Touchable; + +public abstract class Element implements Drawable, Touchable +{ + public boolean blocked; + public boolean visible; + protected float padding; + protected Element parent; + protected Alignment alignment; + protected Rectangle rect; // outer drawing coordinates + protected float x, y; // given position + protected boolean tainted; // geometry must be computed + + protected Element() + { + this.blocked = false; + this.visible = true; + this.padding = 0; + this.parent = null; + this.alignment = alignment.RELATIVE; + this.rect = new Rectangle(0, 0, 0, 0); + this.x = this.y = 0; + this.tainted = true; + } + + @Override public final float getX() { return rect.x; } + @Override public final float getY() { return rect.y; } + @Override public final float getWidth() { return rect.width; } + @Override public final float getHeight() { return rect.height; } + + @Override public final float getInnerX() { return rect.x + padding; } + @Override public final float getInnerY() { return rect.y + padding; } + @Override public final float getInnerWidth() { return rect.width - 2 * padding; } + @Override public final float getInnerHeight() { return rect.height - 2 * padding; } + + @Override public void drawDebug(ShapeRenderer debugShapes) + { + debugShapes.rect(getX(), getY(), getWidth(), getHeight()); + } + + @Override public boolean touch(float x, float y) + { + if (blocked || !visible) return false; + return rect.contains(x, y); + } + + public void taint() + { + this.tainted = true; + } + + @Override public void setPosition(float x, float y, float w, float h) + { + this.x = x; + this.y = y; + this.rect.width = w; + this.rect.height = h; + this.tainted = true; + // rect.(x,y) will be set in computeGeometry + } + + public void setParent(Element parent) + { + this.parent = parent; + this.tainted = true; + } + + public void setPadding(float padding) + { + this.padding = padding; + this.tainted = true; + } + + public void setAlignment(Alignment alignment) + { + this.alignment = alignment; + this.tainted = true; + } + + public final void translate(float dx, float dy) + { + setPosition(x + dx, y + dy); + } + + public final void setPosition(Rectangle r) + { + setPosition(r.x, r.x, r.width, r.height); + } + + public final void setPosition(float x, float y) + { + setPosition(x, y, rect.width, rect.height); + } + + protected void computeGeometry() + { + if (alignment == Alignment.ABSOLUTE || parent == null) { + rect.x = x; + rect.y = y; + } else if (alignment == Alignment.RELATIVE) { + rect.x = x + parent.getInnerX(); + rect.y = y + parent.getInnerX(); + } else { + rect.x = x + alignment.getX(parent, rect.width); + rect.y = y + alignment.getY(parent, rect.height); + } + this.tainted = false; + // System.err.println(String.format("%s : %s", this, rect)); + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Label.java b/core/src/ch/asynk/gdx/boardgame/ui/Label.java new file mode 100644 index 0000000..32ae814 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Label.java @@ -0,0 +1,61 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; + +public class Label extends Element +{ + private BitmapFont font; + private GlyphLayout layout; + private float fx; + private float fy; + private String text; + + public Label(BitmapFont font) + { + this(font, 0); + } + + public Label(BitmapFont font, float padding) + { + this(font, padding, Alignment.RELATIVE); + } + + public Label(BitmapFont font, float padding, Alignment alignment) + { + super(); + this.font = font; + this.padding = padding; + this.alignment = alignment; + this.layout = new GlyphLayout(); + } + + public void write(String text) + { + write(text, getX(), getY()); + } + + public void write(String text, float x, float y) + { + this.text = text; + this.layout.setText(font, (text == null) ? "" : text); + this.tainted = true; + } + + @Override protected void computeGeometry() + { + this.rect.width = (layout.width + (2 * padding)); + this.rect.height = (layout.height + (2 * padding)); + super.computeGeometry(); + fx = getInnerX(); + fy = getInnerY() + layout.height; + } + + @Override public void draw(Batch batch) + { + if (!visible) return; + if (tainted) computeGeometry(); + font.draw(batch, layout, fx, fy); + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Menu.java b/core/src/ch/asynk/gdx/boardgame/ui/Menu.java new file mode 100644 index 0000000..aa62483 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Menu.java @@ -0,0 +1,126 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; + +public class Menu extends Patch +{ + private Label title; + private Label[] entries; + private Integer touchedItem; + + private int entriesOffset; // horizontal offset + private int titleSpacing; // between title and entries + private int entriesSpacing; // between entries + + public Menu(BitmapFont font, NinePatch patch, String title, String[] entries) + { + super(patch); + this.touchedItem = null; + setTitle(font, title); + setEntries(font, entries); + } + + public void setTitle(BitmapFont font, String title) + { + this.title = new Label(font); + this.title.write(title); + this.tainted = true; + } + + public void setEntries(BitmapFont font, String[] entries) + { + this.entries = new Label[entries.length]; + for (int i = 0; i < entries.length; i++) { + Label l = new Label(font); + l.write(entries[i]); + this.entries[i] = l; + } + this.tainted = true; + } + + public void setLabelsOffset(int entriesOffset) + { + this.entriesOffset = entriesOffset; + this.tainted = true; + } + + public void setPaddings(int titlePadding, int labelPadding) + { + this.title.setPadding(titlePadding); + for (Label label : entries) { + label.setPadding(labelPadding); + } + this.tainted = true; + } + + public void setSpacings(int titleSpacing, int entriesSpacing) + { + this.titleSpacing = titleSpacing; + this.entriesSpacing = entriesSpacing; + this.tainted = true; + } + + @Override public void computeGeometry() + { + title.computeGeometry(); + float h = title.getHeight(); + float w = title.getWidth(); + for (Label label : entries) { + label.computeGeometry(); + h += label.getHeight(); + float t = label.getWidth() + entriesOffset; + if (t > w) + w = t; + } + h += (titleSpacing + (entriesSpacing * (entries.length - 1)) + (2 * padding)); + w += (2 * padding); + + rect.width = w; + rect.height = h; + super.computeGeometry(); + + float x = getInnerX(); + float y = getInnerY(); + + // setPosition() will trigger computeGeometry() from within draw() + for (int i = entries.length - 1; i >= 0; i--) { + entries[i].setPosition(x + entriesOffset, y); + y += entries[i].getHeight() + entriesSpacing; + } + y -= entriesSpacing; + y += titleSpacing; + title.setPosition(x, y); + } + + public Integer touched() + { + return touchedItem; + } + + @Override public boolean touch(float x, float y) + { + touchedItem = null; + if (super.touch(x, y)) { + for (int i = 0; i < entries.length; i++) { + if (entries[i].touch(x, y)) { + touchedItem = i; + return true; + } + } + } + return false; + } + + @Override public void draw(Batch batch) + { + if (!visible) return; + if (tainted) computeGeometry(); + super.draw(batch); + title.draw(batch); + for (Label label : entries) { + label.draw(batch); + } + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Patch.java b/core/src/ch/asynk/gdx/boardgame/ui/Patch.java new file mode 100644 index 0000000..df2cc06 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Patch.java @@ -0,0 +1,23 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.NinePatch; + +public class Patch extends Element +{ + private NinePatch patch; + + public Patch(NinePatch patch) + { + super(); + this.patch = patch; + setPosition(0, 0, patch.getTotalWidth(), patch.getTotalHeight()); + } + + @Override public void draw(Batch batch) + { + if (!visible) return; + if (tainted) computeGeometry(); + patch.draw(batch, getX(), getY(), getWidth(), getHeight()); + } +} diff --git a/core/src/ch/asynk/gdx/boardgame/ui/Root.java b/core/src/ch/asynk/gdx/boardgame/ui/Root.java new file mode 100644 index 0000000..2353c41 --- /dev/null +++ b/core/src/ch/asynk/gdx/boardgame/ui/Root.java @@ -0,0 +1,28 @@ +package ch.asynk.gdx.boardgame.ui; + +import com.badlogic.gdx.math.Rectangle; + +public class Root extends Assembly +{ + public Root(int c) + { + super(c); + this.alignment = Alignment.ABSOLUTE; + } + + public void resize(Rectangle r) + { + resize(r.x, r.y, r.width, r.height); + } + + public void resize(float width, float height) + { + resize(getX(), getY(), width, height); + } + + public void resize(float x, float y, float width, float height) + { + setPosition(x, y, width, height); + taint(); + } +} |