v2.5.0: converted notes tab to use new grid UI
This commit is contained in:
@@ -112,13 +112,12 @@ windows.wndinfotalent.upgrade=Upgrade Talent
|
||||
|
||||
windows.wndinfotrap.inactive=This trap is inactive, and can no longer be triggered.
|
||||
|
||||
windows.wndjournal.guide=Guide
|
||||
windows.wndjournal.notes=Notes
|
||||
windows.wndjournal.items=Items
|
||||
windows.wndjournal$guidetab.title=Guidebooks
|
||||
windows.wndjournal$guidetab.title=Tome of Dungeon Mastery
|
||||
windows.wndjournal$alchemytab.title=Alchemy Guide
|
||||
windows.wndjournal$guidetab.missing=page missing
|
||||
windows.wndjournal$notestab.keys=Keys
|
||||
windows.wndjournal$notestab.landmarks=Landmarks
|
||||
windows.wndjournal$notestab.title=Adventuring Notes
|
||||
windows.wndjournal$notestab.desc=As you journey through the dungeon, you will automatically record noteworthy things here.
|
||||
windows.wndjournal$notestab.floor_header=Floor %d
|
||||
windows.wndjournal$catalogtab.title=Catalogs
|
||||
windows.wndjournal$catalogtab.title_equipment=Equipment
|
||||
windows.wndjournal$catalogtab.title_consumables=Consumables
|
||||
|
||||
@@ -21,9 +21,24 @@
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.journal;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.plants.Sungrass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.GhostSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ImpSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkeeperSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.SpawnerSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.StatueSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.WandmakerSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.tiles.TerrainFeaturesTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIcon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||
import com.watabou.noosa.Image;
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
||||
@@ -40,7 +55,13 @@ public class Notes {
|
||||
public int depth(){
|
||||
return depth;
|
||||
}
|
||||
|
||||
public Image icon() { return Icons.STAIRS.get(); }
|
||||
|
||||
public int quantity() { return 1; }
|
||||
|
||||
public abstract String title();
|
||||
|
||||
public abstract String desc();
|
||||
|
||||
@Override
|
||||
@@ -79,8 +100,8 @@ public class Notes {
|
||||
IMP,
|
||||
|
||||
DEMON_SPAWNER;
|
||||
|
||||
public String desc() {
|
||||
|
||||
public String title() {
|
||||
return Messages.get(this, name());
|
||||
}
|
||||
}
|
||||
@@ -95,12 +116,51 @@ public class Notes {
|
||||
this.landmark = landmark;
|
||||
this.depth = depth;
|
||||
}
|
||||
|
||||
|
||||
public Image icon(){
|
||||
switch (landmark){
|
||||
default:
|
||||
return super.icon();
|
||||
|
||||
//TODO we probably want a separate image file for landmark visuals, especially if we expand this
|
||||
case WELL_OF_HEALTH:
|
||||
case WELL_OF_AWARENESS:
|
||||
return new Image(Assets.Environment.TILES_SEWERS, 48, 16, 16, 16);
|
||||
case ALCHEMY:
|
||||
return new Image(Assets.Environment.TILES_SEWERS, 0, 64, 16, 16);
|
||||
case GARDEN:
|
||||
return TerrainFeaturesTilemap.getPlantVisual(new Sungrass());
|
||||
case STATUE:
|
||||
return new Image(new StatueSprite());
|
||||
case SACRIFICIAL_FIRE:
|
||||
return new BuffIcon(BuffIndicator.SACRIFICE, true);
|
||||
case SHOP:
|
||||
return new Image(new ShopkeeperSprite());
|
||||
|
||||
case GHOST:
|
||||
return new Image(new GhostSprite());
|
||||
case WANDMAKER:
|
||||
return new Image(new WandmakerSprite());
|
||||
case TROLL:
|
||||
return new Image(new BlacksmithSprite());
|
||||
case IMP:
|
||||
return new Image(new ImpSprite());
|
||||
|
||||
case DEMON_SPAWNER:
|
||||
return new Image(new SpawnerSprite());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String title() {
|
||||
return landmark.title();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return landmark.desc();
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof LandmarkRecord)
|
||||
@@ -137,16 +197,26 @@ public class Notes {
|
||||
public int depth() {
|
||||
return key.depth;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Image icon() {
|
||||
return new ItemSprite(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String title() {
|
||||
return key.title();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return key.title();
|
||||
return key.desc();
|
||||
}
|
||||
|
||||
public Class<? extends Key> type(){
|
||||
return key.getClass();
|
||||
}
|
||||
|
||||
|
||||
public int quantity(){
|
||||
return key.quantity();
|
||||
}
|
||||
@@ -259,6 +329,21 @@ public class Notes {
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public static ArrayList<Record> getRecords(int depth){
|
||||
ArrayList<Record> filtered = new ArrayList<>();
|
||||
for (Record rec : records){
|
||||
if (rec.depth() == depth){
|
||||
if (rec instanceof KeyRecord){
|
||||
filtered.add(rec); //key records always go at the end
|
||||
} else {
|
||||
filtered.add(0, rec);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public static void remove( Record rec ){
|
||||
records.remove(rec);
|
||||
|
||||
@@ -35,6 +35,7 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
private ArrayList<Component> items = new ArrayList<>();
|
||||
|
||||
private static final int ITEM_SIZE = 17;
|
||||
private static final int MIN_GROUP_SIZE = 3*(ITEM_SIZE+1);
|
||||
|
||||
public ScrollingGridPane(){
|
||||
super(new Component());
|
||||
@@ -77,15 +78,24 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
super.layout();
|
||||
|
||||
float left = 0;
|
||||
boolean freshRow = true;
|
||||
float top = 0;
|
||||
|
||||
//these variables help control logic for laying out multiple grid groups on one line
|
||||
boolean freshRow = true; //whether the previous group is still on its first row
|
||||
boolean lastWasSmallheader = false; //whether the last UI element was a header on its own
|
||||
float widthThisGroup = 0; //how wide the current group is (we use a min of 3 items)
|
||||
|
||||
for (int i = 0; i < items.size(); i++){
|
||||
Component item = items.get(i);
|
||||
if (item instanceof GridHeader){
|
||||
if (left > 0){
|
||||
//this bit of logic here exists so that multiple headers can be on one row in landscape
|
||||
// if both of their groups have a small number of items (e.g. 6)
|
||||
float spaceLeft = width() - left;
|
||||
//we can sometimes get two smaller headers next to each other if a group has no items in it
|
||||
//so we need to treat it as if there were grid items for proper layout
|
||||
if (left > 0 || lastWasSmallheader){
|
||||
|
||||
//this bit of logic exists so that multiple headers can be on one row
|
||||
// if all of their groups have a small number of items, with a min space for 3
|
||||
float spacing = Math.max(0, MIN_GROUP_SIZE - widthThisGroup);
|
||||
float spaceLeft = width() - (left + spacing);
|
||||
int spaceReq = 0;
|
||||
for (int j = i+1; j < items.size(); j++){
|
||||
if (items.get(j) instanceof GridItem){
|
||||
@@ -94,7 +104,9 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (freshRow && spaceLeft >= spaceReq){
|
||||
spaceReq = Math.max(spaceReq, MIN_GROUP_SIZE);
|
||||
if (!((GridHeader) item).center && freshRow && spaceLeft >= spaceReq){
|
||||
left = left + spacing;
|
||||
top -= item.height()+1;
|
||||
} else {
|
||||
left = 0;
|
||||
@@ -104,15 +116,27 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
}
|
||||
item.setRect(left, top, width(), item.height());
|
||||
top += item.height()+1;
|
||||
widthThisGroup = 0;
|
||||
|
||||
if (!((GridHeader) item).center){
|
||||
lastWasSmallheader = true;
|
||||
} else {
|
||||
lastWasSmallheader = false;
|
||||
}
|
||||
|
||||
} if (item instanceof GridItem){
|
||||
if (left + ITEM_SIZE > width()) {
|
||||
left = 0;
|
||||
widthThisGroup = 0;
|
||||
top += ITEM_SIZE+1;
|
||||
freshRow = false;
|
||||
}
|
||||
item.setRect(left, top, ITEM_SIZE, ITEM_SIZE);
|
||||
left += ITEM_SIZE+1;
|
||||
widthThisGroup += ITEM_SIZE+1;
|
||||
lastWasSmallheader = false;
|
||||
}
|
||||
|
||||
}
|
||||
if (left > 0){
|
||||
left = 0;
|
||||
@@ -186,7 +210,6 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
|
||||
protected RenderedTextBlock text;
|
||||
boolean center;
|
||||
protected ColorBlock sep;
|
||||
|
||||
public GridHeader( String text ){
|
||||
this(text, 7, false);
|
||||
@@ -199,10 +222,6 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
this.text = PixelScene.renderTextBlock(text, size);
|
||||
add(this.text);
|
||||
|
||||
if (center) {
|
||||
sep = new ColorBlock(1, 1, 0xFF222222);
|
||||
//add(sep);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -215,11 +234,11 @@ public class ScrollingGridPane extends ScrollPane {
|
||||
super.layout();
|
||||
|
||||
if (center){
|
||||
text.align(RenderedTextBlock.CENTER_ALIGN);
|
||||
text.maxWidth((int)width());
|
||||
text.setPos(x + (width() - text.width()) / 2, y+1);
|
||||
sep.size(width(), 1);
|
||||
sep.x = x;
|
||||
sep.y = bottom();
|
||||
} else {
|
||||
text.maxWidth((int)width());
|
||||
text.setPos(x, y+1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
@@ -119,6 +119,11 @@ public class WndJournal extends WndTabbed {
|
||||
guideTab.active = guideTab.visible = value;
|
||||
if (value) last_index = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String hoverText() {
|
||||
return Messages.get(guideTab, "title");
|
||||
}
|
||||
},
|
||||
new IconTab( new ItemSprite(ItemSpriteSheet.ALCH_PAGE, null) ) {
|
||||
protected void select( boolean value ) {
|
||||
@@ -126,6 +131,11 @@ public class WndJournal extends WndTabbed {
|
||||
alchemyTab.active = alchemyTab.visible = value;
|
||||
if (value) last_index = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String hoverText() {
|
||||
return Messages.get(alchemyTab, "title");
|
||||
}
|
||||
},
|
||||
new IconTab( Icons.get(Icons.STAIRS) ) {
|
||||
protected void select( boolean value ) {
|
||||
@@ -133,6 +143,11 @@ public class WndJournal extends WndTabbed {
|
||||
notesTab.active = notesTab.visible = value;
|
||||
if (value) last_index = 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String hoverText() {
|
||||
return Messages.get(notesTab, "title");
|
||||
}
|
||||
},
|
||||
new IconTab( Icons.CATALOG.get() ) {
|
||||
protected void select( boolean value ) {
|
||||
@@ -140,6 +155,11 @@ public class WndJournal extends WndTabbed {
|
||||
catalogTab.active = catalogTab.visible = value;
|
||||
if (value) last_index = 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String hoverText() {
|
||||
return Messages.get(catalogTab, "title");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -401,52 +421,59 @@ public class WndJournal extends WndTabbed {
|
||||
|
||||
private static class NotesTab extends Component {
|
||||
|
||||
private ScrollingListPane list;
|
||||
private ScrollingGridPane grid;
|
||||
|
||||
@Override
|
||||
protected void createChildren() {
|
||||
list = new ScrollingListPane();
|
||||
add( list );
|
||||
grid = new ScrollingGridPane();
|
||||
add(grid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void layout() {
|
||||
super.layout();
|
||||
list.setRect( x, y, width, height);
|
||||
grid.setRect( x, y, width, height);
|
||||
}
|
||||
|
||||
private void updateList(){
|
||||
//Keys
|
||||
ArrayList<Notes.KeyRecord> keys = Notes.getRecords(Notes.KeyRecord.class);
|
||||
if (!keys.isEmpty()){
|
||||
list.addTitle(Messages.get(this, "keys"));
|
||||
|
||||
for(Notes.Record rec : keys){
|
||||
ScrollingListPane.ListItem item = new ScrollingListPane.ListItem( Icons.get(Icons.STAIRS),
|
||||
Integer.toString(rec.depth()),
|
||||
Messages.titleCase(rec.desc()));
|
||||
if (Dungeon.depth == rec.depth()) item.hardlight(TITLE_COLOR);
|
||||
list.addItem(item);
|
||||
grid.addHeader("_" + Messages.get(this, "title") + "_", 9, true);
|
||||
|
||||
grid.addHeader(Messages.get(this, "desc"), 6, true);
|
||||
|
||||
for (int i = Statistics.deepestFloor; i > 0; i--){
|
||||
|
||||
ArrayList<Notes.Record> recs = Notes.getRecords(i);
|
||||
|
||||
grid.addHeader("_" + Messages.get(this, "floor_header", i) + "_");
|
||||
for( Notes.Record rec : recs){
|
||||
|
||||
ScrollingGridPane.GridItem gridItem = new ScrollingGridPane.GridItem(rec.icon()){
|
||||
@Override
|
||||
public boolean onClick(float x, float y) {
|
||||
if (inside(x, y)) {
|
||||
GameScene.show(new WndTitledMessage(rec.icon(),
|
||||
Messages.titleCase(rec.title()),
|
||||
rec.desc()));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (rec.quantity() > 1){
|
||||
BitmapText text = new BitmapText(Integer.toString(rec.quantity()), PixelScene.pixelFont);
|
||||
text.measure();
|
||||
gridItem.addSecondIcon( text );
|
||||
}
|
||||
|
||||
grid.addItem(gridItem);
|
||||
}
|
||||
}
|
||||
|
||||
//Landmarks
|
||||
ArrayList<Notes.LandmarkRecord> landmarks = Notes.getRecords(Notes.LandmarkRecord.class);
|
||||
if (!landmarks.isEmpty()){
|
||||
|
||||
list.addTitle(Messages.get(this, "landmarks"));
|
||||
grid.setRect(x, y, width, height);
|
||||
|
||||
for (Notes.Record rec : landmarks) {
|
||||
ScrollingListPane.ListItem item = new ScrollingListPane.ListItem( Icons.get(Icons.STAIRS),
|
||||
Integer.toString(rec.depth()),
|
||||
Messages.titleCase(rec.desc()));
|
||||
if (Dungeon.depth == rec.depth()) item.hardlight(TITLE_COLOR);
|
||||
list.addItem(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
list.setRect(x, y, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user