Use structures for leaves and add dropping leaves.

Change-Id: I60c683aeb5447445fedc766c1c7a6323be075cb5
diff --git a/res/raw/fall.rs b/res/raw/fall.rs
index 71ff166..c60711d 100644
--- a/res/raw/fall.rs
+++ b/res/raw/fall.rs
@@ -17,24 +17,8 @@
 #pragma stateFragment(PFBackground)
 #pragma stateStore(PFSBackground)
 
-#define RSID_STATE 0
 #define RSID_RIPPLE_MAP 1
 #define RSID_REFRACTION_MAP 2
-#define RSID_LEAVES 3
-#define RSID_DROP 4
-
-#define LEAF_STRUCT_FIELDS_COUNT 11
-#define LEAF_STRUCT_X 0
-#define LEAF_STRUCT_Y 1
-#define LEAF_STRUCT_SCALE 2
-#define LEAF_STRUCT_ANGLE 3
-#define LEAF_STRUCT_SPIN 4
-#define LEAF_STRUCT_U1 5
-#define LEAF_STRUCT_U2 6
-#define LEAF_STRUCT_ALTITUDE 7
-#define LEAF_STRUCT_RIPPLED 8
-#define LEAF_STRUCT_DELTAX 9
-#define LEAF_STRUCT_DELTAY 10
 
 #define LEAVES_TEXTURES_COUNT 4
 
@@ -65,6 +49,29 @@
     return x + 1 + (y + 1) * (width + 2);
 }
 
+void initLeaves() {
+    struct Leaves_s *leaf = Leaves;
+    int leavesCount = State->leavesCount;
+    float height = State->glHeight;
+
+    int i;
+    for (i = 0; i < leavesCount; i ++) {
+        int sprite = randf(LEAVES_TEXTURES_COUNT);
+        leaf->x = randf2(-1.0f, 1.0f);
+        leaf->y = randf2(-height / 2.0f, height / 2.0f);
+        leaf->scale = randf2(0.4f, 0.5f);
+        leaf->angle = randf2(0.0f, 360.0f);
+        leaf->spin = degf(randf2(-0.02f, 0.02f)) / 4.0f;
+        leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
+        leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
+        leaf->altitude = -1.0f;
+        leaf->rippled = 1.0f;
+        leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
+        leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
+        leaf++;
+    }
+}
+
 void dropWithStrength(int x, int y, int r, int s) {
     int width = State->meshWidth;
     int height = State->meshHeight;
@@ -117,7 +124,7 @@
     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
     int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
 
-    storeI32(RSID_STATE, OFFSETOF_WorldState_rippleIndex, 1 - index);
+    State->rippleIndex = 1 - index;
 
     int a = 1;
     int b = width + 2;
@@ -126,8 +133,7 @@
         int w = width;
         while (w) {
             int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next;
-            droplet -= (droplet >> DAMP);
-            *next = droplet;
+            *next = droplet - (droplet >> DAMP);
             current += 1;
             next += 1;
             w -= 1;
@@ -152,7 +158,7 @@
 }
 
 void generateRipples() {
-    int rippleMapSize = loadI32(RSID_STATE, OFFSETOF_WorldState_rippleMapSize);
+    int rippleMapSize = State->rippleMapSize;
     int width = State->meshWidth;
     int height = State->meshHeight;
     int index = State->rippleIndex;
@@ -165,8 +171,8 @@
     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
     struct vert_s *vert = (struct vert_s *)vertices;
 
-    float fw = 1.f / width;
-    float fh = 1.f / height;
+    float fw = 1.0f / width;
+    float fh = 1.0f / height;
     float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
 
     int h = height - 1;
@@ -236,30 +242,26 @@
     }
 }
 
