RpyPlayer/src/com/annimon/everlastingsummer/ViewActivity.java

329 lines
13 KiB
Java
Raw Normal View History

2015-04-04 15:09:43 +03:00
package com.annimon.everlastingsummer;
import java.io.InputStream;
2015-04-04 15:09:43 +03:00
import java.util.HashMap;
import java.util.Map;
import android.annotation.SuppressLint;
2015-04-04 15:09:43 +03:00
import android.app.Activity;
import android.content.Intent;
2015-04-04 15:09:43 +03:00
import android.media.MediaPlayer;
import android.net.Uri;
2015-04-04 15:09:43 +03:00
import android.os.Bundle;
import android.text.*;
import android.text.style.ForegroundColorSpan;
import android.util.DisplayMetrics;
import android.view.Gravity;
2015-04-04 15:09:43 +03:00
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;
private DisplayMetrics displayMetrics;
2015-04-04 15:09:43 +03:00
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Постоянная подсветка.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// Размер экрана.
displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
2015-04-04 15:09:43 +03:00
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
String scriptpath = "";
final Intent intent = getIntent();
2015-04-04 15:09:43 +03:00
try {
InputStream stream = null;
if (intent.hasExtra(EXTRA_NAME)) {
scriptpath = PathResolver.script( intent.getStringExtra(EXTRA_NAME) );
stream = getAssets().open(scriptpath);
} else if (intent.getData() != null) {
final Uri fileUri = intent.getData();
scriptpath = fileUri.getPath();
stream = getContentResolver().openInputStream(fileUri);
} else {
Toast.makeText(this, "Нет данных для отображения", Toast.LENGTH_LONG).show();
finish();
}
Parser.parse(Lexer.tokenize( IOUtil.readContents(stream) ));
2015-04-04 15:09:43 +03:00
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 params, String position) {
2015-04-04 15:09:43 +03:00
ImageView img;
if (spriteInContainer.containsKey(whoid)) {
img = spriteInContainer.get(whoid);
} else {
img = new ImageView(this);
spriteInContainer.put(whoid, img);
}
final FrameLayout.LayoutParams flp = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.MATCH_PARENT);
setSpritePosition(img, flp, position);
final String path = PathResolver.sprite(whoid, params);
2015-04-04 15:09:43 +03:00
try {
img.setImageBitmap(IOUtil.readBitmap(path));
container.addView(img, flp);
2015-04-04 15:09:43 +03:00
} catch (Exception ioe) {}
}
public void hideSprite(String whoid) {
if (!spriteInContainer.containsKey(whoid)) return;
final ImageView img = spriteInContainer.get(whoid);
spriteInContainer.remove(img);
container.removeView(img);
}
@SuppressLint("RtlHardcoded")
private void setSpritePosition(ImageView img, FrameLayout.LayoutParams params, String position) {
// Позиционирование спрайта. fleft, left, cleft, center, cright, right, fright
final int width = displayMetrics.widthPixels;
if (TextUtils.isEmpty(position) || position.equals("center")) {
params.setMargins(0, 0, 0, 0);
params.gravity = Gravity.CENTER_HORIZONTAL;
} else if (position.equals("left")) {
params.setMargins(0, 0, width/2, 0);
params.gravity = Gravity.LEFT;
} else if (position.equals("cleft")) {
params.setMargins(0, 0, width/3, 0);
params.gravity = Gravity.LEFT;
} else if (position.equals("right")) {
params.setMargins(width/2, 0, 0, 0);
params.gravity = Gravity.RIGHT;
} else if (position.equals("cright")) {
params.setMargins(width/3, 0, 0, 0);
params.gravity = Gravity.RIGHT;
} else if (position.equals("fleft")) {
params.setMargins(0, 0, 0, 0);
params.gravity = Gravity.LEFT;
img.setScaleType(ImageView.ScaleType.FIT_START);
} else if (position.equals("fright")) {
params.setMargins(0, 0, 0, 0);
params.gravity = Gravity.RIGHT;
img.setScaleType(ImageView.ScaleType.FIT_END);
}
}
2015-04-04 15:09:43 +03:00
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.replaceAll("\\{w.*?\\}", "");
2015-04-04 15:09:43 +03:00
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;
}
}
}