v0.7.5b: adjusted text rendering to always occur on the render thread

This commit is contained in:
Evan Debenham 2019-10-08 14:29:50 -04:00
parent d7815b7739
commit bbee1a1372
11 changed files with 261 additions and 145 deletions

View File

@ -32,6 +32,7 @@ import com.watabou.input.InputHandler;
import com.watabou.input.KeyEvent;
import com.watabou.noosa.audio.Music;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Callback;
import com.watabou.utils.PlatformSupport;
import com.watabou.utils.Reflection;
@ -245,6 +246,15 @@ public class Game implements ApplicationListener {
Gdx.app.error("GAME", sw.toString());
}
public static void runOnRenderThread(Callback c){
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
c.call();
}
});
}
public static void vibrate( int milliseconds ) {
Gdx.input.vibrate(milliseconds);
}

View File

@ -127,6 +127,7 @@ import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.GameMath;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
@ -661,7 +662,12 @@ public class Hero extends Char {
Heap heap = Dungeon.level.heaps.get( dst );
if (heap != null && heap.type == Type.FOR_SALE && heap.size() == 1) {
GameScene.show( new WndTradeItem( heap, true ) );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndTradeItem( heap, true ) );
}
});
}
return false;
@ -876,7 +882,12 @@ public class Hero extends Char {
if (Dungeon.depth == 1) {
if (belongings.getItem( Amulet.class ) == null) {
GameScene.show( new WndMessage( Messages.get(this, "leave") ) );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndMessage( Messages.get(this, "leave") ) );
}
});
ready();
} else {
Badges.silentValidateHappyEnd();
@ -1425,7 +1436,13 @@ public class Hero extends Char {
} else {
Dungeon.deleteGame( GamesInProgress.curSlot, false );
GameScene.show( new WndResurrect( ankh, cause ) );
final Ankh finalAnkh = ankh;
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndResurrect( finalAnkh, cause ) );
}
});
}
}

View File

@ -43,8 +43,10 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBlacksmith;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
import java.util.ArrayList;
@ -70,24 +72,29 @@ public class Blacksmith extends NPC {
if (!Quest.given) {
GameScene.show( new WndQuest( this,
Quest.alternative ? Messages.get(this, "blood_1") : Messages.get(this, "gold_1") ) {
Game.runOnRenderThread(new Callback() {
@Override
public void onBackPressed() {
super.onBackPressed();
Quest.given = true;
Quest.completed = false;
Pickaxe pick = new Pickaxe();
if (pick.doPickUp( Dungeon.hero )) {
GLog.i( Messages.get(Dungeon.hero, "you_now_have", pick.name() ));
} else {
Dungeon.level.drop( pick, Dungeon.hero.pos ).sprite.drop();
}
public void call() {
GameScene.show( new WndQuest( Blacksmith.this,
Quest.alternative ? Messages.get(Blacksmith.this, "blood_1") : Messages.get(Blacksmith.this, "gold_1") ) {
@Override
public void onBackPressed() {
super.onBackPressed();
Quest.given = true;
Quest.completed = false;
Pickaxe pick = new Pickaxe();
if (pick.doPickUp( Dungeon.hero )) {
GLog.i( Messages.get(Dungeon.hero, "you_now_have", pick.name() ));
} else {
Dungeon.level.drop( pick, Dungeon.hero.pos ).sprite.drop();
}
}
} );
}
} );
});
Notes.add( Notes.Landmark.TROLL );
@ -133,7 +140,12 @@ public class Blacksmith extends NPC {
}
} else if (!Quest.reforged) {
GameScene.show( new WndBlacksmith( this, Dungeon.hero ) );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndBlacksmith( Blacksmith.this, Dungeon.hero ) );
}
});
} else {

View File

@ -49,8 +49,10 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.GhostSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndSadGhost;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
import com.watabou.utils.Reflection;
@ -114,20 +116,30 @@ public class Ghost extends NPC {
if (Quest.given) {
if (Quest.weapon != null) {
if (Quest.processed) {
GameScene.show(new WndSadGhost(this, Quest.type));
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show(new WndSadGhost(Ghost.this, Quest.type));
}
});
} else {
switch (Quest.type) {
case 1:
default:
GameScene.show(new WndQuest(this, Messages.get(this, "rat_2")));
break;
case 2:
GameScene.show(new WndQuest(this, Messages.get(this, "gnoll_2")));
break;
case 3:
GameScene.show(new WndQuest(this, Messages.get(this, "crab_2")));
break;
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
switch (Quest.type) {
case 1:
default:
GameScene.show(new WndQuest(Ghost.this, Messages.get(Ghost.this, "rat_2")));
break;
case 2:
GameScene.show(new WndQuest(Ghost.this, Messages.get(Ghost.this, "gnoll_2")));
break;
case 3:
GameScene.show(new WndQuest(Ghost.this, Messages.get(Ghost.this, "crab_2")));
break;
}
}
});
int newPos = -1;
for (int i = 0; i < 10; i++) {
@ -165,9 +177,14 @@ public class Ghost extends NPC {
if (questBoss.pos != -1) {
GameScene.add(questBoss);
GameScene.show( new WndQuest( this, txt_quest ) );
Quest.given = true;
Notes.add( Notes.Landmark.GHOST );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndQuest( Ghost.this, txt_quest ) );
}
});
}
}

