Rewrote inventory GUI code to be more coherent. WIP
- Added an equipment slot - Added equipment slot displays - Added HUDManager and refactored layer management - Moved most files from .test.inv to .client.graphics.world.hud - Added component hider - Which is broken because z-index - Why do I use depth stencils in flat layers again? - Refactored KeyMatcher: removed Builders, added action selection
This commit is contained in:
parent
bd6442318d
commit
05b1c73fbc
@ -25,22 +25,34 @@ import ru.windcorp.progressia.client.comms.DefaultClientCommsListener;
|
||||
import ru.windcorp.progressia.client.comms.ServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.events.ClientEvent;
|
||||
import ru.windcorp.progressia.client.events.NewLocalEntityEvent;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.world.Camera;
|
||||
import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
|
||||
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
||||
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.HUDManager;
|
||||
import ru.windcorp.progressia.client.world.WorldRender;
|
||||
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||
import ru.windcorp.progressia.common.world.DefaultWorldData;
|
||||
import ru.windcorp.progressia.test.LayerAbout;
|
||||
import ru.windcorp.progressia.test.LayerTestUI;
|
||||
|
||||
public class Client {
|
||||
|
||||
private final WorldRender world;
|
||||
|
||||
private final LayerWorld layerWorld = new LayerWorld(this);
|
||||
private final LayerTestUI layerTestUI = new LayerTestUI();
|
||||
private final LayerAbout layerAbout = new LayerAbout();
|
||||
|
||||
private final LocalPlayer localPlayer = new LocalPlayer(this);
|
||||
|
||||
private final Camera camera = new Camera((float) Math.toRadians(70));
|
||||
|
||||
private final EventBus eventBus = ReportingEventBus.create("ClientEvents");
|
||||
|
||||
private final HUDManager hudManager = new HUDManager(this);
|
||||
|
||||
private final ServerCommsChannel comms;
|
||||
|
||||
public Client(DefaultWorldData world, ServerCommsChannel comms) {
|
||||
@ -51,6 +63,20 @@ public class Client {
|
||||
subscribe(this);
|
||||
}
|
||||
|
||||
public void install() {
|
||||
GUI.addBottomLayer(layerWorld);
|
||||
GUI.addTopLayer(layerTestUI);
|
||||
hudManager.install();
|
||||
GUI.addTopLayer(layerAbout);
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
GUI.removeLayer(layerWorld);
|
||||
GUI.removeLayer(layerTestUI);
|
||||
hudManager.remove();
|
||||
GUI.removeLayer(layerAbout);
|
||||
}
|
||||
|
||||
public WorldRender getWorld() {
|
||||
return world;
|
||||
}
|
||||
@ -71,6 +97,10 @@ public class Client {
|
||||
return comms;
|
||||
}
|
||||
|
||||
public HUDManager getHUD() {
|
||||
return hudManager;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onLocalPlayerEntityChanged(NewLocalEntityEvent e) {
|
||||
if (e.getNewEntity() == null) {
|
||||
|
@ -19,15 +19,9 @@
|
||||
package ru.windcorp.progressia.client;
|
||||
|
||||
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.LayerHUD;
|
||||
import ru.windcorp.progressia.common.world.DefaultWorldData;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
import ru.windcorp.progressia.test.LayerAbout;
|
||||
import ru.windcorp.progressia.test.LayerTestUI;
|
||||
import ru.windcorp.progressia.test.TestContent;
|
||||
import ru.windcorp.progressia.test.inv.TestInventoryGUIManager;
|
||||
|
||||
public class ClientState {
|
||||
|
||||
@ -55,12 +49,7 @@ public class ClientState {
|
||||
|
||||
setInstance(client);
|
||||
|
||||
GUI.addBottomLayer(new LayerWorld(client));
|
||||
GUI.addTopLayer(new LayerTestUI());
|
||||
GUI.addTopLayer(new LayerHUD(client));
|
||||
TestInventoryGUIManager.setup();
|
||||
GUI.addTopLayer(new LayerAbout());
|
||||
|
||||
client.install();
|
||||
}
|
||||
|
||||
private ClientState() {
|
||||
|
@ -43,6 +43,7 @@ import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent;
|
||||
import ru.windcorp.progressia.client.graphics.gui.event.ParentChangedEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyMatcher;
|
||||
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;
|
||||
@ -557,7 +558,7 @@ public class Component extends Named {
|
||||
inputBus.register(type, handlesConsumed, listener);
|
||||
}
|
||||
|
||||
public <T extends InputEvent> void addListener(Class<? extends T> type, InputListener<T> listener) {
|
||||
public <T extends InputEvent> void addListener(Class<T> type, InputListener<? super T> listener) {
|
||||
if (inputBus == null) {
|
||||
inputBus = new InputBus();
|
||||
}
|
||||
@ -565,6 +566,29 @@ public class Component extends Named {
|
||||
inputBus.register(type, listener);
|
||||
}
|
||||
|
||||
public <T extends InputEvent> void addListener(Class<T> type, Runnable listener) {
|
||||
addListener(type, event -> {
|
||||
listener.run();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void addListener(KeyMatcher matcher, InputListener<? super KeyEvent> listener) {
|
||||
addListener(KeyEvent.class, event -> {
|
||||
if (matcher.test(event)) {
|
||||
return listener.handle(event);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public void addListener(KeyMatcher matcher, Runnable listener) {
|
||||
addListener(matcher, event -> {
|
||||
listener.run();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public void removeListener(InputListener<?> listener) {
|
||||
if (inputBus != null) {
|
||||
inputBus.unregister(listener);
|
||||
|
@ -17,6 +17,8 @@
|
||||
*/
|
||||
package ru.windcorp.progressia.client.graphics.gui;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
||||
|
||||
public class Components {
|
||||
@ -25,6 +27,10 @@ public class Components {
|
||||
return new Group(c.getName() + ".Centerer", new LayoutAlign(), c);
|
||||
}
|
||||
|
||||
public static Component hide(Component c, BooleanSupplier shouldHide) {
|
||||
return new Hider(c.getName() + ".Hider", c, shouldHide);
|
||||
}
|
||||
|
||||
private Components() {
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.client.graphics.gui;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||
|
||||
public class Hider extends Component {
|
||||
|
||||
private final BooleanSupplier shouldHide;
|
||||
private final Component contents;
|
||||
|
||||
public Hider(String name, Component contents, BooleanSupplier shouldHide) {
|
||||
super(name);
|
||||
this.contents = contents;
|
||||
this.shouldHide = shouldHide;
|
||||
|
||||
setLayout(new LayoutFill());
|
||||
addChild(contents);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInput(Input input) {
|
||||
if (shouldHide.getAsBoolean()) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.handleInput(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assembleChildren(RenderTarget target) {
|
||||
Renderable renderable = contents.assembleToRenderable();
|
||||
target.addCustomRenderer(renderer -> {
|
||||
if (!shouldHide.getAsBoolean()) {
|
||||
renderable.render(renderer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -18,22 +18,33 @@
|
||||
|
||||
package ru.windcorp.progressia.client.graphics.input;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public class KeyMatcher {
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
|
||||
public class KeyMatcher implements Predicate<KeyEvent> {
|
||||
|
||||
private static final int ANY_ACTION = -1;
|
||||
|
||||
private final int key;
|
||||
private final int mods;
|
||||
private final int action;
|
||||
|
||||
protected KeyMatcher(int key, int mods) {
|
||||
protected KeyMatcher(int key, int mods, int action) {
|
||||
this.key = key;
|
||||
this.mods = mods;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public boolean matches(KeyEvent event) {
|
||||
if (!event.isPress())
|
||||
@Override
|
||||
public boolean test(KeyEvent event) {
|
||||
if (action != ANY_ACTION && event.getAction() != action)
|
||||
return false;
|
||||
if (event.getKey() != getKey())
|
||||
return false;
|
||||
@ -51,48 +62,79 @@ public class KeyMatcher {
|
||||
return mods;
|
||||
}
|
||||
|
||||
public static KeyMatcher.Builder of(int key) {
|
||||
return new KeyMatcher.Builder(key);
|
||||
public int getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final int key;
|
||||
private int mods = 0;
|
||||
|
||||
public Builder(int key) {
|
||||
this.key = key;
|
||||
public static KeyMatcher of(int key) {
|
||||
return new KeyMatcher(key, 0, GLFW.GLFW_PRESS);
|
||||
}
|
||||
|
||||
public Builder with(int modifier) {
|
||||
this.mods += modifier;
|
||||
return this;
|
||||
private static final Map<String, KeyMatcher> RESOLVED_KEYS = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
public static KeyMatcher of(String glfwConstantName) {
|
||||
return RESOLVED_KEYS.computeIfAbsent(glfwConstantName, givenName -> {
|
||||
String expectedName = "GLFW_KEY_" + givenName.toUpperCase();
|
||||
|
||||
try {
|
||||
Field field = GLFW.class.getDeclaredField(expectedName);
|
||||
return of(field.getInt(null));
|
||||
} catch (NoSuchFieldException e) {
|
||||
String hint = "";
|
||||
|
||||
if (glfwConstantName.startsWith("GLFW_KEY_")) {
|
||||
hint = " (remove prefix \"GLFW_KEY_\")";
|
||||
}
|
||||
|
||||
public Builder withShift() {
|
||||
throw new IllegalArgumentException("Unknown key constant \"" + glfwConstantName + "\"" + hint);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw CrashReports.report(e, "Could not access GLFW key field {}", expectedName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static KeyMatcher ofLeftMouseButton() {
|
||||
return new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_LEFT, 0, GLFW.GLFW_PRESS);
|
||||
}
|
||||
|
||||
public static KeyMatcher ofRightMouseButton() {
|
||||
return new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_RIGHT, 0, GLFW.GLFW_PRESS);
|
||||
}
|
||||
|
||||
public static KeyMatcher ofMiddleMouseButton() {
|
||||
return new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_MIDDLE, 0, GLFW.GLFW_PRESS);
|
||||
}
|
||||
|
||||
public KeyMatcher with(int modifier) {
|
||||
return new KeyMatcher(key, this.mods + modifier, action);
|
||||
}
|
||||
|
||||
public KeyMatcher withShift() {
|
||||
return with(GLFW.GLFW_MOD_SHIFT);
|
||||
}
|
||||
|
||||
public Builder withCtrl() {
|
||||
public KeyMatcher withCtrl() {
|
||||
return with(GLFW.GLFW_MOD_CONTROL);
|
||||
}
|
||||
|
||||
public Builder withAlt() {
|
||||
public KeyMatcher withAlt() {
|
||||
return with(GLFW.GLFW_MOD_ALT);
|
||||
}
|
||||
|
||||
public Builder withSuper() {
|
||||
public KeyMatcher withSuper() {
|
||||
return with(GLFW.GLFW_MOD_SUPER);
|
||||
}
|
||||
|
||||
public KeyMatcher build() {
|
||||
return new KeyMatcher(key, mods);
|
||||
public KeyMatcher onRelease() {
|
||||
return new KeyMatcher(key, mods, GLFW.GLFW_RELEASE);
|
||||
}
|
||||
|
||||
public Predicate<KeyEvent> matcher() {
|
||||
return build()::matches;
|
||||
public KeyMatcher onRepeat() {
|
||||
return new KeyMatcher(key, mods, GLFW.GLFW_REPEAT);
|
||||
}
|
||||
|
||||
public KeyMatcher onAnyAction() {
|
||||
return new KeyMatcher(key, mods, ANY_ACTION);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.test.inv;
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import glm.vec._3.Vec3;
|
||||
import glm.vec._4.Vec4;
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.test.inv;
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
import ru.windcorp.progressia.client.graphics.ExponentAnimation;
|
||||
@ -24,14 +24,13 @@ import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Component;
|
||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.SlotComponent;
|
||||
import ru.windcorp.progressia.client.world.entity.SpeciesRender;
|
||||
import ru.windcorp.progressia.client.world.entity.SpeciesRenderRegistry;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.entity.SpeciesData.Hand;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainerHand;
|
||||
|
||||
public class HandSlots extends Component {
|
||||
public class CursorHUD extends Component {
|
||||
|
||||
private class CursorBoundSlot {
|
||||
|
||||
@ -64,7 +63,7 @@ public class HandSlots extends Component {
|
||||
float target = player.getSelectedHand() == component.getSlot().getContainer() ? 1 : 0;
|
||||
float sel = selection.updateForFrame(target);
|
||||
|
||||
float distance = HandSlots.this.distance * (1 - sel);
|
||||
float distance = CursorHUD.this.distance * (1 - sel);
|
||||
float x = (float) Math.cos(angle) * distance;
|
||||
float y = (float) Math.sin(angle) * distance;
|
||||
float scale = 0.5f + 0.5f * sel;
|
||||
@ -97,7 +96,7 @@ public class HandSlots extends Component {
|
||||
|
||||
private final CursorBoundSlot[] slots;
|
||||
|
||||
public HandSlots(String name, EntityDataPlayer player) {
|
||||
public CursorHUD(String name, EntityDataPlayer player) {
|
||||
super(name);
|
||||
this.player = player;
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
|
||||
public class HUDManager implements HUDWorkspace {
|
||||
|
||||
private final Client client;
|
||||
private final LayerHUD layer;
|
||||
|
||||
public HUDManager(Client client) {
|
||||
this.client = client;
|
||||
this.layer = new LayerHUD(this);
|
||||
}
|
||||
|
||||
public void install() {
|
||||
GUI.addTopLayer(layer);
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
GUI.removeLayer(layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openContainer(InventoryComponent component) {
|
||||
System.err.println("openContainer NYI");
|
||||
}
|
||||
|
||||
public void closeEverything() {
|
||||
System.err.println("closeEverything NYI");
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return layer.isHidden();
|
||||
}
|
||||
|
||||
public void setHidden(boolean hide) {
|
||||
layer.setHidden(hide);
|
||||
}
|
||||
|
||||
public boolean isInventoryShown() {
|
||||
return layer.isInventoryShown();
|
||||
}
|
||||
|
||||
public void setInventoryShown(boolean showInventory) {
|
||||
layer.setInventoryShown(showInventory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Client getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
}
|
@ -15,45 +15,29 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.test.inv;
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainerHand;
|
||||
|
||||
public class TestInventoryGUIManager {
|
||||
public interface HUDWorkspace {
|
||||
|
||||
public static TestInventoryGUILayer layer;
|
||||
Client getClient();
|
||||
|
||||
public static void setup() {
|
||||
layer = new TestInventoryGUILayer();
|
||||
GUI.addTopLayer(layer);
|
||||
default LocalPlayer getPlayer() {
|
||||
return getClient().getLocalPlayer();
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
GUI.getLayers().stream().filter(TestInventoryGUILayer.class::isInstance).forEach(GUI::removeLayer);
|
||||
layer = null;
|
||||
default EntityDataPlayer getPlayerEntity() {
|
||||
return getClient().getLocalPlayer().getEntity();
|
||||
}
|
||||
|
||||
public static void openGUI() {
|
||||
|
||||
Client client = ClientState.getInstance();
|
||||
if (client == null) {
|
||||
return;
|
||||
default ItemContainerHand getHand() {
|
||||
return getClient().getLocalPlayer().getEntity().getSelectedHand();
|
||||
}
|
||||
|
||||
if (layer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityDataPlayer entity = client.getLocalPlayer().getEntity();
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
layer.setContainer(entity.getInventory(), entity);
|
||||
|
||||
}
|
||||
void openContainer(InventoryComponent component);
|
||||
|
||||
}
|
@ -36,7 +36,6 @@ import ru.windcorp.progressia.client.world.entity.SpeciesRender;
|
||||
import ru.windcorp.progressia.client.world.entity.SpeciesRenderRegistry;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.entity.SpeciesData.Hand;
|
||||
import ru.windcorp.progressia.test.inv.TestInventoryGUIManager;
|
||||
|
||||
public class HandsHUD extends Component {
|
||||
|
||||
@ -91,11 +90,11 @@ public class HandsHUD extends Component {
|
||||
|
||||
private final LocalPlayer player;
|
||||
|
||||
public HandsHUD(String name, LocalPlayer player) {
|
||||
public HandsHUD(String name, HUDManager manager) {
|
||||
super(name);
|
||||
this.player = player;
|
||||
this.player = manager.getPlayer();
|
||||
|
||||
EntityDataPlayer entity = player.getEntity();
|
||||
EntityDataPlayer entity = manager.getPlayerEntity();
|
||||
String speciesId = entity.getSpecies().getId();
|
||||
SpeciesRender speciesRender = SpeciesRenderRegistry.getInstance().get(speciesId);
|
||||
|
||||
@ -130,7 +129,7 @@ public class HandsHUD extends Component {
|
||||
}
|
||||
|
||||
private boolean shouldRenderHandPlaceholder() {
|
||||
return TestInventoryGUIManager.layer.hasContainer();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Button;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyMatcher;
|
||||
import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent;
|
||||
import ru.windcorp.progressia.common.Units;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainer;
|
||||
import ru.windcorp.progressia.common.world.item.ItemSlot;
|
||||
import ru.windcorp.progressia.common.world.item.Items;
|
||||
|
||||
public class InteractiveSlotComponent extends Button {
|
||||
|
||||
private static final double MIN_PICK_ALL_DELAY = Units.get("0.5 s");
|
||||
|
||||
private double lastMainAction = Double.NEGATIVE_INFINITY;
|
||||
|
||||
private final SlotComponent slotComponent;
|
||||
private final HUDWorkspace workspace;
|
||||
|
||||
public InteractiveSlotComponent(String name, ItemContainer container, int index, HUDWorkspace workspace) {
|
||||
this(name, new SlotComponent(name, container, index), workspace);
|
||||
}
|
||||
|
||||
public InteractiveSlotComponent(SlotComponent component, HUDWorkspace workspace) {
|
||||
this(component.getName() + ".Interactive", component, workspace);
|
||||
}
|
||||
|
||||
public InteractiveSlotComponent(String name, SlotComponent component, HUDWorkspace workspace) {
|
||||
super(name, null, null);
|
||||
this.slotComponent = component;
|
||||
this.workspace = workspace;
|
||||
|
||||
Vec2i size = slotComponent.getPreferredSize().add(2 * BORDER);
|
||||
setPreferredSize(size);
|
||||
|
||||
addChild(this.slotComponent);
|
||||
setLayout(new LayoutFill(MARGIN));
|
||||
|
||||
addListeners();
|
||||
}
|
||||
|
||||
private void addListeners() {
|
||||
addAction(button -> onMainAction());
|
||||
|
||||
addListener(KeyMatcher.ofRightMouseButton(), this::onAltAction);
|
||||
|
||||
addListener(WheelScrollEvent.class, event -> {
|
||||
if (event.hasVerticalMovement()) {
|
||||
onSingleMoveAction(event.isDown());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void onMainAction() {
|
||||
ItemSlot handSlot = workspace.getHand().slot();
|
||||
ItemSlot invSlot = getSlot();
|
||||
|
||||
boolean success = false;
|
||||
|
||||
double now = GraphicsInterface.getTime();
|
||||
if (now - lastMainAction < MIN_PICK_ALL_DELAY) {
|
||||
lastMainAction = Double.NEGATIVE_INFINITY;
|
||||
pickAll(handSlot);
|
||||
success = true;
|
||||
} else {
|
||||
lastMainAction = now;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.pour(handSlot, invSlot) != 0;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.swap(handSlot, invSlot);
|
||||
}
|
||||
|
||||
if (!success && handSlot.isEmpty()) {
|
||||
success = Items.pour(invSlot, handSlot) != 0;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
requestReassembly();
|
||||
}
|
||||
}
|
||||
|
||||
private void pickAll(ItemSlot handSlot) {
|
||||
for (ItemSlot invSlot : getSlot().getContainer()) {
|
||||
Items.pour(invSlot, handSlot);
|
||||
if (handSlot.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onAltAction() {
|
||||
ItemSlot handSlot = workspace.getHand().slot();
|
||||
ItemSlot invSlot = getSlot();
|
||||
|
||||
boolean success = false;
|
||||
|
||||
if (handSlot.isEmpty()) {
|
||||
success = Items.pour(invSlot, handSlot, invSlot.getAmount() / 2) != 0;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.pour(handSlot, invSlot, 1) != 0;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.swap(handSlot, invSlot);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
requestReassembly();
|
||||
}
|
||||
}
|
||||
|
||||
private void onSingleMoveAction(boolean fromHand) {
|
||||
ItemSlot handSlot = workspace.getHand().slot();
|
||||
ItemSlot invSlot = getSlot();
|
||||
|
||||
ItemSlot from = fromHand ? handSlot : invSlot;
|
||||
ItemSlot into = fromHand ? invSlot : handSlot;
|
||||
|
||||
if (Items.pour(from, into, 1) != 0) {
|
||||
requestReassembly();
|
||||
}
|
||||
}
|
||||
|
||||
public ItemSlot getSlot() {
|
||||
return slotComponent.getSlot();
|
||||
}
|
||||
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.test.inv;
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@ -27,6 +27,6 @@ public abstract class InventoryComponent extends Component {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public abstract Collection<DecoratedSlotComponent> getSlots();
|
||||
public abstract Collection<InteractiveSlotComponent> getSlots();
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.gui.Component;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Group;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutBorderHorizontal;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
|
||||
import ru.windcorp.progressia.client.world.entity.SpeciesRender;
|
||||
import ru.windcorp.progressia.client.world.entity.SpeciesRenderRegistry;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.entity.SpeciesData.EquipmentSlot;
|
||||
|
||||
public class InventoryHUD extends Component {
|
||||
|
||||
public enum Side {
|
||||
LEFT("Left", LayoutBorderHorizontal.LEFT),
|
||||
RIGHT("Right", LayoutBorderHorizontal.RIGHT);
|
||||
|
||||
private final String ccName;
|
||||
private final Object lbhHint;
|
||||
|
||||
private Side(String ccName, Object lbhHint) {
|
||||
this.ccName = ccName;
|
||||
this.lbhHint = lbhHint;
|
||||
}
|
||||
}
|
||||
|
||||
public InventoryHUD(String name, HUDWorkspace workspace) {
|
||||
super(name);
|
||||
setLayout(new LayoutBorderHorizontal());
|
||||
|
||||
EntityDataPlayer entity = workspace.getPlayerEntity();
|
||||
String speciesId = entity.getSpecies().getId();
|
||||
SpeciesRender speciesRender = SpeciesRenderRegistry.getInstance().get(speciesId);
|
||||
|
||||
Map<Side, Component> containers = Maps.toMap(
|
||||
Arrays.asList(Side.values()),
|
||||
side -> new Group(name + "." + side.ccName, new LayoutVertical(15))
|
||||
);
|
||||
|
||||
for (int i = 0; i < entity.getEquipmentCount(); ++i) {
|
||||
|
||||
EquipmentSlot slot = entity.getSpecies().getEquipmentSlots().get(i);
|
||||
|
||||
SlotComponent display = new SlotComponent(name + "." + slot.getName(), entity.getEquipmentSlot(i), 0)
|
||||
.setBackground(speciesRender.getEquipmentSlotBackground(slot))
|
||||
.setScale(2);
|
||||
|
||||
InteractiveSlotComponent interactiveDisplay = new InteractiveSlotComponent(
|
||||
display,
|
||||
workspace
|
||||
);
|
||||
|
||||
containers.get(speciesRender.getEquipmentSlotSide(slot)).addChild(interactiveDisplay);
|
||||
|
||||
}
|
||||
|
||||
containers.forEach((side, comp) -> {
|
||||
addChild(
|
||||
new Group(name + "." + side.ccName + ".Aligner", new LayoutAlign(0, 1, 0), comp)
|
||||
.setLayoutHint(side.lbhHint)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -17,20 +17,33 @@
|
||||
*/
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.client.events.NewLocalEntityEvent;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Components;
|
||||
import ru.windcorp.progressia.client.graphics.gui.GUILayer;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
import ru.windcorp.progressia.test.TestPlayerControls;
|
||||
|
||||
public class LayerHUD extends GUILayer {
|
||||
|
||||
public LayerHUD(Client client) {
|
||||
private final HUDManager manager;
|
||||
|
||||
private boolean showInventory = false;
|
||||
private boolean isHidden = false;
|
||||
|
||||
public LayerHUD(HUDManager manager) {
|
||||
super("LayerHUD", new LayoutFill(15));
|
||||
this.manager = manager;
|
||||
|
||||
setCursorPolicy(CursorPolicy.INDIFFERENT);
|
||||
|
||||
client.subscribe(this);
|
||||
manager.getClient().subscribe(this);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@ -40,11 +53,80 @@ public class LayerHUD extends GUILayer {
|
||||
}
|
||||
|
||||
if (e.getNewEntity() == null) {
|
||||
getRoot().requestReassembly();
|
||||
return;
|
||||
}
|
||||
|
||||
getRoot().addChild(new PermanentHUD(getName(), e.getClient().getLocalPlayer()));
|
||||
getRoot().addChild(new PermanentHUD(getName() + ".Permanent", manager));
|
||||
getRoot().addChild(Components.hide(new InventoryHUD(getName() + ".Equipment", manager), () -> !showInventory));
|
||||
getRoot().addChild(Components.hide(new CursorHUD(getName() + ".Equipment", manager.getPlayerEntity()), () -> !showInventory));
|
||||
|
||||
getRoot().requestReassembly();
|
||||
}
|
||||
|
||||
public boolean isInventoryShown() {
|
||||
return showInventory;
|
||||
}
|
||||
|
||||
public void setInventoryShown(boolean showInventory) {
|
||||
this.showInventory = showInventory;
|
||||
updateCursorPolicy();
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return isHidden;
|
||||
}
|
||||
|
||||
public void setHidden(boolean isHidden) {
|
||||
this.isHidden = isHidden;
|
||||
updateCursorPolicy();
|
||||
}
|
||||
|
||||
private void updateCursorPolicy() {
|
||||
if (showInventory && !isHidden) {
|
||||
setCursorPolicy(CursorPolicy.REQUIRE);
|
||||
} else {
|
||||
setCursorPolicy(CursorPolicy.INDIFFERENT);
|
||||
}
|
||||
|
||||
GUI.updateLayer(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInput(Input input) {
|
||||
if (isHidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.handleInput(input);
|
||||
|
||||
if (showInventory) {
|
||||
TestPlayerControls.getInstance().handleCtrlIfApplicable(input);
|
||||
if (!input.isConsumed()) {
|
||||
handleCloseInventoryIfApplicable(input);
|
||||
}
|
||||
input.consume();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCloseInventoryIfApplicable(Input input) {
|
||||
if (input.getEvent() instanceof KeyEvent) {
|
||||
KeyEvent event = (KeyEvent) input.getEvent();
|
||||
|
||||
if (event.isPress() && (event.getKey() == GLFW.GLFW_KEY_E || event.getKey() == GLFW.GLFW_KEY_ESCAPE)) {
|
||||
setInventoryShown(false);
|
||||
input.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRender() {
|
||||
if (isHidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.doRender();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,21 +19,20 @@ package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.gui.Component;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutBorderVertical;
|
||||
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
|
||||
public class PermanentHUD extends Component {
|
||||
|
||||
public PermanentHUD(String name, LocalPlayer player) {
|
||||
public PermanentHUD(String name, HUDManager manager) {
|
||||
super(name);
|
||||
setLayout(new LayoutBorderVertical());
|
||||
|
||||
EntityDataPlayer entity = player.getEntity();
|
||||
EntityDataPlayer entity = manager.getPlayerEntity();
|
||||
if (entity == null) {
|
||||
throw new IllegalStateException("Player " + player + " does not have an associated entity");
|
||||
throw new IllegalStateException("Player " + manager.getPlayer() + " does not have an associated entity");
|
||||
}
|
||||
|
||||
addChild(new HandsHUD(name + ".Hands", player).setLayoutHint(LayoutBorderVertical.UP));
|
||||
addChild(new HandsHUD(name + ".Hands", manager).setLayoutHint(LayoutBorderVertical.UP));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.test.inv;
|
||||
package ru.windcorp.progressia.client.graphics.world.hud;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@ -32,9 +32,9 @@ import ru.windcorp.progressia.common.world.item.ItemContainer;
|
||||
public class SimpleInventoryComponent extends InventoryComponent {
|
||||
|
||||
private final Group slots = new Group("Inventory.Slots", new LayoutGrid(15));
|
||||
private final Collection<DecoratedSlotComponent> slotCollection = new ArrayList<>();
|
||||
private final Collection<InteractiveSlotComponent> slotCollection = new ArrayList<>();
|
||||
|
||||
public SimpleInventoryComponent(ItemContainer container) {
|
||||
public SimpleInventoryComponent(ItemContainer container, HUDWorkspace workspace) {
|
||||
super("Inventory");
|
||||
|
||||
setLayout(new LayoutBorderHorizontal(15));
|
||||
@ -65,14 +65,14 @@ public class SimpleInventoryComponent extends InventoryComponent {
|
||||
addChild(massBar.setLayoutHint(LayoutBorderHorizontal.LEFT));
|
||||
|
||||
for (int i = 0; i < container.getSlotCount(); ++i) {
|
||||
addSlot(container, i);
|
||||
addSlot(container, i, workspace);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSlot(ItemContainer container, int index) {
|
||||
private void addSlot(ItemContainer container, int index, HUDWorkspace workspace) {
|
||||
final int maxX = 6;
|
||||
|
||||
DecoratedSlotComponent component = new DecoratedSlotComponent("Inventory.Slot." + index, container, index);
|
||||
InteractiveSlotComponent component = new InteractiveSlotComponent("Inventory.Slot." + index, container, index, workspace);
|
||||
|
||||
Vec2i pos = new Vec2i(index % maxX, index / maxX);
|
||||
slots.addChild(component.setLayoutHint(pos));
|
||||
@ -80,7 +80,7 @@ public class SimpleInventoryComponent extends InventoryComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DecoratedSlotComponent> getSlots() {
|
||||
public Collection<InteractiveSlotComponent> getSlots() {
|
||||
return slotCollection;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package ru.windcorp.progressia.client.world.entity;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.InventoryHUD;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.HUDTextures;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.HandsHUD;
|
||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||
@ -34,6 +35,7 @@ public abstract class SpeciesRender extends Namespaced {
|
||||
public abstract EntityRenderable createRenderable(EntityDataPlayer entity);
|
||||
|
||||
public abstract HandsHUD.Side getHandSide(Hand hand);
|
||||
public abstract InventoryHUD.Side getEquipmentSlotSide(EquipmentSlot equipmentSlot);
|
||||
|
||||
public Texture getTexture(String name) {
|
||||
return HUDTextures.getHUDTexture(getNamespace() + "_" + getName() + "/" + name);
|
||||
|
@ -20,6 +20,7 @@ package ru.windcorp.progressia.common.world.entity;
|
||||
import ru.windcorp.progressia.common.Units;
|
||||
import ru.windcorp.progressia.common.state.IntStateField;
|
||||
import ru.windcorp.progressia.common.state.ObjectStateField;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainerEquipment;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainerHand;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainerMixedSimple;
|
||||
|
||||
@ -61,6 +62,10 @@ public class EntityDataPlayer extends EntityData {
|
||||
return speciesDatalet.get(this).getHands().length;
|
||||
}
|
||||
|
||||
public ItemContainerEquipment getEquipmentSlot(int index) {
|
||||
return speciesDatalet.get(this).getEquipment()[index];
|
||||
}
|
||||
|
||||
public int getEquipmentCount() {
|
||||
return speciesDatalet.get(this).getEquipment().length;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
*/
|
||||
package ru.windcorp.progressia.common.world.item;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import ru.windcorp.progressia.common.state.Encodable;
|
||||
@ -31,7 +33,7 @@ import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||
* unique index. If a container has <i>n</i> slots, its slots are numbered 0
|
||||
* through <i>n</i> - 1.
|
||||
*/
|
||||
public abstract class ItemContainer extends Namespaced implements Encodable {
|
||||
public abstract class ItemContainer extends Namespaced implements Encodable, Iterable<ItemSlot> {
|
||||
|
||||
public ItemContainer(String id) {
|
||||
super(id);
|
||||
@ -52,7 +54,32 @@ public abstract class ItemContainer extends Namespaced implements Encodable {
|
||||
*/
|
||||
public abstract int getSlotCount();
|
||||
|
||||
public abstract void forEach(Consumer<ItemSlot> action);
|
||||
@Override
|
||||
public abstract void forEach(Consumer<? super ItemSlot> action);
|
||||
|
||||
@Override
|
||||
public Iterator<ItemSlot> iterator() {
|
||||
return new Iterator<ItemSlot>() {
|
||||
|
||||
private int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < getSlotCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemSlot next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException("index = " + index + ", size = " + getSlotCount());
|
||||
}
|
||||
ItemSlot slot = getSlot(index);
|
||||
index++;
|
||||
return slot;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the mass limit that the container imposes.
|
||||
|
@ -79,7 +79,7 @@ public abstract class ItemContainerMixed extends ItemContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<ItemSlot> action) {
|
||||
public void forEach(Consumer<? super ItemSlot> action) {
|
||||
getSlots().forEach(action);
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ public abstract class ItemContainerSingle extends ItemContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<ItemSlot> action) {
|
||||
public void forEach(Consumer<? super ItemSlot> action) {
|
||||
action.accept(slot);
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,8 @@ public class PlayerManager {
|
||||
player.getInventory().getSlot(9).setContents(ItemDataRegistry.getInstance().create("Test:RedGraniteCobblestone"), 1);
|
||||
player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 1);
|
||||
|
||||
player.getHand(0).slot().setContents(ItemDataRegistry.getInstance().create("Test:Stick"), 7);
|
||||
|
||||
player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation());
|
||||
player.setUpVector(new Vec3(0, 0, 1));
|
||||
player.setLookingAt(new Vec3(2, 1, 0));
|
||||
|
@ -31,7 +31,7 @@ public class SpeciesDataHuman extends SpeciesData {
|
||||
super(id);
|
||||
|
||||
withHands(new Hand("Right"), new Hand("Left"));
|
||||
withEquipmentSlots(/* ._. nope */);
|
||||
withEquipmentSlots(new EquipmentSlot("Backpack", i -> true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,10 +17,12 @@
|
||||
*/
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.HandsHUD.Side;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.InventoryHUD;
|
||||
import ru.windcorp.progressia.client.graphics.world.hud.HandsHUD;
|
||||
import ru.windcorp.progressia.client.world.entity.EntityRenderable;
|
||||
import ru.windcorp.progressia.client.world.entity.SpeciesRender;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.entity.SpeciesData.EquipmentSlot;
|
||||
import ru.windcorp.progressia.common.world.entity.SpeciesData.Hand;
|
||||
|
||||
public class SpeciesRenderHuman extends SpeciesRender {
|
||||
@ -37,8 +39,13 @@ public class SpeciesRenderHuman extends SpeciesRender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Side getHandSide(Hand hand) {
|
||||
return hand.getIndex() == 0 ? Side.RIGHT : Side.LEFT;
|
||||
public HandsHUD.Side getHandSide(Hand hand) {
|
||||
return hand.getIndex() == 0 ? HandsHUD.Side.RIGHT : HandsHUD.Side.LEFT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryHUD.Side getEquipmentSlotSide(EquipmentSlot equipmentSlot) {
|
||||
return InventoryHUD.Side.LEFT;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
@ -70,7 +69,6 @@ import ru.windcorp.progressia.server.world.generation.planet.PlanetGravityModel;
|
||||
import ru.windcorp.progressia.server.world.tile.*;
|
||||
import ru.windcorp.progressia.test.Rocks.RockType;
|
||||
import ru.windcorp.progressia.test.gen.TestGravityModel;
|
||||
import ru.windcorp.progressia.test.inv.TestInventoryGUIManager;
|
||||
|
||||
public class TestContent {
|
||||
|
||||
@ -311,7 +309,7 @@ public class TestContent {
|
||||
"Test:BreakBlock",
|
||||
KeyEvent.class,
|
||||
TestContent::onBlockBreakTrigger,
|
||||
KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_LEFT).matcher(),
|
||||
KeyMatcher.ofLeftMouseButton(),
|
||||
i -> isAnythingSelected()
|
||||
)
|
||||
);
|
||||
@ -323,7 +321,7 @@ public class TestContent {
|
||||
"Test:PlaceBlock",
|
||||
KeyEvent.class,
|
||||
TestContent::onBlockPlaceTrigger,
|
||||
KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_RIGHT).matcher(),
|
||||
KeyMatcher.ofRightMouseButton(),
|
||||
i -> isAnythingSelected() && TestPlayerControls.getInstance().isBlockSelected()
|
||||
)
|
||||
);
|
||||
@ -336,7 +334,7 @@ public class TestContent {
|
||||
"Test:PlaceTile",
|
||||
KeyEvent.class,
|
||||
TestContent::onTilePlaceTrigger,
|
||||
KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_RIGHT).matcher(),
|
||||
KeyMatcher.ofRightMouseButton(),
|
||||
i -> isAnythingSelected() && !TestPlayerControls.getInstance().isBlockSelected()
|
||||
)
|
||||
);
|
||||
@ -347,16 +345,25 @@ public class TestContent {
|
||||
"Test:StartNextMusic",
|
||||
KeyEvent.class,
|
||||
TestMusicPlayer::startNextNow,
|
||||
KeyMatcher.of(GLFW.GLFW_KEY_M).matcher()
|
||||
KeyMatcher.of("M")
|
||||
)
|
||||
);
|
||||
|
||||
triggers.register(
|
||||
ControlTriggers.localOf(
|
||||
"Test:OpenInventory",
|
||||
"Test:ShowInventory",
|
||||
KeyEvent.class,
|
||||
TestInventoryGUIManager::openGUI,
|
||||
KeyMatcher.of(GLFW.GLFW_KEY_E).matcher()
|
||||
TestContent::switchInventory,
|
||||
KeyMatcher.of("E")
|
||||
)
|
||||
);
|
||||
|
||||
triggers.register(
|
||||
ControlTriggers.localOf(
|
||||
"Test:HideHUD",
|
||||
KeyEvent.class,
|
||||
TestContent::switchHUD,
|
||||
KeyMatcher.of("F1")
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -497,6 +504,22 @@ public class TestContent {
|
||||
tileContext.addTile(tile);
|
||||
}
|
||||
|
||||
private static void switchInventory() {
|
||||
ru.windcorp.progressia.client.Client client = ClientState.getInstance();
|
||||
if (client == null || !client.isReady())
|
||||
return;
|
||||
|
||||
client.getHUD().setInventoryShown(!client.getHUD().isInventoryShown());
|
||||
}
|
||||
|
||||
private static void switchHUD() {
|
||||
ru.windcorp.progressia.client.Client client = ClientState.getInstance();
|
||||
if (client == null || !client.isReady())
|
||||
return;
|
||||
|
||||
client.getHUD().setHidden(!client.getHUD().isHidden());
|
||||
}
|
||||
|
||||
private static void registerMisc() {
|
||||
ChunkIO.registerCodec(new TestChunkCodec());
|
||||
|
||||
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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.client.graphics.world.hud.SlotComponent;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainer;
|
||||
import ru.windcorp.progressia.common.world.item.ItemSlot;
|
||||
|
||||
public class DecoratedSlotComponent extends Button {
|
||||
|
||||
private final SlotComponent slotComponent;
|
||||
|
||||
public DecoratedSlotComponent(String name, ItemContainer container, int index) {
|
||||
this(name, new SlotComponent(name, container, index));
|
||||
}
|
||||
|
||||
public DecoratedSlotComponent(String name, SlotComponent component) {
|
||||
super(name, null, null);
|
||||
this.slotComponent = component;
|
||||
|
||||
Vec2i size = slotComponent.getPreferredSize().add(2 * BORDER);
|
||||
setPreferredSize(size);
|
||||
|
||||
addChild(this.slotComponent);
|
||||
setLayout(new LayoutFill(MARGIN));
|
||||
}
|
||||
|
||||
public ItemSlot getSlot() {
|
||||
return slotComponent.getSlot();
|
||||
}
|
||||
|
||||
}
|
@ -1,190 +0,0 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package ru.windcorp.progressia.test.inv;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import ru.windcorp.progressia.client.graphics.Colors;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.gui.BasicButton;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Component;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Components;
|
||||
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.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.InputListener;
|
||||
import ru.windcorp.progressia.common.Units;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.item.ItemSlot;
|
||||
import ru.windcorp.progressia.common.world.item.Items;
|
||||
|
||||
public class InventoryScreen extends Component {
|
||||
|
||||
private static final double MIN_PICK_ALL_DELAY = Units.get("0.5 s");
|
||||
|
||||
private final InventoryComponent mainInventory;
|
||||
|
||||
private final EntityDataPlayer player;
|
||||
|
||||
private double lastLeftClick = Double.NEGATIVE_INFINITY;
|
||||
private ItemSlot lastLeftClickSlot = null;
|
||||
|
||||
public InventoryScreen(String name, InventoryComponent mainInventory, EntityDataPlayer player) {
|
||||
super(name);
|
||||
|
||||
this.mainInventory = mainInventory;
|
||||
|
||||
this.player = player;
|
||||
|
||||
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));
|
||||
|
||||
addChild(new HandSlots(name + ".Hands", player));
|
||||
|
||||
addListeners(mainInventory);
|
||||
|
||||
mainInventory.focusNext();
|
||||
}
|
||||
|
||||
private void addListeners(InventoryComponent mainInventory) {
|
||||
Supplier<ItemSlot> handSlot = () -> player.getSelectedHand().slot();
|
||||
|
||||
Consumer<BasicButton> pickAll = createPickAllAction(handSlot);
|
||||
|
||||
for (DecoratedSlotComponent component : mainInventory.getSlots()) {
|
||||
component.addAction(pickAll);
|
||||
component.addListener(KeyEvent.class, createRMBAction(component.getSlot(), handSlot));
|
||||
component.addListener(WheelScrollEvent.class, createWheelAction(component.getSlot(), handSlot));
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<BasicButton> createPickAllAction(Supplier<ItemSlot> handSlotChooser) {
|
||||
return button -> {
|
||||
|
||||
ItemSlot handSlot = handSlotChooser.get();
|
||||
ItemSlot invSlot = ((DecoratedSlotComponent) button).getSlot();
|
||||
|
||||
boolean success = false;
|
||||
|
||||
double now = GraphicsInterface.getTime();
|
||||
if (lastLeftClickSlot == invSlot && now - lastLeftClick < MIN_PICK_ALL_DELAY) {
|
||||
|
||||
lastLeftClickSlot = null;
|
||||
lastLeftClick = Double.NEGATIVE_INFINITY;
|
||||
|
||||
pickAll(handSlot);
|
||||
|
||||
success = true;
|
||||
|
||||
} else {
|
||||
lastLeftClick = now;
|
||||
lastLeftClickSlot = invSlot;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.pour(handSlot, invSlot) != 0;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.swap(handSlot, invSlot);
|
||||
}
|
||||
|
||||
if (!success && handSlot.isEmpty()) {
|
||||
success = Items.pour(invSlot, handSlot) != 0;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
requestReassembly();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private void pickAll(ItemSlot handSlot) {
|
||||
for (DecoratedSlotComponent component : mainInventory.getSlots()) {
|
||||
|
||||
Items.pour(component.getSlot(), handSlot);
|
||||
if (handSlot.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private InputListener<KeyEvent> createRMBAction(ItemSlot invSlot, Supplier<ItemSlot> handSlotChooser) {
|
||||
return input -> {
|
||||
|
||||
if (input.isPress() && input.isRightMouseButton()) {
|
||||
ItemSlot handSlot = handSlotChooser.get();
|
||||
|
||||
boolean success = false;
|
||||
|
||||
if (handSlot.isEmpty()) {
|
||||
success = Items.pour(invSlot, handSlot, invSlot.getAmount() / 2) != 0;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.pour(handSlot, invSlot, 1) != 0;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
success = Items.swap(handSlot, invSlot);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
requestReassembly();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private InputListener<WheelScrollEvent> createWheelAction(ItemSlot invSlot, Supplier<ItemSlot> handSlotChooser) {
|
||||
return input -> {
|
||||
|
||||
if (!input.hasVerticalMovement()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemSlot handSlot = handSlotChooser.get();
|
||||
|
||||
ItemSlot from = input.isDown() ? handSlot : invSlot;
|
||||
ItemSlot into = input.isDown() ? invSlot : handSlot;
|
||||
|
||||
if (Items.pour(from, into, 1) != 0) {
|
||||
requestReassembly();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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.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.entity.EntityDataPlayer;
|
||||
import ru.windcorp.progressia.common.world.item.ItemContainerMixed;
|
||||
import ru.windcorp.progressia.test.TestPlayerControls;
|
||||
|
||||
public class TestInventoryGUILayer extends GUILayer {
|
||||
|
||||
private ItemContainerMixed container;
|
||||
|
||||
private InventoryScreen display = null;
|
||||
|
||||
public TestInventoryGUILayer() {
|
||||
super("Inventory", new LayoutFill(0));
|
||||
setCursorPolicy(CursorPolicy.INDIFFERENT);
|
||||
}
|
||||
|
||||
public boolean hasContainer() {
|
||||
return container != null;
|
||||
}
|
||||
|
||||
public void setContainer(ItemContainerMixed container, EntityDataPlayer player) {
|
||||
this.container = container;
|
||||
|
||||
getRoot().removeChild(display);
|
||||
display = null;
|
||||
|
||||
if (container != null) {
|
||||
display = new InventoryScreen("Screen", new SimpleInventoryComponent(container), player);
|
||||
|
||||
getRoot().addChild(display);
|
||||
invalidate();
|
||||
|
||||
setCursorPolicy(CursorPolicy.REQUIRE);
|
||||
} else {
|
||||
setCursorPolicy(CursorPolicy.INDIFFERENT);
|
||||
}
|
||||
|
||||
GUI.updateLayer(this);
|
||||
}
|
||||
|
||||
@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 || keyEvent.getKey() == GLFW.GLFW_KEY_ESCAPE)
|
||||
) {
|
||||
setContainer(null, null);
|
||||
input.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TestPlayerControls.getInstance().handleCtrlIfApplicable(input);
|
||||
|
||||
super.handleInput(input);
|
||||
input.consume();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 954 B |
BIN
src/main/resources/assets/textures/items/CardboardBackpack.png
Normal file
BIN
src/main/resources/assets/textures/items/CardboardBackpack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Reference in New Issue
Block a user