Reworked resources to be assets, and made AssetManager a singleton

This commit is contained in:
Bas de Jong
2025-09-30 21:01:59 +02:00
parent d158668dfd
commit 8328387e86
13 changed files with 182 additions and 112 deletions

View File

@@ -1,10 +1,10 @@
package org.toop.framework.assets;
import org.toop.framework.SnowflakeGenerator;
import org.toop.framework.assets.resources.Resource;
import org.toop.framework.assets.resources.BaseResource;
public class Asset <T extends Resource> {
private final Long id; // IS this needed?
public class Asset <T extends BaseResource> {
private final Long id;
private final String name;
private final T resource;

View File

@@ -1,9 +1,8 @@
package org.toop.framework.assets;
import org.toop.framework.assets.resources.AudioResource;
import org.toop.framework.assets.resources.FontResource;
import org.toop.framework.assets.resources.ImageResource;
import org.toop.framework.assets.resources.Resource;
import org.toop.framework.assets.resources.AudioAsset;
import org.toop.framework.assets.resources.BaseResource;
import org.toop.framework.assets.resources.ImageAsset;
import java.io.File;
import java.io.FileNotFoundException;
@@ -12,7 +11,7 @@ import java.util.Objects;
public class AssetLoader {
private final File rootFolder;
private final ArrayList<Asset<Resource>> assets = new ArrayList<>();
private final ArrayList<Asset<? extends BaseResource>> assets = new ArrayList<>();
public AssetLoader(File rootFolder) {
this.rootFolder = rootFolder;
@@ -23,16 +22,21 @@ public class AssetLoader {
return this.rootFolder;
}
public ArrayList<Asset<Resource>> getAssets() {
public ArrayList<Asset<? extends BaseResource>> getAssets() {
return this.assets;
}
private Resource resourceMapper(File file) throws FileNotFoundException {
return switch (getExtension(file.getName())) {
case "wav" -> new AudioResource(file).load();
case "png" -> new ImageResource(file).load();
private <T extends BaseResource> T resourceMapper(Class<T> type, File file) throws FileNotFoundException {
BaseResource resource = switch (getExtension(file.getName())) {
case "wav" -> new AudioAsset(file);
case "png" -> new ImageAsset(file);
default -> null;
};
if (resource == null) return null;
if (!type.isInstance(resource))
throw new IllegalArgumentException("File " + file.getName() + " is not of type " + type);
return type.cast(resource);
}
public static String getExtension(String name) {
@@ -51,9 +55,10 @@ public class AssetLoader {
fileSearcher(fileEntry);
} else {
try {
this.assets.add(
new Asset<>(fileEntry.getName(), this.resourceMapper(fileEntry))
);
BaseResource resource = resourceMapper(BaseResource.class, fileEntry); // generic token
if (resource != null) {
this.assets.add(new Asset<>(fileEntry.getName(), resource));
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}

View File

@@ -1,38 +1,38 @@
package org.toop.framework.assets;
import org.apache.maven.surefire.shared.io.function.IOBaseStream;
import org.toop.framework.assets.resources.Resource;
import org.toop.framework.assets.resources.*;
import java.io.File;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.*;
public class AssetManager {
private static final AssetManager INSTANCE = new AssetManager();
private static final Map<String, Asset<? extends BaseResource>> assets = new HashMap<>();
private final HashMap<String, Asset<Resource>> assets = new HashMap<>();
private AssetManager() {}
public AssetManager(File rootFolder) {
for (Asset<Resource> x : new AssetLoader(rootFolder).getAssets()) {
this.assets.put(x.getName(), x);
}
public static AssetManager getInstance() {
return INSTANCE;
}
public <T extends Resource> HashMap<String, Asset<T>> getAllResourceOfType(Class<T> resourceClass) {
HashMap<String, Asset<T>> a = new HashMap<>();
for (Asset<Resource> b : this.assets.values()) {
if (resourceClass.isInstance(b.getResource())) {
a.put(b.getName(), (Asset<T>) b);
public <T extends BaseResource> ArrayList<Asset<T>> getAllOfType(Class<T> type) {
ArrayList<Asset<T>> list = new ArrayList<>();
for (Asset<? extends BaseResource> asset : assets.values()) { // <-- use .values()
if (type.isInstance(asset.getResource())) {
@SuppressWarnings("unchecked")
Asset<T> typed = (Asset<T>) asset;
list.add(typed);
}
}
return a;
return list;
}
public HashMap<String, Asset<Resource>> getAssets() {
return this.assets;
public static Asset<? extends BaseResource> getById(String guid) {
return assets.get(guid);
}
public Asset<Resource> getAsset(String assetName) {
return assets.get(assetName);
public static Optional<Asset<? extends BaseResource>> findByName(String name) {
return assets.values().stream()
.filter(a -> a.getName().equals(name))
.findFirst();
}
}

View File

@@ -3,13 +3,14 @@ package org.toop.framework.assets.resources;
import javax.sound.sampled.*;
import java.io.*;
public class AudioResource extends Resource implements ResourceType<AudioResource> {
public class AudioAsset extends BaseResource implements LoadableResource {
private AudioInputStream audioInputStream = null;
private Clip clip = null;
private boolean isLoaded = false;
public AudioResource(File audioFile) {
public AudioAsset(final File audioFile) {
super(audioFile);
}
@@ -17,21 +18,38 @@ public class AudioResource extends Resource implements ResourceType<AudioResourc
return this.audioInputStream;
}
public Clip getClip() {
return this.clip;
}
public AudioResource load() {
@Override
public void load() {
try {
this.audioInputStream = AudioSystem.getAudioInputStream(this.stream);
Clip clip = AudioSystem.getClip();
clip.open(this.audioInputStream);
this.clip = clip;
this.isLoaded = true;
} catch (UnsupportedAudioFileException | LineUnavailableException e) {
throw new RuntimeException(e);
} catch (IOException e) { // TODO: Error handling
throw new RuntimeException(e);
}
return this;
}
@Override
public void unload() {
this.clip.stop();
this.clip.flush();
this.clip.close();
this.clip = null;
this.isLoaded = false;
}
@Override
public boolean isLoaded() {
return this.isLoaded;
}
public Clip getClip() {
if (!this.isLoaded) this.load();
return this.clip;
}
}

View File

@@ -2,12 +2,12 @@ package org.toop.framework.assets.resources;
import java.io.*;
public abstract class Resource {
public abstract class BaseResource {
final InputStream stream;
final File file;
Resource(final File file) {
BaseResource(final File file) {
this.file = file;
try {
this.stream = new BufferedInputStream(new FileInputStream(file));

View File

@@ -0,0 +1,28 @@
package org.toop.framework.assets.resources;
import java.io.File;
import java.io.FileNotFoundException;
public class FontAsset extends BaseResource implements LoadableResource {
private boolean isLoaded = false;
public FontAsset(final File fontFile) {
super(fontFile);
}
@Override
public void load() throws FileNotFoundException {
}
@Override
public void unload() {
}
@Override
public boolean isLoaded() {
return false;
}
}

View File

@@ -1,14 +0,0 @@
package org.toop.framework.assets.resources;
import java.io.File;
public class FontResource extends Resource implements ResourceType<FontResource> {
public FontResource(File fontFile) {
super(fontFile);
}
public FontResource load() {
return this;
}
}

View File

@@ -0,0 +1,38 @@
package org.toop.framework.assets.resources;
import javafx.scene.image.Image;
import java.io.File;
import java.io.FileNotFoundException;
public class ImageAsset extends BaseResource implements LoadableResource {
private Image image;
private boolean isLoaded = false;
public ImageAsset(final File file) throws FileNotFoundException {
super(file);
}
@Override
public void load() {
if (!this.isLoaded) {
this.image = new Image(this.stream);
this.isLoaded = true;
}
}
@Override
public void unload() {
this.image = null;
this.isLoaded = false;
}
@Override
public boolean isLoaded() {
return this.isLoaded;
}
public Image getImage() {
if (!this.isLoaded) load();
return image;
}
}

View File

@@ -1,22 +0,0 @@
package org.toop.framework.assets.resources;
import javafx.scene.image.Image;
import java.io.File;
public class ImageResource extends Resource implements ResourceType<ImageResource> {
private Image image = null;
public ImageResource(File imageFile) {
super(imageFile);
}
public Image getImage() {
return this.image;
}
public ImageResource load() {
this.image = new Image(this.stream);
return this;
}
}

View File

@@ -0,0 +1,9 @@
package org.toop.framework.assets.resources;
import java.io.FileNotFoundException;
public interface LoadableResource {
void load() throws FileNotFoundException;
void unload();
boolean isLoaded();
}

View File

@@ -1,5 +0,0 @@
package org.toop.framework.assets.resources;
public interface ResourceType<T extends Resource> {
T load();
}

View File

@@ -0,0 +1,33 @@
package org.toop.framework.assets.resources;
import org.w3c.dom.Text;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TextAsset extends BaseResource implements LoadableResource {
TextAsset(final File file) {
super(file);
}
@Override
public void load() throws FileNotFoundException {
}
@Override
public void unload() {
}
@Override
public boolean isLoaded() {
return false;
}
}

View File

@@ -1,20 +0,0 @@
package org.toop.framework.assets.resources;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.File;
import java.io.IOException;
public class TextResource extends Resource implements ResourceType<TextResource> {
TextResource(File file) {
super(file);
}
public TextResource load() {
return this;
}
}