forked from Clones/Controlify
✏️ Added featured options to config screen + update toast on launch
This commit is contained in:
@ -12,7 +12,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "dev.isxander"
|
group = "dev.isxander"
|
||||||
version = "1.4.6+1.20"
|
version = "1.5.0+1.20"
|
||||||
val isAlpha = "alpha" in version.toString()
|
val isAlpha = "alpha" in version.toString()
|
||||||
val isBeta = "beta" in version.toString()
|
val isBeta = "beta" in version.toString()
|
||||||
if (isAlpha) println("Alpha version detected.")
|
if (isAlpha) println("Alpha version detected.")
|
||||||
|
@ -45,10 +45,10 @@ import net.minecraft.network.chat.Component;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.libsdl.SDL;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@ -124,6 +124,8 @@ public class Controlify implements ControlifyApi {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
notifyOfNewFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Boolean> askNatives() {
|
private CompletableFuture<Boolean> askNatives() {
|
||||||
@ -583,6 +585,31 @@ public class Controlify implements ControlifyApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifyOfNewFeatures() {
|
||||||
|
if (config().isFirstLaunch())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var newFeatureVersions = List.of(
|
||||||
|
"1.5.0"
|
||||||
|
).iterator();
|
||||||
|
|
||||||
|
String foundVersion = null;
|
||||||
|
while (foundVersion == null && newFeatureVersions.hasNext()) {
|
||||||
|
var version = newFeatureVersions.next();
|
||||||
|
if (config().isLastSeenVersionLessThan(version)) {
|
||||||
|
foundVersion = version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundVersion != null) {
|
||||||
|
ToastUtils.sendToast(
|
||||||
|
Component.translatable("controlify.new_features.title", foundVersion),
|
||||||
|
Component.translatable("controlify.new_features." + foundVersion),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Controlify instance() {
|
public static Controlify instance() {
|
||||||
if (instance == null) instance = new Controlify();
|
if (instance == null) instance = new Controlify();
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package dev.isxander.controlify.config;
|
|
||||||
|
|
||||||
import com.google.gson.*;
|
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
public class ClassTypeAdapter implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
|
||||||
try {
|
|
||||||
return Class.forName(json.getAsString());
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) {
|
|
||||||
return new JsonPrimitive(src.getName());
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,6 +8,8 @@ import dev.isxander.controlify.controller.joystick.CompoundJoystickInfo;
|
|||||||
import dev.isxander.controlify.utils.DebugLog;
|
import dev.isxander.controlify.utils.DebugLog;
|
||||||
import dev.isxander.controlify.utils.Log;
|
import dev.isxander.controlify.utils.Log;
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.fabricmc.loader.api.Version;
|
||||||
|
import net.fabricmc.loader.api.VersionParsingException;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -25,7 +27,8 @@ public class ControlifyConfig {
|
|||||||
.serializeNulls()
|
.serializeNulls()
|
||||||
.setPrettyPrinting()
|
.setPrettyPrinting()
|
||||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||||
.registerTypeHierarchyAdapter(Class.class, new ClassTypeAdapter())
|
.registerTypeHierarchyAdapter(Class.class, new TypeAdapters.ClassTypeAdapter())
|
||||||
|
.registerTypeHierarchyAdapter(Version.class, new TypeAdapters.VersionTypeAdapter())
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
private final Controlify controlify;
|
private final Controlify controlify;
|
||||||
@ -35,6 +38,7 @@ public class ControlifyConfig {
|
|||||||
private Map<String, CompoundJoystickInfo> compoundJoysticks = Map.of();
|
private Map<String, CompoundJoystickInfo> compoundJoysticks = Map.of();
|
||||||
private GlobalSettings globalSettings = new GlobalSettings();
|
private GlobalSettings globalSettings = new GlobalSettings();
|
||||||
private boolean firstLaunch;
|
private boolean firstLaunch;
|
||||||
|
private Version lastSeenVersion = null;
|
||||||
|
|
||||||
private boolean dirty;
|
private boolean dirty;
|
||||||
|
|
||||||
@ -59,6 +63,14 @@ public class ControlifyConfig {
|
|||||||
|
|
||||||
if (!Files.exists(CONFIG_PATH)) {
|
if (!Files.exists(CONFIG_PATH)) {
|
||||||
firstLaunch = true;
|
firstLaunch = true;
|
||||||
|
if (lastSeenVersion == null) {
|
||||||
|
try {
|
||||||
|
lastSeenVersion = Version.parse("0.0.0");
|
||||||
|
} catch (VersionParsingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
save();
|
save();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -78,6 +90,8 @@ public class ControlifyConfig {
|
|||||||
private JsonObject generateConfig() {
|
private JsonObject generateConfig() {
|
||||||
JsonObject config = new JsonObject();
|
JsonObject config = new JsonObject();
|
||||||
|
|
||||||
|
config.addProperty("last_seen_version", Log.VERSION.getFriendlyString());
|
||||||
|
|
||||||
JsonObject newControllerData = controllerData.deepCopy(); // we use the old config, so we don't lose disconnected controller data
|
JsonObject newControllerData = controllerData.deepCopy(); // we use the old config, so we don't lose disconnected controller data
|
||||||
|
|
||||||
for (var controller : ControllerManager.getConnectedControllers()) {
|
for (var controller : ControllerManager.getConnectedControllers()) {
|
||||||
@ -103,7 +117,15 @@ public class ControlifyConfig {
|
|||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyConfig(JsonObject object) {
|
private void applyConfig(JsonObject object) throws VersionParsingException {
|
||||||
|
if (lastSeenVersion == null) {
|
||||||
|
boolean hasLastSeenVersion = object.has("last_seen_version");
|
||||||
|
lastSeenVersion = hasLastSeenVersion ? Version.parse(object.get("last_seen_version").getAsString()) : Version.parse("0.0.0");
|
||||||
|
if (!hasLastSeenVersion || lastSeenVersion.compareTo(Log.VERSION) < 0) {
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
globalSettings = GSON.fromJson(object.getAsJsonObject("global"), GlobalSettings.class);
|
globalSettings = GSON.fromJson(object.getAsJsonObject("global"), GlobalSettings.class);
|
||||||
if (globalSettings == null) {
|
if (globalSettings == null) {
|
||||||
globalSettings = new GlobalSettings();
|
globalSettings = new GlobalSettings();
|
||||||
@ -185,6 +207,18 @@ public class ControlifyConfig {
|
|||||||
return firstLaunch;
|
return firstLaunch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLastSeenVersionLessThan(Version version) {
|
||||||
|
return lastSeenVersion.compareTo(version) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLastSeenVersionLessThan(String version) {
|
||||||
|
try {
|
||||||
|
return isLastSeenVersionLessThan(Version.parse(version));
|
||||||
|
} catch (VersionParsingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String currentControllerUid() {
|
public String currentControllerUid() {
|
||||||
return currentControllerUid;
|
return currentControllerUid;
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package dev.isxander.controlify.config;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import net.fabricmc.loader.api.Version;
|
||||||
|
import net.fabricmc.loader.api.VersionParsingException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public final class TypeAdapters {
|
||||||
|
public static class ClassTypeAdapter implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
try {
|
||||||
|
return Class.forName(json.getAsString());
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
return new JsonPrimitive(src.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class VersionTypeAdapter implements JsonSerializer<Version>, JsonDeserializer<Version> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Version src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
return new JsonPrimitive(src.getFriendlyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Version deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
try {
|
||||||
|
return Version.parse(json.getAsString());
|
||||||
|
} catch (VersionParsingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -36,37 +36,61 @@ import java.util.stream.IntStream;
|
|||||||
public class ControllerConfigScreenFactory {
|
public class ControllerConfigScreenFactory {
|
||||||
private static final Function<Float, Component> percentFormatter = v -> Component.literal(String.format("%.0f%%", v*100));
|
private static final Function<Float, Component> percentFormatter = v -> Component.literal(String.format("%.0f%%", v*100));
|
||||||
private static final Function<Float, Component> percentOrOffFormatter = v -> v == 0 ? CommonComponents.OPTION_OFF : percentFormatter.apply(v);
|
private static final Function<Float, Component> percentOrOffFormatter = v -> v == 0 ? CommonComponents.OPTION_OFF : percentFormatter.apply(v);
|
||||||
|
private static final Component newOptionLabel = Component.translatable("controlify.gui.new_options.label").withStyle(ChatFormatting.GOLD);
|
||||||
|
|
||||||
|
private final List<Option<?>> newOptions = new ArrayList<>();
|
||||||
|
|
||||||
public static Screen generateConfigScreen(Screen parent, Controller<?, ?> controller) {
|
public static Screen generateConfigScreen(Screen parent, Controller<?, ?> controller) {
|
||||||
|
return new ControllerConfigScreenFactory().generateConfigScreen0(parent, controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Screen generateConfigScreen0(Screen parent, Controller<?, ?> controller) {
|
||||||
ControllerConfig def = controller.defaultConfig();
|
ControllerConfig def = controller.defaultConfig();
|
||||||
ControllerConfig config = controller.config();
|
ControllerConfig config = controller.config();
|
||||||
|
|
||||||
|
var advancedCategory = createAdvancedCategory(controller);
|
||||||
|
var bindsCategory = createBindsCategory(controller);
|
||||||
|
var basicCategory = createBasicCategory(controller, def, config); // must be last for new options
|
||||||
|
|
||||||
return YetAnotherConfigLib.createBuilder()
|
return YetAnotherConfigLib.createBuilder()
|
||||||
.title(Component.literal("Controlify"))
|
.title(Component.literal("Controlify"))
|
||||||
.category(createBasicCategory(controller, def, config))
|
.category(basicCategory)
|
||||||
.category(createAdvancedCategory(controller))
|
.category(advancedCategory)
|
||||||
.category(createBindsCategory(controller))
|
.category(bindsCategory)
|
||||||
.save(() -> Controlify.instance().config().save())
|
.save(() -> Controlify.instance().config().save())
|
||||||
.build().generateScreen(parent);
|
.build().generateScreen(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConfigCategory createBasicCategory(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
private ConfigCategory createBasicCategory(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
||||||
return ConfigCategory.createBuilder()
|
var sensitivityGroup = makeSensitivityGroup(controller, def, config);
|
||||||
|
var controlsGroup = makeControlsGroup(controller, def, config);
|
||||||
|
var accessibilityGroup = makeAccessibilityGroup(controller, def, config);
|
||||||
|
var deadzoneGroup = makeDeadzoneGroup(controller, def, config);
|
||||||
|
|
||||||
|
ConfigCategory.Builder builder = ConfigCategory.createBuilder()
|
||||||
.name(Component.translatable("controlify.gui.config.category.basic"))
|
.name(Component.translatable("controlify.gui.config.category.basic"))
|
||||||
.option(Option.<String>createBuilder()
|
.option(Option.<String>createBuilder()
|
||||||
.name(Component.translatable("controlify.gui.custom_name"))
|
.name(Component.translatable("controlify.gui.custom_name"))
|
||||||
.description(OptionDescription.of(Component.translatable("controlify.gui.custom_name.tooltip")))
|
.description(OptionDescription.of(Component.translatable("controlify.gui.custom_name.tooltip")))
|
||||||
.binding(def.customName == null ? "" : def.customName, () -> config.customName == null ? "" : config.customName, v -> config.customName = (v.equals("") ? null : v))
|
.binding(def.customName == null ? "" : def.customName, () -> config.customName == null ? "" : config.customName, v -> config.customName = (v.equals("") ? null : v))
|
||||||
.controller(StringControllerBuilder::create)
|
.controller(StringControllerBuilder::create)
|
||||||
.build())
|
.build());
|
||||||
.group(makeSensitivityGroup(controller, def, config))
|
if (!newOptions.isEmpty()) {
|
||||||
.group(makeControlsGroup(controller, def, config))
|
builder.group(OptionGroup.createBuilder()
|
||||||
.group(makeAccessibilityGroup(controller, controller.defaultConfig(), controller.config()))
|
.name(Component.translatable("controlify.gui.new_options").withStyle(ChatFormatting.GOLD, ChatFormatting.BOLD))
|
||||||
.group(makeDeadzoneGroup(controller, controller.defaultConfig(), controller.config()))
|
.description(OptionDescription.of(Component.translatable("controlify.gui.new_options.tooltip")))
|
||||||
.build();
|
.options(newOptions)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
builder.group(sensitivityGroup)
|
||||||
|
.group(controlsGroup)
|
||||||
|
.group(accessibilityGroup)
|
||||||
|
.group(deadzoneGroup);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OptionGroup makeSensitivityGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
private OptionGroup makeSensitivityGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
||||||
return OptionGroup.createBuilder()
|
return OptionGroup.createBuilder()
|
||||||
.name(Component.translatable("controlify.gui.config.group.sensitivity"))
|
.name(Component.translatable("controlify.gui.config.group.sensitivity"))
|
||||||
.option(Option.<Float>createBuilder()
|
.option(Option.<Float>createBuilder()
|
||||||
@ -108,7 +132,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OptionGroup makeControlsGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
private OptionGroup makeControlsGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
||||||
Function<Boolean, Component> holdToggleFormatter = v -> Component.translatable("controlify.gui.format.hold_toggle." + (v ? "toggle" : "hold"));
|
Function<Boolean, Component> holdToggleFormatter = v -> Component.translatable("controlify.gui.format.hold_toggle." + (v ? "toggle" : "hold"));
|
||||||
|
|
||||||
return OptionGroup.createBuilder()
|
return OptionGroup.createBuilder()
|
||||||
@ -145,7 +169,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OptionGroup makeAccessibilityGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
private OptionGroup makeAccessibilityGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
||||||
return OptionGroup.createBuilder()
|
return OptionGroup.createBuilder()
|
||||||
.name(Component.translatable("controlify.config.group.accessibility"))
|
.name(Component.translatable("controlify.config.group.accessibility"))
|
||||||
.option(Option.<Boolean>createBuilder()
|
.option(Option.<Boolean>createBuilder()
|
||||||
@ -186,7 +210,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OptionGroup makeDeadzoneGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
private OptionGroup makeDeadzoneGroup(Controller<?, ?> controller, ControllerConfig def, ControllerConfig config) {
|
||||||
var deadzoneOpts = new ArrayList<Option<Float>>();
|
var deadzoneOpts = new ArrayList<Option<Float>>();
|
||||||
|
|
||||||
var group = OptionGroup.createBuilder()
|
var group = OptionGroup.createBuilder()
|
||||||
@ -251,9 +275,9 @@ public class ControllerConfigScreenFactory {
|
|||||||
var axis = axes[i];
|
var axis = axes[i];
|
||||||
|
|
||||||
Option<Float> deadzoneOpt = Option.<Float>createBuilder()
|
Option<Float> deadzoneOpt = Option.<Float>createBuilder()
|
||||||
.name(Component.translatable("controlify.gui.joystick_axis_deadzone", axis.name()))
|
.name(Component.translatable("controlify.gui.axis_deadzone", axis.name()))
|
||||||
.description(OptionDescription.createBuilder()
|
.description(OptionDescription.createBuilder()
|
||||||
.text(Component.translatable("controlify.gui.joystick_axis_deadzone.tooltip", axis.name()))
|
.text(Component.translatable("controlify.gui.axis_deadzone.tooltip", axis.name()))
|
||||||
.text(Component.translatable("controlify.gui.stickdrift_warning").withStyle(ChatFormatting.RED))
|
.text(Component.translatable("controlify.gui.stickdrift_warning").withStyle(ChatFormatting.RED))
|
||||||
.build())
|
.build())
|
||||||
.binding(jsCfgDef.getDeadzone(i), () -> jsCfg.getDeadzone(i), v -> jsCfg.setDeadzone(i, v))
|
.binding(jsCfgDef.getDeadzone(i), () -> jsCfg.getDeadzone(i), v -> jsCfg.setDeadzone(i, v))
|
||||||
@ -291,7 +315,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
return group.build();
|
return group.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConfigCategory createAdvancedCategory(Controller<?, ?> controller) {
|
private ConfigCategory createAdvancedCategory(Controller<?, ?> controller) {
|
||||||
return ConfigCategory.createBuilder()
|
return ConfigCategory.createBuilder()
|
||||||
.name(Component.translatable("controlify.config.category.advanced"))
|
.name(Component.translatable("controlify.config.category.advanced"))
|
||||||
.option(Option.<Boolean>createBuilder()
|
.option(Option.<Boolean>createBuilder()
|
||||||
@ -305,7 +329,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConfigCategory createBindsCategory(Controller<?, ?> controller) {
|
private ConfigCategory createBindsCategory(Controller<?, ?> controller) {
|
||||||
var category = ConfigCategory.createBuilder()
|
var category = ConfigCategory.createBuilder()
|
||||||
.name(Component.translatable("controlify.gui.group.controls"));
|
.name(Component.translatable("controlify.gui.group.controls"));
|
||||||
|
|
||||||
@ -330,7 +354,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
return category.build();
|
return category.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateConflictingBinds(List<OptionBindPair> all) {
|
private void updateConflictingBinds(List<OptionBindPair> all) {
|
||||||
all.forEach(pair -> ((AbstractBindController<?>) pair.option().controller()).setConflicting(false));
|
all.forEach(pair -> ((AbstractBindController<?>) pair.option().controller()).setConflicting(false));
|
||||||
|
|
||||||
for (OptionBindPair opt : all) {
|
for (OptionBindPair opt : all) {
|
||||||
@ -351,7 +375,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OptionGroup makeVibrationGroup(Controller<?, ?> controller) {
|
private OptionGroup makeVibrationGroup(Controller<?, ?> controller) {
|
||||||
boolean canRumble = controller.supportsRumble();
|
boolean canRumble = controller.supportsRumble();
|
||||||
var config = controller.config();
|
var config = controller.config();
|
||||||
var def = controller.defaultConfig();
|
var def = controller.defaultConfig();
|
||||||
@ -417,7 +441,7 @@ public class ControllerConfigScreenFactory {
|
|||||||
return vibrationGroup.build();
|
return vibrationGroup.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OptionGroup makeGyroGroup(Controller<?, ?> controller) {
|
private OptionGroup makeGyroGroup(Controller<?, ?> controller) {
|
||||||
GamepadController gamepad = (controller instanceof GamepadController) ? (GamepadController) controller : null;
|
GamepadController gamepad = (controller instanceof GamepadController) ? (GamepadController) controller : null;
|
||||||
boolean hasGyro = gamepad != null && gamepad.hasGyro();
|
boolean hasGyro = gamepad != null && gamepad.hasGyro();
|
||||||
|
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package dev.isxander.controlify.utils;
|
package dev.isxander.controlify.utils;
|
||||||
|
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
import net.fabricmc.loader.api.Version;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class Log {
|
public class Log {
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger("Controlify");
|
public static final Logger LOGGER = LoggerFactory.getLogger("Controlify");
|
||||||
|
|
||||||
|
public static final Version VERSION = FabricLoader.getInstance().getModContainer("controlify").orElseThrow().getMetadata().getVersion();
|
||||||
}
|
}
|
||||||
|
@ -80,11 +80,12 @@ public class VirtualMouseHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sensitivity = controller.config().virtualMouseSensitivity;
|
var sensitivity = controller.config().virtualMouseSensitivity;
|
||||||
|
var windowSizeModifier = Math.max(minecraft.getWindow().getWidth(), minecraft.getWindow().getHeight()) / 800f;
|
||||||
|
|
||||||
// quadratic function to make small movements smaller
|
// quadratic function to make small movements smaller
|
||||||
// abs to keep sign
|
// abs to keep sign
|
||||||
targetX += impulseX * Mth.abs(impulseX) * 20f * sensitivity;
|
targetX += impulseX * Mth.abs(impulseX) * 20f * sensitivity * windowSizeModifier;
|
||||||
targetY += impulseY * Mth.abs(impulseY) * 20f * sensitivity;
|
targetY += impulseY * Mth.abs(impulseY) * 20f * sensitivity * windowSizeModifier;
|
||||||
|
|
||||||
targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth());
|
targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth());
|
||||||
targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight());
|
targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight());
|
||||||
@ -128,8 +129,8 @@ public class VirtualMouseHandler {
|
|||||||
if (!virtualMouseEnabled) return;
|
if (!virtualMouseEnabled) return;
|
||||||
|
|
||||||
if (Math.round(targetX * 100) / 100.0 != Math.round(currentX * 100) / 100.0 || Math.round(targetY * 100) / 100.0 != Math.round(currentY * 100) / 100.0) {
|
if (Math.round(targetX * 100) / 100.0 != Math.round(currentX * 100) / 100.0 || Math.round(targetY * 100) / 100.0 != Math.round(currentY * 100) / 100.0) {
|
||||||
currentX = Mth.lerp(minecraft.getDeltaFrameTime(), currentX, targetX);
|
currentX = Mth.lerp(minecraft.getFrameTime(), currentX, targetX);
|
||||||
currentY = Mth.lerp(minecraft.getDeltaFrameTime(), currentY, targetY);
|
currentY = Mth.lerp(minecraft.getFrameTime(), currentY, targetY);
|
||||||
|
|
||||||
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY);
|
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY);
|
||||||
} else {
|
} else {
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
"controlify.gui.ingame_button_guide_scale.tooltip.warning": "This may cause scaling issues that will make it to look bad at anything but 100%.",
|
"controlify.gui.ingame_button_guide_scale.tooltip.warning": "This may cause scaling issues that will make it to look bad at anything but 100%.",
|
||||||
"controlify.gui.open_issue_tracker": "Open Issue Tracker",
|
"controlify.gui.open_issue_tracker": "Open Issue Tracker",
|
||||||
|
|
||||||
|
"controlify.gui.new_options": "New This Update",
|
||||||
|
"controlify.gui.new_options.tooltip": "A showcase of the new options in the latest updates.",
|
||||||
|
"controlify.gui.new_options.label": "This option is new!",
|
||||||
"controlify.gui.battery_level": "Your controller battery is currently %s.",
|
"controlify.gui.battery_level": "Your controller battery is currently %s.",
|
||||||
"controlify.gui.custom_name": "Display Name",
|
"controlify.gui.custom_name": "Display Name",
|
||||||
"controlify.gui.custom_name.tooltip": "Name to display for this controller throughout Minecraft.",
|
"controlify.gui.custom_name.tooltip": "Name to display for this controller throughout Minecraft.",
|
||||||
@ -125,6 +128,9 @@
|
|||||||
|
|
||||||
"controlify.gui.controller_unavailable": "Controller unavailable and cannot be edited.",
|
"controlify.gui.controller_unavailable": "Controller unavailable and cannot be edited.",
|
||||||
|
|
||||||
|
"controlify.new_features.title": "Controlify updated to %s!",
|
||||||
|
"controlify.new_features.1.5.0": "Added a radial menu that can be configured to any action you want. You can find it in your controller settings.",
|
||||||
|
|
||||||
"controlify.vibration_strength.controlify.master": "Master",
|
"controlify.vibration_strength.controlify.master": "Master",
|
||||||
"controlify.vibration_strength.controlify.master.tooltip": "The strength of all vibrations. Will also affect the strength of all other sources.",
|
"controlify.vibration_strength.controlify.master.tooltip": "The strength of all vibrations. Will also affect the strength of all other sources.",
|
||||||
"controlify.vibration_strength.controlify.damage": "Take Damage",
|
"controlify.vibration_strength.controlify.damage": "Take Damage",
|
||||||
|
Reference in New Issue
Block a user