From 00ea4a6281d64b1d01cc5819b80df2f5ba9e2ccb Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Sat, 28 Aug 2021 00:26:35 +0300 Subject: [PATCH] Added player hand containers - Added EntityDataPlayer.{left,right}Hand - No in-world effect yet - List-like functionality of ItemContainer extracted into ItemContainerMixed - Reworked implementation of Inventory screen - Added optional arguments for Group - Added Components.center() --- .../client/graphics/gui/Component.java | 17 ++ .../client/graphics/gui/Components.java | 31 ++++ .../progressia/client/graphics/gui/Group.java | 8 + .../common/world/entity/EntityDataPlayer.java | 28 +++- .../common/world/item/ItemContainer.java | 126 +++------------ .../common/world/item/ItemContainerHand.java | 85 ++++++++++ .../common/world/item/ItemContainerMixed.java | 150 ++++++++++++++++++ ...ner.java => ItemContainerMixedSimple.java} | 25 +-- .../common/world/item/ItemSlot.java | 2 +- .../progressia/server/PlayerManager.java | 9 +- .../test/inv/DecoratedSlotComponent.java | 44 +++++ .../test/inv/InventoryComponent.java | 16 +- .../progressia/test/inv/InventoryScreen.java | 121 ++++++++++++++ .../progressia/test/inv/SlotComponent.java | 18 +-- .../test/inv/TestInventoryGUILayer.java | 57 +++---- .../test/inv/TestInventoryGUIManager.java | 2 +- 16 files changed, 564 insertions(+), 175 deletions(-) create mode 100644 src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java create mode 100644 src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerHand.java create mode 100644 src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java rename src/main/java/ru/windcorp/progressia/common/world/item/{DefaultItemContainer.java => ItemContainerMixedSimple.java} (68%) create mode 100644 src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java create mode 100644 src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 8f1aa9a..79cfddc 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -32,7 +32,9 @@ import com.google.common.eventbus.Subscribe; import glm.vec._2.i.Vec2i; import ru.windcorp.progressia.client.graphics.backend.InputTracker; +import ru.windcorp.progressia.client.graphics.flat.AssembledFlatRenderHelper; import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.flat.RenderTarget.Clip; import ru.windcorp.progressia.client.graphics.gui.event.ChildAddedEvent; import ru.windcorp.progressia.client.graphics.gui.event.ChildRemovedEvent; import ru.windcorp.progressia.client.graphics.gui.event.EnableEvent; @@ -44,6 +46,7 @@ import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.input.bus.InputBus; import ru.windcorp.progressia.client.graphics.input.bus.InputListener; +import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.common.util.Named; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.ReportingEventBus; @@ -844,6 +847,20 @@ public class Component extends Named { } } + + public Renderable assembleToRenderable() { + + RenderTarget target = new RenderTarget(); + assemble(target); + Clip[] clips = target.assemble(); + + return renderer -> { + for (Clip clip : clips) { + clip.render((AssembledFlatRenderHelper) renderer); + } + }; + + } // /** // * Returns a component that displays this component in its center. diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java new file mode 100644 index 0000000..a760106 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java @@ -0,0 +1,31 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.client.graphics.gui; + +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; + +public class Components { + + public static Component center(Component c) { + return new Group(c.getName() + ".Centerer", new LayoutAlign(), c); + } + + private Components() { + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java index d8a8b23..b3ddfcf 100755 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Group.java @@ -24,5 +24,13 @@ public class Group extends Component { super(name); setLayout(layout); } + + public Group(String name, Layout layout, Component... children) { + this(name, layout); + + for (Component child : children) { + addChild(child); + } + } } diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java index 323d781..4c9f598 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java @@ -20,23 +20,39 @@ package ru.windcorp.progressia.common.world.entity; import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.collision.AABB; import ru.windcorp.progressia.common.state.ObjectStateField; -import ru.windcorp.progressia.common.world.item.DefaultItemContainer; -import ru.windcorp.progressia.common.world.item.ItemContainer; +import ru.windcorp.progressia.common.world.item.ItemContainerMixedSimple; +import ru.windcorp.progressia.common.world.item.ItemContainerHand; +import ru.windcorp.progressia.common.world.item.ItemContainerMixed; public class EntityDataPlayer extends EntityData { - private final ObjectStateField inventory = field("Core:Inventory").setShared().def( - () -> new DefaultItemContainer("Core:PlayerInventory", Units.get(15, "kg"), Units.get(50, "L")) + private final ObjectStateField inventory = field("Core:Inventory").setShared().def( + () -> new ItemContainerMixedSimple("Core:PlayerInventory", Units.get(15, "kg"), Units.get(50, "L")) + ).build(); + + private final ObjectStateField leftHand = field("Core:LeftHand").setShared().def( + () -> new ItemContainerHand("Core:PlayerLeftHand", Units.get(10, "kg"), Units.get(5, "L")) + ).build(); + + private final ObjectStateField rightHand = field("Core:RightHand").setShared().def( + () -> new ItemContainerHand("Core:PlayerRightHand", Units.get(10, "kg"), Units.get(5, "L")) ).build(); public EntityDataPlayer(String id) { super(id); - setCollisionModel(new AABB(0, 0, 1.8f / 2, 0.8f, 0.8f, 1.8f)); } - public ItemContainer getInventory() { + public ItemContainerMixed getInventory() { return inventory.get(this); } + + public ItemContainerHand getLeftHand() { + return leftHand.get(this); + } + + public ItemContainerHand getRightHand() { + return rightHand.get(this); + } } diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java index 027420b..7cb124a 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java @@ -17,52 +17,42 @@ */ package ru.windcorp.progressia.common.world.item; -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.Collections; -import java.util.List; +import java.util.function.Consumer; import ru.windcorp.progressia.common.state.Encodable; -import ru.windcorp.progressia.common.state.IOContext; import ru.windcorp.progressia.common.util.namespaces.Namespaced; /** - * A collection of {@link ItemSlot}s representing a single storage unit. The set - * of slots is dynamic: new slots may be added and existing slots may be removed - * at will. A container may impose limits on the maximum total mass and volume - * of its contents, although this is not enforced on data structure level. + * A collection of {@link ItemSlot}s representing a single storage unit. A + * container may impose limits on the maximum total mass and volume of its + * contents, although this is not enforced on data structure level. + *

