aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/testMod/java/io/github/cottonmc/test/GuiBlock.java37
-rw-r--r--src/testMod/java/io/github/cottonmc/test/GuiBlockEntity.java43
-rw-r--r--src/testMod/java/io/github/cottonmc/test/GuiItem.java55
-rw-r--r--src/testMod/java/io/github/cottonmc/test/ImplementedInventory.java213
-rw-r--r--src/testMod/java/io/github/cottonmc/test/LibGuiTest.java91
-rw-r--r--src/testMod/java/io/github/cottonmc/test/NoBlockInventoryBlock.java39
-rw-r--r--src/testMod/java/io/github/cottonmc/test/ReallySimpleDescription.java16
-rw-r--r--src/testMod/java/io/github/cottonmc/test/TestDescription.java80
-rw-r--r--src/testMod/java/io/github/cottonmc/test/TestItemDescription.java156
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/InsetsTestGui.java20
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/Issue182TestGui.java18
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/Issue196TestGui.java16
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java77
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/PaddingTestGui.java35
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/ScrollingTestGui.java32
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/TabTestGui.java26
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/TestClientGui.java156
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/TextFieldTestGui.java20
-rw-r--r--src/testMod/java/io/github/cottonmc/test/client/WHudTest.java25
-rw-r--r--src/testMod/resources/assets/libgui-test/icon.pngbin0 -> 5016 bytes
-rw-r--r--src/testMod/resources/assets/libgui-test/portal.pngbin0 -> 399 bytes
-rw-r--r--src/testMod/resources/assets/libgui-test/portal2.pngbin0 -> 441 bytes
-rw-r--r--src/testMod/resources/assets/libgui-test/saddle.pngbin0 -> 179 bytes
-rw-r--r--src/testMod/resources/fabric.mod.json30
24 files changed, 1185 insertions, 0 deletions
diff --git a/src/testMod/java/io/github/cottonmc/test/GuiBlock.java b/src/testMod/java/io/github/cottonmc/test/GuiBlock.java
new file mode 100644
index 0000000..1b1666f
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/GuiBlock.java
@@ -0,0 +1,37 @@
+package io.github.cottonmc.test;
+
+import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+import net.minecraft.block.Blocks;
+import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.util.ActionResult;
+import net.minecraft.util.Hand;
+import net.minecraft.util.hit.BlockHitResult;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+public class GuiBlock extends BlockWithEntity {
+
+ public GuiBlock() {
+ super(FabricBlockSettings.copy(Blocks.IRON_BLOCK));
+ }
+
+ @Override
+ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hitResult) {
+ player.openHandledScreen(state.createScreenHandlerFactory(world, pos));
+ return ActionResult.SUCCESS;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new GuiBlockEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/GuiBlockEntity.java b/src/testMod/java/io/github/cottonmc/test/GuiBlockEntity.java
new file mode 100644
index 0000000..16e7e3f
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/GuiBlockEntity.java
@@ -0,0 +1,43 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.block.BlockState;
+import net.minecraft.block.entity.BlockEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.screen.ScreenHandlerContext;
+import net.minecraft.text.Text;
+import net.minecraft.util.collection.DefaultedList;
+import net.minecraft.util.math.BlockPos;
+
+public class GuiBlockEntity extends BlockEntity implements ImplementedInventory, NamedScreenHandlerFactory {
+ static final int INVENTORY_SIZE = 8;
+
+ DefaultedList<ItemStack> items = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY);
+
+ public GuiBlockEntity(BlockPos pos, BlockState state) {
+ super(LibGuiTest.GUI_BLOCKENTITY_TYPE, pos, state);
+ }
+
+ @Override
+ public DefaultedList<ItemStack> getItems() {
+ return items;
+ }
+
+ @Override
+ public boolean canPlayerUse(PlayerEntity player) {
+ return pos.isWithinDistance(player.getBlockPos(), 4.5);
+ }
+
+ @Override
+ public Text getDisplayName() {
+ return Text.literal("test title");
+ }
+
+ @Override
+ public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player) {
+ return new TestDescription(LibGuiTest.GUI_SCREEN_HANDLER_TYPE, syncId, inv, ScreenHandlerContext.create(world, pos));
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/GuiItem.java b/src/testMod/java/io/github/cottonmc/test/GuiItem.java
new file mode 100644
index 0000000..27c8d5f
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/GuiItem.java
@@ -0,0 +1,55 @@
+package io.github.cottonmc.test;
+
+import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
+import net.minecraft.entity.EquipmentSlot;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.network.PacketByteBuf;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.server.network.ServerPlayerEntity;
+import net.minecraft.text.Text;
+import net.minecraft.util.ActionResult;
+import net.minecraft.util.Hand;
+import net.minecraft.util.Rarity;
+import net.minecraft.util.TypedActionResult;
+import net.minecraft.world.World;
+
+public class GuiItem extends Item {
+ public GuiItem() {
+ super(new Item.Settings().rarity(Rarity.EPIC));
+ }
+
+ @Override
+ public TypedActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
+ player.openHandledScreen(createScreenHandlerFactory(player, hand));
+ return new TypedActionResult<>(ActionResult.SUCCESS, player.getStackInHand(hand));
+ }
+
+ private NamedScreenHandlerFactory createScreenHandlerFactory(PlayerEntity player, Hand hand) {
+ EquipmentSlot slot = switch (hand) {
+ case MAIN_HAND -> EquipmentSlot.MAINHAND;
+ case OFF_HAND -> EquipmentSlot.OFFHAND;
+ };
+ ItemStack stack = player.getStackInHand(hand);
+ return new ExtendedScreenHandlerFactory() {
+ @Override
+ public Text getDisplayName() {
+ return stack.getName();
+ }
+
+ @Override
+ public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) {
+ return new TestItemDescription(syncId, playerInventory, StackReference.of(player, slot));
+ }
+
+ @Override
+ public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) {
+ buf.writeEnumConstant(slot);
+ }
+ };
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/ImplementedInventory.java b/src/testMod/java/io/github/cottonmc/test/ImplementedInventory.java
new file mode 100644
index 0000000..a1d3911
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/ImplementedInventory.java
@@ -0,0 +1,213 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.inventory.Inventories;
+import net.minecraft.inventory.Inventory;
+import net.minecraft.inventory.SidedInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.collection.DefaultedList;
+import net.minecraft.util.math.Direction;
+
+import java.util.List;
+
+/**
+ * A simple {@code SidedInventory} implementation with only default methods + an item list getter.
+ *
+ * <h2>Reading and writing to tags</h2>
+ * Use {@link Inventories#readNbt(net.minecraft.nbt.NbtCompound, DefaultedList)} and {@link Inventories#writeNbt(net.minecraft.nbt.NbtCompound, DefaultedList)}
+ * on {@linkplain #getItems() the item list}.
+ *
+ * <p>License: <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a>
+ *
+ * @author Juuz
+ */
+@FunctionalInterface
+public interface ImplementedInventory extends SidedInventory {
+ /**
+ * Gets the item list of this inventory.
+ * Must return the same instance every time it's called.
+ *
+ * @return the item list
+ */
+ DefaultedList<ItemStack> getItems();
+
+ // Creation
+
+ /**
+ * Creates an inventory from the item list.
+ *
+ * @param items the item list
+ * @return a new inventory
+ */
+ static ImplementedInventory of(DefaultedList<ItemStack> items) {
+ return () -> items;
+ }
+
+ /**
+ * Creates a new inventory with the size.
+ *
+ * @param size the inventory size
+ * @return a new inventory
+ */
+ static ImplementedInventory ofSize(int size) {
+ return of(DefaultedList.ofSize(size, ItemStack.EMPTY));
+ }
+
+ // SidedInventory
+
+ /**
+ * Gets the available slots to automation on the side.
+ *
+ * <p>The default implementation returns an array of all slots.
+ *
+ * @param side the side
+ * @return the available slots
+ */
+ @Override
+ default int[] getAvailableSlots(Direction side) {
+ int[] result = new int[getItems().size()];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = i;
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns true if the stack can be inserted in the slot at the side.
+ *
+ * <p>The default implementation returns true.
+ *
+ * @param slot the slot
+ * @param stack the stack
+ * @param side the side
+ * @return true if the stack can be inserted
+ */
+ @Override
+ default boolean canInsert(int slot, ItemStack stack, Direction side) {
+ return true;
+ }
+
+ /**
+ * Returns true if the stack can be extracted from the slot at the side.
+ *
+ * <p>The default implementation returns true.
+ *
+ * @param slot the slot
+ * @param stack the stack
+ * @param side the side
+ * @return true if the stack can be extracted
+ */
+ @Override
+ default boolean canExtract(int slot, ItemStack stack, Direction side) {
+ return true;
+ }
+
+ // Inventory
+
+ /**
+ * Returns the inventory size.
+ *
+ * <p>The default implementation returns the size of {@link #getItems()}.
+ *
+ * @return the inventory size
+ */
+ @Override
+ default int size() {
+ return getItems().size();
+ }
+
+ /**
+ * @return true if this inventory has only empty stacks, false otherwise
+ */
+ @Override
+ default boolean isEmpty() {
+ for (int i = 0; i < size(); i++) {
+ ItemStack stack = getStack(i);
+ if (!stack.isEmpty()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets the item in the slot.
+ *
+ * @param slot the slot
+ * @return the item in the slot
+ */
+ @Override
+ default ItemStack getStack(int slot) {
+ return getItems().get(slot);
+ }
+
+ /**
+ * Takes a stack of the size from the slot.
+ *
+ * <p>(default implementation) If there are less items in the slot than what are requested,
+ * takes all items in that slot.
+ *
+ * @param slot the slot
+ * @param count the item count
+ * @return a stack
+ */
+ @Override
+ default ItemStack removeStack(int slot, int count) {
+ ItemStack result = Inventories.splitStack(getItems(), slot, count);
+ if (!result.isEmpty()) {
+ markDirty();
+ }
+
+ return result;
+ }
+
+ /**
+ * Removes the current stack in the {@code slot} and returns it.
+ *
+ * <p>The default implementation uses {@link Inventories#removeStack(List, int)}
+ *
+ * @param slot the slot
+ * @return the removed stack
+ */
+ @Override
+ default ItemStack removeStack(int slot) {
+ return Inventories.removeStack(getItems(), slot);
+ }
+
+ /**
+ * Replaces the current stack in the {@code slot} with the provided stack.
+ *
+ * <p>If the stack is too big for this inventory ({@link Inventory#getMaxCountPerStack()} ()}),
+ * it gets resized to this inventory's maximum amount.
+ *
+ * @param slot the slot
+ * @param stack the stack
+ */
+ @Override
+ default void setStack(int slot, ItemStack stack) {
+ getItems().set(slot, stack);
+ if (stack.getCount() > getMaxCountPerStack()) {
+ stack.setCount(getMaxCountPerStack());
+ }
+ }
+
+ /**
+ * Clears {@linkplain #getItems() the item list}}.
+ */
+ @Override
+ default void clear() {
+ getItems().clear();
+ }
+
+ @Override
+ default void markDirty() {
+ // Override if you want behavior.
+ }
+
+ @Override
+ default boolean canPlayerUse(PlayerEntity player) {
+ return true;
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/LibGuiTest.java b/src/testMod/java/io/github/cottonmc/test/LibGuiTest.java
new file mode 100644
index 0000000..1d48daa
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/LibGuiTest.java
@@ -0,0 +1,91 @@
+package io.github.cottonmc.test;
+
+import net.fabricmc.api.ModInitializer;
+import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
+import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType;
+import net.fabricmc.loader.api.FabricLoader;
+import net.fabricmc.loader.api.ModContainer;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.Block;
+import net.minecraft.block.Blocks;
+import net.minecraft.block.entity.BlockEntityType;
+import net.minecraft.entity.EquipmentSlot;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
+import net.minecraft.item.BlockItem;
+import net.minecraft.item.Item;
+import net.minecraft.registry.Registries;
+import net.minecraft.registry.Registry;
+import net.minecraft.resource.featuretoggle.FeatureFlags;
+import net.minecraft.resource.featuretoggle.FeatureSet;
+import net.minecraft.screen.ScreenHandlerContext;
+import net.minecraft.screen.ScreenHandlerType;
+import net.minecraft.util.Identifier;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Optional;
+
+public class LibGuiTest implements ModInitializer {
+ public static final String MODID = "libgui-test";
+
+ public static GuiBlock GUI_BLOCK;
+ public static Block NO_BLOCK_INVENTORY_BLOCK;
+ public static BlockItem GUI_BLOCK_ITEM;
+ public static BlockEntityType<GuiBlockEntity> GUI_BLOCKENTITY_TYPE;
+ public static ScreenHandlerType<TestDescription> GUI_SCREEN_HANDLER_TYPE;
+ public static ScreenHandlerType<TestItemDescription> ITEM_SCREEN_HANDLER_TYPE;
+ public static ScreenHandlerType<ReallySimpleDescription> REALLY_SIMPLE_SCREEN_HANDLER_TYPE;
+
+ @Override
+ public void onInitialize() {
+ Registry.register(Registries.ITEM, new Identifier(MODID, "client_gui"), new GuiItem());
+
+ GUI_BLOCK = new GuiBlock();
+ Registry.register(Registries.BLOCK, new Identifier(MODID, "gui"), GUI_BLOCK);
+ GUI_BLOCK_ITEM = new BlockItem(GUI_BLOCK, new Item.Settings());
+ Registry.register(Registries.ITEM, new Identifier(MODID, "gui"), GUI_BLOCK_ITEM);
+ NO_BLOCK_INVENTORY_BLOCK = new NoBlockInventoryBlock(AbstractBlock.Settings.copy(Blocks.STONE));
+ Registry.register(Registries.BLOCK, new Identifier(MODID, "no_block_inventory"), NO_BLOCK_INVENTORY_BLOCK);
+ Registry.register(Registries.ITEM, new Identifier(MODID, "no_block_inventory"), new BlockItem(NO_BLOCK_INVENTORY_BLOCK, new Item.Settings()));
+ GUI_BLOCKENTITY_TYPE = FabricBlockEntityTypeBuilder.create(GuiBlockEntity::new, GUI_BLOCK).build(null);
+ Registry.register(Registries.BLOCK_ENTITY_TYPE, new Identifier(MODID, "gui"), GUI_BLOCKENTITY_TYPE);
+
+ GUI_SCREEN_HANDLER_TYPE = new ScreenHandlerType<>((int syncId, PlayerInventory inventory) -> {
+ return new TestDescription(GUI_SCREEN_HANDLER_TYPE, syncId, inventory, ScreenHandlerContext.EMPTY);
+ }, FeatureSet.of(FeatureFlags.VANILLA));
+ Registry.register(Registries.SCREEN_HANDLER, new Identifier(MODID, "gui"), GUI_SCREEN_HANDLER_TYPE);
+ ITEM_SCREEN_HANDLER_TYPE = new ExtendedScreenHandlerType<>((syncId, inventory, buf) -> {
+ var equipmentSlot = buf.readEnumConstant(EquipmentSlot.class);
+ StackReference handStack = StackReference.of(inventory.player, equipmentSlot);
+ return new TestItemDescription(syncId, inventory, handStack);
+ });
+ Registry.register(Registries.SCREEN_HANDLER, new Identifier(MODID, "item_gui"), ITEM_SCREEN_HANDLER_TYPE);
+
+ REALLY_SIMPLE_SCREEN_HANDLER_TYPE = new ScreenHandlerType<>(ReallySimpleDescription::new, FeatureSet.of(FeatureFlags.VANILLA));
+ Registry.register(Registries.SCREEN_HANDLER, new Identifier(MODID, "really_simple"), REALLY_SIMPLE_SCREEN_HANDLER_TYPE);
+
+ Optional<ModContainer> containerOpt = FabricLoader.getInstance().getModContainer("jankson");
+ if (containerOpt.isPresent()) {
+ ModContainer jankson = containerOpt.get();
+ System.out.println("Jankson root path: "+jankson.getRootPath());
+ try {
+ Files.list(jankson.getRootPath()).forEach((path)->{
+ path.getFileSystem().getFileStores().forEach((store)->{
+ System.out.println(" Filestore: "+store.name());
+ });
+ System.out.println(" "+path.toAbsolutePath());
+ });
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ Path modJson = jankson.getPath("/fabric.mod.json");
+ System.out.println("Jankson fabric.mod.json path: "+modJson);
+ System.out.println(Files.exists(modJson) ? "Exists" : "Does Not Exist");
+ } else {
+ System.out.println("Container isn't present!");
+ }
+ }
+
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/NoBlockInventoryBlock.java b/src/testMod/java/io/github/cottonmc/test/NoBlockInventoryBlock.java
new file mode 100644
index 0000000..2b784a6
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/NoBlockInventoryBlock.java
@@ -0,0 +1,39 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.block.Block;
+import net.minecraft.block.BlockState;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.text.Text;
+import net.minecraft.util.ActionResult;
+import net.minecraft.util.Hand;
+import net.minecraft.util.hit.BlockHitResult;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+
+import org.jetbrains.annotations.Nullable;
+
+public class NoBlockInventoryBlock extends Block implements NamedScreenHandlerFactory {
+ public NoBlockInventoryBlock(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
+ player.openHandledScreen(this);
+ return world.isClient ? ActionResult.SUCCESS : ActionResult.CONSUME;
+ }
+
+ @Override
+ public Text getDisplayName() {
+ return getName();
+ }
+
+ @Nullable
+ @Override
+ public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player) {
+ return new ReallySimpleDescription(syncId, inv);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/ReallySimpleDescription.java b/src/testMod/java/io/github/cottonmc/test/ReallySimpleDescription.java
new file mode 100644
index 0000000..bcb9213
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/ReallySimpleDescription.java
@@ -0,0 +1,16 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.entity.player.PlayerInventory;
+
+import io.github.cottonmc.cotton.gui.SyncedGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+
+// A really simple GUI description that only contains a player inventory panel.
+public class ReallySimpleDescription extends SyncedGuiDescription {
+ public ReallySimpleDescription(int syncId, PlayerInventory playerInventory) {
+ super(LibGuiTest.REALLY_SIMPLE_SCREEN_HANDLER_TYPE, syncId, playerInventory);
+ setTitleVisible(false);
+ ((WGridPanel) getRootPanel()).add(createPlayerInventoryPanel(), 0, 0);
+ getRootPanel().validate(this);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/TestDescription.java b/src/testMod/java/io/github/cottonmc/test/TestDescription.java
new file mode 100644
index 0000000..39b09d6
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/TestDescription.java
@@ -0,0 +1,80 @@
+package io.github.cottonmc.test;
+
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.item.Items;
+import net.minecraft.screen.ScreenHandlerContext;
+import net.minecraft.screen.ScreenHandlerType;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import io.github.cottonmc.cotton.gui.SyncedGuiDescription;
+import io.github.cottonmc.cotton.gui.networking.NetworkSide;
+import io.github.cottonmc.cotton.gui.networking.ScreenNetworking;
+import io.github.cottonmc.cotton.gui.widget.WButton;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WItemSlot;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+import io.github.cottonmc.cotton.gui.widget.data.Texture;
+import io.github.cottonmc.cotton.gui.widget.icon.TextureIcon;
+
+public class TestDescription extends SyncedGuiDescription {
+ private static final Identifier TEST_MESSAGE = new Identifier("libgui", "test");
+ private static final Identifier UNREGISTERED_ON_SERVER = new Identifier("libgui", "unregistered_on_server");
+
+ public TestDescription(ScreenHandlerType<?> type, int syncId, PlayerInventory playerInventory, ScreenHandlerContext context) {
+ super(type, syncId, playerInventory, getBlockInventory(context, GuiBlockEntity.INVENTORY_SIZE), null);
+
+ WGridPanel root = (WGridPanel)this.getRootPanel();
+
+ WItemSlot slot = WItemSlot.of(blockInventory, 0, 4, 1);
+ root.add(slot, 0, 1);
+
+ WButton buttonA = new WButton(Text.literal("Send Message"));
+
+ buttonA.setOnClick(() -> {
+ ScreenNetworking.of(this, NetworkSide.CLIENT).send(TEST_MESSAGE, buf -> {});
+ ScreenNetworking.of(this, NetworkSide.CLIENT).send(UNREGISTERED_ON_SERVER, buf -> {});
+ });
+
+ root.add(buttonA, 0, 3, 4, 1);
+
+ WButton buttonB = new WButton(Text.literal("Show Warnings"));
+ buttonB.setOnClick(() -> slot.setIcon(new TextureIcon(new Identifier("libgui-test", "saddle.png"))));
+
+ root.add(buttonB, 5, 3, 4, 1);
+ TextureIcon testIcon = new TextureIcon(new Texture(new Identifier("libgui-test", "icon.png")));
+ root.add(new WButton(testIcon, Text.literal("Button C")), 0, 5, 4, 1);
+ root.add(new WButton(Text.literal("Button D")), 5, 5, 4, 1);
+ root.add(new WTextField(Text.literal("Type something...")).setMaxLength(64), 0, 7, 5, 1);
+
+ root.add(new WLabel(Text.literal("Large slot:")), 0, 9);
+ root.add(WItemSlot.outputOf(blockInventory, 0), 4, 9);
+
+ root.add(WItemSlot.of(blockInventory, 7).setIcon(new TextureIcon(new Identifier("libgui-test", "saddle.png"))), 7, 9);
+
+ root.add(createPlayerInventoryPanel(), 0, 11);
+ System.out.println(root.toString());
+
+ this.getRootPanel().validate(this);
+
+ getRootPanel().streamChildren()
+ .forEach(child -> {
+ if (child instanceof WItemSlot wis) {
+ // Prevent apples from entering the item slots
+ wis.setFilter(stack -> !stack.isOf(Items.APPLE));
+ }
+ });
+
+ ScreenNetworking.of(this, NetworkSide.SERVER).receive(TEST_MESSAGE, buf -> {
+ System.out.println("Received on the server!");
+ });
+
+ try {
+ slot.onHidden();
+ slot.onShown();
+ } catch (Throwable t) {
+ throw new AssertionError("ValidatedSlot.setVisible crashed", t);
+ }
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/TestItemDescription.java b/src/testMod/java/io/github/cottonmc/test/TestItemDescription.java
new file mode 100644
index 0000000..4c9c1f0
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/TestItemDescription.java
@@ -0,0 +1,156 @@
+package io.github.cottonmc.test;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.StackReference;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import io.github.cottonmc.cotton.gui.ItemSyncedGuiDescription;
+import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
+import io.github.cottonmc.cotton.gui.widget.TooltipBuilder;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.WSlider;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+import io.github.cottonmc.cotton.gui.widget.WTiledSprite;
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.Color;
+import io.github.cottonmc.cotton.gui.widget.data.Insets;
+
+public class TestItemDescription extends ItemSyncedGuiDescription {
+ private int r = 0;
+ private int g = 0;
+ private int b = 0;
+
+ public TestItemDescription(int syncId, PlayerInventory playerInventory, StackReference owner) {
+ super(LibGuiTest.ITEM_SCREEN_HANDLER_TYPE, syncId, playerInventory, owner);
+ WGridPanel root = new WGridPanel(22);
+ root.setInsets(Insets.ROOT_PANEL);
+ this.setRootPanel(root);
+ WLabel title = new WLabel(Text.literal("Client Test Gui"), WLabel.DEFAULT_TEXT_COLOR) {
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addTooltip(TooltipBuilder tooltip) {
+ tooltip.add(Text.literal("Radical!"));
+ }
+ };
+ WTiledSprite wood = new WTiledSprite(
+ 8, 8, // tile width and height
+ 500, // animation speed
+ new Identifier("minecraft:textures/block/birch_planks.png"),
+ new Identifier("minecraft:textures/block/dark_oak_planks.png"),
+ new Identifier("minecraft:textures/block/jungle_planks.png")
+ );
+ root.add(wood, 3, 3, 2, 2);
+ root.add(title, 0, 0);
+
+ WTextField text = new WTextField();
+ text.setSuggestion(Text.literal("Search"));
+ root.add(text, 0, 1, 8, 1);
+ text.setSize(7*18, 20);
+ /*
+ ArrayList<String> data = new ArrayList<>();
+ data.add("Wolfram Alpha");
+ data.add("Strange Home");
+ data.add("Nether Base");
+ data.add("Death");
+ data.add("Cake");
+ data.add("Mushroom Island");
+ data.add("A List Item");
+ data.add("Notes");
+ data.add("Slime Island");
+
+ BiConsumer<String, PortalDestination> configurator = (String s, PortalDestination destination) -> {
+ destination.label.setText(new LiteralText(s));
+
+ int hash = s.hashCode();
+ Identifier sprite = ((hash & 0x01) == 0) ? PORTAL1 : PORTAL2;
+ destination.sprite.setImage(sprite);
+
+ int cost = (hash >> 1) & 0x2FF;
+ destination.cost.setText(new LiteralText(""+cost+" XP"));
+ };
+ WListPanel<String, PortalDestination> list = new WListPanel<String, PortalDestination>(data, PortalDestination.class, PortalDestination::new, configurator);
+ list.setListItemHeight(2*18);
+ list.setBackgroundPainter(PANEL);
+ root.add(list, 0, 2, 7, 6);
+
+ root.add(new WButton(new LiteralText("Teleport")), 3,8,4,1);*/
+ WColorBox col = new WColorBox();
+ root.add(col, 3,2,1,3);
+
+ WSlider r = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(r, 0, 2, 1, 3);
+ r.setValueChangeListener((i)->{
+ this.r = i;
+ updateCol(col);
+ System.out.println("h: "+this.r+" s: "+this.g+ " l: "+this.b);
+ System.out.println("col is now "+Integer.toHexString(col.color));
+ });
+ WSlider g = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(g, 1, 2, 1, 3);
+ g.setValueChangeListener((i)->{
+ this.g = i;
+ updateCol(col);
+ });
+ WSlider b = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(b, 2, 2, 1, 3);
+ b.setValueChangeListener((i)->{
+ this.b = i;
+ updateCol(col);
+ });
+
+ root.validate(this);
+ }
+ /*
+ public static class PortalDestination extends WPlainPanel {
+ WSprite sprite;
+ WLabel label;
+ WLabel cost;
+
+ public PortalDestination() {
+ sprite = new WSprite(new Identifier("libgui-test:portal"));
+ this.add(sprite, 2, 2, 18, 18);
+ label = new WLabel("Foo");
+ this.add(label, 18+ 4, 2, 5*18, 18);
+ cost = new WLabel("1000 Xp");
+ this.add(cost, 2, 20, 6*18, 18);
+
+ this.setSize(7*18, 2*18);
+
+ this.setBackgroundPainter(PANEL); //Would fail on a serverside gui
+ }
+ }*/
+
+ private void updateCol(WColorBox col) {
+ Color.HSL hsl = new Color.HSL(r/100f, g/100f, b/100f);
+ col.setColor(hsl.toRgb());
+ }
+
+ public static class WColorBox extends WWidget {
+ protected int color = 0xFF_FFFFFF;
+ public WColorBox() {}
+
+ public WColorBox(int col) {
+ this.color = col;
+ }
+
+ @Override
+ public boolean canResize() {
+ return true;
+ }
+
+ public void setColor(int col) {
+ this.color = col;
+ }
+
+ @Override
+ public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
+ ScreenDrawing.coloredRect(matrices, x, y, this.getWidth(), this.getHeight(), color);
+ }
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/InsetsTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/InsetsTestGui.java
new file mode 100644
index 0000000..f89de7a
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/InsetsTestGui.java
@@ -0,0 +1,20 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WButton;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.data.Insets;
+
+public class InsetsTestGui extends LightweightGuiDescription {
+ public InsetsTestGui() {
+ WGridPanel root = (WGridPanel) rootPanel;
+
+ root.add(new WLabel(Text.literal("Insets demo")), 0, 0);
+ root.add(new WButton(Text.literal("Default")).setOnClick(() -> root.setInsets(Insets.ROOT_PANEL)), 0, 1, 2, 1);
+ root.add(new WButton(Text.literal("None")).setOnClick(() -> root.setInsets(Insets.NONE)), 2, 1, 2, 1);
+ root.add(new WButton(Text.literal("Large")).setOnClick(() -> root.setInsets(new Insets(16))), 4, 1, 2, 1);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/Issue182TestGui.java b/src/testMod/java/io/github/cottonmc/test/client/Issue182TestGui.java
new file mode 100644
index 0000000..5d4a739
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/Issue182TestGui.java
@@ -0,0 +1,18 @@
+package io.github.cottonmc.test.client;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WBox;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+import io.github.cottonmc.cotton.gui.widget.data.Axis;
+
+// Used for testing issue #182 (https://github.com/CottonMC/LibGui/issues/182):
+// Highlighting/selecting text in the top field makes the bottom one blue.
+public final class Issue182TestGui extends LightweightGuiDescription {
+ public Issue182TestGui() {
+ WBox root = new WBox(Axis.VERTICAL);
+ root.add(new WTextField(), 100, 20);
+ root.add(new WTextField(), 100, 20);
+ setRootPanel(root);
+ root.validate(this);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/Issue196TestGui.java b/src/testMod/java/io/github/cottonmc/test/client/Issue196TestGui.java
new file mode 100644
index 0000000..6de8181
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/Issue196TestGui.java
@@ -0,0 +1,16 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+
+public final class Issue196TestGui extends LightweightGuiDescription {
+ public Issue196TestGui() {
+ WTextField textField = new WTextField(Text.literal("Select with tab and type text"));
+ textField.setText("");
+ ((WGridPanel) rootPanel).add(textField, 0, 0, 4, 1);
+ rootPanel.validate(this);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java b/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java
new file mode 100644
index 0000000..635040f
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/LibGuiTestClient.java
@@ -0,0 +1,77 @@
+package io.github.cottonmc.test.client;
+
+import com.mojang.brigadier.Command;
+import com.mojang.brigadier.arguments.IntegerArgumentType;
+import net.fabricmc.api.ClientModInitializer;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.ingame.HandledScreens;
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.CottonClientScreen;
+import io.github.cottonmc.cotton.gui.client.CottonHud;
+import io.github.cottonmc.cotton.gui.client.CottonInventoryScreen;
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.impl.modmenu.ConfigGui;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.test.LibGuiTest;
+import io.github.cottonmc.test.ReallySimpleDescription;
+import io.github.cottonmc.test.TestDescription;
+import io.github.cottonmc.test.TestItemDescription;
+
+import java.util.function.Function;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public class LibGuiTestClient implements ClientModInitializer {
+
+ @Override
+ public void onInitializeClient() {
+ HandledScreens.<TestDescription, CottonInventoryScreen<TestDescription>>register(
+ LibGuiTest.GUI_SCREEN_HANDLER_TYPE,
+ CottonInventoryScreen::new
+ );
+
+ HandledScreens.<ReallySimpleDescription, CottonInventoryScreen<ReallySimpleDescription>>register(
+ LibGuiTest.REALLY_SIMPLE_SCREEN_HANDLER_TYPE,
+ CottonInventoryScreen::new
+ );
+
+ HandledScreens.<TestItemDescription, CottonInventoryScreen<TestItemDescription>>register(
+ LibGuiTest.ITEM_SCREEN_HANDLER_TYPE,
+ CottonInventoryScreen::new
+ );
+
+ CottonHud.add(new WHudTest(), 10, -20, 10, 10);
+ CottonHud.add(new WLabel(Text.literal("Test label")), 10, -30, 10, 10);
+
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, commandRegistryAccess) -> dispatcher.register(
+ literal("libgui")
+ .then(literal("config").executes(openScreen(client -> new ConfigGui(client.currentScreen))))
+ .then(literal("tab").executes(openScreen(client -> new TabTestGui())))
+ .then(literal("scrolling").executes(openScreen(client -> new ScrollingTestGui())))
+ .then(literal("insets").executes(openScreen(client -> new InsetsTestGui())))
+ .then(literal("textfield").executes(openScreen(client -> new TextFieldTestGui())))
+ .then(literal("paddings")
+ .then(argument("horizontal", IntegerArgumentType.integer(0))
+ .then(argument("vertical", IntegerArgumentType.integer(0))
+ .executes(context -> {
+ var hori = IntegerArgumentType.getInteger(context, "horizontal");
+ var vert = IntegerArgumentType.getInteger(context, "vertical");
+ return openScreen(client -> new PaddingTestGui(hori, vert)).run(context);
+ }))))
+ .then(literal("#182").executes(openScreen(client -> new Issue182TestGui())))
+ .then(literal("#196").executes(openScreen(client -> new Issue196TestGui())))
+ ));
+ }
+
+ private static Command<FabricClientCommandSource> openScreen(Function<MinecraftClient, LightweightGuiDescription> screenFactory) {
+ return context -> {
+ var client = context.getSource().getClient();
+ client.send(() -> client.setScreen(new CottonClientScreen(screenFactory.apply(client))));
+ return Command.SINGLE_SUCCESS;
+ };
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/PaddingTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/PaddingTestGui.java
new file mode 100644
index 0000000..9f5d790
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/PaddingTestGui.java
@@ -0,0 +1,35 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.data.HorizontalAlignment;
+import io.github.cottonmc.cotton.gui.widget.data.Insets;
+import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment;
+import io.github.cottonmc.test.TestItemDescription;
+
+public class PaddingTestGui extends LightweightGuiDescription {
+ public PaddingTestGui(int hori, int vert) {
+ var root = new WGridPanel();
+ root.setGaps(hori, vert);
+ setRootPanel(root);
+ root.setInsets(Insets.ROOT_PANEL);
+
+ addBox(root, 0, 0, 2, 1);
+ addBox(root, 0, 1, 1, 2);
+ addBox(root, 1, 1, 1, 1);
+ addBox(root, 1, 2, 1, 1);
+
+ root.validate(this);
+ }
+
+ void addBox(WGridPanel root, int x, int y, int w, int h) {
+ root.add(new TestItemDescription.WColorBox(0xffff0000), x, y, w, h);
+ var l = new WLabel(Text.literal(w + "x" + h), 0xff00ffff);
+ l.setVerticalAlignment(VerticalAlignment.CENTER);
+ l.setHorizontalAlignment(HorizontalAlignment.CENTER);
+ root.add(l, x, y, w, h);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/ScrollingTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/ScrollingTestGui.java
new file mode 100644
index 0000000..bfc25c4
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/ScrollingTestGui.java
@@ -0,0 +1,32 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.item.Items;
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WBox;
+import io.github.cottonmc.cotton.gui.widget.WButton;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.WLabeledSlider;
+import io.github.cottonmc.cotton.gui.widget.WScrollPanel;
+import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.VerticalAlignment;
+import io.github.cottonmc.cotton.gui.widget.icon.ItemIcon;
+
+public class ScrollingTestGui extends LightweightGuiDescription {
+ public ScrollingTestGui() {
+ WGridPanel root = (WGridPanel) rootPanel;
+ WBox box = new WBox(Axis.VERTICAL);
+
+ for (int i = 0; i < 20; i++) {
+ box.add(new WLabeledSlider(0, 10, Text.literal("Slider #" + i)));
+ }
+
+ box.add(new WButton(new ItemIcon(Items.APPLE)));
+
+ root.add(new WLabel(Text.literal("Scrolling test")).setVerticalAlignment(VerticalAlignment.CENTER), 0, 0, 5, 2);
+ root.add(new WScrollPanel(box), 0, 2, 5, 3);
+ root.validate(this);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/TabTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/TabTestGui.java
new file mode 100644
index 0000000..8ed93f9
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/TabTestGui.java
@@ -0,0 +1,26 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.item.Items;
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.impl.modmenu.WKirbSprite;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.WTabPanel;
+import io.github.cottonmc.cotton.gui.widget.icon.ItemIcon;
+
+public class TabTestGui extends LightweightGuiDescription {
+ public TabTestGui() {
+ WTabPanel tabs = new WTabPanel();
+ tabs.add(new WKirbSprite(), builder -> builder.title(Text.literal("Kirb")));
+ tabs.add(new WLabel(Text.literal("just another tab")), builder -> builder.icon(new ItemIcon(Items.ANDESITE)));
+
+ tabs.setSize(7 * 18, 5 * 18);
+ setRootPanel(tabs);
+ getRootPanel().validate(this);
+ }
+
+ @Override
+ public void addPainters() {
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/TestClientGui.java b/src/testMod/java/io/github/cottonmc/test/client/TestClientGui.java
new file mode 100644
index 0000000..839072e
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/TestClientGui.java
@@ -0,0 +1,156 @@
+package io.github.cottonmc.test.client;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.util.math.MatrixStack;
+import net.minecraft.text.Text;
+import net.minecraft.util.Identifier;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
+import io.github.cottonmc.cotton.gui.widget.TooltipBuilder;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WLabel;
+import io.github.cottonmc.cotton.gui.widget.WSlider;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+import io.github.cottonmc.cotton.gui.widget.WTiledSprite;
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import io.github.cottonmc.cotton.gui.widget.data.Axis;
+import io.github.cottonmc.cotton.gui.widget.data.Color;
+import io.github.cottonmc.cotton.gui.widget.data.Insets;
+
+public class TestClientGui extends LightweightGuiDescription {
+ //private static final Identifier PORTAL1 = new Identifier("libgui-test:portal.png");
+ //private static final Identifier PORTAL2 = new Identifier("libgui-test:portal2.png");
+
+ private int r = 0;
+ private int g = 0;
+ private int b = 0;
+
+ public TestClientGui() {
+ WGridPanel root = new WGridPanel(22);
+ root.setInsets(Insets.ROOT_PANEL);
+ this.setRootPanel(root);
+ WLabel title = new WLabel(Text.literal("Client Test Gui"), WLabel.DEFAULT_TEXT_COLOR) {
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addTooltip(TooltipBuilder tooltip) {
+ tooltip.add(Text.literal("Radical!"));
+ }
+ };
+ WTiledSprite wood = new WTiledSprite(
+ 8, 8, // tile width and height
+ 500, // animation speed
+ new Identifier("minecraft:textures/block/birch_planks.png"),
+ new Identifier("minecraft:textures/block/dark_oak_planks.png"),
+ new Identifier("minecraft:textures/block/jungle_planks.png")
+ );
+ root.add(wood, 3, 3, 2, 2);
+ root.add(title, 0, 0);
+
+ WTextField text = new WTextField();
+ text.setSuggestion(Text.literal("Search"));
+ root.add(text, 0, 1, 8, 1);
+ text.setSize(7*18, 20);
+ /*
+ ArrayList<String> data = new ArrayList<>();
+ data.add("Wolfram Alpha");
+ data.add("Strange Home");
+ data.add("Nether Base");
+ data.add("Death");
+ data.add("Cake");
+ data.add("Mushroom Island");
+ data.add("A List Item");
+ data.add("Notes");
+ data.add("Slime Island");
+
+ BiConsumer<String, PortalDestination> configurator = (String s, PortalDestination destination) -> {
+ destination.label.setText(new LiteralText(s));
+
+ int hash = s.hashCode();
+ Identifier sprite = ((hash & 0x01) == 0) ? PORTAL1 : PORTAL2;
+ destination.sprite.setImage(sprite);
+
+ int cost = (hash >> 1) & 0x2FF;
+ destination.cost.setText(new LiteralText(""+cost+" XP"));
+ };
+ WListPanel<String, PortalDestination> list = new WListPanel<String, PortalDestination>(data, PortalDestination.class, PortalDestination::new, configurator);
+ list.setListItemHeight(2*18);
+ list.setBackgroundPainter(PANEL);
+ root.add(list, 0, 2, 7, 6);
+
+ root.add(new WButton(new LiteralText("Teleport")), 3,8,4,1);*/
+ WColorBox col = new WColorBox();
+ root.add(col, 3,2,1,3);
+
+ WSlider r = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(r, 0, 2, 1, 3);
+ r.setValueChangeListener((i)->{
+ this.r = i;
+ updateCol(col);
+ System.out.println("h: "+this.r+" s: "+this.g+ " l: "+this.b);
+ System.out.println("col is now "+Integer.toHexString(col.color));
+ });
+ WSlider g = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(g, 1, 2, 1, 3);
+ g.setValueChangeListener((i)->{
+ this.g = i;
+ updateCol(col);
+ });
+ WSlider b = new WSlider(0, 100, Axis.VERTICAL);
+ root.add(b, 2, 2, 1, 3);
+ b.setValueChangeListener((i)->{
+ this.b = i;
+ updateCol(col);
+ });
+
+ root.validate(this);
+ }
+ /*
+ public static class PortalDestination extends WPlainPanel {
+ WSprite sprite;
+ WLabel label;
+ WLabel cost;
+
+ public PortalDestination() {
+ sprite = new WSprite(new Identifier("libgui-test:portal"));
+ this.add(sprite, 2, 2, 18, 18);
+ label = new WLabel("Foo");
+ this.add(label, 18+ 4, 2, 5*18, 18);
+ cost = new WLabel("1000 Xp");
+ this.add(cost, 2, 20, 6*18, 18);
+
+ this.setSize(7*18, 2*18);
+
+ this.setBackgroundPainter(PANEL); //Would fail on a serverside gui
+ }
+ }*/
+
+ private void updateCol(WColorBox col) {
+ Color.HSL hsl = new Color.HSL(r/100f, g/100f, b/100f);
+ col.setColor(hsl.toRgb());
+ }
+
+ public static class WColorBox extends WWidget {
+ protected int color = 0xFF_FFFFFF;
+ public WColorBox() {}
+
+ public WColorBox(int col) {
+ this.color = col;
+ }
+
+ @Override
+ public boolean canResize() {
+ return true;
+ }
+
+ public void setColor(int col) {
+ this.color = col;
+ }
+
+ @Override
+ public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
+ ScreenDrawing.coloredRect(matrices, x, y, this.getWidth(), this.getHeight(), color);
+ }
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/TextFieldTestGui.java b/src/testMod/java/io/github/cottonmc/test/client/TextFieldTestGui.java
new file mode 100644
index 0000000..ce2a7b6
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/TextFieldTestGui.java
@@ -0,0 +1,20 @@
+package io.github.cottonmc.test.client;
+
+import net.minecraft.item.Items;
+import net.minecraft.text.Text;
+
+import io.github.cottonmc.cotton.gui.client.LightweightGuiDescription;
+import io.github.cottonmc.cotton.gui.widget.WButton;
+import io.github.cottonmc.cotton.gui.widget.WGridPanel;
+import io.github.cottonmc.cotton.gui.widget.WTextField;
+import io.github.cottonmc.cotton.gui.widget.icon.ItemIcon;
+
+public class TextFieldTestGui extends LightweightGuiDescription {
+ public TextFieldTestGui() {
+ WGridPanel grid = (WGridPanel) rootPanel;
+ WTextField textField = new WTextField(Text.literal("Type something")).setMaxLength(Integer.MAX_VALUE);
+ grid.add(textField, 0, 0, 6, 1);
+ grid.add(new WButton(new ItemIcon(Items.BARRIER), Text.literal("Clear")).setOnClick(() -> textField.setText("")), 0, 2, 6, 1);
+ rootPanel.validate(this);
+ }
+}
diff --git a/src/testMod/java/io/github/cottonmc/test/client/WHudTest.java b/src/testMod/java/io/github/cottonmc/test/client/WHudTest.java
new file mode 100644
index 0000000..98f4d0f
--- /dev/null
+++ b/src/testMod/java/io/github/cottonmc/test/client/WHudTest.java
@@ -0,0 +1,25 @@
+package io.github.cottonmc.test.client;
+
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.util.math.MatrixStack;
+
+import io.github.cottonmc.cotton.gui.client.ScreenDrawing;
+import io.github.cottonmc.cotton.gui.widget.WWidget;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+@Environment(EnvType.CLIENT)
+public class WHudTest extends WWidget {
+ private static final Logger LOGGER = LogManager.getLogger();
+
+ @Override
+ public void paint(MatrixStack matrices, int x, int y, int mouseX, int mouseY) {
+ ScreenDrawing.coloredRect(matrices, x, y, width, height, 0xFF_00FF00);
+ }
+
+ @Override
+ public void tick() {
+ LOGGER.debug("tick!");
+ }
+}
diff --git a/src/testMod/resources/assets/libgui-test/icon.png b/src/testMod/resources/assets/libgui-test/icon.png
new file mode 100644
index 0000000..4286522
--- /dev/null
+++ b/src/testMod/resources/assets/libgui-test/icon.png
Binary files differ
diff --git a/src/testMod/resources/assets/libgui-test/portal.png b/src/testMod/resources/assets/libgui-test/portal.png
new file mode 100644
index 0000000..cf64bcc
--- /dev/null
+++ b/src/testMod/resources/assets/libgui-test/portal.png
Binary files differ
diff --git a/src/testMod/resources/assets/libgui-test/portal2.png b/src/testMod/resources/assets/libgui-test/portal2.png
new file mode 100644
index 0000000..3a1c211
--- /dev/null
+++ b/src/testMod/resources/assets/libgui-test/portal2.png
Binary files differ
diff --git a/src/testMod/resources/assets/libgui-test/saddle.png b/src/testMod/resources/assets/libgui-test/saddle.png
new file mode 100644
index 0000000..84394b9
--- /dev/null
+++ b/src/testMod/resources/assets/libgui-test/saddle.png
Binary files differ
diff --git a/src/testMod/resources/fabric.mod.json b/src/testMod/resources/fabric.mod.json
new file mode 100644
index 0000000..2b6adc8
--- /dev/null
+++ b/src/testMod/resources/fabric.mod.json
@@ -0,0 +1,30 @@
+{
+ "schemaVersion": 1,
+ "id": "libgui-test",
+ "version": "1",
+ "name": "LibGui Test",
+ "description": "Some example Guis to shake out errors",
+ "authors": [
+ "Falkreon"
+ ],
+ "contact": {
+ "sources": "https://github.com/CottonMC/LibGUI"
+ },
+ "license": "MIT",
+ "icon": "assets/libgui-test/icon.png",
+ "environment": "*",
+ "entrypoints": {
+ "main": [
+ "io.github.cottonmc.test.LibGuiTest"
+ ],
+ "client": [
+ "io.github.cottonmc.test.client.LibGuiTestClient"
+ ]
+ },
+ "depends": {
+ "fabricloader": ">=0.4.0",
+ "libgui": "*",
+ "jankson": "*",
+ "fabric": "*"
+ }
+}