From 098300f0dbc2a42ce06bc536f9d9eeea746e1b89 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 29 Aug 2020 13:20:59 +0200 Subject: [PATCH] Stop blocking all UI during path playback (closes #269) Instead, just copy the timeline before playback. --- .../simplepathing/gui/GuiPathing.java | 97 ++++++------------- 1 file changed, 28 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java index 47731e6e..ed50d309 100644 --- a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java +++ b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java @@ -29,14 +29,11 @@ import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.container.GuiContainer; import de.johni0702.minecraft.gui.container.GuiPanel; -import de.johni0702.minecraft.gui.element.AbstractGuiClickable; -import de.johni0702.minecraft.gui.element.AbstractGuiElement; import de.johni0702.minecraft.gui.element.GuiElement; import de.johni0702.minecraft.gui.element.GuiHorizontalScrollbar; import de.johni0702.minecraft.gui.element.GuiLabel; import de.johni0702.minecraft.gui.element.GuiTexturedButton; import de.johni0702.minecraft.gui.element.GuiTooltip; -import de.johni0702.minecraft.gui.element.IGuiClickable; import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar; import de.johni0702.minecraft.gui.element.advanced.GuiTimelineTime; import de.johni0702.minecraft.gui.layout.CustomLayout; @@ -46,7 +43,6 @@ import de.johni0702.minecraft.gui.popup.AbstractGuiPopup; import de.johni0702.minecraft.gui.popup.GuiInfoPopup; import de.johni0702.minecraft.gui.popup.GuiYesNoPopup; import de.johni0702.minecraft.gui.utils.Colors; -import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint; import de.johni0702.minecraft.gui.utils.lwjgl.WritablePoint; @@ -102,20 +98,8 @@ public class GuiPathing { public final GuiTexturedButton renderButton = new GuiTexturedButton().onClick(new Runnable() { @Override public void run() { - if (!preparePathsForPlayback(false)) return; - - // Clone the timeline passed to the settings gui as it may be stored for later rendering in a queue - SPTimeline spTimeline = mod.getCurrentTimeline(); - Timeline timeline; - try { - TimelineSerialization serialization = new TimelineSerialization(spTimeline, null); - String serialized = serialization.serialize(Collections.singletonMap("", spTimeline.getTimeline())); - timeline = serialization.deserialize(serialized).get(""); - } catch (Throwable t) { - error(LOGGER, replayHandler.getOverlay(), CrashReport.create(t, "Cloning timeline"), () -> {}); - return; - } - + Timeline timeline = preparePathsForPlayback(false); + if (timeline == null) return; new GuiRenderSettings(replayHandler, timeline).display(); } }).setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 0) @@ -224,48 +208,6 @@ public class GuiPathing { .addElements(new HorizontalLayout.Data(0.5), playPauseButton, renderButton, positionKeyframeButton, timeKeyframeButton, timelinePanel); - /** - * IGuiClickable dummy component that is inserted at a high level. - * During path playback, this catches all click events and forwards them to the - * abort path playback button. - * Dragging does not have to be intercepted as every GUI element should only - * respond to dragging events after it has received and handled a click event. - */ - private final IGuiClickable clickCatcher = new AbstractGuiClickable() { - @Override - public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { - if (player.isActive()) { - // Make sure the mouse is always visible during path playback - // even if the game closes the overlay for some reason (e.g. world change) - replayHandler.getOverlay().setMouseVisible(true); - } - } - - @Override - protected AbstractGuiElement getThis() { - return this; - } - - @Override - protected ReadableDimension calcMinSize() { - return new Dimension(0, 0); - } - - @Override - public boolean mouseClick(ReadablePoint position, int button) { - if (player.isActive()) { - playPauseButton.mouseClick(position, button); - return true; - } - return false; - } - - @Override - public int getLayer() { - return player.isActive() ? 10 : 0; - } - }; - private final ReplayMod core; private final ReplayModSimplePathing mod; private final ReplayHandler replayHandler; @@ -308,14 +250,16 @@ public class GuiPathing { player.getFuture().cancel(false); } else { boolean ignoreTimeKeyframes = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT); - Path timePath = mod.getCurrentTimeline().getTimePath(); - if (!preparePathsForPlayback(ignoreTimeKeyframes)) return; + Timeline timeline = preparePathsForPlayback(ignoreTimeKeyframes); + if (timeline == null) return; + Path timePath = new SPTimeline(timeline).getTimePath(); timePath.setActive(!ignoreTimeKeyframes); + // Start from cursor time unless the control key is pressed (then start from beginning) int startTime = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)? 0 : GuiPathing.this.timeline.getCursorPosition(); - ListenableFuture future = player.start(mod.getCurrentTimeline().getTimeline(), startTime); + ListenableFuture future = player.start(timeline, startTime); overlay.setCloseable(false); overlay.setMouseVisible(true); core.printInfoToChat("replaymod.chat.pathstarted"); @@ -328,14 +272,12 @@ public class GuiPathing { core.printInfoToChat("replaymod.chat.pathfinished"); } overlay.setCloseable(true); - timePath.setActive(true); } @Override public void onFailure(Throwable t) { t.printStackTrace(); overlay.setCloseable(true); - timePath.setActive(true); } }); } @@ -407,13 +349,12 @@ public class GuiPathing { } }); - overlay.addElements(null, panel, clickCatcher); + overlay.addElements(null, panel); overlay.setLayout(new CustomLayout(overlay.getLayout()) { @Override protected void layout(GuiReplayOverlay container, int width, int height) { pos(panel, 10, y(overlay.topPanel) + height(overlay.topPanel) + 3); size(panel, width - 20, 40); - size(clickCatcher, 0, 0); } }); @@ -528,8 +469,26 @@ public class GuiPathing { }).start(); } - private boolean preparePathsForPlayback(boolean ignoreTimeKeyframes) { - SPTimeline timeline = mod.getCurrentTimeline(); + private Timeline preparePathsForPlayback(boolean ignoreTimeKeyframes) { + SPTimeline spTimeline = mod.getCurrentTimeline(); + + if (!validatePathsForPlayback(spTimeline, ignoreTimeKeyframes)) { + return null; + } + + try { + TimelineSerialization serialization = new TimelineSerialization(spTimeline, null); + String serialized = serialization.serialize(Collections.singletonMap("", spTimeline.getTimeline())); + Timeline timeline = serialization.deserialize(serialized).get(""); + timeline.getPaths().forEach(Path::updateAll); + return timeline; + } catch (Throwable t) { + error(LOGGER, replayHandler.getOverlay(), CrashReport.create(t, "Cloning timeline"), () -> {}); + return null; + } + } + + private boolean validatePathsForPlayback(SPTimeline timeline, boolean ignoreTimeKeyframes) { timeline.getTimeline().getPaths().forEach(Path::updateAll); // Make sure there are at least two position keyframes