blob: 9168411d2c799d738b0144d3104832cf45636228 [file] [log] [blame]
Joe Onorato93839052009-08-06 20:34:32 -07001#pragma version(1)
2#pragma stateVertex(PV)
3#pragma stateFragment(PF)
4#pragma stateFragmentStore(PFS)
5
Joe Onorato43e7bcf2009-08-08 18:53:53 -07006#define PI 3.14159f
7
Joe Onorato43e7bcf2009-08-08 18:53:53 -07008// Variables from java ======
9
10// Parameters ======
11#define PARAM_BUBBLE_WIDTH 0
12#define PARAM_BUBBLE_HEIGHT 1
13#define PARAM_BUBBLE_BITMAP_WIDTH 2
14#define PARAM_BUBBLE_BITMAP_HEIGHT 3
Joe Onorato93839052009-08-06 20:34:32 -070015
Joe Onorato1feb3a82009-08-08 22:32:00 -070016// State ======
17#define STATE_ICON_COUNT 0
18#define STATE_SCROLL_X 1
Joe Onoratod769a632009-08-11 17:09:02 -070019#define STATE_FLING_TIME 2
20#define STATE_FLING_VELOCITY_X 3
21#define STATE_ADJUSTED_DECELERATION 4
22#define STATE_CURRENT_SCROLL_X 5 /* with fling offset applied */
Joe Onoratoeb2c02e2009-08-12 21:40:52 -070023#define STATE_FLING_DURATION 6
24#define STATE_FLING_END_POS 7
Joe Onorato93839052009-08-06 20:34:32 -070025
Joe Onorato43e7bcf2009-08-08 18:53:53 -070026// Scratch variables ======
Joe Onoratod769a632009-08-11 17:09:02 -070027#define SCRATCH_ADJUSTED_DECELERATION 0
Joe Onorato93839052009-08-06 20:34:32 -070028
Joe Onorato43e7bcf2009-08-08 18:53:53 -070029// Drawing constants, should be parameters ======
30#define SCREEN_WIDTH 480
31#define SCREEN_HEIGHT 854
32#define COLUMNS_PER_PAGE 4
33#define ROWS_PER_PAGE 4
34#define DIAMETER 8.0f
35
36#define PAGE_PADDING_TOP_PX 80
37#define CELL_PADDING_TOP_PX 5
38#define ICON_HEIGHT_PX 64
39#define ICON_LABEL_GUTTER_PX 5
40#define CELL_PADDING_BOTTOM_PX 5
41#define ROW_GUTTER_PX 10
42
43#define PAGE_PADDING_LEFT_PX 22
44#define CELL_WIDTH_PX 105
45#define ICON_WIDTH_PX 64
46#define COLUMN_GUTTER_PX 5
47#define LABEL_WIDTH_PX 105
48
49int
50count_pages(int iconCount)
Joe Onorato93839052009-08-06 20:34:32 -070051{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070052 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
53 int pages = iconCount / iconsPerPage;
54 if (pages*iconsPerPage != iconCount) {
Joe Onoratod769a632009-08-11 17:09:02 -070055 pages++;
Joe Onorato43e7bcf2009-08-08 18:53:53 -070056 }
Joe Onoratod769a632009-08-11 17:09:02 -070057 return pages;
58}
59
60int current_page(float scrollXPx)
61{
62 return -scrollXPx / SCREEN_WIDTH;
63}
64
65float
66modf(float x, float y)
67{
68 return x-(y*floorf(x/y));
Joe Onorato93839052009-08-06 20:34:32 -070069}
70
Joe Onorato43e7bcf2009-08-08 18:53:53 -070071int
Joe Onoratod769a632009-08-11 17:09:02 -070072main(int launchID)
Joe Onorato93839052009-08-06 20:34:32 -070073{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070074 // Clear to transparent
Joe Onorato93839052009-08-06 20:34:32 -070075 pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -070076
Joe Onorato43e7bcf2009-08-08 18:53:53 -070077 // icons & labels
Joe Onorato1feb3a82009-08-08 22:32:00 -070078 int iconCount = loadI32(ALLOC_STATE, STATE_ICON_COUNT);
Joe Onorato43e7bcf2009-08-08 18:53:53 -070079 int pageCount = count_pages(iconCount);
80
81 float densityScale = 2.0f / SCREEN_WIDTH;
82 float screenTop = SCREEN_HEIGHT/(float)SCREEN_WIDTH; // == (SCREEN_HEIGHT/2)*densityScale;
83
84 float pagePaddingTop = screenTop - (PAGE_PADDING_TOP_PX * densityScale);
85 float pageGutterY = ROW_GUTTER_PX * densityScale;
86 float cellHeight = (CELL_PADDING_TOP_PX + ICON_HEIGHT_PX + ICON_LABEL_GUTTER_PX
87 + loadI32(ALLOC_PARAMS, PARAM_BUBBLE_HEIGHT)
88 + CELL_PADDING_BOTTOM_PX + ROW_GUTTER_PX) * densityScale;
89 float cellPaddingTop = CELL_PADDING_TOP_PX * densityScale;
90 float iconHeight = ICON_HEIGHT_PX * densityScale;
91 float iconLabelGutter = ICON_LABEL_GUTTER_PX * densityScale;
92
93 float pagePaddingLeft = PAGE_PADDING_LEFT_PX * densityScale;
94 float cellWidth = CELL_WIDTH_PX * densityScale;
95 float iconWidth = ICON_WIDTH_PX * densityScale;
96 float columnGutter = COLUMN_GUTTER_PX * densityScale;
97
Joe Onorato43e7bcf2009-08-08 18:53:53 -070098 float labelWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_WIDTH) * densityScale;
99 float labelTextureWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_WIDTH) * densityScale;
100 float labelTextureHeight = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_HEIGHT) * densityScale;
101
Joe Onoratod769a632009-08-11 17:09:02 -0700102 float scrollXPx = loadI32(ALLOC_STATE, STATE_SCROLL_X);
103 float maxScrollX = -(pageCount-1) * SCREEN_WIDTH;
104 int done = 0;
105
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700106 // Clamp -- because java doesn't know how big the icons are
107 if (scrollXPx > 0) {
108 scrollXPx = 0;
109 }
110 if (scrollXPx < maxScrollX) {
111 scrollXPx = maxScrollX;
112 }
113
Joe Onoratod769a632009-08-11 17:09:02 -0700114 // If we've been given a velocity, start a fling
115 float flingVelocityPxMs = loadI32(ALLOC_STATE, STATE_FLING_VELOCITY_X);
116 if (flingVelocityPxMs != 0) {
117 // how many screens will this velocity do? TODO: use long
118 // G * ppi * friction // why G? // friction = 0.015
119 float deceleration = loadF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700120 float flingDurationMs;
Joe Onoratod769a632009-08-11 17:09:02 -0700121 if (deceleration == 0) {
122 // On the first frame, calculate which animation we're going to do. If it's
123 // going to end up less than halfway into a page, we'll bounce back the previous
124 // page. Otherwise, we'll adjust the deceleration so it just makes it to the
125 // page boundary.
126 if (flingVelocityPxMs > 0) {
127 deceleration = -1000;
128 } else {
129 deceleration = 1000;
130 }
131 // v' = v + at --> t = -v / a
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700132 // x' = x + vt + .5 a t^2
133 flingDurationMs = - flingVelocityPxMs / deceleration;
134 float endPos = scrollXPx + (flingVelocityPxMs*flingDurationMs)
135 + ((deceleration*flingDurationMs*flingDurationMs)/2);
Joe Onoratod769a632009-08-11 17:09:02 -0700136
137 if (endPos > 0) {
138 endPos = 0;
139 }
140 if (endPos < maxScrollX) {
141 endPos = maxScrollX;
142 }
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700143 float scrollOnPage = modf(endPos, SCREEN_WIDTH);
144 int endPage = -endPos/SCREEN_WIDTH;
145 if (flingVelocityPxMs < 0) {
146 if (scrollOnPage < (SCREEN_WIDTH/2)) {
147 // adjust the deceleration so we align on the page boundary
148 // a = 2(x-x0-v0t)/t^2
149 endPos = -(endPage+1) * SCREEN_WIDTH;
150 debugI32("endPos case", 1);
151 } else {
152 // TODO: bounce
153 endPos = -(endPage+1) * SCREEN_WIDTH;
154 debugI32("endPos case", 2);
155 }
156 } else {
157 if (scrollOnPage >= (SCREEN_WIDTH/2)) {
158 // adjust the deceleration so we align on the page boundary
159 endPos = -endPage * SCREEN_WIDTH;
160 debugI32("endPos case", 3);
161 } else {
162 // TODO: bounce
163 endPos = -endPage * SCREEN_WIDTH;
164 debugI32("endPos case", 4);
165 }
166 }
167 // v = v0 + at --> (v - v0) / t
168 deceleration = 2*(endPos-scrollXPx-(flingVelocityPxMs*flingDurationMs))
169 / (flingDurationMs*flingDurationMs);
170 endPos = scrollXPx + (flingVelocityPxMs*flingDurationMs)
171 + ((deceleration*flingDurationMs*flingDurationMs)/2);
172
173 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, deceleration);
174 storeF(ALLOC_STATE, STATE_FLING_DURATION, flingDurationMs);
175 storeF(ALLOC_STATE, STATE_FLING_END_POS, endPos);
176 } else {
177 flingDurationMs = loadF(ALLOC_STATE, STATE_FLING_DURATION);
Joe Onoratod769a632009-08-11 17:09:02 -0700178 }
179
180 // adjust the deceleration so we always hit a page boundary
181
182 int flingTime = loadI32(ALLOC_STATE, STATE_FLING_TIME);
183 int now = uptimeMillis();
184 float elapsedTime = (now - flingTime) / 1000.0f;
185 int animEndTime = -flingVelocityPxMs / deceleration;
186
Joe Onoratod769a632009-08-11 17:09:02 -0700187 int flingOffsetPx = (flingVelocityPxMs * elapsedTime)
188 + (deceleration * elapsedTime * elapsedTime / 2.0f);
189 scrollXPx += flingOffsetPx;
190
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700191 if (elapsedTime > flingDurationMs) {
192 scrollXPx = loadF(ALLOC_STATE, STATE_FLING_END_POS);
193 done = 1;
194 }
Joe Onoratod769a632009-08-11 17:09:02 -0700195 }
196
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700197 // Clamp
Joe Onoratod769a632009-08-11 17:09:02 -0700198 if (scrollXPx > 0) {
199 scrollXPx = 0;
200 }
201 if (scrollXPx < maxScrollX) {
202 scrollXPx = maxScrollX;
203 }
204
205 storeI32(ALLOC_STATE, STATE_CURRENT_SCROLL_X, scrollXPx);
206 if (done) {
207 storeI32(ALLOC_STATE, STATE_SCROLL_X, scrollXPx);
208 storeI32(ALLOC_STATE, STATE_FLING_VELOCITY_X, 0);
209 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, 0);
210 }
211
212 // don't draw everything, just the page before and after what we're viewing.
213 int currentPage = current_page(scrollXPx);
214 float screenWidth = SCREEN_WIDTH * densityScale;
215
216 float pageLeft = -1 + ((currentPage-1)*screenWidth);
217 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
218 int icon = (currentPage-1) * iconsPerPage;
219 if (icon < 0) {
220 icon = 0;
221 }
Joe Onorato1feb3a82009-08-08 22:32:00 -0700222 int page;
Joe Onoratod769a632009-08-11 17:09:02 -0700223 int lastIcon = icon + (iconsPerPage*3);
224 if (lastIcon >= iconCount) {
225 lastIcon = iconCount-1;
226 }
Joe Onorato1feb3a82009-08-08 22:32:00 -0700227 pageLeft += scrollXPx * densityScale;
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700228 while (icon <= lastIcon) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700229 // Bug makes 1.0f alpha fail.
230 color(1.0f, 1.0f, 1.0f, 0.99f);
231
232 float cellTop = pagePaddingTop;
233 int row;
Joe Onoratod769a632009-08-11 17:09:02 -0700234 for (row=0; row<ROWS_PER_PAGE && icon<=lastIcon; row++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700235 float s = pageLeft; // distance along the linear strip of icons in normalized coords
236 s += pagePaddingLeft;
237 int col;
Joe Onoratod769a632009-08-11 17:09:02 -0700238 for (col=0; col<COLUMNS_PER_PAGE && icon<=lastIcon; col++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700239 // icon
240 float iconLeft = s + ((cellWidth-iconWidth)/2.0f);
241 float iconRight = iconLeft + iconWidth;
242 float iconTop = cellTop - cellPaddingTop;
243 float iconBottom = iconTop - iconHeight;
Joe Onorato93839052009-08-06 20:34:32 -0700244
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700245 bindProgramFragment(NAMED_PF);
246 bindProgramFragmentStore(NAMED_PFS);
Joe Onorato93839052009-08-06 20:34:32 -0700247
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700248 bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
249 drawRect(iconLeft, iconTop, iconRight, iconBottom, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700250
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700251 // label
252 float labelLeft = s + ((cellWidth-labelWidth)/2.0f);
253 float labelTop = iconBottom - iconLabelGutter;
Joe Onorato93839052009-08-06 20:34:32 -0700254
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700255 bindProgramFragment(NAMED_PFText);
256 bindProgramFragmentStore(NAMED_PFSText);
Joe Onorato93839052009-08-06 20:34:32 -0700257
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700258 bindTexture(NAMED_PFText, 0, loadI32(ALLOC_LABEL_IDS, icon));
259 drawRect(labelLeft, labelTop, labelLeft+labelTextureWidth,
260 labelTop-labelTextureHeight, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700261
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700262 s += cellWidth + columnGutter;
263 icon++;
Joe Onorato93839052009-08-06 20:34:32 -0700264 }
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700265 cellTop -= cellHeight;
Joe Onorato93839052009-08-06 20:34:32 -0700266 }
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700267 pageLeft += 2.0f;
Joe Onorato93839052009-08-06 20:34:32 -0700268 }
269
Joe Onoratod769a632009-08-11 17:09:02 -0700270 return !done;
Joe Onorato93839052009-08-06 20:34:32 -0700271}
272