Zoom curve
This commit is contained in:
@@ -1,30 +1,28 @@
|
|||||||
package org.saturnclient.mod.mods;
|
package org.saturnclient.mod.mods;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import org.saturnclient.common.provider.GLFWProvider;
|
import org.saturnclient.common.provider.GLFWProvider;
|
||||||
import org.saturnclient.config.property.BoolProperty;
|
import org.saturnclient.config.property.BoolProperty;
|
||||||
import org.saturnclient.config.property.FloatProperty;
|
import org.saturnclient.config.property.FloatProperty;
|
||||||
|
import org.saturnclient.config.property.IntProperty;
|
||||||
import org.saturnclient.config.property.KeybindingProperty;
|
import org.saturnclient.config.property.KeybindingProperty;
|
||||||
import org.saturnclient.config.property.Property;
|
import org.saturnclient.config.property.Property;
|
||||||
|
import org.saturnclient.config.property.SelectProperty;
|
||||||
import org.saturnclient.mod.Mod;
|
import org.saturnclient.mod.Mod;
|
||||||
import org.saturnclient.mod.ModSpec;
|
import org.saturnclient.mod.ModSpec;
|
||||||
|
import org.saturnclient.ui.anim.Animation;
|
||||||
|
|
||||||
/**
|
|
||||||
* ZoomMod multiplies the camera's field-of-view to create an
|
|
||||||
* optical-zoom effect.
|
|
||||||
*
|
|
||||||
* The FOV override is applied inside a mixin that polls
|
|
||||||
* {@link #shouldZoom()} and {@link #getZoomLevel()} each frame.
|
|
||||||
* No FeatureProvider is needed — there is no per-tick engine query.
|
|
||||||
*/
|
|
||||||
public class ZoomMod extends Mod {
|
public class ZoomMod extends Mod {
|
||||||
|
|
||||||
private static final BoolProperty enabled = Property.bool(false);
|
private static final BoolProperty enabled = Property.bool(false);
|
||||||
private static final BoolProperty toggle = 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 KeybindingProperty zoomKey = Property.keybinding(GLFWProvider.GLFW_KEY_C);
|
||||||
public static final FloatProperty zoomLevel = Property.floatProp(3.0f);
|
public static final FloatProperty zoomLevel = Property.floatProp(3.0f);
|
||||||
|
public static final IntProperty zoomInDuration = Property.integer(700);
|
||||||
/** Whether zoom is currently active (read by the FOV mixin). */
|
public static final IntProperty zoomOutDuration = Property.integer(300);
|
||||||
public static boolean isZooming = false;
|
public static final SelectProperty curve = Property.select(1, "Ease In Out Cubic", "Ease Out Cubic",
|
||||||
|
"Ease In Out Back");
|
||||||
|
|
||||||
public ZoomMod() {
|
public ZoomMod() {
|
||||||
super(
|
super(
|
||||||
@@ -35,15 +33,31 @@ public class ZoomMod extends Mod {
|
|||||||
enabled.named("Enabled"),
|
enabled.named("Enabled"),
|
||||||
toggle.named("Toggle zoom"),
|
toggle.named("Toggle zoom"),
|
||||||
zoomKey.named("Zoom Keybinding"),
|
zoomKey.named("Zoom Keybinding"),
|
||||||
zoomLevel.named("Zoom Level"));
|
zoomLevel.named("Zoom Level"),
|
||||||
|
zoomInDuration.named("Zoom In Duration"),
|
||||||
|
zoomOutDuration.named("Zoom Out Duration"),
|
||||||
|
curve.named("Curve"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// 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
|
// Mod contract
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
// Update target zoom state
|
||||||
if (toggle.value) {
|
if (toggle.value) {
|
||||||
if (zoomKey.wasKeyPressed()) {
|
if (zoomKey.wasKeyPressed()) {
|
||||||
isZooming = !isZooming;
|
isZooming = !isZooming;
|
||||||
@@ -71,11 +85,41 @@ public class ZoomMod extends Mod {
|
|||||||
|
|
||||||
/** Returns {@code true} when the FOV override should be applied. */
|
/** Returns {@code true} when the FOV override should be applied. */
|
||||||
public static boolean shouldZoom() {
|
public static boolean shouldZoom() {
|
||||||
return enabled.value && isZooming;
|
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). */
|
/** Returns the zoom divisor (e.g. 3.0 → one-third of normal FOV). */
|
||||||
public static float getZoomLevel() {
|
public static float getZoomLevel() {
|
||||||
return zoomLevel.value;
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,21 +10,22 @@ public abstract class Animation {
|
|||||||
public int delay = 0;
|
public int delay = 0;
|
||||||
public Function<Double, Double> curve = Curve::easeInOutCubic;
|
public Function<Double, Double> curve = Curve::easeInOutCubic;
|
||||||
|
|
||||||
|
public static Function<Double, Double> getCurve(int curve) {
|
||||||
|
switch (curve) {
|
||||||
|
case 0:
|
||||||
|
return Curve::easeInOutCubic;
|
||||||
|
case 1:
|
||||||
|
return Curve::easeOutCubic;
|
||||||
|
case 2:
|
||||||
|
return Curve::easeInOutBack;
|
||||||
|
default:
|
||||||
|
return Curve::easeOutCubic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Animation(AnimationConfig config) {
|
Animation(AnimationConfig config) {
|
||||||
this.duration = config.duration.value;
|
this.duration = config.duration.value;
|
||||||
switch (config.curve.value) {
|
this.curve = getCurve(config.curve.value);
|
||||||
case 0:
|
|
||||||
this.curve = Curve::easeInOutCubic;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
this.curve = Curve::easeOutCubic;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
this.curve = Curve::easeInOutBack;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation(int duration) {
|
Animation(int duration) {
|
||||||
|
|||||||
Reference in New Issue
Block a user