From 9eedbce8cd470f6ac61c5ae47d1863e4ac657dd7 Mon Sep 17 00:00:00 2001 From: lantzelot-swe <75668734+lantzelot-swe@users.noreply.github.com> Date: Sun, 6 Feb 2022 12:50:56 +0100 Subject: [PATCH] feat: generate infoslot screenshots based on games in game view If the game view has more than 15 games the screenshots will be created based on the available games. --- src/main/java/se/lantz/db/DbConnector.java | 68 ++++++++++++-- .../java/se/lantz/model/MainViewModel.java | 46 ++++++++-- .../java/se/lantz/model/data/GameView.java | 5 ++ src/main/java/se/lantz/util/FileManager.java | 89 ++++++++++++++++++- 4 files changed, 190 insertions(+), 18 deletions(-) diff --git a/src/main/java/se/lantz/db/DbConnector.java b/src/main/java/se/lantz/db/DbConnector.java index ed8e497..f6faef8 100644 --- a/src/main/java/se/lantz/db/DbConnector.java +++ b/src/main/java/se/lantz/db/DbConnector.java @@ -13,6 +13,8 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -826,6 +828,54 @@ public class DbConnector return returnValue; } + public List getScreenShotNames(List gameIds) + { + //Returns 32 screenshot file names used for creating info slot screens. + List returnList = new ArrayList<>(); + Random screenIndexRandom = new Random(); + String gameIdsString = gameIds.stream().collect(Collectors.joining(",")); + + String sql = "SELECT Screen1File, Screen2File FROM gameinfo WHERE rowid IN (" + gameIdsString + ");"; + logger.debug("Generated SELECT String:\n{}", sql); + + try (Connection conn = this.connect(); PreparedStatement pstmt = conn.prepareStatement(sql)) + { + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + if (gameIds.size() < 32) + { + //Add both screens + returnList.add(rs.getString(DbConstants.SCREEN1)); + returnList.add(rs.getString(DbConstants.SCREEN2)); + } + else + { + //Randomize which screen to pick + if (screenIndexRandom.nextInt(2) == 0) + { + returnList.add(rs.getString(DbConstants.SCREEN1)); + } + else + { + returnList.add(rs.getString(DbConstants.SCREEN2)); + } + } + } + logger.debug("SELECT Executed successfully"); + if (returnList.size() > 32) + { + Collections.shuffle(returnList); + returnList = returnList.subList(0, 31); + } + } + catch (SQLException e) + { + ExceptionHandler.handleException(e, "Could not fetch game details."); + } + return returnList; + } + public int getGameDuplicateIndexToUse(String title, String gameId) { //This is only called when the title changes for an existing game or when adding a new game @@ -1198,21 +1248,21 @@ public class DbConnector } return fixedGames; } - + public void resetJoystickConfigsForView(GameView view) { String joyConfig = FileManager.getConfiguredJoystickConfig(); //Get only the mappings - joyConfig = joyConfig.substring(joyConfig.lastIndexOf(":")+1); - + joyConfig = joyConfig.substring(joyConfig.lastIndexOf(":") + 1); + String joy1Default = "J:1*:" + joyConfig; String joy1NotDefault = "J:1:" + joyConfig; String joy2Default = "J:2*:" + joyConfig; String joy2NotDefault = "J:2:" + joyConfig; - + StringBuilder joy1sqlBuilder = new StringBuilder(); StringBuilder joy2sqlBuilder = new StringBuilder(); - + //Joy1Default joy1sqlBuilder.append("UPDATE gameinfo SET joy1config = '"); joy1sqlBuilder.append(joy1Default); @@ -1228,9 +1278,9 @@ public class DbConnector { joy1sqlBuilder.append("WHERE "); } - joy1sqlBuilder.append("joy1Config LIKE '%*%'"); + joy1sqlBuilder.append("joy1Config LIKE '%*%'"); logger.debug("Generated SQL for joy1 default:\n{}", joy1sqlBuilder.toString()); - + //Joy2Default joy2sqlBuilder.append("UPDATE gameinfo SET joy1config = '"); joy2sqlBuilder.append(joy1NotDefault); @@ -1246,9 +1296,9 @@ public class DbConnector { joy2sqlBuilder.append("WHERE "); } - joy2sqlBuilder.append("joy2Config LIKE '%*%'"); + joy2sqlBuilder.append("joy2Config LIKE '%*%'"); logger.debug("Generated SQL for joy2 default:\n{}", joy2sqlBuilder.toString()); - + try (Connection conn = this.connect(); PreparedStatement joy1tmt = conn.prepareStatement(joy1sqlBuilder.toString()); PreparedStatement joy2tmt = conn.prepareStatement(joy2sqlBuilder.toString())) { diff --git a/src/main/java/se/lantz/model/MainViewModel.java b/src/main/java/se/lantz/model/MainViewModel.java index 204eb0e..8dcba6f 100644 --- a/src/main/java/se/lantz/model/MainViewModel.java +++ b/src/main/java/se/lantz/model/MainViewModel.java @@ -971,7 +971,7 @@ public class MainViewModel extends AbstractModel { stateManager.checkEnablementOfPalNtscMenuItem(check); } - + public void resetJoystickConfigsForCurrentView() { dbConnector.resetJoystickConfigsForView(getSelectedGameView()); @@ -1015,15 +1015,45 @@ public class MainViewModel extends AbstractModel infoModel.resetOldFileNames(); //Cover image - infoModel.setCoverImage(FileManager.getInfoSlotCover(this.selectedGameView.getGameViewId(), this.selectedGameView.getName())); + infoModel.setCoverImage(FileManager.getInfoSlotCover(this.selectedGameView.getGameViewId(), + this.selectedGameView.getName())); //Screen images - BufferedImage screenImage1 = FileManager.getInfoSlotScreenImage(true, this.selectedGameView.getName()); - writeGameViewTextOnScreen(screenImage1, Color.yellow); - infoModel.setScreen1Image(screenImage1); + List screenShotFileNames = new ArrayList<>(); + if (this.selectedGameView.getGameCount() > 15) + { + ArrayList indexList = new ArrayList(); + for (int i = 0; i < selectedGameView.getGameCount(); i++) + { + indexList.add(i); + } - BufferedImage screenImage2 = FileManager.getInfoSlotScreenImage(false, this.selectedGameView.getName()); - writeGameViewTextOnScreen(screenImage2, Color.red); - infoModel.setScreen2Image(screenImage2); + Collections.shuffle(indexList); + + List gameIdList = new ArrayList<>(); + int index = 0; + while (gameIdList.size() < 32 && index < indexList.size()) + { + GameListData randomGame = this.gameListModel.get(indexList.get(index)); + if (!randomGame.isInfoSlot()) + { + gameIdList.add(randomGame.getGameId()); + } + index++; + } + //Only read from db if there are more than 15 games in the current view + if (gameIdList.size() > 15) + { + //Get a screenshot names for the game from db + screenShotFileNames = this.dbConnector.getScreenShotNames(gameIdList); + Collections.shuffle(screenShotFileNames); + } + } + + BufferedImage[] images = FileManager.getInfoSlotScreenImage(this.selectedGameView, screenShotFileNames); + writeGameViewTextOnScreen(images[0], Color.yellow); + infoModel.setScreen1Image(images[0]); + writeGameViewTextOnScreen(images[1], Color.red); + infoModel.setScreen2Image(images[1]); } public void writeGameViewTextOnScreen(BufferedImage image, Color color) diff --git a/src/main/java/se/lantz/model/data/GameView.java b/src/main/java/se/lantz/model/data/GameView.java index c106f70..52bed11 100644 --- a/src/main/java/se/lantz/model/data/GameView.java +++ b/src/main/java/se/lantz/model/data/GameView.java @@ -274,6 +274,11 @@ public class GameView implements Comparable this.gameCount = count; } + public int getGameCount() + { + return this.gameCount; + } + public String getFavNamePreferencesKey() { if (gameViewId < -1) diff --git a/src/main/java/se/lantz/util/FileManager.java b/src/main/java/se/lantz/util/FileManager.java index 753ce83..3cb7914 100644 --- a/src/main/java/se/lantz/util/FileManager.java +++ b/src/main/java/se/lantz/util/FileManager.java @@ -210,7 +210,7 @@ public class FileManager return coverImage; } - public static BufferedImage getInfoSlotScreenImage(boolean first, String gameviewName) + private static BufferedImage getInfoSlotScreenImage(boolean first, String gameviewName) { //Check for USB and check if an existing games folder is available, pick from thumbs... BufferedImage screenImage = null; @@ -253,6 +253,73 @@ public class FileManager return screenImage; } + public static BufferedImage[] getInfoSlotScreenImage(GameView gameview, List screenShotFileNames) + { + BufferedImage[] images = new BufferedImage[2]; + //Check number of games in current view + if (screenShotFileNames.size() > 0) + { + List screenImages = new ArrayList<>(); + for (String fileName : screenShotFileNames) + { + try + { + BufferedImage image = ImageIO.read(new File(SCREENS + fileName)); + //Scale the image to 80x50 + screenImages.add(scaleImageTo80x50(image)); + } + catch (IOException e) + { + ExceptionHandler.handleException(e, "Could not read image for info slot screenshot."); + } + } + //Construct the new image + BufferedImage combinedImage1 = new BufferedImage(320, 200, BufferedImage.TYPE_INT_ARGB); + Graphics g1 = combinedImage1.getGraphics(); + BufferedImage combinedImage2 = new BufferedImage(320, 200, BufferedImage.TYPE_INT_ARGB); + Graphics g2 = combinedImage2.getGraphics(); + int yPos = 0; + int xPos = 0; + + for (int i = 0; i < screenImages.size(); i++) + { + if (i == 16) + { + xPos = 0; + yPos = 0; + } + if (i < 16) + { + drawInfoSlotCombinedImage(g1, screenImages.get(i), xPos, yPos); + } + else + { + drawInfoSlotCombinedImage(g2, screenImages.get(i), xPos, yPos); + } + //Recalculate position + xPos++; + if (xPos > 3) + { + xPos = 0; + yPos++; + } + } + images[0] = combinedImage1; + images[1] = combinedImage2; + } + else + { + images[0] = getInfoSlotScreenImage(true, gameview.getName()); + images[1] = getInfoSlotScreenImage(true, gameview.getName()); + } + return images; + } + + private static void drawInfoSlotCombinedImage(Graphics g, BufferedImage image, int xPos, int yPos) + { + g.drawImage(image, 0 + xPos * 80, 0 + yPos * 50, null); + } + private static BufferedImage getDefaultInfoSlotImage(boolean first) { BufferedImage screenImage = null; @@ -1497,6 +1564,26 @@ public class FileManager return newImage; } + private static BufferedImage scaleImageTo80x50(BufferedImage originalImage) + { + BufferedImage returnImage = originalImage; + if (returnImage.getType() != BufferedImage.TYPE_INT_ARGB) + { + //Convert to 32 bit + BufferedImage copyOfImage = + new BufferedImage(returnImage.getWidth(null), returnImage.getHeight(null), BufferedImage.TYPE_INT_ARGB); + Graphics g = copyOfImage.createGraphics(); + g.drawImage(returnImage, 0, 0, null); + returnImage = copyOfImage; + } + Image newImage = returnImage.getScaledInstance(80, 50, Image.SCALE_SMOOTH); + BufferedImage copyOfImage = + new BufferedImage(newImage.getWidth(null), newImage.getHeight(null), BufferedImage.TYPE_INT_ARGB); + Graphics g = copyOfImage.createGraphics(); + g.drawImage(newImage, 0, 0, null); + return copyOfImage; + } + /** * Creates a temporary file from inputStream, just leaving the File as-is. *