blob: 216d76129990bc8ea8962d6761c579ccf83876c7 [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 ======
Joe Onoratoefabe002009-08-28 09:38:18 -070033#define SCREEN_WIDTH_PX 480
Joe Onorato43e7bcf2009-08-08 18:53:53 -070034#define SCREEN_HEIGHT 854
35#define COLUMNS_PER_PAGE 4
36#define ROWS_PER_PAGE 4
Joe Onorato43e7bcf2009-08-08 18:53:53 -070037
38#define PAGE_PADDING_TOP_PX 80
39#define CELL_PADDING_TOP_PX 5
40#define ICON_HEIGHT_PX 64
Joe Onorato9c1289c2009-08-17 11:03:03 -040041#define ICON_TEXTURE_HEIGHT_PX 128
Joe Onorato43e7bcf2009-08-08 18:53:53 -070042#define ICON_LABEL_GUTTER_PX 5
43#define CELL_PADDING_BOTTOM_PX 5
44#define ROW_GUTTER_PX 10
45
46#define PAGE_PADDING_LEFT_PX 22
47#define CELL_WIDTH_PX 105
48#define ICON_WIDTH_PX 64
Joe Onorato9c1289c2009-08-17 11:03:03 -040049#define ICON_TEXTURE_WIDTH_PX 128
Joe Onoratoefabe002009-08-28 09:38:18 -070050
51#define VIEW_ANGLE 1.28700222f
52#define RADIUS 4.0f
Joe Onorato43e7bcf2009-08-08 18:53:53 -070053
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
Joe Onoratod769a632009-08-11 17:09:02 -070065float
66modf(float x, float y)
67{
68 return x-(y*floorf(x/y));
Joe Onorato93839052009-08-06 20:34:32 -070069}
70
Joe Onorato0d1c5632009-08-28 15:57:18 -070071float
72far_size(float sizeAt0)
73{
74 return sizeAt0 * (RADIUS+2) / 2; // -2 is the camera z=(z-camZ)/z
75}
76
Joe Onoratoefabe002009-08-28 09:38:18 -070077void
78draw_page(int icon, int lastIcon, float centerAngle)
79{
80 int row;
81 int col;
82
83 float iconTextureWidth = ICON_WIDTH_PX / (float)ICON_TEXTURE_WIDTH_PX;
84 float iconTextureHeight = ICON_HEIGHT_PX / (float)ICON_TEXTURE_HEIGHT_PX;
85
86 float iconWidthAngle = VIEW_ANGLE * ICON_WIDTH_PX / SCREEN_WIDTH_PX;
Joe Onorato0d1c5632009-08-28 15:57:18 -070087 float columnGutterAngle = iconWidthAngle * 0.70f;
Joe Onoratoefabe002009-08-28 09:38:18 -070088
Joe Onorato0d1c5632009-08-28 15:57:18 -070089 float farIconSize = far_size(2 * ICON_WIDTH_PX / (float)SCREEN_WIDTH_PX);
90 float iconGutterHeight = farIconSize * 1.1f;
91
92 float labelWidthPx = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_WIDTH);
93 float labelHeightPx = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_HEIGHT);
94
95 float normalizedLabelWidth = 2 * labelWidthPx / (float)SCREEN_WIDTH_PX;
96 float farLabelWidth = far_size(normalizedLabelWidth);
97 float farLabelHeight = far_size(labelHeightPx * (normalizedLabelWidth / labelWidthPx));
98 float labelTextureWidth = labelWidthPx / loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_WIDTH);
99 float labelTextureHeight = labelHeightPx / loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_HEIGHT);
100
Joe Onoratoefabe002009-08-28 09:38:18 -0700101
102 for (row=0; row<ROWS_PER_PAGE && icon<=lastIcon; row++) {
103 float angle = centerAngle;
104 angle -= (columnGutterAngle + iconWidthAngle) * 1.5f;
105
Joe Onorato0d1c5632009-08-28 15:57:18 -0700106 float iconTop = (farIconSize + iconGutterHeight) * 2.2f
107 - row * (farIconSize + iconGutterHeight);
Joe Onoratoefabe002009-08-28 09:38:18 -0700108 float iconBottom = iconTop - farIconSize;
109
Joe Onorato0d1c5632009-08-28 15:57:18 -0700110 float labelTop = iconBottom - (.1 * farLabelHeight);
111 float labelBottom = labelTop - farLabelHeight;
112
Joe Onoratoefabe002009-08-28 09:38:18 -0700113 for (col=0; col<COLUMNS_PER_PAGE && icon<=lastIcon; col++) {
114 // icon
115 float sine = sinf(angle);
116 float cosine = cosf(angle);
117
Joe Onorato0d1c5632009-08-28 15:57:18 -0700118 float centerX = sine * RADIUS;
119 float centerZ = cosine * RADIUS;
120
121 float iconLeftX = centerX - (cosine * farIconSize * .5);
122 float iconRightX = centerX + (cosine * farIconSize * .5);
123 float iconLeftZ = centerZ + (sine * farIconSize * .5);
124 float iconRightZ = centerZ - (sine * farIconSize * .5);
Joe Onoratoefabe002009-08-28 09:38:18 -0700125
126 bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
127 drawQuadTexCoords(
128 iconLeftX, iconTop, iconLeftZ, 0.0f, 0.0f,
129 iconRightX, iconTop, iconRightZ, iconTextureWidth, 0.0f,
130 iconRightX, iconBottom, iconRightZ, iconTextureWidth, iconTextureHeight,
131 iconLeftX, iconBottom, iconLeftZ, 0.0f, iconTextureHeight);
132
133 // label
Joe Onorato0d1c5632009-08-28 15:57:18 -0700134 float labelLeftX = centerX - farLabelWidth * 0.5f;
135 float labelRightX = centerX + farLabelWidth * 0.5f;
Joe Onoratoefabe002009-08-28 09:38:18 -0700136
Joe Onorato0d1c5632009-08-28 15:57:18 -0700137 bindTexture(NAMED_PF, 0, loadI32(ALLOC_LABEL_IDS, icon));
138 drawQuadTexCoords(
139 labelLeftX, labelTop, centerZ, 0.0f, 0.0f,
140 labelRightX, labelTop, centerZ, labelTextureWidth, 0.0f,
141 labelRightX, labelBottom, centerZ, labelTextureWidth, labelTextureHeight,
142 labelLeftX, labelBottom, centerZ, 0.0f, labelTextureHeight);
Joe Onoratoefabe002009-08-28 09:38:18 -0700143
Joe Onoratoefabe002009-08-28 09:38:18 -0700144 angle += columnGutterAngle + iconWidthAngle;
145 icon++;
146 }
147 }
148}
149
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700150int
Joe Onoratod769a632009-08-11 17:09:02 -0700151main(int launchID)
Joe Onorato93839052009-08-06 20:34:32 -0700152{
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700153 // Clear to transparent
Joe Onorato93839052009-08-06 20:34:32 -0700154 pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700155
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700156 // icons & labels
Joe Onorato1feb3a82009-08-08 22:32:00 -0700157 int iconCount = loadI32(ALLOC_STATE, STATE_ICON_COUNT);
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700158 int pageCount = count_pages(iconCount);
159
Joe Onoratoefabe002009-08-28 09:38:18 -0700160 float densityScale = 2.0f / SCREEN_WIDTH_PX;
161 float screenTop = SCREEN_HEIGHT/(float)SCREEN_WIDTH_PX; // == (SCREEN_HEIGHT/2)*densityScale;
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700162
163 float pagePaddingTop = screenTop - (PAGE_PADDING_TOP_PX * densityScale);
164 float pageGutterY = ROW_GUTTER_PX * densityScale;
165 float cellHeight = (CELL_PADDING_TOP_PX + ICON_HEIGHT_PX + ICON_LABEL_GUTTER_PX
166 + loadI32(ALLOC_PARAMS, PARAM_BUBBLE_HEIGHT)
167 + CELL_PADDING_BOTTOM_PX + ROW_GUTTER_PX) * densityScale;
168 float cellPaddingTop = CELL_PADDING_TOP_PX * densityScale;
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700169 float iconLabelGutter = ICON_LABEL_GUTTER_PX * densityScale;
170
Joe Onoratod769a632009-08-11 17:09:02 -0700171 float scrollXPx = loadI32(ALLOC_STATE, STATE_SCROLL_X);
Joe Onoratoefabe002009-08-28 09:38:18 -0700172 float maxScrollX = -(pageCount-1) * SCREEN_WIDTH_PX;
Joe Onoratod769a632009-08-11 17:09:02 -0700173 int done = 0;
174
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700175 // Clamp -- because java doesn't know how big the icons are
176 if (scrollXPx > 0) {
177 scrollXPx = 0;
178 }
179 if (scrollXPx < maxScrollX) {
180 scrollXPx = maxScrollX;
181 }
182
Joe Onoratod769a632009-08-11 17:09:02 -0700183 // If we've been given a velocity, start a fling
184 float flingVelocityPxMs = loadI32(ALLOC_STATE, STATE_FLING_VELOCITY_X);
185 if (flingVelocityPxMs != 0) {
186 // how many screens will this velocity do? TODO: use long
187 // G * ppi * friction // why G? // friction = 0.015
188 float deceleration = loadF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700189 float flingDurationMs;
Joe Onoratod769a632009-08-11 17:09:02 -0700190 if (deceleration == 0) {
191 // On the first frame, calculate which animation we're going to do. If it's
192 // going to end up less than halfway into a page, we'll bounce back the previous
193 // page. Otherwise, we'll adjust the deceleration so it just makes it to the
194 // page boundary.
195 if (flingVelocityPxMs > 0) {
196 deceleration = -1000;
197 } else {
198 deceleration = 1000;
199 }
Joe Onorato9c1289c2009-08-17 11:03:03 -0400200 // minimum velocity
201 if (flingVelocityPxMs < 0) {
202 if (flingVelocityPxMs > -500) {
203 flingVelocityPxMs = -500;
204 }
205 } else {
206 if (flingVelocityPxMs < 500) {
207 flingVelocityPxMs = 500;
208 }
209 }
210
Joe Onoratod769a632009-08-11 17:09:02 -0700211 // v' = v + at --> t = -v / a
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700212 // x' = x + vt + .5 a t^2
213 flingDurationMs = - flingVelocityPxMs / deceleration;
214 float endPos = scrollXPx + (flingVelocityPxMs*flingDurationMs)
215 + ((deceleration*flingDurationMs*flingDurationMs)/2);
Joe Onoratod769a632009-08-11 17:09:02 -0700216
217 if (endPos > 0) {
218 endPos = 0;
219 }
220 if (endPos < maxScrollX) {
221 endPos = maxScrollX;
222 }
Joe Onoratoefabe002009-08-28 09:38:18 -0700223 float scrollOnPage = modf(endPos, SCREEN_WIDTH_PX);
224 int endPage = -endPos/SCREEN_WIDTH_PX;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400225
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700226 if (flingVelocityPxMs < 0) {
Joe Onoratoefabe002009-08-28 09:38:18 -0700227 if (scrollOnPage < (SCREEN_WIDTH_PX/2)) {
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700228 // adjust the deceleration so we align on the page boundary
229 // a = 2(x-x0-v0t)/t^2
Joe Onoratoefabe002009-08-28 09:38:18 -0700230 endPos = -(endPage+1) * SCREEN_WIDTH_PX;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400231 debugI32("endPos case 1", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700232 } else {
233 // TODO: bounce
Joe Onoratoefabe002009-08-28 09:38:18 -0700234 endPos = -(endPage+1) * SCREEN_WIDTH_PX;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400235 debugI32("endPos case 2", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700236 }
237 } else {
Joe Onoratoefabe002009-08-28 09:38:18 -0700238 if (scrollOnPage >= (SCREEN_WIDTH_PX/2)) {
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700239 // adjust the deceleration so we align on the page boundary
Joe Onoratoefabe002009-08-28 09:38:18 -0700240 endPos = -endPage * SCREEN_WIDTH_PX;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400241 debugI32("endPos case 3", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700242 } else {
243 // TODO: bounce
Joe Onoratoefabe002009-08-28 09:38:18 -0700244 endPos = -endPage * SCREEN_WIDTH_PX;
Joe Onorato9c1289c2009-08-17 11:03:03 -0400245 debugI32("endPos case 4", endPos);
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700246 }
247 }
248 // v = v0 + at --> (v - v0) / t
249 deceleration = 2*(endPos-scrollXPx-(flingVelocityPxMs*flingDurationMs))
250 / (flingDurationMs*flingDurationMs);
251 endPos = scrollXPx + (flingVelocityPxMs*flingDurationMs)
252 + ((deceleration*flingDurationMs*flingDurationMs)/2);
253
254 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, deceleration);
255 storeF(ALLOC_STATE, STATE_FLING_DURATION, flingDurationMs);
256 storeF(ALLOC_STATE, STATE_FLING_END_POS, endPos);
257 } else {
258 flingDurationMs = loadF(ALLOC_STATE, STATE_FLING_DURATION);
Joe Onoratod769a632009-08-11 17:09:02 -0700259 }
260
261 // adjust the deceleration so we always hit a page boundary
262
263 int flingTime = loadI32(ALLOC_STATE, STATE_FLING_TIME);
264 int now = uptimeMillis();
265 float elapsedTime = (now - flingTime) / 1000.0f;
266 int animEndTime = -flingVelocityPxMs / deceleration;
267
Joe Onoratod769a632009-08-11 17:09:02 -0700268 int flingOffsetPx = (flingVelocityPxMs * elapsedTime)
269 + (deceleration * elapsedTime * elapsedTime / 2.0f);
270 scrollXPx += flingOffsetPx;
271
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700272 if (elapsedTime > flingDurationMs) {
273 scrollXPx = loadF(ALLOC_STATE, STATE_FLING_END_POS);
274 done = 1;
275 }
Joe Onoratod769a632009-08-11 17:09:02 -0700276 }
277
Joe Onoratoeb2c02e2009-08-12 21:40:52 -0700278 // Clamp
Joe Onoratod769a632009-08-11 17:09:02 -0700279 if (scrollXPx > 0) {
280 scrollXPx = 0;
281 }
282 if (scrollXPx < maxScrollX) {
283 scrollXPx = maxScrollX;
284 }
285
286 storeI32(ALLOC_STATE, STATE_CURRENT_SCROLL_X, scrollXPx);
287 if (done) {
288 storeI32(ALLOC_STATE, STATE_SCROLL_X, scrollXPx);
289 storeI32(ALLOC_STATE, STATE_FLING_VELOCITY_X, 0);
290 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, 0);
291 }
292
Joe Onoratoefabe002009-08-28 09:38:18 -0700293 bindProgramFragment(NAMED_PF);
294 bindProgramFragmentStore(NAMED_PFS);
295
296 // Bug makes 1.0f alpha fail.
297 color(1.0f, 1.0f, 1.0f, 0.99f);
298
299 int lastIcon = iconCount-1;
300
301 float currentPage = -scrollXPx / (float)SCREEN_WIDTH_PX;
302 int page = currentPage;
303 float currentPagePosition = currentPage - page;
Joe Onoratod769a632009-08-11 17:09:02 -0700304
Joe Onoratod769a632009-08-11 17:09:02 -0700305 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
Joe Onoratoefabe002009-08-28 09:38:18 -0700306 int icon = clamp(iconsPerPage * page, 0, lastIcon);
Joe Onorato93839052009-08-06 20:34:32 -0700307
Joe Onoratoefabe002009-08-28 09:38:18 -0700308 draw_page(icon, lastIcon, -VIEW_ANGLE*currentPagePosition);
309 draw_page(icon+iconsPerPage, lastIcon, (-VIEW_ANGLE*currentPagePosition)+VIEW_ANGLE);
Joe Onorato93839052009-08-06 20:34:32 -0700310
Joe Onoratod769a632009-08-11 17:09:02 -0700311 return !done;
Joe Onorato93839052009-08-06 20:34:32 -0700312}
313