blob: d9077855f5ef8394743ab1901a83337c8380b472 [file] [log] [blame]
Jason Sams0aa71662009-10-02 18:43:18 -07001#pragma version(1)
2#pragma stateVertex(PV)
3#pragma stateFragment(PFTexLinear)
4#pragma stateStore(PSIcons)
5
6#define PI 3.14159f
7
8
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_PageCount;
21float g_Zoom;
22float g_ZoomTarget;
23
24// Drawing constants, should be parameters ======
25#define VIEW_ANGLE 1.28700222f
26
27void init() {
28 g_AttractionTable[0] = 6.5f;
29 g_AttractionTable[1] = 6.5f;
30 g_AttractionTable[2] = 7.0f;
31 g_AttractionTable[3] = 6.0f;
32 g_AttractionTable[4] = -6.0f;
33 g_AttractionTable[5] = -7.0f;
34 g_AttractionTable[6] = -6.5f;
35 g_AttractionTable[7] = -6.5f;
36 g_AttractionTable[8] = -6.5f; // dup 7 to avoid a clamp later
37 g_FrictionTable[0] = 3.5f;
38 g_FrictionTable[1] = 3.6f;
39 g_FrictionTable[2] = 4.0f;
40 g_FrictionTable[3] = 5.0f;
41 g_FrictionTable[4] = 5.0f;
42 g_FrictionTable[5] = 4.0f;
43 g_FrictionTable[6] = 3.6f;
44 g_FrictionTable[7] = 3.5f;
45 g_FrictionTable[8] = 3.5f; // dup 7 to avoid a clamp later
46 g_PhysicsTableSize = 7;
47
48 g_PosVelocity = 0;
49 g_PosPage = 0;
50 g_LastTouchDown = 0;
51 g_LastPositionX = 0;
52 g_Zoom = 0;
53 g_ZoomTarget = 0;
54}
55
56void move() {
57 if (g_LastTouchDown) {
58 float dx = -(state->newPositionX - g_LastPositionX);
59 g_PosVelocity = 0;
60 g_PosPage += dx;
61
62 float pmin = -0.25f;
63 float pmax = (g_PageCount - 1) + 0.25f;
64 g_PosPage = clampf(g_PosPage, pmin, pmax);
65 }
66 g_LastTouchDown = state->newTouchDown;
67 g_LastPositionX = state->newPositionX;
68 //debugF("Move P", g_PosPage);
69}
70
71void fling() {
72 g_LastTouchDown = 0;
73 g_PosVelocity = -state->flingVelocityX;
74 float av = fabsf(g_PosVelocity);
75 float minVel = 3.5f;
76
77 minVel *= 1.f - (fabsf(fracf(g_PosPage + 0.5f) - 0.5f) * 0.45f);
78
79 if (av < minVel && av > 0.2f) {
80 if (g_PosVelocity > 0) {
81 g_PosVelocity = minVel;
82 } else {
83 g_PosVelocity = -minVel;
84 }
85 }
86
87 if (g_PosPage <= 0) {
88 g_PosVelocity = maxf(0, g_PosVelocity);
89 }
90 if (g_PosPage > (g_PageCount - 1)) {
91 g_PosVelocity = minf(0, g_PosVelocity);
92 }
93 //debugF("fling v", g_PosVelocity);
94}
95
96void touchUp() {
97 g_LastTouchDown = 0;
98}
99
100void setZoomTarget() {
101 g_ZoomTarget = state->zoomTarget;
102 //debugF("zoom target", g_ZoomTarget);
103}
104
105void setZoom() {
106 readback->zoom = g_Zoom = g_ZoomTarget = state->zoom;
107 //debugF("zoom", g_ZoomTarget);
108}
109
110int
111count_pages(int iconCount)
112{
113 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
114 int pages = iconCount / iconsPerPage;
115 if (pages*iconsPerPage != iconCount) {
116 pages++;
117 }
118 return pages;
119}
120
121float
122modf(float x, float y)
123{
124 return x-(y*floorf(x/y));
125}
126
127void updatePos() {
128 if (g_LastTouchDown) {
129 return;
130 }
131
132 float tablePosNorm = fracf(g_PosPage + 0.5f);
133 float tablePosF = tablePosNorm * g_PhysicsTableSize;
134 int tablePosI = tablePosF;
135 float tablePosFrac = tablePosF - tablePosI;
136 float accel = lerpf(g_AttractionTable[tablePosI],
137 g_AttractionTable[tablePosI + 1],
138 tablePosFrac) * g_DT;
139 float friction = lerpf(g_FrictionTable[tablePosI],
140 g_FrictionTable[tablePosI + 1],
141 tablePosFrac) * g_DT;
142 //debugF(" accel", accel);
143 //debugF(" friction", friction);
144
145 // If our velocity is low OR acceleration is opposing it, apply it.
146 if (fabsf(g_PosVelocity) < 1.0f || (g_PosVelocity * accel) < 0) {
147 g_PosVelocity += accel;
148 }
149
150 if ((friction > fabsf(g_PosVelocity)) && (friction > fabsf(accel))) {
151 // Special get back to center and overcome friction physics.
152 float t = tablePosNorm - 0.5f;
153 if (fabsf(t) < (friction * g_DT)) {
154 // really close, just snap
155 g_PosPage = roundf(g_PosPage);
156 g_PosVelocity = 0;
157 } else {
158 if (t > 0) {
159 g_PosVelocity = -friction;
160 } else {
161 g_PosVelocity = friction;
162 }
163 }
164 } else {
165 // Normal physics
166 if (g_PosVelocity > 0) {
167 g_PosVelocity -= friction;
168 g_PosVelocity = maxf(g_PosVelocity, 0);
169 } else {
170 g_PosVelocity += friction;
171 g_PosVelocity = minf(g_PosVelocity, 0);
172 }
173 }
174 g_PosPage += g_PosVelocity * g_DT;
175
176 // Check for out of boundry conditions.
177 if (g_PosPage < 0 && g_PosVelocity < 0) {
178 float damp = 1.0 + (g_PosPage * 4);
179 damp = clampf(damp, 0.f, 0.9f);
180 g_PosVelocity *= damp;
181 }
182 if (g_PosPage > (g_PageCount-1) && g_PosVelocity > 0) {
183 float damp = 1.0 - ((g_PosPage - g_PageCount + 1) * 4);
184 damp = clampf(damp, 0.f, 0.9f);
185 g_PosVelocity *= damp;
186 }
187}
188
189int positionStrip(float row, float column)
190{
191 float mat1[16];
192
193 float y = 1.2f - row * 0.6f;
194
195 float scale = 256.f / getWidth();
196 float xscale = scale * 4.55 / 1.8f / 2;
197
198 matrixLoadTranslate(mat1, 0.f, y, 0.f);
199 matrixScale(mat1, 1.f, scale, 1.f);
200 vpLoadModelMatrix(mat1);
201
202 float soff = -21.8f - (column * 1.25f);
203 matrixLoadScale(mat1, xscale, 1.f, 1.f);
204 matrixTranslate(mat1, soff, 0, 0);
205 vpLoadTextureMatrix(mat1);
206
207 return - soff * 10.f;
208}
209
210void drawIcon(float row, float column, int iconNum)
211{
212 int offset = positionStrip(row, column);
213 bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, iconNum));
214
215 if (offset < 0) {
216 offset = 0;
217 }
218 if (offset >= (450 - 20)) {
219 offset = (449 - 20);
220 }
221 drawSimpleMeshRange(NAMED_SMMesh, offset * 6, 20 * 6);
222}
223
224void
225draw_home_button()
226{
227 color(1.0f, 1.0f, 1.0f, 1.0f);
228 bindTexture(NAMED_PFTexLinear, 0, params->homeButtonId);
229
230 float scale = 2.0f / SCREEN_WIDTH_PX;
231
232 float x = 0.0f;
233
234 float y = -(SCREEN_HEIGHT_PX / (float)SCREEN_WIDTH_PX);
235 y += g_Zoom * (scale * params->homeButtonTextureHeight / 2);
236
237 float z = 0.0f;
238 drawSprite(x, y, z, params->homeButtonTextureWidth, params->homeButtonTextureHeight);
239}
240
241int
242main(int launchID)
243{
244 // Compute dt in seconds.
245 int newTime = uptimeMillis();
246 g_DT = (newTime - g_LastTime) / 1000.f;
247 g_LastTime = newTime;
248
249 //debugF("zoom", g_Zoom);
250 if (g_Zoom != g_ZoomTarget) {
251 float dz = (g_ZoomTarget - g_Zoom) * g_DT * 5;
252 if (dz && (fabsf(dz) < 0.03f)) {
253 if (dz > 0) {
254 dz = 0.03f;
255 } else {
256 dz = -0.03f;
257 }
258 }
259 if (fabsf(g_Zoom - g_ZoomTarget) < fabsf(dz)) {
260 g_Zoom = g_ZoomTarget;
261 } else {
262 g_Zoom += dz;
263 }
264 readback->zoom = g_Zoom;
265 }
266
267 // Set clear value to dim the background based on the zoom position.
268 if (g_Zoom < 0.001f) {
269 pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
270 // When we're zoomed out and not tracking motion events, reset the pos to 0.
271 if (!g_LastTouchDown) {
272 g_PosPage = 0;
273 }
274 return 1; // 0;
275 } else if (g_Zoom < 0.99f) {
276 pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom);
277 } else {
278 pfClearColor(0.0f, 0.0f, 0.0f, 0.99f);
279 }
280
281 // icons & labels
282 int iconCount = state->iconCount;
283 g_PageCount = count_pages(iconCount);
284
285 updatePos(0.1f);
286 readback->posX = g_PosPage;
287 readback->velocity = g_PosVelocity;
288
289 //debugF(" draw g_PosPage", g_PosPage);
290
291 // Draw the icons ========================================
292
293 // Bug makes 1.0f alpha fail.
294 //color(0.2f, 0.2f, 0.2f, 0.99f);
295 //bindProgramFragment(NAMED_PFColor);
296 //positionStrip(0, 0);
297 //drawSimpleMesh(NAMED_SMMesh);
298
299 bindProgramFragment(NAMED_PFTexLinear);
300
301
302 int lastIcon = iconCount-1;
303
304 int page = g_PosPage;
305 float currentPagePosition = g_PosPage - page;
306
307 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
308 float scale = (1 / g_Zoom);
309
310 float pageAngle = VIEW_ANGLE * 1.2f;
311
312 float zoomOffset = 40 * (1 - g_Zoom);
313 int drawPage;
314 //lastIcon = 1;
315 for (drawPage = 0; drawPage < g_PageCount; drawPage++) {
316 int r, c;
317 for (r=0; r < 4; r++) {
318 for (c=0; c < 4; c++) {
319 int iconNum = drawPage * 16 + c + r * 4;
320 if (iconNum <= lastIcon) {
321 float p = (((float)drawPage) - g_PosPage) * 5.f;
322 p += c - 1.5f;
323 p += zoomOffset;
324 if (fabsf(p) > 2) {
325 drawIcon(r, p, iconNum);
326 }
327 }
328 }
329 }
330 }
331
332 for (drawPage = 0; drawPage < g_PageCount; drawPage++) {
333 int r, c;
334 for (r=0; r < 4; r++) {
335 for (c=0; c < 4; c++) {
336 int iconNum = drawPage * 16 + c + r * 4;
337 if (iconNum <= lastIcon) {
338 float p = (((float)drawPage) - g_PosPage) * 5.f;
339 p += c - 1.5f;
340 p += zoomOffset;
341 float x = (p * 1.13f + 1.88f) * getWidth() * 0.2f;
342 float y = 570 - r * 147;
343
344 if (fabsf(p) <= 2) {
345 drawIcon(r, p, iconNum);
346 }
347 if (fabsf(p) <= 2.5) {
348 float a = (1.2f - maxf(scale, 1.0f)) * 5;
349 color(1.0f, 1.0f, 1.0f, a);
350 bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_LABEL_IDS, iconNum));
351 drawSpriteScreenspace(x, y, 0,
352 params->bubbleBitmapWidth, params->bubbleBitmapHeight);
353 }
354 }
355 }
356 }
357
358 }
359
360 // Draw the home button ========================================
361 //draw_home_button();
362
363 // Bug workaround where the last frame is not always displayed
364 // So we keep rendering until the bug is fixed.
365 return 1; //(g_PosVelocity != 0) || fracf(g_PosPage) || g_Zoom != g_ZoomTarget);
366}
367