Stop blocking all UI during path playback (closes #269)
Instead, just copy the timeline before playback.
This commit is contained in:
@@ -29,14 +29,11 @@ import de.johni0702.minecraft.gui.GuiRenderer;
|
|||||||
import de.johni0702.minecraft.gui.RenderInfo;
|
import de.johni0702.minecraft.gui.RenderInfo;
|
||||||
import de.johni0702.minecraft.gui.container.GuiContainer;
|
import de.johni0702.minecraft.gui.container.GuiContainer;
|
||||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
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.GuiElement;
|
||||||
import de.johni0702.minecraft.gui.element.GuiHorizontalScrollbar;
|
import de.johni0702.minecraft.gui.element.GuiHorizontalScrollbar;
|
||||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||||
import de.johni0702.minecraft.gui.element.GuiTexturedButton;
|
import de.johni0702.minecraft.gui.element.GuiTexturedButton;
|
||||||
import de.johni0702.minecraft.gui.element.GuiTooltip;
|
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.GuiProgressBar;
|
||||||
import de.johni0702.minecraft.gui.element.advanced.GuiTimelineTime;
|
import de.johni0702.minecraft.gui.element.advanced.GuiTimelineTime;
|
||||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
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.GuiInfoPopup;
|
||||||
import de.johni0702.minecraft.gui.popup.GuiYesNoPopup;
|
import de.johni0702.minecraft.gui.popup.GuiYesNoPopup;
|
||||||
import de.johni0702.minecraft.gui.utils.Colors;
|
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.ReadableDimension;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
|
import de.johni0702.minecraft.gui.utils.lwjgl.ReadablePoint;
|
||||||
import de.johni0702.minecraft.gui.utils.lwjgl.WritablePoint;
|
import de.johni0702.minecraft.gui.utils.lwjgl.WritablePoint;
|
||||||
@@ -102,20 +98,8 @@ public class GuiPathing {
|
|||||||
public final GuiTexturedButton renderButton = new GuiTexturedButton().onClick(new Runnable() {
|
public final GuiTexturedButton renderButton = new GuiTexturedButton().onClick(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!preparePathsForPlayback(false)) return;
|
Timeline timeline = preparePathsForPlayback(false);
|
||||||
|
if (timeline == null) 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
new GuiRenderSettings(replayHandler, timeline).display();
|
new GuiRenderSettings(replayHandler, timeline).display();
|
||||||
}
|
}
|
||||||
}).setSize(20, 20).setTexture(ReplayMod.TEXTURE, ReplayMod.TEXTURE_SIZE).setTexturePosH(40, 0)
|
}).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),
|
.addElements(new HorizontalLayout.Data(0.5),
|
||||||
playPauseButton, renderButton, positionKeyframeButton, timeKeyframeButton, timelinePanel);
|
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 ReplayMod core;
|
||||||
private final ReplayModSimplePathing mod;
|
private final ReplayModSimplePathing mod;
|
||||||
private final ReplayHandler replayHandler;
|
private final ReplayHandler replayHandler;
|
||||||
@@ -308,14 +250,16 @@ public class GuiPathing {
|
|||||||
player.getFuture().cancel(false);
|
player.getFuture().cancel(false);
|
||||||
} else {
|
} else {
|
||||||
boolean ignoreTimeKeyframes = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
|
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);
|
timePath.setActive(!ignoreTimeKeyframes);
|
||||||
|
|
||||||
// Start from cursor time unless the control key is pressed (then start from beginning)
|
// 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();
|
int startTime = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)? 0 : GuiPathing.this.timeline.getCursorPosition();
|
||||||
ListenableFuture<Void> future = player.start(mod.getCurrentTimeline().getTimeline(), startTime);
|
ListenableFuture<Void> future = player.start(timeline, startTime);
|
||||||
overlay.setCloseable(false);
|
overlay.setCloseable(false);
|
||||||
overlay.setMouseVisible(true);
|
overlay.setMouseVisible(true);
|
||||||
core.printInfoToChat("replaymod.chat.pathstarted");
|
core.printInfoToChat("replaymod.chat.pathstarted");
|
||||||
@@ -328,14 +272,12 @@ public class GuiPathing {
|
|||||||
core.printInfoToChat("replaymod.chat.pathfinished");
|
core.printInfoToChat("replaymod.chat.pathfinished");
|
||||||
}
|
}
|
||||||
overlay.setCloseable(true);
|
overlay.setCloseable(true);
|
||||||
timePath.setActive(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void onFailure(Throwable t) {
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
overlay.setCloseable(true);
|
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<GuiReplayOverlay>(overlay.getLayout()) {
|
overlay.setLayout(new CustomLayout<GuiReplayOverlay>(overlay.getLayout()) {
|
||||||
@Override
|
@Override
|
||||||
protected void layout(GuiReplayOverlay container, int width, int height) {
|
protected void layout(GuiReplayOverlay container, int width, int height) {
|
||||||
pos(panel, 10, y(overlay.topPanel) + height(overlay.topPanel) + 3);
|
pos(panel, 10, y(overlay.topPanel) + height(overlay.topPanel) + 3);
|
||||||
size(panel, width - 20, 40);
|
size(panel, width - 20, 40);
|
||||||
size(clickCatcher, 0, 0);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -528,8 +469,26 @@ public class GuiPathing {
|
|||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean preparePathsForPlayback(boolean ignoreTimeKeyframes) {
|
private Timeline preparePathsForPlayback(boolean ignoreTimeKeyframes) {
|
||||||
SPTimeline timeline = mod.getCurrentTimeline();
|
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);
|
timeline.getTimeline().getPaths().forEach(Path::updateAll);
|
||||||
|
|
||||||
// Make sure there are at least two position keyframes
|
// Make sure there are at least two position keyframes
|
||||||
|
|||||||
Reference in New Issue
Block a user