266 lines
10 KiB
Java
266 lines
10 KiB
Java
|
package com.annimon.everlastingsummer;
|
|||
|
|
|||
|
import java.util.HashMap;
|
|||
|
import java.util.Map;
|
|||
|
import android.app.Activity;
|
|||
|
import android.media.MediaPlayer;
|
|||
|
import android.os.Bundle;
|
|||
|
import android.text.*;
|
|||
|
import android.text.style.ForegroundColorSpan;
|
|||
|
import android.view.View;
|
|||
|
import android.view.WindowManager;
|
|||
|
import android.widget.FrameLayout;
|
|||
|
import android.widget.ImageView;
|
|||
|
import android.widget.TextView;
|
|||
|
import android.widget.Toast;
|
|||
|
|
|||
|
/**
|
|||
|
* Экран воспроизведения rpy-сценария.
|
|||
|
* @author aNNiMON
|
|||
|
*/
|
|||
|
public final class ViewActivity extends Activity {
|
|||
|
|
|||
|
public static final String EXTRA_NAME = "name";
|
|||
|
private static final FadeInfo NO_FADE = new FadeInfo(false, false, 0);
|
|||
|
private static ViewActivity instance;
|
|||
|
|
|||
|
public static ViewActivity getInstance() {
|
|||
|
return instance;
|
|||
|
}
|
|||
|
|
|||
|
private ImageView background;
|
|||
|
private FrameLayout container;
|
|||
|
private TextView textview;
|
|||
|
private MediaPlayer musicPlayer, soundPlayer;
|
|||
|
|
|||
|
private Map<String, Person> names;
|
|||
|
private Map<String, ImageView> spriteInContainer;
|
|||
|
|
|||
|
@Override
|
|||
|
protected void onCreate(Bundle savedInstanceState) {
|
|||
|
super.onCreate(savedInstanceState);
|
|||
|
|
|||
|
// Постоянная подсветка.
|
|||
|
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
|
|||
|
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|||
|
|
|||
|
setContentView(R.layout.main);
|
|||
|
instance = this;
|
|||
|
|
|||
|
background = (ImageView) findViewById(R.id.background);
|
|||
|
container = (FrameLayout) findViewById(R.id.container);
|
|||
|
textview = (TextView) findViewById(R.id.text);
|
|||
|
|
|||
|
background.setOnClickListener(new View.OnClickListener() {
|
|||
|
@Override
|
|||
|
public void onClick(View v) {
|
|||
|
Parser.getInstance().next();
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
spriteInContainer = new HashMap<String, ImageView>();
|
|||
|
|
|||
|
// Маппинг <короткое_имя, имя/цвет>
|
|||
|
names = new HashMap<String, Person>();
|
|||
|
// https://github.com/yakui-lover/eroge-dopil/blob/master/media.rpy#L365
|
|||
|
names.put("me", new Person("Семён", 0xFFE1DD7D));
|
|||
|
names.put("un", new Person("Лена", 0xFFB956FF)); // night 0xFFAA64D9, sunset: 0xFFB956FF, day: 0xFFB956FF, prolog: 0xFFB956FF
|
|||
|
names.put("dv", new Person("Алиса", 0xFFFFAA00)); // night 0xFFD28B10, sunset: 0xFFFFAA00, day: 0xFFFFAA00, prolog: 0xFFFFAA00
|
|||
|
names.put("sl", new Person("Славя", 0xFFFFD200)); // night 0xFFD6B000, sunset: 0xFFFFD200, day: 0xFFFFD200, prolog: 0xFFFFD200
|
|||
|
names.put("us", new Person("Ульяна", 0xFFFF3200)); // night 0xFFEA3700, sunset: 0xFFFF3200, day: 0xFFFF3200, prolog: 0xFFFF3200
|
|||
|
names.put("mt", new Person("Ольга Дмитриевна", 0xFF00EA32)); // night 0xFF00B627, sunset: 0xFF00EA32, day: 0xFF00EA32, prolog: 0xFF00EA32
|
|||
|
names.put("cs", new Person("Виола", 0xFFA5A5FF)); // night 0xFF8686E6, sunset: 0xFFA5A5FF, day: 0xFFA5A5FF, prolog: 0xFFA5A5FF
|
|||
|
names.put("mz", new Person("Женя", 0xFF4A86FF)); // night 0xFF5481DB, sunset: 0xFF72A0FF, day: 0xFF4A86FF, prolog: 0xFF4A86FF
|
|||
|
names.put("mi", new Person("Мику", 0xFF00DEFF)); // night 0xFF00B4CF, sunset: 0xFF00FBFF, day: 0xFF00DEFF, prolog: 0xFF00DEFF
|
|||
|
names.put("uv", new Person("Юля", 0xFF4EFF00)); // night 0xFF40D000, sunset: 0xFF4EFF00, day: 0xFF4EFF00, prolog: 0xFF4EFF00
|
|||
|
names.put("lk", new Person("Луркмор-кун", 0xFFFF8080));
|
|||
|
names.put("sh", new Person("Шурик", 0xFFFFF226)); // night 0xFFCDC212, sunset: 0xFFFFF226, day: 0xFFFFF226, prolog: 0xFFFFF226
|
|||
|
names.put("el", new Person("Электроник", 0xFFFFFF00)); // night 0xFFCDCD00, sunset: 0xFFFFFF00, day: 0xFFFFFF00, prolog: 0xFFFFFF00
|
|||
|
names.put("pi", new Person("Пионер", 0xFFE60101)); // night 0xFFE60000, sunset: 0xFFE60000, day: 0xFFE60101, prolog: 0xFFE60000
|
|||
|
|
|||
|
names.put("dy", new Person("Голос из динамика", 0xFFC0C0C0));
|
|||
|
names.put("voice", new Person("Голос", 0xFFE1DD7D));
|
|||
|
names.put("voices", new Person("Голоса", 0xFFC0C0C0));
|
|||
|
names.put("message", new Person("Сообщение", 0xFFC0C0C0));
|
|||
|
names.put("all", new Person("Пионеры", 0xFFED4444)); // night 0xFFE33A3A, sunset: 0xFFE33A3A, day: 0xFFED4444, prolog: 0xFFE33A3A
|
|||
|
names.put("kids", new Person("Малышня", 0xFFEB7883));
|
|||
|
names.put("dreamgirl", new Person("...", 0xFFC0C0C0));
|
|||
|
names.put("bush", new Person("Голос", 0xFFC0C0C0));
|
|||
|
names.put("FIXME_voice", new Person("Голос", 0xFFC0C0C0));
|
|||
|
names.put("odn", new Person("Одногруппник", 0xFFC0C0C0));
|
|||
|
names.put("mt_voice", new Person("Голос", 0xFF00EA32)); // night 0xFF00B627, sunset: 0xFF00EA32, day: 0xFF00EA32, prolog: 0xFF00EA32
|
|||
|
|
|||
|
final String name = getIntent().getStringExtra(EXTRA_NAME);
|
|||
|
final String scriptpath = PathResolver.script(name);
|
|||
|
try {
|
|||
|
Parser.parse(Lexer.tokenize( IOUtil.readContents(getAssets().open(scriptpath)) ));
|
|||
|
Parser.getInstance().next();
|
|||
|
} catch (Exception ex) {
|
|||
|
Toast.makeText(this, "Ошибка при открытии файла " + scriptpath, Toast.LENGTH_LONG).show();
|
|||
|
finish();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
@Override
|
|||
|
protected void onPause() {
|
|||
|
stopMusic(NO_FADE);
|
|||
|
stopSound(NO_FADE);
|
|||
|
super.onPause();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void windowShow() {
|
|||
|
if (textview.getVisibility() != View.VISIBLE)
|
|||
|
textview.setVisibility(View.VISIBLE);
|
|||
|
}
|
|||
|
|
|||
|
public void windowHide() {
|
|||
|
if (textview.getVisibility() != View.INVISIBLE)
|
|||
|
textview.setVisibility(View.INVISIBLE);
|
|||
|
}
|
|||
|
|
|||
|
public void background(String type, String name, String effect) {
|
|||
|
spritesClear();
|
|||
|
if (name.equalsIgnoreCase("black")) background.setImageResource(android.R.color.black);
|
|||
|
else if (name.equalsIgnoreCase("white")) background.setImageResource(android.R.color.white);
|
|||
|
else {
|
|||
|
try {
|
|||
|
background.setImageBitmap(IOUtil.readBitmap(PathResolver.background(type, name)));
|
|||
|
} catch (Exception ioe) {
|
|||
|
background.setImageResource(android.R.color.black);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void spritesClear() {
|
|||
|
container.removeAllViews();
|
|||
|
spriteInContainer.clear();
|
|||
|
}
|
|||
|
|
|||
|
public void sprite(String whoid, String emotion, String cloth, String distance, String position) {
|
|||
|
ImageView img;
|
|||
|
if (spriteInContainer.containsKey(whoid)) {
|
|||
|
img = spriteInContainer.get(whoid);
|
|||
|
} else {
|
|||
|
img = new ImageView(this);
|
|||
|
spriteInContainer.put(whoid, img);
|
|||
|
}
|
|||
|
final String path = PathResolver.sprite(whoid, emotion, cloth, distance);;
|
|||
|
try {
|
|||
|
img.setImageBitmap(IOUtil.readBitmap(path));
|
|||
|
container.addView(img);
|
|||
|
} catch (Exception ioe) {}
|
|||
|
}
|
|||
|
|
|||
|
public void pause(final long duration) {
|
|||
|
text("");
|
|||
|
new Thread(new Runnable() {
|
|||
|
@Override
|
|||
|
public void run() {
|
|||
|
try {
|
|||
|
Thread.sleep(duration);
|
|||
|
} catch (InterruptedException e) { }
|
|||
|
runOnUiThread(nextCommandRunnable);
|
|||
|
}
|
|||
|
}).start();
|
|||
|
}
|
|||
|
|
|||
|
public void text(String text) {
|
|||
|
if (TextUtils.isEmpty(text)) windowHide();
|
|||
|
else {
|
|||
|
windowShow();
|
|||
|
textview.setText(formatString(text));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void text(String whoid, String text) {
|
|||
|
if (whoid.equalsIgnoreCase("th")) text("~ " + text + " ~");
|
|||
|
else if (!names.containsKey(whoid)) text(text);
|
|||
|
else {
|
|||
|
windowShow();
|
|||
|
final Person person = names.get(whoid);
|
|||
|
final String who = person.name;
|
|||
|
Spannable spannable = formatString(who + "\n" + text);
|
|||
|
spannable.setSpan(new ForegroundColorSpan(person.color), 0, who.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|||
|
textview.setText(spannable);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private Spannable formatString(String text) {
|
|||
|
String edited = text.replace("{w}", "");
|
|||
|
final char[] codes = {'b','i','s','u'};
|
|||
|
boolean html = false;
|
|||
|
for (int i = 0; i < codes.length; i++) {
|
|||
|
final char ch = codes[i];
|
|||
|
if (edited.contains("{"+ch+"}")) {
|
|||
|
edited = edited.replace("{"+ch+"}", "<"+ch+">");
|
|||
|
edited = edited.replace("{/"+ch+"}", "</"+ch+">");
|
|||
|
html = true;
|
|||
|
}
|
|||
|
}
|
|||
|
return new SpannableString(html ? Html.fromHtml(edited) : edited);
|
|||
|
}
|
|||
|
|
|||
|
public void music(String name, FadeInfo fade) {
|
|||
|
try {
|
|||
|
stopMusic(fade);
|
|||
|
musicPlayer = new MediaPlayer();
|
|||
|
musicPlayer.setDataSource( IOUtil.getFD(PathResolver.music(name)) );
|
|||
|
musicPlayer.prepare();
|
|||
|
musicPlayer.setVolume(1f, 1f);
|
|||
|
musicPlayer.setLooping(true);
|
|||
|
musicPlayer.start();
|
|||
|
} catch (Exception e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void stopMusic(FadeInfo fade) {
|
|||
|
if (musicPlayer == null) return;
|
|||
|
if (musicPlayer.isPlaying()) {
|
|||
|
musicPlayer.stop();
|
|||
|
musicPlayer.release();
|
|||
|
}
|
|||
|
musicPlayer = null;
|
|||
|
}
|
|||
|
|
|||
|
public void sound(String name, boolean loop, FadeInfo fade) {
|
|||
|
try {
|
|||
|
stopSound(fade);
|
|||
|
soundPlayer = new MediaPlayer();
|
|||
|
soundPlayer.setDataSource( IOUtil.getFD(PathResolver.sound(name)) );
|
|||
|
soundPlayer.prepare();
|
|||
|
soundPlayer.setVolume(1f, 1f);
|
|||
|
soundPlayer.setLooping(loop);
|
|||
|
soundPlayer.start();
|
|||
|
} catch (Exception e) {
|
|||
|
e.printStackTrace();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void stopSound(FadeInfo fade) {
|
|||
|
if (soundPlayer == null) return;
|
|||
|
if (soundPlayer.isPlaying()) {
|
|||
|
soundPlayer.stop();
|
|||
|
soundPlayer.release();
|
|||
|
}
|
|||
|
soundPlayer = null;
|
|||
|
}
|
|||
|
|
|||
|
private final Runnable nextCommandRunnable = new Runnable() {
|
|||
|
@Override
|
|||
|
public void run() {
|
|||
|
Parser.getInstance().next();
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
private class Person {
|
|||
|
String name;
|
|||
|
int color;
|
|||
|
Person(String fullName, int color) {
|
|||
|
this.name = fullName;
|
|||
|
this.color = color;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|