package com.cooliris.media; public final class GridCameraManager { private final GridCamera mCamera; private static final Pool<Vector3f> sPool; static { final Vector3f[] vectorPool = new Vector3f[128]; int length = vectorPool.length; for (int i = 0; i < length; ++i) { vectorPool[i] = new Vector3f(); } sPool = new Pool<Vector3f>(vectorPool); } public GridCameraManager(final GridCamera camera) { mCamera = camera; } public void centerCameraForSlot(LayoutInterface layout, int slotIndex, float baseConvergence, Vector3f deltaAnchorPositionIn, int selectedSlotIndex, float zoomValue, float imageTheta, int state) { final GridCamera camera = mCamera; final Pool<Vector3f> pool = sPool; synchronized (camera) { final boolean zoomin = (selectedSlotIndex != Shared.INVALID); final int theta = (int) imageTheta; final int portrait = (theta / 90) % 2; if (slotIndex == selectedSlotIndex) { camera.mConvergenceSpeed = baseConvergence * (zoomin ? 2.0f : 2.0f); } final float oneByZoom = 1.0f / zoomValue; if (slotIndex >= 0) { final Vector3f position = pool.create(); final Vector3f deltaAnchorPosition = pool.create(); try { deltaAnchorPosition.set(deltaAnchorPositionIn); GridCameraManager.getSlotPositionForSlotIndex(slotIndex, camera, layout, deltaAnchorPosition, position); position.x = (zoomValue == 1.0f) ? ((position.x) * camera.mOneByScale) : camera.mLookAtX; position.y = (zoomValue == 1.0f) ? 0 : camera.mLookAtY; if (state == GridLayer.STATE_MEDIA_SETS || state == GridLayer.STATE_TIMELINE) { position.y = -0.1f; } float width = camera.mItemWidth; float height = camera.mItemHeight; if (portrait != 0) { float temp = width; width = height; height = temp; } camera.moveTo(position.x, position.y, zoomin ? camera.getDistanceToFitRect(width * oneByZoom, height * oneByZoom) : 0); } finally { pool.delete(position); pool.delete(deltaAnchorPosition); } } else { camera.moveYTo(0); camera.moveZTo(0); } } } // CR: line too long. Documentation--what are the semantics of the return // value? /** */ public boolean constrainCameraForSlot(LayoutInterface layout, int slotIndex, Vector3f deltaAnchorPositionIn, float currentFocusItemWidth, float currentFocusItemHeight) { final GridCamera camera = mCamera; final Pool<Vector3f> pool = sPool; boolean retVal = false; synchronized (camera) { final Vector3f position = pool.create(); final Vector3f deltaAnchorPosition = pool.create(); final Vector3f topLeft = pool.create(); final Vector3f bottomRight = pool.create(); final Vector3f imgTopLeft = pool.create(); final Vector3f imgBottomRight = pool.create(); try { if (slotIndex >= 0) { deltaAnchorPosition.set(deltaAnchorPositionIn); GridCameraManager.getSlotPositionForSlotIndex(slotIndex, camera, layout, deltaAnchorPosition, position); position.x *= camera.mOneByScale; position.y = 0.0f; float width = (currentFocusItemWidth / 2); float height = (currentFocusItemHeight / 2); imgTopLeft.set(position.x - width, position.y - height, 0); imgBottomRight.set(position.x + width, position.y + height, 0); camera.convertToCameraSpace(0, 0, 0, topLeft); camera.convertToCameraSpace(camera.mWidth, camera.mHeight, 0, bottomRight); float leftExtent = topLeft.x - imgTopLeft.x; float rightExtent = bottomRight.x - imgBottomRight.x; camera.mConvergenceSpeed = 2.0f; if (leftExtent < 0) { retVal = true; camera.moveBy(-leftExtent, 0, 0); } if (rightExtent > 0) { retVal = true; camera.moveBy(-rightExtent, 0, 0); } float topExtent = topLeft.y - imgTopLeft.y; float bottomExtent = bottomRight.y - imgBottomRight.y; if (topExtent < 0) { camera.moveBy(0, -topExtent, 0); } if (bottomExtent > 0) { camera.moveBy(0, -bottomExtent, 0); } } } finally { pool.delete(position); pool.delete(deltaAnchorPosition); pool.delete(topLeft); pool.delete(bottomRight); pool.delete(imgTopLeft); pool.delete(imgBottomRight); } } return retVal; } public void computeVisibleRange(MediaFeed feed, LayoutInterface layout, Vector3f deltaAnchorPositionIn, IndexRange outVisibleRange, IndexRange outBufferedVisibleRange, IndexRange outCompleteRange, int state) { GridCamera camera = mCamera; Pool<Vector3f> pool = sPool; float offset = (camera.mLookAtX * camera.mScale); int itemWidth = camera.mItemWidth; float maxIncrement = camera.mWidth * 0.5f + itemWidth; float left = -maxIncrement + offset; float right = left + 2.0f * maxIncrement; if (state == GridLayer.STATE_MEDIA_SETS || state == GridLayer.STATE_TIMELINE) { right += (itemWidth * 0.5f); } float top = -maxIncrement; float bottom = camera.mHeight + maxIncrement; // the hint to compute the visible display items int numSlots = 0; if (feed != null) { numSlots = feed.getNumSlots(); } synchronized (outCompleteRange) { outCompleteRange.set(0, numSlots - 1); } Vector3f position = pool.create(); Vector3f deltaAnchorPosition = pool.create(); try { int firstVisibleSlotIndex = 0; int lastVisibleSlotIndex = numSlots - 1; int leftEdge = firstVisibleSlotIndex; int rightEdge = lastVisibleSlotIndex; int index = (leftEdge + rightEdge) / 2; lastVisibleSlotIndex = firstVisibleSlotIndex; deltaAnchorPosition.set(deltaAnchorPositionIn); while (index != leftEdge) { GridCameraManager.getSlotPositionForSlotIndex(index, camera, layout, deltaAnchorPosition, position); if (FloatUtils.boundsContainsPoint(left, right, top, bottom, position.x, position.y)) { // this index is visible firstVisibleSlotIndex = index; lastVisibleSlotIndex = index; break; } else { if (position.x > left) { rightEdge = index; } else { leftEdge = index; } index = (leftEdge + rightEdge) / 2; } } // CR: comments would make me a happy panda. while (firstVisibleSlotIndex >= 0 && firstVisibleSlotIndex < numSlots) { GridCameraManager.getSlotPositionForSlotIndex(firstVisibleSlotIndex, camera, layout, deltaAnchorPosition, position); // CR: !fubar instead of fubar == false. if (FloatUtils.boundsContainsPoint(left, right, top, bottom, position.x, position.y) == false) { ++firstVisibleSlotIndex; break; } else { --firstVisibleSlotIndex; } } while (lastVisibleSlotIndex >= 0 && lastVisibleSlotIndex < numSlots) { GridCameraManager.getSlotPositionForSlotIndex(lastVisibleSlotIndex, camera, layout, deltaAnchorPosition, position); if (FloatUtils.boundsContainsPoint(left, right, top, bottom, position.x, position.y) == false) { --lastVisibleSlotIndex; break; } else { ++lastVisibleSlotIndex; } } if (firstVisibleSlotIndex < 0) firstVisibleSlotIndex = 0; if (lastVisibleSlotIndex >= numSlots) lastVisibleSlotIndex = numSlots - 1; while (((lastVisibleSlotIndex - firstVisibleSlotIndex) * GridLayer.MAX_ITEMS_PER_SLOT + GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT - 1) > GridLayer.MAX_ITEMS_DRAWABLE) { lastVisibleSlotIndex--; } synchronized (outVisibleRange) { outVisibleRange.set(firstVisibleSlotIndex, lastVisibleSlotIndex); } if (feed != null) { feed.setVisibleRange(firstVisibleSlotIndex, lastVisibleSlotIndex); } final int buffer = 24; firstVisibleSlotIndex = ((firstVisibleSlotIndex - buffer) / buffer) * buffer; lastVisibleSlotIndex += buffer; lastVisibleSlotIndex = (lastVisibleSlotIndex / buffer) * buffer; if (firstVisibleSlotIndex < 0) { firstVisibleSlotIndex = 0; } if (lastVisibleSlotIndex >= numSlots) { lastVisibleSlotIndex = numSlots - 1; } while (((lastVisibleSlotIndex - firstVisibleSlotIndex) * GridLayer.MAX_ITEMS_PER_SLOT + GridLayer.MAX_DISPLAYED_ITEMS_PER_SLOT - 1) > GridLayer.MAX_ITEMS_DRAWABLE) { lastVisibleSlotIndex--; } synchronized (outBufferedVisibleRange) { outBufferedVisibleRange.set(firstVisibleSlotIndex, lastVisibleSlotIndex); } } finally { pool.delete(position); pool.delete(deltaAnchorPosition); } } public static final void getSlotPositionForSlotIndex(int slotIndex, GridCamera camera, LayoutInterface layout, Vector3f deltaAnchorPosition, Vector3f outVal) { layout.getPositionForSlotIndex(slotIndex, camera.mItemWidth, camera.mItemHeight, outVal); outVal.subtract(deltaAnchorPosition); } public static final float getFillScreenZoomValue(GridCamera camera, Pool<Vector3f> pool, float currentFocusItemWidth, float currentFocusItemHeight) { final Vector3f topLeft = pool.create(); final Vector3f bottomRight = pool.create(); float potentialZoomValue = 1.0f; try { camera.convertToCameraSpace(0, 0, 0, topLeft); camera.convertToCameraSpace(camera.mWidth, camera.mHeight, 0, bottomRight); float xExtent = Math.abs(topLeft.x - bottomRight.x) / currentFocusItemWidth; float yExtent = Math.abs(topLeft.y - bottomRight.y) / currentFocusItemHeight; potentialZoomValue = Math.max(xExtent, yExtent); } finally { pool.delete(topLeft); pool.delete(bottomRight); } return potentialZoomValue; } }