Skip to content

Commit 7ff6bff

Browse files
committed
rewrite scrolling text widget with new animator
1 parent 7e1fda8 commit 7ff6bff

File tree

12 files changed

+193
-151
lines changed

12 files changed

+193
-151
lines changed

src/main/java/com/cleanroommc/modularui/animation/Animator.java

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,47 +6,39 @@
66
import java.util.function.DoubleConsumer;
77
import java.util.function.DoublePredicate;
88

9-
public class Animator extends BaseAnimator implements IAnimator {
9+
public class Animator extends BaseAnimator<Animator> implements IAnimator {
1010

1111
private float min = 0.0f;
1212
private float max = 1.0f;
1313
private int duration = 250;
1414
private IInterpolation curve = Interpolation.LINEAR;
15-
private boolean reverseOnFinish = false;
16-
private int repeats = 0;
15+
1716
private DoublePredicate onUpdate;
1817
private Runnable onFinish;
1918

2019
private int progress = 0;
21-
private boolean startedReverse = false;
22-
private int repeated = 0;
20+
2321

2422
@Override
2523
public void reset(boolean atEnd) {
24+
super.reset(atEnd);
2625
this.progress = atEnd ? this.duration : 0;
27-
this.startedReverse = atEnd;
28-
this.repeated = 0;
2926
}
3027

31-
@Override
32-
public void stop(boolean force) {
33-
if (isAnimating() && !force) {
34-
if (this.reverseOnFinish && this.startedReverse == isAnimatingReverse()) {
35-
onAnimationFinished(false, false);
36-
// started reverse -> bounce back and animate forward
37-
animate(isAnimatingForward());
38-
return;
39-
}
40-
if (repeats != 0 && (repeated < repeats || repeats < 0)) {
41-
onAnimationFinished(true, false);
42-
// started forward -> full cycle finished -> try repeating
43-
boolean reverse = !this.reverseOnFinish == isAnimatingReverse();
44-
animate(reverse);
45-
repeated++;
46-
return;
47-
}
28+
public Animator copy(boolean reversed) {
29+
Animator animator = new Animator()
30+
.curve(this.curve)
31+
.reverseOnFinish(this.reverseOnFinish)
32+
.repeatsOnFinish(this.repeats)
33+
.onUpdate(this.onUpdate)
34+
.duration(this.duration)
35+
.onFinish(this.onFinish);
36+
if (reversed) {
37+
animator.bounds(this.max, this.min);
38+
} else {
39+
animator.bounds(this.min, this.max);
4840
}
49-
super.stop(force);
41+
return animator;
5042
}
5143

5244
@Override
@@ -179,29 +171,7 @@ public Animator curve(IInterpolation curve) {
179171
return this;
180172
}
181173

182-
/**
183-
* Sets if the animation should reverse animate once after it finished.
184-
* If the animation started in reverse it will animate forward on finish.
185-
*
186-
* @param reverseOnFinish if animation should bounce back on finish
187-
* @return this
188-
*/
189-
public Animator reverseOnFinish(boolean reverseOnFinish) {
190-
this.reverseOnFinish = reverseOnFinish;
191-
return this;
192-
}
193174

194-
/**
195-
* Sets how often the animation should repeat. If {@link #reverseOnFinish(boolean)} is set to true, it will repeat the whole cycle.
196-
* If the number of repeats is negative, it will repeat infinitely.
197-
*
198-
* @param repeats how often the animation should repeat.
199-
* @return this
200-
*/
201-
public Animator repeatsOnFinish(int repeats) {
202-
this.repeats = repeats;
203-
return this;
204-
}
205175

206176
/**
207177
* Sets a function which is executed everytime the progress updates, that is on every frame.

src/main/java/com/cleanroommc/modularui/animation/BaseAnimator.java

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,61 @@
22

33
import org.jetbrains.annotations.Nullable;
44

5-
public abstract class BaseAnimator implements IAnimator {
5+
public abstract class BaseAnimator<A extends BaseAnimator<A>> implements IAnimator {
66

77
private IAnimator parent;
8+
protected boolean reverseOnFinish = false;
9+
protected int repeats = 0;
810

911
private byte direction = 0;
1012
private boolean paused = false;
13+
private boolean startedReverse = false;
14+
private int repeated = 0;
1115

1216
void setParent(IAnimator parent) {
1317
this.parent = parent;
1418
}
1519

20+
@SuppressWarnings("unchecked")
21+
public A getThis() {
22+
return (A) this;
23+
}
24+
1625
@Nullable
1726
public final IAnimator getParent() {
1827
return parent;
1928
}
2029

2130
@Override
22-
public void stop(boolean force) {
31+
public void reset(boolean atEnd) {
32+
this.startedReverse = atEnd;
33+
this.repeated = 0;
34+
}
35+
36+
@Override
37+
public boolean stop(boolean force) {
38+
if (isAnimating() && !force) {
39+
if (this.reverseOnFinish && this.startedReverse == isAnimatingReverse()) {
40+
onAnimationFinished(false, false);
41+
// started reverse -> bounce back and animate forward
42+
animate(isAnimatingForward());
43+
return false;
44+
}
45+
if (repeats != 0 && (repeated < repeats || repeats < 0)) {
46+
onAnimationFinished(true, false);
47+
// started forward -> full cycle finished -> try repeating
48+
boolean reverse = !this.reverseOnFinish == isAnimatingReverse();
49+
animate(reverse);
50+
repeated++;
51+
return false;
52+
}
53+
}
2354
this.direction = 0;
55+
return true;
2456
}
2557

58+
protected void onAnimationFinished(boolean finishedOneCycle, boolean finishedAllRepeats) {}
59+
2660
@Override
2761
public void pause() {
2862
this.paused = true;
@@ -59,6 +93,30 @@ public final byte getDirection() {
5993
return direction;
6094
}
6195

96+
/**
97+
* Sets if the animation should reverse animate once after it finished.
98+
* If the animation started in reverse it will animate forward on finish.
99+
*
100+
* @param reverseOnFinish if animation should bounce back on finish
101+
* @return this
102+
*/
103+
public A reverseOnFinish(boolean reverseOnFinish) {
104+
this.reverseOnFinish = reverseOnFinish;
105+
return getThis();
106+
}
107+
108+
/**
109+
* Sets how often the animation should repeat. If {@link #reverseOnFinish(boolean)} is set to true, it will repeat the whole cycle.
110+
* If the number of repeats is negative, it will repeat infinitely.
111+
*
112+
* @param repeats how often the animation should repeat.
113+
* @return this
114+
*/
115+
public A repeatsOnFinish(int repeats) {
116+
this.repeats = repeats;
117+
return getThis();
118+
}
119+
62120
public SequentialAnimator followedBy(IAnimator animator) {
63121
return new SequentialAnimator(this, animator);
64122
}

src/main/java/com/cleanroommc/modularui/animation/IAnimator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ default void animate() {
1818
animate(false);
1919
}
2020

21-
void stop(boolean force);
21+
boolean stop(boolean force);
2222

2323
void pause();
2424

src/main/java/com/cleanroommc/modularui/animation/ParallelAnimator.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import java.util.Collections;
55
import java.util.List;
66

7-
public class ParallelAnimator extends BaseAnimator implements IAnimator {
7+
public class ParallelAnimator extends BaseAnimator<ParallelAnimator> implements IAnimator {
88

99
private final List<IAnimator> animators;
1010
private int waitTimeBetweenAnimators;
@@ -46,15 +46,19 @@ public void animate(boolean reverse) {
4646
}
4747

4848
@Override
49-
public void stop(boolean force) {
50-
super.stop(force);
51-
for (IAnimator animator : animators) {
52-
animator.stop(force);
49+
public boolean stop(boolean force) {
50+
if (super.stop(force)) {
51+
for (IAnimator animator : animators) {
52+
animator.stop(force);
53+
}
54+
return true;
5355
}
56+
return false;
5457
}
5558

5659
@Override
5760
public void reset(boolean atEnd) {
61+
super.reset(atEnd);
5862
this.startedAnimating = 0;
5963
this.finishedAnimating = 0;
6064
for (IAnimator animator : animators) {

src/main/java/com/cleanroommc/modularui/animation/SequentialAnimator.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
import java.util.Collections;
77
import java.util.List;
88

9-
public class SequentialAnimator extends BaseAnimator implements IAnimator {
9+
public class SequentialAnimator extends BaseAnimator<SequentialAnimator> implements IAnimator {
1010

1111
private final List<IAnimator> animators;
1212
private int currentIndex = 0;
1313

1414
public SequentialAnimator(List<IAnimator> animators) {
1515
this.animators = new ArrayList<>(animators);
1616
this.animators.forEach(animator -> {
17-
if (animator instanceof BaseAnimator baseAnimator) {
17+
if (animator instanceof BaseAnimator<?> baseAnimator) {
1818
baseAnimator.setParent(this);
1919
}
2020
});
@@ -24,7 +24,7 @@ public SequentialAnimator(IAnimator... animators) {
2424
this.animators = new ArrayList<>();
2525
Collections.addAll(this.animators, animators);
2626
this.animators.forEach(animator -> {
27-
if (animator instanceof BaseAnimator baseAnimator) {
27+
if (animator instanceof BaseAnimator<?> baseAnimator) {
2828
baseAnimator.setParent(this);
2929
}
3030
});
@@ -40,10 +40,17 @@ public void animate(boolean reverse) {
4040

4141
@Override
4242
public void reset(boolean atEnd) {
43+
super.reset(atEnd);
4344
this.currentIndex = atEnd ? this.animators.size() - 1 : 0;
4445
this.animators.forEach(animator -> animator.reset(atEnd));
4546
}
4647

48+
@Override
49+
public void resume(boolean reverse) {
50+
super.resume(reverse);
51+
this.animators.get(this.currentIndex).resume(reverse);
52+
}
53+
4754
@Override
4855
public int advance(int elapsedTime) {
4956
while (isAnimating() && elapsedTime > 0) {
@@ -52,7 +59,7 @@ public int advance(int elapsedTime) {
5259
if (!animator.isAnimating()) {
5360
// animator has finished
5461
this.currentIndex += getDirection();
55-
ModularUI.LOGGER.info("Finished {}th animator", this.currentIndex);
62+
//ModularUI.LOGGER.info("Finished {}th animator", this.currentIndex);
5663
if (this.currentIndex >= this.animators.size() || this.currentIndex < 0) {
5764
// whole sequence has finished
5865
stop(false);

src/main/java/com/cleanroommc/modularui/api/drawable/IKey.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ default void draw(GuiContext context, int x, int y, int width, int height, Widge
200200
}
201201

202202
@Override
203-
default TextWidget asWidget() {
204-
return new TextWidget(this);
203+
default TextWidget<?> asWidget() {
204+
return new TextWidget<>(this);
205205
}
206206

207207
default StyledText withStyle() {

src/main/java/com/cleanroommc/modularui/drawable/text/TextRenderer.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -174,18 +174,18 @@ public void drawCut(Line line) {
174174
}
175175
}
176176

177-
public void drawScrolling(Line line, int scroll, Area area, GuiContext context) {
177+
public void drawScrolling(Line line, float progress, Area area, GuiContext context) {
178178
if (line.getWidth() <= this.maxWidth) {
179179
drawMeasuredLines(Collections.singletonList(line));
180180
return;
181181
}
182-
scroll = scroll % (int) (line.width + 1);
182+
float scroll = (this.maxWidth - line.getWidth()) * progress;
183+
//scroll = scroll % (int) (line.width + 1);
183184
String drawString = line.getText();//getFontRenderer().trimStringToWidth(line.getText(), (int) (this.maxWidth + scroll));
184-
Area.SHARED.set(this.x, Integer.MIN_VALUE, this.x + (int) this.maxWidth, Integer.MAX_VALUE);
185-
Stencil.apply(Area.SHARED, context);
186-
GlStateManager.translate(-scroll, 0, 0);
187-
drawMeasuredLines(Collections.singletonList(line(drawString)));
185+
Stencil.apply(this.x, -500, (int) this.maxWidth, 1000, context);
188186
GlStateManager.translate(scroll, 0, 0);
187+
drawMeasuredLines(Collections.singletonList(line(drawString)));
188+
GlStateManager.translate(-scroll, 0, 0);
189189
Stencil.remove();
190190
}
191191

@@ -326,7 +326,7 @@ public int upperWidth() {
326326
}
327327

328328
public int lowerWidth() {
329-
return (int) (this.width + 1);
329+
return (int) this.width;
330330
}
331331
}
332332
}

src/main/java/com/cleanroommc/modularui/test/OverlayTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static void init() {
2626

2727
OverlayManager.register(new OverlayHandler(screen -> screen instanceof GuiMainMenu, screen -> {
2828
GuiMainMenu gui = (GuiMainMenu) screen;
29-
TextWidget title = new TextWidget(IKey.str("ModularUI"));
29+
TextWidget<?> title = new TextWidget<>(IKey.str("ModularUI"));
3030
int[] colors = {Color.WHITE.main, Color.AMBER.main, Color.BLUE.main, Color.GREEN.main, Color.DEEP_PURPLE.main, Color.RED.main};
3131
AtomicInteger k = new AtomicInteger();
3232
return new ModularScreen(ModularPanel.defaultPanel("overlay").sizeRel(1f)

src/main/java/com/cleanroommc/modularui/test/TestGuis.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public class TestGuis extends CustomModularScreen {
140140
float period = 3000f;
141141
return ModularPanel.defaultPanel("main")
142142
.size(150)
143-
.child(new TextWidget(IKey.str("Test String")).scale(0.6f).horizontalCenter().top(7))
143+
.child(new TextWidget<>(IKey.str("Test String")).scale(0.6f).horizontalCenter().top(7))
144144
.child(new DraggableWidget<>()
145145
.background(new SpriteDrawable(sprite))
146146
.size(20)
@@ -317,7 +317,7 @@ public ModularPanel buildListUi(ModularGuiContext context) {
317317
.collapseDisabledChild()
318318
.expanded()
319319
.widthRel(1f)
320-
.children(items.size(), i -> new TextWidget(IKey.str(items.get(i)))
320+
.children(items.size(), i -> new TextWidget<>(IKey.str(items.get(i)))
321321
.alignment(Alignment.Center)
322322
.color(Color.WHITE.main)
323323
.widthRel(1f)

src/main/java/com/cleanroommc/modularui/test/TestTile.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager syncManager, UI
254254
.value(SyncHandlers.doubleNumber(() -> this.doubleValue, val -> this.doubleValue = val))
255255
.setNumbersDouble(Function.identity())
256256
.hintText("number"))
257-
.child(IKey.str("Test string").asWidget().padding(2).debugName("test string"))
257+
//.child(IKey.str("Test string").asWidget().padding(2).debugName("test string"))
258+
.child(new ScrollingTextWidget(IKey.str("Very very long test string")).widthRel(1f).height(16))
258259
//.child(IKey.EMPTY.asWidget().debugName("Empty IKey"))
259260
)
260261
.child(new Column()

0 commit comments

Comments
 (0)