Enable full support for icon sets

This commit is contained in:
2022-08-23 10:45:57 +02:00
parent e5f76b29a1
commit 084eeef79a
12 changed files with 302 additions and 19 deletions

View File

@@ -7,6 +7,7 @@ import com.bartlomiejpluta.base.api.character.Character;
import com.bartlomiejpluta.base.api.event.Event;
import com.bartlomiejpluta.base.api.event.EventType;
import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.image.Image;
import com.bartlomiejpluta.base.api.input.Input;
import com.bartlomiejpluta.base.api.map.model.GameMap;
@@ -43,6 +44,8 @@ public interface Context extends Updatable, Renderable, Disposable {
Animation createAnimation(String animationUid);
Icon createIcon(String iconSetUid, int row, int column);
Image getImage(String imageUid);
GUI newGUI();

View File

@@ -0,0 +1,9 @@
package com.bartlomiejpluta.base.api.icon;
import com.bartlomiejpluta.base.api.entity.Entity;
public interface Icon extends Entity {
void changeIcon(int row, int column);
void changeIcon(String iconSetUid, int row, int column);
}

View File

@@ -16,6 +16,8 @@ import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
import com.bartlomiejpluta.base.engine.world.animation.manager.AnimationManager;
import com.bartlomiejpluta.base.engine.world.character.manager.CharacterManager;
import com.bartlomiejpluta.base.engine.world.character.manager.CharacterSetManager;
import com.bartlomiejpluta.base.engine.world.icon.manager.IconManager;
import com.bartlomiejpluta.base.engine.world.icon.manager.IconSetManager;
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
import com.bartlomiejpluta.base.engine.world.tileset.manager.TileSetManager;
@@ -37,8 +39,10 @@ public class DefaultContextManager implements ContextManager {
private final ImageManager imageManager;
private final CharacterSetManager characterSetManager;
private final FontManager fontManager;
private final IconSetManager iconSetManager;
private final CharacterManager characterManager;
private final AnimationManager animationManager;
private final IconManager iconManager;
private final ClassLoader classLoader;
private final Inflater inflater;
private final WidgetDefinitionManager widgetDefinitionManager;
@@ -58,6 +62,7 @@ public class DefaultContextManager implements ContextManager {
project.getImageAssets().forEach(imageManager::registerAsset);
project.getCharacterSetAssets().forEach(characterSetManager::registerAsset);
project.getAnimationAssets().forEach(animationManager::registerAsset);
project.getIconSetAssets().forEach(iconSetManager::registerAsset);
project.getFontAssets().forEach(fontManager::registerAsset);
project.getWidgetDefinitionAssets().forEach(widgetDefinitionManager::registerAsset);
project.getSoundAssets().forEach(soundManager::registerAsset);
@@ -70,17 +75,18 @@ public class DefaultContextManager implements ContextManager {
var context = DefaultContext.builder()
.engine(engine)
.characterManager(characterManager)
.animationManager(animationManager)
.imageManager(imageManager)
.mapManager(mapManager)
.fontManager(fontManager)
.inflater(inflater)
.widgetDefinitionManager(widgetDefinitionManager)
.soundManager(soundManager)
.databaseService(databaseService)
.gameRunner(gameRunner)
.projectName(project.getName())
.build();
.animationManager(animationManager)
.iconManager(iconManager)
.imageManager(imageManager)
.mapManager(mapManager)
.fontManager(fontManager)
.inflater(inflater)
.widgetDefinitionManager(widgetDefinitionManager)
.soundManager(soundManager)
.databaseService(databaseService)
.gameRunner(gameRunner)
.projectName(project.getName())
.build();
ContextHolder.INSTANCE.setContext(context);

View File

@@ -9,6 +9,7 @@ import com.bartlomiejpluta.base.api.context.GamePauseEvent;
import com.bartlomiejpluta.base.api.event.Event;
import com.bartlomiejpluta.base.api.event.EventType;
import com.bartlomiejpluta.base.api.gui.GUI;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.image.Image;
import com.bartlomiejpluta.base.api.input.Input;
import com.bartlomiejpluta.base.api.map.handler.MapHandler;
@@ -23,6 +24,7 @@ import com.bartlomiejpluta.base.engine.gui.render.NanoVGGUI;
import com.bartlomiejpluta.base.engine.gui.xml.inflater.Inflater;
import com.bartlomiejpluta.base.engine.world.animation.manager.AnimationManager;
import com.bartlomiejpluta.base.engine.world.character.manager.CharacterManager;
import com.bartlomiejpluta.base.engine.world.icon.manager.IconManager;
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
import com.bartlomiejpluta.base.engine.world.map.model.DefaultGameMap;
@@ -55,6 +57,9 @@ public class DefaultContext implements Context {
@NonNull
private final AnimationManager animationManager;
@NonNull
private final IconManager iconManager;
@NonNull
private final ImageManager imageManager;
@@ -146,16 +151,20 @@ public class DefaultContext implements Context {
}
@Override
public Character createCharacter(String characterSetUid) {
log.info("Creating new character with UID: [{}]", characterSetUid);
public Character createCharacter(@NonNull String characterSetUid) {
return characterManager.createCharacter(characterSetUid);
}
@Override
public Animation createAnimation(String animationUid) {
public Animation createAnimation(@NonNull String animationUid) {
return animationManager.loadObject(animationUid);
}
@Override
public Icon createIcon(@NonNull String iconSetUid, int row, int column) {
return iconManager.createIcon(iconSetUid, row, column);
}
@Override
public Image getImage(@NonNull String imageUid) {
return imageManager.loadObject(imageUid);

View File

@@ -5,6 +5,7 @@ import com.bartlomiejpluta.base.engine.gui.asset.FontAsset;
import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset;
import com.bartlomiejpluta.base.engine.world.animation.asset.AnimationAsset;
import com.bartlomiejpluta.base.engine.world.character.asset.CharacterSetAsset;
import com.bartlomiejpluta.base.engine.world.icon.asset.IconSetAsset;
import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset;
import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset;
import com.bartlomiejpluta.base.engine.world.tileset.asset.TileSetAsset;
@@ -39,6 +40,9 @@ public class Project {
@NonNull
private final List<AnimationAsset> animationAssets;
@NonNull
private final List<IconSetAsset> iconSetAssets;
@NonNull
private final List<FontAsset> fontAssets;

View File

@@ -6,6 +6,7 @@ import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset;
import com.bartlomiejpluta.base.engine.project.model.Project;
import com.bartlomiejpluta.base.engine.world.animation.asset.AnimationAsset;
import com.bartlomiejpluta.base.engine.world.character.asset.CharacterSetAsset;
import com.bartlomiejpluta.base.engine.world.icon.asset.IconSetAsset;
import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset;
import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset;
import com.bartlomiejpluta.base.engine.world.tileset.asset.TileSetAsset;
@@ -30,11 +31,12 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer {
.mapAssets(proto.getMapsList().stream().map(this::parseGameMapAsset).collect(toList()))
.imageAssets(proto.getImagesList().stream().map(this::parseImageAsset).collect(toList()))
.characterSetAssets(proto.getCharacterSetsList().stream().map(this::parseCharacterSetAsset).collect(toList()))
.animationAssets(proto.getAnimationsList().stream().map(this::parseAnimationAsset).collect(toList()))
.fontAssets(proto.getFontsList().stream().map(this::parseFontAsset).collect(toList()))
.widgetDefinitionAssets(proto.getWidgetsList().stream().map(this::parseWidgetAsset).collect(toList()))
.soundAssets(proto.getSoundsList().stream().map(this::parseSoundAsset).collect(toList()))
.build();
.animationAssets(proto.getAnimationsList().stream().map(this::parseAnimationAsset).collect(toList()))
.iconSetAssets(proto.getIconSetsList().stream().map(this::parseIconSetAsset).collect(toList()))
.fontAssets(proto.getFontsList().stream().map(this::parseFontAsset).collect(toList()))
.widgetDefinitionAssets(proto.getWidgetsList().stream().map(this::parseWidgetAsset).collect(toList()))
.soundAssets(proto.getSoundsList().stream().map(this::parseSoundAsset).collect(toList()))
.build();
}
private TileSetAsset parseTileSetAsset(ProjectProto.TileSetAsset proto) {
@@ -65,6 +67,10 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer {
return new AnimationAsset(proto.getUid(), proto.getSource(), proto.getRows(), proto.getColumns());
}
private IconSetAsset parseIconSetAsset(ProjectProto.IconSetAsset proto) {
return new IconSetAsset(proto.getUid(), proto.getSource(), proto.getRows(), proto.getColumns());
}
private SoundAsset parseSoundAsset(ProjectProto.SoundAsset proto) {
return new SoundAsset(proto.getUid(), proto.getSource());
}

View File

@@ -0,0 +1,17 @@
package com.bartlomiejpluta.base.engine.world.icon.asset;
import com.bartlomiejpluta.base.engine.common.asset.Asset;
import lombok.Getter;
import lombok.NonNull;
@Getter
public class IconSetAsset extends Asset {
private final int rows;
private final int columns;
public IconSetAsset(@NonNull String uid, @NonNull String source, int rows, int columns) {
super(uid, source);
this.rows = rows;
this.columns = columns;
}
}

View File

@@ -0,0 +1,34 @@
package com.bartlomiejpluta.base.engine.world.icon.manager;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
import com.bartlomiejpluta.base.engine.util.mesh.MeshManager;
import com.bartlomiejpluta.base.engine.world.icon.model.DefaultIcon;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DefaultIconManager implements IconManager {
private final MeshManager meshManager;
private final IconSetManager iconSetManager;
private Mesh mesh;
@Override
public void init() {
this.mesh = meshManager.createQuad(1, 1, 0.5f, 1);
}
@Override
public Icon createIcon(String iconSetUid, int row, int column) {
return new DefaultIcon(mesh, iconSetManager, iconSetUid, row, column);
}
@Override
public void cleanUp() {
log.info("There is nothing to clean up here");
}
}

View File

@@ -0,0 +1,43 @@
package com.bartlomiejpluta.base.engine.world.icon.manager;
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
import com.bartlomiejpluta.base.engine.core.gl.object.texture.TextureManager;
import com.bartlomiejpluta.base.engine.error.AppException;
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
import com.bartlomiejpluta.base.engine.world.icon.asset.IconSetAsset;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class DefaultIconSetManager implements IconSetManager {
private final TextureManager textureManager;
private final Map<String, IconSetAsset> assets = new HashMap<>();
private final ProjectConfiguration configuration;
@Override
public void registerAsset(IconSetAsset asset) {
log.info("Registering [{}] icon set asset under UID: [{}]", asset.getSource(), asset.getUid());
assets.put(asset.getUid(), asset);
}
@Override
public Material loadObject(String uid) {
var asset = assets.get(uid);
if (asset == null) {
throw new AppException("The icon set asset with UID: [%s] does not exist", uid);
}
var source = configuration.projectFile("iconsets", asset.getSource());
var texture = textureManager.loadTexture(source, asset.getRows(), asset.getColumns());
return Material.textured(texture);
}
}

View File

@@ -0,0 +1,9 @@
package com.bartlomiejpluta.base.engine.world.icon.manager;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.engine.common.init.Initializable;
import com.bartlomiejpluta.base.internal.gc.Cleanable;
public interface IconManager extends Initializable, Cleanable {
Icon createIcon(String iconSetUid, int row, int column);
}

View File

@@ -0,0 +1,8 @@
package com.bartlomiejpluta.base.engine.world.icon.manager;
import com.bartlomiejpluta.base.engine.common.manager.AssetManager;
import com.bartlomiejpluta.base.engine.core.gl.object.material.Material;
import com.bartlomiejpluta.base.engine.world.icon.asset.IconSetAsset;
public interface IconSetManager extends AssetManager<IconSetAsset, Material> {
}

View File

@@ -0,0 +1,135 @@
package com.bartlomiejpluta.base.engine.world.icon.model;
import com.bartlomiejpluta.base.api.event.Event;
import com.bartlomiejpluta.base.api.icon.Icon;
import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer;
import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh;
import com.bartlomiejpluta.base.engine.error.AppException;
import com.bartlomiejpluta.base.engine.world.icon.manager.IconSetManager;
import com.bartlomiejpluta.base.engine.world.location.LocationableSprite;
import com.bartlomiejpluta.base.lib.event.EventHandler;
import lombok.Getter;
import lombok.Setter;
import org.joml.Vector2f;
import org.joml.Vector2fc;
public class DefaultIcon extends LocationableSprite implements Icon {
private final EventHandler eventHandler = new EventHandler();
private final IconSetManager iconSetManager;
private final Vector2f iconScale = new Vector2f(1, 1);
private Vector2fc iconSetSize;
@Setter
@Getter
private boolean blocking;
@Getter
private ObjectLayer layer;
@Setter
@Getter
private int zIndex;
public DefaultIcon(Mesh mesh, IconSetManager iconSetManager, String iconSetUid, int row, int column) {
super(mesh, iconSetManager.loadObject(iconSetUid));
this.iconSetManager = iconSetManager;
material.setSpritePosition(column, row);
var texture = material.getTexture();
if (texture != null) {
this.iconSetSize = texture.getSpriteSize();
super.setScale(iconSetSize.x() * iconScale.x, iconSetSize.y() * iconScale.y);
}
}
@Override
public void onAdd(ObjectLayer layer) {
this.layer = layer;
}
@Override
public void onRemove(ObjectLayer layer) {
this.layer = null;
}
@Override
public <E extends Event> void handleEvent(E event) {
eventHandler.handleEvent(event);
}
@Override
public void changeIcon(int row, int column) {
material.setSpritePosition(column, row);
}
@Override
public void changeIcon(String iconSetUid, int row, int column) {
this.material = iconSetManager.loadObject(iconSetUid);
material.setSpritePosition(column, row);
var texture = material.getTexture();
if (texture != null) {
this.iconSetSize = texture.getSpriteSize();
super.setScale(iconSetSize.x() * iconScale.x, iconSetSize.y() * iconScale.y);
} else {
this.iconSetSize = null;
}
}
@Override
public void setScaleX(float scaleX) {
if (iconSetSize == null) {
throw new AppException("Cannot change Icon scale if no Icon Set is provided");
}
this.iconScale.x = scaleX;
super.setScaleX(iconSetSize.x() * scaleX);
}
@Override
public void setScaleY(float scaleY) {
if (iconSetSize == null) {
throw new AppException("Cannot change Icon scale if no Icon Set is provided");
}
this.iconScale.y = scaleY;
super.setScaleY(iconSetSize.y() * scaleY);
}
@Override
public void setScale(float scale) {
if (iconSetSize == null) {
throw new AppException("Cannot change Icon scale if no Icon Set is provided");
}
this.iconScale.x = scale;
this.iconScale.y = scale;
super.setScale(iconSetSize.x() * scale, iconSetSize.y() * scale);
}
@Override
public void setScale(float scaleX, float scaleY) {
if (iconSetSize == null) {
throw new AppException("Cannot change Icon scale if no Icon Set is provided");
}
this.iconScale.x = scaleX;
this.iconScale.y = scaleY;
super.setScale(iconSetSize.x() * scaleX, iconSetSize.y() * scaleY);
}
@Override
public float getScaleX() {
return iconScale.x;
}
@Override
public float getScaleY() {
return iconScale.y;
}
@Override
public void update(float dt) {
// noop
}
}