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.wndinfotrap.inactive=This trap is inactive, and can no longer be triggered.
|
||||||
|
|
||||||
windows.wndjournal.guide=Guide
|
windows.wndjournal$guidetab.title=Tome of Dungeon Mastery
|
||||||
windows.wndjournal.notes=Notes
|
windows.wndjournal$alchemytab.title=Alchemy Guide
|
||||||
windows.wndjournal.items=Items
|
|
||||||
windows.wndjournal$guidetab.title=Guidebooks
|
|
||||||
windows.wndjournal$guidetab.missing=page missing
|
windows.wndjournal$guidetab.missing=page missing
|
||||||
windows.wndjournal$notestab.keys=Keys
|
windows.wndjournal$notestab.title=Adventuring Notes
|
||||||
windows.wndjournal$notestab.landmarks=Landmarks
|
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=Catalogs
|
||||||
windows.wndjournal$catalogtab.title_equipment=Equipment
|
windows.wndjournal$catalogtab.title_equipment=Equipment
|
||||||
windows.wndjournal$catalogtab.title_consumables=Consumables
|
windows.wndjournal$catalogtab.title_consumables=Consumables
|
||||||
|
|||||||
@@ -21,9 +21,24 @@
|
|||||||
|
|
||||||
package com.shatteredpixel.shatteredpixeldungeon.journal;
|
package com.shatteredpixel.shatteredpixeldungeon.journal;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
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.Bundlable;
|
||||||
import com.watabou.utils.Bundle;
|
import com.watabou.utils.Bundle;
|
||||||
|
|
||||||
@@ -41,6 +56,12 @@ public class Notes {
|
|||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Image icon() { return Icons.STAIRS.get(); }
|
||||||
|
|
||||||
|
public int quantity() { return 1; }
|
||||||
|
|
||||||
|
public abstract String title();
|
||||||
|
|
||||||
public abstract String desc();
|
public abstract String desc();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -80,7 +101,7 @@ public class Notes {
|
|||||||
|
|
||||||
DEMON_SPAWNER;
|
DEMON_SPAWNER;
|
||||||
|
|
||||||
public String desc() {
|
public String title() {
|
||||||
return Messages.get(this, name());
|
return Messages.get(this, name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,9 +117,48 @@ public class Notes {
|
|||||||
this.depth = depth;
|
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
|
@Override
|
||||||
public String desc() {
|
public String desc() {
|
||||||
return landmark.desc();
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -139,10 +199,20 @@ public class Notes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String desc() {
|
public Image icon() {
|
||||||
|
return new ItemSprite(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String title() {
|
||||||
return key.title();
|
return key.title();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String desc() {
|
||||||
|
return key.desc();
|
||||||
|
}
|
||||||
|
|
||||||
public Class<? extends Key> type(){
|
public Class<? extends Key> type(){
|
||||||
return key.getClass();
|
return key.getClass();
|
||||||
}
|
}
|
||||||
@@ -260,6 +330,21 @@ public class Notes {
|
|||||||
return filtered;
|
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 ){
|
public static void remove( Record rec ){
|
||||||
records.remove(rec);
|
records.remove(rec);
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-14
@@ -35,6 +35,7 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
private ArrayList<Component> items = new ArrayList<>();
|
private ArrayList<Component> items = new ArrayList<>();
|
||||||
|
|
||||||
private static final int ITEM_SIZE = 17;
|
private static final int ITEM_SIZE = 17;
|
||||||
|
private static final int MIN_GROUP_SIZE = 3*(ITEM_SIZE+1);
|
||||||
|
|
||||||
public ScrollingGridPane(){
|
public ScrollingGridPane(){
|
||||||
super(new Component());
|
super(new Component());
|
||||||
@@ -77,15 +78,24 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
super.layout();
|
super.layout();
|
||||||
|
|
||||||
float left = 0;
|
float left = 0;
|
||||||
boolean freshRow = true;
|
|
||||||
float top = 0;
|
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++){
|
for (int i = 0; i < items.size(); i++){
|
||||||
Component item = items.get(i);
|
Component item = items.get(i);
|
||||||
if (item instanceof GridHeader){
|
if (item instanceof GridHeader){
|
||||||
if (left > 0){
|
//we can sometimes get two smaller headers next to each other if a group has no items in it
|
||||||
//this bit of logic here exists so that multiple headers can be on one row in landscape
|
//so we need to treat it as if there were grid items for proper layout
|
||||||
// if both of their groups have a small number of items (e.g. 6)
|
if (left > 0 || lastWasSmallheader){
|
||||||
float spaceLeft = width() - left;
|
|
||||||
|
//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;
|
int spaceReq = 0;
|
||||||
for (int j = i+1; j < items.size(); j++){
|
for (int j = i+1; j < items.size(); j++){
|
||||||
if (items.get(j) instanceof GridItem){
|
if (items.get(j) instanceof GridItem){
|
||||||
@@ -94,7 +104,9 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
break;
|
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;
|
top -= item.height()+1;
|
||||||
} else {
|
} else {
|
||||||
left = 0;
|
left = 0;
|
||||||
@@ -104,15 +116,27 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
}
|
}
|
||||||
item.setRect(left, top, width(), item.height());
|
item.setRect(left, top, width(), item.height());
|
||||||
top += item.height()+1;
|
top += item.height()+1;
|
||||||
|
widthThisGroup = 0;
|
||||||
|
|
||||||
|
if (!((GridHeader) item).center){
|
||||||
|
lastWasSmallheader = true;
|
||||||
|
} else {
|
||||||
|
lastWasSmallheader = false;
|
||||||
|
}
|
||||||
|
|
||||||
} if (item instanceof GridItem){
|
} if (item instanceof GridItem){
|
||||||
if (left + ITEM_SIZE > width()) {
|
if (left + ITEM_SIZE > width()) {
|
||||||
left = 0;
|
left = 0;
|
||||||
|
widthThisGroup = 0;
|
||||||
top += ITEM_SIZE+1;
|
top += ITEM_SIZE+1;
|
||||||
freshRow = false;
|
freshRow = false;
|
||||||
}
|
}
|
||||||
item.setRect(left, top, ITEM_SIZE, ITEM_SIZE);
|
item.setRect(left, top, ITEM_SIZE, ITEM_SIZE);
|
||||||
left += ITEM_SIZE+1;
|
left += ITEM_SIZE+1;
|
||||||
|
widthThisGroup += ITEM_SIZE+1;
|
||||||
|
lastWasSmallheader = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (left > 0){
|
if (left > 0){
|
||||||
left = 0;
|
left = 0;
|
||||||
@@ -186,7 +210,6 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
|
|
||||||
protected RenderedTextBlock text;
|
protected RenderedTextBlock text;
|
||||||
boolean center;
|
boolean center;
|
||||||
protected ColorBlock sep;
|
|
||||||
|
|
||||||
public GridHeader( String text ){
|
public GridHeader( String text ){
|
||||||
this(text, 7, false);
|
this(text, 7, false);
|
||||||
@@ -199,10 +222,6 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
this.text = PixelScene.renderTextBlock(text, size);
|
this.text = PixelScene.renderTextBlock(text, size);
|
||||||
add(this.text);
|
add(this.text);
|
||||||
|
|
||||||
if (center) {
|
|
||||||
sep = new ColorBlock(1, 1, 0xFF222222);
|
|
||||||
//add(sep);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -215,11 +234,11 @@ public class ScrollingGridPane extends ScrollPane {
|
|||||||
super.layout();
|
super.layout();
|
||||||
|
|
||||||
if (center){
|
if (center){
|
||||||
|
text.align(RenderedTextBlock.CENTER_ALIGN);
|
||||||
|
text.maxWidth((int)width());
|
||||||
text.setPos(x + (width() - text.width()) / 2, y+1);
|
text.setPos(x + (width() - text.width()) / 2, y+1);
|
||||||
sep.size(width(), 1);
|
|
||||||
sep.x = x;
|
|
||||||
sep.y = bottom();
|
|
||||||
} else {
|
} else {
|
||||||
|
text.maxWidth((int)width());
|
||||||
text.setPos(x, y+1);
|
text.setPos(x, y+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-31
@@ -22,8 +22,8 @@
|
|||||||
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
package com.shatteredpixel.shatteredpixeldungeon.windows;
|
||||||
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
@@ -119,6 +119,11 @@ public class WndJournal extends WndTabbed {
|
|||||||
guideTab.active = guideTab.visible = value;
|
guideTab.active = guideTab.visible = value;
|
||||||
if (value) last_index = 0;
|
if (value) last_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String hoverText() {
|
||||||
|
return Messages.get(guideTab, "title");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
new IconTab( new ItemSprite(ItemSpriteSheet.ALCH_PAGE, null) ) {
|
new IconTab( new ItemSprite(ItemSpriteSheet.ALCH_PAGE, null) ) {
|
||||||
protected void select( boolean value ) {
|
protected void select( boolean value ) {
|
||||||
@@ -126,6 +131,11 @@ public class WndJournal extends WndTabbed {
|
|||||||
alchemyTab.active = alchemyTab.visible = value;
|
alchemyTab.active = alchemyTab.visible = value;
|
||||||
if (value) last_index = 1;
|
if (value) last_index = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String hoverText() {
|
||||||
|
return Messages.get(alchemyTab, "title");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
new IconTab( Icons.get(Icons.STAIRS) ) {
|
new IconTab( Icons.get(Icons.STAIRS) ) {
|
||||||
protected void select( boolean value ) {
|
protected void select( boolean value ) {
|
||||||
@@ -133,6 +143,11 @@ public class WndJournal extends WndTabbed {
|
|||||||
notesTab.active = notesTab.visible = value;
|
notesTab.active = notesTab.visible = value;
|
||||||
if (value) last_index = 2;
|
if (value) last_index = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String hoverText() {
|
||||||
|
return Messages.get(notesTab, "title");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
new IconTab( Icons.CATALOG.get() ) {
|
new IconTab( Icons.CATALOG.get() ) {
|
||||||
protected void select( boolean value ) {
|
protected void select( boolean value ) {
|
||||||
@@ -140,6 +155,11 @@ public class WndJournal extends WndTabbed {
|
|||||||
catalogTab.active = catalogTab.visible = value;
|
catalogTab.active = catalogTab.visible = value;
|
||||||
if (value) last_index = 3;
|
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 static class NotesTab extends Component {
|
||||||
|
|
||||||
private ScrollingListPane list;
|
private ScrollingGridPane grid;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createChildren() {
|
protected void createChildren() {
|
||||||
list = new ScrollingListPane();
|
grid = new ScrollingGridPane();
|
||||||
add( list );
|
add(grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void layout() {
|
protected void layout() {
|
||||||
super.layout();
|
super.layout();
|
||||||
list.setRect( x, y, width, height);
|
grid.setRect( x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateList(){
|
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){
|
grid.addHeader("_" + Messages.get(this, "title") + "_", 9, true);
|
||||||
ScrollingListPane.ListItem item = new ScrollingListPane.ListItem( Icons.get(Icons.STAIRS),
|
|
||||||
Integer.toString(rec.depth()),
|
grid.addHeader(Messages.get(this, "desc"), 6, true);
|
||||||
Messages.titleCase(rec.desc()));
|
|
||||||
if (Dungeon.depth == rec.depth()) item.hardlight(TITLE_COLOR);
|
for (int i = Statistics.deepestFloor; i > 0; i--){
|
||||||
list.addItem(item);
|
|
||||||
|
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
|
grid.setRect(x, y, width, height);
|
||||||
ArrayList<Notes.LandmarkRecord> landmarks = Notes.getRecords(Notes.LandmarkRecord.class);
|
|
||||||
if (!landmarks.isEmpty()){
|
|
||||||
|
|
||||||
list.addTitle(Messages.get(this, "landmarks"));
|
|
||||||
|
|
||||||
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