diff --git a/gradle.properties b/gradle.properties index 6b3bd65d..f759fe97 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=com.kamesuta.mc modid=signpic modname=SignPicture version_major=2 -version_minor=1 -version_micro=5 +version_minor=2 +version_micro=0.beta version_minecraft=1.7.10 version_forge=10.13.4.1558-1.7.10 \ No newline at end of file diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/WCommon.java b/src/main/java/com/kamesuta/mc/bnnwidget/WCommon.java index a5a0dd63..62193875 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/WCommon.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/WCommon.java @@ -4,7 +4,9 @@ import com.kamesuta.mc.bnnwidget.position.Point; public interface WCommon { - void init(WEvent ev, Area pgp); + void onAdded(); + + void onInit(WEvent ev, Area pgp, Point mouse); void draw(WEvent ev, Area pgp, Point mouse, float frame); @@ -22,7 +24,7 @@ public interface WCommon { void mouseReleased(WEvent ev, Area pgp, Point mouse, int button); - void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse); + boolean onCloseRequest(); boolean onClosing(WEvent ev, Area pgp, Point mouse); diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/WComponent.java b/src/main/java/com/kamesuta/mc/bnnwidget/WComponent.java index 99ccd37c..e0240538 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/WComponent.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/WComponent.java @@ -5,7 +5,10 @@ public class WComponent extends WGui implements WCommon { @Override - public void init(final WEvent ev, final Area pgp) {} + public void onAdded() {} + + @Override + public void onInit(final WEvent ev, final Area pgp, final Point p) {} @Override public void draw(final WEvent ev, final Area pgp, final Point p, final float frame) {} @@ -32,7 +35,9 @@ public void mouseDragged(final WEvent ev, final Area pgp, final Point p, final i public void mouseReleased(final WEvent ev, final Area pgp, final Point mouse, final int button) {} @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse) {} + public boolean onCloseRequest() { + return true; + } @Override public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/WFrame.java b/src/main/java/com/kamesuta/mc/bnnwidget/WFrame.java index 60859618..7169ed55 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/WFrame.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/WFrame.java @@ -53,9 +53,8 @@ protected void sInitGui() { } protected void initWidget() { - final Area gp = getAbsolute(); for (final WCommon widget : this.widgets) - widget.init(this.event, gp); + widget.onAdded(); } protected void init() { @@ -198,10 +197,8 @@ protected void close() { } public void requestClose() { - final Area gp = getAbsolute(); - final Point p = getMouseAbsolute(); for (final WCommon widget : this.widgets) - widget.onCloseRequest(this.event, gp, p); + widget.onCloseRequest(); this.closeRequest = true; } diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/WGui.java b/src/main/java/com/kamesuta/mc/bnnwidget/WGui.java index a7932d06..90b81999 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/WGui.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/WGui.java @@ -137,7 +137,7 @@ public static void drawTexturedModalRect(final float x, final float y, final flo t.draw(); } - public static void drawTexturedModelRectFromIcon(final float x, final float y, final IIcon image, final float width, final float height) + public static void drawTexturedModalRectFromIcon(final float x, final float y, final IIcon image, final float width, final float height) { t.startDrawingQuads(); t.addVertexWithUV(x + 0, y + height, 0, image.getMinU(), image.getMaxV()); @@ -147,7 +147,7 @@ public static void drawTexturedModelRectFromIcon(final float x, final float y, f t.draw(); } - public static void drawTexturedModelRect(final float x, final float y, final float u, final float v, final float width, final float height, final float divu, final float divv) + public static void drawTexturedModalRect(final float x, final float y, final float u, final float v, final float width, final float height, final float divu, final float divv) { final float mulu = 1.0F / divu; final float mulv = 1.0F / divv; @@ -159,7 +159,7 @@ public static void drawTexturedModelRect(final float x, final float y, final flo t.draw(); } - public static void drawTexturedModelRect(final float x, final float y, final float u, final float v, final float uwidth, final float vheight, final float width, final float height, final float divu, final float divv) + public static void drawTexturedModalRect(final float x, final float y, final float u, final float v, final float uwidth, final float vheight, final float width, final float height, final float divu, final float divv) { final float mulu = 1.0F / divu; final float mulv = 1.0F / divv; @@ -244,6 +244,11 @@ public static void drawTexturedModalRect(final Area a, final float u, final floa drawTexturedModalRect(a.x1(), a.y1(), u, v, a.w(), a.h()); } + public static void drawTexturedModalRect(final Area a) + { + drawTexturedModalRect(a.x1(), a.y1(), 0, 0, 1, 1, a.w(), a.h(), 1, 1); + } + /** * Draws a textured rectangle at the stored z-value. Args: x, y, u, v, width, height */ @@ -259,9 +264,9 @@ public static void drawTexturedModalRect(final Area a, final Area texture) t.draw(); } - public static void drawTexturedModelRectFromIcon(final Area a, final IIcon icon) + public static void drawTexturedModalRectFromIcon(final Area a, final IIcon icon) { - drawTexturedModelRectFromIcon(a.x1(), a.y1(), icon, a.w(), a.h()); + drawTexturedModalRectFromIcon(a.x1(), a.y1(), icon, a.w(), a.h()); } public static void translate(final Area p) { diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/WPanel.java b/src/main/java/com/kamesuta/mc/bnnwidget/WPanel.java index baf11cac..745bb10e 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/WPanel.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/WPanel.java @@ -1,6 +1,9 @@ package com.kamesuta.mc.bnnwidget; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; +import java.util.Iterator; import java.util.List; import com.kamesuta.mc.bnnwidget.position.Area; @@ -9,6 +12,7 @@ public class WPanel extends WBase implements WContainer { protected final ArrayList widgets = new ArrayList(); + protected final Deque removelist = new ArrayDeque(); public WPanel(final R position) { super(position); @@ -21,23 +25,35 @@ public List getContainer() { @Override public boolean add(final WCommon widget) { - return this.widgets.add(widget); + final boolean b = this.widgets.add(widget); + widget.onAdded(); + return b; } @Override public boolean remove(final WCommon widget) { - return this.widgets.remove(widget); + if (widget.onCloseRequest()) { + this.widgets.remove(widget); + return true; + } else { + this.removelist.offer(widget); + return false; + } } @Override - public void init(final WEvent ev, final Area pgp) { - initWidget(ev, pgp); - final Area gp = getGuiPosition(pgp); - for (final WCommon widget : this.widgets) - widget.init(ev, gp); + public void onAdded() { + initWidget(); } - protected void initWidget(final WEvent ev, final Area pgp) { + protected void initWidget() { + } + + @Override + public void onInit(final WEvent ev, final Area pgp, final Point p) { + final Area gp = getGuiPosition(pgp); + for (final WCommon widget : this.widgets) + widget.onInit(ev, gp, p); } @Override @@ -52,6 +68,13 @@ public void update(final WEvent ev, final Area pgp, final Point p) { final Area gp = getGuiPosition(pgp); for (final WCommon widget : this.widgets) widget.update(ev, gp, p); + for (final Iterator itr = this.removelist.iterator(); itr.hasNext();) { + final WCommon widget = itr.next(); + if (widget.onClosing(ev, gp, p)) { + this.widgets.remove(widget); + itr.remove(); + } + } } @Override @@ -97,18 +120,32 @@ public void mouseReleased(final WEvent ev, final Area pgp, final Point p, final } @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point p) { - final Area gp = getGuiPosition(pgp); - for (final WCommon widget : this.widgets) - widget.onCloseRequest(ev, gp, p); + public boolean onCloseRequest() { + boolean closable = true; + for (final Iterator itr = this.widgets.iterator(); itr.hasNext();) { + final WCommon widget = itr.next(); + if (widget.onCloseRequest()) + itr.remove(); + else { + this.removelist.offer(widget); + closable = false; + } + } + return closable; } @Override public boolean onClosing(final WEvent ev, final Area pgp, final Point p) { final Area gp = getGuiPosition(pgp); boolean closable = true; - for (final WCommon widget : this.widgets) - closable = closable && widget.onClosing(ev, gp, p); + for (final Iterator itr = this.removelist.iterator(); itr.hasNext();) { + final WCommon widget = itr.next(); + if (widget.onClosing(ev, gp, p)) { + this.widgets.remove(widget); + itr.remove(); + } else + closable = false; + } return closable; } diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/component/FunnyButton.java b/src/main/java/com/kamesuta/mc/bnnwidget/component/FunnyButton.java new file mode 100644 index 00000000..0a7b9182 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/bnnwidget/component/FunnyButton.java @@ -0,0 +1,49 @@ +package com.kamesuta.mc.bnnwidget.component; + +import static org.lwjgl.opengl.GL11.*; + +import com.kamesuta.mc.bnnwidget.WEvent; +import com.kamesuta.mc.bnnwidget.motion.Easings; +import com.kamesuta.mc.bnnwidget.motion.MCoord; +import com.kamesuta.mc.bnnwidget.position.Area; +import com.kamesuta.mc.bnnwidget.position.Point; +import com.kamesuta.mc.bnnwidget.position.R; + +public class FunnyButton extends MButton { + public FunnyButton(final R position, final String text) { + super(position, text); + } + + boolean hover; + MCoord m = new MCoord(0); + MCoord s = new MCoord(1); + + protected void state(final boolean b) { + if (b) { + if (!this.hover) { + this.hover = true; + this.m.stop().add(Easings.easeOutElastic.move(.5f, 6f)).start(); + this.s.stop().add(Easings.easeOutElastic.move(.5f, 1.1f)).start(); + } + } else { + if (this.hover) { + this.hover = false; + this.m.stop().add(Easings.easeOutElastic.move(.5f, 0f)).start(); + this.s.stop().add(Easings.easeOutElastic.move(.5f, 1f)).start(); + } + } + } + + @Override + public void draw(final WEvent ev, final Area pgp, final Point p, final float frame) { + final Area a = getGuiPosition(pgp); + glPushMatrix(); + glTranslatef(a.x1()+a.w()/2, a.y1()+a.h()/2, 0); + final float c = this.s.get(); + glScalef(c, c, 1f); + glRotatef(this.m.get(), 0, 0, 1); + glTranslatef(-a.x1()-a.w()/2, -a.y1()-a.h()/2, 0); + super.draw(ev, pgp, p, frame); + glPopMatrix(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/component/MChatTextField.java b/src/main/java/com/kamesuta/mc/bnnwidget/component/MChatTextField.java index 72500610..f6a5041c 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/component/MChatTextField.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/component/MChatTextField.java @@ -11,25 +11,42 @@ import com.kamesuta.mc.bnnwidget.position.R; import net.minecraft.client.gui.GuiTextField; +import net.minecraft.util.ChatAllowedCharacters; public class MChatTextField extends WBase { protected final GuiTextField t; - public String watermark; + protected String watermark; + protected String allowedCharacters; public MChatTextField(final R position) { super(position); this.t = new GuiTextField(font(), 0, 0, 0, 0); } - public void setWatermark(final String watermark) { + public boolean canAddChar(final char c) { + if (StringUtils.isEmpty(this.allowedCharacters)) + return true; + else if (!ChatAllowedCharacters.isAllowedCharacter(c)) + return true; + else + return this.allowedCharacters.indexOf(c) >= 0; + } + + public MChatTextField setWatermark(final String watermark) { this.watermark = watermark; + return this; } public String getWatermark() { return this.watermark; } + public MChatTextField setAllowedCharacters(final String s) { + this.allowedCharacters = s; + return this; + } + @Override public void draw(final WEvent ev, final Area pgp, final Point p, final float frame) { final Area a = getGuiPosition(pgp); @@ -59,9 +76,8 @@ public void draw(final WEvent ev, final Area pgp, final Point p, final float fra } @Override - public void init(final WEvent ev, final Area pgp) { - final Area a = getGuiPosition(pgp); - updateArea(a); + public void onAdded() { + updateArea(new Area(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE)); } @Override @@ -69,6 +85,8 @@ public void mouseClicked(final WEvent ev, final Area pgp, final Point p, final i final Area a = getGuiPosition(pgp); updateArea(a); final boolean b = isFocused(); + if (button == 1 && a.pointInside(p)) + setText(""); this.t.mouseClicked((int) p.x(), (int) p.y(), button); if (b!=isFocused()) onFocusChanged(); } @@ -80,12 +98,14 @@ public void update(final WEvent ev, final Area pgp, final Point p) { @Override public void keyTyped(final WEvent ev, final Area pgp, final Point p, final char c, final int keycode) { - this.t.textboxKeyTyped(c, keycode); + if (canAddChar(c)) + this.t.textboxKeyTyped(c, keycode); } @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse) { + public boolean onCloseRequest() { setFocused(false); + return true; } protected void updateArea(final Area a) { diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/component/MNumber.java b/src/main/java/com/kamesuta/mc/bnnwidget/component/MNumber.java index 37ea215b..63a0f15d 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/component/MNumber.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/component/MNumber.java @@ -9,10 +9,13 @@ import com.kamesuta.mc.bnnwidget.position.Point; import com.kamesuta.mc.bnnwidget.position.R; import com.kamesuta.mc.bnnwidget.position.RArea; +import com.kamesuta.mc.signpic.image.meta.ImageMeta.MetaParser; + +import net.minecraft.client.gui.GuiScreen; public class MNumber extends WPanel { public MButton neg; - public MTextField field; + public MChatTextField field; public MButton pos; public MNumber(final R position, final float buttonwidth) { @@ -20,29 +23,54 @@ public MNumber(final R position, final float buttonwidth) { this.neg = new MButton(new RArea(Coord.left(0), Coord.width(buttonwidth), Coord.top(0), Coord.bottom(0)), "-") { @Override protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, final int button) { - return MNumber.this.field.setText(Float.toString(NumberUtils.toFloat(MNumber.this.field.getText(), 0)-1f)); + float f; + if (GuiScreen.isShiftKeyDown()) + f = .1f; + else if (GuiScreen.isCtrlKeyDown()) + f = .01f; + else + f = 1f; + MNumber.this.field.setText(MetaParser.format(NumberUtils.toFloat(MNumber.this.field.getText(), 0)-f)); + return true; } }; add(this.neg); - this.field = new MTextField(new RArea(Coord.left(buttonwidth), Coord.right(buttonwidth), Coord.top(0), Coord.bottom(0)), "?") { + this.field = new MChatTextField(new RArea(Coord.left(buttonwidth), Coord.right(buttonwidth), Coord.top(0), Coord.bottom(0))) { @Override protected void onTextChanged(final String oldText) { onNumberChanged(oldText, getText()); } - }; - this.field.setAllowedCharacters("+-.eE0123456789"); + }.setAllowedCharacters("+-.eE0123456789").setWatermark("?"); add(this.field); this.pos = new MButton(new RArea(Coord.right(0), Coord.width(buttonwidth), Coord.top(0), Coord.bottom(0)), "+") { @Override protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, final int button) { - return MNumber.this.field.setText(Float.toString(NumberUtils.toFloat(MNumber.this.field.getText(), 0)+1f)); + float f; + if (GuiScreen.isShiftKeyDown()) + f = .1f; + else if (GuiScreen.isCtrlKeyDown()) + f = .01f; + else + f = 1f; + MNumber.this.field.setText(MetaParser.format(NumberUtils.toFloat(MNumber.this.field.getText(), 0)+f)); + return true; } }; add(this.pos); } public MNumber setNumber(final float f) { - this.field.setText(Float.isNaN(f) ? "" : Float.toString(f)); + this.field.setText(Float.isNaN(f) ? "" : MetaParser.format(f)); + return this; + } + + public MNumber setPosLabel(final String s) { + this.pos.setText(s); + return this; + } + + public MNumber setNegLabel(final String s) { + this.neg.setText(s); return this; } diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/component/MTextField.java b/src/main/java/com/kamesuta/mc/bnnwidget/component/MTextField.java index 14edfe0a..ee284c65 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/component/MTextField.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/component/MTextField.java @@ -18,6 +18,7 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ChatAllowedCharacters; +@Deprecated public class MTextField extends WBase { protected String text = ""; public String watermark; diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/motion/EasingMotion.java b/src/main/java/com/kamesuta/mc/bnnwidget/motion/Easings.java similarity index 99% rename from src/main/java/com/kamesuta/mc/bnnwidget/motion/EasingMotion.java rename to src/main/java/com/kamesuta/mc/bnnwidget/motion/Easings.java index 3222e0ff..c9fcb224 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/motion/EasingMotion.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/motion/Easings.java @@ -4,7 +4,7 @@ * Easing functions. * @author Kamesuta */ -public enum EasingMotion implements Easing { +public enum Easings implements Easing { easeLinear { @Override public double easing(final double t, final double b, final double c, final double d) { diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/motion/MCoord.java b/src/main/java/com/kamesuta/mc/bnnwidget/motion/MCoord.java new file mode 100644 index 00000000..310408eb --- /dev/null +++ b/src/main/java/com/kamesuta/mc/bnnwidget/motion/MCoord.java @@ -0,0 +1,178 @@ +package com.kamesuta.mc.bnnwidget.motion; + +import java.util.ArrayDeque; +import java.util.Deque; + +import com.kamesuta.mc.bnnwidget.position.Coord; + +public class MCoord extends Coord { + protected boolean paused = true; + protected final Deque queue; + protected IMotion current; + protected float coord; + + public MCoord(final float coord, final CoordSide side, final CoordType type) { + super(coord, side, type); + this.queue = new ArrayDeque(); + this.coord = coord; + } + + public MCoord(final float coord) { + this(coord, CoordSide.Top, CoordType.Absolute); + } + + public MCoord add(final IMotion animation) { + this.queue.offer(animation); + return this; + } + + protected void setCurrent(final IMotion current) { + if (this.current != null) + this.current.onFinished(); + this.current = current; + } + + public MCoord stop() { + this.coord = get(); + this.queue.clear(); + setCurrent(null); + return this; + } + + public MCoord stopLast() { + this.coord = getLast(); + this.queue.clear(); + setCurrent(null); + return stop(); + } + + public MCoord pause() { + this.paused = true; + if (this.current != null) + this.current.pause(); + return this; + } + + public MCoord start() { + this.paused = false; + if (this.current != null) + this.current.resume(); + return this; + } + + public MCoord next() { + setCurrent(this.queue.poll()); + start(); + return this; + } + + public MCoord stopNext() { + if (this.current != null) + this.coord = this.current.getEnd(this.coord); + setCurrent(this.queue.poll()); + start(); + return this; + } + + public IMotion getAnimation() { + if ((this.current == null || this.current.isFinished()) && !this.paused) + stopNext(); + return this.current; + } + + public IMotion getAnimationLast() { + return this.queue.peekLast(); + } + + @Override + public float get() { + final IMotion a = getAnimation(); + if (a != null) + return (float) a.get(this.coord); + else + return this.coord; + } + + public float getLast() { + final IMotion a = getAnimationLast(); + if (a != null) + return a.getEnd(this.coord); + else + return this.coord; + } + + public MCoord addAfter(final MCoord q) { + final IMotion a = getAnimationLast(); + if (a != null) + a.after(new Runnable() { + @Override + public void run() { + q.start(); + } + }); + return this; + } + + public MCoord addAfter(final Runnable r) { + final IMotion a = getAnimationLast(); + if (a != null) + a.after(r); + return this; + } + + public boolean isFinished() { + final IMotion a = getAnimationLast(); + if ((this.current!=null && !this.current.isFinished()) || (a!=null && !a.isFinished())) + return false; + else + return true; + } + + public static MCoord top(final float n) { + return new MCoord(n, CoordSide.Top, CoordType.Absolute); + } + + public static MCoord ptop(final float n) { + return new MCoord(n, CoordSide.Top, CoordType.Percent); + } + + public static MCoord left(final float n) { + return new MCoord(n, CoordSide.Left, CoordType.Absolute); + } + + public static MCoord pleft(final float n) { + return new MCoord(n, CoordSide.Left, CoordType.Percent); + } + + public static MCoord bottom(final float n) { + return new MCoord(n, CoordSide.Bottom, CoordType.Absolute); + } + + public static MCoord pbottom(final float n) { + return new MCoord(n, CoordSide.Bottom, CoordType.Percent); + } + + public static MCoord right(final float n) { + return new MCoord(n, CoordSide.Right, CoordType.Absolute); + } + + public static MCoord pright(final float n) { + return new MCoord(n, CoordSide.Right, CoordType.Percent); + } + + public static MCoord width(final float n) { + return new MCoord(n, CoordSide.Width, CoordType.Absolute); + } + + public static MCoord pwidth(final float n) { + return new MCoord(n, CoordSide.Width, CoordType.Percent); + } + + public static MCoord height(final float n) { + return new MCoord(n, CoordSide.Height, CoordType.Absolute); + } + + public static MCoord pheight(final float n) { + return new MCoord(n, CoordSide.Height, CoordType.Percent); + } +} diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/motion/MotionQueue.java b/src/main/java/com/kamesuta/mc/bnnwidget/motion/MotionQueue.java deleted file mode 100644 index 1f31becc..00000000 --- a/src/main/java/com/kamesuta/mc/bnnwidget/motion/MotionQueue.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.kamesuta.mc.bnnwidget.motion; - -import java.util.ArrayDeque; -import java.util.Deque; - -public class MotionQueue { - protected boolean paused = true; - protected final Deque queue; - protected IMotion current; - protected float coord; - - public MotionQueue(final float coord) { - this.queue = new ArrayDeque(); - this.coord = coord; - } - - public MotionQueue add(final IMotion animation) { - this.queue.offer(animation); - return this; - } - - protected void setCurrent(final IMotion current) { - if (this.current != null) - this.current.onFinished(); - this.current = current; - } - - public MotionQueue stop() { - this.coord = get(); - this.queue.clear(); - setCurrent(null); - return this; - } - - public MotionQueue stopLast() { - this.coord = getLast(); - this.queue.clear(); - setCurrent(null); - return stop(); - } - - public MotionQueue pause() { - this.paused = true; - if (this.current != null) - this.current.pause(); - return this; - } - - public MotionQueue start() { - this.paused = false; - if (this.current != null) - this.current.resume(); - return this; - } - - public MotionQueue next() { - setCurrent(this.queue.poll()); - start(); - return this; - } - - public MotionQueue stopNext() { - if (this.current != null) - this.coord = this.current.getEnd(this.coord); - setCurrent(this.queue.poll()); - start(); - return this; - } - - public IMotion getAnimation() { - if ((this.current == null || this.current.isFinished()) && !this.paused) - stopNext(); - return this.current; - } - - public IMotion getAnimationLast() { - return this.queue.peekLast(); - } - - public float get() { - final IMotion a = getAnimation(); - if (a != null) - return (float) a.get(this.coord); - else - return this.coord; - } - - public float getLast() { - final IMotion a = getAnimationLast(); - if (a != null) - return a.getEnd(this.coord); - else - return this.coord; - } - - public MotionQueue addAfter(final MotionQueue q) { - final IMotion a = getAnimationLast(); - if (a != null) - a.after(new Runnable() { - @Override - public void run() { - q.start(); - } - }); - return this; - } - - public MotionQueue addAfter(final Runnable r) { - final IMotion a = getAnimationLast(); - if (a != null) - a.after(r); - return this; - } - - public boolean isFinished() { - final IMotion a = getAnimationLast(); - if (a != null) - return a.isFinished(); - else - return true; - } -} diff --git a/src/main/java/com/kamesuta/mc/bnnwidget/position/Coord.java b/src/main/java/com/kamesuta/mc/bnnwidget/position/Coord.java index 6ffad1a3..ae10d2b9 100644 --- a/src/main/java/com/kamesuta/mc/bnnwidget/position/Coord.java +++ b/src/main/java/com/kamesuta/mc/bnnwidget/position/Coord.java @@ -1,42 +1,24 @@ package com.kamesuta.mc.bnnwidget.position; -import com.kamesuta.mc.bnnwidget.motion.IMotion; -import com.kamesuta.mc.bnnwidget.motion.MotionQueue; - public class Coord { - public final MotionQueue motion; + private final float coord; public CoordSide side; public CoordType type; public Coord(final float coord, final CoordSide side, final CoordType type) { - this.motion = new MotionQueue(coord); + this.coord = coord; this.side = side; this.type = type; } public float get() { - return this.motion.get(); + return this.coord; } public float getAbsCoord(final float abslength) { return this.type.calc(abslength, get()); } - public Coord add(final IMotion motion) { - this.motion.add(motion); - return this; - } - - public Coord addAfter(final MotionQueue q) { - this.motion.addAfter(q); - return this; - } - - public Coord start() { - this.motion.start(); - return this; - } - @Override public String toString() { return String.format("Coord [coord=%s, side=%s, type=%s]", get(), this.side, this.type); diff --git a/src/main/java/com/kamesuta/mc/signpic/Client.java b/src/main/java/com/kamesuta/mc/signpic/Client.java index 92b0750a..c3404f1a 100644 --- a/src/main/java/com/kamesuta/mc/signpic/Client.java +++ b/src/main/java/com/kamesuta/mc/signpic/Client.java @@ -2,9 +2,9 @@ import java.io.File; +import com.kamesuta.mc.signpic.entry.content.ContentLocation; import com.kamesuta.mc.signpic.gui.GuiSignPicEditor; import com.kamesuta.mc.signpic.handler.CoreHandler; -import com.kamesuta.mc.signpic.image.ImageManager; import com.kamesuta.mc.signpic.render.CustomTileEntitySignRenderer; import cpw.mods.fml.client.FMLClientHandler; @@ -18,9 +18,9 @@ public class Client { public final static Minecraft mc = FMLClientHandler.instance().getClient(); - public static ImageManager manager; public static CustomTileEntitySignRenderer renderer; public static CoreHandler handler; + public static ContentLocation location; public static File mcDir; public static File signpicDir; diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/Entry.java b/src/main/java/com/kamesuta/mc/signpic/entry/Entry.java new file mode 100644 index 00000000..11dffd93 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/Entry.java @@ -0,0 +1,25 @@ +package com.kamesuta.mc.signpic.entry; + +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentId; +import com.kamesuta.mc.signpic.image.meta.ImageMeta; + +public class Entry { + public final EntryId id; + public final ContentId contentId; + public final ImageMeta meta; + + protected Entry(final EntryId id) { + this.id = id; + this.contentId = id.getContentId(); + this.meta = id.getMeta(); + } + + public Content content() { + return this.contentId.content(); + } + + public boolean isValid() { + return this.contentId!=null && this.meta!=null; + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/EntryId.java b/src/main/java/com/kamesuta/mc/signpic/entry/EntryId.java new file mode 100644 index 00000000..198f9a7f --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/EntryId.java @@ -0,0 +1,128 @@ +package com.kamesuta.mc.signpic.entry; + +import org.apache.commons.lang3.StringUtils; + +import com.kamesuta.mc.signpic.entry.content.ContentId; +import com.kamesuta.mc.signpic.image.meta.ImageMeta; + +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +public class EntryId { + private final String id; + + public EntryId(final String id) { + this.id = id; + } + + public String id() { + return this.id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof EntryId)) + return false; + final EntryId other = (EntryId) obj; + if (this.id == null) { + if (other.id != null) + return false; + } else if (!this.id.equals(other.id)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("EntryId [id=%s]", this.id); + } + + public static EntryId from(final String string) { + return new EntryId(string); + } + + public static EntryId fromStrings(final String[] strings) { + return new EntryId(StringUtils.join(strings)); + } + + public static EntryId fromTile(final TileEntitySign tile) { + return fromStrings(tile.signText); + } + + public static EntryId fromChats(final IChatComponent[] chats) { + final StringBuilder stb = new StringBuilder(); + for (final IChatComponent chat : chats) { + if (chat!=null) + stb.append(chat.getFormattedText());new ChatComponentText("").getUnformattedText(); + } + return new EntryId(stb.toString()); + } + + public boolean hasContentId() { + return !(StringUtils.isEmpty(this.id) || StringUtils.containsOnly(this.id, "!") || StringUtils.containsOnly(this.id, "$")); + } + + public boolean hasMeta() { + return StringUtils.endsWith(this.id, "]") && StringUtils.contains(this.id, "["); + } + + public boolean isValid() { + return hasContentId() && hasMeta(); + } + + public ContentId getContentId() { + if (hasContentId()) { + String id; + if (StringUtils.contains(this.id, "[")) + id = StringUtils.substring(this.id, 0, StringUtils.lastIndexOf(this.id, "[")); + else + id = this.id; + return new ContentId(id); + } + return null; + } + + public ImageMeta getMeta() { + if (hasMeta()) + return new ImageMeta().parse(StringUtils.substring(this.id, StringUtils.lastIndexOf(this.id, "[")+1, StringUtils.length(this.id)-1)); + else + return null; + } + + public void toStrings(final String[] sign) { + for (int i=0; i<4; i++) { + if (16*i <= StringUtils.length(this.id)) + sign[i] = StringUtils.substring(this.id, 15*i, Math.min(15*(i+1), this.id.length())); + else + sign[i] = ""; + } + } + + public void toEntity(final TileEntitySign tile) { + toStrings(tile.signText); + } + + public Entry entry() { + return EntryManager.instance.get(this); + } + + @Deprecated + public String[] toStrings() { + final String[] strings = new String[4]; + toStrings(strings); + return strings; + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/EntryIdBuilder.java b/src/main/java/com/kamesuta/mc/signpic/entry/EntryIdBuilder.java new file mode 100644 index 00000000..b989c96d --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/EntryIdBuilder.java @@ -0,0 +1,46 @@ +package com.kamesuta.mc.signpic.entry; + +import com.kamesuta.mc.signpic.entry.content.ContentId; +import com.kamesuta.mc.signpic.image.meta.ImageMeta; + +public class EntryIdBuilder { + private ImageMeta meta; + private String uri; + + public EntryIdBuilder(final EntryId source) { + if (source != null) { + this.meta = source.getMeta(); + if (source.hasContentId()) + this.uri = source.getContentId().getURI(); + } + } + + public EntryIdBuilder() { + } + + public void setMeta(final ImageMeta meta) { + this.meta = meta; + } + + public ImageMeta getMeta() { + if (this.meta==null) + return this.meta = new ImageMeta(); + else + return this.meta; + } + + public void setURI(final String uri) { + this.uri = uri; + } + + public String getURI() { + if (this.uri==null) + return this.uri = ""; + else + return this.uri; + } + + public EntryId build() { + return new EntryId(new ContentId(getURI()).getID() + getMeta()); + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/EntryManager.java b/src/main/java/com/kamesuta/mc/signpic/entry/EntryManager.java new file mode 100644 index 00000000..f7f49e2d --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/EntryManager.java @@ -0,0 +1,40 @@ +package com.kamesuta.mc.signpic.entry; + +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.google.common.collect.Maps; +import com.kamesuta.mc.signpic.handler.CoreEvent; + +public class EntryManager implements ITickEntry { + public static final EntryManager instance = new EntryManager(); + + public final ExecutorService threadpool = Executors.newFixedThreadPool(3); + private final Map> registry = Maps.newHashMap(); + + public Entry get(final EntryId id) { + final EntrySlot entries = this.registry.get(id); + if (entries!=null) + return entries.get(); + else { + final Entry entry = new Entry(id); + this.registry.put(id, new EntrySlot(entry)); + return entry; + } + } + + @CoreEvent + @Override + public void onTick() { + for (final Iterator>> itr = this.registry.entrySet().iterator(); itr.hasNext();) { + final Map.Entry> entry = itr.next(); + final EntrySlot collectableSignEntry = entry.getValue(); + + if (collectableSignEntry.shouldCollect()) { + itr.remove(); + } + } + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/EntrySlot.java b/src/main/java/com/kamesuta/mc/signpic/entry/EntrySlot.java new file mode 100644 index 00000000..545fdc61 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/EntrySlot.java @@ -0,0 +1,32 @@ +package com.kamesuta.mc.signpic.entry; + +public class EntrySlot { + public static final int CollectTimes = 20 * 15; + protected static long times = 0; + + protected final T entry; + private long time = 0; + + public EntrySlot(final T entry) { + this.entry = entry; + used(); + } + + public T get() { + used(); + return this.entry; + } + + public EntrySlot used() { + this.time = times; + return this; + } + + public boolean shouldCollect() { + return times - this.time > CollectTimes; + } + + public static void Tick() { + times++; + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/IAsyncProcessable.java b/src/main/java/com/kamesuta/mc/signpic/entry/IAsyncProcessable.java new file mode 100644 index 00000000..d3e03d43 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/IAsyncProcessable.java @@ -0,0 +1,8 @@ +package com.kamesuta.mc.signpic.entry; + +public interface IAsyncProcessable { + /** + * called once, do process at once + */ + void onAsyncProcess() throws Exception; +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/ICollectable.java b/src/main/java/com/kamesuta/mc/signpic/entry/ICollectable.java new file mode 100644 index 00000000..6f414949 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/ICollectable.java @@ -0,0 +1,5 @@ +package com.kamesuta.mc.signpic.entry; + +public interface ICollectable { + void onCollect(); +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/IDivisionProcessable.java b/src/main/java/com/kamesuta/mc/signpic/entry/IDivisionProcessable.java new file mode 100644 index 00000000..f83b83d9 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/IDivisionProcessable.java @@ -0,0 +1,9 @@ +package com.kamesuta.mc.signpic.entry; + +public interface IDivisionProcessable { + /** + * called multiple + * @return is finished + */ + boolean onDivisionProcess() throws Exception; +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/IInitable.java b/src/main/java/com/kamesuta/mc/signpic/entry/IInitable.java new file mode 100644 index 00000000..c0c81787 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/IInitable.java @@ -0,0 +1,5 @@ +package com.kamesuta.mc.signpic.entry; + +public interface IInitable { + void onInit(); +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/ITickEntry.java b/src/main/java/com/kamesuta/mc/signpic/entry/ITickEntry.java new file mode 100644 index 00000000..e86b37ec --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/ITickEntry.java @@ -0,0 +1,5 @@ +package com.kamesuta.mc.signpic.entry; + +public interface ITickEntry { + void onTick(); +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/Content.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/Content.java new file mode 100644 index 00000000..508fc543 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/Content.java @@ -0,0 +1,34 @@ +package com.kamesuta.mc.signpic.entry.content; + +import com.kamesuta.mc.signpic.entry.ICollectable; +import com.kamesuta.mc.signpic.entry.IInitable; +import com.kamesuta.mc.signpic.image.Image; +import com.kamesuta.mc.signpic.image.RemoteImage; +import com.kamesuta.mc.signpic.image.ResourceImage; + +public class Content implements IInitable, ICollectable { + public final ContentId id; + public final ContentState state; + public Image image; + + + public Content(final ContentId id) { + this.id = id; + this.state = new ContentState(); + if (id.isResource()) + this.image = new ResourceImage(this); + else + this.image = new RemoteImage(this); + } + + @Override + public void onInit() { + this.state.setType(ContentStateType.INITALIZED); + this.image.onInit(); + } + + @Override + public void onCollect() { + this.image.onCollect(); + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentDownloader.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentDownloader.java new file mode 100644 index 00000000..fbf844f6 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentDownloader.java @@ -0,0 +1,57 @@ +package com.kamesuta.mc.signpic.entry.content; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.CountingOutputStream; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; + +import com.kamesuta.mc.signpic.entry.IAsyncProcessable; +import com.kamesuta.mc.signpic.util.Downloader; + +public class ContentDownloader implements IAsyncProcessable { + protected final Content content; + protected final ContentLocation location; + + public ContentDownloader(final Content content, final ContentLocation location) { + this.content = content; + this.location = location; + } + + @Override + public void onAsyncProcess() throws URISyntaxException, IllegalStateException, IOException { + InputStream input = null; + CountingOutputStream countoutput = null; + this.content.state.setType(ContentStateType.DOWNLOADING); + try { + final File local = this.location.localLocation(this.content.id); + if (!local.exists()) { + final HttpUriRequest req = new HttpGet(this.location.remoteLocation(this.content.id)); + final HttpResponse response = Downloader.downloader.client.execute(req); + final HttpEntity entity = response.getEntity(); + + this.content.state.progress.overall = entity.getContentLength(); + input = entity.getContent(); + countoutput = new CountingOutputStream(new BufferedOutputStream(new FileOutputStream(local))) { + @Override + protected void afterWrite(final int n) throws IOException { + ContentDownloader.this.content.state.progress.done = getByteCount(); + } + }; + IOUtils.copy(input, countoutput); + } + this.content.state.setType(ContentStateType.DOWNLOADED); + } finally { + IOUtils.closeQuietly(input); + IOUtils.closeQuietly(countoutput); + } + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentId.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentId.java new file mode 100644 index 00000000..b3d6ed1e --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentId.java @@ -0,0 +1,80 @@ +package com.kamesuta.mc.signpic.entry.content; + +import org.apache.commons.lang3.StringUtils; + +import net.minecraft.util.ResourceLocation; + +public class ContentId { + private final String id; + + public ContentId(String uri) { + if (StringUtils.contains(uri, "http://")) + uri = StringUtils.substring(uri, 7, StringUtils.length(uri)); + else if (StringUtils.contains(uri, "https://")) + uri = "$" + StringUtils.substring(uri, 8, StringUtils.length(uri)); + this.id = uri; + } + + public String getID() { + return this.id; + } + + public String getURI() { + if (!StringUtils.startsWith(this.id, "!")) + if (StringUtils.startsWith(this.id, "$")) + return "https://" + StringUtils.substring(this.id, 1); + else if (!StringUtils.startsWith(this.id, "http://") && !StringUtils.startsWith(this.id, "https://")) + return "http://" + this.id; + return this.id; + } + + public String id() { + return this.id; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ContentId)) + return false; + final ContentId other = (ContentId) obj; + if (this.id == null) { + if (other.id != null) + return false; + } else if (!this.id.equals(other.id)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("ContentId [id=%s]", this.id); + } + + public boolean isResource() { + return this.id.startsWith("!"); + } + + public ResourceLocation getResource() { + return new ResourceLocation(StringUtils.substring(this.id, 1)); + } + + public Content content() { + return ContentManager.instance.get(this); + } + + public static ContentId fromResource(final ResourceLocation location) { + return new ContentId("!" + location.toString()); + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentLocation.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentLocation.java new file mode 100644 index 00000000..3cd83b17 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentLocation.java @@ -0,0 +1,22 @@ +package com.kamesuta.mc.signpic.entry.content; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.commons.codec.digest.DigestUtils; + +public class ContentLocation { + public File localroot; + public ContentLocation(final File localroot) { + this.localroot = localroot; + } + + public URI remoteLocation(final ContentId path) throws URISyntaxException { + return new URI(path.getURI()); + } + + public File localLocation(final ContentId path) { + return new File(this.localroot, DigestUtils.md5Hex(path.getURI())); + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentManager.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentManager.java new file mode 100644 index 00000000..15e73458 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentManager.java @@ -0,0 +1,79 @@ +package com.kamesuta.mc.signpic.entry.content; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import com.kamesuta.mc.signpic.entry.IAsyncProcessable; +import com.kamesuta.mc.signpic.entry.IDivisionProcessable; +import com.kamesuta.mc.signpic.entry.ITickEntry; +import com.kamesuta.mc.signpic.handler.CoreEvent; + +public class ContentManager implements ITickEntry { + public static ContentManager instance = new ContentManager(); + + public final ExecutorService threadpool = Executors.newFixedThreadPool(3); + protected final HashMap> registry = new HashMap>(); + public Deque asyncqueue = new ArrayDeque(); + public Deque divisionqueue = new ArrayDeque(); + + public ContentManager() { + } + + public Content get(final ContentId id) { + final ContentSlot entries = this.registry.get(id); + if (entries!=null) + return entries.get(); + else { + final Content entry = new Content(id); + this.registry.put(id, new ContentSlot(entry)); + return entry; + } + } + + @CoreEvent + @Override + public void onTick() { + IAsyncProcessable asyncprocess; + if ((asyncprocess = this.asyncqueue.poll()) != null) { + final IAsyncProcessable asyncprocessexec = asyncprocess; + this.threadpool.execute(new Runnable() { + @Override + public void run() { + try { + asyncprocessexec.onAsyncProcess(); + } catch (final Exception e) { + e.printStackTrace(); + } + } + }); + } + IDivisionProcessable divisionprocess; + if ((divisionprocess = this.divisionqueue.peek()) != null) { + try { + if (divisionprocess.onDivisionProcess()) { + this.divisionqueue.poll(); + } + } catch (final Exception e) { + e.printStackTrace(); + } + } + + for (final Iterator>> itr = this.registry.entrySet().iterator(); itr.hasNext();) { + final Entry> entry = itr.next(); + final ContentSlot collectableSignEntry = entry.getValue(); + + if (collectableSignEntry.shouldInit()) { + collectableSignEntry.onInit(); + } + if (collectableSignEntry.shouldCollect()) { + collectableSignEntry.get().onCollect(); + itr.remove(); + } + } + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentSlot.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentSlot.java new file mode 100644 index 00000000..17e64a74 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentSlot.java @@ -0,0 +1,31 @@ +package com.kamesuta.mc.signpic.entry.content; + +import com.kamesuta.mc.signpic.entry.EntrySlot; +import com.kamesuta.mc.signpic.entry.ICollectable; +import com.kamesuta.mc.signpic.entry.IInitable; + +public class ContentSlot extends EntrySlot implements IInitable, ICollectable { + public static int CollectTimes = 20 * 15; + public static long times = 0; + + private boolean init = true; + + public ContentSlot(final T entry) { + super(entry); + } + + @Override + public void onInit() { + this.init = false; + this.entry.onInit(); + } + + public boolean shouldInit() { + return this.init; + } + + @Override + public void onCollect() { + this.entry.onCollect(); + } +} \ No newline at end of file diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentState.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentState.java new file mode 100644 index 00000000..62ca551f --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentState.java @@ -0,0 +1,46 @@ +package com.kamesuta.mc.signpic.entry.content; + +import net.minecraft.client.resources.I18n; + +public class ContentState { + public Progress progress = new Progress(); + private ContentStateType type = ContentStateType.INIT; + private String message = ""; + + public ContentState setMessage(final String message) { + this.message = message; + return this; + } + + public String getMessage() { + return this.message; + } + + public ContentState setType(final ContentStateType type) { + this.type = type; + return this; + } + + public ContentStateType getType() { + return this.type; + } + + public String getStateMessage() { + return I18n.format(this.type.msg, (int) (this.progress.getProgress()*100)); + } + + public static class Progress { + public long overall; + public long done; + + float per() { + return (float) this.done / (float) this.overall; + } + + public float getProgress() { + if (this.overall > 0) + return Math.max(0, Math.min(1, per())); + return 0; + } + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentStateType.java b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentStateType.java new file mode 100644 index 00000000..c08cb356 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/entry/content/ContentStateType.java @@ -0,0 +1,29 @@ +package com.kamesuta.mc.signpic.entry.content; + +import com.kamesuta.mc.signpic.render.StateRender.LoadingCircle; +import com.kamesuta.mc.signpic.render.StateRender.LoadingCircleType; + +public enum ContentStateType { + INIT("signpic.state.init", LoadingCircle.INIT, LoadingCircleType.WAIT), + INITALIZED("signpic.state.initalized", LoadingCircle.INIT, LoadingCircleType.WAIT), + DOWNLOADING("signpic.state.downloading", LoadingCircle.DOWNLOAD, LoadingCircleType.RUN), + DOWNLOADED("signpic.state.downloaded", LoadingCircle.DOWNLOAD, LoadingCircleType.WAIT), + LOADING("signpic.state.loading", LoadingCircle.CONTENTLOAD, LoadingCircleType.RUN), + LOADED("signpic.state.loaded", LoadingCircle.CONTENTLOAD, LoadingCircleType.WAIT), + AVAILABLE("signpic.state.available"), + ERROR("signpic.state.error"), + ; + + public final String msg; + public final LoadingCircle circle; + public final LoadingCircleType speed; + private ContentStateType(final String s, final LoadingCircle circle, final LoadingCircleType speed) { + this.msg = s; + this.circle = circle; + this.speed = speed; + } + + private ContentStateType(final String s) { + this(s, LoadingCircle.DEFAULT, LoadingCircleType.DEFAULT); + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/gui/GuiOffset.java b/src/main/java/com/kamesuta/mc/signpic/gui/GuiOffset.java new file mode 100644 index 00000000..44c572f8 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/gui/GuiOffset.java @@ -0,0 +1,170 @@ +package com.kamesuta.mc.signpic.gui; + +import org.apache.commons.lang3.math.NumberUtils; + +import com.kamesuta.mc.bnnwidget.WEvent; +import com.kamesuta.mc.bnnwidget.WPanel; +import com.kamesuta.mc.bnnwidget.component.MLabel; +import com.kamesuta.mc.bnnwidget.component.MNumber; +import com.kamesuta.mc.bnnwidget.motion.BlankMotion; +import com.kamesuta.mc.bnnwidget.motion.Easings; +import com.kamesuta.mc.bnnwidget.motion.MCoord; +import com.kamesuta.mc.bnnwidget.position.Area; +import com.kamesuta.mc.bnnwidget.position.Coord; +import com.kamesuta.mc.bnnwidget.position.Point; +import com.kamesuta.mc.bnnwidget.position.R; +import com.kamesuta.mc.bnnwidget.position.RArea; +import com.kamesuta.mc.signpic.image.meta.ImageOffset; + +import net.minecraft.client.resources.I18n; + +public class GuiOffset extends WPanel { + protected ImageOffset offset; + + public GuiOffset(final R position, final ImageOffset offset) { + super(position); + this.offset = offset; + } + + @Override + protected void initWidget() { + final MCoord label = MCoord.pleft(-1f).add(Easings.easeOutBack.move(.25f, 0f)).start(); + add(new MLabel(new RArea(label, Coord.pwidth(1f), Coord.top(15*0), Coord.height(15)), I18n.format("signpic.gui.editor.offset.category")) { + @Override + public boolean onCloseRequest() { + label.stop().add(Easings.easeInBack.move(.25f, -1f)); + return false; + } + + @Override + public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { + return label.isFinished(); + } + }); + final MCoord x = MCoord.pleft(-1f); + add(new OffsetElement(new RArea(x, Coord.pwidth(1f), Coord.top(15*1), Coord.height(15)), x, 0, I18n.format("signpic.gui.editor.offset.x"), I18n.format("signpic.gui.editor.offset.x.neg"), I18n.format("signpic.gui.editor.offset.x.pos")) { + @Override + protected void initWidget() { + addDelay(this.left).add(Easings.easeOutBack.move(.25f, 0f)).start(); + super.initWidget(); + } + + @Override + protected void set(final float f) { + GuiOffset.this.offset.x = f; + onUpdate(); + } + + @Override + protected final float get() { + return GuiOffset.this.offset.x; + } + + @Override + protected MCoord addDelay(final MCoord c) { + return c.add(new BlankMotion(1*.025f)); + } + }); + final MCoord y = MCoord.pleft(-1f); + add(new OffsetElement(new RArea(y, Coord.pwidth(1f), Coord.top(15*2), Coord.height(15)), y, 1, I18n.format("signpic.gui.editor.offset.y"), I18n.format("signpic.gui.editor.offset.y.neg"), I18n.format("signpic.gui.editor.offset.y.pos")) { + @Override + protected void initWidget() { + addDelay(this.left).add(Easings.easeOutBack.move(.25f, 0f)).start(); + super.initWidget(); + } + + @Override + protected void set(final float f) { + GuiOffset.this.offset.y = f; + onUpdate(); + } + + @Override + protected final float get() { + return GuiOffset.this.offset.y; + } + + @Override + protected MCoord addDelay(final MCoord c) { + return c.add(new BlankMotion(2*.025f)); + } + }); + final MCoord z = MCoord.pleft(-1f); + add(new OffsetElement(new RArea(z, Coord.pwidth(1f), Coord.top(15*3), Coord.height(15)), z, 2, I18n.format("signpic.gui.editor.offset.z"), I18n.format("signpic.gui.editor.offset.z.neg"), I18n.format("signpic.gui.editor.offset.z.pos")) { + @Override + protected void initWidget() { + addDelay(this.left).add(Easings.easeOutBack.move(.25f, 0f)).start(); + super.initWidget(); + } + + @Override + protected void set(final float f) { + GuiOffset.this.offset.z = f; + onUpdate(); + } + + @Override + protected final float get() { + return GuiOffset.this.offset.z; + } + + @Override + protected MCoord addDelay(final MCoord c) { + return c.add(new BlankMotion(3*.025f)); + } + }); + } + + protected void onUpdate() {} + + protected abstract class OffsetElement extends WPanel { + protected String label; + protected String neg; + protected String pos; + protected MCoord left; + + public OffsetElement(final R position, final MCoord left, final int i, final String label, final String neg, final String pos) { + super(position); + this.label = label; + this.neg = neg; + this.pos = pos; + this.left = left; + } + + @Override + protected void initWidget() { + add(new MLabel(new RArea(Coord.left(0), Coord.width(15f), Coord.top(0), Coord.pheight(1f)), this.label)); + final MNumber n = new MNumber(new RArea(Coord.left(15), Coord.right(0), Coord.top(0), Coord.pheight(1f)), 15) { + @Override + protected void onNumberChanged(final String oldText, final String newText) { + if (NumberUtils.isNumber(newText)) { + set(NumberUtils.toFloat(newText)); + onUpdate(); + } + } + }.setNumber(get()); + n.neg.setText(this.neg); + n.pos.setText(this.pos); + add(n); + } + + protected abstract float get(); + + protected abstract void set(float f); + + protected MCoord addDelay(final MCoord c) { + return c; + } + + @Override + public boolean onCloseRequest() { + addDelay(this.left.stop()).add(Easings.easeInBack.move(.25f, -1f)).start(); + return false; + } + + @Override + public boolean onClosing(final WEvent ev, final Area pgp, final Point p) { + return this.left.isFinished(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/kamesuta/mc/signpic/gui/GuiRotation.java b/src/main/java/com/kamesuta/mc/signpic/gui/GuiRotation.java new file mode 100644 index 00000000..34d7ea81 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/gui/GuiRotation.java @@ -0,0 +1,272 @@ +package com.kamesuta.mc.signpic.gui; + +import java.util.ListIterator; +import java.util.Map; + +import org.apache.commons.lang3.math.NumberUtils; + +import com.google.common.collect.Maps; +import com.kamesuta.mc.bnnwidget.WEvent; +import com.kamesuta.mc.bnnwidget.WPanel; +import com.kamesuta.mc.bnnwidget.component.MButton; +import com.kamesuta.mc.bnnwidget.component.MLabel; +import com.kamesuta.mc.bnnwidget.component.MNumber; +import com.kamesuta.mc.bnnwidget.motion.BlankMotion; +import com.kamesuta.mc.bnnwidget.motion.Easings; +import com.kamesuta.mc.bnnwidget.motion.MCoord; +import com.kamesuta.mc.bnnwidget.position.Area; +import com.kamesuta.mc.bnnwidget.position.Coord; +import com.kamesuta.mc.bnnwidget.position.Point; +import com.kamesuta.mc.bnnwidget.position.R; +import com.kamesuta.mc.bnnwidget.position.RArea; +import com.kamesuta.mc.signpic.image.meta.ImageRotation; +import com.kamesuta.mc.signpic.image.meta.ImageRotation.Rotate; +import com.kamesuta.mc.signpic.image.meta.ImageRotation.RotateType; + +import net.minecraft.client.resources.I18n; + +public class GuiRotation extends WPanel { + protected RotationEditor editor; + protected RotationPanel panel; + + public GuiRotation(final R position, final ImageRotation rotation) { + super(position); + final MCoord left = MCoord.pleft(-1).add(Easings.easeOutBack.move(.25f, 0f)).start(); + this.editor = new RotationEditor(new RArea(left, Coord.top(0), Coord.pwidth(1f), Coord.height(15))) { + @Override + public boolean onCloseRequest() { + left.stop().add(Easings.easeInBack.move(.25f, -1f)); + return false; + } + + @Override + public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { + return left.isFinished(); + } + }; + this.panel = new RotationPanel(new RArea(Coord.left(0), Coord.top(15), Coord.right(0), Coord.bottom(0)), rotation); + } + + @Override + protected void initWidget() { + final MCoord label = MCoord.pleft(-1f).add(Easings.easeOutBack.move(.25f, 0f)).start(); + add(new MLabel(new RArea(label, Coord.pwidth(1f), Coord.top(15*0), Coord.height(15)), I18n.format("signpic.gui.editor.rotation.category")) { + @Override + public boolean onCloseRequest() { + label.stop().add(Easings.easeInBack.move(.25f, -1f)); + return false; + } + + @Override + public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { + return label.isFinished(); + } + }); + add(this.editor); + add(this.panel); + } + + protected void add(final Rotate rotate) { + this.panel.add(rotate); + this.panel.update(); + } + + protected void remove() { + this.panel.remove(); + this.panel.update(); + } + + protected void onUpdate() {} + + protected class RotationEditor extends WPanel { + public RotationEditor(final R position) { + super(position); + } + + @Override + protected void initWidget() { + add(new MButton(new RArea(Coord.ptop(0), Coord.right(15), Coord.width(15), Coord.pheight(1f)), I18n.format("signpic.gui.editor.rotation.add")) { + @Override + protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, final int button) { + GuiRotation.this.add(new Rotate(RotateType.X, 0)); + return true; + } + }); + add(new MButton(new RArea(Coord.ptop(0), Coord.right(0), Coord.width(15), Coord.pheight(1f)), I18n.format("signpic.gui.editor.rotation.remove")) { + @Override + protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, final int button) { + GuiRotation.this.remove(); + return true; + } + }); + } + } + + protected class RotationPanel extends WPanel { + private final Map map = Maps.newHashMap(); + protected final ImageRotation rotation; + + public RotationPanel(final R position, final ImageRotation rotation) { + super(position); + this.rotation = rotation; + for (final ListIterator itr = rotation.rotates.listIterator(); itr.hasNext();) { + final int n = itr.nextIndex(); + final Rotate rotate = itr.next(); + addWidget(rotate, n); + } + } + + @Override + protected void initWidget() { + update(); + } + + public void add(final Rotate rotate) { + final int n = this.rotation.rotates.size(); + if (n < 3) { + this.rotation.rotates.add(rotate); + addWidget(rotate, n); + } + } + + public void remove() { + if (!this.rotation.rotates.isEmpty()) { + final Rotate rotate = this.rotation.rotates.remove(this.rotation.rotates.size()-1); + remove(this.map.get(rotate)); + } + } + + public void up(final Rotate rotate) { + final int i = RotationPanel.this.rotation.rotates.indexOf(rotate); + if (i!=-1 && i>0) { + final Rotate prev = RotationPanel.this.rotation.rotates.get(i-1); + this.rotation.rotates.set(i, prev); + this.rotation.rotates.set(i-1, rotate); + this.update(); + } + } + + public void down(final Rotate rotate) { + final int i = RotationPanel.this.rotation.rotates.indexOf(rotate); + if (i!=-1 && i 0) { + RotateType rotateType = rotateTypes[0]; + boolean next = false; + for (final RotateType r : rotateTypes) { + if (next) { + rotateType = r; + break; + } + if (r == type) + next = true; + } + type = rotateType; + } + return type; + } + + protected void next() { + this.rotate.type = nextType(this.rotate.type); + onUpdate(); + setText(this.rotate.type.name()); + } + + public RotateType getType() { + return this.rotate.type; + } + } + } + } +} diff --git a/src/main/java/com/kamesuta/mc/signpic/gui/GuiSignPicEditor.java b/src/main/java/com/kamesuta/mc/signpic/gui/GuiSignPicEditor.java index 0028c5f0..5d5a0443 100644 --- a/src/main/java/com/kamesuta/mc/signpic/gui/GuiSignPicEditor.java +++ b/src/main/java/com/kamesuta/mc/signpic/gui/GuiSignPicEditor.java @@ -8,20 +8,20 @@ import com.kamesuta.mc.bnnwidget.WEvent; import com.kamesuta.mc.bnnwidget.WFrame; import com.kamesuta.mc.bnnwidget.WPanel; +import com.kamesuta.mc.bnnwidget.component.FunnyButton; import com.kamesuta.mc.bnnwidget.component.MButton; import com.kamesuta.mc.bnnwidget.component.MChatTextField; -import com.kamesuta.mc.bnnwidget.component.MLabel; -import com.kamesuta.mc.bnnwidget.component.MNumber; import com.kamesuta.mc.bnnwidget.component.MPanel; -import com.kamesuta.mc.bnnwidget.motion.BlankMotion; -import com.kamesuta.mc.bnnwidget.motion.EasingMotion; -import com.kamesuta.mc.bnnwidget.motion.MotionQueue; +import com.kamesuta.mc.bnnwidget.motion.Easings; +import com.kamesuta.mc.bnnwidget.motion.MCoord; import com.kamesuta.mc.bnnwidget.position.Area; import com.kamesuta.mc.bnnwidget.position.Coord; import com.kamesuta.mc.bnnwidget.position.Point; -import com.kamesuta.mc.bnnwidget.position.R; import com.kamesuta.mc.bnnwidget.position.RArea; -import com.kamesuta.mc.signpic.Client; +import com.kamesuta.mc.signpic.entry.Entry; +import com.kamesuta.mc.signpic.entry.EntryId; +import com.kamesuta.mc.signpic.entry.EntryIdBuilder; +import com.kamesuta.mc.signpic.entry.content.ContentManager; import com.kamesuta.mc.signpic.mode.CurrentMode; import com.kamesuta.mc.signpic.render.RenderHelper; import com.kamesuta.mc.signpic.util.Sign; @@ -29,6 +29,8 @@ import net.minecraft.client.resources.I18n; public class GuiSignPicEditor extends WFrame { + private final EntryIdBuilder signbuilder = new EntryIdBuilder(CurrentMode.instance.getEntryId()); + public GuiSignPicEditor() { } @@ -42,9 +44,9 @@ public void initGui() { protected void init() { add(new WPanel(RArea.diff(0, 0, 0, 0)) { @Override - protected void initWidget(final WEvent ev, final Area pgp) { + protected void initWidget() { add(new WBase(RArea.diff(0, 0, 0, 0)) { - MotionQueue m = new MotionQueue(0); + MCoord m = new MCoord(0); @Override public void draw(final WEvent ev, final Area pgp, final Point p, final float frame) { RenderHelper.startShape(); @@ -58,20 +60,21 @@ public void update(final WEvent ev, final Area pgp, final Point p) { if (CurrentMode.instance.isState(CurrentMode.State.PREVIEW)) { if (!this.b) { this.b = true; - this.m.stop().add(EasingMotion.easeLinear.move(.2f, 0f)).start(); + this.m.stop().add(Easings.easeLinear.move(.2f, 0f)).start(); } } else { if (this.b) { this.b = false; - this.m.stop().add(EasingMotion.easeLinear.move(.2f, .5f)).start(); + this.m.stop().add(Easings.easeLinear.move(.2f, .5f)).start(); } } super.update(ev, pgp, p); } @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse) { - this.m.stop().add(EasingMotion.easeLinear.move(.2f, 0f)).start(); + public boolean onCloseRequest() { + this.m.stop().add(Easings.easeLinear.move(.25f, 0f)).start(); + return false; } @Override @@ -80,13 +83,42 @@ public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { } }); - final Coord m = Coord.ptop(-1f); - add(new WPanel(new RArea(m, Coord.left(0), Coord.right(0), Coord.pheight(1f))) { + add(new GuiSize(new RArea(Coord.top(5), Coord.left(5), Coord.width(15*8), Coord.height(15*2)), GuiSignPicEditor.this.signbuilder.getMeta().size) { + @Override + protected void onUpdate() { + super.onUpdate(); + CurrentMode.instance.setEntryId(GuiSignPicEditor.this.signbuilder.build()); + } + }); + + add(new GuiOffset(new RArea(Coord.top(15*3+10), Coord.left(5), Coord.width(15*8), Coord.height(15*3)), GuiSignPicEditor.this.signbuilder.getMeta().offset) { @Override - protected void initWidget(final WEvent ev, final Area pgp) { + protected void onUpdate() { + super.onUpdate(); + CurrentMode.instance.setEntryId(GuiSignPicEditor.this.signbuilder.build()); + } + }); + + add(new GuiRotation(new RArea(Coord.top(15*8), Coord.left(5), Coord.width(15*8), Coord.height(15*4)), GuiSignPicEditor.this.signbuilder.getMeta().rotation) { + @Override + protected void onUpdate() { + super.onUpdate(); + CurrentMode.instance.setEntryId(GuiSignPicEditor.this.signbuilder.build()); + } + }); + + final MCoord m = MCoord.ptop(-1f); + add(new WPanel(new RArea(m, Coord.left(15*8+5), Coord.right(0), Coord.pheight(1f))) { + @Override + protected void initWidget() { add(new MPanel(new RArea(Coord.top(5), Coord.left(5), Coord.right(70), Coord.bottom(25))) { { - add(new SignPicLabel(new RArea(Coord.top(5), Coord.left(5), Coord.right(5), Coord.bottom(5)), Client.manager).setSign(CurrentMode.instance.getSign())); + add(new SignPicLabel(new RArea(Coord.top(5), Coord.left(5), Coord.right(5), Coord.bottom(5)), ContentManager.instance) { + @Override + public EntryId getEntryId() { + return CurrentMode.instance.getEntryId(); + } + }); } protected boolean b = !CurrentMode.instance.isState(CurrentMode.State.PREVIEW); @@ -95,12 +127,12 @@ public void update(final WEvent ev, final Area pgp, final Point p) { if (CurrentMode.instance.isState(CurrentMode.State.PREVIEW)) { if (!this.b) { this.b = true; - m.motion.stop().add(EasingMotion.easeOutElastic.move(.5f, -1f)).start(); + m.stop().add(Easings.easeInBack.move(.25f, -1f)).start(); } } else { if (this.b) { this.b = false; - m.motion.stop().add(EasingMotion.easeOutElastic.move(.5f, 0f)).start(); + m.stop().add(Easings.easeOutBack.move(.25f, 0f)).start(); } } super.update(ev, pgp, p); @@ -109,20 +141,21 @@ public void update(final WEvent ev, final Area pgp, final Point p) { } @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse) { - m.motion.stop().add(EasingMotion.easeOutElastic.move(.5f, -1f)).start(); + public boolean onCloseRequest() { + m.stop().add(Easings.easeInBack.move(.25f, -1f)).start(); + return false; } @Override public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { - return m.motion.isFinished(); + return m.isFinished(); } }); - final Coord p = Coord.right(-65).add(EasingMotion.easeOutBounce.move(.5f, 0)).start(); + final MCoord p = MCoord.right(-65).add(Easings.easeOutBack.move(.25f, 0)).start(); add(new WPanel(new RArea(Coord.top(0), p, Coord.width(70), Coord.bottom(0))) { @Override - protected void initWidget(final WEvent ev, final Area pgp) { + protected void initWidget() { float top = -20f; add(new FunnyButton(new RArea(Coord.right(5), Coord.top(top+=25), Coord.left(5), Coord.height(15)), I18n.format("signpic.gui.editor.see")) { @@ -147,7 +180,7 @@ protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, fina CurrentMode.instance.setMode(CurrentMode.Mode.SETPREVIEW); requestClose(); } else { - CurrentMode.instance.getSign().preview.setVisible(false); + Sign.preview.setVisible(false); } return true; } @@ -159,32 +192,8 @@ public boolean isEnabled() { } }); - float bottom = 175; + float bottom = 25*4+5; - add(new MLabel(new RArea(Coord.right(5), Coord.bottom(bottom-=20), Coord.left(5), Coord.height(15)), I18n.format("signpic.gui.editor.width"))); - add(new MNumber(new RArea(Coord.right(5), Coord.bottom(bottom-=15), Coord.left(5), Coord.height(15)), 15) { - { - if (CurrentMode.instance.getSign().meta.size.vaildWidth()) - setNumber(CurrentMode.instance.getSign().meta.size.width); - } - - @Override - protected void onNumberChanged(final String oldText, final String newText) { - CurrentMode.instance.getSign().meta.size.setWidth(newText); - } - }); - add(new MLabel(new RArea(Coord.right(5), Coord.bottom(bottom-=20), Coord.left(5), Coord.height(15)), I18n.format("signpic.gui.editor.height"))); - add(new MNumber(new RArea(Coord.right(5), Coord.bottom(bottom-=15), Coord.left(5), Coord.height(15)), 15) { - { - if (CurrentMode.instance.getSign().meta.size.vaildHeight()) - setNumber(CurrentMode.instance.getSign().meta.size.height); - } - - @Override - protected void onNumberChanged(final String oldText, final String newText) { - CurrentMode.instance.getSign().meta.size.setHeight(newText); - } - }); add(new FunnyButton(new RArea(Coord.right(5), Coord.bottom(bottom-=25), Coord.left(5), Coord.height(15)), I18n.format("signpic.gui.editor.continue")) { @Override protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, final int button) { @@ -215,7 +224,8 @@ public boolean isEnabled() { add(new FunnyButton(new RArea(Coord.right(5), Coord.bottom(bottom-=25), Coord.left(5), Coord.height(15)), I18n.format("signpic.gui.editor.place")) { @Override protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, final int button) { - if (CurrentMode.instance.getSign().isVaild() && CurrentMode.instance.getSign().isPlaceable()) { + final Entry entry = CurrentMode.instance.getEntryId().entry(); + if (entry.isValid() && Sign.isPlaceable(entry.id)) { CurrentMode.instance.setMode(CurrentMode.Mode.PLACE); requestClose(); return true; @@ -226,7 +236,8 @@ protected boolean onClicked(final WEvent ev, final Area pgp, final Point p, fina @Override public boolean isEnabled() { state(CurrentMode.instance.isMode(CurrentMode.Mode.PLACE)); - return CurrentMode.instance.getSign().isVaild() && CurrentMode.instance.getSign().isPlaceable() && !CurrentMode.instance.isMode(CurrentMode.Mode.PLACE); + final Entry entry = CurrentMode.instance.getEntryId().entry(); + return entry.isValid() && Sign.isPlaceable(entry.id) && !CurrentMode.instance.isMode(CurrentMode.Mode.PLACE); } }); add(new MButton(new RArea(Coord.right(5), Coord.bottom(bottom-=25), Coord.left(5), Coord.height(15)), I18n.format("signpic.gui.editor.cancel")) { @@ -247,46 +258,52 @@ public boolean isEnabled() { } @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse) { - p.motion.stop().add(EasingMotion.easeOutBounce.move(.5f, -65)).add(new BlankMotion(.1f)).start(); + public boolean onCloseRequest() { + p.stop().add(Easings.easeInBack.move(.25f, -65)).start(); + return false; } @Override public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { - return p.motion.isFinished(); + return p.isFinished(); } }); - final Coord d = Coord.bottom(-15).add(EasingMotion.easeOutElastic.move(.5f, 5)).start(); + final MCoord d = MCoord.bottom(-15).add(Easings.easeOutBack.move(.5f, 5)).start(); add(new MChatTextField(new RArea(Coord.left(5), d, Coord.right(70), Coord.height(15))) { @Override - public void init(final WEvent ev, final Area pgp) { - super.init(ev, pgp); + public void onAdded() { + super.onAdded(); setMaxStringLength(Integer.MAX_VALUE); setWatermark(I18n.format("signpic.gui.editor.textfield")); - if (CurrentMode.instance.getSign().id != null) { - setText(CurrentMode.instance.getSign().id); + final String id = GuiSignPicEditor.this.signbuilder.getURI(); + if (id != null) { + setText(id); } } @Override public void onFocusChanged() { - final String text = getText(); - if (Sign.hasMeta(text)) - CurrentMode.instance.getSign().parseText(text); + final EntryId entryId = new EntryId(getText()); + if (entryId.hasMeta()) + GuiSignPicEditor.this.signbuilder.setMeta(entryId.getMeta()); + if (entryId.hasContentId()) + GuiSignPicEditor.this.signbuilder.setURI(entryId.getContentId().getURI()); else - CurrentMode.instance.getSign().id = text; + GuiSignPicEditor.this.signbuilder.setURI(""); + CurrentMode.instance.setEntryId(GuiSignPicEditor.this.signbuilder.build()); } @Override - public void onCloseRequest(final WEvent ev, final Area pgp, final Point mouse) { - super.onCloseRequest(ev, pgp, mouse); - d.motion.stop().add(EasingMotion.easeOutElastic.move(1f, -15)).start(); + public boolean onCloseRequest() { + super.onCloseRequest(); + d.stop().add(Easings.easeInBack.move(.25f, -15)).start(); + return false; } @Override public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { - return d.motion.isFinished(); + return d.isFinished(); } }); } @@ -303,43 +320,4 @@ public void onGuiClosed() { public boolean doesGuiPauseGame() { return false; } - - public class FunnyButton extends MButton { - public FunnyButton(final R position, final String text) { - super(position, text); - } - - boolean hover; - MotionQueue m = new MotionQueue(0); - MotionQueue s = new MotionQueue(1); - - protected void state(final boolean b) { - if (b) { - if (!this.hover) { - this.hover = true; - this.m.stop().add(EasingMotion.easeOutElastic.move(.5f, 6f)).start(); - this.s.stop().add(EasingMotion.easeOutElastic.move(.5f, 1.1f)).start(); - } - } else { - if (this.hover) { - this.hover = false; - this.m.stop().add(EasingMotion.easeOutElastic.move(.5f, 0f)).start(); - this.s.stop().add(EasingMotion.easeOutElastic.move(.5f, 1f)).start(); - } - } - } - - @Override - public void draw(final WEvent ev, final Area pgp, final Point p, final float frame) { - final Area a = getGuiPosition(pgp); - glPushMatrix(); - glTranslatef(a.x1()+a.w()/2, a.y1()+a.h()/2, 0); - final float c = this.s.get(); - glScalef(c, c, 1f); - glRotatef(this.m.get(), 0, 0, 1); - glTranslatef(-a.x1()-a.w()/2, -a.y1()-a.h()/2, 0); - super.draw(ev, pgp, p, frame); - glPopMatrix(); - } - } } diff --git a/src/main/java/com/kamesuta/mc/signpic/gui/GuiSize.java b/src/main/java/com/kamesuta/mc/signpic/gui/GuiSize.java new file mode 100644 index 00000000..aa900236 --- /dev/null +++ b/src/main/java/com/kamesuta/mc/signpic/gui/GuiSize.java @@ -0,0 +1,146 @@ +package com.kamesuta.mc.signpic.gui; + +import org.apache.commons.lang3.math.NumberUtils; + +import com.kamesuta.mc.bnnwidget.WEvent; +import com.kamesuta.mc.bnnwidget.WPanel; +import com.kamesuta.mc.bnnwidget.component.MLabel; +import com.kamesuta.mc.bnnwidget.component.MNumber; +import com.kamesuta.mc.bnnwidget.motion.BlankMotion; +import com.kamesuta.mc.bnnwidget.motion.Easings; +import com.kamesuta.mc.bnnwidget.motion.MCoord; +import com.kamesuta.mc.bnnwidget.position.Area; +import com.kamesuta.mc.bnnwidget.position.Coord; +import com.kamesuta.mc.bnnwidget.position.Point; +import com.kamesuta.mc.bnnwidget.position.R; +import com.kamesuta.mc.bnnwidget.position.RArea; +import com.kamesuta.mc.signpic.image.meta.ImageSize; + +import net.minecraft.client.resources.I18n; + +public class GuiSize extends WPanel { + protected ImageSize size; + + public GuiSize(final R position, final ImageSize size) { + super(position); + this.size = size; + } + + @Override + protected void initWidget() { + final MCoord label = MCoord.pleft(-1f).add(Easings.easeOutBack.move(.25f, 0f)).start(); + add(new MLabel(new RArea(label, Coord.pwidth(1f), Coord.top(15*0), Coord.height(15)), I18n.format("signpic.gui.editor.size.category")) { + @Override + public boolean onCloseRequest() { + label.stop().add(Easings.easeInBack.move(.25f, -1f)); + return false; + } + + @Override + public boolean onClosing(final WEvent ev, final Area pgp, final Point mouse) { + return label.isFinished(); + } + }); + final MCoord w = MCoord.pleft(-1f); + add(new OffsetElement(new RArea(w, Coord.pwidth(1f), Coord.top(15*1), Coord.height(15)), w, 0, I18n.format("signpic.gui.editor.size.width"), I18n.format("signpic.gui.editor.size.width.neg"), I18n.format("signpic.gui.editor.size.width.pos")) { + @Override + protected void initWidget() { + addDelay(this.left).add(Easings.easeOutBack.move(.25f, 0f)).start(); + super.initWidget(); + } + + @Override + protected void set(final float f) { + GuiSize.this.size.width = f; + onUpdate(); + } + + @Override + protected final float get() { + return GuiSize.this.size.width; + } + + @Override + protected MCoord addDelay(final MCoord c) { + return c.add(new BlankMotion(1*.025f)); + } + }); + final MCoord h = MCoord.pleft(-1f); + add(new OffsetElement(new RArea(h, Coord.pwidth(1f), Coord.top(15*2), Coord.height(15)), h, 1, I18n.format("signpic.gui.editor.size.height"), I18n.format("signpic.gui.editor.size.height.neg"), I18n.format("signpic.gui.editor.size.height.pos")) { + @Override + protected void initWidget() { + addDelay(this.left).add(Easings.easeOutBack.move(.25f, 0f)).start(); + super.initWidget(); + } + + @Override + protected void set(final float f) { + GuiSize.this.size.height = f; + onUpdate(); + } + + @Override + protected final float get() { + return GuiSize.this.size.height; + } + + @Override + protected MCoord addDelay(final MCoord c) { + return c.add(new BlankMotion(2*.025f)); + } + }); + } + + protected void onUpdate() {} + + protected abstract class OffsetElement extends WPanel { + protected String label; + protected String neg; + protected String pos; + protected MCoord left; + + public OffsetElement(final R position, final MCoord left, final int i, final String label, final String neg, final String pos) { + super(position); + this.label = label; + this.neg = neg; + this.pos = pos; + this.left = left; + } + + @Override + protected void initWidget() { + add(new MLabel(new RArea(Coord.left(0), Coord.width(15f), Coord.top(0), Coord.pheight(1f)), this.label)); + final MNumber n = new MNumber(new RArea(Coord.left(15), Coord.right(0), Coord.top(0), Coord.pheight(1f)), 15) { + @Override + protected void onNumberChanged(final String oldText, final String newText) { + if (NumberUtils.isNumber(newText)) { + set(NumberUtils.toFloat(newText)); + onUpdate(); + } + } + }.setNumber(get()); + n.neg.setText(this.neg); + n.pos.setText(this.pos); + add(n); + } + + protected abstract float get(); + + protected abstract void set(float f); + + protected MCoord addDelay(final MCoord c) { + return c; + } + + @Override + public boolean onCloseRequest() { + addDelay(this.left.stop()).add(Easings.easeInBack.move(.25f, -1f)).start(); + return false; + } + + @Override + public boolean onClosing(final WEvent ev, final Area pgp, final Point p) { + return this.left.isFinished(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/kamesuta/mc/signpic/gui/SignPicLabel.java b/src/main/java/com/kamesuta/mc/signpic/gui/SignPicLabel.java index 29fd42f9..4ab8eac3 100644 --- a/src/main/java/com/kamesuta/mc/signpic/gui/SignPicLabel.java +++ b/src/main/java/com/kamesuta/mc/signpic/gui/SignPicLabel.java @@ -9,18 +9,23 @@ import com.kamesuta.mc.bnnwidget.position.Area; import com.kamesuta.mc.bnnwidget.position.Point; import com.kamesuta.mc.bnnwidget.position.R; -import com.kamesuta.mc.signpic.image.Image; -import com.kamesuta.mc.signpic.image.ImageManager; +import com.kamesuta.mc.signpic.Client; +import com.kamesuta.mc.signpic.entry.Entry; +import com.kamesuta.mc.signpic.entry.EntryId; +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentManager; import com.kamesuta.mc.signpic.image.meta.ImageSize; import com.kamesuta.mc.signpic.image.meta.ImageSize.ImageSizes; import com.kamesuta.mc.signpic.render.RenderHelper; -import com.kamesuta.mc.signpic.util.Sign; + +import net.minecraft.util.ResourceLocation; public class SignPicLabel extends WBase { - protected Sign sign; - protected ImageManager manager; + public static final ResourceLocation defaultTexture = new ResourceLocation("signpic", "textures/logo.png"); + protected EntryId entryId; + protected ContentManager manager; - public SignPicLabel(final R position, final ImageManager manager) { + public SignPicLabel(final R position, final ContentManager manager) { super(position); this.manager = manager; } @@ -28,33 +33,28 @@ public SignPicLabel(final R position, final ImageManager manager) { @Override public void draw(final WEvent ev, final Area pgp, final Point p, final float frame) { final Area a = getGuiPosition(pgp); - final Sign s = getSign(); - if (s.isVaild()) { - final String id = s.getURL(); - if (s != null && !StringUtils.isEmpty(id)) { - final Image image = this.manager.get(id); - if (image != null) { + final EntryId entryId = getEntryId(); + if (entryId != null) { + final Entry entry = entryId.entry(); + if (entry.isValid()) { + final Content content = entry.content(); + if (content == null || StringUtils.isEmpty(content.id.id())) { RenderHelper.startTexture(); + glColor4f(1f, 1f, 1f, .2f); + texture().bindTexture(defaultTexture); + drawTexturedModalRect(a); + } else { glDisable(GL_CULL_FACE); glPushMatrix(); - translate(a); - final ImageSize siz = new ImageSize().setAspectSize(this.sign.meta.size, image.getSize()); - final ImageSize size = new ImageSize().setSize(ImageSizes.INNER, siz, new ImageSize().setArea(a)); - - glPushMatrix(); - glTranslatef((a.w()-size.width)/2, (a.h()-size.height)/2, 0); - glScalef(size.width, size.height, 1f); - image.getState().mainImage(this.manager, image); - glPopMatrix(); + final ImageSize size1 = new ImageSize().setAspectSize(entry.meta.size, content.image.getSize()); + final ImageSize size2 = new ImageSize().setSize(ImageSizes.INNER, size1, new ImageSize().setArea(a)); + final ImageSize size = new ImageSize().setImageSize(size2).scale(1f/100f); - glPushMatrix(); - glTranslatef(a.w()/2, a.h()/2, 0); - //glScalef(size.width, size.height, 1f); - glScalef(25f, 25f, 1f); - image.getState().themeImage(this.manager, image); - image.getState().message(this.manager, image, font()); - glPopMatrix(); + translate(a); + glTranslatef((a.w()-size2.width)/2f, (a.h()-size2.height)/2f, 0f); + glScalef(100, 100, 1f); + Client.renderer.renderImage(content, size, 1f); glPopMatrix(); glEnable(GL_CULL_FACE); @@ -63,12 +63,12 @@ public void draw(final WEvent ev, final Area pgp, final Point p, final float fra } } - public Sign getSign() { - return this.sign; + public EntryId getEntryId() { + return this.entryId; } - public SignPicLabel setSign(final Sign sign) { - this.sign = sign; + public SignPicLabel setEntryId(final EntryId entryId) { + this.entryId = entryId; return this; } } diff --git a/src/main/java/com/kamesuta/mc/signpic/handler/CoreHandler.java b/src/main/java/com/kamesuta/mc/signpic/handler/CoreHandler.java index 04c8eaa7..90a8cb43 100644 --- a/src/main/java/com/kamesuta/mc/signpic/handler/CoreHandler.java +++ b/src/main/java/com/kamesuta/mc/signpic/handler/CoreHandler.java @@ -1,7 +1,11 @@ package com.kamesuta.mc.signpic.handler; +import org.lwjgl.util.Timer; + import com.kamesuta.mc.signpic.Client; -import com.kamesuta.mc.signpic.image.ImageManager; +import com.kamesuta.mc.signpic.entry.EntryManager; +import com.kamesuta.mc.signpic.entry.EntrySlot; +import com.kamesuta.mc.signpic.entry.content.ContentManager; import com.kamesuta.mc.signpic.information.InformationChecker; import com.kamesuta.mc.signpic.render.SignPicRender; @@ -19,8 +23,9 @@ public class CoreHandler { public final KeyHandler keyHandler = new KeyHandler(); public final SignHandler signHandler = new SignHandler(); - public final ImageManager imageHandler = Client.manager; - public final SignPicRender renderHandler = new SignPicRender(this.imageHandler); + public final EntryManager signEntryManager = EntryManager.instance; + public final ContentManager contentManager = ContentManager.instance; + public final SignPicRender renderHandler = new SignPicRender(); public final InformationChecker informationHandler = new InformationChecker(); public void init() { @@ -38,7 +43,7 @@ public void onKeyInput(final InputEvent event) { @SubscribeEvent public void onRenderTick(final TickEvent.RenderTickEvent event) { - this.imageHandler.onRenderTick(event); + Timer.tick(); } @SubscribeEvent @@ -68,6 +73,11 @@ public void onText(final RenderGameOverlayEvent.Text event) { @SubscribeEvent public void onTick(final ClientTickEvent event) { + Client.startSection("signpic_load"); + this.signEntryManager.onTick(); + this.contentManager.onTick(); this.informationHandler.onTick(event); + EntrySlot.Tick(); + Client.endSection(); } } diff --git a/src/main/java/com/kamesuta/mc/signpic/handler/SignHandler.java b/src/main/java/com/kamesuta/mc/signpic/handler/SignHandler.java index 02e26160..353cbadc 100644 --- a/src/main/java/com/kamesuta/mc/signpic/handler/SignHandler.java +++ b/src/main/java/com/kamesuta/mc/signpic/handler/SignHandler.java @@ -3,6 +3,8 @@ import com.kamesuta.mc.signpic.Client; import com.kamesuta.mc.signpic.Reference; +import com.kamesuta.mc.signpic.entry.Entry; +import com.kamesuta.mc.signpic.entry.EntryId; import com.kamesuta.mc.signpic.mode.CurrentMode; import com.kamesuta.mc.signpic.preview.SignEntity; import com.kamesuta.mc.signpic.util.ChatBuilder; @@ -40,15 +42,15 @@ public void onSign(final GuiOpenEvent event) { try { final GuiEditSign ges = (GuiEditSign) event.gui; final TileEntitySign tileSign = (TileEntitySign) f.get(ges); - CurrentMode.instance.getSign().sendSign(tileSign); + Sign.sendSign(CurrentMode.instance.getEntryId(), tileSign); event.setCanceled(true); if (!CurrentMode.instance.isState(CurrentMode.State.CONTINUE)) { CurrentMode.instance.setMode(); - final SignEntity se = CurrentMode.instance.getSign().preview; + final SignEntity se = Sign.preview; if (se.isRenderable()) { final TileEntitySign preview = se.getTileEntity(); if (preview.xCoord==tileSign.xCoord && preview.yCoord==tileSign.yCoord && preview.zCoord==tileSign.zCoord) { - CurrentMode.instance.getSign().preview.setVisible(false); + Sign.preview.setVisible(false); CurrentMode.instance.setState(CurrentMode.State.PREVIEW, false); CurrentMode.instance.setState(CurrentMode.State.SEE, false); } @@ -68,7 +70,7 @@ public void onSign(final GuiOpenEvent event) { public void onClick(final MouseEvent event) { if (event.buttonstate && Client.mc.gameSettings.keyBindUseItem.getKeyCode() == event.button - 100) { if (CurrentMode.instance.isMode(CurrentMode.Mode.SETPREVIEW)) { - CurrentMode.instance.getSign().preview.capturePlace(); + Sign.preview.capturePlace(); event.setCanceled(true); if (!CurrentMode.instance.isState(CurrentMode.State.CONTINUE)) { CurrentMode.instance.setMode(); @@ -77,9 +79,9 @@ public void onClick(final MouseEvent event) { } else if (CurrentMode.instance.isMode(CurrentMode.Mode.LOAD)) { final TileEntitySign tilesign = Client.getTileSignLooking(); if (tilesign != null) { - final Sign sign = new Sign().parseSignEntity(tilesign); - if (sign.isVaild()) { - CurrentMode.instance.setSign(sign); + final Entry entry = EntryId.fromTile(tilesign).entry(); + if (entry.isValid()) { + CurrentMode.instance.setEntryId(entry.id); event.setCanceled(true); Client.openEditor(); if (!CurrentMode.instance.isState(CurrentMode.State.CONTINUE)) diff --git a/src/main/java/com/kamesuta/mc/signpic/image/Image.java b/src/main/java/com/kamesuta/mc/signpic/image/Image.java index f0ae729d..82d831f1 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/Image.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/Image.java @@ -1,70 +1,39 @@ package com.kamesuta.mc.signpic.image; -import static org.lwjgl.opengl.GL11.*; - +import com.kamesuta.mc.signpic.entry.IAsyncProcessable; +import com.kamesuta.mc.signpic.entry.ICollectable; +import com.kamesuta.mc.signpic.entry.IDivisionProcessable; +import com.kamesuta.mc.signpic.entry.IInitable; +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentStateType; import com.kamesuta.mc.signpic.image.meta.ImageSize; import com.kamesuta.mc.signpic.render.RenderHelper; import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.resources.I18n; -public abstract class Image { +public abstract class Image implements IInitable, IAsyncProcessable, IDivisionProcessable, ICollectable { protected static final ImageSize DefaultSize = new ImageSize().defaultSize(); - protected final String id; - protected ImageState state = ImageState.INIT; - - public Image(final String id) { - this.id = id; - } + protected final Content content; - public String getId() { - return this.id; + public Image(final Content content) { + this.content = content; } public abstract IImageTexture getTexture() throws IllegalStateException; - public ImageState getState() { - return this.state; - } - - public abstract float getProgress(); - - public String getStatusMessage() { - return I18n.format(this.state.msg, (int) (getProgress()*100)); - } - public abstract String getLocal(); - public String advMessage() { - return null; - }; - - public void onImageUsed() {} - - public boolean shouldCollect() { - return false; - } - - public void delete() {} - - public abstract void process(); - - public boolean processTexture() { - return true; - } - public ImageSize getSize() { - if (this.state == ImageState.AVAILABLE) + if (this.content.state.getType() == ContentStateType.AVAILABLE) return getTexture().getSize(); else return DefaultSize; } public void draw() { - if (this.state == ImageState.AVAILABLE) { + if (this.content.state.getType() == ContentStateType.AVAILABLE) { final Tessellator t = Tessellator.instance; RenderHelper.startTexture(); - glColor4f(1.0F, 1.0F, 1.0F, 1.0F); getTexture().bind(); t.startDrawingQuads(); t.addVertexWithUV(0, 0, 0, 0, 0); diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageDownloader.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageDownloader.java deleted file mode 100644 index aa72ce01..00000000 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageDownloader.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.kamesuta.mc.signpic.image; - -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.net.URISyntaxException; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.output.CountingOutputStream; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; - -import com.kamesuta.mc.signpic.util.Downloader; - -import net.minecraft.client.resources.I18n; - -public class ImageDownloader { - protected final ImageLocation location; - protected final RemoteImage image; - - protected long maxsize; - protected CountingOutputStream countoutput; - - public ImageDownloader(final RemoteImage image, final ImageLocation location) { - this.location = location; - this.image = image; - } - - public void load() { - InputStream input = null; - try { - final File local = this.location.localLocation(this.image); - - final HttpUriRequest req = new HttpGet(this.location.remoteLocation(this.image)); - final HttpResponse response = Downloader.downloader.client.execute(req); - final HttpEntity entity = response.getEntity(); - - this.maxsize = entity.getContentLength(); - input = entity.getContent(); - this.countoutput = new CountingOutputStream(new BufferedOutputStream(new FileOutputStream(local))); - IOUtils.copy(input, this.countoutput); - - this.image.state = ImageState.DOWNLOADED; - } catch (final URISyntaxException e) { - this.image.state = ImageState.ERROR; - this.image.advmsg = I18n.format("signpic.advmsg.invaildurl"); - } catch (final Exception e) { - this.image.state = ImageState.FAILED; - this.image.advmsg = I18n.format("signpic.advmsg.dlerror", e); - } finally { - IOUtils.closeQuietly(input); - IOUtils.closeQuietly(this.countoutput); - } - } - - public float getProgress() { - if (this.maxsize > 0) - return Math.max(0, Math.min(1, (getRate() / (float) this.maxsize))); - return 0; - } - - protected long getRate() { - if (this.countoutput != null) - return this.countoutput.getByteCount(); - return 0; - } -} diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageIOLoader.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageIOLoader.java index 3e14fc72..291820a8 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageIOLoader.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/ImageIOLoader.java @@ -18,96 +18,80 @@ import org.apache.commons.io.IOUtils; import com.google.common.collect.Lists; +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentLocation; +import com.kamesuta.mc.signpic.entry.content.ContentStateType; import com.kamesuta.mc.signpic.image.exception.InvaildImageException; import com.kamesuta.mc.signpic.image.meta.ImageSize; import com.kamesuta.mc.signpic.image.meta.ImageSize.ImageSizes; import com.kamesuta.mc.signpic.lib.GifDecoder; import com.kamesuta.mc.signpic.lib.GifDecoder.GifImage; -import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.IResourceManager; import net.minecraft.util.ResourceLocation; public class ImageIOLoader { public static final ImageSize MAX_SIZE = new ImageSize().setSize(512, 512); - protected RemoteImage image; + protected Content content; protected InputStream input; - public ImageIOLoader(final RemoteImage image, final InputStream in) throws IOException { - this.image = image; + public ImageIOLoader(final Content content, final InputStream in) throws IOException { + this.content = content; this.input = in; } - public ImageIOLoader(final RemoteImage image, final File file) throws IOException { - this(image, new FileInputStream(file)); + public ImageIOLoader(final Content content, final File file) throws IOException { + this(content, new FileInputStream(file)); } - public ImageIOLoader(final RemoteImage image, final IResourceManager manager, final ResourceLocation location) throws IOException { - this(image, manager.getResource(location).getInputStream()); + public ImageIOLoader(final Content content, final IResourceManager manager, final ResourceLocation location) throws IOException { + this(content, manager.getResource(location).getInputStream()); } - public void load() { - try { - final byte[] data = IOUtils.toByteArray(this.input); - - final ImageInputStream imagestream = ImageIO.createImageInputStream(new ByteArrayInputStream(data)); - final Iterator iter = ImageIO.getImageReaders(imagestream); - if (!iter.hasNext()) throw new InvaildImageException(); - final ImageReader reader = iter.next(); - - if (reader.getFormatName()=="gif") { - loadGif(data); - } else { - loadImage(reader, imagestream); - } - this.image.state = ImageState.IOLOADED; - } catch (final InvaildImageException e) { - this.image.state = ImageState.ERROR; - this.image.advmsg = I18n.format("signpic.advmsg.invaildimage"); - } catch (final IOException e) { - this.image.state = ImageState.FAILED; - this.image.advmsg = I18n.format("signpic.advmsg.ioerror", e); - } catch (final Exception e) { - this.image.state = ImageState.FAILED; - this.image.advmsg = I18n.format("signpic.advmsg.unknown", e); - } + public ImageIOLoader(final Content content, final ContentLocation location) throws IOException { + this(content, location.localLocation(content.id)); } - protected static final String[] imageatt = new String[] { - "imageLeftPosition", - "imageTopPosition", - "imageWidth", - "imageHeight", - }; - - protected int maxprogress; - protected int progress; - public float getProgress() { - if (this.maxprogress > 0) - return Math.max(0, Math.min(1, (float)this.progress / this.maxprogress)); - return 0; + public ImageTextures load() throws IOException { + final byte[] data = IOUtils.toByteArray(this.input); + + final ImageInputStream imagestream = ImageIO.createImageInputStream(new ByteArrayInputStream(data)); + final Iterator iter = ImageIO.getImageReaders(imagestream); + if (!iter.hasNext()) throw new InvaildImageException(); + final ImageReader reader = iter.next(); + + this.content.state.setType(ContentStateType.LOADING); + ImageTextures textures; + if (reader.getFormatName()=="gif") { + textures = loadGif(data); + } else { + textures = loadImage(reader, imagestream); + } + this.content.state.setType(ContentStateType.LOADED); + return textures; } - protected void loadGif(final byte[] data) throws IOException { + private ImageTextures loadGif(final byte[] data) throws IOException { final GifImage gifImage = GifDecoder.read(data); final int width = gifImage.getWidth(); final int height = gifImage.getHeight(); final ImageSize newsize = new ImageSize().setSize(ImageSizes.LIMIT, width, height, MAX_SIZE); final ArrayList textures = new ArrayList(); - final int frameCount = this.maxprogress = gifImage.getFrameCount(); + final int frameCount = gifImage.getFrameCount(); + this.content.state.progress.overall = frameCount; for (int i = 0; i < frameCount; i++) { final BufferedImage image = gifImage.getFrame(i); final int delay = gifImage.getDelay(i); final ImageTexture texture = new ImageTexture(createResizedImage(image, newsize), (float)delay / 100); textures.add(texture); - this.progress = i; + this.content.state.progress.done = i; } - this.image.texture = new ImageTextures(textures); + return new ImageTextures(textures); } - protected void loadImage(final ImageReader reader, final ImageInputStream imagestream) throws IOException { + private ImageTextures loadImage(final ImageReader reader, final ImageInputStream imagestream) throws IOException { final ImageReadParam param = reader.getDefaultReadParam(); reader.setInput(imagestream, true, true); BufferedImage canvas; @@ -118,10 +102,10 @@ protected void loadImage(final ImageReader reader, final ImageInputStream images imagestream.close(); } final ImageSize newsize = new ImageSize().setSize(ImageSizes.LIMIT, canvas.getWidth(), canvas.getHeight(), MAX_SIZE); - this.image.texture = new ImageTextures(Lists.newArrayList(new ImageTexture(createResizedImage(canvas, newsize)))); + return new ImageTextures(Lists.newArrayList(new ImageTexture(createResizedImage(canvas, newsize)))); } - protected BufferedImage createResizedImage(final BufferedImage image, final ImageSize newsize) { + private BufferedImage createResizedImage(final BufferedImage image, final ImageSize newsize) { final int wid = (int) newsize.width; final int hei = (int) newsize.height; final BufferedImage thumb = new BufferedImage(wid, hei, image.getType()); diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageLoader.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageLoader.java deleted file mode 100644 index b4a27326..00000000 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageLoader.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.kamesuta.mc.signpic.image; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -import net.minecraft.client.resources.I18n; - -public class ImageLoader implements Runnable { - protected RemoteImage image; - protected ImageLocation remote; - - public ImageLoader(final RemoteImage image, final ImageLocation remote) { - this.image = image; - this.remote = remote; - } - - @Override - public void run() { - final File local = this.image.location.localLocation(this.image); - try { - this.image.state = ImageState.DOWNLOADING; - if (local.exists()) { - this.image.state = ImageState.DOWNLOADED; - } else { - if (this.image.downloading == null) { - this.image.downloading = new ImageDownloader(this.image, this.image.location); - this.image.downloading.load(); - } - } - - if (this.image.state == ImageState.DOWNLOADED) { - this.image.state = ImageState.IOLOADING; - if (local.exists()) { - this.image.local = local; - if (this.image.ioloading == null) { - this.image.ioloading = new ImageIOLoader(this.image, local); - this.image.ioloading.load(); - } - } else { - throw new FileNotFoundException("The file was changed"); - } - } - } catch (final IOException e) { - this.image.state = ImageState.ERROR; - this.image.advmsg = I18n.format("signpic.advmsg.ioerror", e); - } catch (final Exception e) { - this.image.state = ImageState.ERROR; - this.image.advmsg = I18n.format("signpic.advmsg.unknown", e); - } - } -} diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageLocation.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageLocation.java deleted file mode 100644 index e0ad8125..00000000 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageLocation.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.kamesuta.mc.signpic.image; - -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; - -import org.apache.commons.codec.digest.DigestUtils; - -public class ImageLocation { - public File localroot; - public ImageLocation(final File localroot) { - this.localroot = localroot; - } - - public URI remoteLocation(final Image image) throws URISyntaxException { - return new URI(image.id); - } - - public File localLocation(final Image image) { - return new File(this.localroot, DigestUtils.md5Hex(image.id)); - } -} diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageManager.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageManager.java deleted file mode 100644 index dc48c454..00000000 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageManager.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.kamesuta.mc.signpic.image; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.lwjgl.util.Timer; - -import com.kamesuta.mc.signpic.Client; -import com.kamesuta.mc.signpic.handler.CoreEvent; - -import cpw.mods.fml.common.gameevent.TickEvent; -import net.minecraft.util.ResourceLocation; - -public class ImageManager { - public static Deque lazyloadqueue = new ArrayDeque(); - public static final ExecutorService threadpool = Executors.newFixedThreadPool(3); - protected final HashMap pool = new HashMap(); - - public ImageLocation location; - - public ImageManager(final ImageLocation location) { - this.location = location; - } - - public Image get(final String id) { - if (id.startsWith("!")) { - return get(new ResourceLocation(id.substring(1))); - } else { - Image image = this.pool.get(id); - if (image == null) { - image = new RemoteImage(id, this.location); - this.pool.put(id, image); - } - image.onImageUsed(); - return image; - } - } - - public Image get(final ResourceLocation location) { - final String id = "!" + location.toString(); - Image image = this.pool.get(id); - if (image == null) { - image = new ResourceImage(location); - this.pool.put(id, image); - } - image.onImageUsed(); - return image; - } - - @CoreEvent - public void onRenderTick(final TickEvent.RenderTickEvent event) { - if (event.phase == TickEvent.Phase.END) { - Client.startSection("signpic-load"); - Image textureload; - if ((textureload = ImageManager.lazyloadqueue.peek()) != null) { - if (textureload.processTexture()) { - ImageManager.lazyloadqueue.poll(); - } - } - - for (final Iterator> itr = this.pool.entrySet().iterator(); itr.hasNext();) { - final Entry entry = itr.next(); - final Image image = entry.getValue(); - image.process(); - if (image.shouldCollect()) { - image.delete(); - itr.remove(); - } - } - - Timer.tick(); - Client.endSection(); - } - } -} diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageState.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageState.java deleted file mode 100644 index 9a6e0e85..00000000 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageState.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.kamesuta.mc.signpic.image; - -import static org.lwjgl.opengl.GL11.*; - -import com.kamesuta.mc.signpic.render.CustomTileEntitySignRenderer; -import com.kamesuta.mc.signpic.render.RenderHelper; -import com.kamesuta.mc.signpic.render.StateRender.Color; -import com.kamesuta.mc.signpic.render.StateRender.Speed; - -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.Tessellator; - -public enum ImageState { - INIT("signpic.state.init", Color.DEFAULT, Speed.WAIT), - INITALIZED("signpic.state.initalized", Color.DEFAULT, Speed.WAIT), - DOWNLOADING("signpic.state.downloading", Color.DOWNLOAD, Speed.RUN), - DOWNLOADED("signpic.state.downloaded", Color.DOWNLOAD, Speed.WAIT), - IOLOADING("signpic.state.ioloading", Color.IOLOAD, Speed.RUN), - IOLOADED("signpic.state.ioloaded", Color.IOLOAD, Speed.WAIT), - TEXTURELOADING("signpic.state.textureloading", Color.TEXTURELOAD, Speed.RUN), - TEXTURELOADED("signpic.state.textureloaded", Color.TEXTURELOAD, Speed.WAIT), - AVAILABLE("signpic.state.available", Color.DEFAULT, Speed.RUN) { - @Override - public void themeImage(final ImageManager manager, final Image image) {} - - @Override - public void mainImage(final ImageManager manager, final Image image) { - image.draw(); - } - - @Override - public void message(final ImageManager manager, final Image image, final FontRenderer fontrenderer) { - } - }, - FAILED("signpic.state.failed", Color.DEFAULT, Speed.WAIT) { - @Override - public void themeImage(final ImageManager manager, final Image image) { - RenderHelper.startTexture(); - glPushMatrix(); - glTranslatef(-.5f, -.5f, 0f); - manager.get(CustomTileEntitySignRenderer.resWarning).draw();; - glPopMatrix(); - } - }, - ERROR("signpic.state.error", Color.DEFAULT, Speed.WAIT) { - @Override - public void themeImage(final ImageManager manager, final Image image) { - RenderHelper.startTexture(); - glPushMatrix(); - glTranslatef(-.5f, -.5f, 0f); - manager.get(CustomTileEntitySignRenderer.resError).draw();; - glPopMatrix(); - } - }, - ; - - public final String msg; - protected final Color color; - protected final Speed speed; - ImageState(final String s, final Color color, final Speed speed) { - this.msg = s; - this.color = color; - this.speed = speed; - } - - public void themeImage(final ImageManager manager, final Image image) { - glLineWidth(3f); - RenderHelper.startShape(); - - glPushMatrix(); - glScalef(.5f, .5f, 1f); - - // Loading Circle - this.color.loadingColor(); - RenderHelper.drawLoadingCircle(this.speed.inner, this.speed.outer); - - // Design Circle - this.color.designColor(); - RenderHelper.drawDesignCircle(); - - // Progress Circle - this.color.progressColor(); - final float progress = image.getProgress(); - RenderHelper.drawProgressCircle(progress); - - glPopMatrix(); - } - - public void message(final ImageManager manager, final Image image, final FontRenderer fontrenderer) { - RenderHelper.startTexture(); - final float f1 = 0.6666667F; - float f3 = 0.06666668F * f1; - glTranslatef(0f, 1f, 0f); - glPushMatrix(); - glScalef(f3, f3, 1f); - final String msg1 = image.getStatusMessage(); - fontrenderer.drawStringWithShadow(msg1, -fontrenderer.getStringWidth(msg1) / 2, -fontrenderer.FONT_HEIGHT, 0xffffff); - glPopMatrix(); - f3 = 0.036666668F * f1; - glPushMatrix(); - glScalef(f3, f3, 1f); - final String msg2 = image.getId(); - fontrenderer.drawStringWithShadow(msg2, -fontrenderer.getStringWidth(msg2) / 2, 0, 0xffffff); - glPopMatrix(); - final String msg3 = image.advMessage(); - if (msg3 != null) { - glPushMatrix(); - glScalef(f3, f3, 1f); - fontrenderer.drawStringWithShadow(msg3, -fontrenderer.getStringWidth(msg3) / 2, fontrenderer.FONT_HEIGHT, 0xffffff); - glPopMatrix(); - } - } - - public void mainImage(final ImageManager manager, final Image image) { - final Tessellator t = Tessellator.instance; - RenderHelper.startShape(); - glLineWidth(1f); - glColor4f(1.0F, 0.0F, 0.0F, 1.0F); - t.startDrawing(GL_LINE_LOOP); - t.addVertex(0, 0, 0); - t.addVertex(0, 1, 0); - t.addVertex(1, 1, 0); - t.addVertex(1, 0, 0); - t.draw(); - } -} diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ImageTextures.java b/src/main/java/com/kamesuta/mc/signpic/image/ImageTextures.java index 07c59368..6e244079 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/ImageTextures.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/ImageTextures.java @@ -21,7 +21,7 @@ public IImageTexture get() { } else if (this.textures.size()>1) { final ImageTexture texture = this.textures.get(this.currenttexture).load(); if(this.timer.getTime() > texture.delay){ - this.timer.reset();; + this.timer.reset(); this.currenttexture = (this.currenttexture texs = this.texture.getAll(); - if (this.processing < texs.size()) { - final ImageTexture tex = texs.get(this.processing); - tex.load(); - this.processing++; - return false; - } else { - this.state = ImageState.TEXTURELOADED; - return true; - } - } else { - Reference.logger.warn("Image#loadTexture only must be called TEXTURELOADING phase"); - return true; - } - } - - protected void complete() { - this.state = ImageState.AVAILABLE; + public void onInit() { + ContentManager.instance.asyncqueue.offer(this); } @Override - public void process() { - switch(this.state) { - case INIT: - init(); - break; - case INITALIZED: - load(); - break; - case IOLOADED: - textureload(); - break; - case TEXTURELOADED: - complete(); - break; - default: - break; + public void onAsyncProcess() { + try { + new ContentDownloader(this.content, Client.location).onAsyncProcess(); + this.texture = new ImageIOLoader(this.content, Client.location).load(); + ContentManager.instance.divisionqueue.offer(this); + } catch (final URISyntaxException e) { + this.content.state.setType(ContentStateType.ERROR); + this.content.state.setMessage(I18n.format("signpic.advmsg.invalidurl")); + } catch (final InvaildImageException e) { + this.content.state.setType(ContentStateType.ERROR); + this.content.state.setMessage(I18n.format("signpic.advmsg.invalidimage")); + } catch (final IOException e) { + this.content.state.setType(ContentStateType.ERROR); + this.content.state.setMessage(I18n.format("signpic.advmsg.ioerror", e)); + } catch (final Exception e) { + this.content.state.setType(ContentStateType.ERROR); + this.content.state.setMessage(I18n.format("signpic.advmsg.unknown", e)); } } @Override - public boolean shouldCollect() { - return this.lastloaded.getTime() > ImageGarbageCollection; + public boolean onDivisionProcess() { + final List texs = this.texture.getAll(); + if (this.processing < (this.content.state.progress.overall = texs.size())) { + final ImageTexture tex = texs.get(this.processing); + tex.load(); + this.processing++; + this.content.state.setType(ContentStateType.LOADING); + this.content.state.progress.done = this.processing; + return false; + } else { + this.content.state.setType(ContentStateType.AVAILABLE); + this.content.state.progress.done = this.content.state.progress.overall; + return true; + } } @Override - public void delete() { + public void onCollect() { if (this.texture!=null) this.texture.delete(); } - @Override - public float getProgress() { - switch(this.state) { - case AVAILABLE: - case DOWNLOADED: - case IOLOADED: - case TEXTURELOADED: - return 1f; - case DOWNLOADING: - if (this.downloading != null) - return this.downloading.getProgress(); - case IOLOADING: - if (this.ioloading != null) - return this.ioloading.getProgress(); - case TEXTURELOADING: - if (this.texture != null && !this.texture.getAll().isEmpty()) - return (float)this.processing / this.texture.getAll().size(); - default: - return 0; - } - } - @Override public IImageTexture getTexture() throws IllegalStateException { return getTextures().get(); } public ImageTextures getTextures() { - if (this.state == ImageState.AVAILABLE) + if (this.content.state.getType() == ContentStateType.AVAILABLE) return this.texture; else throw new IllegalStateException("Not Available"); } - @Override - public void onImageUsed() { - this.lastloaded.set(0); - } - - @Override - public String advMessage() { - return this.advmsg; - } - @Override public String getLocal() { if (this.local != null) - return "File:"+this.local.getName(); + return "File:" + this.local.getName(); else return "None"; } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof RemoteImage)) - return false; - final Image other = (Image) obj; - if (this.id == null) { - if (other.id != null) - return false; - } else if (!this.id.equals(other.id)) - return false; - return true; - } - @Override public String toString() { - return String.format("RemoteImage[%s]", this.id); + return String.format("RemoteImage[%s]", this.content.id); } } diff --git a/src/main/java/com/kamesuta/mc/signpic/image/ResourceImage.java b/src/main/java/com/kamesuta/mc/signpic/image/ResourceImage.java index 2b4431a6..6b1da11f 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/ResourceImage.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/ResourceImage.java @@ -1,64 +1,52 @@ package com.kamesuta.mc.signpic.image; +import org.apache.commons.lang3.StringUtils; + +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentStateType; + import net.minecraft.util.ResourceLocation; public class ResourceImage extends Image { - protected McImageTexture texture; - protected ResourceLocation location; + protected ResourceLocation resource; + protected ResourceImageTexture texture; - public ResourceImage(final ResourceLocation location) { - super("!" + location.toString()); - this.location = location; - this.texture = new McImageTexture(location); - this.state = ImageState.AVAILABLE; + public ResourceImage(final Content content) { + super(content); + this.resource = content.id.getResource(); + this.texture = new ResourceImageTexture(this.resource); } @Override - public void process() { + public String toString() { + return String.format("ResourceImage[%s]", this.content.id); } @Override - public float getProgress() { - return 1f; + public String getLocal() { + return "Resource:" + StringUtils.substring(this.content.id.id(), 1); } @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((this.id == null) ? 0 : this.id.hashCode()); - return result; + public IImageTexture getTexture() { + return this.texture; } @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof RemoteImage)) - return false; - final Image other = (Image) obj; - if (this.id == null) { - if (other.id != null) - return false; - } else if (!this.id.equals(other.id)) - return false; - return true; + public void onInit() { + this.content.state.setType(ContentStateType.AVAILABLE); } @Override - public String toString() { - return String.format("ResourceImage[%s]", this.id); + public void onAsyncProcess() { } @Override - public String getLocal() { - return "Resource:" + this.location; + public boolean onDivisionProcess() { + return true; } @Override - public IImageTexture getTexture() { - return this.texture; + public void onCollect() { } } diff --git a/src/main/java/com/kamesuta/mc/signpic/image/McImageTexture.java b/src/main/java/com/kamesuta/mc/signpic/image/ResourceImageTexture.java similarity index 84% rename from src/main/java/com/kamesuta/mc/signpic/image/McImageTexture.java rename to src/main/java/com/kamesuta/mc/signpic/image/ResourceImageTexture.java index f121a88e..f164d134 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/McImageTexture.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/ResourceImageTexture.java @@ -8,12 +8,12 @@ import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.util.ResourceLocation; -public class McImageTexture implements IImageTexture { +public class ResourceImageTexture implements IImageTexture { protected static final ResourceLocation Null = Client.mc.renderEngine.getDynamicTextureLocation("null", TextureUtil.missingTexture); protected static final ImageSize DefaultSize = new ImageSize().defaultSize(); protected ResourceLocation location; - public McImageTexture(final ResourceLocation location) { + public ResourceImageTexture(final ResourceLocation location) { this.location = location; } diff --git a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageMeta.java b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageMeta.java index d26e3a31..51d93f0a 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageMeta.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageMeta.java @@ -51,13 +51,33 @@ public String toString() { return compose(); } - public static interface MetaParser { - DecimalFormat signformat = new DecimalFormat("0.#"); + public static abstract class MetaParser { + private static final DecimalFormat signformat = new DecimalFormat(".##"); - MetaParser parse(String src, String key, String value); + public static String format(final float f) { + if (f == 0) + return "0"; - MetaParser reset(); + final String str = signformat.format(f); - String compose(); + final String cut = ".0"; + + int end = str.length(); + int last = cut.length(); + + while (end != 0 && last != 0) { + if (cut.charAt(last - 1) == str.charAt(end - 1)) + end--; + else + last--; + } + return str.substring(0, end); + } + + public abstract MetaParser parse(String src, String key, String value); + + public abstract MetaParser reset(); + + public abstract String compose(); } } diff --git a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageOffset.java b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageOffset.java index d8012da4..360352fc 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageOffset.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageOffset.java @@ -3,7 +3,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; -public class ImageOffset implements ImageMeta.MetaParser { +public class ImageOffset extends ImageMeta.MetaParser { public static final float defaultOffset = 0.5f; public float x; @@ -51,25 +51,25 @@ public String compose() { final StringBuilder stb = new StringBuilder(); if (this.x!=0) if (this.x<0) - if (-this.x==defaultOffset) stb.append("L"); - else stb.append("L").append(signformat.format(this.x)); + if (this.x==-defaultOffset) stb.append("L"); + else stb.append("L").append(format(-this.x)); else if (this.x==defaultOffset) stb.append("R"); - else stb.append("R").append(signformat.format(-this.x)); + else stb.append("R").append(format(this.x)); if (this.y!=0) if (this.y<0) - if (-this.y==defaultOffset) stb.append("D"); - else stb.append("D").append(signformat.format(this.y)); + if (this.y==-defaultOffset) stb.append("D"); + else stb.append("D").append(format(-this.y)); else if (this.y==defaultOffset) stb.append("U"); - else stb.append("U").append(signformat.format(-this.y)); + else stb.append("U").append(format(this.y)); if (this.z!=0) if (this.z<0) - if (-this.z==defaultOffset) stb.append("B"); - else stb.append("B").append(signformat.format(this.z)); + if (this.z==-defaultOffset) stb.append("B"); + else stb.append("B").append(format(-this.z)); else if (this.z==defaultOffset) stb.append("F"); - else stb.append("F").append(signformat.format(-this.z)); + else stb.append("F").append(format(this.z)); return stb.toString(); } diff --git a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageRotation.java b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageRotation.java index 1fd5267f..6fbd1190 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageRotation.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageRotation.java @@ -9,7 +9,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; -public class ImageRotation implements ImageMeta.MetaParser { +public class ImageRotation extends ImageMeta.MetaParser { public static final float defaultOffset = 4f; public final List rotates = new LinkedList(); @@ -60,10 +60,13 @@ public void rotate() { } public String compose() { - if (this.rotate == defaultOffset) + final float rotate = ((this.rotate%8)+8)%8; + if (rotate == 0) + return ""; + else if (rotate == defaultOffset) return this.type.name(); else - return this.type.name() + signformat.format(this.rotate); + return this.type.name() + format(rotate); } } diff --git a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageSize.java b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageSize.java index 14d762c8..a10e1d81 100644 --- a/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageSize.java +++ b/src/main/java/com/kamesuta/mc/signpic/image/meta/ImageSize.java @@ -5,7 +5,7 @@ import com.kamesuta.mc.bnnwidget.position.Area; -public class ImageSize implements Cloneable, ImageMeta.MetaParser { +public class ImageSize extends ImageMeta.MetaParser implements Cloneable { public static final float defaultSize = 1f; public static final float unknownSize = Float.NaN; @@ -101,6 +101,12 @@ public ImageSize setSize(final ImageSizes s, final ImageSize raw, final ImageSiz return setSize(s, raw.width, raw.height, max.width, max.height); } + public ImageSize scale(final float scale) { + this.width *= scale; + this.height *= scale; + return this; + } + @Override public ImageSize reset() { return unknownSize(); @@ -117,7 +123,7 @@ else if (StringUtils.equals(key, "x")) @Override public String compose() { - return (vaildWidth() ? signformat.format(this.width) : "") + (vaildHeight() ? "x" + signformat.format(this.height) : ""); + return (vaildWidth() ? format(this.width) : "") + (vaildHeight() ? "x" + format(this.height) : ""); } @Override diff --git a/src/main/java/com/kamesuta/mc/signpic/mode/CurrentMode.java b/src/main/java/com/kamesuta/mc/signpic/mode/CurrentMode.java index 3d351765..4b5448e5 100644 --- a/src/main/java/com/kamesuta/mc/signpic/mode/CurrentMode.java +++ b/src/main/java/com/kamesuta/mc/signpic/mode/CurrentMode.java @@ -2,6 +2,7 @@ import java.util.EnumSet; +import com.kamesuta.mc.signpic.entry.EntryId; import com.kamesuta.mc.signpic.util.Sign; public class CurrentMode { @@ -10,7 +11,7 @@ public class CurrentMode { private CurrentMode() { } - private Sign sign = new Sign(); + private EntryId entryId = new EntryId(""); private Mode mode = Mode.NONE; private final EnumSet states = EnumSet.noneOf(State.class); @@ -49,12 +50,13 @@ public boolean isState(final State state) { return this.states.contains(state); } - public void setSign(final Sign sign) { - this.sign = sign; + public void setEntryId(final EntryId sign) { + this.entryId = sign; + Sign.updatePreview(sign); } - public Sign getSign() { - return this.sign; + public EntryId getEntryId() { + return this.entryId; } public static enum Mode { diff --git a/src/main/java/com/kamesuta/mc/signpic/proxy/ClientProxy.java b/src/main/java/com/kamesuta/mc/signpic/proxy/ClientProxy.java index 75b1de36..f2b602b6 100644 --- a/src/main/java/com/kamesuta/mc/signpic/proxy/ClientProxy.java +++ b/src/main/java/com/kamesuta/mc/signpic/proxy/ClientProxy.java @@ -7,9 +7,8 @@ import com.kamesuta.mc.bnnwidget.StencilClip; import com.kamesuta.mc.signpic.Client; import com.kamesuta.mc.signpic.Reference; +import com.kamesuta.mc.signpic.entry.content.ContentLocation; import com.kamesuta.mc.signpic.handler.CoreHandler; -import com.kamesuta.mc.signpic.image.ImageLocation; -import com.kamesuta.mc.signpic.image.ImageManager; import com.kamesuta.mc.signpic.information.CommandDownloadLatest; import com.kamesuta.mc.signpic.render.CustomTileEntitySignRenderer; import com.mojang.util.UUIDTypeAdapter; @@ -50,9 +49,7 @@ public void preInit(final FMLPreInitializationEvent event) { } // Setup image - final ImageManager manager = new ImageManager(new ImageLocation(cachedir)); - Client.manager = manager; - Client.renderer = new CustomTileEntitySignRenderer(manager); + Client.renderer = new CustomTileEntitySignRenderer(); Client.mcversion = MinecraftForge.MC_VERSION; Client.forgeversion = ForgeVersion.getVersion(); @@ -66,6 +63,8 @@ public void preInit(final FMLPreInitializationEvent event) { Client.modDir = new File(mcdir, "mods"); Client.modFile = event.getSourceFile(); + Client.location = new ContentLocation(Client.signpicCacheDir); + // Get Id final String id = Client.mc.getSession().getPlayerID(); try { diff --git a/src/main/java/com/kamesuta/mc/signpic/render/CustomTileEntitySignRenderer.java b/src/main/java/com/kamesuta/mc/signpic/render/CustomTileEntitySignRenderer.java index 3081b4c5..b4d4af27 100644 --- a/src/main/java/com/kamesuta/mc/signpic/render/CustomTileEntitySignRenderer.java +++ b/src/main/java/com/kamesuta/mc/signpic/render/CustomTileEntitySignRenderer.java @@ -3,11 +3,12 @@ import static org.lwjgl.opengl.GL11.*; import com.kamesuta.mc.signpic.Client; -import com.kamesuta.mc.signpic.image.Image; -import com.kamesuta.mc.signpic.image.ImageManager; +import com.kamesuta.mc.signpic.entry.Entry; +import com.kamesuta.mc.signpic.entry.EntryId; +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentStateType; import com.kamesuta.mc.signpic.image.meta.ImageSize; import com.kamesuta.mc.signpic.mode.CurrentMode; -import com.kamesuta.mc.signpic.util.Sign; import net.minecraft.block.Block; import net.minecraft.client.renderer.Tessellator; @@ -19,34 +20,82 @@ public class CustomTileEntitySignRenderer extends TileEntitySignRenderer { - protected final ImageManager manager; protected final Tessellator t = Tessellator.instance; - public static final ResourceLocation resWarning = new ResourceLocation("signpic", "textures/state/warning.png"); public static final ResourceLocation resError = new ResourceLocation("signpic", "textures/state/error.png"); - public CustomTileEntitySignRenderer(final ImageManager manager) { - this.manager = manager; + public CustomTileEntitySignRenderer() {} + + public void renderImage(final Content content, final ImageSize size, final float opacity) { + glPushMatrix(); + glScalef(size.width, size.height, 1f); + if (content.state.getType() == ContentStateType.AVAILABLE) { + glColor4f(1.0F, 1.0F, 1.0F, opacity * 1.0F); + content.image.draw(); + } else { + final Tessellator t = Tessellator.instance; + RenderHelper.startShape(); + glLineWidth(1f); + glColor4f(1.0F, 0.0F, 0.0F, opacity * 1.0F); + t.startDrawing(GL_LINE_LOOP); + t.addVertex(0, 0, 0); + t.addVertex(0, 1, 0); + t.addVertex(1, 1, 0); + t.addVertex(1, 0, 0); + t.draw(); + } + glPopMatrix(); + + if (size.width<1.5f || size.height<1.5) { + glScalef(.5f, .5f, .5f); + glTranslatef(size.width/2, size.height/4, 0); + } + glTranslatef(size.width/2, size.height/2, 0); + glScalef(.5f, .5f, 1f); + if (content.state.getType() != ContentStateType.AVAILABLE) { + if (content.state.getType() == ContentStateType.ERROR) { + RenderHelper.startShape(); + glPushMatrix(); + glTranslatef(-.5f, -.5f, 0f); + RenderHelper.startTexture(); + bindTexture(resError); + RenderHelper.drawRectTexture(GL_QUADS); + glPopMatrix(); + } + StateRender.drawLoading(content.state.progress, content.state.getType().circle, content.state.getType().speed); + StateRender.drawMessage(content, func_147498_b()); + } } - @Override - public void renderTileEntityAt(final TileEntitySign tile, final double x, final double y, final double z, final float partialTicks) - { - Client.startSection("signpic-render"); - final Sign sign = new Sign().parseSignEntity(tile); - if (sign.isVaild()) { + public void renderSignPicture(final Entry entry, final float opacity) { + // Load Image + final Content content = entry.content(); + + // Size + final ImageSize size = new ImageSize().setAspectSize(entry.meta.size, content.image.getSize()); + + glPushMatrix(); + + glTranslatef(entry.meta.offset.x, entry.meta.offset.y, entry.meta.offset.z); + entry.meta.rotation.rotate(); + + glTranslatef(-size.width/2, size.height + ((size.height>=0)?0:-size.height)-.5f, 0f); + glScalef(1f, -1f, 1f); + + renderImage(content, size, opacity); + + glPopMatrix(); + } + + public void renderSignPictureBase(final TileEntitySign tile, final double x, final double y, final double z, final float partialTicks, final float opacity) { + final Entry entry = EntryId.fromTile(tile).entry(); + if (entry.isValid()) { if (CurrentMode.instance.isState(CurrentMode.State.SEE)) { RenderHelper.startTexture(); - glColor4f(1f, 1f, 1f, .5f); + glColor4f(1f, 1f, 1f, opacity * .5f); super.renderTileEntityAt(tile, x, y, z, partialTicks); } - // Load Image - final Image image = this.manager.get(sign.getURL()); - - // Size - final ImageSize size = new ImageSize().setAspectSize(sign.meta.size, image.getSize()); - // Vanilla Translate final Block block = tile.getBlockType(); glPushMatrix(); @@ -73,37 +122,27 @@ public void renderTileEntityAt(final TileEntitySign tile, final double x, final // Draw Canvas glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); - glPushMatrix(); - - glTranslatef(sign.meta.offset.x, sign.meta.offset.y, sign.meta.offset.z); - sign.meta.rotation.rotate(); - - glTranslatef(-size.width/2, size.height + ((size.height>=0)?0:-size.height)-.5f, 0f); - glScalef(1f, -1f, 1f); - glPushMatrix(); - glScalef(size.width, size.height, 1f); - image.getState().mainImage(this.manager, image); - glPopMatrix(); - - if (size.width<1.5f || size.height<1.5) { - glScalef(.5f, .5f, .5f); - glTranslatef(size.width/2, size.height/4, 0); - } - glTranslatef(size.width/2, size.height/2, 0); - glScalef(.5f, .5f, 1f); - image.getState().themeImage(this.manager, image); - image.getState().message(this.manager, image, func_147498_b()); - - glPopMatrix(); + renderSignPicture(entry, opacity); glEnable(GL_LIGHTING); glEnable(GL_CULL_FACE); glPopMatrix(); } else { + if (opacity < 1f) { + RenderHelper.startTexture(); + glColor4f(1f, 1f, 1f, opacity); + } super.renderTileEntityAt(tile, x, y, z, partialTicks); } + } + + @Override + public void renderTileEntityAt(final TileEntitySign tile, final double x, final double y, final double z, final float partialTicks) + { + Client.startSection("signpic-render"); + renderSignPictureBase(tile, x, y, z, partialTicks, 1f); Client.endSection(); } diff --git a/src/main/java/com/kamesuta/mc/signpic/render/RenderHelper.java b/src/main/java/com/kamesuta/mc/signpic/render/RenderHelper.java index 751f5ae0..8f2a85ac 100644 --- a/src/main/java/com/kamesuta/mc/signpic/render/RenderHelper.java +++ b/src/main/java/com/kamesuta/mc/signpic/render/RenderHelper.java @@ -7,6 +7,39 @@ public class RenderHelper { protected static final Tessellator t = Tessellator.instance; + public static void drawLoadingCircle(final int msPerRoundInner, final int msPerRoundOuter) { + final long time = System.currentTimeMillis(); + final float time1 = time % Math.abs(msPerRoundOuter) / (float)msPerRoundOuter; + t.startDrawing(GL_LINE_LOOP); + addCircleVertex(time1, time1+0.2f, 1.07f); + addCircleVertex(time1+0.2f, time1, 1.09f); + t.draw(); + final float time2 = time % Math.abs(msPerRoundInner) / (float)msPerRoundInner; + t.startDrawing(GL_LINE_LOOP); + addCircleVertex(time2, time2+0.1f, 1.03f); + addCircleVertex(time2+0.1f, time2, 1.05f); + t.draw(); + } + + public static void drawDesignCircle() { + t.startDrawing(GL_LINE_LOOP); + addCircleVertex(0f, 1f, 1f); + t.draw(); + } + + public static void drawProgressCircle(final float progress) { + t.startDrawing(GL_POLYGON); + t.addVertex(0f, 0f, 0f); + addCircleVertex(progress, 0f, 1f); + t.draw(); + } + + public static void drawProgressCircle(final int mode, final float r) { + t.startDrawing(mode); + addCircleVertex(0f, 1f, r); + t.draw(); + } + public static void addCircleVertex(final float start, final float end, final float r, final float acc) { final double sangle = Math.PI*(2d*start-.5); final double sx = Math.cos(sangle); @@ -29,40 +62,40 @@ public static void addCircleVertex(final float start, final float end, final flo addCircleVertex(start, end, r, 32f); } - public static void addRectVertex(final float x1, final float y1, final float x2, final float y2) { - t.addVertex(x1, y2, 0.0D); - t.addVertex(x2, y2, 0.0D); - t.addVertex(x2, y1, 0.0D); - t.addVertex(x1, y1, 0.0D); + public static void drawRect(final int mode) { + drawRect(mode, 0, 0, 1, 1); } - public static void drawLoadingCircle(final int msPerRoundInner, final int msPerRoundOuter) { - final long time = System.currentTimeMillis(); - final float time1 = time % Math.abs(msPerRoundOuter) / (float)msPerRoundOuter; - t.startDrawing(GL_LINE_LOOP); - addCircleVertex(time1, time1+0.2f, 1.07f); - addCircleVertex(time1+0.2f, time1, 1.09f); - t.draw(); - final float time2 = time % Math.abs(msPerRoundInner) / (float)msPerRoundInner; - t.startDrawing(GL_LINE_LOOP); - addCircleVertex(time2, time2+0.1f, 1.03f); - addCircleVertex(time2+0.1f, time2, 1.05f); + public static void drawRect(final int mode, final float x1, final float y1, final float x2, final float y2) { + t.startDrawing(mode); + addRectVertex(x1, y1, x2, y2); t.draw(); } - public static void drawDesignCircle() { - t.startDrawing(GL_LINE_LOOP); - addCircleVertex(0f, 1f, 1f); - t.draw(); + public static void addRectVertex(final float x1, final float y1, final float x2, final float y2) { + t.addVertex(x1, y2, 0); + t.addVertex(x2, y2, 0); + t.addVertex(x2, y1, 0); + t.addVertex(x1, y1, 0); } - public static void drawProgressCircle(final float progress) { - t.startDrawing(GL_POLYGON); - t.addVertex(0f, 0f, 0f); - addCircleVertex(progress, 0f, 1f); + public static void drawRectTexture(final int mode) { + drawRectTexture(mode, 0, 0, 1, 1, 0, 0, 1, 1); + } + + public static void drawRectTexture(final int mode, final float x1, final float y1, final float x2, final float y2, final float u1, final float v1, final float u2, final float v2) { + t.startDrawing(mode); + addRectVertexTexture(x1, y1, x2, y2, u1, v1, u2, v2); t.draw(); } + public static void addRectVertexTexture(final float x1, final float y1, final float x2, final float y2, final float u1, final float v1, final float u2, final float v2) { + t.addVertexWithUV(x1, y2, 0, u1, v2); + t.addVertexWithUV(x2, y2, 0, u2, v2); + t.addVertexWithUV(x2, y1, 0, u2, v1); + t.addVertexWithUV(x1, y1, 0, u1, v1); + } + public static void startTexture() { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); diff --git a/src/main/java/com/kamesuta/mc/signpic/render/SignPicRender.java b/src/main/java/com/kamesuta/mc/signpic/render/SignPicRender.java index 4e083638..94fd575d 100644 --- a/src/main/java/com/kamesuta/mc/signpic/render/SignPicRender.java +++ b/src/main/java/com/kamesuta/mc/signpic/render/SignPicRender.java @@ -4,9 +4,10 @@ import com.kamesuta.mc.bnnwidget.WGui; import com.kamesuta.mc.signpic.Client; +import com.kamesuta.mc.signpic.entry.Entry; +import com.kamesuta.mc.signpic.entry.EntryId; +import com.kamesuta.mc.signpic.entry.content.Content; import com.kamesuta.mc.signpic.handler.CoreEvent; -import com.kamesuta.mc.signpic.image.Image; -import com.kamesuta.mc.signpic.image.ImageManager; import com.kamesuta.mc.signpic.image.meta.ImageSize; import com.kamesuta.mc.signpic.mode.CurrentMode; import com.kamesuta.mc.signpic.util.Sign; @@ -23,20 +24,20 @@ public class SignPicRender extends WGui { public static final ResourceLocation resSign = new ResourceLocation("textures/items/sign.png"); - protected final ImageManager manager; - - public SignPicRender(final ImageManager manager) { - this.manager = manager; + public SignPicRender() { } @CoreEvent public void onRender(final RenderWorldLastEvent event) { - if (CurrentMode.instance.isMode(CurrentMode.Mode.SETPREVIEW)) - CurrentMode.instance.getSign().preview.capturePlace(); + float opacity = 0.7f; + if (CurrentMode.instance.isMode(CurrentMode.Mode.SETPREVIEW)) { + Sign.preview.capturePlace(); + opacity *= 0.7f; + } if (CurrentMode.instance.isState(CurrentMode.State.PREVIEW)) { - if (CurrentMode.instance.getSign().preview.isRenderable() && CurrentMode.instance.getSign().preview.isVisible()) { - final TileEntitySign tile = CurrentMode.instance.getSign().updatePreview().preview.getRenderTileEntity(); - Client.renderer.renderTileEntityAt(tile, tile.xCoord - TileEntityRendererDispatcher.staticPlayerX, tile.yCoord - TileEntityRendererDispatcher.staticPlayerY, tile.zCoord - TileEntityRendererDispatcher.staticPlayerZ, event.partialTicks); + if (Sign.preview.isRenderable() && Sign.preview.isVisible()) { + final TileEntitySign tile = Sign.preview.getRenderTileEntity(); + Client.renderer.renderSignPictureBase(tile, tile.xCoord - TileEntityRendererDispatcher.staticPlayerX, tile.yCoord - TileEntityRendererDispatcher.staticPlayerY, tile.zCoord - TileEntityRendererDispatcher.staticPlayerZ, event.partialTicks, opacity); } } } @@ -55,7 +56,12 @@ public void onDraw(final RenderGameOverlayEvent.Post event) { glPushMatrix(); glScalef(fontrenderer.FONT_HEIGHT, fontrenderer.FONT_HEIGHT, 1f); - this.manager.get(resSign).draw(); + glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + + texture().bindTexture(resSign); + RenderHelper.startTexture(); + RenderHelper.drawRectTexture(GL_QUADS); + glPopMatrix(); glTranslatef(fontrenderer.FONT_HEIGHT, 0f, 0f); @@ -72,25 +78,25 @@ public void onText(final RenderGameOverlayEvent.Text event) { if (Client.mc.gameSettings.showDebugInfo) { final TileEntitySign tilesign = Client.getTileSignLooking(); if (tilesign != null) { - final Sign sign = new Sign().parseSignEntity(tilesign); - if (sign.isVaild()) { - final String id = sign.getURL(); - final ImageSize signsize = sign.meta.size; - final Image image = this.manager.get(id); - final ImageSize imagesize = image.getSize(); - final ImageSize viewsize = new ImageSize().setAspectSize(sign.meta.size, imagesize); - final String advmsg = image.advMessage(); + final Entry entry = EntryId.fromTile(tilesign).entry(); + if (entry.isValid()) { + final String uri = entry.contentId.getURI(); + final ImageSize signsize = entry.meta.size; + final Content content = entry.content(); + final ImageSize imagesize = content.image.getSize(); + final ImageSize viewsize = new ImageSize().setAspectSize(entry.meta.size, imagesize); + final String advmsg = content.state.getMessage(); event.left.add(""); - event.left.add(I18n.format("signpic.over.sign", sign.text())); - event.left.add(I18n.format("signpic.over.id", id)); + event.left.add(I18n.format("signpic.over.sign", entry.id.id())); + event.left.add(I18n.format("signpic.over.id", uri)); event.left.add(I18n.format("signpic.over.size", signsize, signsize.width, signsize.height, imagesize.width, imagesize.height, viewsize.width, viewsize.height)); - event.left.add(I18n.format("signpic.over.status", image.getStatusMessage())); + event.left.add(I18n.format("signpic.over.status", content.state.getStateMessage())); if (advmsg != null) event.left.add(I18n.format("signpic.over.advmsg", advmsg)); if (tilesign.signText != null) event.left.add(I18n.format("signpic.over.raw", tilesign.signText[0], tilesign.signText[1], tilesign.signText[2], tilesign.signText[3])); - event.left.add(I18n.format("signpic.over.local", image.getLocal())); + event.left.add(I18n.format("signpic.over.local", content.image.getLocal())); } } } diff --git a/src/main/java/com/kamesuta/mc/signpic/render/StateRender.java b/src/main/java/com/kamesuta/mc/signpic/render/StateRender.java index e17c890c..94c20108 100644 --- a/src/main/java/com/kamesuta/mc/signpic/render/StateRender.java +++ b/src/main/java/com/kamesuta/mc/signpic/render/StateRender.java @@ -2,66 +2,108 @@ import static org.lwjgl.opengl.GL11.*; +import org.lwjgl.util.Color; + +import com.kamesuta.mc.signpic.entry.content.Content; +import com.kamesuta.mc.signpic.entry.content.ContentState.Progress; + +import net.minecraft.client.gui.FontRenderer; + public class StateRender { - public static enum Color { - DOWNLOAD { - @Override - public void progressColor() { - glColor4f(0f/256f, 102f/256f, 204f/256f, 1f); - } - - @Override - public void designColor() { - glColor4f(23f/256f, 121f/256f, 232f/256f, 1f); - } - }, - IOLOAD { - @Override - public void progressColor() { - glColor4f(0f/256f, 144f/256f, 55f/256f, 1f); - } - - @Override - public void designColor() { - glColor4f(23f/256f, 177f/256f, 55f/256f, 1f); - } - }, - TEXTURELOAD { - @Override - public void progressColor() { - glColor4f(238f/256f, 97f/256f, 35f/256f, 1f); - } - - @Override - public void designColor() { - glColor4f(238f/256f, 134f/256f, 35f/256f, 1f); - } - }, - DEFAULT + public static enum LoadingCircle { + INIT(new Color(0, 255, 255, 255), new Color(160, 160, 160, 255), new Color(120, 120, 120, 255)), + DOWNLOAD(new Color(0, 255, 255, 255), new Color(0, 102, 204, 255), new Color(23, 121, 232, 255)), + CONTENTLOAD(new Color(0, 255, 255, 255), new Color(0, 144, 55), new Color(23, 177, 55, 255)), + DEFAULT(new Color(), new Color(), new Color()) ; + private final Color loading; + private final Color progress; + private final Color design; + private LoadingCircle(final Color loading, final Color progress, final Color design) { + this.loading = loading; + this.progress = progress; + this.design = design; + } + public void loadingColor() { - glColor4f(0.0F, 1.0F, 1.0F, 1.0F); + color(this.loading); } public void progressColor() { - glColor4f(160/256f, 160f/256f, 160f/256f, 1f); + color(this.progress); } public void designColor() { - glColor4f(120/256f, 120f/256f, 120f/256f, 1f); + color(this.design); + } + + private static void color(final Color color) { + glColor4ub(color.getRedByte(), color.getGreenByte(), color.getBlueByte(), color.getAlphaByte()); + } + } + + + public static void drawLoading(final Progress progress, final LoadingCircle type, final LoadingCircleType speed) { + if (type != LoadingCircle.DEFAULT) { + glLineWidth(3f); + RenderHelper.startShape(); + + glPushMatrix(); + glScalef(.5f, .5f, 1f); + + // Loading Circle + type.loadingColor(); + RenderHelper.drawLoadingCircle(speed.inner, speed.outer); + + // Design Circle + type.designColor(); + RenderHelper.drawDesignCircle(); + + // Progress Circle + type.progressColor(); + final float p = progress.getProgress(); + RenderHelper.drawProgressCircle(p); + + glPopMatrix(); + } + } + + public static void drawMessage(final Content content, final FontRenderer fontrenderer) { + RenderHelper.startTexture(); + final float f1 = 0.6666667F; + float f3 = 0.06666668F * f1; + glTranslatef(0f, 1f, 0f); + glPushMatrix(); + glScalef(f3, f3, 1f); + final String msg1 = content.state.getStateMessage(); + fontrenderer.drawStringWithShadow(msg1, -fontrenderer.getStringWidth(msg1) / 2, -fontrenderer.FONT_HEIGHT, 0xffffff); + glPopMatrix(); + f3 = 0.036666668F * f1; + glPushMatrix(); + glScalef(f3, f3, 1f); + final String msg2 = content.id.id(); + fontrenderer.drawStringWithShadow(msg2, -fontrenderer.getStringWidth(msg2) / 2, 0, 0xffffff); + glPopMatrix(); + final String msg3 = content.state.getMessage(); + if (msg3 != null) { + glPushMatrix(); + glScalef(f3, f3, 1f); + fontrenderer.drawStringWithShadow(msg3, -fontrenderer.getStringWidth(msg3) / 2, fontrenderer.FONT_HEIGHT, 0xffffff); + glPopMatrix(); } } - public static enum Speed { + public static enum LoadingCircleType { WAIT(627*-2, 893*-2), RUN(627, 893), + DEFAULT(-1, -1), ; public final int inner; public final int outer; - Speed(final int inner, final int outer) { + LoadingCircleType(final int inner, final int outer) { this.inner = inner; this.outer = outer; } diff --git a/src/main/java/com/kamesuta/mc/signpic/util/Sign.java b/src/main/java/com/kamesuta/mc/signpic/util/Sign.java index 6b77cbaf..577e3034 100644 --- a/src/main/java/com/kamesuta/mc/signpic/util/Sign.java +++ b/src/main/java/com/kamesuta/mc/signpic/util/Sign.java @@ -3,7 +3,8 @@ import org.apache.commons.lang3.StringUtils; import com.kamesuta.mc.signpic.Client; -import com.kamesuta.mc.signpic.image.meta.ImageMeta; +import com.kamesuta.mc.signpic.entry.EntryId; +import com.kamesuta.mc.signpic.entry.EntryIdBuilder; import com.kamesuta.mc.signpic.preview.SignEntity; import net.minecraft.client.network.NetHandlerPlayClient; @@ -13,109 +14,23 @@ public class Sign { public static int maxText = 15*4; - public final SignEntity preview = new SignEntity(); - public String id = ""; - public final ImageMeta meta = new ImageMeta(); + public static final SignEntity preview = new SignEntity(); + public static EntryIdBuilder builder = new EntryIdBuilder(); - public Sign() { + public static boolean isPlaceable(final EntryId entryId) { + return StringUtils.length(entryId.id()) < maxText; } - public Sign parseText(final String text) { - if (hasMeta(text)) { - this.id = extractId(text); - this.meta.parse(extractMeta(text)); - } - return this; + public static void updatePreview(final EntryId entryId) { + entryId.toEntity(preview.getTileEntity()); } - public static String extractMeta(final String src) { - return StringUtils.substring(src, StringUtils.lastIndexOf(src, "[")+1, StringUtils.length(src)-1); - } - - public static String extractId(final String src) { - return StringUtils.substring(src, 0, StringUtils.lastIndexOf(src, "[")); - } - - public static boolean hasMeta(final String text) { - return text!=null && StringUtils.endsWith(text, "]") && StringUtils.contains(text, "["); - } - - public static boolean hasId(final String id) { - return StringUtils.isEmpty(id) || StringUtils.containsOnly(id, "!") || StringUtils.containsOnly(id, "$"); - } - - public String getID() { - String id = this.id; - if (StringUtils.contains(id, "http://")) - id = StringUtils.substring(id, 7, StringUtils.length(id)); - else if (StringUtils.contains(id, "https://")) - id = "$" + StringUtils.substring(id, 8, StringUtils.length(id)); - return id; - } - - public String getURL() { - String id = this.id; - if (!StringUtils.startsWith(id, "!") && !hasId(id)) - if (StringUtils.startsWith(id, "$")) - id = "https://" + StringUtils.substring(id, 1); - else if (!StringUtils.startsWith(id, "http://") && !StringUtils.startsWith(id, "https://")) - id = "http://" + id; - return id; - } - - public Sign parseSignText(final String[] sign) { - return parseText(StringUtils.join(sign)); - } - - public Sign parseSignEntity(final TileEntitySign tile) { - return parseSignText(tile.signText); - } - - public String text() { - return getID() + this.meta; - } - - public boolean isPlaceable() { - return StringUtils.length(text()) < maxText; - } - - public boolean isVaild() { - return !hasId(this.id); - } - - public String[] toSignText() { - final String text = text(); - final String[] sign = new String[4]; - for (int i=0; i<4; i++) { - if (16*i <= StringUtils.length(text)) - sign[i] = StringUtils.substring(text, 15*i, Math.min(15*(i+1), text.length())); - else - sign[i] = ""; - } - return sign; - } - - public Sign writeToEntity(final TileEntitySign tile) { - tile.signText = toSignText(); - return this; - } - - public Sign updatePreview() { - return writeToEntity(this.preview.getTileEntity()); - } - - public Sign sendSign(final TileEntitySign sourceentity) { - writeToEntity(sourceentity); + public static void sendSign(final EntryId entryId, final TileEntitySign sourceentity) { + entryId.toEntity(sourceentity); sourceentity.markDirty(); final NetHandlerPlayClient nethandlerplayclient = Client.mc.getNetHandler(); if (nethandlerplayclient != null) nethandlerplayclient.addToSendQueue(new C12PacketUpdateSign(sourceentity.xCoord, sourceentity.yCoord, sourceentity.zCoord, sourceentity.signText)); sourceentity.setEditable(true); - return this; - } - - @Override - public String toString() { - return String.format("Sign [id=%s, meta=%s]", this.id, this.meta); } } diff --git a/src/main/resources/assets/signpic/lang/en_US.lang b/src/main/resources/assets/signpic/lang/en_US.lang index 03dbf77a..caf39e33 100644 --- a/src/main/resources/assets/signpic/lang/en_US.lang +++ b/src/main/resources/assets/signpic/lang/en_US.lang @@ -23,33 +23,58 @@ signpic.key.gui=Open GUI # GUI signpic.gui.editor.see=View Sign signpic.gui.editor.preview=Preview -signpic.gui.editor.width=Width -signpic.gui.editor.height=Height signpic.gui.editor.continue=Continue signpic.gui.editor.load=Load signpic.gui.editor.place=Place signpic.gui.editor.cancel=Cancel signpic.gui.editor.textfield=Place URL Here! +## Size +signpic.gui.editor.size.category=Size +signpic.gui.editor.size.width=W +signpic.gui.editor.size.height=H +signpic.gui.editor.size.width.neg=- +signpic.gui.editor.size.width.pos=+ +signpic.gui.editor.size.height.neg=- +signpic.gui.editor.size.height.pos=+ +## Offset +signpic.gui.editor.offset.category=Offset +signpic.gui.editor.offset.x=X +signpic.gui.editor.offset.x.neg=⇦ +signpic.gui.editor.offset.x.pos=⇨ +signpic.gui.editor.offset.y=Y +signpic.gui.editor.offset.y.neg=⇩ +signpic.gui.editor.offset.y.pos=⇧ +signpic.gui.editor.offset.z=Z +signpic.gui.editor.offset.z.neg=⇗ +signpic.gui.editor.offset.z.pos=⇙ +## Rotation +signpic.gui.editor.rotation.category=Rotation +signpic.gui.editor.rotation.up=↑ +signpic.gui.editor.rotation.down=↓ +signpic.gui.editor.rotation.x=X +signpic.gui.editor.rotation.y=Y +signpic.gui.editor.rotation.z=Z +signpic.gui.editor.rotation.remove=- +signpic.gui.editor.rotation.add=+ +signpic.gui.editor.rotation.neg=- +signpic.gui.editor.rotation.pos=+ # Image State signpic.state.init=Waiting... signpic.state.initalized=Initalized! signpic.state.downloading=Downloading... (%d%%) signpic.state.downloaded=Finished Downloading! -signpic.state.ioloading=File Loading... (%d%%) -signpic.state.ioloaded=Finished File Loading! -signpic.state.textureloading=Texture Loading... (%d%%) -signpic.state.textureloaded=Finished Texture Loading! +signpic.state.loading=Loading... (%d%%) +signpic.state.loaded=Finished Loading! signpic.state.available=Available! (%d%%) signpic.state.failed=Loading Failed... (%d%%) signpic.state.error=ERROR # Image State Additional Message -signpic.advmsg.invaildurl=Invaild URL -signpic.advmsg.invaildimage=Invaild Image -signpic.advmsg.unknown=Unknown Error: §7%s +signpic.advmsg.invalidurl=Invalid URL +signpic.advmsg.invalidimage=Invalid Image signpic.advmsg.ioerror=Failed to Read: §7%s -signpic.advmsg.dlerror=Failed to Download: §7%s +signpic.advmsg.unknown=Unknown Error: §7%s # Version Checking signpic.versioning.outdated=[§6SignPicture§r] You are running Sign Picture %s, the latest is %s. diff --git a/src/main/resources/assets/signpic/lang/ja_JP.lang b/src/main/resources/assets/signpic/lang/ja_JP.lang index a8bad0a3..bba1ae0d 100644 --- a/src/main/resources/assets/signpic/lang/ja_JP.lang +++ b/src/main/resources/assets/signpic/lang/ja_JP.lang @@ -10,33 +10,36 @@ signpic.chat.error.place=[§6SignPicture§r] 申し訳ございませんがエ # GUI signpic.gui.editor.see=実体表示 signpic.gui.editor.preview=プレビュー -signpic.gui.editor.width=幅 -signpic.gui.editor.height=高さ signpic.gui.editor.continue=連続 signpic.gui.editor.load=ロード signpic.gui.editor.place=設置 signpic.gui.editor.cancel=キャンセル signpic.gui.editor.textfield=ここにURLを入力! +## Size +signpic.gui.editor.size.category=サイズ +signpic.gui.editor.size.width=幅 +signpic.gui.editor.size.height=高さ +## Offset +signpic.gui.editor.offset.category=オフセット +## Rotation +signpic.gui.editor.rotation.category=回転 # Image State signpic.state.init=待機中... signpic.state.initalized=初期化完了! signpic.state.downloading=ダウンロード中... (%d%%) signpic.state.downloaded=ダウンロード完了! -signpic.state.ioloading=ファイル読み込み中... (%d%%) -signpic.state.ioloaded=ファイル読み込み完了! -signpic.state.textureloading=テクスチャ読み込み中... (%d%%) -signpic.state.textureloaded=テクスチャ読み込み完了! +signpic.state.loading=読み込み中... (%d%%) +signpic.state.loaded=読み込み完了! signpic.state.available=正常 (%d%%) signpic.state.failed=読み込み失敗... (%d%%) signpic.state.error=エラー # Image State Additional Message -signpic.advmsg.invaildurl=不正なURL -signpic.advmsg.invaildimage=不正な画像 -signpic.advmsg.unknown=不明なエラー: §7%s +signpic.advmsg.invalidurl=不正なURL +signpic.advmsg.invalidimage=不正な画像 signpic.advmsg.ioerror=ファイル読み込み失敗: §7%s -signpic.advmsg.dlerror=ダウンロード失敗: §7%s +signpic.advmsg.unknown=不明なエラー: §7%s # Version Checking signpic.versioning.outdated=[§6SignPicture§r] 現在のSignPictureのバージョンは %s です。新しいバージョン %s がご利用可能です! diff --git a/src/main/resources/logo.png b/src/main/resources/assets/signpic/textures/logo.png similarity index 100% rename from src/main/resources/logo.png rename to src/main/resources/assets/signpic/textures/logo.png diff --git a/src/main/resources/assets/signpic/textures/state/warning.png b/src/main/resources/assets/signpic/textures/state/warning.png deleted file mode 100644 index f8ded348..00000000 Binary files a/src/main/resources/assets/signpic/textures/state/warning.png and /dev/null differ diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 5da18888..7f73f4b4 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -5,7 +5,7 @@ "description": "The sign tells us how beautiful it is!", "version": "${version}", "mcversion": "${mcversion}", - "logoFile": "logo.png", + "logoFile": "assets/signpic/textures/logo.png", "url": "https://github.com/Team-Fruit/SignPicture/releases", "updateUrl": "https://github.com/Team-Fruit/SignPicture/releases", "authors": ["Kamesuta"],