blob: b8f3341aa1e2152fe11deeb8664d9ee7688bae66 [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
Joe Onorato9c1289c2009-08-17 11:03:03 -040022
23/* with fling offset applied */
24#define STATE_CURRENT_SCROLL_X 5
25
Joe Onoratoeb2c02e2009-08-12 21:40:52 -070026#define STATE_FLING_DURATION 6
27#define STATE_FLING_END_POS 7
Joe Onorato93839052009-08-06 20:34:32 -070028
Joe Onorato43e7bcf2009-08-08 18:53:53 -070029// Scratch variables ======
Joe Onoratod769a632009-08-11 17:09:02 -070030#define SCRATCH_ADJUSTED_DECELERATION 0
Joe Onorato93839052009-08-06 20:34:32 -070031
Joe Onorato43e7bcf2009-08-08 18:53:53 -070032// Drawing constants, should be parameters ======
33#define SCREEN_WIDTH 480
34#define SCREEN_HEIGHT 854
35#define COLUMNS_PER_PAGE 4
36#define ROWS_PER_PAGE 4
37#define DIAMETER 8.0f
38
39#define PAGE_PADDING_TOP_PX 80
40#define CELL_PADDING_TOP_PX 5
41#define ICON_HEIGHT_PX 64
Joe Onorato9c1289c2009-08-17 11:03:03 -040042#define ICON_TEXTURE_HEIGHT_PX 128
Joe Onorato43e7bcf2009-08-08 18:53:53 -070043#define ICON_LABEL_GUTTER_PX 5
44#define CELL_PADDING_BOTTOM_PX 5
45#define ROW_GUTTER_PX 10
46
47#define PAGE_PADDING_LEFT_PX 22
48#define CELL_WIDTH_PX 105
49#define ICON_WIDTH_PX 64
Joe Onorato9c1289c2009-08-17 11:03:03 -040050#define ICON_TEXTURE_WIDTH_PX 128
Joe Onorato43e7bcf2009-08-08 18:53:53 -070051#define COLUMN_GUTTER_PX 5
52#define LABEL_WIDTH_PX 105
53
54int
55count_pages(int iconCount)
Joe Onorato93839052009-08-06 20:34:32 -070056{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070057 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
58 int pages = iconCount / iconsPerPage;
59 if (pages*iconsPerPage != iconCount) {
Joe Onoratod769a632009-08-11 17:09:02 -070060 pages++;
Joe Onorato43e7bcf2009-08-08 18:53:53 -070061 }
Joe Onoratod769a632009-08-11 17:09:02 -070062 return pages;
63}
64
65int current_page(float scrollXPx)
66{
67 return -scrollXPx / SCREEN_WIDTH;
68}
69
70float
71modf(float x, float y)
72{
73 return x-(y*floorf(x/y));
Joe Onorato93839052009-08-06 20:34:32 -070074}
75
Joe Onorato43e7bcf2009-08-08 18:53:53 -070076int
Joe Onoratod769a632009-08-11 17:09:02 -070077main(int launchID)
Joe Onorato93839052009-08-06 20:34:32 -070078{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070079 // Clear to transparent
Joe Onorato93839052009-08-06 20:34:32 -070080 pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -070081
Joe Onorato43e7bcf2009-08-08 18:53:53 -070082 // icons & labels
Joe Onorato1feb3a82009-08-08 22:32:00 -070083 int iconCount = loadI32(ALLOC_STATE, STATE_ICON_COUNT);
Joe Onorato43e7bcf2009-08-08 18:53:53 -070084 int pageCount = count_pages(iconCount);
85
86 float densityScale = 2.0f / SCREEN_WIDTH;
87 float screenTop = SCREEN_HEIGHT/(float)SCREEN_WIDTH; // == (SCREEN_HEIGHT/2)*densityScale;
88
89 float pagePaddingTop = screenTop - (PAGE_PADDING_TOP_PX * densityScale);
90 float pageGutterY = ROW_GUTTER_PX * densityScale;
91 float cellHeight = (CELL_PADDING_TOP_PX + ICON_HEIGHT_PX + ICON_LABEL_GUTTER_PX
92 + loadI32(ALLOC_PARAMS, PARAM_BUBBLE_HEIGHT)
93 + CELL_PADDING_BOTTOM_PX + ROW_GUTTER_PX) * densityScale;
94 float cellPaddingTop = CELL_PADDING_TOP_PX * densityScale;
95 float iconHeight = ICON_HEIGHT_PX * densityScale;
Joe Onorato9c1289c2009-08-17 11:03:03 -040096 float iconTextureHeight = ICON_HEIGHT_PX / ((float)ICON_TEXTURE_HEIGHT_PX);
Joe Onorato43e7bcf2009-08-08 18:53:53 -070097 float iconLabelGutter = ICON_LABEL_GUTTER_PX * densityScale;
98
99 float pagePaddingLeft = PAGE_PADDING_LEFT_PX * densityScale;
100 float cellWidth = CELL_WIDTH_PX * densityScale;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400101
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700102 float iconWidth = ICON_WIDTH_PX * densityScale;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400103 float iconTextureWidth = ICON_WIDTH_PX / ((float)ICON_TEXTURE_WIDTH_PX);
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700104 float columnGutter = COLUMN_GUTTER_PX * densityScale;
105
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700106 float labelWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_WIDTH) * densityScale;
107 float labelTextureWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_WIDTH) * densityScale;
108 float labelTextureHeight = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_HEIGHT) * densityScale;
109
Joe Onoratod769a632009-08-11 17:09:02 -0700110 float scrollXPx = loadI32(ALLOC_STATE, STATE_SCROLL_X);
111 float maxScrollX = -(pageCount-1) * SCREEN_WIDTH;
112 int done = 0;
113
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700114 // Clamp -- because java doesn't know how big the icons are
115 if (scrollXPx > 0) {
116 scrollXPx = 0;
117 }
118 if (scrollXPx < maxScrollX) {
119 scrollXPx = maxScrollX;
120 }
121
Joe Onoratod769a632009-08-11 17:09:02 -0700122 // If we've been given a velocity, start a fling
123 float flingVelocityPxMs = loadI32(ALLOC_STATE, STATE_FLING_VELOCITY_X);
124 if (flingVelocityPxMs != 0) {
125 // how many screens will this velocity do? TODO: use long
126 // G * ppi * friction // why G? // friction = 0.015
127 float deceleration = loadF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700128 float flingDurationMs;
Joe Onoratod769a632009-08-11 17:09:02 -0700129 if (deceleration == 0) {
130 // On the first frame, calculate which animation we're going to do. If it's
131 // going to end up less than halfway into a page, we'll bounce back the previous
132 // page. Otherwise, we'll adjust the deceleration so it just makes it to the
133 // page boundary.
134 if (flingVelocityPxMs > 0) {
135 deceleration = -1000;
136 } else {
137 deceleration = 1000;
138 }
Joe Onorato9c1289c2009-08-17 11:03:03 -0400139 // minimum velocity
140 if (flingVelocityPxMs < 0) {
141 if (flingVelocityPxMs > -500) {
142 flingVelocityPxMs = -500;
143 }
144 } else {
145 if (flingVelocityPxMs < 500) {
146 flingVelocityPxMs = 500;
147 }
148 }
149
Joe Onoratod769a632009-08-11 17:09:02 -0700150 // v' = v + at --> t = -v / a
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700151 // x' = x + vt + .5 a t^2
152 flingDurationMs = - flingVelocityPxMs / deceleration;
153 float endPos = scrollXPx + (flingVelocityPxMs*flingDurationMs)
154 + ((deceleration*flingDurationMs*flingDurationMs)/2);
Joe Onoratod769a632009-08-11 17:09:02 -0700155
156 if (endPos > 0) {
157 endPos = 0;
158 }
159 if (endPos < maxScrollX) {
160 endPos = maxScrollX;
161 }
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700162 float scrollOnPage = modf(endPos, SCREEN_WIDTH);
163 int endPage = -endPos/SCREEN_WIDTH;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400164
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700165 if (flingVelocityPxMs < 0) {
166 if (scrollOnPage < (SCREEN_WIDTH/2)) {
167 // adjust the deceleration so we align on the page boundary
168 // a = 2(x-x0-v0t)/t^2
169 endPos = -(endPage+1) * SCREEN_WIDTH;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400170 debugI32("endPos case 1", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700171 } else {
172 // TODO: bounce
173 endPos = -(endPage+1) * SCREEN_WIDTH;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400174 debugI32("endPos case 2", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700175 }
176 } else {
177 if (scrollOnPage >= (SCREEN_WIDTH/2)) {
178 // adjust the deceleration so we align on the page boundary
179 endPos = -endPage * SCREEN_WIDTH;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400180 debugI32("endPos case 3", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700181 } else {
182 // TODO: bounce
183 endPos = -endPage * SCREEN_WIDTH;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400184 debugI32("endPos case 4", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700185 }
186 }
187 // v = v0 + at --> (v - v0) / t
188 deceleration = 2*(endPos-scrollXPx-(flingVelocityPxMs*flingDurationMs))
189 / (flingDurationMs*flingDurationMs);
190 endPos = scrollXPx + (flingVelocityPxMs*flingDurationMs)
191 + ((deceleration*flingDurationMs*flingDurationMs)/2);
192
193 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, deceleration);
194 storeF(ALLOC_STATE, STATE_FLING_DURATION, flingDurationMs);
195 storeF(ALLOC_STATE, STATE_FLING_END_POS, endPos);
196 } else {
197 flingDurationMs = loadF(ALLOC_STATE, STATE_FLING_DURATION);
Joe Onoratod769a632009-08-11 17:09:02 -0700198 }
199
200 // adjust the deceleration so we always hit a page boundary
201
202 int flingTime = loadI32(ALLOC_STATE, STATE_FLING_TIME);
203 int now = uptimeMillis();
204 float elapsedTime = (now - flingTime) / 1000.0f;
205 int animEndTime = -flingVelocityPxMs / deceleration;
206
Joe Onoratod769a632009-08-11 17:09:02 -0700207 int flingOffsetPx = (flingVelocityPxMs * elapsedTime)
208 + (deceleration * elapsedTime * elapsedTime / 2.0f);
209 scrollXPx += flingOffsetPx;
210
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700211 if (elapsedTime > flingDurationMs) {
212 scrollXPx = loadF(ALLOC_STATE, STATE_FLING_END_POS);
213 done = 1;
214 }
Joe Onoratod769a632009-08-11 17:09:02 -0700215 }
216
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700217 // Clamp
Joe Onoratod769a632009-08-11 17:09:02 -0700218 if (scrollXPx > 0) {
219 scrollXPx = 0;
220 }
221 if (scrollXPx < maxScrollX) {
222 scrollXPx = maxScrollX;
223 }
224
225 storeI32(ALLOC_STATE, STATE_CURRENT_SCROLL_X, scrollXPx);
226 if (done) {
227 storeI32(ALLOC_STATE, STATE_SCROLL_X, scrollXPx);
228 storeI32(ALLOC_STATE, STATE_FLING_VELOCITY_X, 0);
229 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, 0);
230 }
231
232 // don't draw everything, just the page before and after what we're viewing.
233 int currentPage = current_page(scrollXPx);
234 float screenWidth = SCREEN_WIDTH * densityScale;
235
Joe Onoratod769a632009-08-11 17:09:02 -0700236 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400237 int icon = 0;
238 int lastIcon = iconCount-1;
239 float pageLeft = -1 + (scrollXPx * densityScale);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700240 while (icon <= lastIcon) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700241 // Bug makes 1.0f alpha fail.
242 color(1.0f, 1.0f, 1.0f, 0.99f);
243
244 float cellTop = pagePaddingTop;
245 int row;
Joe Onoratod769a632009-08-11 17:09:02 -0700246 for (row=0; row<ROWS_PER_PAGE && icon<=lastIcon; row++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700247 float s = pageLeft; // distance along the linear strip of icons in normalized coords
248 s += pagePaddingLeft;
249 int col;
Joe Onoratod769a632009-08-11 17:09:02 -0700250 for (col=0; col<COLUMNS_PER_PAGE && icon<=lastIcon; col++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700251 // icon
252 float iconLeft = s + ((cellWidth-iconWidth)/2.0f);
253 float iconRight = iconLeft + iconWidth;
254 float iconTop = cellTop - cellPaddingTop;
255 float iconBottom = iconTop - iconHeight;
Joe Onorato93839052009-08-06 20:34:32 -0700256
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700257 bindProgramFragment(NAMED_PF);
258 bindProgramFragmentStore(NAMED_PFS);
Joe Onorato93839052009-08-06 20:34:32 -0700259
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700260 bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
Joe Onorato9c1289c2009-08-17 11:03:03 -0400261 //drawRect(iconLeft, iconTop, iconRight, iconBottom, 0.0f);
262 drawQuadTexCoords(
263 iconLeft, iconTop, 0.0f, 0.0f, 0.0f,
264 iconRight, iconTop, 0.0f, iconTextureWidth, 0.0f,
265 iconRight, iconBottom, 0.0f, iconTextureWidth, iconTextureHeight,
266 iconLeft, iconBottom, 0.0f, 0.0f, iconTextureHeight);
Joe Onorato93839052009-08-06 20:34:32 -0700267
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700268 // label
269 float labelLeft = s + ((cellWidth-labelWidth)/2.0f);
Joe Onorato9c1289c2009-08-17 11:03:03 -0400270 float labelTop = iconTop - iconHeight - iconLabelGutter;
Joe Onorato93839052009-08-06 20:34:32 -0700271
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700272 bindProgramFragment(NAMED_PFText);
273 bindProgramFragmentStore(NAMED_PFSText);
Joe Onorato93839052009-08-06 20:34:32 -0700274
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700275 bindTexture(NAMED_PFText, 0, loadI32(ALLOC_LABEL_IDS, icon));
276 drawRect(labelLeft, labelTop, labelLeft+labelTextureWidth,
277 labelTop-labelTextureHeight, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700278
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700279 s += cellWidth + columnGutter;
280 icon++;
Joe Onorato93839052009-08-06 20:34:32 -0700281 }
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700282 cellTop -= cellHeight;
Joe Onorato93839052009-08-06 20:34:32 -0700283 }
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700284 pageLeft += 2.0f;
Joe Onorato93839052009-08-06 20:34:32 -0700285 }
286
Joe Onoratod769a632009-08-11 17:09:02 -0700287 return !done;
Joe Onorato93839052009-08-06 20:34:32 -0700288}
289