this repo has no description

add TexturesAsset thumbnails

+63 -68
+3 -6
src/main/java/app/pane/AssetsPanel.java
··· 216 216 217 217 private JPanel createSubdirItem(String name) 218 218 { 219 - JPanel panel = createItem(name, ThemedIcon.FOLDER_OPEN_24, null, () -> { 219 + return createItem(name, ThemedIcon.FOLDER_OPEN_24, false, () -> { 220 220 navigateTo(currentPath + name + "/"); 221 221 }); 222 - return panel; 223 222 } 224 223 225 224 private JPanel createAssetItem(AssetHandle asset) 226 225 { 227 - JPanel panel = createItem(asset.getAssetName(), ThemedIcon.PACKAGE_24, asset, () -> { 226 + JPanel panel = createItem(asset.getAssetName(), ThemedIcon.PACKAGE_24, asset.thumbnailHasCheckerboard(), () -> { 228 227 openAsset(asset); 229 228 }); 230 229 ··· 263 262 return panel; 264 263 } 265 264 266 - private JPanel createItem(String name, Icon defaultIcon, AssetHandle asset, Runnable onDoubleClick) 265 + private JPanel createItem(String name, Icon defaultIcon, boolean checkerboard, Runnable onDoubleClick) 267 266 { 268 267 JPanel panel = createItemPanel(); 269 - 270 - boolean checkerboard = asset != null && asset.thumbnailHasCheckerboard(); 271 268 JLabel icon = checkerboard ? new JLabel(defaultIcon) { 272 269 @Override 273 270 protected void paintComponent(Graphics g)
+4 -6
src/main/java/assets/AssetHandle.java
··· 37 37 38 38 public String getAssetName() 39 39 { 40 - int slash = assetPath.lastIndexOf('/'); 41 - if (slash >= 0) 42 - return assetPath.substring(slash + 1); 43 - else 44 - return assetPath; 40 + String name = getName(); 41 + int dot = name.lastIndexOf('.'); 42 + return dot > 0 ? name.substring(0, dot) : name; 45 43 } 46 44 47 45 public String getAssetDescription() ··· 113 111 /** Upgrades a plain AssetHandle to a typed subclass based on file extension. */ 114 112 public static AssetHandle upgrade(AssetHandle handle) 115 113 { 116 - String name = handle.getAssetName(); 114 + String name = handle.getName(); 117 115 if (name.endsWith(".xml")) return new MapAsset(handle); 118 116 if (name.endsWith(".png")) return new BackgroundAsset(handle); 119 117 if (name.endsWith(".json")) return new TexturesAsset(handle);
+3 -3
src/main/java/assets/ui/TexArchiveAssetCellRenderer.java
··· 60 60 String mapFileName = FilenameUtils.getBaseName(bg.assetPath); 61 61 nameLabel.setText(assetDirName + " / " + mapFileName); 62 62 nameLabel.setForeground(null); 63 - previewPanel1.setImage(bg.bimg1); 64 - previewPanel2.setImage(bg.bimg2); 65 - previewPanel3.setImage(bg.bimg3); 63 + previewPanel1.setImage(bg.getPreview(0)); 64 + previewPanel2.setImage(bg.getPreview(1)); 65 + previewPanel3.setImage(bg.getPreview(2)); 66 66 } 67 67 else { 68 68 nameLabel.setText("ERROR");
+53 -53
src/main/java/assets/ui/TexturesAsset.java
··· 1 1 package assets.ui; 2 2 3 3 import java.awt.Graphics2D; 4 + import java.awt.Image; 4 5 import java.awt.RenderingHints; 5 6 import java.awt.image.BufferedImage; 6 7 import java.io.File; ··· 10 11 import java.nio.file.Path; 11 12 import java.util.ArrayList; 12 13 import java.util.Collections; 13 - import java.util.Iterator; 14 14 import java.util.List; 15 15 16 16 import javax.imageio.ImageIO; 17 - import javax.imageio.ImageReader; 18 - import javax.imageio.stream.ImageInputStream; 19 17 20 18 import org.apache.commons.io.FilenameUtils; 21 19 ··· 25 23 26 24 public class TexturesAsset extends AssetHandle 27 25 { 28 - public BufferedImage bimg1; 29 - public BufferedImage bimg2; 30 - public BufferedImage bimg3; 26 + private static final int THUMB_W = THUMBNAIL_WIDTH; 27 + private static final int THUMB_H = THUMBNAIL_HEIGHT; 28 + private static final int GAP = 2; 29 + private static final int ROW_HEIGHT = (THUMB_H - GAP) / 2; // two rows 30 + 31 + private final List<BufferedImage> textures = new ArrayList<>(); 32 + 33 + public BufferedImage getPreview(int index) 34 + { 35 + return index < textures.size() ? textures.get(index) : null; 36 + } 31 37 32 38 public TexturesAsset(AssetHandle asset) 33 39 { ··· 41 47 42 48 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir.toPath(), "*.png")) { 43 49 for (Path file : stream) { 44 - if (Files.isRegularFile(file)) { 50 + if (Files.isRegularFile(file)) 45 51 images.add(file.toFile()); 46 - } 47 52 } 48 53 } 49 54 50 - // pick three textures randomly for previews 51 55 Collections.shuffle(images); 52 56 53 - if (images.size() > 0) { 54 - bimg1 = getPreview(images.get(0)); 55 - } 56 - if (images.size() > 1) { 57 - bimg2 = getPreview(images.get(1)); 58 - } 59 - if (images.size() > 2) { 60 - bimg3 = getPreview(images.get(2)); 57 + for (int i = 0; i < images.size(); i++) { 58 + BufferedImage img = readImage(images.get(i)); 59 + if (img != null) 60 + textures.add(img); 61 61 } 62 62 } 63 63 catch (IOException e) { ··· 65 65 } 66 66 } 67 67 68 - private int getImageSize(File imgFile) throws IOException 68 + @Override 69 + public boolean thumbnailHasCheckerboard() 69 70 { 70 - try (ImageInputStream in = ImageIO.createImageInputStream(imgFile)) { 71 - final Iterator<ImageReader> readers = ImageIO.getImageReaders(in); 72 - if (readers.hasNext()) { 73 - ImageReader reader = readers.next(); 74 - try { 75 - reader.setInput(in); 76 - int width = reader.getWidth(0); 77 - int height = reader.getHeight(0); 78 - return width * height; 79 - } 80 - finally { 81 - reader.dispose(); 82 - } 83 - } 84 - } 85 - return 0; 71 + return false; 86 72 } 87 73 88 - private static BufferedImage getPreview(File imgFile) 74 + @Override 75 + protected Image loadThumbnail() 89 76 { 90 - try { 91 - BufferedImage bimg = ImageIO.read(imgFile); 92 - if (bimg == null) 93 - return null; 77 + if (textures.isEmpty()) 78 + return null; 79 + 80 + var composite = new BufferedImage(THUMB_W, THUMB_H, BufferedImage.TYPE_INT_ARGB); 81 + Graphics2D g = composite.createGraphics(); 82 + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); 83 + 84 + int x = 0; 85 + int y = 0; 86 + for (BufferedImage tex : textures) { 87 + float scale = (float) ROW_HEIGHT / tex.getHeight(); 88 + int w = Math.max(1, Math.round(tex.getWidth() * scale)); 89 + int h = ROW_HEIGHT; 94 90 95 - int targetWidth = 32; 96 - int targetHeight = 32; 97 - float ratio = (float) bimg.getHeight() / (float) bimg.getWidth(); 98 - if (ratio <= 1.0f) { 99 - targetHeight = (int) Math.ceil(targetWidth * ratio); 100 - } 101 - else { 102 - targetWidth = Math.round(targetHeight / ratio); 91 + if (x + w > THUMB_W) { 92 + // Wrap to next row 93 + x = 0; 94 + y += ROW_HEIGHT + GAP; 95 + if (y + ROW_HEIGHT > THUMB_H) 96 + break; 103 97 } 104 98 105 - BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB); 106 - Graphics2D g2d = resized.createGraphics(); 107 - g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 108 - g2d.drawImage(bimg, 0, 0, targetWidth, targetHeight, null); 109 - g2d.dispose(); 110 - return resized; 99 + g.drawImage(tex, x, y, w, h, null); 100 + x += w + GAP; 101 + } 102 + 103 + g.dispose(); 104 + return composite; 105 + } 106 + 107 + private static BufferedImage readImage(File imgFile) 108 + { 109 + try { 110 + return ImageIO.read(imgFile); 111 111 } 112 112 catch (IOException e) { 113 113 return null;