diff options
8 files changed, 229 insertions, 55 deletions
diff --git a/src/main/java/net/sowgro/npehero/devmenu/DiffEditor.java b/src/main/java/net/sowgro/npehero/devmenu/DiffEditor.java index 4d2fc4e..de9aad8 100755 --- a/src/main/java/net/sowgro/npehero/devmenu/DiffEditor.java +++ b/src/main/java/net/sowgro/npehero/devmenu/DiffEditor.java @@ -2,6 +2,7 @@ package net.sowgro.npehero.devmenu; import javafx.beans.binding.DoubleBinding; import javafx.geometry.Pos; +import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; @@ -16,6 +17,7 @@ import javafx.scene.text.Text; import net.sowgro.npehero.main.Difficulty; import net.sowgro.npehero.main.Note; import net.sowgro.npehero.main.Sound; +import net.sowgro.npehero.main.ValidIndicator; public class DiffEditor extends Pane { @@ -23,11 +25,7 @@ public class DiffEditor extends Pane ScrollPane scroll; public Pane prev; - /* - * this class is a layout class, most of its purpose is to place UI elements like Buttons within Panes like VBoxes. - * the creation of these UI elements are mostly not commented due to their repetitive and self explanatory nature. - * style classes are defined in the style.css file. - */ + public DiffEditor(Difficulty diff, Pane prev) { this.diff = diff; @@ -45,23 +43,35 @@ public class DiffEditor extends Pane Button editNotes = new Button("Edit notes"); editNotes.setOnAction(e -> { - Driver.setMenu(new NotesEditor2(diff, this)); + if (diff.level.song == null) { + Driver.setMenu(new ErrorDisplay("You must import a song file before editing the notes!", this)); + } + else { + Driver.setMenu(new NotesEditor2(diff, this)); + } }); Button oldEditNotes = new Button("Edit notes (legacy)"); oldEditNotes.setOnAction(_ -> { - try { - Driver.setMenu(new NotesEditor(diff, this)); - } catch (Exception e1) { - e1.printStackTrace(); - } + Driver.setMenu(new ErrorDisplay( + "Warning: \nThe legacy editor will overwrite all existing notes!", + this, + new NotesEditor(diff, this)) + ); }); Button editScores = new Button("Clear leaderboard"); editScores.setOnAction(e -> diff.leaderboard.entries.clear()); Button playLevel = new Button("Play level"); - playLevel.setOnAction(e -> Driver.setMenu(new LevelSurround(diff.level, diff, this))); + playLevel.setOnAction(e -> { + if (diff.isValid && diff.level.isValid) { + Driver.setMenu(new LevelSurround(diff.level, diff, this)); + } + else { + Driver.setMenu(new ErrorDisplay("This Level is not valid!\nCheck that all required fields\nare populated.", this)); + } + }); Button save = new Button("Save"); save.setOnAction(e -> { //assigns text fields to values @@ -88,8 +98,14 @@ public class DiffEditor extends Pane diff.notes.list.forEach(n -> lanes[n.lane].getChildren().add(drawNote(n))); - VBox notePreview = new VBox(scroll); - notePreview.getChildren().addAll(editNotes,oldEditNotes); + VBox notePreview = new VBox(); + + ValidIndicator validNotes = new ValidIndicator(); + if (diff.notes.list.isEmpty()) { + validNotes.setInvalid("This difficulty does not contain any notes!"); + } + HBox notesLabel = new HBox(new Label("Notes"), validNotes); + notePreview.getChildren().addAll(notesLabel, scroll, editNotes, oldEditNotes); notePreview.setSpacing(10); VBox left = new VBox(); diff --git a/src/main/java/net/sowgro/npehero/devmenu/DiffList.java b/src/main/java/net/sowgro/npehero/devmenu/DiffList.java index 7c5a435..e27e90d 100755 --- a/src/main/java/net/sowgro/npehero/devmenu/DiffList.java +++ b/src/main/java/net/sowgro/npehero/devmenu/DiffList.java @@ -15,24 +15,27 @@ import net.sowgro.npehero.main.Sound; public class DiffList extends Pane { - /* - * this class is a layout class, most of its purpose is to place UI elements like Buttons within Panes like VBoxes. - * the creation of these UI elements are mostly not commented due to their repetitive and self explanatory nature. - * style classes are defined in the style.css file. - */ + public DiffList(Level level, Pane prev) { //sets up table view: requires special getters, setters and constructors to work TableView<Difficulty> diffs = new TableView<>(); TableColumn<Difficulty,String> titleCol = new TableColumn<>("Name"); - TableColumn<Difficulty,Boolean> validCol = new TableColumn<>("Valid?"); + TableColumn<Difficulty,String> validCol = new TableColumn<>("Valid?"); diffs.getColumns().add(titleCol); diffs.getColumns().add(validCol); titleCol.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().title)); - validCol.setCellValueFactory(data -> new ReadOnlyBooleanWrapper(data.getValue().isValid)); + validCol.setCellValueFactory(data -> { + if (data.getValue().isValid) { + return new ReadOnlyStringWrapper("Yes"); + } + else { + return new ReadOnlyStringWrapper("No"); + } + }); diffs.setItems(level.difficulties.list); diff --git a/src/main/java/net/sowgro/npehero/devmenu/ErrorDisplay.java b/src/main/java/net/sowgro/npehero/devmenu/ErrorDisplay.java new file mode 100644 index 0000000..e5cd857 --- /dev/null +++ b/src/main/java/net/sowgro/npehero/devmenu/ErrorDisplay.java @@ -0,0 +1,77 @@ +package net.sowgro.npehero.devmenu; + +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.VBox; +import net.sowgro.npehero.Driver; +import net.sowgro.npehero.main.Sound; + +public class ErrorDisplay extends Pane { + public ErrorDisplay(String message, Pane prev) { + Label main = new Label(message); + main.getStyleClass().add("box"); + + Button exit = new Button(); + exit.setText("Back"); + exit.setOnAction(e -> { + Sound.playSfx(Sound.BACKWARD); + Driver.setMenu(prev); + }); + + VBox centerBox = new VBox(); + centerBox.setAlignment(Pos.CENTER); + centerBox.setSpacing(10); + centerBox.getChildren().addAll(main,exit); + centerBox.setMinWidth(400); + + HBox rootBox = new HBox(); + rootBox.prefWidthProperty().bind(super.prefWidthProperty()); + rootBox.prefHeightProperty().bind(super.prefHeightProperty()); + rootBox.getChildren().add(centerBox); + rootBox.setAlignment(Pos.CENTER); + + super.getChildren().add(rootBox); + } + + public ErrorDisplay(String message, Pane prev, Pane next) { + Label main = new Label(message); + main.getStyleClass().add("box"); + main.setPadding(new Insets(10)); + + Button exit = new Button(); + exit.setText("Cancel"); + exit.setOnAction(e -> { + Sound.playSfx(Sound.BACKWARD); + Driver.setMenu(prev); + }); + + Button nextButton = new Button(); + nextButton.setText("Proceed"); + nextButton.setOnAction(e -> { + Sound.playSfx(Sound.FORWARD); + Driver.setMenu(next); + }); + + HBox bottom = new HBox(exit, nextButton); + bottom.setAlignment(Pos.CENTER); + bottom.setSpacing(10); + + VBox centerBox = new VBox(); + centerBox.setAlignment(Pos.CENTER); + centerBox.setSpacing(10); + centerBox.getChildren().addAll(main,bottom); + centerBox.setMinWidth(400); + + HBox rootBox = new HBox(); + rootBox.prefWidthProperty().bind(super.prefWidthProperty()); + rootBox.prefHeightProperty().bind(super.prefHeightProperty()); + rootBox.getChildren().add(centerBox); + rootBox.setAlignment(Pos.CENTER); + + super.getChildren().add(rootBox); + } +} diff --git a/src/main/java/net/sowgro/npehero/devmenu/LevelEditor.java b/src/main/java/net/sowgro/npehero/devmenu/LevelEditor.java index 3a7561e..eef42f5 100755 --- a/src/main/java/net/sowgro/npehero/devmenu/LevelEditor.java +++ b/src/main/java/net/sowgro/npehero/devmenu/LevelEditor.java @@ -2,13 +2,10 @@ package net.sowgro.npehero.devmenu; import java.io.File; -import javafx.beans.property.ReadOnlyBooleanWrapper; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.geometry.Pos; import javafx.scene.control.*; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Pane; -import javafx.scene.layout.VBox; +import javafx.scene.layout.*; import javafx.scene.text.Text; import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; @@ -16,6 +13,7 @@ import net.sowgro.npehero.Driver; import net.sowgro.npehero.main.Difficulty; import net.sowgro.npehero.main.Level; import net.sowgro.npehero.main.Sound; +import net.sowgro.npehero.main.ValidIndicator; public class LevelEditor extends Pane { @@ -23,11 +21,6 @@ public class LevelEditor extends Pane private File selectedPreview = null; private File selectedBackground = null; - /* - * this class is a layout class, most of its purpose is to place UI elements like Buttons within Panes like VBoxes. - * the creation of these UI elements are mostly not commented due to their repetitive and self explanatory nature. - * style classes are defined in the style.css file. - */ public LevelEditor(Level level, Pane prev) { Text folderNameLabel = new Text("Folder name"); @@ -63,35 +56,53 @@ public class LevelEditor extends Pane HBox colorPickerBox = new HBox(); colorPickerBox.getChildren().addAll(colorsPickers); - Text filesLabel = new Text("Files"); + ValidIndicator songValid = new ValidIndicator(); + if (level.song == null) { + songValid.setInvalid("Missing file song.wav!"); + } + HBox filesLabel = new HBox(new Text("Files"), songValid); FileChooser backgroundChooser = new FileChooser(); backgroundChooser.getExtensionFilters().add(new ExtensionFilter("PNG", "*.png")); - Button backgroundButton = new Button("Import background PNG"); + Button backgroundButton = new Button("Background Image"); backgroundButton.setOnAction(e -> {selectedBackground = backgroundChooser.showOpenDialog(Driver.primaryStage);}); FileChooser previewChooser = new FileChooser(); previewChooser.getExtensionFilters().add(new ExtensionFilter("PNG", "*.png")); - Button previewButton = new Button("Import preview PNG"); + Button previewButton = new Button("Preview Image"); previewButton.setOnAction(e -> {selectedPreview = previewChooser.showOpenDialog(Driver.primaryStage);}); FileChooser songChooser = new FileChooser(); songChooser.getExtensionFilters().add(new ExtensionFilter("WAV", "*.wav")); - Button songButton = new Button("Import song WAV"); + Button songButton = new Button("Song file"); songButton.setOnAction(e -> selectedSong = songChooser.showOpenDialog(Driver.primaryStage)); - Text diffLabel = new Text("Difficulties"); + + ValidIndicator diffsInvalid = new ValidIndicator(); + if (level.difficulties.validList.isEmpty()) { + diffsInvalid.setInvalid("This level contains no valid difficulties!"); + } + HBox diffLabel = new HBox(new Text("Difficulties"), diffsInvalid); + diffLabel.setSpacing(5); + TableView<Difficulty> diffList = new TableView<>(); TableColumn<Difficulty,String> diffCol = new TableColumn<>("Difficulty"); - TableColumn<Difficulty,Boolean> validCol = new TableColumn<>("Valid?"); + TableColumn<Difficulty,String> validCol = new TableColumn<>("Valid?"); diffList.getColumns().add(diffCol); diffList.getColumns().add(validCol); diffCol.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().title)); - validCol.setCellValueFactory(data -> new ReadOnlyBooleanWrapper(data.getValue().isValid)); + validCol.setCellValueFactory(data -> { + if (data.getValue().isValid) { + return new ReadOnlyStringWrapper("Yes"); + } + else { + return new ReadOnlyStringWrapper("No"); + } + }); diffList.setItems(level.difficulties.list); @@ -136,17 +147,20 @@ public class LevelEditor extends Pane level.writeMetadata(); }); - VBox options = new VBox(); - options.getChildren().addAll(folderNameLabel,folderName,titleLabel,title,artistLabel,artist,descLabel,desc,colorsLabel, - colorPickerBox,filesLabel,previewButton,backgroundButton,songButton,save); - options.setSpacing(10); + VBox left = new VBox(filesLabel, songButton, previewButton, backgroundButton, colorsLabel, colorPickerBox); + left.setSpacing(10); + left.setPrefWidth(300); - VBox diffBox = new VBox(); - diffBox.getChildren().addAll(diffLabel,diffList,/*buttons,newDiffBox,*/ newDiffs); - diffBox.setSpacing(10); + VBox center = new VBox(folderNameLabel,folderName,titleLabel,title,artistLabel,artist,descLabel,desc); + center.setSpacing(10); + center.setPrefWidth(300); + + VBox right = new VBox(diffLabel,diffList,newDiffs); + right.setSpacing(10); + center.setPrefWidth(300); HBox mainBox = new HBox(); - mainBox.getChildren().addAll(options,diffBox); + mainBox.getChildren().addAll(left, center, right); mainBox.setSpacing(30); Button exit = new Button(); @@ -156,10 +170,14 @@ public class LevelEditor extends Pane Driver.setMenu(prev); }); + HBox bottom = new HBox(save, exit); + bottom.setAlignment(Pos.CENTER); + bottom.setSpacing(10); + VBox centerBox = new VBox(); centerBox.setAlignment(Pos.CENTER); centerBox.setSpacing(10); - centerBox.getChildren().addAll(mainBox,exit); + centerBox.getChildren().addAll(mainBox,bottom); centerBox.setMinWidth(400); HBox rootBox = new HBox(); diff --git a/src/main/java/net/sowgro/npehero/devmenu/LevelList.java b/src/main/java/net/sowgro/npehero/devmenu/LevelList.java index 92ede43..6bdb893 100755 --- a/src/main/java/net/sowgro/npehero/devmenu/LevelList.java +++ b/src/main/java/net/sowgro/npehero/devmenu/LevelList.java @@ -14,13 +14,11 @@ import net.sowgro.npehero.main.Level; import net.sowgro.npehero.main.Levels; import net.sowgro.npehero.main.Sound; +import java.time.Year; + public class LevelList extends Pane { - /* - * this class is a layout class, most of its purpose is to place UI elements like Buttons within Panes like VBoxes. - * the creation of these UI elements are mostly not commented due to their repetitive and self explanatory nature. - * style classes are defined in the style.css file. - */ + public LevelList() { //sets up table view: requires special getters, setters and constructors to work @@ -28,7 +26,7 @@ public class LevelList extends Pane TableColumn<Level,String> titleCol = new TableColumn<>("Title"); TableColumn<Level,String> artistCol = new TableColumn<>("Artist"); - TableColumn<Level,Boolean> validCol = new TableColumn<>("Valid?"); + TableColumn<Level,String> validCol = new TableColumn<>("Valid?"); levels.getColumns().add(titleCol); levels.getColumns().add(artistCol); @@ -36,7 +34,14 @@ public class LevelList extends Pane titleCol.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().title)); artistCol.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().artist)); - validCol.setCellValueFactory(data -> new ReadOnlyBooleanWrapper(data.getValue().isValid)); + validCol.setCellValueFactory(data -> { + if (data.getValue().isValid) { + return new ReadOnlyStringWrapper("Yes"); + } + else { + return new ReadOnlyStringWrapper("No"); + } + }); levels.setItems(Levels.list); diff --git a/src/main/java/net/sowgro/npehero/devmenu/NotesEditor.java b/src/main/java/net/sowgro/npehero/devmenu/NotesEditor.java index 5a606dc..e024ca4 100755 --- a/src/main/java/net/sowgro/npehero/devmenu/NotesEditor.java +++ b/src/main/java/net/sowgro/npehero/devmenu/NotesEditor.java @@ -27,7 +27,7 @@ public class NotesEditor extends Pane Difficulty diff; Timer timer; PrintWriter writer; - public NotesEditor(Difficulty diff, Pane prev) throws FileNotFoundException, UnsupportedEncodingException + public NotesEditor(Difficulty diff, Pane prev) { this.diff = diff; @@ -66,7 +66,11 @@ public class NotesEditor extends Pane super.getChildren().add(rootBox); - writer = new PrintWriter(diff.notes.getFile(), "UTF-8"); + try { + writer = new PrintWriter(diff.notes.getFile(), "UTF-8"); + } catch (FileNotFoundException | UnsupportedEncodingException e) { + throw new RuntimeException(e); + } Scene scene = Driver.primaryStage.getScene(); scene.addEventFilter(KeyEvent.KEY_PRESSED, e -> { diff --git a/src/main/java/net/sowgro/npehero/main/ValidIndicator.java b/src/main/java/net/sowgro/npehero/main/ValidIndicator.java new file mode 100644 index 0000000..79df643 --- /dev/null +++ b/src/main/java/net/sowgro/npehero/main/ValidIndicator.java @@ -0,0 +1,50 @@ +package net.sowgro.npehero.main; + +import javafx.scene.control.Tooltip; +import javafx.scene.layout.Background; +import javafx.scene.layout.Region; +import javafx.scene.paint.Color; +import javafx.scene.shape.SVGPath; +import javafx.util.Duration; +import net.sowgro.npehero.Driver; + +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class ValidIndicator extends Region { + public ValidIndicator() { + this.setScaleX(0.7); + this.setScaleY(0.7); + this.prefWidthProperty().bind(super.heightProperty()); + } + + public void setValid() { + this.setShape(null); + this.setBackground(Background.EMPTY); + } + + public void setInvalid(String reason) { + Tooltip diffLabelTooltip = new Tooltip(reason); + diffLabelTooltip.setShowDelay(Duration.ZERO); + SVGPath diffLabelIcon = new SVGPath(); + diffLabelIcon.setContent(pathFromSvg(Driver.getResource("error.svg"))); + this.setShape(diffLabelIcon); + this.setBackground(Background.fill(Color.web("#a70000"))); + Tooltip.install(this, diffLabelTooltip); + } + + private String pathFromSvg(URL url) { + try { + String fileContent = Files.readString(Paths.get(url.toURI())); + String startKey = "<path d=\""; + String endKey = "\""; + int startIndex = fileContent.indexOf(startKey) + startKey.length(); + int endIndex = fileContent.substring(startIndex).indexOf(endKey) + startIndex; + return fileContent.substring(startIndex, endIndex); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/resources/net/sowgro/npehero/error.svg b/src/main/resources/net/sowgro/npehero/error.svg new file mode 100644 index 0000000..9a02236 --- /dev/null +++ b/src/main/resources/net/sowgro/npehero/error.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240Zm40 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
\ No newline at end of file |