View File

@ -37,7 +37,9 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ImpSprite;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndImp;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.watabou.noosa.Game;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
@ -94,7 +96,12 @@ public class Imp extends NPC {
DwarfToken tokens = Dungeon.hero.belongings.getItem( DwarfToken.class );
if (tokens != null && (tokens.quantity() >= 8 || (!Quest.alternative && tokens.quantity() >= 6))) {
GameScene.show( new WndImp( this, tokens ) );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndImp( Imp.this, tokens ) );
}
});
} else {
tell( Quest.alternative ?
Messages.get(this, "monks_2", Dungeon.hero.givenName())
@ -113,8 +120,12 @@ public class Imp extends NPC {
}
private void tell( String text ) {
GameScene.show(
new WndQuest( this, text ));
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndQuest( Imp.this, text ));
}
});
}
public void flee() {

View File

@ -32,6 +32,8 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ShopkeeperSprite;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTradeItem;
import com.watabou.noosa.Game;
import com.watabou.utils.Callback;
public class Shopkeeper extends NPC {
@ -100,7 +102,12 @@ public class Shopkeeper extends NPC {
@Override
public boolean interact() {
sell();
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
sell();
}
});
return false;
}
}

View File

@ -42,7 +42,9 @@ import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.WandmakerSprite;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndQuest;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndWandmaker;
import com.watabou.noosa.Game;
import com.watabou.utils.Bundle;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
import java.util.ArrayList;
@ -100,11 +102,16 @@ public class Wandmaker extends NPC {
}
if (item != null) {
GameScene.show( new WndWandmaker( this, item ) );
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show( new WndWandmaker( Wandmaker.this, item ) );
}
});
} else {
String msg = "";
String msg;
switch(Quest.type){
case 1:
case 1: default:
msg = Messages.get(this, "reminder_dust", Dungeon.hero.givenName());
break;
case 2:
@ -114,7 +121,12 @@ public class Wandmaker extends NPC {
msg = Messages.get(this, "reminder_berry", Dungeon.hero.givenName());
break;
}
GameScene.show(new WndQuest(this, msg));
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show(new WndQuest(Wandmaker.this, msg));
}
});
}
} else {
@ -151,14 +163,19 @@ public class Wandmaker extends NPC {
}
msg2 += Messages.get(this, "intro_2");
final String msg2final = msg2;
final NPC wandmaker = this;
GameScene.show(new WndQuest(wandmaker, msg1){
final String msg1Final = msg1;
final String msg2Final = msg2;
Game.runOnRenderThread(new Callback() {
@Override
public void hide() {
super.hide();
GameScene.show(new WndQuest(wandmaker, msg2final));
public void call() {
GameScene.show(new WndQuest(Wandmaker.this, msg1Final){
@Override
public void hide() {
super.hide();
GameScene.show(new WndQuest(Wandmaker.this, msg2Final));
}
});
}
});

View File

@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.RenderedText;
import com.watabou.utils.Callback;
import com.watabou.utils.SparseArray;
import java.util.ArrayList;
@ -40,8 +41,6 @@ public class FloatingText extends RenderedText {
private int key = -1;
private float cameraZoom = -1;
private static final SparseArray<ArrayList<FloatingText>> stacks = new SparseArray<>();
public FloatingText() {
@ -82,13 +81,9 @@ public class FloatingText extends RenderedText {
public void reset( float x, float y, String text, int color ) {
revive();
if (cameraZoom != Camera.main.zoom) {
cameraZoom = Camera.main.zoom;
PixelScene.chooseFont( 9, cameraZoom );
size( 9 * (int)cameraZoom);
scale.set( 1 /cameraZoom );
}
size( 9 * PixelScene.defaultZoom);
scale.set( 1 / (float)PixelScene.defaultZoom );
text( text );
hardlight( color );
@ -102,18 +97,28 @@ public class FloatingText extends RenderedText {
/* STATIC METHODS */
public static void show( float x, float y, String text, int color ) {
FloatingText txt = GameScene.status();
if (txt != null){
txt.reset(x, y, text, color);
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
FloatingText txt = GameScene.status();
if (txt != null){
txt.reset(x, y, text, color);
}
}
});
}
public static void show( float x, float y, int key, String text, int color ) {
FloatingText txt = GameScene.status();
if (txt != null) {
txt.reset(x, y, text, color);
push(txt, key);
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
FloatingText txt = GameScene.status();
if (txt != null){
txt.reset(x, y, text, color);
push(txt, key);
}
}
});
}
private static void push( FloatingText txt, int key ) {

View File

@ -44,6 +44,7 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Callback;
import com.watabou.utils.Random;
public class Chasm {
@ -51,20 +52,25 @@ public class Chasm {
public static boolean jumpConfirmed = false;
public static void heroJump( final Hero hero ) {
GameScene.show(
new WndOptions( Messages.get(Chasm.class, "chasm"),
Messages.get(Chasm.class, "jump"),
Messages.get(Chasm.class, "yes"),
Messages.get(Chasm.class, "no") ) {
@Override
protected void onSelect( int index ) {
if (index == 0) {
jumpConfirmed = true;
hero.resume();
}
}
Game.runOnRenderThread(new Callback() {
@Override
public void call() {
GameScene.show(
new WndOptions( Messages.get(Chasm.class, "chasm"),
Messages.get(Chasm.class, "jump"),
Messages.get(Chasm.class, "yes"),
Messages.get(Chasm.class, "no") ) {
@Override
protected void onSelect( int index ) {
if (index == 0) {
jumpConfirmed = true;
hero.resume();
}
}
}
);
}
);
});
}
public static void heroFall( int pos ) {

View File

@ -536,6 +536,8 @@ public class GameScene extends PixelScene {
if (Runtime.getRuntime().availableProcessors() == 1) {
actorThread.setPriority(Thread.NORM_PRIORITY - 1);
}
actorThread.setName("SHPD Actor Thread");
Thread.currentThread().setName("SHPD Render Thread");
actorThread.start();
} else {
synchronized (actorThread) {

View File

@ -47,7 +47,82 @@ public class GameLog extends Component implements Signal.Listener<String> {
recreateLines();
}
private static ArrayList<String> textsToAdd = new ArrayList<>();
@Override
public synchronized void update() {
for (String text : textsToAdd){
if (length != entries.size()){
clear();
recreateLines();
}
int color = CharSprite.DEFAULT;
if (text.startsWith( GLog.POSITIVE )) {
text = text.substring( GLog.POSITIVE.length() );
color = CharSprite.POSITIVE;
} else
if (text.startsWith( GLog.NEGATIVE )) {
text = text.substring( GLog.NEGATIVE.length() );
color = CharSprite.NEGATIVE;
} else
if (text.startsWith( GLog.WARNING )) {
text = text.substring( GLog.WARNING.length() );
color = CharSprite.WARNING;
} else
if (text.startsWith( GLog.HIGHLIGHT )) {
text = text.substring( GLog.HIGHLIGHT.length() );
color = CharSprite.NEUTRAL;
}
if (lastEntry != null && color == lastColor && lastEntry.nLines < MAX_LINES) {
String lastMessage = lastEntry.text();
lastEntry.text( lastMessage.length() == 0 ? text : lastMessage + " " + text );
entries.get( entries.size() - 1 ).text = lastEntry.text();
} else {
lastEntry = PixelScene.renderMultiline( text, 6 );
lastEntry.hardlight( color );
lastColor = color;
add( lastEntry );
entries.add( new Entry( text, color ) );
}
if (length > 0) {
int nLines;
do {
nLines = 0;
for (int i = 0; i < length-1; i++) {
nLines += ((RenderedTextMultiline) members.get(i)).nLines;
}
if (nLines > MAX_LINES) {
RenderedTextMultiline r = ((RenderedTextMultiline) members.get(0));
remove(r);
r.destroy();
entries.remove( 0 );
}
} while (nLines > MAX_LINES);
if (entries.isEmpty()) {
lastEntry = null;
}
}
}
if (!textsToAdd.isEmpty()){
layout();
textsToAdd.clear();
}
super.update();
}
private synchronized void recreateLines() {
for (Entry entry : entries) {
lastEntry = PixelScene.renderMultiline( entry.text, 6 );
@ -62,70 +137,7 @@ public class GameLog extends Component implements Signal.Listener<String> {
@Override
public synchronized boolean onSignal( String text ) {
if (length != entries.size()){
clear();
recreateLines();
}
int color = CharSprite.DEFAULT;
if (text.startsWith( GLog.POSITIVE )) {
text = text.substring( GLog.POSITIVE.length() );
color = CharSprite.POSITIVE;
} else
if (text.startsWith( GLog.NEGATIVE )) {
text = text.substring( GLog.NEGATIVE.length() );
color = CharSprite.NEGATIVE;
} else
if (text.startsWith( GLog.WARNING )) {
text = text.substring( GLog.WARNING.length() );
color = CharSprite.WARNING;
} else
if (text.startsWith( GLog.HIGHLIGHT )) {
text = text.substring( GLog.HIGHLIGHT.length() );
color = CharSprite.NEUTRAL;
}
if (lastEntry != null && color == lastColor && lastEntry.nLines < MAX_LINES) {
String lastMessage = lastEntry.text();
lastEntry.text( lastMessage.length() == 0 ? text : lastMessage + " " + text );
entries.get( entries.size() - 1 ).text = lastEntry.text();
} else {
lastEntry = PixelScene.renderMultiline( text, 6 );
lastEntry.hardlight( color );
lastColor = color;
add( lastEntry );
entries.add( new Entry( text, color ) );
}
if (length > 0) {
int nLines;
do {
nLines = 0;
for (int i = 0; i < length-1; i++) {
nLines += ((RenderedTextMultiline) members.get(i)).nLines;
}
if (nLines > MAX_LINES) {
RenderedTextMultiline r = ((RenderedTextMultiline) members.get(0));
remove(r);
r.destroy();
entries.remove( 0 );
}
} while (nLines > MAX_LINES);
if (entries.isEmpty()) {
lastEntry = null;
}
}
layout();
textsToAdd.add(text);
return false;
}