-void drawLeaf(int index, float* vertices, int meshWidth, int meshHeight,
-        float glWidth, float glHeight) {
-
-    float *leafStruct = loadArrayF(RSID_LEAVES, index);
-
-    float x = leafStruct[LEAF_STRUCT_X];
+void drawLeaf(struct Leaves_s *leaf, int meshWidth, int meshHeight, float glWidth, float glHeight) {
+    float x = leaf->x;
     float x1 = x - LEAF_SIZE;
     float x2 = x + LEAF_SIZE;
 
-    float y = leafStruct[LEAF_STRUCT_Y];
+    float y = leaf->y;
     float y1 = y - LEAF_SIZE;
     float y2 = y + LEAF_SIZE;
 
-    float u1 = leafStruct[LEAF_STRUCT_U1];
-    float u2 = leafStruct[LEAF_STRUCT_U2];
+    float u1 = leaf->u1;
+    float u2 = leaf->u2;
 
     float z1 = 0.0f;
     float z2 = 0.0f;
     float z3 = 0.0f;
     float z4 = 0.0f;
 
-    float a = leafStruct[LEAF_STRUCT_ALTITUDE];
-    float s = leafStruct[LEAF_STRUCT_SCALE];
-    float r = leafStruct[LEAF_STRUCT_ANGLE];
+    float a = leaf->altitude;
+    float s = leaf->scale;
+    float r = leaf->angle;
 
     float tz = 0.0f;
     if (a > 0.0f) {
@@ -270,8 +272,30 @@
     x2 -= x;
     y1 -= y;
     y2 -= y;
+    
+    float matrix[16];    
 
-    float matrix[16];
+    if (a > 0.0f) {
+        color(0.0f, 0.0f, 0.0f, 0.15f);
+    
+        matrixLoadIdentity(matrix);
+        matrixTranslate(matrix, x, y, 0.0f);
+        matrixScale(matrix, s, s, 1.0f);
+        matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
+        vpLoadModelMatrix(matrix);
+
+        drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
+                          x2, y1, z2, u2, 1.0f,
+                          x2, y2, z3, u2, 0.0f,
+                          x1, y2, z4, u1, 0.0f);
+
+        float alpha = 1.0f;
+        if (a >= 0.4f) alpha = 1.0f - (a - 0.5f) / 0.1f;
+        color(1.0f, 1.0f, 1.0f, alpha);
+    } else {
+        color(1.0f, 1.0f, 1.0f, 1.0f);
+    }
+
     matrixLoadIdentity(matrix);
     matrixTranslate(matrix, x, y, tz);
     matrixScale(matrix, s, s, 1.0f);
@@ -283,65 +307,64 @@
                       x2, y2, z3, u2, 0.0f,
                       x1, y2, z4, u1, 0.0f);
 
-    float spin = leafStruct[LEAF_STRUCT_SPIN];
+    float spin = leaf->spin;
     if (a <= 0.0f) {
-        float rippled = leafStruct[LEAF_STRUCT_RIPPLED];
+        float rippled = leaf->rippled;
         if (rippled < 0.0f) {
             drop(((x + glWidth * 0.5f) / glWidth) * meshWidth,
-                 meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight,
-                 DROP_RADIUS);
+                 meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight, 1);
             spin /= 4.0f;
-            leafStruct[LEAF_STRUCT_SPIN] = spin;
-            leafStruct[LEAF_STRUCT_RIPPLED] = 1.0f;
-        } else {
-//            dropWithStrength(((x + glWidth / 2.0f) / glWidth) * meshWidth,
-//                meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
-//                2, 5);
+            leaf->spin = spin;
+            leaf->rippled = 1.0f;
         }
-        leafStruct[LEAF_STRUCT_X] = x + leafStruct[LEAF_STRUCT_DELTAX];
-        leafStruct[LEAF_STRUCT_Y] = y + leafStruct[LEAF_STRUCT_DELTAY];
+        leaf->x = x + leaf->deltaX;
+        leaf->y = y + leaf->deltaY;
         r += spin;
-        leafStruct[LEAF_STRUCT_ANGLE] = r;
+        leaf->angle = r;
     } else {
         a -= 0.005f;
-        leafStruct[LEAF_STRUCT_ALTITUDE] = a;
+        leaf->altitude = a;
         r += spin * 2.0f;
-        leafStruct[LEAF_STRUCT_ANGLE] = r;
+        leaf->angle = r;
     }
 
     if (-LEAF_SIZE * s + x > glWidth / 2.0f || LEAF_SIZE * s + x < -glWidth / 2.0f ||
-        LEAF_SIZE * s + y < -glHeight / 2.0f) {
+            LEAF_SIZE * s + y < -glHeight / 2.0f) {
 
         int sprite = randf(LEAVES_TEXTURES_COUNT);
-        leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);
-        leafStruct[LEAF_STRUCT_Y] = glHeight / 2.0f + LEAF_SIZE * 2 * randf(1.0f);
-        leafStruct[LEAF_STRUCT_SCALE] = randf2(0.4f, 0.5f);
-        leafStruct[LEAF_STRUCT_SPIN] = degf(randf2(-0.02f, 0.02f)) / 4.0f;
-        leafStruct[LEAF_STRUCT_U1] = sprite / (float) LEAVES_TEXTURES_COUNT;
-        leafStruct[LEAF_STRUCT_U2] = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
-        leafStruct[LEAF_STRUCT_DELTAX] = randf2(-0.02f, 0.02f) / 60.0f;
-        leafStruct[LEAF_STRUCT_DELTAY] = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
+        leaf->x = randf2(-1.0f, 1.0f);
+        leaf->y = randf2(-glHeight / 2.0f, glHeight / 2.0f);
+        leaf->scale = randf2(0.4f, 0.5f);
+        leaf->spin = degf(randf2(-0.02f, 0.02f)) / 4.0f;
+        leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
+        leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
+        leaf->altitude = 0.6f;
+        leaf->rippled = -1.0f;
+        leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
+        leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
     }
 }
 
 void drawLeaves() {
-    bindProgramFragment(NAMED_PFBackground);
+    bindProgramFragment(NAMED_PFSky);
     bindProgramFragmentStore(NAMED_PFSLeaf);
     bindProgramVertex(NAMED_PVSky);
-    bindTexture(NAMED_PFBackground, 0, NAMED_TLeaves);
+    bindTexture(NAMED_PFSky, 0, NAMED_TLeaves);
+
+    color(1.0f, 1.0f, 1.0f, 1.0f);
 
     int leavesCount = State->leavesCount;
-    int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
     int width = State->meshWidth;
     int height = State->meshHeight;
     float glWidth = State->glWidth;
     float glHeight = State->glHeight;
 
-    float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
+    struct Leaves_s *leaf = Leaves;
 
     int i = 0;
-    for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
-        drawLeaf(i, vertices, width, height, glWidth, glHeight);
+    for ( ; i < leavesCount; i += 1) {
+        drawLeaf(leaf, width, height, glWidth, glHeight);
+        leaf += 1;
     }
 
     float matrix[16];
diff --git a/src/com/android/wallpaper/fall/FallRS.java b/src/com/android/wallpaper/fall/FallRS.java
index 10ceab4..06bf97b 100644
--- a/src/com/android/wallpaper/fall/FallRS.java
+++ b/src/com/android/wallpaper/fall/FallRS.java
@@ -25,6 +25,7 @@
 import android.renderscript.Light;
 import android.renderscript.Type;
 import android.renderscript.SimpleMesh;
+import android.renderscript.Script;
 import static android.renderscript.Sampler.Value.LINEAR;
 import static android.renderscript.Sampler.Value.WRAP;
 import static android.renderscript.ProgramStore.DepthFunc.*;
@@ -47,46 +48,17 @@
     private static final int RSID_STATE = 0;
 
     private static final int TEXTURES_COUNT = 3;
-    private static final int LEAVES_TEXTURES_COUNT = 4;
     private static final int RSID_TEXTURE_RIVERBED = 0;
     private static final int RSID_TEXTURE_LEAVES = 1;
     private static final int RSID_TEXTURE_SKY = 2;
 
     private static final int RSID_RIPPLE_MAP = 1;
-
     private static final int RSID_REFRACTION_MAP = 2;
-
     private static final int RSID_LEAVES = 3;
-    private static final int LEAVES_COUNT = 14;
-    private static final int LEAF_STRUCT_FIELDS_COUNT = 11;
-    private static final int LEAF_STRUCT_X = 0;
-    private static final int LEAF_STRUCT_Y = 1;
-    private static final int LEAF_STRUCT_SCALE = 2;
-    private static final int LEAF_STRUCT_ANGLE = 3;
-    private static final int LEAF_STRUCT_SPIN = 4;
-    private static final int LEAF_STRUCT_U1 = 5;
-    private static final int LEAF_STRUCT_U2 = 6;
-    private static final int LEAF_STRUCT_ALTITUDE = 7;
-    private static final int LEAF_STRUCT_RIPPLED = 8;
-    private static final int LEAF_STRUCT_DELTAX = 9;
-    private static final int LEAF_STRUCT_DELTAY = 10;
-
-    class Leaf {
-        float x;
-        float y;
-        float scale;
-        float angle;
-        float spin;
-        float u1;
-        float u2;
-        float altitude;
-        float rippled;
-        float deltaX;
-        float deltaY;
-    }
-
     private static final int RSID_DROP = 4;
 
+    private static final int LEAVES_COUNT = 14;
+
     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
 
     @SuppressWarnings({"FieldCanBeLocal"})
@@ -125,6 +97,8 @@
     private Allocation mRefractionMap;
 
     private Allocation mLeaves;
+    private Type mLeavesType;
+    
     private float mGlHeight;
 
     public FallRS(int width, int height) {
@@ -158,7 +132,9 @@
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setType(mStateType, "State", RSID_STATE);
         sb.setType(mDropType, "Drop", RSID_DROP);
+        sb.setType(mLeavesType, "Leaves", RSID_LEAVES);
         sb.setScript(mResources, R.raw.fall);
+        Script.Invokable invokable = sb.addInvokable("initLeaves");
         sb.setRoot(true);
 
         ScriptC script = sb.create();
@@ -171,6 +147,8 @@
         script.bindAllocation(mLeaves, RSID_LEAVES);
         script.bindAllocation(mDropState, RSID_DROP);
 
+        invokable.execute();
+
         return script;
     }
 
@@ -249,12 +227,8 @@
     }
 
     private void createLeaves() {
-        final float[] leaves = new float[LEAVES_COUNT * LEAF_STRUCT_FIELDS_COUNT];
-        mLeaves = Allocation.createSized(mRS, USER_F32(mRS), leaves.length);
-        for (int i = 0; i < leaves.length; i += LEAF_STRUCT_FIELDS_COUNT) {
-            createLeaf(leaves, i);
-        }
-        mLeaves.data(leaves);
+        mLeavesType = Type.createFromClass(mRS, Leaf.class, LEAVES_COUNT, "Leaf");
+        mLeaves = Allocation.createTyped(mRS, mLeavesType);        
     }
 
     private void createRefractionMap() {
@@ -323,21 +297,19 @@
         mDropState.data(mDrop);
     }
 
