blob: bae390fdce388647860ec2807841742b9180bfdd [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 Onorato93839052009-08-06 20:34:32 -070023
Joe Onorato43e7bcf2009-08-08 18:53:53 -070024// Scratch variables ======
Joe Onoratod769a632009-08-11 17:09:02 -070025#define SCRATCH_ADJUSTED_DECELERATION 0
Joe Onorato93839052009-08-06 20:34:32 -070026
Joe Onorato43e7bcf2009-08-08 18:53:53 -070027// Drawing constants, should be parameters ======
28#define SCREEN_WIDTH 480
29#define SCREEN_HEIGHT 854
30#define COLUMNS_PER_PAGE 4
31#define ROWS_PER_PAGE 4
32#define DIAMETER 8.0f
33
34#define PAGE_PADDING_TOP_PX 80
35#define CELL_PADDING_TOP_PX 5
36#define ICON_HEIGHT_PX 64
37#define ICON_LABEL_GUTTER_PX 5
38#define CELL_PADDING_BOTTOM_PX 5
39#define ROW_GUTTER_PX 10
40
41#define PAGE_PADDING_LEFT_PX 22
42#define CELL_WIDTH_PX 105
43#define ICON_WIDTH_PX 64
44#define COLUMN_GUTTER_PX 5
45#define LABEL_WIDTH_PX 105
46
Joe Onoratod769a632009-08-11 17:09:02 -070047
Joe Onorato43e7bcf2009-08-08 18:53:53 -070048int
49count_pages(int iconCount)
Joe Onorato93839052009-08-06 20:34:32 -070050{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070051 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
52 int pages = iconCount / iconsPerPage;
53 if (pages*iconsPerPage != iconCount) {
Joe Onoratod769a632009-08-11 17:09:02 -070054 pages++;
Joe Onorato43e7bcf2009-08-08 18:53:53 -070055 }
Joe Onoratod769a632009-08-11 17:09:02 -070056 return pages;
57}
58
59int current_page(float scrollXPx)
60{
61 return -scrollXPx / SCREEN_WIDTH;
62}
63
64float
65modf(float x, float y)
66{
67 return x-(y*floorf(x/y));
Joe Onorato93839052009-08-06 20:34:32 -070068}
69
Joe Onorato43e7bcf2009-08-08 18:53:53 -070070int
Joe Onoratod769a632009-08-11 17:09:02 -070071main(int launchID)
Joe Onorato93839052009-08-06 20:34:32 -070072{
Joe Onorato43e7bcf2009-08-08 18:53:53 -070073 // Clear to transparent
Joe Onorato93839052009-08-06 20:34:32 -070074 pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -070075
Joe Onorato43e7bcf2009-08-08 18:53:53 -070076 // icons & labels
Joe Onorato1feb3a82009-08-08 22:32:00 -070077 int iconCount = loadI32(ALLOC_STATE, STATE_ICON_COUNT);
Joe Onorato43e7bcf2009-08-08 18:53:53 -070078 int pageCount = count_pages(iconCount);
79
80 float densityScale = 2.0f / SCREEN_WIDTH;
81 float screenTop = SCREEN_HEIGHT/(float)SCREEN_WIDTH; // == (SCREEN_HEIGHT/2)*densityScale;
82
83 float pagePaddingTop = screenTop - (PAGE_PADDING_TOP_PX * densityScale);
84 float pageGutterY = ROW_GUTTER_PX * densityScale;
85 float cellHeight = (CELL_PADDING_TOP_PX + ICON_HEIGHT_PX + ICON_LABEL_GUTTER_PX
86 + loadI32(ALLOC_PARAMS, PARAM_BUBBLE_HEIGHT)
87 + CELL_PADDING_BOTTOM_PX + ROW_GUTTER_PX) * densityScale;
88 float cellPaddingTop = CELL_PADDING_TOP_PX * densityScale;
89 float iconHeight = ICON_HEIGHT_PX * densityScale;
90 float iconLabelGutter = ICON_LABEL_GUTTER_PX * densityScale;
91
92 float pagePaddingLeft = PAGE_PADDING_LEFT_PX * densityScale;
93 float cellWidth = CELL_WIDTH_PX * densityScale;
94 float iconWidth = ICON_WIDTH_PX * densityScale;
95 float columnGutter = COLUMN_GUTTER_PX * densityScale;
96
Joe Onorato43e7bcf2009-08-08 18:53:53 -070097 float labelWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_WIDTH) * densityScale;
98 float labelTextureWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_WIDTH) * densityScale;
99 float labelTextureHeight = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_HEIGHT) * densityScale;
100
Joe Onoratod769a632009-08-11 17:09:02 -0700101 float scrollXPx = loadI32(ALLOC_STATE, STATE_SCROLL_X);
102 float maxScrollX = -(pageCount-1) * SCREEN_WIDTH;
103 int done = 0;
104
105 // If we've been given a velocity, start a fling
106 float flingVelocityPxMs = loadI32(ALLOC_STATE, STATE_FLING_VELOCITY_X);
107 if (flingVelocityPxMs != 0) {
108 // how many screens will this velocity do? TODO: use long
109 // G * ppi * friction // why G? // friction = 0.015
110 float deceleration = loadF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION);
111 if (deceleration == 0) {
112 // On the first frame, calculate which animation we're going to do. If it's
113 // going to end up less than halfway into a page, we'll bounce back the previous
114 // page. Otherwise, we'll adjust the deceleration so it just makes it to the
115 // page boundary.
116 if (flingVelocityPxMs > 0) {
117 deceleration = -1000;
118 } else {
119 deceleration = 1000;
120 }
121 // v' = v + at --> t = -v / a
122 // x' = x + vt + .5 a t^2 --> x' = x + (-v^2/a) + (v^2/2a)
123 float endPos = scrollXPx + (-(flingVelocityPxMs*flingVelocityPxMs)/deceleration)
124 + ((flingVelocityPxMs*flingVelocityPxMs)/(2.0f*deceleration));
125
126 if (endPos > 0) {
127 endPos = 0;
128 }
129 if (endPos < maxScrollX) {
130 endPos = maxScrollX;
131 }
132 float screenWidthFloat = SCREEN_WIDTH;
133 float scrollOnPage = modf(endPos, screenWidthFloat);
134 }
135
136 // adjust the deceleration so we always hit a page boundary
137
138 int flingTime = loadI32(ALLOC_STATE, STATE_FLING_TIME);
139 int now = uptimeMillis();
140 float elapsedTime = (now - flingTime) / 1000.0f;
141 int animEndTime = -flingVelocityPxMs / deceleration;
142
143 done = elapsedTime >= animEndTime;
144 if (done) {
145 // clamp the time to the end value
146 elapsedTime = animEndTime;
147 }
148
149 float tension = 2.0f;
150 float interp = elapsedTime * elapsedTime * ((tension + 1) * elapsedTime + tension) + 1.0f; // normalized 0..1
151
152 int flingOffsetPx = (flingVelocityPxMs * elapsedTime)
153 + (deceleration * elapsedTime * elapsedTime / 2.0f);
154 scrollXPx += flingOffsetPx;
155
156 }
157
158 if (scrollXPx > 0) {
159 scrollXPx = 0;
160 }
161 if (scrollXPx < maxScrollX) {
162 scrollXPx = maxScrollX;
163 }
164
165 storeI32(ALLOC_STATE, STATE_CURRENT_SCROLL_X, scrollXPx);
166 if (done) {
167 storeI32(ALLOC_STATE, STATE_SCROLL_X, scrollXPx);
168 storeI32(ALLOC_STATE, STATE_FLING_VELOCITY_X, 0);
169 storeF(ALLOC_STATE, STATE_ADJUSTED_DECELERATION, 0);
170 }
171
172 // don't draw everything, just the page before and after what we're viewing.
173 int currentPage = current_page(scrollXPx);
174 float screenWidth = SCREEN_WIDTH * densityScale;
175
176 float pageLeft = -1 + ((currentPage-1)*screenWidth);
177 int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
178 int icon = (currentPage-1) * iconsPerPage;
179 if (icon < 0) {
180 icon = 0;
181 }
Joe Onorato1feb3a82009-08-08 22:32:00 -0700182 int page;
Joe Onoratod769a632009-08-11 17:09:02 -0700183 int lastIcon = icon + (iconsPerPage*3);
184 if (lastIcon >= iconCount) {
185 lastIcon = iconCount-1;
186 }
Joe Onorato1feb3a82009-08-08 22:32:00 -0700187 pageLeft += scrollXPx * densityScale;
Joe Onoratod769a632009-08-11 17:09:02 -0700188 for (page=currentPage-1; page<pageCount && page<=(currentPage+1); page++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700189 // Bug makes 1.0f alpha fail.
190 color(1.0f, 1.0f, 1.0f, 0.99f);
191
192 float cellTop = pagePaddingTop;
193 int row;
Joe Onoratod769a632009-08-11 17:09:02 -0700194 for (row=0; row<ROWS_PER_PAGE && icon<=lastIcon; row++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700195 float s = pageLeft; // distance along the linear strip of icons in normalized coords
196 s += pagePaddingLeft;
197 int col;
Joe Onoratod769a632009-08-11 17:09:02 -0700198 for (col=0; col<COLUMNS_PER_PAGE && icon<=lastIcon; col++) {
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700199 // icon
200 float iconLeft = s + ((cellWidth-iconWidth)/2.0f);
201 float iconRight = iconLeft + iconWidth;
202 float iconTop = cellTop - cellPaddingTop;
203 float iconBottom = iconTop - iconHeight;
Joe Onorato93839052009-08-06 20:34:32 -0700204
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700205 bindProgramFragment(NAMED_PF);
206 bindProgramFragmentStore(NAMED_PFS);
Joe Onorato93839052009-08-06 20:34:32 -0700207
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700208 bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
209 drawRect(iconLeft, iconTop, iconRight, iconBottom, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700210
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700211 // label
212 float labelLeft = s + ((cellWidth-labelWidth)/2.0f);
213 float labelTop = iconBottom - iconLabelGutter;
Joe Onorato93839052009-08-06 20:34:32 -0700214
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700215 bindProgramFragment(NAMED_PFText);
216 bindProgramFragmentStore(NAMED_PFSText);
Joe Onorato93839052009-08-06 20:34:32 -0700217
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700218 bindTexture(NAMED_PFText, 0, loadI32(ALLOC_LABEL_IDS, icon));
219 drawRect(labelLeft, labelTop, labelLeft+labelTextureWidth,
220 labelTop-labelTextureHeight, 0.0f);
Joe Onorato93839052009-08-06 20:34:32 -0700221
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700222 s += cellWidth + columnGutter;
223 icon++;
Joe Onorato93839052009-08-06 20:34:32 -0700224 }
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700225 cellTop -= cellHeight;
Joe Onorato93839052009-08-06 20:34:32 -0700226 }
Joe Onorato43e7bcf2009-08-08 18:53:53 -0700227 pageLeft += 2.0f;
Joe Onorato93839052009-08-06 20:34:32 -0700228 }
229
Joe Onoratod769a632009-08-11 17:09:02 -0700230 return !done;
Joe Onorato93839052009-08-06 20:34:32 -0700231}
232