v2.5.0: added functionality for custom note! Only plain text notes atm
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
ui.customnotebutton.hover_text=Add a Custom Note
|
||||
ui.customnotebutton.default_title_text=Custom Text Note
|
||||
ui.customnotebutton$customnotewindow.edit_title=Edit Title
|
||||
ui.customnotebutton$customnotewindow.add_text=Add Text
|
||||
ui.customnotebutton$customnotewindow.edit_text=Edit Text
|
||||
ui.customnotebutton$customnotewindow.delete=Delete
|
||||
ui.customnotebutton$customnotewindow.delete_warn=Are you sure you want to delete this custom note?
|
||||
ui.customnotebutton$customnotewindow.confirm=Confirm
|
||||
ui.customnotebutton$customnotewindow.cancel=Cancel
|
||||
|
||||
ui.quickslotbutton.select_item=Quickslot an item
|
||||
|
||||
ui.talentspane.tier=tier %d
|
||||
|
||||
@@ -117,6 +117,7 @@ windows.wndjournal$alchemytab.title=Alchemy Guide
|
||||
windows.wndjournal$guidetab.missing=page missing
|
||||
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.custom_notes=Custom Notes
|
||||
windows.wndjournal$notestab.floor_header=Floor %d
|
||||
windows.wndjournal$catalogtab.title=Catalogs
|
||||
windows.wndjournal$catalogtab.title_equipment=Equipment
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.RatKing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.WeakFloorRoom;
|
||||
@@ -77,6 +78,8 @@ public class Notes {
|
||||
public Visual secondIcon() { return null; }
|
||||
|
||||
public int quantity() { return 1; }
|
||||
|
||||
protected abstract int order();
|
||||
|
||||
public abstract String title();
|
||||
|
||||
@@ -243,6 +246,11 @@ public class Notes {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int order(){
|
||||
return landmark.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (obj instanceof LandmarkRecord)
|
||||
@@ -310,6 +318,11 @@ public class Notes {
|
||||
return key.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int order() {
|
||||
return 1000 + Generator.Category.order(key);
|
||||
}
|
||||
|
||||
public int quantity(){
|
||||
return key.quantity();
|
||||
}
|
||||
@@ -338,6 +351,128 @@ public class Notes {
|
||||
bundle.put( KEY, key );
|
||||
}
|
||||
}
|
||||
|
||||
public enum CustomType {
|
||||
TEXT,
|
||||
DEPTH, //TODO
|
||||
ITEM, //TODO
|
||||
ITEM_TYPE //TODO
|
||||
}
|
||||
|
||||
public static class CustomRecord extends Record {
|
||||
|
||||
protected CustomType type;
|
||||
|
||||
protected int ID;
|
||||
protected Class itemClass;
|
||||
|
||||
protected String title;
|
||||
protected String body;
|
||||
|
||||
public CustomRecord() {}
|
||||
|
||||
public CustomRecord(String title, String desc) {
|
||||
type = CustomType.TEXT;
|
||||
this.title = title;
|
||||
body = desc;
|
||||
}
|
||||
|
||||
public CustomRecord(int depth, String title, String desc) {
|
||||
type = CustomType.DEPTH;
|
||||
this.depth = depth;
|
||||
this.title = title;
|
||||
body = desc;
|
||||
}
|
||||
|
||||
public CustomRecord(Item item, String title, String desc) {
|
||||
type = CustomType.ITEM;
|
||||
itemClass = item.getClass();
|
||||
this.title = title;
|
||||
body = desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
if (type == CustomType.DEPTH){
|
||||
return depth;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image icon() {
|
||||
switch (type){
|
||||
case TEXT: default:
|
||||
return Icons.SCROLL_COLOR.get();
|
||||
case DEPTH:
|
||||
return Icons.STAIRS.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Visual secondIcon() {
|
||||
switch (type){
|
||||
case TEXT: default:
|
||||
//TODO perhaps use first few chars from title?
|
||||
return null;
|
||||
case DEPTH:
|
||||
BitmapText text = new BitmapText(Integer.toString(depth()), PixelScene.pixelFont);
|
||||
text.measure();
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int order() {
|
||||
return 2000 + ID;
|
||||
}
|
||||
|
||||
public void editText(String title, String desc){
|
||||
this.title = title;
|
||||
this.body = desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String title() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof CustomRecord && ((CustomRecord) obj).ID == ID;
|
||||
}
|
||||
|
||||
private static final String TYPE = "type";
|
||||
private static final String ID_NUMBER = "id_number";
|
||||
|
||||
private static final String TITLE = "title";
|
||||
private static final String BODY = "body";
|
||||
|
||||
@Override
|
||||
public void storeInBundle(Bundle bundle) {
|
||||
super.storeInBundle(bundle);
|
||||
bundle.put(TYPE, type);
|
||||
bundle.put(ID_NUMBER, ID);
|
||||
bundle.put(TITLE, title);
|
||||
bundle.put(BODY, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle(Bundle bundle) {
|
||||
super.restoreFromBundle(bundle);
|
||||
type = bundle.getEnum(TYPE, CustomType.class);
|
||||
ID = bundle.getInt(ID_NUMBER);
|
||||
|
||||
title = bundle.getString(TITLE);
|
||||
body = bundle.getString(BODY);
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayList<Record> records;
|
||||
|
||||
@@ -345,14 +480,19 @@ public class Notes {
|
||||
records = new ArrayList<>();
|
||||
}
|
||||
|
||||
private static final String RECORDS = "records";
|
||||
|
||||
private static final String RECORDS = "records";
|
||||
private static final String NEXT_CUSTOM_ID = "next_custom_id";
|
||||
|
||||
protected static int nextCustomID = 0;
|
||||
|
||||
public static void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( RECORDS, records );
|
||||
bundle.put( NEXT_CUSTOM_ID, nextCustomID );
|
||||
}
|
||||
|
||||
public static void restoreFromBundle( Bundle bundle ) {
|
||||
records = new ArrayList<>();
|
||||
nextCustomID = bundle.getInt( NEXT_CUSTOM_ID );
|
||||
for (Bundlable rec : bundle.getCollection( RECORDS ) ) {
|
||||
records.add( (Record) rec );
|
||||
}
|
||||
@@ -362,7 +502,7 @@ public class Notes {
|
||||
LandmarkRecord l = new LandmarkRecord( landmark, Dungeon.depth );
|
||||
if (!records.contains(l)) {
|
||||
boolean result = records.add(new LandmarkRecord(landmark, Dungeon.depth));
|
||||
Collections.sort(records);
|
||||
Collections.sort(records, comparator);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
@@ -380,7 +520,7 @@ public class Notes {
|
||||
KeyRecord k = new KeyRecord(key);
|
||||
if (!records.contains(k)){
|
||||
boolean result = records.add(k);
|
||||
Collections.sort(records);
|
||||
Collections.sort(records, comparator);
|
||||
return result;
|
||||
} else {
|
||||
k = (KeyRecord) records.get(records.indexOf(k));
|
||||
@@ -412,9 +552,23 @@ public class Notes {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static ArrayList<Record> getRecords(){
|
||||
return getRecords(Record.class);
|
||||
|
||||
public static boolean add( CustomRecord rec ){
|
||||
rec.ID = nextCustomID++;
|
||||
if (!records.contains(rec)){
|
||||
boolean result = records.add(rec);
|
||||
Collections.sort(records, comparator);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean remove( CustomRecord rec ){
|
||||
if (records.contains(rec)){
|
||||
records.remove(rec);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static <T extends Record> ArrayList<T> getRecords( Class<T> recordType ){
|
||||
@@ -443,23 +597,8 @@ public class Notes {
|
||||
private static final Comparator<Record> comparator = new Comparator<Record>() {
|
||||
@Override
|
||||
public int compare(Record r1, Record r2) {
|
||||
if (r1 instanceof LandmarkRecord){
|
||||
if (r2 instanceof LandmarkRecord){
|
||||
return ((LandmarkRecord) r1).landmark.ordinal() - ((LandmarkRecord) r2).landmark.ordinal();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else if (r2 instanceof LandmarkRecord){
|
||||
return 1;
|
||||
} else {
|
||||
//matches order in key display
|
||||
return Generator.Category.order(((KeyRecord)r2).key) - Generator.Category.order(((KeyRecord)r1).key);
|
||||
}
|
||||
return r1.order() - r2.order();
|
||||
}
|
||||
};
|
||||
|
||||
public static void remove( Record rec ){
|
||||
records.remove(rec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2024 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.ui;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndJournalItem;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTextInput;
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.utils.Callback;
|
||||
|
||||
//this is contained in its own class as custom notes have a lot of messy window UI logic
|
||||
public class CustomNoteButton extends IconButton {
|
||||
|
||||
public CustomNoteButton () {
|
||||
super(Icons.PLUS.get());
|
||||
|
||||
width = 11;
|
||||
height = 11;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
super.onClick();
|
||||
|
||||
//TODO we want a selection window for note type here, atm it's only plaintext notes
|
||||
Notes.CustomRecord custom = new Notes.CustomRecord(Messages.get(this, "default_title_text"), "");
|
||||
Notes.add(custom);
|
||||
refreshScene(custom);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String hoverText() {
|
||||
return Messages.get(this, "hover_text");
|
||||
}
|
||||
|
||||
public static class CustomNoteWindow extends WndJournalItem {
|
||||
|
||||
public CustomNoteWindow(Notes.CustomRecord rec) {
|
||||
super(rec.icon(), rec.title(), rec.desc());
|
||||
|
||||
RedButton title = new RedButton( Messages.get(CustomNoteWindow.class, "edit_title") ){
|
||||
@Override
|
||||
protected void onClick() {
|
||||
GameScene.show(new WndTextInput(Messages.get(CustomNoteWindow.class, "edit_title"),
|
||||
"",
|
||||
rec.title(),
|
||||
50,
|
||||
false,
|
||||
Messages.get(CustomNoteWindow.class, "confirm"),
|
||||
Messages.get(CustomNoteWindow.class, "cancel")){
|
||||
@Override
|
||||
public void onSelect(boolean positive, String text) {
|
||||
if (positive){
|
||||
rec.editText(text, rec.desc());
|
||||
refreshScene(rec);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
add(title);
|
||||
title.setRect(0, Math.min(height+2, PixelScene.uiCamera.height-50), width/2-1, 16);
|
||||
|
||||
String editBodyText = rec.desc().isEmpty() ? Messages.get(CustomNoteWindow.class, "add_text") : Messages.get(CustomNoteWindow.class, "edit_text");
|
||||
RedButton body = new RedButton(editBodyText){
|
||||
@Override
|
||||
protected void onClick() {
|
||||
GameScene.show(new WndTextInput(editBodyText,
|
||||
"",
|
||||
rec.desc(),
|
||||
500,
|
||||
true,
|
||||
Messages.get(CustomNoteWindow.class, "confirm"),
|
||||
Messages.get(CustomNoteWindow.class, "cancel")){
|
||||
@Override
|
||||
public void onSelect(boolean positive, String text) {
|
||||
if (positive){
|
||||
rec.editText(rec.title(), text);
|
||||
refreshScene(rec);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
add(body);
|
||||
body.setRect(title.right()+2, title.top(), width/2-1, 16);
|
||||
|
||||
RedButton delete = new RedButton( Messages.get(CustomNoteWindow.class, "delete") ){
|
||||
@Override
|
||||
protected void onClick() {
|
||||
GameScene.show(new WndOptions(Icons.WARNING.get(),
|
||||
Messages.get(CustomNoteWindow.class, "delete"),
|
||||
Messages.get(CustomNoteWindow.class, "delete_warn"),
|
||||
Messages.get(CustomNoteWindow.class, "confirm"),
|
||||
Messages.get(CustomNoteWindow.class, "cancel")){
|
||||
@Override
|
||||
protected void onSelect(int index) {
|
||||
if (index == 0){
|
||||
Notes.remove(rec);
|
||||
refreshScene(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
add(delete);
|
||||
delete.setRect(0, title.bottom()+1, width, 16);
|
||||
|
||||
resize(width, (int)delete.bottom());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void refreshScene(Notes.CustomRecord recToShow){
|
||||
if (recToShow == null){
|
||||
ShatteredPixelDungeon.seamlessResetScene();
|
||||
} else {
|
||||
ShatteredPixelDungeon.seamlessResetScene(new Game.SceneChangeCallback() {
|
||||
@Override
|
||||
public void beforeCreate() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCreate() {
|
||||
Game.runOnRenderThread(new Callback() {
|
||||
@Override
|
||||
public void call() {
|
||||
ShatteredPixelDungeon.scene().addToFront(new CustomNoteWindow(recToShow));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.tiles.TerrainFeaturesTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.CustomNoteButton;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickRecipe;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
|
||||
@@ -424,6 +425,7 @@ public class WndJournal extends WndTabbed {
|
||||
private static class NotesTab extends Component {
|
||||
|
||||
private ScrollingGridPane grid;
|
||||
private CustomNoteButton custom;
|
||||
|
||||
@Override
|
||||
protected void createChildren() {
|
||||
@@ -443,6 +445,33 @@ public class WndJournal extends WndTabbed {
|
||||
|
||||
grid.addHeader(Messages.get(this, "desc"), 6, true);
|
||||
|
||||
ArrayList<Notes.CustomRecord> customRecs = Notes.getRecords(Notes.CustomRecord.class);
|
||||
|
||||
if (!customRecs.isEmpty()){
|
||||
grid.addHeader("_" + Messages.get(this, "custom_notes") + "_");
|
||||
|
||||
for (Notes.CustomRecord rec : customRecs){
|
||||
ScrollingGridPane.GridItem gridItem = new ScrollingGridPane.GridItem(rec.icon()){
|
||||
@Override
|
||||
public boolean onClick(float x, float y) {
|
||||
if (inside(x, y)) {
|
||||
GameScene.show(new CustomNoteButton.CustomNoteWindow(rec));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Visual secondIcon = rec.secondIcon();
|
||||
if (secondIcon != null){
|
||||
gridItem.addSecondIcon( secondIcon );
|
||||
}
|
||||
|
||||
grid.addItem(gridItem);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = Statistics.deepestFloor; i > 0; i--){
|
||||
|
||||
ArrayList<Notes.Record> recs = Notes.getRecords(i);
|
||||
@@ -473,6 +502,10 @@ public class WndJournal extends WndTabbed {
|
||||
}
|
||||
}
|
||||
|
||||
custom = new CustomNoteButton();
|
||||
grid.content().add(custom);
|
||||
custom.setPos(width-custom.width()-1, 0);
|
||||
|
||||
grid.setRect(x, y, width, height);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user