-    private void createLeaf(float[] leaves, int index) {
-        int sprite = random(LEAVES_TEXTURES_COUNT);
-        //noinspection PointlessArithmeticExpression
-        leaves[index + LEAF_STRUCT_X] = random(-1.0f, 1.0f);
-        leaves[index + LEAF_STRUCT_Y] = random(-mGlHeight / 2.0f, mGlHeight / 2.0f);
-        leaves[index + LEAF_STRUCT_SCALE] = random(0.4f, 0.5f);
-        leaves[index + LEAF_STRUCT_ANGLE] = random(0.0f, 360.0f);
-        leaves[index + LEAF_STRUCT_SPIN] = degrees(random(-0.02f, 0.02f)) / 4.0f;
-        leaves[index + LEAF_STRUCT_U1] = sprite / (float) LEAVES_TEXTURES_COUNT;
-        leaves[index + LEAF_STRUCT_U2] = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
-        leaves[index + LEAF_STRUCT_ALTITUDE] = -1.0f;
-        leaves[index + LEAF_STRUCT_RIPPLED] = 1.0f;
-        leaves[index + LEAF_STRUCT_DELTAX] = random(-0.02f, 0.02f) / 60.0f;
-        leaves[index + LEAF_STRUCT_DELTAY] = -0.08f * random(0.9f, 1.1f) / 60.0f;
-    }
+    static class Leaf {
+        public float x;
+        public float y;
+        public float scale;
+        public float angle;
+        public float spin;
+        public float u1;
+        public float u2;
+        public float altitude;
+        public float rippled;
+        public float deltaX;
+        public float deltaY;
+    }    
 
     private void loadTextures() {
         final Allocation[] textures = new Allocation[TEXTURES_COUNT];
@@ -347,8 +319,7 @@
 
         final int count = textures.length;
         for (int i = 0; i < count; i++) {
-            final Allocation texture = textures[i];
-            texture.uploadToTexture(0);
+            textures[i].uploadToTexture(0);
         }
     }