package gminers.glasspane.component.progress;
import gminers.kitchensink.Rendering;
import gminers.kitchensink.WaveType;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.FieldDefaults;
import org.lwjgl.opengl.GL11;
/**
* Implements a progress bar, used for displaying how complete an asynchronous long-running operation is. Or whatever other twisted uses you
* may have for it.
*
* @author Aesen Vismea
*
*/
@FieldDefaults(level = AccessLevel.PROTECTED)
@ToString
public class PaneProgressBar
extends PaneProgressIndicator {
/**
* Whether or not to draw an outline around this bar.
*/
@Getter @Setter protected boolean outlined = true;
/**
* The wave to use for the indeterminate animation.
*/
@Getter @Setter protected WaveType indeterminateWave = WaveType.SINE;
/**
* Whether or not to allow the indeterminate bar to leave the bounds of the bar. Turning this off is useful for some waves to make them
* look better, such as tangent.<br/>
* When turning this off, it is usually a good idea to make sure clipToSize is enabled.
*/
@Getter @Setter protected boolean indeterminateWaveKeptInBounds = true;
/**
* Whether or not to use the 'lag' value for progress text display.
*/
@Getter @Setter protected boolean useLagValueForProgressText = true;
/**
* Defines the width of the indeterminate animation's segment. (width / indeterminateSegmentDivisor = segmentLength)
*/
@Getter @Setter protected double indeterminateSegmentDivisor = 5D;
/**
* How accurate this bar should be - 1.0 means it will always follow the value exactly, values less than 1.0 make it animate smoothly
* towards the value, with lower values being slower.
*/
@Getter @Setter protected double accuracy = 0.25;
protected int step = 0;
protected float lag = 0;
protected float target = 0;
@Override
protected void doTick() {
target = ((float) progress / (float) maximumProgress);
if (Float.isNaN(lag)) {
lag = 0f;
}
if (!indeterminate) {
if (lag < target) {
lag += getAdjustment(target, lag);
} else if (lag > target) {
lag -= getAdjustment(lag, target);
}
} else {
step++;
}
}
protected float getAdjustment(final float big, final float small) {
final float diff = (big - small);
return (float) (diff > 0.000001 ? (diff * accuracy) : diff);
}
@Override
protected void doRender(final int mouseX, final int mouseY, final float partialTicks) {
int perceivedWidth = width;
int perceivedHeight = height;
if (outlined) {
perceivedWidth -= 2;
perceivedHeight -= 2;
GL11.glTranslatef(1, 1, 0);
}
Rendering.drawRect(0, 0, perceivedWidth, perceivedHeight, color | 0xFF000000);
if (indeterminate) {
final int segmentLength = (int) (perceivedWidth / indeterminateSegmentDivisor);
final double appl = (step + partialTicks) / indeterminateSegmentDivisor;
final int segmentX = segmentOffset(appl, perceivedWidth, segmentLength);
if (outlined) {
final int shadowColor = (indeterminateColor & 16579836) >> 2 | indeterminateColor & -16777216;
Rendering.drawRect(segmentX, -1, segmentX + segmentLength, perceivedHeight + 1,
shadowColor | 0xFF000000);
}
Rendering.drawRect(segmentX, 0, segmentX + segmentLength, perceivedHeight, indeterminateColor | 0xFF000000);
} else {
float lagg = lag;
if (lag < target) {
lagg += getAdjustment(target, lag) * partialTicks;
} else if (lag > target) {
lagg -= getAdjustment(lag, target) * partialTicks;
}
final int segmentLength = (int) (lagg * perceivedWidth);
if (outlined && segmentLength > 0) {
final int shadowColor = (filledColor & 16579836) >> 2 | filledColor & -16777216;
Rendering.drawRect(-1, -1, segmentLength + (lagg == 1.0 ? 1 : 0), perceivedHeight + 1,
shadowColor | 0xFF000000);
}
Rendering.drawRect(0, 0, segmentLength, perceivedHeight, filledColor | 0xFF000000);
}
drawProgressText(useLagValueForProgressText ? lag : target);
if (outlined) {
GL11.glTranslatef(-1, -1, 0);
final int shadowColor = (color & 16579836) >> 2 | color & -16777216;
Rendering.drawRect(0, 0, width, 1, shadowColor | 0xFF000000);
Rendering.drawRect(width - 1, 1, width, height, shadowColor | 0xFF000000);
Rendering.drawRect(0, height - 1, width - 1, height, shadowColor | 0xFF000000);
Rendering.drawRect(0, 0, 1, height - 1, shadowColor | 0xFF000000);
}
}
public float getLagPercentage() {
return lag;
}
protected int segmentOffset(final double appl, final int max, final int segmentLength) {
if (indeterminateWaveKeptInBounds) {
return (int) (indeterminateWave.calculate(appl) * (max - segmentLength));
} else {
return (int) ((indeterminateWave.calculate(appl) * (max + segmentLength))) - segmentLength;
}
}
}