+ * At any moment container has a definite amount of slots, each identified by a + * unique index. If a container has n slots, its slots are numbered 0 + * through n - 1. */ public abstract class ItemContainer extends Namespaced implements Encodable { - private final List synchronizedListView; - protected final List list; - - public ItemContainer(String id, List list) { + public ItemContainer(String id) { super(id); - this.list = list; - this.synchronizedListView = Collections.synchronizedList(list); } /** - * Retrieves the modifiable {@link List} of all slots. Edits commissioned - * through the returned object update the state of the container. - *

- * It should be assumed that the returned list is - * {@linkplain Collections#synchronizedList(List) synchronized}. + * Retrieves the slot with the given index. * - * @return a list view of this container + * @param index the index of the slot to retrieve + * @return the slot or {@code null} if the slot does not exist */ - public final List getSlots() { - return this.synchronizedListView; - } + public abstract ItemSlot getSlot(int index); /** - * Appends additional empty slots to the end of this container. + * Returns the current slot count of this container. * - * @param amount the amount of slots to add + * @return the number of slots in this container */ - public abstract void addSlots(int amount); + public abstract int getSlotCount(); + + public abstract void forEach(Consumer action); /** * Computes and returns the mass limit that the container imposes. @@ -82,84 +72,4 @@ public abstract class ItemContainer extends Namespaced implements Encodable { */ public abstract float getVolumeLimit(); - @Override - public synchronized void read(DataInput input, IOContext context) throws IOException { - List slots = getSlots(); - synchronized (slots) { - - int needSlots = input.readInt(); - int hasSlots = slots.size(); - - int costOfResetting = needSlots; - int costOfEditing = Math.abs(needSlots - hasSlots); - - if (costOfResetting < costOfEditing) { - slots.clear(); - addSlots(needSlots); - } else { - while (slots.size() > needSlots) { - getSlots().remove(slots.size() - 1); - } - - if (slots.size() < needSlots) { - addSlots(needSlots - slots.size()); - } - } - - for (int i = 0; i < needSlots; ++i) { - slots.get(i).read(input, context); - } - - } - } - - @Override - public synchronized void write(DataOutput output, IOContext context) throws IOException { - List slots = getSlots(); - synchronized (slots) { - - output.writeInt(slots.size()); - for (int i = 0; i < slots.size(); ++i) { - slots.get(i).write(output, context); - } - - } - } - - @Override - public void copy(Encodable destination) { - ItemContainer container = (ItemContainer) destination; - List mySlots = this.getSlots(); - List containerSlots = container.getSlots(); - - synchronized (mySlots) { - synchronized (containerSlots) { - - int needSlots = mySlots.size(); - int hasSlots = containerSlots.size(); - - int costOfResetting = needSlots; - int costOfEditing = Math.abs(needSlots - hasSlots); - - if (costOfResetting < costOfEditing) { - containerSlots.clear(); - container.addSlots(needSlots); - } else { - while (containerSlots.size() > needSlots) { - getSlots().remove(containerSlots.size() - 1); - } - - if (containerSlots.size() < needSlots) { - addSlots(needSlots - containerSlots.size()); - } - } - - for (int i = 0; i < needSlots; ++i) { - mySlots.get(i).copy(containerSlots.get(i)); - } - - } - } - } - } diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerHand.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerHand.java new file mode 100644 index 0000000..a6bc3b1 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerHand.java @@ -0,0 +1,85 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.common.world.item; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.function.Consumer; + +import ru.windcorp.progressia.common.state.Encodable; +import ru.windcorp.progressia.common.state.IOContext; + +public class ItemContainerHand extends ItemContainer { + + private final ItemSlot slot = new ItemSlot(); + + private final float massLimit; + private final float volumeLimit; + + public ItemContainerHand(String id, float massLimit, float volumeLimit) { + super(id); + this.massLimit = massLimit; + this.volumeLimit = volumeLimit; + } + + @Override + public void read(DataInput input, IOContext context) throws IOException { + slot.read(input, context); + } + + @Override + public void write(DataOutput output, IOContext context) throws IOException { + slot.write(output, context); + } + + @Override + public void copy(Encodable destination) { + slot.copy(((ItemContainerHand) destination).slot); + } + + @Override + public ItemSlot getSlot(int index) { + if (index == 0) { + return slot; + } else { + return null; + } + } + + @Override + public int getSlotCount() { + return 1; + } + + @Override + public void forEach(Consumer action) { + action.accept(slot); + } + + @Override + public float getMassLimit() { + return massLimit; + } + + @Override + public float getVolumeLimit() { + return volumeLimit; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java new file mode 100644 index 0000000..c6d4b44 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java @@ -0,0 +1,150 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.common.world.item; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.List; +import java.util.function.Consumer; + +import ru.windcorp.progressia.common.state.Encodable; +import ru.windcorp.progressia.common.state.IOContext; + +/** + * An {@link ItemContainer} capable of storing multiple item stacks. The set + * of slots is dynamic: new slots may be added and existing slots may be removed + * at will. + */ +public abstract class ItemContainerMixed extends ItemContainer { + + public ItemContainerMixed(String id) { + super(id); + } + + /** + * Retrieves the modifiable {@link List} of all slots. Edits commissioned + * through the returned object update the state of the container. + * + * @return a list view of this container + */ + protected abstract List getSlots(); + + /** + * Appends additional empty slots to the end of this container. + * + * @param amount the amount of slots to add + */ + public abstract void addSlots(int amount); + + @Override + public ItemSlot getSlot(int index) { + return getSlots().get(index); + } + + @Override + public int getSlotCount() { + return getSlots().size(); + } + + @Override + public void forEach(Consumer action) { + getSlots().forEach(action); + } + + @Override + public synchronized void read(DataInput input, IOContext context) throws IOException { + List slots = getSlots(); + synchronized (slots) { + + int needSlots = input.readInt(); + int hasSlots = slots.size(); + + int costOfResetting = needSlots; + int costOfEditing = Math.abs(needSlots - hasSlots); + + if (costOfResetting < costOfEditing) { + slots.clear(); + addSlots(needSlots); + } else { + while (slots.size() > needSlots) { + getSlots().remove(slots.size() - 1); + } + + if (slots.size() < needSlots) { + addSlots(needSlots - slots.size()); + } + } + + for (int i = 0; i < needSlots; ++i) { + slots.get(i).read(input, context); + } + + } + } + + @Override + public synchronized void write(DataOutput output, IOContext context) throws IOException { + List slots = getSlots(); + synchronized (slots) { + + output.writeInt(slots.size()); + for (int i = 0; i < slots.size(); ++i) { + slots.get(i).write(output, context); + } + + } + } + + @Override + public void copy(Encodable destination) { + ItemContainerMixed container = (ItemContainerMixed) destination; + List mySlots = this.getSlots(); + List containerSlots = container.getSlots(); + + synchronized (mySlots) { + synchronized (containerSlots) { + + int needSlots = mySlots.size(); + int hasSlots = containerSlots.size(); + + int costOfResetting = needSlots; + int costOfEditing = Math.abs(needSlots - hasSlots); + + if (costOfResetting < costOfEditing) { + containerSlots.clear(); + container.addSlots(needSlots); + } else { + while (containerSlots.size() > needSlots) { + getSlots().remove(containerSlots.size() - 1); + } + + if (containerSlots.size() < needSlots) { + addSlots(needSlots - containerSlots.size()); + } + } + + for (int i = 0; i < needSlots; ++i) { + mySlots.get(i).copy(containerSlots.get(i)); + } + + } + } + } + +} diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/DefaultItemContainer.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixedSimple.java similarity index 68% rename from src/main/java/ru/windcorp/progressia/common/world/item/DefaultItemContainer.java rename to src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixedSimple.java index 40d47db..5748d41 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/item/DefaultItemContainer.java +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixedSimple.java @@ -18,25 +18,32 @@ package ru.windcorp.progressia.common.world.item; import java.util.ArrayList; +import java.util.List; -public class DefaultItemContainer extends ItemContainer { +public class ItemContainerMixedSimple extends ItemContainerMixed { + + private final List list; private final float massLimit; private final float volumeLimit; - public DefaultItemContainer(String id, float massLimit, float volumeLimit) { - super(id, new ArrayList<>()); + public ItemContainerMixedSimple(String id, float massLimit, float volumeLimit) { + super(id); + this.list = new ArrayList<>(); this.massLimit = massLimit; this.volumeLimit = volumeLimit; } + + @Override + protected List getSlots() { + return list; + } @Override - public void addSlots(int amount) { - synchronized (getSlots()) { - ((ArrayList) list).ensureCapacity(list.size() + amount); - for (int i = 0; i < amount; ++i) { - list.add(new ItemSlot()); - } + public synchronized void addSlots(int amount) { + ((ArrayList) list).ensureCapacity(list.size() + amount); + for (int i = 0; i < amount; ++i) { + list.add(new ItemSlot()); } } diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemSlot.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemSlot.java index 45d5478..1baa70a 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/item/ItemSlot.java +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemSlot.java @@ -26,7 +26,7 @@ import ru.windcorp.progressia.common.state.IOContext; /** * An entity optionally containing an {@link ItemData}. Item slots are typically - * found in {@link ItemContainer}s. + * found in {@link ItemContainerMixed}s. */ public class ItemSlot implements Encodable { diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index d33b4d7..abcc8d6 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -68,9 +68,14 @@ public class PlayerManager { ItemData stack = ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"); stack.setSizeNow(5); - player.getInventory().getSlots().get(3).setContents(stack); + player.getInventory().getSlot(3).setContents(stack); - player.getInventory().getSlots().get(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream")); + player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream")); + + player.getLeftHand().getSlot(0).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream")); + stack = ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"); + stack.setSizeNow(64); + player.getRightHand().getSlot(0).setContents(stack); player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation()); player.setUpVector(new Vec3(0, 0, 1)); diff --git a/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java b/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java new file mode 100644 index 0000000..da68eec --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java @@ -0,0 +1,44 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.test.inv; + +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.gui.Button; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; +import ru.windcorp.progressia.common.world.item.ItemSlot; + +public class DecoratedSlotComponent extends Button { + + private final SlotComponent slotComponent; + + public DecoratedSlotComponent(String name, ItemSlot slot) { + super(name, null, null); + this.slotComponent = new SlotComponent(name, slot); + + Vec2i size = slotComponent.getPreferredSize().add(2 * BORDER); + setPreferredSize(size); + + addChild(new SlotComponent(name, slot)); + setLayout(new LayoutFill(MARGIN)); + } + + public ItemSlot getSlot() { + return slotComponent.getSlot(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java b/src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java index 425dd2f..864cbf0 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java +++ b/src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java @@ -27,31 +27,25 @@ import ru.windcorp.progressia.common.world.item.ItemSlot; public class InventoryComponent extends Component { - private final TestInventoryGUILayer layer; private final Group slots = new Group("Inventory.Slots", new LayoutGrid(15)); - public InventoryComponent(TestInventoryGUILayer layer) { + public InventoryComponent(ItemContainer container) { super("Inventory"); - this.layer = layer; setLayout(new LayoutBorderHorizontal(15)); addChild(slots.setLayoutHint(LayoutBorderHorizontal.CENTER)); - getContainer().getSlots().forEach(this::addSlot); + container.forEach(this::addSlot); } private void addSlot(ItemSlot slot) { final int maxX = 6; int i = slots.getChildren().size(); - - SlotComponent component = new SlotComponent("Inventory.Slot" + i, slot); - + + DecoratedSlotComponent component = new DecoratedSlotComponent("Inventory.Slot" + i, slot); + Vec2i pos = new Vec2i(i % maxX, i / maxX); slots.addChild(component.setLayoutHint(pos)); } - private ItemContainer getContainer() { - return layer.container; - } - } diff --git a/src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java b/src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java new file mode 100644 index 0000000..52b1a60 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java @@ -0,0 +1,121 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.test.inv; + +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.Colors; +import ru.windcorp.progressia.client.graphics.backend.InputTracker; +import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.gui.Component; +import ru.windcorp.progressia.client.graphics.gui.Components; +import ru.windcorp.progressia.client.graphics.gui.Group; +import ru.windcorp.progressia.client.graphics.gui.Layout; +import ru.windcorp.progressia.client.graphics.gui.Panel; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; +import ru.windcorp.progressia.client.graphics.model.Renderable; +import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; + +public class InventoryScreen extends Component { + + public static class CursorFollower extends Component { + + public CursorFollower(Component child) { + super("CursorFollower"); + addChild(child); + setLayout(null); + + Vec2i size = child.getPreferredSize(); + child.setBounds(-size.x / 2, -size.y / 2, size); + layoutSelf(); + } + + @Override + protected void assembleChildren(RenderTarget target) { + Renderable renderable = getChildren().get(0).assembleToRenderable(); + + target.addCustomRenderer(renderer -> { + renderer.pushTransform().translate( + (float) InputTracker.getCursorX(), + (float) InputTracker.getCursorY(), + 0 + ); + + renderable.render(renderer); + + renderer.popTransform(); + + }); + } + + } + + private final Component hands; + + public InventoryScreen(String name, Component mainInventory, EntityDataPlayer player) { + super(name); + + setLayout(new LayoutFill(0)); + + addChild(new Panel(name + ".Background", new LayoutAlign(10), Colors.toVector(0x66000000), null)); + + Panel mainInventoryPanel = new Panel(name + ".Content", new LayoutFill(20)); + mainInventoryPanel.addChild(mainInventory); + addChild(Components.center(mainInventoryPanel)); + + this.hands = createHands(name, player); + addChild(new CursorFollower(this.hands)); + } + + private Component createHands(String name, EntityDataPlayer player) { + + SlotComponent leftHand = new SlotComponent(name + ".HandLeft", player.getLeftHand().getSlot(0)); + SlotComponent rightHand = new SlotComponent(name + ".HandRight", player.getRightHand().getSlot(0)); + + final int gap = 15; + final int offset = 60; + + Component hands = new Group(name + ".Hands", null, leftHand, rightHand); + hands.setLayout(new Layout() { + + @Override + public void layout(Component c) { + Vec2i leftSize = leftHand.getPreferredSize(); + Vec2i rightSize = rightHand.getPreferredSize(); + + leftHand.setBounds(c.getX(), c.getY(), leftSize); + rightHand.setBounds(c.getX() + leftSize.x + gap, c.getY() + offset, rightSize); + } + + @Override + public Vec2i calculatePreferredSize(Component c) { + Vec2i leftSize = leftHand.getPreferredSize(); + Vec2i rightSize = rightHand.getPreferredSize(); + + return new Vec2i( + leftSize.x + gap + rightSize.x, + Math.max(leftSize.y + offset, rightSize.y + offset) + ); + } + + }); + + return hands; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java b/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java index d9adf69..7dc76c9 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java +++ b/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java @@ -20,7 +20,7 @@ package ru.windcorp.progressia.test.inv; import glm.mat._4.Mat4; import ru.windcorp.progressia.client.graphics.flat.RenderTarget; import ru.windcorp.progressia.client.graphics.font.Font; -import ru.windcorp.progressia.client.graphics.gui.Button; +import ru.windcorp.progressia.client.graphics.gui.Component; import ru.windcorp.progressia.client.graphics.gui.DynamicLabel; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; import ru.windcorp.progressia.client.world.item.ItemRenderRegistry; @@ -28,10 +28,10 @@ import ru.windcorp.progressia.client.world.item.ItemRenderable; import ru.windcorp.progressia.common.world.item.ItemData; import ru.windcorp.progressia.common.world.item.ItemSlot; -public class SlotComponent extends Button { +public class SlotComponent extends Component { - private static final float TEXTURE_SIZE = 24; - private static final float SCALE = 2; + static final float TEXTURE_SIZE = 24; + static final float SCALE = 2; private final ItemSlot slot; private ItemRenderable itemRenderer = null; @@ -40,16 +40,16 @@ public class SlotComponent extends Button { private String sizeDisplayString = ""; public SlotComponent(String name, ItemSlot slot) { - super(name, null, null); + super(name); this.slot = slot; - int side = (int) (TEXTURE_SIZE * SCALE) + 2 * BORDER; + int side = (int) (TEXTURE_SIZE * SCALE); setPreferredSize(side, side); Font sizeFont = new Font().deriveOutlined().withScale(1); - addChild(new DynamicLabel(name + ".Size", sizeFont, () -> sizeDisplayString, side - 2 * MARGIN)); + addChild(new DynamicLabel(name + ".Size", sizeFont, () -> sizeDisplayString, side)); - setLayout(new LayoutAlign(0, 0, MARGIN)); + setLayout(new LayoutAlign(0, 0, 0)); } public ItemSlot getSlot() { @@ -87,7 +87,7 @@ public class SlotComponent extends Button { private void assembleItem(RenderTarget target) { if (itemRenderer != null) { - target.pushTransform(new Mat4().translate(getX() + BORDER, getY() + BORDER, 0).scale(SCALE)); + target.pushTransform(new Mat4().translate(getX(), getY(), 0).scale(SCALE)); target.addCustomRenderer(itemRenderer); target.popTransform(); } diff --git a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java b/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java index 0498972..8b4f865 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java +++ b/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java @@ -20,71 +20,72 @@ package ru.windcorp.progressia.test.inv; import org.lwjgl.glfw.GLFW; import ru.windcorp.progressia.client.graphics.GUI; -import ru.windcorp.progressia.client.graphics.gui.menu.MenuLayer; +import ru.windcorp.progressia.client.graphics.gui.GUILayer; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; import ru.windcorp.progressia.client.graphics.input.bus.Input; -import ru.windcorp.progressia.common.world.item.ItemContainer; +import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; +import ru.windcorp.progressia.common.world.item.ItemContainerMixed; -public class TestInventoryGUILayer extends MenuLayer { - - ItemContainer container; - private InventoryComponent display = null; +public class TestInventoryGUILayer extends GUILayer { + + private ItemContainerMixed container; + + private InventoryScreen display = null; public TestInventoryGUILayer() { - super("Inventory"); + super("Inventory", new LayoutFill(0)); setCursorPolicy(CursorPolicy.INDIFFERENT); - - addTitle(); // pppffffttt } - - public void setContainer(ItemContainer container) { + + public void setContainer(ItemContainerMixed container, EntityDataPlayer player) { this.container = container; - - getContent().removeChild(display); + + getRoot().removeChild(display); display = null; - + if (container != null) { - display = new InventoryComponent(this); - getContent().addChild(display); + display = new InventoryScreen("Screen", new InventoryComponent(container), player); + + getRoot().addChild(display); invalidate(); - + setCursorPolicy(CursorPolicy.REQUIRE); } else { setCursorPolicy(CursorPolicy.INDIFFERENT); } - + GUI.updateLayer(this); } - @Override - protected Runnable getCloseAction() { - return () -> setContainer(null); - } - @Override protected void doRender() { if (container != null) { super.doRender(); } } - + @Override protected void handleInput(Input input) { if (container != null) { if (!input.isConsumed()) { InputEvent event = input.getEvent(); - + if (event instanceof KeyEvent) { KeyEvent keyEvent = (KeyEvent) event; - if (keyEvent.isPress() && keyEvent.getKey() == GLFW.GLFW_KEY_E) { - getCloseAction().run(); + if ( + keyEvent.isPress() + && (keyEvent.getKey() == GLFW.GLFW_KEY_E || keyEvent.getKey() == GLFW.GLFW_KEY_ESCAPE) + ) { + setContainer(null, null); input.consume(); } } } - + super.handleInput(input); + input.consume(); } } diff --git a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java b/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java index 6af3966..0181a3c 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java +++ b/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java @@ -52,7 +52,7 @@ public class TestInventoryGUIManager { return; } - layer.setContainer(entity.getInventory()); + layer.setContainer(entity.getInventory(), entity); }