Add support for window inflating

This commit is contained in:
2021-03-16 19:29:48 +01:00
parent cd9fba8637
commit 397e9e1f9c
7 changed files with 140 additions and 28 deletions

View File

@@ -6,7 +6,7 @@ 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.gui.xml.inflater.Inflater;
import com.bartlomiejpluta.base.engine.project.config.ProjectConfiguration;
import com.bartlomiejpluta.base.engine.project.serial.ProjectDeserializer;
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
@@ -35,7 +35,7 @@ public class DefaultContextManager implements ContextManager {
private final FontManager fontManager;
private final EntityManager entityManager;
private final ClassLoader classLoader;
private final ComponentInflater inflater;
private final Inflater inflater;
private final WidgetDefinitionManager widgetDefinitionManager;
@SneakyThrows

View File

@@ -14,7 +14,7 @@ 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.gui.xml.inflater.Inflater;
import com.bartlomiejpluta.base.engine.world.entity.manager.EntityManager;
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
import com.bartlomiejpluta.base.engine.world.map.manager.MapManager;
@@ -48,7 +48,7 @@ public class DefaultContext implements Context {
private final FontManager fontManager;
@NonNull
private final ComponentInflater inflater;
private final Inflater inflater;
@NonNull
private final WidgetDefinitionManager widgetDefinitionManager;

View File

@@ -4,6 +4,7 @@ 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.gui.window.Window;
import com.bartlomiejpluta.base.api.game.input.KeyEvent;
import com.bartlomiejpluta.base.api.game.screen.Screen;
import com.bartlomiejpluta.base.api.internal.render.ShaderManager;
@@ -11,7 +12,7 @@ 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.gui.xml.inflater.Inflater;
import com.bartlomiejpluta.base.engine.world.image.manager.ImageManager;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -35,7 +36,7 @@ public class NanoVGGUI implements GUI {
private final Context context;
private final FontManager fontManager;
private final ImageManager imageManager;
private final ComponentInflater inflater;
private final Inflater inflater;
private final WidgetDefinitionManager widgetDefinitionManager;
private long nvg;
@@ -69,7 +70,14 @@ public class NanoVGGUI implements GUI {
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);
return inflater.inflateComponent(is, context, this);
}
@Override
public Window inflateWindow(String widgetUid) {
log.info("Inflating window by widget definition with UID: [{}]", widgetUid);
var is = widgetDefinitionManager.loadObject(widgetUid);
return inflater.inflateWindow(is, context, this);
}
@Override

View File

@@ -4,6 +4,9 @@ import com.bartlomiejpluta.base.api.game.context.Context;
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
import com.bartlomiejpluta.base.api.game.gui.base.SizeMode;
import com.bartlomiejpluta.base.api.game.gui.component.Component;
import com.bartlomiejpluta.base.api.game.gui.window.Window;
import com.bartlomiejpluta.base.api.game.gui.window.WindowPosition;
import com.bartlomiejpluta.base.engine.error.AppException;
import com.bartlomiejpluta.base.engine.util.reflection.ClassLoader;
import lombok.SneakyThrows;
import org.codehaus.janino.ExpressionEvaluator;
@@ -18,14 +21,17 @@ import java.io.InputStream;
import java.util.stream.Stream;
@org.springframework.stereotype.Component
public class ComponentInflater {
private static final String[] IMPORTS = Stream.of(GUI.class, SizeMode.class).map(Class::getCanonicalName).toArray(String[]::new);
public class Inflater {
private static final String[] IMPORTS = Stream.of(GUI.class, SizeMode.class, WindowPosition.class)
.map(Class::getCanonicalName)
.toArray(String[]::new);
private final DocumentBuilder builder;
private final ClassLoader loader;
@Autowired
@SneakyThrows
public ComponentInflater(ClassLoader loader) {
public Inflater(ClassLoader loader) {
this.loader = loader;
var factory = DocumentBuilderFactory.newInstance();
@@ -34,21 +40,98 @@ public class ComponentInflater {
}
@SneakyThrows
public Component inflate(String xml, Context context, GUI gui) {
public Component inflateComponent(String xml, Context context, GUI gui) {
var document = builder.parse(xml);
return parseNode(document.getDocumentElement(), context, gui);
return inflateComponent(document.getDocumentElement(), context, gui);
}
@SneakyThrows
public Component inflate(File file, Context context, GUI gui) {
public Component inflateComponent(File file, Context context, GUI gui) {
var document = builder.parse(file);
return parseNode(document.getDocumentElement(), context, gui);
return inflateComponent(document.getDocumentElement(), context, gui);
}
@SneakyThrows
public Component inflate(InputStream is, Context context, GUI gui) {
public Component inflateComponent(InputStream is, Context context, GUI gui) {
var document = builder.parse(is);
return parseNode(document.getDocumentElement(), context, gui);
return inflateComponent(document.getDocumentElement(), context, gui);
}
@SneakyThrows
public Window inflateWindow(String xml, Context context, GUI gui) {
var document = builder.parse(xml);
return inflateWindow(document.getDocumentElement(), context, gui);
}
@SneakyThrows
public Window inflateWindow(File file, Context context, GUI gui) {
var document = builder.parse(file);
return inflateWindow(document.getDocumentElement(), context, gui);
}
@SneakyThrows
public Window inflateWindow(InputStream is, Context context, GUI gui) {
var document = builder.parse(is);
return inflateWindow(document.getDocumentElement(), context, gui);
}
@SneakyThrows
private Window inflateWindow(Node root, Context context, GUI gui) {
var uri = root.getNamespaceURI();
var name = root.getLocalName();
if (uri != null) {
name = uri + "." + name;
}
var canonicalName = name.replaceAll("\\*", "").replaceAll("\\.+", ".");
var windowClass = loader.loadClass(canonicalName);
var window = (Window) windowClass.getConstructor(Context.class, GUI.class).newInstance(context, gui);
var attributes = root.getAttributes();
// Set attributes via setter methods
for (int i = 0; i < attributes.getLength(); ++i) {
var attribute = attributes.item(i);
// Ignore namespaces definitions
if ("xmlns".equals(attribute.getPrefix())) {
continue;
}
var setterName = createSetterMethodName(attribute.getLocalName());
var value = parseValue(attribute.getNodeValue());
var setter = windowClass.getMethod(setterName, value.getClass());
setter.invoke(window, value);
}
// Parse window content
var children = root.getChildNodes();
boolean hasContent = false;
for (int i = 0; i < children.getLength(); ++i) {
var child = children.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (hasContent) {
throw new AppException("Window can have at most 1 child");
}
var content = parseNode(child, context, gui);
window.setContent(content);
hasContent = true;
}
return window;
}
private Component inflateComponent(Node root, Context context, GUI gui) {
return parseNode(root, context, gui);
}
@SneakyThrows