diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java index 877dc29c..62f22e8e 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/gui/base/GUI.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.api.game.gui.base; +import com.bartlomiejpluta.base.api.game.gui.component.Component; import com.bartlomiejpluta.base.api.game.input.KeyEventHandler; import com.bartlomiejpluta.base.api.internal.gc.Disposable; import com.bartlomiejpluta.base.api.internal.render.Renderable; @@ -20,6 +21,8 @@ public interface GUI extends Renderable, Disposable, KeyEventHandler { int IMAGE_PREMULTIPLIED = 1 << 4; int IMAGE_NEAREST = 1 << 5; + Component inflateComponent(String widgetUid); + Widget getRoot(); void setRoot(Widget root); diff --git a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt index 2c466730..45646bf8 100644 --- a/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt +++ b/editor/src/main/kotlin/com/bartlomiejpluta/base/editor/code/build/project/DefaultProjectAssembler.kt @@ -28,6 +28,7 @@ class DefaultProjectAssembler : ProjectAssembler { packager.pack(project.imagesDirectory, targetJar, "BOOT-INF/classes/project/images") packager.pack(project.entitySetsDirectory, targetJar, "BOOT-INF/classes/project/entsets") packager.pack(project.fontsDirectory, targetJar, "BOOT-INF/classes/project/fonts") + packager.pack(project.widgetsDirectory, targetJar, "BOOT-INF/classes/project/widgets") packager.copy(project.projectFile, targetJar, "BOOT-INF/classes/project") } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/context/manager/DefaultContextManager.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/context/manager/DefaultContextManager.java index b34f054c..a6c43287 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/context/manager/DefaultContextManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/context/manager/DefaultContextManager.java @@ -5,6 +5,7 @@ import com.bartlomiejpluta.base.api.game.runner.GameRunner; import com.bartlomiejpluta.base.engine.context.model.DefaultContext; import com.bartlomiejpluta.base.engine.core.engine.GameEngine; import com.bartlomiejpluta.base.engine.gui.manager.FontManager; +import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager; import com.bartlomiejpluta.base.engine.gui.xml.inflater.ComponentInflater; import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration; import com.bartlomiejpluta.base.engine.project.serial.ProjectDeserializer; @@ -35,6 +36,7 @@ public class DefaultContextManager implements ContextManager { private final EntityManager entityManager; private final ClassLoader classLoader; private final ComponentInflater inflater; + private final WidgetDefinitionManager widgetDefinitionManager; @SneakyThrows @Override @@ -49,6 +51,7 @@ public class DefaultContextManager implements ContextManager { project.getImageAssets().forEach(imageManager::registerAsset); project.getEntitySetAssets().forEach(entitySetManager::registerAsset); project.getFontAssets().forEach(fontManager::registerAsset); + project.getWidgetDefinitionAssets().forEach(widgetDefinitionManager::registerAsset); log.info("Creating game runner instance"); var runnerClass = classLoader.loadClass(project.getRunner()); @@ -62,6 +65,7 @@ public class DefaultContextManager implements ContextManager { .mapManager(mapManager) .fontManager(fontManager) .inflater(inflater) + .widgetDefinitionManager(widgetDefinitionManager) .gameRunner(gameRunner) .projectName(project.getName()) .build(); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java index c50b4c64..5bddf781 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/context/model/DefaultContext.java @@ -12,6 +12,7 @@ import com.bartlomiejpluta.base.api.game.screen.Screen; import com.bartlomiejpluta.base.api.internal.render.ShaderManager; import com.bartlomiejpluta.base.engine.core.engine.GameEngine; import com.bartlomiejpluta.base.engine.gui.manager.FontManager; +import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager; import com.bartlomiejpluta.base.engine.gui.render.NanoVGGUI; import com.bartlomiejpluta.base.engine.gui.xml.inflater.ComponentInflater; import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager; @@ -49,6 +50,9 @@ public class DefaultContext implements Context { @NonNull private final ComponentInflater inflater; + @NonNull + private final WidgetDefinitionManager widgetDefinitionManager; + @Getter @NonNull private final GameRunner gameRunner; @@ -104,7 +108,7 @@ public class DefaultContext implements Context { @Override public GUI newGUI() { log.info("Creating new GUI"); - var gui = new NanoVGGUI(this, fontManager, imageManager, inflater); + var gui = new NanoVGGUI(this, fontManager, imageManager, inflater, widgetDefinitionManager); guis.add(gui); gui.init(screen); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/asset/WidgetDefinitionAsset.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/asset/WidgetDefinitionAsset.java new file mode 100644 index 00000000..2a392d2b --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/asset/WidgetDefinitionAsset.java @@ -0,0 +1,11 @@ +package com.bartlomiejpluta.base.engine.gui.asset; + +import com.bartlomiejpluta.base.engine.common.asset.Asset; +import lombok.NonNull; + +public class WidgetDefinitionAsset extends Asset { + + public WidgetDefinitionAsset(@NonNull String uid, @NonNull String source) { + super(uid, source); + } +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/manager/DefaultWidgetDefinitionManager.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/manager/DefaultWidgetDefinitionManager.java new file mode 100644 index 00000000..4a6ec197 --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/manager/DefaultWidgetDefinitionManager.java @@ -0,0 +1,41 @@ +package com.bartlomiejpluta.base.engine.gui.manager; + +import com.bartlomiejpluta.base.engine.error.AppException; +import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset; +import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration; +import com.bartlomiejpluta.base.engine.util.res.ResourcesManager; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@Component +@RequiredArgsConstructor +public class DefaultWidgetDefinitionManager implements WidgetDefinitionManager { + private final Map assets = new HashMap<>(); + private final ProjectConfiguration projectConfiguration; + private final ResourcesManager resourcesManager; + + @Override + public void registerAsset(WidgetDefinitionAsset asset) { + log.info("Registering [{}] widget definition asset under UID: [{}]", asset.getSource(), asset.getUid()); + assets.put(asset.getUid(), asset); + } + + @Override + public InputStream loadObject(String uid) { + var asset = assets.get(uid); + + if (asset == null) { + throw new AppException("The widget definition asset with UID: [%s] does not exist", uid); + } + + var source = projectConfiguration.projectFile("widgets", asset.getSource()); + + return resourcesManager.loadResourceAsStream(source); + } +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/manager/WidgetDefinitionManager.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/manager/WidgetDefinitionManager.java new file mode 100644 index 00000000..e01e8968 --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/manager/WidgetDefinitionManager.java @@ -0,0 +1,9 @@ +package com.bartlomiejpluta.base.engine.gui.manager; + +import com.bartlomiejpluta.base.engine.common.manager.AssetManager; +import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset; + +import java.io.InputStream; + +public interface WidgetDefinitionManager extends AssetManager { +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java index cf688149..f3cb85d1 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/gui/render/NanoVGGUI.java @@ -3,11 +3,13 @@ package com.bartlomiejpluta.base.engine.gui.render; import com.bartlomiejpluta.base.api.game.camera.Camera; import com.bartlomiejpluta.base.api.game.context.Context; import com.bartlomiejpluta.base.api.game.gui.base.*; +import com.bartlomiejpluta.base.api.game.gui.component.Component; import com.bartlomiejpluta.base.api.game.input.KeyEvent; import com.bartlomiejpluta.base.api.game.screen.Screen; import com.bartlomiejpluta.base.api.internal.render.ShaderManager; import com.bartlomiejpluta.base.engine.error.AppException; import com.bartlomiejpluta.base.engine.gui.manager.FontManager; +import com.bartlomiejpluta.base.engine.gui.manager.WidgetDefinitionManager; import com.bartlomiejpluta.base.engine.gui.widget.ScreenWidget; import com.bartlomiejpluta.base.engine.gui.xml.inflater.ComponentInflater; import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager; @@ -33,7 +35,8 @@ public class NanoVGGUI implements GUI { private final Context context; private final FontManager fontManager; private final ImageManager imageManager; - private final ComponentInflater componentInflater; + private final ComponentInflater inflater; + private final WidgetDefinitionManager widgetDefinitionManager; private long nvg; private ScreenWidget screenWidget; @@ -62,6 +65,13 @@ public class NanoVGGUI implements GUI { nvgEndFrame(nvg); } + @Override + public Component inflateComponent(String widgetUid) { + log.info("Inflating component by widget definition with UID: [{}]", widgetUid); + var is = widgetDefinitionManager.loadObject(widgetUid); + return inflater.inflate(is, context, this); + } + @Override public Widget getRoot() { return screenWidget.getRoot(); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/project/model/Project.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/project/model/Project.java index 28f3d989..531560db 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/project/model/Project.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/project/model/Project.java @@ -1,6 +1,7 @@ package com.bartlomiejpluta.base.engine.project.model; import com.bartlomiejpluta.base.engine.gui.asset.FontAsset; +import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset; import com.bartlomiejpluta.base.engine.world.entity.asset.EntitySetAsset; import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset; import com.bartlomiejpluta.base.engine.world.map.asset.GameMapAsset; @@ -35,4 +36,7 @@ public class Project { @NonNull private final List fontAssets; + + @NonNull + private final List widgetDefinitionAssets; } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/project/serial/ProtobufProjectDeserializer.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/project/serial/ProtobufProjectDeserializer.java index 84293a70..a0c9719b 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/project/serial/ProtobufProjectDeserializer.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/project/serial/ProtobufProjectDeserializer.java @@ -1,6 +1,7 @@ package com.bartlomiejpluta.base.engine.project.serial; import com.bartlomiejpluta.base.engine.gui.asset.FontAsset; +import com.bartlomiejpluta.base.engine.gui.asset.WidgetDefinitionAsset; import com.bartlomiejpluta.base.engine.project.model.Project; import com.bartlomiejpluta.base.engine.world.entity.asset.EntitySetAsset; import com.bartlomiejpluta.base.engine.world.image.asset.ImageAsset; @@ -26,8 +27,9 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer { var imageAssets = proto.getImagesList().stream().map(this::parseImageAsset).collect(toList()); var entitySetAssets = proto.getEntitySetsList().stream().map(this::parseEntitySetAsset).collect(toList()); var fontAssets = proto.getFontsList().stream().map(this::parseFontAsset).collect(toList()); + var widgetAssets = proto.getWidgetsList().stream().map(this::parseWidgetAsset).collect(toList()); - return new Project(name, runner, tileSetAssets, mapAssets, imageAssets, entitySetAssets, fontAssets); + return new Project(name, runner, tileSetAssets, mapAssets, imageAssets, entitySetAssets, fontAssets, widgetAssets); } private TileSetAsset parseTileSetAsset(ProjectProto.TileSetAsset proto) { @@ -49,4 +51,8 @@ public class ProtobufProjectDeserializer extends ProjectDeserializer { private FontAsset parseFontAsset(ProjectProto.FontAsset proto) { return new FontAsset(proto.getUid(), proto.getSource()); } + + private WidgetDefinitionAsset parseWidgetAsset(ProjectProto.WidgetAsset proto) { + return new WidgetDefinitionAsset(proto.getUid(), proto.getSource()); + } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/util/res/ResourcesManager.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/util/res/ResourcesManager.java index c5868193..0dc8c267 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/util/res/ResourcesManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/util/res/ResourcesManager.java @@ -11,8 +11,12 @@ import java.util.Scanner; @Component public class ResourcesManager { + public InputStream loadResourceAsStream(String fileName) { + return ResourcesManager.class.getResourceAsStream(fileName); + } + public String loadResourceAsString(String fileName) { - try (InputStream in = ResourcesManager.class.getResourceAsStream(fileName); + try (InputStream in = loadResourceAsStream(fileName); Scanner scanner = new Scanner(in, java.nio.charset.StandardCharsets.UTF_8.name())) { return scanner.useDelimiter("\\A").next(); } catch (Exception e) { @@ -22,7 +26,7 @@ public class ResourcesManager { public ByteBuffer loadResourceAsByteBuffer(String fileName) { try { - var bytes = ResourcesManager.class.getResourceAsStream(fileName).readAllBytes(); + var bytes = loadResourceAsStream(fileName).readAllBytes(); return ByteBuffer .allocateDirect(bytes.length) .order(ByteOrder.nativeOrder())