From e03a34f2dedf1c09a289b72b2f052123d5da91db Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sun, 24 Mar 2024 02:00:45 -0500 Subject: [PATCH 01/39] Fixed bug with new instance declaration when calling event. --- src/main/java/me/piitex/renjava/RenJava.java | 213 ++++++++++++------- 1 file changed, 133 insertions(+), 80 deletions(-) diff --git a/src/main/java/me/piitex/renjava/RenJava.java b/src/main/java/me/piitex/renjava/RenJava.java index e10d5fd..ebdcaa6 100644 --- a/src/main/java/me/piitex/renjava/RenJava.java +++ b/src/main/java/me/piitex/renjava/RenJava.java @@ -2,12 +2,17 @@ import javafx.application.HostServices; import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.layout.Pane; +import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; +import javafx.scene.text.Text; import javafx.stage.Stage; import javafx.stage.StageStyle; import me.piitex.renjava.addons.Addon; import me.piitex.renjava.addons.AddonLoader; +import me.piitex.renjava.api.builders.FontLoader; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.exceptions.InvalidCharacterException; import me.piitex.renjava.api.music.Tracks; @@ -33,6 +38,8 @@ import me.piitex.renjava.gui.layouts.impl.VerticalLayout; import me.piitex.renjava.gui.overlay.ButtonOverlay; import me.piitex.renjava.gui.StageType; +import me.piitex.renjava.gui.overlay.TextFlowOverlay; +import me.piitex.renjava.gui.overlay.TextOverlay; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -49,16 +56,13 @@ * The `RenJava` class handles various aspects of the game, including managing the game window, handling events, managing characters and stories, and saving and loading game data. * It also provides methods for registering event listeners, characters, and persistent data objects. *

- * To start the game, create an instance of your extended `RenJava` class and pass the necessary parameters, such as the game name, author, and version, to the constructor. - * The `RenJava` framework will automatically create an instance of your class and initialize the game. + * The Game and Configuration annotations are used to build default systems for the framework. Although it's not a hard requirement creating these annotations + * is very important for other systems to work as intended. The Logger relies on the Game annotation to pass the name of the logger. + * The GUI relies on the Configuration to properly display the window. *

