Functional tech tree
|
Before Width: | Height: | Size: 152 B |
BIN
core/assets-raw/sprites/ui/content-background-locked.9.png
Normal file
|
After Width: | Height: | Size: 297 B |
|
Before Width: | Height: | Size: 285 B After Width: | Height: | Size: 285 B |
|
Before Width: | Height: | Size: 325 B After Width: | Height: | Size: 308 B |
|
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 190 B |
|
Before Width: | Height: | Size: 88 B |
BIN
core/assets-raw/sprites/ui/icons/icon-tree-locked.png
Normal file
|
After Width: | Height: | Size: 373 B |
@@ -51,6 +51,9 @@ name = Name:
|
|||||||
noname = Pick a[accent] player name[] first.
|
noname = Pick a[accent] player name[] first.
|
||||||
filename = File Name:
|
filename = File Name:
|
||||||
unlocked = New content unlocked!
|
unlocked = New content unlocked!
|
||||||
|
completed = [accent]Completed
|
||||||
|
research = Research
|
||||||
|
researched = [LIGHT_GRAY]{0} researched.
|
||||||
players = {0} players online
|
players = {0} players online
|
||||||
players.single = {0} player online
|
players.single = {0} player online
|
||||||
server.closing = [accent]Closing server...
|
server.closing = [accent]Closing server...
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 963 KiB After Width: | Height: | Size: 967 KiB |
@@ -24,6 +24,7 @@ ButtonStyle: {
|
|||||||
},
|
},
|
||||||
TextButtonStyle: {
|
TextButtonStyle: {
|
||||||
default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, down: button-down, up: button},
|
default: {over: button-over, disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, down: button-down, up: button},
|
||||||
|
node: {disabled: content-background, font: default-font, fontColor: white, disabledFontColor: gray, up: content-background, over: content-background-over},
|
||||||
right: {over: button-right-over, font: default-font, fontColor: white, disabledFontColor: gray, down: button-right-down, up: button-right},
|
right: {over: button-right-over, font: default-font, fontColor: white, disabledFontColor: gray, down: button-right-down, up: button-right},
|
||||||
wave: {font: default-font, fontColor: white, disabledFontColor: gray, up: button-edge-4},
|
wave: {font: default-font, fontColor: white, disabledFontColor: gray, up: button-edge-4},
|
||||||
clear: {over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray, down: flat-over, up: flat},
|
clear: {over: flat-over, font: default-font, fontColor: white, disabledFontColor: gray, down: flat-over, up: flat},
|
||||||
@@ -37,7 +38,7 @@ TextButtonStyle: {
|
|||||||
},
|
},
|
||||||
ImageButtonStyle: {
|
ImageButtonStyle: {
|
||||||
default: {down: button-down, up: button, over: button-over, imageDisabledColor: gray, imageUpColor: white },
|
default: {down: button-down, up: button, over: button-over, imageDisabledColor: gray, imageUpColor: white },
|
||||||
node: {down: content-background-over, up: content-background, over: content-background-over},
|
node: {up: content-background, over: content-background-over},
|
||||||
right: {over: button-right-over, down: button-right-down, up: button-right},
|
right: {over: button-right-over, down: button-right-down, up: button-right},
|
||||||
empty: { imageDownColor: accent, imageUpColor: white},
|
empty: { imageDownColor: accent, imageUpColor: white},
|
||||||
emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: gray},
|
emptytoggle: {imageCheckedColor: white, imageDownColor: white, imageUpColor: gray},
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public class Recipes implements ContentList{
|
|||||||
new Recipe(effect, Blocks.container, new ItemStack(Items.titanium, 200));
|
new Recipe(effect, Blocks.container, new ItemStack(Items.titanium, 200));
|
||||||
new Recipe(effect, Blocks.vault, new ItemStack(Items.titanium, 500), new ItemStack(Items.thorium, 250));
|
new Recipe(effect, Blocks.vault, new ItemStack(Items.titanium, 500), new ItemStack(Items.thorium, 250));
|
||||||
new Recipe(effect, Blocks.launchPad, new ItemStack(Items.copper, 500));
|
new Recipe(effect, Blocks.launchPad, new ItemStack(Items.copper, 500));
|
||||||
|
new Recipe(effect, Blocks.core, new ItemStack(Items.titanium, 2000)).setHidden(true).setAlwaysUnlocked(true);
|
||||||
|
|
||||||
//projectors
|
//projectors
|
||||||
new Recipe(effect, Blocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.titanium, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180));
|
new Recipe(effect, Blocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.titanium, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180));
|
||||||
@@ -160,9 +161,6 @@ public class Recipes implements ContentList{
|
|||||||
|
|
||||||
new Recipe(units, Blocks.repairPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.copper, 30), new ItemStack(Items.silicon, 30));
|
new Recipe(units, Blocks.repairPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.copper, 30), new ItemStack(Items.silicon, 30));
|
||||||
|
|
||||||
//removed for testing MOBA-style unit production
|
|
||||||
//new Recipe(units, Blocks.commandCenter, new ItemStack(Items.lead, 100), new ItemStack(Items.densealloy, 100), new ItemStack(Items.silicon, 200));
|
|
||||||
|
|
||||||
//LIQUIDS
|
//LIQUIDS
|
||||||
new Recipe(liquid, Blocks.conduit, new ItemStack(Items.lead, 1));
|
new Recipe(liquid, Blocks.conduit, new ItemStack(Items.lead, 1));
|
||||||
new Recipe(liquid, Blocks.pulseConduit, new ItemStack(Items.titanium, 1), new ItemStack(Items.lead, 1));
|
new Recipe(liquid, Blocks.pulseConduit, new ItemStack(Items.titanium, 1), new ItemStack(Items.lead, 1));
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class TechTree implements ContentList{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
root = node(null, with(), () -> {
|
root = node(Blocks.core, with(), () -> {
|
||||||
|
|
||||||
node(Blocks.conveyor, with(Items.copper, 100), () -> {
|
node(Blocks.conveyor, with(Items.copper, 100), () -> {
|
||||||
node(Blocks.launchPad, with(Items.copper, 100), () -> {
|
node(Blocks.launchPad, with(Items.copper, 100), () -> {
|
||||||
@@ -252,12 +252,8 @@ public class TechTree implements ContentList{
|
|||||||
return new TechNode(block, requirements, children);
|
return new TechNode(block, requirements, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TechNode node(Block block, ItemStack[] requirements){
|
private void node(Block block, ItemStack[] requirements){
|
||||||
return new TechNode(block, requirements, () -> {});
|
new TechNode(block, requirements, () -> {});
|
||||||
}
|
|
||||||
|
|
||||||
private TechNode node(Block block){
|
|
||||||
return new TechNode(block, with(), () -> {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TechNode{
|
public static class TechNode{
|
||||||
@@ -281,5 +277,9 @@ public class TechTree implements ContentList{
|
|||||||
children.run();
|
children.run();
|
||||||
context = last;
|
context = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Recipe recipe(){
|
||||||
|
return Recipe.getByResult(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ public class GlobalData{
|
|||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean has(Item item, int amount){
|
||||||
|
return items.get(item, 0) >= amount;
|
||||||
|
}
|
||||||
|
|
||||||
public ObjectIntMap<Item> items(){
|
public ObjectIntMap<Item> items(){
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class Palette{
|
|||||||
heal = Color.valueOf("98ffa9"),
|
heal = Color.valueOf("98ffa9"),
|
||||||
bar = Color.SLATE,
|
bar = Color.SLATE,
|
||||||
accent = Color.valueOf("ffd37f"),
|
accent = Color.valueOf("ffd37f"),
|
||||||
|
locked = Color.valueOf("6b6b6b"),
|
||||||
accentBack = Color.valueOf("d4816b"),
|
accentBack = Color.valueOf("d4816b"),
|
||||||
place = Color.valueOf("6335f8"),
|
place = Color.valueOf("6335f8"),
|
||||||
remove = Color.valueOf("e55454"),
|
remove = Color.valueOf("e55454"),
|
||||||
|
|||||||
@@ -8,11 +8,15 @@ import io.anuke.arc.util.Pack;
|
|||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.Blocks;
|
||||||
import io.anuke.mindustry.entities.traits.SaveTrait;
|
import io.anuke.mindustry.entities.traits.SaveTrait;
|
||||||
import io.anuke.mindustry.entities.traits.TypeTrait;
|
import io.anuke.mindustry.entities.traits.TypeTrait;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.Content;
|
||||||
|
import io.anuke.mindustry.game.MappableContent;
|
||||||
|
import io.anuke.mindustry.game.Rules;
|
||||||
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.gen.Serialization;
|
import io.anuke.mindustry.gen.Serialization;
|
||||||
import io.anuke.mindustry.type.ContentType;
|
import io.anuke.mindustry.type.ContentType;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.BlockPart;
|
import io.anuke.mindustry.world.blocks.BlockPart;
|
||||||
|
import io.anuke.mindustry.world.blocks.storage.CoreBlock;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -120,7 +124,7 @@ public abstract class SaveFileVersion{
|
|||||||
tile.entity.readConfig(stream);
|
tile.entity.readConfig(stream);
|
||||||
tile.entity.read(stream);
|
tile.entity.read(stream);
|
||||||
|
|
||||||
if(tile.block() == Blocks.core){
|
if(tile.block() instanceof CoreBlock){
|
||||||
state.teams.get(t).cores.add(tile);
|
state.teams.get(t).cores.add(tile);
|
||||||
}
|
}
|
||||||
}else if(wallid == 0){
|
}else if(wallid == 0){
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
ObjectIntMap<Item> items = data.items();
|
ObjectIntMap<Item> items = data.items();
|
||||||
for(Item item : Vars.content.items()){
|
for(Item item : Vars.content.items()){
|
||||||
if(item.type == ItemType.material && data.isUnlocked(item)){
|
if(item.type == ItemType.material && data.isUnlocked(item)){
|
||||||
add(items.get(item, 0) + "").left();
|
label(() -> items.get(item, 0) + "").left();
|
||||||
addImage(item.region).size(8*4).pad(4);
|
addImage(item.region).size(8*4).pad(4);
|
||||||
add("[LIGHT_GRAY]" + item.localizedName()).left();
|
add("[LIGHT_GRAY]" + item.localizedName()).left();
|
||||||
row();
|
row();
|
||||||
|
|||||||
@@ -1,34 +1,42 @@
|
|||||||
package io.anuke.mindustry.ui.dialogs;
|
package io.anuke.mindustry.ui.dialogs;
|
||||||
|
|
||||||
|
import io.anuke.arc.Core;
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.arc.collection.Array;
|
||||||
import io.anuke.arc.collection.ObjectSet;
|
import io.anuke.arc.collection.ObjectSet;
|
||||||
|
import io.anuke.arc.graphics.Color;
|
||||||
import io.anuke.arc.graphics.g2d.Lines;
|
import io.anuke.arc.graphics.g2d.Lines;
|
||||||
import io.anuke.arc.graphics.g2d.ScissorStack;
|
import io.anuke.arc.graphics.g2d.ScissorStack;
|
||||||
import io.anuke.arc.input.KeyCode;
|
import io.anuke.arc.input.KeyCode;
|
||||||
|
import io.anuke.arc.math.Interpolation;
|
||||||
import io.anuke.arc.math.geom.Rectangle;
|
import io.anuke.arc.math.geom.Rectangle;
|
||||||
import io.anuke.arc.scene.Group;
|
import io.anuke.arc.scene.Group;
|
||||||
|
import io.anuke.arc.scene.actions.Actions;
|
||||||
import io.anuke.arc.scene.event.InputEvent;
|
import io.anuke.arc.scene.event.InputEvent;
|
||||||
import io.anuke.arc.scene.event.InputListener;
|
import io.anuke.arc.scene.event.InputListener;
|
||||||
|
import io.anuke.arc.scene.event.Touchable;
|
||||||
|
import io.anuke.arc.scene.style.TextureRegionDrawable;
|
||||||
import io.anuke.arc.scene.ui.ImageButton;
|
import io.anuke.arc.scene.ui.ImageButton;
|
||||||
|
import io.anuke.arc.scene.ui.layout.Table;
|
||||||
import io.anuke.arc.util.Align;
|
import io.anuke.arc.util.Align;
|
||||||
import io.anuke.arc.util.Log;
|
import io.anuke.arc.util.Log;
|
||||||
import io.anuke.arc.util.Structs;
|
import io.anuke.arc.util.Structs;
|
||||||
import io.anuke.mindustry.Vars;
|
|
||||||
import io.anuke.mindustry.content.Blocks;
|
|
||||||
import io.anuke.mindustry.content.TechTree;
|
import io.anuke.mindustry.content.TechTree;
|
||||||
import io.anuke.mindustry.content.TechTree.TechNode;
|
import io.anuke.mindustry.content.TechTree.TechNode;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.type.Recipe.RecipeVisibility;
|
import io.anuke.mindustry.type.Recipe.RecipeVisibility;
|
||||||
import io.anuke.mindustry.ui.TreeLayout;
|
import io.anuke.mindustry.ui.TreeLayout;
|
||||||
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
|
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
|
||||||
import io.anuke.mindustry.world.Block.Icon;
|
import io.anuke.mindustry.world.Block.Icon;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.content;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class TechTreeDialog extends FloatingDialog{
|
public class TechTreeDialog extends FloatingDialog{
|
||||||
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
||||||
|
private TechTreeNode root = new TechTreeNode(TechTree.root, null);
|
||||||
private static final float nodeSize = 60f;
|
private static final float nodeSize = 60f;
|
||||||
|
private int toasts;
|
||||||
|
|
||||||
public TechTreeDialog(){
|
public TechTreeDialog(){
|
||||||
super("$techtree");
|
super("$techtree");
|
||||||
@@ -36,14 +44,14 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
TreeLayout layout = new TreeLayout();
|
TreeLayout layout = new TreeLayout();
|
||||||
layout.gapBetweenLevels = 60f;
|
layout.gapBetweenLevels = 60f;
|
||||||
layout.gapBetweenNodes = 40f;
|
layout.gapBetweenNodes = 40f;
|
||||||
layout.layout(new TechTreeNode(TechTree.root, null));
|
layout.layout(root);
|
||||||
|
|
||||||
cont.add(new View()).grow();
|
cont.add(new View()).grow();
|
||||||
|
|
||||||
{ //debug code; TODO remove
|
{ //debug code; TODO remove
|
||||||
ObjectSet<Recipe> used = new ObjectSet<Recipe>().select(t -> true);
|
ObjectSet<Recipe> used = new ObjectSet<Recipe>().select(t -> true);
|
||||||
for(TechTreeNode node : nodes){
|
for(TechTreeNode node : nodes){
|
||||||
if(node.node.block != null) used.add(Recipe.getByResult(node.node.block));
|
used.add(node.node.recipe());
|
||||||
}
|
}
|
||||||
Array<Recipe> recipes = content.recipes().select(r -> r.visibility == RecipeVisibility.all && !used.contains(r));
|
Array<Recipe> recipes = content.recipes().select(r -> r.visibility == RecipeVisibility.all && !used.contains(r));
|
||||||
recipes.sort(Structs.comparing(r -> r.cost));
|
recipes.sort(Structs.comparing(r -> r.cost));
|
||||||
@@ -55,11 +63,44 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shown(() -> checkNodes(root));
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkNodes(TechTreeNode node){
|
||||||
|
boolean locked = locked(node);
|
||||||
|
if(!locked) node.visible = true;
|
||||||
|
for(TreeNode child : node.children){
|
||||||
|
TechTreeNode l = (TechTreeNode)child;
|
||||||
|
l.visible = !locked;
|
||||||
|
checkNodes(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showToast(String info){
|
||||||
|
toasts ++;
|
||||||
|
int t = toasts;
|
||||||
|
Table table = new Table();
|
||||||
|
table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.run(() -> toasts --), Actions.removeActor());
|
||||||
|
table.top().add(info);
|
||||||
|
table.update(() -> {
|
||||||
|
table.toFront();
|
||||||
|
table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21 - t*20f, Align.top);
|
||||||
|
});
|
||||||
|
Core.scene.add(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean locked(TreeNode node){
|
||||||
|
return locked(((TechTreeNode)node).node);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean locked(TechNode node){
|
||||||
|
return !data.isUnlocked(node.recipe());
|
||||||
|
}
|
||||||
|
|
||||||
class TechTreeNode extends TreeNode{
|
class TechTreeNode extends TreeNode{
|
||||||
final TechNode node;
|
final TechNode node;
|
||||||
|
boolean visible = true;
|
||||||
|
|
||||||
public TechTreeNode(TechNode node, TreeNode parent){
|
public TechTreeNode(TechNode node, TreeNode parent){
|
||||||
this.node = node;
|
this.node = node;
|
||||||
@@ -77,21 +118,47 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
|
|
||||||
class View extends Group{
|
class View extends Group{
|
||||||
float panX = 0, panY = 0;
|
float panX = 0, panY = 0;
|
||||||
Rectangle clip = new Rectangle();
|
|
||||||
boolean moved = false;
|
boolean moved = false;
|
||||||
|
Rectangle clip = new Rectangle();
|
||||||
|
ImageButton hoverNode;
|
||||||
|
Table infoTable = new Table();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
infoTable.touchable(Touchable.enabled);
|
||||||
|
|
||||||
for(TechTreeNode node : nodes){
|
for(TechTreeNode node : nodes){
|
||||||
ImageButton button = new ImageButton(node.node.block == null ? Blocks.core.icon(Icon.medium) : node.node.block.icon(Icon.medium), "node");
|
ImageButton button = new ImageButton(node.node.block.icon(Icon.medium), "node");
|
||||||
button.clicked(() -> {
|
button.clicked(() -> {
|
||||||
if(moved) return;
|
if(mobile){
|
||||||
Vars.ui.content.show(Recipe.getByResult(node.node.block == null ? Blocks.conveyor : node.node.block));
|
hoverNode = button;
|
||||||
|
rebuild();
|
||||||
|
}else if(data.hasItems(node.node.requirements) && locked(node)){
|
||||||
|
unlock(node.node);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
button.tapped(() -> {
|
button.hovered(() -> {
|
||||||
moved = false;
|
if(!mobile && hoverNode != button && node.visible){
|
||||||
|
hoverNode = button;
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
button.exited(() -> {
|
||||||
|
if(hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){
|
||||||
|
hoverNode = null;
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
button.touchable(() -> !node.visible ? Touchable.disabled : Touchable.enabled);
|
||||||
|
button.setUserObject(node.node);
|
||||||
|
button.tapped(() -> moved = false);
|
||||||
button.setSize(nodeSize, nodeSize);
|
button.setSize(nodeSize, nodeSize);
|
||||||
button.update(() -> button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f - 0.5f, Align.center));
|
button.update(() -> {
|
||||||
|
button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f - 0.5f, Align.center);
|
||||||
|
button.getStyle().up = Core.scene.skin.getDrawable(!locked(node) ? "content-background" : "content-background-locked");
|
||||||
|
((TextureRegionDrawable)button.getStyle().imageUp)
|
||||||
|
.setRegion(node.visible ? node.node.block.icon(Icon.medium) : Core.atlas.find("icon-tree-locked"));
|
||||||
|
button.getImage().setColor(!locked(node) ? Color.WHITE : Color.GRAY);
|
||||||
|
});
|
||||||
addChild(button);
|
addChild(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +182,75 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unlock(TechNode node){
|
||||||
|
data.unlockContent(node.recipe());
|
||||||
|
data.removeItems(node.requirements);
|
||||||
|
showToast(Core.bundle.format("researched", node.block.formalName));
|
||||||
|
checkNodes(root);
|
||||||
|
hoverNode = null;
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rebuild(){
|
||||||
|
ImageButton button = hoverNode;
|
||||||
|
|
||||||
|
infoTable.remove();
|
||||||
|
infoTable.clear();
|
||||||
|
infoTable.update(null);
|
||||||
|
|
||||||
|
if(button == null) return;
|
||||||
|
|
||||||
|
TechNode node = (TechNode)button.getUserObject();
|
||||||
|
|
||||||
|
infoTable.exited(() -> {
|
||||||
|
if(hoverNode == button && !infoTable.hasMouse() && !hoverNode.hasMouse()){
|
||||||
|
hoverNode = null;
|
||||||
|
rebuild();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
infoTable.background("content-background");
|
||||||
|
infoTable.update(() -> infoTable.setPosition(button.getX() + button.getWidth(), button.getY() + button.getHeight(), Align.topLeft));
|
||||||
|
|
||||||
|
infoTable.margin(0).left().defaults().left();
|
||||||
|
|
||||||
|
infoTable.addImageButton("icon-info", "node", 14*2, () -> ui.content.show(node.recipe())).growY().width(50f);
|
||||||
|
|
||||||
|
infoTable.add().grow();
|
||||||
|
|
||||||
|
infoTable.table(desc -> {
|
||||||
|
desc.left().defaults().left();
|
||||||
|
desc.add(node.block.formalName);
|
||||||
|
desc.row();
|
||||||
|
if(locked(node)){
|
||||||
|
desc.table(t -> {
|
||||||
|
t.left();
|
||||||
|
for(ItemStack req : node.requirements){
|
||||||
|
t.table(list -> {
|
||||||
|
list.left();
|
||||||
|
list.addImage(req.item.getContentIcon()).size(8 * 3).padRight(3);
|
||||||
|
list.add(req.item.localizedName()).color(Color.LIGHT_GRAY);
|
||||||
|
list.add(" " + Math.min(data.items().get(req.item, 0), req.amount) + " / " + req.amount)
|
||||||
|
.color(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET);
|
||||||
|
}).fillX().left();
|
||||||
|
t.row();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
desc.add("$completed");
|
||||||
|
}
|
||||||
|
}).pad(9);
|
||||||
|
|
||||||
|
if(mobile && locked(node)){
|
||||||
|
infoTable.row();
|
||||||
|
infoTable.addImageTextButton("$research", "icon-check", "node", 16*2, () -> unlock(node))
|
||||||
|
.disabled(b -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
addChild(infoTable);
|
||||||
|
infoTable.pack();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
if(!ScissorStack.pushScissors(clip.set(x, y, width, height))){
|
if(!ScissorStack.pushScissors(clip.set(x, y, width, height))){
|
||||||
@@ -123,26 +259,16 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
|
|
||||||
float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y;
|
float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y;
|
||||||
|
|
||||||
Lines.stroke(3f, Palette.accent);
|
|
||||||
|
|
||||||
for(TreeNode node : nodes){
|
for(TreeNode node : nodes){
|
||||||
for(TreeNode child : node.children){
|
for(TreeNode child : node.children){
|
||||||
|
Lines.stroke(3f, locked(node) || locked(child) ? Palette.locked : Palette.accent);
|
||||||
|
|
||||||
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
|
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.draw();
|
super.draw();
|
||||||
|
|
||||||
/*
|
|
||||||
Draw.color();
|
|
||||||
|
|
||||||
for(TechTreeNode node : nodes){
|
|
||||||
Draw.drawable("content-background", node.x + offsetX - nodeSize/2f, node.y + offsetY - nodeSize/2f, nodeSize, nodeSize);
|
|
||||||
|
|
||||||
TextureRegion region = node.node.block == null ? Blocks.core.icon(Icon.medium) : node.node.block.icon(Icon.medium);
|
|
||||||
Draw.rect(region, node.x + offsetX, node.y + offsetY - 0.5f, region.getWidth(), region.getHeight());
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ScissorStack.popScissors();
|
ScissorStack.popScissors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||