优化更多界面的动画 (#4790)
This commit is contained in:
@@ -49,6 +49,7 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
import org.jackhuang.hmcl.task.TaskExecutor;
|
import org.jackhuang.hmcl.task.TaskExecutor;
|
||||||
import org.jackhuang.hmcl.ui.account.AccountListPage;
|
import org.jackhuang.hmcl.ui.account.AccountListPage;
|
||||||
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
import org.jackhuang.hmcl.ui.animation.AnimationUtils;
|
||||||
|
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
||||||
import org.jackhuang.hmcl.ui.animation.Motion;
|
import org.jackhuang.hmcl.ui.animation.Motion;
|
||||||
import org.jackhuang.hmcl.ui.construct.*;
|
import org.jackhuang.hmcl.ui.construct.*;
|
||||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType;
|
||||||
@@ -91,7 +92,7 @@ public final class Controllers {
|
|||||||
|
|
||||||
private static Scene scene;
|
private static Scene scene;
|
||||||
private static Stage stage;
|
private static Stage stage;
|
||||||
private static Lazy<VersionPage> versionPage = new Lazy<>(VersionPage::new);
|
private static VersionPage versionPage;
|
||||||
private static Lazy<GameListPage> gameListPage = new Lazy<>(() -> {
|
private static Lazy<GameListPage> gameListPage = new Lazy<>(() -> {
|
||||||
GameListPage gameListPage = new GameListPage();
|
GameListPage gameListPage = new GameListPage();
|
||||||
gameListPage.selectedProfileProperty().bindBidirectional(Profiles.selectedProfileProperty());
|
gameListPage.selectedProfileProperty().bindBidirectional(Profiles.selectedProfileProperty());
|
||||||
@@ -128,7 +129,18 @@ public final class Controllers {
|
|||||||
|
|
||||||
// FXThread
|
// FXThread
|
||||||
public static VersionPage getVersionPage() {
|
public static VersionPage getVersionPage() {
|
||||||
return versionPage.get();
|
if (versionPage == null) {
|
||||||
|
versionPage = new VersionPage();
|
||||||
|
}
|
||||||
|
return versionPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXThread
|
||||||
|
public static void prepareVersionPage() {
|
||||||
|
if (versionPage == null) {
|
||||||
|
LOG.info("Prepare the version page");
|
||||||
|
versionPage = FXUtils.prepareNode(new VersionPage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FXThread
|
// FXThread
|
||||||
@@ -521,7 +533,11 @@ public final class Controllers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void navigate(Node node) {
|
public static void navigate(Node node) {
|
||||||
decorator.navigate(node);
|
decorator.navigate(node, ContainerAnimations.NAVIGATION, Motion.SHORT4, Motion.EASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void navigateForward(Node node) {
|
||||||
|
decorator.navigate(node, ContainerAnimations.FORWARD, Motion.SHORT4, Motion.EASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showToast(String content) {
|
public static void showToast(String content) {
|
||||||
|
|||||||
@@ -17,13 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.ui.animation;
|
package org.jackhuang.hmcl.ui.animation;
|
||||||
|
|
||||||
import javafx.animation.Interpolator;
|
import javafx.animation.*;
|
||||||
import javafx.animation.KeyFrame;
|
|
||||||
import javafx.animation.KeyValue;
|
|
||||||
import javafx.animation.Timeline;
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.util.Duration;
|
import javafx.util.Duration;
|
||||||
|
import org.jackhuang.hmcl.ui.decorator.DecoratorAnimatedPage;
|
||||||
|
|
||||||
public enum ContainerAnimations implements TransitionPane.AnimationProducer {
|
public enum ContainerAnimations implements TransitionPane.AnimationProducer {
|
||||||
NONE {
|
NONE {
|
||||||
@@ -199,6 +197,56 @@ public enum ContainerAnimations implements TransitionPane.AnimationProducer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
NAVIGATION {
|
||||||
|
@Override
|
||||||
|
public void init(TransitionPane container, Node previousNode, Node nextNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Animation animate(Pane container, Node previousNode, Node nextNode, Duration duration, Interpolator interpolator) {
|
||||||
|
Timeline timeline = new Timeline();
|
||||||
|
if (previousNode instanceof TransitionPane.EmptyPane) {
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration halfDuration = duration.divide(2);
|
||||||
|
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(Duration.ZERO,
|
||||||
|
new KeyValue(previousNode.opacityProperty(), 1, interpolator)));
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(halfDuration,
|
||||||
|
new KeyValue(previousNode.opacityProperty(), 0, interpolator)));
|
||||||
|
if (previousNode instanceof DecoratorAnimatedPage prevPage) {
|
||||||
|
Node left = prevPage.getLeft();
|
||||||
|
Node center = prevPage.getCenter();
|
||||||
|
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(Duration.ZERO,
|
||||||
|
new KeyValue(left.translateXProperty(), 0, interpolator),
|
||||||
|
new KeyValue(center.translateXProperty(), 0, interpolator)));
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(halfDuration,
|
||||||
|
new KeyValue(left.translateXProperty(), -30, interpolator),
|
||||||
|
new KeyValue(center.translateXProperty(), 30, interpolator)));
|
||||||
|
}
|
||||||
|
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(halfDuration,
|
||||||
|
new KeyValue(nextNode.opacityProperty(), 0, interpolator)));
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(duration,
|
||||||
|
new KeyValue(nextNode.opacityProperty(), 1, interpolator)));
|
||||||
|
if (nextNode instanceof DecoratorAnimatedPage nextPage) {
|
||||||
|
Node left = nextPage.getLeft();
|
||||||
|
Node center = nextPage.getCenter();
|
||||||
|
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(halfDuration,
|
||||||
|
new KeyValue(left.translateXProperty(), -30, interpolator),
|
||||||
|
new KeyValue(center.translateXProperty(), 30, interpolator)));
|
||||||
|
timeline.getKeyFrames().add(new KeyFrame(duration,
|
||||||
|
new KeyValue(left.translateXProperty(), 0, interpolator),
|
||||||
|
new KeyValue(center.translateXProperty(), 0, interpolator)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeline;
|
||||||
|
}
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
protected static void reset(Node node) {
|
protected static void reset(Node node) {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import org.jackhuang.hmcl.ui.Controllers;
|
|||||||
import org.jackhuang.hmcl.ui.FXUtils;
|
import org.jackhuang.hmcl.ui.FXUtils;
|
||||||
import org.jackhuang.hmcl.ui.account.AddAuthlibInjectorServerPane;
|
import org.jackhuang.hmcl.ui.account.AddAuthlibInjectorServerPane;
|
||||||
import org.jackhuang.hmcl.ui.animation.*;
|
import org.jackhuang.hmcl.ui.animation.*;
|
||||||
|
import org.jackhuang.hmcl.ui.animation.TransitionPane.AnimationProducer;
|
||||||
import org.jackhuang.hmcl.ui.construct.DialogAware;
|
import org.jackhuang.hmcl.ui.construct.DialogAware;
|
||||||
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
||||||
import org.jackhuang.hmcl.ui.construct.Navigator;
|
import org.jackhuang.hmcl.ui.construct.Navigator;
|
||||||
@@ -364,57 +365,8 @@ public class DecoratorController {
|
|||||||
|
|
||||||
// ==== Navigation ====
|
// ==== Navigation ====
|
||||||
|
|
||||||
private static final TransitionPane.AnimationProducer ANIMATION = (Pane container,
|
public void navigate(Node node, AnimationProducer animationProducer, Duration duration, Interpolator interpolator) {
|
||||||
Node previousNode, Node nextNode,
|
navigator.navigate(node, animationProducer, duration, interpolator);
|
||||||
Duration duration,
|
|
||||||
Interpolator interpolator) -> {
|
|
||||||
Timeline timeline = new Timeline();
|
|
||||||
if (previousNode instanceof TransitionPane.EmptyPane) {
|
|
||||||
return timeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
Duration halfDuration = duration.divide(2);
|
|
||||||
|
|
||||||
List<KeyFrame> keyFrames = new ArrayList<>();
|
|
||||||
|
|
||||||
keyFrames.add(new KeyFrame(Duration.ZERO,
|
|
||||||
new KeyValue(previousNode.opacityProperty(), 1, interpolator)));
|
|
||||||
keyFrames.add(new KeyFrame(halfDuration,
|
|
||||||
new KeyValue(previousNode.opacityProperty(), 0, interpolator)));
|
|
||||||
if (previousNode instanceof DecoratorAnimatedPage prevPage) {
|
|
||||||
Node left = prevPage.getLeft();
|
|
||||||
Node center = prevPage.getCenter();
|
|
||||||
|
|
||||||
keyFrames.add(new KeyFrame(Duration.ZERO,
|
|
||||||
new KeyValue(left.translateXProperty(), 0, interpolator),
|
|
||||||
new KeyValue(center.translateXProperty(), 0, interpolator)));
|
|
||||||
keyFrames.add(new KeyFrame(halfDuration,
|
|
||||||
new KeyValue(left.translateXProperty(), -30, interpolator),
|
|
||||||
new KeyValue(center.translateXProperty(), 30, interpolator)));
|
|
||||||
}
|
|
||||||
|
|
||||||
keyFrames.add(new KeyFrame(halfDuration,
|
|
||||||
new KeyValue(nextNode.opacityProperty(), 0, interpolator)));
|
|
||||||
keyFrames.add(new KeyFrame(duration,
|
|
||||||
new KeyValue(nextNode.opacityProperty(), 1, interpolator)));
|
|
||||||
if (nextNode instanceof DecoratorAnimatedPage nextPage) {
|
|
||||||
Node left = nextPage.getLeft();
|
|
||||||
Node center = nextPage.getCenter();
|
|
||||||
|
|
||||||
keyFrames.add(new KeyFrame(halfDuration,
|
|
||||||
new KeyValue(left.translateXProperty(), -30, interpolator),
|
|
||||||
new KeyValue(center.translateXProperty(), 30, interpolator)));
|
|
||||||
keyFrames.add(new KeyFrame(duration,
|
|
||||||
new KeyValue(left.translateXProperty(), 0, interpolator),
|
|
||||||
new KeyValue(center.translateXProperty(), 0, interpolator)));
|
|
||||||
}
|
|
||||||
|
|
||||||
timeline.getKeyFrames().setAll(keyFrames);
|
|
||||||
return timeline;
|
|
||||||
};
|
|
||||||
|
|
||||||
public void navigate(Node node) {
|
|
||||||
navigator.navigate(node, ANIMATION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close() {
|
private void close() {
|
||||||
@@ -586,7 +538,8 @@ public class DecoratorController {
|
|||||||
public void startWizard(WizardProvider wizardProvider, String category) {
|
public void startWizard(WizardProvider wizardProvider, String category) {
|
||||||
FXUtils.checkFxUserThread();
|
FXUtils.checkFxUserThread();
|
||||||
|
|
||||||
navigator.navigate(new DecoratorWizardDisplayer(wizardProvider, category), ContainerAnimations.FADE);
|
navigator.navigate(new DecoratorWizardDisplayer(wizardProvider, category),
|
||||||
|
ContainerAnimations.FORWARD, Motion.SHORT4, Motion.EASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==== Authlib Injector DnD ====
|
// ==== Authlib Injector DnD ====
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public final class JavaManagementPage extends ListPageBase<JavaManagementPage.Ja
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onShowRestoreJavaPage() {
|
void onShowRestoreJavaPage() {
|
||||||
Controllers.navigate(new JavaRestorePage(ConfigHolder.globalConfig().getDisabledJava()));
|
Controllers.navigateForward(new JavaRestorePage(ConfigHolder.globalConfig().getDisabledJava()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAddJavaBinary(Path file) {
|
private void onAddJavaBinary(Path file) {
|
||||||
|
|||||||
@@ -161,6 +161,9 @@ public class RootPage extends DecoratorAnimatedPage implements DecoratorPage {
|
|||||||
String currentId = getSkinnable().getMainPage().getCurrentGame();
|
String currentId = getSkinnable().getMainPage().getCurrentGame();
|
||||||
return Lang.indexWhere(list, instance -> instance.getId().equals(currentId));
|
return Lang.indexWhere(list, instance -> instance.getId().equals(currentId));
|
||||||
}, it -> getSkinnable().getMainPage().getProfile().setSelectedVersion(it.getId()));
|
}, it -> getSkinnable().getMainPage().getProfile().setSelectedVersion(it.getId()));
|
||||||
|
if (AnimationUtils.isAnimationEnabled()) {
|
||||||
|
FXUtils.prepareOnMouseEnter(gameListItem, Controllers::prepareVersionPage);
|
||||||
|
}
|
||||||
|
|
||||||
// third item in left sidebar
|
// third item in left sidebar
|
||||||
AdvancedListItem gameItem = new AdvancedListItem();
|
AdvancedListItem gameItem = new AdvancedListItem();
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ public final class ModListPage extends ListPageBase<ModListPageSkin.ModInfoObjec
|
|||||||
} else if (result.isEmpty()) {
|
} else if (result.isEmpty()) {
|
||||||
Controllers.dialog(i18n("mods.check_updates.empty"));
|
Controllers.dialog(i18n("mods.check_updates.empty"));
|
||||||
} else {
|
} else {
|
||||||
Controllers.navigate(new ModUpdatesPage(modManager, result));
|
Controllers.navigateForward(new ModUpdatesPage(modManager, result));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.withStagesHint(Collections.singletonList("mods.check_updates")),
|
.withStagesHint(Collections.singletonList("mods.check_updates")),
|
||||||
|
|||||||
@@ -461,7 +461,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
|||||||
if (advancedVersionSettingPage == null)
|
if (advancedVersionSettingPage == null)
|
||||||
advancedVersionSettingPage = new AdvancedVersionSettingPage(profile, versionId, lastVersionSetting);
|
advancedVersionSettingPage = new AdvancedVersionSettingPage(profile, versionId, lastVersionSetting);
|
||||||
|
|
||||||
Controllers.navigate(advancedVersionSettingPage);
|
Controllers.navigateForward(advancedVersionSettingPage);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
showAdvancedSettingPane.setRight(button);
|
showAdvancedSettingPane.setRight(button);
|
||||||
|
|||||||
@@ -91,6 +91,6 @@ public final class WorldListItem extends Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showManagePage() {
|
public void showManagePage() {
|
||||||
Controllers.navigate(new WorldManagePage(world, backupsDir));
|
Controllers.navigateForward(new WorldManagePage(world, backupsDir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user