{@code
+  *    @Game(name = "My Game", author = "You", version = "1.0);
+  *    @Configuration(title = "My Game 1.0", width = 1920, height = 1080);
  *     public class MyGameClass extends RenJava {
- *
- *         // Note: The constructor cannot contain any parameters.
- *         public MyGameClass() {
- *             super("game name", "author", "version");
- *         }
- *
  *         // abstraction methods.
  *     }
  * }
@@ -67,8 +71,8 @@ */ public abstract class RenJava { protected String name; - protected String author; - protected String version; + protected String author; + protected String version; private Logger logger; private Player player; // Audio Tracking @@ -93,27 +97,8 @@ public abstract class RenJava { private static RenJava instance; - /** - * Entry point for the RenJava framework. This class is designed to be extended by your own class, which will serve as the entry point for your game. - *

- * Note: Do not call this constructor directly. The RenJava framework creates a new instance of your class automatically using reflection. - *

- * Make sure to use {@link Game} to specify the information of the game. - *

{@code
-     * public class YourGame extends RenJava {
-     *
-     *     @Game(name = "Your Game", author = "You", version = "1.0")
-     *     public YourGame() {
-     *
-     *     }
-     * }
-     * }
- * If you do not specify the game information it will assume default values. - * - * @see Game - */ public RenJava() { - // Super is ran first than the superior method is ran. + // Super is ran first then the superior method is ran. instance = this; } @@ -130,7 +115,7 @@ protected void init() { logger.addHandler(fileHandler); logger.info("Starting application..."); } catch (IOException e) { - e.printStackTrace(); + getLogger().severe("Could not initialize logger. " + e.getMessage()); } this.registerListener(new MenuClickEventListener()); this.registerListener(new GameFlowEventListener()); @@ -417,17 +402,20 @@ public Menu buildSideMenu() { Font uiFont = RenJava.getInstance().getConfiguration().getUiFont().getFont(); - ButtonOverlay startButton = new ButtonOverlay("menu-start-button", "Start", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, Color.BLUE, 1, 1); - ButtonOverlay loadButton = new ButtonOverlay("menu-load-button", "Load", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, Color.BLUE, 1, 1); - ButtonOverlay optionsButton = new ButtonOverlay("menu-preference-button", "Preferences", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, Color.BLUE, 1, 1); - ButtonOverlay aboutButton = new ButtonOverlay("menu-about-button", "About", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, Color.BLUE, 1, 1); + Color hoverColor = getConfiguration().getHoverColor(); + + ButtonOverlay startButton = new ButtonOverlay("menu-start-button", "Start", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, hoverColor, 1, 1); + ButtonOverlay loadButton = new ButtonOverlay("menu-load-button", "Load", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, hoverColor, 1, 1); + ButtonOverlay saveButton = new ButtonOverlay("menu-save-button", "Save", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, hoverColor, 1, 1); + ButtonOverlay optionsButton = new ButtonOverlay("menu-preference-button", "Preferences", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, hoverColor, 1, 1); + ButtonOverlay aboutButton = new ButtonOverlay("menu-about-button", "About", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, hoverColor, 1, 1); // Create vbox for the buttons. You can also do an HBox VerticalLayout layout = new VerticalLayout(200, 500); layout.setX(50); layout.setY(250); layout.setSpacing(20); - layout.addOverlays(startButton, loadButton, optionsButton, aboutButton); + layout.addOverlays(startButton, loadButton, saveButton, optionsButton, aboutButton); // You don't have to add the button overlays just add the layout which already contains the overlays. menu.addLayout(layout); @@ -445,47 +433,92 @@ public Menu buildLoadMenu(int page) { int maxSavesPerPage = 6; - int index = 1; + int index = ((maxSavesPerPage * page) - maxSavesPerPage) + 1; VerticalLayout rootLayout = new VerticalLayout(1000, 400); // The root is a vertical which stacks the two horizontal layouts. HorizontalLayout topLayout = new HorizontalLayout(1000, 200); HorizontalLayout bottomLayout = new HorizontalLayout(1000, 200); while (index <= maxSavesPerPage) { - // Create a button overlay of the scene that the save file would have been on., - // This will be a little challenging, it should be possible given the api of the Save object. + System.out.println("Rendering save-" + index); + VerticalLayout buttonBox = new VerticalLayout(400, 300); Save save = new Save(index); - if (save.getFile() != null) { - if (index <= 3) { - // Top layout + TextOverlay slotText = new TextOverlay(new Text("Slot " + index), getConfiguration().getUiFont(), 1, 1); + buttonBox.addOverlays(slotText); + if (save.exists()) { + System.out.println("Save file exists..."); + // Build the pane + Pane pane = save.buildPreview(); + buttonBox.addSubPane(pane); + } else { + System.out.println("Empty save..."); + ButtonOverlay loadButton = new ButtonOverlay("save-" + index, new ImageLoader("gui/button/slot_idle_background.png"), 1,1,0.8,0.8); + loadButton.setBackgroundColor(Color.TRANSPARENT); + loadButton.setBorderColor(Color.TRANSPARENT); + loadButton.setHoverImage(new ImageLoader("gui/button/slot_hover_background.png")); + loadButton.setMaxHeight(210); + buttonBox.addOverlays(loadButton); + } - } else { - // Bottom layout - } + VBox vBox = (VBox) buttonBox.getPane(); // Can cast because I know its a vertical box. + vBox.setAlignment(Pos.CENTER); + buttonBox.setSpacing(1); + if (index <= 3) { + topLayout.addChildLayout(buttonBox); } else { - // Process empty slot + bottomLayout.addChildLayout(buttonBox); } index++; } rootLayout.addChildLayout(topLayout); rootLayout.addChildLayout(bottomLayout); + rootLayout.setX(500); + rootLayout.setY(300); + + menu.addLayout(rootLayout); + + // Add Page buttons below. + // There should be 8 per view. + int pageViewMax = 8; + int pageIndex = 0; + HorizontalLayout pageLayout = new HorizontalLayout(100, 100); + while (pageIndex < pageViewMax) { + pageIndex++; + ButtonOverlay pageButton = new ButtonOverlay("page-" + pageIndex, pageIndex + "", new FontLoader(getConfiguration().getUiFont(), 26).getFont(), Color.BLACK, 1, 1); + pageButton.setBackgroundColor(Color.TRANSPARENT); + pageButton.setBorderColor(Color.TRANSPARENT); + if (page == index) { + pageButton.setTextFill(Color.RED); + } + pageButton.setHoverColor(Color.RED); + pageLayout.addOverlays(pageButton); + } + pageLayout.setX(1000); + pageLayout.setY(950); + menu.addLayout(pageLayout); return menu; } - public Menu buildLoadingScreen() { + public Menu buildSettingsMenu() { return null; } - public Menu buildSettingsScreen() { + public Menu buildAboutMenu() { + Menu menu = new Menu(1920, 1080, new ImageLoader("gui/overlay/main_menu.png")); - return null; - } + Font font = new FontLoader(getConfiguration().getDefaultFont().getFont(), 20).getFont(); - public Menu buildAboutScreen() { + TextFlowOverlay aboutText = new TextFlowOverlay("RenJava is inspired by RenPy and built with JavaFX. This project is free for commercial use and open sourced." + + "Credits to the contributors for JavaFX for making this project possible. Credits to RenPy for making the best visual novel engine.", 500, 500); + aboutText.setFont(font); + aboutText.setX(500); + aboutText.setY(300); - return null; + menu.addOverlay(aboutText); + + return menu; } /** @@ -580,11 +613,16 @@ public static RenJava getInstance() { * @param event Event to be executed. */ public static void callEvent(Event event) { - Collection lowestMethods = new HashSet<>(); - Collection lowMethods = new HashSet<>(); - Collection normalMethods = new HashSet<>(); - Collection highMethods = new HashSet<>(); - Collection highestMethods = new HashSet<>(); +// Collection lowestMethods = new HashSet<>(); +// Collection lowMethods = new HashSet<>(); +// Collection normalMethods = new HashSet<>(); +// Collection highMethods = new HashSet<>(); +// Collection highestMethods = new HashSet<>(); + Map lowestMethods = new HashMap<>(); + Map lowMethods = new HashMap<>(); + Map normalMethods = new HashMap<>(); + Map highMethods = new HashMap<>(); + Map highestMethods = new HashMap<>(); Collection eventListeners = new HashSet<>(getInstance().getRegisteredListeners()); for (Addon addon : getInstance().getAddonLoader().getAddons()) { @@ -605,11 +643,11 @@ public static void callEvent(Event event) { if (scan) { Listener listener1 = method.getAnnotation(Listener.class); switch (listener1.priority()) { - case HIGHEST -> highestMethods.add(method); - case HIGH -> highMethods.add(method); - case NORMAL -> normalMethods.add(method); - case LOW -> lowMethods.add(method); - case LOWEST -> lowestMethods.add(method); + case HIGHEST -> highestMethods.put(listener, method); + case HIGH -> highMethods.put(listener,method); + case NORMAL -> normalMethods.put(listener,method); + case LOW -> lowMethods.put(listener,method); + case LOWEST -> lowestMethods.put(listener,method); } } } @@ -617,27 +655,42 @@ public static void callEvent(Event event) { } // There has got to be a way to make this better. - for (Method method : highestMethods) { - invokeMethod(method, event); - } - for (Method method : highMethods) { - invokeMethod(method, event); - } - for (Method method : normalMethods) { - invokeMethod(method, event); - } - for (Method method : lowMethods) { - invokeMethod(method, event); - } - for (Method method : lowestMethods) { - invokeMethod(method, event); - } +// for (Method method : highestMethods) { +// invokeMethod(method, event); +// } +// for (Method method : highMethods) { +// invokeMethod(method, event); +// } +// for (Method method : normalMethods) { +// invokeMethod(method, event); +// } +// for (Method method : lowMethods) { +// invokeMethod(method, event); +// } +// for (Method method : lowestMethods) { +// invokeMethod(method, event); +// } + highestMethods.forEach((listener, method) -> { + invokeMethod(listener, method, event); + }); + highMethods.forEach((listener, method) -> { + invokeMethod(listener, method, event); + }); + normalMethods.forEach((listener, method) -> { + invokeMethod(listener, method, event); + }); + lowMethods.forEach((listener, method) -> { + invokeMethod(listener, method, event); + }); + lowestMethods.forEach((listener, method) -> { + invokeMethod(listener, method, event); + }); } - private static void invokeMethod(Method method, Event event) { + private static void invokeMethod(EventListener listener, Method method, Event event) { try { - method.invoke(method.getDeclaringClass().getDeclaredConstructor().newInstance(), event); - } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) { + method.invoke(listener, event); + } catch (IllegalAccessException e) { throw new RuntimeException(); } catch (InvocationTargetException e) { e.printStackTrace(); From a405bdf06f0f2adaa8a9093b68a36f0140213a35 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:22:24 -0500 Subject: [PATCH 02/39] Added function to check if a save file exists. --- src/main/java/me/piitex/renjava/api/saves/Save.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/saves/Save.java b/src/main/java/me/piitex/renjava/api/saves/Save.java index a793b30..5000989 100644 --- a/src/main/java/me/piitex/renjava/api/saves/Save.java +++ b/src/main/java/me/piitex/renjava/api/saves/Save.java @@ -39,6 +39,10 @@ public Save(int slot) { this.file = new File(System.getProperty("user.dir") + "/game/saves/save-" + slot + ".dat"); } + public boolean exists() { + return file.exists(); + } + // Writes save file public void write() { // First get all PersistentData to write. @@ -64,7 +68,7 @@ public void write() { if (mapSection != null) { System.out.println("Map Section: "); - System.out.println(mapSection.toString()); + System.out.println(mapSection); rootSection.addSubSection(mapSection); continue; @@ -331,7 +335,10 @@ public Pane buildPreview() { // Default image ImageLoader saveImage = new ImageLoader("gui/button/slot_idle_background.png"); try { - pane.getChildren().add(new ImageView(saveImage.build())); + ImageView view = new ImageView(saveImage.build()); + view.setFitHeight(419); + view.setFitWidth(309); + pane.getChildren().add(view); } catch (ImageNotFoundException e) { RenJava.getInstance().getLogger().severe(e.getMessage()); } From 0564153f92ebf4881182158cbd6b0db51fed981f Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:23:01 -0500 Subject: [PATCH 03/39] Added more customization to the choice scene. --- .../api/scenes/types/choices/ChoiceScene.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java index 848c89d..39bf4b5 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java @@ -16,6 +16,7 @@ import me.piitex.renjava.gui.exceptions.ImageNotFoundException; import me.piitex.renjava.gui.layouts.impl.VerticalLayout; import me.piitex.renjava.gui.overlay.ButtonOverlay; +import org.jetbrains.annotations.NotNull; import java.util.LinkedHashSet; import java.util.Map; @@ -63,7 +64,7 @@ * @see ChoiceSelectInterface */ public class ChoiceScene extends RenScene { - private ImageLoader backgroundImage; + private final ImageLoader backgroundImage; private ChoiceSelectInterface selectInterface; @@ -151,8 +152,6 @@ public Menu build(boolean ui) { if (ui) { VerticalLayout layout = new VerticalLayout(500, 500); - //layout.setX(((double) (RenJava.getInstance().getConfiguration().getWidth() - layout.getWidth()) / 2) - 600); - //layout.setY(((double) (RenJava.getInstance().getConfiguration().getHeight() - layout.getHeight()) / 2) - 200); Map.Entry midPoint = RenJava.getInstance().getConfiguration().getMidPoint(); System.out.println("Set X: " + midPoint.getKey()); System.out.println("Set Y: " + midPoint.getValue()); @@ -161,6 +160,10 @@ public Menu build(boolean ui) { layout.setSpacing(20.0); ImageLoader choiceBoxImage = new ImageLoader("gui/button/choice_idle_background.png"); + int scrollStart = 5; + if (choices.size() > scrollStart) { + layout.setScrollbar(true); + } for (Choice choice : choices) { ButtonOverlay buttonOverlay; try { @@ -169,6 +172,7 @@ public Menu build(boolean ui) { } catch (ImageNotFoundException e) { RenJava.getInstance().getLogger().severe(e.getMessage()); } + } menu.addLayout(layout); } @@ -185,12 +189,7 @@ public void render(Menu menu) { } private Button getChoiceButton(Choice choice, Image image) { - ButtonOverlay buttonOverlay = new ButtonOverlay(choice.getId(), choice.getText(), RenJava.getInstance().getConfiguration().getDefaultFont().getFont(), Color.BLACK, 0, 0, 1, 1); - buttonOverlay.setBorderColor(Color.TRANSPARENT); - buttonOverlay.setBackgroundColor(Color.TRANSPARENT); - buttonOverlay.setHover(true); - buttonOverlay.setTextFill(Color.WHITE); - buttonOverlay.setHoverColor(Color.BLUE); + ButtonOverlay buttonOverlay = getButtonOverlay(choice); ChoiceButtonBuildEvent choiceButtonBuildEvent = new ChoiceButtonBuildEvent(buttonOverlay); @@ -213,4 +212,15 @@ private Button getChoiceButton(Choice choice, Image image) { }); return button; } + + @NotNull + private static ButtonOverlay getButtonOverlay(Choice choice) { + ButtonOverlay buttonOverlay = new ButtonOverlay(choice.getId(), choice.getText(), RenJava.getInstance().getConfiguration().getChoiceButtonFont().getFont(), Color.BLACK, 0, 0, 1, 1); + buttonOverlay.setBorderColor(Color.TRANSPARENT); + buttonOverlay.setBackgroundColor(Color.TRANSPARENT); + buttonOverlay.setHover(true); + buttonOverlay.setTextFill(RenJava.getInstance().getConfiguration().getChoiceButtonColor()); //TODO: Make this configurable + buttonOverlay.setHoverColor(RenJava.getInstance().getConfiguration().getHoverColor()); + return buttonOverlay; + } } From 69ef3c27cec76a12b3b2c034a219f15fe25e9c63 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:24:47 -0500 Subject: [PATCH 04/39] Code cleanup --- .../piitex/renjava/api/saves/data/Mapper.java | 69 +++++++++++++++++++ .../types/TranslationTransition.java | 9 ++- .../api/scenes/types/AutoPlayScene.java | 2 +- .../configuration/SettingsProperties.java | 4 +- .../defaults/GameFlowEventListener.java | 2 +- .../java/me/piitex/renjava/gui/Element.java | 1 + .../java/me/piitex/renjava/gui/StageType.java | 2 +- .../gui/layouts/impl/HorizontalLayout.java | 1 - .../renjava/gui/overlay/ImageOverlay.java | 4 +- 9 files changed, 84 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/saves/data/Mapper.java b/src/main/java/me/piitex/renjava/api/saves/data/Mapper.java index 9916f7f..acbaa47 100644 --- a/src/main/java/me/piitex/renjava/api/saves/data/Mapper.java +++ b/src/main/java/me/piitex/renjava/api/saves/data/Mapper.java @@ -1,10 +1,79 @@ package me.piitex.renjava.api.saves.data; +import me.piitex.renjava.api.saves.file.SectionKeyValue; + import java.util.HashMap; import java.util.Map; public class Mapper { + public enum MapperEnum { + STRING_STRING, + STRING_INT, + STRING_BOOLEAN, + STRING_DOUBLE, + STRING_LONG, + STRING_FLOAT, + STRING_SHORT, + STRING_BYTE, + INT_STRING, + INT_BOOLEAN, + INT_INT, + INT_DOUBLE, + INT_LONG, + INT_FLOAT, + INT_SHORT, + INT_BYTE, + DOUBLE_STRING, + DOUBLE_BOOLEAN, + DOUBLE_INT, + DOUBLE_DOUBLE, + DOUBLE_LONG, + DOUBLE_FLOAT, + DOUBLE_SHORT, + DOUBLE_BYTE, + BYTE_STRING, + BYTE_BOOLEAN, + BYTE_INT, + BYTE_DOUBLE, + BYTE_LONG, + BYTE_FLOAT, + BYTE_SHORT, + BYTE_BYTE + } + + public static MapperEnum getType(String typeName) { + typeName = typeName.replace("java.util.Map<", ""); + + // + typeName = typeName.replace("java.lang.", ""); + // + + String[] typeSplit = typeName.replace("<", "").replace(">", "").split(","); + //String + //Integer + + + // Conversion is required as the map needs to be set to the actual type in order to save it. + String key = typeSplit[0]; + String value = typeSplit[1]; + + return MapperEnum.valueOf(key.toUpperCase() + "_" + value.toUpperCase()); + } + + public static void processMap(MapperEnum mapType, Map genericMap, SectionKeyValue mapSection) { + switch (mapType) { + case STRING_STRING -> { + Map map = new HashMap<>(); + genericMap.forEach((o, o2) -> { + map.put((String) o, (String) o2); + }); + + map.forEach(mapSection::addKeyValue); + } + } + } + public static Map toStringMap(Map map) { Map toReturn = new HashMap<>(); map.entrySet().forEach(objectObjectEntry -> { diff --git a/src/main/java/me/piitex/renjava/api/scenes/transitions/types/TranslationTransition.java b/src/main/java/me/piitex/renjava/api/scenes/transitions/types/TranslationTransition.java index 9fcfc5f..a9e5067 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/transitions/types/TranslationTransition.java +++ b/src/main/java/me/piitex/renjava/api/scenes/transitions/types/TranslationTransition.java @@ -6,9 +6,12 @@ import me.piitex.renjava.api.scenes.transitions.Transitions; public class TranslationTransition extends Transitions { - private double byX, byY; - private double fromX, fromY; - private double toX, toY; + private final double byX; + private final double byY; + private final double fromX; + private final double fromY; + private final double toX; + private final double toY; private TranslationTransition transition; diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java index 0a472dd..bedeaab 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java @@ -35,7 +35,7 @@ public Menu build(boolean ui) { @Override public void render(Menu menu) { System.out.println("Rendering: " + getId()); - menu.render(null, this); + menu.render(); renJava.setStage(renJava.getStage(), StageType.IMAGE_SCENE); SceneStartEvent event = new SceneStartEvent(this); diff --git a/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java b/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java index 13b777f..a533500 100644 --- a/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java +++ b/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java @@ -1,5 +1,7 @@ package me.piitex.renjava.configuration; +import me.piitex.renjava.RenJava; + import java.io.*; import java.util.Properties; @@ -91,7 +93,7 @@ private void write(String key, String value) { properties.store(outputStream, null); outputStream.close(); } catch (IOException e) { - e.printStackTrace(); + RenJava.getInstance().getLogger().severe("Could not write to settings file: " + e.getMessage()); } } } diff --git a/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java index e7ba27b..2b1e5d2 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java @@ -75,7 +75,7 @@ public void onMouseClick(MouseClickEvent event) { MainMenuBuildEvent buildEvent = new MainMenuBuildEvent(menu); RenJava.callEvent(buildEvent); - menu.render(null, null); + menu.render(); player.setRightClickMenu(true); MainMenuRenderEvent renderEvent = new MainMenuRenderEvent(menu, true); diff --git a/src/main/java/me/piitex/renjava/gui/Element.java b/src/main/java/me/piitex/renjava/gui/Element.java index 5686ea6..daef454 100644 --- a/src/main/java/me/piitex/renjava/gui/Element.java +++ b/src/main/java/me/piitex/renjava/gui/Element.java @@ -38,6 +38,7 @@ public Element(Overlay overlay) { Button button = buttonOverlay.build(); button.setTranslateX(buttonOverlay.x()); button.setTranslateY(buttonOverlay.y()); + System.out.println("Rendering button: " + buttonOverlay.getId()); this.node = button; } else if (overlay instanceof TextFlowOverlay textFlowOverlay) { TextFlow textFlow = textFlowOverlay.build(); diff --git a/src/main/java/me/piitex/renjava/gui/StageType.java b/src/main/java/me/piitex/renjava/gui/StageType.java index 299d8b3..8fdbe62 100644 --- a/src/main/java/me/piitex/renjava/gui/StageType.java +++ b/src/main/java/me/piitex/renjava/gui/StageType.java @@ -10,5 +10,5 @@ public enum StageType { ANIMATION_SCENE, INTERACTABLE_SCENE, INPUT_SCENE, - CHOICE_SCENE, + CHOICE_SCENE, SAVE_MENU, } diff --git a/src/main/java/me/piitex/renjava/gui/layouts/impl/HorizontalLayout.java b/src/main/java/me/piitex/renjava/gui/layouts/impl/HorizontalLayout.java index 44168f8..08b92be 100644 --- a/src/main/java/me/piitex/renjava/gui/layouts/impl/HorizontalLayout.java +++ b/src/main/java/me/piitex/renjava/gui/layouts/impl/HorizontalLayout.java @@ -7,7 +7,6 @@ * Groups overlays and elements horizontally. */ public class HorizontalLayout extends Layout { - // Overlays are ordered based on insertion. The first overlay added is the first one to be displayed in the layout. public HorizontalLayout(int width, int height) { diff --git a/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java index 4e8584b..21ec57f 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java @@ -8,8 +8,8 @@ public class ImageOverlay implements Overlay { private final Image image; - private double x; - private double y; + private final double x; + private final double y; private final String fileName; private Transitions transitions; From 8b14783ef90fae0189459b2bd20119d849428fbf Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:25:39 -0500 Subject: [PATCH 05/39] Framework no longer requires a super method and is now based on annotations. --- src/main/java/me/piitex/renjava/Game.java | 26 +++++++++++---- src/main/java/me/piitex/renjava/Launch.java | 23 ++++++++++--- src/main/java/me/piitex/renjava/RenJava.java | 23 ++----------- .../renjava/configuration/Configuration.java | 33 +++++++++++++++++++ 4 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 src/main/java/me/piitex/renjava/configuration/Configuration.java diff --git a/src/main/java/me/piitex/renjava/Game.java b/src/main/java/me/piitex/renjava/Game.java index 89da13f..812254f 100644 --- a/src/main/java/me/piitex/renjava/Game.java +++ b/src/main/java/me/piitex/renjava/Game.java @@ -6,12 +6,24 @@ import java.lang.annotation.Target; /** - * Used to set default information about the game. Use this annotation to tag the ReJava class constructor. + * Annotation used to set default information about the game. + * Use this annotation to tag the ReJava class constructor. */ -@Target(ElementType.CONSTRUCTOR) -@Retention(value = RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) public @interface Game { - String name() default ("Name"); - String author() default("Author"); - String version() default("1.0"); -} + /** + * The name of the game. + */ + String name(); + + /** + * The author of the game. + */ + String author(); + + /** + * The version of the game. + */ + String version(); +} \ No newline at end of file diff --git a/src/main/java/me/piitex/renjava/Launch.java b/src/main/java/me/piitex/renjava/Launch.java index a7a69b7..ea72d25 100644 --- a/src/main/java/me/piitex/renjava/Launch.java +++ b/src/main/java/me/piitex/renjava/Launch.java @@ -8,6 +8,9 @@ import java.util.Arrays; import java.util.Collection; +import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.configuration.Configuration; +import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.gui.GuiLoader; import org.reflections.Reflections; import org.reflections.scanners.Scanners; @@ -37,23 +40,35 @@ public static void main(String[] args) { try { Object o = c.getDeclaredConstructor().newInstance(); RenJava renJava = (RenJava) o; - if (c.getDeclaredConstructor().isAnnotationPresent(Game.class)) { - Game game = c.getDeclaredConstructor().getAnnotation(Game.class); + if (renJava.getClass().isAnnotationPresent(Game.class)) { + Game game = renJava.getClass().getAnnotation(Game.class); renJava.name = game.name(); renJava.author = game.author(); renJava.version = game.version(); } else { - System.err.println("Please annotate your main constructor with Game.\n\t\t@Game\n\t\tpublic void " + c.getDeclaredConstructor().getName() + "() { }"); + System.err.println("ERROR: Please annotate your main class with 'Game'."); renJava.name = "Error"; renJava.author = "Error"; renJava.version = "Error"; } + + // Build configuration + if (renJava.getClass().isAnnotationPresent(Configuration.class)) { + Configuration conf = renJava.getClass().getAnnotation(Configuration.class); + RenJavaConfiguration configuration = new RenJavaConfiguration(conf.title().replace("{version}", renJava.version).replace("{name}", renJava.name), conf.width(), conf.height(), new ImageLoader(conf.windowIconPath())); + renJava.setConfiguration(configuration); + } else { + System.err.println("ERROR: Configuration annotation not found. Please annotate your main class with 'Configuration'"); + RenJavaConfiguration configuration = new RenJavaConfiguration("Error", 1920, 1080, new ImageLoader("gui/window_icon.png")); + renJava.setConfiguration(configuration); + } + renJava.init(); // Initialize game launch(args); //c.getDeclaredConstructor().newInstance(); } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { - e.printStackTrace(); + System.err.println("ERROR: Could initialize the RenJava framework: " + e.getMessage()); } return; } diff --git a/src/main/java/me/piitex/renjava/RenJava.java b/src/main/java/me/piitex/renjava/RenJava.java index ebdcaa6..b251718 100644 --- a/src/main/java/me/piitex/renjava/RenJava.java +++ b/src/main/java/me/piitex/renjava/RenJava.java @@ -613,11 +613,6 @@ public static RenJava getInstance() { * @param event Event to be executed. */ public static void callEvent(Event event) { -// Collection lowestMethods = new HashSet<>(); -// Collection lowMethods = new HashSet<>(); -// Collection normalMethods = new HashSet<>(); -// Collection highMethods = new HashSet<>(); -// Collection highestMethods = new HashSet<>(); Map lowestMethods = new HashMap<>(); Map lowMethods = new HashMap<>(); Map normalMethods = new HashMap<>(); @@ -654,22 +649,8 @@ public static void callEvent(Event event) { } } - // There has got to be a way to make this better. -// for (Method method : highestMethods) { -// invokeMethod(method, event); -// } -// for (Method method : highMethods) { -// invokeMethod(method, event); -// } -// for (Method method : normalMethods) { -// invokeMethod(method, event); -// } -// for (Method method : lowMethods) { -// invokeMethod(method, event); -// } -// for (Method method : lowestMethods) { -// invokeMethod(method, event); -// } + //FIXME: I'm pretty sure ths is in the wrong order. Low method should be called first, high method called last. Needs some testing and debating before + // Determining the final order. highestMethods.forEach((listener, method) -> { invokeMethod(listener, method, event); }); diff --git a/src/main/java/me/piitex/renjava/configuration/Configuration.java b/src/main/java/me/piitex/renjava/configuration/Configuration.java new file mode 100644 index 0000000..83b01a5 --- /dev/null +++ b/src/main/java/me/piitex/renjava/configuration/Configuration.java @@ -0,0 +1,33 @@ +package me.piitex.renjava.configuration; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to define configuration settings for the application window. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Configuration { + /** + * The title of the application window. + */ + String title(); + + /** + * The width of the base resolution. + */ + int width(); + + /** + * The height of the base resolution. + */ + int height(); + + /** + * The file path for the window icon. Default value is "gui/window_icon.png". + */ + String windowIconPath() default "gui/window_icon.png"; +} \ No newline at end of file From b82a1245360016319dfea620dc0b862f7403c96a Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:26:30 -0500 Subject: [PATCH 06/39] Separated layout rendering from the menu function. --- src/main/java/me/piitex/renjava/gui/Menu.java | 56 ++++++------------- .../me/piitex/renjava/gui/layouts/Layout.java | 52 +++++++++++++++++ 2 files changed, 69 insertions(+), 39 deletions(-) diff --git a/src/main/java/me/piitex/renjava/gui/Menu.java b/src/main/java/me/piitex/renjava/gui/Menu.java index 3f08c94..f675e10 100644 --- a/src/main/java/me/piitex/renjava/gui/Menu.java +++ b/src/main/java/me/piitex/renjava/gui/Menu.java @@ -36,10 +36,10 @@ public class Menu { private Image backgroundImage; private final LinkedHashSet nodes = new LinkedHashSet<>(); - private final LinkedHashSet parents = new LinkedHashSet<>(); private final LinkedHashSet layouts = new LinkedHashSet<>(); private final LinkedHashSet overlays = new LinkedHashSet<>(); private final LinkedHashSet children = new LinkedHashSet<>(); + private final LinkedHashSet subPanes = new LinkedHashSet<>(); // Constants private static final RenJava renJava = RenJava.getInstance(); @@ -55,7 +55,7 @@ public Menu(double width, double height, ImageLoader imageLoader) { try { this.backgroundImage = imageLoader.build(); } catch (ImageNotFoundException e) { - e.printStackTrace(); + renJava.getLogger().severe(e.getMessage()); } } this.width = width; @@ -134,16 +134,17 @@ public Menu addOverlay(Overlay overlay) { return this; } - public LinkedHashSet getParents() { - return parents; + public LinkedHashSet getChildren() { + return children; } - public void addParent(LayoutMenu layoutMenu) { - parents.add(layoutMenu); + public LinkedHashSet getSubPanes() { + return subPanes; } - public LinkedHashSet getChildren() { - return children; + public Menu addSubPane(Pane pane) { + subPanes.add(pane); + return this; } /* Rendering functions */ @@ -158,6 +159,10 @@ public Menu addMenu(Menu menu) { return this; } + public Pane render() { + return render(null, null); + } + /** * Renders the menu on the screen. * @@ -186,43 +191,16 @@ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { logger.info("Rendering layouts..."); for (Layout layout : layouts) { - for (Overlay overlay : layout.getOverlays()) { - new Element(overlay).render(layout.getPane()); - } - for (Layout child : layout.getChildLayouts()) { - // A child layout should be added to a main layout. - for (Overlay overlay : child.getOverlays()) { - new Element(overlay).render(child.getPane()); - } - - Pane childPane = layout.getPane(); - childPane.setTranslateX(child.getX()); - childPane.setTranslateY(child.getY()); - childPane.setPrefSize(child.getWidth(), child.getHeight()); - if (childPane instanceof HBox hBox) { - hBox.setSpacing(layout.getSpacing()); - } else if (childPane instanceof VBox vBox) { - vBox.setSpacing(layout.getSpacing()); - } - layout.getPane().getChildren().add(childPane); // Adds the child layout to the main layout. - } - Pane box = layout.getPane(); - box.setTranslateX(layout.getX()); - box.setTranslateY(layout.getY()); - box.setPrefSize(layout.getWidth(), layout.getHeight()); - if (box instanceof HBox hBox) { - hBox.setSpacing(layout.getSpacing()); - } else if (box instanceof VBox vBox) { - vBox.setSpacing(layout.getSpacing()); - } - - root.getChildren().add(box); + layout.render(root); } for (Overlay overlay : overlays) { new Element(overlay).render(root); } + for (Pane sub : subPanes) { + root.getChildren().add(sub); + } for (Menu menu : children) { if (menu != null) { diff --git a/src/main/java/me/piitex/renjava/gui/layouts/Layout.java b/src/main/java/me/piitex/renjava/gui/layouts/Layout.java index 280da3e..fdb205f 100644 --- a/src/main/java/me/piitex/renjava/gui/layouts/Layout.java +++ b/src/main/java/me/piitex/renjava/gui/layouts/Layout.java @@ -1,6 +1,11 @@ package me.piitex.renjava.gui.layouts; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; +import javafx.scene.layout.VBox; +import me.piitex.renjava.gui.Element; import me.piitex.renjava.gui.overlay.Overlay; import java.util.Collection; @@ -13,12 +18,43 @@ public abstract class Layout { private double y; private int width, height; private double spacing; + private boolean scrollbar = false; private final LinkedHashSet overlays = new LinkedHashSet<>(); private final LinkedHashSet childLayouts = new LinkedHashSet<>(); + private final LinkedHashSet subPanes = new LinkedHashSet<>(); protected Layout(Pane pane) { this.pane = pane; } + + public void render(Pane root) { + for (Overlay overlay : getOverlays()) { + // Check if the layout should be a scroll pane. + if (isScrollbar()) { + ScrollPane scrollPane = new ScrollPane(pane); + BorderPane subRoot = new BorderPane(scrollPane); + root.getChildren().add(subRoot); // Adds as border (could be wrong) + } + new Element(overlay).render(pane); + } + for (Pane sub : subPanes) { + pane.getChildren().add(sub); + } + pane.setTranslateX(x); + pane.setTranslateY(y); + pane.setPrefSize(width, height); + if (pane instanceof HBox hBox) { + hBox.setSpacing(spacing); + } else if (pane instanceof VBox vBox) { + vBox.setSpacing(spacing); + } + + root.getChildren().add(pane); + + for (Layout child : childLayouts) { + child.render(pane); + } + } public Pane getPane() { return pane; @@ -64,6 +100,14 @@ public void setSpacing(double spacing) { this.spacing = spacing; } + public boolean isScrollbar() { + return scrollbar; + } + + public void setScrollbar(boolean scrollbar) { + this.scrollbar = scrollbar; + } + public Collection getOverlays() { return overlays; } @@ -79,4 +123,12 @@ public void addChildLayout(Layout layout) { public LinkedHashSet getChildLayouts() { return childLayouts; } + + public LinkedHashSet getSubPanes() { + return subPanes; + } + + public void addSubPane(Pane pane) { + subPanes.add(pane); + } } From f0178692e44ba54e280fab286e1f03ea85bf73ae Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:26:58 -0500 Subject: [PATCH 07/39] Added string parameters to TextOverlay. --- .../renjava/gui/overlay/TextOverlay.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java index 17f7959..94db2d6 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java @@ -8,10 +8,24 @@ public class TextOverlay implements Overlay { private final Text text; private FontLoader fontLoader; - private double x; - private double y; + private final double x; + private final double y; private Transitions transitions; + public TextOverlay(String text, double x, double y) { + this.text = new Text(text); + this.x = x; + this.y = y; + } + + public TextOverlay(String text, FontLoader fontLoader, double x, double y) { + this.text = new Text(text); + this.fontLoader = fontLoader; + this.x = x; + this.y = y; + } + + public TextOverlay(Text text, double x, double y) { this.text = text; this.x = x; From 5409554b2b27c9018c974bc2c5acef2544c151ef Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:27:29 -0500 Subject: [PATCH 08/39] Added functionality to change the image of button during hover event. --- .../renjava/gui/overlay/ButtonOverlay.java | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java index 48b176f..2774002 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java @@ -5,6 +5,7 @@ import javafx.scene.image.ImageView; import javafx.scene.paint.Color; import javafx.scene.text.Font; +import javafx.scene.text.TextAlignment; import me.piitex.renjava.RenJava; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; @@ -25,11 +26,13 @@ public class ButtonOverlay implements Overlay { private Color backgroundColor; private Color borderColor; private Color hoverColor; + private ImageLoader hoverImage; private boolean hover; private int borderWidth = 0; private int backgroundRadius = 0; private double x = 1, y = 1; + private int maxHeight = 0, maxWidth = 0; private final double xScale, yScale; public ButtonOverlay(String id, String text, Color textFill, double xScale, double yScale) { @@ -262,6 +265,16 @@ public Color getHoverColor() { public void setHoverColor(Color hoverColor) { this.hoverColor = hoverColor; + this.hover = true; + } + + public ImageLoader getHoverImage() { + return hoverImage; + } + + public void setHoverImage(ImageLoader hoverImage) { + this.hoverImage = hoverImage; + this.hover = true; } public boolean isHover() { @@ -306,6 +319,22 @@ public void setY(double y) { this.y = y; } + public int getMaxHeight() { + return maxHeight; + } + + public void setMaxHeight(int maxHeight) { + this.maxHeight = maxHeight; + } + + public int getMaxWidth() { + return maxWidth; + } + + public void setMaxWidth(int maxWidth) { + this.maxWidth = maxWidth; + } + @Override public Transitions getTransition() { return transitions; @@ -345,6 +374,12 @@ public Button build() { if (textFill != null) { button.setTextFill(textFill); } + if (maxHeight > 0) { + button.setMaxHeight(maxHeight); + } + if (maxWidth > 0) { + button.setMaxWidth(maxWidth); + } String inLine = ""; if (backgroundColor != null) { inLine += "-fx-background-color: " + cssColor(backgroundColor) + "; "; @@ -359,12 +394,24 @@ public Button build() { if (hover) { AtomicReference attomicInLine = new AtomicReference<>(inLine); button.setOnMouseEntered(mouseEvent -> { - button.setTextFill(hoverColor); - button.setStyle(attomicInLine.get()); + if (hoverColor != null) { + button.setTextFill(hoverColor); + button.setStyle(attomicInLine.get()); + } + if (hoverImage != null) { + try { + button.setGraphic(new ImageView(hoverImage.build())); + } catch (ImageNotFoundException e) { + RenJava.getInstance().getLogger().severe(e.getMessage()); + } + } }); button.setOnMouseExited(mouseEvent -> { button.setTextFill(textFill); button.setStyle(attomicInLine.get()); + if (image != null) { + button.setGraphic(new ImageView(image)); + } }); } @@ -385,13 +432,12 @@ public Button build() { } // Helper css function - public String cssColor(Color color) { - String webFormat = String.format("rgba(%d, %d, %d, %f)", + private String cssColor(Color color) { + return String.format("rgba(%d, %d, %d, %f)", (int) (255 * color.getRed()), (int) (255 * color.getGreen()), (int) (255 * color.getBlue()), color.getOpacity()); - return webFormat; } public static ButtonOverlay copyOf(String id, ButtonOverlay builder) { From b6977a2dbaeaaa7c5770670a54e505ab50b08aea Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:27:51 -0500 Subject: [PATCH 09/39] Removed unnecessary gui classes. --- .../me/piitex/renjava/gui/LayoutMenu.java | 92 ------------------- .../renjava/gui/layouts/ScrollPaneMenu.java | 25 ----- 2 files changed, 117 deletions(-) delete mode 100644 src/main/java/me/piitex/renjava/gui/LayoutMenu.java delete mode 100644 src/main/java/me/piitex/renjava/gui/layouts/ScrollPaneMenu.java diff --git a/src/main/java/me/piitex/renjava/gui/LayoutMenu.java b/src/main/java/me/piitex/renjava/gui/LayoutMenu.java deleted file mode 100644 index 5419058..0000000 --- a/src/main/java/me/piitex/renjava/gui/LayoutMenu.java +++ /dev/null @@ -1,92 +0,0 @@ -package me.piitex.renjava.gui; - -import javafx.scene.Node; -import me.piitex.renjava.gui.layouts.Layout; -import me.piitex.renjava.gui.overlay.Overlay; - -import java.util.LinkedHashSet; - -public abstract class LayoutMenu { - private final Menu menu; - private final int width, height; - private int x, y; - - private final LinkedHashSet nodes = new LinkedHashSet<>(); - private final LinkedHashSet layouts = new LinkedHashSet<>(); - private final LinkedHashSet overlays = new LinkedHashSet<>(); - private final LinkedHashSet children = new LinkedHashSet<>(); - - public LayoutMenu(Menu menu, int width, int height) { - this.menu = menu; - this.width = width; - this.height = height; - menu.addParent(this); - } - - public Menu getMenu() { - return menu; - } - - public abstract void render(); - - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public int getY() { - return y; - } - - public void setY(int y) { - this.y = y; - } - - public LinkedHashSet getNodes() { - return nodes; - } - - public void addNode(Node node) { - this.nodes.add(node); - } - - public LinkedHashSet getLayouts() { - return layouts; - } - - public LayoutMenu addLayout(Layout layout) { - layouts.add(layout); - return this; - } - - public LinkedHashSet getOverlays() { - return overlays; - } - - public LayoutMenu addOverlay(Overlay overlay) { - overlays.add(overlay); - return this; - } - - public LinkedHashSet getChildren() { - return children; - } - - /* Rendering functions */ - - public LayoutMenu addMenu(Menu menu) { - this.children.add(menu); - return this; - } -} diff --git a/src/main/java/me/piitex/renjava/gui/layouts/ScrollPaneMenu.java b/src/main/java/me/piitex/renjava/gui/layouts/ScrollPaneMenu.java deleted file mode 100644 index 80aa92a..0000000 --- a/src/main/java/me/piitex/renjava/gui/layouts/ScrollPaneMenu.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.piitex.renjava.gui.layouts; - -import javafx.scene.control.ScrollPane; -import javafx.scene.layout.Pane; - -import me.piitex.renjava.gui.Menu; -import me.piitex.renjava.gui.LayoutMenu; - -public class ScrollPaneMenu extends LayoutMenu { - - public ScrollPaneMenu(Menu menu, int width, int height) { - super(menu, width, height); - } - - @Override - public void render() { - Pane pane = getMenu().getPane(); - ScrollPane scrollPane = new ScrollPane(); - scrollPane.setPrefSize(getWidth(), getHeight()); - scrollPane.setTranslateX(getX()); - scrollPane.setTranslateY(getY()); - - pane.getChildren().add(scrollPane); // Adds to menu - } -} From 2981cbdf5f2edc8b5ad2414e846194d3a12622a2 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:28:23 -0500 Subject: [PATCH 10/39] Separated logging checks. --- .../java/me/piitex/renjava/gui/GuiLoader.java | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/main/java/me/piitex/renjava/gui/GuiLoader.java b/src/main/java/me/piitex/renjava/gui/GuiLoader.java index 1a4e8f4..c26ffbb 100644 --- a/src/main/java/me/piitex/renjava/gui/GuiLoader.java +++ b/src/main/java/me/piitex/renjava/gui/GuiLoader.java @@ -9,6 +9,7 @@ import me.piitex.renjava.RenJava; import me.piitex.renjava.api.builders.FontLoader; import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.events.types.*; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; @@ -41,7 +42,7 @@ private void buildSplashScreen() { return; // Don't create a splash screen if one wasn't set. } - menu.render(null, null); + menu.render(); PauseTransition wait = new PauseTransition(Duration.seconds(3)); // TODO: 2/17/2024 Make this configurable. wait.setOnFinished(actionEvent -> { stage.close(); // Closes stage for the splash screen (required) @@ -65,12 +66,36 @@ private void buildMainMenu() { // Gonna put some default checks here. // If there is no default font set one - if (renJava.getConfiguration().getDefaultFont() == null) { - renJava.getLogger().severe("No default font set."); +// if (renJava.getConfiguration().getDefaultFont() == null) { +// renJava.getLogger().severe("No default font set."); +// renJava.getConfiguration().setDefaultFont(new FontLoader("Arial", 24)); +// renJava.getConfiguration().setUiFont(new FontLoader("Arial", 26)); +// renJava.getConfiguration().setCharacterDisplayFont(new FontLoader("Arial", 26)); +// renJava.getConfiguration().setChoiceButtonFont(new FontLoader("Arial", 28)); +// } + RenJavaConfiguration configuration = renJava.getConfiguration(); + if (configuration.getDefaultFont() == null) { + renJava.getLogger().severe("Default font not set."); renJava.getConfiguration().setDefaultFont(new FontLoader("Arial", 24)); + } + if (configuration.getUiFont() == null) { + renJava.getLogger().severe("UI font not set."); renJava.getConfiguration().setUiFont(new FontLoader("Arial", 26)); + } + if (configuration.getCharacterDisplayFont() == null) { + renJava.getLogger().warning("Character display font not set."); renJava.getConfiguration().setCharacterDisplayFont(new FontLoader("Arial", 26)); } + if (configuration.getDialogueFont() == null) { + renJava.getLogger().warning("Dialogue font not set."); + renJava.getConfiguration().setDialogueFont(new FontLoader("Arial", 26)); + } + if (configuration.getChoiceButtonFont() == null) { + renJava.getLogger().warning("Choice button font not set."); + renJava.getConfiguration().setChoiceButtonFont(new FontLoader("Arial", 28)); + } + + stage = new Stage(); renJava.buildStage(stage); // Builds the stage parameters (Game Window) @@ -100,7 +125,7 @@ private void buildMainMenu() { MainMenDispatchEvent dispatchEvent = new MainMenDispatchEvent(menu); RenJava.callEvent(dispatchEvent); - menu.render(null, null); + menu.render(); MainMenuRenderEvent renderEvent = new MainMenuRenderEvent(menu); RenJava.callEvent(renderEvent); From d6a7bfe510e452eca33c0fa73a2444ae752c6a7b Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:28:52 -0500 Subject: [PATCH 11/39] Implemented saving and loading button handlers. --- .../defaults/MenuClickEventListener.java | 86 +++++++++++++------ 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java index fc77b39..67d1317 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java @@ -12,6 +12,7 @@ import me.piitex.renjava.events.types.ButtonClickEvent; import me.piitex.renjava.events.types.GameStartEvent; import me.piitex.renjava.gui.Menu; +import me.piitex.renjava.gui.StageType; public class MenuClickEventListener implements EventListener { private static final RenJava renJava = RenJava.getInstance(); @@ -32,49 +33,82 @@ public void onButtonClick(ButtonClickEvent event) { } if (button.getId().equalsIgnoreCase("menu-load-button")) { // NOTE: 10/20/2023 new LoadScreenView(new ImageLoader("gui/overlay/game_menu.png")).build(renJava.getStage(), true); - new Save(1).load(true); - - - // After loading play the current scene and story - String storyID = renJava.getPlayer().getCurrentStoryID(); - if (storyID == null) { - renJava.getLogger().severe("Save file could not be loaded. The data is either not formatted or corrupted."); - return; - } - - System.out.println("Story: " + renJava.getPlayer().getCurrentStoryID()); - - renJava.createStory(); - - // Force update fields - renJava.getPlayer().setCurrentStory(storyID); - renJava.getPlayer().getCurrentStory().init(); // Re-initialize story - - renJava.getPlayer().setCurrentScene(renJava.getPlayer().getCurrentSceneID()); - - renJava.getPlayer().getCurrentStory().displayScene(renJava.getPlayer().getCurrentSceneID()); + Menu menu = renJava.buildLoadMenu(1); // Builds first page + menu.addMenu(renJava.buildSideMenu()); + menu.render(); + renJava.setStage(renJava.getStage(), StageType.LOAD_MENU); // Update stage type } if (button.getId().equalsIgnoreCase("menu-preference-button")) { //new PreferenceScreenView(new ImageLoader("gui/overlay/game_menu.png")).build(renJava.getStage(), true); - Menu settings = renJava.buildSettingsScreen(); + Menu settings = renJava.buildSettingsMenu(); settings.addMenu(renJava.buildSideMenu()); - settings.render(null, null); + settings.render(); } if (button.getId().equalsIgnoreCase("menu-about-button")) { - Menu about = renJava.buildAboutScreen(); + Menu about = renJava.buildAboutMenu(); about.addMenu(renJava.buildSideMenu()); - about.render(null, null); + about.render(); + renJava.setStage(renJava.getStage(), StageType.ABOUT_MENU); } if (button.getId().equalsIgnoreCase("menu-save-button")) { //new Save(1, renJava.getPlayer().getCurrentStory().getId(), renJava.getPlayer().getCurrentScene().getId()); - new Save(1).write(); // Writes the save. + Menu menu = renJava.buildLoadMenu(1); // Builds first page + menu.addMenu(renJava.buildSideMenu()); + menu.render(); + + renJava.setStage(renJava.getStage(), StageType.SAVE_MENU); } if (button.getId().equalsIgnoreCase("menu-quit-button")) { renJava.getAddonLoader().disable(); Platform.exit(); } + + // Handle loading and saving buttons + if (renJava.getStageType() == StageType.LOAD_MENU) { + // Loading + if (button.getId().contains("save-")) { + int slot = Integer.parseInt(button.getId().replace("save-", "")); + Save save = new Save(slot); + if (!save.exists()) { + renJava.getLogger().warning("Save file does not exist."); + return; + } + + save.load(true); + + String storyID = renJava.getPlayer().getCurrentStoryID(); + if (storyID == null) { + renJava.getLogger().severe("Save file could not be loaded. The data is either not formatted or corrupted."); + return; + } + + System.out.println("Story: " + renJava.getPlayer().getCurrentStoryID()); + + renJava.createStory(); + + // Force update fields + renJava.getPlayer().setCurrentStory(storyID); + renJava.getPlayer().getCurrentStory().init(); // Re-initialize story + + renJava.getPlayer().setCurrentScene(renJava.getPlayer().getCurrentSceneID()); + + renJava.getPlayer().getCurrentStory().displayScene(renJava.getPlayer().getCurrentSceneID()); + } + } + if (renJava.getStageType() == StageType.SAVE_MENU) { + // Save + int slot = Integer.parseInt(button.getId().replace("save-", "")); + Save save = new Save(slot); + save.write(); + + // Re-render + Menu menu = renJava.buildLoadMenu(1); // Builds first page + menu.addMenu(renJava.buildSideMenu()); + menu.render(); + renJava.setStage(renJava.getStage(), StageType.SAVE_MENU); // Update stage type + } } } From 1b994b2490064cc2671f364666bce3297b11fd73 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 02:29:14 -0500 Subject: [PATCH 12/39] Added more functionality to the configuration. --- .../configuration/RenJavaConfiguration.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java b/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java index e768da3..feac4c0 100644 --- a/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java +++ b/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java @@ -17,8 +17,10 @@ public class RenJavaConfiguration { private FontLoader dialogueFont; private FontLoader uiFont; private FontLoader characterDisplayFont; + private FontLoader choiceButtonFont; private Color dialogueColor = Color.BLACK; - + private Color choiceButtonColor = Color.BLACK; + private Color hoverColor = Color.BLUE; private int dialogueBoxWidth = 1000; private int dialogueBoxHeight = 600; @@ -110,6 +112,14 @@ public FontLoader getCharacterDisplayFont() { return characterDisplayFont; } + public FontLoader getChoiceButtonFont() { + return choiceButtonFont; + } + + public void setChoiceButtonFont(FontLoader choiceButtonFont) { + this.choiceButtonFont = choiceButtonFont; + } + public void setCharacterDisplayFont(FontLoader characterDisplayFont) { this.characterDisplayFont = characterDisplayFont; } @@ -122,6 +132,22 @@ public void setDialogueColor(Color dialogueColor) { this.dialogueColor = dialogueColor; } + public Color getChoiceButtonColor() { + return choiceButtonColor; + } + + public void setChoiceButtonColor(Color choiceButtonColor) { + this.choiceButtonColor = choiceButtonColor; + } + + public Color getHoverColor() { + return hoverColor; + } + + public void setHoverColor(Color hoverColor) { + this.hoverColor = hoverColor; + } + public int getDialogueBoxWidth() { return dialogueBoxWidth; } From a6ed953b936738251739dd1ec0105607d50aa575 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 17:11:02 -0500 Subject: [PATCH 13/39] Implemented SL4J logging. --- dependency-reduced-pom.xml | 11 +--- pom.xml | 24 +++++--- src/main/java/me/piitex/renjava/Launch.java | 8 +++ src/main/java/me/piitex/renjava/RenJava.java | 57 +++++++++++-------- .../java/me/piitex/renjava/RenLoader.java | 33 +++++------ .../me/piitex/renjava/RenLoggerFormat.java | 25 -------- .../java/me/piitex/renjava/addons/Addon.java | 10 ++-- .../me/piitex/renjava/addons/AddonLoader.java | 14 +++-- .../me/piitex/renjava/api/music/Track.java | 6 +- .../me/piitex/renjava/api/player/Player.java | 5 +- .../me/piitex/renjava/api/saves/Save.java | 7 ++- .../transitions/types/FadingTransition.java | 7 +-- .../api/scenes/types/AnimationScene.java | 5 +- .../api/scenes/types/AutoPlayScene.java | 1 - .../renjava/api/scenes/types/ImageScene.java | 1 - .../api/scenes/types/choices/ChoiceScene.java | 6 +- .../me/piitex/renjava/api/stories/Story.java | 8 +-- .../configuration/SettingsProperties.java | 4 +- .../defaults/GameFlowEventListener.java | 20 +++---- .../defaults/MenuClickEventListener.java | 9 ++- .../events/defaults/ScenesEventListener.java | 6 +- .../java/me/piitex/renjava/gui/Element.java | 1 - .../java/me/piitex/renjava/gui/GuiLoader.java | 31 +++++----- src/main/java/me/piitex/renjava/gui/Menu.java | 8 +-- .../piitex/renjava/gui/console/Console.java | 24 -------- .../renjava/gui/console/GameConsole.java | 8 --- .../renjava/gui/overlay/ButtonOverlay.java | 4 +- .../renjava/gui/overlay/ImageOverlay.java | 4 +- .../renjava/loggers/ApplicationLogger.java | 20 +++++++ .../me/piitex/renjava/loggers/RenLogger.java | 14 +++++ .../me/piitex/renjava/tasks/KeyHeldTask.java | 3 +- .../me/piitex/renjava/utils/RPAArchive.java | 3 +- src/main/java/module-info.java | 6 ++ src/main/resources/log4j2.xml | 17 ++++++ 34 files changed, 207 insertions(+), 203 deletions(-) delete mode 100644 src/main/java/me/piitex/renjava/RenLoggerFormat.java delete mode 100644 src/main/java/me/piitex/renjava/gui/console/Console.java delete mode 100644 src/main/java/me/piitex/renjava/gui/console/GameConsole.java create mode 100644 src/main/java/me/piitex/renjava/loggers/ApplicationLogger.java create mode 100644 src/main/java/me/piitex/renjava/loggers/RenLogger.java create mode 100644 src/main/resources/log4j2.xml diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 59b8f0e..0a6163c 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -4,7 +4,7 @@ me.piitex RenJava RenJava - 0.0.757-SNAPSHOT + 0.0.802-SNAPSHOT @@ -12,14 +12,7 @@ **/jasperreports_extension.properties **/tecsofti-fonts.xml - **/*.ttf - **/*.png - **/*.jpeg - **/*.webp - **/*.webm - **/*.mp3 - **/*.wav - **/*.css + **/*.* diff --git a/pom.xml b/pom.xml index c574289..66d161a 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,21 @@ javafx-media 21.0.2 + + org.apache.logging.log4j + log4j-api + 2.23.1 + + + org.apache.logging.log4j + log4j-core + 2.23.1 + + + org.apache.logging.log4j + log4j-slf4j2-impl + 2.23.1 + org.junit.jupiter junit-jupiter-api @@ -177,14 +192,7 @@ **/jasperreports_extension.properties **/tecsofti-fonts.xml - **/*.ttf - **/*.png - **/*.jpeg - **/*.webp - **/*.webm - **/*.mp3 - **/*.wav - **/*.css + **/*.* diff --git a/src/main/java/me/piitex/renjava/Launch.java b/src/main/java/me/piitex/renjava/Launch.java index ea72d25..51f7a11 100644 --- a/src/main/java/me/piitex/renjava/Launch.java +++ b/src/main/java/me/piitex/renjava/Launch.java @@ -12,6 +12,7 @@ import me.piitex.renjava.configuration.Configuration; import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.gui.GuiLoader; +import me.piitex.renjava.loggers.ApplicationLogger; import org.reflections.Reflections; import org.reflections.scanners.Scanners; import org.reflections.util.ClasspathHelper; @@ -57,12 +58,19 @@ public static void main(String[] args) { Configuration conf = renJava.getClass().getAnnotation(Configuration.class); RenJavaConfiguration configuration = new RenJavaConfiguration(conf.title().replace("{version}", renJava.version).replace("{name}", renJava.name), conf.width(), conf.height(), new ImageLoader(conf.windowIconPath())); renJava.setConfiguration(configuration); + } else { System.err.println("ERROR: Configuration annotation not found. Please annotate your main class with 'Configuration'"); RenJavaConfiguration configuration = new RenJavaConfiguration("Error", 1920, 1080, new ImageLoader("gui/window_icon.png")); renJava.setConfiguration(configuration); } + // Initialize the application logger + ApplicationLogger applicationLogger = new ApplicationLogger(c); + renJava.setLogger(applicationLogger.LOGGER); + + renJava.getLogger().info("Initialized logger..."); + renJava.init(); // Initialize game launch(args); //c.getDeclaredConstructor().newInstance(); diff --git a/src/main/java/me/piitex/renjava/RenJava.java b/src/main/java/me/piitex/renjava/RenJava.java index b251718..70ebe74 100644 --- a/src/main/java/me/piitex/renjava/RenJava.java +++ b/src/main/java/me/piitex/renjava/RenJava.java @@ -33,21 +33,20 @@ import me.piitex.renjava.gui.exceptions.ImageNotFoundException; import me.piitex.renjava.gui.Menu; -import me.piitex.renjava.gui.layouts.Layout; import me.piitex.renjava.gui.layouts.impl.HorizontalLayout; import me.piitex.renjava.gui.layouts.impl.VerticalLayout; import me.piitex.renjava.gui.overlay.ButtonOverlay; import me.piitex.renjava.gui.StageType; import me.piitex.renjava.gui.overlay.TextFlowOverlay; import me.piitex.renjava.gui.overlay.TextOverlay; +import me.piitex.renjava.loggers.RenLogger; +import org.slf4j.Logger; -import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; -import java.util.logging.*; - /** +/** * The RenJava class serves as the entry point for the RenJava framework. It provides the core functionality and structure for creating visual novel games. *

* To use the RenJava framework, create a new class that extends the `RenJava` class and override its methods to define the behavior of your game. @@ -73,10 +72,12 @@ public abstract class RenJava { protected String name; protected String author; protected String version; - private Logger logger; private Player player; // Audio Tracking private Tracks tracks; + + private Logger logger; + private AddonLoader addonLoader; private Stage stage; // Move this somewhere else. @@ -107,16 +108,20 @@ protected void init() { this.player = new Player(); this.tracks = new Tracks(); // Load logger - this.logger = Logger.getLogger(name); - FileHandler fileHandler; - try { - fileHandler = new FileHandler("log.txt"); - fileHandler.setFormatter(new RenLoggerFormat()); - logger.addHandler(fileHandler); - logger.info("Starting application..."); - } catch (IOException e) { - getLogger().severe("Could not initialize logger. " + e.getMessage()); - } +// this.logger = Logger.getLogger(name); +// FileHandler fileHandler; +// try { +// fileHandler = new FileHandler("log.txt"); +// fileHandler.setFormatter(new RenLoggerFormat()); +// logger.addHandler(fileHandler); +// logger.info("Starting application..."); +// } catch (IOException e) { +// getLogger().severe("Could not initialize logger. " + e.getMessage()); +// } + + // Initializes the Ren logger which is separated from the application logger. + RenLogger.init(); + this.registerListener(new MenuClickEventListener()); this.registerListener(new GameFlowEventListener()); this.registerListener(new StoryHandlerEventListener()); @@ -124,7 +129,7 @@ protected void init() { this.registerData(player); this.registerData(tracks); new RenLoader(this); - this.addonLoader = new AddonLoader(logger); + this.addonLoader = new AddonLoader(); } public String getName() { @@ -143,18 +148,22 @@ public Player getPlayer() { return player; } + public Logger getLogger() { + return logger; + } + + public void setLogger(Logger logger) { + this.logger = logger; + } + public Tracks getTracks() { return tracks; } - public AddonLoader getAddonLoader() { + public AddonLoader getAddonLoader() { return addonLoader; } - public Logger getLogger() { - return logger; - } - public String getBuildVersion() { return buildVersion; } @@ -229,7 +238,7 @@ public Collection getCharacters() { */ public Character getCharacter(String id) { if (!registeredCharacters.containsKey(id)) { - getLogger().severe(new InvalidCharacterException(id).getMessage()); + RenLogger.LOGGER.error(new InvalidCharacterException(id).getMessage()); return null; } return registeredCharacters.get(id.toLowerCase()); @@ -295,10 +304,10 @@ public void buildStage(Stage stage) { try { stage.getIcons().add(windowIcon.buildRaw()); } catch (ImageNotFoundException e) { - logger.severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); } } else { - logger.warning("No window icon set. Please set a window icon for a better user experience."); + RenLogger.LOGGER.warn("No window icon set. Please set a window icon for a better user experience."); } stage.initStyle(StageStyle.DECORATED); diff --git a/src/main/java/me/piitex/renjava/RenLoader.java b/src/main/java/me/piitex/renjava/RenLoader.java index 3ffb0a1..44edf86 100644 --- a/src/main/java/me/piitex/renjava/RenLoader.java +++ b/src/main/java/me/piitex/renjava/RenLoader.java @@ -7,19 +7,22 @@ import me.piitex.renjava.api.builders.FontLoader; import me.piitex.renjava.api.music.Track; import me.piitex.renjava.configuration.SettingsProperties; +import me.piitex.renjava.loggers.RenLogger; +; public class RenLoader { private final RenJava renJava; boolean shutdown = false; + public RenLoader(RenJava renJava) { this.renJava = renJava; - renJava.getLogger().info("Starting processes..."); + RenLogger.LOGGER.info("Starting processes..."); renJava.buildVersion = getVersion(); setupMain(); setupGame(); if (shutdown) { // Shutdown application. - renJava.getLogger().severe("Game assets do not exist. Please download default assets and place them inside the 'game' folder."); + RenLogger.LOGGER.error("Game assets do not exist. Please download default assets and place them inside the 'game' folder."); Platform.exit(); System.exit(0); return; @@ -28,23 +31,17 @@ public RenLoader(RenJava renJava) { } private void setupMain() { - renJava.getLogger().info("Checking game environment..."); + RenLogger.LOGGER.info("Checking game environment..."); File gameDirectory = new File(System.getProperty("user.dir") + "/game/"); if (gameDirectory.mkdir()) { - renJava.getLogger().severe("Game directory does not exist. The game will not work properly, please move all assets into the newly created game directory."); + RenLogger.LOGGER.error("Game directory does not exist. The game will not work properly, please move all assets into the newly created game directory."); shutdown = true; } File renJavaDirectory = new File(System.getProperty("user.dir") + "/renjava/"); if (renJavaDirectory.mkdir()) { - renJava.getLogger().warning("RenJava folder does not exist. User settings will be reset to defaults."); - } - File logFile = new File(System.getProperty("user.dir"), "log.txt"); - try { - logFile.createNewFile(); - } catch (IOException e) { - renJava.getLogger().warning("Could not create log file. Ensure the application has read and write permissions."); + RenLogger.LOGGER.warn("RenJava folder does not exist. User settings will be reset to defaults."); } for (File file : new File(System.getProperty("user.dir")).listFiles()) { if (file.getName().endsWith(".txt.lck")) { @@ -63,21 +60,21 @@ private void setupGame() { audioLoaded++; renJava.getTracks().addTrack(new Track(file)); } - renJava.getLogger().info("Loaded " + audioLoaded + " audio file(s)"); + RenLogger.LOGGER.info("Loaded " + audioLoaded + " audio file(s)"); File imageDirectory = new File(directory, "/images/"); if (imageDirectory.mkdir()) { - renJava.getLogger().warning("Images folder does not exist, creating..."); + RenLogger.LOGGER.warn("Images folder does not exist, creating..."); } File savesDirectory = new File(directory, "/saves/"); if (savesDirectory.mkdir()) { - renJava.getLogger().warning("Saves folder does not exist, creating..."); + RenLogger.LOGGER.warn("Saves folder does not exist, creating..."); } File fontsDirectory = new File(directory, "/fonts/"); if (fontsDirectory.mkdir()) { - renJava.getLogger().warning("Fonts folder does not exist, creating..."); + RenLogger.LOGGER.warn("Fonts folder does not exist, creating..."); } - renJava.getLogger().info("Loading fonts..."); + RenLogger.LOGGER.info("Loading fonts..."); int fonts = 0; for (File file : fontsDirectory.listFiles()) { if (file.getName().endsWith(".ttf")) { @@ -85,13 +82,13 @@ private void setupGame() { new FontLoader(file.getName()); } } - renJava.getLogger().info("Loaded " + fonts + " font(s)."); + RenLogger.LOGGER.info("Loaded " + fonts + " font(s)."); File cssDirectory = new File(directory, "/css/"); cssDirectory.mkdir(); } private void startPreProcess() { - renJava.getLogger().info("Generating pre-load data..."); + RenLogger.LOGGER.info("Generating pre-load data..."); loadRPAFiles(); renJava.preEnabled(); diff --git a/src/main/java/me/piitex/renjava/RenLoggerFormat.java b/src/main/java/me/piitex/renjava/RenLoggerFormat.java deleted file mode 100644 index 0ba2ac1..0000000 --- a/src/main/java/me/piitex/renjava/RenLoggerFormat.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.piitex.renjava; - -import java.util.logging.Formatter; -import java.util.logging.LogRecord; - -public class RenLoggerFormat extends Formatter { - - @Override - public String format(LogRecord record) { - String buffer = record.getLevel() + - ": " + - record.getMessage() + - "\n"; - return buffer; - } - - @Override - public String formatMessage(LogRecord record) { - String buffer = record.getLevel() + - ": " + - record.getMessage() + - "\n"; - return buffer; - } -} diff --git a/src/main/java/me/piitex/renjava/addons/Addon.java b/src/main/java/me/piitex/renjava/addons/Addon.java index 8b7d93e..01ef48d 100644 --- a/src/main/java/me/piitex/renjava/addons/Addon.java +++ b/src/main/java/me/piitex/renjava/addons/Addon.java @@ -1,14 +1,11 @@ package me.piitex.renjava.addons; -import me.piitex.renjava.RenJava; -import me.piitex.renjava.RenLoggerFormat; +import me.piitex.renjava.loggers.ApplicationLogger; import me.piitex.renjava.events.EventListener; +import org.slf4j.Logger; -import java.io.IOException; import java.util.Collection; import java.util.HashSet; -import java.util.logging.FileHandler; -import java.util.logging.Logger; /** *

@@ -42,7 +39,7 @@ public abstract class Addon { private final String name; private final Collection registeredListeners = new HashSet<>(); private final Collection dependencies = new HashSet<>(); - private final Logger logger = RenJava.getInstance().getLogger(); + private final Logger logger; /** * Constructs a new Addon with the specified name. @@ -51,6 +48,7 @@ public abstract class Addon { */ public Addon(String name) { this.name = name; + logger = new ApplicationLogger(name).LOGGER; } /** diff --git a/src/main/java/me/piitex/renjava/addons/AddonLoader.java b/src/main/java/me/piitex/renjava/addons/AddonLoader.java index 7822b56..7b290b9 100644 --- a/src/main/java/me/piitex/renjava/addons/AddonLoader.java +++ b/src/main/java/me/piitex/renjava/addons/AddonLoader.java @@ -1,6 +1,9 @@ package me.piitex.renjava.addons; +import me.piitex.renjava.loggers.RenLogger; +import org.slf4j.Logger;; import org.jetbrains.annotations.Nullable; + import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.URL; @@ -9,7 +12,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -17,14 +19,14 @@ public class AddonLoader { private final List addons = new ArrayList<>(); private final Logger logger; - public AddonLoader(Logger logger) { - this.logger = logger; + public AddonLoader() { + logger = RenLogger.LOGGER; } public void load() { File directory = new File(System.getProperty("user.dir") + "/addons/"); if (directory.mkdir()) { - logger.warning("Created directory '" + "addons" + "'."); + logger.warn("Created directory '" + "addons" + "'."); } logger.info("Initializing Addon Loader..."); int size = directory.listFiles().length; @@ -49,7 +51,7 @@ public void load() { } ZipEntry entry = zipFile.getEntry("build.info"); if (entry == null) { - logger.severe("Could not find build.info for " + file.getName() + " Addon will load with the presumption there are no dependencies."); + logger.error("Could not find build.info for " + file.getName() + " Addon will load with the presumption there are no dependencies."); nonDependants.add(file); continue; } @@ -96,7 +98,7 @@ public void load() { while (!validations.isEmpty()) { lateLoaders.forEach((file, string) -> { if (lastValidated.get().equalsIgnoreCase(file.getName())) { - logger.severe("Could not initialize " + file.getName() + ": May be the result of a missing dependency."); + logger.error("Could not initialize " + file.getName() + ": May be the result of a missing dependency."); validations.remove(file); return; } diff --git a/src/main/java/me/piitex/renjava/api/music/Track.java b/src/main/java/me/piitex/renjava/api/music/Track.java index 167bbe3..8d67fc6 100644 --- a/src/main/java/me/piitex/renjava/api/music/Track.java +++ b/src/main/java/me/piitex/renjava/api/music/Track.java @@ -4,11 +4,9 @@ import javafx.scene.media.MediaPlayer; import javafx.util.Duration; import me.piitex.renjava.RenJava; -import me.piitex.renjava.api.APIChange; +import me.piitex.renjava.loggers.RenLogger; -import javax.sound.sampled.*; import java.io.File; -import java.io.IOException; public class Track { private final String id; @@ -38,7 +36,7 @@ protected void play(boolean loop) { RenJava.getInstance().getTracks().setPlaying(false); }); } - RenJava.getInstance().getLogger().warning("Volume: " + RenJava.getInstance().getSettings().getVolume() / 500d); + RenLogger.LOGGER.warn("Volume: " + RenJava.getInstance().getSettings().getVolume() / 500d); player.setVolume(RenJava.getInstance().getSettings().getVolume() / 500d); player.play(); } diff --git a/src/main/java/me/piitex/renjava/api/player/Player.java b/src/main/java/me/piitex/renjava/api/player/Player.java index 0f491cd..b2f0e66 100644 --- a/src/main/java/me/piitex/renjava/api/player/Player.java +++ b/src/main/java/me/piitex/renjava/api/player/Player.java @@ -1,6 +1,7 @@ package me.piitex.renjava.api.player; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.APINote; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.exceptions.InvalidStoryException; @@ -102,10 +103,10 @@ public Map getStoryIdMap() { public void startStory(String id) { if (!storyIdMap.containsKey(id)) { - RenJava.getInstance().getLogger().severe(new InvalidStoryException(id).getMessage()); + RenLogger.LOGGER.error(new InvalidStoryException(id).getMessage()); return; } - RenJava.getInstance().getLogger().info("Starting story '" + id + "'"); + RenLogger.LOGGER.info("Starting story '" + id + "'"); RenJava.getInstance().getPlayer().setCurrentStory(id); getStory(id).start(); } diff --git a/src/main/java/me/piitex/renjava/api/saves/Save.java b/src/main/java/me/piitex/renjava/api/saves/Save.java index 5000989..723b7b4 100644 --- a/src/main/java/me/piitex/renjava/api/saves/Save.java +++ b/src/main/java/me/piitex/renjava/api/saves/Save.java @@ -4,6 +4,7 @@ import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.saves.data.Data; import me.piitex.renjava.api.saves.data.PersistentData; @@ -78,7 +79,7 @@ public void write() { System.out.println("Processing field: " + field.getName()); Object object = field.get(data); if (object == null) { - RenJava.getInstance().getLogger().warning("Value for '" + field.getName() + "' is null. Will not process data."); + RenLogger.LOGGER.warn("Value for '" + field.getName() + "' is null. Will not process data."); continue; } rootSection.addKeyValue(field.getName(), object.toString()); @@ -144,7 +145,7 @@ public void load(boolean process) { throw new RuntimeException(e); } finally { if (fullData == null) { - RenJava.getInstance().getLogger().severe("Save file does not exist."); + RenLogger.LOGGER.error("Save file does not exist."); return; } } @@ -340,7 +341,7 @@ public Pane buildPreview() { view.setFitWidth(309); pane.getChildren().add(view); } catch (ImageNotFoundException e) { - RenJava.getInstance().getLogger().severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); } } else { Story story = RenJava.getInstance().getPlayer().getStory((String) sceneSection.get("currentStory")); diff --git a/src/main/java/me/piitex/renjava/api/scenes/transitions/types/FadingTransition.java b/src/main/java/me/piitex/renjava/api/scenes/transitions/types/FadingTransition.java index 1cc5692..ae24078 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/transitions/types/FadingTransition.java +++ b/src/main/java/me/piitex/renjava/api/scenes/transitions/types/FadingTransition.java @@ -3,10 +3,9 @@ import javafx.animation.FadeTransition; import javafx.scene.Node; import javafx.util.Duration; -import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.scenes.transitions.Transitions; - -import java.util.logging.Logger; +import org.slf4j.Logger;; public class FadingTransition extends Transitions { private final double fromValue; @@ -46,7 +45,7 @@ public boolean isAutoReverse() { @Override public void play(Node node) { // Remove logger - Logger logger = RenJava.getInstance().getLogger(); + Logger logger = RenLogger.LOGGER; logger.info("Playing fading transition..."); fadeTransition = new FadeTransition(Duration.valueOf(getDuration() + "ms")); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java index 8aa46bd..4825da1 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java @@ -9,6 +9,7 @@ import javafx.scene.text.TextAlignment; import javafx.scene.text.TextFlow; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.characters.Character; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.gui.Menu; @@ -60,10 +61,10 @@ public Menu build(boolean ui) { text = new Text(dialogue); if (getCharacterNameDisplay() != null && !getCharacterNameDisplay().isEmpty()) { // Set character display - RenJava.getInstance().getLogger().info("Character Display Name Validation: " + getCharacterNameDisplay()); + RenLogger.LOGGER.info("Character Display Name Validation: " + getCharacterNameDisplay()); characterDisplay = new Text(getCharacterNameDisplay()); } else { - RenJava.getInstance().getLogger().info("Character Display Name Validation: " + character.getDisplayName()); + RenLogger.LOGGER.info("Character Display Name Validation: " + character.getDisplayName()); characterDisplay = new Text(character.getDisplayName()); } characterDisplay.setFill(character.getColor()); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java index bedeaab..0a444dc 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java @@ -34,7 +34,6 @@ public Menu build(boolean ui) { @Override public void render(Menu menu) { - System.out.println("Rendering: " + getId()); menu.render(); renJava.setStage(renJava.getStage(), StageType.IMAGE_SCENE); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java index c8cd128..be2b069 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java @@ -74,7 +74,6 @@ public ImageScene(String id, @Nullable Character character, String dialogue, @Nu this.dialogue = dialogue; if (loader != null) { this.backgroundImage = loader; - renJava.getLogger().info("Story: " + getStory().getId()); renJava.getPlayer().setLastDisplayedImage(new AbstractMap.SimpleEntry<>(getStory().getId(), loader)); } if (character != null) { diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java index 39bf4b5..7ac5f27 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java @@ -6,6 +6,7 @@ import javafx.scene.image.ImageView; import javafx.scene.paint.Color; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.events.types.ButtonClickEvent; import me.piitex.renjava.events.types.ChoiceButtonBuildEvent; @@ -153,8 +154,7 @@ public Menu build(boolean ui) { if (ui) { VerticalLayout layout = new VerticalLayout(500, 500); Map.Entry midPoint = RenJava.getInstance().getConfiguration().getMidPoint(); - System.out.println("Set X: " + midPoint.getKey()); - System.out.println("Set Y: " + midPoint.getValue()); + layout.setX(midPoint.getKey() - 600); layout.setY(midPoint.getValue() - 200); layout.setSpacing(20.0); @@ -170,7 +170,7 @@ public Menu build(boolean ui) { buttonOverlay = new ButtonOverlay(getChoiceButton(choice, choiceBoxImage.build())); layout.addOverlays(buttonOverlay); } catch (ImageNotFoundException e) { - RenJava.getInstance().getLogger().severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); } } diff --git a/src/main/java/me/piitex/renjava/api/stories/Story.java b/src/main/java/me/piitex/renjava/api/stories/Story.java index a641497..d5d72df 100644 --- a/src/main/java/me/piitex/renjava/api/stories/Story.java +++ b/src/main/java/me/piitex/renjava/api/stories/Story.java @@ -1,7 +1,7 @@ package me.piitex.renjava.api.stories; import me.piitex.renjava.RenJava; -import me.piitex.renjava.api.player.Player; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.scenes.types.AnimationScene; import me.piitex.renjava.api.scenes.types.ImageScene; @@ -14,9 +14,9 @@ import me.piitex.renjava.events.types.SceneBuildEvent; import me.piitex.renjava.events.types.SceneEndEvent; import me.piitex.renjava.gui.Menu; +import org.slf4j.Logger;; import java.util.*; -import java.util.logging.Logger; /** * The Story class represents a narrative or gameplay progression in the RenJava framework. @@ -68,7 +68,7 @@ public abstract class Story { private StoryStartInterface startInterface; private StoryEndInterface endInterface; - private final Logger logger = RenJava.getInstance().getLogger(); + private final Logger logger = RenLogger.LOGGER; private final RenJava renJava; @@ -163,7 +163,7 @@ public void clear() { */ public void addScene(RenScene scene) { if (scenes.containsKey(scene.getId())) { - logger.warning(new DuplicateSceneIdException(scene.getId()).getMessage()); + logger.warn(new DuplicateSceneIdException(scene.getId()).getMessage()); scenes.replace(scene.getId(), scenes.get(id), scene); return; } diff --git a/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java b/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java index a533500..85160ba 100644 --- a/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java +++ b/src/main/java/me/piitex/renjava/configuration/SettingsProperties.java @@ -1,6 +1,6 @@ package me.piitex.renjava.configuration; -import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import java.io.*; import java.util.Properties; @@ -93,7 +93,7 @@ private void write(String key, String value) { properties.store(outputStream, null); outputStream.close(); } catch (IOException e) { - RenJava.getInstance().getLogger().severe("Could not write to settings file: " + e.getMessage()); + RenLogger.LOGGER.error("Could not write to settings file: " + e.getMessage()); } } } diff --git a/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java index 2b1e5d2..4c34918 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java @@ -2,11 +2,10 @@ import javafx.scene.input.KeyCode; import javafx.scene.input.MouseButton; -import javafx.scene.layout.Background; import javafx.scene.layout.Pane; -import javafx.scene.paint.Paint; import javafx.stage.Stage; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.player.Player; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.scenes.types.InteractableScene; @@ -20,13 +19,10 @@ import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; import me.piitex.renjava.tasks.KeyHeldTask; +import org.slf4j.Logger;; -import java.lang.reflect.Field; -import java.util.AbstractMap; import java.util.Timer; -import java.util.logging.Logger; -import static javafx.scene.paint.Color.BLACK; public class GameFlowEventListener implements EventListener { // Also experimental, task that runs while the ctrl key is held. Maybe I can change this to a do while or something... I'm not sure. @@ -45,7 +41,7 @@ public void onMouseClick(MouseClickEvent event) { RenScene scene = renJava.getPlayer().getCurrentScene(); Player player = renJava.getPlayer(); MouseButton button = event.getEvent().getButton(); - Logger logger = renJava.getLogger(); + Logger logger = RenLogger.LOGGER; // Only do this if it's not the title screen or any other menu screen @@ -55,7 +51,7 @@ public void onMouseClick(MouseClickEvent event) { case MIDDLE -> { if (gameMenu) { // Hide ui elements from scene - renJava.getLogger().info("Toggling UI!"); + logger.info("Toggling UI!"); player.setUiToggled(!player.isUiToggled()); scene.build(player.isUiToggled()); } @@ -123,7 +119,7 @@ public void onKeyPress(KeyPressEvent event) { @Listener public void onScrollInput(ScrollInputEvent event) { - renJava.getLogger().info("Scroll Y: " + event.getScrollEvent().getDeltaY()); + RenLogger.LOGGER.info("Scroll Y: " + event.getScrollEvent().getDeltaY()); // If the scroll y is less than 0 they are scrolling down. double y = event.getScrollEvent().getDeltaY(); @@ -140,7 +136,7 @@ public void onScrollInput(ScrollInputEvent event) { @Listener(priority = Priority.LOWEST) public void onScrollUp(ScrollUpEvent event) { - Logger logger = renJava.getLogger(); + Logger logger = RenLogger.LOGGER; logger.info("Scroll up called!"); if (event.isCancelled()) return; // If the event is canceled, do not roll back. if (renJava.getPlayer().getCurrentScene() != null) { @@ -180,14 +176,14 @@ private void playNextScene() { StageType stageType = renJava.getStageType(); RenScene scene = renJava.getPlayer().getCurrentScene(); Player player = renJava.getPlayer(); - Logger logger = renJava.getLogger(); + Logger logger = RenLogger.LOGGER; // Only do this if it's not the title screen or any other menu screen boolean gameMenu = stageType == StageType.IMAGE_SCENE || stageType == StageType.INPUT_SCENE || stageType == StageType.CHOICE_SCENE || stageType == StageType.INTERACTABLE_SCENE || stageType == StageType.ANIMATION_SCENE; if (gameMenu) { if (scene == null) { - logger.severe("The scene is null."); + logger.error("The scene is null."); return; } // Go to the next scene map diff --git a/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java index 67d1317..dd398af 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java @@ -4,9 +4,8 @@ import javafx.scene.control.Button; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.saves.Save; -import me.piitex.renjava.api.saves.exceptions.SaveFileNotFound; -import me.piitex.renjava.api.stories.Story; import me.piitex.renjava.events.EventListener; import me.piitex.renjava.events.Listener; import me.piitex.renjava.events.types.ButtonClickEvent; @@ -21,7 +20,7 @@ public class MenuClickEventListener implements EventListener { public void onButtonClick(ButtonClickEvent event) { Button button = event.getButton(); if (button.getId().equalsIgnoreCase("menu-start-button")) { - renJava.getLogger().info("Creating new game..."); + RenLogger.LOGGER.info("Creating new game..."); renJava.createBaseData(); renJava.createStory(); @@ -72,7 +71,7 @@ public void onButtonClick(ButtonClickEvent event) { int slot = Integer.parseInt(button.getId().replace("save-", "")); Save save = new Save(slot); if (!save.exists()) { - renJava.getLogger().warning("Save file does not exist."); + RenLogger.LOGGER.warn("Save file does not exist."); return; } @@ -80,7 +79,7 @@ public void onButtonClick(ButtonClickEvent event) { String storyID = renJava.getPlayer().getCurrentStoryID(); if (storyID == null) { - renJava.getLogger().severe("Save file could not be loaded. The data is either not formatted or corrupted."); + RenLogger.LOGGER.error("Save file could not be loaded. The data is either not formatted or corrupted."); return; } diff --git a/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java index 32b21a9..4ef2008 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java @@ -4,10 +4,9 @@ import javafx.scene.control.Button; import javafx.scene.control.TextField; import me.piitex.renjava.RenJava; -import me.piitex.renjava.api.player.Player; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.scenes.types.AutoPlayScene; -import me.piitex.renjava.api.scenes.types.ImageScene; import me.piitex.renjava.api.scenes.types.choices.Choice; import me.piitex.renjava.api.scenes.types.choices.ChoiceScene; import me.piitex.renjava.api.scenes.types.input.InputScene; @@ -17,7 +16,6 @@ import me.piitex.renjava.events.Priority; import me.piitex.renjava.events.types.*; -import java.util.AbstractMap; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; @@ -60,7 +58,7 @@ public void onSceneEnd(SceneEndEvent event) { if (event.getScene() instanceof InputScene scene) { TextField field = scene.getInputField(); if (field == null) { - RenJava.getInstance().getLogger().severe("TextField for InputScene is null."); + RenLogger.LOGGER.error("TextField for InputScene is null."); return; } InputSceneEndEvent endEvent = new InputSceneEndEvent(scene, field.getText()); diff --git a/src/main/java/me/piitex/renjava/gui/Element.java b/src/main/java/me/piitex/renjava/gui/Element.java index daef454..5686ea6 100644 --- a/src/main/java/me/piitex/renjava/gui/Element.java +++ b/src/main/java/me/piitex/renjava/gui/Element.java @@ -38,7 +38,6 @@ public Element(Overlay overlay) { Button button = buttonOverlay.build(); button.setTranslateX(buttonOverlay.x()); button.setTranslateY(buttonOverlay.y()); - System.out.println("Rendering button: " + buttonOverlay.getId()); this.node = button; } else if (overlay instanceof TextFlowOverlay textFlowOverlay) { TextFlow textFlow = textFlowOverlay.build(); diff --git a/src/main/java/me/piitex/renjava/gui/GuiLoader.java b/src/main/java/me/piitex/renjava/gui/GuiLoader.java index c26ffbb..f252c05 100644 --- a/src/main/java/me/piitex/renjava/gui/GuiLoader.java +++ b/src/main/java/me/piitex/renjava/gui/GuiLoader.java @@ -7,13 +7,13 @@ import javafx.stage.StageStyle; import javafx.util.Duration; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.builders.FontLoader; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.events.types.*; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; - -import java.util.logging.Logger; +; /** * Loader class for loading the GUI. Starts with the splash screen first. @@ -30,14 +30,14 @@ public GuiLoader(Stage stage, RenJava renJava, HostServices services) { } private void buildSplashScreen() { - renJava.getLogger().info("Creating Splash screen..."); + RenLogger.LOGGER.info("Creating Splash screen..."); stage.initStyle(StageStyle.UNDECORATED); // Update Stage renJava.setStage(stage, StageType.MAIN_MENU); Menu menu = renJava.buildSplashScreen(); if (menu == null) { - renJava.getLogger().warning("No splash screen was rendered.."); + RenLogger.LOGGER.warn("No splash screen was rendered.."); renJavaFrameworkBuild(); return; // Don't create a splash screen if one wasn't set. } @@ -53,21 +53,20 @@ private void buildSplashScreen() { } private void renJavaFrameworkBuild() { - renJava.getLogger().info("Creating base data..."); + RenLogger.LOGGER.info("Creating base data..."); renJava.createBaseData(); - renJava.getLogger().info("Creating story..."); + RenLogger.LOGGER.info("Creating story..."); renJava.createStory(); postProcess(); buildMainMenu(); } private void buildMainMenu() { - Logger logger = renJava.getLogger(); // Gonna put some default checks here. // If there is no default font set one // if (renJava.getConfiguration().getDefaultFont() == null) { -// renJava.getLogger().severe("No default font set."); +// RenLogger.LOGGER.severe("No default font set."); // renJava.getConfiguration().setDefaultFont(new FontLoader("Arial", 24)); // renJava.getConfiguration().setUiFont(new FontLoader("Arial", 26)); // renJava.getConfiguration().setCharacterDisplayFont(new FontLoader("Arial", 26)); @@ -75,23 +74,23 @@ private void buildMainMenu() { // } RenJavaConfiguration configuration = renJava.getConfiguration(); if (configuration.getDefaultFont() == null) { - renJava.getLogger().severe("Default font not set."); + RenLogger.LOGGER.error("Default font not set."); renJava.getConfiguration().setDefaultFont(new FontLoader("Arial", 24)); } if (configuration.getUiFont() == null) { - renJava.getLogger().severe("UI font not set."); + RenLogger.LOGGER.error("UI font not set."); renJava.getConfiguration().setUiFont(new FontLoader("Arial", 26)); } if (configuration.getCharacterDisplayFont() == null) { - renJava.getLogger().warning("Character display font not set."); + RenLogger.LOGGER.warn("Character display font not set."); renJava.getConfiguration().setCharacterDisplayFont(new FontLoader("Arial", 26)); } if (configuration.getDialogueFont() == null) { - renJava.getLogger().warning("Dialogue font not set."); + RenLogger.LOGGER.warn("Dialogue font not set."); renJava.getConfiguration().setDialogueFont(new FontLoader("Arial", 26)); } if (configuration.getChoiceButtonFont() == null) { - renJava.getLogger().warning("Choice button font not set."); + RenLogger.LOGGER.warn("Choice button font not set."); renJava.getConfiguration().setChoiceButtonFont(new FontLoader("Arial", 28)); } @@ -106,13 +105,13 @@ private void buildMainMenu() { RenJava.callEvent(event); if (menu == null) { - logger.severe("No title screen was built. Please customize your own title screen for better user experience."); - logger.warning("Building RenJava default title screen..."); + RenLogger.LOGGER.error("No title screen was built. Please customize your own title screen for better user experience."); + RenLogger.LOGGER.warn("Building RenJava default title screen..."); menu = new Menu(renJava.getConfiguration().getHeight(), renJava.getConfiguration().getWidth()).setTitle(renJava.getName() + " v" + renJava.getVersion()); try { menu.setBackgroundImage(new ImageLoader("gui/main_menu.png").build()); } catch (ImageNotFoundException e) { - logger.severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); } } diff --git a/src/main/java/me/piitex/renjava/gui/Menu.java b/src/main/java/me/piitex/renjava/gui/Menu.java index f675e10..2426a0b 100644 --- a/src/main/java/me/piitex/renjava/gui/Menu.java +++ b/src/main/java/me/piitex/renjava/gui/Menu.java @@ -8,6 +8,7 @@ import javafx.stage.Stage; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.scenes.transitions.Transitions; @@ -18,7 +19,6 @@ import org.jetbrains.annotations.Nullable; import java.util.LinkedHashSet; -import java.util.logging.Logger; import static javafx.scene.paint.Color.BLACK; @@ -55,7 +55,7 @@ public Menu(double width, double height, ImageLoader imageLoader) { try { this.backgroundImage = imageLoader.build(); } catch (ImageNotFoundException e) { - renJava.getLogger().severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); } } this.width = width; @@ -170,8 +170,6 @@ public Pane render() { * @param renScene The RenScene that is being used. If null, it will be assumed this is a main menu screen. */ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { - Logger logger = renJava.getLogger(); - if (root == null) { root = new Pane(); } @@ -189,7 +187,7 @@ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { backgroundImgElement.render(root); } - logger.info("Rendering layouts..."); + RenLogger.LOGGER.info("Rendering layouts..."); for (Layout layout : layouts) { layout.render(root); } diff --git a/src/main/java/me/piitex/renjava/gui/console/Console.java b/src/main/java/me/piitex/renjava/gui/console/Console.java deleted file mode 100644 index e10eaad..0000000 --- a/src/main/java/me/piitex/renjava/gui/console/Console.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.piitex.renjava.gui.console; - -import javafx.scene.Group; -import javafx.scene.Scene; -import javafx.scene.input.KeyCode; - -public class Console { - - private GameConsole console; - - public void start(Group root, Scene scene) { - - // Create the console - console = new GameConsole(); - console.setVisible(false); - - // Register the key listener for F8 key press event - scene.setOnKeyPressed(event -> { - if (event.getCode() == KeyCode.F8) { - console.setVisible(!console.isVisible()); - } - }); - } -} diff --git a/src/main/java/me/piitex/renjava/gui/console/GameConsole.java b/src/main/java/me/piitex/renjava/gui/console/GameConsole.java deleted file mode 100644 index fb0aba1..0000000 --- a/src/main/java/me/piitex/renjava/gui/console/GameConsole.java +++ /dev/null @@ -1,8 +0,0 @@ -package me.piitex.renjava.gui.console; - -import javafx.scene.layout.VBox; - -public class GameConsole extends VBox { - - -} diff --git a/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java index 2774002..532172b 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java @@ -5,8 +5,8 @@ import javafx.scene.image.ImageView; import javafx.scene.paint.Color; import javafx.scene.text.Font; -import javafx.scene.text.TextAlignment; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; import me.piitex.renjava.events.types.ButtonClickEvent; @@ -402,7 +402,7 @@ public Button build() { try { button.setGraphic(new ImageView(hoverImage.build())); } catch (ImageNotFoundException e) { - RenJava.getInstance().getLogger().severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); } } }); diff --git a/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java index 21ec57f..6e37db4 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java @@ -1,7 +1,7 @@ package me.piitex.renjava.gui.overlay; import javafx.scene.image.Image; -import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; @@ -26,7 +26,7 @@ public ImageOverlay(ImageLoader imageLoader, double x, double y) { this.image = imageLoader.build(); this.fileName = imageLoader.getFile().getName(); } catch (ImageNotFoundException e) { - RenJava.getInstance().getLogger().severe(e.getMessage()); + RenLogger.LOGGER.error(e.getMessage()); throw new RuntimeException(); } this.x = x; diff --git a/src/main/java/me/piitex/renjava/loggers/ApplicationLogger.java b/src/main/java/me/piitex/renjava/loggers/ApplicationLogger.java new file mode 100644 index 0000000..283f422 --- /dev/null +++ b/src/main/java/me/piitex/renjava/loggers/ApplicationLogger.java @@ -0,0 +1,20 @@ +package me.piitex.renjava.loggers; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ApplicationLogger { + public Logger LOGGER; + + public ApplicationLogger(String name) { + LOGGER = LoggerFactory.getLogger(name); + } + + public ApplicationLogger(Class clazz) { + String[] splitClassName = clazz.getName().split("\\."); + int index = splitClassName.length; + String name = splitClassName[index - 1]; + + LOGGER = LoggerFactory.getLogger(name); + } +} \ No newline at end of file diff --git a/src/main/java/me/piitex/renjava/loggers/RenLogger.java b/src/main/java/me/piitex/renjava/loggers/RenLogger.java new file mode 100644 index 0000000..c955f30 --- /dev/null +++ b/src/main/java/me/piitex/renjava/loggers/RenLogger.java @@ -0,0 +1,14 @@ +package me.piitex.renjava.loggers; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RenLogger { + public static Logger LOGGER; + + public static void init() { + LOGGER = LoggerFactory.getLogger("Ren"); + } + +} diff --git a/src/main/java/me/piitex/renjava/tasks/KeyHeldTask.java b/src/main/java/me/piitex/renjava/tasks/KeyHeldTask.java index f39b557..8f32f75 100644 --- a/src/main/java/me/piitex/renjava/tasks/KeyHeldTask.java +++ b/src/main/java/me/piitex/renjava/tasks/KeyHeldTask.java @@ -2,6 +2,7 @@ import javafx.application.Platform; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.player.Player; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.stories.Story; @@ -21,7 +22,7 @@ public KeyHeldTask(RenScene scene) { @Override public void run() { - RenJava.getInstance().getLogger().info("Skipping scene..."); + RenLogger.LOGGER.info("Skipping scene..."); Player player = RenJava.getInstance().getPlayer(); AbstractMap.SimpleEntry entry = new AbstractMap.SimpleEntry<>(scene.getStory(), scene.getId()); if (player.getViewedScenes().get(entry) != null) { diff --git a/src/main/java/me/piitex/renjava/utils/RPAArchive.java b/src/main/java/me/piitex/renjava/utils/RPAArchive.java index 3e69885..7f8b722 100644 --- a/src/main/java/me/piitex/renjava/utils/RPAArchive.java +++ b/src/main/java/me/piitex/renjava/utils/RPAArchive.java @@ -1,6 +1,7 @@ package me.piitex.renjava.utils; import me.piitex.renjava.RenJava; +import me.piitex.renjava.loggers.RenLogger; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.filefilter.RegexFileFilter; @@ -23,7 +24,7 @@ public RPAArchive(RenJava renJava) { DirectoryFileFilter.DIRECTORY); for (File file : files) { if (file.getName().endsWith(".rpa")) { - renJava.getLogger().info("Loading archive: " + file.getName()); + RenLogger.LOGGER.info("Loading archive: " + file.getName()); } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 65a6bf1..e3e3d10 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -10,6 +10,10 @@ requires org.apache.commons.io; requires org.jetbrains.annotations; requires com.goxr3plus.streamplayer; + requires org.slf4j; + requires org.apache.logging.log4j; + requires org.apache.logging.log4j.core; + requires org.apache.logging.log4j.slf4j2.impl; opens me.piitex.renjava; exports me.piitex.renjava; exports me.piitex.renjava.configuration; @@ -36,4 +40,6 @@ exports me.piitex.renjava.api.saves.data; exports me.piitex.renjava.api.scenes.animation; exports me.piitex.renjava.addons; + exports me.piitex.renjava.loggers; + opens me.piitex.renjava.loggers; } \ No newline at end of file diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..7eccebb --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file From d8ad8793988f53efef819e953307204926adf3a0 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 17:49:58 -0500 Subject: [PATCH 14/39] Added ShutDownEvent --- src/main/java/me/piitex/renjava/RenJava.java | 4 ++++ .../java/me/piitex/renjava/events/types/ShutdownEvent.java | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 src/main/java/me/piitex/renjava/events/types/ShutdownEvent.java diff --git a/src/main/java/me/piitex/renjava/RenJava.java b/src/main/java/me/piitex/renjava/RenJava.java index 70ebe74..beb7b9f 100644 --- a/src/main/java/me/piitex/renjava/RenJava.java +++ b/src/main/java/me/piitex/renjava/RenJava.java @@ -31,6 +31,7 @@ import me.piitex.renjava.events.defaults.ScenesEventListener; import me.piitex.renjava.events.defaults.StoryHandlerEventListener; +import me.piitex.renjava.events.types.ShutdownEvent; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.layouts.impl.HorizontalLayout; @@ -321,6 +322,9 @@ public void buildStage(Stage stage) { stage.setOnHiding(windowEvent -> { getAddonLoader().disable(); + ShutdownEvent shutdownEvent = new ShutdownEvent(); + callEvent(shutdownEvent); + Platform.exit(); System.exit(0); }); diff --git a/src/main/java/me/piitex/renjava/events/types/ShutdownEvent.java b/src/main/java/me/piitex/renjava/events/types/ShutdownEvent.java new file mode 100644 index 0000000..a1c2e93 --- /dev/null +++ b/src/main/java/me/piitex/renjava/events/types/ShutdownEvent.java @@ -0,0 +1,6 @@ +package me.piitex.renjava.events.types; + +import me.piitex.renjava.events.Event; + +public class ShutdownEvent extends Event { +} From 84cf1481a5efd52f5bde5c0a59ad22442be9ba9d Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 21:04:27 -0500 Subject: [PATCH 15/39] Framework will now create a build.info file which will be used to increase loading time and performance. --- src/main/java/me/piitex/renjava/Launch.java | 140 +++++++++++++------- 1 file changed, 90 insertions(+), 50 deletions(-) diff --git a/src/main/java/me/piitex/renjava/Launch.java b/src/main/java/me/piitex/renjava/Launch.java index 51f7a11..b4e32ee 100644 --- a/src/main/java/me/piitex/renjava/Launch.java +++ b/src/main/java/me/piitex/renjava/Launch.java @@ -3,6 +3,7 @@ import javafx.application.Application; import javafx.stage.Stage; +import java.io.*; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.Arrays; @@ -19,69 +20,108 @@ import org.reflections.util.ConfigurationBuilder; import java.util.HashSet; +import java.util.Scanner; import java.util.stream.Collectors; public class Launch extends Application { public static void main(String[] args) { - // Scans for all classes in all packages. (We need to do all packages because this allows the author the freedom to do their own package scheme.) - Collection allPackagePrefixes = Arrays.stream(Package.getPackages()) - .map(Package::getName) - .map(s -> s.split("\\.")[0]) - .distinct() - .map(ClasspathHelper::forPackage) - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - ConfigurationBuilder config = new ConfigurationBuilder().addUrls(allPackagePrefixes) - .addScanners(Scanners.SubTypes); - Reflections reflections = new Reflections(config); - - // Detect any classes that extend RenJava - for (Class c : reflections.getSubTypesOf(RenJava.class)) { - try { - Object o = c.getDeclaredConstructor().newInstance(); - RenJava renJava = (RenJava) o; - if (renJava.getClass().isAnnotationPresent(Game.class)) { - Game game = renJava.getClass().getAnnotation(Game.class); - renJava.name = game.name(); - renJava.author = game.author(); - renJava.version = game.version(); - } else { - System.err.println("ERROR: Please annotate your main class with 'Game'."); - renJava.name = "Error"; - renJava.author = "Error"; - renJava.version = "Error"; + File file = new File(System.getProperty("user.dir") + "/build.info"); + boolean failed = true; + + if (file.exists()) { + try (InputStream inputStream = new FileInputStream(file); + Scanner scanner = new Scanner(inputStream)) { + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (line.toLowerCase().startsWith("main=")) { + String[] split = line.split("="); + String clazzName = split[1]; + Class clazz = Class.forName(clazzName); + loadClass(clazz, args); + failed = false; + break; + } } + } catch (IOException | ClassNotFoundException e) { + System.err.println("Failed to load class: " + e.getMessage()); + } + } - // Build configuration - if (renJava.getClass().isAnnotationPresent(Configuration.class)) { - Configuration conf = renJava.getClass().getAnnotation(Configuration.class); - RenJavaConfiguration configuration = new RenJavaConfiguration(conf.title().replace("{version}", renJava.version).replace("{name}", renJava.name), conf.width(), conf.height(), new ImageLoader(conf.windowIconPath())); - renJava.setConfiguration(configuration); + if (failed) { + System.err.println("Build info not found. Scanning for RenJava class. This will have noticeable performance impact."); + // Scans for all classes in all packages. (We need to do all packages because this allows the author the freedom to do their own package scheme.) + Collection allPackagePrefixes = Arrays.stream(Package.getPackages()) + .map(Package::getName) + .map(s -> s.split("\\.")[0]) + .distinct() + .map(ClasspathHelper::forPackage) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + ConfigurationBuilder config = new ConfigurationBuilder().addUrls(allPackagePrefixes) + .addScanners(Scanners.SubTypes); + Reflections reflections = new Reflections(config); - } else { - System.err.println("ERROR: Configuration annotation not found. Please annotate your main class with 'Configuration'"); - RenJavaConfiguration configuration = new RenJavaConfiguration("Error", 1920, 1080, new ImageLoader("gui/window_icon.png")); - renJava.setConfiguration(configuration); - } + // Detect any classes that extend RenJava + for (Class c : reflections.getSubTypesOf(RenJava.class)) { + loadClass(c, args); + return; + } + } + } + + private static void loadClass(Class clazz, String[] args) { + try { + //FIXME: For performance save the path of the main class to reduce loading time + File file = new File(System.getProperty("user.dir") + "/build.info"); + if (!file.exists()) { + file.createNewFile(); + FileWriter writer = new FileWriter(file); + writer.append("main=").append(clazz.getName()); + writer.close(); + } - // Initialize the application logger - ApplicationLogger applicationLogger = new ApplicationLogger(c); - renJava.setLogger(applicationLogger.LOGGER); - renJava.getLogger().info("Initialized logger..."); - renJava.init(); // Initialize game - launch(args); - //c.getDeclaredConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { - System.err.println("ERROR: Could initialize the RenJava framework: " + e.getMessage()); + Object o = clazz.getDeclaredConstructor().newInstance(); + RenJava renJava = (RenJava) o; + if (renJava.getClass().isAnnotationPresent(Game.class)) { + Game game = renJava.getClass().getAnnotation(Game.class); + renJava.name = game.name(); + renJava.author = game.author(); + renJava.version = game.version(); + } else { + System.err.println("ERROR: Please annotate your main class with 'Game'."); + renJava.name = "Error"; + renJava.author = "Error"; + renJava.version = "Error"; } - return; - } - System.err.println("Could not initialize RenJava. Please make a class which extends 'RenJava'."); + // Build configuration + if (renJava.getClass().isAnnotationPresent(Configuration.class)) { + Configuration conf = renJava.getClass().getAnnotation(Configuration.class); + RenJavaConfiguration configuration = new RenJavaConfiguration(conf.title().replace("{version}", renJava.version).replace("{name}", renJava.name), conf.width(), conf.height(), new ImageLoader(conf.windowIconPath())); + renJava.setConfiguration(configuration); + + } else { + System.err.println("ERROR: Configuration annotation not found. Please annotate your main class with 'Configuration'"); + RenJavaConfiguration configuration = new RenJavaConfiguration("Error", 1920, 1080, new ImageLoader("gui/window_icon.png")); + renJava.setConfiguration(configuration); + } + + // Initialize the application logger + ApplicationLogger applicationLogger = new ApplicationLogger(clazz); + renJava.setLogger(applicationLogger.LOGGER); + + renJava.getLogger().info("Initialized logger..."); + + renJava.init(); // Initialize game + launch(args); + //c.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | + IOException e) { + System.err.println("ERROR: Could initialize the RenJava framework: " + e.getMessage()); + } } @Override From 1007b7d024cb252d8541d1dec446a1d17195b072 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 22:59:48 -0500 Subject: [PATCH 16/39] Added error logging when music file does not exist. --- .../piitex/renjava/api/exceptions/MusicFileNotFound.java | 7 +++++++ src/main/java/me/piitex/renjava/api/music/Tracks.java | 5 +++++ 2 files changed, 12 insertions(+) create mode 100644 src/main/java/me/piitex/renjava/api/exceptions/MusicFileNotFound.java diff --git a/src/main/java/me/piitex/renjava/api/exceptions/MusicFileNotFound.java b/src/main/java/me/piitex/renjava/api/exceptions/MusicFileNotFound.java new file mode 100644 index 0000000..baadeaa --- /dev/null +++ b/src/main/java/me/piitex/renjava/api/exceptions/MusicFileNotFound.java @@ -0,0 +1,7 @@ +package me.piitex.renjava.api.exceptions; + +public class MusicFileNotFound extends Exception { + public MusicFileNotFound(String fileName) { + super("Could not load track '" + fileName + "' as it does not exist. Please ensure the file is located within `/game/audio/" + fileName + "'"); + } +} diff --git a/src/main/java/me/piitex/renjava/api/music/Tracks.java b/src/main/java/me/piitex/renjava/api/music/Tracks.java index d910d73..f8e285e 100644 --- a/src/main/java/me/piitex/renjava/api/music/Tracks.java +++ b/src/main/java/me/piitex/renjava/api/music/Tracks.java @@ -1,5 +1,7 @@ package me.piitex.renjava.api.music; +import me.piitex.renjava.RenJava; +import me.piitex.renjava.api.exceptions.MusicFileNotFound; import me.piitex.renjava.api.saves.data.Data; import me.piitex.renjava.api.saves.data.PersistentData; @@ -21,6 +23,9 @@ public void addTrack(Track track) { } public Track getTrack(String trackID) { + if (tracks.get(trackID) == null) { + RenJava.getInstance().getLogger().error(new MusicFileNotFound(trackID).getMessage()); + } return tracks.get(trackID); } From b1ad800eb873ff1bea8a7e69a24ab30b1c2718e8 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 23:01:20 -0500 Subject: [PATCH 17/39] Added/Changed logging. --- src/main/java/me/piitex/renjava/api/player/Player.java | 2 +- src/main/java/me/piitex/renjava/gui/Menu.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/renjava/api/player/Player.java b/src/main/java/me/piitex/renjava/api/player/Player.java index b2f0e66..20efd52 100644 --- a/src/main/java/me/piitex/renjava/api/player/Player.java +++ b/src/main/java/me/piitex/renjava/api/player/Player.java @@ -103,7 +103,7 @@ public Map getStoryIdMap() { public void startStory(String id) { if (!storyIdMap.containsKey(id)) { - RenLogger.LOGGER.error(new InvalidStoryException(id).getMessage()); + RenJava.getInstance().getLogger().error(new InvalidStoryException(id).getMessage()); return; } RenLogger.LOGGER.info("Starting story '" + id + "'"); diff --git a/src/main/java/me/piitex/renjava/gui/Menu.java b/src/main/java/me/piitex/renjava/gui/Menu.java index 2426a0b..3f3762c 100644 --- a/src/main/java/me/piitex/renjava/gui/Menu.java +++ b/src/main/java/me/piitex/renjava/gui/Menu.java @@ -170,6 +170,7 @@ public Pane render() { * @param renScene The RenScene that is being used. If null, it will be assumed this is a main menu screen. */ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { + RenLogger.LOGGER.info("Rendering menu..."); if (root == null) { root = new Pane(); } @@ -192,10 +193,12 @@ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { layout.render(root); } + RenLogger.LOGGER.info("Rendering overlays..."); for (Overlay overlay : overlays) { new Element(overlay).render(root); } + RenLogger.LOGGER.info("Rendering sub-panes..."); for (Pane sub : subPanes) { root.getChildren().add(sub); } From 3c8c9a2dd94a151d25a4c60fbda27437063d47d7 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 23:01:48 -0500 Subject: [PATCH 18/39] Code cleanup. --- src/main/java/me/piitex/renjava/RenJava.java | 57 +++---------------- .../java/me/piitex/renjava/gui/GuiLoader.java | 15 +---- 2 files changed, 9 insertions(+), 63 deletions(-) diff --git a/src/main/java/me/piitex/renjava/RenJava.java b/src/main/java/me/piitex/renjava/RenJava.java index beb7b9f..852f019 100644 --- a/src/main/java/me/piitex/renjava/RenJava.java +++ b/src/main/java/me/piitex/renjava/RenJava.java @@ -108,17 +108,6 @@ protected void init() { // Run after super this.player = new Player(); this.tracks = new Tracks(); - // Load logger -// this.logger = Logger.getLogger(name); -// FileHandler fileHandler; -// try { -// fileHandler = new FileHandler("log.txt"); -// fileHandler.setFormatter(new RenLoggerFormat()); -// logger.addHandler(fileHandler); -// logger.info("Starting application..."); -// } catch (IOException e) { -// getLogger().severe("Could not initialize logger. " + e.getMessage()); -// } // Initializes the Ren logger which is separated from the application logger. RenLogger.init(); @@ -239,7 +228,7 @@ public Collection getCharacters() { */ public Character getCharacter(String id) { if (!registeredCharacters.containsKey(id)) { - RenLogger.LOGGER.error(new InvalidCharacterException(id).getMessage()); + RenJava.getInstance().getLogger().error(new InvalidCharacterException(id).getMessage()); return null; } return registeredCharacters.get(id.toLowerCase()); @@ -374,40 +363,8 @@ public void buildStage(Stage stage) { */ public abstract void createBaseData(); - /** - * Called to create a splash screen that is displayed before the title screen is loaded. - *

- * The `buildSplashScreen()` method should return a `SplashScreenView` object, which represents the splash screen view to be displayed. - * You can customize the appearance and behavior of the splash screen by configuring the `SplashScreenView` object. - *

- * The `SplashScreenView` class provides methods for setting the splash screen image, duration, and any additional UI elements or animations. - * You can use these methods to create an engaging and visually appealing splash screen for your game. - *

- * Example usage: - *

{@code
-     *     public SplashScreenView buildSplashScreen() {
-     *         // Create a SplashScreenView object
-     *         SplashScreenView splashScreen = new SplashScreenView();
-     *
-     *         // Set the splash screen image
-     *         splashScreen.setImage("splash.png");
-     *
-     *         // Set the duration of the splash screen (in seconds)
-     *         splashScreen.setDuration(3);
-     *
-     *         // Return the SplashScreenView object
-     *         return splashScreen;
-     *     }
-     * }
- * - * @return A `SplashScreenView` object representing the splash screen view to be displayed. - */ public abstract Menu buildSplashScreen(); - /** - * Called to create the main menu. (This is NOT optional) - * @return A MainTitleScreenView object which is parsed to a stage - */ public abstract Menu buildTitleScreen(); public Menu buildSideMenu() { @@ -578,16 +535,16 @@ public Menu buildAboutMenu() { *
*

* The start() method is used to initiate the story by displaying the first scene of the story. - * It retrieves the current story from the StoryManager using the story ID and builds the scene on the stage. - * This method should be called when the game starts. + * Using the {@link Player} object, call the first story (aka event) of the game. *

* * Example usage: *
{@code
-     *     // Get the current story from the StoryManager
-     *     Story myStory = this.getPlayer().getStory("my-story");
-     *     // Start the story
-     *     myStory.start();
+     *  @Override
+     *  public void start() {
+     *     this.getPlayer().startStory("my-story");
+     *  }
+     *
      * }
*/ public abstract void start(); diff --git a/src/main/java/me/piitex/renjava/gui/GuiLoader.java b/src/main/java/me/piitex/renjava/gui/GuiLoader.java index f252c05..8f6accd 100644 --- a/src/main/java/me/piitex/renjava/gui/GuiLoader.java +++ b/src/main/java/me/piitex/renjava/gui/GuiLoader.java @@ -62,16 +62,8 @@ private void renJavaFrameworkBuild() { } private void buildMainMenu() { - // Gonna put some default checks here. - // If there is no default font set one -// if (renJava.getConfiguration().getDefaultFont() == null) { -// RenLogger.LOGGER.severe("No default font set."); -// renJava.getConfiguration().setDefaultFont(new FontLoader("Arial", 24)); -// renJava.getConfiguration().setUiFont(new FontLoader("Arial", 26)); -// renJava.getConfiguration().setCharacterDisplayFont(new FontLoader("Arial", 26)); -// renJava.getConfiguration().setChoiceButtonFont(new FontLoader("Arial", 28)); -// } + RenJavaConfiguration configuration = renJava.getConfiguration(); if (configuration.getDefaultFont() == null) { RenLogger.LOGGER.error("Default font not set."); @@ -94,18 +86,15 @@ private void buildMainMenu() { renJava.getConfiguration().setChoiceButtonFont(new FontLoader("Arial", 28)); } - stage = new Stage(); - renJava.buildStage(stage); // Builds the stage parameters (Game Window) Menu menu = renJava.buildTitleScreen(); - MainMenuBuildEvent event = new MainMenuBuildEvent(menu); RenJava.callEvent(event); if (menu == null) { - RenLogger.LOGGER.error("No title screen was built. Please customize your own title screen for better user experience."); + RenLogger.LOGGER.error("No title screen was found. Please customize your own title screen for better user experience."); RenLogger.LOGGER.warn("Building RenJava default title screen..."); menu = new Menu(renJava.getConfiguration().getHeight(), renJava.getConfiguration().getWidth()).setTitle(renJava.getName() + " v" + renJava.getVersion()); try { From 1cf6a82b2f674df918a0c0e3cc1130630c90d273 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Mon, 25 Mar 2024 23:02:15 -0500 Subject: [PATCH 19/39] Updated README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index be46dfc..399201e 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ Visual novel game engine based off of [RenPy](https://www.renpy.org/) built with **Community** - [Website](), [Discord](), [YouTube]() -## Requirements -- [Java-17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) (You can typically download this within your IDE.) +## Project Requirements +- [Java-17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) (You can typically download this within your IDE) - [intellij](https://www.jetbrains.com/idea/download/?section=windows) or [Eclipse](https://www.eclipse.org/downloads/) -- Maven (should come with your IDE.) +- [Maven](https://maven.apache.org/download.cgi) (Might come with your IDE) ## Application Requirements - Java From 6b2d3cf8ae1b299b11cacedeaf82982ff7271679 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Fri, 29 Mar 2024 03:42:46 -0500 Subject: [PATCH 20/39] Updated logging and fixed error when loading singleton array. --- .../me/piitex/renjava/api/saves/Save.java | 140 +++++++++--------- 1 file changed, 73 insertions(+), 67 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/saves/Save.java b/src/main/java/me/piitex/renjava/api/saves/Save.java index 723b7b4..80325ed 100644 --- a/src/main/java/me/piitex/renjava/api/saves/Save.java +++ b/src/main/java/me/piitex/renjava/api/saves/Save.java @@ -1,11 +1,9 @@ package me.piitex.renjava.api.saves; - -import javafx.scene.image.ImageView; -import javafx.scene.layout.Pane; import me.piitex.renjava.RenJava; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.loggers.RenLogger; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.api.saves.data.Data; import me.piitex.renjava.api.saves.data.PersistentData; import me.piitex.renjava.api.saves.file.SectionKeyValue; @@ -67,16 +65,16 @@ public void write() { if (field.isAnnotationPresent(Data.class)) { SectionKeyValue mapSection = handleMap(data, field); if (mapSection != null) { - System.out.println("Map Section: "); +// System.out.println("Map Section: "); - System.out.println(mapSection); +// System.out.println(mapSection); rootSection.addSubSection(mapSection); continue; } // Handle fields try { - System.out.println("Processing field: " + field.getName()); +// System.out.println("Processing field: " + field.getName()); Object object = field.get(data); if (object == null) { RenLogger.LOGGER.warn("Value for '" + field.getName() + "' is null. Will not process data."); @@ -113,7 +111,7 @@ public void write() { private SectionKeyValue handleMap(PersistentData data, Field field) { if (field.getGenericType().getTypeName().contains("Map<")) { try { - System.out.println("Map type: " + field.getGenericType().getTypeName()); +// System.out.println("Map type: " + field.getGenericType().getTypeName()); SectionKeyValue sectionKeyValue = new SectionKeyValue(field.getName()); reconstructMap(sectionKeyValue, data, field); return sectionKeyValue; @@ -127,7 +125,7 @@ private SectionKeyValue handleMap(PersistentData data, Field field) { private void reconstructMap(SectionKeyValue sectionKeyValue, PersistentData data, Field field) throws IllegalAccessException { Map map = (Map) field.get(data); map.entrySet().forEach(objectObjectEntry -> { - System.out.println("Reconstructing entry..."); +// System.out.println("Reconstructing entry..."); sectionKeyValue.addKeyValue(objectObjectEntry.getKey().toString(), objectObjectEntry.getValue().toString()); }); } @@ -142,14 +140,20 @@ public void load(boolean process) { try { fullData = new Scanner(file).useDelimiter("\\Z").next(); } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } finally { - if (fullData == null) { - RenLogger.LOGGER.error("Save file does not exist."); - return; + // Only error if they are trying to process the loading function. + if (process) { + RenLogger.LOGGER.error(e.getMessage()); + } else { + // If process is false then its being cached and doesn't need to throw an error. + RenLogger.LOGGER.info(e.getMessage()); } } + if (fullData == null) { + RenLogger.LOGGER.error("Save file does not exist."); + return; + } + for (PersistentData persistentData : RenJava.getInstance().getRegisteredData()) { String clazzName = persistentData.getClass().getName(); SectionKeyValue rootSection = new SectionKeyValue(clazzName); @@ -157,16 +161,16 @@ public void load(boolean process) { String[] classSplit = fullData.split(clazzName + ":"); String fields = classSplit[1]; - System.out.println("Class Split: " + classSplit[1]); +// System.out.println("Class Split: " + classSplit[1]); String[] fieldSplit = fields.split("\n"); for (String field : fieldSplit) { - System.out.println("Field: " + field); +// System.out.println("Field: " + field); if (field.trim().isEmpty()) continue; String[] keyValueSplit = field.split(":"); String key = keyValueSplit[0]; if (keyValueSplit.length == 1) { if (key.startsWith(" ") || key.startsWith("\t")) { - System.out.println("Mapping found: " + key.trim()); +// System.out.println("Mapping found: " + key.trim()); mapSection = new SectionKeyValue(key.trim()); rootSection.addSubSection(mapSection); continue; @@ -176,7 +180,7 @@ public void load(boolean process) { } String value = keyValueSplit[1]; if ((key.startsWith(" ") || key.startsWith("\t")) && value.trim().isEmpty()) { - System.out.println("Mapping found: " + key.trim()); +// System.out.println("Mapping found: " + key.trim()); mapSection = new SectionKeyValue(key.trim()); rootSection.addSubSection(mapSection); } else if (value.trim().isEmpty()) { @@ -185,12 +189,12 @@ public void load(boolean process) { if (mapSection != null) { mapSection.addKeyValue(key.trim(), value.trim()); } - System.out.println("Mapping entry found: " + key.trim() + "," + value.trim()); +// System.out.println("Mapping entry found: " + key.trim() + "," + value.trim()); } else if (key.startsWith("\t") || key.startsWith(" ")){ // Handle generic entry // Check if entry is an array - if (value.contains(",")) { + if (value.contains(",") || value.contains("[")) { if (value.contains("[")) { value = value.replace("[", "").replace("]", ""); } @@ -205,7 +209,7 @@ public void load(boolean process) { processSection(persistentData, rootSection); } else { if (rootSection.getSection().contains("me.piitex.renjava.api.player.Player")) { - System.out.println("Mapping scene..."); +// System.out.println("Mapping scene..."); sceneSection = rootSection; } } @@ -221,18 +225,18 @@ public void processSection(PersistentData persistentData, SectionKeyValue rootSe // key: value // - System.out.println("================================================"); - System.out.println(); - System.out.println(rootSection.toString()); - System.out.println(); - System.out.println("================================================"); +// System.out.println("================================================"); +// System.out.println(); +// System.out.println(rootSection.toString()); +// System.out.println(); +// System.out.println("================================================"); // Next set the mapping to the fields List fields = new ArrayList<>(List.of(persistentData.getClass().getDeclaredFields())); fields.addAll(List.of(persistentData.getClass().getFields())); for (Field field : fields) { if (field.isAnnotationPresent(Data.class)) { - System.out.println("Processing Field: " + field.getName()); + //System.out.println("Processing Field: " + field.getName()); field.setAccessible(true); if (field.getGenericType().getTypeName().contains("Map<")) { // This is a map load. Scan for subsections if the field name matches. Add all data @@ -243,11 +247,11 @@ public void processSection(PersistentData persistentData, SectionKeyValue rootSe // Set the current values to whatever the load file is deconstructMap(subSection, persistentData, field); - try { - System.out.println("Map: " + field.get(persistentData).toString()); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } +// try { +// System.out.println("Map: " + field.get(persistentData).toString()); +// } catch (IllegalAccessException e) { +// throw new RuntimeException(e); +// } } } @@ -255,27 +259,27 @@ public void processSection(PersistentData persistentData, SectionKeyValue rootSe String keyToSet = (String) rootSection.getKeyValueMap().keySet().stream().filter(key -> key.toString().equalsIgnoreCase(field.getName())).findAny().orElse(null); if (keyToSet != null) { - System.out.println("Key To Set: " + keyToSet); +// System.out.println("Key To Set: " + keyToSet); try { // Casting string might not be a good idea. String value = (String) rootSection.getKeyValueMap().get(keyToSet); - System.out.println("Setting values for: " + field.getName()); +// System.out.println("Setting values for: " + field.getName()); setField(field, persistentData, value.strip()); // Testing checks - if (field.getName().equalsIgnoreCase("currentStory")) { - System.out.println("Current Story: " + field.get(persistentData)); - } - if (field.getName().equalsIgnoreCase("currentScene")) { - System.out.println("Current Scene: " + field.get(persistentData)); - } +// if (field.getName().equalsIgnoreCase("currentStory")) { +// System.out.println("Current Story: " + field.get(persistentData)); +// } +// if (field.getName().equalsIgnoreCase("currentScene")) { +// System.out.println("Current Scene: " + field.get(persistentData)); +// } } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); + RenLogger.LOGGER.trace(e.getMessage()); } } else { - System.err.println("Could not set field: " + field.getName()); + RenLogger.LOGGER.error("Could not set key '" + field.getName() + "'"); } } } @@ -290,7 +294,7 @@ private void deconstructMap(SectionKeyValue subSection, PersistentData data, Fie } if (objectMap == null) { - System.out.println("Map was null. Defaulting..."); +// System.out.println("Map was null. Defaulting..."); objectMap = new HashMap<>(); } @@ -298,8 +302,8 @@ private void deconstructMap(SectionKeyValue subSection, PersistentData data, Fie // TODO: 3/3/2024 Convert generic map type to actual type using the Mapper class Map finalObjectMap = objectMap; subSection.getKeyValueMap().forEach((key, value) -> { - System.out.println("Setting map..."); - System.out.println(key + ": " + value); +// System.out.println("Setting map..."); +// System.out.println(key + ": " + value); finalObjectMap.put(key, value); }); } @@ -327,39 +331,41 @@ private void setField(Field field, PersistentData data, String string2) throws N } // Builds the preview for saving and loading - public Pane buildPreview() { - Pane pane = new Pane(); + public Menu buildPreview() { + Menu menu = new Menu(1920, 1080); // Get the current scene the save is on. // Build the scene. // Scale it to a small box. + + // Default image + ImageOverlay saveImage = new ImageOverlay("gui/button/slot_idle_background.png"); if (sceneSection == null) { + RenLogger.LOGGER.info("Save slot '" + slot + "' scene does not exist."); // Default image - ImageLoader saveImage = new ImageLoader("gui/button/slot_idle_background.png"); - try { - ImageView view = new ImageView(saveImage.build()); - view.setFitHeight(419); - view.setFitWidth(309); - pane.getChildren().add(view); - } catch (ImageNotFoundException e) { - RenLogger.LOGGER.error(e.getMessage()); - } + menu.setBackgroundImage(saveImage); } else { Story story = RenJava.getInstance().getPlayer().getStory((String) sceneSection.get("currentStory")); - RenScene currentScene = story.getScene((String) sceneSection.get("currentScene")); - Menu menu = currentScene.build(true); - pane = menu.getPane(); - } - // Scale the pane to fit a small box. + //FIXME: This will produce a lot of programming debt. This is an extremely cheap unoptimized hack. - // 414 x 309 - // 1920 1080 - // 0.2, 0.28 - pane.setMaxWidth(414); - pane.setMaxHeight(309); + // Set the player to the current story (which is off to a horrible start) + RenJava.getInstance().getPlayer().setCurrentStory(story.getId()); + // Initialize the story to process the scenes. (Used to execute the `addScene` functions which maps the scenes to the story.) + story.init(); - return pane; + // Render the scene to the load button. + RenScene currentScene = story.getScene((String) sceneSection.get("currentScene")); + if (currentScene == null) { + RenLogger.LOGGER.error("Save slot '" + slot + "' appears to be corrupt or haas missing information. Unable to render save preview for the file. '" + sceneSection.get("currentScene") + "'"); + menu.setBackgroundImage(saveImage); + return menu; + } + RenLogger.LOGGER.debug("Save preview found for slot '" + slot + "'. " + currentScene.getId()); + + return currentScene.build(true); + } + return menu; } public File getFile() { From adac99db6b82f88bf587dcbf18ce445501302751 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 09:40:10 -0500 Subject: [PATCH 21/39] Improved and added functionality of gui elements. --- .../api/{builders => loaders}/FontLoader.java | 12 +- .../{builders => loaders}/ImageLoader.java | 7 +- .../renjava/gui/overlay/ButtonOverlay.java | 171 ++++++++++++++---- .../renjava/gui/overlay/ImageOverlay.java | 139 +++++++++++++- .../gui/overlay/InputFieldOverlay.java | 59 +++++- .../piitex/renjava/gui/overlay/Overlay.java | 20 ++ .../renjava/gui/overlay/TextFlowOverlay.java | 51 +++++- .../renjava/gui/overlay/TextOverlay.java | 59 +++++- 8 files changed, 454 insertions(+), 64 deletions(-) rename src/main/java/me/piitex/renjava/api/{builders => loaders}/FontLoader.java (92%) rename src/main/java/me/piitex/renjava/api/{builders => loaders}/ImageLoader.java (92%) diff --git a/src/main/java/me/piitex/renjava/api/builders/FontLoader.java b/src/main/java/me/piitex/renjava/api/loaders/FontLoader.java similarity index 92% rename from src/main/java/me/piitex/renjava/api/builders/FontLoader.java rename to src/main/java/me/piitex/renjava/api/loaders/FontLoader.java index 99bbe7e..96e4750 100644 --- a/src/main/java/me/piitex/renjava/api/builders/FontLoader.java +++ b/src/main/java/me/piitex/renjava/api/loaders/FontLoader.java @@ -1,4 +1,4 @@ -package me.piitex.renjava.api.builders; +package me.piitex.renjava.api.loaders; import javafx.scene.text.Font; import javafx.scene.text.FontPosture; @@ -16,7 +16,6 @@ public class FontLoader { private Font font; private FontWeight weight; private FontPosture posture; - private static final Map cachedFonts = new HashMap<>(); public FontLoader(FontLoader font, double size) { @@ -64,6 +63,7 @@ public FontLoader(String name) { try { if (!cachedFonts.containsKey(name)) { this.font = Font.loadFont(new FileInputStream(file), 24); + cachedFonts.put(name, font); } } catch (FileNotFoundException e) { this.font = Font.font(name, size); @@ -79,6 +79,14 @@ public double getSize() { return size; } + public FontPosture getPosture() { + return posture; + } + + public FontWeight getWeight() { + return weight; + } + public void setSize(double size) { this.size = size; this.font = Font.font(name, size); diff --git a/src/main/java/me/piitex/renjava/api/builders/ImageLoader.java b/src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java similarity index 92% rename from src/main/java/me/piitex/renjava/api/builders/ImageLoader.java rename to src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java index db6f7e3..6adb25d 100644 --- a/src/main/java/me/piitex/renjava/api/builders/ImageLoader.java +++ b/src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java @@ -1,4 +1,4 @@ -package me.piitex.renjava.api.builders; +package me.piitex.renjava.api.loaders; import javafx.scene.image.*; import me.piitex.renjava.api.APIChange; @@ -30,6 +30,11 @@ public ImageLoader(String name) { this.file = new File(directory, name); } + public ImageLoader(String directory, String name) { + File fileDirectory = new File(System.getProperty("user.dir") + "/" + directory + "/"); + this.file = new File(fileDirectory, name); + } + @APIChange(description = "Now supports .webp images.", changedVersion = "0.0.289") public Image build() throws ImageNotFoundException { try { diff --git a/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java index 532172b..2821d80 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/ButtonOverlay.java @@ -1,13 +1,17 @@ package me.piitex.renjava.gui.overlay; +import javafx.geometry.Pos; import javafx.scene.control.Button; +import javafx.scene.control.ContentDisplay; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.text.Font; import me.piitex.renjava.RenJava; +import me.piitex.renjava.gui.Menu; import me.piitex.renjava.loggers.RenLogger; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; import me.piitex.renjava.events.types.ButtonClickEvent; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; @@ -17,11 +21,12 @@ public class ButtonOverlay implements Overlay { private Button button; private Transitions transitions; - + private Menu menu; private final String id; private String text; + private double scaleX, scaleY; private Font font; - private Image image; + private ImageOverlay image; private Color textFill; private Color backgroundColor; private Color borderColor; @@ -32,7 +37,7 @@ public class ButtonOverlay implements Overlay { private int backgroundRadius = 0; private double x = 1, y = 1; - private int maxHeight = 0, maxWidth = 0; + private double maxHeight, maxWidth; private final double xScale, yScale; public ButtonOverlay(String id, String text, Color textFill, double xScale, double yScale) { @@ -161,19 +166,26 @@ public ButtonOverlay(String id, String text, Font font, Color textFill, Color ba * @param xScale X-Axis scale of the button. * @param yScale Y-Axis scale of the button. */ - public ButtonOverlay(String id, ImageLoader imageLoader, double x, double y, double xScale, double yScale) { + public ButtonOverlay(String id, ImageOverlay imageLoader, double x, double y, double xScale, double yScale) { this.id = id; - try { - this.image = imageLoader.build(); - } catch (ImageNotFoundException e) { - throw new RuntimeException(e); - } + this.image = imageLoader; this.x = x; this.y = y; this.xScale = xScale; this.yScale = yScale; } + public ButtonOverlay(String id, ImageOverlay imageLoader, double x, double y, int maxWidth, int maxHeight, double xScale, double yScale) { + this.id = id; + this.image = imageLoader; + this.x = x; + this.y = y; + this.xScale = xScale; + this.yScale = yScale; + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + } + /** * Create a button with image and text * @@ -185,13 +197,9 @@ public ButtonOverlay(String id, ImageLoader imageLoader, double x, double y, dou * @param xScale X-Axis scale of the button. * @param yScale Y-Axis scale of the button. */ - public ButtonOverlay(String id, ImageLoader imageLoader, String text, double x, double y, double xScale, double yScale) { + public ButtonOverlay(String id, ImageOverlay imageLoader, String text, double x, double y, double xScale, double yScale) { this.id = id; - try { - this.image = imageLoader.build(); - } catch (ImageNotFoundException e) { - throw new RuntimeException(e); - } + this.image = imageLoader; this.text = text; this.x = x; this.y = y; @@ -200,6 +208,28 @@ public ButtonOverlay(String id, ImageLoader imageLoader, String text, double x, this.button = build(); } + public ButtonOverlay(String id, Menu menu, double x, double y, double xScale, double yScale) { + this.id = id; + this.menu = menu; + this.x = x; + this.y = y; + this.xScale = xScale; + this.yScale = yScale; + this.button = build(); + } + + public ButtonOverlay(String id, Menu menu, double x, double y, int maxWidth, int maxHeight) { + this.id = id; + this.menu = menu; + this.x = x; + this.y = y; + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + this.xScale = 1; + this.yScale = 1; + this.button = build(); + } + public ButtonOverlay(Button button) { this.button = button; this.id = button.getId(); @@ -227,11 +257,11 @@ public void setFont(Font font) { this.font = font; } - public Image getImage() { + public ImageOverlay getImage() { return image; } - public void setImage(Image image) { + public void setImage(ImageOverlay image) { this.image = image; } @@ -306,6 +336,7 @@ public double x() { return x; } + @Override public void setX(double x) { this.x = x; } @@ -315,26 +346,51 @@ public double y() { return y; } - public void setY(double y) { - this.y = y; + @Override + public double scaleX() { + return scaleX; } - public int getMaxHeight() { - return maxHeight; + @Override + public double scaleY() { + return scaleY; } - public void setMaxHeight(int maxHeight) { - this.maxHeight = maxHeight; + @Override + public void setScaleX(double scaleX) { + this.scaleX = scaleX; } - public int getMaxWidth() { + @Override + public void setScaleY(double scaleY) { + this.scaleY = scaleY; + } + + @Override + public double width() { return maxWidth; } - public void setMaxWidth(int maxWidth) { - this.maxWidth = maxWidth; + @Override + public double height() { + return maxHeight; } + @Override + public void setWidth(double width) { + this.maxWidth = width; + } + + @Override + public void setHeight(double height) { + this.maxHeight = height; + } + + public void setY(double y) { + this.y = y; + } + + @Override public Transitions getTransition() { return transitions; @@ -359,8 +415,47 @@ public Button build() { Button button = new Button(); button.setId(id); if (image != null) { - ImageView imageView = new ImageView(image); + ImageView imageView = new ImageView(image.getImage()); + imageView.setFitWidth(image.width()); + imageView.setFitHeight(image.height()); + if (image.x() > 0) { + imageView.setX(image.x()); + } + if (image.y() > 0) { + imageView.setY(image.y()); + } + button.setAlignment(Pos.TOP_CENTER); button.setGraphic(imageView); + if (image.x() > 0) { + button.getGraphic().setTranslateX(image.x()); + } + if (image.y() > 0) { + // This can move the image within the button box + // The y and x values are separate from the main menu + // Top left of the box is 0,0 + // Bottom right of the box is boxWidth, boxHeight + button.getGraphic().setTranslateY(image.y()); + } + } + if (menu != null) { + //TODO: This is so fucking stupid if it works. + menu.setRenderFadeInFill(false); + menu.setRenderFadeOutFill(false); + + // Resize elements + menu.setScaleX(width() / menu.getWidth()); + menu.setScaleY(height() / menu.getHeight()); + + Pane node = menu.render(false); + + node.setMaxSize(maxWidth, maxHeight); + node.setTranslateX(button.getTranslateX() - 20); + node.setTranslateY(button.getTranslateY() - 20); + node.setPrefWidth(node.getMaxWidth() - 100); + node.setPrefHeight(node.getMaxHeight() - 100); + button.setGraphic(node); +// button.setContentDisplay(ContentDisplay.LEFT); +// button.setAlignment(Pos.CENTER_LEFT); } if (text != null && !text.isEmpty()) { button.setText(text); @@ -376,27 +471,33 @@ public Button build() { } if (maxHeight > 0) { button.setMaxHeight(maxHeight); + button.setPrefHeight(maxHeight); } if (maxWidth > 0) { button.setMaxWidth(maxWidth); + button.setPrefWidth(maxWidth); } String inLine = ""; if (backgroundColor != null) { inLine += "-fx-background-color: " + cssColor(backgroundColor) + "; "; + } else { + inLine += "-fx-background-color: transparent; "; } if (borderColor != null) { inLine += "-fx-border-color: " + cssColor(borderColor) + "; "; + } else { + inLine += "-fx-border-color: transparent; "; } inLine += "-fx-border-width: " + borderWidth + "; "; inLine += "-fx-background-radius: " + backgroundRadius + ";"; // https://stackoverflow.com/questions/30680570/javafx-button-border-and-hover if (hover) { - AtomicReference attomicInLine = new AtomicReference<>(inLine); + AtomicReference atomicInLine = new AtomicReference<>(inLine); button.setOnMouseEntered(mouseEvent -> { if (hoverColor != null) { button.setTextFill(hoverColor); - button.setStyle(attomicInLine.get()); + button.setStyle(atomicInLine.get()); } if (hoverImage != null) { try { @@ -408,9 +509,9 @@ public Button build() { }); button.setOnMouseExited(mouseEvent -> { button.setTextFill(textFill); - button.setStyle(attomicInLine.get()); + button.setStyle(atomicInLine.get()); if (image != null) { - button.setGraphic(new ImageView(image)); + button.setGraphic(new ImageView(image.getImage())); } }); } @@ -439,10 +540,4 @@ private String cssColor(Color color) { (int) (255 * color.getBlue()), color.getOpacity()); } - - public static ButtonOverlay copyOf(String id, ButtonOverlay builder) { - ButtonOverlay toReturn = new ButtonOverlay(id, builder.getText(), builder.getFont(), builder.getTextFill(), builder.x(), builder.y(), builder.getXScale(), builder.getYScale()); - toReturn.setImage(builder.getImage()); - return toReturn; - } } diff --git a/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java index 6e37db4..a36bf6d 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/ImageOverlay.java @@ -1,21 +1,84 @@ package me.piitex.renjava.gui.overlay; import javafx.scene.image.Image; +import javafx.scene.image.WritableImage; +import me.piitex.renjava.RenJava; import me.piitex.renjava.loggers.RenLogger; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; public class ImageOverlay implements Overlay { - private final Image image; - private final double x; - private final double y; - private final String fileName; + private Image image; + private double x; + private double y; + private double scaleX, scaleY; + private double width; + private double height; + private boolean preserveRatio = true; + private String fileName; private Transitions transitions; - public ImageOverlay(Image image, int x, int y) { + public ImageOverlay(Image image) { this.image = image; + this.width = image.getWidth(); + this.height = image.getHeight(); + this.x = 0; + this.y = 0; + this.fileName = "Unknown"; + } + + public ImageOverlay(WritableImage image) { + this.image = image; + this.width = image.getWidth(); + this.height = image.getHeight(); + this.x = 0; + this.y = 0; + this.fileName = "Unknown"; + } + + public ImageOverlay(ImageLoader imageLoader) { + try { + this.image = imageLoader.build(); + this.width = image.getWidth(); + this.height = image.getHeight(); + this.fileName = imageLoader.getFile().getName(); + } catch (ImageNotFoundException e) { + RenJava.getInstance().getLogger().error(e.getMessage()); + } + this.x = 0; + this.y = 0; + } + + public ImageOverlay(String imagePath) { + ImageLoader loader = new ImageLoader(imagePath); + try { + this.image = loader.build(); + this.fileName = loader.getFile().getName(); + this.width = image.getWidth(); + this.height = image.getHeight(); + } catch (ImageNotFoundException e) { + RenJava.getInstance().getLogger().error(e.getMessage()); + } + this.x = 0; + this.y = 0; + } + + public ImageOverlay(String directory, String imagePath) throws ImageNotFoundException { + ImageLoader loader = new ImageLoader(directory, imagePath); + this.image = loader.build(); + this.fileName = loader.getFile().getName(); + this.width = image.getWidth(); + this.height = image.getHeight(); + this.x = 0; + this.y = 0; + } + + public ImageOverlay(Image image, double x, double y) { + this.image = image; + this.width = image.getWidth(); + this.height = image.getHeight(); this.x = x; this.y = y; this.fileName = "Unknown"; @@ -24,10 +87,11 @@ public ImageOverlay(Image image, int x, int y) { public ImageOverlay(ImageLoader imageLoader, double x, double y) { try { this.image = imageLoader.build(); + this.width = image.getWidth(); + this.height = image.getHeight(); this.fileName = imageLoader.getFile().getName(); } catch (ImageNotFoundException e) { RenLogger.LOGGER.error(e.getMessage()); - throw new RuntimeException(); } this.x = x; this.y = y; @@ -51,12 +115,71 @@ public double y() { return y; } + @Override + public void setX(double x) { + this.x = x; + } + + @Override + public void setY(double y) { + this.y = y; + } + + @Override + public double scaleX() { + return scaleX; + } + + @Override + public double scaleY() { + return scaleY; + } + + @Override + public void setScaleX(double scaleX) { + this.scaleX = scaleX; + } + + @Override + public void setScaleY(double scaleY) { + this.scaleY = scaleY; + } + + @Override + public double width() { + return width; + } + + @Override + public double height() { + return height; + } + + @Override + public void setWidth(double width) { + this.width = width; + } + + @Override + public void setHeight(double height) { + this.height = height; + } + + public boolean isPreserveRatio() { + return preserveRatio; + } + + public void setPreserveRatio(boolean preserveRatio) { + this.preserveRatio = preserveRatio; + } + @Override public Transitions getTransition() { return transitions; } - public void setTransitions(Transitions transitions) { + public ImageOverlay setTransitions(Transitions transitions) { this.transitions = transitions; + return this; } } diff --git a/src/main/java/me/piitex/renjava/gui/overlay/InputFieldOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/InputFieldOverlay.java index cb3cd41..d67aa39 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/InputFieldOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/InputFieldOverlay.java @@ -1,12 +1,14 @@ package me.piitex.renjava.gui.overlay; import javafx.scene.control.TextField; -import me.piitex.renjava.api.builders.FontLoader; +import me.piitex.renjava.api.loaders.FontLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; public class InputFieldOverlay implements Overlay { - private final double x; - private final double y; + private double x; + private double y; + private double scaleX, scaleY; + private double height, width; private final FontLoader fontLoader; private Transitions transitions; @@ -26,6 +28,56 @@ public double y() { return y; } + @Override + public void setX(double x) { + this.x = x; + } + + @Override + public void setY(double y) { + this.y = y; + } + + @Override + public double scaleX() { + return scaleX; + } + + @Override + public double scaleY() { + return scaleY; + } + + @Override + public void setScaleX(double scaleX) { + this.scaleX = scaleX; + } + + @Override + public void setScaleY(double scaleY) { + this.scaleY = scaleY; + } + + @Override + public double width() { + return width; + } + + @Override + public double height() { + return height; + } + + @Override + public void setWidth(double width) { + this.width = width; + } + + @Override + public void setHeight(double height) { + this.height = height; + } + @Override public Transitions getTransition() { return transitions; @@ -45,6 +97,7 @@ public TextField build() { textField.setTranslateY(y); textField.setStyle(""); textField.setStyle("-fx-control-inner-background: transparent; -fx-background-color transparent;"); + textField.setPrefSize(width, height); return textField; } } diff --git a/src/main/java/me/piitex/renjava/gui/overlay/Overlay.java b/src/main/java/me/piitex/renjava/gui/overlay/Overlay.java index 0c83c93..7a1efb8 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/Overlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/Overlay.java @@ -8,5 +8,25 @@ public interface Overlay { double y(); + void setX(double x); + + void setY(double y); + + double scaleX(); + + double scaleY(); + + void setScaleX(double scaleX); + + void setScaleY(double scaleY); + + double width(); + + double height(); + + void setWidth(double width); + + void setHeight(double height); + Transitions getTransition(); } diff --git a/src/main/java/me/piitex/renjava/gui/overlay/TextFlowOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/TextFlowOverlay.java index 9ce93eb..aa2e109 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/TextFlowOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/TextFlowOverlay.java @@ -12,13 +12,14 @@ public class TextFlowOverlay implements Overlay { private double x; private double y; + private double scaleX, scaleY; private Transitions transitions; private Font font; private Color textColor; private LinkedList texts = new LinkedList<>(); - private final int width, height; + private double width, height; public TextFlowOverlay(String text, int width, int height) { this.width = width; @@ -43,6 +44,7 @@ public double x() { return x; } + @Override public void setX(double x) { this.x = x; } @@ -52,6 +54,46 @@ public double y() { return y; } + @Override + public double scaleX() { + return scaleX; + } + + @Override + public double scaleY() { + return scaleY; + } + + @Override + public void setScaleX(double scaleX) { + this.scaleX = scaleX; + } + + @Override + public void setScaleY(double scaleY) { + this.scaleY = scaleY; + } + + @Override + public double width() { + return width; + } + + @Override + public double height() { + return height; + } + + @Override + public void setWidth(double width) { + this.width = width; + } + + @Override + public void setHeight(double height) { + this.height = height; + } + public void setY(double y) { this.y = y; } @@ -81,13 +123,6 @@ public void setTransitions(Transitions transitions) { this.transitions = transitions; } - public int getWidth() { - return width; - } - - public int getHeight() { - return height; - } public LinkedList getTexts() { return texts; diff --git a/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java b/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java index 94db2d6..86f0647 100644 --- a/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java +++ b/src/main/java/me/piitex/renjava/gui/overlay/TextOverlay.java @@ -2,14 +2,16 @@ import javafx.scene.text.Text; -import me.piitex.renjava.api.builders.FontLoader; +import me.piitex.renjava.api.loaders.FontLoader; import me.piitex.renjava.api.scenes.transitions.Transitions; public class TextOverlay implements Overlay { private final Text text; private FontLoader fontLoader; - private final double x; - private final double y; + private double x; + private double y; + private double scaleX, scaleY; + private double width, height; private Transitions transitions; public TextOverlay(String text, double x, double y) { @@ -25,7 +27,6 @@ public TextOverlay(String text, FontLoader fontLoader, double x, double y) { this.y = y; } - public TextOverlay(Text text, double x, double y) { this.text = text; this.x = x; @@ -53,6 +54,56 @@ public double y() { return y; } + @Override + public void setX(double x) { + this.x = x; + } + + @Override + public void setY(double y) { + this.y = y; + } + + @Override + public double scaleX() { + return scaleX; + } + + @Override + public double scaleY() { + return scaleY; + } + + @Override + public void setScaleX(double scaleX) { + this.scaleX = scaleX; + } + + @Override + public void setScaleY(double scaleY) { + this.scaleY = scaleY; + } + + @Override + public double width() { + return width; + } + + @Override + public double height() { + return height; + } + + @Override + public void setWidth(double width) { + this.width = width; + } + + @Override + public void setHeight(double height) { + this.height = height; + } + public FontLoader getFontLoader() { return fontLoader; } From 08a558fb86105f76c461eb1bd28ff5730dfa7e13 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 12:18:45 -0500 Subject: [PATCH 22/39] Characters will no longer be automatically registered when created. --- .../me/piitex/renjava/api/characters/Character.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/characters/Character.java b/src/main/java/me/piitex/renjava/api/characters/Character.java index f9c6a09..8372d6f 100644 --- a/src/main/java/me/piitex/renjava/api/characters/Character.java +++ b/src/main/java/me/piitex/renjava/api/characters/Character.java @@ -18,7 +18,7 @@ * This class is abstract and serves as a base class for creating specific character implementations by extending it and providing additional functionality. * * @see javafx.scene.paint.Color - * @see me.piitex.renjava.RenJava + * @see RenJava */ public abstract class Character { private final String id; // The ID must be unique. The ID system allows you to have multiple characters with the same name. @@ -48,19 +48,13 @@ public abstract class Character { * @param color The color is used to color the display name. * * @see javafx.scene.paint.Color - * @see me.piitex.renjava.RenJava + * @see RenJava */ public Character(String id, String name, Color color) { this.id = id; this.name = name; this.color = color; this.displayName = name; - - RenJava.getInstance().registerCharacter(this); - - if (this instanceof PersistentData) { - RenJava.getInstance().registerData((PersistentData) this); - } } public String getId() { From 17f76ca168bae6c4f526de13ed6ea064e7196b12 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 12:19:36 -0500 Subject: [PATCH 23/39] Re-named package builders to loaders. --- src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java | 2 +- .../piitex/renjava/api/{builders => loaders}/VideoLoader.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/me/piitex/renjava/api/{builders => loaders}/VideoLoader.java (96%) diff --git a/src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java b/src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java index 6adb25d..2969ce7 100644 --- a/src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java +++ b/src/main/java/me/piitex/renjava/api/loaders/ImageLoader.java @@ -62,7 +62,7 @@ public File getFile() { // Credit: https://stackoverflow.com/questions/30970005/bufferedimage-to-javafx-image - private Image getImage(BufferedImage img){ + private Image getImage(BufferedImage img) { //converting to a good type, read about types here: https://openjfx.io/javadoc/13/javafx.graphics/javafx/scene/image/PixelBuffer.html BufferedImage newImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE); newImg.createGraphics().drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null); diff --git a/src/main/java/me/piitex/renjava/api/builders/VideoLoader.java b/src/main/java/me/piitex/renjava/api/loaders/VideoLoader.java similarity index 96% rename from src/main/java/me/piitex/renjava/api/builders/VideoLoader.java rename to src/main/java/me/piitex/renjava/api/loaders/VideoLoader.java index 372df67..d55b242 100644 --- a/src/main/java/me/piitex/renjava/api/builders/VideoLoader.java +++ b/src/main/java/me/piitex/renjava/api/loaders/VideoLoader.java @@ -1,4 +1,4 @@ -package me.piitex.renjava.api.builders; +package me.piitex.renjava.api.loaders; import javafx.scene.media.Media; import javafx.scene.media.MediaPlayer; From 11ec63a18298dd3fd23df8db74aa0da7b1cd0d1e Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 13:35:09 -0500 Subject: [PATCH 24/39] Converted ImageLoader to ImageOverlay for all RenScenes' --- .../scenes/animation/AnimationBuilder.java | 2 +- .../api/scenes/types/AnimationScene.java | 10 +++---- .../api/scenes/types/AutoPlayScene.java | 24 +++++++++++---- .../renjava/api/scenes/types/ImageScene.java | 30 +++++++++++-------- .../api/scenes/types/InteractableScene.java | 9 +++--- .../api/scenes/types/choices/ChoiceScene.java | 9 +++--- .../api/scenes/types/input/InputScene.java | 12 ++++---- 7 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/scenes/animation/AnimationBuilder.java b/src/main/java/me/piitex/renjava/api/scenes/animation/AnimationBuilder.java index 3dcab41..150858e 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/animation/AnimationBuilder.java +++ b/src/main/java/me/piitex/renjava/api/scenes/animation/AnimationBuilder.java @@ -25,7 +25,7 @@ public Timeline build() throws ImageNotFoundException { Timeline timeline = null; // TODO: 2/7/2024 Calculate keyframes base on the time inputted. if (animationTarget == AnimationTarget.IMAGE) { - ImageView imageView = new ImageView(renScene.getBackgroundImage().build()); + ImageView imageView = new ImageView(renScene.getBackgroundImage().getImage()); KeyFrame keyFrame = new KeyFrame(Duration.seconds(0), new KeyValue(imageView.opacityProperty(), 0)); // First second KeyFrame keyFrame2 = new KeyFrame(Duration.seconds(0.5), new KeyValue(imageView.opacityProperty(), 0.2)); // First second KeyFrame keyFrame3 = new KeyFrame(Duration.seconds(1.5), new KeyValue(imageView.opacityProperty(), 0.5)); // First second diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java index 4825da1..d4d8682 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/AnimationScene.java @@ -14,9 +14,9 @@ import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; -import me.piitex.renjava.api.builders.FontLoader; -import me.piitex.renjava.api.builders.ImageLoader; -import me.piitex.renjava.api.builders.VideoLoader; +import me.piitex.renjava.api.loaders.FontLoader; +import me.piitex.renjava.api.loaders.ImageLoader; +import me.piitex.renjava.api.loaders.VideoLoader; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; public class AnimationScene extends RenScene { @@ -61,10 +61,8 @@ public Menu build(boolean ui) { text = new Text(dialogue); if (getCharacterNameDisplay() != null && !getCharacterNameDisplay().isEmpty()) { // Set character display - RenLogger.LOGGER.info("Character Display Name Validation: " + getCharacterNameDisplay()); characterDisplay = new Text(getCharacterNameDisplay()); } else { - RenLogger.LOGGER.info("Character Display Name Validation: " + character.getDisplayName()); characterDisplay = new Text(character.getDisplayName()); } characterDisplay.setFill(character.getColor()); @@ -94,7 +92,7 @@ public Menu build(boolean ui) { texFlow.getChildren().add(text); // Add the text to the textflow root.getChildren().add(texFlow); - characterDisplay.setFont(new FontLoader("JandaManateeSolid.ttf", 36).getFont()); + characterDisplay.setFont(new FontLoader(RenJava.getInstance().getConfiguration().getCharacterDisplayFont(), 36).getFont()); characterDisplay.setX(setX + 200); characterDisplay.setY(setY + 70); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java index 0a444dc..c88e0ab 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/AutoPlayScene.java @@ -1,25 +1,27 @@ package me.piitex.renjava.api.scenes.types; import me.piitex.renjava.RenJava; -import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.characters.Character; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.events.types.SceneStartEvent; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; +import me.piitex.renjava.gui.overlay.ImageOverlay; import org.jetbrains.annotations.Nullable; public class AutoPlayScene extends RenScene { - private final ImageLoader backgroundImage; + private ImageOverlay backgroundImage; private final Character character; private final String dialogue; private final int duration; + private boolean useImage = true; + private static final RenJava renJava = RenJava.getInstance(); - public AutoPlayScene(String id, @Nullable Character character, @Nullable String dialogue, ImageLoader backgroundImage, int duration) { + public AutoPlayScene(String id, @Nullable Character character, @Nullable String dialogue, ImageOverlay backgroundImage, int duration) { super(id, backgroundImage); this.character = character; this.dialogue = dialogue; @@ -27,14 +29,26 @@ public AutoPlayScene(String id, @Nullable Character character, @Nullable String this.duration = duration; } + public AutoPlayScene(String id, @Nullable Character character, @Nullable String dialogue, int duration) { + super(id, null); + this.character = character; + this.dialogue = dialogue; + this.duration = duration; + useImage = false; + } + @Override public Menu build(boolean ui) { - return new ImageScene(null, character, dialogue, backgroundImage).build(ui); + if (useImage) { + return new ImageScene(null, character, dialogue, backgroundImage).build(ui); + } else { + return new ImageScene(null, character, dialogue).build(ui); + } } @Override public void render(Menu menu) { - menu.render(); + menu.render(this); renJava.setStage(renJava.getStage(), StageType.IMAGE_SCENE); SceneStartEvent event = new SceneStartEvent(this); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java index be2b069..5458c64 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/ImageScene.java @@ -10,10 +10,11 @@ import me.piitex.renjava.events.types.SceneStartEvent; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; -import me.piitex.renjava.api.builders.FontLoader; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.FontLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.gui.overlay.*; +import me.piitex.renjava.loggers.RenLogger; import org.jetbrains.annotations.Nullable; import java.io.File; @@ -50,7 +51,7 @@ public class ImageScene extends RenScene { private Character character; private String dialogue; - private ImageLoader backgroundImage; + private ImageOverlay backgroundImage; private Font font; private String characterDisplayName; @@ -66,15 +67,15 @@ public class ImageScene extends RenScene { * @param id The ID used to identify the scene. * @param character The character who is talking. Pass null if no character is talking in the scene. * @param dialogue The dialogue of the character. Pass null or an empty string if no one is talking. - * @param loader The background image loader for the scene. + * @param backgroundImage The background image loader for the scene. */ - public ImageScene(String id, @Nullable Character character, String dialogue, @Nullable ImageLoader loader) { - super(id, loader); + public ImageScene(String id, @Nullable Character character, String dialogue, @Nullable ImageOverlay backgroundImage) { + super(id, backgroundImage); this.character = character; this.dialogue = dialogue; - if (loader != null) { - this.backgroundImage = loader; - renJava.getPlayer().setLastDisplayedImage(new AbstractMap.SimpleEntry<>(getStory().getId(), loader)); + if (backgroundImage != null) { + this.backgroundImage = backgroundImage; + renJava.getPlayer().setLastDisplayedImage(new AbstractMap.SimpleEntry<>(getStory().getId(), backgroundImage)); } if (character != null) { this.characterDisplayName = character.getDisplayName(); @@ -133,6 +134,7 @@ public Menu build(boolean ui) { characterDisplay.setFill(character.getColor()); if (dialogue != null && !dialogue.isEmpty()) { + RenLogger.LOGGER.debug("Rendering textbox"); ImageLoader textbox = new ImageLoader("gui/textbox.png"); Menu textboxMenu = new Menu(configuration.getDialogueBoxWidth(), configuration.getDialogueBoxHeight()); @@ -155,7 +157,7 @@ public Menu build(boolean ui) { textboxMenu.addOverlay(textFlowOverlay); characterDisplay.setFill(character.getColor()); - TextOverlay characterText = new TextOverlay(characterDisplay, new FontLoader(configuration.getDefaultFont().getFont(), configuration.getCharacterTextSize()), + TextOverlay characterText = new TextOverlay(characterDisplay, new FontLoader(configuration.getCharacterDisplayFont(), configuration.getCharacterTextSize()), configuration.getCharacterTextX() + configuration.getCharacterTextOffsetX(), configuration.getCharacterTextY() + configuration.getCharacterTextOffsetY()); @@ -164,7 +166,11 @@ public Menu build(boolean ui) { textboxMenu.addOverlay(characterText); + RenLogger.LOGGER.debug("Textbox Menu Debug: " + textboxMenu.getOverlays().size()); + rootMenu.addMenu(textboxMenu); + + RenLogger.LOGGER.debug("Root Menu Debug: " + rootMenu.getChildren().size()); } } } @@ -174,7 +180,7 @@ public Menu build(boolean ui) { try { RenJava.getInstance().getStage().getScene().getStylesheets().add(file.toURI().toURL().toExternalForm()); } catch (MalformedURLException e) { - e.printStackTrace(); + renJava.getLogger().error(e.getMessage()); } } @@ -188,7 +194,7 @@ public Menu build(boolean ui) { @Override public void render(Menu menu) { renJava.setStage(renJava.getStage(), StageType.IMAGE_SCENE); - menu.render(null, this); + menu.render(this); SceneStartEvent event = new SceneStartEvent(this); RenJava.callEvent(event); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/InteractableScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/InteractableScene.java index c72dbd9..95e343a 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/InteractableScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/InteractableScene.java @@ -1,6 +1,5 @@ package me.piitex.renjava.api.scenes.types; -import javafx.stage.Stage; import me.piitex.renjava.RenJava; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.stories.Story; @@ -8,7 +7,7 @@ import me.piitex.renjava.events.types.SceneBuildEvent; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.gui.overlay.Overlay; /** @@ -57,7 +56,7 @@ */ public class InteractableScene extends RenScene { - private final ImageLoader backgroundImage; + private final ImageOverlay backgroundImage; private static final RenJava renJava = RenJava.getInstance(); @@ -94,7 +93,7 @@ public StageType getStageType() { * @see Overlay * @see EventListener */ - public InteractableScene(String id, ImageLoader backgroundImage) { + public InteractableScene(String id, ImageOverlay backgroundImage) { super(id, backgroundImage); this.backgroundImage = backgroundImage; } @@ -112,7 +111,7 @@ public Menu build(boolean ui) { @Override public void render(Menu menu) { - menu.render(null, this); + menu.render(this); renJava.setStage(renJava.getStage(), StageType.INTERACTABLE_SCENE); } } diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java index 7ac5f27..dcfde87 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/choices/ChoiceScene.java @@ -6,6 +6,7 @@ import javafx.scene.image.ImageView; import javafx.scene.paint.Color; import me.piitex.renjava.RenJava; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.events.types.ButtonClickEvent; @@ -13,7 +14,7 @@ import me.piitex.renjava.events.types.SceneStartEvent; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.gui.exceptions.ImageNotFoundException; import me.piitex.renjava.gui.layouts.impl.VerticalLayout; import me.piitex.renjava.gui.overlay.ButtonOverlay; @@ -65,7 +66,7 @@ * @see ChoiceSelectInterface */ public class ChoiceScene extends RenScene { - private final ImageLoader backgroundImage; + private final ImageOverlay backgroundImage; private ChoiceSelectInterface selectInterface; @@ -82,7 +83,7 @@ public StageType getStageType() { * @param id The unique identifier for the scene. * @param backgroundImage The background image for the scene. */ - public ChoiceScene(String id, ImageLoader backgroundImage) { + public ChoiceScene(String id, ImageOverlay backgroundImage) { super(id, backgroundImage); this.backgroundImage = backgroundImage; } @@ -182,7 +183,7 @@ public Menu build(boolean ui) { @Override public void render(Menu menu) { RenJava.getInstance().setStage(RenJava.getInstance().getStage(), StageType.CHOICE_SCENE); - menu.render(null, this); + menu.render(this); SceneStartEvent event = new SceneStartEvent(this); RenJava.callEvent(event); diff --git a/src/main/java/me/piitex/renjava/api/scenes/types/input/InputScene.java b/src/main/java/me/piitex/renjava/api/scenes/types/input/InputScene.java index a672f35..a670ea6 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/types/input/InputScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/types/input/InputScene.java @@ -3,13 +3,13 @@ import javafx.scene.control.TextField; import javafx.scene.text.Text; import me.piitex.renjava.RenJava; -import me.piitex.renjava.api.builders.FontLoader; +import me.piitex.renjava.api.loaders.FontLoader; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.scenes.types.ImageScene; import me.piitex.renjava.events.types.SceneStartEvent; import me.piitex.renjava.gui.Menu; import me.piitex.renjava.gui.StageType; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.gui.overlay.InputFieldOverlay; import me.piitex.renjava.gui.overlay.TextFlowOverlay; import org.jetbrains.annotations.Nullable; @@ -34,7 +34,7 @@ */ public class InputScene extends RenScene { private final String text; - private final ImageLoader loader; + private final ImageOverlay loader; private TextField inputField; private InputSetInterface setInterface; @@ -44,7 +44,7 @@ public class InputScene extends RenScene { * @param id The ID of the InputScene. * @param loader The image loader used to load the background image. */ - public InputScene(String id, @Nullable String text, ImageLoader loader) { + public InputScene(String id, @Nullable String text, ImageOverlay loader) { super(id, loader); this.text = text; this.loader = loader; @@ -64,7 +64,7 @@ public InputSetInterface getSetInterface() { @Override public Menu build(boolean ui) { - Menu menu = new Menu(1920.0, 1080.0); + Menu menu = new Menu(1920, 1080); Menu imageMenu = (new ImageScene(null, null, this.text, this.loader)).build(ui); if (ui) { TextFlowOverlay textFlowOverlay; @@ -84,7 +84,7 @@ public Menu build(boolean ui) { @Override public void render(Menu menu) { RenJava.getInstance().setStage(RenJava.getInstance().getStage(), StageType.INPUT_SCENE); - menu.render(null, this); // FIXME: 12/29/2023 Render depending on if ui is toggled + menu.render(this); // FIXME: 12/29/2023 Render depending on if ui is toggled SceneStartEvent event = new SceneStartEvent(this); RenJava.callEvent(event); From c7b0fc071920c908dfdce3cd42e4d47b33e307b6 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 13:43:20 -0500 Subject: [PATCH 25/39] Added advanced scene tracking. --- .../me/piitex/renjava/api/player/Player.java | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/player/Player.java b/src/main/java/me/piitex/renjava/api/player/Player.java index 20efd52..0f66148 100644 --- a/src/main/java/me/piitex/renjava/api/player/Player.java +++ b/src/main/java/me/piitex/renjava/api/player/Player.java @@ -1,9 +1,10 @@ package me.piitex.renjava.api.player; +import javafx.scene.Scene; import me.piitex.renjava.RenJava; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.loggers.RenLogger; import me.piitex.renjava.api.APINote; -import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.exceptions.InvalidStoryException; import me.piitex.renjava.api.saves.data.Data; import me.piitex.renjava.api.saves.data.PersistentData; @@ -21,7 +22,7 @@ public class Player implements PersistentData { @Data private String currentStory; // Entry to map the story for the image - private Map.Entry lastDisplayedImage; + private Map.Entry lastDisplayedImage; private boolean transitionPlaying = false; private boolean uiToggled = true; @@ -37,6 +38,9 @@ public class Player implements PersistentData { private final Map storyIdMap = new HashMap<>(); + private Scene lastRenderedScene; + private RenScene lastRenderedRenScene; + public boolean hasSeenScene(Story story, String sceneID) { return viewedScenes.containsKey(story.getId()) && viewedScenes.containsValue(sceneID); } @@ -119,11 +123,11 @@ public void setRightClickMenu(boolean rightClickMenu) { this.rightClickMenu = rightClickMenu; } - public Map.Entry getLastDisplayedImage() { + public Map.Entry getLastDisplayedImage() { return lastDisplayedImage; } - public void setLastDisplayedImage(Map.Entry lastDisplayedImage) { + public void setLastDisplayedImage(Map.Entry lastDisplayedImage) { this.lastDisplayedImage = lastDisplayedImage; } @@ -151,6 +155,22 @@ public void setTransitionPlaying(boolean transitionPlaying) { this.transitionPlaying = transitionPlaying; } + public Scene getLastRenderedScene() { + return lastRenderedScene; + } + + public void setLastRenderedScene(Scene lastRenderedScene) { + this.lastRenderedScene = lastRenderedScene; + } + + public RenScene getLastRenderedRenScene() { + return lastRenderedRenScene; + } + + public void setLastRenderedRenScene(RenScene lastRenderedRenScene) { + this.lastRenderedRenScene = lastRenderedRenScene; + } + public void updateScene(RenScene renScene) { setCurrentScene(renScene.getId()); // Update the scene. getViewedScenes().put(renScene.getStory().getId(), renScene.getId()); From 69751fb8b4a953faa8810f0d61a066ff9dc1f403 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 13:44:57 -0500 Subject: [PATCH 26/39] Converted ImageLoader to ImageOverlay for all RenScenes' --- .../me/piitex/renjava/api/scenes/RenScene.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/scenes/RenScene.java b/src/main/java/me/piitex/renjava/api/scenes/RenScene.java index 6c3adea..34b3f25 100644 --- a/src/main/java/me/piitex/renjava/api/scenes/RenScene.java +++ b/src/main/java/me/piitex/renjava/api/scenes/RenScene.java @@ -3,18 +3,15 @@ import me.piitex.renjava.RenJava; import me.piitex.renjava.api.scenes.animation.AnimationBuilder; import me.piitex.renjava.api.scenes.transitions.Transitions; -import me.piitex.renjava.api.scenes.types.SceneBuildInterface; +import me.piitex.renjava.api.scenes.types.*; import me.piitex.renjava.gui.layouts.Container; -import me.piitex.renjava.api.scenes.types.AnimationScene; -import me.piitex.renjava.api.scenes.types.ImageScene; -import me.piitex.renjava.api.scenes.types.InteractableScene; import me.piitex.renjava.api.scenes.types.choices.ChoiceScene; import me.piitex.renjava.api.scenes.types.input.InputScene; import me.piitex.renjava.api.stories.Story; import me.piitex.renjava.gui.StageType; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.gui.overlay.Overlay; import java.io.File; @@ -32,6 +29,7 @@ *

* * @see ImageScene + * @see AutoPlayScene * @see InteractableScene * @see AnimationScene * @see InputScene @@ -39,7 +37,7 @@ */ public abstract class RenScene extends Container { private final String id; - private ImageLoader backgroundImage; + private ImageOverlay backgroundImage; private Story story; private int index; private SceneStartInterface startInterface; @@ -57,7 +55,7 @@ public abstract class RenScene extends Container { private final Collection styleSheets = new HashSet<>(); - public RenScene(String id, ImageLoader backgroundImage) { + public RenScene(String id, ImageOverlay backgroundImage) { this.id = id; this.backgroundImage = backgroundImage; setStory(RenJava.getInstance().getPlayer().getCurrentStory()); // Update the current story. @@ -109,11 +107,11 @@ public String getId() { return id; } - public ImageLoader getBackgroundImage() { + public ImageOverlay getBackgroundImage() { return backgroundImage; } - public void setBackgroundImage(ImageLoader backgroundImage) { + public void setBackgroundImage(ImageOverlay backgroundImage) { this.backgroundImage = backgroundImage; } @@ -162,4 +160,4 @@ public void addStyleSheets(File file) { public Collection getStyleSheets() { return styleSheets; } -} +} \ No newline at end of file From f1dd690cc0dd95a8f0d2dc17e3fa4cbee6b91365 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 13:46:09 -0500 Subject: [PATCH 27/39] Fixed bug where story wouldn't update when manually displaying scenes. --- .../me/piitex/renjava/api/stories/Story.java | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/main/java/me/piitex/renjava/api/stories/Story.java b/src/main/java/me/piitex/renjava/api/stories/Story.java index d5d72df..ec2c995 100644 --- a/src/main/java/me/piitex/renjava/api/stories/Story.java +++ b/src/main/java/me/piitex/renjava/api/stories/Story.java @@ -115,7 +115,7 @@ public void start() { // Update RenJava Player BEFORE the scenes are added renJava.getPlayer().setCurrentStory(this.getId()); - clear(); // Clear previous mappings + clear(); // Clear previous mappings (allows refreshing) init(); // Initialize when starting logger.info("Building scene..."); @@ -141,17 +141,6 @@ public void refresh() { init(); } - /** - * Refreshes a specific scene in the story by replacing it with a new instance of the scene. - * This method is useful when you want to update a scene dynamically during the story. - * - * @param sceneID The ID of the scene to refresh. - */ - public void refresh(String sceneID) { - RenScene scene = getScene(sceneID); - scenes.replace(sceneID, scene, scene); - } - public void clear() { scenes.clear(); sceneIndexMap.clear(); @@ -167,6 +156,7 @@ public void addScene(RenScene scene) { scenes.replace(scene.getId(), scenes.get(id), scene); return; } + scene.setStory(this); scenes.put(scene.getId(), scene); int index = sceneIndexMap.size(); sceneIndexMap.put(index, scene); @@ -179,10 +169,7 @@ public void addScene(RenScene scene) { */ public void addScenes(RenScene... scenes) { for (RenScene renScene : scenes) { - this.scenes.put(renScene.getId(), renScene); - int index = sceneIndexMap.size(); - sceneIndexMap.put(index, renScene); - renScene.setIndex(index); + addScene(renScene); } } From 21981a556ebd724c7db9d5a6ecd3f15569cdbf54 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 13:47:22 -0500 Subject: [PATCH 28/39] Added SceneRenderEvent --- .../events/types/SceneRenderEvent.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/me/piitex/renjava/events/types/SceneRenderEvent.java diff --git a/src/main/java/me/piitex/renjava/events/types/SceneRenderEvent.java b/src/main/java/me/piitex/renjava/events/types/SceneRenderEvent.java new file mode 100644 index 0000000..f74da8f --- /dev/null +++ b/src/main/java/me/piitex/renjava/events/types/SceneRenderEvent.java @@ -0,0 +1,23 @@ +package me.piitex.renjava.events.types; + +import javafx.scene.Scene; +import me.piitex.renjava.api.scenes.RenScene; +import me.piitex.renjava.events.Event; + +public class SceneRenderEvent extends Event { + private final RenScene renScene; + private final Scene scene; + + public SceneRenderEvent(RenScene renScene, Scene scene) { + this.renScene = renScene; + this.scene = scene; + } + + public RenScene getRenScene() { + return renScene; + } + + public Scene getScene() { + return scene; + } +} From acba4e1ceb5b53dd6f75e415c84622e1f1075f79 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 13:48:38 -0500 Subject: [PATCH 29/39] Added more rendering functions and converted ImageLoader to ImageOverlay. --- src/main/java/me/piitex/renjava/gui/Menu.java | 155 +++++++++++++----- 1 file changed, 112 insertions(+), 43 deletions(-) diff --git a/src/main/java/me/piitex/renjava/gui/Menu.java b/src/main/java/me/piitex/renjava/gui/Menu.java index 3f3762c..e977d55 100644 --- a/src/main/java/me/piitex/renjava/gui/Menu.java +++ b/src/main/java/me/piitex/renjava/gui/Menu.java @@ -3,17 +3,14 @@ import javafx.geometry.Insets; import javafx.scene.Node; import javafx.scene.Scene; -import javafx.scene.image.Image; import javafx.scene.layout.*; import javafx.stage.Stage; import me.piitex.renjava.RenJava; import me.piitex.renjava.loggers.RenLogger; -import me.piitex.renjava.api.builders.ImageLoader; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.scenes.transitions.Transitions; import me.piitex.renjava.events.types.*; -import me.piitex.renjava.gui.exceptions.ImageNotFoundException; import me.piitex.renjava.gui.layouts.Layout; import me.piitex.renjava.gui.overlay.*; import org.jetbrains.annotations.Nullable; @@ -26,14 +23,17 @@ public class Menu { private final Stage stage; private Pane pane; private static Menu rootMenu; - private final double width, height; - - private int x, y; + private double width, height; + private boolean renderFadeInFill = true; + private boolean renderFadeOutFill = true; + private double x, y; + private double scaleX; + private double scaleY; // Pre configured data. private String title = renJava.getName(); - private Image backgroundImage; + private ImageOverlay backgroundImage; private final LinkedHashSet nodes = new LinkedHashSet<>(); private final LinkedHashSet layouts = new LinkedHashSet<>(); @@ -50,14 +50,8 @@ public Menu(double width, double height) { this.stage = renJava.getStage(); } - public Menu(double width, double height, ImageLoader imageLoader) { - if (imageLoader != null) { - try { - this.backgroundImage = imageLoader.build(); - } catch (ImageNotFoundException e) { - RenLogger.LOGGER.error(e.getMessage()); - } - } + public Menu(double width, double height, ImageOverlay backgroundImage) { + this.backgroundImage = backgroundImage; this.width = width; this.height = height; this.stage = renJava.getStage(); @@ -75,15 +69,23 @@ public double getHeight() { return height; } + public void setHeight(int height) { + this.height = height; + } + public double getWidth() { return width; } - public int getX() { + public void setWidth(int width) { + this.width = width; + } + + public double getX() { return x; } - public int getY() { + public double getY() { return y; } @@ -95,15 +97,39 @@ public void setY(int y) { this.y = y; } + public double getScaleX() { + return scaleX; + } + + public void setScaleX(double scaleX) { + this.scaleX = scaleX; + } + + public double getScaleY() { + return scaleY; + } + + public void setScaleY(double scaleY) { + this.scaleY = scaleY; + } + + public void setRenderFadeInFill(boolean renderFadeInFill) { + this.renderFadeInFill = renderFadeInFill; + } + + public void setRenderFadeOutFill(boolean renderFadeOutFill) { + this.renderFadeOutFill = renderFadeOutFill; + } + public String getTitle() { return title; } - public Image getBackgroundImage() { + public ImageOverlay getBackgroundImage() { return backgroundImage; } - public Menu setBackgroundImage(Image backgroundImage) { + public Menu setBackgroundImage(ImageOverlay backgroundImage) { this.backgroundImage = backgroundImage; return this; } @@ -160,7 +186,19 @@ public Menu addMenu(Menu menu) { } public Pane render() { - return render(null, null); + return render(null, null, true); + } + + public Pane render(boolean render) { + return render(null, null, render); + } + + public Pane render(Pane pane) { + return render(pane, null, true); + } + + public Pane render(RenScene renScene) { + return render(null, renScene, true); } /** @@ -169,22 +207,38 @@ public Pane render() { * @param root The root Group to which the menu will be added. If null, a new Group will be created. * @param renScene The RenScene that is being used. If null, it will be assumed this is a main menu screen. */ - public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { + public Pane render(@Nullable Pane root, @Nullable RenScene renScene, boolean render) { RenLogger.LOGGER.info("Rendering menu..."); if (root == null) { + RenLogger.LOGGER.debug("Root pane is null."); root = new Pane(); } root.setTranslateX(x); root.setTranslateY(y); - root.setPrefSize(width, height); + if (scaleX > 0) { + root.setPrefWidth(width * scaleX); + root.setMaxWidth(width * scaleX); + root.setMinWidth(width * scaleX); + } + if (scaleY > 0) { + root.setPrefHeight(height * scaleY); + root.setMaxHeight(height * scaleY); + root.setMinHeight(height * scaleY); + } // Background fill is used for fade ins. - BackgroundFill backgroundFill = new BackgroundFill(BLACK, new CornerRadii(1), new Insets(0,0,0,0)); - root.setBackground(new Background(backgroundFill)); + if (renderFadeInFill) { + BackgroundFill backgroundFill = new BackgroundFill(BLACK, new CornerRadii(1), new Insets(0, 0, 0, 0)); + root.setBackground(new Background(backgroundFill)); + } if (backgroundImage != null) { - Element backgroundImgElement = new Element(new ImageOverlay(backgroundImage, 0, 0)); + ImageOverlay backGroundImageOverlay = backgroundImage; + + backGroundImageOverlay.setScaleX(this.scaleX); + backGroundImageOverlay.setScaleY(this.scaleY); + Element backgroundImgElement = new Element(backGroundImageOverlay); backgroundImgElement.render(root); } @@ -195,6 +249,9 @@ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { RenLogger.LOGGER.info("Rendering overlays..."); for (Overlay overlay : overlays) { + overlay.setScaleX(scaleX); + overlay.setScaleY(scaleY); + new Element(overlay).render(root); } @@ -204,36 +261,48 @@ public Pane render(@Nullable Pane root, @Nullable RenScene renScene) { } for (Menu menu : children) { + RenLogger.LOGGER.info("Rendering child menus..."); if (menu != null) { - menu.render(root, renScene); // Renders menu on top of this menu. + menu.setRenderFadeOutFill(renderFadeOutFill); + menu.setRenderFadeInFill(renderFadeInFill); + menu.setScaleX(scaleX); + menu.setScaleY(scaleY); + menu.render(root, renScene, render); // Renders menu on top of this menu. } } rootMenu = this; - Scene scene; - if (stage.getScene() != null) { - scene = stage.getScene(); - stage.getScene().setRoot(root); - } else { - stage.setScene(new Scene(root)); - scene = stage.getScene(); - } + if (render) { + Scene scene; + if (stage.getScene() != null) { + scene = stage.getScene(); + stage.getScene().setRoot(root); + } else { + stage.setScene(new Scene(root)); + scene = stage.getScene(); + } - setInputControls(scene); + setInputControls(scene); - this.pane = root; + this.pane = root; - scene.setFill(BLACK); // Scene fill is used for fade outs. + if (renderFadeOutFill) { + scene.setFill(BLACK); // Scene fill is used for fade outs. + } - // Apply transition to root - if (renScene != null && renScene.getStartTransition() != null) { - Transitions transitions = renScene.getStartTransition(); - transitions.play(root); + // Apply transition to root + if (renScene != null && renScene.getStartTransition() != null) { + Transitions transitions = renScene.getStartTransition(); + transitions.play(root); + } + if (renScene != null) { + renScene.setStage(stage); + RenJava.getInstance().getPlayer().setLastRenderedRenScene(renScene); + } + stage.show(); } - stage.show(); - return root; } From dc0952b44fdf2241fd4a89f1233f05e05498a744 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:00:59 -0500 Subject: [PATCH 30/39] Added setStage function to all scenes. --- src/main/java/me/piitex/renjava/gui/layouts/Container.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/me/piitex/renjava/gui/layouts/Container.java b/src/main/java/me/piitex/renjava/gui/layouts/Container.java index 840569b..2294c18 100644 --- a/src/main/java/me/piitex/renjava/gui/layouts/Container.java +++ b/src/main/java/me/piitex/renjava/gui/layouts/Container.java @@ -30,4 +30,8 @@ public Collection getLayouts() { public Stage getStage() { return stage; } + + public void setStage(Stage stage) { + this.stage = stage; + } } From 80fda7b4d4131c14e9a1af8a067f4a1ffe879aaa Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:02:08 -0500 Subject: [PATCH 31/39] Added null checks for sub panes. --- src/main/java/me/piitex/renjava/gui/layouts/Layout.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/renjava/gui/layouts/Layout.java b/src/main/java/me/piitex/renjava/gui/layouts/Layout.java index fdb205f..2944702 100644 --- a/src/main/java/me/piitex/renjava/gui/layouts/Layout.java +++ b/src/main/java/me/piitex/renjava/gui/layouts/Layout.java @@ -38,7 +38,9 @@ public void render(Pane root) { new Element(overlay).render(pane); } for (Pane sub : subPanes) { - pane.getChildren().add(sub); + if (sub != null) { + pane.getChildren().add(sub); + } } pane.setTranslateX(x); pane.setTranslateY(y); From efa87082699a45d56c0161544c2567e1eacd67b1 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:02:54 -0500 Subject: [PATCH 32/39] Fixed image positioning and added render scaling. --- .../java/me/piitex/renjava/gui/Element.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/me/piitex/renjava/gui/Element.java b/src/main/java/me/piitex/renjava/gui/Element.java index 5686ea6..769e09b 100644 --- a/src/main/java/me/piitex/renjava/gui/Element.java +++ b/src/main/java/me/piitex/renjava/gui/Element.java @@ -11,6 +11,7 @@ import javafx.scene.text.TextFlow; import me.piitex.renjava.api.scenes.transitions.Transitions; import me.piitex.renjava.gui.overlay.*; +import me.piitex.renjava.loggers.RenLogger; public class Element { private final Overlay overlay; @@ -19,9 +20,29 @@ public class Element { public Element(Overlay overlay) { this.overlay = overlay; + //FIXME: When scaling the height and width the x and y positions need to be scaled to match the modified width and height. + double scaleX = overlay.scaleX(); + double scaleY = overlay.scaleY(); + if (scaleX > 0) { + overlay.setWidth(overlay.width() * scaleX); + + overlay.setX(overlay.x() * scaleX); + } + if (scaleY > 0) { + overlay.setHeight(overlay.height() * scaleY); + overlay.setY(overlay.y() * scaleY); + } if (overlay instanceof ImageOverlay imageOverlay) { + RenLogger.LOGGER.debug("Processing " + imageOverlay.getFileName()); Image image = imageOverlay.getImage(); ImageView imageView = new ImageView(image); + imageView.setPreserveRatio(true); + if (imageOverlay.width() != 0) { + imageView.setFitWidth(imageOverlay.width()); + } + if (imageOverlay.width() != 0) { + imageView.setFitHeight(imageOverlay.width()); + } imageView.setTranslateX(imageOverlay.x()); imageView.setTranslateY(imageOverlay.y()); this.node = imageView; From 5bc3ef4260cb194784b0c7148aa78dbe30cf75a3 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:03:59 -0500 Subject: [PATCH 33/39] Added listener to handle scene tracking. --- .../renjava/events/defaults/ScenesEventListener.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java index 4ef2008..d34d844 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/ScenesEventListener.java @@ -98,4 +98,13 @@ public void onSceneBuild(SceneBuildEvent event) { scene.getBuildInterface().onBuild(event); } } + + @Listener(priority = Priority.HIGHEST) + public void onSceneRender(SceneRenderEvent event) { + // Event used to save the preview for the save file. + RenLogger.LOGGER.info("Updating tracker for {}", event.getRenScene().getId()); + RenJava.getInstance().getPlayer().setLastRenderedScene(event.getScene()); // Update the player/tracker information + RenJava.getInstance().getPlayer().setLastRenderedRenScene(event.getRenScene()); + + } } From 6f31e23aac8c52f674c6820f8f0ab87bf7f1e6ae Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:05:43 -0500 Subject: [PATCH 34/39] Added save preview for loading and saving screens. --- src/main/java/me/piitex/renjava/RenJava.java | 97 ++++++++++--------- .../me/piitex/renjava/api/saves/Save.java | 67 +++++++------ .../defaults/MenuClickEventListener.java | 4 +- 3 files changed, 87 insertions(+), 81 deletions(-) diff --git a/src/main/java/me/piitex/renjava/RenJava.java b/src/main/java/me/piitex/renjava/RenJava.java index 852f019..fde09ac 100644 --- a/src/main/java/me/piitex/renjava/RenJava.java +++ b/src/main/java/me/piitex/renjava/RenJava.java @@ -2,18 +2,15 @@ import javafx.application.HostServices; import javafx.application.Platform; -import javafx.geometry.Pos; -import javafx.scene.layout.Pane; -import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; -import javafx.scene.text.Text; import javafx.stage.Stage; import javafx.stage.StageStyle; import me.piitex.renjava.addons.Addon; import me.piitex.renjava.addons.AddonLoader; -import me.piitex.renjava.api.builders.FontLoader; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.Game; +import me.piitex.renjava.api.loaders.FontLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.api.exceptions.InvalidCharacterException; import me.piitex.renjava.api.music.Tracks; import me.piitex.renjava.api.saves.Save; @@ -21,6 +18,7 @@ import me.piitex.renjava.api.saves.data.PersistentData; import me.piitex.renjava.api.characters.Character; import me.piitex.renjava.api.player.Player; +import me.piitex.renjava.configuration.Configuration; import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.configuration.SettingsProperties; import me.piitex.renjava.events.Event; @@ -38,9 +36,10 @@ import me.piitex.renjava.gui.layouts.impl.VerticalLayout; import me.piitex.renjava.gui.overlay.ButtonOverlay; import me.piitex.renjava.gui.StageType; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.gui.overlay.TextFlowOverlay; -import me.piitex.renjava.gui.overlay.TextOverlay; import me.piitex.renjava.loggers.RenLogger; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import java.lang.reflect.InvocationTargetException; @@ -68,6 +67,9 @@ * } * * Note: Do not call the `RenJava` constructor directly. The framework creates a new instance of your class automatically using reflections. + * + * @see Game + * @see Configuration */ public abstract class RenJava { protected String name; @@ -99,8 +101,8 @@ public abstract class RenJava { private static RenJava instance; - public RenJava() { - // Super is ran first then the superior method is ran. + protected RenJava() { + // Super is executed first then the superior method is executed. instance = this; } @@ -357,7 +359,9 @@ public void buildStage(Stage stage) { * new Character("character1", "Character 1", Color.RED); * new Character("character2", "Character 2", Color.BLUE); * - * // Perform any other necessary setup tasks + * // Registers data to be included in the save file. + * MyDataClass dataClass = new MyDataClass(); + * registerData(dataClass); * } * } */ @@ -368,7 +372,7 @@ public void buildStage(Stage stage) { public abstract Menu buildTitleScreen(); public Menu buildSideMenu() { - Menu menu = new Menu(350, 500, new ImageLoader("gui/overlay/main_menu.png")); + Menu menu = new Menu(1920, 1080, new ImageOverlay("gui/overlay/main_menu.png")); Font uiFont = RenJava.getInstance().getConfiguration().getUiFont().getFont(); @@ -381,7 +385,7 @@ public Menu buildSideMenu() { ButtonOverlay aboutButton = new ButtonOverlay("menu-about-button", "About", uiFont, Color.BLACK, Color.TRANSPARENT, Color.TRANSPARENT, hoverColor, 1, 1); // Create vbox for the buttons. You can also do an HBox - VerticalLayout layout = new VerticalLayout(200, 500); + VerticalLayout layout = new VerticalLayout(400, 500); layout.setX(50); layout.setY(250); layout.setSpacing(20); @@ -394,7 +398,7 @@ public Menu buildSideMenu() { } public Menu buildLoadMenu(int page) { - Menu menu = new Menu(1920, 1080, new ImageLoader("gui/main_menu.png")); + Menu menu = new Menu(1920, 1080, new ImageOverlay("gui/main_menu.png")); // Setup pagination. // 6 save slots per page // 2 Rows @@ -404,37 +408,20 @@ public Menu buildLoadMenu(int page) { int maxSavesPerPage = 6; int index = ((maxSavesPerPage * page) - maxSavesPerPage) + 1; - VerticalLayout rootLayout = new VerticalLayout(1000, 400); // The root is a vertical which stacks the two horizontal layouts. - HorizontalLayout topLayout = new HorizontalLayout(1000, 200); - HorizontalLayout bottomLayout = new HorizontalLayout(1000, 200); + VerticalLayout rootLayout = new VerticalLayout(1000, 800); // The root is a vertical which stacks the two horizontal layouts. + rootLayout.setSpacing(10); + HorizontalLayout topLayout = new HorizontalLayout(1000, 350); + topLayout.setSpacing(20); + HorizontalLayout bottomLayout = new HorizontalLayout(1000, 350); + bottomLayout.setSpacing(20); while (index <= maxSavesPerPage) { - System.out.println("Rendering save-" + index); - VerticalLayout buttonBox = new VerticalLayout(400, 300); - Save save = new Save(index); - TextOverlay slotText = new TextOverlay(new Text("Slot " + index), getConfiguration().getUiFont(), 1, 1); - buttonBox.addOverlays(slotText); - if (save.exists()) { - System.out.println("Save file exists..."); - // Build the pane - Pane pane = save.buildPreview(); - buttonBox.addSubPane(pane); - } else { - System.out.println("Empty save..."); - ButtonOverlay loadButton = new ButtonOverlay("save-" + index, new ImageLoader("gui/button/slot_idle_background.png"), 1,1,0.8,0.8); - loadButton.setBackgroundColor(Color.TRANSPARENT); - loadButton.setBorderColor(Color.TRANSPARENT); - loadButton.setHoverImage(new ImageLoader("gui/button/slot_hover_background.png")); - loadButton.setMaxHeight(210); - buttonBox.addOverlays(loadButton); - } - - VBox vBox = (VBox) buttonBox.getPane(); // Can cast because I know its a vertical box. - vBox.setAlignment(Pos.CENTER); - buttonBox.setSpacing(1); + ButtonOverlay loadButton = getButtonOverlay(page, index); if (index <= 3) { - topLayout.addChildLayout(buttonBox); + topLayout.addOverlays(loadButton); + //topLayout.addSubPane(saveMenu.render()); } else { - bottomLayout.addChildLayout(buttonBox); + bottomLayout.addOverlays(loadButton); + //bottomLayout.addSubPane(saveMenu.render()); } index++; } @@ -442,7 +429,8 @@ public Menu buildLoadMenu(int page) { rootLayout.addChildLayout(topLayout); rootLayout.addChildLayout(bottomLayout); rootLayout.setX(500); - rootLayout.setY(300); + rootLayout.setY(250); + menu.addLayout(rootLayout); @@ -456,10 +444,10 @@ public Menu buildLoadMenu(int page) { ButtonOverlay pageButton = new ButtonOverlay("page-" + pageIndex, pageIndex + "", new FontLoader(getConfiguration().getUiFont(), 26).getFont(), Color.BLACK, 1, 1); pageButton.setBackgroundColor(Color.TRANSPARENT); pageButton.setBorderColor(Color.TRANSPARENT); - if (page == index) { - pageButton.setTextFill(Color.RED); + if (page == pageIndex) { + pageButton.setTextFill(Color.BLACK); } - pageButton.setHoverColor(Color.RED); + pageButton.setHoverColor(configuration.getHoverColor()); pageLayout.addOverlays(pageButton); } pageLayout.setX(1000); @@ -470,13 +458,28 @@ public Menu buildLoadMenu(int page) { return menu; } + @NotNull + private static ButtonOverlay getButtonOverlay(int page, int index) { + Save save = new Save(index); + save.load(false); + ImageOverlay saveImage; + ButtonOverlay loadButton; + saveImage = save.buildPreview(page); + + loadButton = new ButtonOverlay("save-" + index, saveImage, 0, 0, 414, 309, 1, 1); + + loadButton.setBackgroundColor(Color.TRANSPARENT); + loadButton.setBorderColor(Color.TRANSPARENT); + return loadButton; + } + public Menu buildSettingsMenu() { return null; } public Menu buildAboutMenu() { - Menu menu = new Menu(1920, 1080, new ImageLoader("gui/overlay/main_menu.png")); + Menu menu = new Menu(1920, 1080, new ImageOverlay("gui/overlay/main_menu.png")); Font font = new FontLoader(getConfiguration().getDefaultFont().getFont(), 20).getFont(); @@ -619,8 +622,6 @@ public static void callEvent(Event event) { } } - //FIXME: I'm pretty sure ths is in the wrong order. Low method should be called first, high method called last. Needs some testing and debating before - // Determining the final order. highestMethods.forEach((listener, method) -> { invokeMethod(listener, method, event); }); diff --git a/src/main/java/me/piitex/renjava/api/saves/Save.java b/src/main/java/me/piitex/renjava/api/saves/Save.java index 80325ed..8b74775 100644 --- a/src/main/java/me/piitex/renjava/api/saves/Save.java +++ b/src/main/java/me/piitex/renjava/api/saves/Save.java @@ -1,17 +1,20 @@ package me.piitex.renjava.api.saves; +import javafx.embed.swing.SwingFXUtils; +import javafx.scene.image.WritableImage; import me.piitex.renjava.RenJava; +import me.piitex.renjava.gui.exceptions.ImageNotFoundException; import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.loggers.RenLogger; -import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.api.saves.data.Data; import me.piitex.renjava.api.saves.data.PersistentData; import me.piitex.renjava.api.saves.file.SectionKeyValue; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.api.stories.Story; import me.piitex.renjava.gui.Menu; -import me.piitex.renjava.gui.exceptions.ImageNotFoundException; +import javax.imageio.ImageIO; +import java.awt.image.RenderedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; @@ -35,7 +38,8 @@ public Save(File file) { public Save(int slot) { this.slot = slot; - this.file = new File(System.getProperty("user.dir") + "/game/saves/save-" + slot + ".dat"); + File directory = new File(System.getProperty("user.dir") + "/game/saves/"); + this.file = new File(directory,"save-" + slot + ".dat"); } public boolean exists() { @@ -92,6 +96,13 @@ public void write() { } FileWriter fileWriter = null; + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + RenLogger.LOGGER.error("Could not create save file: {}", e.getMessage()); + } + } try { fileWriter = new FileWriter(file); fileWriter.write(appendString.toString()); @@ -143,9 +154,6 @@ public void load(boolean process) { // Only error if they are trying to process the loading function. if (process) { RenLogger.LOGGER.error(e.getMessage()); - } else { - // If process is false then its being cached and doesn't need to throw an error. - RenLogger.LOGGER.info(e.getMessage()); } } @@ -225,12 +233,6 @@ public void processSection(PersistentData persistentData, SectionKeyValue rootSe // key: value // -// System.out.println("================================================"); -// System.out.println(); -// System.out.println(rootSection.toString()); -// System.out.println(); -// System.out.println("================================================"); - // Next set the mapping to the fields List fields = new ArrayList<>(List.of(persistentData.getClass().getDeclaredFields())); fields.addAll(List.of(persistentData.getClass().getFields())); @@ -330,20 +332,10 @@ private void setField(Field field, PersistentData data, String string2) throws N } } - // Builds the preview for saving and loading - public Menu buildPreview() { - Menu menu = new Menu(1920, 1080); - // Get the current scene the save is on. - // Build the scene. - // Scale it to a small box. - - // Default image - ImageOverlay saveImage = new ImageOverlay("gui/button/slot_idle_background.png"); - if (sceneSection == null) { - RenLogger.LOGGER.info("Save slot '" + slot + "' scene does not exist."); - // Default image - menu.setBackgroundImage(saveImage); - } else { + public ImageOverlay buildPreview(int page) { + ImageOverlay saveImage; + if (file.exists()) { + System.out.println("Save file " + page + " exists."); Story story = RenJava.getInstance().getPlayer().getStory((String) sceneSection.get("currentStory")); //FIXME: This will produce a lot of programming debt. This is an extremely cheap unoptimized hack. @@ -358,14 +350,27 @@ public Menu buildPreview() { RenScene currentScene = story.getScene((String) sceneSection.get("currentScene")); if (currentScene == null) { RenLogger.LOGGER.error("Save slot '" + slot + "' appears to be corrupt or haas missing information. Unable to render save preview for the file. '" + sceneSection.get("currentScene") + "'"); - menu.setBackgroundImage(saveImage); - return menu; + return new ImageOverlay("gui/button/slot_idle_background.png"); } - RenLogger.LOGGER.debug("Save preview found for slot '" + slot + "'. " + currentScene.getId()); - return currentScene.build(true); + currentScene.render(currentScene.build(true)); + + WritableImage snapshot = currentScene.getStage().getScene().snapshot(null); + saveImage = new ImageOverlay(snapshot); + + saveImage.setWidth(384); + saveImage.setHeight(216); + + // Since the Renpy assets account for Text they made a transparency space. + // To circumvent this extra space we need to add the length of the space so everything is properly aligned. + saveImage.setX(15); + saveImage.setY(15); + + // Get whatever page they are on + return saveImage; } - return menu; + saveImage = new ImageOverlay("gui/button/slot_idle_background.png"); + return saveImage; } public File getFile() { diff --git a/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java index dd398af..e1990e2 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/MenuClickEventListener.java @@ -83,8 +83,6 @@ public void onButtonClick(ButtonClickEvent event) { return; } - System.out.println("Story: " + renJava.getPlayer().getCurrentStoryID()); - renJava.createStory(); // Force update fields @@ -98,6 +96,8 @@ public void onButtonClick(ButtonClickEvent event) { } if (renJava.getStageType() == StageType.SAVE_MENU) { // Save + System.out.println("Button id: " + button.getId()); + if (!button.getId().startsWith("save-")) return; int slot = Integer.parseInt(button.getId().replace("save-", "")); Save save = new Save(slot); save.write(); From bac47421a82926462ed3ce5a012f6ec2c9facaf7 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:06:28 -0500 Subject: [PATCH 35/39] Code cleanup. --- src/main/java/me/piitex/renjava/Launch.java | 27 ++++++++++--------- .../java/me/piitex/renjava/RenLoader.java | 2 +- .../me/piitex/renjava/{ => api}/Game.java | 4 +-- .../configuration/RenJavaConfiguration.java | 7 ++--- .../defaults/GameFlowEventListener.java | 2 +- ...hEvent.java => MainMenuDispatchEvent.java} | 6 ++--- .../renjava/events/types/MouseClickEvent.java | 1 - .../renjava/events/types/SceneStartEvent.java | 1 - .../java/me/piitex/renjava/gui/GuiLoader.java | 14 ++++------ .../exceptions/ImageNotFoundException.java | 2 +- src/main/java/module-info.java | 5 +++- 11 files changed, 33 insertions(+), 38 deletions(-) rename src/main/java/me/piitex/renjava/{ => api}/Game.java (85%) rename src/main/java/me/piitex/renjava/events/types/{MainMenDispatchEvent.java => MainMenuDispatchEvent.java} (61%) diff --git a/src/main/java/me/piitex/renjava/Launch.java b/src/main/java/me/piitex/renjava/Launch.java index b4e32ee..4bb84d4 100644 --- a/src/main/java/me/piitex/renjava/Launch.java +++ b/src/main/java/me/piitex/renjava/Launch.java @@ -9,7 +9,8 @@ import java.util.Arrays; import java.util.Collection; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.Game; +import me.piitex.renjava.api.loaders.ImageLoader; import me.piitex.renjava.configuration.Configuration; import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.gui.GuiLoader; @@ -19,14 +20,13 @@ import org.reflections.util.ClasspathHelper; import org.reflections.util.ConfigurationBuilder; -import java.util.HashSet; import java.util.Scanner; import java.util.stream.Collectors; public class Launch extends Application { public static void main(String[] args) { - File file = new File(System.getProperty("user.dir") + "/build.info"); + File file = new File(System.getProperty("user.dir") + "/renjava/build.info"); boolean failed = true; if (file.exists()) { @@ -49,7 +49,7 @@ public static void main(String[] args) { } if (failed) { - System.err.println("Build info not found. Scanning for RenJava class. This will have noticeable performance impact."); + System.err.println("Build info not found. Scanning for RenJava class. This will have noticeable performance impact on low end computers."); // Scans for all classes in all packages. (We need to do all packages because this allows the author the freedom to do their own package scheme.) Collection allPackagePrefixes = Arrays.stream(Package.getPackages()) .map(Package::getName) @@ -71,18 +71,22 @@ public static void main(String[] args) { } private static void loadClass(Class clazz, String[] args) { + //FIXME: For performance save the path of the main class to reduce loading time try { - //FIXME: For performance save the path of the main class to reduce loading time - File file = new File(System.getProperty("user.dir") + "/build.info"); + File file = new File(System.getProperty("user.dir") + "/renjava/build.info"); if (!file.exists()) { file.createNewFile(); - FileWriter writer = new FileWriter(file); - writer.append("main=").append(clazz.getName()); - writer.close(); } + FileWriter writer = new FileWriter(file); + writer.append("main=").append(clazz.getName()); + writer.close(); + } catch (IOException e) { + System.err.println("Could not create the 'build.info' file. This might be a first time setup. Once the application opens please exit and relaunch."); + } + try { Object o = clazz.getDeclaredConstructor().newInstance(); RenJava renJava = (RenJava) o; if (renJava.getClass().isAnnotationPresent(Game.class)) { @@ -100,7 +104,7 @@ private static void loadClass(Class clazz, String[] args) { // Build configuration if (renJava.getClass().isAnnotationPresent(Configuration.class)) { Configuration conf = renJava.getClass().getAnnotation(Configuration.class); - RenJavaConfiguration configuration = new RenJavaConfiguration(conf.title().replace("{version}", renJava.version).replace("{name}", renJava.name), conf.width(), conf.height(), new ImageLoader(conf.windowIconPath())); + RenJavaConfiguration configuration = new RenJavaConfiguration(conf.title().replace("{version}", renJava.version).replace("{name}", renJava.name).replace("{author}", renJava.author), conf.width(), conf.height(), new ImageLoader(conf.windowIconPath())); renJava.setConfiguration(configuration); } else { @@ -118,8 +122,7 @@ private static void loadClass(Class clazz, String[] args) { renJava.init(); // Initialize game launch(args); //c.getDeclaredConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | - IOException e) { + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { System.err.println("ERROR: Could initialize the RenJava framework: " + e.getMessage()); } } diff --git a/src/main/java/me/piitex/renjava/RenLoader.java b/src/main/java/me/piitex/renjava/RenLoader.java index 44edf86..79ce034 100644 --- a/src/main/java/me/piitex/renjava/RenLoader.java +++ b/src/main/java/me/piitex/renjava/RenLoader.java @@ -4,7 +4,7 @@ import java.util.Properties; import javafx.application.Platform; -import me.piitex.renjava.api.builders.FontLoader; +import me.piitex.renjava.api.loaders.FontLoader; import me.piitex.renjava.api.music.Track; import me.piitex.renjava.configuration.SettingsProperties; import me.piitex.renjava.loggers.RenLogger; diff --git a/src/main/java/me/piitex/renjava/Game.java b/src/main/java/me/piitex/renjava/api/Game.java similarity index 85% rename from src/main/java/me/piitex/renjava/Game.java rename to src/main/java/me/piitex/renjava/api/Game.java index 812254f..ee3d264 100644 --- a/src/main/java/me/piitex/renjava/Game.java +++ b/src/main/java/me/piitex/renjava/api/Game.java @@ -1,4 +1,4 @@ -package me.piitex.renjava; +package me.piitex.renjava.api; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -7,7 +7,7 @@ /** * Annotation used to set default information about the game. - * Use this annotation to tag the ReJava class constructor. + * Use this annotation to tag the ReJava class. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java b/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java index feac4c0..b0bf024 100644 --- a/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java +++ b/src/main/java/me/piitex/renjava/configuration/RenJavaConfiguration.java @@ -1,9 +1,8 @@ package me.piitex.renjava.configuration; import javafx.scene.paint.Color; -import javafx.scene.paint.Paint; -import me.piitex.renjava.api.builders.FontLoader; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.FontLoader; +import me.piitex.renjava.api.loaders.ImageLoader; import java.util.Map; @@ -272,7 +271,6 @@ public int getCharacterTextOffsetX() { /** * Sets how far to the right the character display name will be displayed. This is already aligned to the corner of the image. - * @param characterTextOffsetX */ public void setCharacterTextOffsetX(int characterTextOffsetX) { this.characterTextOffsetX = characterTextOffsetX; @@ -284,7 +282,6 @@ public int getCharacterTextOffsetY() { /** * Sets how far down the character display name will be displayed. This is already aligned to the corner of the image. - * @param characterTextOffsetY */ public void setCharacterTextOffsetY(int characterTextOffsetY) { this.characterTextOffsetY = characterTextOffsetY; diff --git a/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java b/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java index 4c34918..ba9951b 100644 --- a/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java +++ b/src/main/java/me/piitex/renjava/events/defaults/GameFlowEventListener.java @@ -83,7 +83,7 @@ public void onMouseClick(MouseClickEvent event) { Menu menu = renScene.build(true); SceneBuildEvent sceneBuildEvent = new SceneBuildEvent(renScene, menu); RenJava.callEvent(sceneBuildEvent); - menu.render(null, renScene); + menu.render(renScene); player.setRightClickMenu(false); } } diff --git a/src/main/java/me/piitex/renjava/events/types/MainMenDispatchEvent.java b/src/main/java/me/piitex/renjava/events/types/MainMenuDispatchEvent.java similarity index 61% rename from src/main/java/me/piitex/renjava/events/types/MainMenDispatchEvent.java rename to src/main/java/me/piitex/renjava/events/types/MainMenuDispatchEvent.java index d313eea..3dda15a 100644 --- a/src/main/java/me/piitex/renjava/events/types/MainMenDispatchEvent.java +++ b/src/main/java/me/piitex/renjava/events/types/MainMenuDispatchEvent.java @@ -1,14 +1,12 @@ package me.piitex.renjava.events.types; -import javafx.scene.Scene; -import javafx.stage.Stage; import me.piitex.renjava.events.Event; import me.piitex.renjava.gui.Menu; -public class MainMenDispatchEvent extends Event { +public class MainMenuDispatchEvent extends Event { private final Menu menu; - public MainMenDispatchEvent(Menu menu) { + public MainMenuDispatchEvent(Menu menu) { this.menu = menu; } diff --git a/src/main/java/me/piitex/renjava/events/types/MouseClickEvent.java b/src/main/java/me/piitex/renjava/events/types/MouseClickEvent.java index 82a6485..0d06bb2 100644 --- a/src/main/java/me/piitex/renjava/events/types/MouseClickEvent.java +++ b/src/main/java/me/piitex/renjava/events/types/MouseClickEvent.java @@ -1,7 +1,6 @@ package me.piitex.renjava.events.types; import javafx.scene.input.MouseEvent; -import me.piitex.renjava.RenJava; import me.piitex.renjava.events.Event; public class MouseClickEvent extends Event { diff --git a/src/main/java/me/piitex/renjava/events/types/SceneStartEvent.java b/src/main/java/me/piitex/renjava/events/types/SceneStartEvent.java index 7cac547..ba0edac 100644 --- a/src/main/java/me/piitex/renjava/events/types/SceneStartEvent.java +++ b/src/main/java/me/piitex/renjava/events/types/SceneStartEvent.java @@ -1,6 +1,5 @@ package me.piitex.renjava.events.types; -import me.piitex.renjava.RenJava; import me.piitex.renjava.api.scenes.RenScene; import me.piitex.renjava.events.Event; diff --git a/src/main/java/me/piitex/renjava/gui/GuiLoader.java b/src/main/java/me/piitex/renjava/gui/GuiLoader.java index 8f6accd..9cbfcab 100644 --- a/src/main/java/me/piitex/renjava/gui/GuiLoader.java +++ b/src/main/java/me/piitex/renjava/gui/GuiLoader.java @@ -7,12 +7,11 @@ import javafx.stage.StageStyle; import javafx.util.Duration; import me.piitex.renjava.RenJava; +import me.piitex.renjava.gui.overlay.ImageOverlay; import me.piitex.renjava.loggers.RenLogger; -import me.piitex.renjava.api.builders.FontLoader; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.FontLoader; import me.piitex.renjava.configuration.RenJavaConfiguration; import me.piitex.renjava.events.types.*; -import me.piitex.renjava.gui.exceptions.ImageNotFoundException; ; /** @@ -97,11 +96,8 @@ private void buildMainMenu() { RenLogger.LOGGER.error("No title screen was found. Please customize your own title screen for better user experience."); RenLogger.LOGGER.warn("Building RenJava default title screen..."); menu = new Menu(renJava.getConfiguration().getHeight(), renJava.getConfiguration().getWidth()).setTitle(renJava.getName() + " v" + renJava.getVersion()); - try { - menu.setBackgroundImage(new ImageLoader("gui/main_menu.png").build()); - } catch (ImageNotFoundException e) { - RenLogger.LOGGER.error(e.getMessage()); - } + + menu.setBackgroundImage(new ImageOverlay("gui/main_menu.png")); } Menu sideMenu = renJava.buildSideMenu(); @@ -110,7 +106,7 @@ private void buildMainMenu() { menu.addMenu(sideMenu); - MainMenDispatchEvent dispatchEvent = new MainMenDispatchEvent(menu); + MainMenuDispatchEvent dispatchEvent = new MainMenuDispatchEvent(menu); RenJava.callEvent(dispatchEvent); menu.render(); diff --git a/src/main/java/me/piitex/renjava/gui/exceptions/ImageNotFoundException.java b/src/main/java/me/piitex/renjava/gui/exceptions/ImageNotFoundException.java index a5c36a6..6c1bf92 100644 --- a/src/main/java/me/piitex/renjava/gui/exceptions/ImageNotFoundException.java +++ b/src/main/java/me/piitex/renjava/gui/exceptions/ImageNotFoundException.java @@ -1,6 +1,6 @@ package me.piitex.renjava.gui.exceptions; -import me.piitex.renjava.api.builders.ImageLoader; +import me.piitex.renjava.api.loaders.ImageLoader; public class ImageNotFoundException extends Exception { diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e3e3d10..313bf8b 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,6 +1,7 @@ module RenJava { requires javafx.graphics; requires javafx.fxml; + requires javafx.swing; requires javafx.controls; requires javafx.media; requires java.logging; @@ -20,7 +21,7 @@ exports me.piitex.renjava.gui; exports me.piitex.renjava.utils; exports me.piitex.renjava.api.characters; - exports me.piitex.renjava.api.builders; + exports me.piitex.renjava.api.loaders; exports me.piitex.renjava.gui.overlay; exports me.piitex.renjava.gui.layouts; exports me.piitex.renjava.gui.layouts.impl; @@ -42,4 +43,6 @@ exports me.piitex.renjava.addons; exports me.piitex.renjava.loggers; opens me.piitex.renjava.loggers; + exports me.piitex.renjava.api; + opens me.piitex.renjava.api; } \ No newline at end of file From 170245004b2dbc3e34eb6ec30ed3aaa2919224e3 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:07:00 -0500 Subject: [PATCH 36/39] Added JavaFX swing utility. --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 66d161a..46df886 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,11 @@ javafx-media 21.0.2
+ + org.openjfx + javafx-swing + 21.0.2 + org.apache.logging.log4j log4j-api From cf134ff4c3262f3dcf5e06a6dfac7e7d0972761e Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:07:36 -0500 Subject: [PATCH 37/39] Improved console logging and appenders. --- src/main/resources/log4j2.xml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 7eccebb..a3a4ab7 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -4,14 +4,19 @@ - - - + + + + + + + - + \ No newline at end of file From 64c4e4c945fe483d11736929368f334e0f3ba014 Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Sat, 4 May 2024 19:20:50 -0500 Subject: [PATCH 38/39] Removed testing font. --- .../resources/game/fonts/JandaManateeSolid.ttf | Bin 37728 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/resources/game/fonts/JandaManateeSolid.ttf diff --git a/src/main/resources/game/fonts/JandaManateeSolid.ttf b/src/main/resources/game/fonts/JandaManateeSolid.ttf deleted file mode 100644 index b4ae06a985b3cb675dbdbd2970a4c49f18b5f5bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37728 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 EpL-GtmjD0& From 8ea449aa971ab7c0eca874e07e72265844c6140c Mon Sep 17 00:00:00 2001 From: Hackusate_PvP Date: Tue, 7 May 2024 12:41:10 -0500 Subject: [PATCH 39/39] Poms for next version. --- README.md | 2 +- dependency-reduced-pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 399201e..259a42c 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Visual novel game engine based off of [RenPy](https://www.renpy.org/) built with [JavaFX](https://openjfx.io/). **Community** -- [Website](), [Discord](), [YouTube]() +- [Website]() (Not yet created), [Discord]() (Not yet created), [YouTube](https://www.youtube.com/channel/UC4iv_X0Pi8FoHFMUHBkHw1A) ## Project Requirements - [Java-17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) (You can typically download this within your IDE) diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 0a6163c..dc8d22d 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -4,7 +4,7 @@ me.piitex RenJava RenJava - 0.0.802-SNAPSHOT + 0.1.0-SNAPSHOT diff --git a/pom.xml b/pom.xml index 46df886..d6ebc2a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.piitex RenJava - 0.0.802-SNAPSHOT + 0.1.0-SNAPSHOT RenJava