Skip to content

Commit 613ef5f

Browse files
committed
feat(editor): add scene2d preset slots (v2.0.9)
1 parent 0583b1d commit 613ef5f

4 files changed

Lines changed: 112 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [2.0.9] - 2026-04-05
6+
7+
### Added
8+
- **Scene2D Preset Slots:** `CustomGameEditor.java` now supports quick in-session preset save/load slots using deep-cloned `GameType` snapshots, enabling fast iteration without replacing the active draft permanently.
9+
10+
### Changed
11+
- Bumped `VERSION.md` to `2.0.9`.
12+
13+
### Validation
14+
- `./gradlew compileJava`
15+
516
## [2.0.8] - 2026-04-05
617

718
### Added

HANDOFF.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ This session focused on the newer Scene2D `CustomGameEditor` so the Java port ha
6161
- Expanded the Java editor summary so those movement/randomizer rules are visible immediately.
6262
- Bumped the Java repo version again to `2.0.8`.
6363

64+
### Additional Follow-Up - 2026-04-05 (Preset Slots)
65+
- Added in-session preset save/load slots to the Scene2D custom editor using deep-cloned `GameType` snapshots.
66+
- Bumped the Java repo version again to `2.0.9`.
67+
6468
### Recommended Next Steps
6569
1. Add color/block-type controls to the Scene2D editor.
6670
2. Bridge Scene2D custom editor state into the older TWL editor stack where useful.

VERSION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.8
1+
2.0.9

src/main/java/com/bobsgame/client/engine/game/gui/customGameEditor/CustomGameEditor.java

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@
1414
import com.bobsgame.puzzle.Piece;
1515
import com.bobsgame.puzzle.PieceType;
1616

