aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsg-programs <msgdoesstuff@gmail.com>2023-07-16 14:44:32 +0200
committermsg-programs <msgdoesstuff@gmail.com>2023-07-16 14:44:32 +0200
commitf9740d423146fafa83a85704580368cdc1131377 (patch)
treec78cce959f68f77ee669a304f329e2763c61beac
parentb63b73b2815db7e1442981e550980e5784c33e78 (diff)
downloadSkyblocker-f9740d423146fafa83a85704580368cdc1131377.tar.gz
Skyblocker-f9740d423146fafa83a85704580368cdc1131377.tar.bz2
Skyblocker-f9740d423146fafa83a85704580368cdc1131377.zip
POC for JSON-based tabhud config.
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java1
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java11
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PipelineStage.java14
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PlaceStage.java29
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenBuilder.java94
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenMaster.java76
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java4
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java29
-rw-r--r--src/main/resources/assets/skyblocker/tabhud/assignment.json11
-rw-r--r--src/main/resources/assets/skyblocker/tabhud/empty_screen.json17
-rw-r--r--src/main/resources/assets/skyblocker/tabhud/garden_info_screen.json88
-rw-r--r--src/main/resources/assets/skyblocker/tabhud/generic_info_screen.json69
13 files changed, 433 insertions, 14 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
index cc712405..461817ce 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java
@@ -17,6 +17,7 @@ import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
import me.xmrvizzy.skyblocker.skyblock.quicknav.QuickNav;
import me.xmrvizzy.skyblocker.skyblock.rift.TheRift;
import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud;
+import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.ScreenMaster;
import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr;
import me.xmrvizzy.skyblocker.utils.*;
import me.xmrvizzy.skyblocker.utils.title.TitleContainer;
diff --git a/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java b/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java
index ef65190f..b3d78fa8 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/mixin/PlayerListHudMixin.java
@@ -9,6 +9,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud;
import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.Screen;
+import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.ScreenBuilder;
+import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.ScreenMaster;
import me.xmrvizzy.skyblocker.utils.Utils;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@@ -45,9 +47,14 @@ public class PlayerListHudMixin {
int w = scaledW;
int h = MinecraftClient.getInstance().getWindow().getScaledHeight();
+ float scale = SkyblockerConfig.get().general.tabHud.tabHudScale / 100f;
+ w = (int) (w / scale);
+ h = (int) (h / scale);
+
try {
- Screen screen = Screen.getCorrect(w, h, footer);
- screen.render(context);
+ ScreenMaster.render(context, w,h,footer);
+ // Screen screen = Screen.getCorrect(w, h, footer);
+ // screen.render(context);
info.cancel();
} catch (Exception e) {
TabHud.LOGGER.error("Drawing default hud. Reason: Screen exception {}", e);
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PipelineStage.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PipelineStage.java
new file mode 100644
index 00000000..d33078d8
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PipelineStage.java
@@ -0,0 +1,14 @@
+package me.xmrvizzy.skyblocker.skyblock.tabhud.screens;
+
+import java.util.ArrayList;
+
+import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget;
+
+public abstract class PipelineStage {
+
+ protected ArrayList<Widget> primary = null;
+ protected ArrayList<Widget> secondary = null;
+
+ public abstract void run(int screenW, int screenH);
+
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PlaceStage.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PlaceStage.java
new file mode 100644
index 00000000..aba952a0
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/PlaceStage.java
@@ -0,0 +1,29 @@
+package me.xmrvizzy.skyblocker.skyblock.tabhud.screens;
+
+import java.util.ArrayList;
+
+import com.google.gson.JsonObject;
+import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget;
+
+public class PlaceStage extends PipelineStage {
+
+ private String where;
+
+ public PlaceStage(ScreenBuilder builder, JsonObject descr) {
+ this.where = descr.get("where").getAsString();
+ this.primary = new ArrayList<Widget>(descr.getAsJsonArray("apply_to")
+ .asList()
+ .stream()
+ .map(x -> builder.getInstance(x.getAsString()))
+ .toList());
+ }
+
+ public void run(int screenW, int screenH) {
+ for (Widget wid : primary) {
+ if (where.equals("center")) {
+ wid.setY((screenH - wid.getHeight()) / 2);
+ wid.setX((screenW - wid.getWidth()) / 2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java
index 6d06c637..2673e1df 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/Screen.java
@@ -26,13 +26,12 @@ import me.xmrvizzy.skyblocker.skyblock.tabhud.screens.playerList.PlayerListScree
import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerLocator;
import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget;
import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;
public class Screen {
private ArrayList<Widget> widgets = new ArrayList<>();
- private int w, h;
+ public int w, h;
public Screen(int w, int h) {
float scale = SkyblockerConfig.get().general.tabHud.tabHudScale / 100f;
@@ -41,6 +40,7 @@ public class Screen {
}
public static Screen getCorrect(int w, int h, Text footer) {
+
if (TabHud.genericTgl.isPressed()) {
return Screen.correctGenericScrn(w, h, footer);
} else if (TabHud.playerTgl.isPressed()) {
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenBuilder.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenBuilder.java
new file mode 100644
index 00000000..c9c4ad18
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenBuilder.java
@@ -0,0 +1,94 @@
+package me.xmrvizzy.skyblocker.skyblock.tabhud.screens;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.EmptyWidget;
+import me.xmrvizzy.skyblocker.skyblock.tabhud.widget.Widget;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+public class ScreenBuilder {
+
+ private ArrayList<PipelineStage> layoutPipeline = new ArrayList<>();
+
+ private ArrayList<Widget> instances = new ArrayList<>();
+ private HashMap<String, Widget> objectMap = new HashMap<>();
+
+
+ public ScreenBuilder(String jsonfile) throws IOException {
+
+ Identifier ident = new Identifier(SkyblockerMod.NAMESPACE, "tabhud/" + jsonfile + ".json");
+ BufferedReader reader = MinecraftClient.getInstance().getResourceManager().openAsReader(ident);
+ JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
+ reader.close();
+
+ JsonArray widgets = json.getAsJsonArray("widgets");
+ JsonArray layout = json.getAsJsonArray("layout");
+
+ for (JsonElement w : widgets) {
+ JsonObject widget = w.getAsJsonObject();
+ String name = widget.get("name").getAsString();
+ String alias = widget.get("alias").getAsString();
+
+ JsonElement args = widget.get("args");
+ JsonObject argsObj = (args == null) ? null : args.getAsJsonObject();
+
+ Widget wid = instanceFrom(name, argsObj);
+ objectMap.put(alias, wid);
+ instances.add(wid);
+ }
+
+ for (JsonElement l : layout) {
+ layoutPipeline.add(createStage(l.getAsJsonObject()));
+ }
+
+ }
+
+ public Widget instanceFrom(String name, JsonObject args) {
+ return switch (name) {
+ case "EmptyWidget" -> new EmptyWidget();
+ default -> new EmptyWidget();
+ };
+ }
+
+ public PipelineStage createStage(JsonObject descr) {
+
+ String op = descr.get("op").getAsString();
+
+ switch (op) {
+ case "place":
+ return new PlaceStage(this, descr);
+ }
+ return null;
+ }
+
+ public Widget getInstance(String name) {
+ return this.objectMap.get(name);
+ }
+
+ public void run(DrawContext context, int screenW, int screenH, Text footer) {
+
+ for (Widget w : instances) {
+ w.update();
+ }
+ for (PipelineStage ps : layoutPipeline) {
+ ps.run(screenW, screenH);
+ }
+ for (Widget w : instances) {
+ w.render(context);
+ }
+ }
+
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenMaster.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenMaster.java
new file mode 100644
index 00000000..02b595d1
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/screens/ScreenMaster.java
@@ -0,0 +1,76 @@
+package me.xmrvizzy.skyblocker.skyblock.tabhud.screens;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+public class ScreenMaster {
+
+ private static final Identifier ASSIGNMENT_JSON = new Identifier(SkyblockerMod.NAMESPACE, "tabhud/assignment.json");
+ private static final Logger LOGGER = LoggerFactory.getLogger("skyblocker");
+
+ private static HashMap<String, ScreenBuilder> screenAMap = new HashMap<>();
+ // private static HashMap<String, ScreenBuilder> screenBMap = new HashMap<>();
+ // private static HashMap<String, ScreenBuilder> screenCMap = new HashMap<>();
+
+ static {
+ init();
+ }
+
+ public static void init() {
+ try (BufferedReader reader = MinecraftClient.getInstance().getResourceManager().openAsReader(ASSIGNMENT_JSON)) {
+
+ JsonObject json = JsonParser.parseReader(reader).getAsJsonObject();
+ JsonObject screenA = json.getAsJsonObject("screenA");
+ for (Entry<String, JsonElement> entry : screenA.entrySet()) {
+ screenAMap.put(entry.getKey(), new ScreenBuilder(entry.getValue().getAsString()));
+ }
+
+ } catch (IOException ioex) {
+ LOGGER.info("[Skyblocker] Couldn't load tabhud config!");
+ ioex.printStackTrace();
+ }
+ }
+
+ public static void render(DrawContext context, int w, int h, Text footer) {
+ screenAMap.get("default").run(context, w, h, footer);
+ }
+}
+
+/*
+ *
+ * stackWidgetsH
+stackWidgetsW
+--> stack (direction?) horiz/vert (align?) center/top/bottom/left/right
+
+centerH
+centerW
+center
+--> center (center/horiz/vert)
+----> place (one) (where?) center/top/bot/left/right/[corners]
+
+offCenterL
+offCenterR
+--> offCenter left/right/top/bot
+----> offsetPlace (where?) center/left/right/top/bot (offset to where?) left/right/top/bot
+
+----> align (any) (reference?) left, leftOfCenter, horizontalCenter, rightOfCenter, right, top, topOfCenter, verticalCenter, botOfCenter, bot
+
+collideAgainstL
+collideAgainstR
+--> collideAgainst (from where?) left/right/top/bot
+ */ \ No newline at end of file
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java
index 52d6cfbd..61da439a 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/EmptyWidget.java
@@ -14,7 +14,11 @@ public class EmptyWidget extends Widget {
public EmptyWidget() {
super(TITLE, Formatting.RED.getColorValue());
+ }
+ @Override
+ public void update() {
+ super.update();
Text info = Text.of("No info for this area!");
PlainTextComponent inf = new PlainTextComponent(info);
this.addComponent(inf);
diff --git a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java
index 33f77933..15b2adf2 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/skyblock/tabhud/widget/Widget.java
@@ -45,12 +45,17 @@ public abstract class Widget {
}
public final void addComponent(Component c) {
- components.add(c);
+ this.components.add(c);
+ }
+
+ public void update() {
+ this.components.clear();
}
/**
* Shorthand function for simple components.
- * If the entry at idx has the format "<textA>: <textB>", an IcoTextComponent is added as such:
+ * If the entry at idx has the format "<textA>: <textB>", an IcoTextComponent is
+ * added as such:
* [ico] [string] [textB.formatted(fmt)]
*/
public final void addSimpleIcoText(ItemStack ico, String string, Formatting fmt, int idx) {
@@ -60,9 +65,12 @@ public abstract class Widget {
/**
* Calculate the size of this widget.
- * <b>Must be called before returning from the widget constructor and after all components are added!</b>
+ * <b>Must be called before returning from the widget constructor and after all
+ * components are added!</b>
*/
public final void pack() {
+ h = 0;
+ w = 0;
for (Component c : components) {
h += c.getHeight() + Component.PAD_L;
w = Math.max(w, c.getWidth() + Component.PAD_S);
@@ -111,7 +119,7 @@ public abstract class Widget {
* Draw this widget, possibly with a background
*/
public final void render(DrawContext context, boolean hasBG) {
- MatrixStack ms = context.getMatrices();
+ MatrixStack ms = context.getMatrices();
// not sure if this is the way to go, but it fixes Z-layer issues
// like blocks being rendered behind the BG and the hotbar clipping into things
@@ -124,9 +132,9 @@ public abstract class Widget {
// move above other UI elements
ms.translate(0, 0, 200);
if (hasBG) {
- context.fill(x + 1, y, x + w - 1, y + h, COL_BG_BOX);
- context.fill(x, y + 1, x + 1, y + h - 1, COL_BG_BOX);
- context.fill(x + w - 1, y + 1, x + w, y + h - 1, COL_BG_BOX);
+ context.fill(x + 1, y, x + w - 1, y + h, COL_BG_BOX);
+ context.fill(x, y + 1, x + 1, y + h - 1, COL_BG_BOX);
+ context.fill(x + w - 1, y + 1, x + w, y + h - 1, COL_BG_BOX);
}
// move above background (if exists)
ms.translate(0, 0, 100);
@@ -163,9 +171,10 @@ public abstract class Widget {
}
/**
- * If the entry at idx has the format "[textA]: [textB]", the following is returned:
+ * If the entry at idx has the format "[textA]: [textB]", the following is
+ * returned:
* [entryName] [textB.formatted(contentFmt)]
- */
+ */
public static Text simpleEntryText(int idx, String entryName, Formatting contentFmt) {
String src = PlayerListMgr.strAt(idx);
@@ -185,7 +194,7 @@ public abstract class Widget {
/**
* @return [entryName] [entryContent.formatted(contentFmt)]
- */
+ */
public static Text simpleEntryText(String entryContent, String entryName, Formatting contentFmt) {
return Text.literal(entryName).append(Text.literal(entryContent).formatted(contentFmt));
}
diff --git a/src/main/resources/assets/skyblocker/tabhud/assignment.json b/src/main/resources/assets/skyblocker/tabhud/assignment.json
new file mode 100644
index 00000000..a7b8dd80
--- /dev/null
+++ b/src/main/resources/assets/skyblocker/tabhud/assignment.json
@@ -0,0 +1,11 @@
+{
+ "screenA": {
+ "default": "generic_info_screen"
+ },
+ "screenB": {
+ "default": "empty_screen"
+ },
+ "screenC": {
+ "default": "empty_screen"
+ }
+} \ No newline at end of file
diff --git a/src/main/resources/assets/skyblocker/tabhud/empty_screen.json b/src/main/resources/assets/skyblocker/tabhud/empty_screen.json
new file mode 100644
index 00000000..0252940a
--- /dev/null
+++ b/src/main/resources/assets/skyblocker/tabhud/empty_screen.json
@@ -0,0 +1,17 @@
+{
+ "widgets": [
+ {
+ "name": "EmptyWidget",
+ "alias": "ew"
+ }
+ ],
+ "layout": [
+ {
+ "op": "place",
+ "where": "center",
+ "apply_to": [
+ "ew"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/main/resources/assets/skyblocker/tabhud/garden_info_screen.json b/src/main/resources/assets/skyblocker/tabhud/garden_info_screen.json
new file mode 100644
index 00000000..3ddfdfc3
--- /dev/null
+++ b/src/main/resources/assets/skyblocker/tabhud/garden_info_screen.json
@@ -0,0 +1,88 @@
+{
+ "widgets":[
+ {
+ "name": "GardenSkillsWidget",
+ "alias": "gsw",
+ "args": null
+ },
+ {
+ "name": "EventWidget",
+ "alias": "evw",
+ "args": true
+ },
+ {
+ "name": "UpgradeWidget",
+ "alias": "uw",
+ "args": null
+ },
+ {
+ "name": "ProfileWidget",
+ "alias": "pw",
+ "args": null
+ },
+ {
+ "name": "EffectWidget",
+ "alias": "efw",
+ "args": null
+ },
+ {
+ "name": "JacobsContestWidget",
+ "alias": "jcw",
+ "args": null
+ },
+ {
+ "name": "CookieWidget",
+ "alias": "cw",
+ "args": null
+ }
+ ],
+ "layout": [
+ {
+ "op": "stack",
+ "direction": "vertical",
+ "align": "center",
+ "apply_to": ["gsw", "evw", "uw"]
+ },
+ {
+ "op": "stack",
+ "direction": "vertical",
+ "align": "center",
+ "apply_to": ["pw", "efw"]
+ },
+ {
+ "op": "stack",
+ "direction": "vertical",
+ "align": "center",
+ "apply_to": ["jcw", "cw"]
+ },
+ {
+ "op": "align",
+ "align": "center",
+ "apply_to": ["gsw", "evw", "uw"]
+ },
+ {
+ "op": "collideAgainst",
+ "direction": "left",
+ "widget": "pw",
+ "colliders": ["gsw", "evw", "uw"]
+ },
+ {
+ "op": "collideAgainst",
+ "direction": "left",
+ "widget": "efw",
+ "colliders": ["gsw", "evw", "uw"]
+ },
+ {
+ "op": "collideAgainst",
+ "direction": "right",
+ "widget": "jcw",
+ "colliders": ["gsw", "evw", "uw"]
+ },
+ {
+ "op": "collideAgainst",
+ "direction": "right",
+ "widget": "cw",
+ "colliders": ["gsw", "evw", "uw"]
+ }
+ ]
+} \ No newline at end of file
diff --git a/src/main/resources/assets/skyblocker/tabhud/generic_info_screen.json b/src/main/resources/assets/skyblocker/tabhud/generic_info_screen.json
new file mode 100644
index 00000000..27a28008
--- /dev/null
+++ b/src/main/resources/assets/skyblocker/tabhud/generic_info_screen.json
@@ -0,0 +1,69 @@
+{
+ "widgets":[
+ {
+ "name": "SkillsWidget",
+ "alias": "sw"
+ },
+ {
+ "name": "EventWidget",
+ "alias": "evw"
+ },
+ {
+ "name": "UpgradeWidget",
+ "alias": "uw"
+ },
+ {
+ "name": "ProfileWidget",
+ "alias": "pw"
+ },
+ {
+ "name": "EffectWidget",
+ "alias": "efw"
+ },
+ {
+ "name": "ElectionWidget",
+ "alias": "elw"
+ },
+ {
+ "name": "CookieWidget",
+ "alias": "cw"
+ }
+ ],
+ "layout": [
+ {
+ "op": "stack",
+ "direction": "vertical",
+ "align": "center",
+ "apply_to": ["sw", "evw", "uw"]
+ },
+ {
+ "op": "stack",
+ "direction": "vertical",
+ "align": "center",
+ "apply_to": ["pw", "efw"]
+ },
+ {
+ "op": "stack",
+ "direction": "vertical",
+ "align": "center",
+ "apply_to": ["elw", "cw"]
+ },
+ {
+ "op": "align",
+ "reference": "horizontalCenter",
+ "apply_to": ["sw", "evw", "uw"]
+ },
+ {
+ "op": "collideAgainst",
+ "direction": "left",
+ "widgets": ["pw", "efw"],
+ "colliders": ["sw", "evw", "uw"]
+ },
+ {
+ "op": "collideAgainst",
+ "direction": "right",
+ "widgets": ["elw", "cw"],
+ "colliders": ["sw", "evw", "uw"]
+ }
+ ]
+} \ No newline at end of file