/** Sets mPageCurl curl position. */ private void setCurlPos(PointF curlPos, PointF curlDir, double radius) { // First reposition curl so that page doesn't 'rip off' from book. if (mCurlState == CURL_RIGHT || (mCurlState == CURL_LEFT && mViewMode == SHOW_ONE_PAGE)) { RectF pageRect = mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT); if (curlPos.x >= pageRect.right) { mPageCurl.reset(); requestRender(); return; } if (curlPos.x < pageRect.left) { curlPos.x = pageRect.left; } if (curlDir.y != 0) { float diffX = curlPos.x - pageRect.left; float leftY = curlPos.y + (diffX * curlDir.x / curlDir.y); if (curlDir.y < 0 && leftY < pageRect.top) { curlDir.x = curlPos.y - pageRect.top; curlDir.y = pageRect.left - curlPos.x; } else if (curlDir.y > 0 && leftY > pageRect.bottom) { curlDir.x = pageRect.bottom - curlPos.y; curlDir.y = curlPos.x - pageRect.left; } } } else if (mCurlState == CURL_LEFT) { RectF pageRect = mRenderer.getPageRect(CurlRenderer.PAGE_LEFT); if (curlPos.x <= pageRect.left) { mPageCurl.reset(); requestRender(); return; } if (curlPos.x > pageRect.right) { curlPos.x = pageRect.right; } if (curlDir.y != 0) { float diffX = curlPos.x - pageRect.right; float rightY = curlPos.y + (diffX * curlDir.x / curlDir.y); if (curlDir.y < 0 && rightY < pageRect.top) { curlDir.x = pageRect.top - curlPos.y; curlDir.y = curlPos.x - pageRect.right; } else if (curlDir.y > 0 && rightY > pageRect.bottom) { curlDir.x = curlPos.y - pageRect.bottom; curlDir.y = pageRect.right - curlPos.x; } } } // Finally normalize direction vector and do rendering. double dist = Math.sqrt(curlDir.x * curlDir.x + curlDir.y * curlDir.y); if (dist != 0) { curlDir.x /= dist; curlDir.y /= dist; mPageCurl.curl(curlPos, curlDir, radius); } else { mPageCurl.reset(); } requestRender(); }
@Override public void onSurfaceCreated() { // In case surface is recreated, let page meshes drop allocated texture // ids and ask for new ones. There's no need to set textures here as // onPageSizeChanged should be called later on. mPageLeft.resetTexture(); mPageRight.resetTexture(); mPageCurl.resetTexture(); }
/** * Sets view mode. Value can be either SHOW_ONE_PAGE or SHOW_TWO_PAGES. In former case right page * is made size of display, and in latter case two pages are laid on visible area. */ public void setViewMode(int viewMode) { switch (viewMode) { case SHOW_ONE_PAGE: mViewMode = viewMode; mPageLeft.setFlipTexture(true); mRenderer.setViewMode(CurlRenderer.SHOW_ONE_PAGE); break; case SHOW_TWO_PAGES: mViewMode = viewMode; mPageLeft.setFlipTexture(false); mRenderer.setViewMode(CurlRenderer.SHOW_TWO_PAGES); break; } }
/** Initialize method. */ private void init(Context ctx) { this.handler = new Handler(); mRenderer = new CurlRenderer(this); setEGLContextClientVersion(2); setRenderer(mRenderer); setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); setOnTouchListener(this); // Even though left and right pages are static we have to allocate room // for curl on them too as we are switching meshes. Another way would be // to swap texture ids only. mPageLeft = new CurlMesh(10); mPageRight = new CurlMesh(10); mPageCurl = new CurlMesh(10); mPageLeft.setFlipTexture(true); mPageRight.setFlipTexture(false); }
@Override public void onDrawFrame() { // We are not animating. if (mAnimate == false) { return; } long currentTime = System.currentTimeMillis(); // If animation is done. if (currentTime >= mAnimationStartTime + mAnimationDurationTime) { if (mAnimationTargetEvent == SET_CURL_TO_RIGHT) { // Switch curled page to right. CurlMesh right = mPageCurl; CurlMesh curl = mPageRight; right.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); right.setFlipTexture(false); right.reset(); mRenderer.removeCurlMesh(curl); mPageCurl = curl; mPageRight = right; // If we were curling left page update current index. if (mCurlState == CURL_LEFT) { --mCurrentIndex; } } else if (mAnimationTargetEvent == SET_CURL_TO_LEFT) { // Switch curled page to left. CurlMesh left = mPageCurl; CurlMesh curl = mPageLeft; left.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_LEFT)); left.setFlipTexture(true); left.reset(); mRenderer.removeCurlMesh(curl); if (!mRenderLeftPage) { mRenderer.removeCurlMesh(left); } mPageCurl = curl; mPageLeft = left; // If we were curling right page update current index. if (mCurlState == CURL_RIGHT) { ++mCurrentIndex; } } mCurlState = CURL_NONE; mAnimate = false; requestRender(); } else { mPointerPos.mPos.set(mAnimationSource); float t = 1f - ((float) (currentTime - mAnimationStartTime) / mAnimationDurationTime); t = 1f - (t * t * t * (3 - 2 * t)); mPointerPos.mPos.x += (mAnimationTarget.x - mAnimationSource.x) * t; mPointerPos.mPos.y += (mAnimationTarget.y - mAnimationSource.y) * t; updateCurlPos(mPointerPos); } }
/** Updates bitmaps for page meshes. */ private void updatePages() { Log.d("artbook", ">>>>>update page(s): " + Thread.currentThread()); if (mPageProvider == null || mPageBitmapWidth <= 0 || mPageBitmapHeight <= 0) { return; } // Remove meshes from renderer. mRenderer.removeCurlMesh(mPageLeft); mRenderer.removeCurlMesh(mPageRight); mRenderer.removeCurlMesh(mPageCurl); int leftIdx = mCurrentIndex - 1; int rightIdx = mCurrentIndex; int curlIdx = -1; if (mCurlState == CURL_LEFT) { curlIdx = leftIdx; --leftIdx; } else if (mCurlState == CURL_RIGHT) { curlIdx = rightIdx; ++rightIdx; } if (rightIdx >= 0 && rightIdx < mPageProvider.getPageCount()) { updatePage(mPageRight.getTexturePage(), rightIdx); mPageRight.setFlipTexture(false); mPageRight.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); mPageRight.reset(); mRenderer.addCurlMesh(mPageRight); } if (leftIdx >= 0 && leftIdx < mPageProvider.getPageCount()) { updatePage(mPageLeft.getTexturePage(), leftIdx); mPageLeft.setFlipTexture(true); mPageLeft.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_LEFT)); mPageLeft.reset(); if (mRenderLeftPage) { mRenderer.addCurlMesh(mPageLeft); } } if (curlIdx >= 0 && curlIdx < mPageProvider.getPageCount()) { updatePage(mPageCurl.getTexturePage(), curlIdx); if (mCurlState == CURL_RIGHT) { mPageCurl.setFlipTexture(true); mPageCurl.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); } else { mPageCurl.setFlipTexture(false); mPageCurl.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_LEFT)); } mPageCurl.reset(); mRenderer.addCurlMesh(mPageCurl); } }
/** Switches meshes and loads new bitmaps if available. Updated to support 2 pages in landscape */ private void startCurl(int page) { switch (page) { // Once right side page is curled, first right page is assigned into // curled page. And if there are more bitmaps available new bitmap is // loaded into right side mesh. case CURL_RIGHT: { // Remove meshes from renderer. mRenderer.removeCurlMesh(mPageLeft); mRenderer.removeCurlMesh(mPageRight); mRenderer.removeCurlMesh(mPageCurl); // We are curling right page. CurlMesh curl = mPageRight; mPageRight = mPageCurl; mPageCurl = curl; if (mCurrentIndex > 0) { mPageLeft.setFlipTexture(true); mPageLeft.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_LEFT)); mPageLeft.reset(); if (mRenderLeftPage) { mRenderer.addCurlMesh(mPageLeft); } } if (mCurrentIndex < mPageProvider.getPageCount() - 1) { updatePage(mPageRight.getTexturePage(), mCurrentIndex + 1); mPageRight.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); mPageRight.setFlipTexture(false); mPageRight.reset(); mRenderer.addCurlMesh(mPageRight); } // Add curled page to renderer. mPageCurl.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); mPageCurl.setFlipTexture(false); mPageCurl.reset(); mRenderer.addCurlMesh(mPageCurl); mCurlState = CURL_RIGHT; break; } // On left side curl, left page is assigned to curled page. And if // there are more bitmaps available before currentIndex, new bitmap // is loaded into left page. case CURL_LEFT: { // Remove meshes from renderer. mRenderer.removeCurlMesh(mPageLeft); mRenderer.removeCurlMesh(mPageRight); mRenderer.removeCurlMesh(mPageCurl); // We are curling left page. CurlMesh curl = mPageLeft; mPageLeft = mPageCurl; mPageCurl = curl; if (mCurrentIndex > 1) { updatePage(mPageLeft.getTexturePage(), mCurrentIndex - 2); mPageLeft.setFlipTexture(true); mPageLeft.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_LEFT)); mPageLeft.reset(); if (mRenderLeftPage) { mRenderer.addCurlMesh(mPageLeft); } } // If there is something to show on right page add it to renderer. if (mCurrentIndex < mPageProvider.getPageCount()) { mPageRight.setFlipTexture(false); mPageRight.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); mPageRight.reset(); mRenderer.addCurlMesh(mPageRight); } // How dragging previous page happens depends on view mode. if (mViewMode == SHOW_ONE_PAGE || (mCurlState == CURL_LEFT && mViewMode == SHOW_TWO_PAGES)) { mPageCurl.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_RIGHT)); mPageCurl.setFlipTexture(false); } else { mPageCurl.setRect(mRenderer.getPageRect(CurlRenderer.PAGE_LEFT)); mPageCurl.setFlipTexture(true); } mPageCurl.reset(); mRenderer.addCurlMesh(mPageCurl); mCurlState = CURL_LEFT; break; } } }