17+
import java.io.ByteArrayInputStream;
18+
import java.io.ByteArrayOutputStream;
19+
import java.io.ObjectInputStream;
20+
import java.io.ObjectOutputStream;
21+
1722
public class CustomGameEditor extends Scene2DPanel {
1823
private final Table mainTable;
24+
private final TextButton saveSlot1Btn;
25+
private final TextButton loadSlot1Btn;
26+
private final TextButton saveSlot2Btn;
27+
private final TextButton loadSlot2Btn;
28+
private final TextButton saveSlot3Btn;
29+
private final TextButton loadSlot3Btn;
1930
private final TextButton addPieceBtn;
2031
private final TextButton duplicatePieceBtn;
2132
private final TextButton removePieceBtn;
@@ -50,7 +61,8 @@ public class CustomGameEditor extends Scene2DPanel {
5061
private final CheckBox flip180Checkbox;
5162
private final CheckBox floorKickCheckbox;
5263

53-
private final GameType currentGameType = new GameType();
64+
private GameType currentGameType = new GameType();
65+
private final GameType[] presetSlots = new GameType[3];
5466
private int selectedPieceIndex = -1;
5567
private int selectedRotationIndex = 0;
5668

@@ -89,6 +101,12 @@ public CustomGameEditor(Engine engine) {
89101
hintLabel.setWrap(true);
90102
summaryLabel.setWrap(true);
91103

104+
saveSlot1Btn = new TextButton("Save Slot 1", skin);
105+
loadSlot1Btn = new TextButton("Load Slot 1", skin);
106+
saveSlot2Btn = new TextButton("Save Slot 2", skin);
107+
loadSlot2Btn = new TextButton("Load Slot 2", skin);
108+
saveSlot3Btn = new TextButton("Save Slot 3", skin);
109+
loadSlot3Btn = new TextButton("Load Slot 3", skin);
92110
addPieceBtn = new TextButton("Add Piece Type", skin);
93111
duplicatePieceBtn = new TextButton("Duplicate Piece", skin);
94112
removePieceBtn = new TextButton("Remove Piece", skin);
@@ -101,6 +119,15 @@ public CustomGameEditor(Engine engine) {
101119
nextRotationBtn = new TextButton("Rot >", skin);
102120
clearRotationBtn = new TextButton("Clear Rotation", skin);
103121

122+
Table presetRow = new Table();
123+
presetRow.defaults().pad(4);
124+
presetRow.add(saveSlot1Btn);
125+
presetRow.add(loadSlot1Btn);
126+
presetRow.add(saveSlot2Btn);
127+
presetRow.add(loadSlot2Btn);
128+
presetRow.add(saveSlot3Btn);
129+
presetRow.add(loadSlot3Btn);
130+
104131
Table controlsRow1 = new Table();
105132
controlsRow1.defaults().pad(4);
106133
controlsRow1.add(addPieceBtn);
@@ -155,6 +182,43 @@ public void clicked(InputEvent event, float x, float y) {
155182
gridTable.row();
156183
}
157184

185+
saveSlot1Btn.addListener(new ClickListener() {
186+
@Override
187+
public void clicked(InputEvent event, float x, float y) {
188+
savePresetSlot(0);
189+
}
190+
});
191+
loadSlot1Btn.addListener(new ClickListener() {
192+
@Override
193+
public void clicked(InputEvent event, float x, float y) {
194+
loadPresetSlot(0);
195+
}
196+
});
197+
saveSlot2Btn.addListener(new ClickListener() {
198+
@Override
199+
public void clicked(InputEvent event, float x, float y) {
200+
savePresetSlot(1);
201+
}
202+
});
203+
loadSlot2Btn.addListener(new ClickListener() {
204+
@Override
205+
public void clicked(InputEvent event, float x, float y) {
206+
loadPresetSlot(1);
207+
}
208+
});
209+
saveSlot3Btn.addListener(new ClickListener() {
210+
@Override
211+
public void clicked(InputEvent event, float x, float y) {
212+
savePresetSlot(2);
213+
}
214+
});
215+
loadSlot3Btn.addListener(new ClickListener() {
216+
@Override
217+
public void clicked(InputEvent event, float x, float y) {
218+
loadPresetSlot(2);
219+
}
220+
});
221+
158222
addPieceBtn.addListener(new ClickListener() {
159223
@Override
160224
public void clicked(InputEvent event, float x, float y) {
@@ -258,6 +322,7 @@ public void clicked(InputEvent event, float x, float y) {
258322
mainTable.defaults().left().padBottom(8);
259323
mainTable.add(titleLabel).left().row();
260324
mainTable.add(hintLabel).width(520).left().row();
325+
mainTable.add(presetRow).left().row();
261326
mainTable.add(controlsRow1).left().row();
262327
mainTable.add(controlsRow2).left().row();
263328
mainTable.add(advancedRulesTable).left().row();
@@ -294,6 +359,36 @@ private void addRotation() {
294359
refreshEditorState();
295360
}
296361

362+
private GameType deepCloneGameType(GameType source) {
363+
try {
364+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
365+
ObjectOutputStream out = new ObjectOutputStream(bos);
366+
out.writeObject(source);
367+
out.flush();
368+
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
369+
return (GameType) in.readObject();
370+
} catch (Exception e) {
371+
throw new RuntimeException("Failed to clone GameType preset", e);
372+
}
373+
}
374+
375+
private void savePresetSlot(int slotIndex) {
376+
applyRuleCheckboxes();
377+
presetSlots[slotIndex] = deepCloneGameType(currentGameType);
378+
summaryLabel.setText("Saved current ruleset to preset slot " + (slotIndex + 1));
379+
}
380+
381+
private void loadPresetSlot(int slotIndex) {
382+
if (presetSlots[slotIndex] == null) {
383+
summaryLabel.setText("Preset slot " + (slotIndex + 1) + " is empty.");
384+
return;
385+
}
386+
currentGameType = deepCloneGameType(presetSlots[slotIndex]);
387+
selectedPieceIndex = currentGameType.pieceTypes.isEmpty() ? -1 : 0;
388+
selectedRotationIndex = 0;
389+
refreshEditorState();
390+
}
391+
297392
private Piece.Rotation cloneRotation(Piece.Rotation source) {
298393
Piece.Rotation clone = new Piece.Rotation();
299394
for (Piece.BlockOffset offset : source.blockOffsets) {

0 commit comments

Comments
 (0)