aboutsummaryrefslogtreecommitdiff
path: root/src/org
diff options
context:
space:
mode:
authorevgenyzinoviev <me@ch1p.com>2015-08-14 17:11:48 +0300
committerevgenyzinoviev <me@ch1p.com>2015-08-14 17:11:48 +0300
commitae0e6ec634d8ab515ae381145a89d9ce649ba082 (patch)
tree081af7274605451b6e48d20961dbcf47bdf43b93 /src/org
initial
Diffstat (limited to 'src/org')
-rwxr-xr-xsrc/org/happysanta/gd/API/API.java101
-rwxr-xr-xsrc/org/happysanta/gd/API/APIException.java9
-rw-r--r--src/org/happysanta/gd/API/DownloadFile.java144
-rw-r--r--src/org/happysanta/gd/API/DownloadHandler.java14
-rwxr-xr-xsrc/org/happysanta/gd/API/LevelsResponse.java64
-rw-r--r--src/org/happysanta/gd/API/NotificationsResponse.java76
-rw-r--r--src/org/happysanta/gd/API/Request.java143
-rw-r--r--src/org/happysanta/gd/API/Response.java26
-rwxr-xr-xsrc/org/happysanta/gd/API/ResponseHandler.java9
-rw-r--r--src/org/happysanta/gd/Callback.java7
-rwxr-xr-xsrc/org/happysanta/gd/Command.java11
-rwxr-xr-xsrc/org/happysanta/gd/CommandListener.java7
-rw-r--r--src/org/happysanta/gd/DoubleCallback.java7
-rw-r--r--src/org/happysanta/gd/FileDialog.java209
-rwxr-xr-xsrc/org/happysanta/gd/GDActivity.java1177
-rw-r--r--src/org/happysanta/gd/GDApplication.java24
-rwxr-xr-xsrc/org/happysanta/gd/Game/Bitmap.java184
-rwxr-xr-xsrc/org/happysanta/gd/Game/FPMath.java80
-rwxr-xr-xsrc/org/happysanta/gd/Game/GameView.java968
-rwxr-xr-xsrc/org/happysanta/gd/Game/Physics.java1336
-rwxr-xr-xsrc/org/happysanta/gd/Game/k.java34
-rwxr-xr-xsrc/org/happysanta/gd/Global.java21
-rwxr-xr-xsrc/org/happysanta/gd/Helpers.java309
-rw-r--r--src/org/happysanta/gd/KeyboardController.java303
-rw-r--r--src/org/happysanta/gd/Levels/InvalidTrackException.java12
-rwxr-xr-xsrc/org/happysanta/gd/Levels/Level.java245
-rw-r--r--src/org/happysanta/gd/Levels/LevelHeader.java53
-rwxr-xr-xsrc/org/happysanta/gd/Levels/Loader.java335
-rw-r--r--src/org/happysanta/gd/Levels/Reader.java52
-rwxr-xr-xsrc/org/happysanta/gd/Menu/ActionMenuElement.java141
-rw-r--r--src/org/happysanta/gd/Menu/BigTextMenuElement.java30
-rw-r--r--src/org/happysanta/gd/Menu/ClickableMenuElement.java196
-rwxr-xr-xsrc/org/happysanta/gd/Menu/DownloadLevelsMenuScreen.java222
-rwxr-xr-xsrc/org/happysanta/gd/Menu/EmptyLineMenuElement.java42
-rwxr-xr-xsrc/org/happysanta/gd/Menu/HighScoreTextMenuElement.java100
-rw-r--r--src/org/happysanta/gd/Menu/InstalledLevelsMenuScreen.java103
-rwxr-xr-xsrc/org/happysanta/gd/Menu/LevelMenuElement.java370
-rw-r--r--src/org/happysanta/gd/Menu/LevelsAdapter.java53
-rw-r--r--src/org/happysanta/gd/Menu/LevelsCountTextMenuElement.java86
-rw-r--r--src/org/happysanta/gd/Menu/LevelsMenuScreen.java429
-rwxr-xr-xsrc/org/happysanta/gd/Menu/Menu.java1554
-rw-r--r--src/org/happysanta/gd/Menu/MenuElement.java20
-rwxr-xr-xsrc/org/happysanta/gd/Menu/MenuElementOld.java32
-rwxr-xr-xsrc/org/happysanta/gd/Menu/MenuHandler.java12
-rwxr-xr-xsrc/org/happysanta/gd/Menu/MenuScreen.java277
-rw-r--r--src/org/happysanta/gd/Menu/NameInputMenuScreen.java175
-rw-r--r--src/org/happysanta/gd/Menu/OnMenuElementHighlightListener.java10
-rw-r--r--src/org/happysanta/gd/Menu/OptionsMenuElement.java301
-rwxr-xr-xsrc/org/happysanta/gd/Menu/SimpleMenuElement.java176
-rw-r--r--src/org/happysanta/gd/Menu/SimpleMenuElementNew.java77
-rwxr-xr-xsrc/org/happysanta/gd/Menu/TextMenuElement.java80
-rw-r--r--src/org/happysanta/gd/Menu/Views/LevelNameLeadingMarginSpan2.java38
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuHelmetView.java111
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuImageView.java34
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuLinearLayout.java68
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuRelativeLayout.java55
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuTextView.java73
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuTitleLinearLayout.java39
-rw-r--r--src/org/happysanta/gd/Menu/Views/MenuView.java12
-rw-r--r--src/org/happysanta/gd/Menu/Views/ObservableScrollView.java31
-rw-r--r--src/org/happysanta/gd/Settings.java215
-rw-r--r--src/org/happysanta/gd/Storage/HighScores.java152
-rw-r--r--src/org/happysanta/gd/Storage/Level.java300
-rw-r--r--src/org/happysanta/gd/Storage/LevelsDataSource.java293
-rw-r--r--src/org/happysanta/gd/Storage/LevelsManager.java503
-rw-r--r--src/org/happysanta/gd/Storage/LevelsSQLiteOpenHelper.java141
-rwxr-xr-xsrc/org/happysanta/gd/Util/HexDump.java124
-rw-r--r--src/org/happysanta/gd/WaitForNetworkConnection.java34
68 files changed, 12669 insertions, 0 deletions
diff --git a/src/org/happysanta/gd/API/API.java b/src/org/happysanta/gd/API/API.java
new file mode 100755
index 0000000..8e1ee0d
--- /dev/null
+++ b/src/org/happysanta/gd/API/API.java
@@ -0,0 +1,101 @@
+package org.happysanta.gd.API;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.message.BasicNameValuePair;
+
+import java.io.*;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.happysanta.gd.Helpers.getDeviceName;
+
+public class API {
+
+ public static final String URL = "http://gdtr.net/api.php";
+ public static final String DEBUG_URL = "http://dev.gdtr.net/api.php";
+ public static final String MRG_URL = "http://gdtr.net/mrg/%d.mrg";
+ public static final int VERSION = 2;
+
+ public static Request getLevels(int offset, int limit, LevelsSortType sort, ResponseHandler handler)
+ throws Exception {
+ List<NameValuePair> params = new LinkedList<NameValuePair>();
+ params.add(new BasicNameValuePair("sort", sort.toString()));
+ params.add(new BasicNameValuePair("offset", String.valueOf(offset)));
+ params.add(new BasicNameValuePair("limit", String.valueOf(limit)));
+
+ return new Request("getLevels", params, handler);
+ }
+
+ public static Request getNotifications(boolean installedFromAPK, ResponseHandler handler) {
+ List<NameValuePair> params = new LinkedList<NameValuePair>();
+ params.add(new BasicNameValuePair("apk", String.valueOf(installedFromAPK ? 1 : 0)));
+ return new Request("getNotifications", params, handler);
+ }
+
+ public static Request sendStats(String statsJSON, String installationID, int useCheats, ResponseHandler handler) {
+ List<NameValuePair> params = new LinkedList<NameValuePair>();
+ params.add(new BasicNameValuePair("stats", statsJSON));
+ params.add(new BasicNameValuePair("id", installationID));
+ params.add(new BasicNameValuePair("use_cheats", String.valueOf(useCheats)));
+ return new Request("sendStats", params, handler);
+ }
+
+ public static Request sendKeyboardLogs(String log, ResponseHandler handler) {
+ List<NameValuePair> params = new LinkedList<NameValuePair>();
+ params.add(new BasicNameValuePair("log", log));
+ params.add(new BasicNameValuePair("device", getDeviceName()));
+ return new Request("sendKeyboardLogs", params, handler, true);
+ }
+
+ public static DownloadFile downloadMrg(long id, FileOutputStream output, DownloadHandler handler) {
+ return new DownloadFile(String.format(MRG_URL, id), output, handler);
+ }
+
+ public static String getMrgURL(long id) {
+ return String.format(MRG_URL, id);
+ }
+
+ public static enum LevelsSortType {
+ POPULAR("popular"), TRACKS("tracks"), RECENT("recent"), OLDEST("oldest");
+
+ private final String text;
+
+ private LevelsSortType(final String text) {
+ this.text = text;
+ }
+
+ @Override
+ public String toString() {
+ return text;
+ }
+ }
+
+ public static LevelsSortType getSortTypeById(int id) {
+ switch (id) {
+ case 0:
+ return LevelsSortType.POPULAR;
+ case 1:
+ return LevelsSortType.RECENT;
+ case 2:
+ return LevelsSortType.OLDEST;
+ case 3:
+ return LevelsSortType.TRACKS;
+ }
+ return null;
+ }
+
+ public static int getIdBySortType(LevelsSortType type) {
+ switch (type) {
+ case POPULAR:
+ return 0;
+ case RECENT:
+ return 1;
+ case OLDEST:
+ return 2;
+ case TRACKS:
+ return 3;
+ }
+ return 0;
+ }
+
+}
diff --git a/src/org/happysanta/gd/API/APIException.java b/src/org/happysanta/gd/API/APIException.java
new file mode 100755
index 0000000..6cf2c14
--- /dev/null
+++ b/src/org/happysanta/gd/API/APIException.java
@@ -0,0 +1,9 @@
+package org.happysanta.gd.API;
+
+public class APIException extends java.lang.Exception {
+
+ public APIException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/org/happysanta/gd/API/DownloadFile.java b/src/org/happysanta/gd/API/DownloadFile.java
new file mode 100644
index 0000000..2920c27
--- /dev/null
+++ b/src/org/happysanta/gd/API/DownloadFile.java
@@ -0,0 +1,144 @@
+package org.happysanta.gd.API;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.PowerManager;
+import org.apache.http.HttpException;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class DownloadFile {
+
+ private String urlString;
+ private DownloadHandler handler;
+ private FileOutputStream output;
+ private AsyncDownloadTask task;
+
+ public DownloadFile(String url, FileOutputStream output) {
+ this.urlString = url;
+ this.output = output;
+ }
+
+ public DownloadFile(String url, FileOutputStream output, DownloadHandler handler) {
+ this(url, output);
+ this.handler = handler;
+ }
+
+ public void setDownloadHandler(DownloadHandler handler) {
+ this.handler = handler;
+ }
+
+ public void start() {
+ task = new AsyncDownloadTask();
+ task.execute();
+ }
+
+ public void cancel() {
+ if (task != null) {
+ task.cancel(true);
+ task = null;
+ }
+ }
+
+ protected class AsyncDownloadTask extends AsyncTask<Void, Integer, Throwable> {
+
+ private PowerManager.WakeLock lock;
+
+ @Override
+ protected Throwable doInBackground(Void... params) {
+ // OutputStream output = (FileOutputStream)params[1];
+ InputStream input = null;
+ HttpURLConnection connection = null;
+
+ try {
+ URL url = new URL(urlString);
+ connection = (HttpURLConnection) url.openConnection();
+ connection.connect();
+
+ // expect HTTP 200 OK, so we don't mistakenly save error report
+ // instead of the file
+ if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ return new HttpException("Server returned HTTP " + connection.getResponseCode()
+ + " " + connection.getResponseMessage());
+ }
+
+ // this will be useful to display download percentage
+ // might be -1: server did not report the length
+ int fileLength = connection.getContentLength();
+
+ // download the file
+ input = connection.getInputStream();
+
+ byte data[] = new byte[4096];
+ long total = 0;
+ int count;
+ while ((count = input.read(data)) != -1) {
+ // allow canceling with back button
+ if (isCancelled()) {
+ input.close();
+ return null;
+ }
+
+ total += count;
+
+ // publishing the progress....
+ if (fileLength > 0) // only if total length is known
+ publishProgress((int) (total * 100 / fileLength));
+
+ output.write(data, 0, count);
+ }
+ } catch (Exception e) {
+ return e;
+ } finally {
+ try {
+ if (output != null)
+ output.close();
+ if (input != null)
+ input.close();
+ } catch (IOException ignored) {
+ }
+
+ if (connection != null)
+ connection.disconnect();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+
+ // take CPU lock to prevent CPU from going off if the user
+ // presses the power button during download
+ PowerManager pm = (PowerManager) getGDActivity().getSystemService(Context.POWER_SERVICE);
+ lock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ getClass().getName());
+ lock.acquire();
+
+ handler.onStart();
+ }
+
+ @Override
+ protected void onProgressUpdate(Integer... progress) {
+ super.onProgressUpdate(progress);
+
+ handler.onProgress(progress[0]);
+ }
+
+ @Override
+ protected void onPostExecute(Throwable error) {
+ lock.release();
+ handler.onFinish(error);
+ }
+
+ }
+
+
+}
diff --git a/src/org/happysanta/gd/API/DownloadHandler.java b/src/org/happysanta/gd/API/DownloadHandler.java
new file mode 100644
index 0000000..ec43651
--- /dev/null
+++ b/src/org/happysanta/gd/API/DownloadHandler.java
@@ -0,0 +1,14 @@
+package org.happysanta.gd.API;
+
+/**
+ * Created by evgeny on 6/10/14.
+ */
+public interface DownloadHandler {
+
+ public abstract void onStart();
+
+ public abstract void onFinish(Throwable error);
+
+ public abstract void onProgress(int progress);
+
+} \ No newline at end of file
diff --git a/src/org/happysanta/gd/API/LevelsResponse.java b/src/org/happysanta/gd/API/LevelsResponse.java
new file mode 100755
index 0000000..b62a6e6
--- /dev/null
+++ b/src/org/happysanta/gd/API/LevelsResponse.java
@@ -0,0 +1,64 @@
+package org.happysanta.gd.API;
+
+import org.happysanta.gd.Storage.Level;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Vector;
+
+public class LevelsResponse {
+
+ protected Level levels[] = null;
+ protected int totalCount = 0;
+
+ public LevelsResponse(Response response) {
+ parse(response);
+ }
+
+ protected void parse(Response response) {
+ JSONArray json = response.getJSON();
+ try {
+ JSONObject object = json.getJSONObject(1);
+ Vector<Level> levels = new Vector<>();
+ totalCount = object.getInt("count");
+ JSONArray items = object.getJSONArray("items");
+
+ try {
+ JSONObject item;
+ JSONArray tracks;
+ for (int i = 0; i < items.length(); i++) {
+ item = items.getJSONObject(i);
+ tracks = item.getJSONArray("tracks");
+
+ levels.addElement(new Level(
+ 0,
+ item.getString("name"),
+ item.getJSONObject("author").getString("name"),
+ tracks.getInt(0),
+ tracks.getInt(1),
+ tracks.getInt(2),
+ item.getInt("added"),
+ item.getInt("size"),
+ item.getInt("id")
+ ));
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ } finally {
+ this.levels = levels.toArray(new Level[0]);
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public int getTotalCount() {
+ return totalCount;
+ }
+
+ public Level[] getLevels() {
+ return levels;
+ }
+
+}
diff --git a/src/org/happysanta/gd/API/NotificationsResponse.java b/src/org/happysanta/gd/API/NotificationsResponse.java
new file mode 100644
index 0000000..06dca09
--- /dev/null
+++ b/src/org/happysanta/gd/API/NotificationsResponse.java
@@ -0,0 +1,76 @@
+package org.happysanta.gd.API;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+public class NotificationsResponse {
+
+ private String title;
+ private String message;
+ private String url;
+ private int buttonsCount = 1;
+ private String[] buttons = new String[2];
+ private boolean empty = true;
+ private boolean isURL = false;
+
+ public NotificationsResponse(Response response) {
+ parse(response);
+ }
+
+ protected void parse(Response response) {
+ JSONArray json = response.getJSON();
+ try {
+ JSONArray jsonResponse = json.getJSONArray(1);
+ if (jsonResponse.length() > 0) {
+ JSONObject notification = jsonResponse.getJSONObject(0);
+ title = notification.getString("title");
+ message = notification.getString("message");
+ buttons[0] = notification.getString("button_ok");
+ if (notification.has("button_cancel")) {
+ buttonsCount = 2;
+ buttons[1] = notification.getString("button_cancel");
+ }
+ if (notification.has("open_url")) {
+ url = notification.getString("open_url");
+ isURL = true;
+ }
+ empty = false;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public boolean isEmpty() {
+ return empty;
+ }
+
+ public boolean hasURL() {
+ return isURL;
+ }
+
+ public String getURL() {
+ return url;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public boolean hasTwoButtons() {
+ return buttonsCount == 2;
+ }
+
+ public String getOKButton() {
+ return buttons[0];
+ }
+
+ public String getCancelButton() {
+ return buttons[1];
+ }
+
+}
diff --git a/src/org/happysanta/gd/API/Request.java b/src/org/happysanta/gd/API/Request.java
new file mode 100644
index 0000000..d8bfa6e
--- /dev/null
+++ b/src/org/happysanta/gd/API/Request.java
@@ -0,0 +1,143 @@
+package org.happysanta.gd.API;
+
+import android.os.AsyncTask;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Locale;
+
+import static org.happysanta.gd.Helpers.getAppVersion;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class Request {
+
+ // enum Method { GET, POST };
+
+ private List<NameValuePair> params;
+ private ResponseHandler handler;
+ private AsyncRequestTask task;
+ private String apiURL;
+
+ public Request(String method, List<NameValuePair> params, ResponseHandler handler, boolean useDebugURL) {
+ construct(method, params, handler, useDebugURL ? API.DEBUG_URL : API.URL);
+ }
+
+ public Request(String method, List<NameValuePair> params, ResponseHandler handler) {
+ construct(method, params, handler, API.URL);
+ }
+
+ private void construct(String method, List<NameValuePair> params, ResponseHandler handler, String apiURL) {
+ this.apiURL = apiURL;
+
+ params.add(new BasicNameValuePair("v", String.valueOf(API.VERSION)));
+ params.add(new BasicNameValuePair("method", method));
+ params.add(new BasicNameValuePair("app_version", getAppVersion()));
+ params.add(new BasicNameValuePair("app_lang", Locale.getDefault().getDisplayLanguage()));
+
+ this.params = params;
+ this.handler = handler;
+
+ go();
+ }
+
+ private void go() {
+ task = new AsyncRequestTask();
+ task.execute(apiURL);
+ }
+
+ public void cancel() {
+ if (task != null) {
+ task.cancel(true);
+ task = null;
+ }
+ }
+
+ private void onDone(String result) {
+ Response response;
+ logDebug("API.Request.onDone()");
+
+ try {
+ response = new Response(result);
+ } catch (APIException e) {
+ handler.onError(e);
+ return;
+ } catch (Exception e) {
+ // e.printStackTrace();
+ handler.onError(new APIException(result == null ? "Network error" : "JSON parsing error"));
+ return;
+ // exception = new Exception();
+ }
+
+ // handler.onResponse(response);
+
+ if (response != null)
+ handler.onResponse(response);
+ else
+ handler.onError(new APIException("JSON parsing error"));
+ }
+
+ protected class AsyncRequestTask extends AsyncTask<String, Void, String> {
+
+ @Override
+ protected String doInBackground(String... objects) {
+ String url = objects[0];
+
+ DefaultHttpClient client = new DefaultHttpClient();
+ HttpPost post = new HttpPost(url);
+ try {
+ post.setEntity(new UrlEncodedFormEntity(params));
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ return null;
+ }
+ String result = null;
+ InputStream is = null;
+
+ try {
+ HttpResponse response = client.execute(post);
+ HttpEntity entity = response.getEntity();
+ is = entity.getContent();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"), 8);
+ StringBuilder sb = new StringBuilder();
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (isCancelled()) break;
+ sb.append(line + "\n");
+ }
+ result = sb.toString();
+ } catch (java.lang.Exception e) {
+ logDebug("API request failed: " + e.getMessage());
+ // e.printStackTrace();
+ return null;
+ } finally {
+ try {
+ if (is != null) is.close();
+ } catch (IOException e) {
+ // e.printStackTrace();
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public void onPostExecute(String result) {
+ onDone(result);
+ }
+
+ }
+
+}
diff --git a/src/org/happysanta/gd/API/Response.java b/src/org/happysanta/gd/API/Response.java
new file mode 100644
index 0000000..827fae4
--- /dev/null
+++ b/src/org/happysanta/gd/API/Response.java
@@ -0,0 +1,26 @@
+package org.happysanta.gd.API;
+
+import org.happysanta.gd.API.*;
+import org.json.JSONArray;
+import org.json.JSONException;
+
+public class Response {
+
+ JSONArray jsonArray;
+
+ public Response(String result) throws JSONException, APIException {
+ jsonArray = new JSONArray(result);
+ if (!isOK()) {
+ throw new APIException(jsonArray.getString(1));
+ }
+ }
+
+ public boolean isOK() throws JSONException {
+ return jsonArray.getString(0).equals("ok");
+ }
+
+ public JSONArray getJSON() {
+ return jsonArray;
+ }
+
+}
diff --git a/src/org/happysanta/gd/API/ResponseHandler.java b/src/org/happysanta/gd/API/ResponseHandler.java
new file mode 100755
index 0000000..7b39c99
--- /dev/null
+++ b/src/org/happysanta/gd/API/ResponseHandler.java
@@ -0,0 +1,9 @@
+package org.happysanta.gd.API;
+
+public interface ResponseHandler {
+
+ public void onResponse(Response response);
+
+ public void onError(APIException error);
+
+}
diff --git a/src/org/happysanta/gd/Callback.java b/src/org/happysanta/gd/Callback.java
new file mode 100644
index 0000000..a2a2c3f
--- /dev/null
+++ b/src/org/happysanta/gd/Callback.java
@@ -0,0 +1,7 @@
+package org.happysanta.gd;
+
+public interface Callback {
+
+ public abstract void onDone(Object... objects);
+
+}
diff --git a/src/org/happysanta/gd/Command.java b/src/org/happysanta/gd/Command.java
new file mode 100755
index 0000000..821ddc9
--- /dev/null
+++ b/src/org/happysanta/gd/Command.java
@@ -0,0 +1,11 @@
+package org.happysanta.gd;
+
+public class Command {
+
+ public String title;
+
+ public Command(String title, int unused1, int unused2) {
+ this.title = title;
+ }
+
+}
diff --git a/src/org/happysanta/gd/CommandListener.java b/src/org/happysanta/gd/CommandListener.java
new file mode 100755
index 0000000..7af87e8
--- /dev/null
+++ b/src/org/happysanta/gd/CommandListener.java
@@ -0,0 +1,7 @@
+package org.happysanta.gd;
+
+public interface CommandListener {
+
+ public void commandAction(Command cmd);
+
+}
diff --git a/src/org/happysanta/gd/DoubleCallback.java b/src/org/happysanta/gd/DoubleCallback.java
new file mode 100644
index 0000000..f7d6b7e
--- /dev/null
+++ b/src/org/happysanta/gd/DoubleCallback.java
@@ -0,0 +1,7 @@
+package org.happysanta.gd;
+
+public interface DoubleCallback extends Callback {
+
+ public abstract void onFail();
+
+}
diff --git a/src/org/happysanta/gd/FileDialog.java b/src/org/happysanta/gd/FileDialog.java
new file mode 100644
index 0000000..78b0326
--- /dev/null
+++ b/src/org/happysanta/gd/FileDialog.java
@@ -0,0 +1,209 @@
+package org.happysanta.gd;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Environment;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class FileDialog {
+ private static final String PARENT_DIR = "..";
+ private final String TAG = getClass().getName();
+ private String[] fileList;
+ private File currentPath;
+
+ public interface FileSelectedListener {
+ void fileSelected(File file);
+ }
+
+ public interface DirectorySelectedListener {
+ void directorySelected(File directory);
+ }
+
+ private ListenerList<FileSelectedListener> fileListenerList = new ListenerList<FileDialog.FileSelectedListener>();
+ private ListenerList<DirectorySelectedListener> dirListenerList = new ListenerList<FileDialog.DirectorySelectedListener>();
+ private final Activity activity;
+ private boolean selectDirectoryOption = false;
+ private String fileEndsWith;
+
+ public FileDialog(Activity activity, File path, String fileEndsWith) {
+ this.activity = activity;
+ this.fileEndsWith = fileEndsWith != null ? fileEndsWith.toLowerCase() : fileEndsWith;
+ if (!path.exists()) path = Environment.getExternalStorageDirectory();
+ // logDebug("FileDialog contrustor, path = " + path);
+ loadFileList(path);
+ }
+
+ /**
+ * @return file dialog
+ */
+ public Dialog createFileDialog() {
+ Dialog dialog = null;
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+
+ builder.setTitle(currentPath.getPath());
+ if (selectDirectoryOption) {
+ builder.setPositiveButton("Select directory", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ Helpers.logDebug(currentPath.getParent());
+ // Log.d(TAG, currentPath.getPath());
+ fireDirectorySelectedEvent(currentPath);
+ }
+ });
+ }
+
+ builder.setItems(fileList, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ String fileChosen = fileList[which];
+ File chosenFile = getChosenFile(fileChosen);
+ if (chosenFile.isDirectory()) {
+ loadFileList(chosenFile);
+ dialog.cancel();
+ dialog.dismiss();
+ showDialog();
+ } else fireFileSelectedEvent(chosenFile);
+ }
+ });
+
+ dialog = builder.show();
+ return dialog;
+ }
+
+
+ public void addFileListener(FileSelectedListener listener) {
+ fileListenerList.add(listener);
+ }
+
+ public void removeFileListener(FileSelectedListener listener) {
+ fileListenerList.remove(listener);
+ }
+
+ public void setSelectDirectoryOption(boolean selectDirectoryOption) {
+ this.selectDirectoryOption = selectDirectoryOption;
+ }
+
+ public void addDirectoryListener(DirectorySelectedListener listener) {
+ dirListenerList.add(listener);
+ }
+
+ public void removeDirectoryListener(DirectorySelectedListener listener) {
+ dirListenerList.remove(listener);
+ }
+
+ /**
+ * Show file dialog
+ */
+ public void showDialog() {
+ createFileDialog().show();
+ }
+
+ private void fireFileSelectedEvent(final File file) {
+ fileListenerList.fireEvent(new ListenerList.FireHandler<FileSelectedListener>() {
+ public void fireEvent(FileSelectedListener listener) {
+ listener.fileSelected(file);
+ }
+ });
+ }
+
+ private void fireDirectorySelectedEvent(final File directory) {
+ dirListenerList.fireEvent(new ListenerList.FireHandler<DirectorySelectedListener>() {
+ public void fireEvent(DirectorySelectedListener listener) {
+ listener.directorySelected(directory);
+ }
+ });
+ }
+
+ private void loadFileList(File path) {
+ this.currentPath = path;
+
+ ArrayList<String> dirs = new ArrayList<>();
+ ArrayList<String> files = new ArrayList<>();
+ ArrayList<String> totalList = new ArrayList<>();
+
+ if (path.exists()) {
+ if (path.getParentFile() != null) dirs.add(PARENT_DIR);
+ FilenameFilter filter = new FilenameFilter() {
+ public boolean accept(File dir, String filename) {
+ File sel = new File(dir, filename);
+ if (!sel.canRead()) return false;
+ if (sel.isHidden()) return false;
+ if (selectDirectoryOption) return sel.isDirectory();
+ else {
+ boolean endsWith = fileEndsWith != null ? filename.toLowerCase().endsWith(fileEndsWith) : true;
+ return endsWith || sel.isDirectory();
+ }
+ }
+ };
+
+ File[] list = path.listFiles(filter);
+ try {
+ if (list != null && list.length > 0) {
+ for (File file : list) {
+ if (file.isDirectory())
+ dirs.add(file.getName() + "/");
+ else
+ files.add(file.getName());
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ Comparator<String> comparator = new Comparator<String>() {
+ @Override
+ public int compare(String lhs, String rhs) {
+ return lhs.compareTo(rhs);
+ }
+ };
+
+ Collections.sort(dirs, comparator);
+ Collections.sort(files, comparator);
+
+ totalList.addAll(dirs);
+ totalList.addAll(files);
+ }
+
+ fileList = totalList.toArray(new String[]{});
+ }
+
+ private File getChosenFile(String fileChosen) {
+ if (fileChosen.equals(PARENT_DIR)) return currentPath.getParentFile();
+ else return new File(currentPath, fileChosen);
+ }
+}
+
+class ListenerList<L> {
+ private List<L> listenerList = new ArrayList<L>();
+
+ public interface FireHandler<L> {
+ void fireEvent(L listener);
+ }
+
+ public void add(L listener) {
+ listenerList.add(listener);
+ }
+
+ public void fireEvent(FireHandler<L> fireHandler) {
+ List<L> copy = new ArrayList<L>(listenerList);
+ for (L l : copy) {
+ fireHandler.fireEvent(l);
+ }
+ }
+
+ public void remove(L listener) {
+ listenerList.remove(listener);
+ }
+
+ public List<L> getListenerList() {
+ return listenerList;
+ }
+} \ No newline at end of file
diff --git a/src/org/happysanta/gd/GDActivity.java b/src/org/happysanta/gd/GDActivity.java
new file mode 100755
index 0000000..88876a6
--- /dev/null
+++ b/src/org/happysanta/gd/GDActivity.java
@@ -0,0 +1,1177 @@
+package org.happysanta.gd;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Html;
+import android.view.*;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import org.happysanta.gd.API.*;
+import org.happysanta.gd.Game.*;
+import org.happysanta.gd.Levels.Loader;
+import org.happysanta.gd.Menu.Views.MenuHelmetView;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+import org.happysanta.gd.Menu.Views.MenuTitleLinearLayout;
+import org.happysanta.gd.Menu.Views.ObservableScrollView;
+import org.happysanta.gd.Storage.LevelsManager;
+import org.acra.util.Installation;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class GDActivity extends Activity implements Runnable {
+
+ public static GDActivity shared = null;
+ public static final int MENU_TITLE_LAYOUT_TOP_PADDING = 25;
+ public static final int MENU_TITLE_LAYOUT_BOTTOM_PADDING = 13;
+ public static final int MENU_TITLE_LAYOUT_X_PADDING = 30;
+ public static final int MENU_TITLE_FONT_SIZE = 30;
+ public static final int GAME_MENU_BUTTON_LAYOUT_WIDTH = 40;
+ public static final int GAME_MENU_BUTTON_LAYOUT_HEIGHT = 56;
+
+ private static final long IMAGES_DELAY = 1000L;
+ private static final long IMAGES_DELAY_DEBUG = 100L;
+
+ public int m_longI = 0;
+
+ private boolean wasPaused = false;
+ private boolean wasStarted = false;
+ private boolean wasDestroyed = false;
+ private boolean restartingStarted = false;
+ public boolean alive = false;
+ public boolean m_cZ = true;
+ private boolean menuShown = false;
+ public boolean fullResetting = false;
+ public boolean exiting = false;
+
+ public GameView gameView = null;
+ // public MenuView menuView = null;
+ public Loader levelLoader;
+ public Physics physEngine;
+ public org.happysanta.gd.Menu.Menu menu;
+ public boolean m_caseZ;
+ public int m_nullI;
+ public long m_forJ;
+ // public long seconds;
+ public long startedTime = 0;
+ public long finishedTime = 0;
+ public long pausedTime = 0;
+ public long pausedTimeStarted = 0;
+ public long m_byteJ;
+ public boolean inited = false;
+ public boolean m_ifZ;
+ private Thread thread;
+ private MenuImageView menuBtn;
+ public MenuTitleLinearLayout titleLayout;
+ public ObservableScrollView scrollView;
+ private FrameLayout frame;
+ private MenuLinearLayout menuLayout;
+ private KeyboardController keyboardController;
+ private boolean isNormalAndroid = true;
+ private boolean buttonCoordsCalculated = false;
+ public TextView menuTitleTextView;
+ private boolean menuReady = false;
+ private ArrayList<Command> commands = new ArrayList<Command>();
+ private MenuLinearLayout keyboardLayout;
+ private MenuTextView portedTextView;
+ private int buttonHeight = 60;
+ public LevelsManager levelsManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ shared = this;
+
+ if (Helpers.isSDK10OrLower()) {
+ isNormalAndroid = false;
+ }
+
+ final GDActivity self = this;
+ Request request = API.getNotifications(Global.INSTALLED_FROM_APK, new ResponseHandler() {
+ @Override
+ public void onResponse(final Response apiResponse) {
+ try {
+ final NotificationsResponse response = new NotificationsResponse(apiResponse);
+ if (!response.isEmpty()) {
+ final Runnable onOk = new Runnable() {
+ @Override
+ public void run() {
+ if (response.hasURL()) {
+ String url = response.getURL();
+ try {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ startActivity(browserIntent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+
+ if (response.hasTwoButtons()) {
+ AlertDialog.Builder alert = new AlertDialog.Builder(self)
+ .setTitle(response.getTitle())
+ .setMessage(response.getMessage())
+ .setPositiveButton(response.getOKButton(), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ onOk.run();
+ }
+ })
+ .setNegativeButton(response.getCancelButton(), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+
+ }
+ });
+ alert.show();
+ } else {
+ AlertDialog alertDialog = new AlertDialog.Builder(self)
+ .setTitle(response.getTitle())
+ .setMessage(response.getMessage())
+ .setPositiveButton(response.getOKButton(), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ onOk.run();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ }
+ })
+ .create();
+ alertDialog.show();
+ }
+ }
+ } catch (Exception e) {
+ // e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onError(APIException error) {
+
+ }
+ });
+
+ if (true) {
+ gameView = new GameView(this);
+
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+ scrollView = new ObservableScrollView(this);
+ scrollView.setBackgroundColor(0x00ffffff);
+ scrollView.setFillViewport(true);
+ scrollView.setOnScrollListener(new ObservableScrollView.OnScrollListener() {
+ @Override
+ public void onScroll(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {
+ if (isMenuShown() && menu != null && menu.currentMenu != null) {
+ int h = scrollView.getChildAt(0).getHeight() - scrollView.getHeight();
+ double p = 100.0 * y / h;
+ if (p > 100f)
+ p = 100f;
+
+ menu.currentMenu.onScroll(p);
+ }
+ }
+ });
+ scrollView.setVisibility(View.GONE);
+
+ frame = new FrameLayout(this);
+ frame.setBackgroundColor(0xffffffff);
+
+ titleLayout = new MenuTitleLinearLayout(this);
+ titleLayout.setBackgroundColor(0x00ffffff);
+ titleLayout.setGravity(Gravity.TOP);
+ titleLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ titleLayout.setPadding(Helpers.getDp(MENU_TITLE_LAYOUT_X_PADDING), Helpers.getDp(MENU_TITLE_LAYOUT_TOP_PADDING), Helpers.getDp(MENU_TITLE_LAYOUT_X_PADDING), Helpers.getDp(MENU_TITLE_LAYOUT_BOTTOM_PADDING));
+
+ menuTitleTextView = new TextView(this);
+ menuTitleTextView.setText(getString(R.string.main));
+ menuTitleTextView.setTextColor(0xff000000);
+ menuTitleTextView.setTypeface(Global.robotoCondensedTypeface);
+ menuTitleTextView.setTextSize(MENU_TITLE_FONT_SIZE);
+ menuTitleTextView.setLineSpacing(0f, 1.1f);
+ menuTitleTextView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ ));
+ menuTitleTextView.setVisibility(android.view.View.GONE);
+
+ titleLayout.addView(menuTitleTextView);
+
+ scrollView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, 1));
+
+ // Keyboard
+ String[] buttonResources = {
+ "btn_br", "btn_br", "btn_b",
+ "btn_br", "btn_br", "btn_b",
+ "btn_r", "btn_r", "btn_n"
+ };
+ if (getString(R.string.screen_type).equals("tablet")) {
+ buttonHeight = 85;
+ } else if (Global.density < 1.5) {
+ buttonHeight = 55;
+ }
+
+ keyboardLayout = new MenuLinearLayout(this, true);
+ keyboardLayout.setOrientation(LinearLayout.VERTICAL);
+
+ keyboardController = new KeyboardController(this);
+
+ for (int i = 0; i < 3; i++) {
+ LinearLayout row = new LinearLayout(this);
+ row.setPadding(Helpers.getDp(KeyboardController.PADDING), i == 0 ? Helpers.getDp(KeyboardController.PADDING) : 0, Helpers.getDp(KeyboardController.PADDING), 0);
+ row.setOrientation(LinearLayout.HORIZONTAL);
+ row.setBackgroundColor(0xc6ffffff);
+ for (int j = 0; j < 3; j++) {
+ LinearLayout btn = new LinearLayout(this);
+ TextView btnText = new TextView(this);
+ btnText.setText(String.valueOf(i * 3 + j + 1));
+ btnText.setTextColor(0xff000000);
+ btnText.setTextSize(17);
+ btn.setBackgroundResource(getResources().getIdentifier(buttonResources[i * 3 + j], "drawable", getPackageName()));
+ btn.addView(btnText, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ btn.setGravity(Gravity.CENTER);
+ btn.setWeightSum(1);
+
+ row.addView(btn, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, Helpers.getDp(buttonHeight), 1));
+
+ keyboardController.addButton(btn, j, i);
+ }
+
+ keyboardLayout.addView(row);
+ }
+
+ keyboardLayout.setGravity(Gravity.BOTTOM);
+ keyboardLayout.setPadding(0, 0, 0, Helpers.getDp(KeyboardController.PADDING));
+ keyboardLayout.setOnTouchListener(keyboardController);
+ keyboardLayout.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
+
+ hideKeyboardLayout();
+
+ menuBtn = new MenuImageView(this);
+ menuBtn.setImageResource(R.drawable.ic_menu);
+ menuBtn.setScaleType(ImageView.ScaleType.CENTER);
+ menuBtn.setLayoutParams(new FrameLayout.LayoutParams(Helpers.getDp(GAME_MENU_BUTTON_LAYOUT_WIDTH), Helpers.getDp(GAME_MENU_BUTTON_LAYOUT_HEIGHT), Gravity.RIGHT | Gravity.TOP));
+ menuBtn.setOnClickListener(new android.view.View.OnClickListener() {
+ @Override
+ public void onClick(android.view.View v) {
+ gameView.showMenu();
+ }
+ });
+ menuBtn.setVisibility(android.view.View.GONE);
+
+ menuLayout = new MenuLinearLayout(this);
+ menuLayout.setOrientation(LinearLayout.VERTICAL);
+ menuLayout.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT
+ ));
+
+ portedTextView = new MenuTextView(this);
+ portedTextView.setTypeface(Global.robotoCondensedTypeface);
+ portedTextView.setTextSize(15);
+ portedTextView.setLineSpacing(0f, 1.2f);
+ portedTextView.setText(Html.fromHtml(getString(R.string.ported_text)));
+ portedTextView.setGravity(Gravity.CENTER);
+ portedTextView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
+ portedTextView.setPadding(0, 0, 0, Helpers.getDp(10));
+
+ menuLayout.addView(titleLayout);
+ menuLayout.addView(scrollView);
+
+ frame.addView(menuLayout);
+ frame.addView(keyboardLayout);
+ frame.addView(menuBtn);
+ frame.addView(portedTextView);
+
+ gameView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, 1));
+ frame.addView(gameView, 0);
+
+ setContentView(frame);
+
+ gameView._doIV(1); // flag for 1st image, as I understand..
+ thread = null;
+ m_caseZ = false;
+ m_nullI = 2;
+ m_forJ = 0;
+ m_byteJ = 0;
+ inited = false;
+ m_ifZ = false;
+ wasDestroyed = false;
+ restartingStarted = false;
+
+ frame.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ frame.getViewTreeObserver().removeOnPreDrawListener(this);
+ // setButtonsLayoutHeight();
+ doStart();
+ return true;
+ }
+ });
+
+
+
+ /* gameView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ gameView.getViewTreeObserver().removeOnPreDrawListener(this);
+ doStart();
+ return true;
+ }
+ }); */
+
+ /* alive = true;
+ m_cZ = false;
+
+ Thread.currentThread().setName("main_thread");
+
+ if (thread == null) {
+ thread = new Thread(this);
+ thread.setName("game_thread");
+ } */
+
+ /*synchronized (thread) {
+ thread.start();
+ try {
+ thread.wait();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ for (int i = 1; i <= 4; i++) {
+ menu.load(i);
+ }
+
+ wasStarted = true;*/
+ }
+ }
+
+ protected void doStart() {
+ alive = true;
+ m_cZ = false;
+
+ Thread.currentThread().setName("main_thread");
+
+ if (thread == null) {
+ thread = new Thread(this);
+ thread.setName("game_thread");
+ thread.start();
+ }
+
+ wasStarted = true;
+ }
+
+ // protected boolean viewDone = false;
+
+ @Override
+ public void run() {
+ Helpers.logDebug("!!! run()");
+ long l1;
+
+ if (!inited) {
+ Helpers.logDebug("run(): initing");
+ try {
+ // Game view
+ /* gameView = new GameView(shared);
+ gameView.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT, 1));
+ frame.addView(gameView, 0); */
+
+ /* gameView._doIV(1);
+ thread = null;
+ m_caseZ = false;
+ m_nullI = 2;
+ m_forJ = 0L;
+ seconds = 0L;
+ m_byteJ = 0L;
+ inited = false;
+ m_ifZ = false; */
+
+ long imageDelay = Global.DEBUG ? IMAGES_DELAY_DEBUG : IMAGES_DELAY; // delay of first image
+ Thread.yield();
+
+ /*gameView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ gameView.getViewTreeObserver().removeOnPreDrawListener(this);
+ viewDone = true;
+ logDebug("gameView is ready");
+ //doStart();
+ return true;
+ }
+ });
+
+ logDebug("before while..");
+ while (!viewDone) {
+ // Thread.sleep(1);
+ }
+ logDebug("after while..");*/
+
+ // do we really need this?!
+ /*while (gameView == null || gameView.getParent() == null) {
+ try {
+ Thread.sleep(100);
+ } catch (Exception x) {}
+ }*/
+
+ MenuHelmetView.clearStaticFields();
+
+ levelsManager = new LevelsManager();
+ try {
+ levelLoader = new Loader(levelsManager.getCurrentLevelsFile());
+ } catch (IOException e) {
+ e.printStackTrace();
+ // logDebug("Reset level id now");
+ levelsManager.resetId();
+ levelsManager.reload();
+
+ levelLoader = new Loader(levelsManager.getCurrentLevelsFile());
+ }
+
+ physEngine = new Physics(levelLoader);
+ gameView.setPhysicsEngine(physEngine);
+
+ // logDebug(levelsManager.getLevelsStat());
+ sendStats();
+
+ /* synchronized (Thread.currentThread()) {
+ Thread.currentThread().notify();
+ } */
+ menu = new org.happysanta.gd.Menu.Menu();
+ // menu = null;
+ // menu.hideKeyboard();
+ for (int i = 1; i <= 4; i++) {
+ menu.load(i);
+ }
+
+ // menu = new Menu();
+ // menu.hideKeyboard();
+
+ /*menu.load(1);
+ menu.load(2);
+ menu.load(3);
+
+ Runnable createMenuRunnable = new Runnable() {
+ @Override
+ public void run() {
+ menu.load(4);
+ synchronized (this) {
+ notify();
+ }
+ }
+ };
+
+ synchronized (createMenuRunnable) {
+ // logDebug("before runOnUiThread()");
+ runOnUiThread(createMenuRunnable);
+ try {
+ // logDebug("before wait()");
+ createMenuRunnable.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }*/
+
+ portedTextView.setVisibility(View.VISIBLE);
+
+ gameView.setMenu(menu);
+ gameView._doIIV(-50, 150);
+ setMode(1);
+
+ // Show first image
+ Helpers.logDebug("show first image");
+ long l2;
+ for (; imageDelay > 0L; imageDelay -= l2)
+ l2 = _avJ();
+
+ // Show second image
+ portedTextView.setVisibility(View.GONE);
+ Helpers.logDebug("show second image");
+ imageDelay = Global.DEBUG ? IMAGES_DELAY_DEBUG : IMAGES_DELAY;
+ gameView._doIV(2);
+ long l3;
+ for (long l4 = imageDelay; l4 > 0L; l4 -= l3)
+ l3 = _avJ();
+
+ while (m_longI < 10)
+ _avJ();
+
+ gameView._doIV(0);
+ Helpers.logDebug("images DONE");
+ inited = true;
+
+ } catch (Exception _ex) {
+ _ex.printStackTrace();
+ // Log.w("GDTR", _ex);
+ throw new RuntimeException(_ex);
+ }
+ }
+
+ // logDebug("inited, continue");
+
+ restart(false);
+ // logDebug("showMenu() now");
+
+ /*if (menu != null) */
+ menu.showMenu(0);
+ if (/*menu != null && */menu.canStartTrack())
+ restart(true);
+ l1 = 0L;
+
+ // try {
+ Helpers.logDebug("start main loop");
+ while (alive) {
+ /*if (!alive) {
+ logDebug("!alive");
+ break;
+ }*/
+
+ // try {
+ if (physEngine._bytevI() != menu._jvI()) {
+ int j = gameView._intII(menu._jvI());
+ physEngine._doIV(j);
+ menu._intIV(j);
+ }
+
+ if (menuShown) {
+ menu.showMenu(1);
+ if (menu.canStartTrack())
+ restart(true);
+ }
+
+ for (int i1 = m_nullI; i1 > 0 && alive; i1--) {
+ /* if (m_ifZ)
+ seconds += 20L; */
+ if (m_forJ == 0L)
+ m_forJ = System.currentTimeMillis();
+ int k = 0;
+ if (/*physEngine != null && */(k = physEngine._dovI()) == 3 && m_byteJ == 0L) {
+ m_byteJ = System.currentTimeMillis() + 3000L;
+ gameView.showInfoMessage(getString(R.string.crashed), 3000);
+ //m_di.postInvalidate();
+ //m_di.serviceRepaints();
+ }
+ if (m_byteJ != 0L && m_byteJ < System.currentTimeMillis())
+ restart(true);
+ if (k == 5) {
+ finishedTime = System.currentTimeMillis();
+ gameView.showInfoMessage(getString(R.string.crashed), 3000);
+ //m_di.postInvalidate();
+ //m_di.serviceRepaints();
+ try {
+ long l2 = 1000L;
+ if (m_byteJ > 0L)
+ l2 = Math.min(m_byteJ - System.currentTimeMillis(), 1000L);
+ if (l2 > 0L)
+ Thread.sleep(l2);
+ } catch (InterruptedException _ex) {
+ }
+ restart(true);
+ } else if (k == 4) {
+ // logDebug("k == 4");
+ m_forJ = 0;
+ // seconds = 0;
+ startedTime = 0;
+ finishedTime = 0;
+ pausedTime = 0;
+ } else if (k == 1 || k == 2) {
+ finishedTime = System.currentTimeMillis();
+ // logDebug("game-run: k = " + k);
+ /* if (k == 2)
+ seconds -= 10L; */
+ goalLoop();
+ // menu.setLastTrackTime(seconds / 10L);
+ menu.setLastTrackTime((finishedTime - startedTime) / 10);
+ menu.showMenu(2);
+
+ if (menu.canStartTrack())
+ restart(true);
+ if (!alive) {
+ Helpers.logDebug("!alive (2)");
+ break;
+ }
+ }
+ m_ifZ = k != 4;
+ if (m_ifZ && startedTime == 0) {
+ startedTime = System.currentTimeMillis();
+ }
+ }
+
+ if (!alive) {
+ Helpers.logDebug("!alive (3)");
+ break;
+ }
+
+ //try {
+ /*if (physEngine != null)*/
+ physEngine._charvV();
+ long l;
+ if ((l = System.currentTimeMillis()) - l1 < 30L) {
+ try {
+ synchronized (this) {
+ wait(Math.max(30L - (l - l1), 1L));
+ }
+ } catch (InterruptedException interruptedexception) {
+ }
+ l1 = System.currentTimeMillis();
+ } else {
+ l1 = l;
+ }
+ //m_di.postInvalidate();
+ /*} catch (Exception exception) {
+ exception.printStackTrace();
+ }*/
+ }
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ //}
+
+ Helpers.logDebug("game thread finished, destroyApp(false) next");
+
+ // finish();
+ destroyApp(false);
+ // return;
+ }
+
+ @Override
+ protected void onResume() {
+ Helpers.logDebug("@@@ [GDActivity \"+hashCode()+\"] onResume()");
+ super.onResume();
+ Helpers.logDebug("[GDActivity \"+hashCode()+\"] onResume(), inited = " + inited);
+ if (wasPaused && wasStarted) {
+ // logDebug("onResume(): wasPaused && wasResumed");
+ // start();
+ m_cZ = false;
+ wasPaused = false;
+
+ // Menu.HelmetRotation.start();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ Helpers.logDebug("@@@ [GDActivity " + hashCode() + "] onPause()");
+
+ wasPaused = true;
+ m_cZ = true;
+ Helpers.logDebug("inited : " + inited);
+ if (!menuShown && inited)
+ gameToMenu();
+
+ // menu.helmetRotationStop();
+ // Menu.HelmetRotation.stop();
+ // if (menu != null)
+ // menu.saveAll();
+ // levelsManager.updateLevelSettings();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ Helpers.logDebug("@@@ [GDActivity " + hashCode() + "] onDestroy()");
+ destroyApp(false);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ Helpers.logDebug("@@@ [GDActivity " + hashCode() + "] onStop()");
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ Helpers.logDebug("@@@ [GDActivity " + hashCode() + "] onStart()");
+ }
+
+ @Override
+ protected void onRestart() {
+ super.onRestart();
+ Helpers.logDebug("@@@ [GDActivity " + hashCode() + "] onRestart()");
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (gameView != null && menu != null && inited) {
+ if (menuShown)
+ menu.back();
+ else
+ gameView.showMenu();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(android.view.Menu menu) {
+ menu.clear();
+ int id = 1;
+ for (Command cmd : commands) {
+ MenuItem item = menu.add(0, id, 0, cmd.title);
+ id++;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ gameView.commandAction(commands.get(item.getItemId() - 1));
+ return true;
+ }
+
+ public void setMode(int j) {
+ physEngine._byteIV(j);
+ }
+
+ public boolean isMenuShown() {
+ return menuShown;
+ }
+
+ // @UiThread
+ public void setMenu(final LinearLayout layout) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ scrollView.removeAllViews();
+ if (layout.getParent() != null) {
+ ((ViewManager) layout.getParent()).removeView(layout);
+ }
+ scrollView.addView(layout);
+ }
+ });
+ }
+
+ public void goalLoop() {
+ if (!alive) {
+ return;
+ }
+
+ long l1 = 0L;
+ if (!physEngine.m_NZ)
+ gameView.showInfoMessage(getString(R.string.wheelie), 1000);
+ else
+ gameView.showInfoMessage(getString(R.string.finished1), 1000);
+ for (long l2 = System.currentTimeMillis() + 1000L; l2 > System.currentTimeMillis(); gameView.postInvalidate()) {
+ if (menuShown) {
+ //m_di.postInvalidate();
+ return;
+ }
+ for (int j = m_nullI; j > 0; j--)
+ if (physEngine._dovI() == 5)
+ try {
+ long l3;
+ if ((l3 = l2 - System.currentTimeMillis()) > 0L)
+ Thread.sleep(l3);
+ return;
+ } catch (InterruptedException _ex) {
+ return;
+ }
+
+ physEngine._charvV();
+ long l;
+ if ((l = System.currentTimeMillis()) - l1 < 30L) {
+ try {
+ synchronized (this) {
+ wait(Math.max(30L - (l - l1), 1L));
+ }
+ } catch (InterruptedException interruptedexception) {
+ }
+ l1 = System.currentTimeMillis();
+ } else {
+ l1 = l;
+ }
+ }
+ }
+
+ public void restart(boolean flag) {
+ // logDebug("[GDActivity] restart()");
+ if (!alive) {
+ return;
+ }
+
+ physEngine._doZV(true);
+ // logDebug("[GDActivity] restart(): 1");
+ m_forJ = 0;
+ // seconds = 0;
+ startedTime = 0;
+ finishedTime = 0;
+ pausedTime = 0;
+ m_byteJ = 0;
+ if (flag)
+ gameView.showInfoMessage(levelLoader.getLevelName(menu.getSelectedLevel(), menu.getSelectedTrack()), 3000);
+ // logDebug("[GDActivity] restart(): 2");
+ gameView._casevV();
+ // logDebug("[GDActivity] restart(): 3");
+ }
+
+ public void destroyApp(final boolean restart) {
+ if (wasDestroyed) {
+ return;
+ }
+
+ wasDestroyed = true;
+ alive = false;
+
+ final GDActivity self = this;
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Helpers.logDebug("[GDActivity " + self.hashCode() + "] destroyApp()");
+ inited = false;
+ m_caseZ = true;
+
+ synchronized (gameView) {
+ destroyResources();
+
+ if (exiting || restart) {
+ finish();
+ }
+
+ if (restart) {
+ doRestartApp();
+ }
+ }
+ }
+ });
+ }
+
+ private void destroyResources() {
+ Helpers.logDebug("[GDActivity " + hashCode() + "] destroyResources()");
+
+ // if (thread != null) thread.interrupt();
+ if (gameView != null) gameView.destroy();
+
+ menuShown = false;
+ if (menu != null) {
+ if (!fullResetting) menu.saveAll();
+ menu.destroy();
+ }
+
+ if (levelsManager != null) levelsManager.closeDataSource();
+ }
+
+ public int getButtonsLayoutHeight() {
+ return buttonHeight * 3 + KeyboardController.PADDING * 2;
+ }
+
+ // @UiThread
+ public void hideKeyboardLayout() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ keyboardLayout.setVisibility(android.view.View.GONE);
+
+ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) scrollView.getLayoutParams();
+ params.setMargins(0, 0, 0, 0);
+ scrollView.setLayoutParams(params);
+ }
+ });
+ }
+
+ // @UiThread
+ public void showKeyboardLayout() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ keyboardLayout.setVisibility(android.view.View.VISIBLE);
+
+ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) scrollView.getLayoutParams();
+ params.setMargins(0, 0, 0, Helpers.getDp(getButtonsLayoutHeight()));
+ scrollView.setLayoutParams(params);
+ }
+ });
+ }
+
+ public void addCommand(Command cmd) {
+ if (!commands.contains(cmd))
+ commands.add(cmd);
+ if (isNormalAndroid)
+ invalidateOptionsMenu();
+ }
+
+ public void removeCommand(Command cmd) {
+ commands.remove(cmd);
+ if (isNormalAndroid)
+ invalidateOptionsMenu();
+ }
+
+ public void gameToMenu() {
+ Helpers.logDebug("gameToMenu()");
+
+ if (gameView == null) {
+ Helpers.logDebug("gameToMenu(): gameView == null");
+ return;
+ }
+
+ pausedTimeStarted = System.currentTimeMillis();
+
+ gameView.removeMenuCommand();
+ menuShown = true;
+ // menu.helmetRotationStart();
+ // Menu.HelmetRotation.start();
+ if (menu != null)
+ menu.addCommands();
+
+ // hideKeyboardLayout();
+ if (!Settings.isKeyboardInMenuEnabled())
+ hideKeyboardLayout();
+ else
+ showKeyboardLayout();
+
+ gameToMenuUpdateUi();
+ }
+
+ // @UiThread
+ protected void gameToMenuUpdateUi() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ menuBtn.setVisibility(android.view.View.GONE);
+ menuTitleTextView.setVisibility(android.view.View.VISIBLE);
+ scrollView.setVisibility(android.view.View.VISIBLE);
+ }
+ });
+ }
+
+ public void menuToGame() {
+ Helpers.logDebug("menuToGame()");
+
+ if (pausedTimeStarted > 0 && startedTime > 0) {
+ pausedTime += (System.currentTimeMillis() - pausedTimeStarted);
+ pausedTimeStarted = 0;
+ }
+
+ if (menu != null) menu.removeCommands();
+ menuShown = false;
+ // menu.helmetRotationStop();
+ // Menu.HelmetRotation.stop();
+ if (gameView != null) gameView.addMenuCommand();
+ showKeyboardLayout();
+ // menu.showKeyboard();
+
+ menuToGameUpdateUi();
+
+ keyboardController.clearLogBuffer();
+ }
+
+ // @UiThread
+ protected void menuToGameUpdateUi() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ menuBtn.setVisibility(android.view.View.VISIBLE);
+ menuTitleTextView.setVisibility(android.view.View.GONE);
+ scrollView.setVisibility(android.view.View.GONE);
+
+ // Clear menu
+ scrollView.removeAllViews();
+ menuTitleTextView.setText("");
+ menu.menuDisabled = true;
+ // menu.currentMenu = null;
+ }
+ });
+ }
+
+ public void scrollTextMenuUp() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ int y = scrollView.getScrollY();
+ scrollView.scrollTo(0, y - Helpers.getDp(20));
+ }
+ });
+ }
+
+ public void scrollTextMenuDown() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ int y = scrollView.getScrollY();
+ scrollView.scrollTo(0, y + Helpers.getDp(20));
+ }
+ });
+ }
+
+ public void scrollToView(final View view) {
+ final GDActivity gd = Helpers.getGDActivity();
+ final ObservableScrollView scrollView = gd.scrollView;
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Rect scrollBounds = new Rect();
+ scrollView.getHitRect(scrollBounds);
+
+ if (!view.getLocalVisibleRect(scrollBounds)
+ || scrollBounds.height() < view.getHeight()) {
+ int top = view.getTop(),
+ height = view.getHeight(),
+ scrollY = scrollView.getScrollY(),
+ scrollHeight = scrollView.getHeight(),
+ y = top;
+
+ /*logDebug("top = " + top);
+ logDebug("height = " + height);
+ logDebug("scrollY = " + scrollY);
+ logDebug("scrollHeight = " + scrollHeight);*/
+
+ if (top < scrollY) {
+ // scroll to y
+ } else if (top + height > scrollY + scrollHeight) {
+ y = top + height - scrollHeight;
+ if (y < 0)
+ y = 0;
+ }
+
+ // logDebug("View is not visible, scroll to y = " + y);
+ scrollView.scrollTo(0, y);
+ } else {
+ // logDebug("View is visible");
+ }
+ }
+ });
+ }
+
+ private long _avJ() {
+ m_longI++;
+ long l = System.currentTimeMillis();
+ if (m_longI < 1 || m_longI > 10) { // maybe < 1 not needed?
+ m_longI--;
+ try {
+ Thread.sleep(100L);
+ } catch (InterruptedException _ex) {
+ }
+ }
+ return System.currentTimeMillis() - l;
+ }
+
+ public void restartApp() {
+ if (!restartingStarted) {
+ destroyApp(true);
+ restartingStarted = true;
+ }
+ }
+
+ private void doRestartApp() {
+ Intent mStartActivity = new Intent(this, GDActivity.class);
+ int mPendingIntentId = 123456;
+ PendingIntent mPendingIntent = PendingIntent.getActivity(this, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+ AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
+ }
+
+ private void sendStats() {
+ long lastTs = Settings.getLastSendStats();
+ Helpers.logDebug("sendStats: lastTs = " + lastTs);
+ if (lastTs == 0) {
+ Helpers.logDebug("sendStats: set it to current ts and return");
+ Settings.setLastSendStats(Helpers.getTimestamp());
+ return;
+ }
+
+ // if (Helpers.getTimestamp() < lastTs + 3600 * 8) {
+ if (Helpers.getTimestamp() < lastTs + 10) {
+ Helpers.logDebug("sendStats: just return");
+ return;
+ }
+
+ final GDActivity self = this;
+ Thread statsThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ HashMap<String, Double> stats = levelsManager.getLevelsStat();
+
+ JSONObject statsJSON = new JSONObject(stats);
+ String id = Installation.id(self);
+ int useCheats = org.happysanta.gd.Menu.Menu.isNameCheat(Settings.getName()) ? 1 : 0;
+
+ API.sendStats(statsJSON.toString(), id, useCheats, new ResponseHandler() {
+ @Override
+ public void onResponse(Response response) {
+ Helpers.logDebug("send stats OK");
+ Settings.setLastSendStats(Helpers.getTimestamp());
+ }
+
+ @Override
+ public void onError(APIException error) {
+ Helpers.logDebug("send stats error: " + error.getMessage());
+ // logDebug(error);
+ // error.printStackTrace();
+ }
+ });
+ } catch (Exception e) {
+ Helpers.logDebug("send stats exception: " + e.getMessage());
+ // e.printStackTrace();
+ }
+ }
+ };
+ statsThread.start();
+ }
+
+ public void sendKeyboardLogs() {
+ final ProgressDialog progressDialog = ProgressDialog.show(this, getString(R.string.please_wait), getString(R.string.please_wait), true);
+ API.sendKeyboardLogs(keyboardController.getLog(), new ResponseHandler() {
+ @Override
+ public void onResponse(Response response) {
+ progressDialog.dismiss();
+ keyboardController.clearLogBuffer();
+ Helpers.showAlert(getString(R.string.ok), "Done", null);
+ }
+
+ @Override
+ public void onError(APIException error) {
+ progressDialog.dismiss();
+ Helpers.showAlert(getString(R.string.error), "Unable to send logs. Maybe log is empty?", null);
+ }
+ });
+ }
+
+ private class ButtonCoords {
+
+ public int x = 0;
+ public int y = 0;
+ public int w = 0;
+ public int h = 0;
+
+ public ButtonCoords() {
+ }
+
+ public boolean in(float x, float y) {
+ if (x < this.x || x > this.x + this.w || y < this.y || y > this.y + this.h) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+} \ No newline at end of file
diff --git a/src/org/happysanta/gd/GDApplication.java b/src/org/happysanta/gd/GDApplication.java
new file mode 100644
index 0000000..120a5a7
--- /dev/null
+++ b/src/org/happysanta/gd/GDApplication.java
@@ -0,0 +1,24 @@
+package org.happysanta.gd;
+
+import android.app.Application;
+import org.acra.*;
+import org.acra.annotation.*;
+
+import static org.acra.ReportField.*;
+
+@ReportsCrashes(
+ formKey = "",
+ formUri = "http://gdtr.net/report.php",
+ customReportContent = {APP_VERSION_NAME, APP_VERSION_CODE, ANDROID_VERSION, PHONE_MODEL, PRODUCT, DISPLAY, STACK_TRACE, LOGCAT, USER_CRASH_DATE, INSTALLATION_ID, CUSTOM_DATA}
+)
+public class GDApplication extends Application {
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if (Global.ACRA_ENABLED) {
+ ACRA.init(this);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/org/happysanta/gd/Game/Bitmap.java b/src/org/happysanta/gd/Game/Bitmap.java
new file mode 100755
index 0000000..087a865
--- /dev/null
+++ b/src/org/happysanta/gd/Game/Bitmap.java
@@ -0,0 +1,184 @@
+package org.happysanta.gd.Game;
+
+import org.happysanta.gd.Global;
+import org.happysanta.gd.R;
+
+import java.io.IOException;
+
+import static org.happysanta.gd.Helpers.*;
+
+public class Bitmap {
+
+ public final static int HELMET = 0;
+ public final static int CODEBREW_LOGO = 1;
+ public final static int GD_LOGO = 2;
+ public final static int STEERING = 3;
+ public final static int WHEELS = 4;
+ public final static int ARROWS = 5;
+ public final static int FLAGS = 6;
+ public final static int LOCKS = 7;
+ public final static int MEDALS = 8;
+ public final static int LEVELS_WHEELS = 9;
+ public final static int FENDER = 10;
+ public final static int ENGINE = 11;
+ public final static int BIKER = 12;
+
+ public final static int BLUEARM = 100;
+ public final static int BLUELEG = 101;
+ public final static int BLUEBODY = 102;
+
+ public android.graphics.Bitmap bitmap;
+ protected static GDBitmapHolder holders[];
+ protected static Bitmap empty = null;
+
+ Bitmap(android.graphics.Bitmap b) {
+ bitmap = b;
+ }
+
+ static {
+ holders = new GDBitmapHolder[]{
+ // 0
+ new GDBitmapHolder(Bitmap.fromDrawable(R.drawable.s_helmet)),
+
+ // 1
+ new GDBitmapHolder(Bitmap.fromDrawable(R.drawable.codebrew)),
+
+ // 2
+ new GDBitmapHolder(Bitmap.fromDrawable(R.drawable.gd)),
+
+ // 3
+ new GDBitmapHolder(Bitmap.fromDrawable(R.drawable.s_steering)),
+
+ // 4
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.s_wheel1),
+ Bitmap.fromDrawable(R.drawable.s_wheel2)
+ }),
+
+ // 5
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.s_arrow_up),
+ Bitmap.fromDrawable(R.drawable.s_arrow_down)
+ }),
+
+ // 6
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.s_flag_start0),
+ Bitmap.fromDrawable(R.drawable.s_flag_start1),
+ Bitmap.fromDrawable(R.drawable.s_flag_start2),
+ Bitmap.fromDrawable(R.drawable.s_flag_finish0),
+ Bitmap.fromDrawable(R.drawable.s_flag_finish1),
+ Bitmap.fromDrawable(R.drawable.s_flag_finish2)
+ }),
+
+ // 7
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.s_lock0),
+ Bitmap.fromDrawable(R.drawable.s_lock1),
+ Bitmap.fromDrawable(R.drawable.s_lock2)
+ }),
+
+ // 8
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.s_medal_gold),
+ Bitmap.fromDrawable(R.drawable.s_medal_silver),
+ Bitmap.fromDrawable(R.drawable.s_medal_bronze)
+ }),
+
+ // 9
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.levels_wheel0),
+ Bitmap.fromDrawable(R.drawable.levels_wheel1),
+ Bitmap.fromDrawable(R.drawable.levels_wheel2)
+ }),
+
+ // 10
+ new GDBitmapHolder(Bitmap.fromDrawable(R.drawable.s_fender)),
+
+ // 11
+ new GDBitmapHolder(Bitmap.fromDrawable(R.drawable.s_engine)),
+
+ // 12
+ new GDBitmapHolder(new Bitmap[]{
+ Bitmap.fromDrawable(R.drawable.s_bluearm),
+ Bitmap.fromDrawable(R.drawable.s_blueleg),
+ Bitmap.fromDrawable(R.drawable.s_bluebody)
+ })
+ };
+ empty = new Bitmap(android.graphics.Bitmap.createBitmap(1, 1, android.graphics.Bitmap.Config.ARGB_8888));
+ }
+
+ public static Bitmap get(int index) {
+ if (index >= BLUEARM && index <= BLUEBODY) {
+ return get(BIKER, index - 100);
+ }
+
+ if (holders.length >= index - 1) {
+ GDBitmapHolder holder = holders[index];
+
+ if (holder != null && !holder.isArray && holder.bitmap != null) {
+ return holder.bitmap;
+ }
+ }
+
+ return empty;
+ }
+
+ public static Bitmap get(int index, int arrayIndex) {
+ if (holders.length >= index - 1) {
+ GDBitmapHolder holder = holders[index];
+ if (holder != null && holder.isArray && holder.bitmaps != null && holder.bitmaps.length >= arrayIndex - 1) {
+ return holder.bitmaps[arrayIndex];
+ }
+ }
+
+ return empty;
+ }
+
+ public static Bitmap getEmpty() {
+ return empty;
+ }
+
+ public static Bitmap fromDrawable(int id) {
+ return new Bitmap(loadBitmapFromDrawable(id));
+ }
+
+ public static Bitmap fromAsset(String s) throws IOException {
+ return new Bitmap(loadBitmapFromAsset(s));
+ }
+
+ public int getWidth() {
+ return bitmap.getWidth();
+ }
+
+ public int getHeight() {
+ return bitmap.getHeight();
+ }
+
+ public int getWidthDp() {
+ return Math.round(getWidth() / Global.density);
+ }
+
+ public int getHeightDp() {
+ return Math.round(getHeight() / Global.density);
+ }
+
+ private static class GDBitmapHolder {
+
+ public Bitmap bitmap = null;
+ public Bitmap bitmaps[] = null;
+ public boolean isArray = false;
+
+ GDBitmapHolder(Bitmap bitmap) {
+ this.bitmap = bitmap;
+ }
+
+ GDBitmapHolder(Bitmap bitmaps[]) {
+ this.bitmaps = new Bitmap[bitmaps.length];
+ System.arraycopy(bitmaps, 0, this.bitmaps, 0, bitmaps.length);
+ isArray = true;
+ }
+
+ }
+
+}
diff --git a/src/org/happysanta/gd/Game/FPMath.java b/src/org/happysanta/gd/Game/FPMath.java
new file mode 100755
index 0000000..9ddc4ab
--- /dev/null
+++ b/src/org/happysanta/gd/Game/FPMath.java
@@ -0,0 +1,80 @@
+package org.happysanta.gd.Game;
+
+// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
+// Jad home page: http://www.kpdus.com/jad.html
+// Decompiler options: packimports(3) fieldsfirst ansi
+
+
+public class FPMath {
+
+ // public static final int UNSIGNED_MASK = 0x7fffffff;
+// public static final int SIGN_MASK = 0x80000000;
+ //public static final int m_ifI;
+// public static final int m_aI = 1;
+ public static int HALF_PI = 0x19220; // 1,57080949111162
+ // public static int DOUBLE_PI = 0x6487f; // 6,283192187380789
+ public static int PI = 0x3243f; // 3,141588464179446
+ // public static int ONE = 0x10000;
+ private static int m_jI;
+ private static int m_kI;
+// private static int SIN_TABLE[] = {
+// 0, 1608, 3215, 4821, 6423, 8022, 9616, 11204, 12785, 14359,
+// 15923, 17479, 19024, 20557, 22078, 23586, 25079, 26557, 28020, 29465,
+// 30893, 32302, 33692, 35061, 36409, 37736, 39039, 40319, 41575, 42806,
+// 44011, 45189, 46340, 47464, 48558, 49624, 50660, 51665, 52639, 53581,
+// 54491, 55368, 56212, 57022, 57797, 58538, 59243, 59913, 60547, 61144,
+// 61705, 62228, 62714, 63162, 63571, 63943, 64276, 64571, 64826, 65043,
+// 65220, 65358, 65457, 65516
+// };
+// private static int ARCTG_TABLE[] = {
+// 0, 1023, 2047, 3069, 4090, 5109, 6126, 7139, 8149, 9155,
+// 10157, 11155, 12146, 13133, 14113, 15087, 16054, 17015, 17967, 18912,
+// 19849, 20778, 21698, 22610, 23512, 24405, 25289, 26163, 27027, 27882,
+// 28726, 29561, 30385, 31199, 32003, 32796, 33579, 34352, 35114, 35866,
+// 36608, 37339, 38060, 38771, 39471, 40161, 40841, 41512, 42172, 42822,
+// 43463, 44094, 44716, 45328, 45931, 46524, 47109, 47684, 48251, 48809,
+// 49358, 49899, 50431, 50955
+// };
+
+ public FPMath() {
+ }
+
+ public static int divide(int i, int j) {
+ int res = (int) (((long) i << 32) / (long) j >> 16);
+ return res;
+ }
+
+ public static int sin(int i) {
+ float fi = i / (float) 0xFFFF;
+ return (int) Math.round(Math.sin(fi) * 65536);
+ }
+
+ public static int _doII(int i) {
+ return sin(HALF_PI - i);
+ }
+
+ public static int arctg(int i) {
+ float fi = i / (float) 0xFFFF;
+ return (int) Math.round(Math.atan(fi) * 65536);
+ }
+
+ public static int _ifIII(int i, int j) {
+ if ((j >= 0 ? j : -j) < 3)
+ return (i <= 0 ? -1 : 1) * HALF_PI;
+ int k = arctg(divide(i, j));
+ if (i > 0)
+ if (j > 0)
+ return k;
+ else
+ return PI + k;
+ if (j > 0)
+ return k;
+ else
+ return k - PI;
+ }
+
+ static {
+ m_jI = 64;
+ m_kI = m_jI << 16;
+ }
+}
diff --git a/src/org/happysanta/gd/Game/GameView.java b/src/org/happysanta/gd/Game/GameView.java
new file mode 100755
index 0000000..ad181e0
--- /dev/null
+++ b/src/org/happysanta/gd/Game/GameView.java
@@ -0,0 +1,968 @@
+package org.happysanta.gd.Game;
+
+import android.graphics.*;
+import android.view.View;
+import org.happysanta.gd.Command;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Menu;
+import org.happysanta.gd.Menu.MenuScreen;
+import org.happysanta.gd.Menu.SimpleMenuElement;
+
+import java.io.IOException;
+import java.util.Timer;
+
+import static org.happysanta.gd.Helpers.*;
+
+public class GameView extends View {
+
+ private static int m_VI = 0;
+ private static int m_vcI = 0;
+ private final int[] startFlagIndexes = {
+ 2, 0, 1, 0
+ };
+ private final int[] finishFlagIndexes = {
+ 4, 3, 5, 3
+ };
+ public int m_abI;
+ public int m_dI;
+ public int m_lI;
+ public boolean drawTimer;
+ public android.graphics.Bitmap m_zaBitmap[];
+ public boolean m_KZ;
+ public long m_rJ;
+ Menu menu;
+ int m_uI;
+ int m_aiI;
+ int m_agI;
+ int m_gI;
+ private Canvas canvas;
+ private int m_XI;
+ private int m_BI;
+ private Physics physEngine;
+ private int m_TI;
+ private int m_QI;
+ private GDActivity activity;
+ private Paint infoFont;
+ private Paint timerFont;
+ private boolean m_ahZ;
+ private int m_oI;
+ private boolean m_AZ;
+ private int m_OI;
+ private android.graphics.Bitmap m_MBitmap;
+ private Canvas m_dcGraphics;
+ private boolean m_ecZ;
+ private String infoMessage;
+ private int gc;
+ private Timer timer;
+ private Command menuCommand;
+ private Paint paint = new Paint();
+ private Object m_ocObject;
+ private byte[][] m_DaaB = {
+ {0, 0},
+ {1, 0},
+ {0, -1},
+ {0, 0},
+ {0, 0},
+ {0, 1},
+ {-1, 0}
+ };
+ private byte[][][] m_maaaB = {
+ {
+ {
+ 0, 0
+ },
+ {
+ 1, -1
+ },
+ {
+ 1, 0
+ },
+ {
+ 1, 1
+ },
+ {
+ 0, -1
+ },
+ {
+ -1, 0
+ },
+ {
+ 0, 1
+ },
+ {
+ -1, -1
+ },
+ {
+ -1, 0
+ },
+ {
+ -1, 1
+ }
+ }, {
+ {
+ 0, 0
+ },
+ {
+ 1, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ -1, 0
+ },
+ {
+ 0, -1
+ },
+ {
+ 0, 1
+ },
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ }
+ },
+ {
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ 1, 0
+ },
+ {
+ 0, -1
+ },
+ {
+ 0, 1
+ },
+ {
+ -1, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ },
+ {
+ 0, 0
+ }
+ }
+ };
+ private int inputOption;
+ private boolean[] m_aeaZ;
+ private boolean[] m_LaZ;
+ // private int defaultHeight;
+ // private int defaultWidth;
+
+ public GameView(GDActivity micro) {
+ super(micro);
+ // clear static
+ m_vcI = 0;
+ m_VI = 0;
+
+ canvas = null;
+ physEngine = null;
+ menu = null;
+ m_TI = 0;
+ m_QI = 0;
+ activity = null;
+ infoFont = null;
+ m_ahZ = false;
+ drawTimer = true;
+ m_oI = 1;
+ m_uI = 0;
+ m_zaBitmap = null;
+
+ m_KZ = false;
+ m_AZ = true;
+ m_MBitmap = null;
+ m_dcGraphics = null;
+ m_ecZ = false;
+ infoMessage = null;
+ gc = 0;
+ timer = new Timer();
+ m_rJ = -1L;
+ m_ocObject = new Object();
+ m_aiI = 0;
+ m_agI = 0;
+ m_gI = -1;
+ inputOption = 2;
+ m_aeaZ = new boolean[7];
+ m_LaZ = new boolean[10];
+ // String s;
+ // String s1;
+ paint.setAntiAlias(true);
+ paint.setStrokeWidth(1);
+
+ invalidate();
+ m_KZ = false;
+ activity = micro;
+ _ifvV();
+
+ infoFont = new Paint();
+ infoFont.setTextSize(20);
+ infoFont.setAntiAlias(true);
+ infoFont.setTypeface(Global.robotoCondensedTypeface);
+
+ timerFont = new Paint();
+ timerFont.setTextSize(18);
+ timerFont.setAntiAlias(true);
+ timerFont.setTypeface(Global.robotoCondensedTypeface);
+
+ m_XI = 0;
+ m_BI = m_dI;
+ menuCommand = new Command("Menu", 1, 1);
+ }
+
+ public void drawBitmap(Bitmap b, float x, float y) {
+ drawBitmap(b, x, y, canvas);
+ }
+
+ public void drawBitmap(Bitmap b, float x, float y, Canvas g) {
+ Paint paint = null;
+ if (!isSDK11OrHigher()) {
+ paint = new Paint();
+ paint.setFlags(Paint.DITHER_FLAG);
+ paint.setFilterBitmap(true);
+ }
+ g.drawBitmap(b.bitmap,
+ new Rect(0, 0, b.getWidth(), b.getHeight()),
+ new RectF(x, y, x + b.getWidthDp(), y + b.getHeightDp()),
+ paint);
+ }
+
+ public static void _dovV() {
+ m_vcI += 655;
+ int j = 32768 + ((FPMath.sin(m_vcI) >= 0 ? FPMath.sin(m_vcI) : -FPMath.sin(m_vcI)) >> 1);
+ m_VI += (int) (6553L * (long) j >> 16);
+ }
+
+ /*
+ TODO
+ суть этого метода в том, что после того, как splash-картинки проигрались, они удаляются из памяти, т.к. они больше нафиг не нужны
+ видимо это было критично на старых телефонах
+ можно и тут в принципе сделать
+ */
+ public void _doIV(int j) {
+ m_oI = j;
+ if (j == 0) {
+ // Bitmap.get(Bitmap.CODEBREW_LOGO) = null;
+ // Bitmap.get(Bitmap.GD_LOGO) = null;
+ }
+ }
+
+ public void _aZV(boolean flag) {
+ m_AZ = flag;
+ _ifvV();
+ }
+
+ public void _ifvV() {
+ m_abI = getScaledWidth();
+ m_lI = m_dI = getScaledHeight();
+ if (m_KZ && m_AZ)
+ m_dI -= 80;
+ //postInvalidate();
+ }
+
+ public android.graphics.Bitmap[] spritesFromBitmap(android.graphics.Bitmap bitmap, int j, int k) {
+ int l = bitmap.getWidth() / j;
+ int i1 = bitmap.getHeight() / k;
+ android.graphics.Bitmap aBitmap[] = new android.graphics.Bitmap[j * k];
+ for (int j1 = 0; j1 < j * k; j1++) {
+ aBitmap[j1] = android.graphics.Bitmap.createBitmap(l, i1, android.graphics.Bitmap.Config.ARGB_8888);
+ new Canvas(aBitmap[j1]).drawBitmap(bitmap, -l * (j1 % j), -i1 * (j1 / j), null);
+ }
+
+ return aBitmap;
+ }
+
+ public int _intII(int j) {
+ synchronized (m_ocObject) {
+ try {
+ {
+ if ((j & 1) != 0) {
+ /* try {
+ if (Bitmap.get(Bitmap.FENDER) == null) {
+ //Bitmap.get(Bitmap.FENDER) = Bitmap.fromAsset("/fender.png");
+ //Bitmap.get(Bitmap.FENDER).mulWidth = 1.0f/6.0f;
+ //Bitmap.get(Bitmap.FENDER).mulHeight = 1.0f/6.0;
+ Bitmap.get(Bitmap.FENDER) = Bitmap.fromDrawable(R.drawable.s_fender);
+ }
+ if (Bitmap.get(Bitmap.ENGINE) == null) {
+ //Bitmap.get(Bitmap.ENGINE) = Bitmap.fromAsset("/engine.png");
+ //Bitmap.get(Bitmap.ENGINE).mulHeight = 1.0f/6.0f;
+ //Bitmap.get(Bitmap.ENGINE).mulWidth = 1.0f/6.0f;
+ Bitmap.get(Bitmap.ENGINE) = Bitmap.fromDrawable(R.drawable.s_engine);
+ }
+ } catch (Throwable _ex) {
+ Bitmap.get(Bitmap.FENDER) = Bitmap.get(Bitmap.ENGINE) = null;
+ j &= -2;
+ } */
+ } else {
+ // Bitmap.get(Bitmap.ENGINE) = Bitmap.get(Bitmap.FENDER) = null;
+ // System.gc();
+ }
+ if ((j & 2) != 0) {
+ // blueleg
+ /*try {
+ if (bikerSprites[1] == null)
+ bikerSprites[1] = Bitmap.fromDrawable(R.drawable.s_blueleg);
+ } catch (Throwable _ex) {
+ bikerSprites[1] = null;
+ bikerSprites[0] = null;
+ bikerSprites[2] = null;
+ j &= -3;
+ System.out.println("There may be error");
+ return 0;
+ }*/
+
+ // bluearm
+ /*try {
+ bikerSprites[0] = Bitmap.fromDrawable(R.drawable.s_bluearm);
+ } catch (Throwable _ex) {
+ bikerSprites[0] = bikerSprites[1];
+ }
+
+ // bluebody
+ try {
+ bikerSprites[2] = Bitmap.fromDrawable(R.drawable.s_bluebody);
+ } catch (Throwable _ex) {
+ bikerSprites[2] = bikerSprites[1];
+ }*/
+ } else {
+ // bikerSprites[1] = bikerSprites[2] = bikerSprites[0] = null;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("There may be error [1]");
+ }
+ }
+ return j;
+ }
+
+ public android.graphics.Bitmap[] loadSprites(String s, int j, int k) {
+ android.graphics.Bitmap bitmap;
+ try {
+ bitmap = loadBitmapFromAsset(s);
+ } catch (IOException _ex) {
+ android.graphics.Bitmap aBitmap[] = new android.graphics.Bitmap[j * k];
+ for (int l = 0; l < j * k; l++)
+ aBitmap[l] = Bitmap.getEmpty().bitmap;
+
+ return aBitmap;
+ }
+ return spritesFromBitmap(bitmap, j, k);
+ }
+
+ public void _casevV() {
+ physEngine._nullvV();
+ _avV();
+ m_aiI = 0;
+ m_agI = 0;
+ }
+
+ public void setPhysicsEngine(Physics b1) {
+ physEngine = b1;
+ physEngine._caseIV(m_abI >= m_dI ? m_dI : m_abI);
+ }
+
+ public void setMenu(Menu menu) {
+ this.menu = menu;
+ }
+
+ /* public Bitmap _aStringBitmap(String s) {
+ Bitmap bitmap = null;
+ try {
+ bitmap = Global.loadBitmapFromAsset(s);
+ } catch (IOException _ex) {
+ }
+ return bitmap;
+ } */
+
+ public void _doIIV(int j, int k) {
+ m_XI = j;
+ m_BI = k;
+ physEngine._ifIIV(-j, -j + m_abI);
+ }
+
+ public int _charvI() {
+ return m_XI;
+ }
+
+ private float offsetX(float j) {
+ return j + m_XI;
+ }
+
+ private float offsetY(float j) {
+ return -j + m_BI - getGDActivity().getButtonsLayoutHeight() / 2;
+ }
+
+ public void _newvV() {
+ paint.setColor(0xFFFFFFFF);
+ paint.setStyle(Paint.Style.FILL);
+ canvas.drawRect(0, m_dI, m_abI, 80, paint);
+ byte byte0 = 35;
+ int j = m_abI / 2;
+ int k = m_dI + 40;
+ // m_CGraphics.setColor(150, 0, 0);
+ paint.setColor(0xFF960000);
+ int i1;
+ paint.setStyle(Paint.Style.STROKE);
+ if (m_aiI != 0 || m_agI != 0) {
+ i1 = (int) (((long) (int) ((long) m_OI * 0xb40000L >> 16) << 32) / 0x3243fL >> 16) >> 16;
+ int l = i1 - i1 % 45;
+ l -= 90;
+ //m_CGraphics.fillArc(j - byte0, k - byte0, 2 * byte0, 2 * byte0, l - 22, 45);
+ canvas.drawArc(new RectF(j - byte0, k - byte0, 2 * byte0 + j - byte0, 2 * byte0 + k - byte0), l - 22, 45, true, paint);
+ }
+ //m_CGraphics.setColor(0, 0, 0);
+ paint.setColor(0xFF000000);
+ canvas.drawArc(new RectF(j - byte0, k - byte0, 2 * byte0 + j - byte0, 2 * byte0 + k - byte0), 0, 360, true, paint);
+ byte0 = 2;
+ canvas.drawArc(new RectF(j - byte0, k - byte0, 2 * byte0 + j - byte0, 2 * byte0 + k - byte0), 0, 360, true, paint);
+ paint.setStyle(Paint.Style.FILL);
+ }
+
+ public void _aIIIV(int j, int k, int l, int i1) {
+ canvas.drawLine(offsetX(j), offsetY(k), offsetX(l), offsetY(i1), paint);
+ }
+
+ public void drawLine(int j, int k, int l, int i1) {
+ canvas.drawLine(offsetX((j << 2) / (float) 0xFFFF), offsetY((k << 2) / (float) 0xFFFF), offsetX((l << 2) / (float) 0xFFFF), offsetY((i1 << 2) / (float) 0xFFFF), paint);
+ }
+
+ public void _aIIIV(int j, int k, int l, int i1, int j1) {
+ drawBikerPart(j, k, l, i1, j1, 32768);
+ }
+
+ public void drawBikerPart(int j, int k, int l, int i1, int j1, int k1) {
+ float l1 = offsetX((int) ((long) l * (long) k1 >> 16) + (int) ((long) j * (long) (0x10000 - k1) >> 16) >> 16);
+ float i2 = offsetY((int) ((long) i1 * (long) k1 >> 16) + (int) ((long) k * (long) (0x10000 - k1) >> 16) >> 16);
+ int j2 = FPMath._ifIII(l - j, i1 - k);
+ int index = 0;
+ switch (j1) {
+ case 0: // '\0'
+ index = _aIIII(j2, 0, 0x3243f, 16, false);
+ break;
+
+ case 1: // '\001'
+ index = _aIIII(j2, 0, 0x3243f, 16, false);
+ break;
+
+ case 2: // '\002'
+ index = _aIIII(j2, 0, 0x3243f, 16, false);
+ break;
+ }
+ float fAngleDeg = (float) (j2 / (float) 0xFFFF / Math.PI * 180) - 180;
+ index = 0;
+
+ Bitmap bikerSprite = Bitmap.get(Bitmap.BIKER, j1);
+ if (bikerSprite != null) {
+ float x = l1 - bikerSprite.getWidthDp() / 2;
+ float y = i2 - bikerSprite.getHeightDp() / 2;
+
+ canvas.save();
+ canvas.rotate(fAngleDeg, x + bikerSprite.getWidthDp() / 2, y + bikerSprite.getHeightDp() / 2);
+ drawBitmap(bikerSprite, x, y);
+ canvas.restore();
+ }
+ }
+
+ // �������� �����
+ public void _ifIIIV(int j, int k, int l, int i1) {
+ l++;
+ float j1 = offsetX(j - l);
+ float k1 = offsetY(k + l);
+ int l1 = l << 1;
+ if ((i1 = -(int) (((long) (int) ((long) i1 * 0xb40000L >> 16) << 32) / 0x3243fL >> 16)) < 0)
+ i1 += 360;
+ paint.setStyle(Paint.Style.STROKE);
+ canvas.drawArc(new RectF(j1, k1, j1 + l1, k1 + l1), -((i1 >> 16) + 170), -90, false, paint);
+ paint.setStyle(Paint.Style.FILL);
+ }
+
+ // Draws red circle
+ public void drawLineWheel(float j, float k, int l) {
+ float i1 = l / 2;
+ float j1 = offsetX(j - i1);
+ float k1 = offsetY(k + i1);
+
+ paint.setStyle(Paint.Style.STROKE);
+ canvas.drawArc(new RectF(j1, k1, j1 + l, k1 + l), 0, 360, true, paint);
+ paint.setStyle(Paint.Style.FILL);
+ }
+
+ public void _forIIIV(int j, int k, int l, int i1) {
+ float j1 = offsetX(j);
+ float k1 = offsetY(k);
+ canvas.drawRect(j1, k1, j1 + l, k1 + i1, paint);
+ }
+
+ public void drawSteering(int j, int k) {
+ float x = offsetX(j - Bitmap.get(Bitmap.STEERING).getWidthDp() / 2);
+ float y = offsetY(k + Bitmap.get(Bitmap.STEERING).getHeightDp() / 2);
+
+ drawBitmap(Bitmap.get(Bitmap.STEERING), x, y);
+ }
+
+ public void drawHelmet(float j, float k, int l) {
+ float fAngleDeg = (float) (l / (float) 0xFFFF / Math.PI * 180) - 90 - 10;
+ if (fAngleDeg >= 360) fAngleDeg -= 360;
+ if (fAngleDeg < 0) fAngleDeg = 360 + fAngleDeg;
+ if (Bitmap.get(Bitmap.HELMET) != null) {
+ float x = offsetX(j) - Bitmap.get(Bitmap.HELMET).getWidthDp() / 2;
+ float y = offsetY(k) - Bitmap.get(Bitmap.HELMET).getHeightDp() / 2;
+ canvas.save();
+ canvas.rotate(fAngleDeg, x + Bitmap.get(Bitmap.HELMET).getWidthDp() / 2, y + Bitmap.get(Bitmap.HELMET).getHeightDp() / 2);
+
+ drawBitmap(Bitmap.get(Bitmap.HELMET), x, y);
+ canvas.restore();
+ }
+ }
+
+ public void _ifIIIIV(int j, int k, int l, int i1, int j1, int k1) {
+ }
+
+ public void drawTimer(long l) {
+ // logDebug("Timer: " + l);
+ String txt = String.format("%d:%02d:%02d", l / 6000, (l / 100) % 60, l % 100);
+ // logDebug("drawTimter: long = " + l + ", string = " + txt);
+ canvas.drawText(txt, 18, -infoFont.ascent() + 17, timerFont);
+ }
+
+ public synchronized void showInfoMessage(String s, int j) {
+ m_ahZ = false;
+ gc++;
+ infoMessage = s;
+ if (timer != null) {
+ timer.schedule(new SimpleMenuElement(gc), j);
+ }
+ }
+
+ public void _tryIV(int j) {
+ if (gc == j)
+ m_ahZ = true;
+ }
+
+ public void drawStartFlag(int j, int k) {
+ if (m_VI > 0x38000)
+ m_VI = 0;
+ setColor(0, 0, 0);
+ _aIIIV(j, k, j, k + 32);
+ drawBitmap(Bitmap.get(Bitmap.FLAGS, startFlagIndexes[m_VI >> 16]), offsetX(j), offsetY(k) - 32);
+ }
+
+ public void drawFinishFlag(int j, int k) {
+ if (m_VI > 0x38000)
+ m_VI = 0;
+ setColor(0, 0, 0);
+ _aIIIV(j, k, j, k + 32);
+ drawBitmap(Bitmap.get(Bitmap.FLAGS, finishFlagIndexes[m_VI >> 16]), offsetX(j), offsetY(k) - 32);
+ }
+
+ public void drawWheel(float j, float k, int l) {
+ int wheel;
+ if (l == 1)
+ wheel = 0; // small
+ else
+ wheel = 1; // big
+
+ float x = offsetX(j - Bitmap.get(Bitmap.WHEELS, wheel).getWidthDp() / 2);
+ float y = offsetY(k + Bitmap.get(Bitmap.WHEELS, wheel).getHeightDp() / 2);
+
+ drawBitmap(Bitmap.get(Bitmap.WHEELS, wheel), x, y);
+ }
+
+ int _aIIII(int j, int k, int l, int i1, boolean flag) {
+ for (j += k; j < 0; j += l) ;
+ for (; j >= l; j -= l) ;
+ if (flag)
+ j = l - j;
+ int j1;
+ if ((j1 = (int) ((long) (int) (((long) j << 32) / (long) l >> 16) * (long) (i1 << 16) >> 16)) >> 16 < i1 - 1)
+ return j1 >> 16;
+ else
+ return i1 - 1;
+ }
+
+ public void drawEngine(float j, float k, int l) {
+ float fAngleDeg = (float) (l / (float) 0xFFFF / Math.PI * 180) - 180;
+ float x = offsetX(j) - Bitmap.get(Bitmap.ENGINE).getWidthDp() / 2;
+ float y = offsetY(k) - Bitmap.get(Bitmap.ENGINE).getHeightDp() / 2;
+ if (Bitmap.get(Bitmap.ENGINE) != null) {
+ canvas.save();
+ canvas.rotate(fAngleDeg, x + Bitmap.get(Bitmap.ENGINE).getWidthDp() / 2, y + Bitmap.get(Bitmap.ENGINE).getHeightDp() / 2);
+ drawBitmap(Bitmap.get(Bitmap.ENGINE), x, y);
+ canvas.restore();
+ }
+ }
+
+ public void drawFender(float j, float k, int l) {
+ float fAngleDeg = (float) (l / (float) 0xFFFF / Math.PI * 180) - 180 + 15;
+ if (fAngleDeg >= 360) fAngleDeg -= 360;
+ if (Bitmap.get(Bitmap.FENDER) != null) {
+ float x = offsetX(j) - Bitmap.get(Bitmap.FENDER).getWidthDp() / 2;
+ float y = offsetY(k) - Bitmap.get(Bitmap.FENDER).getHeightDp() / 2;
+
+ canvas.save();
+ canvas.rotate(fAngleDeg, x + Bitmap.get(Bitmap.FENDER).getWidthDp() / 2, y + Bitmap.get(Bitmap.FENDER).getHeightDp() / 2);
+ drawBitmap(Bitmap.get(Bitmap.FENDER), x, y);
+ canvas.restore();
+ }
+ }
+
+ public void _tryvV() {
+ paint.setColor(0xFFFFFFFF);
+ canvas.drawRect(0, 0, m_abI, m_dI, paint);
+ }
+
+ public void setColor(int r, int g, int b) {
+ GDActivity _tmp = activity;
+ if (getGDActivity().isMenuShown()) {
+ r += 128;
+ g += 128;
+ b += 128;
+ if (r > 240)
+ r = 240;
+ if (g > 240)
+ g = 240;
+ if (b > 240)
+ b = 240;
+ }
+ //m_CGraphics.setColor(j, k, l);
+ paint.setColor(0xFF000000 | (r << 16) | (g << 8) | b);
+ }
+
+ // Draw boot logos and something else
+ public void drawGame(Canvas g) {
+ final GDActivity gd = getGDActivity();
+ label0:
+ {
+ int j;
+ synchronized (m_ocObject) {
+ if (gd.alive && !gd.m_caseZ)
+ break label0;
+ }
+ return;
+ }
+
+ if (m_ecZ)
+ canvas = m_dcGraphics;
+ else
+ canvas = g;
+ if (m_oI != 0) {
+ if (m_oI == 1) {
+ // Draw codebrew
+ paint.setColor(0xFFFFFFFF);
+ canvas.drawRect(0, 0, getScaledWidth(), getScaledHeight(), paint);
+ if (Bitmap.get(Bitmap.CODEBREW_LOGO) != null) {
+ drawBitmap(Bitmap.get(Bitmap.CODEBREW_LOGO),
+ getScaledWidth() / 2 - Bitmap.get(Bitmap.CODEBREW_LOGO).getWidthDp() / 2,
+ (float) (getScaledHeight() / 2 - Bitmap.get(Bitmap.CODEBREW_LOGO).getHeightDp() / 1.6));
+ }
+ } else {
+ // Draw gd
+ paint.setColor(0xFFFFFFFF);
+ canvas.drawRect(0, 0, getScaledWidth(), getScaledHeight(), paint);
+ if (Bitmap.get(Bitmap.GD_LOGO) != null) {
+ drawBitmap(Bitmap.get(Bitmap.GD_LOGO),
+ getScaledWidth() / 2 - Bitmap.get(Bitmap.GD_LOGO).getWidthDp() / 2,
+ (float) (getScaledHeight() / 2 - Bitmap.get(Bitmap.GD_LOGO).getHeightDp() / 1.6));
+ }
+ }
+ int j = (int) (((long) (gd.m_longI << 16) << 32) / 0xa0000L >> 16);
+ drawProgress(j, true);
+ } else {
+ if (m_lI != getHeight())
+ _ifvV();
+ physEngine._voidvV();
+ _doIIV(-physEngine._elsevI() + m_TI + m_abI / 2, physEngine._ifvI() + m_QI + m_dI / 2);
+ physEngine._ifiV(this);
+ if (drawTimer) {
+ long time = 0, finished;
+ if (gd.startedTime > 0) {
+ if (gd.finishedTime > 0)
+ finished = gd.finishedTime;
+ else
+ finished = System.currentTimeMillis();
+ time = (finished - gd.startedTime - gd.pausedTime) / 10;
+ }
+ drawTimer(time);
+ }
+ if (infoMessage != null) {
+ setColor(0, 0, 0);
+ infoFont.setColor(paint.getColor());
+ /*if (m_dI <= 128)
+ canvas.drawText(infoMessage, m_abI / 2 - infoFont.measureText(infoMessage) / 2, 1, infoFont);
+ else*/
+
+ canvas.drawText(infoMessage, m_abI / 2 - infoFont.measureText(infoMessage) / 2, m_dI / 5, infoFont);
+ if (m_ahZ) {
+ m_ahZ = false;
+ infoMessage = null;
+ }
+ }
+ int j = physEngine._tryvI();
+ drawProgress(j, false);
+ if (m_KZ && m_AZ)
+ _newvV();
+ }
+ canvas = null;
+ if (m_ecZ)
+ g.drawBitmap(m_MBitmap, 0, 0, null);
+ }
+
+ public void drawProgress(int j, boolean flag) {
+ double progr = j / (double) 0xFFFF;
+
+ paint.setColor(0xffc4c4c4);
+ canvas.drawRect(0, 0, getScaledWidth(), 3, paint);
+
+ paint.setColor(0xff29aa27);
+ canvas.drawRect(0, 0, Math.round(getScaledWidth() * Math.min(Math.max(progr, 0), 1)), 3, paint);
+ }
+
+ private void _ifIIV(int j, int k) {
+ if (!getGDActivity().isMenuShown()) {
+ byte byte0 = 0;
+ byte byte1 = 0;
+ m_aiI = j;
+ m_agI = k;
+ int l = j << 16;
+ int i1 = k << 16;
+ int j1 = m_abI / 2 << 16;
+ int k1 = m_dI + 40 << 16;
+ if (m_KZ && m_AZ) {
+ int l1 = FPMath._ifIII(l - j1, i1 - k1);
+ for (l1 += 25735; l1 < 0; l1 += 0x6487e) ;
+ for (; l1 > 0x6487e; l1 -= 0x6487e) ;
+ m_OI = l1;
+ int i2;
+ if ((i2 = 51471) >= l1)
+ byte0 = -1;
+ else if (l1 < (int) ((long) i2 * 0x20000L >> 16)) {
+ byte0 = -1;
+ byte1 = 1;
+ } else if (l1 < (int) ((long) i2 * 0x30000L >> 16))
+ byte1 = 1;
+ else if (l1 < (int) ((long) i2 * 0x40000L >> 16)) {
+ byte0 = 1;
+ byte1 = 1;
+ } else if (l1 < (int) ((long) i2 * 0x50000L >> 16))
+ byte0 = 1;
+ else if (l1 < (int) ((long) i2 * 0x60000L >> 16)) {
+ byte0 = 1;
+ byte1 = -1;
+ } else if (l1 < (int) ((long) i2 * 0x70000L >> 16))
+ byte1 = -1;
+ else if (l1 < (int) ((long) i2 * 0x80000L >> 16)) {
+ byte0 = -1;
+ byte1 = -1;
+ }
+ physEngine._aIIV(byte0, byte1);
+ }
+ }
+ }
+
+ public void _pointerPressedIIV(int j, int k) {
+ if (!getGDActivity().isMenuShown())
+ _ifIIV(j, k);
+ }
+
+ public void _pointerReleasedIIV(int j, int k) {
+ if (!getGDActivity().isMenuShown()) {
+ m_aiI = 0;
+ m_agI = 0;
+ physEngine._nullvV();
+ }
+ }
+
+ public void _pointerDraggedIIV(int j, int k) {
+ if (!getGDActivity().isMenuShown())
+ _ifIIV(j, k);
+ }
+
+ public void setInputOption(int option) {
+ inputOption = option;
+ }
+
+ private void _avV() {
+ for (int j = 0; j < 10; j++)
+ m_LaZ[j] = false;
+
+ for (int k = 0; k < 7; k++)
+ m_aeaZ[k] = false;
+
+ }
+
+ private void _xavV() {
+ int j = 0;
+ int k = 0;
+ int l = inputOption;
+ for (int i1 = 0; i1 < 10; i1++)
+ if (m_LaZ[i1]) {
+ j += m_maaaB[l][i1][0];
+ k += m_maaaB[l][i1][1];
+ }
+
+ for (int j1 = 0; j1 < 7; j1++)
+ if (m_aeaZ[j1]) {
+ j += m_DaaB[j1][0];
+ k += m_DaaB[j1][1];
+ }
+
+ physEngine._aIIV(j, k);
+ }
+
+ protected void processKeyPressed(int j) {
+ int k = getGameAction(j);
+ int l;
+ if ((l = j - 48) >= 0 && l < 10)
+ m_LaZ[l] = true;
+ else if (k >= 0 && k < 7)
+ m_aeaZ[k] = true;
+ _xavV();
+ }
+
+ protected void processKeyReleased(int j) {
+ int k = getGameAction(j);
+ int l;
+ if ((l = j - 48) >= 0 && l < 10)
+ m_LaZ[l] = false;
+ else if (k >= 0 && k < 7)
+ m_aeaZ[k] = false;
+ _xavV();
+ }
+
+ public void showMenu() {
+ if (menu != null) {
+ menu.m_blZ = true;
+ getGDActivity().gameToMenu();
+ }
+ }
+
+ /* protected void hideNotify() {
+ if (!getGDActivity().isMenuShown()) {
+ GDActivity.m_cZ = true;
+ activity.gameToMenu();
+ }
+ } */
+
+ /* protected void showNotify() {
+ GDActivity.m_cZ = false;
+ } */
+
+ protected void keyRepeated(int j) {
+ if (getGDActivity().isMenuShown() && menu != null)
+ menu._tryIV(j);
+ }
+
+ public synchronized void keyPressed(int j) {
+ if (getGDActivity().isMenuShown() && menu != null)
+ menu.keyPressed(j);
+ processKeyPressed(j);
+ }
+
+ public synchronized void keyReleased(int j) {
+ processKeyReleased(j);
+ }
+
+ @Override
+ public void onDraw(Canvas g) {
+ g.save();
+ if (!Global.DISABLE_SCALING)
+ g.scale(Global.density, Global.density);
+ if (getGDActivity().isMenuShown() && menu != null) {
+ menu.draw(g);
+ } else {
+ drawGame(g);
+ }
+ g.restore();
+ invalidate();
+ }
+
+ public void commandAction(Command command) {
+ if (getGDActivity().isMenuShown() && menu != null) {
+ menu.onCommand(command);
+ } else {
+ showMenu();
+ }
+ }
+
+ public void removeMenuCommand() {
+ removeCommand(menuCommand);
+ }
+
+ public void addMenuCommand() {
+ addCommand(menuCommand);
+ }
+
+ public static int getGameAction(int key) {
+ // logDebug("getGameAction: key = " + key);
+ switch (key) {
+ case 50: // 2
+ return MenuScreen.KEY_UP; // up
+ case 56: // 8
+ return MenuScreen.KEY_DOWN; // down
+ case 52: // 4
+ return MenuScreen.KEY_LEFT; // left
+ case 54: // 6
+ return MenuScreen.KEY_RIGHT; // right
+ case 53: // 5
+ return MenuScreen.KEY_FIRE; // fire
+ }
+ return 0;
+ }
+
+ public void addCommand(Command cmd) {
+ GDActivity.shared.addCommand(cmd);
+ }
+
+ public void removeCommand(Command cmd) {
+ GDActivity.shared.removeCommand(cmd);
+ }
+
+ public int getScaledWidth() {
+ float density = Global.DISABLE_SCALING ? 1 : Global.density;
+ return Math.round(getWidth() / density);
+ }
+
+ public int getScaledHeight() {
+ float density = Global.DISABLE_SCALING ? 1 : Global.density;
+ return Math.round(getHeight() / density);
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = MeasureSpec.getSize(widthMeasureSpec), height = MeasureSpec.getSize(heightMeasureSpec);
+ setMeasuredDimension(width, height);
+ }
+
+ public synchronized void destroy() {
+ if (timer != null) {
+ timer.cancel();
+ timer.purge();
+ timer = null;
+ }
+ }
+
+}
diff --git a/src/org/happysanta/gd/Game/Physics.java b/src/org/happysanta/gd/Game/Physics.java
new file mode 100755
index 0000000..d6e25b3
--- /dev/null
+++ b/src/org/happysanta/gd/Game/Physics.java
@@ -0,0 +1,1336 @@
+package org.happysanta.gd.Game;
+
+// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
+// Jad home page: http://www.kpdus.com/jad.html
+// Decompiler options: packimports(3) fieldsfirst ansi
+
+
+import org.happysanta.gd.Levels.Loader;
+import org.happysanta.gd.Menu.SimpleMenuElement;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getLevelLoader;
+
+public class Physics {
+
+ /*public static final int m_agI = 1;
+ //public static final int m_byteI;
+ public static final int m_ahI = 1;
+ public static final int m_LI = 2;
+ public static final int m_uI = 3;
+ //public static final int m_aI;
+ public static final int m_VI = 1;
+ public static final int m_BI = 2;
+ public static final int m_acI = 3;
+ public static final int m_newI = 4;
+ public static final int m_ZI = 5 */
+ public static int m_YI;
+ public static int m_voidI;
+ public static int m_gI;
+ public static int m_fI;
+ public static int m_eI;
+ public static int m_aeI;
+ public static int m_adI;
+ public static int m_yI;
+ public static int m_qI;
+ public static int m_xI;
+ public static int m_foraI[] = {
+ 0x1c000, 0x10000, 32768
+ };
+ public static int m_PI;
+ public static int m_jI;
+ public static int m_QI;
+ public static int m_charI;
+ public static int m_abI;
+ public static int m_WI;
+ public static int m_AI;
+ public static int m_longI;
+ public static int m_hI = 0;
+ // private final int m_pI = 3276;
+ private final int m_KaaI[][] = {
+ {
+ 0x2cccc, -52428
+ }, {
+ 0x40000, 0xfffd8000
+ }, {
+ 0x63333, 0xffff0000
+ }, {
+ 0x6cccc, -39321
+ }, {
+ 0x39999, 39321
+ }, {
+ 16384, 0xfffdcccd
+ }, {
+ 13107, 0xfffecccd
+ }, {
+ 0x46666, 0x14000
+ }
+ };
+ private final int m_ucaaI[][] = {
+ {
+ 0x2e666, 0xfffe4ccd
+ }, {
+ 0x4b333, 0xfffc6667
+ }, {
+ 0x51999, 0xfffe4000
+ }, {
+ 0x60000, -58982
+ }, {
+ 0x40000, 0x18000
+ }, {
+ 0x10000, 0xfffe199a
+ }, {
+ 13107, 0xfffecccd
+ }, {
+ 0x46666, 0x14000
+ }
+ };
+ private final int m_SaaI[][] = {
+ {
+ 0x26666, 13107
+ }, {
+ 0x48000, -13107
+ }, {
+ 0x59999, 0x16666
+ }, {
+ 0x63333, 0x2e666
+ }, {
+ 0x54ccc, 0x11999
+ }, {
+ 39321, 0xfffe8000
+ }, {
+ 13107, -52428
+ }, {
+ 0x48000, 0x14000
+ }
+ };
+ private final int m_wcaaI[][] = {
+ {
+ 0x2cccc, -39321
+ }, {
+ 0x40000, 0xfffe0000
+ }, {
+ 0x60000, 0xffff0000
+ }, {
+ 0x70000, -39321
+ }, {
+ 0x48000, 6553
+ }, {
+ 16384, 0xfffdcccd
+ }, {
+ 13107, 0xfffecccd
+ }, {
+ 0x46666, 0x14ccc
+ }
+ };
+ private final int m_DaaI[][] = {
+ {
+ 0x2e666, 0xfffe999a
+ }, {
+ 0x3e666, 0xfffc6667
+ }, {
+ 0x51999, 0xfffe4000
+ }, {
+ 0x60000, -42598
+ }, {
+ 0x49999, 6553
+ }, {
+ 0x10000, 0xfffecccd
+ }, {
+ 13107, 0xfffecccd
+ }, {
+ 0x46666, 0x14ccc
+ }
+ };
+ private final int m_MaaI[][] = {
+ {
+ 0x26666, 13107
+ }, {
+ 0x48000, -13107
+ }, {
+ 0x59999, 0x19999
+ }, {
+ 0x63333, 0x2b333
+ }, {
+ 0x54ccc, 0x11999
+ }, {
+ 39321, 0xfffe8000
+ }, {
+ 13107, -52428
+ }, {
+ 0x46666, 0x14ccc
+ }
+ };
+ public k m_Hak[];
+ public boolean m_bZ;
+ public int m_zI;
+ public boolean m_elseZ;
+ public boolean m_UZ;
+ public boolean m_NZ;
+ SimpleMenuElement m_aaan[];
+ private int m_vaI;
+ private int m_waI;
+ private int m_xaI;
+ private SimpleMenuElement m_ian[];
+ private int m_cI;
+ private Loader m_lf;
+ private int m_EI;
+ private int m_CI;
+ private boolean m_IZ;
+ private boolean m_mZ;
+ private int m_TI;
+ private int m_kI;
+ private boolean m_vZ;
+ private boolean m_afZ;
+ private int m_tI;
+ private boolean m_dZ;
+ private boolean m_FZ;
+ private boolean m_XZ;
+ private boolean m_wZ;
+ private boolean m_ifZ;
+ private boolean m_sZ;
+ private boolean m_OZ;
+ private boolean m_rZ;
+ private boolean m_RZ;
+ private boolean m_doZ;
+ private int m_oI;
+ private int m_nI;
+ private int m_GI;
+ private int m_JaaI[][] = {
+ {
+ 45875
+ }, {
+ 32768
+ }, {
+ 52428
+ }
+ };
+ private final int leftWheelUpdatingFrequency = 20;
+ private long leftWheelLastUpdated = 0;
+ private int leftWheelParams[][];
+
+ public Physics(Loader f1) {
+ m_vaI = 0;
+ m_waI = 1;
+ m_xaI = -1;
+ m_cI = 0;
+ m_EI = 0;
+ m_CI = 0;
+ m_IZ = false;
+ m_mZ = false;
+ m_TI = 32768;
+ m_kI = 0;
+ m_vZ = false;
+ m_bZ = false;
+ m_afZ = false;
+ m_aaan = new SimpleMenuElement[6];
+ for (int j = 0; j < 6; j++)
+ m_aaan[j] = new SimpleMenuElement();
+
+ m_tI = 0;
+ m_zI = 0;
+ m_elseZ = false;
+ m_UZ = false;
+ m_dZ = false;
+ m_FZ = false;
+ m_XZ = false;
+ m_wZ = false;
+ m_ifZ = false;
+ m_sZ = false;
+ m_OZ = false;
+ m_rZ = false;
+ m_RZ = false;
+ m_NZ = false;
+ m_doZ = true;
+ m_oI = 0;
+ m_nI = 0;
+ m_GI = 0xa0000;
+ m_lf = f1;
+ _doZV(true);
+ m_vZ = false;
+ _charvV();
+ m_IZ = false;
+
+ leftWheelParams = new int[5][4];
+ }
+
+ public static int _doIII(int j, int i1) {
+ int j1 = j >= 0 ? j : -j;
+ int k1;
+ int l1;
+ int i2;
+ if ((k1 = i1 >= 0 ? i1 : -i1) >= j1) {
+ l1 = k1;
+ i2 = j1;
+ } else {
+ l1 = j1;
+ i2 = k1;
+ }
+ return (int) (64448L * (long) l1 >> 16) + (int) (28224L * (long) i2 >> 16);
+ }
+
+ public int _bytevI() {
+ if (m_elseZ && m_UZ)
+ return 3;
+ if (m_UZ)
+ return 1;
+ return !m_elseZ ? 0 : 2;
+ }
+
+ public void _doIV(int j) {
+ m_elseZ = false;
+ m_UZ = false;
+ if ((j & 2) != 0)
+ m_elseZ = true;
+ if ((j & 1) != 0)
+ m_UZ = true;
+ }
+
+ public void _byteIV(int j) {
+ m_zI = j;
+ switch (j) {
+ case 1: // '\001'
+ default:
+ m_YI = 1310;
+ break;
+ }
+ m_voidI = 0x190000;
+ setLeague(1);
+ _doZV(true);
+ }
+
+ public void setLeague(int j) {
+ m_hI = j;
+ m_gI = 45875;
+ m_fI = 13107;
+ m_eI = 39321;
+ m_yI = 0x140000;
+ m_xI = 0x40000;
+ m_jI = 6553;
+ switch (j) {
+ case 3: // '\003'
+ m_aeI = 32768;
+ m_adI = 32768;
+ m_PI = 0x160000;
+ m_QI = 0x4b00000;
+ m_charI = 0x360000;
+ m_abI = 6553;
+ m_WI = 26214;
+ m_AI = 0x10000;
+ m_longI = 0x140000;
+ m_qI = 0x14a0000;
+ break;
+
+ case 2: // '\002'
+ m_aeI = 32768;
+ m_adI = 32768;
+ m_PI = 0x140000;
+ m_QI = 0x47e0000;
+ m_charI = 0x350000;
+ m_abI = 6553;
+ m_WI = 26214;
+ m_AI = 39321;
+ m_longI = 0x50000;
+ m_qI = 0x14a0000;
+ break;
+
+ case 1: // '\001'
+ m_aeI = 32768;
+ m_adI = 32768;
+ m_PI = 0x110000;
+ m_QI = 0x3e80000;
+ m_charI = 0x320000;
+ m_abI = 6553;
+ m_WI = 26214;
+ m_AI = 26214;
+ m_longI = 0x50000;
+ m_qI = 0x12c0000;
+ break;
+
+ case 0: // '\0'
+ default:
+ m_aeI = 19660;
+ m_adI = 19660;
+ m_PI = 0x110000;
+ m_QI = 0x3200000;
+ m_charI = 0x320000;
+ m_abI = 327;
+ m_WI = 0;
+ m_AI = 32768;
+ m_longI = 0x50000;
+ m_qI = 0x12c0000;
+ break;
+ }
+ _doZV(true);
+ }
+
+ public void _doZV(boolean flag) {
+ m_tI = 0;
+ _iIIV(m_lf._newvI(), m_lf._avI());
+ m_cI = 0;
+ m_kI = 0;
+ m_IZ = false;
+ m_mZ = false;
+ m_RZ = false;
+ m_NZ = false;
+ m_vZ = false;
+ m_bZ = false;
+ m_afZ = false;
+ m_lf.levels._aIIV((m_Hak[2].m_ifan[5].x + 0x18000) - m_foraI[0], (m_Hak[1].m_ifan[5].x - 0x18000) + m_foraI[0]);
+ }
+
+ public void _aZV(boolean flag) {
+ int j = (flag ? 0x10000 : 0xffff0000) << 1;
+ for (int i1 = 0; i1 < 6; i1++) {
+ for (int j1 = 0; j1 < 6; j1++)
+ m_Hak[i1].m_ifan[j1].y += j;
+ }
+
+ }
+
+ private void _iIIV(int j, int i1) {
+ if (m_Hak == null)
+ m_Hak = new k[6];
+ if (m_ian == null)
+ m_ian = new SimpleMenuElement[10];
+ int l1 = 0;
+ int i2 = 0;
+ int j2 = 0;
+ int k2 = 0;
+ for (int j1 = 0; j1 < 6; j1++) {
+ int l2 = 0;
+ switch (j1) {
+ case 0: // '\0'
+ i2 = 1;
+ l1 = 0x58000;
+ j2 = 0;
+ k2 = 0;
+ break;
+
+ case 4: // '\004'
+ i2 = 1;
+ l1 = 0x38000;
+ j2 = 0xfffe0000;
+ k2 = 0x30000;
+ break;
+
+ case 3: // '\003'
+ i2 = 1;
+ l1 = 0x38000;
+ j2 = 0x20000;
+ k2 = 0x30000;
+ break;
+
+ case 1: // '\001'
+ i2 = 0;
+ l1 = 0x18000;
+ j2 = 0x38000;
+ k2 = 0;
+ break;
+
+ case 2: // '\002'
+ i2 = 0;
+ l1 = 0x58000;
+ j2 = 0xfffc8000;
+ k2 = 0;
+ l2 = 21626;
+ break;
+
+ case 5: // '\005'
+ i2 = 2;
+ l1 = 0x48000;
+ j2 = 0;
+ k2 = 0x50000;
+ break;
+ }
+ if (m_Hak[j1] == null)
+ m_Hak[j1] = new k();
+ m_Hak[j1]._avV();
+ m_Hak[j1].m_aI = m_foraI[i2];
+ m_Hak[j1].m_intI = i2;
+ m_Hak[j1].m_forI = (int) ((long) (int) (0x1000000000000L / (long) l1 >> 16) * (long) m_yI >> 16);
+ m_Hak[j1].m_ifan[m_vaI].x = j + j2;
+ m_Hak[j1].m_ifan[m_vaI].y = i1 + k2;
+ m_Hak[j1].m_ifan[5].x = j + j2;
+ m_Hak[j1].m_ifan[5].y = i1 + k2;
+ m_Hak[j1].m_newI = l2;
+ }
+
+ for (int k1 = 0; k1 < 10; k1++) {
+ if (m_ian[k1] == null)
+ m_ian[k1] = new SimpleMenuElement();
+ m_ian[k1].init();
+ m_ian[k1].x = m_qI;
+ m_ian[k1].m_bI = m_xI;
+ }
+
+ m_ian[0].y = 0x38000;
+ m_ian[1].y = 0x38000;
+ m_ian[2].y = 0x39b05;
+ m_ian[3].y = 0x39b05;
+ m_ian[4].y = 0x40000;
+ m_ian[5].y = 0x35aa6;
+ m_ian[6].y = 0x35aa6;
+ m_ian[7].y = 0x2d413;
+ m_ian[8].y = 0x2d413;
+ m_ian[9].y = 0x50000;
+ m_ian[5].m_bI = (int) ((long) m_xI * 45875L >> 16);
+ m_ian[6].x = (int) (6553L * (long) m_qI >> 16);
+ m_ian[5].x = (int) (6553L * (long) m_qI >> 16);
+ m_ian[9].x = (int) (0x11999L * (long) m_qI >> 16);
+ m_ian[8].x = (int) (0x11999L * (long) m_qI >> 16);
+ m_ian[7].x = (int) (0x11999L * (long) m_qI >> 16);
+ }
+
+ public void _ifIIV(int j, int i1) {
+ m_lf._ifIIV(j, i1);
+ }
+
+ public void _nullvV() {
+ m_ifZ = m_sZ = m_rZ = m_OZ = false;
+ }
+
+ public void _aIIV(int j, int i1) {
+ if (!m_vZ) {
+ m_ifZ = m_sZ = m_rZ = m_OZ = false;
+ if (j > 0)
+ m_ifZ = true;
+ else if (j < 0)
+ m_sZ = true;
+ if (i1 > 0) {
+ m_rZ = true;
+ return;
+ }
+ if (i1 < 0)
+ m_OZ = true;
+ }
+ }
+
+ public synchronized void _casevV() {
+ _doZV(true);
+ m_vZ = true;
+ }
+
+ public synchronized void _avV() {
+ m_vZ = false;
+ }
+
+ public boolean _gotovZ() {
+ return m_vZ;
+ }
+
+ private void _pvV() {
+ int j = m_Hak[1].m_ifan[m_vaI].x - m_Hak[2].m_ifan[m_vaI].x;
+ int i1 = m_Hak[1].m_ifan[m_vaI].y - m_Hak[2].m_ifan[m_vaI].y;
+ int j1 = _doIII(j, i1);
+ int _tmp = (int) (((long) j << 32) / (long) j1 >> 16);
+ i1 = (int) (((long) i1 << 32) / (long) j1 >> 16);
+ m_FZ = false;
+ if (i1 < 0) {
+ m_XZ = true;
+ m_wZ = false;
+ } else if (i1 > 0) {
+ m_wZ = true;
+ m_XZ = false;
+ }
+ boolean flag;
+ if ((flag = (m_Hak[2].m_ifan[m_vaI].y - m_Hak[0].m_ifan[m_vaI].y <= 0 ? -1 : 1) * (m_Hak[2].m_ifan[m_vaI].m_eI - m_Hak[0].m_ifan[m_vaI].m_eI <= 0 ? -1 : 1) > 0) && m_wZ || !flag && m_XZ) {
+ m_dZ = true;
+ return;
+ } else {
+ m_dZ = false;
+ return;
+ }
+ }
+
+ private void _qvV() {
+ if (!m_IZ) {
+ int j = m_Hak[1].m_ifan[m_vaI].x - m_Hak[2].m_ifan[m_vaI].x;
+ int i1 = m_Hak[1].m_ifan[m_vaI].y - m_Hak[2].m_ifan[m_vaI].y;
+ int j1 = _doIII(j, i1);
+ j = (int) (((long) j << 32) / (long) j1 >> 16);
+ i1 = (int) (((long) i1 << 32) / (long) j1 >> 16);
+ if (m_dZ && m_cI >= -m_QI)
+ m_cI -= m_charI;
+ if (m_FZ) {
+ m_cI = 0;
+ m_Hak[1].m_ifan[m_vaI].m_gotoI = (int) ((long) m_Hak[1].m_ifan[m_vaI].m_gotoI * (long) (0x10000 - m_abI) >> 16);
+ m_Hak[2].m_ifan[m_vaI].m_gotoI = (int) ((long) m_Hak[2].m_ifan[m_vaI].m_gotoI * (long) (0x10000 - m_abI) >> 16);
+ if (m_Hak[1].m_ifan[m_vaI].m_gotoI < 6553)
+ m_Hak[1].m_ifan[m_vaI].m_gotoI = 0;
+ if (m_Hak[2].m_ifan[m_vaI].m_gotoI < 6553)
+ m_Hak[2].m_ifan[m_vaI].m_gotoI = 0;
+ }
+ m_Hak[0].m_forI = (int) (11915L * (long) m_yI >> 16);
+ m_Hak[0].m_forI = (int) (11915L * (long) m_yI >> 16);
+ m_Hak[4].m_forI = (int) (18724L * (long) m_yI >> 16);
+ m_Hak[3].m_forI = (int) (18724L * (long) m_yI >> 16);
+ m_Hak[1].m_forI = (int) (43690L * (long) m_yI >> 16);
+ m_Hak[2].m_forI = (int) (11915L * (long) m_yI >> 16);
+ m_Hak[5].m_forI = (int) (14563L * (long) m_yI >> 16);
+ if (m_XZ) {
+ m_Hak[0].m_forI = (int) (18724L * (long) m_yI >> 16);
+ m_Hak[4].m_forI = (int) (14563L * (long) m_yI >> 16);
+ m_Hak[3].m_forI = (int) (18724L * (long) m_yI >> 16);
+ m_Hak[1].m_forI = (int) (43690L * (long) m_yI >> 16);
+ m_Hak[2].m_forI = (int) (10082L * (long) m_yI >> 16);
+ } else if (m_wZ) {
+ m_Hak[0].m_forI = (int) (18724L * (long) m_yI >> 16);
+ m_Hak[4].m_forI = (int) (18724L * (long) m_yI >> 16);
+ m_Hak[3].m_forI = (int) (14563L * (long) m_yI >> 16);
+ m_Hak[1].m_forI = (int) (26214L * (long) m_yI >> 16);
+ m_Hak[2].m_forI = (int) (11915L * (long) m_yI >> 16);
+ }
+ if (m_XZ || m_wZ) {
+ int k1 = -i1;
+ int l1 = j;
+ if (m_XZ && m_kI > -m_longI) {
+ int i2 = 0x10000;
+ if (m_kI < 0)
+ i2 = (int) (((long) (m_longI - (m_kI >= 0 ? m_kI : -m_kI)) << 32) / (long) m_longI >> 16);
+ int k2 = (int) ((long) m_AI * (long) i2 >> 16);
+ int i3 = (int) ((long) k1 * (long) k2 >> 16);
+ int k3 = (int) ((long) l1 * (long) k2 >> 16);
+ int i4 = (int) ((long) j * (long) k2 >> 16);
+ int k4 = (int) ((long) i1 * (long) k2 >> 16);
+ if (m_TI > 32768)
+ m_TI = m_TI - 1638 >= 0 ? m_TI - 1638 : 0;
+ else
+ m_TI = m_TI - 3276 >= 0 ? m_TI - 3276 : 0;
+ m_Hak[4].m_ifan[m_vaI].m_eI -= i3;
+ m_Hak[4].m_ifan[m_vaI].m_dI -= k3;
+ m_Hak[3].m_ifan[m_vaI].m_eI += i3;
+ m_Hak[3].m_ifan[m_vaI].m_dI += k3;
+ m_Hak[5].m_ifan[m_vaI].m_eI -= i4;
+ m_Hak[5].m_ifan[m_vaI].m_dI -= k4;
+ }
+ if (m_wZ && m_kI < m_longI) {
+ int j2 = 0x10000;
+ if (m_kI > 0)
+ j2 = (int) (((long) (m_longI - m_kI) << 32) / (long) m_longI >> 16);
+ int l2 = (int) ((long) m_AI * (long) j2 >> 16);
+ int j3 = (int) ((long) k1 * (long) l2 >> 16);
+ int l3 = (int) ((long) l1 * (long) l2 >> 16);
+ int j4 = (int) ((long) j * (long) l2 >> 16);
+ int l4 = (int) ((long) i1 * (long) l2 >> 16);
+ if (m_TI > 32768)
+ m_TI = m_TI + 1638 >= 0x10000 ? 0x10000 : m_TI + 1638;
+ else
+ m_TI = m_TI + 3276 >= 0x10000 ? 0x10000 : m_TI + 3276;
+ m_Hak[4].m_ifan[m_vaI].m_eI += j3;
+ m_Hak[4].m_ifan[m_vaI].m_dI += l3;
+ m_Hak[3].m_ifan[m_vaI].m_eI -= j3;
+ m_Hak[3].m_ifan[m_vaI].m_dI -= l3;
+ m_Hak[5].m_ifan[m_vaI].m_eI += j4;
+ m_Hak[5].m_ifan[m_vaI].m_dI += l4;
+ }
+ return;
+ }
+ if (m_TI < 26214) {
+ m_TI += 3276;
+ return;
+ }
+ if (m_TI > 39321) {
+ m_TI -= 3276;
+ return;
+ }
+ m_TI = 32768;
+ }
+ }
+
+ public synchronized int _dovI() {
+ m_dZ = m_ifZ;
+ m_FZ = m_sZ;
+ m_XZ = m_OZ;
+ m_wZ = m_rZ;
+ if (m_vZ)
+ _pvV();
+ GameView._dovV();
+ _qvV();
+ int j;
+ if ((j = _uII(m_YI)) == 5 || m_mZ)
+ return 5;
+ if (m_IZ)
+ return 3;
+ if (_newvZ()) {
+ m_NZ = false;
+ return 4;
+ } else {
+ return j;
+ }
+ }
+
+ public boolean _newvZ() {
+ return m_Hak[1].m_ifan[m_vaI].x < m_lf._intvI();
+ }
+
+ public boolean _longvZ() {
+ return m_Hak[1].m_ifan[m_waI].x > m_lf._dovI() || m_Hak[2].m_ifan[m_waI].x > m_lf._dovI();
+ }
+
+ private int _uII(int j) {
+ boolean flag = m_RZ;
+ int i1 = 0;
+ int j1 = j;
+ int j2;
+ do {
+ if (i1 >= j)
+ break;
+ _aaIV(j1 - i1);
+ int k1;
+ if (!flag && _longvZ())
+ k1 = 3;
+ else
+ k1 = _baII(m_waI);
+ if (!flag && m_RZ)
+ return k1 == 3 ? 1 : 2;
+ if (k1 == 0) {
+ if (((j1 = i1 + j1 >> 1) - i1 >= 0 ? j1 - i1 : -(j1 - i1)) < 65)
+ return 5;
+ } else if (k1 == 3) {
+ m_RZ = true;
+ j1 = i1 + j1 >> 1;
+ } else {
+ int i2;
+ if (k1 == 1)
+ do {
+ _caIV(m_waI);
+ j2 = _baII(m_waI);
+ i2 = j2;
+ if (j2 == 0)
+ return 5;
+ } while (i2 != 2);
+ i1 = j1;
+ j1 = j;
+ m_vaI = m_vaI != 1 ? 1 : 0;
+ m_waI = m_waI != 1 ? 1 : 0;
+ }
+ } while (true);
+ int l1;
+ if ((l1 = (int) ((long) (m_Hak[1].m_ifan[m_vaI].x - m_Hak[2].m_ifan[m_vaI].x) * (long) (m_Hak[1].m_ifan[m_vaI].x - m_Hak[2].m_ifan[m_vaI].x) >> 16) + (int) ((long) (m_Hak[1].m_ifan[m_vaI].y - m_Hak[2].m_ifan[m_vaI].y) * (long) (m_Hak[1].m_ifan[m_vaI].y - m_Hak[2].m_ifan[m_vaI].y) >> 16)) < 0xf0000)
+ m_IZ = true;
+ if (l1 > 0x460000)
+ m_IZ = true;
+ return 0;
+ }
+
+ private void _aIV(int j) {
+ for (int i1 = 0; i1 < 6; i1++) {
+ k k1;
+ SimpleMenuElement n1;
+ (n1 = (k1 = m_Hak[i1]).m_ifan[j]).m_nullI = 0;
+ n1.m_longI = 0;
+ n1.m_fI = 0;
+ n1.m_longI -= (int) (((long) m_voidI << 32) / (long) k1.m_forI >> 16);
+ }
+
+ if (!m_IZ) {
+ _akkV(m_Hak[0], m_ian[1], m_Hak[2], j, 0x10000);
+ _akkV(m_Hak[0], m_ian[0], m_Hak[1], j, 0x10000);
+ _akkV(m_Hak[2], m_ian[6], m_Hak[4], j, 0x20000);
+ _akkV(m_Hak[1], m_ian[5], m_Hak[3], j, 0x20000);
+ }
+ _akkV(m_Hak[0], m_ian[2], m_Hak[3], j, 0x10000);
+ _akkV(m_Hak[0], m_ian[3], m_Hak[4], j, 0x10000);
+ _akkV(m_Hak[3], m_ian[4], m_Hak[4], j, 0x10000);
+ _akkV(m_Hak[5], m_ian[8], m_Hak[3], j, 0x10000);
+ _akkV(m_Hak[5], m_ian[7], m_Hak[4], j, 0x10000);
+ _akkV(m_Hak[5], m_ian[9], m_Hak[0], j, 0x10000);
+ SimpleMenuElement n2 = m_Hak[2].m_ifan[j];
+ m_cI = (int) ((long) m_cI * (long) (0x10000 - m_jI) >> 16);
+ n2.m_fI = m_cI;
+ if (n2.m_gotoI > m_PI)
+ n2.m_gotoI = m_PI;
+ if (n2.m_gotoI < -m_PI)
+ n2.m_gotoI = -m_PI;
+ int j1 = 0;
+ int l1 = 0;
+ for (int i2 = 0; i2 < 6; i2++) {
+ j1 += m_Hak[i2].m_ifan[j].m_eI;
+ l1 += m_Hak[i2].m_ifan[j].m_dI;
+ }
+
+ j1 = (int) (((long) j1 << 32) / 0x60000L >> 16);
+ l1 = (int) (((long) l1 << 32) / 0x60000L >> 16);
+ int j3 = 0;
+ for (int k3 = 0; k3 < 6; k3++) {
+ int j2 = m_Hak[k3].m_ifan[j].m_eI - j1;
+ int k2 = m_Hak[k3].m_ifan[j].m_dI - l1;
+ if ((j3 = _doIII(j2, k2)) > 0x1e0000) {
+ int l2 = (int) (((long) j2 << 32) / (long) j3 >> 16);
+ int i3 = (int) (((long) k2 << 32) / (long) j3 >> 16);
+ m_Hak[k3].m_ifan[j].m_eI -= l2;
+ m_Hak[k3].m_ifan[j].m_dI -= i3;
+ }
+ }
+
+ byte byte0 = ((byte) (m_Hak[2].m_ifan[j].y - m_Hak[0].m_ifan[j].y < 0 ? -1 : 1));
+ byte byte1 = ((byte) (m_Hak[2].m_ifan[j].m_eI - m_Hak[0].m_ifan[j].m_eI < 0 ? -1 : 1));
+ if (byte0 * byte1 > 0) {
+ m_kI = j3;
+ return;
+ } else {
+ m_kI = -j3;
+ return;
+ }
+ }
+
+ private void _akkV(k k1, SimpleMenuElement n1, k k2, int j, int i1) {
+ SimpleMenuElement n2 = k1.m_ifan[j];
+ SimpleMenuElement n3 = k2.m_ifan[j];
+ int j1 = n2.x - n3.x;
+ int l1 = n2.y - n3.y;
+ int i2;
+ if (((i2 = _doIII(j1, l1)) >= 0 ? i2 : -i2) >= 3) {
+ j1 = (int) (((long) j1 << 32) / (long) i2 >> 16);
+ l1 = (int) (((long) l1 << 32) / (long) i2 >> 16);
+ int j2 = i2 - n1.y;
+ int l2 = (int) ((long) j1 * (long) (int) ((long) j2 * (long) n1.x >> 16) >> 16);
+ int i3 = (int) ((long) l1 * (long) (int) ((long) j2 * (long) n1.x >> 16) >> 16);
+ int j3 = n2.m_eI - n3.m_eI;
+ int k3 = n2.m_dI - n3.m_dI;
+ int l3 = (int) ((long) ((int) ((long) j1 * (long) j3 >> 16) + (int) ((long) l1 * (long) k3 >> 16)) * (long) n1.m_bI >> 16);
+ l2 += (int) ((long) j1 * (long) l3 >> 16);
+ i3 += (int) ((long) l1 * (long) l3 >> 16);
+ l2 = (int) ((long) l2 * (long) i1 >> 16);
+ i3 = (int) ((long) i3 * (long) i1 >> 16);
+ n2.m_nullI -= l2;
+ n2.m_longI -= i3;
+ n3.m_nullI += l2;
+ n3.m_longI += i3;
+ }
+ }
+
+ private void _aIIV(int j, int i1, int j1) {
+ for (int l1 = 0; l1 < 6; l1++) {
+ SimpleMenuElement n1 = m_Hak[l1].m_ifan[j];
+ SimpleMenuElement n2;
+ (n2 = m_Hak[l1].m_ifan[i1]).x = (int) ((long) n1.m_eI * (long) j1 >> 16);
+ n2.y = (int) ((long) n1.m_dI * (long) j1 >> 16);
+ int k1 = (int) ((long) j1 * (long) m_Hak[l1].m_forI >> 16);
+ n2.m_eI = (int) ((long) n1.m_nullI * (long) k1 >> 16);
+ n2.m_dI = (int) ((long) n1.m_longI * (long) k1 >> 16);
+ }
+
+ }
+
+ private void _zIIV(int j, int i1, int j1) {
+ for (int k1 = 0; k1 < 6; k1++) {
+ SimpleMenuElement n1 = m_Hak[k1].m_ifan[j];
+ SimpleMenuElement n2 = m_Hak[k1].m_ifan[i1];
+ SimpleMenuElement n3 = m_Hak[k1].m_ifan[j1];
+ n1.x = n2.x + (n3.x >> 1);
+ n1.y = n2.y + (n3.y >> 1);
+ n1.m_eI = n2.m_eI + (n3.m_eI >> 1);
+ n1.m_dI = n2.m_dI + (n3.m_dI >> 1);
+ }
+
+ }
+
+ private void _aaIV(int j) {
+ _aIV(m_vaI);
+ _aIIV(m_vaI, 2, j);
+ _zIIV(4, m_vaI, 2);
+ _aIV(4);
+ _aIIV(4, 3, j >> 1);
+ _zIIV(4, m_vaI, 3);
+ _zIIV(m_waI, m_vaI, 2);
+ _zIIV(m_waI, m_waI, 3);
+
+ // wheels?!?!?!?! oh my god i found it!!!!!
+ for (int i1 = 1; i1 <= 2; i1++) {
+ SimpleMenuElement n1 = m_Hak[i1].m_ifan[m_vaI];
+ SimpleMenuElement n2;
+ (n2 = m_Hak[i1].m_ifan[m_waI]).m_bI = n1.m_bI + (int) ((long) j * (long) n1.m_gotoI >> 16);
+ n2.m_gotoI = n1.m_gotoI + (int) ((long) j * (long) (int) ((long) m_Hak[i1].m_newI * (long) n1.m_fI >> 16) >> 16);
+ }
+
+ }
+
+ private int _baII(int j) {
+ byte byte0 = 2;
+ int i1;
+ i1 = (i1 = m_Hak[1].m_ifan[j].x >= m_Hak[2].m_ifan[j].x ? m_Hak[1].m_ifan[j].x : m_Hak[2].m_ifan[j].x) >= m_Hak[5].m_ifan[j].x ? i1 : m_Hak[5].m_ifan[j].x;
+ int j1;
+ j1 = (j1 = m_Hak[1].m_ifan[j].x >= m_Hak[2].m_ifan[j].x ? m_Hak[2].m_ifan[j].x : m_Hak[1].m_ifan[j].x) >= m_Hak[5].m_ifan[j].x ? m_Hak[5].m_ifan[j].x : j1;
+ m_lf._aIIV(j1 - m_foraI[0], i1 + m_foraI[0], m_Hak[5].m_ifan[j].y);
+ int k1 = m_Hak[1].m_ifan[j].x - m_Hak[2].m_ifan[j].x;
+ int l1 = m_Hak[1].m_ifan[j].y - m_Hak[2].m_ifan[j].y;
+ int i2 = _doIII(k1, l1);
+ k1 = (int) (((long) k1 << 32) / (long) i2 >> 16);
+ int j2 = -(int) (((long) l1 << 32) / (long) i2 >> 16);
+ int k2 = k1;
+ for (int l2 = 0; l2 < 6; l2++) {
+ if (l2 == 4 || l2 == 3)
+ continue;
+ SimpleMenuElement n1 = m_Hak[l2].m_ifan[j];
+ if (l2 == 0) {
+ n1.x += (int) ((long) j2 * 0x10000L >> 16);
+ n1.y += (int) ((long) k2 * 0x10000L >> 16);
+ }
+ int i3 = m_lf._anvI(n1, m_Hak[l2].m_intI);
+ if (l2 == 0) {
+ n1.x -= (int) ((long) j2 * 0x10000L >> 16);
+ n1.y -= (int) ((long) k2 * 0x10000L >> 16);
+ }
+ m_EI = m_lf.m_eI;
+ m_CI = m_lf.m_dI;
+ if (l2 == 5 && i3 != 2)
+ m_mZ = true;
+ if (l2 == 1 && i3 != 2)
+ m_NZ = true;
+ if (i3 == 1) {
+ m_xaI = l2;
+ byte0 = 1;
+ continue;
+ }
+ if (i3 != 0)
+ continue;
+ m_xaI = l2;
+ byte0 = 0;
+ break;
+ }
+
+ return byte0;
+ }
+
+ private void _caIV(int j) {
+ k k1;
+ SimpleMenuElement n1;
+ (n1 = (k1 = m_Hak[m_xaI]).m_ifan[j]).x += (int) ((long) m_EI * 3276L >> 16);
+ n1.y += (int) ((long) m_CI * 3276L >> 16);
+ int i1;
+ int j1;
+ int l1;
+ int i2;
+ int j2;
+ if (m_FZ && (m_xaI == 2 || m_xaI == 1) && n1.m_gotoI < 6553) {
+ i1 = m_gI - m_WI;
+ j1 = 13107;
+ l1 = 39321;
+ i2 = 26214 - m_WI;
+ j2 = 26214 - m_WI;
+ } else {
+ i1 = m_gI;
+ j1 = m_fI;
+ l1 = m_eI;
+ i2 = m_aeI;
+ j2 = m_adI;
+ }
+ int k2 = _doIII(m_EI, m_CI);
+ m_EI = (int) (((long) m_EI << 32) / (long) k2 >> 16);
+ m_CI = (int) (((long) m_CI << 32) / (long) k2 >> 16);
+ int l2 = n1.m_eI;
+ int i3 = n1.m_dI;
+ int j3 = -((int) ((long) l2 * (long) m_EI >> 16) + (int) ((long) i3 * (long) m_CI >> 16));
+ int k3 = -((int) ((long) l2 * (long) (-m_CI) >> 16) + (int) ((long) i3 * (long) m_EI >> 16));
+ int l3 = (int) ((long) i1 * (long) n1.m_gotoI >> 16) - (int) ((long) j1 * (long) (int) (((long) k3 << 32) / (long) k1.m_aI >> 16) >> 16);
+ int i4 = (int) ((long) i2 * (long) k3 >> 16) - (int) ((long) l1 * (long) (int) ((long) n1.m_gotoI * (long) k1.m_aI >> 16) >> 16);
+ int j4 = -(int) ((long) j2 * (long) j3 >> 16);
+ int k4 = (int) ((long) (-i4) * (long) (-m_CI) >> 16);
+ int l4 = (int) ((long) (-i4) * (long) m_EI >> 16);
+ int i5 = (int) ((long) (-j4) * (long) m_EI >> 16);
+ int j5 = (int) ((long) (-j4) * (long) m_CI >> 16);
+ n1.m_gotoI = l3;
+ n1.m_eI = k4 + i5;
+ n1.m_dI = l4 + j5;
+ }
+
+ public void _ifZV(boolean flag) {
+ m_doZ = flag;
+ }
+
+ public void _caseIV(int j) {
+ m_GI = (int) (((long) (int) (0xa0000L * (long) (j << 16) >> 16) << 32) / 0x800000L >> 16);
+ }
+
+ public int _elsevI() {
+ if (m_doZ)
+ m_oI = (int) (((long) m_aaan[0].m_eI << 32) / 0x180000L >> 16) + (int) ((long) m_oI * 57344L >> 16);
+ else
+ m_oI = 0;
+ m_oI = m_oI >= m_GI ? m_GI : m_oI;
+ m_oI = m_oI >= -m_GI ? m_oI : -m_GI;
+ return (m_aaan[0].x + m_oI << 2) >> 16;
+ }
+
+ public int _ifvI() {
+ if (m_doZ)
+ m_nI = (int) (((long) m_aaan[0].m_dI << 32) / 0x180000L >> 16) + (int) ((long) m_nI * 57344L >> 16);
+ else
+ m_nI = 0;
+ m_nI = m_nI >= m_GI ? m_GI : m_nI;
+ m_nI = m_nI >= -m_GI ? m_nI : -m_GI;
+ return (m_aaan[0].y + m_nI << 2) >> 16;
+ }
+
+ public int _tryvI() {
+ int j = m_aaan[1].x >= m_aaan[2].x ? m_aaan[1].x : m_aaan[2].x;
+ if (m_IZ)
+ return m_lf._aII(m_aaan[0].x);
+ else
+ return m_lf._aII(j);
+ }
+
+ public void _charvV() {
+ synchronized (m_Hak) {
+ for (int j = 0; j < 6; j++) {
+ m_Hak[j].m_ifan[5].x = m_Hak[j].m_ifan[m_vaI].x;
+ m_Hak[j].m_ifan[5].y = m_Hak[j].m_ifan[m_vaI].y;
+ m_Hak[j].m_ifan[5].m_bI = m_Hak[j].m_ifan[m_vaI].m_bI;
+ }
+
+ m_Hak[0].m_ifan[5].m_eI = m_Hak[0].m_ifan[m_vaI].m_eI;
+ m_Hak[0].m_ifan[5].m_dI = m_Hak[0].m_ifan[m_vaI].m_dI;
+ m_Hak[2].m_ifan[5].m_gotoI = m_Hak[2].m_ifan[m_vaI].m_gotoI;
+ }
+ }
+
+ public void _voidvV() {
+ synchronized (m_Hak) {
+ for (int j = 0; j < 6; j++) {
+ m_aaan[j].x = m_Hak[j].m_ifan[5].x;
+ m_aaan[j].y = m_Hak[j].m_ifan[5].y;
+ m_aaan[j].m_bI = m_Hak[j].m_ifan[5].m_bI;
+ }
+
+ m_aaan[0].m_eI = m_Hak[0].m_ifan[5].m_eI;
+ m_aaan[0].m_dI = m_Hak[0].m_ifan[5].m_dI;
+ m_aaan[2].m_gotoI = m_Hak[2].m_ifan[5].m_gotoI;
+ }
+ }
+
+ private void _aiIV(GameView view, int i1, int j1) {
+ int k1 = FPMath._ifIII(m_aaan[0].x - m_aaan[3].x, m_aaan[0].y - m_aaan[3].y);
+ int l1 = FPMath._ifIII(m_aaan[0].x - m_aaan[4].x, m_aaan[0].y - m_aaan[4].y);
+ int engineX = (m_aaan[0].x >> 1) + (m_aaan[3].x >> 1);
+ int engineY = (m_aaan[0].y >> 1) + (m_aaan[3].y >> 1);
+ int fenderX = (m_aaan[0].x >> 1) + (m_aaan[4].x >> 1);
+ int fenderY = (m_aaan[0].y >> 1) + (m_aaan[4].y >> 1);
+ int i3 = -j1;
+ int j3 = i1;
+ engineX += (int) ((long) i3 * 0x10000L >> 16) - (int) ((long) i1 * 32768L >> 16);
+ engineY += (int) ((long) j3 * 0x10000L >> 16) - (int) ((long) j1 * 32768L >> 16);
+ fenderX += (int) ((long) i3 * 0x10000L >> 16) - (int) ((long) i1 * 0x1ccccL >> 16);
+ fenderY += (int) ((long) j3 * 0x10000L >> 16) - (int) ((long) j1 * 0x20000L >> 16);
+ view.drawFender((fenderX << 2) / (float) 0xFFFF /*>> 16*/, (fenderY << 2) / (float) 0xFFFF /*>> 16*/, l1);
+ view.drawEngine((engineX << 2) / (float) 0xFFFF /*>> 16*/, (engineY << 2) / (float) 0xFFFF /*>> 16*/, k1);
+ }
+
+ private void _laiV(GameView view) {
+ view.setColor(128, 128, 128);
+ view.drawLine(m_aaan[3].x, m_aaan[3].y, m_aaan[1].x, m_aaan[1].y);
+ }
+
+ private void _aiV(GameView gameView) {
+ int i1 = 1;
+ int j1 = 1;
+ switch (m_hI) {
+ case 2: // '\002'
+ case 3: // '\003'
+ i1 = j1 = 0;
+ break;
+
+ case 1: // '\001'
+ i1 = 0;
+ break;
+ }
+ gameView.drawWheel((m_aaan[2].x << 2) / (float) 0xFFFF /*>> 16*/, (m_aaan[2].y << 2) / (float) 0xFFFF /*>> 16*/, i1);
+ gameView.drawWheel((m_aaan[1].x << 2) / (float) 0xFFFF /*>> 16*/, (m_aaan[1].y << 2) / (float) 0xFFFF /*>> 16*/, j1);
+ }
+
+ private void _doiV(GameView gameView) {
+ int i1;
+ int j1 = (int) ((long) (i1 = m_Hak[1].m_aI) * 58982L >> 16);
+ int k1 = (int) ((long) i1 * 45875L >> 16);
+ gameView.setColor(0, 0, 0);
+ if (getGDActivity().isMenuShown()) {
+ gameView.drawLineWheel((m_aaan[1].x << 2) >> 16, (m_aaan[1].y << 2) >> 16, (i1 + i1 << 2) >> 16);
+ gameView.drawLineWheel((m_aaan[1].x << 2) >> 16, (m_aaan[1].y << 2) >> 16, (j1 + j1 << 2) >> 16);
+ gameView.drawLineWheel((m_aaan[2].x << 2) >> 16, (m_aaan[2].y << 2) >> 16, (i1 + i1 << 2) >> 16);
+ gameView.drawLineWheel((m_aaan[2].x << 2) >> 16, (m_aaan[2].y << 2) >> 16, (k1 + k1 << 2) >> 16);
+ }
+
+ // right wheel
+ int l1 = j1;
+ int i2 = 0;
+ int j2;
+ int k2 = FPMath._doII(j2 = m_aaan[1].m_bI);
+ int l2 = FPMath.sin(j2);
+ int i3 = l1;
+ l1 = (int) ((long) k2 * (long) l1 >> 16) + (int) ((long) (-l2) * (long) i2 >> 16);
+ i2 = (int) ((long) l2 * (long) i3 >> 16) + (int) ((long) k2 * (long) i2 >> 16);
+ k2 = FPMath._doII(j2 = 0x141b2);
+ l2 = FPMath.sin(j2);
+ for (int k3 = 0; k3 < 5; k3++) {
+ gameView.drawLine(m_aaan[1].x, m_aaan[1].y, m_aaan[1].x + l1, m_aaan[1].y + i2);
+ i3 = l1;
+ l1 = (int) ((long) k2 * (long) l1 >> 16) + (int) ((long) (-l2) * (long) i2 >> 16);
+ i2 = (int) ((long) l2 * (long) i3 >> 16) + (int) ((long) k2 * (long) i2 >> 16);
+ }
+
+ // left wheel
+ l1 = j1;
+ i2 = 0;
+ // k2 = FPMath._doII(j2 = m_aaan[2].m_bI);
+ k2 = FPMath._doII(j2 = Math.round(m_aaan[2].m_bI / 1.75f));
+ l2 = FPMath.sin(j2);
+ i3 = l1;
+ l1 = (int) ((long) k2 * (long) l1 >> 16) + (int) ((long) (-l2) * (long) i2 >> 16);
+ i2 = (int) ((long) l2 * (long) i3 >> 16) + (int) ((long) k2 * (long) i2 >> 16);
+ k2 = FPMath._doII(j2 = 0x141b2);
+ l2 = FPMath.sin(j2);
+
+ boolean toUpdate = true;
+ for (int l3 = 0; l3 < 5; l3++) {
+ if (toUpdate) {
+ // Log.d("AGDTR", "toUpdate is true");
+ leftWheelParams[l3][0] = m_aaan[2].x;
+ leftWheelParams[l3][1] = m_aaan[2].y;
+ leftWheelParams[l3][2] = m_aaan[2].x + l1;
+ leftWheelParams[l3][3] = m_aaan[2].y + i2;
+ }
+ // gameView.drawLine(m_aaan[2].x, m_aaan[2].y, m_aaan[2].x + l1, m_aaan[2].y + i2);
+ gameView.drawLine(leftWheelParams[l3][0], leftWheelParams[l3][1], leftWheelParams[l3][2], leftWheelParams[l3][3]);
+ int j3 = l1;
+ l1 = (int) ((long) k2 * (long) l1 >> 16) + (int) ((long) (-l2) * (long) i2 >> 16);
+ i2 = (int) ((long) l2 * (long) j3 >> 16) + (int) ((long) k2 * (long) i2 >> 16);
+ }
+ // if (toUpdate) leftWheelLastUpdated = System.currentTimeMillis();
+ // Log.d("AGDTR", "diff: " + (System.currentTimeMillis() - leftWheelLastUpdated));
+
+ if (m_hI > 0) {
+ gameView.setColor(255, 0, 0);
+ if (m_hI > 2)
+ gameView.setColor(100, 100, 255);
+ gameView.drawLineWheel((m_aaan[2].x << 2) / (float) 0xFFFF /*>> 16*/, (m_aaan[2].y << 2) / (float) 0xFFFF /*>> 16*/, 4);
+ gameView.drawLineWheel((m_aaan[1].x << 2) / (float) 0xFFFF /*>> 16*/, (m_aaan[1].y << 2) / (float) 0xFFFF /*>> 16*/, 4);
+ }
+ }
+
+ private void _ifiIIV(GameView j, int i1, int j1, int k1, int l1) {
+ int i2 = 0;
+ int j2 = 0x10000;
+ int k2 = m_aaan[0].x;
+ int l2 = m_aaan[0].y;
+ int i3 = 0;
+ int j3 = 0;
+ int k3 = 0;
+ int l3 = 0;
+ int i4 = 0;
+ int j4 = 0;
+ int k4 = 0;
+ int l4 = 0;
+ int i5 = 0;
+ int j5 = 0;
+ int k5 = 0;
+ int l5 = 0;
+ int i6 = 0;
+ int j6 = 0;
+ int k6 = 0;
+ int l6 = 0;
+ int ai[][] = (int[][]) null;
+ int ai1[][] = (int[][]) null;
+ int ai2[][] = (int[][]) null;
+ if (m_elseZ) {
+ if (m_TI < 32768) {
+ ai1 = m_ucaaI;
+ ai2 = m_KaaI;
+ j2 = (int) ((long) m_TI * 0x20000L >> 16);
+ } else if (m_TI > 32768) {
+ i2 = 1;
+ ai1 = m_KaaI;
+ ai2 = m_SaaI;
+ j2 = (int) ((long) (m_TI - 32768) * 0x20000L >> 16);
+ } else {
+ ai = m_KaaI;
+ }
+ } else if (m_TI < 32768) {
+ ai1 = m_DaaI;
+ ai2 = m_wcaaI;
+ j2 = (int) ((long) m_TI * 0x20000L >> 16);
+ } else if (m_TI > 32768) {
+ i2 = 1;
+ ai1 = m_wcaaI;
+ ai2 = m_MaaI;
+ j2 = (int) ((long) (m_TI - 32768) * 0x20000L >> 16);
+ } else {
+ ai = m_wcaaI;
+ }
+ for (int j7 = 0; j7 < m_KaaI.length; j7++) {
+ int i8;
+ int j8;
+ if (ai1 != null) {
+ j8 = (int) ((long) ai1[j7][0] * (long) (0x10000 - j2) >> 16) + (int) ((long) ai2[j7][0] * (long) j2 >> 16);
+ i8 = (int) ((long) ai1[j7][1] * (long) (0x10000 - j2) >> 16) + (int) ((long) ai2[j7][1] * (long) j2 >> 16);
+ } else {
+ j8 = ai[j7][0];
+ i8 = ai[j7][1];
+ }
+ int k8 = k2 + (int) ((long) k1 * (long) j8 >> 16) + (int) ((long) i1 * (long) i8 >> 16);
+ int l8 = l2 + (int) ((long) l1 * (long) j8 >> 16) + (int) ((long) j1 * (long) i8 >> 16);
+ switch (j7) {
+ case 0: // '\0'
+ k4 = k8;
+ l4 = l8;
+ break;
+
+ case 1: // '\001'
+ i5 = k8;
+ j5 = l8;
+ break;
+
+ case 2: // '\002'
+ k5 = k8;
+ l5 = l8;
+ break;
+
+ case 3: // '\003'
+ i6 = k8;
+ j6 = l8;
+ break;
+
+ case 4: // '\004'
+ k6 = k8;
+ l6 = l8;
+ break;
+
+ case 5: // '\005'
+ k3 = k8;
+ l3 = l8;
+ break;
+
+ case 6: // '\006'
+ i4 = k8;
+ j4 = l8;
+ break;
+
+ case 7: // '\007'
+ i3 = k8;
+ j3 = l8;
+ break;
+ }
+ }
+
+ int i7 = (int) ((long) m_JaaI[i2][0] * (long) (0x10000 - j2) >> 16) + (int) ((long) m_JaaI[i2 + 1][0] * (long) j2 >> 16);
+ if (m_elseZ) {
+ j._aIIIV(k3 << 2, l3 << 2, k4 << 2, l4 << 2, 1);
+ j._aIIIV(k4 << 2, l4 << 2, i5 << 2, j5 << 2, 1);
+ j.drawBikerPart(i5 << 2, j5 << 2, k5 << 2, l5 << 2, 2, i7);
+ j._aIIIV(k5 << 2, l5 << 2, k6 << 2, l6 << 2, 0);
+ int k7 = FPMath._ifIII(i1, j1);
+ if (m_TI > 32768)
+ k7 += 20588;
+ j.drawHelmet((i6 << 2) / (float) 0xFFFF /*>> 16*/, (j6 << 2) / (float) 0xFFFF /*>> 16*/, k7);
+ } else {
+ j.setColor(0, 0, 0);
+ j.drawLine(k3, l3, k4, l4);
+ j.drawLine(k4, l4, i5, j5);
+ j.setColor(0, 0, 128);
+ j.drawLine(i5, j5, k5, l5);
+ j.drawLine(k5, l5, k6, l6);
+ j.drawLine(k6, l6, i3, j3);
+ int l7 = 0x10000;
+ j.setColor(156, 0, 0);
+ j.drawLineWheel((i6 << 2) >> 16, (j6 << 2) >> 16, (l7 + l7 << 2) >> 16);
+ }
+ j.setColor(0, 0, 0);
+ j.drawSteering((i3 << 2) >> 16, (j3 << 2) >> 16);
+ j.drawSteering((i4 << 2) >> 16, (j4 << 2) >> 16);
+ }
+
+ private void _aiIIV(GameView j, int i1, int j1, int k1, int l1) {
+ int i2 = m_aaan[2].x;
+ int j2 = m_aaan[2].y;
+ int k2 = i2 + (int) ((long) k1 * (long) 32768 >> 16);
+ int l2 = j2 + (int) ((long) l1 * (long) 32768 >> 16);
+ int i3 = i2 - (int) ((long) k1 * (long) 32768 >> 16);
+ int j3 = j2 - (int) ((long) l1 * (long) 32768 >> 16);
+ int k3 = m_aaan[0].x + (int) ((long) i1 * 32768L >> 16);
+ int l3 = m_aaan[0].y + (int) ((long) j1 * 32768L >> 16);
+ int i4 = k3 - (int) ((long) i1 * 0x20000L >> 16);
+ int j4 = l3 - (int) ((long) j1 * 0x20000L >> 16);
+ int k4 = i4 + (int) ((long) k1 * 0x10000L >> 16);
+ int l4 = j4 + (int) ((long) l1 * 0x10000L >> 16);
+ int i5 = i4 + (int) ((long) i1 * 49152L >> 16) + (int) ((long) k1 * 49152L >> 16);
+ int j5 = j4 + (int) ((long) j1 * 49152L >> 16) + (int) ((long) l1 * 49152L >> 16);
+ int k5 = i4 + (int) ((long) k1 * 32768L >> 16);
+ int l5 = j4 + (int) ((long) l1 * 32768L >> 16);
+ int i6 = m_aaan[1].x;
+ int j6 = m_aaan[1].y;
+ int k6 = m_aaan[4].x - (int) ((long) i1 * 49152L >> 16);
+ int l6 = m_aaan[4].y - (int) ((long) j1 * 49152L >> 16);
+ int i7 = k6 - (int) ((long) k1 * 32768L >> 16);
+ int j7 = l6 - (int) ((long) l1 * 32768L >> 16);
+ int k7 = (k6 - (int) ((long) i1 * 0x20000L >> 16)) + (int) ((long) k1 * 16384L >> 16);
+ int l7 = (l6 - (int) ((long) j1 * 0x20000L >> 16)) + (int) ((long) l1 * 16384L >> 16);
+ int i8 = m_aaan[3].x;
+ int j8 = m_aaan[3].y;
+ int k8 = i8 + (int) ((long) k1 * 32768L >> 16);
+ int l8 = j8 + (int) ((long) l1 * 32768L >> 16);
+ int i9 = (i8 + (int) ((long) k1 * 0x1c000L >> 16)) - (int) ((long) i1 * 32768L >> 16);
+ int j9 = (j8 + (int) ((long) l1 * 0x1c000L >> 16)) - (int) ((long) j1 * 32768L >> 16);
+ j.setColor(50, 50, 50);
+ j.drawLineWheel((k5 << 2) >> 16, (l5 << 2) >> 16, (32768 + 32768 << 2) >> 16);
+ if (!m_IZ) {
+ j.drawLine(k2, l2, k4, l4);
+ j.drawLine(i3, j3, i4, j4);
+ }
+ j.drawLine(k3, l3, i4, j4);
+ j.drawLine(k3, l3, i8, j8);
+ j.drawLine(i5, j5, k8, l8);
+ j.drawLine(k8, l8, i9, j9);
+ if (!m_IZ) {
+ j.drawLine(i8, j8, i6, j6);
+ j.drawLine(i9, j9, i6, j6);
+ }
+ j.drawLine(k4, l4, i7, j7);
+ j.drawLine(i5, j5, k6, l6);
+ j.drawLine(k6, l6, k7, l7);
+ j.drawLine(i7, j7, k7, l7);
+ }
+
+ public void _ifiV(GameView j) {
+ j._tryvV();
+ int i1 = m_aaan[3].x - m_aaan[4].x;
+ int j1 = m_aaan[3].y - m_aaan[4].y;
+ int k1;
+ if ((k1 = _doIII(i1, j1)) != 0) {
+ i1 = (int) (((long) i1 << 32) / (long) k1 >> 16);
+ j1 = (int) (((long) j1 << 32) / (long) k1 >> 16);
+ }
+ int l1 = -j1;
+ int i2 = i1;
+ if (m_IZ) {
+ int k2 = m_aaan[4].x;
+ int j2;
+ if ((j2 = m_aaan[3].x) >= k2) {
+ int l2 = j2;
+ j2 = k2;
+ k2 = l2;
+ }
+ m_lf.levels._aIIV(j2, k2);
+ }
+
+ Loader loader = getLevelLoader();
+ if (loader != null && loader.isPerspectiveEnabled())
+ m_lf._aiIV(j, m_aaan[0].x, m_aaan[0].y);
+ if (m_UZ)
+ _aiIV(j, i1, j1);
+ if (!getGDActivity().isMenuShown())
+ _aiV(j);
+ _doiV(j);
+ if (m_UZ)
+ j.setColor(170, 0, 0);
+ else
+ j.setColor(50, 50, 50);
+ j._ifIIIV((m_aaan[1].x << 2) >> 16, (m_aaan[1].y << 2) >> 16, (m_foraI[0] << 2) >> 16, FPMath._ifIII(i1, j1));
+ if (!m_IZ)
+ _laiV(j);
+ _ifiIIV(j, i1, j1, l1, i2);
+ if (!m_UZ)
+ _aiIIV(j, i1, j1, l1, i2);
+ m_lf._aiV(j);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Game/k.java b/src/org/happysanta/gd/Game/k.java
new file mode 100755
index 0000000..7a45482
--- /dev/null
+++ b/src/org/happysanta/gd/Game/k.java
@@ -0,0 +1,34 @@
+package org.happysanta.gd.Game;
+
+// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
+// Jad home page: http://www.kpdus.com/jad.html
+// Decompiler options: packimports(3) fieldsfirst ansi
+
+
+import org.happysanta.gd.Menu.SimpleMenuElement;
+
+public class k {
+
+ public boolean m_doZ;
+ public int m_aI;
+ public int m_intI;
+ public int m_forI;
+ public int m_newI;
+ public SimpleMenuElement m_ifan[];
+
+ public k() {
+ m_ifan = new SimpleMenuElement[6];
+ for (int i = 0; i < 6; i++)
+ m_ifan[i] = new SimpleMenuElement();
+
+ _avV();
+ }
+
+ public void _avV() {
+ m_aI = m_forI = m_newI = 0;
+ m_doZ = true;
+ for (int i = 0; i < 6; i++)
+ m_ifan[i].init();
+
+ }
+}
diff --git a/src/org/happysanta/gd/Global.java b/src/org/happysanta/gd/Global.java
new file mode 100755
index 0000000..3fb600b
--- /dev/null
+++ b/src/org/happysanta/gd/Global.java
@@ -0,0 +1,21 @@
+package org.happysanta.gd;
+
+import android.graphics.Typeface;
+
+public class Global {
+
+ public static final boolean DEBUG = false;
+ public static final boolean DISABLE_SCALING = false;
+ public static final boolean INSTALLED_FROM_APK = true;
+ public static final boolean ACRA_ENABLED = true;
+ // public static final boolean ENABLE_TOUCH_HACK_FOR_ALL = false;
+
+ public static float density = 0;
+ public static Typeface robotoCondensedTypeface;
+
+ static {
+ density = Helpers.getGDActivity().getResources().getDisplayMetrics().density;
+ robotoCondensedTypeface = Typeface.createFromAsset(Helpers.getGDActivity().getAssets(), "RobotoCondensed-Regular.ttf");
+ }
+
+}
diff --git a/src/org/happysanta/gd/Helpers.java b/src/org/happysanta/gd/Helpers.java
new file mode 100755
index 0000000..667a880
--- /dev/null
+++ b/src/org/happysanta/gd/Helpers.java
@@ -0,0 +1,309 @@
+package org.happysanta.gd;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Build;
+import android.util.Log;
+import org.happysanta.gd.Game.GameView;
+import org.happysanta.gd.Levels.Loader;
+import org.happysanta.gd.Menu.Menu;
+import org.happysanta.gd.Storage.LevelsManager;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class Helpers {
+
+ private static char[] cp1251Map = new char[]{
+ '\u0000', '\u0001', '\u0002', '\u0003', '\u0004', '\u0005', '\u0006', '\u0007',
+ '\u0008', '\u0009', '\n', '\u000B', '\u000C', '\r', '\u000E', '\u000F',
+ '\u0010', '\u0011', '\u0012', '\u0013', '\u0014', '\u0015', '\u0016', '\u0017',
+ '\u0018', '\u0019', '\u001A', '\u001B', '\u001C', '\u001D', '\u001E', '\u001F',
+ '\u0020', '\u0021', '\u0022', '\u0023', '\u0024', '\u0025', '\u0026', '\'',
+ '\u0028', '\u0029', '\u002A', '\u002B', '\u002C', '\u002D', '\u002E', '\u002F',
+ '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037',
+ '\u0038', '\u0039', '\u003A', '\u003B', '\u003C', '\u003D', '\u003E', '\u003F',
+ '\u0040', '\u0041', '\u0042', '\u0043', '\u0044', '\u0045', '\u0046', '\u0047',
+ '\u0048', '\u0049', '\u004A', '\u004B', '\u004C', '\u004D', '\u004E', '\u004F',
+ '\u0050', '\u0051', '\u0052', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057',
+ '\u0058', '\u0059', '\u005A', '\u005B', '\\', '\u005D', '\u005E', '\u005F',
+ '\u0060', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066', '\u0067',
+ '\u0068', '\u0069', '\u006A', '\u006B', '\u006C', '\u006D', '\u006E', '\u006F',
+ '\u0070', '\u0071', '\u0072', '\u0073', '\u0074', '\u0075', '\u0076', '\u0077',
+ '\u0078', '\u0079', '\u007A', '\u007B', '\u007C', '\u007D', '\u007E', '\u007F',
+ '\u0402', '\u0403', '\u201A', '\u0453', '\u201E', '\u2026', '\u2020', '\u2021',
+ '\u20AC', '\u2030', '\u0409', '\u2039', '\u040A', '\u040C', '\u040B', '\u040F',
+ '\u0452', '\u2018', '\u2019', '\u201C', '\u201D', '\u2022', '\u2013', '\u2014',
+ '\uFFFD', '\u2122', '\u0459', '\u203A', '\u045A', '\u045C', '\u045B', '\u045F',
+ '\u00A0', '\u040E', '\u045E', '\u0408', '\u00A4', '\u0490', '\u00A6', '\u00A7',
+ '\u0401', '\u00A9', '\u0404', '\u00AB', '\u00AC', '\u00AD', '\u00AE', '\u0407',
+ '\u00B0', '\u00B1', '\u0406', '\u0456', '\u0491', '\u00B5', '\u00B6', '\u00B7',
+ '\u0451', '\u2116', '\u0454', '\u00BB', '\u0458', '\u0405', '\u0455', '\u0457',
+ '\u0410', '\u0411', '\u0412', '\u0413', '\u0414', '\u0415', '\u0416', '\u0417',
+ '\u0418', '\u0419', '\u041A', '\u041B', '\u041C', '\u041D', '\u041E', '\u041F',
+ '\u0420', '\u0421', '\u0422', '\u0423', '\u0424', '\u0425', '\u0426', '\u0427',
+ '\u0428', '\u0429', '\u042A', '\u042B', '\u042C', '\u042D', '\u042E', '\u042F',
+ '\u0430', '\u0431', '\u0432', '\u0433', '\u0434', '\u0435', '\u0436', '\u0437',
+ '\u0438', '\u0439', '\u043A', '\u043B', '\u043C', '\u043D', '\u043E', '\u043F',
+ '\u0440', '\u0441', '\u0442', '\u0443', '\u0444', '\u0445', '\u0446', '\u0447',
+ '\u0448', '\u0449', '\u044A', '\u044B', '\u044C', '\u044D', '\u044E', '\u044F'
+ };
+
+ public static GDActivity getGDActivity() {
+ return GDActivity.shared;
+ }
+
+ public static GameView getGDView() {
+ return GDActivity.shared.gameView;
+ }
+
+ public static Menu getGameMenu() {
+ return GDActivity.shared.menu;
+ }
+
+ public static Loader getLevelLoader() {
+ return GDActivity.shared.levelLoader;
+ }
+
+ public static LevelsManager getLevelsManager() {
+ return GDActivity.shared.levelsManager;
+ }
+
+ public static int getDp(int px) {
+ return Math.round(px * Global.density);
+ }
+
+ public static int getDp(float px) {
+ return Math.round(px * Global.density);
+ }
+
+ public static String getCurrentStackTrace() {
+ String del = "\n";
+ StringBuilder sb = new StringBuilder();
+ StackTraceElement[] list = Thread.currentThread().getStackTrace();
+ // for (StackTraceElement e: list) {
+ for (int i = 0; i < list.length; i++) {
+ sb.append(list[i].toString() + (i < list.length - 1 ? del : ""));
+ }
+ return sb.toString();
+ }
+
+ public static Bitmap loadBitmapFromDrawable(int id) {
+ BitmapFactory.Options options = null;
+ if (!isSDK11OrHigher()) {
+ options = new BitmapFactory.Options();
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ }
+ return BitmapFactory.decodeResource(getGDActivity().getResources(), id);
+ }
+
+ public static Bitmap loadBitmapFromAsset(String name) throws IOException {
+ if (name.startsWith("/")) name = name.substring(1);
+ Bitmap bmp = null;
+ InputStream s = getGDActivity().getAssets().open(name);
+ bmp = BitmapFactory.decodeStream(s);
+ s.close();
+ return bmp;
+ }
+
+ public static void logDebug(String s) {
+ Log.d("AGDTR<" + Thread.currentThread().getName() + ">", s);
+ }
+
+ public static void logDebug(Object s) {
+ Log.d("AGDTR<" + Thread.currentThread().getName() + ">", s.toString());
+ }
+
+ public static boolean isOnline() {
+ ConnectivityManager cm = (ConnectivityManager) getGDActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo netInfo = cm.getActiveNetworkInfo();
+ return netInfo != null && netInfo.isConnectedOrConnecting();
+ }
+
+ /*public static String trimLine(String s, Paint f, int w) {
+ // logDebug("trimLine; s = " + s + ", w = " + w + "; measure = " + f.measureText(s));
+ String points = "...", result = s;
+ float avgWidth = f.measureText("o"), pointsWidth = f.measureText(points);
+ float diff;
+ int i = 0,
+ len = s.length(),
+ half = 0,
+ c = 0,
+ st1 = 0,
+ st2 = len - 1;
+
+ if (s.equals("") || f.measureText(s) <= w) return s;
+
+ w -= pointsWidth;
+
+ int tmpMax = (int)Math.round(Math.floor(w / Math.round(avgWidth / 1.5)) * 2);
+ if (len > tmpMax) {
+ s = s.substring(0, tmpMax);
+ len = s.length();
+ }
+
+ while (true) {
+ i++;
+ // if (i >= 100) return s;
+ if (half == 0) {
+ c = Math.round(len / 2);
+ } else {
+ switch (half) {
+ case 1:
+ st2 = c;
+ c -= (st2 - st1) / 2;
+ break;
+
+ case 2:
+ st1 = c;
+ c += (st2 - st1) / 2;
+ break;
+ }
+ }
+
+ String sub = s.substring(0, c > len - 1 ? len - 1 : c);
+ float subWidth = f.measureText(sub);
+
+ if (subWidth > w + avgWidth) half = 1;
+ else if (subWidth < w - avgWidth) half = 2;
+ else {
+ diff = subWidth - w;
+
+ if (diff > 0) {
+ result = s.substring(0, c - 1);
+ if (!result.equals(s)) result += points;
+ } else {
+ result = s.substring(0, c + 1);
+ if (!result.equals(s)) result += points;
+ }
+
+ return result;
+ }
+ }
+
+ // return s;
+ }*/
+
+ public static String getString(int r) {
+ return GDActivity.shared.getString(r);
+ }
+
+ public static String[] getStringArray(int r) {
+ return GDActivity.shared.getResources().getStringArray(r);
+ }
+
+ public static void runOnUiThread(Runnable runnable) {
+ GDActivity.shared.runOnUiThread(runnable);
+ }
+
+ public static long getTimestamp() {
+ return System.currentTimeMillis() / 1000L;
+ }
+
+ public static void showAlert(String title, String message, final Runnable listener) {
+ Context context = getGDActivity();
+ AlertDialog alertDialog = new AlertDialog.Builder(context)
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (listener != null) listener.run();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (listener != null) listener.run();
+ }
+ })
+ .create();
+ alertDialog.show();
+ }
+
+ public static void showConfirm(String title, String message, final Runnable onOk, final Runnable onCancel) {
+ Context context = getGDActivity();
+ AlertDialog.Builder alert = new AlertDialog.Builder(context)
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (onOk != null) onOk.run();
+ }
+ })
+ .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (onCancel != null) onCancel.run();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (onCancel != null) onCancel.run();
+ }
+ });
+ alert.show();
+ }
+
+ public static boolean isSDK11OrHigher() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+ }
+
+ public static boolean isSDK10OrLower() {
+ return Build.VERSION.SDK_INT <= 10;
+ }
+
+ public static String getAppVersion() {
+ String v = "0.0";
+ try {
+ PackageInfo pInfo = GDActivity.shared.getPackageManager().getPackageInfo(GDActivity.shared.getPackageName(), 0);
+ v = pInfo.versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ return v;
+ }
+
+ public static String decodeCp1251(byte[] data) {
+ if (data == null) {
+ return "";
+ }
+ StringBuffer sb = new StringBuffer(data.length);
+ for (int i = 0; i < data.length; i++) {
+ if (data[i] == 0) break;
+ sb.append(cp1251Map[data[i] & 0xFF]);
+ }
+ return sb.toString();
+ }
+
+ public static String getDeviceName() {
+ String manufacturer = Build.MANUFACTURER;
+ String model = Build.MODEL;
+ if (model.startsWith(manufacturer)) {
+ return capitalize(model);
+ } else {
+ return capitalize(manufacturer) + " " + model;
+ }
+ }
+
+ private static String capitalize(String s) {
+ if (s == null || s.length() == 0) {
+ return "";
+ }
+ char first = s.charAt(0);
+ if (Character.isUpperCase(first)) {
+ return s;
+ } else {
+ return Character.toUpperCase(first) + s.substring(1);
+ }
+ }
+
+}
diff --git a/src/org/happysanta/gd/KeyboardController.java b/src/org/happysanta/gd/KeyboardController.java
new file mode 100644
index 0000000..4438677
--- /dev/null
+++ b/src/org/happysanta/gd/KeyboardController.java
@@ -0,0 +1,303 @@
+package org.happysanta.gd;
+
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+import org.happysanta.gd.Game.GameView;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import static org.happysanta.gd.Helpers.getDp;
+
+public class KeyboardController implements View.OnTouchListener {
+
+ private static final int MAX_POINTERS = 10;
+ public static final int PADDING = 15;
+ private static final boolean DISABLE_MOVE = false;
+
+ private static int PADDING_DP = 0;
+
+ private GDActivity gd;
+ private int[] buf;
+ private LinearLayout[] btns;
+ private PointerInfo[] pointers;
+ private StringBuffer logBuffer;
+
+ static {
+ PADDING_DP = getDp(PADDING);
+ }
+
+ KeyboardController(GDActivity gd) {
+ this.gd = gd;
+ buf = new int[2];
+ btns = new LinearLayout[9];
+ pointers = new PointerInfo[MAX_POINTERS];
+ for (int i = 0; i < MAX_POINTERS; i++) {
+ pointers[i] = new PointerInfo(i);
+ }
+
+ logBuffer = new StringBuffer();
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ GameView gameView = gd.gameView;
+
+ v.getLocationOnScreen(buf);
+ Rect rect = new Rect(buf[0], buf[1], buf[0] + v.getWidth(), buf[1] + v.getHeight());
+
+ rect.left += PADDING_DP;
+ rect.right -= PADDING_DP;
+ rect.top += PADDING_DP;
+ rect.bottom -= PADDING_DP;
+
+ /*int actionRaw = MotionEventCompat.getAction/event.getAction();
+ if (actionRaw != MotionEvent.ACTION_MOVE) {
+ log("EVT_RAW " + actionRaw + " " + actionToString(actionRaw));
+ }*/
+
+ // int action = actionRaw & MotionEvent.ACTION_MASK;
+ int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN
+ || action == MotionEvent.ACTION_POINTER_DOWN
+ || action == MotionEvent.ACTION_UP
+ || action == MotionEvent.ACTION_POINTER_UP
+// || action == MotionEvent.ACTION_CANCEL
+ /*|| action == MotionEvent.ACTION_POINTER_2_DOWN
+ || action == MotionEvent.ACTION_POINTER_3_DOWN
+ || action == MotionEvent.ACTION_POINTER_2_UP
+ || action == MotionEvent.ACTION_POINTER_3_UP*/) {
+ /*int index = event.getActionIndex();
+ int pointerId = event.getPointerId(index);*/
+
+ int index = event.getActionIndex();
+ int pointerId = event.getPointerId(index);
+// int pointerId = event.getPointerId(index);
+
+ if (pointerId >= MAX_POINTERS) {
+ return true;
+ }
+
+ int x = Math.round(event.getX(index));
+ int y = Math.round(event.getY(index));
+
+ //if (Global.DEBUG || true) {
+// log("EVT [ind=" + index + ", pntId=" + pointerId + "] " + actionToString(action) + " "
+// + "(x=" + x + ", y=" + y + "), "
+// + "(rx=" + event.getRawX() + ", ry=" + event.getRawY() + ")"
+// );
+// log("EVT DUMP " + event.toString());
+// log("RECT l="+rect.left+", r="+rect.right+", t="+rect.top+", b="+rect.bottom);
+ // }
+
+ LinearLayout btn;
+ PointerInfo pointer = pointers[pointerId];
+
+ int btnIndex = whichButton(rect, x, y);
+
+// log("BTN index="+btnIndex, true);
+
+ // logBuffer("x="+x+", y="+y+", btn="+btnIndex);
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN:
+ press(v);
+
+ pointer.setButtonIndex(btnIndex);
+ btn = pointer.getButton();
+
+ btn.setPressed(true);
+ gameView.keyPressed(gameKeyCode(btnIndex));
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ // case MotionEvent.ACTION_CANCEL:
+ btn = pointer.getButton();
+ if (btn != null) {
+ btn.setPressed(false);
+ if (DISABLE_MOVE) {
+ btnIndex = pointer.btnIndex;
+ }
+ gameView.keyReleased(gameKeyCode(btnIndex));
+ pointer.finish();
+ }
+ break;
+ }
+ } else if (action == MotionEvent.ACTION_MOVE && !gd.isMenuShown() && !DISABLE_MOVE) {
+ int pointerCount = event.getPointerCount();
+// int pointerCount = event.getPointerCount();
+ LinearLayout btn, oldBtn;
+ PointerInfo pointer;
+
+ for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
+ int pointerId = event.getPointerId(pointerIndex);
+ if (pointerId >= MAX_POINTERS) continue;
+
+ int x = Math.round(event.getX(pointerIndex));
+ int y = Math.round(event.getY(pointerIndex));
+
+// int x = Math.round(event.getX(pointerIndex));
+// int y = Math.round(event.getY(pointerIndex));
+ int btnIndex = whichButton(rect, x, y);
+
+ pointer = pointers[pointerId];
+ if (btnIndex != pointer.btnIndex) {
+ oldBtn = btns[pointer.btnIndex];
+ oldBtn.setPressed(false);
+ gameView.keyReleased(gameKeyCode(pointer.btnIndex));
+
+ press(v);
+
+ pointer.setButtonIndex(btnIndex);
+ btn = pointer.getButton();
+ btn.setPressed(true);
+ gameView.keyPressed(gameKeyCode(pointer.btnIndex));
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private synchronized void log(Object o, boolean last) {
+ String logStr = o.toString();
+ Log.d("GD Keyboard", o.toString());
+
+ if (last)
+ Log.d("", "");
+
+ /*if (!gd.isMenuShown()) {
+ logBuffer.append("<");
+ logBuffer.append(getCurrentTime());
+ logBuffer.append("> ");
+
+ logBuffer.append(logStr);
+ logBuffer.append("\n");
+
+ if (last)
+ logBuffer.append("\n");
+ }*/
+ }
+
+ private void log(Object o) {
+ log(o, false);
+ }
+
+ public synchronized void clearLogBuffer() {
+ logBuffer = null;
+ logBuffer = new StringBuffer();
+ }
+
+ public String getLog() {
+ return logBuffer.toString();
+ }
+
+ private static String getCurrentTime() {
+ Calendar cal = Calendar.getInstance();
+ cal.getTime();
+ SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
+ return sdf.format(cal.getTime());
+ }
+
+ private static String actionToString(int action) {
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ return "ACTION_DOWN";
+ case MotionEvent.ACTION_POINTER_DOWN:
+ return "ACTION_POINTER_DOWN";
+ case MotionEvent.ACTION_POINTER_2_DOWN:
+ return "ACTION_POINTER_2_DOWN";
+ case MotionEvent.ACTION_POINTER_2_UP:
+ return "ACTION_POINTER_2_UP";
+ case MotionEvent.ACTION_POINTER_3_DOWN:
+ return "ACTION_POINTER_3_DOWN";
+ case MotionEvent.ACTION_POINTER_3_UP:
+ return "ACTION_POINTER_3_UP";
+ case MotionEvent.ACTION_UP:
+ return "ACTION_UP";
+ case MotionEvent.ACTION_POINTER_UP:
+ return "ACTION_POINTER_UP";
+ case MotionEvent.ACTION_MOVE:
+ return "ACTION_MOVE";
+ }
+ return "?";
+ }
+
+ private static int whichButton(Rect rect, int x, int y) {
+ int cellW = rect.width() / 3,
+ cellH = rect.height() / 3;
+
+ // logBuffer("cellW="+cellW+", cellH="+cellH);
+
+ int posX = 0, posY = 0;
+
+ if (x < PADDING_DP + cellW)
+ posX = 0;
+ else if (x < PADDING_DP + cellW * 2)
+ posX = 1;
+ else
+ posX = 2;
+
+ if (y < PADDING_DP + cellH)
+ posY = 0;
+ else if (y < PADDING_DP + cellH * 2)
+ posY = 1;
+ else
+ posY = 2;
+
+ return posY * 3 + posX;
+ }
+
+ private static int gameKeyCode(int btnIndex) {
+ return btnIndex + 49;
+ }
+
+ private static void press(View v) {
+ if (Settings.isVibrateOnTouchEnabled()) {
+ v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
+ }
+ }
+
+ public void addButton(LinearLayout btn, int x, int y) {
+ btns[y * 3 + x] = btn;
+ }
+
+ private class PointerInfo {
+
+ private int id;
+ private int btnIndex = -1;
+ private boolean active = false;
+
+ PointerInfo(int id) {
+ this.id = id;
+ }
+
+ void finish() {
+ active = false;
+ btnIndex = -1;
+ }
+
+ /*void setActive() {
+ active = true;
+ }*/
+
+ void setButtonIndex(int index) {
+ active = true;
+ btnIndex = index;
+ }
+
+ LinearLayout getButton() {
+ if (!active)
+ return null;
+ return btns[btnIndex];
+ }
+
+ }
+
+}
diff --git a/src/org/happysanta/gd/Levels/InvalidTrackException.java b/src/org/happysanta/gd/Levels/InvalidTrackException.java
new file mode 100644
index 0000000..9b2b827
--- /dev/null
+++ b/src/org/happysanta/gd/Levels/InvalidTrackException.java
@@ -0,0 +1,12 @@
+package org.happysanta.gd.Levels;
+
+/**
+ * Created by evgeny on 6/15/14.
+ */
+public class InvalidTrackException extends Exception {
+
+ public InvalidTrackException(Exception e) {
+ super(e);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Levels/Level.java b/src/org/happysanta/gd/Levels/Level.java
new file mode 100755
index 0000000..78f89ac
--- /dev/null
+++ b/src/org/happysanta/gd/Levels/Level.java
@@ -0,0 +1,245 @@
+package org.happysanta.gd.Levels;
+
+import org.happysanta.gd.Game.GameView;
+import org.happysanta.gd.Game.Physics;
+
+import java.io.DataInputStream;
+
+import static org.happysanta.gd.Helpers.getLevelLoader;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class Level {
+
+ public int startX;
+ public int startY;
+ public int finishX;
+ public int m_gotoI;
+ public int m_forI;
+ public int finishY;
+ public int pointsCount;
+ public int m_intI;
+ public int points[][];
+ public String levelName;
+ private int m_aI;
+ private int m_dI;
+ private int m_eI;
+ private int m_bI;
+ private int m_gI;
+ private int m_rI;
+
+ public Level() {
+ m_aI = 0;
+ m_dI = 0;
+ m_eI = 0;
+ m_bI = 0;
+ m_gI = 0;
+ m_gotoI = 0;
+ m_forI = 0;
+ points = (int[][]) null;
+ levelName = "levelname";
+ m_rI = 0;
+ clear();
+ }
+
+ public void clear() {
+ startX = 0;
+ startY = 0;
+ finishX = 0xc80000;
+ pointsCount = 0;
+ m_intI = 0;
+ }
+
+ public int _doII(int j) {
+ int k = j - points[m_gotoI][0];
+ int i1;
+ if (((i1 = points[m_forI][0] - points[m_gotoI][0]) >= 0 ? i1 : -i1) < 3 || k > i1)
+ return 0x10000;
+ else
+ return (int) (((long) k << 32) / (long) i1 >> 16);
+ }
+
+ public void _ifIIV(int j, int k) {
+ m_aI = (j << 16) >> 3;
+ m_dI = (k << 16) >> 3;
+ }
+
+ public void _aIIV(int j, int k) {
+ m_eI = j >> 1;
+ m_bI = k >> 1;
+ }
+
+ public void _aIIV(int j, int k, int i1) {
+ m_eI = j;
+ m_bI = k;
+ m_gI = i1;
+ }
+
+ public void _ifiIV(GameView view, int k, int i1) {
+ if (i1 <= pointsCount - 1) {
+ int j1 = m_gI - (points[k][1] + points[i1 + 1][1] >> 1) >= 0 ? m_gI - (points[k][1] + points[i1 + 1][1] >> 1) : 0;
+ if (m_gI <= points[k][1] || m_gI <= points[i1 + 1][1])
+ j1 = j1 >= 0x50000 ? 0x50000 : j1;
+ m_rI = (int) ((long) m_rI * 49152L >> 16) + (int) ((long) j1 * 16384L >> 16);
+ if (m_rI <= 0x88000) {
+ int k1 = (int) (0x190000L * (long) m_rI >> 16) >> 16;
+ view.setColor(k1, k1, k1);
+ int l1 = points[k][0] - points[k + 1][0];
+ int i2 = (int) (((long) (points[k][1] - points[k + 1][1]) << 32) / (long) l1 >> 16);
+ int j2 = points[k][1] - (int) ((long) points[k][0] * (long) i2 >> 16);
+ int k2 = (int) ((long) m_eI * (long) i2 >> 16) + j2;
+ l1 = points[i1][0] - points[i1 + 1][0];
+ i2 = (int) (((long) (points[i1][1] - points[i1 + 1][1]) << 32) / (long) l1 >> 16);
+ j2 = points[i1][1] - (int) ((long) points[i1][0] * (long) i2 >> 16);
+ int l2 = (int) ((long) m_bI * (long) i2 >> 16) + j2;
+ if (k == i1) {
+ view._aIIIV((m_eI << 3) >> 16, (k2 + 0x10000 << 3) >> 16, (m_bI << 3) >> 16, (l2 + 0x10000 << 3) >> 16);
+ return;
+ }
+ view._aIIIV((m_eI << 3) >> 16, (k2 + 0x10000 << 3) >> 16, (points[k + 1][0] << 3) >> 16, (points[k + 1][1] + 0x10000 << 3) >> 16);
+ for (int i3 = k + 1; i3 < i1; i3++)
+ view._aIIIV((points[i3][0] << 3) >> 16, (points[i3][1] + 0x10000 << 3) >> 16, (points[i3 + 1][0] << 3) >> 16, (points[i3 + 1][1] + 0x10000 << 3) >> 16);
+
+ view._aIIIV((points[i1][0] << 3) >> 16, (points[i1][1] + 0x10000 << 3) >> 16, (m_bI << 3) >> 16, (l2 + 0x10000 << 3) >> 16);
+ }
+ }
+ }
+
+ public synchronized void _aiIV(GameView view, int k, int i1) {
+ int k2 = 0;
+ int l2 = 0;
+ int j2;
+ for (j2 = 0; j2 < pointsCount - 1 && points[j2][0] <= m_aI; j2++) ;
+ if (j2 > 0)
+ j2--;
+ int i3 = k - points[j2][0];
+ int j3 = (i1 + 0x320000) - points[j2][1];
+ int k3 = Physics._doIII(i3, j3);
+ i3 = (int) (((long) i3 << 32) / (long) (k3 >> 1 >> 1) >> 16);
+ j3 = (int) (((long) j3 << 32) / (long) (k3 >> 1 >> 1) >> 16);
+ view.setColor(0, 170, 0);
+ do {
+ if (j2 >= pointsCount - 1)
+ break;
+ int j1 = i3;
+ int l1 = j3;
+ i3 = k - points[j2 + 1][0];
+ j3 = (i1 + 0x320000) - points[j2 + 1][1];
+ int l3 = Physics._doIII(i3, j3);
+ i3 = (int) (((long) i3 << 32) / (long) (l3 >> 1 >> 1) >> 16);
+ j3 = (int) (((long) j3 << 32) / (long) (l3 >> 1 >> 1) >> 16);
+ view._aIIIV((points[j2][0] + j1 << 3) >> 16, (points[j2][1] + l1 << 3) >> 16, (points[j2 + 1][0] + i3 << 3) >> 16, (points[j2 + 1][1] + j3 << 3) >> 16);
+ view._aIIIV((points[j2][0] << 3) >> 16, (points[j2][1] << 3) >> 16, (points[j2][0] + j1 << 3) >> 16, (points[j2][1] + l1 << 3) >> 16);
+ if (j2 > 1) {
+ if (points[j2][0] > m_eI && k2 == 0)
+ k2 = j2 - 1;
+ if (points[j2][0] > m_bI && l2 == 0)
+ l2 = j2 - 1;
+ }
+ if (m_gotoI == j2) {
+ view.drawStartFlag((points[m_gotoI][0] + j1 << 3) >> 16, (points[m_gotoI][1] + l1 << 3) >> 16);
+ view.setColor(0, 170, 0);
+ }
+ if (m_forI == j2) {
+ view.drawFinishFlag((points[m_forI][0] + j1 << 3) >> 16, (points[m_forI][1] + l1 << 3) >> 16);
+ view.setColor(0, 170, 0);
+ }
+ if (points[j2][0] > m_dI)
+ break;
+ j2++;
+ } while (true);
+ int k1 = i3;
+ int i2 = j3;
+ view._aIIIV((points[pointsCount - 1][0] << 3) >> 16, (points[pointsCount - 1][1] << 3) >> 16, (points[pointsCount - 1][0] + k1 << 3) >> 16, (points[pointsCount - 1][1] + i2 << 3) >> 16);
+ if (getLevelLoader().isShadowsEnabled())
+ _ifiIV(view, k2, l2);
+ }
+
+ public synchronized void _aiV(GameView view) {
+ int k;
+ for (k = 0; k < pointsCount - 1 && points[k][0] <= m_aI; k++) ;
+ if (k > 0)
+ k--;
+ do {
+ if (k >= pointsCount - 1)
+ break;
+ view._aIIIV((points[k][0] << 3) >> 16, (points[k][1] << 3) >> 16, (points[k + 1][0] << 3) >> 16, (points[k + 1][1] << 3) >> 16);
+ if (m_gotoI == k) {
+ view.drawStartFlag((points[m_gotoI][0] << 3) >> 16, (points[m_gotoI][1] << 3) >> 16);
+ view.setColor(0, 255, 0);
+ }
+ if (m_forI == k) {
+ view.drawFinishFlag((points[m_forI][0] << 3) >> 16, (points[m_forI][1] << 3) >> 16);
+ view.setColor(0, 255, 0);
+ }
+ if (points[k][0] > m_dI)
+ break;
+ k++;
+ } while (true);
+ }
+
+ public void unpackInt(int x, int y) {
+ addPoint((x << 16) >> 3, (y << 16) >> 3);
+ }
+
+ public void addPoint(int x, int y) {
+ if (points == null || points.length <= pointsCount) {
+ int i1 = 100;
+ if (points != null)
+ i1 = i1 >= points.length + 30 ? i1 : points.length + 30;
+ int ai[][] = new int[i1][2];
+ if (points != null)
+ System.arraycopy(points, 0, ai, 0, points.length);
+ points = ai;
+ }
+ if (pointsCount == 0 || points[pointsCount - 1][0] < x) {
+ points[pointsCount][0] = x;
+ points[pointsCount][1] = y;
+ pointsCount++;
+ }
+ }
+
+ public synchronized void readTrackData(DataInputStream in) {
+ try {
+ clear();
+ if (in.readByte() == 50) {
+ byte bytes[] = new byte[20];
+ in.readFully(bytes);
+ }
+ m_forI = 0;
+ m_gotoI = 0;
+ startX = in.readInt();
+ startY = in.readInt();
+ finishX = in.readInt();
+ finishY = in.readInt();
+ short pointsCount = in.readShort();
+ int firstPointX = in.readInt();
+ int firstPointY = in.readInt();
+ int k1 = firstPointX;
+ int l1 = firstPointY;
+ unpackInt(k1, l1);
+ for (int i = 1; i < pointsCount; i++) {
+ int x;
+ int y;
+ byte byte0;
+ if ((byte0 = in.readByte()) == -1) {
+ k1 = l1 = 0;
+ x = in.readInt();
+ y = in.readInt();
+ } else {
+ x = byte0;
+ y = in.readByte();
+ }
+ k1 += x;
+ l1 += y;
+ unpackInt(k1, l1);
+ }
+
+ /*logDebug("Points: ");
+ for (int[] point: points) {
+ logDebug("(" + ((point[0] >> 16) << 3) + ", " + ((point[1] >> 16) << 3) + ")");
+ }*/
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/src/org/happysanta/gd/Levels/LevelHeader.java b/src/org/happysanta/gd/Levels/LevelHeader.java
new file mode 100644
index 0000000..68aa112
--- /dev/null
+++ b/src/org/happysanta/gd/Levels/LevelHeader.java
@@ -0,0 +1,53 @@
+package org.happysanta.gd.Levels;
+
+public class LevelHeader {
+
+ private int pointers[][] = new int[3][];
+ private String names[][] = new String[3][];
+ private int counts[] = new int[3];
+
+ public LevelHeader() {
+ }
+
+ public void setCount(int level, int count) {
+ if (level >= counts.length)
+ return;
+
+ pointers[level] = new int[count];
+ names[level] = new String[count];
+ counts[level] = count;
+ }
+
+ public int getCount(int level) {
+ if (level < counts.length)
+ return counts[level];
+ else
+ return 0;
+ }
+
+ public void setPointer(int level, int index, int value) {
+ pointers[level][index] = value;
+ }
+
+ public void setName(int level, int index, String value) {
+ names[level][index] = value;
+ }
+
+ public int[][] getPointers() {
+ return pointers;
+ }
+
+ public String[][] getNames() {
+ return names;
+ }
+
+ public boolean isCountsOk() {
+ for (int i = 0; i < counts.length; i++) {
+ if (counts[i] <= 0)
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Levels/Loader.java b/src/org/happysanta/gd/Levels/Loader.java
new file mode 100755
index 0000000..48ef645
--- /dev/null
+++ b/src/org/happysanta/gd/Levels/Loader.java
@@ -0,0 +1,335 @@
+package org.happysanta.gd.Levels;
+
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Game.GameView;
+import org.happysanta.gd.Menu.SimpleMenuElement;
+import org.happysanta.gd.Game.Physics;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class Loader {
+
+ //public static final int m_bI;
+ // public static final int m_forI = 1;
+ // public static final int m_intI = 2;
+ //public static final int m_doI;
+ // public static final int m_ifI = 1;
+
+ public File levelsFile;
+ public Level levels;
+ public int m_nullI;
+ public int m_fI;
+ public String names[][];
+ public int m_jI;
+ public int m_iI;
+ public int m_longI;
+ public int m_eI;
+ public int m_dI;
+
+ private boolean perspectiveEnabled = true;
+ private boolean shadowsEnabled = true;
+ private int pointers[][] = new int[3][];
+ private int m_eaI = 0;
+ private int m_faI = 0;
+ private int m_aI = 0;
+ private int m_kI = 0;
+ private int m_saaI[][];
+ private int m_haI[];
+ private int m_vaI[];
+ private int m_daI;
+
+ public Loader() throws IOException {
+ reset();
+ }
+
+ public Loader(File levelsFile) throws IOException {
+ if (levelsFile != null)
+ this.levelsFile = levelsFile;
+ reset();
+ }
+
+ private void reset() throws IOException {
+ m_saaI = null;
+ levels = null;
+ m_haI = new int[3];
+ m_vaI = new int[3];
+ m_nullI = 0;
+ m_fI = -1;
+ names = new String[3][];
+ m_daI = 0;
+ for (int j = 0; j < 3; j++) {
+ m_haI[j] = (int) ((long) (Physics.m_foraI[j] + 19660 >> 1) * (long) (Physics.m_foraI[j] + 19660 >> 1) >> 16);
+ m_vaI[j] = (int) ((long) (Physics.m_foraI[j] - 19660 >> 1) * (long) (Physics.m_foraI[j] - 19660 >> 1) >> 16);
+ }
+
+ // try {
+ readLevels();
+ // } catch ( _ex) {
+ // _ex.printStackTrace();
+ //}
+ _ifvV();
+ }
+
+
+ public void setLevelsFile(File file) throws IOException {
+ levelsFile = file;
+ reset();
+ }
+
+ public InputStream getLevelsInputStream(String s) throws IOException {
+ if (levelsFile == null)
+ return GDActivity.shared.getAssets().open(s);
+ else
+ return new FileInputStream(levelsFile);
+ }
+
+ private void readLevels() throws IOException {
+ //try {
+ InputStream in = getLevelsInputStream("levels.mrg");
+ LevelHeader header = Reader.readHeader(in);
+
+ pointers = header.getPointers();
+ names = header.getNames();
+ //} catch (Exception ex) {
+ // logDebug("Levels.Loader: error while reading mrg file");
+ // ex.printStackTrace();
+ //}
+ }
+
+ public String getLevelName(int j, int k) {
+ if (j < names.length && k < names[j].length)
+ return names[j][k];
+ else
+ return "---";
+ }
+
+ public void _ifvV() {
+ try {
+ _doIII(m_nullI, m_fI + 1);
+ } catch (InvalidTrackException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public int _doIII(int j, int k) throws InvalidTrackException {
+ m_nullI = j;
+ m_fI = k;
+ if (m_fI >= names[m_nullI].length)
+ m_fI = 0;
+ _hIIV(m_nullI + 1, m_fI + 1);
+ return m_fI;
+ }
+
+ private void _hIIV(int j, int k) throws InvalidTrackException {
+ try {
+ InputStream is = getLevelsInputStream("levels.mrg");
+ DataInputStream dis = new DataInputStream(is);
+ for (int i1 = pointers[j - 1][k - 1]; i1 > 0; i1 -= dis.skipBytes(i1)) ;
+ if (levels == null)
+ levels = new Level();
+ levels.readTrackData(dis);
+ dis.close();
+ load(levels);
+ } catch (IOException _ex) {
+ _ex.printStackTrace();
+ }
+ }
+
+ public void _ifIV(int j) {
+ m_jI = levels.startX << 1;
+ m_iI = levels.startY << 1;
+ }
+
+ public int _dovI() {
+ return levels.points[levels.m_forI][0] << 1;
+ }
+
+ public int _intvI() {
+ return levels.points[levels.m_gotoI][0] << 1;
+ }
+
+ public int _newvI() {
+ return levels.startX << 1;
+ }
+
+ public int _avI() {
+ return levels.startY << 1;
+ }
+
+ public int _aII(int j) {
+ return levels._doII(j >> 1);
+ }
+
+ public void load(Level l1) throws InvalidTrackException {
+ try {
+ m_longI = 0x80000000;
+ levels = l1;
+ int j = levels.pointsCount;
+ if (m_saaI == null || m_daI < j) {
+ m_saaI = (int[][]) null;
+ // System.gc();
+ m_daI = j >= 100 ? j : 100;
+ m_saaI = new int[m_daI][2];
+ }
+ m_eaI = 0;
+ m_faI = 0;
+ m_aI = l1.points[m_eaI][0];
+ m_kI = l1.points[m_faI][0];
+ for (int k = 0; k < j; k++) {
+ int i1 = l1.points[(k + 1) % j][0] - l1.points[k][0];
+ int j1 = l1.points[(k + 1) % j][1] - l1.points[k][1];
+ if (k != 0 && k != j - 1)
+ m_longI = m_longI >= l1.points[k][0] ? m_longI : l1.points[k][0];
+ int k1 = -j1;
+ int i2 = i1;
+ int j2 = Physics._doIII(k1, i2);
+ m_saaI[k][0] = (int) (((long) k1 << 32) / (long) j2 >> 16);
+ m_saaI[k][1] = (int) (((long) i2 << 32) / (long) j2 >> 16);
+ if (levels.m_gotoI == 0 && l1.points[k][0] > levels.startX)
+ levels.m_gotoI = k + 1;
+ if (levels.m_forI == 0 && l1.points[k][0] > levels.finishX)
+ levels.m_forI = k;
+ }
+
+ m_eaI = 0;
+ m_faI = 0;
+ m_aI = 0;
+ m_kI = 0;
+ } catch (ArithmeticException e) {
+ throw new InvalidTrackException(e);
+ }
+ }
+
+ public void _ifIIV(int j, int k) {
+ levels._ifIIV(j, k);
+ }
+
+ public void _aiIV(GameView j, int k, int i1) {
+ if (j != null) {
+ j.setColor(0, 170, 0);
+ k >>= 1;
+ i1 >>= 1;
+ levels._aiIV(j, k, i1);
+ }
+ }
+
+ public void _aiV(GameView j) {
+ j.setColor(0, 255, 0);
+ levels._aiV(j);
+ }
+
+ public void _aIIV(int j, int k, int i1) {
+ levels._aIIV(j + 0x18000 >> 1, k - 0x18000 >> 1, i1 >> 1);
+ k >>= 1;
+ j >>= 1;
+ m_faI = m_faI >= levels.pointsCount - 1 ? levels.pointsCount - 1 : m_faI;
+ m_eaI = m_eaI >= 0 ? m_eaI : 0;
+ if (k > m_kI)
+ while (m_faI < levels.pointsCount - 1 && k > levels.points[++m_faI][0]) ;
+ else if (j < m_aI) {
+ while (m_eaI > 0 && j < levels.points[--m_eaI][0]) ;
+ } else {
+ while (m_eaI < levels.pointsCount && j > levels.points[++m_eaI][0]) ;
+ if (m_eaI > 0)
+ m_eaI--;
+ while (m_faI > 0 && k < levels.points[--m_faI][0]) ;
+ m_faI = m_faI + 1 >= levels.pointsCount - 1 ? levels.pointsCount - 1 : m_faI + 1;
+ }
+ m_aI = levels.points[m_eaI][0];
+ m_kI = levels.points[m_faI][0];
+ }
+
+ public int _anvI(SimpleMenuElement n1, int j) {
+ int k3 = 0;
+ byte byte1 = 2;
+ int l3 = n1.x >> 1;
+ int i4 = n1.y >> 1;
+ if (perspectiveEnabled)
+ i4 -= 0x10000;
+ int j4 = 0;
+ int k4 = 0;
+ for (int l4 = m_eaI; l4 < m_faI; l4++) {
+ int k = levels.points[l4][0];
+ int i1 = levels.points[l4][1];
+ int j1 = levels.points[l4 + 1][0];
+ int k1;
+ int _tmp = (k1 = levels.points[l4 + 1][1]) < i1 ? i1 : k1;
+ if (l3 - m_haI[j] > j1 || l3 + m_haI[j] < k)
+ continue;
+ int l1 = k - j1;
+ int i2 = i1 - k1;
+ int j2 = (int) ((long) l1 * (long) l1 >> 16) + (int) ((long) i2 * (long) i2 >> 16);
+ int k2 = (int) ((long) (l3 - k) * (long) (-l1) >> 16) + (int) ((long) (i4 - i1) * (long) (-i2) >> 16);
+ int l2;
+ if ((j2 >= 0 ? j2 : -j2) >= 3)
+ l2 = (int) (((long) k2 << 32) / (long) j2 >> 16);
+ else
+ l2 = (k2 <= 0 ? -1 : 1) * (j2 <= 0 ? -1 : 1) * 0x7fffffff;
+ if (l2 < 0)
+ l2 = 0;
+ if (l2 > 0x10000)
+ l2 = 0x10000;
+ int i3 = k + (int) ((long) l2 * (long) (-l1) >> 16);
+ int j3 = i1 + (int) ((long) l2 * (long) (-i2) >> 16);
+ l1 = l3 - i3;
+ i2 = i4 - j3;
+ byte byte0;
+ long l5;
+ if ((l5 = ((long) l1 * (long) l1 >> 16) + ((long) i2 * (long) i2 >> 16)) < (long) m_haI[j]) {
+ if (l5 >= (long) m_vaI[j])
+ byte0 = 1;
+ else
+ byte0 = 0;
+ } else {
+ byte0 = 2;
+ }
+ if (byte0 == 0 && (int) ((long) m_saaI[l4][0] * (long) n1.m_eI >> 16) + (int) ((long) m_saaI[l4][1] * (long) n1.m_dI >> 16) < 0) {
+ m_eI = m_saaI[l4][0];
+ m_dI = m_saaI[l4][1];
+ return 0;
+ }
+ if (byte0 != 1 || (int) ((long) m_saaI[l4][0] * (long) n1.m_eI >> 16) + (int) ((long) m_saaI[l4][1] * (long) n1.m_dI >> 16) >= 0)
+ continue;
+ k3++;
+ byte1 = 1;
+ if (k3 == 1) {
+ j4 = m_saaI[l4][0];
+ k4 = m_saaI[l4][1];
+ } else {
+ j4 += m_saaI[l4][0];
+ k4 += m_saaI[l4][1];
+ }
+ }
+
+ if (byte1 == 1) {
+ if ((int) ((long) j4 * (long) n1.m_eI >> 16) + (int) ((long) k4 * (long) n1.m_dI >> 16) >= 0)
+ return 2;
+ m_eI = j4;
+ m_dI = k4;
+ }
+ return byte1;
+ }
+
+ public boolean isShadowsEnabled() {
+ return shadowsEnabled;
+ }
+
+ public boolean isPerspectiveEnabled() {
+ return perspectiveEnabled;
+ }
+
+ public void setPerspectiveEnabled(boolean enabled) {
+ perspectiveEnabled = enabled;
+ }
+
+ public void setShadowsEnabled(boolean enabled) {
+ shadowsEnabled = enabled;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Levels/Reader.java b/src/org/happysanta/gd/Levels/Reader.java
new file mode 100644
index 0000000..f0ce9a6
--- /dev/null
+++ b/src/org/happysanta/gd/Levels/Reader.java
@@ -0,0 +1,52 @@
+package org.happysanta.gd.Levels;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.happysanta.gd.Helpers.decodeCp1251;
+
+public class Reader {
+
+ private static final int MAX_VALID_TRACKS = 16384;
+
+ public static LevelHeader readHeader(InputStream in) throws IOException {
+ LevelHeader header = new LevelHeader();
+ DataInputStream din = new DataInputStream(in);
+ byte buf[] = new byte[40];
+ String tmp;
+ for (int i = 0; i < 3; i++) {
+ int tCount = din.readInt();
+ if (tCount > MAX_VALID_TRACKS) {
+ din.close();
+ throw new IOException("Level file is not valid");
+ }
+ header.setCount(i, tCount);
+
+ label0:
+ for (int j = 0; j < header.getCount(i); j++) {
+ int trackPointer = din.readInt();
+ header.setPointer(i, j, trackPointer);
+ int nameLen = 0;
+ do {
+ if (nameLen >= 40)
+ continue label0;
+
+ buf[nameLen] = din.readByte();
+ if (buf[nameLen] == 0) {
+ // tmp = (new String(buf, 0, nameLen, "CP-1251"));
+ tmp = decodeCp1251(buf);
+ header.setName(i, j, tmp.replace('_', ' '));
+ continue label0;
+ }
+ nameLen++;
+ } while (true);
+ }
+
+ }
+ din.close();
+
+ return header;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/ActionMenuElement.java b/src/org/happysanta/gd/Menu/ActionMenuElement.java
new file mode 100755
index 0000000..fb0b706
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/ActionMenuElement.java
@@ -0,0 +1,141 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+import org.happysanta.gd.R;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class ActionMenuElement
+ extends ClickableMenuElement
+ implements MenuHandler, MenuElement {
+
+ protected static final int DISABLED_COLOR = 0xff999999;
+ public static final int LOCK_IMAGE_MARGIN_RIGHT = 5;
+ public static final int locks[] = new int[]{
+ R.drawable.s_lock0,
+ R.drawable.s_lock1,
+ R.drawable.s_lock2
+ };
+
+ public static final int LINE_SPACING = 15;
+ public static final int X_OFFSET = 48;
+
+ public static final int OK = 0;
+ public static final int BACK = 1;
+ public static final int EXIT = 2;
+ public static final int YES = 3;
+ public static final int NO = 4;
+ public static final int PLAY_MENU = 5;
+ public static final int GO_TO_MAIN = 6;
+ public static final int RESTART = 7;
+ public static final int NEXT = 8;
+ public static final int CONTINUE = 9;
+ public static final int INSTALL = 10;
+ public static final int LOAD = 11;
+ public static final int SELECT_FILE = 12;
+ public static final int DELETE = 13;
+ public static final int RESTART_WITH_NEW_LEVEL = 14;
+ public static final int SEND_LOGS = 15;
+
+ protected MenuHandler handler;
+ protected boolean isLocked = false;
+ protected boolean isBlackLock = true;
+ protected MenuImageView lockImage = null;
+
+ protected int actionValue = -1;
+
+ public ActionMenuElement(String s, int value, MenuHandler handler) {
+ actionValue = value;
+ this.handler = handler;
+
+ text = s;
+
+ createAllViews();
+ }
+
+ @Override
+ protected void createAllViews() {
+ super.createAllViews();
+
+ Context context = getGDActivity();
+ lockImage = new MenuImageView(context);
+ lockImage.setScaleType(ImageView.ScaleType.CENTER);
+ lockImage.setVisibility(View.GONE);
+
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
+ lp.setMargins(0, 0, getDp(ActionMenuElement.LOCK_IMAGE_MARGIN_RIGHT), 0);
+ lockImage.setLayoutParams(lp);
+
+ layout.addView(lockImage, 1);
+ }
+
+ public ActionMenuElement(String s, MenuHandler handler/*, MenuScreen screen*/) {
+ this(s, -1, handler);
+ }
+
+ public int getActionValue() {
+ return actionValue;
+ }
+
+ public void setHandler(MenuHandler hander) {
+ this.handler = hander;
+ }
+
+ public void setLock(boolean flag, boolean flag1) {
+ isLocked = flag;
+ isBlackLock = flag1;
+
+ lockImage.setVisibility(isLocked ? View.VISIBLE : View.GONE);
+ lockImage.setImageResource(locks[isBlackLock ? 0 : 1]);
+ }
+
+ @Override
+ public void setText(String s) {
+ text = s;
+ updateViewText();
+ }
+
+ @Override
+ public void performAction(int k) {
+ if (disabled || handler == null) return;
+
+ if (k == MenuScreen.KEY_FIRE) {
+ handler.handleAction(this);
+ }
+ }
+
+ @Override
+ protected void onHighlightChanged() {
+ lockImage.setImageResource(locks[isHighlighted ? 2 : (isBlackLock ? 0 : 1)]);
+ }
+
+ @Override
+ public MenuScreen getCurrentMenu() {
+ return null;
+ }
+
+ @Override
+ public void setCurrentMenu(MenuScreen e1, boolean flag) {
+ }
+
+ @Override
+ public void handleAction(MenuElement item) {
+ }
+
+ public void setDisabled(boolean disabled) {
+ this.disabled = disabled;
+
+ if (disabled) {
+ ((MenuTextView) textView).setTextColor(DISABLED_COLOR);
+ } else {
+ ((MenuTextView) textView).setTextColor(defaultColorStateList());
+ }
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/BigTextMenuElement.java b/src/org/happysanta/gd/Menu/BigTextMenuElement.java
new file mode 100644
index 0000000..8b30e64
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/BigTextMenuElement.java
@@ -0,0 +1,30 @@
+package org.happysanta.gd.Menu;
+
+import android.text.Spanned;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+
+public class BigTextMenuElement
+ extends TextMenuElement {
+
+ public static final int TEXT_SIZE = 19;
+
+ public BigTextMenuElement(String s) {
+ super(s);
+ createTextView();
+ setTextParams(textView);
+ }
+
+ public BigTextMenuElement(Spanned s) {
+ super(s);
+ createTextView();
+ setTextParams(textView);
+ }
+
+ protected static void setTextParams(MenuTextView textView) {
+ textView.setTextSize(TEXT_SIZE);
+ textView.setTypeface(Global.robotoCondensedTypeface);
+ textView.setLineSpacing(0f, 1.2f);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/ClickableMenuElement.java b/src/org/happysanta/gd/Menu/ClickableMenuElement.java
new file mode 100644
index 0000000..f33db34
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/ClickableMenuElement.java
@@ -0,0 +1,196 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.MenuHelmetView;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+import org.happysanta.gd.R;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class ClickableMenuElement
+ implements MenuElement {
+
+ public static final int TEXT_SIZE = 20;
+ public static final int PADDING_TOP = 5;
+ protected View textView;
+ protected String text;
+ protected View.OnTouchListener onTouchListener;
+ protected LinearLayout layout;
+ protected MenuHelmetView helmet;
+ protected OnMenuElementHighlightListener onMenuElementHighlightListener = null;
+ protected boolean isHighlighted = false;
+ protected Thread originalThread = null;
+ protected boolean disabled = false;
+
+ public ClickableMenuElement() {
+ }
+
+ public ClickableMenuElement(String text) {
+ this.text = text;
+ originalThread = Thread.currentThread();
+
+ createAllViews();
+ }
+
+ protected boolean inViewBounds(View view, int x, int y) {
+ Rect rect = new Rect();
+ int location[] = new int[2];
+
+ view.getDrawingRect(rect);
+ view.getLocationOnScreen(location);
+ rect.offset(location[0], location[1]);
+
+ return rect.contains(x, y);
+ }
+
+ protected void createAllViews() {
+ final ClickableMenuElement self = this;
+ Context context = getGDActivity();
+
+ layout = new LinearLayout(context);
+ layout.setOrientation(LinearLayout.HORIZONTAL);
+ layout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ helmet = new MenuHelmetView(context);
+ helmet.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
+
+ /*if (!isSDK11OrHigher()) {
+ helmet.setMeasuredHeight(true);
+ }*/
+
+ onTouchListener = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ if (disabled) return false;
+
+ switch (motionEvent.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ view.setSelected(true);
+ helmet.setShow(true);
+
+ if (onMenuElementHighlightListener != null)
+ onMenuElementHighlightListener.onElementHighlight(self);
+
+ setHighlighted(true);
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ view.setSelected(false);
+
+ if (motionEvent.getAction() == MotionEvent.ACTION_UP && inViewBounds(view, (int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
+ performAction(MenuScreen.KEY_FIRE);
+ }
+
+ setHighlighted(false);
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (!inViewBounds(view, (int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
+ view.setSelected(false);
+ setHighlighted(false);
+ } else {
+ view.setSelected(true);
+ setHighlighted(true);
+ }
+ break;
+ }
+ return true;
+ }
+ };
+
+ textView = createMainView();
+
+ layout.addView(helmet);
+ layout.addView(textView);
+ layout.setOnTouchListener(onTouchListener);
+ }
+
+ protected View createMainView() {
+ Context context = getGDActivity();
+ MenuTextView mtv = new MenuTextView(context);
+ mtv.setText(getTextForView());
+ mtv.setTextColor(defaultColorStateList());
+ mtv.setTypeface(Global.robotoCondensedTypeface);
+ mtv.setTextSize(TEXT_SIZE);
+ mtv.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ ));
+ mtv.setPadding(0, getDp(PADDING_TOP), 0, getDp(PADDING_TOP));
+
+ return mtv;
+ }
+
+ protected ColorStateList defaultColorStateList() {
+ return getGDActivity().getResources().getColorStateList(R.drawable.menu_item_color);
+ }
+
+ @Override
+ public boolean isSelectable() {
+ return true;
+ }
+
+ @Override
+ public View getView() {
+ return layout;
+ }
+
+ protected MenuTextView getMenuTextView() {
+ return (MenuTextView) textView;
+ }
+
+ @Override
+ public void setText(String text) {
+ this.text = text;
+ updateViewText();
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ protected void updateViewText() {
+ if (textView != null && textView instanceof MenuTextView)
+ ((MenuTextView) textView).setTextOnUiThread(getTextForView());
+ }
+
+ protected String getTextForView() {
+ return text;
+ }
+
+ @Override
+ public void performAction(int k) {
+
+ }
+
+ public void setOnHighlightListener(OnMenuElementHighlightListener listener) {
+ onMenuElementHighlightListener = listener;
+ }
+
+ public void showHelmet() {
+ helmet.setShow(true);
+ }
+
+ private void setHighlighted(boolean highlighted) {
+ isHighlighted = highlighted;
+ onHighlightChanged();
+ }
+
+ protected void onHighlightChanged() {
+ }
+
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/DownloadLevelsMenuScreen.java b/src/org/happysanta/gd/Menu/DownloadLevelsMenuScreen.java
new file mode 100755
index 0000000..fe072ce
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/DownloadLevelsMenuScreen.java
@@ -0,0 +1,222 @@
+package org.happysanta.gd.Menu;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.View;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+import org.happysanta.gd.API.*;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.R;
+import org.happysanta.gd.API.Response;
+import org.happysanta.gd.Settings;
+import org.happysanta.gd.WaitForNetworkConnection;
+
+import static org.happysanta.gd.Helpers.*;
+import static org.happysanta.gd.Helpers.getDp;
+
+public class DownloadLevelsMenuScreen extends LevelsMenuScreen {
+
+ protected final static int API_LIMIT = 100;
+ public static API.LevelsSortType sort;
+
+ protected MenuImageView sortImage;
+ // protected API api;
+ protected Request request;
+ protected int offset = 0;
+ protected boolean isLoading = false;
+ protected boolean fullLoaded = false;
+ protected WaitForNetworkConnection waitForNetworkConnection = null;
+ protected Toast toast;
+
+ public DownloadLevelsMenuScreen(String title, MenuScreen navTarget) {
+ super(title, navTarget);
+
+ // api = new API();
+ // api.setSort(sort);
+
+ Context context = getGDActivity();
+
+ // Sort icon
+ sortImage = new MenuImageView(context);
+ sortImage.setImageResource(R.drawable.ic_sort);
+ sortImage.setAdjustViewBounds(true);
+ sortImage.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showSortDialog();
+ }
+ });
+ sortImage.setVisibility(View.GONE);
+ sortImage.setPadding(getDp(10), 0, 0, 0);
+
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ getDp(40)
+ );
+ params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+
+ sortImage.setLayoutParams(params);
+ }
+
+ @Override
+ protected void loadLevels() {
+ try {
+ if (!checkNetwork())
+ return;
+
+ showLoading();
+ isLoading = true;
+ request = API.getLevels(offset, API_LIMIT, sort, new ResponseHandler() {
+ @Override
+ public void onResponse(final Response response) {
+ final LevelsResponse levelsResponse = new LevelsResponse(response);
+ if (status != Statuses.NORMAL) {
+ clearList();
+ setStatus(Statuses.NORMAL);
+ }
+
+ hideLoading();
+
+ addElements = new AsyncAddElements() {
+ @Override
+ protected void onPostExecute(Void v) {
+ logDebug("offset = " + offset + ", totalCount = " + levelsResponse.getTotalCount());
+ fullLoaded = offset >= levelsResponse.getTotalCount();
+ if (!fullLoaded)
+ showLoading();
+
+ isLoading = false;
+ }
+ };
+ addElements.execute(levelsResponse.getLevels());
+ }
+
+ @Override
+ public void onError(APIException error) {
+ showError(error.getMessage());
+ isLoading = false;
+ }
+ });
+
+ offset += API_LIMIT;
+ } catch (Exception e) {
+ e.printStackTrace();
+ showError(getString(R.string.download_error));
+
+ isLoading = false;
+ }
+ }
+
+ @Override
+ public void reloadLevels() {
+ if (request != null) request.cancel();
+ offset = 0;
+ isLoading = false;
+ fullLoaded = false;
+
+ super.reloadLevels();
+ }
+
+ protected void showSortDialog() {
+ final CharSequence[] items = getStringArray(R.array.sort_variants);
+
+ AlertDialog dialog = new AlertDialog.Builder(getGDActivity())
+ .setTitle(getString(R.string.sort_by))
+ .setSingleChoiceItems(items, API.getIdBySortType(sort), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int item) {
+ API.LevelsSortType newSort = API.getSortTypeById(item);
+
+ if (newSort != sort) {
+ sort = newSort;
+ // api.setSort(newSort);
+ Settings.setLevelsSort(sort);
+ reloadLevels();
+ }
+
+ dialog.dismiss();
+ }
+ })
+ .create();
+
+ dialog.show();
+ }
+
+ protected boolean checkNetwork() {
+ if (!isOnline()) {
+ if (elements.isEmpty()) {
+ showError(getString(R.string.waiting_for_network));
+
+ if (waitForNetworkConnection != null)
+ waitForNetworkConnection.cancel(true);
+
+ waitForNetworkConnection = new WaitForNetworkConnection();
+ waitForNetworkConnection.execute(null, new Runnable() {
+ @Override
+ public void run() {
+ reloadLevels();
+ }
+ });
+ } else {
+ if (toast != null) {
+ toast.cancel();
+ }
+
+ toast = Toast.makeText(getGDActivity().getApplicationContext(), getString(R.string.no_internet_connection), Toast.LENGTH_SHORT);
+ toast.show();
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onHide(MenuScreen newMenu) {
+ logDebug("onHide");
+ super.onHide(newMenu);
+
+ GDActivity activity = getGDActivity();
+
+ if (newMenu != getGameMenu().levelScreen) {
+ offset = 0;
+ isLoading = false;
+ fullLoaded = false;
+
+ if (request != null) request.cancel();
+ // api.cancelRequest();
+ if (waitForNetworkConnection != null)
+ waitForNetworkConnection.cancel(true);
+ }
+
+ activity.titleLayout.removeView(sortImage);
+ sortImage.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onShow() {
+ super.onShow();
+
+ GDActivity activity = getGDActivity();
+
+ activity.titleLayout.addView(sortImage);
+ sortImage.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onScroll(double percent) {
+ if (percent >= 97 && !isLoading && !fullLoaded) {
+ loadLevels();
+ }
+ }
+
+ @Override
+ public void deleteElement(LevelMenuElement el) {
+ super.deleteElement(el);
+ offset--;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/EmptyLineMenuElement.java b/src/org/happysanta/gd/Menu/EmptyLineMenuElement.java
new file mode 100755
index 0000000..e0901f9
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/EmptyLineMenuElement.java
@@ -0,0 +1,42 @@
+package org.happysanta.gd.Menu;
+
+import android.view.View;
+import android.view.ViewGroup;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class EmptyLineMenuElement implements MenuElement {
+
+ protected String text;
+ protected int offset;
+ protected MenuTextView view;
+
+ EmptyLineMenuElement(int offset) {
+ this.offset = offset;
+
+ view = new MenuTextView(getGDActivity());
+ view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDp(offset)));
+ }
+
+ @Override
+ public View getView() {
+ return view;
+ }
+
+ @Override
+ public boolean isSelectable() {
+ return false;
+ }
+
+ @Override
+ public void setText(String s) {
+ text = s;
+ }
+
+ @Override
+ public void performAction(int k) {
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/HighScoreTextMenuElement.java b/src/org/happysanta/gd/Menu/HighScoreTextMenuElement.java
new file mode 100755
index 0000000..fc392df
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/HighScoreTextMenuElement.java
@@ -0,0 +1,100 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.text.Spanned;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+import org.happysanta.gd.R;
+
+import static org.happysanta.gd.Helpers.*;
+
+public class HighScoreTextMenuElement
+ extends TextMenuElement
+ implements MenuElement {
+
+ protected static final int TEXT_LEFT_MARGIN = 5;
+ protected static final int SUBTITLE_MARGIN_BOTTOM = 8;
+ protected static final int SUBTITLE_TEXT_SIZE = 20;
+ protected static final int LAYOUT_PADDING = 3;
+ protected static int medals[] = new int[]{
+ R.drawable.s_medal_gold,
+ R.drawable.s_medal_silver,
+ R.drawable.s_medal_bronze
+ };
+ protected static Typeface defaultTypeface = null;
+
+ protected boolean showMedal = false;
+ protected MenuLinearLayout layout;
+ protected MenuImageView image;
+
+ public HighScoreTextMenuElement(String s) {
+ super(s);
+ createAllViews();
+ }
+
+ public HighScoreTextMenuElement(Spanned text) {
+ super(text);
+ createAllViews();
+ }
+
+ protected void createAllViews() {
+ Context context = getGDActivity();
+
+ layout = new MenuLinearLayout(context);
+ layout.setOrientation(LinearLayout.HORIZONTAL);
+ layout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ image = new MenuImageView(context);
+ image.setScaleType(ImageView.ScaleType.CENTER);
+ image.setVisibility(View.GONE);
+
+ // textView was already created in super constructor
+ textView.setLineSpacing(0, 1);
+
+ if (defaultTypeface == null) {
+ defaultTypeface = textView.getTypeface();
+ }
+
+ LinearLayout.LayoutParams textViewLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ // textViewLayoutParams.setMargins(getDp(TEXT_LEFT_MARGIN), 0, 0, 0);
+ textView.setLayoutParams(textViewLayoutParams);
+
+ layout.addView(image, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
+ layout.addView(textView);
+ }
+
+ @Override
+ public View getView() {
+ return layout;
+ }
+
+ public void setMedal(boolean showMedal, int medalIndex) {
+ image.setVisibility(showMedal ? View.VISIBLE : View.GONE);
+ image.setImageResource(medals[medalIndex]);
+
+ LinearLayout.LayoutParams textViewLayoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();
+ textViewLayoutParams.setMargins(showMedal ? getDp(TEXT_LEFT_MARGIN) : 0, 0, 0, 0);
+ textView.setLayoutParams(textViewLayoutParams);
+
+ this.showMedal = showMedal;
+ }
+
+ public void setIsSubtitle(boolean is) {
+ textView.setTextSize(is ? SUBTITLE_TEXT_SIZE : TEXT_SIZE);
+ textView.setTypeface(is ? Global.robotoCondensedTypeface : defaultTypeface);
+
+ LinearLayout.LayoutParams textViewLayoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();
+ textViewLayoutParams.setMargins(!is && showMedal ? getDp(TEXT_LEFT_MARGIN) : 0, 0, 0, is ? getDp(SUBTITLE_MARGIN_BOTTOM) : 0);
+ textView.setLayoutParams(textViewLayoutParams);
+ }
+
+ public void setLayoutPadding(boolean use) {
+ layout.setPadding(0, use ? getDp(LAYOUT_PADDING) : 0, 0, use ? getDp(LAYOUT_PADDING) : 0);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/InstalledLevelsMenuScreen.java b/src/org/happysanta/gd/Menu/InstalledLevelsMenuScreen.java
new file mode 100644
index 0000000..b3adbab
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/InstalledLevelsMenuScreen.java
@@ -0,0 +1,103 @@
+package org.happysanta.gd.Menu;
+
+import android.os.AsyncTask;
+import android.view.ViewTreeObserver;
+import org.happysanta.gd.Storage.Level;
+import org.happysanta.gd.Storage.LevelsManager;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class InstalledLevelsMenuScreen extends LevelsMenuScreen {
+
+ LevelsManager levelsManager;
+ protected boolean isLoading = false;
+ AsyncLoadLevels asyncLoadLevels = null;
+
+ public InstalledLevelsMenuScreen(String title, MenuScreen navTarget) {
+ super(title, navTarget);
+ levelsManager = getGDActivity().levelsManager;
+ }
+
+ @Override
+ public void loadLevels() {
+ showLoading();
+ isLoading = true;
+
+ asyncLoadLevels = new AsyncLoadLevels() {
+ @Override
+ public void onPostExecute(Level[] levels) {
+ if (status != Statuses.NORMAL) {
+ clearList();
+ setStatus(Statuses.NORMAL);
+ }
+ hideLoading();
+
+ addElements = new AsyncAddElements() {
+ @Override
+ protected void onPostExecute(Void v) {
+ isLoading = false;
+ if (selectedIndex != -1) {
+ // listLayout.requestLayout();
+ // listLayout.invalidate();
+
+ // View someView = findViewById(R.id.someView);
+ final ViewTreeObserver obs = listLayout.getViewTreeObserver();
+ obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+
+ public boolean onPreDraw() {
+ scrollToItem(selectedIndex);
+ try {
+ obs.removeOnPreDrawListener(this);
+ } catch (IllegalStateException e) {
+ }
+
+ return true;
+ }
+ });
+
+ // scrollToItem(selectedIndex);
+ }
+ }
+ };
+ addElements.execute(levels);
+ }
+ };
+ asyncLoadLevels.execute();
+ }
+
+ @Override
+ public void onShow() {
+ super.onShow();
+ }
+
+ @Override
+ public void onHide(MenuScreen newMenu) {
+ super.onHide(newMenu);
+ }
+
+ @Override
+ protected boolean hideDate() {
+ return true;
+ }
+
+ @Override
+ public void reloadLevels() {
+ if (asyncLoadLevels != null) {
+ asyncLoadLevels.cancel(true);
+ asyncLoadLevels = null;
+ }
+
+ isLoading = false;
+ super.reloadLevels();
+ }
+
+ private class AsyncLoadLevels extends AsyncTask<Void, Void, Level[]> {
+
+ @Override
+ protected Level[] doInBackground(Void... params) {
+ return levelsManager.getAllInstalledLevels();
+ }
+
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/LevelMenuElement.java b/src/org/happysanta/gd/Menu/LevelMenuElement.java
new file mode 100755
index 0000000..e577e94
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/LevelMenuElement.java
@@ -0,0 +1,370 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.text.Html;
+import android.text.SpannableString;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import org.happysanta.gd.Callback;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.LevelNameLeadingMarginSpan2;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+import org.happysanta.gd.Menu.Views.MenuRelativeLayout;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+import org.happysanta.gd.R;
+import org.happysanta.gd.Storage.Level;
+import org.happysanta.gd.Storage.LevelsManager;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getGameMenu;
+import static org.happysanta.gd.Helpers.getLevelsManager;
+import static org.happysanta.gd.Helpers.getString;
+import static org.happysanta.gd.Helpers.logDebug;
+import static org.happysanta.gd.Helpers.showConfirm;
+
+public class LevelMenuElement
+ extends ClickableMenuElement
+ implements MenuHandler {
+
+ protected static final int PADDING_TOP = 7;
+ protected static final int PADDING_BOTTOM = 7;
+ protected static final int LEVEL_TEXT_SIZE = 16;
+ protected static final int NAME_SIZE = 20;
+
+ protected static final int INSTALLED_MARGIN = 15;
+ protected static final int ACTIVE_MARGIN = 21;
+
+ protected Level level;
+
+ protected MenuTextView textView;
+ protected MenuLinearLayout mainLayout;
+ protected MenuRelativeLayout nameLayout;
+ protected MenuTextView tracksCountTextView;
+ protected MenuScreen screen;
+ protected MenuImageView installedIcon = null;
+ protected MenuImageView activeIcon = null;
+ protected boolean installed = false;
+ protected boolean active = false;
+ protected boolean showDate = true;
+
+ public LevelMenuElement() {
+ }
+
+ public LevelMenuElement(Level level, MenuScreen screen) {
+ this.level = level;
+ this.screen = screen;
+
+ createAllViews();
+ }
+
+ @Override
+ protected View createMainView() {
+ Context context = getGDActivity();
+
+ mainLayout = new MenuLinearLayout(context);
+ mainLayout.setOrientation(LinearLayout.VERTICAL);
+ mainLayout.setPadding(0, getDp(PADDING_TOP), 0, getDp(PADDING_BOTTOM));
+
+ nameLayout = new MenuRelativeLayout(context);
+ // nameLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+ // Text
+ textView = new MenuTextView(context);
+ // textView.setText(level.getName());
+ updateNameLine();
+ textView.setTextColor(context.getResources().getColorStateList(R.drawable.menu_item_color));
+ textView.setTypeface(Global.robotoCondensedTypeface);
+ textView.setTextSize(NAME_SIZE);
+ textView.setLineSpacing(0f, 1.1f);
+ textView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ ));
+ textView.setPadding(0, getDp(PADDING_TOP), 0, 0);
+
+ tracksCountTextView = new MenuTextView(context);
+ tracksCountTextView.setTextSize(LEVEL_TEXT_SIZE);
+ tracksCountTextView.setTypeface(Global.robotoCondensedTypeface);
+ updateLevelsLine();
+
+ nameLayout.addView(textView);
+ mainLayout.addView(nameLayout);
+ mainLayout.addView(tracksCountTextView);
+
+ return mainLayout;
+ }
+
+ public void updateNameLine() {
+ String name = level.getName() + (Global.DEBUG ? " (id" + level.getAnyId() + ")" : "");
+ // if (!active) {
+ int margin = 0;
+ if (installed)
+ margin = INSTALLED_MARGIN;
+ else if (active)
+ margin = ACTIVE_MARGIN;
+
+ SpannableString ss = new SpannableString(name);
+ ss.setSpan(new LevelNameLeadingMarginSpan2(1, installed || active ? getDp(margin) : 0), 0, ss.length(), 0);
+ textView.setTextOnUiThread(ss);
+ /*} else {
+ textView.setTextOnUiThread(Html.fromHtml(String.format(getString(R.string.active_name_tpl), name)));
+ }*/
+ }
+
+ public void updateLevelsLine() {
+ if (showDate) {
+ tracksCountTextView.setText(Html.fromHtml(String.format(getString(R.string.levels_count_tpl),
+ level.getCountEasy() + " - " + level.getCountMedium() + " - " + level.getCountHard(), level.getShortAddedDate())));
+ } else {
+ tracksCountTextView.setText(level.getCountEasy() + " - " + level.getCountMedium() + " - " + level.getCountHard());
+ }
+ }
+
+ @Override
+ protected void onHighlightChanged() {
+ if (installed && installedIcon != null) {
+ installedIcon.setImageResource(isHighlighted ? R.drawable.ic_downloaded_selected : R.drawable.ic_downloaded);
+ }
+ if (active && activeIcon != null) {
+ activeIcon.setImageResource(isHighlighted ? R.drawable.ic_installed_selected : R.drawable.ic_installed);
+ }
+ }
+
+ @Override
+ protected void createAllViews() {
+ super.createAllViews();
+
+ helmet.setMeasuredHeight(true);
+
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ lp.setMargins(0, getDp(PADDING_TOP * 2 + 5), 0, 0);
+
+ helmet.setLayoutParams(lp);
+ }
+
+ public void setInstalled(boolean installed) {
+ this.installed = installed;
+ if (installed) {
+ if (installedIcon == null) {
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT
+ );
+ // params.setMargins(0, getDp(PADDING_TOP * 2 + 2), getDp(7), 0);
+ params.setMargins(0, getDp(PADDING_TOP * 2 + 2), 0, 0);
+
+ installedIcon = new MenuImageView(getGDActivity());
+ installedIcon.setLayoutParams(params);
+ installedIcon.setImageResource(R.drawable.ic_downloaded);
+ }
+
+ if (installedIcon.getParent() != nameLayout) {
+ nameLayout.addView(installedIcon);
+ }
+ } else if (!installed && installedIcon != null && installedIcon.getParent() == nameLayout) {
+ nameLayout.removeView(installedIcon);
+ }
+
+ updateNameLine();
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ if (active) {
+ if (activeIcon == null) {
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
+ RelativeLayout.LayoutParams.WRAP_CONTENT,
+ RelativeLayout.LayoutParams.WRAP_CONTENT
+ );
+ // params.setMargins(0, getDp(PADDING_TOP * 2 + 2), getDp(7), 0);
+ params.setMargins(0, getDp(PADDING_TOP * 2 + 2), 0, 0);
+
+ activeIcon = new MenuImageView(getGDActivity());
+ activeIcon.setLayoutParams(params);
+ activeIcon.setImageResource(R.drawable.ic_installed);
+ }
+
+ if (activeIcon.getParent() != nameLayout) {
+ nameLayout.addView(activeIcon);
+ }
+ } else if (!active && activeIcon != null && activeIcon.getParent() == nameLayout) {
+ nameLayout.removeView(activeIcon);
+ }
+
+ updateNameLine();
+ }
+
+ public void setShowDate(boolean showDate) {
+ this.showDate = showDate;
+ updateLevelsLine();
+ }
+
+ @Override
+ public void performAction(int k) {
+ if (k == MenuScreen.KEY_FIRE) {
+ buildScreen();
+ }
+ }
+
+ protected void buildScreen() {
+ Menu menu = getGameMenu();
+ MenuScreen screen = menu.levelScreen;
+ LevelsManager levelsManager = getLevelsManager();
+
+ screen.clear();
+ // System.gc();
+
+ logDebug(level);
+
+ screen.setNavTarget(this.screen);
+ screen.setTitle(level.getName());
+
+ if (!level.getAuthor().equals(""))
+ screen.addItem(new BigTextMenuElement(Html.fromHtml(String.format(getString(R.string.author_tpl), level.getAuthor()))));
+ if (level.getInstalledTs() > 0)
+ screen.addItem(new BigTextMenuElement(Html.fromHtml(String.format(getString(R.string.installed_tpl), level.getFullInstalledDate()))));
+ else if (level.getAddedTs() > 0)
+ screen.addItem(new BigTextMenuElement(Html.fromHtml(String.format(getString(R.string.added_tpl), level.getFullAddedDate()))));
+ screen.addItem(new BigTextMenuElement(Html.fromHtml(String.format(getString(R.string.tracks_tpl), level.getCountEasy() + " / " + level.getCountMedium() + " / " + level.getCountHard()))));
+ screen.addItem(menu.createEmptyLine(true));
+
+ if (!level.isInstalled()) {
+ ActionMenuElement installAction = menu.createAction(ActionMenuElement.INSTALL);
+ installAction.setText(String.format(
+ getString(R.string.install_kb), level.getSizeKb()
+ ));
+ installAction.setHandler(this);
+
+ screen.addItem(installAction);
+ } else {
+ if (!level.isDefault()) {
+ ActionMenuElement installed = new ActionMenuElement(getString(R.string.installed), null);
+ installed.setDisabled(true);
+ screen.addItem(installed);
+ }
+
+ if (level.getId() == levelsManager.getCurrentId()) {
+ ActionMenuElement active = new ActionMenuElement(getString(R.string.active), null);
+ active.setDisabled(true);
+ screen.addItem(active);
+ } else {
+ ActionMenuElement loadAction = menu.createAction(ActionMenuElement.LOAD);
+ loadAction.setHandler(this);
+ screen.addItem(loadAction);
+ }
+
+ if (!level.isDefault() && levelsManager.getCurrentId() != level.getId()) {
+ ActionMenuElement deleteAction = menu.createAction(ActionMenuElement.DELETE);
+ deleteAction.setHandler(this);
+
+ screen.addItem(deleteAction);
+ }
+ }
+
+ screen.addItem(menu.createAction(ActionMenuElement.BACK));
+
+ if (menu.getCurrentMenu() != screen) {
+ menu.setCurrentMenu(screen, false);
+ } else {
+ screen.highlightElement();
+ }
+ }
+
+ @Override
+ public MenuScreen getCurrentMenu() {
+ return null;
+ }
+
+ @Override
+ public void setCurrentMenu(MenuScreen e1, boolean flag) {
+ }
+
+ @Override
+ public void handleAction(MenuElement item) {
+ if (item instanceof ActionMenuElement) {
+ final GDActivity gd = getGDActivity();
+ final Menu menu = getGameMenu();
+
+ switch (((ActionMenuElement) item).getActionValue()) {
+ case ActionMenuElement.DELETE:
+ if (!level.isInstalled())
+ break;
+
+ showConfirm(
+ getString(R.string.delete_levels),
+ getString(R.string.delete_levels_confirmation),
+ new Runnable() {
+ @Override
+ public void run() {
+ gd.levelsManager.deleteAsync(level, new Runnable() {
+ @Override
+ public void run() {
+ long id = level.getId();
+
+ MenuScreen target = menu.getCurrentMenu().getNavTarget();
+ if (target instanceof InstalledLevelsMenuScreen) {
+ InstalledLevelsMenuScreen installedScreen = (InstalledLevelsMenuScreen) target;
+ LevelMenuElement el = installedScreen.getElementByLevelId(id, 0);
+ if (el != null)
+ installedScreen.deleteElement(el);
+ level.setId(0);
+ menu.back();
+ } else if (target instanceof DownloadLevelsMenuScreen) {
+ DownloadLevelsMenuScreen downloadScreen = (DownloadLevelsMenuScreen) target;
+ LevelMenuElement el = downloadScreen.getElementByLevelId(id, 0);
+ if (el != null)
+ el.setInstalled(false);
+
+ level.setId(0);
+ buildScreen();
+ }
+ }
+ });
+ }
+ },
+ null
+ );
+ break;
+
+ case ActionMenuElement.INSTALL:
+ gd.levelsManager.downloadLevel(level, new Callback() {
+ @Override
+ public void onDone(Object... objects) {
+ long id = (long) objects[0];
+ level.setId(id);
+
+ MenuScreen target = menu.getCurrentMenu().getNavTarget();
+ if (target instanceof DownloadLevelsMenuScreen) {
+ DownloadLevelsMenuScreen downloadScreen = (DownloadLevelsMenuScreen) target;
+ LevelMenuElement el = downloadScreen.getElementByLevelId(id, 0);
+ if (el != null)
+ el.setInstalled(true);
+ }
+
+ buildScreen();
+ }
+ });
+ break;
+
+ case ActionMenuElement.LOAD:
+ gd.levelsManager.load(level);
+ // buildScreen();
+ break;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return level.toString();
+ }
+
+} \ No newline at end of file
diff --git a/src/org/happysanta/gd/Menu/LevelsAdapter.java b/src/org/happysanta/gd/Menu/LevelsAdapter.java
new file mode 100644
index 0000000..9f7ddc9
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/LevelsAdapter.java
@@ -0,0 +1,53 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.text.Html;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.R;
+import org.happysanta.gd.Storage.Level;
+
+import java.util.ArrayList;
+
+import static org.happysanta.gd.Helpers.getString;
+
+public class LevelsAdapter extends ArrayAdapter<Level> {
+
+ private ArrayList<Level> levels;
+
+ public LevelsAdapter(Context context, ArrayList<Level> levels) {
+ super(context, R.layout.levels_list_item, levels);
+ this.levels = levels;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View v = convertView;
+ if (v == null) {
+ LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ v = inflater.inflate(R.layout.levels_list_item, null);
+ }
+
+ Level level = levels.get(position);
+ if (level != null) {
+ TextView name = (TextView) v.findViewById(R.id.level_name);
+ TextView count = (TextView) v.findViewById(R.id.level_count);
+
+ name.setTypeface(Global.robotoCondensedTypeface);
+ count.setTypeface(Global.robotoCondensedTypeface);
+
+ name.setText(level.getName());
+ count.setText(Html.fromHtml(String.format(getString(R.string.levels_count_tpl),
+ level.getCountEasy() + " - " + level.getCountMedium() + " - " + level.getCountHard(), level.getShortAddedDate())));
+ }
+
+ return v;
+ }
+
+}
+
+
diff --git a/src/org/happysanta/gd/Menu/LevelsCountTextMenuElement.java b/src/org/happysanta/gd/Menu/LevelsCountTextMenuElement.java
new file mode 100644
index 0000000..7ead337
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/LevelsCountTextMenuElement.java
@@ -0,0 +1,86 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+import org.happysanta.gd.R;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class LevelsCountTextMenuElement
+ extends BigTextMenuElement {
+
+ protected static final int PADDING_LEFT = 4;
+ protected static final int PADDING_RIGHT = 8;
+ protected static final int MARGIN_RIGHT = 3;
+
+ protected int tracks[];
+
+ protected MenuLinearLayout layout;
+ protected MenuImageView tracksImages[];
+ protected MenuTextView tracksTexts[];
+
+ public LevelsCountTextMenuElement(String s, int easy, int medium, int hard) {
+ super(s);
+
+ tracks = new int[3];
+ tracks[0] = easy;
+ tracks[1] = medium;
+ tracks[2] = hard;
+
+ createViews();
+ }
+
+ protected void createViews() {
+ Context context = getGDActivity();
+
+ layout = new MenuLinearLayout(context);
+ layout.setOrientation(LinearLayout.HORIZONTAL);
+ layout.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ ));
+
+ tracksImages = new MenuImageView[3];
+ for (int i = 0; i < 3; i++) {
+ tracksImages[i] = new MenuImageView(context);
+ tracksImages[i].setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
+ }
+
+ tracksImages[0].setImageResource(R.drawable.levels_wheel0);
+ tracksImages[1].setImageResource(R.drawable.levels_wheel1);
+ tracksImages[2].setImageResource(R.drawable.levels_wheel2);
+
+ // Tracks texts
+ tracksTexts = new MenuTextView[3];
+ for (int i = 0; i < 3; i++) {
+ tracksTexts[i] = new MenuTextView(context);
+ setTextParams(tracksTexts[i]);
+
+ tracksTexts[i].setText(String.valueOf(tracks[i]));
+ tracksTexts[i].setPadding(getDp(PADDING_LEFT), 0, getDp(PADDING_RIGHT), 0);
+ }
+
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ params.setMargins(0, 0, getDp(MARGIN_RIGHT), 0);
+
+ textView.setLayoutParams(params);
+
+ layout.addView(textView);
+
+ // Add tracks to layout
+ for (int i = 0; i < 3; i++) {
+ layout.addView(tracksImages[i]);
+ layout.addView(tracksTexts[i]);
+ }
+ }
+
+ @Override
+ public View getView() {
+ return layout;
+ }
+}
diff --git a/src/org/happysanta/gd/Menu/LevelsMenuScreen.java b/src/org/happysanta/gd/Menu/LevelsMenuScreen.java
new file mode 100644
index 0000000..22b7539
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/LevelsMenuScreen.java
@@ -0,0 +1,429 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+import org.happysanta.gd.R;
+import org.happysanta.gd.Storage.Level;
+import org.happysanta.gd.Storage.LevelsManager;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Vector;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getGDView;
+import static org.happysanta.gd.Helpers.getGameMenu;
+import static org.happysanta.gd.Helpers.getLevelsManager;
+import static org.happysanta.gd.Helpers.getString;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class LevelsMenuScreen extends MenuScreen {
+
+ enum Statuses {NORMAL, DOWNLOADING, ERROR}
+
+ protected final static int ERROR_COLOR = 0xff777777;
+
+ protected Statuses status = Statuses.NORMAL;
+ protected int savedScrollY = 0;
+
+ protected Vector elements;
+ protected ArrayList<Level> levels;
+
+ protected FrameLayout progressWrap;
+ protected ProgressBar progressBar;
+
+ protected MenuLinearLayout listLayout;
+ protected TextMenuElement errorText;
+ protected AsyncAddElements addElements = null;
+ protected boolean leftFromScreen = false;
+
+ public LevelsMenuScreen(String title, MenuScreen navTarget) {
+ super(title, navTarget);
+
+ elements = new Vector();
+ levels = new ArrayList<>();
+
+ Context context = getGDActivity();
+
+ // Create progress
+ progressWrap = new FrameLayout(context);
+ progressWrap.setLayoutParams(new LinearLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.MATCH_PARENT
+ ));
+
+ progressBar = new ProgressBar(context);
+ progressBar.setIndeterminate(true);
+
+ // Create error
+ errorText = new TextMenuElement(getString(R.string.download_error));
+ TextView errorTextView = (TextView) errorText.getView();
+
+ errorTextView.setTextColor(ERROR_COLOR);
+ errorTextView.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT
+ ));
+ errorTextView.setGravity(Gravity.CENTER);
+
+ listLayout = new MenuLinearLayout(context);
+ listLayout.setOrientation(LinearLayout.VERTICAL);
+ listLayout.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT
+ ));
+
+ layout.addView(listLayout);
+
+ // List view
+ // listView = new ListView(context);
+ /*listView.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ ));*/
+
+ // adapter = new LevelsAdapter(context, levels);
+ // listView.setAdapter(adapter);
+
+ // layout.addView(listView);
+ }
+
+ public int addListItem(MenuElement item) {
+ elements.addElement(item);
+ listLayout.addView(item.getView());
+
+ if (item instanceof ClickableMenuElement)
+ ((ClickableMenuElement) item).setOnHighlightListener(this);
+
+ return elements.size() - 1;
+ }
+
+ public void setStatus(Statuses status) {
+ this.status = status;
+
+ getGDView().invalidate();
+ }
+
+ protected void clearList() {
+ elements.removeAllElements();
+ levels.clear();
+ listLayout.removeAllViews();
+ lastHighlighted = null;
+ // System.gc();
+ }
+
+ protected void showError(String error) {
+ clearList();
+ errorText.setText(error);
+ addListItem(errorText);
+
+ setStatus(Statuses.ERROR);
+ }
+
+ protected void showLoading() {
+ // clearList();
+
+ if (elements.isEmpty()) {
+ if (progressBar.getParent() == listLayout) {
+ listLayout.removeView(progressBar);
+ } else if (progressBar.getParent() != progressWrap) {
+ progressWrap.addView(progressBar, new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL
+ ));
+ }
+
+ listLayout.addView(progressWrap);
+ } else {
+ if (progressBar.getParent() == progressWrap) {
+ progressWrap.removeView(progressBar);
+ } else if (progressBar.getParent() != listLayout) {
+ listLayout.addView(progressBar, new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER_HORIZONTAL
+ ));
+ }
+ }
+
+ // setStatus(Statuses.DOWNLOADING);
+ }
+
+ protected void hideLoading() {
+ if (progressBar.getParent() == listLayout) {
+ listLayout.removeView(progressBar);
+ } else if (progressBar.getParent() == progressWrap) {
+ // progressWrap.setVisibility(GameView.GONE);
+ listLayout.removeView(progressWrap);
+ }
+ }
+
+ public void highlightFirstElement() {
+ for (int i = 0; i < elements.size(); i++) {
+ if (elements.elementAt(i) instanceof LevelMenuElement) {
+ highlightElementAt(i);
+ break;
+ }
+ }
+ }
+
+ public void highlightElementAt(int index) {
+ LevelMenuElement item = null;
+ try {
+ item = (LevelMenuElement) elements.elementAt(index);
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ item.showHelmet();
+ lastHighlighted = item;
+ selectedIndex = index;
+ }
+
+ protected void load() {
+ clearList();
+ loadLevels();
+ }
+
+ protected void loadLevels() {
+
+ }
+
+ @Override
+ public void onShow() {
+ super.onShow();
+ GDActivity activity = getGDActivity();
+
+ if (leftFromScreen) {
+ clearList();
+ leftFromScreen = false;
+ }
+
+ switch (status) {
+ case DOWNLOADING:
+ break;
+
+ case NORMAL:
+ if (elements.isEmpty()) {
+ load();
+ }
+ break;
+ }
+
+ if (lastHighlighted != null) {
+ lastHighlighted.showHelmet();
+ }
+
+ if (savedScrollY != 0) {
+ activity.scrollView.scrollTo(0, savedScrollY);
+ }
+ }
+
+ @Override
+ public void onHide(MenuScreen newMenu) {
+ GDActivity activity = getGDActivity();
+
+ if (newMenu != getGameMenu().levelScreen) {
+ if (addElements != null) {
+ addElements.cancel(true);
+ addElements = null;
+ }
+
+ savedScrollY = 0;
+ status = Statuses.NORMAL;
+
+ hideLoading();
+ clearList();
+
+ leftFromScreen = true;
+ } else {
+ savedScrollY = activity.scrollView.getScrollY();
+ }
+ }
+
+ protected boolean hideDate() {
+ return false;
+ }
+
+ protected LevelsMenuScreen getThis() {
+ return this;
+ }
+
+ public void reloadLevels() {
+ if (addElements != null) {
+ addElements.cancel(true);
+ addElements = null;
+ }
+
+ clearList();
+ loadLevels();
+ }
+
+ public LevelMenuElement getElementByLevelId(long id, long apiId) {
+ for (Object _el : elements) {
+ LevelMenuElement el = (LevelMenuElement) _el;
+
+ if ((id > 0 && el.level.getId() == id) || apiId > 0 && el.level.getApiId() == apiId)
+ return el;
+ }
+
+ return null;
+ }
+
+ public void deleteElement(LevelMenuElement el) {
+ View view = el.getView();
+ listLayout.removeView(view);
+
+ int index = elements.indexOf(el);
+
+ elements.remove(el);
+ levels.remove(el.level);
+
+ if (el == lastHighlighted) {
+ index--;
+ if (index < 0)
+ index = 0;
+
+ highlightElementAt(index);
+ }
+ }
+
+ @Override
+ public void performAction(int k) {
+ logDebug("LevelsMenuScreen.performAction: k = " + k);
+ int from = 0;
+ switch (k) {
+ default:
+ if (selectedIndex != -1) {
+ for (int i = selectedIndex; i < elements.size(); i++) {
+ MenuElement item;
+ if ((item = (MenuElement) elements.elementAt(i)) != null && item.isSelectable()) {
+ item.performAction(k);
+ return;
+ }
+ }
+ }
+ break;
+
+ case KEY_UP:
+ if (selectedIndex > 0) {
+ from = selectedIndex - 1;
+ } else {
+ from = elements.size() - 1;
+ }
+
+ for (int i = from; i >= 0; i--) {
+ MenuElement el = (MenuElement) elements.elementAt(i);
+ if (!(el instanceof LevelMenuElement)) {
+ continue;
+ }
+
+ highlightElementAt(i);
+ scrollToItem(el);
+ break;
+ }
+ break;
+
+ case KEY_DOWN:
+ if (selectedIndex < elements.size() - 1) {
+ from = selectedIndex + 1;
+ } else {
+ from = 0;
+ }
+
+ for (int i = from; i < elements.size(); i++) {
+ MenuElement el = (MenuElement) elements.elementAt(i);
+ if (!(el instanceof LevelMenuElement)) {
+ continue;
+ }
+
+ highlightElementAt(i);
+ scrollToItem(el);
+ break;
+ }
+ break;
+ }
+ }
+
+ protected void scrollToItem(int index) {
+ LevelMenuElement el = (LevelMenuElement) elements.elementAt(index);
+ // logDebug(el);
+ scrollToItem(el);
+ }
+
+ protected class AsyncAddElements extends AsyncTask<Level[], Void, Void> {
+
+ @Override
+ protected Void doInBackground(Level[]... params) {
+ Level[] _levels = params[0];
+ boolean checkInstalled = getThis() instanceof DownloadLevelsMenuScreen;
+ boolean checkActive = getThis() instanceof InstalledLevelsMenuScreen;
+
+ ArrayList<Long> ids;
+ HashMap<Long, Long> installed = null;
+ LevelsManager levelsManager = getLevelsManager();
+
+ if (checkInstalled) {
+ ids = new ArrayList<>();
+
+ for (Level level : _levels) {
+ ids.add(level.getApiId());
+ }
+
+ installed = getGDActivity().levelsManager.findInstalledLevels(ids);
+ }
+
+ boolean alreadyHl = false;
+
+ for (Level level : _levels) {
+ if (isCancelled()) {
+ clearList();
+ return null;
+ }
+
+ LevelMenuElement el = new LevelMenuElement(level, getThis());
+ boolean toHl = false;
+
+ if (hideDate())
+ el.setShowDate(false);
+
+ if (checkInstalled && installed.containsKey(level.getApiId())) {
+ level.setId(installed.get(level.getApiId()));
+ el.setInstalled(true);
+ }
+ if (checkActive && level.getId() == levelsManager.getCurrentId()) {
+ el.setActive(true);
+ toHl = true;
+ }
+
+ if (!isCancelled()) {
+ int index = addListItem(el);
+ if (toHl && !alreadyHl) {
+ highlightElementAt(index);
+ // scrollToItem(index);
+ alreadyHl = true;
+ }
+
+ if (lastHighlighted == null)
+ highlightFirstElement();
+ }
+ }
+
+ levels.addAll(Arrays.asList(_levels));
+ return null;
+ }
+
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Menu.java b/src/org/happysanta/gd/Menu/Menu.java
new file mode 100755
index 0000000..7485176
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Menu.java
@@ -0,0 +1,1554 @@
+package org.happysanta.gd.Menu;
+
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Environment;
+import android.text.Html;
+import android.text.InputType;
+import android.widget.EditText;
+import org.happysanta.gd.Command;
+import org.happysanta.gd.FileDialog;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Game.GameView;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Levels.InvalidTrackException;
+import org.happysanta.gd.Levels.Loader;
+import org.happysanta.gd.R;
+import org.happysanta.gd.Settings;
+import org.happysanta.gd.Storage.HighScores;
+import org.happysanta.gd.Storage.Level;
+import org.happysanta.gd.Storage.LevelsManager;
+import org.acra.ACRA;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+
+import static org.happysanta.gd.Helpers.*;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class Menu
+ implements MenuHandler {
+
+ // private final static int SETTINGS_LENGTH = 21;
+ // private final static boolean ENABLE_MANAGER = true;
+
+ public MenuScreen currentMenu;
+ public Level level;
+ private HighScores currentScores;
+ public int selectedLeague = 0;
+ public boolean m_blZ = false;
+ public boolean menuDisabled = false;
+ // byte[] unlockedTracks = new byte[3];
+ // byte leaguesUnlockedCount = 0;
+ // byte levelsUnlockedCount = 0;
+ int[] selectedTrack = {
+ 0, 0, 0
+ };
+ String[][] trackNames;
+ String[] leagues = new String[3];
+ String[] fullLeaguesList = new String[4];
+ // private byte[] settings;
+ // private SaveManager saveManager;
+ private Command okCommand;
+ private Command backCommand;
+ private MenuScreen mainMenu;
+ private MenuScreen playMenu;
+ private MenuScreen optionsMenu;
+ private MenuScreen aboutScreen;
+ private MenuScreen helpMenu;
+ private MenuScreen eraseScreen;
+ private MenuScreen resetScreen;
+ private MenuScreen finishedMenu;
+ private MenuScreen ingameScreen;
+ private SimpleMenuElementNew gameMenuItem;
+ // private SimpleMenuElementNew optionsMenuItem;
+ // private SimpleMenuElementNew helpMenuItem;
+ private OptionsMenuElement levelSelector;
+ private MenuScreen levelSelectorCurrentMenu;
+ private OptionsMenuElement trackSelector;
+ private MenuScreen trackSelectorCurrentMenu;
+ private OptionsMenuElement leagueSelector;
+ private MenuScreen leagueSelectorCurrentMenu;
+ private MenuScreen highScoreMenu;
+ private SimpleMenuElementNew highscoreItem;
+ private ActionMenuElement startItem;
+ private OptionsMenuElement perspectiveOptionItem;
+ private OptionsMenuElement shadowsOptionItem;
+ private OptionsMenuElement driverSpriteOptionItem;
+ private OptionsMenuElement bikeSpriteOptionItem;
+ private OptionsMenuElement inputOptionItem;
+ private OptionsMenuElement lookAheadOptionItem;
+ private OptionsMenuElement keyboardInMenuOptionItem;
+ private OptionsMenuElement vibrateOnTouchOptionItem;
+ private SimpleMenuElementNew clearHighscoreOptionItem;
+ private SimpleMenuElementNew fullResetItem;
+ // private ActionMenuElement yesAction;
+ // private ActionMenuElement noAction;
+ private SimpleMenuElementNew aboutMenuItem;
+ private MenuScreen objectiveHelpScreen;
+ private SimpleMenuElementNew objectiveHelpItem;
+ private MenuScreen keysHelpScreen;
+ private SimpleMenuElementNew keysHelpItem;
+ private MenuScreen unlockingHelpScreen;
+ private SimpleMenuElementNew unlockingHelpItem;
+ private MenuScreen highscoreHelpScreen;
+ private SimpleMenuElementNew highscoreHelpItem;
+ private MenuScreen optionsHelpScreen;
+ private SimpleMenuElementNew optionsHelpItem;
+ private NameInputMenuScreen nameScreen;
+ private ActionMenuElement continueAction;
+ // private ActionMenuElement goToMainAction;
+ // private ActionMenuElement exitMenuItem;
+ private ActionMenuElement ingameRestartAction;
+ private ActionMenuElement finishedRestartAction;
+ private ActionMenuElement nextAction;
+ // private ActionMenuElement okAction;
+ private ActionMenuElement nameAction;
+ private long lastTrackTime;
+ private int m_ajI;
+ private int m_atI;
+ private String finishedTime;
+ private byte[] nameChars;
+ // private RecordStore recordStore;
+ // private int m_afI = -1;
+ private boolean settingsLoadedOK;
+ private int levelIndex = 0;
+ private int track = 0;
+ private boolean leagueCompleted = false;
+ private boolean m_SZ = false;
+ private Object m_BObject;
+ private String[] difficultyLevels = null; /* {
+ "Easy", "Medium", "Hard"
+ }; */
+ // private long finishTime = 0L;
+ /*private byte perspectiveOptionEnabled = 0;
+ private byte shadowsOptionEnabled = 0;
+ private byte driverSpriteOptionEnabled = 0;
+ private byte bikerSpriteOptionEnabled = 0;
+ private byte inputOptionValue = 0;
+ private byte lookAheadOptionEnabled = 0;
+ private byte keyboardInMenuEnabled = 1;
+ private byte vibrateOnTouchEnabled = 1;*/
+ // private byte selectedTrackIndex = 0;
+ // private byte selectedLevel = 0;
+ // private byte selectedLeague = 0;
+ // private byte m_aTB = 0;
+ // private byte m_arB = 0;
+ private String[] onOffStrings = null;
+ private String[] keysetStrings = null;
+ // private EmptyLineMenuElement emptyLine;
+ // private EmptyLineMenuElement emptyLineBeforeAction;
+ // private AlertDialog alertDialog = null;
+ private Paint bgPaint;
+ public MenuScreen managerScreen;
+ public InstalledLevelsMenuScreen managerInstalledScreen;
+ public DownloadLevelsMenuScreen managerDownloadScreen;
+ // private MenuScreen managerDownloadOptionsScreen;
+ private SimpleMenuElementNew managerMenuItem;
+ public MenuScreen levelScreen;
+ // private SimpleMenuElement managerInstalledItem;
+ // private SimpleMenuElement managerDownloadItem;
+ // private HelmetRotationTask helmetRotationTask;
+ // private Timer helmetRotationTimer;
+ // public int helmetAngle;
+
+ public Menu() {
+ // Background color (instead of raster.png)
+ bgPaint = new Paint();
+ bgPaint.setColor(0x80FFFFFF);
+ }
+
+ public void load(int step) {
+ GDActivity activity = getGDActivity();
+ Loader loader = getLevelLoader();
+ LevelsManager levelsManager = getLevelsManager();
+
+ level = levelsManager.getCurrentLevel();
+
+ switch (step) {
+ case 1:
+ m_BObject = new Object();
+ nameChars = new byte[]{
+ 65, 65, 65 // A A A
+ };
+ onOffStrings = getStringArray(R.array.on_off);
+ keysetStrings = getStringArray(R.array.keyset);
+ difficultyLevels = getStringArray(R.array.difficulty);
+
+ // saveManager = new SaveManager();
+ lastTrackTime = -1L;
+ m_ajI = -1;
+ m_atI = -1;
+ finishedTime = null;
+ // settingsLoadedOK = false;
+ /*settings = new byte[SETTINGS_LENGTH];
+ for (int l = 0; l < SETTINGS_LENGTH; l++)
+ settings[l] = -127;*/
+
+ settingsLoadedOK = true;
+ /*try {
+ recordStore = RecordStore.openRecordStore(*//*(Loader.levelsFile != null ? Loader.levelsFile.getName().hashCode() : "") + *//*
+ getLevelsManager().getCurrentId() + "_" + "GDTRStates", true);
+ settingsLoadedOK = true;
+ return;
+ } catch (Exception _ex) {
+ settingsLoadedOK = false;
+ }*/
+
+ break;
+
+ case 2:
+ // m_afI = -1;
+ /*RecordEnumeration enumeration;
+ try {
+ enumeration = recordStore.enumerateRecords(null, null, false);
+ } catch (*//*RecordStoreNotOpen*//*Exception _ex) {
+ return;
+ }
+ if (enumeration.numRecords() > 0) {
+ byte[] abyte0;
+ try {
+ abyte0 = enumeration.nextRecord();
+ enumeration.reset();
+ m_afI = enumeration.nextRecordId();
+ } catch (Exception _ex) {
+ return;
+ }
+ if (abyte0.length <= SETTINGS_LENGTH)
+ System.arraycopy(abyte0, 0, settings, 0, abyte0.length);
+ enumeration.destroy();
+ }*/
+
+ /*byte[] chars;
+ if ((chars = readNameChars(16, (byte) -1)) != null && chars[0] != -1) {
+ for (int i = 0; i < 3; i++)
+ nameChars[i] = chars[i];
+
+ }*/
+
+ nameChars = Settings.getName();
+ // if (nameChars[0] == 82 && nameChars[1] == 75 && nameChars[2] == 69) {
+ if (isNameCheat(nameChars)) {
+ // Unlock everything for cheat
+ level.setUnlockedLeagues(3);
+ level.setUnlockedLevels(2);
+ level.setUnlocked(
+ loader.names[0].length - 1,
+ loader.names[1].length - 1,
+ loader.names[2].length - 1
+ );
+ // logDebug(level);
+ // leaguesUnlockedCount = 3;
+ // levelsUnlockedCount = 2;
+ /*unlockedTracks[0] = (byte) (loader.names[0].length - 1);
+ unlockedTracks[1] = (byte) (loader.names[1].length - 1);
+ unlockedTracks[2] = (byte) (loader.names[2].length - 1);*/
+ } else if (level.isSettingsClear()) {
+ level.setUnlockedLeagues(0);
+ level.setUnlockedLevels(1);
+ level.setUnlocked(0, 0, -1);
+ // leaguesUnlockedCount = 0;
+ // levelsUnlockedCount = 1;
+ /*unlockedTracks[0] = 0;
+ unlockedTracks[1] = 0;
+ unlockedTracks[2] = -1;*/
+ }
+ break;
+
+ case 3:
+ // Load settings
+ /*perspectiveOptionEnabled = readSetting(0, perspectiveOptionEnabled);
+ shadowsOptionEnabled = readSetting(1, shadowsOptionEnabled);
+ driverSpriteOptionEnabled = readSetting(2, driverSpriteOptionEnabled);
+ bikerSpriteOptionEnabled = readSetting(3, bikerSpriteOptionEnabled);
+ lookAheadOptionEnabled = readSetting(4, lookAheadOptionEnabled);
+
+ keyboardInMenuEnabled = readSetting(13, keyboardInMenuEnabled);
+ inputOptionValue = readSetting(14, inputOptionValue);*/
+ // m_arB = readSetting(15, m_arB); // nonsense
+
+ /*vibrateOnTouchEnabled = readSetting(19, keyboardInMenuEnabled);
+
+ selectedLevel = readSetting(10, selectedLevel);
+ selectedTrackIndex = readSetting(11, selectedTrackIndex);
+ selectedLeague = readSetting(12, selectedLeague);*/
+
+ // byte levelsSort = readSetting(20, (byte)0);
+
+ DownloadLevelsMenuScreen.sort = Settings.getLevelsSort();
+
+
+ levelIndex = level.getSelectedLevel();
+ track = level.getSelectedTrack();
+
+ if (nameChars[0] != 82 || nameChars[1] != 75 || nameChars[2] != 69) {
+ //level.setUnlockedLeagues();
+ /*leaguesUnlockedCount = readSetting(5, leaguesUnlockedCount);
+ levelsUnlockedCount = readSetting(6, levelsUnlockedCount);
+ for (int i = 0; i < 3; i++)
+ unlockedTracks[i] = readSetting(7 + i, unlockedTracks[i]);*/
+ }
+
+ try {
+ selectedTrack[level.getSelectedLevel()] = level.getSelectedTrack();
+ } catch (ArrayIndexOutOfBoundsException _ex) {
+ level.setSelectedLevel(0);
+ level.setSelectedTrack(0);
+ selectedTrack[level.getSelectedLevel()] = level.getSelectedTrack();
+ }
+ getLevelLoader().setPerspectiveEnabled(Settings.isPerspectiveEnabled());
+ getLevelLoader().setShadowsEnabled(Settings.isShadowsEnabled());
+ activity.physEngine._ifZV(Settings.isLookAheadEnabled());
+ getGDView().setInputOption(Settings.getInputOption());
+ // getGDView()._aZV(m_aTB == 0);
+ getGDView()._aZV(true);
+ String[] leaguesList = getStringArray(R.array.leagues);
+ fullLeaguesList = getStringArray(R.array.leagues_full);
+ trackNames = getLevelLoader().names;
+
+ if (level.getUnlockedLeagues() < 3) {
+ leagues = leaguesList;
+ } else {
+ leagues = fullLeaguesList;
+ }
+
+ selectedLeague = level.getSelectedLeague();
+
+ break;
+
+ case 4:
+ mainMenu = new MenuScreen(getString(R.string.main), null);
+ playMenu = new MenuScreen(getString(R.string.play), mainMenu);
+ managerScreen = new MenuScreen(getString(R.string.mods), mainMenu);
+ optionsMenu = new MenuScreen(getString(R.string.options), mainMenu);
+ aboutScreen = new MenuScreen(getString(R.string.about) + " v" + getAppVersion(), mainMenu);
+ helpMenu = new MenuScreen(getString(R.string.help), mainMenu);
+
+ continueAction = new ActionMenuElement(getString(R.string._continue), ActionMenuElement.CONTINUE, this);
+ nextAction = new ActionMenuElement(getString(R.string.track) + ": " + getLevelLoader().getLevelName(0, 1), ActionMenuElement.NEXT, this);
+ ingameRestartAction = new ActionMenuElement(getString(R.string.restart) + ": " + getLevelLoader().getLevelName(0, 0), ActionMenuElement.RESTART, this);
+ finishedRestartAction = new ActionMenuElement(getString(R.string.restart) + ": " + getLevelLoader().getLevelName(0, 0), ActionMenuElement.RESTART, this);
+
+ /*nextAction = new ActionMenuElement(getString(R.string.track) + ": DEFAULT", ActionMenuElement.NEXT, this);
+ ingameRestartAction = new ActionMenuElement(getString(R.string.restart) + ": DEFAULT", ActionMenuElement.RESTART, this);
+ finishedRestartAction = new ActionMenuElement(getString(R.string.restart) + ": DEFAULT", ActionMenuElement.RESTART, this);*/
+
+ highScoreMenu = new MenuScreen(getString(R.string.highscores), playMenu);
+ finishedMenu = new MenuScreen(getString(R.string.finished), playMenu);
+ ingameScreen = new MenuScreen(getString(R.string.ingame), playMenu);
+ nameScreen = new NameInputMenuScreen(getString(R.string.enter_name), finishedMenu, nameChars);
+ eraseScreen = new MenuScreen(getString(R.string.confirm_clear), optionsMenu);
+ resetScreen = new MenuScreen(getString(R.string.confirm_reset), eraseScreen);
+
+ gameMenuItem = new SimpleMenuElementNew(getString(R.string.play_menu), playMenu, this);
+ managerMenuItem = new SimpleMenuElementNew(getString(R.string.mods), managerScreen, this);
+ aboutMenuItem = new SimpleMenuElementNew(getString(R.string.about), aboutScreen, this);
+
+ mainMenu.addItem(gameMenuItem);
+ //if (ENABLE_MANAGER)
+ mainMenu.addItem(new SimpleMenuElementNew(getString(R.string.mods), managerScreen, this));
+ mainMenu.addItem(new SimpleMenuElementNew(getString(R.string.options), optionsMenu, this));
+ mainMenu.addItem(new SimpleMenuElementNew(getString(R.string.help), helpMenu, this));
+ mainMenu.addItem(aboutMenuItem);
+ if (Global.DEBUG) {
+ // mainMenu.addItem(createAction(ActionMenuElement.RESTART_WITH_NEW_LEVEL));
+ mainMenu.addItem(createAction(ActionMenuElement.SEND_LOGS));
+ }
+ mainMenu.addItem(createAction(ActionMenuElement.EXIT));
+
+ levelSelector = new OptionsMenuElement(getString(R.string.level), level.getSelectedLevel(), this, difficultyLevels, false, playMenu);
+ trackSelector = new OptionsMenuElement(getString(R.string.track), selectedTrack[level.getSelectedLevel()], this, trackNames[level.getSelectedLevel()], false, playMenu);
+ leagueSelector = new OptionsMenuElement(getString(R.string.league), selectedLeague, this, leagues, false, playMenu);
+ try {
+ trackSelector.setUnlockedCount(level.getUnlocked(level.getSelectedLevel()));
+ } catch (ArrayIndexOutOfBoundsException _ex) {
+ trackSelector.setUnlockedCount(0);
+ }
+ levelSelector.setUnlockedCount(level.getUnlockedLevels());
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ highscoreItem = new SimpleMenuElementNew(getString(R.string.highscores), highScoreMenu, this);
+ highScoreMenu.addItem(createAction(ActionMenuElement.BACK));
+ startItem = new ActionMenuElement(getString(R.string.start) + ">", this);
+ playMenu.addItem(startItem);
+ playMenu.addItem(levelSelector);
+ playMenu.addItem(trackSelector);
+ playMenu.addItem(leagueSelector);
+ playMenu.addItem(highscoreItem);
+ playMenu.addItem(createAction(ActionMenuElement.GO_TO_MAIN));
+ // if (hasPointer)
+ // softwareJoystickOptionItem = new ActionMenuElement("Software Joystick", m_aTB, this, onOffStrings, true, activity, optionsMenu, false);
+ perspectiveOptionItem = new OptionsMenuElement(getString(R.string.perspective), Settings.isPerspectiveEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ shadowsOptionItem = new OptionsMenuElement(getString(R.string.shadows), Settings.isShadowsEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ driverSpriteOptionItem = new OptionsMenuElement(getString(R.string.driver_sprite), Settings.isDriverSpriteEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ bikeSpriteOptionItem = new OptionsMenuElement(getString(R.string.bike_sprite), Settings.isBikeSpriteEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ inputOptionItem = new OptionsMenuElement(getString(R.string.input), Settings.getInputOption(), this, keysetStrings, false, optionsMenu);
+ lookAheadOptionItem = new OptionsMenuElement(getString(R.string.look_ahead), Settings.isLookAheadEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ vibrateOnTouchOptionItem = new OptionsMenuElement(getString(R.string.vibrate_on_touch), Settings.isVibrateOnTouchEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ keyboardInMenuOptionItem = new OptionsMenuElement(getString(R.string.keyboard_in_menu), Settings.isKeyboardInMenuEnabled() ? 0 : 1, this, onOffStrings, true, optionsMenu);
+ clearHighscoreOptionItem = new SimpleMenuElementNew(getString(R.string.clear_highscore), eraseScreen, this);
+
+ // if (hasPointer)
+ // optionsMenu.addItem(softwareJoystickOptionItem);
+ optionsMenu.addItem(perspectiveOptionItem);
+ optionsMenu.addItem(shadowsOptionItem);
+ optionsMenu.addItem(driverSpriteOptionItem);
+ optionsMenu.addItem(bikeSpriteOptionItem);
+ optionsMenu.addItem(inputOptionItem);
+ optionsMenu.addItem(lookAheadOptionItem);
+ optionsMenu.addItem(vibrateOnTouchOptionItem);
+ optionsMenu.addItem(keyboardInMenuOptionItem);
+ optionsMenu.addItem(clearHighscoreOptionItem);
+ optionsMenu.addItem(createAction(ActionMenuElement.BACK));
+
+ // noAction = new ActionMenuElement(getString(R.string.no), 0, this, null, false, mainMenu, true);
+ // yesAction = new ActionMenuElement(getString(R.string.yes), 0, this, null, false, mainMenu, true);
+ fullResetItem = new SimpleMenuElementNew(getString(R.string.full_reset), resetScreen, this);
+ eraseScreen.addItem(new TextMenuElement(getString(R.string.erase_text1)));
+ eraseScreen.addItem(new TextMenuElement(getString(R.string.erase_text2)));
+ eraseScreen.addItem(createEmptyLine(true));
+ eraseScreen.addItem(createAction(ActionMenuElement.NO));
+ eraseScreen.addItem(createAction(ActionMenuElement.YES));
+ eraseScreen.addItem(fullResetItem);
+ resetScreen.addItem(new TextMenuElement(getString(R.string.reset_text1)));
+ resetScreen.addItem(new TextMenuElement(getString(R.string.reset_text2)));
+ resetScreen.addItem(createEmptyLine(true));
+ resetScreen.addItem(createAction(ActionMenuElement.NO));
+ resetScreen.addItem(createAction(ActionMenuElement.YES));
+
+ objectiveHelpScreen = new MenuScreen(getString(R.string.objective), helpMenu);
+ objectiveHelpScreen.setIsTextScreen(true);
+ objectiveHelpItem = new SimpleMenuElementNew(getString(R.string.objective), objectiveHelpScreen, this);
+ objectiveHelpScreen.addItem(new TextMenuElement(Html.fromHtml(getString(R.string.objective_text))));
+ objectiveHelpScreen.addItem(createAction(ActionMenuElement.BACK));
+
+ keysHelpScreen = new MenuScreen(getString(R.string.keys), helpMenu);
+ keysHelpScreen.setIsTextScreen(true);
+ keysHelpItem = new SimpleMenuElementNew(getString(R.string.keys), keysHelpScreen, this);
+ keysHelpScreen.addItem(new TextMenuElement(Html.fromHtml(getString(R.string.keyset_text))));
+ keysHelpScreen.addItem(new ActionMenuElement(getString(R.string.back), ActionMenuElement.BACK, this));
+
+ unlockingHelpScreen = new MenuScreen(getString(R.string.unlocking), helpMenu);
+ unlockingHelpScreen.setIsTextScreen(true);
+ unlockingHelpItem = new SimpleMenuElementNew(getString(R.string.unlocking), unlockingHelpScreen, this);
+ unlockingHelpScreen.addItem(new TextMenuElement(Html.fromHtml(getString(R.string.unlocking_text))));
+ unlockingHelpScreen.addItem(createAction(ActionMenuElement.BACK));
+
+ highscoreHelpScreen = new MenuScreen(getString(R.string.highscores), helpMenu);
+ highscoreHelpScreen.setIsTextScreen(true);
+ highscoreHelpItem = new SimpleMenuElementNew(getString(R.string.highscores), highscoreHelpScreen, this);
+ highscoreHelpScreen.addItem(new TextMenuElement(Html.fromHtml(getString(R.string.highscore_text))));
+ highscoreHelpScreen.addItem(createAction(ActionMenuElement.BACK));
+
+ optionsHelpScreen = new MenuScreen(getString(R.string.options), helpMenu);
+ optionsHelpScreen.setIsTextScreen(true);
+ optionsHelpItem = new SimpleMenuElementNew(getString(R.string.options), optionsHelpScreen, this);
+ optionsHelpScreen.addItem(new TextMenuElement(Html.fromHtml(getString(R.string.options_text))));
+ optionsHelpScreen.addItem(createAction(ActionMenuElement.BACK));
+
+ helpMenu.addItem(objectiveHelpItem);
+ helpMenu.addItem(keysHelpItem);
+ helpMenu.addItem(unlockingHelpItem);
+ helpMenu.addItem(highscoreHelpItem);
+ helpMenu.addItem(optionsHelpItem);
+ helpMenu.addItem(createAction(ActionMenuElement.BACK));
+
+ aboutScreen.setIsTextScreen(true);
+ aboutScreen.addItem(new TextMenuElement(Html.fromHtml(getString(R.string.about_text))));
+ aboutScreen.addItem(createAction(ActionMenuElement.BACK));
+
+ ingameScreen.addItem(continueAction);
+ ingameScreen.addItem(ingameRestartAction);
+ ingameScreen.addItem(new SimpleMenuElementNew(getString(R.string.options), optionsMenu, this));
+ ingameScreen.addItem(new SimpleMenuElementNew(getString(R.string.help), helpMenu, this));
+ ingameScreen.addItem(createAction(ActionMenuElement.PLAY_MENU));
+ nameAction = new ActionMenuElement(getString(R.string.name) + " - " + new String(nameChars), 0, this);
+ okCommand = new Command(getString(R.string.ok), 4, 1);
+ backCommand = new Command(getString(R.string.back), 2, 1);
+ setCurrentMenu(mainMenu, false);
+
+ // LevelsManager
+ managerInstalledScreen = new InstalledLevelsMenuScreen(getString(R.string.installed_mods), managerScreen);
+ managerDownloadScreen = new DownloadLevelsMenuScreen(getString(R.string.download_mods), managerScreen);
+ // managerDownloadOptionsScreen = new MenuScreen(getString(R.string.download_options), managerDownloadScreen);
+
+ /*managerInstalledScreen.setIsLevelsList(true);
+ managerDownloadScreen.setIsLevelsList(true);*/
+
+ // LevelsManager
+ managerScreen.addItem(new SimpleMenuElementNew(getString(R.string.download_mods), managerDownloadScreen, this));
+ managerScreen.addItem(new SimpleMenuElementNew(getString(R.string.installed_mods), managerInstalledScreen, this));
+ managerScreen.addItem(createEmptyLine(true));
+ // managerScreen.addItem(new ActionMenuElement(getString(R.string.install_mrg), this));
+ managerScreen.addItem(new ActionMenuElement(getString(R.string.install_mrg), ActionMenuElement.SELECT_FILE, this));
+
+ // LevelsManager installed
+ // managerInstalledScreen.addItem(new TextMenuElement(getString(R.string.installed_levels_text)));
+
+ // Level screen
+ levelScreen = new MenuScreen("", null);
+ break;
+ }
+ }
+
+ /*public void reloadLevels() {
+ Loader loader = getLevelLoader();
+ trackNames = loader.names;
+ setUnlockedLevels();
+ }*/
+
+ protected ActionMenuElement createAction(int action) {
+ int r;
+ switch (action) {
+ case ActionMenuElement.BACK:
+ r = R.string.back;
+ break;
+
+ case ActionMenuElement.NO:
+ r = R.string.no;
+ break;
+
+ case ActionMenuElement.YES:
+ r = R.string.yes;
+ break;
+
+ case ActionMenuElement.EXIT:
+ r = R.string.exit;
+ break;
+
+ case ActionMenuElement.OK:
+ r = R.string.ok;
+ break;
+
+ case ActionMenuElement.PLAY_MENU:
+ r = R.string.play_menu;
+ break;
+
+ case ActionMenuElement.GO_TO_MAIN:
+ r = R.string.go_to_main;
+ break;
+
+ case ActionMenuElement.RESTART:
+ r = R.string.restart;
+ break;
+
+ case ActionMenuElement.NEXT:
+ r = R.string.next;
+ break;
+
+ case ActionMenuElement.CONTINUE:
+ r = R.string._continue;
+ break;
+
+ case ActionMenuElement.LOAD:
+ r = R.string.load_this_game;
+ break;
+
+ case ActionMenuElement.INSTALL:
+ r = R.string.install_kb;
+ break;
+
+ case ActionMenuElement.DELETE:
+ r = R.string.delete;
+ break;
+
+ case ActionMenuElement.RESTART_WITH_NEW_LEVEL:
+ r = R.string.restart_with_new_level;
+ break;
+
+ case ActionMenuElement.SEND_LOGS:
+ r = R.string.send_logs;
+ break;
+
+ default:
+ return null;
+ }
+
+ return new ActionMenuElement(getString(r), action, this);
+ }
+
+ public EmptyLineMenuElement createEmptyLine(boolean beforeAction) {
+ return new EmptyLineMenuElement(beforeAction ? 10 : 20);
+ }
+
+ public int getSelectedLevel() {
+ return levelSelector.getSelectedOption();
+ }
+
+ public int getSelectedTrack() {
+ return trackSelector.getSelectedOption();
+ }
+
+ // not sure about this name
+ public boolean canStartTrack() {
+ if (m_SZ) {
+ m_SZ = false;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void saveCompletedTrack() {
+ // ATTENTION!!!
+ // WHEN CHANGING THIS CODE, COPY-PASTE TO startTrack() !!!
+
+ LevelsManager levelsManager = getLevelsManager();
+
+ try {
+ currentScores.saveHighScore(leagueSelector.getSelectedOption(), new String(nameChars, "UTF-8"), lastTrackTime);
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ showAlert(getString(R.string.error), e.getMessage(), null);
+ }
+ // saveManager.write();
+ levelsManager.saveHighScores(currentScores);
+
+ leagueCompleted = false;
+
+ finishedMenu.clear();
+ finishedMenu.addItem(new TextMenuElement(Html.fromHtml("<b>" + getString(R.string.time) + "</b>: " + finishedTime)));
+
+ System.gc();
+ String[] as = currentScores.getScores(leagueSelector.getSelectedOption());
+ for (int k = 0; k < as.length; k++)
+ if (as[k] != null)
+ finishedMenu.addItem(new TextMenuElement("" + (k + 1) + ". " + as[k]));
+
+ byte byte0 = -1;
+ // logDebug("trackSelector.getUnlockedCount() = " + trackSelector.getUnlockedCount());
+ // logDebug("trackSelector.getSelectedOption() = " + trackSelector.getSelectedOption());
+
+ // {
+ // int unlockedTracks = trackSelector.getUnlockedCount();
+ // int selectedTrack = trackSelector.getSelectedOption();
+ // int selectedLevel = levelSelector.getSelectedOption();
+ // int unlockedInLevel = level.getUnlocked(selectedLevel);
+
+ // logDebug("unlockedTracks (trackSelector) = " + trackSelector.getUnlockedCount());
+ // logDebug("selectedTrack (trackSelector) = " + selectedTrack);
+ // logDebug("selectedLevel (levelSelector) = " + levelSelector.getSelectedOption());
+ // logDebug("unlockedInLevel (level.getUnlocked()) = " + level.getUnlocked(levelSelector.getSelectedOption()));
+
+ if (trackSelector.getUnlockedCount() >= trackSelector.getSelectedOption()) {
+ trackSelector.setUnlockedCount(
+ trackSelector.getSelectedOption() + 1 >= level.getUnlocked(levelSelector.getSelectedOption())
+ ? trackSelector.getSelectedOption() + 1
+ : level.getUnlocked(levelSelector.getSelectedOption())
+ );
+ level.setUnlocked(levelSelector.getSelectedOption(),
+ trackSelector.getUnlockedCount() >= level.getUnlocked(levelSelector.getSelectedOption())
+ ? trackSelector.getUnlockedCount()
+ : level.getUnlocked(levelSelector.getSelectedOption())
+ );
+ }
+ // }
+
+ // Completed league
+ if (trackSelector.getSelectedOption() == trackSelector.getOptionCount()) {
+ leagueCompleted = true;
+ switch (levelSelector.getSelectedOption()) {
+ default:
+ break;
+
+ case 0:
+ if (level.getUnlockedLeagues() < 1) {
+ byte0 = 1;
+ level.setUnlockedLeagues(1);
+ // leaguesUnlockedCount = 1;
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ }
+ break;
+
+ case 1:
+ if (level.getUnlockedLeagues() < 2) {
+ byte0 = 2;
+ level.setUnlockedLeagues(2);
+ // leaguesUnlockedCount = 2;
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ }
+ break;
+
+ case 2:
+ if (level.getUnlockedLeagues() < 3) {
+ byte0 = 3;
+ level.setUnlockedLeagues(3);
+ leagueSelector.setOptions(fullLeaguesList);
+ leagues = fullLeaguesList;
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ }
+ break;
+ }
+
+ levelSelector.setUnlockedCount(levelSelector.getUnlockedCount() + 1);
+
+ int newUnlocked = level.getUnlocked(levelSelector.getSelectedOption()) + 1,
+ tracksCount = level.getCount(levelSelector.getSelectedOption());
+
+ if (newUnlocked > tracksCount)
+ newUnlocked = tracksCount;
+
+ level.setUnlocked(levelSelector.getSelectedOption(), newUnlocked);
+ if (level.getUnlocked(levelSelector.getUnlockedCount()) == -1) {
+ level.setUnlocked(levelSelector.getUnlockedCount(), 0);
+ }
+ // if (unlockedTracks[levelSelector.getUnlockedCount()] == -1)
+ // unlockedTracks[levelSelector.getUnlockedCount()] = 0;
+ } else {
+ trackSelector.performAction(MenuScreen.KEY_RIGHT);
+ }
+
+ // int completedCount = _bbII(levelSelector.getSelectedOption());
+ int completedCount = level.getUnlocked(levelSelector.getSelectedOption()); // TODO test
+ finishedMenu.addItem(new TextMenuElement(Html.fromHtml(String.format(getString(R.string.tracks_completed_tpl),
+ completedCount, trackNames[levelSelector.getSelectedOption()].length, difficultyLevels[levelSelector.getSelectedOption()]))));
+ System.gc();
+
+ if (!leagueCompleted) {
+ ingameRestartAction.setText(getString(R.string.restart) + ": " + getLevelLoader().getLevelName(levelSelector.getSelectedOption(), trackSelector.getSelectedOption()));
+ nextAction.setText(getString(R.string.next) + ": " + getLevelLoader().getLevelName(levelIndex, track + 1));
+
+ // getLevelsManager().updateLevelSettings();
+ saveAll();
+ } else {
+ // League completed
+ if (levelSelector.getSelectedOption() < levelSelector.getOptionCount()) {
+ levelSelector.setSelectedOption(levelSelector.getSelectedOption() + 1);
+ trackSelector.setSelectedOption(0);
+ trackSelector.setUnlockedCount(level.getUnlocked(levelSelector.getSelectedOption()));
+ }
+
+ if (byte0 != -1) {
+ finishedMenu.addItem(new TextMenuElement(getString(R.string.congratulations) + leagues[byte0]));
+ if (byte0 == 3)
+ finishedMenu.addItem(new TextMenuElement(getString(R.string.enjoy)));
+ showAlert(getString(R.string.league_unlocked), getString(R.string.league_unlocked_text) + leagues[byte0], null);
+
+ // getLevelsManager().updateLevelSettings();
+ saveAll();
+ } else {
+ boolean flag = true;
+ for (int i1 = 0; i1 < 3; i1++)
+ if (level.getUnlocked(i1) != getLevelLoader().names[i1].length - 1)
+ flag = false;
+
+ if (!flag)
+ finishedMenu.addItem(new TextMenuElement(getString(R.string.level_completed_text)));
+ }
+ }
+
+ if (!leagueCompleted)
+ finishedMenu.addItem(nextAction);
+
+ finishedRestartAction.setText(getString(R.string.restart) + ": " + getLevelLoader().getLevelName(levelIndex, track));
+ finishedMenu.addItem(finishedRestartAction);
+ finishedMenu.addItem(createAction(ActionMenuElement.PLAY_MENU));
+
+ setCurrentMenu(finishedMenu, false);
+ }
+
+ //public void _hvV() {
+ // getGDActivity().m_di.postInvalidate();
+ //}
+
+ /* public int getGameViewScaledHeight() {
+ return getGDView().getScaledHeight();
+ }
+
+ public int getGameViewScaledWidth() {
+ return getGDView().getScaledWidth();
+ } */
+
+ public void showMenu(int k) {
+ logDebug("[Menu] showMenu()");
+ // k = 2;
+
+ GDActivity gd = getGDActivity();
+ GameView view = getGDView();
+ Loader loader = getLevelLoader();
+
+ m_blZ = false;
+ menuDisabled = false;
+ switch (k) {
+ case 0: // Just started
+ setCurrentMenu(mainMenu, false);
+ gd.physEngine._casevV();
+ m_SZ = true;
+ break;
+
+ case 1: // Ingame
+ levelIndex = levelSelector.getSelectedOption();
+ track = trackSelector.getSelectedOption();
+ ingameRestartAction.setText(getString(R.string.restart) + ": " + loader.getLevelName(levelIndex, track));
+ m_SZ = false;
+ ingameScreen.resetHighlighted();
+ setCurrentMenu(ingameScreen, false);
+ break;
+
+ case 2: // Finished
+ // finishTime = System.currentTimeMillis();
+ finishedMenu.clear();
+
+ levelIndex = levelSelector.getSelectedOption();
+ track = trackSelector.getSelectedOption();
+ HighScores scores = getLevelsManager().getHighScores(levelSelector.getSelectedOption(), trackSelector.getSelectedOption());
+ currentScores = scores;
+
+ // saveManager.setTrack(levelSelector.getSelectedOption(), trackSelector.getSelectedOption());
+ int place = scores.getPlace(leagueSelector.getSelectedOption(), lastTrackTime);
+ finishedTime = getDurationString(lastTrackTime);
+
+ if (place >= 0 && place <= 2) {
+ HighScoreTextMenuElement placeText = new HighScoreTextMenuElement("");
+ placeText.setText(getStringArray(R.array.finished_places)[place]);
+ placeText.setMedal(true, place);
+
+ finishedMenu.addItem(placeText);
+
+ TextMenuElement h2 = new TextMenuElement(finishedTime);
+ finishedMenu.addItem(h2);
+
+ // finishedMenu.addItem(createEmptyLine(true));
+ finishedMenu.addItem(createAction(ActionMenuElement.OK));
+ finishedMenu.addItem(nameAction);
+
+ setCurrentMenu(finishedMenu, false);
+ m_blZ = false;
+ } else {
+ saveCompletedTrack();
+ }
+ break;
+
+ default:
+ setCurrentMenu(mainMenu, false);
+ break;
+ }
+
+ long l1 = System.currentTimeMillis();
+ view.drawTimer = false;
+ long l4 = 0L;
+ int i1 = 50;
+ gd.physEngine._charvV();
+ gd.gameToMenu();
+
+ do {
+ if (!gd.isMenuShown() || !gd.alive || currentMenu == null)
+ break;
+
+ if (gd.m_cZ) {
+ while (gd.m_cZ) {
+ // logDebug("[Menu] showMenu() waiting loop");
+ if (!gd.alive || currentMenu == null) {
+ break;
+ }
+
+ try {
+ Thread.sleep(100L);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ if (gd.physEngine != null && gd.physEngine._gotovZ()) {
+ int j1;
+ if ((j1 = gd.physEngine._dovI()) != 0 && j1 != 4)
+ try {
+ gd.physEngine._doZV(true);
+ } catch (NullPointerException e) {
+ }
+ gd.physEngine._charvV();
+ // _hvV();
+ long l2;
+ if ((l2 = System.currentTimeMillis()) - l4 < (long) i1) {
+ try {
+ synchronized (m_BObject) {
+ m_BObject.wait((long) i1 - (l2 - l4) >= 1L ? (long) i1 - (l2 - l4) : 1L);
+ }
+ } catch (InterruptedException e) {
+ }
+ l4 = System.currentTimeMillis();
+ } else {
+ l4 = l2;
+ }
+ } else {
+ i1 = 50;
+ long l3;
+ if ((l3 = System.currentTimeMillis()) - l4 < (long) i1) {
+ Object obj;
+ try {
+ synchronized (obj = new Object()) {
+ obj.wait((long) i1 - (l3 - l4) >= 1L ? (long) i1 - (l3 - l4) : 1L);
+ }
+ } catch (InterruptedException e) {
+ }
+ l4 = System.currentTimeMillis();
+ } else {
+ l4 = l3;
+ }
+ }
+ } while (true);
+
+ logDebug("[Menu.showMenu] out loop");
+
+ gd.m_forJ += System.currentTimeMillis() - l1;
+ if (view != null)
+ view.drawTimer = true;
+
+ if (currentMenu == null && gd != null) {
+ logDebug("[Menu.showMenu] currentMenu == null, set alive = false");
+ gd.exiting = true;
+ gd.alive = false;
+ }
+ }
+
+ public synchronized void draw(Canvas g1) {
+ if (currentMenu != null && !m_blZ) {
+ getGDView().drawGame(g1);
+ drawBackgroundColor(g1);
+ // currentMenu.draw(g1);
+ }
+ }
+
+ private void drawBackgroundColor(Canvas g1) {
+ g1.drawRect(0, 0, getGDView().getScaledWidth(), getGDView().getScaledHeight(), bgPaint);
+ }
+
+ public void _tryIV(int k) {
+ // logDebug("_tryIV k = " + k);
+ if (getGDView().getGameAction(k) != 8)
+ keyPressed(k);
+ }
+
+ public void keyPressed(int k) {
+ if (currentMenu != null && !menuDisabled)
+ switch (getGDView().getGameAction(k)) {
+ case MenuScreen.KEY_UP: // up
+ currentMenu.performAction(MenuScreen.KEY_UP);
+ return;
+
+ case MenuScreen.KEY_DOWN: // down
+ currentMenu.performAction(MenuScreen.KEY_DOWN);
+ return;
+
+ case MenuScreen.KEY_FIRE: // fire
+ currentMenu.performAction(MenuScreen.KEY_FIRE);
+ return;
+
+ case MenuScreen.KEY_RIGHT: // right
+ currentMenu.performAction(MenuScreen.KEY_RIGHT);
+ if (currentMenu == highScoreMenu) {
+ selectedLeague++;
+ if (selectedLeague > leagueSelector.getUnlockedCount())
+ selectedLeague = leagueSelector.getUnlockedCount();
+ showHighScoreMenu(selectedLeague);
+ return;
+ }
+ break;
+
+ case MenuScreen.KEY_LEFT: // left
+ currentMenu.performAction(MenuScreen.KEY_LEFT);
+ if (currentMenu != highScoreMenu)
+ break;
+ selectedLeague--;
+ if (selectedLeague < 0)
+ selectedLeague = 0;
+ showHighScoreMenu(selectedLeague);
+ break;
+ }
+ }
+
+ public void onCommand(Command command) {
+ if (command == okCommand) {
+ ok();
+ } else if (command == backCommand && currentMenu != null) {
+ back();
+ }
+ }
+
+ public void back() {
+ if (currentMenu == ingameScreen) {
+ getGDActivity().menuToGame();
+ return;
+ }
+ if (currentMenu != null)
+ setCurrentMenu(currentMenu.getNavTarget(), true);
+ }
+
+ public void ok() {
+ if (currentMenu != null) {
+ currentMenu.performAction(1);
+ return;
+ }
+ }
+
+ public MenuScreen getCurrentMenu() {
+ return currentMenu;
+ }
+
+ public void setCurrentMenu(MenuScreen newMenu, boolean flag) {
+ menuDisabled = false;
+ GDActivity gd = getGDActivity();
+ GameView view = getGDView();
+
+ if (!Settings.isKeyboardInMenuEnabled()) {
+ if (newMenu == nameScreen) {
+ gd.showKeyboardLayout();
+ } else {
+ gd.hideKeyboardLayout();
+ }
+ }
+
+ view.removeCommand(backCommand);
+ if (newMenu != mainMenu && newMenu != finishedMenu && newMenu != null)
+ view.addCommand(backCommand);
+
+ if (newMenu == highScoreMenu) {
+ selectedLeague = leagueSelector.getSelectedOption();
+ showHighScoreMenu(selectedLeague);
+ } else if (newMenu == finishedMenu) {
+ // logDebug("it's finished!!!");
+ nameChars = nameScreen.getChars();
+ nameAction.setText(getString(R.string.name) + " - " + new String(nameChars));
+ } else if (newMenu == playMenu) {
+ trackSelector.setOptions(getLevelLoader().names[levelSelector.getSelectedOption()], false);
+ if (currentMenu == trackSelectorCurrentMenu) {
+ selectedTrack[levelSelector.getSelectedOption()] = trackSelector.getSelectedOption();
+ }
+ trackSelector.setUnlockedCount(level.getUnlocked(levelSelector.getSelectedOption()));
+ trackSelector.setSelectedOption(selectedTrack[levelSelector.getSelectedOption()]);
+ }
+ if (newMenu == mainMenu || newMenu == playMenu && gd.physEngine != null)
+ gd.physEngine._casevV();
+
+ if (currentMenu != null)
+ currentMenu.onHide(newMenu);
+
+ currentMenu = newMenu;
+ if (currentMenu != null) {
+ gd.setMenu(currentMenu.getLayout());
+ currentMenu.onShow();
+
+ // getGDActivity().setMenu(currentMenu.getTable());
+ // if (!isOnOffToggle) currentMenu.scrollUp();
+ }
+
+ // getGDActivity().physEngine._casevV();
+ m_blZ = false;
+
+ // */
+ }
+
+ public void showHighScoreMenu(int league) {
+ HighScores highScores = getLevelsManager().getHighScores(levelSelector.getSelectedOption(), trackSelector.getSelectedOption());
+
+ highScoreMenu.clear();
+ highScoreMenu.setTitle(getString(R.string.highscores) + ": " + getLevelLoader().getLevelName(levelSelector.getSelectedOption(), trackSelector.getSelectedOption()));
+
+ HighScoreTextMenuElement subtitle = new HighScoreTextMenuElement(Html.fromHtml(getString(R.string.league) + ": " + leagueSelector.getOptions()[league]));
+ subtitle.setIsSubtitle(true);
+
+ highScoreMenu.addItem(subtitle);
+
+ String[] scores = highScores.getScores(league);
+
+ for (int place = 0; place < scores.length; place++) {
+ if (scores[place] == null)
+ continue;
+
+ HighScoreTextMenuElement h1 = new HighScoreTextMenuElement("" + (place + 1) + ". " + scores[place]);
+ if (place == 0)
+ h1.setMedal(true, 0);
+ else if (place == 1)
+ h1.setMedal(true, 1);
+ else if (place == 2)
+ h1.setMedal(true, 2);
+
+ h1.setLayoutPadding(true);
+ highScoreMenu.addItem(h1);
+ }
+
+ // saveManager.closeRecordStore();
+ if (scores[0] == null)
+ highScoreMenu.addItem(new TextMenuElement(getString(R.string.no_highscores)));
+
+ highScoreMenu.addItem(createAction(ActionMenuElement.BACK));
+ highScoreMenu.highlightElement();
+
+ // System.gc();
+ }
+
+ public synchronized void destroy() {
+ currentMenu = null;
+ }
+
+ public synchronized void saveAll() {
+ logDebug("saveAll()");
+
+ try {
+ if (level != null) {
+ Settings.setName(nameChars);
+
+ level.setUnlockedLeagues(leagueSelector.getUnlockedCount());
+ level.setUnlockedLevels(levelSelector.getUnlockedCount());
+
+ level.setSelectedLevel(levelSelector.getSelectedOption());
+ level.setSelectedTrack(trackSelector.getSelectedOption());
+ level.setSelectedLeague(leagueSelector.getSelectedOption());
+
+ getLevelsManager().updateLevelSettings();
+ } else {
+ logDebug("saveAll(): level == null");
+ }
+ } catch (Exception e) {
+ logDebug("saveAll exception: " + e);
+ }
+ }
+
+ public void handleAction(MenuElement item) {
+ final GDActivity gd = getGDActivity();
+
+ if (currentMenu == null) {
+ return;
+ }
+
+ if (item == startItem)
+ if (levelSelector.getSelectedOption() > levelSelector.getUnlockedCount() || trackSelector.getSelectedOption() > trackSelector.getUnlockedCount() || leagueSelector.getSelectedOption() > leagueSelector.getUnlockedCount()) {
+ showAlert("GD Classic", getString(R.string.complete_to_unlock), null);
+ return;
+ } else {
+ gd.physEngine._avV();
+ startTrack(levelSelector.getSelectedOption(), trackSelector.getSelectedOption());
+ gd.physEngine.setLeague(leagueSelector.getSelectedOption());
+ m_SZ = true;
+ gd.menuToGame();
+ return;
+ }
+
+ if (item == vibrateOnTouchOptionItem) {
+ Settings.setVibrateOnTouchEnabled(((OptionsMenuElement) item).getSelectedOption() == 0);
+ }
+ if (item == keyboardInMenuOptionItem) {
+ boolean enabled = ((OptionsMenuElement) item).getSelectedOption() == 0;
+ Settings.setKeyboardInMenuEnabled(enabled);
+ if (enabled) gd.showKeyboardLayout();
+ else gd.hideKeyboardLayout();
+ }
+ if (item == perspectiveOptionItem) {
+ gd.physEngine._aZV(perspectiveOptionItem.getSelectedOption() == 0);
+ getLevelLoader().setPerspectiveEnabled(perspectiveOptionItem.getSelectedOption() == 0);
+ Settings.setPerspectiveEnabled(perspectiveOptionItem.getSelectedOption() == 0);
+ return;
+ }
+ if (item == shadowsOptionItem) {
+ getLevelLoader().setShadowsEnabled(shadowsOptionItem.getSelectedOption() == 0);
+ Settings.setShadowsEnabled(shadowsOptionItem.getSelectedOption() == 0);
+ return;
+ }
+ if (item == driverSpriteOptionItem) {
+ if (driverSpriteOptionItem._charvZ()) {
+ driverSpriteOptionItem.setSelectedOption(driverSpriteOptionItem.getSelectedOption() + 1);
+ }
+ Settings.setDriverSpriteEnabled(driverSpriteOptionItem.getSelectedOption() == 0);
+ } else if (item == bikeSpriteOptionItem) {
+ if (bikeSpriteOptionItem._charvZ()) {
+ bikeSpriteOptionItem.setSelectedOption(bikeSpriteOptionItem.getSelectedOption() + 1);
+ }
+ Settings.setBikeSpriteEnabled(bikeSpriteOptionItem.getSelectedOption() == 0);
+ } else {
+ if (item == inputOptionItem) {
+ if (inputOptionItem._charvZ())
+ inputOptionItem.setSelectedOption(inputOptionItem.getSelectedOption() + 1);
+ getGDView().setInputOption(inputOptionItem.getSelectedOption());
+ Settings.setInputOption(inputOptionItem.getSelectedOption());
+ return;
+ }
+ if (item == lookAheadOptionItem) {
+ gd.physEngine._ifZV(lookAheadOptionItem.getSelectedOption() == 0);
+ Settings.setLookAheadEnabled(lookAheadOptionItem.getSelectedOption() == 0);
+ return;
+ }
+ if (item instanceof ActionMenuElement) {
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.RESTART_WITH_NEW_LEVEL) {
+ LevelsManager manager = gd.levelsManager;
+ long nextId = manager.getCurrentId() == 1 ? 2 : 1;
+ gd.levelsManager.load(manager.getLeveL(nextId));
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.SEND_LOGS) {
+ gd.sendKeyboardLogs();
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.SELECT_FILE) {
+ installFromFileBrowse();
+ return;
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.YES) {
+ if (currentMenu == eraseScreen) {
+ getLevelsManager().clearHighScores();
+ showAlert(getString(R.string.cleared), getString(R.string.cleared_text), null);
+ } else if (currentMenu == resetScreen) {
+ showAlert(getString(R.string.reset), getString(R.string.reset_text), new Runnable() {
+ @Override
+ public void run() {
+ resetAll();
+ }
+ });
+ }
+ setCurrentMenu(currentMenu.getNavTarget(), false);
+ return;
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.NO) {
+ setCurrentMenu(currentMenu.getNavTarget(), false);
+ return;
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.BACK) {
+ setCurrentMenu(currentMenu.getNavTarget(), true);
+ return;
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.PLAY_MENU) {
+ levelSelector.setSelectedOption(levelIndex);
+ trackSelector.setUnlockedCount(level.getUnlocked(levelIndex));
+ trackSelector.setSelectedOption(track);
+ setCurrentMenu(currentMenu.getNavTarget(), false);
+ return;
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.GO_TO_MAIN) {
+ setCurrentMenu(mainMenu, false);
+ return;
+ }
+ if (((ActionMenuElement) item).getActionValue() == ActionMenuElement.EXIT) {
+ getGDActivity().exiting = true;
+ if (currentMenu != null) {
+ setCurrentMenu(currentMenu.getNavTarget(), false);
+ } else {
+ setCurrentMenu(null, false);
+ }
+ return;
+ }
+ }
+
+ if (item == ingameRestartAction || item == finishedRestartAction) {
+ if (leagueSelector.getSelectedOption() <= leagueSelector.getUnlockedCount()) {
+ levelSelector.setSelectedOption(levelIndex);
+ trackSelector.setUnlockedCount(level.getUnlocked(levelIndex));
+ trackSelector.setSelectedOption(track);
+ gd.physEngine.setLeague(leagueSelector.getSelectedOption());
+ m_SZ = true;
+ gd.menuToGame();
+ return;
+ }
+ } else {
+ if (item == nextAction) {
+ // if (!leagueCompleted)
+ // trackSelector.performAction(MenuScreen.KEY_RIGHT);
+ startTrack(levelSelector.getSelectedOption(), trackSelector.getSelectedOption());
+ gd.physEngine.setLeague(leagueSelector.getSelectedOption());
+ // saveAll();
+ // getLevelsManager().updateLevelSettings();
+ m_SZ = true;
+ gd.menuToGame();
+ return;
+ }
+ if (item == continueAction) {
+ // _hvV();
+ gd.menuToGame();
+ return;
+ }
+ if (item == nameAction) {
+ nameScreen.resetCursorPosition();
+ setCurrentMenu(nameScreen, false);
+ return;
+ }
+ if (item instanceof ActionMenuElement && ((ActionMenuElement) item).getActionValue() == ActionMenuElement.OK) {
+ saveCompletedTrack();
+ return;
+ }
+ if (item == trackSelector) {
+ if (trackSelector._charvZ()) {
+ trackSelector.setUnlockedCount(level.getUnlocked(levelSelector.getSelectedOption()));
+ trackSelector.update();
+ trackSelectorCurrentMenu = trackSelector.getCurrentMenu();
+ setCurrentMenu(trackSelectorCurrentMenu, false);
+ // trackSelectorCurrentMenu._doIV(trackSelector.getSelectedOption());
+ }
+ selectedTrack[levelSelector.getSelectedOption()] = trackSelector.getSelectedOption();
+ return;
+ }
+ if (item == levelSelector) {
+ if (levelSelector._charvZ()) {
+ levelSelectorCurrentMenu = levelSelector.getCurrentMenu();
+ setCurrentMenu(levelSelectorCurrentMenu, false);
+ }
+ trackSelector.setOptions(getLevelLoader().names[levelSelector.getSelectedOption()], false);
+ trackSelector.setUnlockedCount(level.getUnlocked(levelSelector.getSelectedOption()));
+ trackSelector.setSelectedOption(selectedTrack[levelSelector.getSelectedOption()]);
+ // trackSelector.update();
+ // logDebug("update tracks ");
+ return;
+ }
+ if (item == leagueSelector && leagueSelector._charvZ()) {
+ leagueSelectorCurrentMenu = leagueSelector.getCurrentMenu();
+ // leagueSelector.update();
+ leagueSelector.setScreen(currentMenu);
+ setCurrentMenu(leagueSelectorCurrentMenu, false);
+ // leagueSelectorCurrentMenu._doIV(leagueSelector.getSelectedOption());
+ }
+ }
+ }
+ }
+
+ protected void startTrack(int levelIndex, int trackIndex) {
+ // ATTENTION!!!
+ // WHEN CHANGING THIS CODE, COPY-PASTE TO saveCompletedTrack() !!!
+
+ if (Global.ACRA_ENABLED) {
+ ACRA.getErrorReporter().putCustomData("level_index:", String.valueOf(levelIndex));
+ ACRA.getErrorReporter().putCustomData("track_index:", String.valueOf(trackIndex));
+ }
+
+ /*Menu _menu = null;
+ _menu.back();*/
+
+ try {
+ getLevelLoader()._doIII(levelIndex, trackIndex);
+ } catch (InvalidTrackException e) {
+ showConfirm(getString(R.string.oops), getString(R.string.e_level_damaged), new Runnable() {
+ @Override
+ public void run() {
+ if (trackSelector.getSelectedOption() + 1 < level.getCount(levelSelector.getSelectedOption())) {
+ trackSelector.setUnlockedCount(trackSelector.getSelectedOption() + 1);
+ level.setUnlocked(levelSelector.getSelectedOption(), trackSelector.getUnlockedCount());
+ } else {
+ switch (levelSelector.getSelectedOption()) {
+ case 0:
+ if (level.getUnlockedLeagues() < 1) {
+ level.setUnlockedLeagues(1);
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ }
+ break;
+
+ case 1:
+ if (level.getUnlockedLeagues() < 2) {
+ level.setUnlockedLeagues(2);
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ }
+ break;
+
+ case 2:
+ if (level.getUnlockedLeagues() < 3) {
+ level.setUnlockedLeagues(3);
+ leagueSelector.setOptions(fullLeaguesList);
+ leagues = fullLeaguesList;
+ leagueSelector.setUnlockedCount(level.getUnlockedLeagues());
+ }
+ break;
+ }
+
+ int newUnlocked = level.getUnlocked(levelSelector.getSelectedOption()) + 1,
+ tracksCount = level.getCount(levelSelector.getSelectedOption());
+
+ if (newUnlocked > tracksCount)
+ newUnlocked = tracksCount;
+
+ levelSelector.setUnlockedCount(levelSelector.getUnlockedCount() + 1);
+ level.setUnlocked(levelSelector.getSelectedOption(), newUnlocked);
+ }
+ }
+ }, null);
+ }
+ }
+
+ public int _jvI() {
+ int k = 0;
+ if (driverSpriteOptionItem.getSelectedOption() == 0)
+ k |= 2;
+ if (bikeSpriteOptionItem.getSelectedOption() == 0)
+ k |= 1;
+ return k;
+ }
+
+ public void _intIV(int k) {
+ bikeSpriteOptionItem.setSelectedOption(1);
+ driverSpriteOptionItem.setSelectedOption(1);
+ if ((k & 1) > 0)
+ bikeSpriteOptionItem.setSelectedOption(0);
+ if ((k & 2) > 0)
+ driverSpriteOptionItem.setSelectedOption(0);
+ }
+
+ /*public int _ovI() {
+ return levelSelector.getSelectedOption();
+ }
+
+ public int _nvI() {
+ return trackSelector.getSelectedOption();
+ }
+
+ public int _lvI() {
+ return leagueSelector.getSelectedOption();
+ }*/
+
+ public void setLastTrackTime(long l) {
+ lastTrackTime = l;
+ }
+
+ /*private byte[] readNameChars(int pos, byte defaultValue) {
+ switch (pos) {
+ case 16: // '\020'
+ byte[] abyte0 = new byte[3];
+ for (int l = 0; l < 3; l++)
+ abyte0[l] = settings[16 + l];
+
+ if (abyte0[0] == -127)
+ abyte0[0] = defaultValue;
+ return abyte0;
+ }
+ return null;
+ }
+
+ private byte readSetting(int index, byte defaultValue) {
+ if (settings[index] == -127)
+ return defaultValue;
+ else
+ return settings[index];
+ }
+
+ private void saveNameChars(int pos, byte[] chars) {
+ if (settingsLoadedOK && pos == 16) {
+ for (int l = 0; l < 3; l++)
+ settings[16 + l] = chars[l];
+
+ }
+ }*/
+
+ private String getDurationString(long l) {
+ m_ajI = (int) (l / 100L);
+ m_atI = (int) (l % 100L);
+ String s;
+ if (m_ajI / 60 < 10)
+ s = " 0" + m_ajI / 60;
+ else
+ s = " " + m_ajI / 60;
+ if (m_ajI % 60 < 10)
+ s = s + ":0" + m_ajI % 60;
+ else
+ s = s + ":" + m_ajI % 60;
+ if (m_atI < 10)
+ s = s + ".0" + m_atI;
+ else
+ s = s + "." + m_atI;
+ return s;
+ }
+
+ /*private void setSetting(int k, byte byte0) {
+ if (settingsLoadedOK)
+ settings[k] = byte0;
+ }*/
+
+ private void resetAll() {
+ Settings.resetAll();
+ getLevelsManager().resetAllLevelsSettings();
+ getLevelsManager().clearAllHighScores();
+
+ getGDActivity().fullResetting = true;
+ getGDActivity().destroyApp(true);
+ }
+
+ public void removeCommands() {
+ getGDView().removeCommand(okCommand);
+ getGDView().removeCommand(backCommand);
+ }
+
+ public void addCommands() {
+ if (currentMenu != mainMenu && currentMenu != finishedMenu && currentMenu != null)
+ getGDView().addCommand(backCommand);
+ getGDView().addCommand(okCommand);
+ }
+
+ /*private int _bbII(int k) {
+ String[] as = RecordStore.listRecordStores();
+ if (saveManager == null || as == null)
+ return 0;
+ int l = 0;
+ for (int i1 = 0; i1 < as.length; i1++)
+ if (as[i1].startsWith("" + k))
+ l++;
+
+ return l;
+ }*/
+
+ /*public boolean isKeyboardEnabled() {
+ return keyboardInMenuEnabled == 0;
+ }*/
+
+ // public boolean isVibrateOnTouchEnabled() {
+ // return vibrateOnTouchEnabled == 0;
+ //}
+
+ /*public void hideKeyboard(boolean firstRun) {
+ if (!Settings.isKeyboardInMenuEnabled()) {
+ getGDActivity().hideKeyboardLayout();
+ // MenuScreen.setSize(getGDView().getScaledWidth(), getGDView().getScaledHeight());
+ } else if (firstRun) {
+ getGDActivity().showKeyboardLayout();
+ }*//*else {
+ // MenuScreen.setSize(getGDView().getScaledWidth(), getGDView().getScaledHeight() - getGDActivity().getButtonsLayoutHeight());
+ }*//*
+ }
+
+ public void showKeyboard() {
+ getGDActivity().showKeyboardLayout();
+ // MenuScreen.setSize(getGDView().getScaledWidth(), getGDView().getScaledHeight() - getGDActivity().getButtonsLayoutHeight());
+ }*/
+
+ public void installFromFileBrowse() {
+ if (!LevelsManager.isExternalStorageReadable()) {
+ showAlert(getString(R.string.error), getString(R.string.e_external_storage_is_not_readable), null);
+ return;
+ }
+
+ final GDActivity gd = getGDActivity();
+ FileDialog fileDialog = new FileDialog(gd, Environment.getExternalStorageDirectory(), ".mrg");
+ fileDialog.addFileListener(new FileDialog.FileSelectedListener() {
+ public void fileSelected(final File file) {
+ final EditText input = new EditText(gd);
+ input.setInputType(InputType.TYPE_CLASS_TEXT);
+
+ AlertDialog.Builder alert = new AlertDialog.Builder(gd)
+ .setTitle(getString(R.string.enter_levels_name_title))
+ .setMessage(getString(R.string.enter_levels_name))
+ .setView(input)
+ .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ boolean ok = true;
+ String name = input.getText().toString();
+ if (name.equals("")) name = file.getName();
+
+ ProgressDialog progressDialog = ProgressDialog.show(gd, getString(R.string.install), getString(R.string.installing), true);
+
+ try {
+ gd.levelsManager.install(file, name, "", 0);
+ } catch (Exception e) {
+ ok = false;
+ e.printStackTrace();
+ showAlert(getString(R.string.error), e.getMessage(), null);
+ } finally {
+ progressDialog.dismiss();
+ }
+
+ if (ok) {
+ gd.levelsManager.showSuccessfullyInstalledDialog();
+ }
+ }
+ })
+ .setNegativeButton(getString(R.string.cancel), null);
+ alert.show();
+ }
+ });
+ fileDialog.showDialog();
+ }
+
+ public static boolean isNameCheat(byte[] chars) {
+ return chars[0] == 82 && chars[1] == 75 && chars[2] == 69;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/MenuElement.java b/src/org/happysanta/gd/Menu/MenuElement.java
new file mode 100644
index 0000000..82fe490
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/MenuElement.java
@@ -0,0 +1,20 @@
+package org.happysanta.gd.Menu;
+
+import android.view.View;
+
+/**
+ * Author: ch1p
+ */
+public interface MenuElement {
+
+ // public abstract void setText(String s);
+
+ public abstract boolean isSelectable();
+
+ public abstract View getView();
+
+ public abstract void setText(String text);
+
+ public void performAction(int k);
+
+}
diff --git a/src/org/happysanta/gd/Menu/MenuElementOld.java b/src/org/happysanta/gd/Menu/MenuElementOld.java
new file mode 100755
index 0000000..6a4400f
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/MenuElementOld.java
@@ -0,0 +1,32 @@
+package org.happysanta.gd.Menu;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.view.View;
+
+public interface MenuElementOld {
+
+ public abstract void setText(String s);
+
+ // Why y before x?!
+ public abstract void draw(Canvas g, int y, int x);
+
+ public abstract boolean isSelectable();
+
+ public abstract int getLineSpacing();
+
+ public abstract void performAction(int i);
+
+ public abstract void setFont(Paint font);
+
+ public abstract int getHeight();
+
+ public abstract int getFirstLineHeight();
+
+ public abstract int getXOffset();
+
+ public abstract void setPressed(boolean flag);
+
+ public abstract View getView();
+
+}
diff --git a/src/org/happysanta/gd/Menu/MenuHandler.java b/src/org/happysanta/gd/Menu/MenuHandler.java
new file mode 100755
index 0000000..208e579
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/MenuHandler.java
@@ -0,0 +1,12 @@
+package org.happysanta.gd.Menu;
+
+public interface MenuHandler {
+
+ public abstract MenuScreen getCurrentMenu();
+
+ public abstract void setCurrentMenu(MenuScreen e, boolean flag);
+
+ // public abstract void destroy();
+
+ public abstract void handleAction(MenuElement item);
+}
diff --git a/src/org/happysanta/gd/Menu/MenuScreen.java b/src/org/happysanta/gd/Menu/MenuScreen.java
new file mode 100755
index 0000000..c49c085
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/MenuScreen.java
@@ -0,0 +1,277 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.view.ViewTreeObserver;
+import android.widget.LinearLayout;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+
+import java.util.Vector;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.isSDK11OrHigher;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class MenuScreen
+ implements OnMenuElementHighlightListener {
+
+ public static final int KEY_FIRE = 5;
+ public static final int KEY_UP = 2;
+ public static final int KEY_DOWN = 8;
+ public static final int KEY_LEFT = 4;
+ public static final int KEY_RIGHT = 6;
+
+ protected static final int LAYOUT_LEFT_PADDING = 30;
+ protected static final int LAYOUT_TOP_PADDING = 0;
+ protected static final int LAYOUT_BOTTOM_PADDING = 15;
+
+ protected MenuScreen navTarget;
+ protected String title;
+ protected int selectedIndex;
+ protected Vector menuItems;
+ protected MenuLinearLayout layout;
+ protected ClickableMenuElement lastHighlighted;
+ protected boolean isTextScreen = false;
+
+ public MenuScreen(String title, MenuScreen navTarget) {
+ this.title = title;
+ selectedIndex = -1;
+ menuItems = new Vector();
+ this.navTarget = navTarget;
+
+ Context context = getGDActivity();
+
+ layout = new MenuLinearLayout(context);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.setPadding(getDp(LAYOUT_LEFT_PADDING), getDp(LAYOUT_TOP_PADDING), getDp(LAYOUT_LEFT_PADDING), getDp(LAYOUT_BOTTOM_PADDING));
+
+ // Disable multi-touch in menu
+ if (isSDK11OrHigher())
+ layout.setMotionEventSplittingEnabled(false);
+ }
+
+ public void addItem(MenuElement item) {
+ layout.addView(item.getView());
+ menuItems.add(item);
+
+ if (item instanceof ClickableMenuElement)
+ ((ClickableMenuElement) item).setOnHighlightListener(this);
+ }
+
+ protected void scrollToItem(MenuElement item) {
+ // int y = item.getView().getTop();
+ // logDebug("scrollTo: y = " + y);
+
+ // getGameMenu().scrollTo(y);
+ getGDActivity().scrollToView(item.getView());
+ }
+
+ public void performAction(int k) {
+ // logDebug("MenuScreen.performAction: k = " + k);
+ int from = 0;
+ switch (k) {
+ default:
+ // logDebug("selectedIndex = " + selectedIndex);
+ if (selectedIndex != -1) {
+ for (int i = selectedIndex; i < menuItems.size(); i++) {
+ MenuElement item;
+ if ((item = (MenuElement) menuItems.elementAt(i)) != null && item.isSelectable()) {
+ item.performAction(k);
+ return;
+ }
+ }
+ }
+ break;
+
+ case KEY_UP:
+ if (isTextScreen) {
+ getGDActivity().scrollTextMenuUp();
+ return;
+ }
+
+ if (selectedIndex > 0 && !elementIsFirstClickable(selectedIndex)) {
+ from = selectedIndex - 1;
+ } else {
+ from = menuItems.size() - 1;
+ }
+
+ for (int i = from; i >= 0; i--) {
+ MenuElement el = (MenuElement) menuItems.elementAt(i);
+ if (!(el instanceof ClickableMenuElement) || ((ClickableMenuElement) el).isDisabled()) {
+ continue;
+ }
+
+ highlightElement((ClickableMenuElement) el);
+ selectedIndex = i;
+ scrollToItem(el);
+ break;
+ }
+ break;
+
+ case KEY_DOWN:
+ if (isTextScreen) {
+ getGDActivity().scrollTextMenuDown();
+ return;
+ }
+
+ if (selectedIndex < menuItems.size() - 1) {
+ from = selectedIndex + 1;
+ } else {
+ from = 0;
+ }
+ for (int i = from; i < menuItems.size(); i++) {
+ MenuElement el = (MenuElement) menuItems.elementAt(i);
+ if (!(el instanceof ClickableMenuElement) || ((ClickableMenuElement) el).isDisabled()) {
+ continue;
+ }
+
+ highlightElement((ClickableMenuElement) el);
+ selectedIndex = i;
+ scrollToItem(el);
+ break;
+ }
+ break;
+ }
+ }
+
+ protected boolean elementIsFirstClickable(int index) {
+ for (int i = 0; i < menuItems.size(); i++) {
+ MenuElement el = (MenuElement) menuItems.elementAt(i);
+ if (!(el instanceof ClickableMenuElement) || ((ClickableMenuElement) el).isDisabled()) {
+ if (i == index) {
+ return false;
+ }
+ } else {
+ if (i < index) return false;
+ if (i == index) return true;
+ }
+ }
+
+ return false;
+ }
+
+ public MenuScreen getNavTarget() {
+ return navTarget;
+ }
+
+ public void setNavTarget(MenuScreen target) {
+ navTarget = target;
+ }
+
+ /*public void setIsLevelsList(boolean is) {
+ isLevelsList = is;
+ }*/
+
+ public void clear() {
+ menuItems.removeAllElements();
+ layout.removeAllViews();
+
+ selectedIndex = -1;
+ lastHighlighted = null;
+ }
+
+ public LinearLayout getLayout() {
+ return layout;
+ }
+
+ protected void setTitle(String s) {
+ title = s;
+ }
+
+ protected void updateTitle() {
+ final GDActivity gd = getGDActivity();
+ gd.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ gd.menuTitleTextView.setText(title);
+ // activity.menuTitleTextView.invalidate();
+ gd.titleLayout.invalidate();
+ }
+ });
+ }
+
+ public void onHide(MenuScreen newMenu) {
+ }
+
+ public void onShow() {
+ updateTitle();
+ highlightElement();
+ }
+
+ public void resetHighlighted() {
+ lastHighlighted = null;
+ }
+
+ public void highlightElement() {
+ if (lastHighlighted != null) {
+ lastHighlighted.showHelmet();
+ final ViewTreeObserver obs = layout.getViewTreeObserver();
+ obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ try {
+ obs.removeOnPreDrawListener(this);
+ scrollToItem(lastHighlighted);
+ } catch (Exception e) {
+ }
+
+ return true;
+ }
+ });
+ } else {
+ for (int i = 0; i < menuItems.size(); i++) {
+ if (menuItems.elementAt(i) instanceof ClickableMenuElement) {
+ ClickableMenuElement item = (ClickableMenuElement) menuItems.elementAt(i);
+ if (item.isDisabled()) continue;
+
+ highlightElement(item);
+ scrollToItem(lastHighlighted);
+ selectedIndex = i;
+
+ break;
+ }
+ }
+ }
+ }
+
+ public void setSelected(int index) {
+ try {
+ if (menuItems.elementAt(index) instanceof ClickableMenuElement) {
+ ClickableMenuElement item = (ClickableMenuElement) menuItems.elementAt(index);
+ if (item.isDisabled()) return;
+
+ highlightElement(item);
+ selectedIndex = index;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void highlightElement(ClickableMenuElement el) {
+ el.showHelmet();
+ lastHighlighted = el;
+ }
+
+ public void onScroll(double percent) {
+ }
+
+ @Override
+ public void onElementHighlight(ClickableMenuElement el) {
+ lastHighlighted = el;
+
+ int index = menuItems.indexOf(el);
+ if (index != -1)
+ selectedIndex = index;
+ }
+
+ public void setIsTextScreen(boolean isTextScreen) {
+ this.isTextScreen = isTextScreen;
+ }
+
+ /*public boolean isTextScreen() {
+ return isTextScreen;
+ }*/
+
+}
diff --git a/src/org/happysanta/gd/Menu/NameInputMenuScreen.java b/src/org/happysanta/gd/Menu/NameInputMenuScreen.java
new file mode 100644
index 0000000..e742c7c
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/NameInputMenuScreen.java
@@ -0,0 +1,175 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.MenuLinearLayout;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getGameMenu;
+
+public class NameInputMenuScreen extends MenuScreen {
+
+ protected static final String CURSOR = "^";
+ protected static final int WORD_SPACE = 3;
+
+ protected static int wordWidth = 0;
+
+ protected int cursorPosition = 0;
+ protected byte chars[];
+
+ protected MenuTextView nameTextViews[];
+ protected MenuTextView cursorTextViews[];
+ protected MenuLinearLayout nameLayout;
+ protected MenuLinearLayout cursorLayout;
+
+ static {
+ wordWidth = getWordWidth();
+ }
+
+ public NameInputMenuScreen(String title, MenuScreen navTarget, byte nameChars[]) {
+ super(title, navTarget);
+
+ chars = nameChars;
+
+ Context context = getGDActivity();
+
+ nameTextViews = new MenuTextView[3];
+ cursorTextViews = new MenuTextView[3];
+
+ nameLayout = new MenuLinearLayout(context);
+ nameLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+ cursorLayout = new MenuLinearLayout(context);
+ cursorLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+ for (int i = 0; i < 3; i++) {
+ nameTextViews[i] = createTextView();
+ nameLayout.addView(nameTextViews[i]);
+
+ cursorTextViews[i] = createTextView();
+ cursorLayout.addView(cursorTextViews[i]);
+ }
+
+ layout.addView(nameLayout, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+ layout.addView(cursorLayout, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
+
+ updateText();
+ updateCursorPosition();
+ }
+
+ protected MenuTextView createTextView() {
+ Context context = getGDActivity();
+ MenuTextView textView = new MenuTextView(context);
+ textView.setTextColor(0xff000000);
+ textView.setTypeface(Global.robotoCondensedTypeface);
+ textView.setTextSize(ClickableMenuElement.TEXT_SIZE);
+ textView.setLayoutParams(new LinearLayout.LayoutParams(
+ wordWidth,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ ));
+ return textView;
+ }
+
+ protected static int getWordWidth() {
+ Context context = getGDActivity();
+
+ String text = "W";
+ TextView textView = new TextView(context);
+ textView.setTextSize(ClickableMenuElement.TEXT_SIZE);
+ textView.setTypeface(Global.robotoCondensedTypeface);
+
+ Rect bounds = new Rect();
+
+ Paint textPaint = textView.getPaint();
+ textPaint.getTextBounds(text, 0, text.length(), bounds);
+
+ return bounds.width() + getDp(WORD_SPACE);
+ }
+
+ @Override
+ public void performAction(int k) {
+ switch (k) {
+ default:
+ break;
+
+ case MenuScreen.KEY_FIRE: // select
+ if (cursorPosition == 2) {
+ getGameMenu().setCurrentMenu(navTarget, false);
+ } else {
+ cursorPosition++;
+ updateCursorPosition();
+ }
+ break;
+
+ case MenuScreen.KEY_RIGHT: // right
+ cursorPosition++;
+ if (cursorPosition > 2) {
+ cursorPosition = 2;
+ }
+ updateCursorPosition();
+ break;
+
+ case MenuScreen.KEY_LEFT: // left
+ cursorPosition--;
+ if (cursorPosition < 0)
+ cursorPosition = 0;
+ updateCursorPosition();
+ break;
+
+ case MenuScreen.KEY_UP: // up
+ if (chars[cursorPosition] == 32) {
+ chars[cursorPosition] = 65;
+ updateText();
+ break;
+ }
+ chars[cursorPosition]++;
+ if (chars[cursorPosition] > 90) {
+ chars[cursorPosition] = 32;
+ }
+ updateText();
+ break;
+
+ case MenuScreen.KEY_DOWN: // down
+ if (chars[cursorPosition] == 32) {
+ chars[cursorPosition] = 90;
+ updateText();
+ break;
+ }
+ chars[cursorPosition]--;
+ if (chars[cursorPosition] < 65) {
+ chars[cursorPosition] = 32;
+ }
+ updateText();
+ break;
+ }
+ }
+
+ protected void updateText() {
+ for (int i = 0; i < nameTextViews.length; i++) {
+ nameTextViews[i].setTextOnUiThread(String.valueOf((char) chars[i]));
+ }
+ }
+
+ protected void updateCursorPosition() {
+ for (int i = 0; i < cursorTextViews.length; i++) {
+ cursorTextViews[i].setTextOnUiThread(i == cursorPosition ? CURSOR : "");
+ }
+ }
+
+ public byte[] getChars() {
+ return chars;
+ }
+
+ public void resetCursorPosition() {
+ cursorPosition = 0;
+ updateCursorPosition();
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/OnMenuElementHighlightListener.java b/src/org/happysanta/gd/Menu/OnMenuElementHighlightListener.java
new file mode 100644
index 0000000..f065bf1
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/OnMenuElementHighlightListener.java
@@ -0,0 +1,10 @@
+package org.happysanta.gd.Menu;
+
+/**
+ * Author: ch1p
+ */
+public interface OnMenuElementHighlightListener {
+
+ public abstract void onElementHighlight(ClickableMenuElement el);
+
+}
diff --git a/src/org/happysanta/gd/Menu/OptionsMenuElement.java b/src/org/happysanta/gd/Menu/OptionsMenuElement.java
new file mode 100644
index 0000000..2119b32
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/OptionsMenuElement.java
@@ -0,0 +1,301 @@
+package org.happysanta.gd.Menu;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.MenuImageView;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+import org.happysanta.gd.R;
+// import com.grishka.agdtr.R;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getString;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class OptionsMenuElement
+ extends ClickableMenuElement
+ implements MenuElement, MenuHandler {
+
+ protected int selectedIndex;
+ protected String options[];
+ protected int unlockedCount;
+ protected MenuHandler handler;
+ protected MenuScreen optionsScreen = null;
+ protected MenuScreen screen = null;
+ protected boolean isOnOffToggle;
+ protected boolean m_oZ = false;
+ protected String selectedOption;
+ protected ActionMenuElement optionsScreenItems[] = null;
+ protected MenuImageView lockImage = null;
+ protected MenuTextView optionTextView = null;
+
+ public OptionsMenuElement(String text, int selectedIndex, MenuHandler handler, String options[], boolean isOnOffToggle, MenuScreen screen) {
+ this.text = text;
+ this.selectedIndex = selectedIndex;
+ this.handler = handler;
+ this.options = options;
+ if (this.options == null) this.options = new String[]{""};
+ unlockedCount = this.options.length - 1;
+ this.isOnOffToggle = isOnOffToggle;
+
+ createAllViews();
+ setSelectedOption(selectedIndex);
+
+ if (isOnOffToggle) {
+ if (selectedIndex == 1) {
+ selectedOption = getString(R.string.off);
+ } else {
+ selectedOption = getString(R.string.on);
+ }
+ } else {
+ this.screen = screen;
+ updateSelectedOption();
+ update();
+ }
+ }
+
+ @Override
+ protected void createAllViews() {
+ Context context = getGDActivity();
+
+ super.createAllViews();
+
+ textView.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ ));
+
+ optionTextView = new MenuTextView(context);
+ optionTextView.setText(selectedOption);
+ optionTextView.setTextColor(getMenuTextView().getTextColors());
+ optionTextView.setTextSize(TEXT_SIZE);
+ optionTextView.setTypeface(Global.robotoCondensedTypeface);
+ optionTextView.setLayoutParams(new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ ));
+ optionTextView.setPadding(
+ textView.getPaddingLeft(),
+ textView.getPaddingTop(),
+ textView.getPaddingRight(),
+ textView.getPaddingBottom()
+ );
+
+ lockImage = new MenuImageView(context);
+ lockImage.setImageResource(ActionMenuElement.locks[0]);
+ lockImage.setScaleType(ImageView.ScaleType.CENTER);
+ lockImage.setVisibility(View.GONE);
+
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
+ lp.setMargins(0, 0, getDp(ActionMenuElement.LOCK_IMAGE_MARGIN_RIGHT), 0);
+ lockImage.setLayoutParams(lp);
+ lockImage.setVisibility(View.GONE);
+
+ layout.addView(lockImage);
+ layout.addView(optionTextView);
+ }
+
+ private void updateSelectedOption() {
+ selectedOption = options[selectedIndex];
+ updateViewText();
+
+ if (selectedIndex > unlockedCount && !isOnOffToggle) {
+ lockImage.setVisibility(View.VISIBLE);
+ } else {
+ lockImage.setVisibility(View.GONE);
+ }
+ }
+
+ public int getUnlockedCount() {
+ return unlockedCount;
+ }
+
+ public void setUnlockedCount(int k) {
+ unlockedCount = k;
+ if (unlockedCount > options.length - 1)
+ unlockedCount = options.length - 1;
+ if (optionsScreen != null) {
+ for (int l = 0; l < optionsScreenItems.length; l++)
+ if (l > k)
+ optionsScreenItems[l].setLock(true, true);
+ else
+ optionsScreenItems[l].setLock(false, false);
+ }
+ updateSelectedOption();
+ }
+
+ public int getOptionCount() {
+ return options.length - 1;
+ }
+
+ public String[] getOptions() {
+ return options;
+ }
+
+ public void setOptions(String as[]) {
+ setOptions(as, true);
+ }
+
+ public void setOptions(String as[], boolean update) {
+ options = as;
+ if (selectedIndex > options.length - 1)
+ selectedIndex = options.length - 1;
+ if (unlockedCount > options.length - 1)
+ unlockedCount = options.length - 1;
+ updateSelectedOption();
+ if (update) update();
+ }
+
+ public int getSelectedOption() {
+ return selectedIndex;
+ }
+
+ public void setSelectedOption(int k) {
+ selectedIndex = k;
+ if (selectedIndex > options.length - 1)
+ selectedIndex = 0;
+ if (selectedIndex < 0)
+ selectedIndex = options.length - 1;
+ updateSelectedOption();
+ }
+
+ public void update() {
+ optionsScreen = new MenuScreen(text, screen);
+ optionsScreenItems = new ActionMenuElement[options.length];
+ for (int k = 0; k < optionsScreenItems.length; k++) {
+ if (k > unlockedCount) {
+ optionsScreenItems[k] = new ActionMenuElement(options[k], this);
+ optionsScreenItems[k].setLock(true, true);
+ } else {
+ optionsScreenItems[k] = new ActionMenuElement(options[k], this);
+ }
+ optionsScreen.addItem(optionsScreenItems[k]);
+ }
+ optionsScreen.setSelected(selectedIndex);
+
+ // System.gc();
+ }
+
+ public boolean _charvZ() {
+ if (m_oZ) {
+ m_oZ = false;
+ return true;
+ } else {
+ return m_oZ;
+ }
+ }
+
+ @Override
+ public void handleAction(MenuElement item) {
+ int k = 0;
+ do {
+ if (k >= optionsScreenItems.length)
+ break;
+ if (item == optionsScreenItems[k]) {
+ selectedIndex = k;
+ updateSelectedOption();
+ break;
+ }
+ k++;
+ } while (true);
+
+ handler.setCurrentMenu(screen, true);
+ handler.handleAction(this);
+ }
+
+ @Override
+ public MenuScreen getCurrentMenu() {
+ return optionsScreen;
+ }
+
+ @Override
+ public void setCurrentMenu(MenuScreen e1, boolean flag) {
+ }
+
+ @Override
+ protected void updateViewText() {
+ if (textView != null && textView instanceof MenuTextView)
+ ((MenuTextView) textView).setTextOnUiThread(getTextForView());
+ if (optionTextView != null) optionTextView.setTextOnUiThread(selectedOption);
+ }
+
+ @Override
+ public void performAction(int k) {
+ // logDebug("OptionMenuElement performAction: k = " + k);
+ switch (k) {
+ case MenuScreen.KEY_FIRE:
+ if (isOnOffToggle) {
+ selectedIndex++;
+ if (selectedIndex > 1)
+ selectedIndex = 0;
+ if (selectedIndex == 1)
+ selectedOption = getString(R.string.off);
+ else
+ selectedOption = getString(R.string.on);
+ updateViewText();
+ handler.handleAction(this);
+ return;
+ } else {
+ m_oZ = true;
+ handler.handleAction(this);
+ return;
+ }
+
+ case MenuScreen.KEY_RIGHT:
+ if (isOnOffToggle) {
+ if (selectedIndex == 1) {
+ selectedIndex = 0;
+ selectedOption = getString(R.string.on);
+ handler.handleAction(this);
+ updateViewText();
+ }
+ return;
+ }
+ selectedIndex++;
+ if (selectedIndex > options.length - 1)
+ selectedIndex = options.length - 1;
+ else
+ handler.handleAction(this);
+ updateSelectedOption();
+ return;
+
+ case MenuScreen.KEY_LEFT: // '\003'
+ if (isOnOffToggle) {
+ if (selectedIndex == 0) {
+ selectedIndex = 1;
+ selectedOption = getString(R.string.off);
+ handler.handleAction(this);
+ updateViewText();
+ }
+ return;
+ }
+ selectedIndex--;
+ if (selectedIndex < 0) {
+ selectedIndex = 0;
+ } else {
+ updateSelectedOption();
+ handler.handleAction(this);
+ }
+ updateSelectedOption();
+ break;
+ }
+ }
+
+ public void setScreen(MenuScreen screen) {
+ this.screen = screen;
+ }
+
+ @Override
+ protected String getTextForView() {
+ return text + ": ";
+ }
+
+ @Override
+ protected void onHighlightChanged() {
+ lockImage.setImageResource(ActionMenuElement.locks[isHighlighted ? 2 : 0]);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/SimpleMenuElement.java b/src/org/happysanta/gd/Menu/SimpleMenuElement.java
new file mode 100755
index 0000000..57842f5
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/SimpleMenuElement.java
@@ -0,0 +1,176 @@
+package org.happysanta.gd.Menu;
+
+// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
+// Jad home page: http://www.kpdus.com/jad.html
+// Decompiler options: packimports(3) fieldsfirst ansi
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.view.View;
+import android.view.ViewGroup;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+
+import java.util.TimerTask;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getGDView;
+
+public class SimpleMenuElement extends TimerTask
+ implements MenuElementOld {
+
+ // public static final int LINE_SPACING = 15;
+ protected static Paint gFont;
+
+ public int x;
+ public int y;
+ public int m_bI;
+ public int m_eI;
+ public int m_dI;
+ public int m_gotoI;
+ public int m_nullI;
+ public int m_longI;
+ public int m_fI;
+ int m_cI;
+ // GDActivity activity;
+ protected String text;
+ protected MenuScreen m_we;
+ protected MenuHandler m_hc;
+ protected Paint font;
+ protected boolean isPressed = false;
+ protected MenuTextView textView;
+
+ /*static {
+ gFont = ActionMenuElement.getGFont();
+ }*/
+
+ public SimpleMenuElement() {
+ init();
+ }
+
+ public SimpleMenuElement(int k) {
+ m_cI = k;
+ font = gFont;
+ }
+
+ public SimpleMenuElement(String s, MenuScreen e1, MenuHandler c1) {
+ text = s + ">";
+ m_we = e1;
+ m_hc = c1;
+ font = gFont;
+
+ textView = new MenuTextView(getGDActivity());
+ textView.setText(text);
+ textView.setTextColor(0xff000000);
+ // textView.setTextColor(R.drawable.menu_item_color);
+ textView.setTypeface(Global.robotoCondensedTypeface);
+ textView.setTextSize(20);
+ textView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ ));
+ }
+
+ public void init() {
+ x = y = m_bI = 0;
+ m_eI = m_dI = m_gotoI = 0;
+ m_nullI = m_longI = m_fI = 0;
+ }
+
+ @Override
+ public View getView() {
+ return textView;
+ }
+
+ @Override
+ public void run() {
+ getGDView()._tryIV(m_cI);
+ }
+
+ @Override
+ public void setText(String s) {
+ text = s + ">";
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ @Override
+ public boolean isSelectable() {
+ return true;
+ }
+
+ @Override
+ public void performAction(int k) {
+ /*switch (k) {
+ case MenuScreen.KEY_FIRE:
+ case MenuScreen.KEY_RIGHT:
+ m_hc.handleAction(this);
+ m_we.setNavTarget(m_hc.getCurrentMenu());
+ m_hc.setCurrentMenu(m_we, false);
+ // fall through
+
+ case 3: // '\003'
+ default:
+ return;
+ }*/
+ }
+
+ /* public void _aeV(MenuScreen e1) {
+ screen = e1;
+ } */
+
+ @Override
+ public void draw(Canvas g, int y, int x) {
+ // if (isPressed)
+ // setPressedColor();
+ g.drawText(text, x, y - font.ascent(), font);
+ // if (isPressed)
+ // setNormalColor();
+ }
+
+ @Override
+ public int getLineSpacing() {
+ return ActionMenuElement.LINE_SPACING;
+ }
+
+ @Override
+ public void setFont(Paint font) {
+ this.font = font;
+ }
+
+ @Override
+ public int getHeight() {
+ return Math.round(font.descent() - font.ascent());
+ }
+
+ @Override
+ public int getFirstLineHeight() {
+ return getHeight();
+ }
+
+ /* @Override
+ public int getHeight() {
+ return getHeight() + getLineSpacing();
+ } */
+
+ @Override
+ public int getXOffset() {
+ return ActionMenuElement.X_OFFSET;
+ }
+
+ @Override
+ public void setPressed(boolean flag) {
+ isPressed = flag;
+ }
+
+ /*protected void setPressedColor() {
+ font.setColor(ActionMenuElement.PRESSED_COLOR);
+ }
+
+ protected void setNormalColor() {
+ font.setColor(ActionMenuElement.NORMAL_COLOR);
+ }*/
+
+}
diff --git a/src/org/happysanta/gd/Menu/SimpleMenuElementNew.java b/src/org/happysanta/gd/Menu/SimpleMenuElementNew.java
new file mode 100644
index 0000000..474a6ad
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/SimpleMenuElementNew.java
@@ -0,0 +1,77 @@
+package org.happysanta.gd.Menu;
+
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class SimpleMenuElementNew extends ClickableMenuElement
+ implements MenuElement {
+
+ // protected static Paint gFont;
+
+ public int x;
+ public int y;
+ /* public int m_bI;
+ public int m_eI;
+ public int m_dI;
+ public int m_gotoI;
+ public int m_nullI;
+ public int m_longI;
+ public int m_fI;
+ int m_cI; */
+ protected MenuScreen screen;
+ protected MenuHandler handler;
+ // protected Paint font;
+ // protected boolean isPressed = false;
+
+ /* static {
+ gFont = ActionMenuElement.getGFont();
+ } */
+
+ /* public SimpleMenuElementNew() {
+ init();
+ }
+
+ public SimpleMenuElementNew(int k) {
+ m_cI = k;
+ // font = gFont;
+ } */
+
+ public SimpleMenuElementNew(String text, MenuScreen screen, MenuHandler handler) {
+ this.text = text + ">";
+ this.screen = screen;
+ this.handler = handler;
+
+ createAllViews();
+
+ // textView = createAllViews();
+ }
+
+ /* public void init() {
+ x = y = m_bI = 0;
+ m_eI = m_dI = m_gotoI = 0;
+ m_nullI = m_longI = m_fI = 0;
+ } */
+
+ @Override
+ public void setText(String s) {
+ super.setText(s + ">");
+ }
+
+ // @Override
+ public void performAction(int k) {
+ logDebug("SimpleMenuElementNew performAction k = " + k);
+
+ switch (k) {
+ case MenuScreen.KEY_FIRE:
+ case MenuScreen.KEY_RIGHT:
+ handler.handleAction(this);
+ screen.setNavTarget(handler.getCurrentMenu());
+ handler.setCurrentMenu(screen, false);
+ break;
+ }
+ }
+
+ /* public void _aeV(MenuScreen e1) {
+ screen = e1;
+ } */
+
+}
diff --git a/src/org/happysanta/gd/Menu/TextMenuElement.java b/src/org/happysanta/gd/Menu/TextMenuElement.java
new file mode 100755
index 0000000..7485389
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/TextMenuElement.java
@@ -0,0 +1,80 @@
+package org.happysanta.gd.Menu;
+
+// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
+// Jad home page: http://www.kpdus.com/jad.html
+// Decompiler options: packimports(3) fieldsfirst ansi
+
+import android.content.Context;
+import android.text.Html;
+import android.text.Spanned;
+import android.text.SpannedString;
+import android.text.util.Linkify;
+import android.view.View;
+import android.view.ViewGroup;
+import org.happysanta.gd.Menu.Views.MenuTextView;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class TextMenuElement
+ implements MenuElement {
+
+ protected static final int TEXT_SIZE = 15;
+ protected static final int TEXT_COLOR = 0xff000000;
+
+ protected Spanned spanned;
+ protected MenuTextView textView;
+
+ public TextMenuElement(String text) {
+ this.spanned = SpannedString.valueOf(text);
+ textView = createTextView();
+ }
+
+ public TextMenuElement(Spanned text) {
+ this.spanned = text;
+ textView = createTextView();
+ }
+
+ protected MenuTextView createTextView() {
+ Context activity = getGDActivity();
+
+ MenuTextView textView = new MenuTextView(activity);
+ textView.setText(spanned);
+ textView.setTextColor(TEXT_COLOR);
+ textView.setTextSize(TEXT_SIZE);
+ textView.setLineSpacing(0f, 1.5f);
+ textView.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ ));
+
+ Linkify.addLinks(textView, Linkify.WEB_URLS);
+ textView.setLinksClickable(true);
+
+ return textView;
+ }
+
+ @Override
+ public View getView() {
+ return textView;
+ }
+
+ public String getText() {
+ return spanned.toString();
+ }
+
+ @Override
+ public void setText(String text) {
+ this.spanned = Html.fromHtml(text);
+ textView.setTextOnUiThread(spanned);
+ }
+
+ @Override
+ public boolean isSelectable() {
+ return false;
+ }
+
+ @Override
+ public void performAction(int k) {
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/LevelNameLeadingMarginSpan2.java b/src/org/happysanta/gd/Menu/Views/LevelNameLeadingMarginSpan2.java
new file mode 100644
index 0000000..09c744d
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/LevelNameLeadingMarginSpan2.java
@@ -0,0 +1,38 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.text.Layout;
+import android.text.style.LeadingMarginSpan;
+
+public class LevelNameLeadingMarginSpan2 implements LeadingMarginSpan.LeadingMarginSpan2 {
+
+ private int margin;
+ private int lines;
+
+ public LevelNameLeadingMarginSpan2(int lines, int margin) {
+ this.margin = margin;
+ this.lines = lines;
+ }
+
+ @Override
+ public int getLeadingMargin(boolean first) {
+ if (first) {
+ return margin;
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
+ int top, int baseline, int bottom, CharSequence text,
+ int start, int end, boolean first, Layout layout) {
+ }
+
+ @Override
+ public int getLeadingMarginLineCount() {
+ return lines;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuHelmetView.java b/src/org/happysanta/gd/Menu/Views/MenuHelmetView.java
new file mode 100644
index 0000000..bb2a37a
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuHelmetView.java
@@ -0,0 +1,111 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+import org.happysanta.gd.Game.Bitmap;
+import org.happysanta.gd.Global;
+
+import static org.happysanta.gd.Helpers.getDp;
+import static org.happysanta.gd.Helpers.isSDK11OrHigher;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class MenuHelmetView extends View {
+
+ protected static final int WIDTH = 8;
+ protected static final int HEIGHT = 8;
+ /*protected static final int PADDING_LEFT = 0;
+ protected static final int PADDING_TOP = 5;
+ protected static final int PADDING_RIGHT = 5;
+ protected static final int PADDING_BOTTOM = 0;*/
+
+ protected static int angle = 0;
+ protected static long angleLastMs = 0;
+ protected static final int angleInterval = 50;
+ protected static final int angleDelta = 10;
+
+ protected boolean show = false;
+ protected boolean _setMeasuredHeight = false;
+ protected Bitmap helmet = Bitmap.get(Bitmap.HELMET);
+ protected static MenuHelmetView lastActive = null;
+
+ public static void clearStaticFields() {
+ lastActive = null;
+ angle = 0;
+ angleLastMs = 0;
+ }
+
+ public MenuHelmetView(Context context) {
+ super(context);
+ }
+
+ public MenuHelmetView(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ canvas.save();
+ canvas.scale(Global.density, Global.density);
+
+ drawHelmet(canvas);
+
+ canvas.restore();
+ invalidate();
+ }
+
+ protected void drawHelmet(Canvas canvas) {
+ if (show) {
+ long ms = System.currentTimeMillis();
+ if (angleLastMs == 0 || ms - angleLastMs >= angleInterval) {
+ angle += angleDelta;
+ if (angle >= 360) angle -= 360;
+ angleLastMs = ms;
+ }
+
+ int y = getScaledHeight() / 2 - helmet.getHeightDp() / 2;
+
+ canvas.save();
+ canvas.rotate(angle, helmet.getWidthDp() / 2, y + helmet.getHeightDp() / 2);
+ canvas.drawBitmap(helmet.bitmap, new Rect(0, 0, helmet.getWidth(), helmet.getHeight()), new RectF(0, y, helmet.getWidthDp(), y + helmet.getHeightDp()), null);
+ canvas.restore();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(getDp(WIDTH * 2.2f));
+ int height = heightMeasureSpec;
+ if (_setMeasuredHeight)
+ height = MeasureSpec.getSize(getDp(HEIGHT * 2.2f));
+ else if (!isSDK11OrHigher()) {
+ height = MeasureSpec.getSize(getDp(HEIGHT * 4.5f));
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ public void setShow(boolean show) {
+ setShow(show, true);
+ }
+
+ public void setShow(boolean show, boolean checkLast) {
+ if (checkLast && lastActive != null) {
+ lastActive.setShow(false, false);
+ }
+ this.show = show;
+ lastActive = this;
+ }
+
+ protected int getScaledHeight() {
+ return Math.round(getHeight() / Global.density);
+ }
+
+ public void setMeasuredHeight(boolean setMeasuredHeight) {
+ this._setMeasuredHeight = setMeasuredHeight;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuImageView.java b/src/org/happysanta/gd/Menu/Views/MenuImageView.java
new file mode 100644
index 0000000..1ef3f70
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuImageView.java
@@ -0,0 +1,34 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.content.Context;
+import android.widget.ImageView;
+
+import static org.happysanta.gd.Helpers.runOnUiThread;
+
+public class MenuImageView extends ImageView {
+
+ public MenuImageView(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void setImageResource(final int resid) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuImageView.super.setImageResource(resid);
+ }
+ });
+ }
+
+ @Override
+ public void setVisibility(final int visibility) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuImageView.super.setVisibility(visibility);
+ }
+ });
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuLinearLayout.java b/src/org/happysanta/gd/Menu/Views/MenuLinearLayout.java
new file mode 100644
index 0000000..98f665e
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuLinearLayout.java
@@ -0,0 +1,68 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import static org.happysanta.gd.Helpers.runOnUiThread;
+
+public class MenuLinearLayout extends LinearLayout {
+
+ boolean interceptTouchEvents = false;
+
+ public MenuLinearLayout(Context context) {
+ super(context);
+ }
+
+ public MenuLinearLayout(Context context, boolean interceptTouchEvents) {
+ super(context);
+ this.interceptTouchEvents = interceptTouchEvents;
+ }
+
+ @Override
+ public void removeAllViews() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuLinearLayout.super.removeAllViews();
+ }
+ });
+ }
+
+ @Override
+ public void setVisibility(final int visibility) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuLinearLayout.super.setVisibility(visibility);
+ }
+ });
+ }
+
+ @Override
+ public void addView(final View view) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuLinearLayout.super.addView(view);
+ }
+ });
+ }
+
+ @Override
+ public void setPadding(final int left, final int top, final int right, final int bottom) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuLinearLayout.super.setPadding(left, top, right, bottom);
+ }
+ });
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent evt) {
+ return interceptTouchEvents;
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuRelativeLayout.java b/src/org/happysanta/gd/Menu/Views/MenuRelativeLayout.java
new file mode 100644
index 0000000..3e5e0d2
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuRelativeLayout.java
@@ -0,0 +1,55 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import static org.happysanta.gd.Helpers.runOnUiThread;
+
+public class MenuRelativeLayout extends RelativeLayout {
+
+ public MenuRelativeLayout(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void removeAllViews() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuRelativeLayout.super.removeAllViews();
+ }
+ });
+ }
+
+ @Override
+ public void setVisibility(final int visibility) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuRelativeLayout.super.setVisibility(visibility);
+ }
+ });
+ }
+
+ @Override
+ public void addView(final View view) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuRelativeLayout.super.addView(view);
+ }
+ });
+ }
+
+ @Override
+ public void setPadding(final int left, final int top, final int right, final int bottom) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuRelativeLayout.super.setPadding(left, top, right, bottom);
+ }
+ });
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuTextView.java b/src/org/happysanta/gd/Menu/Views/MenuTextView.java
new file mode 100644
index 0000000..4b48f5f
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuTextView.java
@@ -0,0 +1,73 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.widget.TextView;
+
+import static org.happysanta.gd.Helpers.runOnUiThread;
+
+public class MenuTextView extends TextView {
+
+ protected boolean isAttached = false;
+
+ public MenuTextView(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ isAttached = true;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ isAttached = false;
+ }
+
+ @Override
+ public boolean isAttachedToWindow() {
+ return isAttached;
+ }
+
+ public void setTextOnUiThread(final CharSequence sequence) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuTextView.super.setText(sequence);
+ }
+ });
+ }
+
+ @Override
+ public void setTextSize(final float size) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuTextView.super.setTextSize(size);
+ }
+ });
+ }
+
+ @Override
+ public void setTypeface(final Typeface typeface) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuTextView.super.setTypeface(typeface);
+ }
+ });
+ }
+
+ @Override
+ public void setVisibility(final int visibility) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ MenuTextView.super.setVisibility(visibility);
+ }
+ });
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuTitleLinearLayout.java b/src/org/happysanta/gd/Menu/Views/MenuTitleLinearLayout.java
new file mode 100644
index 0000000..5c3f790
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuTitleLinearLayout.java
@@ -0,0 +1,39 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.app.Activity;
+import android.widget.RelativeLayout;
+
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class MenuTitleLinearLayout extends RelativeLayout {
+
+ private Callback onSizeChangedCallback = null;
+
+ public MenuTitleLinearLayout(Activity activity) {
+ super(activity);
+ }
+
+ @Override
+ public void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ if (onSizeChangedCallback != null) {
+ onSizeChangedCallback.run(w, h, oldw, oldh);
+ }
+ }
+
+ /*public void forceInvokeOnSizeChangedCallback() {
+ if (onSizeChangedCallback != null) {
+ onSizeChangedCallback.run(getWidth(), getHeight(), 0, 0);
+ }
+ }*/
+
+ public void setOnSizeChangedCallback(Callback callback) {
+ onSizeChangedCallback = callback;
+ }
+
+ public interface Callback {
+ public abstract void run(int w, int h, int oldw, int oldh);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/MenuView.java b/src/org/happysanta/gd/Menu/Views/MenuView.java
new file mode 100644
index 0000000..ba47071
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/MenuView.java
@@ -0,0 +1,12 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.view.View;
+import org.happysanta.gd.GDActivity;
+
+public class MenuView extends View {
+
+ public MenuView(GDActivity activity) {
+ super(activity);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Menu/Views/ObservableScrollView.java b/src/org/happysanta/gd/Menu/Views/ObservableScrollView.java
new file mode 100644
index 0000000..5801928
--- /dev/null
+++ b/src/org/happysanta/gd/Menu/Views/ObservableScrollView.java
@@ -0,0 +1,31 @@
+package org.happysanta.gd.Menu.Views;
+
+import android.content.Context;
+import android.widget.ScrollView;
+
+public class ObservableScrollView
+ extends ScrollView {
+
+ private OnScrollListener scrollListener = null;
+
+ public ObservableScrollView(Context context) {
+ super(context);
+ }
+
+ public void setOnScrollListener(OnScrollListener scrollListener) {
+ this.scrollListener = scrollListener;
+ }
+
+ @Override
+ protected void onScrollChanged(int x, int y, int oldx, int oldy) {
+ super.onScrollChanged(x, y, oldx, oldy);
+ if (scrollListener != null) {
+ scrollListener.onScroll(this, x, y, oldx, oldy);
+ }
+ }
+
+ public interface OnScrollListener {
+ public abstract void onScroll(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Settings.java b/src/org/happysanta/gd/Settings.java
new file mode 100644
index 0000000..93857ca
--- /dev/null
+++ b/src/org/happysanta/gd/Settings.java
@@ -0,0 +1,215 @@
+package org.happysanta.gd;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Build;
+import org.happysanta.gd.API.API;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class Settings {
+
+ private static final String LEVEL_ID = "level_id";
+ private static final int LEVEL_ID_DEFAULT = 0;
+
+ private static final String PERSPECTIVE_ENABLED = "perspective_enabled";
+ private static final boolean PERSPECTIVE_ENABLED_DEFAULT = true;
+
+ private static final String SHADOWS_ENABLED = "shadows_enabled";
+ private static final boolean SHADOWS_ENABLED_DEFAULT = true;
+
+ private static final String DRIVER_SPRITE_ENABLED = "driver_sprite_enabled";
+ private static final boolean DRIVER_SPRITE_ENABLED_DEFAULT = true;
+
+ private static final String BIKE_SPRITE_ENABLED = "bike_sprite_enabled";
+ private static final boolean BIKE_SPRITE_ENABLED_DEFAULT = true;
+
+ private static final String INPUT_OPTION = "input_option";
+ private static final int INPUT_OPTION_DEFAULT = 0;
+
+ private static final String LOOK_AHEAD_ENABLED = "look_ahead_enabled";
+ private static final boolean LOOK_AHEAD_ENABLED_DEFAULT = true;
+
+ private static final String VIBRATE_ENABLED = "vibrate_enabled";
+ private static final boolean VIBRATE_ENABLED_DEFAULT = true;
+
+ private static final String KEYBOARD_IN_MENU_ENABLED = "keyboard_enabled";
+ private static final boolean KEYBOARD_IN_MENU_ENABLED_DEFAULT = true;
+
+ private static final String LAST_SEND_STATS = "last_send_stats";
+ private static final long LAST_SEND_STATS_DEFAULT = 0;
+
+ private static final String NAME = "name";
+ public static final String NAME_DEFAULT = "AAA";
+ public static final byte[] NAME_CHARS_DEFALUT = new byte[]{65, 65, 65};
+
+ private static final String LEVELS_SORT = "level_sort"; // in download list
+ private static final int LEVELS_SORT_DEFAULT = 0;
+
+ private static SharedPreferences preferences;
+
+ static {
+ preferences = getGDActivity().getSharedPreferences("GDSettings", Context.MODE_PRIVATE);
+ }
+
+ public static void resetAll() {
+ setPerspectiveEnabled(PERSPECTIVE_ENABLED_DEFAULT);
+ setShadowsEnabled(SHADOWS_ENABLED_DEFAULT);
+ setDriverSpriteEnabled(DRIVER_SPRITE_ENABLED_DEFAULT);
+ setBikeSpriteEnabled(BIKE_SPRITE_ENABLED_DEFAULT);
+ setLookAheadEnabled(LOOK_AHEAD_ENABLED_DEFAULT);
+ setVibrateOnTouchEnabled(VIBRATE_ENABLED_DEFAULT);
+ setKeyboardInMenuEnabled(KEYBOARD_IN_MENU_ENABLED_DEFAULT);
+ setInputOption(INPUT_OPTION_DEFAULT);
+ setLevelsSort(LEVELS_SORT_DEFAULT);
+ setName(NAME_CHARS_DEFALUT);
+ }
+
+ public static long getLevelId() {
+ return preferences.getLong(LEVEL_ID, LEVEL_ID_DEFAULT);
+ }
+
+ public static void setLevelId(long levelId) {
+ setLong(LEVEL_ID, levelId);
+ }
+
+ public static boolean isPerspectiveEnabled() {
+ return preferences.getBoolean(PERSPECTIVE_ENABLED, PERSPECTIVE_ENABLED_DEFAULT);
+ }
+
+ public static void setPerspectiveEnabled(boolean enabled) {
+ setBoolean(PERSPECTIVE_ENABLED, enabled);
+ }
+
+ public static boolean isShadowsEnabled() {
+ return preferences.getBoolean(SHADOWS_ENABLED, SHADOWS_ENABLED_DEFAULT);
+ }
+
+ public static void setShadowsEnabled(boolean enabled) {
+ setBoolean(SHADOWS_ENABLED, enabled);
+ }
+
+ public static boolean isDriverSpriteEnabled() {
+ return preferences.getBoolean(DRIVER_SPRITE_ENABLED, DRIVER_SPRITE_ENABLED_DEFAULT);
+ }
+
+ public static void setDriverSpriteEnabled(boolean enabled) {
+ setBoolean(DRIVER_SPRITE_ENABLED, enabled);
+ }
+
+ public static boolean isBikeSpriteEnabled() {
+ return preferences.getBoolean(BIKE_SPRITE_ENABLED, BIKE_SPRITE_ENABLED_DEFAULT);
+ }
+
+ public static void setBikeSpriteEnabled(boolean enabled) {
+ setBoolean(BIKE_SPRITE_ENABLED, enabled);
+ }
+
+ public static boolean isLookAheadEnabled() {
+ return preferences.getBoolean(LOOK_AHEAD_ENABLED, LOOK_AHEAD_ENABLED_DEFAULT);
+ }
+
+ public static void setLookAheadEnabled(boolean enabled) {
+ setBoolean(LOOK_AHEAD_ENABLED, enabled);
+ }
+
+ public static boolean isKeyboardInMenuEnabled() {
+ return preferences.getBoolean(KEYBOARD_IN_MENU_ENABLED, KEYBOARD_IN_MENU_ENABLED_DEFAULT);
+ }
+
+ public static void setKeyboardInMenuEnabled(boolean enabled) {
+ setBoolean(KEYBOARD_IN_MENU_ENABLED, enabled);
+ }
+
+ public static boolean isVibrateOnTouchEnabled() {
+ return preferences.getBoolean(VIBRATE_ENABLED, VIBRATE_ENABLED_DEFAULT);
+ }
+
+ public static void setVibrateOnTouchEnabled(boolean enabled) {
+ setBoolean(VIBRATE_ENABLED, enabled);
+ }
+
+ public static int getInputOption() {
+ return preferences.getInt(INPUT_OPTION, INPUT_OPTION_DEFAULT);
+ }
+
+ public static void setInputOption(int value) {
+ setInt(INPUT_OPTION, value);
+ }
+
+ public static long getLastSendStats() {
+ return preferences.getLong(LAST_SEND_STATS, LAST_SEND_STATS_DEFAULT);
+ }
+
+ public static void setLastSendStats(long value) {
+ setLong(LAST_SEND_STATS, value);
+ }
+
+ public static API.LevelsSortType getLevelsSort() {
+ return API.getSortTypeById(preferences.getInt(LEVELS_SORT, LEVELS_SORT_DEFAULT));
+ }
+
+ public static void setLevelsSort(API.LevelsSortType type) {
+ setInt(LEVELS_SORT, API.getIdBySortType(type));
+ }
+
+ public static void setLevelsSort(int type) {
+ setInt(LEVELS_SORT, type);
+ }
+
+ public static byte[] getName() {
+ String name = preferences.getString(NAME, NAME_DEFAULT);
+ if (name.length() < 3) {
+ name = NAME_DEFAULT;
+ }
+ return new byte[]{
+ (byte) name.charAt(0),
+ (byte) name.charAt(1),
+ (byte) name.charAt(2)
+ };
+ }
+
+ public static void setName(byte[] chars) {
+ if (chars.length < 3) {
+ setString(NAME, NAME_DEFAULT);
+ } else {
+ String name = "";
+ for (int i = 0; i < 3; i++) {
+ name += String.valueOf((char) chars[i]);
+ }
+ setString(NAME, name);
+ }
+ }
+
+ private static void setLong(String key, long value) {
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putLong(key, value);
+ editorApply(editor);
+ }
+
+ private static void setInt(String key, int value) {
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putInt(key, value);
+ editorApply(editor);
+ }
+
+ private static void setBoolean(String key, boolean value) {
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(key, value);
+ editorApply(editor);
+ }
+
+ private static void setString(String key, String value) {
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(key, value);
+ editorApply(editor);
+ }
+
+ private static void editorApply(SharedPreferences.Editor editor) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD)
+ editor.apply();
+ else
+ editor.commit();
+ }
+
+}
diff --git a/src/org/happysanta/gd/Storage/HighScores.java b/src/org/happysanta/gd/Storage/HighScores.java
new file mode 100644
index 0000000..e3678c9
--- /dev/null
+++ b/src/org/happysanta/gd/Storage/HighScores.java
@@ -0,0 +1,152 @@
+package org.happysanta.gd.Storage;
+
+import org.happysanta.gd.Settings;
+
+public class HighScores {
+
+ private static final long MAX_TIME = 0xffff28L;
+
+ private long id;
+ private long levelId = 0;
+ private int level = 0;
+ private int track = 0;
+ private long[][] times = new long[4][3];
+ private String[][] names = new String[4][3];
+
+ public HighScores() {
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public long getLevelId() {
+ return levelId;
+ }
+
+ public void setLevelId(long levelId) {
+ this.levelId = levelId;
+ }
+
+ public int getLevel() {
+ return level;
+ }
+
+ public void setLevel(int level) {
+ this.level = level;
+ }
+
+ public long getTrack() {
+ return track;
+ }
+
+ public void setTrack(int track) {
+ this.track = track;
+ }
+
+ public long getTime(int league, int place) {
+ return times[league][place];
+ }
+
+ public void setTime(int league, int place, long value) {
+ times[league][place] = value;
+ }
+
+ public String getName(int league, int place) {
+ return names[league][place];
+ }
+
+ public void setName(int league, int place, String value) {
+ names[league][place] = value;
+ }
+
+ public String[] getScores(int league) {
+ String[] scores = new String[3];
+ for (int places = 0; places < 3; places++) {
+ if (times[league][places] != 0L) {
+ int k = (int) times[league][places] / 100;
+ int l = (int) times[league][places] % 100;
+ scores[places] = names[league][places] + " ";
+ if (k / 60 < 10)
+ scores[places] += " 0" + k / 60;
+ else
+ scores[places] += " " + k / 60;
+ if (k % 60 < 10)
+ scores[places] += ":0" + k % 60;
+ else
+ scores[places] += ":" + k % 60;
+ if (l < 10)
+ scores[places] += ".0" + l;
+ else
+ scores[places] += "." + l;
+ } else {
+ scores[places] = null;
+ }
+ }
+
+ return scores;
+ }
+
+ public int getPlace(int league, long time) {
+ for (int place = 0; place < 3; place++)
+ if (times[league][place] > time || times[league][place] == 0L)
+ return place;
+
+ return 3;
+ }
+
+ private void clearTimes() {
+ for (int leagues = 0; leagues < 4; leagues++) {
+ for (int places = 0; places < 3; places++)
+ times[leagues][places] = 0L;
+ }
+ }
+
+ public void saveHighScore(int league, String name, long time) {
+ name = trimName(name);
+ int place;
+ if ((place = getPlace(league, time)) != 3) {
+ if (time > MAX_TIME)
+ time = MAX_TIME;
+ moveScoreEntries(league, place);
+
+ times[league][place] = time;
+ names[league][place] = name;
+ }
+ }
+
+ private void moveScoreEntries(int league, int i) {
+ for (int place = 2; place > i; place--) {
+ times[league][place] = times[league][place - 1];
+ names[league][place] = names[league][place - 1];
+ }
+ }
+
+ private static String trimName(String name) {
+ if (name.length() > 3)
+ name = name.substring(0, 3);
+ else if (name.length() < 3)
+ name = Settings.NAME_DEFAULT;
+
+ return name.toUpperCase();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("Storage.HighScores {");
+
+ s.append("id: " + id + ", ");
+ s.append("level_id: " + levelId + ", ");
+ s.append("level: " + level + ", ");
+ s.append("track: " + track);
+
+ s.append("}");
+ return s.toString();
+ }
+
+}
diff --git a/src/org/happysanta/gd/Storage/Level.java b/src/org/happysanta/gd/Storage/Level.java
new file mode 100644
index 0000000..3030b7b
--- /dev/null
+++ b/src/org/happysanta/gd/Storage/Level.java
@@ -0,0 +1,300 @@
+package org.happysanta.gd.Storage;
+
+import android.text.format.DateUtils;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+
+public class Level {
+
+ private long id = 0;
+ private String name;
+ private String author;
+ private int[] count;
+ private int size = 0;
+ private long addedTs = 0;
+ private long installedTs = 0;
+ private boolean _isDefault = false;
+ private long apiId = 0;
+ private int[] unlocked;
+ private int selectedTrack = 0;
+ private int selectedLevel = 0;
+ private int selectedLeague = 0;
+ private int unlockedLevels = 0;
+ private int unlockedLeagues = 0;
+
+ public Level() {
+ count = new int[3];
+ unlocked = new int[3];
+ }
+
+ public Level(long id, String name, String author, int countEasy, int countMedium, int countHard, int addedTs, int size, long apiId) {
+ this(id, name, author, countEasy, countMedium, countHard, addedTs, size, apiId, 0, 0, 0);
+ }
+
+ public Level(long id, String name, String author, int countEasy, int countMedium, int countHard, int addedTs, int size, long apiId, int unlockedEasy, int unlockedMedium, int unlockedHard) {
+ this.id = id;
+ this.name = name;
+ this.author = author;
+ this.count = new int[]{
+ countEasy, countMedium, countHard
+ };
+ this.addedTs = addedTs;
+ this.size = size;
+ this.apiId = apiId;
+ this.unlocked = new int[]{
+ unlockedEasy, unlockedMedium, unlockedHard
+ };
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public long getAnyId() {
+ return id > 0 ? id : apiId;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public int getCountEasy() {
+ return this.count[0];
+ }
+
+ public int getCountMedium() {
+ return this.count[1];
+ }
+
+ public int getCountHard() {
+ return this.count[2];
+ }
+
+ public int getCount(int level) {
+ return this.count[level];
+ }
+
+ public void setCountEasy(int count) {
+ this.count[0] = count;
+ }
+
+ public void setCountMedium(int count) {
+ this.count[1] = count;
+ }
+
+ public void setCountHard(int count) {
+ this.count[2] = count;
+ }
+
+ public void setCount(int easy, int medium, int hard) {
+ setCountEasy(easy);
+ setCountMedium(medium);
+ setCountHard(hard);
+ }
+
+ public long getAddedTs() {
+ return addedTs;
+ }
+
+ public void setAddedTs(long ts) {
+ addedTs = ts;
+ }
+
+ public long getInstalledTs() {
+ return installedTs;
+ }
+
+ public void setInstalledTs(long ts) {
+ installedTs = ts;
+ }
+
+ public void setIsDefault(boolean isDefault) {
+ this._isDefault = isDefault;
+ }
+
+ public boolean isDefault() {
+ return _isDefault;
+ }
+
+ public long getApiId() {
+ return apiId;
+ }
+
+ public void setApiId(long apiId) {
+ this.apiId = apiId;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ public boolean isInstalled() {
+ return id > 0;
+ }
+
+ public String getSizeKb() {
+ return String.valueOf(Math.round((size / 1024f) * 100f) / 100f);
+ }
+
+ public String getShortAddedDate() {
+ return getShortDate(addedTs);
+ }
+
+ public String getFullAddedDate() {
+ return getFullDate(addedTs);
+ }
+
+ public String getShortInstalledDate() {
+ return getShortDate(installedTs);
+ }
+
+ public String getFullInstalledDate() {
+ return getFullDate(installedTs);
+ }
+
+ public int getUnlockedEasy() {
+ return this.unlocked[0];
+ }
+
+ public int getUnlockedMedium() {
+ return this.unlocked[1];
+ }
+
+ public int getUnlockedHard() {
+ return this.unlocked[2];
+ }
+
+ public int getUnlocked(int level) {
+ //if (level < 3)
+ return unlocked[level];
+
+ //logDebug("Level.getUnlocked: level = " + level + ", out of bounds");
+ //return 0;
+ }
+
+ public int[] getUnlockedAll() {
+ return unlocked;
+ }
+
+ public void setUnlockedEasy(int unlocked) {
+ this.unlocked[0] = unlocked;
+ }
+
+ public void setUnlockedMedium(int unlocked) {
+ this.unlocked[1] = unlocked;
+ }
+
+ public void setUnlockedHard(int unlocked) {
+ this.unlocked[2] = unlocked;
+ }
+
+ public void setUnlocked(int easy, int medium, int hard) {
+ setUnlockedEasy(easy);
+ setUnlockedMedium(medium);
+ setUnlockedHard(hard);
+ }
+
+ public void setUnlocked(int level, int value) {
+ unlocked[level] = value;
+ }
+
+ public int getSelectedTrack() {
+ return selectedTrack;
+ }
+
+ public int getSelectedLevel() {
+ return selectedLevel;
+ }
+
+ public int getSelectedLeague() {
+ return selectedLeague;
+ }
+
+ public void setSelectedTrack(int selectedTrack) {
+ this.selectedTrack = selectedTrack;
+ }
+
+ public void setSelectedLevel(int selectedLevel) {
+ this.selectedLevel = selectedLevel;
+ }
+
+ public void setSelectedLeague(int selectedLeague) {
+ this.selectedLeague = selectedLeague;
+ }
+
+ public int getUnlockedLevels() {
+ return unlockedLevels;
+ }
+
+ public int getUnlockedLeagues() {
+ return unlockedLeagues;
+ }
+
+ public void setUnlockedLevels(int unlockedLevels) {
+ this.unlockedLevels = unlockedLevels;
+ }
+
+ public void setUnlockedLeagues(int unlockedLeagues) {
+ this.unlockedLeagues = unlockedLeagues;
+ }
+
+ public boolean isSettingsClear() {
+ return unlockedLevels == 0
+ && unlocked[0] == 0
+ && unlocked[1] == 0
+ && unlocked[2] == 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("Storage.Level {");
+
+ s.append("id: " + id + ", ");
+ s.append("name: \"" + name + "\", ");
+ s.append("author: \"" + author + "\", ");
+ s.append("count: " + count[0] + "/" + count[1] + "/" + count[2] + ", ");
+ s.append("added_ts: " + addedTs + ", ");
+ s.append("installed_ts: " + installedTs + ", ");
+ s.append("default: " + (_isDefault ? 1 : 0) + ", ");
+ s.append("api_id: " + apiId + ", ");
+ s.append("unlocked: " + unlocked[0] + "/" + unlocked[1] + "/" + unlocked[2] + ", ");
+ s.append("selected_track: " + selectedTrack + ", ");
+ s.append("selected_level: " + selectedLevel + ", ");
+ s.append("selected_league: " + selectedLeague + ", ");
+ s.append("unlocked_levels: " + unlockedLevels + ", ");
+ s.append("unlocked_leagues: " + unlockedLeagues);
+
+ s.append("}");
+ return s.toString();
+ }
+
+ private static String getShortDate(long date) {
+ return DateUtils.formatDateTime(getGDActivity(), date * 1000L, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH);
+ }
+
+ private static String getFullDate(long date) {
+ return DateUtils.formatDateTime(getGDActivity(), date * 1000L, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR);
+ }
+
+}
diff --git a/src/org/happysanta/gd/Storage/LevelsDataSource.java b/src/org/happysanta/gd/Storage/LevelsDataSource.java
new file mode 100644
index 0000000..40e7f14
--- /dev/null
+++ b/src/org/happysanta/gd/Storage/LevelsDataSource.java
@@ -0,0 +1,293 @@
+package org.happysanta.gd.Storage;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class LevelsDataSource {
+
+ private SQLiteDatabase db;
+ private LevelsSQLiteOpenHelper dbHelper;
+
+ public LevelsDataSource(Context context) {
+ dbHelper = new LevelsSQLiteOpenHelper(context);
+ }
+
+ public synchronized void open() throws SQLException {
+ db = dbHelper.getWritableDatabase();
+ }
+
+ public synchronized void close() {
+ dbHelper.close();
+ }
+
+ public synchronized Level createLevel(String name, String author, int countEasy, int countMedium, int countHard, long addedTs, long installedTs, boolean isDefault, long apiId) {
+ ContentValues values = new ContentValues();
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_NAME, name);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_AUTHOR, author);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_COUNT_EASY, countEasy);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_COUNT_MEDIUM, countMedium);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_COUNT_HARD, countHard);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_ADDED, addedTs);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_INSTALLED, installedTs);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_IS_DEFAULT, isDefault ? 1 : 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_API_ID, apiId);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_EASY, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_MEDIUM, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_HARD, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_TRACK, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEVEL, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEAGUE, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEVELS, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEAGUES, 0);
+
+ long insertId = db.insert(LevelsSQLiteOpenHelper.TABLE_LEVELS, null, values);
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_LEVELS, null,
+ LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID + " = " + insertId,
+ null, null, null, null);
+
+ cursor.moveToFirst();
+
+ Level level = cursorToLevel(cursor);
+ cursor.close();
+ return level;
+ }
+
+ public synchronized void deleteLevel(Level level) {
+ long id = level.getId();
+ db.delete(LevelsSQLiteOpenHelper.TABLE_LEVELS, LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID + " = " + id, null);
+ db.delete(LevelsSQLiteOpenHelper.TABLE_HIGHSCORES, LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_LEVEL_ID + " = " + id, null);
+ }
+
+ // This will also reset auto increment counter
+ public synchronized void deleteAllLevels() {
+ db.delete(LevelsSQLiteOpenHelper.TABLE_LEVELS, null, null);
+ db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + LevelsSQLiteOpenHelper.TABLE_LEVELS + "'");
+ }
+
+ public synchronized void resetAllLevelsSettings() {
+ ContentValues values = new ContentValues();
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_EASY, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_MEDIUM, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_HARD, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEAGUE, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEVEL, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_TRACK, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEAGUES, 0);
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEVELS, 0);
+
+ int result = db.update(LevelsSQLiteOpenHelper.TABLE_LEVELS, values, null, null);
+ logDebug("LevelsDataSource.resetAllLevelsSettings: result = " + result);
+ }
+
+ public synchronized void updateLevel(Level level) {
+ ContentValues values = new ContentValues();
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_EASY, level.getUnlockedEasy());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_MEDIUM, level.getUnlockedMedium());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_HARD, level.getUnlockedHard());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEAGUE, level.getSelectedLeague());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEVEL, level.getSelectedLevel());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_TRACK, level.getSelectedTrack());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEAGUES, level.getUnlockedLeagues());
+ values.put(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEVELS, level.getUnlockedLevels());
+
+ // logDebug("LevelsDataSource.updateLevel selectedLeague: " + level.getSelectedLeague());
+
+ db.update(LevelsSQLiteOpenHelper.TABLE_LEVELS, values, LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID + " = " + level.getId(), null);
+ }
+
+ public synchronized HashMap<Long, Long> findInstalledLevels(ArrayList<Long> apiIds) {
+ HashMap<Long, Long> installed = new HashMap<>();
+
+ String[] apiIdsArray = new String[apiIds.size()];
+ for (int i = 0; i < apiIdsArray.length; i++) {
+ apiIdsArray[i] = apiIds.get(i).toString();
+ }
+
+ Cursor cursor = db.rawQuery("SELECT " + LevelsSQLiteOpenHelper.LEVELS_COLUMN_API_ID + ", " + LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID + " FROM " + LevelsSQLiteOpenHelper.TABLE_LEVELS + " WHERE " + LevelsSQLiteOpenHelper.LEVELS_COLUMN_API_ID + " IN (" + makePlaceholders(apiIdsArray.length) + ")", apiIdsArray);
+ cursor.moveToFirst();
+
+ while (!cursor.isAfterLast()) {
+ long apiId = cursor.getLong(0),
+ id = cursor.getLong(1);
+ installed.put(apiId, id);
+ cursor.moveToNext();
+ }
+ cursor.close();
+
+ return installed;
+ }
+
+ public synchronized List<Level> getAllLevels() {
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_LEVELS, null, null, null, null, null, null);
+
+ List<Level> levels = levelsFromCursor(cursor);
+ cursor.close();
+
+ return levels;
+ }
+
+ public synchronized List<Level> getLevels(int offset, int count) {
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_LEVELS, null, null, null, null, LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID + " ASC", offset + ", " + count);
+
+ List<Level> levels = levelsFromCursor(cursor);
+ cursor.close();
+
+ return levels;
+ }
+
+ public synchronized Level getLevel(long id) {
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_LEVELS, null, LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID + " = " + id, null, null, null, null);
+ cursor.moveToFirst();
+
+ Level level = null;
+ if (cursor.getCount() > 0) {
+ level = cursorToLevel(cursor);
+ }
+
+ cursor.close();
+ return level;
+ }
+
+ public List<Level> levelsFromCursor(Cursor cursor) {
+ cursor.moveToFirst();
+ List<Level> levels = new ArrayList<>();
+ while (!cursor.isAfterLast()) {
+ Level level = cursorToLevel(cursor);
+ levels.add(level);
+ cursor.moveToNext();
+ }
+ return levels;
+ }
+
+ public synchronized boolean isDefaultLevelCreated() {
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_LEVELS, new String[]{LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID}, LevelsSQLiteOpenHelper.LEVELS_COLUMN_IS_DEFAULT + " = 1", null, null, null, null);
+ boolean created = cursor.getCount() > 0;
+ cursor.close();
+ return created;
+ }
+
+ public synchronized boolean isApiIdInstalled(long apiId) {
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_LEVELS, new String[]{LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID}, LevelsSQLiteOpenHelper.LEVELS_COLUMN_API_ID + " = " + apiId, null, null, null, null);
+ boolean installed = cursor.getCount() > 0;
+ cursor.close();
+ return installed;
+ }
+
+ public synchronized HighScores getHighScores(long levelId, int level, int track) {
+ Cursor cursor = db.query(LevelsSQLiteOpenHelper.TABLE_HIGHSCORES, null,
+ LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_LEVEL_ID + " = " + levelId + " AND " + LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_LEVEL + " = " + level + " AND " + LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_TRACK + " = " + track,
+ null, null, null, null);
+ cursor.moveToFirst();
+
+ HighScores highScores = new HighScores();
+ highScores.setLevelId(levelId);
+ highScores.setLevel(level);
+ highScores.setTrack(track);
+ if (cursor.getCount() > 0)
+ fillHighScoresFromCursor(cursor, highScores);
+ else {
+ long id = createEmptyHighScore(levelId, level, track);
+ highScores.setId(id);
+ }
+
+ cursor.close();
+ return highScores;
+ }
+
+ private synchronized long createEmptyHighScore(long levelId, int level, int track) {
+ ContentValues values = new ContentValues();
+ values.put(LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_LEVEL_ID, levelId);
+ values.put(LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_LEVEL, level);
+ values.put(LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_TRACK, track);
+ for (int league = 0; league < 4; league++) {
+ for (int place = 0; place < 3; place++) {
+ values.put(LevelsSQLiteOpenHelper.getHighscoresTimeColumn(league, place), 0);
+ values.put(LevelsSQLiteOpenHelper.getHighscoresNameColumn(league, place), 0);
+ }
+ }
+
+ long insertId = db.insert(LevelsSQLiteOpenHelper.TABLE_HIGHSCORES, null, values);
+ return insertId;
+ }
+
+ public synchronized void updateHighScores(HighScores scores) {
+ ContentValues values = new ContentValues();
+ for (int league = 0; league < 4; league++) {
+ for (int place = 0; place < 3; place++) {
+ values.put(LevelsSQLiteOpenHelper.getHighscoresTimeColumn(league, place), scores.getTime(league, place));
+ values.put(LevelsSQLiteOpenHelper.getHighscoresNameColumn(league, place), scores.getName(league, place));
+ }
+ }
+
+ db.update(LevelsSQLiteOpenHelper.TABLE_HIGHSCORES, values, LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_ID + " = " + scores.getId(), null);
+ }
+
+ public synchronized void clearHighScores(long levelId) {
+ db.delete(LevelsSQLiteOpenHelper.TABLE_HIGHSCORES,
+ levelId > 0 ? LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_LEVEL_ID + " = " + levelId : null,
+ null);
+ if (levelId == 0) {
+ db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" + LevelsSQLiteOpenHelper.TABLE_HIGHSCORES + "'");
+ }
+ }
+
+ private Level cursorToLevel(Cursor cursor) {
+ Level level = new Level();
+ level.setId(cursor.getLong(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_ID)));
+ level.setName(cursor.getString(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_NAME)));
+ level.setAuthor(cursor.getString(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_AUTHOR)));
+ level.setCount(
+ cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_COUNT_EASY)),
+ cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_COUNT_MEDIUM)),
+ cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_COUNT_HARD)));
+ level.setAddedTs(cursor.getLong(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_ADDED)));
+ level.setInstalledTs(cursor.getLong(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_INSTALLED)));
+ level.setIsDefault(cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_IS_DEFAULT)) == 1);
+ level.setApiId(cursor.getLong(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_API_ID)));
+ level.setUnlocked(
+ cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_EASY)),
+ cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_MEDIUM)),
+ cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_HARD)));
+ level.setSelectedLevel(cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEVEL)));
+ level.setSelectedTrack(cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_TRACK)));
+ level.setSelectedLeague(cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_SELECTED_LEAGUE)));
+ level.setUnlockedLevels(cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEVELS)));
+ level.setUnlockedLeagues(cursor.getInt(cursor.getColumnIndex(LevelsSQLiteOpenHelper.LEVELS_COLUMN_UNLOCKED_LEAGUES)));
+
+ return level;
+ }
+
+ private void fillHighScoresFromCursor(Cursor cursor, HighScores highScores) {
+ highScores.setId(cursor.getLong(cursor.getColumnIndex(LevelsSQLiteOpenHelper.HIGHSCORES_COLUMN_ID)));
+
+ for (int league = 0; league < 4; league++) {
+ for (int place = 0; place < 3; place++) {
+ highScores.setTime(league, place, cursor.getLong(cursor.getColumnIndex(LevelsSQLiteOpenHelper.getHighscoresTimeColumn(league, place))));
+ highScores.setName(league, place, cursor.getString(cursor.getColumnIndex(LevelsSQLiteOpenHelper.getHighscoresNameColumn(league, place))));
+ }
+ }
+ }
+
+ private String makePlaceholders(int len) {
+ if (len < 1) {
+ throw new RuntimeException("No placeholders");
+ } else {
+ StringBuilder sb = new StringBuilder(len * 2 - 1);
+ sb.append("?");
+ for (int i = 1; i < len; i++) {
+ sb.append(",?");
+ }
+ return sb.toString();
+ }
+ }
+
+}
diff --git a/src/org/happysanta/gd/Storage/LevelsManager.java b/src/org/happysanta/gd/Storage/LevelsManager.java
new file mode 100644
index 0000000..697c9ff
--- /dev/null
+++ b/src/org/happysanta/gd/Storage/LevelsManager.java
@@ -0,0 +1,503 @@
+package org.happysanta.gd.Storage;
+
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.os.AsyncTask;
+import android.os.Environment;
+import android.os.StatFs;
+import org.happysanta.gd.API.API;
+import org.happysanta.gd.API.DownloadFile;
+import org.happysanta.gd.API.DownloadHandler;
+import org.happysanta.gd.Callback;
+import org.happysanta.gd.DoubleCallback;
+import org.happysanta.gd.GDActivity;
+import org.happysanta.gd.Global;
+import org.happysanta.gd.Levels.LevelHeader;
+import org.happysanta.gd.Levels.Reader;
+import org.happysanta.gd.Menu.Menu;
+import org.happysanta.gd.Menu.MenuScreen;
+import org.happysanta.gd.R;
+import org.happysanta.gd.Settings;
+import org.acra.ACRA;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static org.happysanta.gd.Helpers.getGDActivity;
+import static org.happysanta.gd.Helpers.getGameMenu;
+import static org.happysanta.gd.Helpers.getString;
+import static org.happysanta.gd.Helpers.getTimestamp;
+import static org.happysanta.gd.Helpers.isOnline;
+import static org.happysanta.gd.Helpers.logDebug;
+import static org.happysanta.gd.Helpers.showAlert;
+
+public class LevelsManager {
+
+ private LevelsDataSource dataSource;
+ private boolean dbOK = false;
+ private Level currentLevel;
+
+ public LevelsManager() {
+ GDActivity gd = getGDActivity();
+ dataSource = new LevelsDataSource(gd);
+
+ try {
+ dataSource.open();
+
+ if (!dataSource.isDefaultLevelCreated()) {
+ Level level = dataSource.createLevel("GDTR original", "Codebrew Software", 10, 10, 10, 0, 0, true, 1);
+ logDebug("LevelsManager: Default level created!");
+ logDebug(level);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ logDebug("LevelsManager: db feels bad :(");
+ // return;
+ }
+
+ logDebug("LevelsManager: db feels OK :)");
+
+ // Shared prefs
+ // SharedPreferences settings = getSharedPreferences();
+ // long levelId = settings.getLong(PREFS_LEVEL_ID, 0);
+ long levelId = Settings.getLevelId();
+ if (levelId < 1 || !mrgIsAvailable(levelId)) {
+ logDebug("LevelsManager: levelId = " + levelId + ", < 1 or mrg is not available; now: reset id");
+ /*SharedPreferences.Editor editor = settings.edit();
+ editor.putLong(PREFS_LEVEL_ID, 1);
+ editor.commit();*/
+ resetId();
+ }
+
+ reload();
+ dbOK = true;
+ }
+
+ public void resetId() {
+ Settings.setLevelId(1);
+ }
+
+ public void reload() {
+ long id = Settings.getLevelId();
+ currentLevel = dataSource.getLevel(id);
+
+ if (currentLevel == null) {
+ logDebug("LevelsManager: failed to load currentLevel; currentId = " + id);
+ } else {
+ logDebug("LevelsManager: level = " + currentLevel);
+ }
+
+ if (Global.ACRA_ENABLED) {
+ ACRA.getErrorReporter().putCustomData("level_api_id:", String.valueOf(currentLevel.getApiId()));
+ }
+ }
+
+ public void closeDataSource() {
+ dataSource.close();
+ }
+
+ public long getCurrentId() {
+ return currentLevel.getId();
+ }
+
+ public void setCurrentId(long id) {
+ // currentId = id;
+ Settings.setLevelId(id);
+ /*SharedPreferences settings = getSharedPreferences();
+ SharedPreferences.Editor edit = settings.edit();
+ edit.putLong(PREFS_LEVEL_ID, id);
+ edit.commit();*/
+ }
+
+ public Level getCurrentLevel() {
+ return currentLevel;
+ }
+
+ public File getCurrentLevelsFile() {
+ if (currentLevel.getId() > 1)
+ return getMrgFileById(currentLevel.getId());
+
+ return null;
+ }
+
+ private boolean mrgIsAvailable(long id) {
+ if (id == 1) // This is default built-in levels.mrg
+ return true;
+
+ File file = getMrgFileById(id);
+ return isExternalStorageReadable() && file.exists();
+ }
+
+ public boolean isDbOK() {
+ return dbOK;
+ }
+
+ public long install(File file, String name, String author, long apiId) throws Exception {
+ if (!isSpaceAvailable(file.length())) {
+ throw new Exception(getString(R.string.e_no_space_left));
+ }
+
+ InputStream inputStream = new FileInputStream(file);
+ LevelHeader header = Reader.readHeader(inputStream);
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+
+ if (!header.isCountsOk()) {
+ throw new IOException(file.getName() + " is not valid");
+ }
+
+ Level level = dataSource.createLevel(name, author, header.getCount(0), header.getCount(1), header.getCount(2), 0, getTimestamp(), false, apiId);
+ long id = level.getId();
+ if (id < 1) {
+ throw new Exception(getString(R.string.e_cannot_save_level));
+ }
+
+ File newFile = getMrgFileById(id);
+ copy(file, newFile);
+
+ return id;
+ }
+
+ public void installAsync(File file, String name, String author, long apiId, final DoubleCallback callback) {
+ GDActivity gd = getGDActivity();
+ final ProgressDialog progressDialog = ProgressDialog.show(gd, getString(R.string.install), getString(R.string.installing), true);
+
+ new AsyncInstallLevel() {
+ @Override
+ protected void onPostExecute(Object result) {
+ progressDialog.dismiss();
+
+ if (result instanceof Throwable) {
+ Throwable throwable = (Throwable) result;
+ throwable.printStackTrace();
+ showAlert(getString(R.string.error), throwable.getMessage(), null);
+ if (callback != null)
+ callback.onFail();
+ return;
+ }
+
+ if (callback != null)
+ callback.onDone((long) result);
+ }
+ }.execute(file, name, author, apiId);
+ }
+
+ public void load(Level level) throws RuntimeException {
+ /*File file = getMrgFileById(level.getId());
+ if (!mrgIsAvailable(level.getId())) {
+ throw new RuntimeException("Unable to load levels \"" +level.getName() + "\"");
+ }*/
+
+ // Loader loader = getLevelLoader();
+ // Menu menu = getGameMenu();
+
+ // loader.setLevelsFile(file);
+ // menu.reloadLevels();
+
+ setCurrentId(level.getId());
+ getGDActivity().restartApp();
+ }
+
+ public boolean isApiIdInstalled(long apiId) {
+ return dataSource.isApiIdInstalled(apiId);
+ }
+
+ public Level[] getInstalledLevels(int offset, int count) {
+ return dataSource.getLevels(offset, count).toArray(new Level[0]);
+ }
+
+ public Level getLeveL(long id) {
+ return dataSource.getLevel(id);
+ }
+
+ public Level[] getAllInstalledLevels() {
+ return dataSource.getAllLevels().toArray(new Level[0]);
+ }
+
+ public synchronized HashMap<String, Double> getLevelsStat() {
+ Level[] levels = getAllInstalledLevels();
+ HashMap<String, Double> stat = new HashMap<>();
+ if (levels.length > 0) {
+ for (Level level : levels) {
+ int[] completed = level.getUnlockedAll();
+ int completedCount = 0;
+ for (int i = 0; i < completed.length; i++) {
+ if (completed[i] < 0) completed[i] = 0;
+ completedCount += completed[i];
+ }
+
+ double totalCount = level.getCountEasy() + level.getCountMedium() + level.getCountHard();
+ double per = completedCount / totalCount * 100;
+
+ stat.put(String.valueOf(level.getApiId()), per);
+ }
+ }
+ return stat;
+ }
+
+ public void delete(Level level) {
+ dataSource.deleteLevel(level);
+ File file = getMrgFileById(level.getId());
+ try {
+ if (file.exists()) {
+ file.delete();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void deleteAsync(Level level, final Runnable callback) {
+ GDActivity gd = getGDActivity();
+ final ProgressDialog progressDialog = ProgressDialog.show(gd, getString(R.string.delete), getString(R.string.deleting), true);
+
+ new AsyncDeleteLevel() {
+ @Override
+ protected void onPostExecute(Void v) {
+ progressDialog.dismiss();
+ if (callback != null)
+ callback.run();
+ }
+ }.execute(level);
+ }
+
+ public void updateLevelSettings() {
+ dataSource.updateLevel(currentLevel);
+ }
+
+ public void downloadLevel(final Level level, final Callback successCallback) {
+ final GDActivity gd = getGDActivity();
+ File outputDir = gd.getCacheDir();
+
+ try {
+ boolean readable = isExternalStorageReadable();
+ if (!readable) {
+ throw new Exception(getString(R.string.e_external_storage_is_not_readable));
+ }
+
+ if (!isOnline()) {
+ throw new Exception(getString(R.string.e_no_network_connection));
+ }
+
+ if (!isSpaceAvailable(level.getSize())) {
+ throw new Exception(getString(R.string.e_no_space_left));
+ }
+
+ final File outputFile = File.createTempFile("levels" + level.getApiId(), "mrg", outputDir);
+ FileOutputStream out = new FileOutputStream(outputFile);
+
+ // logDebug("downloadLevel: 4");
+ // final API api = new API();
+ final ProgressDialog progress;
+ final DownloadFile downloadFile = new DownloadFile(API.getMrgURL(level.getApiId()), out);
+
+ progress = new ProgressDialog(gd);
+ progress.setMessage(getString(R.string.downloading));
+ progress.setIndeterminate(true);
+ progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ progress.setCancelable(true);
+
+ final DownloadHandler handler = new DownloadHandler() {
+ @Override
+ public void onFinish(Throwable error) {
+ progress.dismiss();
+
+ if (error != null) {
+ // error.printStackTrace();
+ error.printStackTrace();
+ showAlert(getString(R.string.error), error.getMessage(), null);
+
+ outputFile.delete();
+ return;
+ }
+
+ // Install
+ installAsync(outputFile, level.getName(), level.getAuthor(), level.getApiId(), new DoubleCallback() {
+ @Override
+ public void onDone(Object... objects) {
+ long id = (long) objects[0];
+ outputFile.delete();
+
+ if (successCallback != null)
+ successCallback.onDone(id);
+ }
+
+ @Override
+ public void onFail() {
+ outputFile.delete();
+ }
+ });
+ }
+
+ @Override
+ public void onStart() {
+ progress.show();
+ }
+
+ @Override
+ public void onProgress(int pr) {
+ progress.setIndeterminate(false);
+ progress.setMax(100);
+ progress.setProgress(pr);
+ }
+ };
+ progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ downloadFile.cancel();
+ handler.onFinish(new InterruptedException(getString(R.string.e_downloading_was_interrupted)));
+ }
+ });
+
+ downloadFile.setDownloadHandler(handler);
+ downloadFile.start();
+ } catch (Exception e) {
+ showAlert(getString(R.string.error), e.getMessage(), null);
+ }
+ }
+
+ public void showSuccessfullyInstalledDialog() {
+ GDActivity gd = getGDActivity();
+ AlertDialog success = new AlertDialog.Builder(gd)
+ .setTitle(getString(R.string.installed))
+ .setMessage(getString(R.string.successfully_installed))
+ .setPositiveButton(getString(R.string.ok), null)
+ .setNegativeButton(getString(R.string.open_installed), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Menu menu = getGameMenu();
+ MenuScreen currentMenu = getGameMenu().getCurrentMenu(),
+ newMenu = menu.managerInstalledScreen;
+
+ if (currentMenu == menu.managerDownloadScreen || currentMenu.getNavTarget() == menu.managerDownloadScreen) {
+ menu.managerDownloadScreen.onHide(menu.managerScreen);
+ }
+
+ menu.setCurrentMenu(newMenu, false);
+ }
+ })
+ .create();
+ success.show();
+ }
+
+ public HashMap<Long, Long> findInstalledLevels(ArrayList<Long> apiIds) {
+ return dataSource.findInstalledLevels(apiIds);
+ }
+
+ public HighScores getHighScores(int level, int track) {
+ HighScores scores = dataSource.getHighScores(currentLevel.getId(), level, track);
+ // logDebug("LevelsManager.getHighScores: " + scores);
+ return scores;
+ }
+
+ public void saveHighScores(HighScores scores) {
+ dataSource.updateHighScores(scores);
+ }
+
+ public void clearHighScores() {
+ dataSource.clearHighScores(currentLevel.getId());
+ }
+
+ public void clearAllHighScores() {
+ dataSource.clearHighScores(0);
+ }
+
+ public void resetAllLevelsSettings() {
+ dataSource.resetAllLevelsSettings();
+
+ logDebug("All levels now: " + dataSource.getAllLevels());
+ logDebug("Level#1: " + dataSource.getLevel(1));
+ }
+
+ public static boolean isExternalStorageWritable() {
+ String state = Environment.getExternalStorageState();
+ if (Environment.MEDIA_MOUNTED.equals(state)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isExternalStorageReadable() {
+ String state = Environment.getExternalStorageState();
+ if (Environment.MEDIA_MOUNTED.equals(state) ||
+ Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static File getLevelsDirectory() {
+ File file = new File(Environment.getExternalStorageDirectory(), "GDLevels");
+ if (!file.mkdirs()) {
+ logDebug("LevelsManager.getLevelsDirectory: directory not created");
+ }
+ return file;
+ }
+
+ public static String getMrgFileNameById(long id) {
+ return getLevelsDirectory().getAbsolutePath() + "/" + id + ".mrg";
+ }
+
+ public static File getMrgFileById(long id) {
+ if (id == 1) return null;
+ return new File(getMrgFileNameById(id));
+ }
+
+ public static void copy(File src, File dst) throws IOException {
+ InputStream in = new FileInputStream(src);
+ OutputStream out = new FileOutputStream(dst);
+
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+
+ in.close();
+ out.close();
+ }
+
+ public static boolean isSpaceAvailable(long bytes) {
+ StatFs stat = new StatFs(getLevelsDirectory().getPath());
+ long bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks();
+ return bytesAvailable >= bytes;
+ }
+
+ private class AsyncDeleteLevel extends AsyncTask<Level, Void, Void> {
+ @Override
+ protected Void doInBackground(Level... levels) {
+ delete(levels[0]);
+ return null;
+ }
+ }
+
+ private class AsyncInstallLevel extends AsyncTask<Object, Void, Object> {
+ @Override
+ protected Object doInBackground(Object... objects) {
+ File file = (File) objects[0];
+ String name = (String) objects[1];
+ String author = (String) objects[2];
+ long apiId = (long) objects[3];
+
+ long id = 0;
+ try {
+ id = install(file, name, author, apiId);
+ } catch (Throwable e) {
+ return e;
+ }
+
+ return id;
+ }
+ }
+
+}
diff --git a/src/org/happysanta/gd/Storage/LevelsSQLiteOpenHelper.java b/src/org/happysanta/gd/Storage/LevelsSQLiteOpenHelper.java
new file mode 100644
index 0000000..024a17f
--- /dev/null
+++ b/src/org/happysanta/gd/Storage/LevelsSQLiteOpenHelper.java
@@ -0,0 +1,141 @@
+package org.happysanta.gd.Storage;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class LevelsSQLiteOpenHelper extends SQLiteOpenHelper {
+
+ private static final int DATABASE_VERSION = 1;
+ private static final String DATABASE_NAME = "levels.db";
+
+ public static final String TABLE_LEVELS = "levels";
+ public static final String TABLE_HIGHSCORES = "highscores";
+
+ public static final String LEVELS_COLUMN_ID = "_id";
+ public static final String LEVELS_COLUMN_NAME = "name";
+ public static final String LEVELS_COLUMN_AUTHOR = "author";
+ public static final String LEVELS_COLUMN_COUNT_EASY = "count_easy";
+ public static final String LEVELS_COLUMN_COUNT_MEDIUM = "count_medium";
+ public static final String LEVELS_COLUMN_COUNT_HARD = "count_hard";
+ public static final String LEVELS_COLUMN_ADDED = "added_ts";
+ public static final String LEVELS_COLUMN_INSTALLED = "installed_ts";
+ public static final String LEVELS_COLUMN_IS_DEFAULT = "is_default";
+ public static final String LEVELS_COLUMN_API_ID = "api_id";
+ public static final String LEVELS_COLUMN_UNLOCKED_EASY = "unlocked_easy";
+ public static final String LEVELS_COLUMN_UNLOCKED_MEDIUM = "unlocked_medium";
+ public static final String LEVELS_COLUMN_UNLOCKED_HARD = "unlocked_hard";
+ public static final String LEVELS_COLUMN_SELECTED_LEVEL = "selected_level";
+ public static final String LEVELS_COLUMN_SELECTED_TRACK = "selected_track";
+ public static final String LEVELS_COLUMN_SELECTED_LEAGUE = "selected_league";
+ public static final String LEVELS_COLUMN_UNLOCKED_LEVELS = "unlocked_levels";
+ public static final String LEVELS_COLUMN_UNLOCKED_LEAGUES = "unlocked_leagues";
+
+ public static final String HIGHSCORES_COLUMN_ID = "_id";
+ public static final String HIGHSCORES_COLUMN_LEVEL_ID = "level_id";
+ public static final String HIGHSCORES_COLUMN_LEVEL = "level";
+ public static final String HIGHSCORES_COLUMN_TRACK = "track";
+
+ private static final String TABLE_LEVELS_CREATE = "CREATE TABLE "
+ + TABLE_LEVELS + "("
+ + LEVELS_COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
+ + LEVELS_COLUMN_NAME + " TEXT NOT NULL, "
+ + LEVELS_COLUMN_AUTHOR + " TEXT NOT NULL, "
+ + LEVELS_COLUMN_COUNT_EASY + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_COUNT_MEDIUM + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_COUNT_HARD + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_ADDED + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_INSTALLED + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_IS_DEFAULT + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_API_ID + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_UNLOCKED_EASY + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_UNLOCKED_MEDIUM + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_UNLOCKED_HARD + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_SELECTED_LEVEL + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_SELECTED_TRACK + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_SELECTED_LEAGUE + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_UNLOCKED_LEVELS + " INTEGER NOT NULL, "
+ + LEVELS_COLUMN_UNLOCKED_LEAGUES + " INTEGER NOT NULL"
+ + ");";
+
+ private static final String TABLE_HIGHSCORES_CREATE = " CREATE TABLE "
+ + TABLE_HIGHSCORES + "("
+ + HIGHSCORES_COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
+ + HIGHSCORES_COLUMN_LEVEL_ID + " INTEGER NOT NULL, "
+ + HIGHSCORES_COLUMN_LEVEL + " INTEGER NOT NULL, "
+ + HIGHSCORES_COLUMN_TRACK + " INTEGER NOT NULL, "
+
+ // 100cc
+ + getHighscoresTimeColumn(0, 0) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(0, 0) + " TEXT, "
+ + getHighscoresTimeColumn(0, 1) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(0, 1) + " TEXT, "
+ + getHighscoresTimeColumn(0, 2) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(0, 2) + " TEXT, "
+
+ // 175cc
+ + getHighscoresTimeColumn(1, 0) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(1, 0) + " TEXT, "
+ + getHighscoresTimeColumn(1, 1) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(1, 1) + " TEXT, "
+ + getHighscoresTimeColumn(1, 2) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(1, 2) + " TEXT, "
+
+ // 220cc
+ + getHighscoresTimeColumn(2, 0) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(2, 0) + " TEXT, "
+ + getHighscoresTimeColumn(2, 1) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(2, 1) + " TEXT, "
+ + getHighscoresTimeColumn(2, 2) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(2, 2) + " TEXT, "
+
+ // 325cc
+ + getHighscoresTimeColumn(3, 0) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(3, 0) + " TEXT, "
+ + getHighscoresTimeColumn(3, 1) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(3, 1) + " TEXT, "
+ + getHighscoresTimeColumn(3, 2) + " INTEGER NOT NULL, "
+ + getHighscoresNameColumn(3, 2) + " TEXT"
+
+ + ")";
+
+ LevelsSQLiteOpenHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(TABLE_LEVELS_CREATE);
+ createLevelsIndexes(db);
+
+ db.execSQL(TABLE_HIGHSCORES_CREATE);
+ createHighscoresIndexes(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+
+ }
+
+ private void createLevelsIndexes(SQLiteDatabase db) {
+ db.execSQL("CREATE INDEX " + LEVELS_COLUMN_API_ID + "_index ON " + TABLE_LEVELS + "(" + LEVELS_COLUMN_API_ID + ")");
+ db.execSQL("CREATE INDEX " + LEVELS_COLUMN_IS_DEFAULT + "_index ON " + TABLE_LEVELS + "(" + LEVELS_COLUMN_IS_DEFAULT + ")");
+ }
+
+ private void createHighscoresIndexes(SQLiteDatabase db) {
+ db.execSQL("CREATE INDEX level_id_level_track_index ON " + TABLE_HIGHSCORES + "("
+ + HIGHSCORES_COLUMN_LEVEL_ID + ", "
+ + HIGHSCORES_COLUMN_LEVEL + ", "
+ + HIGHSCORES_COLUMN_TRACK
+ + ")");
+ }
+
+ public static String getHighscoresTimeColumn(int league, int place) {
+ return "l" + league + "_p" + place + "_time";
+ }
+
+ public static String getHighscoresNameColumn(int league, int place) {
+ return "l" + league + "_p" + place + "_name";
+ }
+
+}
diff --git a/src/org/happysanta/gd/Util/HexDump.java b/src/org/happysanta/gd/Util/HexDump.java
new file mode 100755
index 0000000..443555c
--- /dev/null
+++ b/src/org/happysanta/gd/Util/HexDump.java
@@ -0,0 +1,124 @@
+package org.happysanta.gd.Util;
+
+public class HexDump {
+ private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ public static String dumpHexString(byte[] array) {
+ return dumpHexString(array, 0, array.length);
+ }
+
+ public static String dumpHexString(byte[] array, int offset, int length) {
+ StringBuilder result = new StringBuilder();
+
+ byte[] line = new byte[16];
+ int lineIndex = 0;
+
+ result.append("\n0x");
+ result.append(toHexString(offset));
+
+ for (int i = offset; i < offset + length; i++) {
+ if (lineIndex == 16) {
+ result.append(" ");
+
+ for (int j = 0; j < 16; j++) {
+ if (line[j] > ' ' && line[j] < '~') {
+ result.append(new String(line, j, 1));
+ } else {
+ result.append(".");
+ }
+ }
+
+ result.append("\n0x");
+ result.append(toHexString(i));
+ lineIndex = 0;
+ }
+
+ byte b = array[i];
+ result.append(" ");
+ result.append(HEX_DIGITS[(b >>> 4) & 0x0F]);
+ result.append(HEX_DIGITS[b & 0x0F]);
+
+ line[lineIndex++] = b;
+ }
+
+ if (lineIndex != 16) {
+ int count = (16 - lineIndex) * 3;
+ count++;
+ for (int i = 0; i < count; i++) {
+ result.append(" ");
+ }
+
+ for (int i = 0; i < lineIndex; i++) {
+ if (line[i] > ' ' && line[i] < '~') {
+ result.append(new String(line, i, 1));
+ } else {
+ result.append(".");
+ }
+ }
+ }
+
+ return result.toString();
+ }
+
+ public static String toHexString(byte b) {
+ return toHexString(toByteArray(b));
+ }
+
+ public static String toHexString(byte[] array) {
+ return toHexString(array, 0, array.length);
+ }
+
+ public static String toHexString(byte[] array, int offset, int length) {
+ char[] buf = new char[length * 2];
+
+ int bufIndex = 0;
+ for (int i = offset; i < offset + length; i++) {
+ byte b = array[i];
+ buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F];
+ buf[bufIndex++] = HEX_DIGITS[b & 0x0F];
+ }
+
+ return new String(buf);
+ }
+
+ public static String toHexString(int i) {
+ return toHexString(toByteArray(i));
+ }
+
+ public static byte[] toByteArray(byte b) {
+ byte[] array = new byte[1];
+ array[0] = b;
+ return array;
+ }
+
+ public static byte[] toByteArray(int i) {
+ byte[] array = new byte[4];
+
+ array[3] = (byte) (i & 0xFF);
+ array[2] = (byte) ((i >> 8) & 0xFF);
+ array[1] = (byte) ((i >> 16) & 0xFF);
+ array[0] = (byte) ((i >> 24) & 0xFF);
+
+ return array;
+ }
+
+ private static int toByte(char c) {
+ if (c >= '0' && c <= '9') return (c - '0');
+ if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
+ if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
+
+ throw new RuntimeException("Invalid hex char '" + c + "'");
+ }
+
+ public static byte[] hexStringToByteArray(String hexString) {
+ int length = hexString.length();
+ byte[] buffer = new byte[length / 2];
+
+ for (int i = 0; i < length; i += 2) {
+ buffer[i / 2] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1)));
+ }
+
+ return buffer;
+ }
+}
+
diff --git a/src/org/happysanta/gd/WaitForNetworkConnection.java b/src/org/happysanta/gd/WaitForNetworkConnection.java
new file mode 100644
index 0000000..d711715
--- /dev/null
+++ b/src/org/happysanta/gd/WaitForNetworkConnection.java
@@ -0,0 +1,34 @@
+package org.happysanta.gd;
+
+import android.os.AsyncTask;
+
+import static org.happysanta.gd.Helpers.isOnline;
+import static org.happysanta.gd.Helpers.logDebug;
+
+public class WaitForNetworkConnection extends AsyncTask<Object, Void, Void> {
+
+ protected Runnable callback;
+
+ @Override
+ public Void doInBackground(Object... params) {
+ callback = (Runnable) params[1];
+
+ while (!isOnline()) {
+ logDebug("Waiting for network...");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ break;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public void onPostExecute(Void v) {
+ logDebug("Network OK, callback.run() now...");
+ callback.run();
+ }
+
+}