Enable scrolling

Our thumbnail grid has 15 images. If your phone has more than 15 photos, you'll need to scroll through the list. For this project, we'll implement a simple mechanic to scroll the list up and down, using triangular scroll buttons.

Creating the Triangle component

Like other RenderObjects in our RenderBox, the Triangle component defines coordinates, normals, indices, and other data that describes a triangle. We create a constructor method that allocates buffers. Like the Plane component, we want to use the BorderMaterial class so that it can be highlighted when selected. And like the Plane component, it will determine when the user is looking at it. Without further ado, here's the code.

Create a new Java class file, Triangle.java, in the RenderBoxExt/components folder. We begin by declaring it extends RenderObject and by declaring the following variables:

public class Triangle extends RenderObject {

    /*
    Special triangle for border shader

    *   0/3 (0,1,0)/(0,1,0) (0,1)/(1,1)
              /|
             / | 
            *--*--*
            1  2  4
     */

    private static final float YAW_LIMIT = 0.15f;
    private static final float PITCH_LIMIT = 0.15f;
    public static final float[] COORDS = new float[] {
            0f, 1.0f, 0.0f,
            -1.0f, -1.0f, 0.0f,
            0.0f, -1.0f, 0.0f,
            0f, 1.0f, 0.0f,
            1.0f, -1.0f, 0.0f,
    };
    public static final float[] TEX_COORDS = new float[] {
            0f, 1f,
            0f, 0f,
            0.5f, 0f,
            1f, 1f,
            1f, 0f
    };
    public static final float[] COLORS = new float[] {
            0.5f, 0.5f, 0.5f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f
    };
    public static final float[] NORMALS = new float[] {
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f,
            0.0f, 0.0f, -1.0f
    };
    public static final short[] INDICES = new short[] {
            1, 0, 2,
            2, 3, 4
    };

    private static FloatBuffer vertexBuffer;
    private static FloatBuffer colorBuffer;
    private static FloatBuffer normalBuffer;
    private static FloatBuffer texCoordBuffer;
    private static ShortBuffer indexBuffer;
    static final int numIndices = 6;

    static boolean setup;
}

In case it's not clear as to why we need this 2-triangle triangle, it has to do with how the UVs work. You can't get a full border with just one triangle, at least not the way we've written the border shader.

Add a constructor, along with an allocateBuffers helper:

    public Triangle(){
        super();
        allocateBuffers();
    }

    public static void allocateBuffers(){
        //Already allocated?
        if (vertexBuffer != null) return;
        vertexBuffer = allocateFloatBuffer(COORDS);
        texCoordBuffer = allocateFloatBuffer(TEX_COORDS);
        colorBuffer = allocateFloatBuffer(COLORS);
        normalBuffer = allocateFloatBuffer(NORMALS);
        indexBuffer = allocateShortBuffer(INDICES);
    }

We can create various materials, but we really only plan to use BorderMaterial, so let's support this like we did with Plane:

    public void setupBorderMaterial(BorderMaterial material){
        this.material = material;
        material.setBuffers(vertexBuffer, texCoordBuffer, indexBuffer, numIndices);
    }

Adding triangles to the UI

In MainActivity, we can add the up and down triangle buttons to scroll the thumbnails. At the top of the MainActivity class, declare variables for the triangles and their materials:

    Triangle up, down;
    BorderMaterial upMaterial, downMaterial;
    boolean upSelected, downSelected;

Define a setupScrollButtons helper as follows:

    void setupScrollButtons() {
        up = new Triangle();
        upMaterial = new BorderMaterial();
        up.setupBorderMaterial(upMaterial);
        new Transform()
            .setLocalPosition(0,6,-5)
            .addComponent(up);

        down = new Triangle();
        downMaterial = new BorderMaterial();
        down.setupBorderMaterial(downMaterial);
        new Transform()
            .setLocalPosition(0,-6,-5)
            .setLocalRotation(0,0,180)
            .addComponent(down);
    }

Then, call it from the setup method:

    public void setup() {
        setupMaxTextureSize();
        setupBackground();
        setupScreen();
        loadImageList(imagesPath);
        setupThumbnailGrid();
        setupScrollButtons();
        updateThumbnails();
    }

When you run the project, you will see the arrows:

Adding triangles to the UI

Interacting with the scroll buttons

Now we will detect when the user is looking at a triangle, by using isLooking in selectObject (which is called from the postDraw hook):

    void selectObject() {
        ...

        if (up.isLooking) {
            upSelected = true;
            upMaterial.borderColor = selectedColor;
        } else {
            upSelected = false;
            upMaterial.borderColor = normalColor;
        }

        if (down.isLooking) {
            downSelected = true;
            downMaterial.borderColor = selectedColor;
        } else {
            downSelected = false;
            downMaterial.borderColor = normalColor;
        }
    }

Implementing the scrolling method

To implement scrolling the thumbnail images, we'll keep the grid planes in place and just scroll the textures. Use an offset variable to hold the index of the first image in the grid:

    static int thumbOffset = 0;

Now, modify the updateThumbnails method to populate the plane textures using the thumb offset as the starting index of the image textures:

    void updateThumbnails() {
        int count = thumbOffset;
        for (Thumbnail thumb : thumbnails) {
        . . .

We can perform scrolling when the up or down arrows are pressed in onCardboardTrigger by shifting the thumbOffset variable one row at a time (GRID_X):

    public void onCardboardTrigger() {
        if (selectedThumbnail != null) {
            vibrator.vibrate(25);
            showImage(selectedThumbnail.image);
        }
        if (upSelected) {
            // scroll up
            thumbOffset -= GRID_X;
            if (thumbOffset < 0) {
                thumbOffset = images.size() - GRID_X;
            }
            vibrator.vibrate(25);
            updateThumbnails();
        }
        if (downSelected) {
            // scroll down
            if (thumbOffset < images.size()) {
                thumbOffset += GRID_X;
            } else {
                thumbOffset = 0;
            }
            vibrator.vibrate(25);
            updateThumbnails();
        }
    }

As with showImage, the updateThumbnails method needs to run on the render thread:

    void updateThumbnails() {
        cardboardView.queueEvent(new Runnable() {
            @Override
            public void run() {
                ...

Run the project. You can now click on the up and down arrows to scroll through your photos.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset