blob: 98e573856b1a762e0e9c013c8941996d00681add [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
Jason Sams86c87ed2009-09-18 13:55:55 -07008
9// Attraction to center values from page edge to page center.
10float g_AttractionTable[9];
11float g_FrictionTable[9];
12float g_PhysicsTableSize;
13
14float g_PosPage;
15float g_PosVelocity;
16float g_LastPositionX;
17int g_LastTouchDown;
18float g_DT;
19int g_LastTime;
20int g_Rendering;
21int g_PageCount;
Joe Onorato93839052009-08-06 20:34:32 -070022
Joe Onorato43e7bcf2009-08-08 18:53:53 -070023// Drawing constants, should be parameters ======
Joe Onoratoefabe002009-08-28 09:38:18 -070024#define VIEW_ANGLE 1.28700222f
Joe Onorato43e7bcf2009-08-08 18:53:53 -070025
Jason Sams78aebd82009-09-15 13:06:59 -070026void init() {
Jason Sams86c87ed2009-09-18 13:55:55 -070027 g_AttractionTable[0] = 4.5f;
28 g_AttractionTable[1] = 4.5f;
29 g_AttractionTable[2] = 5.0f;
30 g_AttractionTable[3] = 4.0f;
31 g_AttractionTable[4] = -4.0f;
32 g_AttractionTable[5] = -5.0f;
33 g_AttractionTable[6] = -4.5f;
34 g_AttractionTable[7] = -4.5f;
35 g_AttractionTable[8] = -4.5f; // dup 7 to avoid a clamp later
36 g_FrictionTable[0] = 3.5f;
37 g_FrictionTable[1] = 3.6f;
38 g_FrictionTable[2] = 3.7f;
39 g_FrictionTable[3] = 3.8f;
40 g_FrictionTable[4] = 3.8f;
41 g_FrictionTable[5] = 3.7f;
42 g_FrictionTable[6] = 3.6f;
43 g_FrictionTable[7] = 3.5f;
44 g_FrictionTable[8] = 3.5f; // dup 7 to avoid a clamp later
45 g_PhysicsTableSize = 7;
46
47 g_PosVelocity = 0;
48 g_PosPage = 0;
49 g_LastTouchDown = 0;
50 g_LastPositionX = 0;
51}
52
53void clampPosition() {
54 if (g_PosPage < 0) {
55 g_PosPage = 0;
56 g_PosVelocity = 0;
57 }
58 if (g_PosPage > (g_PageCount - 1)) {
59 g_PosPage = (g_PageCount - 1);
60 g_PosVelocity = 0;
61 }
62}
63
64void move() {
65 if (g_LastTouchDown) {
66 float dx = -(state->newPositionX - g_LastPositionX);
67 g_PosVelocity = 0;
68 g_PosPage += dx;
69 }
70 g_LastTouchDown = state->newTouchDown;
71 g_LastPositionX = state->newPositionX;
72 clampPosition();
73}
74
75void fling() {
76 g_LastTouchDown = 0;
77 g_PosVelocity = -state->flingVelocityX;
78 if (g_PosPage <= 0) {
79 g_PosVelocity = maxf(0, g_PosVelocity);
80 }
81 if (g_PosPage > (g_PageCount - 1)) {
82 g_PosVelocity = minf(0, (g_PageCount - 1) - g_PosPage);
83 }
Jason Sams78aebd82009-09-15 13:06:59 -070084}
85
Joe Onoratofb0ca672009-09-14 17:55:46 -040086int g_lastFrameTime = 0;
87void print_frame_rate()
88{
89 int now = uptimeMillis();
90 if (g_lastFrameTime != 0) {
91 debugI32("frame_rate", 1000/(now-g_lastFrameTime));
92 }
93 g_lastFrameTime = now;
94}
95
Joe Onorato43e7bcf2009-08-08 18:53:53 -070096int
97count_pages(int iconCount)
Joe Onorato93839052009-08-06 20:34:32 -070098{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070099 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
100 int pages = iconCount / iconsPerPage;
101 if (pages*iconsPerPage != iconCount) {
Joe Onoratod769a632009-08-11 17:09:02 -0700102 pages++;
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700103 }
Joe Onoratod769a632009-08-11 17:09:02 -0700104 return pages;
105}
106
Joe Onoratod769a632009-08-11 17:09:02 -0700107float
108modf(float x, float y)
109{
110 return x-(y*floorf(x/y));
Joe Onorato93839052009-08-06 20:34:32 -0700111}
112
Jason Sams86c87ed2009-09-18 13:55:55 -0700113void updatePos() {
114 if (g_LastTouchDown) {
115 return;
116 }
117
118 //debugF("g_PosPage", g_PosPage);
119 //debugF(" g_PosVelocity", g_PosVelocity);
120
121 float tablePosNorm = fracf(g_PosPage + 0.5f);
122 float tablePosF = tablePosNorm * g_PhysicsTableSize;
123 int tablePosI = tablePosF;
124 float tablePosFrac = tablePosF - tablePosI;
125 //debugF("tablePosNorm", tablePosNorm);
126 //debugF("tablePosF", tablePosF);
127 //debugF("tablePosI", tablePosI);
128 //debugF("tablePosFrac", tablePosFrac);
129
130 float accel = lerpf(g_AttractionTable[tablePosI],
131 g_AttractionTable[tablePosI + 1],
132 tablePosFrac) * g_DT;
133 float friction = lerpf(g_FrictionTable[tablePosI],
134 g_FrictionTable[tablePosI + 1],
135 tablePosFrac) * g_DT;
136 //debugF(" accel", accel);
137 //debugF(" friction", friction);
138
139 g_PosVelocity += accel;
140 if ((friction > fabsf(g_PosVelocity)) && (friction > fabsf(accel))) {
141 // Special get back to center and overcome friction physics.
142 float t = tablePosNorm - 0.5f;
143 if (fabsf(t) < (friction * g_DT)) {
144 // really close, just snap
145 g_PosPage = roundf(g_PosPage);
146 g_PosVelocity = 0;
147 } else {
148 if (t > 0) {
149 g_PosVelocity = -friction;
150 } else {
151 g_PosVelocity = friction;
152 }
153 }
154 } else {
155 // Normal physics
156 if (g_PosVelocity > 0) {
157 g_PosVelocity -= friction;
158 if (g_PosVelocity < 0) {
159 g_PosVelocity = 0;
160 }
161 } else {
162 g_PosVelocity += friction;
163 if (g_PosVelocity > 0) {
164 g_PosVelocity = 0;
165 }
166 }
167 }
168 g_PosPage += g_PosVelocity * g_DT;
169
170 // Check for out of boundry conditions.
171 if (g_PosPage < 0 && g_PosVelocity < 0) {
172 float damp = 1.0 + (g_PosPage * 3);
173 damp = clampf(damp, 0.f, 0.9f);
174 g_PosVelocity *= damp;
175 }
176 if (g_PosPage > (g_PageCount-1) && g_PosVelocity > 0) {
177 float damp = 1.0 - ((g_PosPage - g_PageCount + 1) * 3);
178 damp = clampf(damp, 0.f, 0.9f);
179 g_PosVelocity *= damp;
180 }
181}
182
Joe Onorato0d1c5632009-08-28 15:57:18 -0700183float
184far_size(float sizeAt0)
185{
186 return sizeAt0 * (RADIUS+2) / 2; // -2 is the camera z=(z-camZ)/z
187}
188
Joe Onoratoefabe002009-08-28 09:38:18 -0700189void
190draw_page(int icon, int lastIcon, float centerAngle)
191{
192 int row;
193 int col;
194
Jason Sams86c87ed2009-09-18 13:55:55 -0700195 //debugF("center angle", centerAngle);
Jason Sams78aebd82009-09-15 13:06:59 -0700196 float scale = 1.0f - state->zoom;
Joe Onorato85a02a82009-09-08 12:34:22 -0700197
Joe Onoratoefabe002009-08-28 09:38:18 -0700198 float iconTextureWidth = ICON_WIDTH_PX / (float)ICON_TEXTURE_WIDTH_PX;
199 float iconTextureHeight = ICON_HEIGHT_PX / (float)ICON_TEXTURE_HEIGHT_PX;
200
201 float iconWidthAngle = VIEW_ANGLE * ICON_WIDTH_PX / SCREEN_WIDTH_PX;
Joe Onorato0d1c5632009-08-28 15:57:18 -0700202 float columnGutterAngle = iconWidthAngle * 0.70f;
Joe Onoratoefabe002009-08-28 09:38:18 -0700203
Joe Onorato6665c0f2009-09-02 15:27:24 -0700204 float farIconSize = FAR_ICON_SIZE;
Joe Onorato0d1c5632009-08-28 15:57:18 -0700205 float iconGutterHeight = farIconSize * 1.1f;
206
Joe Onorato6665c0f2009-09-02 15:27:24 -0700207 float farIconTextureSize = far_size(2 * ICON_TEXTURE_WIDTH_PX / (float)SCREEN_WIDTH_PX);
208
Jason Sams78aebd82009-09-15 13:06:59 -0700209 float normalizedLabelWidth = 2 * params->bubbleWidth / (float)SCREEN_WIDTH_PX;
Joe Onorato0d1c5632009-08-28 15:57:18 -0700210 float farLabelWidth = far_size(normalizedLabelWidth);
Jason Sams78aebd82009-09-15 13:06:59 -0700211 float farLabelHeight = far_size(params->bubbleHeight * (normalizedLabelWidth / params->bubbleWidth));
212 float labelTextureWidth = (float)params->bubbleWidth / params->bubbleBitmapWidth;
213 float labelTextureHeight = (float)params->bubbleHeight / params->bubbleBitmapHeight;
Joe Onoratoefabe002009-08-28 09:38:18 -0700214
215 for (row=0; row<ROWS_PER_PAGE && icon<=lastIcon; row++) {
216 float angle = centerAngle;
217 angle -= (columnGutterAngle + iconWidthAngle) * 1.5f;
218
Joe Onorato6665c0f2009-09-02 15:27:24 -0700219 float iconTop = (farIconSize + iconGutterHeight) * (2.0f + ICON_TOP_OFFSET)
Joe Onorato0d1c5632009-08-28 15:57:18 -0700220 - row * (farIconSize + iconGutterHeight);
Joe Onoratod40eec32009-09-08 12:34:22 -0700221 iconTop -= 6 * scale; // make the zoom point below center
Joe Onoratoefabe002009-08-28 09:38:18 -0700222 float iconBottom = iconTop - farIconSize;
223
Joe Onorato0d1c5632009-08-28 15:57:18 -0700224 float labelTop = iconBottom - (.1 * farLabelHeight);
225 float labelBottom = labelTop - farLabelHeight;
226
Joe Onorato6665c0f2009-09-02 15:27:24 -0700227 float iconTextureTop = iconTop + (0.5f * (farIconTextureSize - farIconSize));
228 float iconTextureBottom = iconTextureTop - farIconTextureSize;
229
Joe Onoratoefabe002009-08-28 09:38:18 -0700230 for (col=0; col<COLUMNS_PER_PAGE && icon<=lastIcon; col++) {
231 // icon
232 float sine = sinf(angle);
233 float cosine = cosf(angle);
234
Joe Onorato0d1c5632009-08-28 15:57:18 -0700235 float centerX = sine * RADIUS;
236 float centerZ = cosine * RADIUS;
Joe Onoratod40eec32009-09-08 12:34:22 -0700237 centerZ -= ((RADIUS+2+1)*scale); // 2 is camera loc, 1 put it slightly behind that.
Joe Onorato0d1c5632009-08-28 15:57:18 -0700238
Joe Onorato6665c0f2009-09-02 15:27:24 -0700239 float iconLeftX = centerX - (cosine * farIconTextureSize * .5);
240 float iconRightX = centerX + (cosine * farIconTextureSize * .5);
241 float iconLeftZ = centerZ + (sine * farIconTextureSize * .5);
242 float iconRightZ = centerZ - (sine * farIconTextureSize * .5);
243
Jason Sams78aebd82009-09-15 13:06:59 -0700244 if (state->selectedIconIndex == icon) {
245 bindTexture(NAMED_PF, 0, state->selectedIconTexture);
Joe Onorato6665c0f2009-09-02 15:27:24 -0700246 drawQuadTexCoords(
247 iconLeftX, iconTextureTop, iconLeftZ, 0.0f, 0.0f,
248 iconRightX, iconTextureTop, iconRightZ, 1.0f, 0.0f,
249 iconRightX, iconTextureBottom, iconRightZ, 1.0f, 1.0f,
250 iconLeftX, iconTextureBottom, iconLeftZ, 0.0f, 1.0f);
Joe Onorato1291a8c2009-09-15 15:07:25 -0400251 } else {
252 bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
253 drawQuadTexCoords(
254 iconLeftX, iconTextureTop, iconLeftZ, 0.0f, 0.0f,
255 iconRightX, iconTextureTop, iconRightZ, 1.0f, 0.0f,
256 iconRightX, iconTextureBottom, iconRightZ, 1.0f, 1.0f,
257 iconLeftX, iconTextureBottom, iconLeftZ, 0.0f, 1.0f);
Joe Onorato6665c0f2009-09-02 15:27:24 -0700258 }
Joe Onoratoefabe002009-08-28 09:38:18 -0700259
Joe Onoratoefabe002009-08-28 09:38:18 -0700260 // label
Joe Onoratofb0ca672009-09-14 17:55:46 -0400261 if (scale <= 0.1f) {
Joe Onorato85a02a82009-09-08 12:34:22 -0700262 float labelLeftX = centerX - farLabelWidth * 0.5f;
263 float labelRightX = centerX + farLabelWidth * 0.5f;
Joe Onoratoefabe002009-08-28 09:38:18 -0700264
Joe Onorato85a02a82009-09-08 12:34:22 -0700265 bindTexture(NAMED_PF, 0, loadI32(ALLOC_LABEL_IDS, icon));
266 drawQuadTexCoords(
267 labelLeftX, labelTop, centerZ, 0.0f, 0.0f,
268 labelRightX, labelTop, centerZ, labelTextureWidth, 0.0f,
269 labelRightX, labelBottom, centerZ, labelTextureWidth, labelTextureHeight,
270 labelLeftX, labelBottom, centerZ, 0.0f, labelTextureHeight);
271 }
Joe Onoratoefabe002009-08-28 09:38:18 -0700272
Joe Onoratoefabe002009-08-28 09:38:18 -0700273 angle += columnGutterAngle + iconWidthAngle;
274 icon++;
275 }
276 }
277}
278
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700279int
Joe Onoratod769a632009-08-11 17:09:02 -0700280main(int launchID)
Joe Onorato93839052009-08-06 20:34:32 -0700281{
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700282 // Clear to transparent
Joe Onorato93839052009-08-06 20:34:32 -0700283 pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700284
Jason Sams86c87ed2009-09-18 13:55:55 -0700285 int newTime = uptimeMillis();
286 g_DT = (newTime - g_LastTime) / 1000.f;
287 g_LastTime = newTime;
288 //debugF("*** dt ", g_DT);
289
Joe Onorato006b25f2009-09-03 11:38:43 -0700290 // If we're not supposed to be showing, don't do anything.
Jason Sams78aebd82009-09-15 13:06:59 -0700291 if (!state->visible) {
Joe Onorato006b25f2009-09-03 11:38:43 -0700292 return 0;
293 }
294
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700295 // icons & labels
Jason Sams78aebd82009-09-15 13:06:59 -0700296 int iconCount = state->iconCount;
Jason Sams86c87ed2009-09-18 13:55:55 -0700297 g_PageCount = count_pages(iconCount);
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700298
Jason Sams86c87ed2009-09-18 13:55:55 -0700299 updatePos(0.1f);
300 state->readPosX = g_PosPage;
301 state->readVel = g_PosVelocity;
Joe Onoratod769a632009-08-11 17:09:02 -0700302
Jason Sams86c87ed2009-09-18 13:55:55 -0700303 //debugF(" draw g_PosPage", g_PosPage);
Joe Onoratod769a632009-08-11 17:09:02 -0700304
Joe Onoratoc567acb2009-08-31 14:34:43 -0700305 // Draw the icons ========================================
306 bindProgramVertex(NAMED_PV);
Joe Onoratoefabe002009-08-28 09:38:18 -0700307 bindProgramFragment(NAMED_PF);
308 bindProgramFragmentStore(NAMED_PFS);
309
310 // Bug makes 1.0f alpha fail.
311 color(1.0f, 1.0f, 1.0f, 0.99f);
312
313 int lastIcon = iconCount-1;
314
Jason Sams86c87ed2009-09-18 13:55:55 -0700315 int page = g_PosPage;
316 float currentPagePosition = g_PosPage - page;
Joe Onoratod769a632009-08-11 17:09:02 -0700317
Joe Onoratod769a632009-08-11 17:09:02 -0700318 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
Joe Onoratoefabe002009-08-28 09:38:18 -0700319 int icon = clamp(iconsPerPage * page, 0, lastIcon);
Joe Onorato93839052009-08-06 20:34:32 -0700320
Joe Onoratoefabe002009-08-28 09:38:18 -0700321 draw_page(icon, lastIcon, -VIEW_ANGLE*currentPagePosition);
322 draw_page(icon+iconsPerPage, lastIcon, (-VIEW_ANGLE*currentPagePosition)+VIEW_ANGLE);
Jason Sams78aebd82009-09-15 13:06:59 -0700323
Jason Sams86c87ed2009-09-18 13:55:55 -0700324
Joe Onorato6665c0f2009-09-02 15:27:24 -0700325 // Draw the border lines for debugging ========================================
Joe Onoratoc567acb2009-08-31 14:34:43 -0700326 /*
327 bindProgramVertex(NAMED_PVOrtho);
328 bindProgramFragment(NAMED_PFText);
329 bindProgramFragmentStore(NAMED_PFSText);
330
Joe Onorato6665c0f2009-09-02 15:27:24 -0700331 color(1.0f, 1.0f, 0.0f, 0.99f);
332 int i;
333 for (i=0; i<ROWS_PER_PAGE+1; i++) {
334 int y = loadI32(ALLOC_Y_BORDERS, i);
335 drawRect(0, y, SCREEN_WIDTH_PX, y+1, 0.0f);
336 }
337 for (i=0; i<COLUMNS_PER_PAGE+1; i++) {
338 int x = loadI32(ALLOC_X_BORDERS, i);
339 drawRect(x, 0, x+1, SCREEN_HEIGHT_PX, 0.0f);
340 }
341 */
342
343 // Draw the scroll handle ========================================
344 /*
Joe Onoratoc567acb2009-08-31 14:34:43 -0700345 bindTexture(NAMED_PFText, 0, loadI32(ALLOC_PARAMS, PARAM_SCROLL_HANDLE_ID));
346 float handleLeft = 40 + (320 * (scrollXPx/(float)(maxScrollXPx)));
347 float handleTop = 680;
348 float handleWidth = loadI32(ALLOC_PARAMS, PARAM_SCROLL_HANDLE_TEX_WIDTH);
349 float handleHeight = loadI32(ALLOC_PARAMS, PARAM_SCROLL_HANDLE_TEX_HEIGHT);
350 drawRect(handleLeft, handleTop, handleLeft+handleWidth, handleTop+handleHeight, 0.0f);
351 */
Joe Onorato93839052009-08-06 20:34:32 -0700352
Jason Sams86c87ed2009-09-18 13:55:55 -0700353 //print_frame_rate();
Joe Onoratofb0ca672009-09-14 17:55:46 -0400354
Jason Sams86c87ed2009-09-18 13:55:55 -0700355 // Bug workaround where the last frame is not always displayed
356 // So we render the last frame twice.
357 int rendering = g_Rendering;
358 g_Rendering = (g_PosVelocity != 0) || fracf(g_PosPage);
359 rendering |= g_Rendering;
360 return rendering;
Joe Onorato93839052009-08-06 20:34:32 -0700361}
362