diff --git a/app/build.gradle b/app/build.gradle
index 97a4bcd6..b0c072ce 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,8 +1,8 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 23
- buildToolsVersion '25.0.0'
+ compileSdkVersion 25
+ buildToolsVersion '25.0.2'
defaultConfig {
applicationId "com.asha.md360player4android"
@@ -23,9 +23,11 @@ android {
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
- compile 'com.android.support:appcompat-v7:23.2.0'
+ compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.squareup.picasso:picasso:2.5.2'
//required, enough for most devices.
+ compile 'com.android.support:recyclerview-v7:25.3.1'
+ compile 'com.android.support:cardview-v7:25.3.1'
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.6.0'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.6.0'
compile project(path: ':vrlib')
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 59fb70b2..00bcc7e8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,15 +13,21 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/asha/md360player4android/RecyclerViewActivity.java b/app/src/main/java/com/asha/md360player4android/RecyclerViewActivity.java
new file mode 100644
index 00000000..b49e9ceb
--- /dev/null
+++ b/app/src/main/java/com/asha/md360player4android/RecyclerViewActivity.java
@@ -0,0 +1,318 @@
+package com.asha.md360player4android;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.DrawableRes;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.asha.vrlib.MDVRLibrary;
+import com.asha.vrlib.texture.MD360BitmapTexture;
+import com.google.android.apps.muzei.render.GLTextureView;
+import com.squareup.picasso.Picasso;
+import com.squareup.picasso.Target;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.asha.vrlib.MDVRLibrary.INTERACTIVE_MODE_CARDBORAD_MOTION_WITH_TOUCH;
+
+public class RecyclerViewActivity extends AppCompatActivity {
+
+ private Uri[] sMockData;
+
+ private static final String TAG = "MainActivity";
+
+ private VRLibManager manager;
+
+ public RecyclerViewActivity() {
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sMockData = new Uri[] {
+ getDrawableUri(R.drawable.bitmap360)
+ ,getDrawableUri(R.drawable.texture)
+ };
+
+ setContentView(R.layout.activity_main);
+ manager = new VRLibManager(this);
+
+ RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
+ final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
+ final FeedAdapter adapter = new FeedAdapter();
+ recyclerView.setLayoutManager(layoutManager);
+ recyclerView.setItemAnimator(null);
+ recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+ if (newState != RecyclerView.SCROLL_STATE_DRAGGING) {
+ int pos = layoutManager.findFirstCompletelyVisibleItemPosition();
+ adapter.onPosition(pos);
+ }
+ }
+ });
+ recyclerView.setAdapter(adapter);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ manager.fireResumed();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ manager.firePaused();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ manager.fireDestroy();
+ }
+
+ private static class FeedModel {
+
+ private final Uri uri;
+ private final int index;
+ private int pos;
+
+ public FeedModel(int index, Uri uri) {
+ this.index = index;
+ this.uri = uri;
+ }
+
+ public void setPos(int pos) {
+ this.pos = pos;
+ }
+ }
+
+ private abstract class FeedVH extends RecyclerView.ViewHolder {
+
+ public FeedVH(ViewGroup vp, int layoutId) {
+ super(create(vp, layoutId));
+ }
+
+ public abstract void bind(FeedModel feedModel);
+ }
+
+ private class FeedSimpleVH extends FeedVH {
+
+ public FeedSimpleVH(ViewGroup vp) {
+ super(vp, R.layout.feed_simple_layout);
+ }
+
+ @Override
+ public void bind(FeedModel feedModel) {
+ }
+ }
+
+ private class FeedVRVH extends FeedVH implements MDVRLibrary.IBitmapProvider {
+
+ private ImageView cover;
+
+ private TextView text;
+
+ private GLTextureView glTextureView;
+
+ private ViewGroup parent;
+
+ private MDVRLibrary vrlib;
+
+ private FeedModel model;
+
+ public FeedVRVH(ViewGroup vp) {
+ super(vp, R.layout.feed_panorama_layout);
+ cover = (ImageView) itemView.findViewById(R.id.feed_img_cover);
+ text = (TextView) itemView.findViewById(R.id.feed_text);
+ glTextureView = (GLTextureView) itemView.findViewById(R.id.feed_texture_view);
+ parent = (ViewGroup) glTextureView.getParent();
+ }
+
+ @Override
+ public void bind(FeedModel model) {
+ Log.d(TAG, "FeedVRVH bind.");
+ this.model = model;
+ // Picasso.with(itemView.getContext()).load(model.url).into(cover);
+ ensureVRLib();
+ vrlib.notifyPlayerChanged();
+ /*
+ if (model.pos == model.index) {
+ text.setText("on");
+ if (glTextureView.getParent() == null) {
+ // parent.addView(glTextureView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ }
+
+ } else {
+ text.setText("off");
+ // parent.removeView(glTextureView);
+ }
+ */
+ }
+
+ private void ensureVRLib() {
+ if (vrlib == null) {
+ vrlib = manager.create(this, glTextureView);
+ }
+ }
+
+ @Override
+ public void onProvideBitmap(final MD360BitmapTexture.Callback callback) {
+ if (model == null) {
+ return;
+ }
+ Log.d(TAG, "onProvideBitmap");
+ Picasso.with(itemView.getContext()).load(model.uri).into(new Target() {
+ @Override
+ public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
+ Log.d(TAG, "onProvideBitmap onBitmapLoaded");
+
+ vrlib.onTextureResize(bitmap.getWidth(), bitmap.getHeight());
+ callback.texture(bitmap);
+ }
+
+ @Override
+ public void onBitmapFailed(Drawable errorDrawable) {
+
+ }
+
+ @Override
+ public void onPrepareLoad(Drawable placeHolderDrawable) {
+
+ }
+ });
+ }
+ }
+
+ private Uri getDrawableUri(@DrawableRes int resId){
+ Resources resources = getResources();
+ return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + resources.getResourcePackageName(resId) + '/' + resources.getResourceTypeName(resId) + '/' + resources.getResourceEntryName(resId) );
+ }
+
+ private class FeedAdapter extends RecyclerView.Adapter {
+
+ private List feeds = new ArrayList<>();
+
+ public FeedAdapter() {
+ int i = -1;
+ while (i++ < 50) {
+ Uri url = sMockData[(int) (Math.random() * sMockData.length)];
+ feeds.add(new FeedModel(i, url));
+ }
+ }
+
+ @Override
+ public FeedVH onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType == 0) {
+ return new FeedVRVH(parent);
+ } else {
+ return new FeedSimpleVH(parent);
+ }
+
+ }
+
+ @Override
+ public void onBindViewHolder(FeedVH holder, int position) {
+ holder.bind(feeds.get(position));
+ }
+
+ @Override
+ public void onViewRecycled(FeedVH holder) {
+ super.onViewRecycled(holder);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return position == 0 ? 0 : 1;
+ }
+
+ @Override
+ public int getItemCount() {
+ return feeds.size();
+ }
+
+ private int prevPos = -1;
+ public void onPosition(int pos) {
+ if (prevPos == pos) {
+ return;
+ }
+
+ for (FeedModel feedModel : feeds) {
+ feedModel.setPos(pos);
+ }
+
+ notifyItemChanged(prevPos);
+ notifyItemChanged(pos);
+ prevPos = pos;
+ }
+ }
+
+ private static View create(ViewGroup vp, int layout) {
+ return LayoutInflater.from(vp.getContext()).inflate(layout, vp, false);
+ }
+
+ private static class VRLibManager {
+ private Activity activity;
+
+ private boolean isResumed;
+
+ private List libs = new LinkedList<>();
+
+ public VRLibManager(Activity activity) {
+ this.activity = activity;
+ }
+
+ public MDVRLibrary create(MDVRLibrary.IBitmapProvider provider, GLTextureView textureView) {
+ MDVRLibrary lib = MDVRLibrary.with(activity).
+ asBitmap(provider).
+ interactiveMode(INTERACTIVE_MODE_CARDBORAD_MOTION_WITH_TOUCH).
+ build(textureView);
+ add(lib);
+ return lib;
+ }
+
+ private void add(MDVRLibrary lib) {
+ if (isResumed) {
+ lib.onResume(activity);
+ }
+
+ libs.add(lib);
+ }
+
+ public void fireResumed() {
+ isResumed = true;
+ for (MDVRLibrary library : libs) {
+ library.onResume(activity);
+ }
+ }
+
+ public void firePaused() {
+ isResumed = false;
+ for (MDVRLibrary library : libs) {
+ library.onPause(activity);
+ }
+ }
+
+ public void fireDestroy() {
+ for (MDVRLibrary library : libs) {
+ library.onDestroy();
+ }
+ }
+ }
+}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..7eb1449e
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_md_using_surface_view.xml b/app/src/main/res/layout/activity_md_using_surface_view.xml
index ebd369ff..8cd26aae 100644
--- a/app/src/main/res/layout/activity_md_using_surface_view.xml
+++ b/app/src/main/res/layout/activity_md_using_surface_view.xml
@@ -36,254 +36,224 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/feed_simple_layout.xml b/app/src/main/res/layout/feed_simple_layout.xml
new file mode 100644
index 00000000..af6b0f48
--- /dev/null
+++ b/app/src/main/res/layout/feed_simple_layout.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vrlib/build.gradle b/vrlib/build.gradle
index 60fa43b5..f19a331c 100644
--- a/vrlib/build.gradle
+++ b/vrlib/build.gradle
@@ -1,12 +1,12 @@
apply plugin: 'com.android.library'
android {
- compileSdkVersion 23
- buildToolsVersion '25.0.0'
+ compileSdkVersion 25
+ buildToolsVersion '25.0.2'
defaultConfig {
minSdkVersion 15
- targetSdkVersion 23
+ targetSdkVersion 25
versionCode 6
versionName "1.0.1"
}
diff --git a/vrlib/src/main/java/com/asha/vrlib/MD360Renderer.java b/vrlib/src/main/java/com/asha/vrlib/MD360Renderer.java
index f9045e02..b3343ad6 100644
--- a/vrlib/src/main/java/com/asha/vrlib/MD360Renderer.java
+++ b/vrlib/src/main/java/com/asha/vrlib/MD360Renderer.java
@@ -82,7 +82,7 @@ public void onDrawFrame(GL10 glUnused){
mGLHandler.dealMessage();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
- glCheck("MD360Renderer onDrawFrame 1");
+ glCheck("MD360Renderer onDrawFrame begin. ");
int size = mDisplayModeManager.getVisibleSize();
@@ -127,6 +127,7 @@ public void onDrawFrame(GL10 glUnused){
}
mMainLinePipe.commit(mWidth,mHeight,size);
+ glCheck("MD360Renderer onDrawFrame end. ");
// mFps.step();
}
diff --git a/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsLinePipe.java b/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsLinePipe.java
index de7453f3..307e62fd 100644
--- a/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsLinePipe.java
+++ b/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsLinePipe.java
@@ -12,10 +12,17 @@ public abstract class MDAbsLinePipe {
abstract protected void init(Context context);
private boolean mIsInit;
+ private long mTid;
// MDPosition position = MDPosition.sOriginalPosition;
public final void setup(Context context){
+ long tid = Thread.currentThread().getId();
+ if (mTid != tid) {
+ mTid = tid;
+ mIsInit = false;
+ }
+
if (!mIsInit){
init(context);
mIsInit = true;
diff --git a/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsPlugin.java b/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsPlugin.java
index 2b66003c..d775460f 100644
--- a/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsPlugin.java
+++ b/vrlib/src/main/java/com/asha/vrlib/plugins/MDAbsPlugin.java
@@ -13,9 +13,17 @@ public abstract class MDAbsPlugin {
private boolean mIsInit;
+ private long mTid;
+
private MDPosition mPosition = MDPosition.getOriginalPosition();
public final void setupInGL(Context context){
+ long tid = Thread.currentThread().getId();
+ if (tid != mTid) {
+ mTid = tid;
+ mIsInit = false;
+ }
+
if (!mIsInit){
initInGL(context);
mIsInit = true;
diff --git a/vrlib/src/main/java/com/asha/vrlib/strategy/projection/PlaneProjection.java b/vrlib/src/main/java/com/asha/vrlib/strategy/projection/PlaneProjection.java
index e04abd30..6639f707 100644
--- a/vrlib/src/main/java/com/asha/vrlib/strategy/projection/PlaneProjection.java
+++ b/vrlib/src/main/java/com/asha/vrlib/strategy/projection/PlaneProjection.java
@@ -215,8 +215,11 @@ public MD360Director createDirector(int index) {
private class OrthogonalDirector extends MD360Director{
+ private final float sNearBase;
+
private OrthogonalDirector(Builder builder) {
super(builder);
+ sNearBase = getNear();
}
@Override
@@ -238,12 +241,13 @@ public void updateSensorMatrix(float[] sensorMatrix) {
protected void updateProjection(){
planeScaleCalculator.setViewportRatio(getRatio());
planeScaleCalculator.calculate();
- final float left = - planeScaleCalculator.getViewportWidth()/2;
- final float right = planeScaleCalculator.getViewportWidth()/2;
- final float bottom = - planeScaleCalculator.getViewportHeight()/2;
- final float top = planeScaleCalculator.getViewportHeight()/2;
+ float scale = sNearBase / getNear();
+ final float left = - planeScaleCalculator.getViewportWidth() / 2 * scale;
+ final float right = planeScaleCalculator.getViewportWidth() / 2 * scale;
+ final float bottom = - planeScaleCalculator.getViewportHeight() / 2 * scale;
+ final float top = planeScaleCalculator.getViewportHeight() / 2 * scale;
final float far = 500;
- Matrix.orthoM(getProjectionMatrix(), 0, left, right, bottom, top, getNear(), far);
+ Matrix.orthoM(getProjectionMatrix(), 0, left, right, bottom, top, 1, far);
}
}
diff --git a/vrlib/src/main/java/com/asha/vrlib/texture/MD360BitmapTexture.java b/vrlib/src/main/java/com/asha/vrlib/texture/MD360BitmapTexture.java
index dce57a9a..e64614f3 100644
--- a/vrlib/src/main/java/com/asha/vrlib/texture/MD360BitmapTexture.java
+++ b/vrlib/src/main/java/com/asha/vrlib/texture/MD360BitmapTexture.java
@@ -151,6 +151,7 @@ public AsyncCallback(int maxSize) {
@Override
public void texture(Bitmap bitmap) {
+ releaseBitmap();
this.bitmapRef = new SoftReference<>(bitmap);
}
diff --git a/vrlib/src/main/java/com/google/android/apps/muzei/render/GLTextureView.java b/vrlib/src/main/java/com/google/android/apps/muzei/render/GLTextureView.java
index fd2b3ea3..b73f6f17 100644
--- a/vrlib/src/main/java/com/google/android/apps/muzei/render/GLTextureView.java
+++ b/vrlib/src/main/java/com/google/android/apps/muzei/render/GLTextureView.java
@@ -43,13 +43,13 @@
*/
public class GLTextureView extends TextureView implements TextureView.SurfaceTextureListener {
private final static String TAG = "GLTextureView";
- private final static boolean LOG_ATTACH_DETACH = false;
- private final static boolean LOG_THREADS = false;
- private final static boolean LOG_PAUSE_RESUME = false;
- private final static boolean LOG_SURFACE = false;
- private final static boolean LOG_RENDERER = false;
- private final static boolean LOG_RENDERER_DRAW_FRAME = false;
- private final static boolean LOG_EGL = false;
+ private final static boolean LOG_ATTACH_DETACH = true;
+ private final static boolean LOG_THREADS = true;
+ private final static boolean LOG_PAUSE_RESUME = true;
+ private final static boolean LOG_SURFACE = true;
+ private final static boolean LOG_RENDERER = true;
+ private final static boolean LOG_RENDERER_DRAW_FRAME = true;
+ private final static boolean LOG_EGL = true;
/**
* The renderer only renders
* when the surface is created, or when {@link #requestRender} is called.
@@ -464,13 +464,21 @@ protected void onAttachedToWindow() {
}
if (mDetached && (mRenderer != null)) {
int renderMode = RENDERMODE_CONTINUOUSLY;
+ int w = 0, h = 0;
+
if (mGLThread != null) {
renderMode = mGLThread.getRenderMode();
+ w = mGLThread.mWidth;
+ h = mGLThread.mHeight;
}
mGLThread = new GLThread(mThisWeakRef);
if (renderMode != RENDERMODE_CONTINUOUSLY) {
mGLThread.setRenderMode(renderMode);
}
+ if (w != 0 && h != 0) {
+ mGLThread.mWidth = w;
+ mGLThread.mHeight = h;
+ }
mGLThread.start();
}
mDetached = false;
@@ -484,7 +492,7 @@ protected void onAttachedToWindow() {
@Override
protected void onDetachedFromWindow() {
if (LOG_ATTACH_DETACH) {
- Log.d(TAG, "onDetachedFromWindow");
+ Log.d(TAG, "onDetachedFromWindow:" + mGLThread);
}
if (mGLThread != null) {
mGLThread.requestExitAndWait();
@@ -1063,6 +1071,8 @@ private void guardedRun() throws InterruptedException {
while (true) {
synchronized (sGLThreadManager) {
while (true) {
+ Log.e(TAG, "guardedRun run:" + Thread.currentThread());
+
if (mShouldExit) {
return;
}
@@ -1335,6 +1345,8 @@ private void guardedRun() throws InterruptedException {
stopEglSurfaceLocked();
stopEglContextLocked();
}
+
+ Log.e(TAG, "guardedRun exit:" + Thread.currentThread());
}
}
@@ -1451,6 +1463,7 @@ public void onResume() {
}
public void onWindowResize(int w, int h) {
+ Log.d(TAG, "onWindowResize:" + w + "," + h);
synchronized (sGLThreadManager) {
mWidth = w;
mHeight = h;