/*
* Copyright 2014 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.rendering.nui.layers.ingame.inventory;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import org.terasology.entitySystem.entity.EntityRef;
import org.terasology.input.MouseInput;
import org.terasology.logic.inventory.InventoryUtils;
import org.terasology.math.geom.Rect2i;
import org.terasology.math.geom.Vector2i;
import org.terasology.rendering.nui.BaseInteractionListener;
import org.terasology.rendering.nui.Canvas;
import org.terasology.rendering.nui.CoreWidget;
import org.terasology.rendering.nui.InteractionListener;
import org.terasology.rendering.nui.LayoutConfig;
import org.terasology.rendering.nui.UIWidget;
import org.terasology.rendering.nui.databinding.Binding;
import org.terasology.rendering.nui.databinding.DefaultBinding;
import org.terasology.rendering.nui.databinding.ReadOnlyBinding;
import org.terasology.rendering.nui.events.NUIMouseClickEvent;
import java.util.Iterator;
import java.util.List;
/**
*/
public class InventoryGrid extends CoreWidget {
@LayoutConfig
private int maxHorizontalCells = 10;
@LayoutConfig
private Binding<Integer> cellOffset = new DefaultBinding<>(0);
@LayoutConfig
private Binding<Integer> maxCellCount = new DefaultBinding<>(Integer.MAX_VALUE);
private List<InventoryCell> cells = Lists.newArrayList();
private Binding<EntityRef> targetEntity = new DefaultBinding<>(EntityRef.NULL);
private InteractionListener interactionListener = new BaseInteractionListener() {
@Override
public boolean onMouseClick(NUIMouseClickEvent event) {
MouseInput mouseButton = event.getMouseButton();
if (mouseButton == MouseInput.MOUSE_LEFT) {
return true;
}
return false;
}
};
@Override
public void update(float delta) {
super.update(delta);
int numSlots = getNumSlots();
// allow the UI to grow or shrink the cell count if the inventory changes size
if (numSlots < cells.size()) {
for (int i = cells.size(); i > numSlots && i > 0; --i) {
cells.remove(i - 1);
}
} else if (numSlots > cells.size()) {
for (int i = cells.size(); i < numSlots && i < getMaxCellCount(); ++i) {
InventoryCell cell = new InventoryCell();
cell.bindTargetInventory(new ReadOnlyBinding<EntityRef>() {
@Override
public EntityRef get() {
return getTargetEntity();
}
});
cell.bindTargetSlot(new SlotBinding(i));
cells.add(cell);
}
}
}
@Override
public void onDraw(Canvas canvas) {
int numSlots = getNumSlots();
if (numSlots == 0 || cells.isEmpty()) {
return;
}
Vector2i cellSize = canvas.calculatePreferredSize(cells.get(0));
if (cellSize.getX() == 0 || cellSize.getY() == 0) {
return;
}
canvas.addInteractionRegion(interactionListener);
int horizontalCells = Math.max(1, Math.min(maxHorizontalCells, canvas.size().getX() / cellSize.getX()));
for (int i = 0; i < numSlots && i < cells.size(); ++i) {
int horizPos = i % horizontalCells;
int vertPos = i / horizontalCells;
canvas.drawWidget(cells.get(i), Rect2i.createFromMinAndSize(horizPos * cellSize.x, vertPos * cellSize.y, cellSize.x, cellSize.y));
}
}
@Override
public Vector2i getPreferredContentSize(Canvas canvas, Vector2i sizeHint) {
int numSlots = getNumSlots();
if (numSlots == 0 || cells.isEmpty()) {
return Vector2i.zero();
}
Vector2i cellSize = canvas.calculatePreferredSize(cells.get(0));
if (cellSize.getX() == 0 || cellSize.getY() == 0) {
return Vector2i.zero();
}
int horizontalCells = Math.min(Math.min(maxHorizontalCells, numSlots), sizeHint.getX() / cellSize.getX());
int verticalCells = ((numSlots - 1) / horizontalCells) + 1;
return new Vector2i(horizontalCells * cellSize.x, verticalCells * cellSize.y);
}
@Override
public Iterator<UIWidget> iterator() {
return Iterators.transform(cells.iterator(), new Function<UIWidget, UIWidget>() {
@Override
public UIWidget apply(UIWidget input) {
return input;
}
});
}
public int getMaxHorizontalCells() {
return maxHorizontalCells;
}
public void setMaxHorizontalCells(int maxHorizontalCells) {
this.maxHorizontalCells = maxHorizontalCells;
}
public void bindTargetEntity(Binding<EntityRef> binding) {
targetEntity = binding;
}
public EntityRef getTargetEntity() {
return targetEntity.get();
}
/**
*
* @deprecated Use bindTargetEntity to assign a read only binding that is a getter
*/
@Deprecated
public void setTargetEntity(EntityRef val) {
targetEntity.set(val);
}
public void bindCellOffset(Binding<Integer> binding) {
cellOffset = binding;
}
public int getCellOffset() {
return cellOffset.get();
}
public void setCellOffset(int val) {
cellOffset.set(val);
}
public void bindMaxCellCount(Binding<Integer> binding) {
maxCellCount = binding;
}
public int getMaxCellCount() {
return maxCellCount.get();
}
public void setMaxCellCount(int val) {
maxCellCount.set(val);
}
public int getNumSlots() {
return Math.min(InventoryUtils.getSlotCount(getTargetEntity()) - getCellOffset(), getMaxCellCount());
}
private final class SlotBinding extends ReadOnlyBinding<Integer> {
private int slot;
private SlotBinding(int slot) {
this.slot = slot;
}
@Override
public Integer get() {
return getCellOffset() + slot;
}
}
}