From 38832e15f82f9f89678c79ef109a3dae59e34444 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sat, 8 Feb 2020 21:21:48 +0000 Subject: [PATCH 01/20] Initial import of NUI from Terasology. --- engine/build.gradle | 2 + .../org/destinationsol/SolApplication.java | 11 + .../destinationsol/assets/AssetHelper.java | 38 +- .../destinationsol/assets/fonts/FontData.java | 4 +- .../assets/fonts/FontFileFormat.java | 17 +- .../destinationsol/assets/fonts/UIFont.java | 113 +++ .../assets/sound/PlayableSound.java | 9 +- .../assets/textures/DSTexture.java | 5 + .../assets/textures/DSTextureData.java | 5 +- ...CaseInsensitiveEnumTypeAdapterFactory.java | 77 ++ .../destinationsol/assets/ui/UIFormat.java | 246 ++++++ .../assets/ui/UISkinFormat.java | 236 ++++++ .../destinationsol/modules/ModuleManager.java | 1 + .../destinationsol/ui/SolInputManager.java | 2 + .../org/destinationsol/ui/nui/NUIManager.java | 205 +++++ .../destinationsol/ui/nui/NUIScreenLayer.java | 80 ++ .../ui/nui/screens/MigTestScreen.java | 52 ++ .../main/resources/assets/skins/default.skin | 588 +++++++++++++++ .../resources/assets/skins/migTestSkin.skin | 129 ++++ .../resources/assets/textures/ui/nui/area.png | Bin 0 -> 415 bytes .../resources/assets/textures/ui/nui/box.png | Bin 0 -> 125 bytes .../assets/textures/ui/nui/boxActive.png | Bin 0 -> 130 bytes .../assets/textures/ui/nui/boxDisabled.png | Bin 0 -> 125 bytes .../assets/textures/ui/nui/button.png | Bin 0 -> 241 bytes .../assets/textures/ui/nui/buttonDown.png | Bin 0 -> 240 bytes .../assets/textures/ui/nui/buttonOver.png | Bin 0 -> 240 bytes .../assets/textures/ui/nui/checkbox.png | Bin 0 -> 132 bytes .../textures/ui/nui/checkboxChecked.png | Bin 0 -> 212 bytes .../ui/nui/checkboxCheckedDisabled.png | Bin 0 -> 228 bytes .../textures/ui/nui/checkboxCheckedHover.png | Bin 0 -> 223 bytes .../textures/ui/nui/checkboxDisabled.png | Bin 0 -> 132 bytes .../assets/textures/ui/nui/checkboxHover.png | Bin 0 -> 138 bytes .../assets/textures/ui/nui/dropdown.png | Bin 0 -> 300 bytes .../assets/textures/ui/nui/dropdownActive.png | Bin 0 -> 315 bytes .../textures/ui/nui/dropdownDisabled.png | Bin 0 -> 315 bytes .../assets/textures/ui/nui/dropdownList.png | Bin 0 -> 186 bytes .../ui/nui/dropdownListItemActive.png | Bin 0 -> 163 bytes .../assets/textures/ui/nui/handle.png | Bin 0 -> 1660 bytes .../assets/textures/ui/nui/resetBox.png | Bin 0 -> 384 bytes .../textures/ui/nui/resetBoxDisabled.png | Bin 0 -> 391 bytes .../assets/textures/ui/nui/sliderTrack.png | Bin 0 -> 1298 bytes .../textures/ui/nui/terasology/LICENSE_NOTES | 45 ++ .../ui/nui/terasology/radial/radialUnit.png | Bin 0 -> 4250 bytes .../terasology/radial/radialUnitSelected.png | Bin 0 -> 3398 bytes .../textures/ui/nui/terasology/statusBar.png | Bin 0 -> 3542 bytes .../ui/nui/terasology/testWindowBorder.png | Bin 0 -> 643 bytes .../nui/terasology/testWindowBorder.texinfo | 3 + .../nui/terasology/testWindowBorderOver.png | Bin 0 -> 633 bytes .../terasology/testWindowBorderOver.texinfo | 3 + .../ui/nui/terasology/treeView/LICENSE_NOTES | 43 ++ .../ui/nui/terasology/treeView/contract.png | Bin 0 -> 522 bytes .../nui/terasology/treeView/contractOver.png | Bin 0 -> 553 bytes .../ui/nui/terasology/treeView/expand.png | Bin 0 -> 509 bytes .../ui/nui/terasology/treeView/expandOver.png | Bin 0 -> 551 bytes .../main/resources/assets/ui/migTestScreen.ui | 698 ++++++++++++++++++ 55 files changed, 2601 insertions(+), 11 deletions(-) create mode 100644 engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java create mode 100644 engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java create mode 100644 engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java create mode 100644 engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java create mode 100644 engine/src/main/resources/assets/skins/default.skin create mode 100644 engine/src/main/resources/assets/skins/migTestSkin.skin create mode 100644 engine/src/main/resources/assets/textures/ui/nui/area.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/box.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/boxActive.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/boxDisabled.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/button.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/buttonDown.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/buttonOver.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/checkbox.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/checkboxChecked.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedDisabled.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedHover.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/checkboxDisabled.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/checkboxHover.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/dropdown.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/dropdownActive.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/dropdownDisabled.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/dropdownList.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/dropdownListItemActive.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/handle.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/resetBox.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/resetBoxDisabled.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/sliderTrack.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/LICENSE_NOTES create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnit.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnitSelected.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/statusBar.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.texinfo create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contract.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contractOver.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expand.png create mode 100644 engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expandOver.png create mode 100644 engine/src/main/resources/assets/ui/migTestScreen.ui diff --git a/engine/build.gradle b/engine/build.gradle index 1198d0b35..e379f0a5c 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -31,6 +31,8 @@ dependencies { compile(group: 'org.terasology.gestalt', name: 'gestalt-entity-system', version: '7.0.5') compile(group: 'org.terasology.gestalt', name: 'gestalt-module', version: '7.0.5') compile(group: 'org.terasology.gestalt', name: 'gestalt-util', version: '7.0.5') + compile group: 'org.terasology.nui', name: 'nui', version: '0.2' + compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '0.2' compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index ee54bef1a..1e09a9929 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -46,6 +46,7 @@ import org.destinationsol.ui.SolInputManager; import org.destinationsol.ui.SolLayouts; import org.destinationsol.ui.UiDrawer; +import org.destinationsol.ui.nui.NUIManager; import org.destinationsol.util.FramerateLimiter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -85,6 +86,7 @@ public class SolApplication implements ApplicationListener { private String fatalErrorTrace; private SolGame solGame; private ParameterAdapterManager parameterAdapterManager; + private NUIManager nuiManager; private Context context; // TODO: Make this non-static. public static DisplayDimensions displayDimensions; @@ -150,6 +152,8 @@ public void create() { inputManager.setScreen(this, menuScreens.main); parameterAdapterManager = ParameterAdapterManager.createCore(this); + + nuiManager = new NUIManager(this, commonDrawer); } @Override @@ -224,6 +228,7 @@ private void update() { } inputManager.update(this); + nuiManager.update(this); if (solGame != null) { solGame.update(); @@ -240,6 +245,8 @@ private void draw() { } uiDrawer.updateMtx(); inputManager.draw(uiDrawer, this); + nuiManager.draw(commonDrawer); + inputManager.drawCursor(uiDrawer); if (solGame != null) { solGame.drawDebugUi(uiDrawer); @@ -327,6 +334,10 @@ public MenuBackgroundManager getMenuBackgroundManager() { return menuBackgroundManager; } + public NUIManager getNuiManager() { + return nuiManager; + } + // TODO: Make this non-static. public static void addResizeSubscriber(ResizeSubscriber resizeSubscriber) { resizeSubscribers.add(resizeSubscriber); diff --git a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java index 75c485ea5..8e860c98f 100644 --- a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java +++ b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java @@ -16,11 +16,23 @@ package org.destinationsol.assets; import org.destinationsol.assets.music.AndroidOggMusicFileFormat; -import org.destinationsol.assets.music.OggMusic; -import org.destinationsol.assets.music.OggMusicData; import org.destinationsol.assets.sound.AndroidOggSoundFileFormat; -import org.destinationsol.assets.sound.OggSound; import org.destinationsol.assets.sound.OggSoundData; +import org.destinationsol.assets.audio.OggMusic; +import org.destinationsol.assets.audio.OggMusicFileFormat; +import org.destinationsol.assets.audio.OggSound; +import org.destinationsol.assets.audio.OggSoundFileFormat; +import org.destinationsol.assets.emitters.Emitter; +import org.destinationsol.assets.emitters.EmitterFileFormat; +import org.destinationsol.assets.fonts.Font; +import org.destinationsol.assets.fonts.FontFileFormat; +import org.destinationsol.assets.json.Json; +import org.destinationsol.assets.json.JsonDeltaFileFormat; +import org.destinationsol.assets.json.JsonFileFormat; +import org.destinationsol.assets.textures.DSTexture; +import org.destinationsol.assets.textures.DSTextureFileFormat; +import org.destinationsol.assets.ui.UIFormat; +import org.destinationsol.assets.ui.UISkinFormat; import org.terasology.gestalt.assets.Asset; import org.terasology.gestalt.assets.AssetData; import org.terasology.gestalt.assets.AssetType; @@ -35,6 +47,13 @@ import org.terasology.gestalt.entitysystem.prefab.PrefabJsonFormat; import org.terasology.gestalt.module.ModuleEnvironment; import org.terasology.gestalt.naming.Name; +import org.terasology.nui.UIWidget; +import org.terasology.nui.asset.UIElement; +import org.terasology.nui.reflection.WidgetLibrary; +import org.terasology.nui.skin.UISkin; +import org.terasology.reflection.copy.CopyStrategyLibrary; +import org.terasology.reflection.reflect.ReflectFactory; +import org.terasology.reflection.reflect.ReflectionReflectFactory;. import java.util.Optional; import java.util.Set; @@ -63,6 +82,19 @@ public void init(ModuleEnvironment environment, ComponentManager componentManage new ModuleEnvironmentDependencyProvider(environment))), componentManager, assetTypeManager.getAssetManager()).create()); + ReflectFactory reflectFactory = new ReflectionReflectFactory(); + WidgetLibrary widgetLibrary = new WidgetLibrary(environment, reflectFactory, new CopyStrategyLibrary(reflectFactory)); + for (Class widgetClass : environment.getSubtypesOf(UIWidget.class)) { + Name moduleName = environment.getModuleProviding(widgetClass); + widgetLibrary.register(new ResourceUrn(moduleName, new Name(widgetClass.getSimpleName())), widgetClass); + } + + assetTypeManager.createAssetType(UISkin.class, UISkin::new, "skins"); + ((AssetFileDataProducer)assetTypeManager.getAssetType(UISkin.class).get().getProducers().get(0)).addAssetFormat(new UISkinFormat(widgetLibrary)); + + assetTypeManager.createAssetType(UIElement.class, UIElement::new, "ui"); + ((AssetFileDataProducer)assetTypeManager.getAssetType(UIElement.class).get().getProducers().get(0)).addAssetFormat(new UIFormat(widgetLibrary)); + assetTypeManager.switchEnvironment(environment); } diff --git a/engine/src/main/java/org/destinationsol/assets/fonts/FontData.java b/engine/src/main/java/org/destinationsol/assets/fonts/FontData.java index 9656d8915..d6b63e87c 100644 --- a/engine/src/main/java/org/destinationsol/assets/fonts/FontData.java +++ b/engine/src/main/java/org/destinationsol/assets/fonts/FontData.java @@ -17,11 +17,13 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont; import org.terasology.gestalt.assets.AssetData; +import org.terasology.nui.backends.libgdx.LibGDXFont; -public class FontData implements AssetData { +public class FontData extends LibGDXFont implements AssetData { private BitmapFont bitmapFont; public FontData(BitmapFont bitmapFont) { + super(bitmapFont); this.bitmapFont = bitmapFont; } diff --git a/engine/src/main/java/org/destinationsol/assets/fonts/FontFileFormat.java b/engine/src/main/java/org/destinationsol/assets/fonts/FontFileFormat.java index d3e2fd88b..225b08d2b 100644 --- a/engine/src/main/java/org/destinationsol/assets/fonts/FontFileFormat.java +++ b/engine/src/main/java/org/destinationsol/assets/fonts/FontFileFormat.java @@ -15,8 +15,10 @@ */ package org.destinationsol.assets.fonts; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.utils.Array; import org.destinationsol.assets.AssetDataFileHandle; import org.destinationsol.assets.Assets; import org.terasology.gestalt.assets.ResourceUrn; @@ -38,12 +40,17 @@ public FontData load(ResourceUrn urn, List inputs) throws IOExcep AssetDataFileHandle fontDataHandle = new AssetDataFileHandle(inputs.get(0)); BitmapFont.BitmapFontData fontData = new BitmapFont.BitmapFontData(fontDataHandle, true); - String[] fontTexturePath = fontData.imagePaths[0].split("/"); - String fontTextureName = fontTexturePath[fontTexturePath.length - 1]; - fontTextureName = fontTextureName.substring(0, fontTextureName.lastIndexOf('.')); - TextureRegion fontTexture = new TextureRegion(Assets.getDSTexture(urn.getModuleName() + ":" + fontTextureName).getTexture()); + TextureRegion[] fontTextures = new TextureRegion[fontData.imagePaths.length]; + for (int textureNo = 0; textureNo < fontData.imagePaths.length; textureNo++){ + String[] pathSegments = fontData.imagePaths[textureNo].split("/"); + String fontTextureName = pathSegments[pathSegments.length - 1]; + fontTextureName = fontTextureName.substring(0, fontTextureName.lastIndexOf('.')); + Texture texture = Assets.getDSTexture(urn.getModuleName() + ":" + fontTextureName).getTexture(); + TextureRegion fontTexture = new TextureRegion(texture); + fontTextures[textureNo] = fontTexture; + } - BitmapFont bitmapFont = new BitmapFont(fontData, fontTexture, false); + BitmapFont bitmapFont = new BitmapFont(fontData, Array.with(fontTextures), false); bitmapFont.setUseIntegerPositions(false); return new FontData(bitmapFont); } diff --git a/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java b/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java new file mode 100644 index 000000000..ce7c0e58a --- /dev/null +++ b/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java @@ -0,0 +1,113 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.assets.fonts; + +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import org.terasology.math.geom.Vector2i; +import org.terasology.nui.backends.libgdx.LibGDXFont; + +import java.util.List; + +/** + * This class wraps a {@link Font} asset in order to adapt it to NUI's LibGDX back-end. + */ +public class UIFont extends LibGDXFont { + private float fontScale; + private float previousFontScaleX; + private float previousFontScaleY; + private static final float FONT_SCALE = 8.0f; + + public UIFont(Font font) { + super(font.getBitmapFont()); + + fontScale = FONT_SCALE / super.getGdxFont().getData().xHeight; + } + + private void scale() { + scale(fontScale, fontScale); + } + + private void scale(float scaleX, float scaleY) { + previousFontScaleX = super.getGdxFont().getScaleX(); + previousFontScaleY = super.getGdxFont().getScaleY(); + super.getGdxFont().getData().setScale(scaleX, scaleY); + } + + private void reset() { + super.getGdxFont().getData().setScale(previousFontScaleX, previousFontScaleY); + } + + @Override + public Vector2i getSize(List lines) { + scale(); + Vector2i result = super.getSize(lines); + reset(); + return result; + } + + @Override + public int getWidth(Character c) { + scale(); + int result = super.getWidth(c); + reset(); + return result; + } + + @Override + public int getLineHeight() { + scale(); + int result = super.getLineHeight(); + reset(); + return result; + } + + @Override + public int getHeight(String text) { + scale(); + int result = super.getHeight(text); + reset(); + return result; + } + + @Override + public int getBaseHeight() { + scale(); + int result = super.getBaseHeight(); + reset(); + return result; + } + + @Override + public int getWidth(String text) { + scale(); + int result = super.getWidth(text); + reset(); + return result; + } + + @Override + public BitmapFont getGdxFont() { + super.getGdxFont().getData().setScale(fontScale, -fontScale); + return super.getGdxFont(); + } + + @Override + public GlyphLayout getGlyphLayout() { + super.getGdxFont().getData().setScale(fontScale, -fontScale); + return super.getGlyphLayout(); + } +} diff --git a/engine/src/main/java/org/destinationsol/assets/sound/PlayableSound.java b/engine/src/main/java/org/destinationsol/assets/sound/PlayableSound.java index f5df0451e..3ac286bd4 100644 --- a/engine/src/main/java/org/destinationsol/assets/sound/PlayableSound.java +++ b/engine/src/main/java/org/destinationsol/assets/sound/PlayableSound.java @@ -17,10 +17,12 @@ import org.destinationsol.assets.sound.OggSound; +import org.terasology.nui.asset.Sound; + /** * A class that stores an OggSound or a set of OggSounds. */ -public interface PlayableSound { +public interface PlayableSound extends Sound { /** * Returns an OggSound selected from the sound set. @@ -35,4 +37,9 @@ public interface PlayableSound { * @return */ float getBasePitch(); + + @Override + default void play(float volume) { + getOggSound().getSound().play(volume, getBasePitch(), 0); + } } diff --git a/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java b/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java index 53492e599..d97f8b804 100644 --- a/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java +++ b/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java @@ -20,6 +20,7 @@ import org.terasology.gestalt.assets.AssetType; import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.gestalt.assets.module.annotations.RegisterAssetType; +import org.terasology.nui.UITextureRegion; @RegisterAssetType(folderName = {"textures", "ships", "items", "grounds", "mazes", "asteroids", "fonts"}, factoryClass = DSTextureFactory.class) public class DSTexture extends Asset { @@ -38,4 +39,8 @@ protected void doReload(DSTextureData data) { public Texture getTexture() { return dsTextureData.getTexture(); } + + public UITextureRegion getUiTexture() { + return dsTextureData; + } } diff --git a/engine/src/main/java/org/destinationsol/assets/textures/DSTextureData.java b/engine/src/main/java/org/destinationsol/assets/textures/DSTextureData.java index 5619e8e45..069c05d56 100644 --- a/engine/src/main/java/org/destinationsol/assets/textures/DSTextureData.java +++ b/engine/src/main/java/org/destinationsol/assets/textures/DSTextureData.java @@ -16,12 +16,15 @@ package org.destinationsol.assets.textures; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.TextureRegion; import org.terasology.gestalt.assets.AssetData; +import org.terasology.nui.backends.libgdx.LibGDXTexture; -public class DSTextureData implements AssetData { +public class DSTextureData extends LibGDXTexture implements AssetData { private Texture texture; public DSTextureData(Texture texture) { + super(new TextureRegion(texture)); this.texture = texture; } diff --git a/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java b/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java new file mode 100644 index 000000000..1fc41a185 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.assets.ui; + +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.util.Locale; +import java.util.Map; + +/** + * A Gson Adapter factory for supporting enums in a case-insensitive manner + * + */ +public class CaseInsensitiveEnumTypeAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + Class rawType = (Class) type.getRawType(); + if (!rawType.isEnum()) { + return null; + } + + final Map lowercaseToConstant = Maps.newHashMap(); + for (T constant : rawType.getEnumConstants()) { + String norm = normalize(constant.toString()); + lowercaseToConstant.put(norm, constant); + } + + return new TypeAdapter() { + @Override + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(normalize(value.toString())); + } + } + + @Override + public T read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } else { + String value = reader.nextString(); + return lowercaseToConstant.get(normalize(value)); + } + } + }; + } + + private String normalize(String name) { + return name.toLowerCase(Locale.ENGLISH); + } +} + diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java new file mode 100644 index 000000000..0eab22822 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java @@ -0,0 +1,246 @@ +/* + * Copyright 2016 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.assets.ui; + +import com.google.common.base.Charsets; +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import com.google.gson.stream.JsonReader; +import org.destinationsol.assets.Assets; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.gestalt.assets.format.AbstractAssetFileFormat; +import org.terasology.gestalt.assets.format.AssetDataFile; +import org.terasology.gestalt.assets.management.AssetManager; +import org.terasology.gestalt.assets.module.annotations.RegisterAssetFileFormat; +import org.terasology.math.geom.Vector2i; +import org.terasology.nui.Color; +import org.terasology.nui.LayoutHint; +import org.terasology.nui.UILayout; +import org.terasology.nui.UITextureRegion; +import org.terasology.nui.UIWidget; +import org.terasology.nui.asset.UIData; +import org.terasology.nui.asset.font.Font; +import org.terasology.nui.reflection.WidgetLibrary; +import org.terasology.nui.skin.UISkin; +import org.terasology.nui.widgets.UILabel; +import org.terasology.reflection.ReflectionUtil; +import org.terasology.reflection.metadata.ClassMetadata; +import org.terasology.reflection.metadata.FieldMetadata; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; + +/** + * Handles loading UI widgets from json format files. + */ +@RegisterAssetFileFormat +public class UIFormat extends AbstractAssetFileFormat { + + public static final String CONTENTS_FIELD = "contents"; + public static final String LAYOUT_INFO_FIELD = "layoutInfo"; + public static final String ID_FIELD = "id"; + public static final String TYPE_FIELD = "type"; + + private static final Logger logger = LoggerFactory.getLogger(UIFormat.class); + private static WidgetLibrary library; + + public UIFormat(WidgetLibrary library) { + super("ui"); + + UIFormat.library = library; + } + + @Override + public UIData load(ResourceUrn resourceUrn, List inputs) throws IOException { + try (JsonReader reader = new JsonReader(new InputStreamReader(inputs.get(0).openStream(), Charsets.UTF_8))) { + reader.setLenient(true); + UIData data = load(new JsonParser().parse(reader)); + data.setSource(inputs.get(0)); + return data; + } + } + + public UIData load(JsonElement element) throws IOException { + return load(element, null); + } + + public UIData load(JsonElement element, Locale otherLocale) throws IOException { + GsonBuilder gsonBuilder = new GsonBuilder() + .registerTypeAdapterFactory(new CaseInsensitiveEnumTypeAdapterFactory()) + .registerTypeAdapter(UIData.class, new UIDataTypeAdapter()) + .registerTypeAdapter(UISkin.class, new JsonDeserializer() { + @Override + public UISkin deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return Assets.getAssetHelper().get(new ResourceUrn(json.getAsString()), UISkin.class).get(); + } + }) + .registerTypeAdapter(UITextureRegion.class, new UISkinFormat.TextureRegionTypeAdapter()) + .registerTypeAdapter(Optional.class, new UISkinFormat.OptionalTextureRegionTypeAdapter()) + .registerTypeAdapter(Font.class, new UISkinFormat.FontTypeAdapter()) + .registerTypeAdapter(Color.class, new UISkinFormat.ColorTypeHandler()) + .registerTypeAdapter(Vector2i.class, new Vector2iTypeAdaptor()) + .registerTypeHierarchyAdapter(UIWidget.class, new UIWidgetTypeAdapter()); + Gson gson = gsonBuilder.create(); + return gson.fromJson(element, UIData.class); + } + + /** + * Load UIData with a single, root widget + */ + private static final class UIDataTypeAdapter implements JsonDeserializer { + + @Override + public UIData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + return new UIData((UIWidget) context.deserialize(json, UIWidget.class)); + } + } + + private static final class Vector2iTypeAdaptor implements JsonDeserializer { + + @Override + public Vector2i deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonArray array = json.getAsJsonArray(); + return new Vector2i(array.get(0).getAsInt(), array.get(1).getAsInt()); + } + } + + /** + * Loads a widget. This requires the following custom handling: + *
    + *
  • The class of the widget is determined through a URI in the "type" attribute
  • + *
  • If the "id" attribute is present, it is passed to the constructor
  • + *
  • If the widget is a layout, then a "contents" attribute provides a list of widgets for content. + * Each contained widget may have a "layoutInfo" attribute providing the layout hint for its container.
  • + *
+ */ + private static final class UIWidgetTypeAdapter implements JsonDeserializer { + @Override + public UIWidget deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonPrimitive() && json.getAsJsonPrimitive().isString()) { + return new UILabel(json.getAsString()); + } + + JsonObject jsonObject = json.getAsJsonObject(); + + String type = jsonObject.get(TYPE_FIELD).getAsString(); + ClassMetadata elementMetadata = library.resolve(type); + if (elementMetadata == null) { + logger.error("Unknown UIWidget type {}", type); + return null; + } + + String id = null; + if (jsonObject.has(ID_FIELD)) { + id = jsonObject.get(ID_FIELD).getAsString(); + } + + UIWidget element = elementMetadata.newInstance(); + if (id != null) { + FieldMetadata fieldMetadata = elementMetadata.getField(ID_FIELD); + if (fieldMetadata == null) { + logger.warn("UIWidget type {} lacks id field", elementMetadata.getUri()); + } else { + fieldMetadata.setValue(element, id); + } + } + + // Deserialize normal fields. + Set unknownFields = new HashSet<>(); + for (Entry entry : jsonObject.entrySet()) { + String name = entry.getKey(); + if (!ID_FIELD.equals(name) + && !CONTENTS_FIELD.equals(name) + && !TYPE_FIELD.equals(name) + && !LAYOUT_INFO_FIELD.equals(name)) { + unknownFields.add(name); + } + } + + for (FieldMetadata field : elementMetadata.getFields()) { + if (jsonObject.has(field.getSerializationName())) { + unknownFields.remove(field.getSerializationName()); + if (field.getName().equals(CONTENTS_FIELD) && UILayout.class.isAssignableFrom(elementMetadata.getType())) { + continue; + } + try { + if (List.class.isAssignableFrom(field.getType())) { + Type contentType = ReflectionUtil.getTypeParameter(field.getField().getGenericType(), 0); + if (contentType != null) { + List result = Lists.newArrayList(); + JsonArray list = jsonObject.getAsJsonArray(field.getSerializationName()); + for (JsonElement item : list) { + result.add(context.deserialize(item, contentType)); + } + field.setValue(element, result); + } + } else { + field.setValue(element, context.deserialize(jsonObject.get(field.getSerializationName()), field.getType())); + } + } catch (RuntimeException e) { + logger.error("Failed to deserialize field {} of {}", field.getName(), type, e); + } + } + } + + for (String key : unknownFields) { + logger.warn("Field '{}' not recognized for {} in {}", key, typeOfT, json); + } + + // Deserialize contents and layout hints + if (UILayout.class.isAssignableFrom(elementMetadata.getType())) { + UILayout layout = (UILayout) element; + + Class layoutHintType = (Class) + ReflectionUtil.getTypeParameter(elementMetadata.getType().getGenericSuperclass(), 0); + if (jsonObject.has(CONTENTS_FIELD)) { + for (JsonElement child : jsonObject.getAsJsonArray(CONTENTS_FIELD)) { + UIWidget childElement = context.deserialize(child, UIWidget.class); + if (childElement != null) { + LayoutHint hint = null; + if (child.isJsonObject()) { + JsonObject childObject = child.getAsJsonObject(); + if (layoutHintType != null && !layoutHintType.isInterface() && !Modifier.isAbstract(layoutHintType.getModifiers()) + && childObject.has(LAYOUT_INFO_FIELD)) { + hint = context.deserialize(childObject.get(LAYOUT_INFO_FIELD), layoutHintType); + } + } + layout.addWidget(childElement, hint); + } + } + } + } + return element; + } + } +} diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java new file mode 100644 index 000000000..67c11bbb2 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java @@ -0,0 +1,236 @@ +package org.destinationsol.assets.ui; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.google.common.base.Charsets; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.stream.JsonReader; +import org.destinationsol.assets.Assets; +import org.destinationsol.assets.fonts.UIFont; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.gestalt.assets.format.AbstractAssetFileFormat; +import org.terasology.gestalt.assets.format.AssetDataFile; +import org.terasology.gestalt.assets.module.annotations.RegisterAssetFileFormat; +import org.terasology.nui.Color; +import org.terasology.nui.UITextureRegion; +import org.terasology.nui.UIWidget; +import org.terasology.nui.asset.font.Font; +import org.terasology.nui.skin.UISkin; +import org.terasology.nui.skin.UISkinBuilder; +import org.terasology.nui.skin.UISkinData; +import org.terasology.nui.skin.UIStyleFragment; +import org.terasology.reflection.metadata.ClassLibrary; +import org.terasology.reflection.metadata.ClassMetadata; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + */ +@RegisterAssetFileFormat +public class UISkinFormat extends AbstractAssetFileFormat { + + private static final Logger logger = LoggerFactory.getLogger(UISkinFormat.class); + private Gson gson; + private static ClassLibrary widgetClassLibrary; + + public UISkinFormat(ClassLibrary widgetClassLibrary) { + super("skin"); + gson = new GsonBuilder() + .registerTypeAdapter(UISkinData.class, new UISkinTypeAdapter()) + .registerTypeAdapterFactory(new CaseInsensitiveEnumTypeAdapterFactory()) + .registerTypeAdapter(UITextureRegion.class, new TextureRegionTypeAdapter()) + .registerTypeAdapter(Optional.class, new OptionalTextureRegionTypeAdapter()) + .registerTypeAdapter(Font.class, new FontTypeAdapter()) + .registerTypeAdapter(Color.class, new ColorTypeHandler()) + .enableComplexMapKeySerialization() + .serializeNulls() + .create(); + UISkinFormat.widgetClassLibrary = widgetClassLibrary; + } + + @Override + public UISkinData load(ResourceUrn urn, List inputs) throws IOException { + try (JsonReader reader = new JsonReader(new InputStreamReader(inputs.get(0).openStream(), Charsets.UTF_8))) { + reader.setLenient(true); + UISkinData data = gson.fromJson(reader, UISkinData.class); + data.setSource(inputs.get(0)); + return data; + } catch (JsonSyntaxException e) { + e.printStackTrace(); + throw new IOException("Failed to load skin '" + urn + "'", e); + } + } + + public UISkinData load(JsonElement element) throws IOException { + return gson.fromJson(element, UISkinData.class); + } + + public static class TextureRegionTypeAdapter implements JsonDeserializer { + + @Override + public UITextureRegion deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + String uri = json.getAsString(); + return Assets.getDSTexture(uri).getUiTexture(); + } + } + + private static class UISkinTypeAdapter implements JsonDeserializer { + @Override + public UISkinData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonObject()) { + UISkinBuilder builder = new UISkinBuilder(); + DefaultInfo defaultInfo = null; + defaultInfo = context.deserialize(json, DefaultInfo.class); + defaultInfo.apply(builder); + return builder.build(); + } + return null; + } + } + + private static class DefaultInfo extends FamilyInfo { + public String inherit; + public Map families; + + @Override + public void apply(UISkinBuilder builder) { + super.apply(builder); + if (inherit != null) { + Optional skin = Assets.getAssetHelper().get(new ResourceUrn(inherit), UISkin.class); + if (skin.isPresent()) { + builder.setBaseSkin(skin.get()); + } + } + if (families != null) { + for (Map.Entry entry : families.entrySet()) { + builder.setFamily(entry.getKey()); + entry.getValue().apply(builder); + } + } + } + } + + private static class FamilyInfo extends StyleInfo { + public Map elements; + + public void apply(UISkinBuilder builder) { + super.apply(builder); + if (elements != null) { + for (Map.Entry entry : elements.entrySet()) { + ClassLibrary library = widgetClassLibrary; + ClassMetadata metadata = library.resolve(entry.getKey()); + if (metadata != null) { + builder.setElementClass(metadata.getType()); + entry.getValue().apply(builder); + } else { + logger.warn("Failed to resolve UIWidget class {}, skipping style information", entry.getKey()); + } + + } + } + } + } + + private static class PartsInfo extends StyleInfo { + public Map modes; + + public void apply(UISkinBuilder builder) { + super.apply(builder); + if (modes != null) { + for (Map.Entry entry : modes.entrySet()) { + builder.setElementMode(entry.getKey()); + entry.getValue().apply(builder); + } + } + } + } + + private static class ElementInfo extends StyleInfo { + public Map parts; + public Map modes; + + public void apply(UISkinBuilder builder) { + super.apply(builder); + if (modes != null) { + for (Map.Entry entry : modes.entrySet()) { + builder.setElementMode(entry.getKey()); + entry.getValue().apply(builder); + } + } + if (parts != null) { + for (Map.Entry entry : parts.entrySet()) { + builder.setElementPart(entry.getKey()); + entry.getValue().apply(builder); + } + } + } + } + + private static class StyleInfo extends UIStyleFragment { + + private void apply(UISkinBuilder builder) { + builder.setStyleFragment(this); + } + } + + public static class OptionalTextureRegionTypeAdapter implements JsonDeserializer> { + @Override + public Optional deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + String name = json.getAsString(); + if (name.isEmpty()) { + return Optional.empty(); + } + + if (!name.contains(":")) { + name = "engine:" + name; + } + return Optional.of(Assets.getDSTexture(name).getUiTexture()); + } + } + + public static class FontTypeAdapter implements JsonDeserializer { + @Override + public Font deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + String name = json.getAsString(); + if (!name.contains(":")) { + name = "engine:" + name; + } + return new UIFont(Assets.getFont(name)); + } + } + + /** + * Serializes {@link Color} instances to an int array [r, g, b, a]. + * De-serializing also supports hexadecimal strings such as "AAAAAAFF". + */ + public static class ColorTypeHandler implements JsonDeserializer { + @Override + public Color deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + if (json.isJsonArray()) { + JsonArray array = json.getAsJsonArray(); + return new Color(array.get(0).getAsFloat(), array.get(1).getAsFloat(), array.get(2).getAsFloat(), array.get(3).getAsFloat()); + } + if (json.isJsonPrimitive()) { + return new Color(Integer.parseUnsignedInt(json.getAsString(), 16)); + } + + return null; + } + } +} diff --git a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java index c27861b0e..25f5dda79 100644 --- a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java +++ b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java @@ -41,6 +41,7 @@ import org.terasology.gestalt.module.sandbox.ModuleSecurityManager; import org.terasology.gestalt.module.sandbox.ModuleSecurityPolicy; import org.terasology.gestalt.module.sandbox.StandardPermissionProviderFactory; +import org.terasology.nui.UIWidget; import java.io.File; import java.lang.reflect.InvocationTargetException; diff --git a/engine/src/main/java/org/destinationsol/ui/SolInputManager.java b/engine/src/main/java/org/destinationsol/ui/SolInputManager.java index 8ebe33414..fd61f2701 100644 --- a/engine/src/main/java/org/destinationsol/ui/SolInputManager.java +++ b/engine/src/main/java/org/destinationsol/ui/SolInputManager.java @@ -353,7 +353,9 @@ public void draw(UiDrawer uiDrawer, SolApplication solApplication) { if (tutorialManager != null && getTopScreen() != game.getScreens().menuScreen) { tutorialManager.draw(uiDrawer); } + } + public void drawCursor(UiDrawer uiDrawer) { if (currCursor != null) { uiDrawer.draw(currCursor, CURSOR_SZ, CURSOR_SZ, CURSOR_SZ / 2, CURSOR_SZ / 2, mousePos.x, mousePos.y, 0, SolColor.WHITE); } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java new file mode 100644 index 000000000..df3d7ef4f --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -0,0 +1,205 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.ui.nui; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import org.destinationsol.CommonDrawer; +import org.destinationsol.SolApplication; +import org.destinationsol.assets.Assets; +import org.destinationsol.assets.audio.OggSound; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.input.InputType; +import org.terasology.input.MouseInput; +import org.terasology.input.device.KeyboardAction; +import org.terasology.input.device.KeyboardDevice; +import org.terasology.input.device.MouseAction; +import org.terasology.input.device.MouseDevice; +import org.terasology.nui.FocusManager; +import org.terasology.nui.FocusManagerImpl; +import org.terasology.nui.TabbingManager; +import org.terasology.nui.UITextureRegion; +import org.terasology.nui.UIWidget; +import org.terasology.nui.asset.UIElement; +import org.terasology.nui.backends.libgdx.LibGDXCanvasRenderer; +import org.terasology.nui.backends.libgdx.LibGDXKeyboardDevice; +import org.terasology.nui.backends.libgdx.LibGDXMouseDevice; +import org.terasology.nui.canvas.CanvasImpl; +import org.terasology.nui.events.NUIKeyEvent; +import org.terasology.nui.events.NUIMouseButtonEvent; +import org.terasology.nui.events.NUIMouseWheelEvent; +import org.terasology.nui.skin.UISkin; +import org.terasology.nui.widgets.UIButton; +import org.terasology.nui.widgets.UIText; + +import java.util.Deque; +import java.util.Iterator; +import java.util.LinkedList; + +public class NUIManager { + private LibGDXCanvasRenderer canvasRenderer; + private CanvasImpl canvas; + private UITextureRegion whiteTexture; + private MouseDevice mouse; + private KeyboardDevice keyboard; + private FocusManager focusManager; + private UISkin skin; + + private Deque uiScreens = new LinkedList<>(); + private Deque uiOverlays = new LinkedList<>(); + + private static final String WHITE_TEXTURE_URN = "engine:uiWhiteTex"; + private static final String DEFAULT_SKIN_URN = "engine:default"; + private static final String BUTTON_CLICK_URN = "engine:uiHover"; + private static final float BUTTON_CLICK_PITCH = 0.9f; + + public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { + mouse = new LibGDXMouseDevice(); + keyboard = new LibGDXKeyboardDevice(); + canvasRenderer = new LibGDXCanvasRenderer(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), + commonDrawer.getSpriteBatch(), new ShapeRenderer(), false, true); + focusManager = new FocusManagerImpl(); + whiteTexture = Assets.getDSTexture(WHITE_TEXTURE_URN).getUiTexture(); + skin = Assets.getAssetHelper().get(new ResourceUrn(DEFAULT_SKIN_URN), UISkin.class).get(); + + canvas = new CanvasImpl(canvasRenderer, focusManager, keyboard, mouse, whiteTexture, skin, 100); + TabbingManager.setFocusManager(focusManager); + + OggSound sound = Assets.getSound(BUTTON_CLICK_URN); + sound.setBasePitch(BUTTON_CLICK_PITCH); + + UIButton.DEFAULT_CLICK_SOUND = sound; + UIText.DEFAULT_CURSOR_TEXTURE = whiteTexture; + + //pushScreen((NUIScreenLayer) Assets.getAssetHelper().get(new ResourceUrn("engine:migTestScreen"), UIElement.class).get().getRootWidget()); + //pushScreen((NUIScreenLayer) Assets.getAssetHelper().get(new ResourceUrn("engine:console"), UIElement.class).get().getRootWidget()); + + // NOTE: SolApplication::addResizeSubscriber is not intended to be static, so use the instance form for compatibility + solApplication.addResizeSubscriber(() -> canvasRenderer.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight())); + } + + public void update(SolApplication solApplication) { + canvas.processMousePosition(mouse.getPosition()); + canvas.setGameTime(System.currentTimeMillis()); + + for (KeyboardAction action : keyboard.getInputQueue()) { + if (focusManager.getFocus() != null) { + focusManager.getFocus().onKeyEvent(new NUIKeyEvent(mouse, keyboard, action.getInput(), action.getInputChar(), action.getState())); + } + } + + for (MouseAction action : mouse.getInputQueue()) { + if (action.getInput().getType() == InputType.MOUSE_BUTTON) { + if (action.getState().isDown()) { + canvas.processMouseClick((MouseInput) action.getInput(), action.getMousePosition()); + } else { + canvas.processMouseRelease((MouseInput) action.getInput(), action.getMousePosition()); + } + + if (focusManager.getFocus() != null) { + focusManager.getFocus().onMouseButtonEvent(new NUIMouseButtonEvent((MouseInput) action.getInput(), action.getState(), action.getMousePosition())); + } + } else if (action.getInput().getType() == InputType.MOUSE_WHEEL) { + canvas.processMouseWheel(action.getTurns(), action.getMousePosition()); + if (focusManager.getFocus() != null) { + focusManager.getFocus().onMouseWheelEvent(new NUIMouseWheelEvent(mouse, keyboard, action.getMousePosition(), action.getTurns())); + } + } + } + + for (NUIScreenLayer uiScreen : uiScreens) { + UIWidget element = uiScreen.contents; + element.update(Gdx.graphics.getDeltaTime()); + + if (uiScreen.isBlockingInput()) { + break; + } + } + } + + public void draw(CommonDrawer gameDrawer) { + gameDrawer.getSpriteBatch().flush(); + + canvas.preRender(); + + // NOTE: Need to render in the inverse to how they are updated, so the top screen is drawn last + Iterator screenIterator = uiScreens.descendingIterator(); + while (screenIterator.hasNext()) { + NUIScreenLayer screenLayer = screenIterator.next(); + canvas.setSkin(screenLayer.getSkin()); + canvas.drawWidget(screenLayer.contents); + } + + canvas.postRender(); + + gameDrawer.getSpriteBatch().flush(); + } + + public NUIScreenLayer getTopScreen() { + return uiScreens.peek(); + } + + public void pushScreen(NUIScreenLayer layer) { + uiScreens.push(layer); + layer.initialise(); + } + + public NUIScreenLayer popScreen() { + return uiScreens.pop(); + } + + public void removeScreen(NUIScreenLayer screen) { + uiScreens.remove(screen); + } + + public Deque getScreens() { + return uiScreens; + } + + public void pushOverlay(NUIScreenLayer overlay) { + uiOverlays.push(overlay); + } + + public NUIScreenLayer popOverlay() { + return uiOverlays.pop(); + } + + public void removeOverlay(NUIScreenLayer overlay) { + uiOverlays.remove(overlay); + } + + public Deque getOverlays() { + return uiOverlays; + } + + public boolean hasOverlay(NUIScreenLayer overlay) { + return uiOverlays.contains(overlay); + } + + public boolean hasOverlayOfType(Class type) { + for (NUIScreenLayer layer : uiOverlays) { + if (layer.getClass().isAssignableFrom(type)) { + return true; + } + } + + return false; + } + + public UISkin getDefaultSkin() { + return skin; + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java new file mode 100644 index 000000000..3e71901d0 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java @@ -0,0 +1,80 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.ui.nui; + +import org.terasology.input.Input; +import org.terasology.input.InputType; +import org.terasology.math.geom.Vector2i; +import org.terasology.nui.AbstractWidget; +import org.terasology.nui.Canvas; +import org.terasology.nui.LayoutConfig; +import org.terasology.nui.UIWidget; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; + +public abstract class NUIScreenLayer extends AbstractWidget { + @LayoutConfig + protected UIWidget contents; + + @Override + public void onDraw(Canvas canvas) { + canvas.drawWidget(contents); + } + + @Override + public boolean canBeFocus() { + return false; + } + + /** + * Returns the preferred content size of this widget. + * + * @param canvas A {@link Canvas} on which this widget is drawn. + * @param sizeHint A {@link Vector2i} representing how much available space is for this widget. + * @return A {@link Vector2i} which represents the preferred size of this widget. + */ + @Override + public Vector2i getPreferredContentSize(Canvas canvas, Vector2i sizeHint) { + return sizeHint; + } + + @Override + public Vector2i getMaxContentSize(Canvas canvas) { + return new Vector2i(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + if (contents == null) { + return Collections.emptyIterator(); + } + return Arrays.asList(contents).iterator(); + } + + public void initialise() { + } + + public boolean isBlockingInput() { + return false; + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java new file mode 100644 index 000000000..498f40ac5 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java @@ -0,0 +1,52 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.ui.nui.screens; + +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.terasology.math.geom.Vector2i; +import org.terasology.nui.Canvas; +import org.terasology.nui.UIWidget; +import org.terasology.nui.widgets.UIDropdown; +import org.terasology.nui.widgets.UIDropdownScrollable; +import org.terasology.nui.widgets.UIList; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public class MigTestScreen extends NUIScreenLayer { + @Override + public void initialise() { + List values = Arrays.asList("one", "two", "three", "12345678901234567890"); + String selectedValue = values.get(1); + + for (String id : new String[]{"dropdown1", "dropdown2", "dropdown3", "dropdown4"}) { + contents.find(id, UIDropdown.class).setOptions(values); + contents.find(id, UIDropdown.class).setSelection(selectedValue); + } + + for (String id : new String[]{"dropdownScrollable1", "dropdownScrollable2", "dropdownScrollable3", "dropdownScrollable4"}) { + contents.find(id, UIDropdownScrollable.class).setVisibleOptions(2); + contents.find(id, UIDropdownScrollable.class).setOptions(values); + contents.find(id, UIDropdownScrollable.class).setSelection(selectedValue); + } + + for (String id : new String[]{"list1", "list2", "list3", "list4"}) { + contents.find(id, UIList.class).setList(values); + } + } +} diff --git a/engine/src/main/resources/assets/skins/default.skin b/engine/src/main/resources/assets/skins/default.skin new file mode 100644 index 000000000..189d3cea0 --- /dev/null +++ b/engine/src/main/resources/assets/skins/default.skin @@ -0,0 +1,588 @@ +{ + "text-shadowed": true, + "font": "engine:main", + "elements": { + "UILabel": { + "text-align-vertical": "top", + "modes": { + "enabled": { + "text-color": "FFFFFFFF" + }, + "disabled": { + "text-color": "888888FF" + } + } + }, + "UITooltip": { + "background": "engine:area", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "align-horizontal": "left", + "align-vertical": "bottom", + "text-align-horizontal": "left" + }, + "UIText": { + "text-align-horizontal": "left", + "text-align-vertical": "top", + "hint-text-color": "C0C0C0FF", + "background": "engine:box", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "modes": { + "disabled": { + "text-color": "888888FF", + "background": "engine:boxDisabled" + } + } + }, + "ResettableUIText": { + "background": "engine:resetBox", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 29 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 31 + }, + "modes": { + "disabled": { + "text-color": "888888FF", + "background": "engine:resetBoxDisabled" + } + } + }, + "UIImage": { + "texture-scale-mode": "scale fit" + }, + "UIImageSlideshow": { + "texture-scale-mode": "scale fit" + }, + "RowLayout": { + }, + "UIBox": { + "background": "engine:area", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 12, + "bottom": 12, + "left": 12, + "right": 12 + } + }, + "UITabBox": { + "background": "engine:area", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 12, + "bottom": 12, + "left": 12, + "right": 12 + } + }, + "UILoadBar": { + "background": "engine:area", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "min-width": 256, + "max-width": 512, + "fixed-height": 20 + }, + "UIList": { + "parts": { + "item": { + "text-align-horizontal": "center", + "text-align-vertical": "middle", + "background": "button", + "background-border": { + "top": 2, + "bottom": 2, + "left": 2, + "right": 2 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 2, + "right": 2 + }, + "texture-scale-mode": "scale fit", + "modes": { + "hover": { + "background": "buttonOver" + }, + "active": { + "background": "buttonDown", + "text-color": "FFFF00FF" + }, + "disabled": { + "background": "button", + "text-color": "BBBBBBFF" + } + } + } + } + }, + "UIDropdown": { + "text-align-horizontal": "left", + "fixed-height": 32, + "parts": { + "base": { + "background": "dropdown", + "background-border": { + "top": 3, + "bottom": 3, + "left": 3, + "right": 29 + }, + "margin": { + "top": 3, + "bottom": 3, + "left": 5, + "right": 31 + }, + "modes": { + "active": { + "background": "dropdownActive" + }, + "disabled": { + "text-color": "888888FF", + "background": "dropdownDisabled" + } + } + }, + "list": { + "background": "dropdownList", + "background-border": { + "top": 0, + "bottom": 3, + "left": 3, + "right": 3 + }, + "margin": { + "top": 3, + "bottom": 3, + "left": 5, + "right": 5 + } + }, + "list-item": { + "margin": { + "top": 3, + "bottom": 3, + "left": 5, + "right": 5 + }, + "modes": { + "hover": { + "text-color": "FFFF00FF", + "background": "dropdownListItemActive" + } + } + } + } + }, + "UIDropdownScrollable": { + "text-align-horizontal": "left", + "fixed-height": 32, + "parts": { + "base": { + "background": "dropdown", + "background-border": { + "top": 3, + "bottom": 3, + "left": 3, + "right": 29 + }, + "margin": { + "top": 3, + "bottom": 3, + "left": 5, + "right": 31 + }, + "modes": { + "active": { + "background": "dropdownActive" + }, + "disabled": { + "text-color": "888888FF", + "background": "dropdownDisabled" + } + } + }, + "list": { + "background": "dropdownList", + "background-border": { + "top": 0, + "bottom": 3, + "left": 3, + "right": 3 + }, + "margin": { + "top": 3, + "bottom": 3, + "left": 5, + "right": 5 + } + }, + "list-item": { + "margin": { + "top": 3, + "bottom": 3, + "left": 5, + "right": 5 + }, + "modes": { + "hover": { + "text-color": "FFFF00FF", + "background": "dropdownListItemActive" + } + } + } + } + }, + "UIButton": { + "text-align-horizontal": "center", + "text-align-vertical": "middle", + "background": "button", + "background-border": { + "top": 2, + "bottom": 2, + "left": 2, + "right": 2 + }, + "margin": { + "top": 2, + "bottom": 2, + "left": 10, + "right": 10 + }, + "texture-scale-mode": "scale fit", + "modes": { + "hover": { + "background": "buttonOver" + }, + "down": { + "background": "buttonDown", + "text-color": "FFFF00FF" + }, + "disabled": { + "background": "button", + "text-color": "BBBBBBFF" + } + } + }, + "UIInputBind": { + "text-align-horizontal": "center", + "text-align-vertical": "middle", + "background": "button", + "background-border": { + "top": 2, + "bottom": 2, + "left": 2, + "right": 2 + }, + "texture-scale-mode": "scale fit", + "modes": { + "hover": { + "background": "buttonOver" + }, + "active": { + "background": "buttonDown", + "text-color": "FFFF00FF" + } + } + }, + "UICheckbox": { + "background": "engine:checkbox", + "fixed-width": 24, + "fixed-height": 24, + "align-horizontal": "left", + "modes": { + "hover": { + "background": "engine:checkboxHover" + }, + "active": { + "background": "engine:checkboxChecked" + }, + "hover-active": { + "background": "engine:checkboxCheckedHover" + }, + "disabled": { + "background": "engine:checkboxDisabled" + }, + "disabled-active": { + "background": "engine:checkboxCheckedDisabled" + } + } + }, + "ScrollableArea": { + "background": "engine:box", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + } + }, + "ColumnLayout": { + "align-vertical": "TOP" + }, + "UIScrollbar": { + "parts": { + "sliderVertical": { + "background": "engine:sliderTrack", + "fixed-width": 8, + "background-border": { + "top": 3, + "bottom": 3, + "left": 0, + "right": 0 + } + }, + "sliderHorizontal": { + "background": "engine:sliderTrack", + "fixed-height": 8, + "background-border": { + "top": 0, + "bottom": 0, + "left": 3, + "right": 3 + } + }, + "handle": { + "background": "engine:handle", + "fixed-width": 16, + "fixed-height": 16 + } + } + }, + "UISlider": { + "text-align-horizontal": "center", + "text-align-vertical": "middle", + "fixed-height": 32, + "parts": { + "slider": { + "background": "engine:sliderTrack", + "fixed-height": 8, + "min-width": 8, + "background-border": { + "top": 0, + "bottom": 0, + "left": 3, + "right": 3 + } + }, + "ticker": { + "background": "engine:box", + "fixed-height": 32, + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 5, + "right": 5 + }, + "modes": { + "active": { + "background": "engine:boxActive" + }, + "disabled": { + "text-color": "888888FF", + "background": "engine:boxDisabled" + } + } + } + } + }, + "UIDoubleSlider": { + "text-align-horizontal": "center", + "text-align-vertical": "middle", + "fixed-height": 32, + "parts": { + "slider": { + "background": "engine:sliderTrack", + "fixed-height": 8, + "min-width": 8, + "background-border": { + "top": 0, + "bottom": 0, + "left": 3, + "right": 3 + } + }, + "tickerLeft": { + "background": "engine:box", + "fixed-height": 32, + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 5, + "right": 5 + }, + "modes": { + "active": { + "background": "engine:boxActive" + }, + "disabled": { + "text-color": "888888FF", + "background": "engine:boxDisabled" + } + } + }, + "tickerRight": { + "background": "engine:box", + "fixed-height": 32, + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 5, + "right": 5 + }, + "modes": { + "active": { + "background": "engine:boxActive" + }, + "enabled": { + "text-color": "FFFFFFFF" + }, + "disabled": { + "text-color": "888888FF", + "background": "engine:boxDisabled" + } + } + } + } + }, + "UITreeView": { + "parts": { + "expand-button": { + "background": "button", + "background-border": { + "top": 2, + "bottom": 2, + "left": 2, + "right": 2 + }, + "texture-scale-mode": "scale fit", + "modes": { + "contract": { + "background": "contract" + }, + "contract-hover": { + "background": "contractOver" + }, + "expand": { + "background": "expand" + }, + "expand-hover": { + "background": "expandOver" + } + } + }, + "tree-node": { + "text-align-horizontal": "left", + "text-align-vertical": "middle", + "background": "button", + "background-border": { + "top": 2, + "bottom": 2, + "left": 2, + "right": 2 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 2, + "right": 2 + }, + "texture-scale-mode": "scale fit", + "modes": { + "hover": { + "background": "buttonOver" + }, + "active": { + "background": "buttonDown", + "text-color": "FFFF00FF" + }, + "disabled": { + "background": "button", + "text-color": "888888FF" + }, + "hover-disabled": { + "background": "buttonOver", + "text-color": "888888FF" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/engine/src/main/resources/assets/skins/migTestSkin.skin b/engine/src/main/resources/assets/skins/migTestSkin.skin new file mode 100644 index 000000000..a74fc705e --- /dev/null +++ b/engine/src/main/resources/assets/skins/migTestSkin.skin @@ -0,0 +1,129 @@ +{ + "inherit": "engine:default", + "elements": { + "UIButton": { + "modes": { + "disabled": { + "text-color": "AAAAAAFF" + } + } + }, + "UIButtonWebBrowser": { + "text-color": "8B85FFFF" + } + }, + "families": { + "menu-options": { + "elements": { + "UIButton": { + "min-width": 192, + "min-height": 32 + } + } + }, + "option-grid": { + "elements": { + "UILabel": { + "text-align-vertical": "middle", + "text-align-horizontal": "right" + } + } + }, + "title": { + "font": "main", + "text-color": "F0F0F0FF" + }, + "subtitle": { + "font": "main", + "text-color": "F0F0F0FF" + }, + "error": { + "text-color": "FF4444FF" + }, + "warning": { + "text-color": "FF4500FF" + }, + "highlight": { + "text-color": "FFFF00FF", + "font": "main" + }, + "subheading": { + "font": "main", + "text-align-horizontal": "left", + "margin": { + "bottom": 4, + "left": 4 + } + }, + "left-label": { + "elements": { + "UILabel": { + "text-align-vertical": "bottom", + "text-align-horizontal": "left" + } + } + }, + "module-list": { + "elements": { + "UIList": { + "parts": { + "item": { + "modes": { + "gameplay": { + "text-color": "8B85FFFF" + }, + "enabled": { + "text-color": "00FF00FF" + }, + "dependency": { + "text-color": "FFFF00FF" + }, + "available": { + "text-color": "FFFFFFFF" + }, + "disabled": { + "text-color": "AAAAAAFF" + }, + "invalid": { + "text-color": "FF0000FF" + }, + "latest": { + "text-color": "FFFF00FF" + }, + "strict": { + "text-color": "FFFFFFFF" + } + } + } + } + } + } + }, + "biome-list": { + "elements": { + "UIList": { + "parts": { + "item": { + "modes": { + "internal": { + "text-color": "FFFFFFFF" + }, + "external": { + "text-color": "8B85FFFF" + } + } + } + } + } + } + }, + "description": { + "elements": { + "UILabel": { + "text-align-vertical": "top", + "text-align-horizontal": "left" + } + } + } + } +} diff --git a/engine/src/main/resources/assets/textures/ui/nui/area.png b/engine/src/main/resources/assets/textures/ui/nui/area.png new file mode 100644 index 0000000000000000000000000000000000000000..6809968f86b0c81ee47bacd622a9403d3083c60b GIT binary patch literal 415 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrU`+FLaSW-L^Y+R{!Da^@2FHYb z>Zb}$9tlZxR}o2I-7f7pvq}2x?XQ1xQe-c)8+bDmzTSFYIs8NZbK@Tjg-jj74s#eD zu?VO)STG*pRPY-WLWIQYt@D+`4UVw`!{`qGp<65-8$2AdfdS9p>FVdQ&MBb@01uIP AIsgCw literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/box.png b/engine/src/main/resources/assets/textures/ui/nui/box.png new file mode 100644 index 0000000000000000000000000000000000000000..83885716b9b316f408598ffb83de84e6b66e5110 GIT binary patch literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz7f%<*kcif|*EjMqDDW^JFVdQ&MBb@06QoqfdBvi literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/boxActive.png b/engine/src/main/resources/assets/textures/ui/nui/boxActive.png new file mode 100644 index 0000000000000000000000000000000000000000..7e7fc0e9b3277e99c50426f35e0a9a9081950c9a GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzPfr)ekcif|*EjMqDDW^JWZx*9 zoN}$_pv#t!H4GkmR+rcUyGp<}rA>`njxgN@xNA7;Phw literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/button.png b/engine/src/main/resources/assets/textures/ui/nui/button.png new file mode 100644 index 0000000000000000000000000000000000000000..38dd795ffaa6be1be418dd9d93d74bfbcf5cd5b3 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}DLQae0d978JRyuGBz$e_S*z+eI2 zU(<^UY>%Rwy3ZHBlS^59pYcy>g9Y;uNriI^g=`(h4s#eE@d%_3u+SamsZ*FTHwC_T Q1p0x&)78&qol`;+01+%qRsaA1 literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/buttonDown.png b/engine/src/main/resources/assets/textures/ui/nui/buttonDown.png new file mode 100644 index 0000000000000000000000000000000000000000..5bd1bc55c07887ec3b763f5181f0cc54a036e7eb GIT binary patch literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}DLQrkUU978JRyuIYe$RNOQz(GXZ z*CeUpjov}I*^lqoo`~Ad{Npr3AzO#B!yLv(JOb$r7R*N^70wN?&<^(1yO{P`Iwmm! Py};n<>gTe~DWM4f8=Fdr literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/buttonOver.png b/engine/src/main/resources/assets/textures/ui/nui/buttonOver.png new file mode 100644 index 0000000000000000000000000000000000000000..a4824e7a74e62cdd1d1cef57850074df5a688fa8 GIT binary patch literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}DLQrkUU978JRyuIYe$RNOQz(M75 zj7d_(8@+>avmf8FJrT8^`NwI7LbeWLhdGRocm&cLESQf-Dx4c&p&jhfs!Vl0?g#Gy Py};n<>gTe~DWM4fvkXgB literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkbox.png b/engine/src/main/resources/assets/textures/ui/nui/checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..2df2117bdf07c199fc1b8828ad0cf066ed20ced2 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzZ%-G;kcif|*B1&hCS`!`O`bU1ppE8q476>gTe~DWM4f3{NKd literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxChecked.png b/engine/src/main/resources/assets/textures/ui/nui/checkboxChecked.png new file mode 100644 index 0000000000000000000000000000000000000000..da7a961f09d737cf50b17b0d9bdebd0a7768f450 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJ*`6+rArY-_ukYk-Fc5ILXecQ< zQFm*#v6hmmgACI{W;W@CbJ_lR>#UXC)~m5wj3H*}kFJ8pZwBhJbl=!Ie zfa_qFI%6M4n#>IUO;5TzWZrLLd~(w>je%K$;efl{^3$to&Z~c)5UjcQ;QCiUXEJ!Y L`njxgN@xNA&e2Xn literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedDisabled.png b/engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedDisabled.png new file mode 100644 index 0000000000000000000000000000000000000000..eb28715ab7ef60bc0834cc603a03f444b5be824a GIT binary patch literal 228 zcmVlVn##~kOyK_oNcL(1Bzy1uLq#A3UQ8erUPK@VE-sJ@7Ztbz7ZbP(KNYz8zY_3} z>DA%0BJ)ccDD?y6m eS`!`O`bU1ppE8q476>gTe~DWM4f3{NKd literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxHover.png b/engine/src/main/resources/assets/textures/ui/nui/checkboxHover.png new file mode 100644 index 0000000000000000000000000000000000000000..cdb1bde46c3eae0ff4270248724898023f9da606 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJKu;IPkcif|*B3H27znT&tPKeg zys)1mL_|d^;ez~;JZAH6P22tQL>1I}?K>nM|K1ii^YmK_?gNu7e@$gzWMbhEP;h7f iGkzSkl=a>D-2CP*PUHV3FJ*y-GkCiCxvX0rUkk)Yy)>Ukz0Rz-E1a-2Ywhx&QkR>UM%O2u`_2Jn!|Cd zho9|2kEURctUS*G&19t+Ms^Yo#d59&r8Nc(YInO5&H*)?-Q`m7^Q@$Njqr^vI~T`) mWA<8bzx*K3`wX70elF{r5}E**JATx3pI!KR z*V*;g&scu%f4+xV=gQ{9sa+ipuU7FT94tCl>%wz?ji8{j*UL|@b}>inm~v^UNt6F! zcJ_eQNgT&`&Z0rfwtGPeNTRg+LD>`@`9G=~ zvX(mUe=h4Vhgsk`!x2k{LOzE(T>oXX&RT=q^o}c9-S(mcyPqF0P#8R2{an^LB{Ts5 D1Acwt literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdownDisabled.png b/engine/src/main/resources/assets/textures/ui/nui/dropdownDisabled.png new file mode 100644 index 0000000000000000000000000000000000000000..79903b7b16044e172a9743fad8434d3021d500aa GIT binary patch literal 315 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfcNCx;TbZ%z1lzZ&r(gMC-%y z!|h+oR)+0aqxtO99s|SBUAk*krfz8Yd+{cV?77MVZmzBGOSujT8zgM9`&P$rdph%l zubcwgt9Pxle*amA&4B0d*4*2t>+h$_9M^v!y@%;UF~cL71`BqDbBrBG%!fNu;3l<>JS&7{&mk8_;jAzxF7j)&QvMMOVhN!&$^-6Thnx@;2tSE ziw3PJE*sK*JYZP0QMGC7VRrU_siuNCl0b=9Hr)xYKOAHXc^Su|3X)i>+LWp-Y4^iB v;i^}A-Dz!PSL_h}XBjdpoS~4<;SRqSuSK$?10ORmP#8R2{an^LB{Ts5khXt` literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdownList.png b/engine/src/main/resources/assets/textures/ui/nui/dropdownList.png new file mode 100644 index 0000000000000000000000000000000000000000..fab68f850580292d291a9545b9fdac8ef86b8c79 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW&!sYXv1$B>FSZ?70~wKxbc91Q(4 zr{C1-IKwm6q-^Ud*K760ey;U8=nk8mpZF%&X&2s_MSc*G*0 r-e5tJ(CPElwRa!o|6~N}EoYo{jrrSRH*FSZ!Z}#GAQsIFmSNA z*3Q$X##L2v{!DDj-204wQX4Fok4P$@7GFmV6? literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/handle.png b/engine/src/main/resources/assets/textures/ui/nui/handle.png new file mode 100644 index 0000000000000000000000000000000000000000..58883209fce8550725a16f62e224b65d2b8fe03a GIT binary patch literal 1660 zcmV-?27~#DP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1Y?mK-Mx{Ld+J1SAlkGb2N^+F1^IK+y+KK%Og=V!>n1Nu$*2TI$2Q2p$^FddFVA0N^u zhRU=3;W){+@$gFN;q66pDNoHG#>a^HgUt`t{J-~Xd#}qn%LOKv+o*>rr-ymny>(U< zl#0K^=Faw_C=Dqw5JwY1)=>s2F=*VBX_C>Vb=pA#5Hl~XXqg8H9RY(4WGIhAclJV? zD~O+|f#QL1NEqcO7CLJ6s2kLvcv1_99)d8BmES7iE0gy2gd&RV@>4tfvS%7lICDfH z5~hIz+P72XIQUUMKhA3cXL8)!V4%hB5?;6-7R3 zQ&lr4HAptBHcT+<+*8k8dg-;duH6QQkwzXe%BZ6a9X5HUi9DWV*4d^`TeJ{LD=%4P z)zy|R+X%ItcHXkfuDfjw+n%h^owlFL8?4dI8Xu;7VtulP(OMrO$hQ-5&cGOF0^!ve zpcI&$v)CwScIKS3sEn)-21s#oCOKnZFfU@+^yKava}rYdGrR>5!GD6e;M9GAx$k-V z5o^=VL6;6go`&w!n2>##Zrp4EZA@719joHUp8^h}2TzDJ3j!fFVMket*{qXACg7vr zXHCGx0zQr$?nbs?98M#04amaCGXq*MmxLkwe$tvw8E_JmrYvcxWZNDlgBZA>yh`{EJfDjnh)st2Z>Ni@qEr}oqh&|BR=?qcrH*6b6|JX?4EoBfSMpzt$nB;4MVcFE|^5d~0w)?CIK$ zy|^B~;UPuxMy%8=H2p$>)30JL#Wlha4J5G#gFs#Xf}^ge_N|UPoPOyDt_-^j{Iw7s z*c>2iXOA*y=Q;h%^*O!146-}M_X5bVc{BvAM z000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004-NklK?|4Zr~F*s0#?QV9zi+{d2I) zSOz0&djeHb&`rIney?8BcDuz8&N<7>KXT3>qVYWE{4igN$lY+KHk%Ecb7$7tcg*}1 z0II5jF=ouO*$l=QFf($_Z`SMeFKg}h{eIu7-EQ|Dz-z7bhxvSt#bSY~s-TntGlQ8y zL?9w)tznEo2;pVUxv|#%)BxTpr7r5a{%h>VV!2$RX_~7TV`Qb&#cH*Baxnl95$d{z z*7};Y)+mYLd7M&0Y2=*2gG9vur4tOh!lm5@()kqj{{>P!!2>mT8V98$644(Sr%1_z zQ6_N^V=M;%FbyE31f^8Dp@;~jN~DyI023|E(^M$!KI{+27>iXPq9Z`53gaF;iyOx; zjfikK98N9_Ashj^t~)=KNFqYt_vrin3ya9T_x`-=x+mMZZCiv8K8naI1^^Mc40PY~CWzb##(dCjH-_%xd zUdGp_#-?f|Cn-cR29>0h;%zNY|&nCJNltcN9Ks~!a~#@-UdITnHgJKomYl!Mzg0ZV3Mk1vohrphMDIKzc5LJ%BFNJ-|}KCu{=Q z1N6pP&@E$Q3eX9;f4Niw3eW+iTf9U93SgYt`+Kbf6u>aj315u_6u>Agk+zz}tP9@^BD$nI06Crkz(ach eL=V;Q0pJPT3dZ1p{*sgc000060ZNR__yPR&T1-;T4u?&_9xB8L97Zqv)JnJ(GMG zx21vpf!zn+?`tY!2tOjBZ+PtV;;j3-^cZC}>YSF&X}@}UZ0irvPezYGy8t{ zBp@rrFVdQ&MBb@0P%&J^Z)<= literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/sliderTrack.png b/engine/src/main/resources/assets/textures/ui/nui/sliderTrack.png new file mode 100644 index 0000000000000000000000000000000000000000..54862a3a0671a3587f74aaa63310544d85f11c9b GIT binary patch literal 1298 zcmV+t1?~EYP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+U=HGjw~k(hTmC5mVj-H&2lI%Qg)E#=ZB(tE@w2F zDCZ?oifN#YF~*-=Jz@Oy=L~<~Ax<8Wn&*;p#FI)YTru%@KXvyM)9&~4EaCeHdEjS( zArg#oHsm88kVA=%qPJtGLay%&m2noXj|=q}Vm}8Q`E!uaeLy^hLp_Fs&&lcje%;rK zxwyT*LOc5Ntna(x6IPeRIBORT{il)iQP*jX}=8^Sd01m+eg)<}|5HpEV zrfAH;h!98zpbFPn5?{bVs@&luCy@*|r~;ggJw{uVm2WX#gaDzEgBaMLGyy9mMgCZF zU5nN%c~w}>me(7#npiTmY-Vo7YH;!7>e|%!^rc zN{JV_#Vi&^RVc$rU2r-rVj!3Xu}*ridn2bo^6%jm0D^x9xvX18%J`kAuK)l524YJ`L;&dk z=m67XtQ@BR000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jdJC3=$_Q*R}ir000?u zMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004PNklF~g^W#}k1 zX=mr-8gBR4!6VC_u@`uSJCXZ<2gR#xMGG+ z&bQP0^iLoBeckMO;r|6z?dfl`iT~bdFUP=`5h6f{0HIBO0mx)LrxUR^DF6Tf07*qo IM6N<$f;~J|>;M1& literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/LICENSE_NOTES b/engine/src/main/resources/assets/textures/ui/nui/terasology/LICENSE_NOTES new file mode 100644 index 000000000..db8f8f6ff --- /dev/null +++ b/engine/src/main/resources/assets/textures/ui/nui/terasology/LICENSE_NOTES @@ -0,0 +1,45 @@ +The icons in this folder are not under the same license like the source code. See /docs/Credits.md for more information. + +---Image info from Terasology's docs/Credits.md--- +Icons: +Some NUI editor icons belong to "Fugue Icons" by Yusuke Kamiyamane, licensed under the Creative Commons Attribution 3.0 License: + editor_array.png + editor_attribute.png + editor_object.png + editor_uibox.png + editor_uibutton.png + editor_uicheckbox.png + editor_uidoubleslider.png + editor_uidropdown.png + editor_uidropdownscrollable.png + editor_uiimage.png + editor_uilabel.png + editor_uilist.png + editor_uiloadbar.png + editor_uiscrollbar.png + editor_uislider.png + editor_uitext.png + editor_uitextentry.png + editor_uitooltip.png + editor_uitreeview.png + editor_zoomablelayout.png + +Some icons have been made by Florian Köberle and are licensed under the Creative Commons Attribution 4.0 License: + editor_cardLayout.png + editor_columnlayout.png + editor_flowlayout.png + editor_miglayout.png + editor_relativelayout.png + editor_rowlayout.png + editor_uispace.png + contract.png + contractOver.png + expand.png + expandOver.png + +Icons prepared by kartikey0303 (also CC BY 4.0) + checkboxChecked.png + checkboxCheckedDisabled.png + checkboxCheckedHover.png + +-- NOTE: Only the items in the "terasology" folder are covered by this license. Any other images may be covered by other licenses. \ No newline at end of file diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnit.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnit.png new file mode 100644 index 0000000000000000000000000000000000000000..c27c56e592d61a008f257471b5d1ac19ac007d46 GIT binary patch literal 4250 zcmV;L5M}R)P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000HWNklH-Del4ks5(&owxu)bEJ_ z61ER|4IE)$34mX;r%k^KNDPK~o?q9XwSHX}HxMRn=KDpXriam9!}PN-&{-k`ffEE1 zC*wo&z44q3KhruW5Ht}urNLC&cv>N?8lM8f+RqQ42p$A3ZDE4(bwJ=UA51mOKkDX0t!nt zw$xGlqx#!Vfz-JG5?~k@3|at`1_0B4hoWsj1kX!WnEv~p1CH7NS^!$WtKt#=9g7|c z(T80t#Qzv=Aa*E(7JwG;EyVv=ZNNX`UWGjY@jq4@Knp+%fB*ml03ZMW0RRX9K;54O zP)R{<0pkpye_8wa;U7kg1Q=NUFbDu(27mwn1OOla0096906^mb5WH_38VmqQ4+mmj zhYqzbe+o#BgC$zPurOH601yBG09XP50096906=2{;17dv7BI{iz%Kynx=Jk3SZ4sn z7>O1DZ2>?V7%Toa0Qg9N`j3Cw^3ej&0=A;JhS3K4h<_nO^x+>N0GnIGP#^N&`|xuI zP#z`#Gdlk_`hFbA~1{qynfoRirJ01e&(a46JA^`{>Fw+p~t zR6s4mV56QMwg99+-_?Hz03`+oLv5L#Tm4x>Al(r_ZRpHne-8ohZ|I z0q8G43baxEx#pib2f#qs&)|0&0Bj5U+4fyd0Hi>F)qe_ra3BN(Jk38-{ihRv3cCWH zd;Vex5T*cj1w8lsXXmxk34m76NA$nd0suiD=D#%q0D|_-e+vLWP|y4;`~4ySU}sQg z;=l9z9p45Z+!_3yMFWDn&A&7HZ%u$b2+$7rn}2Hy2qC~sa9__aWxfzXOn1Iu=bV&M zI<2)Z#%yK+d=<@m(|!r_ZwG)vV6F9^MBPLgK)4q9G-dBpkhN&TK!l~cq0HGF-2v7S@@03anxQ0a?G z!my_tK=urd{jQkl^tCcw%fAbox?rx-TDxt9$3LfV=COAtl w>ry{+<{DF;M1&07*qoM6N<$fYvMhiyt$W@}(NYP7#7*R7y5H*Ni zCW#gVFG@(1d93%|dOyy$*E;*`bJp3v&X;h*RF97OGBp5z&Ol$=;v8`o0jE5FyVM;A z&VkBL-{w95G|U$P0lE1c08pEGpinn%xcdh9-go!)Ll~e?2)}#2ZXRB)00hkzSYpwZ z>uhR=i~Cwe@wjv&Ukg?^!a^$%$C4^2%1gy)7|;8BhSj`-Nk<3D)mIcxo|J@p!fGx? z`PKJ%IBllBthqdnwp@#c=}S~^ zchA>l31lQSzaL1R!-GxPoj!OHc#_4g=0kOW=k$a1e@E9S69AqnuC(uuJDi}yhz~W}qtpujUfs_HpO&`=Y0>UsOO&x&K0x9$O7!d#s1rB|D zd_f>O2e9bwVpM-#t6^LdJ$EXnPPK_&Nhi_{F76M*U?g~ihYi@Tu_!o_Ip!iII)igK zWg_JmzU&PGP?XAgzU|&=&@g??@UTJ>p59)3<2@zms*}^w*~&(}vwzc8>j+urq9@ zJpps-^*dbkqsDJN8?nlNC4p644(P}a7UY80^MJ)(F+GayC_n$R+DSLgF}o! zd8LD5zJun(K_Oa;zq?b5QH$CIcjcagNYx`P;n<;CZczux&q!`Lg1LKanjgJHr`0=p zH9v+wj_|?`;nqkhsAeCW*^zfP9^&-anlA~?o)dG#+o2D=l*o_x7|&vU)hJb7U)tg^ z8eyf+y{mSQOeyY`ZgZ+iACP%;65FaLogP_duJ)O>0o7EdcsW}41D|{qE*) zl97(H))(WOyp+r=$ru`s>Q>~xlz@^EYDyt9c=HN9c4xjGi~hTYoGXkgax0Xs*)p0|FLNyx z%ATW{w4d_zLW0<($dAUM)k&Hg*o#$U>sP^K#teh#wDENiJZM?DMjhc?6n+*9A7JIQM~9w z*3^FL48sh;3@%Ygba_Qd#bO1G)t=P=I=TFgWmt`_m8|7bIo0RPN~?;38=IC~me_KY zvbYLtnJ-%7Rk+P*0;NrtahDnDm3h${`=!<%1dTIieUKQhCtYRi-;wg&f^UXq9zGCl z$v)+7NmQ#Sf3Ad*HI&8FTkNH~X~34U{g3hkOsUp{OSAUEA1|`(h

_Dv>j8l6Jl2 zS&^BQX2`Ku`yE`Nv2W>OaNF9SD`AqS=u_`Mr3ZSn)|BDV2@Wi9%))N1ccaL|^OF>FOUO^+1 z4U_F$3zMc2krEYS731Ea!J!vJlR5HvYSL3OYk6yVQ+dQj2iqW9F?<>RovT6JvTcdY zHony-##YIu*xJhWcD-(OLAAhSOLa>rQ)!cFnrUU>B(|&eC;lV8ypgkZWtwuX2Jejz zbHqBaV;euzbZw`#rG+(z{d1}Yql=rNujIDn4!{5Q9*go#<;C3L{B4b}5Br(xl342z z#*t~+B|P(hNVi9UW!|_RmL1!4KWZ;NF~R83fJBzML>^bqLSNgmVZed^?XMwY2L*Zc zd7WEjbFa4*wmr7v=ARA9JrgOkk-h(^s}J?Xd}UOF=2?c6C$TEr3}qIHZCK-zbe2rT zR8Q4576(=wI_|Km|5CsAY)O4dRdG>f(Z+sIk`f;p}_CU%9>3dO|5U}80r{Nk-Ik4k6B2ae98?i02DXlH6K=3%AHlwOM) z%8RO3NZeJORcw}P*65LNvl*PQF0eN6GP~1vhTKE z@blr${g_g=a*0b~%9%*xc+>0Y|I%a>En|Bku*)1MkVGBa$=!*)Dmkh!8b6J?CCX#E zt1oI2^7Kb)t9&s32ian=m8NK+@|0F%I^%^rr&^XuTSyCu|^niZtK;ys=G>cs{X-q)Jv=s*J5u{R;j*wj2HEu zFst0cWYvVX35J+>M&9Y@f7H@w{*mtZ?_J9 z>C8!H4GGV+MB!0QFW;-aYjrLCI6S1HfqsSFNB==9Y>zE8I8Gh;jBayut$z$*pO+<=M0y($)~_cDT+}s5rc^-xmCnjWjt?sHC>gwin`i_~Gz?$hHuEPv~@b zpk*ddXuG=Atkr%WxurRST8Nv_usfTd-kFcMO9(958=coXq>PCgIZHiAWrrqmXI)_Ytkcz5B%Wvy;Mmf{i9dU)m@l04)L(k)}Oy5Dp|jlHN=Kaw*)!x_}YD0Y4Ym z0d`CW?&i@Mpo|IscEN&hKXny2}Q>Gk493sQUNwpAUZRJA@PL=*VpL3pH0}heg<0D{K z6^Kbi{L%0NjDr%S^lJcmf1r`PPYKi#2G=zv03sW6wvGXCw+xbq3V^SslRS(N@YQ?| zljE2S4d}V*dROil==Y@u@Q`OSTi27a)U$W^H{`_{P9YgYTEMukoR(z|sfoVR<);M7 z5dm);lu~|Ry`6DTu7K!P0WgRB?$tO6jA4$Q4GLs95v1|Fvo6^us@U~`%^*;Na~v1S tv;z4Q`eS-y!eDvl=smb_P9cI4D15xr9MJdA{<#~#K*vN2bPDNB8 zb~7$DE-^7j^FlWO01Z+}L_t(oM}1d`SDM!nw|(tPU-val)9h)sCeg%bq6jW1DuRl; z0wO9RsDQX8X^hdVZPKi5(dZi4j4VNDgxCl5$4m=^(!m67a_}j6a`c-2Ye9U(Yii zKF@4h$9nQYbo+l|x?YOWy&T)~N?hNoaRaZ%555s^cr#)6ZI0>fMDsg|qwgk-Z%DRo zOt!tBV&9Z9y*b6PmG9cdpWU81zcX#&gY?B+>E7LfmAx6O`#=H*4VY5rcBIa3=g(|Q zacn`m?3=i@jmZ=5LA1oNcR3^L6O3=eDG7!*+4?u)23~{HW4m98)x8|k`66V+di(S_f)-&|OpWU1Kwnrsl5+NfBy^ zU_?s{Y@)b-2|gIuL=a>hIdjk4a&NTt-dO8BOY1k|XTO;^_btGB{#)CH?arVlObD#d?{`9B$t3NMX``L5tm&NP9cyIi&bmQ0M zo4>By{B`vf!pbeQT)GMRU%c0UUc3&T;19cCFGN6bTvvXWxr`z^K891!SyRNhlNY|T zT|k*kocm_{+&7l9_W+RRXv^2;7RdZ-(-~BPuSI0BxJH^>WA%Y*8eLDhp|%^FgRUCX zR}HF92US-AKnzHdKuW^u1L=%0NPyzR78Hlvt0qkb)wN;G)nUywqvo2a`r3&0`e+S; zrS^uU?&bub{xfUiEnDL)`|;1Fj(k9OUjYk~+6 z2cn^vj*mW{J^`oPvNztEY`kS{xCt1qgG{cE)uOD-H8)0TP@YDV^VK1;3S1f{i2Fca zLUU00z78NIxdjEGlmRlRsW=RU_+y`qF$A+A>>t z$)&t7gW_Cpl%JoH1I|sBowt>pvzE5PiI$SqF=?y0xW!y_#w0moEJV3Mh6WL23pqFS zLq$XrNQo*Ui|R%F0gxJ>)n7HG|7RbNL6x0xfT}Jw1+?rWB*7^{Edw-9OFF6SWUF-X zs_q0;Z-Tmyqv=o5=#w>r$r=M!JIvFX_%$Q^8Z*CkG_BT>RyQuFw`SJaG8*ie4fd=? zN6v9aZsSbu30MA!xxABZ;mHNzNss8%Vqw!#;i=`qrd3JPsAgW@N_qV|J@ogre~p~CJ%lAh3_{v*GqvlWhbDJm~dwZv1e zq!Qo*M;cE`<$O|wJF#*$QRzxlIup?L>A3PqHbj$KW6CC2G7D2S#*~>Ea3Y*rJanvh z@TgROR5}n=)OQ4OlXQm`>O#aF!Q%E{5o8Xv_}W4g2z8Oop-jGZ(WQS$>>_~NFwhbQ z3`%*h9)s(X$q(K^n){?4gZtne?63y+ea`;v?{M!U4up!p`+Ebw?LGeEjl3rtQ`C9QK)YWw>&rpteed6eb zB+Glr6C1gc#4~hi3(vU)9+!N0Wx99ZXQ*Ilw_tfs#_C>>_!*kEuoJBCROP$2@*G=J zrZ#io8ESnWJwq)UlHeI?Ue7VU9Y6dQJbBsr*V+BA!|9MiY!~$mUB`N~4xY=52jnv} z^7m(OA^zHF-N5Bz6ZWAvrJ+25P@SQyLA?9#@gE=n;St2oeI`;#0CAru+DmQ6OB%=i z$n)XG)JN~9J>HbwzD3ZnRnWOj(7ipQXGdn=&dh-ivIcf#8}{T3?aejq%N^ODXWpMT zcA#K9xL_irz;;MzKP;RI6*Q59FHn=Z<`sW89ZLvm*R?ONdtZLfhXs8Hg#8DE z`e2bEL^KRIEH;G}n!_Yx;Sx)D(Zo@yH9~5SD7G_7rlU%n%u*Mt)D>Me7gIJLC-<=B zi|q2Hc*P1wvC2^_CzN~RK_mCXfmJpaBXdQU&ajG|%;M=Nh)_HkA+;VW8b1ob3rE8X zM~;Y%p`zhKqM;DcV2DtEu%Q27LGOOZDqpuRw`*Tc$DW+_-H>zkBY&}LY9};nY9y3o z$1wL1ieqR0lHft&HkdOAKq%lP*3+#49FqWGAG&AZlaRuWLz2$JMY_-;n83YZ(*E$` zfn&w`W2J_O(jgdzQ8H6hnVDHO8ZEcPluyK#TVoZrI2gjpsRX4Xp<*Vnawe&AHd*E7 zs^+;cY}H=A+MB9bPODx`(=4X~S1O5}QBPP=_mQHmP{1j;>NQd@gvW^H@S7e!vA@5*%K3Vn>i5ThK5 zQySSyQ+(w}Lggr@YAjJTo}{uStE^nLovX3)G}HWQCtvGK)6S;X%n54T8MO#>wu-3Q*+PQSCD^2T6g}v3&e2qOtJ;{ZbD6%E7YK#MC zRg5H5nApnUIFy4S7V?n~M9ceFkfFRMs;rA4>xzKPA%Cizz|v^^X@>w#Y3KwHRNldq zcQDJ_2}uz`k{U`$0FyOVUj)CN=8w?DQs|lwSa$hbEUqh`^0l@7st8LKl;~fSy<=ucF_70q72li7HdF#>^!yAO$X< z8ZN*F7m!vvg)X4hnSn2$-gf~Fo;+x`{{mKo=mHk=8)z3$H=9)l7vNlT0a~~Kh(Crd z08WI9_gz3jr9K|Ag51yr^u(ZSyQ0g93!s;SD literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.png new file mode 100644 index 0000000000000000000000000000000000000000..af56733270755cc03fcabade47658ec33867cc78 GIT binary patch literal 643 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucL8%hgh?3y^w370~qEv=}#LT=BJwMkFg)(D3 zQ$0gN_s>q|Kx037x;TbZ#J!!Z7<4#5#8p{)q7GxHi_&fumD2}Q`EI6`NS@GRY+k=+ z&7VEfA5`{#hN=xmQI=d`uD#~iMHUF%s1yAe%tkJZzD&I%ZFXR z4qkg_Y*Sv()?vOc?BKNb)@~IMY%}UUFXg{;$X8kBIHS|Pe`ovUe^);g%a>Zv@;mzP z3;q8e-nB;WxoQ3`h&^K8!GM=_r|kA!S-t-5%)F9+C5wys z91=Wq%My28v}9K>SR%ID;O>h#%mNZY-LW(BO3pEI@T@$l=VNa5oPnk7N|N|8>AA%W zOwL&wxi9ygvt(#g99qW7J}_c-*1i8GdcB?5_k9l;`5v>Y#L1XjIMh~^nDYtf%RQEU z{<2s1j_I8FtAATCxMh4?`SI)3`+rWq*~?=Pzvt#B;V11MqUXuzFD==B=r~{gpTn11 QfN6xm)78&qol`;+0P(O93IG5A literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.texinfo b/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.texinfo new file mode 100644 index 000000000..15f1ede8c --- /dev/null +++ b/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.texinfo @@ -0,0 +1,3 @@ +{ + "filterMode" : "Linear" +} diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.png new file mode 100644 index 0000000000000000000000000000000000000000..24d6fac8fd7d87b86ebdea59dc79cc4f3dbb7f86 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Ea{HEjtmSN`?>!lvI6;>1s;*b z3=DjSK$uZf!>a)(C{^MbQ4*Y=R#Ki=l*$m0n3-3i=jR%tP-d)Ws%L2E{@KZ#fr0U> zr;B4qMcmujib011L|m0$J8WW65$a6g^qAJ@ExYOT3!@1-jEws>ZTj@NPVMBJ7Ng>~ ze=8rI{jz1cb+I1n^mS7}6qik(vULlI^#KEgDanW_kDepT)bXd?twv#W+`uoa;myZrlo3CKsa{teh3eBazS?$F)KanWf;15hD44$rj JF6*2UngBtC3vmDd literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo b/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo new file mode 100644 index 000000000..15f1ede8c --- /dev/null +++ b/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo @@ -0,0 +1,3 @@ +{ + "filterMode" : "Linear" +} diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES b/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES new file mode 100644 index 000000000..6fb9b6c1d --- /dev/null +++ b/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES @@ -0,0 +1,43 @@ +The icons in this folder are not under the same license like the source code. See /docs/Credits.md for more information. + +---Image info from Terasology's docs/Credits.md--- +Icons: +Some NUI editor icons belong to "Fugue Icons" by Yusuke Kamiyamane, licensed under the Creative Commons Attribution 3.0 License: + editor_array.png + editor_attribute.png + editor_object.png + editor_uibox.png + editor_uibutton.png + editor_uicheckbox.png + editor_uidoubleslider.png + editor_uidropdown.png + editor_uidropdownscrollable.png + editor_uiimage.png + editor_uilabel.png + editor_uilist.png + editor_uiloadbar.png + editor_uiscrollbar.png + editor_uislider.png + editor_uitext.png + editor_uitextentry.png + editor_uitooltip.png + editor_uitreeview.png + editor_zoomablelayout.png + +Some icons have been made by Florian Köberle and are licensed under the Creative Commons Attribution 4.0 License: + editor_cardLayout.png + editor_columnlayout.png + editor_flowlayout.png + editor_miglayout.png + editor_relativelayout.png + editor_rowlayout.png + editor_uispace.png + contract.png + contractOver.png + expand.png + expandOver.png + +Icons prepared by kartikey0303 (also CC BY 4.0) + checkboxChecked.png + checkboxCheckedDisabled.png + checkboxCheckedHover.png \ No newline at end of file diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contract.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contract.png new file mode 100644 index 0000000000000000000000000000000000000000..cce2841054547c4a05d0f8c8192edb5b70aab285 GIT binary patch literal 522 zcmV+l0`>igP)uRmL;L;hq|&zG$e%hAp*`q1-0ph z`o5}ex;OTN-1altNJy*zfm9 z(-cz5+bD|O9jkv*003sQ*+(L}5ki2O|A1R-K}5*&97&QuDFrFz-Fm&gKUMoI0RWgz zr=RjXf9-i5gb;AfJ#}7|C6Xio5kYH>Uaxl_hT+{gb&uYGUt>5N-fXv9k!9JddabG| z5E0TeeS-J<{fE_Rbru}BU;+RT1cA5NY(5_jhnMwHWLXBK6pS$#3B8G zDdksYPUAR!+XM~(VCKfTSS&={MAK|MfqxZO{|j1yR-hGV1+Fge9hB366*&E50ssI2 M07*qoM6N<$f}Qc%2mk;8 literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contractOver.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contractOver.png new file mode 100644 index 0000000000000000000000000000000000000000..3d6b2bab2fc2cb0984404fdca18b1cc67979aa76 GIT binary patch literal 553 zcmV+^0@nSBP)QW| z4wMdsE_#w2AqU6_vI^d~5m-2q{4Cp=MM-EEojC45y6^*S^x%D;5Yl_hIfqMzcTsvL z&r(F*_|BIkbn+m49P>-Fk9&*7Y_jWN(#ySlDjRaLdt8rIrcYYnB; z&+&L%wG}AyJbxJk!3W>>K}5*&9A#M|%Q9GNkL!?=QewB;K?s4tU~oO3&p$l{U`?7) zk|bZW*6%&fgLCc=u(cLNQ9x@ADJ9}KhA{@5^PA~(dV8vNBLM)|Y&Kt|lXu zRUP5`{T^`~Lu(Bp0_XfTilUn)bsGx+VC(hzAx+b_hmEoX0xkv z;6S^7z>P+uH;l0#S(ZU5g?_((-v$nxeujUQ*lxG4Ip+w1KrR-Gk8R*UyDRuTJjR%7 r3x5uQe~ydyf=-|l=ma`}iwisgMKT~2ShwaS00000NkvXXu0mjf)&}Iv literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expand.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expand.png new file mode 100644 index 0000000000000000000000000000000000000000..d45d643fad41a59fbfca81d5ea1ab4c11b4903fa GIT binary patch literal 509 zcmVs&H90$n?;wMb54p}ZyA`8niPa0*Q?0VUwS1Pq5mw@|=pwfa054Bi$7a2)6L`Fx)B`~5eC0F+XW@B5X* z;V|#@dUsdC7(hhgI1XIb_2W36b-UfW5XJxzfz}$X>q042*>1N{r_*`&F9AYC5D|Eu z2c?uB$MLM)Zd+BtrUiYcKtw=9&*5pBLTe2o%B$7tr{!`Py(l2hbH&Wi zTH|y&-Arn^h8RQ^cBV*m00000NkvXXu0mjfR=wK2 literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expandOver.png b/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expandOver.png new file mode 100644 index 0000000000000000000000000000000000000000..38e6cc91109862afd79178814a8fd78d9347efc2 GIT binary patch literal 551 zcmV+?0@(eDP)6P`W9^|e<-DWkD?+7K8{!K zBHlb%Efgw+J@qCY7ez0k?pD$!Gf7W{o(kEeT?!kRW9Ivj34sXb9Liilsp%D<0{pLl zuv9=C$M54feo-1A48!L2dR=X|+vlYKgb+cq*=(Fnr}bvDDSQ&%0A_Y!7(z-}Pm*M{ zTrLYCyaCo)Xsscogb<>UB*}-xV)62y0i1J=h+wTntyY5&qMjtlYCfOmItgz85ea4n zGb0EBNGai*tMB*w^>jM*M&ug7?SY`5F3CzFX6BG*g!E1ZasWf>li2bdYw zTB)^e`1F!_!ifk(gfvZ&rYVduAR^Ohwcd@#34hI-xz|7yHD0(v-4nO<$$^~F%cfa4ElmauWZnyio*Xw=B6At9K zgtyy`kH;gdwck3O&Qp=_T!8cW?1(6fqUfpL@5e>LfgB?MkhR>>-qoy literal 0 HcmV?d00001 diff --git a/engine/src/main/resources/assets/ui/migTestScreen.ui b/engine/src/main/resources/assets/ui/migTestScreen.ui new file mode 100644 index 000000000..aa4ba8f2b --- /dev/null +++ b/engine/src/main/resources/assets/ui/migTestScreen.ui @@ -0,0 +1,698 @@ +{ + "type": "engine:MigTestScreen", + "skin": "engine:migTestSkin", + "contents": { + "type": "migLayout", + "layoutConstraints": "", + "colConstraints": "[min][pref][min][pref][grow]", + "rowConstraints": "[min]", + "debug": true, + "contents": [ + { + "type": "UILabel", + "id": "", + "text": "", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UILabel", + "id": "", + "text": "disabled", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UILabel", + "id": "", + "text": "min", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UILabel", + "id": "", + "text": "pref", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UILabel", + "id": "", + "text": "grow", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UILabel", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UILabel", + "id": "label1", + "text": "label1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UILabel", + "id": "label2", + "text": "label2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UILabel", + "id": "label3", + "text": "label3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UILabel", + "id": "label4", + "text": "label4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIButton", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIButton", + "id": "button1", + "text": "button1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UIButton", + "id": "button2", + "text": "button2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIButton", + "id": "button3", + "text": "button3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIButton", + "id": "button4", + "text": "button4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UISlider", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UISlider", + "id": "slider1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UISlider", + "id": "slider2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UISlider", + "id": "slider3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UISlider", + "id": "slider4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIDoubleSlider", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIDoubleSlider", + "id": "doubleSlider1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UIDoubleSlider", + "id": "doubleSlider2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIDoubleSlider", + "id": "doubleSlider3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIDoubleSlider", + "id": "doubleSlider4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIText", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIText", + "id": "text1", + "text": "text1", + "layoutInfo": { + "cc": "" + }, + "readOnly": true, + "enabled": false + }, + { + "type": "UIText", + "id": "text2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIText", + "id": "text3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIText", + "id": "text4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIText with hint", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIText", + "id": "text1", + "hintText": "Enter text here", + "text": "text1", + "layoutInfo": { + "cc": "" + }, + "readOnly": true, + "enabled": false + }, + { + "type": "UIText", + "id": "text2", + "hintText": "Enter text here", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIText", + "id": "text3", + "hintText": "Enter text here", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIText", + "id": "text4", + "hintText": "Enter extra long hint text here that just keeps on going", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "ResettableUIText", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "ResettableUIText", + "id": "rtext1", + "text": "text1", + "layoutInfo": { + "cc": "" + }, + "readOnly": true, + "enabled": false + }, + { + "type": "ResettableUIText", + "id": "rtext2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "ResettableUIText", + "id": "rtext3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "ResettableUIText", + "id": "rtext4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIDropdown", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIDropdown", + "id": "dropdown1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UIDropdown", + "id": "dropdown2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIDropdown", + "id": "dropdown3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIDropdown", + "id": "dropdown4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIDropdownScrollable", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIDropdownScrollable", + "id": "dropdownScrollable1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UIDropdownScrollable", + "id": "dropdownScrollable2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIDropdownScrollable", + "id": "dropdownScrollable3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIDropdownScrollable", + "id": "dropdownScrollable4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UICheckbox", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UICheckbox", + "id": "checkbox1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UICheckbox", + "id": "checkbox2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UICheckbox", + "id": "checkbox3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UICheckbox", + "id": "checkbox4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIList", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIList", + "id": "list1", + "layoutInfo": { + "cc": "" + }, + "enabled": false + }, + { + "type": "UIList", + "id": "list2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIList", + "id": "list3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIList", + "id": "list4", + "layoutInfo": { + "cc": "grow" + } + }, + { + "type": "UILabel", + "id": "", + "text": "UIBox", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "UIBox", + "id": "box1", + "layoutInfo": { + "cc": "" + }, + "content": { + "type": "ColumnLayout", + "family": "option-grid", + "columns": 2, + "column-widths": [0.35, 0.65], + "verticalSpacing": 8, + "horizontalSpacing": 8, + "layoutInfo": { + "width": 360, + "height": 192, + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "offset": 16, + "widget": "subtitle" + }, + "position-bottom": { + "target": "TOP", + "offset": 32, + "widget": "close" + } + }, + "contents": [ + { + "type": "UILabel", + "text": "Example" + }, + { + "type": "UISlider" + } + ] + }, + "enabled": false + }, + { + "type": "UIBox", + "id": "box2", + "layoutInfo": { + "cc": "w min, h min" + }, + "content": { + "type": "ColumnLayout", + "family": "option-grid", + "columns": 2, + "column-widths": [0.35, 0.65], + "verticalSpacing": 8, + "horizontalSpacing": 8, + "layoutInfo": { + "width": 360, + "height": 192, + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "offset": 16, + "widget": "subtitle" + }, + "position-bottom": { + "target": "TOP", + "offset": 32, + "widget": "close" + } + }, + "contents": [ + { + "type": "UILabel", + "text": "Example" + }, + { + "type": "UISlider" + } + ] + } + }, + { + "type": "UIBox", + "id": "box3", + "layoutInfo": { + "cc": "" + }, + "content": { + "type": "ColumnLayout", + "family": "option-grid", + "columns": 2, + "column-widths": [0.35, 0.65], + "verticalSpacing": 8, + "horizontalSpacing": 8, + "layoutInfo": { + "width": 360, + "height": 192, + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "offset": 16, + "widget": "subtitle" + }, + "position-bottom": { + "target": "TOP", + "offset": 32, + "widget": "close" + } + }, + "contents": [ + { + "type": "UILabel", + "text": "Example" + }, + { + "type": "UISlider" + } + ] + } + }, + { + "type": "UIBox", + "id": "box4", + "layoutInfo": { + "cc": "grow" + }, + "content": { + "type": "ColumnLayout", + "family": "option-grid", + "columns": 2, + "column-widths": [0.35, 0.65], + "verticalSpacing": 8, + "horizontalSpacing": 8, + "layoutInfo": { + "width": 360, + "height": 192, + "position-horizontal-center": {}, + "position-top": { + "target": "BOTTOM", + "offset": 16, + "widget": "subtitle" + }, + "position-bottom": { + "target": "TOP", + "offset": 32, + "widget": "close" + } + }, + "contents": [ + { + "type": "UILabel", + "text": "Example" + }, + { + "type": "UISlider" + } + ] + } + }, + { + "type": "UILabel", + "id": "", + "text": "ScrollableArea", + "layoutInfo": { + "cc": "newline" + } + }, + { + "type": "ScrollableArea", + "id": "scrollbar1", + "layoutInfo": { + "width": 70, + "cc": "", + "position-horizontal-center": {} + }, + "enabled": false, + "content": { + "type": "RelativeLayout", + "contents": [ + { + "type": "UILabel", + "id": "message", + "text": "Lorem ipsum, Lorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsum", + "layoutInfo": { + "position-left": {}, + "position-right": {}, + "use-content-height": true, + "position-bottom": {} + } + } + ] + } + }, + { + "type": "UIScrollbar", + "id": "scrollbar2", + "layoutInfo": { + "cc": "w min, h min" + } + }, + { + "type": "UIScrollbar", + "id": "scrollbar3", + "layoutInfo": { + "cc": "" + } + }, + { + "type": "UIScrollbar", + "id": "scrollbar4", + "layoutInfo": { + "cc": "grow" + } + } + ] + } +} \ No newline at end of file From 1e3add6aa52924c4b8bed1d4a0c7042d2bc3cbab Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sun, 9 Feb 2020 10:15:37 +0000 Subject: [PATCH 02/20] Overlays are now correctly initialised with NUI. --- .../org/destinationsol/ui/nui/NUIManager.java | 49 +++++++++++++++---- .../destinationsol/ui/nui/NUIScreenLayer.java | 16 ++++++ 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index df3d7ef4f..8d5f6bbf9 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -37,6 +37,7 @@ import org.terasology.nui.backends.libgdx.LibGDXCanvasRenderer; import org.terasology.nui.backends.libgdx.LibGDXKeyboardDevice; import org.terasology.nui.backends.libgdx.LibGDXMouseDevice; +import org.terasology.nui.backends.libgdx.NUIInputProcessor; import org.terasology.nui.canvas.CanvasImpl; import org.terasology.nui.events.NUIKeyEvent; import org.terasology.nui.events.NUIMouseButtonEvent; @@ -67,6 +68,8 @@ public class NUIManager { private static final float BUTTON_CLICK_PITCH = 0.9f; public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { + NUIInputProcessor.CONSUME_INPUT = true; + mouse = new LibGDXMouseDevice(); keyboard = new LibGDXKeyboardDevice(); canvasRenderer = new LibGDXCanvasRenderer(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), @@ -121,13 +124,20 @@ public void update(SolApplication solApplication) { } for (NUIScreenLayer uiScreen : uiScreens) { - UIWidget element = uiScreen.contents; - element.update(Gdx.graphics.getDeltaTime()); + uiScreen.update(Gdx.graphics.getDeltaTime()); if (uiScreen.isBlockingInput()) { break; } } + + for (NUIScreenLayer overlay : uiOverlays) { + overlay.update(Gdx.graphics.getDeltaTime()); + + if (overlay.isBlockingInput()) { + break; + } + } } public void draw(CommonDrawer gameDrawer) { @@ -140,7 +150,15 @@ public void draw(CommonDrawer gameDrawer) { while (screenIterator.hasNext()) { NUIScreenLayer screenLayer = screenIterator.next(); canvas.setSkin(screenLayer.getSkin()); - canvas.drawWidget(screenLayer.contents); + canvas.drawWidget(screenLayer); + } + + // NOTE: Need to render in the inverse to how they are updated, so the top screen is drawn last + Iterator overlayIterator = uiOverlays.descendingIterator(); + while (overlayIterator.hasNext()) { + NUIScreenLayer screenLayer = overlayIterator.next(); + canvas.setSkin(screenLayer.getSkin()); + canvas.drawWidget(screenLayer); } canvas.postRender(); @@ -153,7 +171,16 @@ public NUIScreenLayer getTopScreen() { } public void pushScreen(NUIScreenLayer layer) { - uiScreens.push(layer); + pushScreen(layer, false); + } + + public void pushScreen(NUIScreenLayer layer, boolean isOverlay) { + if (!isOverlay) { + uiScreens.push(layer); + } else { + uiOverlays.push(layer); + } + layer.setFocusManager(focusManager); layer.initialise(); } @@ -165,12 +192,12 @@ public void removeScreen(NUIScreenLayer screen) { uiScreens.remove(screen); } - public Deque getScreens() { - return uiScreens; + public boolean hasScreen(NUIScreenLayer screen) { + return uiScreens.contains(screen); } - public void pushOverlay(NUIScreenLayer overlay) { - uiOverlays.push(overlay); + public Deque getScreens() { + return uiScreens; } public NUIScreenLayer popOverlay() { @@ -189,8 +216,10 @@ public boolean hasOverlay(NUIScreenLayer overlay) { return uiOverlays.contains(overlay); } - public boolean hasOverlayOfType(Class type) { - for (NUIScreenLayer layer : uiOverlays) { + public boolean hasScreenOfType(Class type, boolean isOverlay) { + Deque screens = (isOverlay ? uiOverlays : uiScreens); + + for (NUIScreenLayer layer : screens) { if (layer.getClass().isAssignableFrom(type)) { return true; } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java index 3e71901d0..68ae06944 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java @@ -20,6 +20,7 @@ import org.terasology.math.geom.Vector2i; import org.terasology.nui.AbstractWidget; import org.terasology.nui.Canvas; +import org.terasology.nui.FocusManager; import org.terasology.nui.LayoutConfig; import org.terasology.nui.UIWidget; @@ -30,12 +31,19 @@ public abstract class NUIScreenLayer extends AbstractWidget { @LayoutConfig protected UIWidget contents; + protected FocusManager focusManager; @Override public void onDraw(Canvas canvas) { canvas.drawWidget(contents); } + @Override + public void update(float delta) { + super.update(delta); + contents.update(delta); + } + @Override public boolean canBeFocus() { return false; @@ -77,4 +85,12 @@ public void initialise() { public boolean isBlockingInput() { return false; } + + void setFocusManager(FocusManager focusManager) { + this.focusManager = focusManager; + } + + protected FocusManager getFocusManager() { + return focusManager; + } } From 2cbd4d9ef121d33a2711aa69edceac4951255987 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Mon, 10 Feb 2020 14:41:26 +0000 Subject: [PATCH 03/20] Removed commented NUI code used for testing. --- engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index 8d5f6bbf9..1f1a1ef49 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -87,9 +87,6 @@ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { UIButton.DEFAULT_CLICK_SOUND = sound; UIText.DEFAULT_CURSOR_TEXTURE = whiteTexture; - //pushScreen((NUIScreenLayer) Assets.getAssetHelper().get(new ResourceUrn("engine:migTestScreen"), UIElement.class).get().getRootWidget()); - //pushScreen((NUIScreenLayer) Assets.getAssetHelper().get(new ResourceUrn("engine:console"), UIElement.class).get().getRootWidget()); - // NOTE: SolApplication::addResizeSubscriber is not intended to be static, so use the instance form for compatibility solApplication.addResizeSubscriber(() -> canvasRenderer.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight())); } From 4b12e0b89ea0224f402bd3bc06079769ca64f256 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Fri, 14 Feb 2020 09:50:11 +0000 Subject: [PATCH 04/20] Ported Terasology's console UI (NUI) to Destination Sol. --- .../game/screens/MainGameScreen.java | 24 +++- .../ui/nui/screens/ConsoleScreen.java | 119 ++++++++++++++++++ .../ui/nui/screens/UICommandEntry.java | 114 +++++++++++++++++ .../main/resources/assets/skins/console.skin | 54 ++++++++ .../assets/textures/ui/nui/boxLight.png | Bin 0 -> 129 bytes .../src/main/resources/assets/ui/console.ui | 52 ++++++++ 6 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java create mode 100644 engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java create mode 100644 engine/src/main/resources/assets/skins/console.skin create mode 100644 engine/src/main/resources/assets/textures/ui/nui/boxLight.png create mode 100644 engine/src/main/resources/assets/ui/console.ui diff --git a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java index 0876180d2..75922ac87 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java @@ -49,6 +49,9 @@ import org.destinationsol.ui.SolUiControl; import org.destinationsol.ui.SolUiScreen; import org.destinationsol.ui.UiDrawer; +import org.destinationsol.ui.nui.screens.ConsoleScreen; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.nui.asset.UIElement; import java.util.ArrayList; import java.util.List; @@ -96,6 +99,7 @@ public class MainGameScreen extends SolUiBaseScreen { private final TextPlace myChargesExcessTp; private final TextPlace myMoneyExcessTp; private final SolApplication solApplication; + private final ConsoleScreen consoleScreen; private List gameOverlayScreens = new ArrayList<>(); private List warnDrawers = new ArrayList<>(); @@ -174,6 +178,8 @@ public class MainGameScreen extends SolUiBaseScreen { compassTexture = Assets.getAtlasRegion("engine:uiCompass"); myCompassTint = SolColor.col(1, 0); + consoleScreen = (ConsoleScreen) Assets.getAssetHelper().get(new ResourceUrn("engine:console"), UIElement.class).get().getRootWidget(); + myLifeTp = new TextPlace(SolColor.W50); myRepairsExcessTp = new TextPlace(SolColor.WHITE); myShieldLifeTp = new TextPlace(SolColor.W50); @@ -242,7 +248,6 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi if (menuControl.isJustOff()) { inputMan.setScreen(solApplication, screens.menuScreen); } - boolean controlsEnabled = inputMan.getTopScreen() == this; shipControl.update(solApplication, controlsEnabled); @@ -289,12 +294,27 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi updateTalk(game); + if (solApplication.getNuiManager().hasScreenOfType(ConsoleScreen.class, true)) { + controls.forEach(x -> x.setEnabled(false)); + consoleControlGrave.setEnabled(true); + consoleControlF1.setEnabled(true); + } + if (pauseControl.isJustOff()) { game.setPaused(!game.isPaused()); } if (consoleControlGrave.isJustOff() || consoleControlF1.isJustOff()) { - inputMan.setScreen(solApplication, screens.consoleScreen); + if (solApplication.getNuiManager().hasScreenOfType(ConsoleScreen.class, true)) { + solApplication.getNuiManager().removeOverlay(consoleScreen); + game.setPaused(false); + controls.forEach(x -> x.setEnabled(true)); + consoleControlGrave.setEnabled(true); + consoleControlF1.setEnabled(true); + } else { + solApplication.getNuiManager().pushScreen(consoleScreen, true); + game.setPaused(true); + } } for (SolUiScreen screen : gameOverlayScreens) { diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java new file mode 100644 index 000000000..4668cca33 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java @@ -0,0 +1,119 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.ui.nui.screens; + +import org.destinationsol.game.console.Console; +import org.destinationsol.game.console.ConsoleImpl; +import org.destinationsol.game.console.CyclingTabCompletionEngine; +import org.destinationsol.game.console.Message; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.terasology.input.MouseInput; +import org.terasology.nui.BaseInteractionListener; +import org.terasology.nui.Canvas; +import org.terasology.nui.FontColor; +import org.terasology.nui.InteractionListener; +import org.terasology.nui.databinding.ReadOnlyBinding; +import org.terasology.nui.events.NUIMouseClickEvent; +import org.terasology.nui.layouts.ScrollableArea; +import org.terasology.nui.widgets.UIText; + +import java.util.List; + +public class ConsoleScreen extends NUIScreenLayer { + private Console console; + + private UICommandEntry commandLine; + + private boolean welcomePrinted; + + private InteractionListener screenListener = new BaseInteractionListener() { + @Override + public boolean onMouseClick(NUIMouseClickEvent event) { + if (event.getMouseButton() == MouseInput.MOUSE_LEFT && commandLine != null) { + focusManager.setFocus(commandLine); + } + return true; + } + }; + + @Override + public void initialise() { + if (!welcomePrinted) { + console = ConsoleImpl.instance; + + final ScrollableArea scrollArea = find("scrollArea", ScrollableArea.class); + scrollArea.moveToBottom(); + + commandLine = find("commandLine", UICommandEntry.class); + commandLine.setTabCompletionEngine(new CyclingTabCompletionEngine(console)); + commandLine.bindCommandHistory(new ReadOnlyBinding>() { + @Override + public List get() { + return console.getPreviousCommands(); + } + }); + commandLine.subscribe(widget -> { + String text = commandLine.getText(); + if (!text.isEmpty()) { + console.execute(text); + } + scrollArea.moveToBottom(); + }); + + final UIText history = find("messageHistory", UIText.class); + history.bindText(new ReadOnlyBinding() { + @Override + public String get() { + StringBuilder messageList = new StringBuilder(); + for (Message message : console.getMessages()) { + messageList.append(FontColor.getColored(message.getMessage(), new org.terasology.nui.Color(message.getType().getColor().toIntBits()))); + messageList.append(Console.NEW_LINE); + } + return messageList.toString(); + } + }); + + onOpened(); + } + + focusManager.setFocus(commandLine); + } + + public void onOpened() { + if (!welcomePrinted) { + console.addMessage("Welcome to the world of Destination Sol! Your journey begins!" + Console.NEW_LINE + + "Type 'help' to see a list with available commands or 'help ' for command details." + Console.NEW_LINE + + "Text parameters do not need quotes, unless containing spaces. No commas between parameters." + Console.NEW_LINE + + "You can use auto-completion by typing a partial command then hitting [tab] - examples:" + Console.NEW_LINE + Console.NEW_LINE + + "go + [tab] => 'godMode'" + Console.NEW_LINE + + "help gh + [tab] => 'help godMode' (can auto complete commands fed to help)" + Console.NEW_LINE + + "(use [tab] again to cycle between choices)" + Console.NEW_LINE + + "gM + [tab] => 'godMode' (camel casing abbreviated commands)" + Console.NEW_LINE); + welcomePrinted = true; + } + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.addInteractionRegion(screenListener, canvas.getRegion()); + } + + @Override + public boolean isBlockingInput() { + return true; + } +} diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java new file mode 100644 index 000000000..d8f62737e --- /dev/null +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java @@ -0,0 +1,114 @@ +/* + * Copyright 2014 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.ui.nui.screens; + +import com.google.common.collect.Lists; +import org.destinationsol.game.console.TabCompletionEngine; +import org.terasology.input.Keyboard; +import org.terasology.nui.databinding.Binding; +import org.terasology.nui.databinding.DefaultBinding; +import org.terasology.nui.events.NUIKeyEvent; +import org.terasology.nui.widgets.UIText; + +import java.util.List; + +/** + */ +public class UICommandEntry extends UIText { + private Binding> commandHistory = new DefaultBinding<>(Lists.newArrayList()); + private int index; + private TabCompletionEngine tabCompletionEngine; + + public UICommandEntry() { + subscribe((int oldPosition, int newPosition) -> { + if (tabCompletionEngine == null) { + return; + } + + tabCompletionEngine.reset(); + }); + } + + @Override + public boolean onKeyEvent(NUIKeyEvent event) { + if (event.isDown()) { + int id = event.getKey().getId(); + + if (id != Keyboard.KeyId.TAB && tabCompletionEngine != null) { + tabCompletionEngine.reset(); + } + + switch (id) { + case Keyboard.KeyId.UP: + if (index > 0) { + index--; + if (getCommandHistory().size() > index) { + setText(getCommandHistory().get(index)); + } + setCursorPosition(getText().length()); + } + return true; + case Keyboard.KeyId.DOWN: + if (index < getCommandHistory().size()) { + index++; + if (index == getCommandHistory().size()) { + setText(""); + } else { + setText(getCommandHistory().get(index)); + setCursorPosition(getText().length()); + } + } + return true; + case Keyboard.KeyId.TAB: + if (tabCompletionEngine != null) { + setText(tabCompletionEngine.complete(getText())); + setCursorPosition(getText().length(), true, false); + return true; + } + break; + case Keyboard.KeyId.ENTER: + boolean consumed = super.onKeyEvent(event); + setText(""); + index = getCommandHistory().size(); + return consumed; + default: + return super.onKeyEvent(event); + } + } + return false; + } + + public void bindCommandHistory(Binding> binding) { + commandHistory = binding; + index = commandHistory.get().size(); + } + + public List getCommandHistory() { + return commandHistory.get(); + } + + public void setCommandHistory(List val) { + commandHistory.set(val); + } + + public TabCompletionEngine getTabCompletionEngine() { + return tabCompletionEngine; + } + + public void setTabCompletionEngine(TabCompletionEngine tabCompletionEngine) { + this.tabCompletionEngine = tabCompletionEngine; + } +} diff --git a/engine/src/main/resources/assets/skins/console.skin b/engine/src/main/resources/assets/skins/console.skin new file mode 100644 index 000000000..b96a3dd37 --- /dev/null +++ b/engine/src/main/resources/assets/skins/console.skin @@ -0,0 +1,54 @@ +{ + "inherit": "engine:default", + "elements": { + "UILabel": { + "text-align-horizontal": "LEFT", + "text-align-vertical": "top", + "text-shadowed": false + }, + "ScrollableArea": { + "background": "engine:buttonDown", + "background-border": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + }, + "margin": { + "top": 4, + "bottom": 4, + "left": 4, + "right": 4 + } + } + }, + "families": { + "history": { + "elements": { + "UIText": { + "background": "", + "text-shadowed": false, + "background-border": { + "top": 0, + "bottom": 0, + "left": 0, + "right": 0 + }, + "margin": { + "top": 0, + "bottom": 0, + "left": 0, + "right": 0 + } + } + } + }, + "commandInput": { + "elements": { + "UICommandEntry": { + "background": "engine:boxLight" + } + } + } + } +} diff --git a/engine/src/main/resources/assets/textures/ui/nui/boxLight.png b/engine/src/main/resources/assets/textures/ui/nui/boxLight.png new file mode 100644 index 0000000000000000000000000000000000000000..0bb39e2cefeb027c7c4bb2d7de9d0eaf0212650d GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz4^J1zkcif|*B1&hDDbcxY+kry zisMWRFXq`?9FG>=`+IJ;$+wvzaqD&1B{bI`zso4Equ|iMz{teHApl`~%9jvr_{6H$ YbBTEs=dQ1jKr Date: Tue, 18 Feb 2020 09:21:40 +0000 Subject: [PATCH 05/20] Added a new showNUIScreen command. Removed overlays from NUIManager, as they served the same purpose and ui screens. Pressing the Esc key should now close NUI screens. --- .../commands/ShowNUIScreenCommandHandler.java | 41 +++++++ .../suggesters/NUIScreenSuggester.java | 37 +++++++ .../game/screens/MainGameScreen.java | 22 ++-- .../org/destinationsol/ui/nui/NUIManager.java | 102 ++++++++---------- .../destinationsol/ui/nui/NUIScreenLayer.java | 31 +++++- .../ui/nui/screens/ConsoleScreen.java | 19 +++- 6 files changed, 181 insertions(+), 71 deletions(-) create mode 100644 engine/src/main/java/org/destinationsol/game/console/commands/ShowNUIScreenCommandHandler.java create mode 100644 engine/src/main/java/org/destinationsol/game/console/suggesters/NUIScreenSuggester.java diff --git a/engine/src/main/java/org/destinationsol/game/console/commands/ShowNUIScreenCommandHandler.java b/engine/src/main/java/org/destinationsol/game/console/commands/ShowNUIScreenCommandHandler.java new file mode 100644 index 000000000..02c9f7912 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/game/console/commands/ShowNUIScreenCommandHandler.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.game.console.commands; + +import org.destinationsol.assets.Assets; +import org.destinationsol.game.SolGame; +import org.destinationsol.game.console.annotations.Command; +import org.destinationsol.game.console.annotations.CommandParam; +import org.destinationsol.game.console.annotations.Game; +import org.destinationsol.game.console.annotations.RegisterCommands; +import org.destinationsol.game.console.suggesters.NUIScreenSuggester; +import org.destinationsol.ui.nui.NUIManager; +import org.destinationsol.ui.nui.NUIScreenLayer; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.nui.asset.UIElement; + +/** + * A command used to display a particular NUI screen + */ +@RegisterCommands +public class ShowNUIScreenCommandHandler { + @Command(shortDescription = "Displays a NUI screen") + public String showNUIScreen(@Game SolGame game, @CommandParam(value = "screen", suggester = NUIScreenSuggester.class) String screen) { + NUIManager nuiManager = game.getSolApplication().getNuiManager(); + nuiManager.pushScreen((NUIScreenLayer) Assets.getAssetHelper().get(new ResourceUrn(screen), UIElement.class).get().getRootWidget()); + return "Screen displayed."; + } +} diff --git a/engine/src/main/java/org/destinationsol/game/console/suggesters/NUIScreenSuggester.java b/engine/src/main/java/org/destinationsol/game/console/suggesters/NUIScreenSuggester.java new file mode 100644 index 000000000..8307af9b4 --- /dev/null +++ b/engine/src/main/java/org/destinationsol/game/console/suggesters/NUIScreenSuggester.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020 The Terasology Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.destinationsol.game.console.suggesters; + +import org.destinationsol.assets.Assets; +import org.destinationsol.game.SolGame; +import org.destinationsol.game.console.CommandParameterSuggester; +import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.nui.asset.UIElement; + +import java.util.HashSet; +import java.util.Set; + +public class NUIScreenSuggester implements CommandParameterSuggester { + @Override + public Set suggest(SolGame game, Object... resolvedParameters) { + Set suggestions = new HashSet<>(); + for (ResourceUrn urn : Assets.getAssetHelper().list(UIElement.class)) { + suggestions.add(urn.toString()); + } + + return suggestions; + } +} diff --git a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java index 75922ac87..0a9346f67 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java @@ -294,7 +294,7 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi updateTalk(game); - if (solApplication.getNuiManager().hasScreenOfType(ConsoleScreen.class, true)) { + if (solApplication.getNuiManager().hasScreen(consoleScreen)) { controls.forEach(x -> x.setEnabled(false)); consoleControlGrave.setEnabled(true); consoleControlF1.setEnabled(true); @@ -304,15 +304,21 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi game.setPaused(!game.isPaused()); } + if (consoleScreen.isConsoleJustClosed()) { + game.setPaused(false); + controls.forEach(x -> x.setEnabled(true)); + consoleControlGrave.setEnabled(true); + consoleControlF1.setEnabled(true); + + menuControl.update(inputPointers, false, false, inputMan, solApplication); + menuControl.update(inputPointers, false, false, inputMan, solApplication); + } + if (consoleControlGrave.isJustOff() || consoleControlF1.isJustOff()) { - if (solApplication.getNuiManager().hasScreenOfType(ConsoleScreen.class, true)) { - solApplication.getNuiManager().removeOverlay(consoleScreen); - game.setPaused(false); - controls.forEach(x -> x.setEnabled(true)); - consoleControlGrave.setEnabled(true); - consoleControlF1.setEnabled(true); + if (solApplication.getNuiManager().hasScreen(consoleScreen)) { + solApplication.getNuiManager().removeScreen(consoleScreen); } else { - solApplication.getNuiManager().pushScreen(consoleScreen, true); + solApplication.getNuiManager().pushScreen(consoleScreen); game.setPaused(true); } } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index 1f1a1ef49..5d325f579 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -32,8 +32,6 @@ import org.terasology.nui.FocusManagerImpl; import org.terasology.nui.TabbingManager; import org.terasology.nui.UITextureRegion; -import org.terasology.nui.UIWidget; -import org.terasology.nui.asset.UIElement; import org.terasology.nui.backends.libgdx.LibGDXCanvasRenderer; import org.terasology.nui.backends.libgdx.LibGDXKeyboardDevice; import org.terasology.nui.backends.libgdx.LibGDXMouseDevice; @@ -60,7 +58,6 @@ public class NUIManager { private UISkin skin; private Deque uiScreens = new LinkedList<>(); - private Deque uiOverlays = new LinkedList<>(); private static final String WHITE_TEXTURE_URN = "engine:uiWhiteTex"; private static final String DEFAULT_SKIN_URN = "engine:default"; @@ -96,8 +93,16 @@ public void update(SolApplication solApplication) { canvas.setGameTime(System.currentTimeMillis()); for (KeyboardAction action : keyboard.getInputQueue()) { + NUIKeyEvent event = new NUIKeyEvent(mouse, keyboard, action.getInput(), action.getInputChar(), action.getState()); + if (focusManager.getFocus() != null) { - focusManager.getFocus().onKeyEvent(new NUIKeyEvent(mouse, keyboard, action.getInput(), action.getInputChar(), action.getState())); + focusManager.getFocus().onKeyEvent(event); + } + + for (NUIScreenLayer uiScreen : uiScreens) { + if (uiScreen.onKeyEvent(event) || uiScreen.isBlockingInput() || event.isConsumed()) { + break; + } } } @@ -109,31 +114,38 @@ public void update(SolApplication solApplication) { canvas.processMouseRelease((MouseInput) action.getInput(), action.getMousePosition()); } + NUIMouseButtonEvent event = new NUIMouseButtonEvent((MouseInput) action.getInput(), action.getState(), action.getMousePosition()); + if (focusManager.getFocus() != null) { - focusManager.getFocus().onMouseButtonEvent(new NUIMouseButtonEvent((MouseInput) action.getInput(), action.getState(), action.getMousePosition())); + focusManager.getFocus().onMouseButtonEvent(event); + } + + for (NUIScreenLayer uiScreen : uiScreens) { + uiScreen.onMouseButtonEvent(event); + if (event.isConsumed()) { + break; + } } } else if (action.getInput().getType() == InputType.MOUSE_WHEEL) { canvas.processMouseWheel(action.getTurns(), action.getMousePosition()); + + NUIMouseWheelEvent event = new NUIMouseWheelEvent(mouse, keyboard, action.getMousePosition(), action.getTurns()); + if (focusManager.getFocus() != null) { - focusManager.getFocus().onMouseWheelEvent(new NUIMouseWheelEvent(mouse, keyboard, action.getMousePosition(), action.getTurns())); + focusManager.getFocus().onMouseWheelEvent(event); + } + + for (NUIScreenLayer uiScreen : uiScreens) { + uiScreen.onMouseWheelEvent(event); + if (event.isConsumed()) { + break; + } } } } for (NUIScreenLayer uiScreen : uiScreens) { uiScreen.update(Gdx.graphics.getDeltaTime()); - - if (uiScreen.isBlockingInput()) { - break; - } - } - - for (NUIScreenLayer overlay : uiOverlays) { - overlay.update(Gdx.graphics.getDeltaTime()); - - if (overlay.isBlockingInput()) { - break; - } } } @@ -150,14 +162,6 @@ public void draw(CommonDrawer gameDrawer) { canvas.drawWidget(screenLayer); } - // NOTE: Need to render in the inverse to how they are updated, so the top screen is drawn last - Iterator overlayIterator = uiOverlays.descendingIterator(); - while (overlayIterator.hasNext()) { - NUIScreenLayer screenLayer = overlayIterator.next(); - canvas.setSkin(screenLayer.getSkin()); - canvas.drawWidget(screenLayer); - } - canvas.postRender(); gameDrawer.getSpriteBatch().flush(); @@ -168,24 +172,22 @@ public NUIScreenLayer getTopScreen() { } public void pushScreen(NUIScreenLayer layer) { - pushScreen(layer, false); - } + uiScreens.push(layer); - public void pushScreen(NUIScreenLayer layer, boolean isOverlay) { - if (!isOverlay) { - uiScreens.push(layer); - } else { - uiOverlays.push(layer); - } layer.setFocusManager(focusManager); + layer.setNuiManager(this); layer.initialise(); } public NUIScreenLayer popScreen() { + if (!uiScreens.isEmpty()) { + uiScreens.peek().onRemoved(); + } return uiScreens.pop(); } public void removeScreen(NUIScreenLayer screen) { + screen.onRemoved(); uiScreens.remove(screen); } @@ -193,31 +195,9 @@ public boolean hasScreen(NUIScreenLayer screen) { return uiScreens.contains(screen); } - public Deque getScreens() { - return uiScreens; - } - - public NUIScreenLayer popOverlay() { - return uiOverlays.pop(); - } - - public void removeOverlay(NUIScreenLayer overlay) { - uiOverlays.remove(overlay); - } - - public Deque getOverlays() { - return uiOverlays; - } - - public boolean hasOverlay(NUIScreenLayer overlay) { - return uiOverlays.contains(overlay); - } - - public boolean hasScreenOfType(Class type, boolean isOverlay) { - Deque screens = (isOverlay ? uiOverlays : uiScreens); - - for (NUIScreenLayer layer : screens) { - if (layer.getClass().isAssignableFrom(type)) { + public boolean hasScreenOfType(Class type) { + for (NUIScreenLayer screenLayer : uiScreens) { + if (screenLayer.getClass().isAssignableFrom(type)) { return true; } } @@ -225,6 +205,10 @@ public boolean hasScreenOfType(Class type, boolean isO return false; } + public Deque getScreens() { + return uiScreens; + } + public UISkin getDefaultSkin() { return skin; } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java index 68ae06944..38756dbe3 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java @@ -15,14 +15,15 @@ */ package org.destinationsol.ui.nui; -import org.terasology.input.Input; -import org.terasology.input.InputType; +import org.terasology.input.ButtonState; +import org.terasology.input.Keyboard; import org.terasology.math.geom.Vector2i; import org.terasology.nui.AbstractWidget; import org.terasology.nui.Canvas; import org.terasology.nui.FocusManager; import org.terasology.nui.LayoutConfig; import org.terasology.nui.UIWidget; +import org.terasology.nui.events.NUIKeyEvent; import java.util.Arrays; import java.util.Collections; @@ -32,6 +33,7 @@ public abstract class NUIScreenLayer extends AbstractWidget { @LayoutConfig protected UIWidget contents; protected FocusManager focusManager; + protected NUIManager nuiManager; @Override public void onDraw(Canvas canvas) { @@ -79,13 +81,30 @@ public Iterator iterator() { return Arrays.asList(contents).iterator(); } + @Override + public boolean onKeyEvent(NUIKeyEvent event) { + if (escapeCloses() && event.getState() == ButtonState.UP && event.getKey() == Keyboard.Key.ESCAPE) { + nuiManager.removeScreen(this); + return true; + } + + return super.onKeyEvent(event); + } + public void initialise() { } + public void onRemoved() { + } + public boolean isBlockingInput() { return false; } + protected boolean escapeCloses() { + return true; + } + void setFocusManager(FocusManager focusManager) { this.focusManager = focusManager; } @@ -93,4 +112,12 @@ void setFocusManager(FocusManager focusManager) { protected FocusManager getFocusManager() { return focusManager; } + + void setNuiManager(NUIManager nuiManager) { + this.nuiManager = nuiManager; + } + + protected NUIManager getNuiManager() { + return nuiManager; + } } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java index 4668cca33..df55ae38f 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java @@ -34,10 +34,9 @@ public class ConsoleScreen extends NUIScreenLayer { private Console console; - private UICommandEntry commandLine; - private boolean welcomePrinted; + private boolean screenClosed; private InteractionListener screenListener = new BaseInteractionListener() { @Override @@ -51,6 +50,8 @@ public boolean onMouseClick(NUIMouseClickEvent event) { @Override public void initialise() { + screenClosed = false; + if (!welcomePrinted) { console = ConsoleImpl.instance; @@ -106,6 +107,11 @@ public void onOpened() { } } + @Override + public void onRemoved() { + screenClosed = true; + } + @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -116,4 +122,13 @@ public void onDraw(Canvas canvas) { public boolean isBlockingInput() { return true; } + + public boolean isConsoleJustClosed() { + if (screenClosed) { + screenClosed = false; + return true; + } + + return false; + } } From 7c21af3993fbae8e93fa05a5ffb27c08c52f76af Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Fri, 20 Mar 2020 17:28:45 +0000 Subject: [PATCH 06/20] Moved UICommandEntry to the org.terasology.nui.widgets package. --- .../org/destinationsol/ui/nui/screens/ConsoleScreen.java | 1 + .../ui/nui/{screens => widgets}/UICommandEntry.java | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) rename engine/src/main/java/org/destinationsol/ui/nui/{screens => widgets}/UICommandEntry.java (94%) diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java index df55ae38f..f7a2e8685 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java @@ -20,6 +20,7 @@ import org.destinationsol.game.console.CyclingTabCompletionEngine; import org.destinationsol.game.console.Message; import org.destinationsol.ui.nui.NUIScreenLayer; +import org.destinationsol.ui.nui.widgets.UICommandEntry; import org.terasology.input.MouseInput; import org.terasology.nui.BaseInteractionListener; import org.terasology.nui.Canvas; diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java b/engine/src/main/java/org/destinationsol/ui/nui/widgets/UICommandEntry.java similarity index 94% rename from engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java rename to engine/src/main/java/org/destinationsol/ui/nui/widgets/UICommandEntry.java index d8f62737e..62837d240 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/UICommandEntry.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/widgets/UICommandEntry.java @@ -1,11 +1,11 @@ /* - * Copyright 2014 MovingBlocks + * Copyright 2020 The Terasology Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.destinationsol.ui.nui.screens; +package org.destinationsol.ui.nui.widgets; import com.google.common.collect.Lists; import org.destinationsol.game.console.TabCompletionEngine; @@ -26,6 +26,7 @@ import java.util.List; /** + * A UI Widget used for command-line input and tab-completion in the console screen. */ public class UICommandEntry extends UIText { private Binding> commandHistory = new DefaultBinding<>(Lists.newArrayList()); From a9a8e54170b240a4a35ee68ea247bc96fac21057 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Thu, 4 Jun 2020 17:44:40 +0100 Subject: [PATCH 07/20] Added a note about some files being borrowed from Terasology. The files generally relate to UI file formats, which are re-used for compatibility reasons. --- .../assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java | 2 +- .../src/main/java/org/destinationsol/assets/ui/UIFormat.java | 1 + .../main/java/org/destinationsol/assets/ui/UISkinFormat.java | 5 +---- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java b/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java index 1fc41a185..1e8b5dea7 100644 --- a/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java +++ b/engine/src/main/java/org/destinationsol/assets/ui/CaseInsensitiveEnumTypeAdapterFactory.java @@ -30,7 +30,7 @@ /** * A Gson Adapter factory for supporting enums in a case-insensitive manner - * + * NOTE: Taken from Terasology for compatibility with NUI JSON files. */ public class CaseInsensitiveEnumTypeAdapterFactory implements TypeAdapterFactory { diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java index 0eab22822..e916081e7 100644 --- a/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java +++ b/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java @@ -63,6 +63,7 @@ /** * Handles loading UI widgets from json format files. + * NOTE: Taken from Terasology for compatibility with NUI JSON files. */ @RegisterAssetFileFormat public class UIFormat extends AbstractAssetFileFormat { diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java index 67c11bbb2..d79abe1c7 100644 --- a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java +++ b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java @@ -1,9 +1,5 @@ package org.destinationsol.assets.ui; -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.google.common.base.Charsets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -41,6 +37,7 @@ import java.util.Optional; /** + * NOTE: Taken from Terasology for compatibility with NUI JSON files. */ @RegisterAssetFileFormat public class UISkinFormat extends AbstractAssetFileFormat { From ed6ee34eddd67ecaae035ef2016559f2d54e5a25 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Thu, 4 Jun 2020 19:38:31 +0100 Subject: [PATCH 08/20] Fixed compilation and runtime issues after rebase against current develop (af60af9). --- .../destinationsol/assets/AssetHelper.java | 19 +++++------------- .../destinationsol/modules/ModuleManager.java | 13 ++++++++++++ .../org/destinationsol/ui/nui/NUIManager.java | 2 +- .../destinationsol}/assets/skins/console.skin | 0 .../destinationsol}/assets/skins/default.skin | 0 .../assets/skins/migTestSkin.skin | 0 .../assets/textures/ui/nui/area.png | Bin .../assets/textures/ui/nui/box.png | Bin .../assets/textures/ui/nui/boxActive.png | Bin .../assets/textures/ui/nui/boxDisabled.png | Bin .../assets/textures/ui/nui/boxLight.png | Bin .../assets/textures/ui/nui/button.png | Bin .../assets/textures/ui/nui/buttonDown.png | Bin .../assets/textures/ui/nui/buttonOver.png | Bin .../assets/textures/ui/nui/checkbox.png | Bin .../textures/ui/nui/checkboxChecked.png | Bin .../ui/nui/checkboxCheckedDisabled.png | Bin .../textures/ui/nui/checkboxCheckedHover.png | Bin .../textures/ui/nui/checkboxDisabled.png | Bin .../assets/textures/ui/nui/checkboxHover.png | Bin .../assets/textures/ui/nui/dropdown.png | Bin .../assets/textures/ui/nui/dropdownActive.png | Bin .../textures/ui/nui/dropdownDisabled.png | Bin .../assets/textures/ui/nui/dropdownList.png | Bin .../ui/nui/dropdownListItemActive.png | Bin .../assets/textures/ui/nui/handle.png | Bin .../assets/textures/ui/nui/resetBox.png | Bin .../textures/ui/nui/resetBoxDisabled.png | Bin .../assets/textures/ui/nui/sliderTrack.png | Bin .../textures/ui/nui/terasology/LICENSE_NOTES | 0 .../ui/nui/terasology/radial/radialUnit.png | Bin .../terasology/radial/radialUnitSelected.png | Bin .../textures/ui/nui/terasology/statusBar.png | Bin .../ui/nui/terasology/testWindowBorder.png | Bin .../nui/terasology/testWindowBorder.texinfo | 0 .../nui/terasology/testWindowBorderOver.png | Bin .../terasology/testWindowBorderOver.texinfo | 0 .../ui/nui/terasology/treeView/LICENSE_NOTES | 0 .../ui/nui/terasology/treeView/contract.png | Bin .../nui/terasology/treeView/contractOver.png | Bin .../ui/nui/terasology/treeView/expand.png | Bin .../ui/nui/terasology/treeView/expandOver.png | Bin .../destinationsol}/assets/ui/console.ui | 0 .../assets/ui/migTestScreen.ui | 0 44 files changed, 19 insertions(+), 15 deletions(-) rename engine/src/main/resources/{ => org/destinationsol}/assets/skins/console.skin (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/skins/default.skin (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/skins/migTestSkin.skin (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/area.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/box.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/boxActive.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/boxDisabled.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/boxLight.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/button.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/buttonDown.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/buttonOver.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/checkbox.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/checkboxChecked.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/checkboxCheckedDisabled.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/checkboxCheckedHover.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/checkboxDisabled.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/checkboxHover.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/dropdown.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/dropdownActive.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/dropdownDisabled.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/dropdownList.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/dropdownListItemActive.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/handle.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/resetBox.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/resetBoxDisabled.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/sliderTrack.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/LICENSE_NOTES (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/radial/radialUnit.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/radial/radialUnitSelected.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/statusBar.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/testWindowBorder.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/testWindowBorder.texinfo (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/testWindowBorderOver.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/treeView/contract.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/treeView/contractOver.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/treeView/expand.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/textures/ui/nui/terasology/treeView/expandOver.png (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/ui/console.ui (100%) rename engine/src/main/resources/{ => org/destinationsol}/assets/ui/migTestScreen.ui (100%) diff --git a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java index 8e860c98f..de582bf6c 100644 --- a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java +++ b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java @@ -18,25 +18,16 @@ import org.destinationsol.assets.music.AndroidOggMusicFileFormat; import org.destinationsol.assets.sound.AndroidOggSoundFileFormat; import org.destinationsol.assets.sound.OggSoundData; -import org.destinationsol.assets.audio.OggMusic; -import org.destinationsol.assets.audio.OggMusicFileFormat; -import org.destinationsol.assets.audio.OggSound; -import org.destinationsol.assets.audio.OggSoundFileFormat; -import org.destinationsol.assets.emitters.Emitter; -import org.destinationsol.assets.emitters.EmitterFileFormat; -import org.destinationsol.assets.fonts.Font; -import org.destinationsol.assets.fonts.FontFileFormat; -import org.destinationsol.assets.json.Json; -import org.destinationsol.assets.json.JsonDeltaFileFormat; -import org.destinationsol.assets.json.JsonFileFormat; -import org.destinationsol.assets.textures.DSTexture; -import org.destinationsol.assets.textures.DSTextureFileFormat; +import org.destinationsol.assets.music.OggMusicData; +import org.destinationsol.assets.music.OggMusic; +import org.destinationsol.assets.sound.OggSound; import org.destinationsol.assets.ui.UIFormat; import org.destinationsol.assets.ui.UISkinFormat; import org.terasology.gestalt.assets.Asset; import org.terasology.gestalt.assets.AssetData; import org.terasology.gestalt.assets.AssetType; import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.gestalt.assets.format.producer.AssetFileDataProducer; import org.terasology.gestalt.assets.module.ModuleAwareAssetTypeManager; import org.terasology.gestalt.assets.module.ModuleAwareAssetTypeManagerImpl; import org.terasology.gestalt.assets.module.ModuleDependencyResolutionStrategy; @@ -53,7 +44,7 @@ import org.terasology.nui.skin.UISkin; import org.terasology.reflection.copy.CopyStrategyLibrary; import org.terasology.reflection.reflect.ReflectFactory; -import org.terasology.reflection.reflect.ReflectionReflectFactory;. +import org.terasology.reflection.reflect.ReflectionReflectFactory; import java.util.Optional; import java.util.Set; diff --git a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java index 25f5dda79..33ec88d4f 100644 --- a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java +++ b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java @@ -16,6 +16,7 @@ package org.destinationsol.modules; import com.google.common.collect.Sets; +import com.google.common.reflect.Reflection; import org.destinationsol.assets.AssetHelper; import org.destinationsol.assets.Assets; import org.destinationsol.assets.music.OggMusic; @@ -34,13 +35,17 @@ import org.terasology.gestalt.module.Module; import org.terasology.gestalt.module.ModuleEnvironment; import org.terasology.gestalt.module.ModuleFactory; +import org.terasology.gestalt.module.ModuleMetadata; import org.terasology.gestalt.module.ModulePathScanner; import org.terasology.gestalt.module.ModuleRegistry; import org.terasology.gestalt.module.TableModuleRegistry; +import org.terasology.gestalt.module.resources.EmptyFileSource; import org.terasology.gestalt.module.sandbox.APIScanner; import org.terasology.gestalt.module.sandbox.ModuleSecurityManager; import org.terasology.gestalt.module.sandbox.ModuleSecurityPolicy; import org.terasology.gestalt.module.sandbox.StandardPermissionProviderFactory; +import org.terasology.gestalt.naming.Name; +import org.terasology.gestalt.naming.Version; import org.terasology.nui.UIWidget; import java.io.File; @@ -48,6 +53,7 @@ import java.lang.reflect.ReflectPermission; import java.nio.file.Paths; import java.security.Policy; +import java.util.Collections; import java.util.Set; /** @@ -178,6 +184,12 @@ public void init() throws Exception { try { ModuleFactory moduleFactory = new ModuleFactory(); engineModule = moduleFactory.createPackageModule("org.destinationsol"); + // TODO: Find a better way to do this! + Module nuiModule = new Module(new ModuleMetadata(new Name("nui"), new Version("0.2.0")), new EmptyFileSource(), + Collections.emptyList(), new Reflections("org.terasology.nui"), x -> { + String classPackageName = Reflection.getPackageName(x); + return "org.terasology.nui".equals(classPackageName) || classPackageName.startsWith("org.terasology.nui."); + }); // scan for all standard modules registry = new TableModuleRegistry(); @@ -187,6 +199,7 @@ public void init() throws Exception { Set requiredModules = Sets.newHashSet(); registry.add(engineModule); + registry.add(nuiModule); requiredModules.addAll(registry); loadEnvironment(requiredModules); diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index 5d325f579..233af778b 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -20,7 +20,7 @@ import org.destinationsol.CommonDrawer; import org.destinationsol.SolApplication; import org.destinationsol.assets.Assets; -import org.destinationsol.assets.audio.OggSound; +import org.destinationsol.assets.sound.OggSound; import org.terasology.gestalt.assets.ResourceUrn; import org.terasology.input.InputType; import org.terasology.input.MouseInput; diff --git a/engine/src/main/resources/assets/skins/console.skin b/engine/src/main/resources/org/destinationsol/assets/skins/console.skin similarity index 100% rename from engine/src/main/resources/assets/skins/console.skin rename to engine/src/main/resources/org/destinationsol/assets/skins/console.skin diff --git a/engine/src/main/resources/assets/skins/default.skin b/engine/src/main/resources/org/destinationsol/assets/skins/default.skin similarity index 100% rename from engine/src/main/resources/assets/skins/default.skin rename to engine/src/main/resources/org/destinationsol/assets/skins/default.skin diff --git a/engine/src/main/resources/assets/skins/migTestSkin.skin b/engine/src/main/resources/org/destinationsol/assets/skins/migTestSkin.skin similarity index 100% rename from engine/src/main/resources/assets/skins/migTestSkin.skin rename to engine/src/main/resources/org/destinationsol/assets/skins/migTestSkin.skin diff --git a/engine/src/main/resources/assets/textures/ui/nui/area.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/area.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/area.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/area.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/box.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/box.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/box.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/box.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/boxActive.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/boxActive.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/boxActive.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/boxActive.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/boxDisabled.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/boxDisabled.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/boxDisabled.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/boxDisabled.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/boxLight.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/boxLight.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/boxLight.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/boxLight.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/button.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/button.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/button.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/button.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/buttonDown.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/buttonDown.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/buttonDown.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/buttonDown.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/buttonOver.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/buttonOver.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/buttonOver.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/buttonOver.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkbox.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkbox.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/checkbox.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkbox.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxChecked.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxChecked.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/checkboxChecked.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxChecked.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedDisabled.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxCheckedDisabled.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedDisabled.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxCheckedDisabled.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedHover.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxCheckedHover.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/checkboxCheckedHover.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxCheckedHover.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxDisabled.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxDisabled.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/checkboxDisabled.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxDisabled.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/checkboxHover.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxHover.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/checkboxHover.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/checkboxHover.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdown.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdown.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/dropdown.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdown.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdownActive.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownActive.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/dropdownActive.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownActive.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdownDisabled.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownDisabled.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/dropdownDisabled.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownDisabled.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdownList.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownList.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/dropdownList.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownList.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/dropdownListItemActive.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownListItemActive.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/dropdownListItemActive.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/dropdownListItemActive.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/handle.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/handle.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/handle.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/handle.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/resetBox.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/resetBox.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/resetBox.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/resetBox.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/resetBoxDisabled.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/resetBoxDisabled.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/resetBoxDisabled.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/resetBoxDisabled.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/sliderTrack.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/sliderTrack.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/sliderTrack.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/sliderTrack.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/LICENSE_NOTES b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/LICENSE_NOTES similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/LICENSE_NOTES rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/LICENSE_NOTES diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnit.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/radial/radialUnit.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnit.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/radial/radialUnit.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnitSelected.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/radial/radialUnitSelected.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/radial/radialUnitSelected.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/radial/radialUnitSelected.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/statusBar.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/statusBar.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/statusBar.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/statusBar.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorder.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorder.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.texinfo b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorder.texinfo similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorder.texinfo rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorder.texinfo diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorderOver.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorderOver.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/testWindowBorderOver.texinfo diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/LICENSE_NOTES diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contract.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/contract.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contract.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/contract.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contractOver.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/contractOver.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/contractOver.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/contractOver.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expand.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/expand.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expand.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/expand.png diff --git a/engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expandOver.png b/engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/expandOver.png similarity index 100% rename from engine/src/main/resources/assets/textures/ui/nui/terasology/treeView/expandOver.png rename to engine/src/main/resources/org/destinationsol/assets/textures/ui/nui/terasology/treeView/expandOver.png diff --git a/engine/src/main/resources/assets/ui/console.ui b/engine/src/main/resources/org/destinationsol/assets/ui/console.ui similarity index 100% rename from engine/src/main/resources/assets/ui/console.ui rename to engine/src/main/resources/org/destinationsol/assets/ui/console.ui diff --git a/engine/src/main/resources/assets/ui/migTestScreen.ui b/engine/src/main/resources/org/destinationsol/assets/ui/migTestScreen.ui similarity index 100% rename from engine/src/main/resources/assets/ui/migTestScreen.ui rename to engine/src/main/resources/org/destinationsol/assets/ui/migTestScreen.ui From 1931fdb1369315296e523a9442a61c76eabd1b5c Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sat, 11 Jul 2020 19:21:12 +0100 Subject: [PATCH 09/20] Fixed NUI on Android and updated to a JOML-based NUI. --- engine/build.gradle | 12 ++++++++++++ .../java/org/destinationsol/assets/fonts/UIFont.java | 2 +- .../java/org/destinationsol/ui/nui/NUIManager.java | 2 +- .../org/destinationsol/ui/nui/NUIScreenLayer.java | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/engine/build.gradle b/engine/build.gradle index e379f0a5c..c6873816f 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -6,6 +6,7 @@ import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; import org.reflections.scanners.TypeAnnotationsScanner; import org.reflections.util.ConfigurationBuilder; +import org.reflections.util.ClasspathHelper; // Dependencies needed for what our Gradle scripts themselves use. It cannot be included via an external Gradle file :-( buildscript { @@ -13,12 +14,21 @@ buildscript { // External libs - jcenter is Bintray and is supposed to be a superset of Maven Central, but do both just in case jcenter() mavenCentral() + + // HACK: Needed for NUI reflections + mavenLocal() + google() + maven { url "http://artifactory.terasology.org/artifactory/virtual-repo-live" } } dependencies { // Needed for caching reflected data during builds classpath 'org.reflections:reflections:0.9.10' classpath 'dom4j:dom4j:1.6.1' + + // HACK: Needed for NUI reflections + classpath group: 'org.terasology.nui', name: 'nui', version: '0.2' + classpath group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' } } @@ -33,6 +43,7 @@ dependencies { compile(group: 'org.terasology.gestalt', name: 'gestalt-util', version: '7.0.5') compile group: 'org.terasology.nui', name: 'nui', version: '0.2' compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '0.2' + compile group: 'org.terasology', name: 'TeraMath', version: '1.5.0' compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' @@ -66,6 +77,7 @@ task cacheReflections { dirToReflect.mkdirs() Reflections reflections = new Reflections(new ConfigurationBuilder() .addUrls(dirToReflect.toURI().toURL()) + .addUrls(ClasspathHelper.forPackage("org.terasology.nui.widgets")) .setScanners(new TypeAnnotationsScanner(), new SubTypesScanner())) reflections.save(sourceSets.main.output.classesDir.toString() + "/reflections.cache") } diff --git a/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java b/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java index ce7c0e58a..6998110c0 100644 --- a/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java +++ b/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java @@ -17,7 +17,7 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.GlyphLayout; -import org.terasology.math.geom.Vector2i; +import org.joml.Vector2i; import org.terasology.nui.backends.libgdx.LibGDXFont; import java.util.List; diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index 233af778b..bfab01ba8 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -89,7 +89,7 @@ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { } public void update(SolApplication solApplication) { - canvas.processMousePosition(mouse.getPosition()); + canvas.processMousePosition(mouse.getMousePosition()); canvas.setGameTime(System.currentTimeMillis()); for (KeyboardAction action : keyboard.getInputQueue()) { diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java index 38756dbe3..bc6251eda 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java @@ -15,9 +15,9 @@ */ package org.destinationsol.ui.nui; +import org.joml.Vector2i; import org.terasology.input.ButtonState; import org.terasology.input.Keyboard; -import org.terasology.math.geom.Vector2i; import org.terasology.nui.AbstractWidget; import org.terasology.nui.Canvas; import org.terasology.nui.FocusManager; From d80280329b6c964b9b0c020f37b48c401db23b1a Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Fri, 17 Jul 2020 09:38:37 +0100 Subject: [PATCH 10/20] Fixed resize issues and Android compatiblity fixes. --- .../java/org/destinationsol/assets/ui/UISkinFormat.java | 5 ++++- .../main/java/org/destinationsol/menu/ResolutionScreen.java | 2 ++ .../src/main/java/org/destinationsol/ui/nui/NUIManager.java | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java index d79abe1c7..2b07ce3a1 100644 --- a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java +++ b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java @@ -1,6 +1,7 @@ package org.destinationsol.assets.ui; import com.google.common.base.Charsets; +import com.google.common.primitives.UnsignedInts; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; @@ -224,7 +225,9 @@ public Color deserialize(JsonElement json, Type typeOfT, JsonDeserializationCont return new Color(array.get(0).getAsFloat(), array.get(1).getAsFloat(), array.get(2).getAsFloat(), array.get(3).getAsFloat()); } if (json.isJsonPrimitive()) { - return new Color(Integer.parseUnsignedInt(json.getAsString(), 16)); + // NOTE: Integer.parseUnsignedInt is not available on Android API 24 (7.0). + // Since we're still pulling-in Guava, we use it's equivalent. + return new Color(UnsignedInts.parseUnsignedInt(json.getAsString(), 16)); } return null; diff --git a/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java b/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java index caeef26d5..b114199ab 100644 --- a/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java +++ b/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java @@ -79,11 +79,13 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi } if (mode != null) { Gdx.graphics.setFullscreenMode(mode); + solApplication.getNuiManager().resize(mode.width, mode.height); } else { logger.warn("The resolution {}x{} is not supported in fullscreen mode!", options.x, options.y); } } else { Gdx.graphics.setWindowedMode(options.x, options.y); + solApplication.getNuiManager().resize(options.x, options.y); } inputManager.setScreen(solApplication, solApplication.getMenuScreens().options); return; diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index bfab01ba8..65af3c9c1 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -85,7 +85,7 @@ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { UIText.DEFAULT_CURSOR_TEXTURE = whiteTexture; // NOTE: SolApplication::addResizeSubscriber is not intended to be static, so use the instance form for compatibility - solApplication.addResizeSubscriber(() -> canvasRenderer.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight())); + solApplication.addResizeSubscriber(() -> resize(Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight())); } public void update(SolApplication solApplication) { @@ -212,4 +212,8 @@ public Deque getScreens() { public UISkin getDefaultSkin() { return skin; } + + public void resize(int width, int height) { + canvasRenderer.resize(width, height); + } } From 2d32f637964e209bdbc1b5c4266aa87022548d19 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Fri, 17 Jul 2020 17:10:18 +0100 Subject: [PATCH 11/20] Added support for NUI UI scaling. The UI size can now be different to the screen resolution, which is often helpful when running a very high native resolutions. The setting can be found in the Options->Resolution menu from the main menu. --- .../java/org/destinationsol/GameOptions.java | 20 ++++++++++++++++++- .../org/destinationsol/SolApplication.java | 2 +- .../assets/ui/UISkinFormat.java | 2 +- .../destinationsol/menu/ResolutionScreen.java | 15 ++++++++++++-- .../org/destinationsol/ui/nui/NUIManager.java | 10 +++++++++- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/GameOptions.java b/engine/src/main/java/org/destinationsol/GameOptions.java index 8babf82c0..4f7c8388f 100644 --- a/engine/src/main/java/org/destinationsol/GameOptions.java +++ b/engine/src/main/java/org/destinationsol/GameOptions.java @@ -133,6 +133,7 @@ public Volume advance() { public static final int DEFAULT_BUTTON_RIGHT = -1; public static final int DEFAULT_MAP_SCROLL_SPEED = 10; public static final int DEFAULT_MOBILE_MAP_SCROLL_SPEED = 5; + private static final float DEFAULT_NUI_UI_SCALE = 1.0f; public int x; public int y; @@ -177,6 +178,7 @@ public Volume advance() { private int controllerButtonUp; private int controllerButtonDown; private int mapScrollSpeed; + public float nuiUiScale; private ResolutionProvider resolutionProvider; @@ -226,6 +228,7 @@ public GameOptions(boolean mobile, SolFileReader solFileReader) { controllerButtonDown = reader.getInt("controllerButtonDown", DEFAULT_BUTTON_DOWN); canSellEquippedItems = reader.getBoolean("canSellEquippedItems", false); mapScrollSpeed = reader.getInt("mapScrollSpeed", mobile ? DEFAULT_MOBILE_MAP_SCROLL_SPEED : DEFAULT_MAP_SCROLL_SPEED); + nuiUiScale = reader.getFloat("nuiUiScale", DEFAULT_NUI_UI_SCALE); } public void advanceResolution() { @@ -268,6 +271,13 @@ public void advanceMapScrollSpeed() { } } + public void advanceNuiUiScale() { + nuiUiScale += 0.25f; + if (nuiUiScale > 2.0f) { + nuiUiScale = 0.25f; + } + } + /** * Save the configuration settings to file. */ @@ -286,7 +296,7 @@ public void save() { "controllerButtonShoot2", getControllerButtonShoot2(), "controllerButtonAbility", getControllerButtonAbility(), "controllerButtonLeft", getControllerButtonLeft(), "controllerButtonRight", getControllerButtonRight(), "controllerButtonUp", getControllerButtonUp(), "controllerButtonDown", getControllerButtonDown(), - "mapScrollSpeed", getMapScrollSpeed()); + "mapScrollSpeed", getMapScrollSpeed(), "nuiUiScale", getNuiUiScale()); } /** @@ -1005,4 +1015,12 @@ public int getMapScrollSpeed() { public void setMapScrollSpeed(int mapScrollSpeed) { this.mapScrollSpeed = mapScrollSpeed; } + + public float getNuiUiScale() { + return nuiUiScale; + } + + public void setNuiUiScale(float nuiUiScale) { + this.nuiUiScale = nuiUiScale; + } } diff --git a/engine/src/main/java/org/destinationsol/SolApplication.java b/engine/src/main/java/org/destinationsol/SolApplication.java index 1e09a9929..35c3cc1f7 100644 --- a/engine/src/main/java/org/destinationsol/SolApplication.java +++ b/engine/src/main/java/org/destinationsol/SolApplication.java @@ -153,7 +153,7 @@ public void create() { inputManager.setScreen(this, menuScreens.main); parameterAdapterManager = ParameterAdapterManager.createCore(this); - nuiManager = new NUIManager(this, commonDrawer); + nuiManager = new NUIManager(this, commonDrawer, options); } @Override diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java index 2b07ce3a1..1d58503a5 100644 --- a/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java +++ b/engine/src/main/java/org/destinationsol/assets/ui/UISkinFormat.java @@ -226,7 +226,7 @@ public Color deserialize(JsonElement json, Type typeOfT, JsonDeserializationCont } if (json.isJsonPrimitive()) { // NOTE: Integer.parseUnsignedInt is not available on Android API 24 (7.0). - // Since we're still pulling-in Guava, we use it's equivalent. + // Since we still have Guava, we use its equivalent. return new Color(UnsignedInts.parseUnsignedInt(json.getAsString(), 16)); } diff --git a/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java b/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java index b114199ab..00483721a 100644 --- a/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java +++ b/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java @@ -41,18 +41,23 @@ public class ResolutionScreen extends SolUiBaseScreen { private final SolUiControl closeControl; private final SolUiControl resolutionControl; private final SolUiControl fullscreenControl; + private final SolUiControl nuiUIScaleControl; ResolutionScreen(MenuLayout menuLayout, GameOptions gameOptions) { displayDimensions = SolApplication.displayDimensions; - resolutionControl = new SolUiControl(menuLayout.buttonRect(-1, 2), true); + resolutionControl = new SolUiControl(menuLayout.buttonRect(-1, 1), true); resolutionControl.setDisplayName("Resolution"); controls.add(resolutionControl); - fullscreenControl = new SolUiControl(menuLayout.buttonRect(-1, 3), true); + fullscreenControl = new SolUiControl(menuLayout.buttonRect(-1, 2), true); fullscreenControl.setDisplayName("Fullscreen"); controls.add(fullscreenControl); + nuiUIScaleControl = new SolUiControl(menuLayout.buttonRect(-1, 3), true); + nuiUIScaleControl.setDisplayName("Map Pan Speed"); + controls.add(nuiUIScaleControl); + closeControl = new SolUiControl(menuLayout.buttonRect(-1, 4), true, gameOptions.getKeyEscape()); closeControl.setDisplayName("Back"); controls.add(closeControl); @@ -101,6 +106,12 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi options.advanceFullscreen(); } + nuiUIScaleControl.setDisplayName("NUI UI scale: " + options.getNuiUiScale()); + if (nuiUIScaleControl.isJustOff()) { + options.advanceNuiUiScale(); + solApplication.getNuiManager().setUiScale(options.getNuiUiScale()); + } + solApplication.getMenuBackgroundManager().update(); } diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index 65af3c9c1..baecdce15 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -18,6 +18,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import org.destinationsol.CommonDrawer; +import org.destinationsol.GameOptions; import org.destinationsol.SolApplication; import org.destinationsol.assets.Assets; import org.destinationsol.assets.sound.OggSound; @@ -64,7 +65,7 @@ public class NUIManager { private static final String BUTTON_CLICK_URN = "engine:uiHover"; private static final float BUTTON_CLICK_PITCH = 0.9f; - public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { + public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer, GameOptions options) { NUIInputProcessor.CONSUME_INPUT = true; mouse = new LibGDXMouseDevice(); @@ -86,6 +87,8 @@ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer) { // NOTE: SolApplication::addResizeSubscriber is not intended to be static, so use the instance form for compatibility solApplication.addResizeSubscriber(() -> resize(Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight())); + + setUiScale(options.getNuiUiScale()); } public void update(SolApplication solApplication) { @@ -216,4 +219,9 @@ public UISkin getDefaultSkin() { public void resize(int width, int height) { canvasRenderer.resize(width, height); } + + public void setUiScale(float scale) { + canvas.setUiScale(1.0f / scale); + canvasRenderer.setUiScale(scale); + } } From d285cd71e8560964fdfac5e720cfc196a58df34e Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Mon, 20 Jul 2020 21:34:00 +0100 Subject: [PATCH 12/20] Updated NUI to use 2.0.0-SNAPSHOT and added JavaDoc to NUIManager. --- engine/build.gradle | 6 +- .../org/destinationsol/ui/nui/NUIManager.java | 93 +++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/engine/build.gradle b/engine/build.gradle index c6873816f..d6fb66014 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -27,7 +27,7 @@ buildscript { classpath 'dom4j:dom4j:1.6.1' // HACK: Needed for NUI reflections - classpath group: 'org.terasology.nui', name: 'nui', version: '0.2' + classpath group: 'org.terasology.nui', name: 'nui', version: '2.0.0-SNAPSHOT' classpath group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' } } @@ -41,8 +41,8 @@ dependencies { compile(group: 'org.terasology.gestalt', name: 'gestalt-entity-system', version: '7.0.5') compile(group: 'org.terasology.gestalt', name: 'gestalt-module', version: '7.0.5') compile(group: 'org.terasology.gestalt', name: 'gestalt-util', version: '7.0.5') - compile group: 'org.terasology.nui', name: 'nui', version: '0.2' - compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '0.2' + compile group: 'org.terasology.nui', name: 'nui', version: '2.0.0-SNAPSHOT' + compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '2.0.0-SNAPSHOT' compile group: 'org.terasology', name: 'TeraMath', version: '1.5.0' compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index baecdce15..febad79a9 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -49,22 +49,62 @@ import java.util.Iterator; import java.util.LinkedList; +/** + * The NUI Manager is responsible for the initialisation and interaction between the NUI library and the game. + * It manages the rendering and update cycles of NUI widgets, which are contained in {@link NUIScreenLayer} + * containers. Each NUIScreenLayer manages its own UI-specific logic and rendering. + */ public class NUIManager { + /** + * This LibGDX renderer used for NUI. It shares a SpriteBatch with the main game, although not a ShapeRenderer. + */ private LibGDXCanvasRenderer canvasRenderer; + /** + * The game's canvas, which is used for all NUI rendering operations. See also {@link NUIManager#canvasRenderer}. + */ private CanvasImpl canvas; + /** + * A blank white texture, used by-default for the text cursor. + */ private UITextureRegion whiteTexture; + /** + * The NUI mouse device. Receives input directly form LibGDX, independently of the game. + */ private MouseDevice mouse; + /** + * The NUI keyboard device. Receives input directly from LibHDX, independently of the game. + */ private KeyboardDevice keyboard; + /** + * This allows NUI to determine which widgets are in-focus at the moment, which is used primarily for tabbing. + */ private FocusManager focusManager; + /** + * The default UI skin used by all widgets. + */ private UISkin skin; + /** + * The UI stack. The elements are rendered from most recently added to least recent, so a stack-like structure + * was used. + */ private Deque uiScreens = new LinkedList<>(); private static final String WHITE_TEXTURE_URN = "engine:uiWhiteTex"; private static final String DEFAULT_SKIN_URN = "engine:default"; private static final String BUTTON_CLICK_URN = "engine:uiHover"; + /** + * The value 0.9 was found from {@link org.destinationsol.ui.SolInputManager#playClick}, so it was copied here to + * retain the same click sound as the built-in UI. + */ private static final float BUTTON_CLICK_PITCH = 0.9f; + /** + * Creates and initialises a new NUIManager instance, which involves initialising a canvas and NUI input handlers. + * @param solApplication the application to use for initialisation + * @param commonDrawer used to directly access the game's LibGDX {@link com.badlogic.gdx.graphics.g2d.SpriteBatch} + * @param options used to initialise the UI scale with its previously-saved value + */ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer, GameOptions options) { NUIInputProcessor.CONSUME_INPUT = true; @@ -91,6 +131,10 @@ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer, Game setUiScale(options.getNuiUiScale()); } + /** + * Processes NUI input events (Keyboard and Mouse) and updates all UI layers. + * @param solApplication the application to use + */ public void update(SolApplication solApplication) { canvas.processMousePosition(mouse.getMousePosition()); canvas.setGameTime(System.currentTimeMillis()); @@ -152,6 +196,10 @@ public void update(SolApplication solApplication) { } } + /** + * Renders all UI layers. + * @param gameDrawer used to directly access the game's LibGDX {@link com.badlogic.gdx.graphics.g2d.SpriteBatch} + */ public void draw(CommonDrawer gameDrawer) { gameDrawer.getSpriteBatch().flush(); @@ -170,10 +218,18 @@ public void draw(CommonDrawer gameDrawer) { gameDrawer.getSpriteBatch().flush(); } + /** + * Obtains the topmost screen (rendered on-top of all others) + * @return the topmost screen + */ public NUIScreenLayer getTopScreen() { return uiScreens.peek(); } + /** + * Pushes a screen onto the UI stack. + * @param layer the screen to add + */ public void pushScreen(NUIScreenLayer layer) { uiScreens.push(layer); @@ -182,6 +238,10 @@ public void pushScreen(NUIScreenLayer layer) { layer.initialise(); } + /** + * Removes the topmost screen from the UI stack and returns it. + * @return the topmost screen + */ public NUIScreenLayer popScreen() { if (!uiScreens.isEmpty()) { uiScreens.peek().onRemoved(); @@ -189,15 +249,29 @@ public NUIScreenLayer popScreen() { return uiScreens.pop(); } + /** + * Removes a screen form the UI stack. It is no longer updated or drawn. + * @param screen the screen to remove + */ public void removeScreen(NUIScreenLayer screen) { screen.onRemoved(); uiScreens.remove(screen); } + /** + * States if a screen is currently present on the UI stack. + * @param screen the screen to search for + * @return true if the screen is currently on the UI stack, otherwise false + */ public boolean hasScreen(NUIScreenLayer screen) { return uiScreens.contains(screen); } + /** + * States if a screen of a specified type is present on the UI stack. + * @param type the type of screen to search for + * @return true if a screen of the specified type is currently on the UI stack, otherwise false + */ public boolean hasScreenOfType(Class type) { for (NUIScreenLayer screenLayer : uiScreens) { if (screenLayer.getClass().isAssignableFrom(type)) { @@ -208,18 +282,37 @@ public boolean hasScreenOfType(Class type) { return false; } + /** + * Returns all of the UI screens currently on the UI stack. + * @return the UI stack + */ public Deque getScreens() { return uiScreens; } + /** + * Returns the default {@link UISkin} for widgets. + * @return the default {@link UISkin} + */ public UISkin getDefaultSkin() { return skin; } + /** + * Re-sizes the current canvas to a particular width and height. This is not always the same as the game's current + * rendering resolution. + * @param width the width to use + * @param height the height to use + */ public void resize(int width, int height) { canvasRenderer.resize(width, height); } + /** + * Sets the UI scale to a specified value. This will internally render the UI at specified scale and up-scale it + * to the target resolution. + * @param scale the new UI scale to use + */ public void setUiScale(float scale) { canvas.setUiScale(1.0f / scale); canvasRenderer.setUiScale(scale); From 2fb8edbe479fef2a38875c9d9c1c362eaeae3f5b Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Mon, 20 Jul 2020 22:04:39 +0100 Subject: [PATCH 13/20] Added JavaDoc for NUIScreenLayer. --- .../destinationsol/ui/nui/NUIScreenLayer.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java index bc6251eda..8657cadcc 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIScreenLayer.java @@ -29,23 +29,50 @@ import java.util.Collections; import java.util.Iterator; +/** + * A specialised {@link UIWidget} designed to contain the widgets comprising a single UI screen (or screen layer). + */ public abstract class NUIScreenLayer extends AbstractWidget { + /** + * The contents of the UI screen. It contains all of the widgets in the screen and can be queried with the + * {@link #find} method. + */ @LayoutConfig protected UIWidget contents; + /** + * The focus manager assigned to the UI screen. + */ protected FocusManager focusManager; + /** + * The game's NUI Manager. + */ protected NUIManager nuiManager; + /** + * This should just render the widgets contained in the UI screen, however it can be overridden to render custom + * graphics as well. + * @param canvas the canvas to draw on + */ @Override public void onDraw(Canvas canvas) { canvas.drawWidget(contents); } + /** + * This updates the widgets contained in the UI screen. It is called every cycle and can therefore be used for + * updating the contents of the widgets as well. + * @param delta the time elapsed since the last update cycle + */ @Override public void update(float delta) { super.update(delta); contents.update(delta); } + /** + * UI Screens can not by-default become focused themselves, as the focus should be on their contents instead. + * @return false, by default + */ @Override public boolean canBeFocus() { return false; @@ -63,6 +90,11 @@ public Vector2i getPreferredContentSize(Canvas canvas, Vector2i sizeHint) { return sizeHint; } + /** + * UI Screens can potentially occupy any size, as their contents is not restricted. + * @param canvas the canvas to render to + * @return the maximum possible size (Integer.MAX_VALUE, Integer.MAX_VALUE). + */ @Override public Vector2i getMaxContentSize(Canvas canvas) { return new Vector2i(Integer.MAX_VALUE, Integer.MAX_VALUE); @@ -81,6 +113,12 @@ public Iterator iterator() { return Arrays.asList(contents).iterator(); } + /** + * This manages by-default the escape key closing the UI screen, however it can be overridden for more specific + * behaviour, such (for example) as pressing a certain key to trigger a sub-menu. + * @param event the key event generated + * @return true, if the event should be consumed, otherwise false + */ @Override public boolean onKeyEvent(NUIKeyEvent event) { if (escapeCloses() && event.getState() == ButtonState.UP && event.getKey() == Keyboard.Key.ESCAPE) { @@ -91,32 +129,64 @@ public boolean onKeyEvent(NUIKeyEvent event) { return super.onKeyEvent(event); } + /** + * Called to initialise the UI screen, allowing it to register widget callbacks and assign widget values + * programmatically. This is called whenever the UI screen becomes visible. + */ public void initialise() { } + /** + * Called when the UI screen is removed from display. + */ public void onRemoved() { } + /** + * States if the inputs received by this UI screen should not be received by other UI screens underneath. + * @return true if inputs should be blocked, otherwise false + */ public boolean isBlockingInput() { return false; } + /** + * Is this UI screen closed when the escape key is pressed? + * @return true, if the screen should be closed + */ protected boolean escapeCloses() { return true; } + /** + * Sets the focus manager to use. + * Primary usage is in {@link NUIManager#pushScreen} + * @param focusManager the focus manager to use. + */ void setFocusManager(FocusManager focusManager) { this.focusManager = focusManager; } + /** + * Returns the focus manager currently assigned to this UI screen. + * @return the currently assigned focus manager + */ protected FocusManager getFocusManager() { return focusManager; } + /** + * Sets the game's NUI Manager. + * @param nuiManager the game's NUI Manager + */ void setNuiManager(NUIManager nuiManager) { this.nuiManager = nuiManager; } + /** + * Returns the game's NUI Manager. + * @return the game's NUI Manager + */ protected NUIManager getNuiManager() { return nuiManager; } From 7d0f9aabb738d77dca72ce7d47a47336e2c6fe5a Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Mon, 20 Jul 2020 22:07:12 +0100 Subject: [PATCH 14/20] Added minor JavaDoc for the UI screens. --- .../java/org/destinationsol/ui/nui/screens/ConsoleScreen.java | 4 ++++ .../java/org/destinationsol/ui/nui/screens/MigTestScreen.java | 3 +++ 2 files changed, 7 insertions(+) diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java index f7a2e8685..8d3ccce37 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/ConsoleScreen.java @@ -33,6 +33,10 @@ import java.util.List; +/** + * The console screen. You can enter commands into this UI and they will be executed. The logic is in {@link Console}. + * This was taken from Terasology originally. + */ public class ConsoleScreen extends NUIScreenLayer { private Console console; private UICommandEntry commandLine; diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java index 498f40ac5..36fc5b6f4 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java @@ -28,6 +28,9 @@ import java.util.Iterator; import java.util.List; +/** + * A test screen used to verify that NUI widgets render and interact correctly. It was taken from Terasology. + */ public class MigTestScreen extends NUIScreenLayer { @Override public void initialise() { From 24c2345e86948ebfe35a8c2236e8d3eda744b2d1 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Mon, 20 Jul 2020 22:16:09 +0100 Subject: [PATCH 15/20] Updated NUI module version in ModuleManager and minor explanatory comment additions. --- .../src/main/java/org/destinationsol/assets/AssetHelper.java | 1 + .../src/main/java/org/destinationsol/assets/fonts/UIFont.java | 3 ++- .../java/org/destinationsol/assets/textures/DSTexture.java | 4 ++++ .../main/java/org/destinationsol/modules/ModuleManager.java | 2 +- .../src/main/java/org/destinationsol/ui/nui/NUIManager.java | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java index de582bf6c..5a6249690 100644 --- a/engine/src/main/java/org/destinationsol/assets/AssetHelper.java +++ b/engine/src/main/java/org/destinationsol/assets/AssetHelper.java @@ -73,6 +73,7 @@ public void init(ModuleEnvironment environment, ComponentManager componentManage new ModuleEnvironmentDependencyProvider(environment))), componentManager, assetTypeManager.getAssetManager()).create()); + // The NUI widgets are loaded here so that they can be found when reading the UI JSON files (in UIFormat.UIWidgetTypeAdapter) ReflectFactory reflectFactory = new ReflectionReflectFactory(); WidgetLibrary widgetLibrary = new WidgetLibrary(environment, reflectFactory, new CopyStrategyLibrary(reflectFactory)); for (Class widgetClass : environment.getSubtypesOf(UIWidget.class)) { diff --git a/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java b/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java index 6998110c0..ac1746086 100644 --- a/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java +++ b/engine/src/main/java/org/destinationsol/assets/fonts/UIFont.java @@ -23,7 +23,8 @@ import java.util.List; /** - * This class wraps a {@link Font} asset in order to adapt it to NUI's LibGDX back-end. + * This class wraps a {@link Font} asset in order to adapt it to NUI's LibGDX back-end. It handles font scaling, + * so that NUI renders correctly. */ public class UIFont extends LibGDXFont { private float fontScale; diff --git a/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java b/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java index d97f8b804..21356c29d 100644 --- a/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java +++ b/engine/src/main/java/org/destinationsol/assets/textures/DSTexture.java @@ -40,6 +40,10 @@ public Texture getTexture() { return dsTextureData.getTexture(); } + /** + * Obtains the NUI {@link UITextureRegion} associated with this texture. + * @return the assoicated UI texture + */ public UITextureRegion getUiTexture() { return dsTextureData; } diff --git a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java index 33ec88d4f..09513c58b 100644 --- a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java +++ b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java @@ -185,7 +185,7 @@ public void init() throws Exception { ModuleFactory moduleFactory = new ModuleFactory(); engineModule = moduleFactory.createPackageModule("org.destinationsol"); // TODO: Find a better way to do this! - Module nuiModule = new Module(new ModuleMetadata(new Name("nui"), new Version("0.2.0")), new EmptyFileSource(), + Module nuiModule = new Module(new ModuleMetadata(new Name("nui"), new Version("2.0.0-SNAPSHOT")), new EmptyFileSource(), Collections.emptyList(), new Reflections("org.terasology.nui"), x -> { String classPackageName = Reflection.getPackageName(x); return "org.terasology.nui".equals(classPackageName) || classPackageName.startsWith("org.terasology.nui."); diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index febad79a9..46f40a906 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -122,6 +122,7 @@ public NUIManager(SolApplication solApplication, CommonDrawer commonDrawer, Game OggSound sound = Assets.getSound(BUTTON_CLICK_URN); sound.setBasePitch(BUTTON_CLICK_PITCH); + // NUI widgets do not know how to obtain assets directly, so we need to provide defaults values here. UIButton.DEFAULT_CLICK_SOUND = sound; UIText.DEFAULT_CURSOR_TEXTURE = whiteTexture; From 6f0f9e7cd53dc5b0a9ee0aec0eb57b1246efc824 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sat, 15 Aug 2020 11:11:21 +0100 Subject: [PATCH 16/20] Updated NUI to version 2.0.0. --- engine/build.gradle | 4 ++-- .../main/java/org/destinationsol/modules/ModuleManager.java | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/engine/build.gradle b/engine/build.gradle index d6fb66014..62c4fc7eb 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -41,8 +41,8 @@ dependencies { compile(group: 'org.terasology.gestalt', name: 'gestalt-entity-system', version: '7.0.5') compile(group: 'org.terasology.gestalt', name: 'gestalt-module', version: '7.0.5') compile(group: 'org.terasology.gestalt', name: 'gestalt-util', version: '7.0.5') - compile group: 'org.terasology.nui', name: 'nui', version: '2.0.0-SNAPSHOT' - compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '2.0.0-SNAPSHOT' + compile group: 'org.terasology.nui', name: 'nui', version: '2.0.0' + compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '2.0.0' compile group: 'org.terasology', name: 'TeraMath', version: '1.5.0' compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' diff --git a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java index 09513c58b..d466bf7c3 100644 --- a/engine/src/main/java/org/destinationsol/modules/ModuleManager.java +++ b/engine/src/main/java/org/destinationsol/modules/ModuleManager.java @@ -184,8 +184,10 @@ public void init() throws Exception { try { ModuleFactory moduleFactory = new ModuleFactory(); engineModule = moduleFactory.createPackageModule("org.destinationsol"); - // TODO: Find a better way to do this! - Module nuiModule = new Module(new ModuleMetadata(new Name("nui"), new Version("2.0.0-SNAPSHOT")), new EmptyFileSource(), + // In order for the NUI widgets to be detected, they first need to be found and cached. The build script + // reflects over the NUI jar and saves a list of all the widgets within the engine's reflections.cache. + // TODO: Find a better way to do this. + Module nuiModule = new Module(new ModuleMetadata(new Name("nui"), new Version("2.0.0")), new EmptyFileSource(), Collections.emptyList(), new Reflections("org.terasology.nui"), x -> { String classPackageName = Reflection.getPackageName(x); return "org.terasology.nui".equals(classPackageName) || classPackageName.startsWith("org.terasology.nui."); From fa519b4f47a34771e3fdfa70ca9c31e317a3ac43 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sun, 16 Aug 2020 12:46:11 +0100 Subject: [PATCH 17/20] Removed dependency on TeraMath. The only classes using TeraMath types were part of the NUI-related code, which should have been using JOML types instead. --- engine/build.gradle | 1 - .../src/main/java/org/destinationsol/assets/ui/UIFormat.java | 2 +- .../org/destinationsol/ui/nui/screens/MigTestScreen.java | 5 ----- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/engine/build.gradle b/engine/build.gradle index 62c4fc7eb..cdb2b707a 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -43,7 +43,6 @@ dependencies { compile(group: 'org.terasology.gestalt', name: 'gestalt-util', version: '7.0.5') compile group: 'org.terasology.nui', name: 'nui', version: '2.0.0' compile group: 'org.terasology.nui', name: 'nui-libgdx', version: '2.0.0' - compile group: 'org.terasology', name: 'TeraMath', version: '1.5.0' compile group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' diff --git a/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java b/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java index e916081e7..2e03b1a4e 100644 --- a/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java +++ b/engine/src/main/java/org/destinationsol/assets/ui/UIFormat.java @@ -28,6 +28,7 @@ import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; import org.destinationsol.assets.Assets; +import org.joml.Vector2i; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terasology.gestalt.assets.ResourceUrn; @@ -35,7 +36,6 @@ import org.terasology.gestalt.assets.format.AssetDataFile; import org.terasology.gestalt.assets.management.AssetManager; import org.terasology.gestalt.assets.module.annotations.RegisterAssetFileFormat; -import org.terasology.math.geom.Vector2i; import org.terasology.nui.Color; import org.terasology.nui.LayoutHint; import org.terasology.nui.UILayout; diff --git a/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java b/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java index 36fc5b6f4..4b0d5dbe4 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/screens/MigTestScreen.java @@ -16,16 +16,11 @@ package org.destinationsol.ui.nui.screens; import org.destinationsol.ui.nui.NUIScreenLayer; -import org.terasology.math.geom.Vector2i; -import org.terasology.nui.Canvas; -import org.terasology.nui.UIWidget; import org.terasology.nui.widgets.UIDropdown; import org.terasology.nui.widgets.UIDropdownScrollable; import org.terasology.nui.widgets.UIList; import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; import java.util.List; /** From f362af5dc4676b6aba76e5b118ec5e12c407c3e0 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sun, 16 Aug 2020 12:49:14 +0100 Subject: [PATCH 18/20] Changed "Map Pan Speed" text to "NUI UI scale" to accurately describe the UI button. --- .../src/main/java/org/destinationsol/menu/ResolutionScreen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java b/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java index 00483721a..70fe9bef8 100644 --- a/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java +++ b/engine/src/main/java/org/destinationsol/menu/ResolutionScreen.java @@ -55,7 +55,7 @@ public class ResolutionScreen extends SolUiBaseScreen { controls.add(fullscreenControl); nuiUIScaleControl = new SolUiControl(menuLayout.buttonRect(-1, 3), true); - nuiUIScaleControl.setDisplayName("Map Pan Speed"); + nuiUIScaleControl.setDisplayName("NUI UI scale"); controls.add(nuiUIScaleControl); closeControl = new SolUiControl(menuLayout.buttonRect(-1, 4), true, gameOptions.getKeyEscape()); From d13df9a84abe0129a20a8af13146e7ec562daeb8 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sun, 16 Aug 2020 12:58:35 +0100 Subject: [PATCH 19/20] Changed UI scale to increase visible size with larger values. --- .../src/main/java/org/destinationsol/ui/nui/NUIManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java index 46f40a906..808858428 100644 --- a/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java +++ b/engine/src/main/java/org/destinationsol/ui/nui/NUIManager.java @@ -315,7 +315,7 @@ public void resize(int width, int height) { * @param scale the new UI scale to use */ public void setUiScale(float scale) { - canvas.setUiScale(1.0f / scale); - canvasRenderer.setUiScale(scale); + canvas.setUiScale(scale); + canvasRenderer.setUiScale(1.0f / scale); } } From 1dafc8dc9f1e86a66c51a73748843d46beee9f40 Mon Sep 17 00:00:00 2001 From: Benjamin Amos Date: Sun, 16 Aug 2020 13:01:57 +0100 Subject: [PATCH 20/20] Removed excess menuControl.update calls from MainGameScreen. --- .../java/org/destinationsol/game/screens/MainGameScreen.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java index 0a9346f67..f013c2dbf 100644 --- a/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java +++ b/engine/src/main/java/org/destinationsol/game/screens/MainGameScreen.java @@ -309,9 +309,6 @@ public void updateCustom(SolApplication solApplication, SolInputManager.InputPoi controls.forEach(x -> x.setEnabled(true)); consoleControlGrave.setEnabled(true); consoleControlF1.setEnabled(true); - - menuControl.update(inputPointers, false, false, inputMan, solApplication); - menuControl.update(inputPointers, false, false, inputMan, solApplication); } if (consoleControlGrave.isJustOff() || consoleControlF1.isJustOff()) {