mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-03-13 17:46:58 +08:00
添加动画开关 (#2111)
This commit is contained in:
parent
389d430dbd
commit
ab264955f5
@ -191,6 +191,9 @@ public final class Config implements Cloneable, Observable {
|
||||
@SerializedName("preferredLoginType")
|
||||
private StringProperty preferredLoginType = new SimpleStringProperty();
|
||||
|
||||
@SerializedName("animationDisabled")
|
||||
private BooleanProperty animationDisabled = new SimpleBooleanProperty();
|
||||
|
||||
private transient ObservableHelper helper = new ObservableHelper(this);
|
||||
|
||||
public Config() {
|
||||
@ -601,6 +604,18 @@ public final class Config implements Cloneable, Observable {
|
||||
return preferredLoginType;
|
||||
}
|
||||
|
||||
public boolean isAnimationDisabled() {
|
||||
return animationDisabled.get();
|
||||
}
|
||||
|
||||
public BooleanProperty animationDisabledProperty() {
|
||||
return animationDisabled;
|
||||
}
|
||||
|
||||
public void setAnimationDisabled(boolean animationDisabled) {
|
||||
this.animationDisabled.set(animationDisabled);
|
||||
}
|
||||
|
||||
public boolean isTitleTransparent() {
|
||||
return titleTransparent.get();
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package org.jackhuang.hmcl.setting;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import org.jackhuang.hmcl.Metadata;
|
||||
import org.jackhuang.hmcl.game.HMCLCacheRepository;
|
||||
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||
import org.jackhuang.hmcl.util.CacheRepository;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
|
||||
@ -54,6 +55,7 @@ public final class Settings {
|
||||
Accounts.init();
|
||||
Profiles.init();
|
||||
AuthlibInjectorServers.init();
|
||||
AnimationUtils.init();
|
||||
|
||||
CacheRepository.setInstance(HMCLCacheRepository.REPOSITORY);
|
||||
HMCLCacheRepository.REPOSITORY.directoryProperty().bind(Bindings.createStringBinding(() -> {
|
||||
|
@ -47,6 +47,7 @@ import javafx.util.Callback;
|
||||
import javafx.util.Duration;
|
||||
import javafx.util.StringConverter;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||
import org.jackhuang.hmcl.ui.construct.JFXHyperlink;
|
||||
import org.jackhuang.hmcl.util.Holder;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
@ -275,7 +276,8 @@ public final class FXUtils {
|
||||
}
|
||||
|
||||
public static void smoothScrolling(ScrollPane scrollPane) {
|
||||
ScrollUtils.addSmoothScrolling(scrollPane);
|
||||
if (AnimationUtils.isAnimationEnabled())
|
||||
ScrollUtils.addSmoothScrolling(scrollPane);
|
||||
}
|
||||
|
||||
public static void installFastTooltip(Node node, Tooltip tooltip) {
|
||||
|
@ -0,0 +1,23 @@
|
||||
package org.jackhuang.hmcl.ui.animation;
|
||||
|
||||
import org.jackhuang.hmcl.setting.ConfigHolder;
|
||||
|
||||
public final class AnimationUtils {
|
||||
|
||||
private AnimationUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger initialization of this class.
|
||||
* Should be called from {@link org.jackhuang.hmcl.setting.Settings#init()}.
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
public static void init() {
|
||||
}
|
||||
|
||||
private static final boolean enabled = !ConfigHolder.config().isAnimationDisabled();
|
||||
|
||||
public static boolean isAnimationEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
}
|
@ -69,18 +69,23 @@ public class TransitionPane extends StackPane implements AnimationHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
transition.init(this);
|
||||
if (AnimationUtils.isAnimationEnabled()) {
|
||||
transition.init(this);
|
||||
|
||||
// runLater or "init" will not work
|
||||
Platform.runLater(() -> {
|
||||
Timeline newAnimation = new Timeline();
|
||||
newAnimation.getKeyFrames().addAll(transition.animate(this));
|
||||
newAnimation.getKeyFrames().add(new KeyFrame(duration, e -> {
|
||||
setMouseTransparent(false);
|
||||
getChildren().remove(previousNode);
|
||||
}));
|
||||
FXUtils.playAnimation(this, "transition_pane", newAnimation);
|
||||
});
|
||||
// runLater or "init" will not work
|
||||
Platform.runLater(() -> {
|
||||
Timeline newAnimation = new Timeline();
|
||||
newAnimation.getKeyFrames().addAll(transition.animate(this));
|
||||
newAnimation.getKeyFrames().add(new KeyFrame(duration, e -> {
|
||||
setMouseTransparent(false);
|
||||
getChildren().remove(previousNode);
|
||||
}));
|
||||
FXUtils.playAnimation(this, "transition_pane", newAnimation);
|
||||
});
|
||||
} else {
|
||||
setMouseTransparent(false);
|
||||
getChildren().remove(previousNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateContent(Node newView) {
|
||||
|
@ -25,6 +25,9 @@ import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
@ -35,6 +38,7 @@ import javafx.util.Duration;
|
||||
import org.jackhuang.hmcl.setting.Theme;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.SVG;
|
||||
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||
|
||||
/**
|
||||
* @author huangyuhui
|
||||
@ -70,6 +74,7 @@ class ComponentListCell extends StackPane {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void updateLayout() {
|
||||
if (content instanceof ComponentList) {
|
||||
ComponentList list = (ComponentList) content;
|
||||
@ -134,42 +139,66 @@ class ComponentListCell extends StackPane {
|
||||
container.getChildren().setAll(content);
|
||||
groupNode.getChildren().add(container);
|
||||
|
||||
Runnable onExpand = () -> {
|
||||
if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) {
|
||||
expandAnimation.stop();
|
||||
}
|
||||
EventHandler<Event> onExpand;
|
||||
if (AnimationUtils.isAnimationEnabled()) {
|
||||
onExpand = e -> {
|
||||
if (expandAnimation != null && expandAnimation.getStatus() == Animation.Status.RUNNING) {
|
||||
expandAnimation.stop();
|
||||
}
|
||||
|
||||
setExpanded(!isExpanded());
|
||||
setExpanded(!isExpanded());
|
||||
|
||||
if (isExpanded()) {
|
||||
list.onExpand();
|
||||
list.layout();
|
||||
}
|
||||
if (isExpanded()) {
|
||||
list.onExpand();
|
||||
list.layout();
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1);
|
||||
double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1);
|
||||
double contentHeight = isExpanded() ? newAnimatedHeight : 0;
|
||||
|
||||
if (isExpanded()) {
|
||||
updateClip(newHeight);
|
||||
}
|
||||
|
||||
expandAnimation = new Timeline(new KeyFrame(new Duration(320.0),
|
||||
new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE),
|
||||
new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE)
|
||||
));
|
||||
|
||||
if (!isExpanded()) {
|
||||
expandAnimation.setOnFinished(e2 -> updateClip(newHeight));
|
||||
}
|
||||
|
||||
expandAnimation.play();
|
||||
});
|
||||
};
|
||||
} else {
|
||||
onExpand = e -> {
|
||||
setExpanded(!isExpanded());
|
||||
|
||||
Platform.runLater(() -> {
|
||||
double newAnimatedHeight = (content.prefHeight(-1) + 8 + 10) * (isExpanded() ? 1 : -1);
|
||||
double newHeight = isExpanded() ? getHeight() + newAnimatedHeight : prefHeight(-1);
|
||||
double contentHeight = isExpanded() ? newAnimatedHeight : 0;
|
||||
|
||||
if (isExpanded()) {
|
||||
list.onExpand();
|
||||
list.layout();
|
||||
updateClip(newHeight);
|
||||
}
|
||||
|
||||
expandAnimation = new Timeline(new KeyFrame(new Duration(320.0),
|
||||
new KeyValue(container.minHeightProperty(), contentHeight, FXUtils.SINE),
|
||||
new KeyValue(container.maxHeightProperty(), contentHeight, FXUtils.SINE)
|
||||
));
|
||||
container.setMinHeight(contentHeight);
|
||||
container.setMaxHeight(contentHeight);
|
||||
|
||||
if (!isExpanded()) {
|
||||
expandAnimation.setOnFinished(e2 -> updateClip(newHeight));
|
||||
updateClip(newHeight);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
expandAnimation.play();
|
||||
});
|
||||
};
|
||||
|
||||
headerRippler.setOnMouseClicked(e -> onExpand.run());
|
||||
expandButton.setOnMouseClicked(e -> onExpand.run());
|
||||
headerRippler.setOnMouseClicked(onExpand);
|
||||
expandButton.setOnAction((EventHandler<ActionEvent>) (Object) onExpand);
|
||||
|
||||
expandedProperty().addListener((a, b, newValue) ->
|
||||
expandIcon.setRotate(newValue ? 180 : 0));
|
||||
|
@ -45,6 +45,7 @@ import org.jackhuang.hmcl.setting.Theme;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.SVG;
|
||||
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||
import org.jackhuang.hmcl.ui.construct.AnnouncementCard;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.PopupMenu;
|
||||
@ -254,18 +255,22 @@ public final class MainPage extends StackPane implements DecoratorPage {
|
||||
}
|
||||
|
||||
private void doAnimation(boolean show) {
|
||||
Duration duration = Duration.millis(320);
|
||||
Timeline nowAnimation = new Timeline();
|
||||
nowAnimation.getKeyFrames().addAll(
|
||||
new KeyFrame(Duration.ZERO,
|
||||
new KeyValue(updatePane.translateXProperty(), show ? 260 : 0, SINE)),
|
||||
new KeyFrame(duration,
|
||||
new KeyValue(updatePane.translateXProperty(), show ? 0 : 260, SINE)));
|
||||
if (show) nowAnimation.getKeyFrames().add(
|
||||
new KeyFrame(Duration.ZERO, e -> updatePane.setVisible(true)));
|
||||
else nowAnimation.getKeyFrames().add(
|
||||
new KeyFrame(duration, e -> updatePane.setVisible(false)));
|
||||
nowAnimation.play();
|
||||
if (AnimationUtils.isAnimationEnabled()) {
|
||||
Duration duration = Duration.millis(320);
|
||||
Timeline nowAnimation = new Timeline();
|
||||
nowAnimation.getKeyFrames().addAll(
|
||||
new KeyFrame(Duration.ZERO,
|
||||
new KeyValue(updatePane.translateXProperty(), show ? 260 : 0, SINE)),
|
||||
new KeyFrame(duration,
|
||||
new KeyValue(updatePane.translateXProperty(), show ? 0 : 260, SINE)));
|
||||
if (show) nowAnimation.getKeyFrames().add(
|
||||
new KeyFrame(Duration.ZERO, e -> updatePane.setVisible(true)));
|
||||
else nowAnimation.getKeyFrames().add(
|
||||
new KeyFrame(duration, e -> updatePane.setVisible(false)));
|
||||
nowAnimation.play();
|
||||
} else {
|
||||
updatePane.setVisible(show);
|
||||
}
|
||||
}
|
||||
|
||||
private void launch() {
|
||||
|
@ -88,6 +88,12 @@ public class PersonalizationPage extends StackPane {
|
||||
titleTransparentButton.selectedProperty().bindBidirectional(config().titleTransparentProperty());
|
||||
titleTransparentButton.setTitle(i18n("settings.launcher.title_transparent"));
|
||||
}
|
||||
{
|
||||
OptionToggleButton animationButton = new OptionToggleButton();
|
||||
themeList.getContent().add(animationButton);
|
||||
animationButton.selectedProperty().bindBidirectional(config().animationDisabledProperty());
|
||||
animationButton.setTitle(i18n("settings.launcher.turn_off_animations"));
|
||||
}
|
||||
content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.appearance")), themeList);
|
||||
|
||||
{
|
||||
|
@ -1066,6 +1066,7 @@ settings.launcher.proxy.socks=SOCKS
|
||||
settings.launcher.proxy.username=Username
|
||||
settings.launcher.theme=Theme
|
||||
settings.launcher.title_transparent=Transparent titlebar
|
||||
settings.launcher.turn_off_animations=Turn off animation (applies after restart)
|
||||
settings.launcher.version_list_source=Version List
|
||||
|
||||
settings.memory=Memory
|
||||
|
@ -936,6 +936,7 @@ settings.launcher.proxy.socks=Socks
|
||||
settings.launcher.proxy.username=帳戶
|
||||
settings.launcher.theme=主題
|
||||
settings.launcher.title_transparent=標題欄透明
|
||||
settings.launcher.turn_off_animations=關閉動畫 (重啟後生效)
|
||||
settings.launcher.version_list_source=版本列表來源
|
||||
|
||||
settings.memory=遊戲記憶體
|
||||
|
@ -934,6 +934,7 @@ settings.launcher.proxy.socks=Socks
|
||||
settings.launcher.proxy.username=帐户
|
||||
settings.launcher.theme=主题
|
||||
settings.launcher.title_transparent=标题栏透明
|
||||
settings.launcher.turn_off_animations=关闭动画 (重启后生效)
|
||||
settings.launcher.version_list_source=版本列表源
|
||||
|
||||
settings.memory=游戏内存
|
||||
|
Loading…
x
Reference in New Issue
Block a user