Skip to content

Commit e1acf59

Browse files
committed
Added undo in editor.
1 parent 486e519 commit e1acf59

File tree

4 files changed

+75
-11
lines changed

4 files changed

+75
-11
lines changed

editor/src/main/java/oxy/bascenario/editor/inspector/Inspector.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,10 @@ public void render() {
120120

121121
boolean objectEquals = !old.equals(object.object);
122122
if (objectEquals || requireWait != object.requireWait || object.layer != layer || !Objects.equals(vec2, object.vec2)) {
123-
object.requireWait = requireWait;
124-
object.layer = layer;
125-
object.vec2 = vec2;
126-
123+
final int oldTrack = object.track;
124+
long oldDuration = old instanceof SoundAsElement sound ? AudioUtils.toDuration(screen.getScenario().name(), sound) : TimeCompiler.compileTime(old);
127125
if (objectEquals) {
128126
long duration = object.object instanceof SoundAsElement sound ? AudioUtils.toDuration(screen.getScenario().name(), sound) : TimeCompiler.compileTime(object.object);
129-
long oldDuration = old instanceof SoundAsElement sound ? AudioUtils.toDuration(screen.getScenario().name(), sound) : TimeCompiler.compileTime(old);
130127
if (duration == Long.MAX_VALUE) {
131128
duration = 0;
132129
}
@@ -139,7 +136,22 @@ public void render() {
139136
object.track = findNonOccupiedSlot(object.track, object.start, object.duration, object);
140137
}
141138

142-
timeline.queueUpdate = true;
139+
final boolean oldWait = object.requireWait;
140+
final RenderLayer oldLayer = object.layer;
141+
final Vec2 oldVec2 = object.vec2;
142+
final long oldTime = oldDuration == Long.MAX_VALUE ? 0 : oldDuration;
143+
timeline.queueUndo(() -> {
144+
object.object = old;
145+
object.duration = oldTime;
146+
object.requireWait = oldWait;
147+
object.layer = oldLayer;
148+
object.vec2 = oldVec2;
149+
object.track = oldTrack;
150+
});
151+
152+
object.requireWait = requireWait;
153+
object.layer = layer;
154+
object.vec2 = vec2;
143155
}
144156

145157
ImGui.end();

editor/src/main/java/oxy/bascenario/editor/screen/BaseScenarioEditorScreen.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import imgui.ImGuiViewport;
66
import imgui.flag.ImGuiCol;
77
import imgui.flag.ImGuiDockNodeFlags;
8+
import imgui.flag.ImGuiKey;
89
import imgui.flag.ImGuiWindowFlags;
910
import lombok.Getter;
1011
import net.raphimc.thingl.ThinGL;
@@ -55,6 +56,11 @@ public void render(float delta) {
5556
ImGui.begin("Scenario View", ImGuiWindowFlags.NoBackground);
5657
renderScenarioWindow();
5758
ImGui.end();
59+
60+
boolean control = ImGui.isKeyDown(ImGuiKey.RightCtrl) || ImGui.isKeyDown(ImGuiKey.LeftCtrl);
61+
if ((control) && ImGui.isKeyReleased(ImGuiKey.Z)) {
62+
timeline.undo();
63+
}
5864
}
5965

6066
public void update() {
@@ -87,6 +93,13 @@ private void renderMenuBar() {
8793
ImGui.endMenu();
8894
}
8995

96+
if (ImGui.beginMenu("Edit")) {
97+
if (ImGui.menuItem("Undo", "Ctrl+Z", false, timeline.canUndo())) {
98+
timeline.undo();
99+
}
100+
ImGui.endMenu();
101+
}
102+
90103
if (ImGui.beginMenu("Save")) {
91104
boolean asJson;
92105
if ((asJson = ImGui.menuItem("As Json")) || ImGui.menuItem("As Binary")) {

editor/src/main/java/oxy/bascenario/editor/timeline/ObjectRenderer.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ private void handleMouse() {
139139
public void accept() {
140140
final ImVec2 pos = ImGui.getWindowPos(), size = ImGui.getWindowSize();
141141

142+
final long oldStart = object.start;
143+
final int oldTrack = object.track;
142144
if (second) {
143145
object.start = nearestTime + 1;
144146
} else {
@@ -147,7 +149,10 @@ public void accept() {
147149
}
148150
object.track = trackFromY(timeline, object.renderer.y);
149151

150-
timeline.queueUpdate = true;
152+
timeline.queueUndo(() -> {
153+
object.start = oldStart;
154+
object.track = oldTrack;
155+
});
151156
}
152157
});
153158

@@ -185,11 +190,18 @@ private boolean handleDurationResize() {
185190
}
186191

187192
if (TimeCompiler.canResize(object.object)) {
193+
final long oldDuration = object.duration;
194+
final Object oldObject = object;
195+
final float oldWidth = this.width;
188196
object.duration = Math.max(0, object.duration + duration);
189197
object.object = TimeCompiler.addTime(object.object, (int) duration);
190198

191199
this.width = ((float) object.duration / (Timeline.DEFAULT_MAX_TIME * timeline.getScale())) * (size.x - size.x / 4);
192-
timeline.queueUpdate = true;
200+
timeline.queueUndo(() -> {
201+
this.width = oldWidth;
202+
this.object.duration = oldDuration;
203+
this.object.object = oldObject;
204+
});
193205
}
194206

195207
resizing = ImGui.isMouseDown(0);

editor/src/main/java/oxy/bascenario/editor/timeline/Timeline.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414

1515
import java.util.ArrayList;
1616
import java.util.Comparator;
17+
import java.util.Deque;
1718
import java.util.List;
19+
import java.util.concurrent.ConcurrentLinkedDeque;
1820

1921
// Shit code but whatever.
2022
public class Timeline {
@@ -30,10 +32,34 @@ public void put(int track, long start, long duration, Object object, RenderLayer
3032
this.objects.add(objectOrEvent);
3133
this.objects.sort(Comparator.comparingLong(o -> o.start));
3234

33-
this.queueUpdate = true;
35+
queueUndo(() -> this.objects.remove(objectOrEvent));
3436
this.setSelectedObject(objectOrEvent);
3537
}
3638

39+
// Undo and Redo
40+
private final Deque<Runnable> undo = new ConcurrentLinkedDeque<>();
41+
public void queueUndo(Runnable run) {
42+
this.queueUpdate = true;
43+
undo.add(run);
44+
if (undo.size() > 30) {
45+
undo.poll();
46+
}
47+
}
48+
public boolean canUndo() {
49+
return !undo.isEmpty();
50+
}
51+
public void undo() {
52+
if (undo.isEmpty()) {
53+
System.out.println("Nothin left to Undo!");
54+
return;
55+
}
56+
57+
undo.pollLast().run();
58+
System.out.println("Undo!");
59+
this.queueUpdate = true;
60+
// this.redo =
61+
}
62+
// private Runnable redo;
3763

3864
@Getter @Setter
3965
private ObjectOrEvent selectedObject;
@@ -47,7 +73,7 @@ public boolean isDragging(ObjectOrEvent object) {
4773
return this.draggingObject != null && object == this.draggingObject.object;
4874
}
4975

50-
public boolean queueUpdate;
76+
private boolean queueUpdate;
5177

5278
public Timeline(BaseScenarioEditorScreen screen, Scenario.Builder scenario) {
5379
this.screen = screen;
@@ -129,9 +155,10 @@ public void render() {
129155
drawTimelineCursor(size.x / 4, pos, size);
130156

131157
if (ImGui.isWindowFocused() && this.selectedObject != null && ImGui.isKeyPressed(ImGuiKey.Delete)) {
158+
final ObjectOrEvent old = this.selectedObject;
159+
queueUndo(() -> this.objects.add(old));
132160
this.objects.remove(this.selectedObject);
133161
this.selectedObject = null;
134-
this.queueUpdate = true;
135162
}
136163

137164
if (ImGui.isWindowFocused() && ImGui.isKeyPressed(ImGuiKey.Space)) {

0 commit comments

Comments
 (0)