mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-13 12:16:53 +07:00
Tech tree rendering + layout
This commit is contained in:
parent
4ff1d0c2e1
commit
49253964d8
BIN
core/assets-raw/sprites/ui/content-background.9.png
Normal file
BIN
core/assets-raw/sprites/ui/content-background.9.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 325 B |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 617 KiB After Width: | Height: | Size: 614 KiB |
56
core/src/io/anuke/mindustry/content/TechTree.java
Normal file
56
core/src/io/anuke/mindustry/content/TechTree.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package io.anuke.mindustry.content;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.game.Content;
|
||||||
|
import io.anuke.mindustry.game.ContentList;
|
||||||
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.type.ItemStack.with;
|
||||||
|
|
||||||
|
public class TechTree implements ContentList{
|
||||||
|
public static TechNode root;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load(){
|
||||||
|
root = new TechNode(Items.copper, with(),
|
||||||
|
new TechNode(Blocks.copperWall, with(Items.copper, 100),
|
||||||
|
new TechNode(Blocks.copperWallLarge, with(Items.copper, 100))
|
||||||
|
),
|
||||||
|
|
||||||
|
new TechNode(Blocks.conveyor, with(Items.copper, 10),
|
||||||
|
new TechNode(Blocks.router, with(Items.copper, 10),
|
||||||
|
new TechNode(Blocks.distributor, with(Items.copper, 10)),
|
||||||
|
new TechNode(Blocks.overflowGate, with(Items.copper, 10)),
|
||||||
|
new TechNode(Blocks.sorter, with(Items.copper, 10))
|
||||||
|
),
|
||||||
|
new TechNode(Blocks.junction, with(Items.copper, 10)),
|
||||||
|
new TechNode(Blocks.itemBridge, with(Items.copper, 10))
|
||||||
|
),
|
||||||
|
|
||||||
|
new TechNode(Items.lead, with(),
|
||||||
|
new TechNode(Items.metaglass, with(),
|
||||||
|
new TechNode(Blocks.conduit, with(Items.metaglass, 10)),
|
||||||
|
new TechNode(Blocks.liquidJunction, with(Items.metaglass, 10)),
|
||||||
|
new TechNode(Blocks.liquidRouter, with(Items.metaglass, 10),
|
||||||
|
new TechNode(Blocks.liquidTank, with(Items.metaglass, 10))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TechNode{
|
||||||
|
public final Content content;
|
||||||
|
public final ItemStack[] requirements;
|
||||||
|
public final TechNode[] children;
|
||||||
|
public TechNode parent;
|
||||||
|
|
||||||
|
TechNode(Content content, ItemStack[] requirements, TechNode... children){
|
||||||
|
this.content = content;
|
||||||
|
this.requirements = requirements;
|
||||||
|
this.children = children;
|
||||||
|
for(TechNode node : children){
|
||||||
|
node.parent = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -45,6 +45,7 @@ public class ContentLoader{
|
|||||||
new UnitTypes(),
|
new UnitTypes(),
|
||||||
new Blocks(),
|
new Blocks(),
|
||||||
new Recipes(),
|
new Recipes(),
|
||||||
|
new TechTree(),
|
||||||
new Zones(),
|
new Zones(),
|
||||||
|
|
||||||
//these are not really content classes, but this makes initialization easier
|
//these are not really content classes, but this makes initialization easier
|
||||||
|
@ -67,6 +67,7 @@ public class UI implements ApplicationListener{
|
|||||||
public UnlocksDialog unlocks;
|
public UnlocksDialog unlocks;
|
||||||
public ContentInfoDialog content;
|
public ContentInfoDialog content;
|
||||||
public DeployDialog deploy;
|
public DeployDialog deploy;
|
||||||
|
public TechTreeDialog tech;
|
||||||
|
|
||||||
public Cursor drillCursor, unloadCursor;
|
public Cursor drillCursor, unloadCursor;
|
||||||
|
|
||||||
@ -177,6 +178,7 @@ public class UI implements ApplicationListener{
|
|||||||
localplayers = new LocalPlayerDialog();
|
localplayers = new LocalPlayerDialog();
|
||||||
content = new ContentInfoDialog();
|
content = new ContentInfoDialog();
|
||||||
deploy = new DeployDialog();
|
deploy = new DeployDialog();
|
||||||
|
tech = new TechTreeDialog();
|
||||||
|
|
||||||
Group group = Core.scene.root;
|
Group group = Core.scene.root;
|
||||||
|
|
||||||
|
@ -301,11 +301,6 @@ public class DesktopInput extends InputHandler{
|
|||||||
return !controlling ? Core.input.mouseY() : controly;
|
return !controlling ? Core.input.mouseY() : controly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCursorVisible(){
|
|
||||||
return controlling;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateController(){
|
public void updateController(){
|
||||||
|
|
||||||
|
310
core/src/io/anuke/mindustry/ui/TreeLayout.java
Normal file
310
core/src/io/anuke/mindustry/ui/TreeLayout.java
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
|
||||||
|
|
||||||
|
package io.anuke.mindustry.ui;
|
||||||
|
|
||||||
|
import io.anuke.arc.collection.FloatArray;
|
||||||
|
import io.anuke.arc.math.geom.Rectangle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Algorithm taken from <a href="https://github.com/abego/treelayout">TreeLayout</a>.
|
||||||
|
*/
|
||||||
|
public class TreeLayout{
|
||||||
|
public TreeLocation rootLocation = TreeLocation.top;
|
||||||
|
public TreeAlignment alignment = TreeAlignment.awayFromRoot;
|
||||||
|
public float gapBetweenLevels = 10;
|
||||||
|
public float gapBetweenNodes = 10f;
|
||||||
|
|
||||||
|
private final FloatArray sizeOfLevel = new FloatArray();
|
||||||
|
private float boundsLeft = Float.MAX_VALUE;
|
||||||
|
private float boundsRight = Float.MIN_VALUE;
|
||||||
|
private float boundsTop = Float.MAX_VALUE;
|
||||||
|
private float boundsBottom = Float.MIN_VALUE;
|
||||||
|
|
||||||
|
public void layout(TreeNode root){
|
||||||
|
firstWalk(root, null);
|
||||||
|
calcSizeOfLevels(root, 0);
|
||||||
|
secondWalk(root, -root.prelim, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getWidthOrHeightOfNode(TreeNode treeNode, boolean returnWidth){
|
||||||
|
return returnWidth ? treeNode.width : treeNode.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getNodeThickness(TreeNode treeNode){
|
||||||
|
return getWidthOrHeightOfNode(treeNode, !isLevelChangeInYAxis());
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getNodeSize(TreeNode treeNode){
|
||||||
|
return getWidthOrHeightOfNode(treeNode, isLevelChangeInYAxis());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLevelChangeInYAxis(){
|
||||||
|
return rootLocation == TreeLocation.top || rootLocation == TreeLocation.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLevelChangeSign(){
|
||||||
|
return rootLocation == TreeLocation.bottom || rootLocation == TreeLocation.right ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBounds(TreeNode node, float centerX, float centerY){
|
||||||
|
float width = node.width;
|
||||||
|
float height = node.height;
|
||||||
|
float left = centerX - width / 2;
|
||||||
|
float right = centerX + width / 2;
|
||||||
|
float top = centerY - height / 2;
|
||||||
|
float bottom = centerY + height / 2;
|
||||||
|
if(boundsLeft > left){
|
||||||
|
boundsLeft = left;
|
||||||
|
}
|
||||||
|
if(boundsRight < right){
|
||||||
|
boundsRight = right;
|
||||||
|
}
|
||||||
|
if(boundsTop > top){
|
||||||
|
boundsTop = top;
|
||||||
|
}
|
||||||
|
if(boundsBottom < bottom){
|
||||||
|
boundsBottom = bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle getBounds(){
|
||||||
|
return new Rectangle(0, 0, boundsRight - boundsLeft, boundsBottom - boundsTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void calcSizeOfLevels(TreeNode node, int level){
|
||||||
|
float oldSize;
|
||||||
|
if(sizeOfLevel.size <= level){
|
||||||
|
sizeOfLevel.add(0);
|
||||||
|
oldSize = 0;
|
||||||
|
}else{
|
||||||
|
oldSize = sizeOfLevel.get(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
float size = getNodeThickness(node);
|
||||||
|
if(oldSize < size){
|
||||||
|
sizeOfLevel.set(level, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!node.isLeaf()){
|
||||||
|
for(TreeNode child : node.children){
|
||||||
|
calcSizeOfLevels(child, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevelCount(){
|
||||||
|
return sizeOfLevel.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getGapBetweenNodes(TreeNode a, TreeNode b){
|
||||||
|
return gapBetweenNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSizeOfLevel(int level){
|
||||||
|
if(!(level >= 0)) throw new IllegalArgumentException("level must be >= 0");
|
||||||
|
if(!(level < getLevelCount())) throw new IllegalArgumentException("level must be < levelCount");
|
||||||
|
|
||||||
|
return sizeOfLevel.get(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNode getAncestor(TreeNode node){
|
||||||
|
return node.ancestor != null ? node.ancestor : node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getDistance(TreeNode v, TreeNode w){
|
||||||
|
float sizeOfNodes = getNodeSize(v) + getNodeSize(w);
|
||||||
|
|
||||||
|
return sizeOfNodes / 2 + getGapBetweenNodes(v, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNode nextLeft(TreeNode v){
|
||||||
|
return v.isLeaf() ? v.thread : v.children[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNode nextRight(TreeNode v){
|
||||||
|
return v.isLeaf() ? v.thread : v.children[v.children.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getNumber(TreeNode node, TreeNode parentNode){
|
||||||
|
if(node.number == -1){
|
||||||
|
int number = 1;
|
||||||
|
for(TreeNode child : parentNode.children){
|
||||||
|
child.number = number++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node.number;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNode ancestor(TreeNode vIMinus, TreeNode parentOfV, TreeNode defaultAncestor){
|
||||||
|
TreeNode ancestor = getAncestor(vIMinus);
|
||||||
|
return ancestor.parent == parentOfV ? ancestor : defaultAncestor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveSubtree(TreeNode wMinus, TreeNode wPlus, TreeNode parent, float shift){
|
||||||
|
int subtrees = getNumber(wPlus, parent) - getNumber(wMinus, parent);
|
||||||
|
wPlus.change = wPlus.change - shift / subtrees;
|
||||||
|
wPlus.shift = wPlus.shift + shift;
|
||||||
|
wMinus.change = wMinus.change + shift / subtrees;
|
||||||
|
wPlus.prelim = wPlus.prelim + shift;
|
||||||
|
wPlus.mode = wPlus.mode + shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNode apportion(TreeNode v, TreeNode defaultAncestor,
|
||||||
|
TreeNode leftSibling, TreeNode parentOfV){
|
||||||
|
if(leftSibling == null){
|
||||||
|
return defaultAncestor;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode vOPlus = v;
|
||||||
|
TreeNode vIPlus = v;
|
||||||
|
TreeNode vIMinus = leftSibling;
|
||||||
|
|
||||||
|
TreeNode vOMinus = parentOfV.children[0];
|
||||||
|
|
||||||
|
float sIPlus = (vIPlus).mode;
|
||||||
|
float sOPlus = (vOPlus).mode;
|
||||||
|
float sIMinus = (vIMinus).mode;
|
||||||
|
float sOMinus = (vOMinus).mode;
|
||||||
|
|
||||||
|
TreeNode nextRightVIMinus = nextRight(vIMinus);
|
||||||
|
TreeNode nextLeftVIPlus = nextLeft(vIPlus);
|
||||||
|
|
||||||
|
while(nextRightVIMinus != null && nextLeftVIPlus != null){
|
||||||
|
vIMinus = nextRightVIMinus;
|
||||||
|
vIPlus = nextLeftVIPlus;
|
||||||
|
vOMinus = nextLeft(vOMinus);
|
||||||
|
vOPlus = nextRight(vOPlus);
|
||||||
|
vOPlus.ancestor = v;
|
||||||
|
float shift = (vIMinus.prelim + sIMinus)
|
||||||
|
- (vIPlus.prelim + sIPlus)
|
||||||
|
+ getDistance(vIMinus, vIPlus);
|
||||||
|
|
||||||
|
if(shift > 0){
|
||||||
|
moveSubtree(ancestor(vIMinus, parentOfV, defaultAncestor),
|
||||||
|
v, parentOfV, shift);
|
||||||
|
sIPlus = sIPlus + shift;
|
||||||
|
sOPlus = sOPlus + shift;
|
||||||
|
}
|
||||||
|
sIMinus += vIMinus.mode;
|
||||||
|
sIPlus += vIPlus.mode;
|
||||||
|
sOMinus += vOMinus.mode;
|
||||||
|
sOPlus += vOPlus.mode;
|
||||||
|
|
||||||
|
nextRightVIMinus = nextRight(vIMinus);
|
||||||
|
nextLeftVIPlus = nextLeft(vIPlus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nextRightVIMinus != null && nextRight(vOPlus) == null){
|
||||||
|
vOPlus.thread = nextRightVIMinus;
|
||||||
|
vOPlus.mode += sIMinus - sOPlus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nextLeftVIPlus != null && nextLeft(vOMinus) == null){
|
||||||
|
vOMinus.thread = nextLeftVIPlus;
|
||||||
|
vOMinus.mode += sIPlus - sOMinus;
|
||||||
|
defaultAncestor = v;
|
||||||
|
}
|
||||||
|
return defaultAncestor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeShifts(TreeNode v){
|
||||||
|
float shift = 0;
|
||||||
|
float change = 0;
|
||||||
|
|
||||||
|
for(int i = v.children.length - 1; i >= 0; i --){
|
||||||
|
TreeNode w = v.children[i];
|
||||||
|
change = change + w.change;
|
||||||
|
w.prelim += shift;
|
||||||
|
w.mode += shift;
|
||||||
|
shift += w.shift + change;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void firstWalk(TreeNode v, TreeNode leftSibling){
|
||||||
|
if(v.isLeaf()){
|
||||||
|
if(leftSibling != null){
|
||||||
|
v.prelim = leftSibling.prelim + getDistance(v, leftSibling);
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
TreeNode defaultAncestor = v.children[0];
|
||||||
|
TreeNode previousChild = null;
|
||||||
|
for(TreeNode w : v.children){
|
||||||
|
firstWalk(w, previousChild);
|
||||||
|
defaultAncestor = apportion(w, defaultAncestor, previousChild,
|
||||||
|
v);
|
||||||
|
previousChild = w;
|
||||||
|
}
|
||||||
|
executeShifts(v);
|
||||||
|
float midpoint = (v.children[0].prelim + v.children[v.children.length-1].prelim) / 2f;
|
||||||
|
TreeNode w = leftSibling;
|
||||||
|
if(w != null){
|
||||||
|
v.prelim = w.prelim + getDistance(v, w);
|
||||||
|
v.mode = v.prelim - midpoint;
|
||||||
|
}else{
|
||||||
|
v.prelim = midpoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void secondWalk(TreeNode v, float m, int level, float levelStart){
|
||||||
|
float levelChangeSign = getLevelChangeSign();
|
||||||
|
boolean levelChangeOnYAxis = isLevelChangeInYAxis();
|
||||||
|
float levelSize = getSizeOfLevel(level);
|
||||||
|
|
||||||
|
float x = v.prelim + m;
|
||||||
|
|
||||||
|
float y;
|
||||||
|
if(alignment == TreeAlignment.center){
|
||||||
|
y = levelStart + levelChangeSign * (levelSize / 2);
|
||||||
|
}else if(alignment == TreeAlignment.towardsRoot){
|
||||||
|
y = levelStart + levelChangeSign * (getNodeThickness(v) / 2);
|
||||||
|
}else{
|
||||||
|
y = levelStart + levelSize - levelChangeSign
|
||||||
|
* (getNodeThickness(v) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!levelChangeOnYAxis){
|
||||||
|
float t = x;
|
||||||
|
x = y;
|
||||||
|
y = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.x = x;
|
||||||
|
v.y = y;
|
||||||
|
updateBounds(v, x, y);
|
||||||
|
|
||||||
|
if(!v.isLeaf()){
|
||||||
|
float nextLevelStart = levelStart
|
||||||
|
+ (levelSize + gapBetweenLevels)
|
||||||
|
* levelChangeSign;
|
||||||
|
for(TreeNode w : v.children){
|
||||||
|
secondWalk(w, m + v.mode, level + 1, nextLevelStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TreeLocation{
|
||||||
|
top, left, bottom, right
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TreeAlignment{
|
||||||
|
center, towardsRoot, awayFromRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TreeNode{
|
||||||
|
public float width, height, x, y;
|
||||||
|
|
||||||
|
//should be initialized by user
|
||||||
|
public TreeNode[] children;
|
||||||
|
public TreeNode parent;
|
||||||
|
|
||||||
|
private float mode, prelim, change, shift;
|
||||||
|
private int number = -1;
|
||||||
|
private TreeNode thread, ancestor;
|
||||||
|
|
||||||
|
boolean isLeaf(){
|
||||||
|
return children == null || children.length == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,7 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
cont.clear();
|
cont.clear();
|
||||||
|
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
buttons.addButton("$techtree", () -> ui.tech.show()).size(200f, 60f);
|
||||||
|
|
||||||
cont.stack(new Table(){{
|
cont.stack(new Table(){{
|
||||||
top().left().margin(10);
|
top().left().margin(10);
|
||||||
|
107
core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java
Normal file
107
core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
|
import io.anuke.arc.Core;
|
||||||
|
import io.anuke.arc.collection.ObjectSet;
|
||||||
|
import io.anuke.arc.graphics.g2d.Draw;
|
||||||
|
import io.anuke.arc.graphics.g2d.Lines;
|
||||||
|
import io.anuke.arc.graphics.g2d.ScissorStack;
|
||||||
|
import io.anuke.arc.graphics.g2d.TextureRegion;
|
||||||
|
import io.anuke.arc.input.KeyCode;
|
||||||
|
import io.anuke.arc.math.geom.Rectangle;
|
||||||
|
import io.anuke.arc.scene.Element;
|
||||||
|
import io.anuke.arc.scene.event.InputEvent;
|
||||||
|
import io.anuke.arc.scene.event.InputListener;
|
||||||
|
import io.anuke.mindustry.content.TechTree;
|
||||||
|
import io.anuke.mindustry.content.TechTree.TechNode;
|
||||||
|
import io.anuke.mindustry.game.Content;
|
||||||
|
import io.anuke.mindustry.game.UnlockableContent;
|
||||||
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
|
import io.anuke.mindustry.ui.TreeLayout;
|
||||||
|
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
|
|
||||||
|
public class TechTreeDialog extends FloatingDialog{
|
||||||
|
private TreeLayout layout;
|
||||||
|
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
||||||
|
|
||||||
|
public TechTreeDialog(){
|
||||||
|
super("$techtree");
|
||||||
|
|
||||||
|
layout = new TreeLayout();
|
||||||
|
layout.gapBetweenLevels = 60f;
|
||||||
|
layout.gapBetweenNodes = 40f;
|
||||||
|
layout.layout(new TechTreeNode(TechTree.root, null));
|
||||||
|
|
||||||
|
cont.add(new View()).grow();
|
||||||
|
|
||||||
|
addCloseButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TechTreeNode extends TreeNode{
|
||||||
|
final TechNode node;
|
||||||
|
|
||||||
|
public TechTreeNode(TechNode node, TreeNode parent){
|
||||||
|
this.node = node;
|
||||||
|
this.parent = parent;
|
||||||
|
this.width = this.height = 60f;
|
||||||
|
nodes.add(this);
|
||||||
|
if(node.children != null){
|
||||||
|
children = new TechTreeNode[node.children.length];
|
||||||
|
for(int i = 0; i < children.length; i++){
|
||||||
|
children[i] = new TechTreeNode(node.children[i], this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class View extends Element{
|
||||||
|
float panX = 0, panY = 0;
|
||||||
|
Rectangle clip = new Rectangle();
|
||||||
|
|
||||||
|
{
|
||||||
|
addListener(new InputListener(){
|
||||||
|
@Override
|
||||||
|
public void touchDragged(InputEvent event, float x, float y, int pointer){
|
||||||
|
super.touchDragged(event, x, y, pointer);
|
||||||
|
panX += Core.input.deltaX(pointer);
|
||||||
|
panY += Core.input.deltaY(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean touchDown(InputEvent event, float x, float y, int pointer, KeyCode button){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
if(!ScissorStack.pushScissors(clip.set(x, y, width, height))){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y;
|
||||||
|
|
||||||
|
Lines.stroke(3f, Palette.accent);
|
||||||
|
|
||||||
|
for(TreeNode node : nodes){
|
||||||
|
for(TreeNode child : node.children){
|
||||||
|
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.color();
|
||||||
|
|
||||||
|
for(TechTreeNode node : nodes){
|
||||||
|
Draw.drawable("content-background", node.x + offsetX - node.width/2f, node.y + offsetY - node.height/2f, node.width, node.height);
|
||||||
|
|
||||||
|
Content content = node.node.content;
|
||||||
|
TextureRegion region = content instanceof Block ? ((Block)content).getEditorIcon() :
|
||||||
|
((UnlockableContent)content).getContentIcon();
|
||||||
|
Draw.rect(region, node.x + offsetX, node.y + offsetY, 8*3, 8*3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScissorStack.popScissors();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,7 +17,7 @@ public class LiquidHeatGenerator extends ItemLiquidGenerator{
|
|||||||
super.setStats();
|
super.setStats();
|
||||||
|
|
||||||
stats.remove(BlockStat.basePowerGeneration);
|
stats.remove(BlockStat.basePowerGeneration);
|
||||||
// Right now, Lava is the only thing that can be used.
|
// right now, Lava is the only thing that can be used.
|
||||||
stats.add(BlockStat.basePowerGeneration, powerProduction * getLiquidEfficiency(Liquids.slag) / maxLiquidGenerate * 60f, StatUnit.powerSecond);
|
stats.add(BlockStat.basePowerGeneration, powerProduction * getLiquidEfficiency(Liquids.slag) / maxLiquidGenerate * 60f, StatUnit.powerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user