CurveProperty holds the easing curves in the order Animation.getCurve takes them, replacing three copies of the list in zoom, freelook and the animation config; it's saved the same way. Its dropdown opens a CurveOptions popup: a CurvePreview graph beside the list, with a dot running along the hovered curve, or the current one. Co-Authored-By: Claude Opus 5.5 <[email protected]>
124 lines
4.5 KiB
Java
124 lines
4.5 KiB
Java
package org.saturnclient.mod.mods;
|
||
|
||
import java.util.function.Function;
|
||
|
||
import org.saturnclient.common.provider.GLFWProvider;
|
||
import org.saturnclient.config.property.BoolProperty;
|
||
import org.saturnclient.config.property.CurveProperty;
|
||
import org.saturnclient.config.property.FloatProperty;
|
||
import org.saturnclient.config.property.IntProperty;
|
||
import org.saturnclient.config.property.KeybindingProperty;
|
||
import org.saturnclient.config.property.Property;
|
||
import org.saturnclient.mod.Mod;
|
||
import org.saturnclient.mod.ModSpec;
|
||
import org.saturnclient.ui.anim.Animation;
|
||
|
||
public class ZoomMod extends Mod {
|
||
|
||
private static final BoolProperty enabled = Property.bool(false);
|
||
private static final BoolProperty toggle = Property.bool(false);
|
||
public static final KeybindingProperty zoomKey = Property.keybinding(GLFWProvider.GLFW_KEY_C);
|
||
public static final FloatProperty zoomLevel = Property.floatProp(3.0f).range(1f, 10f, 0.5f).unit("×");
|
||
public static final IntProperty zoomInDuration = Property.integer(700).range(0, 2000, 50).unit("ms");
|
||
public static final IntProperty zoomOutDuration = Property.integer(300).range(0, 2000, 50).unit("ms");
|
||
public static final CurveProperty curve = Property.curve(1);
|
||
|
||
public ZoomMod() {
|
||
super(
|
||
new ModSpec("Zoom", "zoom")
|
||
.description("Zoom in for a closer view")
|
||
.tags("Camera", "Utility")
|
||
.version("v0.2.0"),
|
||
enabled.named("Enabled"),
|
||
toggle.named("Toggle zoom").description("Press the key once instead of holding it"),
|
||
zoomKey.named("Zoom Keybinding").description("The key that zooms in"),
|
||
zoomLevel.named("Zoom Level").description("How far the camera zooms in"),
|
||
zoomInDuration.named("Zoom In Duration").description("How long zooming in takes"),
|
||
zoomOutDuration.named("Zoom Out Duration").description("How long zooming back out takes"),
|
||
curve.named("Curve").description("Easing of the zoom"));
|
||
}
|
||
|
||
// ---------------------------------------------------------------
|
||
// Mod fields
|
||
// ---------------------------------------------------------------
|
||
|
||
/** Zooming state */
|
||
public static boolean isZooming = false;
|
||
|
||
/** Animation state */
|
||
private static float progress = 0f; // 0 → 1
|
||
private static long lastTime = System.currentTimeMillis();
|
||
private static boolean lastTarget = false; // remember previous zoom state
|
||
|
||
// ---------------------------------------------------------------
|
||
// Mod contract
|
||
// ---------------------------------------------------------------
|
||
|
||
@Override
|
||
public void tick() {
|
||
// Update target zoom state
|
||
if (toggle.value) {
|
||
if (zoomKey.wasKeyPressed()) {
|
||
isZooming = !isZooming;
|
||
}
|
||
} else {
|
||
isZooming = zoomKey.isKeyPressed();
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public void onEnabled(boolean e) {
|
||
enabled.value = e;
|
||
if (!e)
|
||
isZooming = false;
|
||
}
|
||
|
||
@Override
|
||
public boolean isEnabled() {
|
||
return enabled.value;
|
||
}
|
||
|
||
// ---------------------------------------------------------------
|
||
// Mixin query API
|
||
// ---------------------------------------------------------------
|
||
|
||
/** Returns {@code true} when the FOV override should be applied. */
|
||
public static boolean shouldZoom() {
|
||
return enabled.value && (isZooming || progress > 0f);
|
||
}
|
||
|
||
public static int getZoomDuration() {
|
||
if (isZooming) {
|
||
return zoomInDuration.value;
|
||
} else {
|
||
return zoomOutDuration.value;
|
||
}
|
||
}
|
||
|
||
/** Returns the zoom divisor (e.g. 3.0 → one-third of normal FOV). */
|
||
public static float getZoomLevel() {
|
||
// Detect target change and reset timer
|
||
if (isZooming != lastTarget) {
|
||
lastTime = System.currentTimeMillis();
|
||
lastTarget = isZooming;
|
||
}
|
||
|
||
long now = System.currentTimeMillis();
|
||
float delta = (now - lastTime) / (float) getZoomDuration();
|
||
lastTime = now;
|
||
|
||
// Animate progress toward target
|
||
if (isZooming) {
|
||
progress = Math.min(1f, progress + delta);
|
||
} else {
|
||
progress = Math.max(0f, progress - delta);
|
||
}
|
||
|
||
// Apply curve
|
||
Function<Double, Double> curveFn = Animation.getCurve(curve.value);
|
||
double curved = curveFn.apply((double) progress);
|
||
|
||
// Map to zoom level
|
||
return 1.0f + (float) curved * (zoomLevel.value - 1f);
|
||
}
|
||
} |