Skip to content

Commit 6110f5b

Browse files
committed
feat(editor): add scene2d symmetry and duplicate hints (v2.0.12)
1 parent d5e9f85 commit 6110f5b

4 files changed

Lines changed: 66 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.12] - 2026-04-05
6+
7+
### Added
8+
- **Scene2D Symmetry & Duplicate Hints:** `CustomGameEditor.java` now reports current-rotation symmetry and highlights duplicate rotations in the rotation overview, giving authors direct feedback about redundant states.
9+
10+
### Changed
11+
- Bumped `VERSION.md` to `2.0.12`.
12+
13+
### Validation
14+
- `./gradlew compileJava`
15+
516
## [2.0.11] - 2026-04-05
617

718
### Added

HANDOFF.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ This session focused on the newer Scene2D `CustomGameEditor` so the Java port ha
7474
- Expanded rotation overview buttons to include bounding-box information.
7575
- Bumped the Java repo version again to `2.0.11`.
7676

77+
### Additional Follow-Up - 2026-04-05 (Symmetry & Duplicate Hints)
78+
- Added current-rotation symmetry reporting and duplicate-rotation warnings to the Scene2D custom editor analytics.
79+
- Bumped the Java repo version again to `2.0.12`.
80+
7781
### Recommended Next Steps
7882
1. Add color/block-type controls to the Scene2D editor.
7983
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.11
1+
2.0.12

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,12 +663,14 @@ private void rebuildRotationOverview(PieceType pieceType) {
663663
return;
664664
}
665665

666+
java.util.HashSet<Integer> duplicateIndices = getDuplicateRotationIndices(pieceType);
666667
rotationOverviewTable.defaults().pad(4);
667668
for (int i = 0; i < pieceType.rotationSet.size(); i++) {
668669
final int rotationIndex = i;
669670
final Piece.Rotation rotation = pieceType.rotationSet.get(i);
670671
String prefix = (rotationIndex == selectedRotationIndex) ? "> " : "";
671-
TextButton button = new TextButton(prefix + "R" + rotationIndex + " (" + getFilledCellCount(rotation) + ", " + getRotationBoundingBox(rotation) + ")", engine.uiSkin);
672+
String duplicateLabel = duplicateIndices.contains(rotationIndex) ? ", dup" : "";
673+
TextButton button = new TextButton(prefix + "R" + rotationIndex + " (" + getFilledCellCount(rotation) + ", " + getRotationBoundingBox(rotation) + duplicateLabel + ")", engine.uiSkin);
672674
button.addListener(new ClickListener() {
673675
@Override
674676
public void clicked(InputEvent event, float x, float y) {
@@ -712,6 +714,51 @@ private String getRotationBoundingBox(Piece.Rotation rotation) {
712714
return (maxX - minX + 1) + "x" + (maxY - minY + 1);
713715
}
714716

717+
private String getRotationSymmetry(Piece.Rotation rotation) {
718+
if (rotation == null || rotation.blockOffsets.isEmpty()) return "none";
719+
int minX = Integer.MAX_VALUE;
720+
int maxX = Integer.MIN_VALUE;
721+
int minY = Integer.MAX_VALUE;
722+
int maxY = Integer.MIN_VALUE;
723+
java.util.HashSet<String> occupied = new java.util.HashSet<String>();
724+
for (Piece.BlockOffset offset : rotation.blockOffsets) {
725+
minX = Math.min(minX, offset.x);
726+
maxX = Math.max(maxX, offset.x);
727+
minY = Math.min(minY, offset.y);
728+
maxY = Math.max(maxY, offset.y);
729+
occupied.add(offset.x + "," + offset.y);
730+
}
731+
732+
boolean horizontal = true;
733+
boolean vertical = true;
734+
for (Piece.BlockOffset offset : rotation.blockOffsets) {
735+
int mirrorX = maxX - (offset.x - minX);
736+
int mirrorY = maxY - (offset.y - minY);
737+
if (!occupied.contains(mirrorX + "," + offset.y)) horizontal = false;
738+
if (!occupied.contains(offset.x + "," + mirrorY)) vertical = false;
739+
}
740+
741+
if (horizontal && vertical) return "horizontal + vertical";
742+
if (horizontal) return "horizontal";
743+
if (vertical) return "vertical";
744+
return "none";
745+
}
746+
747+
private java.util.HashSet<Integer> getDuplicateRotationIndices(PieceType pieceType) {
748+
java.util.HashSet<Integer> duplicates = new java.util.HashSet<Integer>();
749+
if (pieceType == null || pieceType.rotationSet == null) return duplicates;
750+
java.util.HashMap<String, Integer> firstSeen = new java.util.HashMap<String, Integer>();
751+
for (int i = 0; i < pieceType.rotationSet.size(); i++) {
752+
String signature = getRotationSignature(pieceType.rotationSet.get(i));
753+
if (firstSeen.containsKey(signature)) {
754+
duplicates.add(i);
755+
} else {
756+
firstSeen.put(signature, i);
757+
}
758+
}
759+
return duplicates;
760+
}
761+
715762
private int getUniqueRotationCount(PieceType pieceType) {
716763
if (pieceType == null || pieceType.rotationSet == null) return 0;
717764
java.util.HashSet<String> signatures = new java.util.HashSet<String>();
@@ -810,6 +857,7 @@ private void refreshEditorState() {
810857
int currentRotationCount = pieceType != null && pieceType.rotationSet != null ? pieceType.rotationSet.size() : 0;
811858
int uniqueRotationCount = getUniqueRotationCount(pieceType);
812859
int duplicateRotationCount = Math.max(0, currentRotationCount - uniqueRotationCount);
860+
String symmetry = getRotationSymmetry(rotation);
813861
summaryLabel.setText(
814862
"Mode: " + currentGameType.gameMode
815863
+ " | Grid: " + currentGameType.gridWidth + "x" + currentGameType.gridHeight
@@ -818,6 +866,7 @@ private void refreshEditorState() {
818866
+ " | Current piece rotations: " + currentRotationCount
819867
+ " | Filled cells in current rotation: " + getFilledCellCount(rotation)
820868
+ " | Current bbox: " + getRotationBoundingBox(rotation)
869+
+ " | Symmetry: " + symmetry
821870
+ " | Unique/duplicate rotations: " + uniqueRotationCount + "/" + duplicateRotationCount
822871
+ " | Rules: " + getEnabledRuleSummary()
823872
);

0 commit comments

Comments
 (0)