package net.alcuria.umbracraft.editor.widget; import net.alcuria.umbracraft.Db.DefinitionReference; import net.alcuria.umbracraft.definitions.map.EntityReferenceDefinition; import net.alcuria.umbracraft.definitions.map.MapDefinition; import net.alcuria.umbracraft.definitions.map.MapTileDefinition; import net.alcuria.umbracraft.editor.Drawables; import net.alcuria.umbracraft.editor.Editor; import net.alcuria.umbracraft.listeners.Listener; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.actions.Actions; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.kotcrab.vis.ui.widget.VisLabel; import com.kotcrab.vis.ui.widget.VisTextField; /** A widget to preview a particular map with the ability to click on a tile and * view its coordinates. * @author Andrew Keturi */ public class MapPreviewWidget { /** Displays selected coordinates */ private Label coords; /** The currently viewed definition. We probably shouldn't modify this */ private MapDefinition definition; /** The color of the last selected actor */ private Color lastColor; /** The last actor the user selected */ private Actor lastSelected; /** Content tables */ private Table root, mapTable; public MapPreviewWidget(MapDefinition definition) { this.definition = definition; } public Actor getActor() { if (root == null) { root = new Table(); update(); updateMap(); } return root; } public void update() { root.clear(); WidgetUtils.divider(root, "blue"); root.add(new Table() { { add(WidgetUtils.tooltip("Enter the name of a map to get a top-down preview. Click to get coordinates.")); add(new VisLabel("Map Preview:")).padRight(10); SuggestionWidget suggestions = new SuggestionWidget(Editor.db().list(MapDefinition.class, DefinitionReference.MAPS).keys(), 200, true); add(suggestions.getActor()).row(); suggestions.addSelectListener(updateMapListener(suggestions.getTextField())); suggestions.setGenericPopulate(updateMapListener(suggestions.getTextField())); } }).row(); root.add(mapTable = new Table()).row(); root.add(coords = new VisLabel()); } private void updateMap() { mapTable.clear(); if (definition != null) { for (int j = 0; j < definition.getHeight(); j++) { Table row = new Table(); for (int i = 0; i < definition.getWidth(); i++) { // check if there is an EntityReference here String entityName = null; for (EntityReferenceDefinition entity : definition.entities) { if (entity.x == i && entity.y == definition.getHeight() - j - 1) { entityName = entity.name; break; } } // create and add the tile final Actor tile = new Image(Drawables.get("white")); if (entityName != null) { // color this tile red since we have an entity here tile.setColor(Color.YELLOW); tile.addAction(Actions.forever(Actions.sequence(Actions.alpha(0, 0.5f, Interpolation.sine), Actions.alpha(1, 0.5f, Interpolation.sine)))); } else { // no entity here, adjust the color based on the height final MapTileDefinition tileDefinition = definition.getTileDefinition(i, j); float color = MathUtils.clamp(1 - tileDefinition.altitude * 0.1f, 0, 1); tile.setColor(color, color, color, 1); } row.add(tile).size(4).pad(0); // add a listener that when clicked will display the coordinates final int tileX = i; final int tileY = definition.getHeight() - j - 1; final String entityDisplayName = entityName != null ? entityName : ""; tile.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { coords.setText(String.format("(%d, %d) %s", tileX, tileY, entityDisplayName)); // update the previously-selected tile's color if (lastSelected != null && lastColor != null) { lastSelected.setColor(lastColor); } // keep around a reference to this selection for next click, then set the color lastSelected = tile; lastColor = tile.getColor().cpy(); tile.setColor(Color.LIME); } }); } mapTable.add(row).row(); } } } private Listener updateMapListener(final VisTextField textField) { return new Listener() { @Override public void invoke() { // TODO: null checks try { final MapDefinition current = Editor.db().map(textField.getText()); if (current != null) { definition = current; updateMap(); } } catch (NullPointerException e) { // couldn't find the map, no worries -- clear any old maps out mapTable.clear(); } } }; } }