From 0f505e57055a42af1ee944c7a29e0ab2cdb627fc Mon Sep 17 00:00:00 2001 From: Jason Sams Date: Tue, 13 Oct 2009 17:18:35 -0700 Subject: [PATCH] Checkpoint new rollo scripts. Not currently in use. --- res/raw/rollo2.c | 84 +++++--- res/raw/rollo3.c | 493 +++++++++++++++++++++++++++++++++++++++++++++++ res/raw/rollo4.c | 429 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 981 insertions(+), 25 deletions(-) create mode 100644 res/raw/rollo3.c create mode 100644 res/raw/rollo4.c diff --git a/res/raw/rollo2.c b/res/raw/rollo2.c index d9077855f5..cc273b1ab3 100644 --- a/res/raw/rollo2.c +++ b/res/raw/rollo2.c @@ -19,11 +19,40 @@ float g_DT; int g_LastTime; int g_PageCount; float g_Zoom; -float g_ZoomTarget; +float g_OldPosPage; +float g_OldPosVelocity; +float g_OldZoom; // Drawing constants, should be parameters ====== #define VIEW_ANGLE 1.28700222f +int g_DrawLastFrame; +int lastFrame(int draw) { + // We draw one extra frame to work around the last frame post bug. + // We also need to track if we drew the last frame to deal with large DT + // in the physics. + int ret = g_DrawLastFrame | draw; + g_DrawLastFrame = draw; + return ret; // should return draw instead. +} + +void updateReadback() { + if ((g_OldPosPage != g_PosPage) || + (g_OldPosVelocity != g_PosVelocity) || + (g_OldZoom != g_Zoom)) { + + g_OldPosPage = g_PosPage; + g_OldPosVelocity = g_PosVelocity; + g_OldZoom = g_Zoom; + + int i[3]; + i[0] = g_PosPage * (1 << 16); + i[1] = g_PosVelocity * (1 << 16); + i[2] = g_OldZoom * (1 << 16); + sendToClient(&i[0], 1, 12, 1); + } +} + void init() { g_AttractionTable[0] = 6.5f; g_AttractionTable[1] = 6.5f; @@ -50,7 +79,6 @@ void init() { g_LastTouchDown = 0; g_LastPositionX = 0; g_Zoom = 0; - g_ZoomTarget = 0; } void move() { @@ -97,16 +125,6 @@ void touchUp() { g_LastTouchDown = 0; } -void setZoomTarget() { - g_ZoomTarget = state->zoomTarget; - //debugF("zoom target", g_ZoomTarget); -} - -void setZoom() { - readback->zoom = g_Zoom = g_ZoomTarget = state->zoom; - //debugF("zoom", g_ZoomTarget); -} - int count_pages(int iconCount) { @@ -246,9 +264,19 @@ main(int launchID) g_DT = (newTime - g_LastTime) / 1000.f; g_LastTime = newTime; - //debugF("zoom", g_Zoom); - if (g_Zoom != g_ZoomTarget) { - float dz = (g_ZoomTarget - g_Zoom) * g_DT * 5; + if (!g_DrawLastFrame) { + // If we stopped rendering we cannot use DT. + // assume 30fps in this case. + g_DT = 0.033f; + } + if (g_DT > 0.2f) { + // physics may break if DT is large. + g_DT = 0.2f; + } + + debugF("zoom", g_Zoom); + if (g_Zoom != state->zoomTarget) { + float dz = (state->zoomTarget - g_Zoom) * g_DT * 5; if (dz && (fabsf(dz) < 0.03f)) { if (dz > 0) { dz = 0.03f; @@ -256,26 +284,26 @@ main(int launchID) dz = -0.03f; } } - if (fabsf(g_Zoom - g_ZoomTarget) < fabsf(dz)) { - g_Zoom = g_ZoomTarget; + if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) { + g_Zoom = state->zoomTarget; } else { g_Zoom += dz; } - readback->zoom = g_Zoom; + updateReadback(); } // Set clear value to dim the background based on the zoom position. - if (g_Zoom < 0.001f) { + if ((g_Zoom < 0.001f) && (state->zoomTarget < 0.001f)) { pfClearColor(0.0f, 0.0f, 0.0f, 0.0f); // When we're zoomed out and not tracking motion events, reset the pos to 0. if (!g_LastTouchDown) { g_PosPage = 0; } - return 1; // 0; - } else if (g_Zoom < 0.99f) { + return lastFrame(0); + } else if (g_Zoom < 0.85f) { pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom); } else { - pfClearColor(0.0f, 0.0f, 0.0f, 0.99f); + pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom); } // icons & labels @@ -283,10 +311,9 @@ main(int launchID) g_PageCount = count_pages(iconCount); updatePos(0.1f); - readback->posX = g_PosPage; - readback->velocity = g_PosVelocity; + updateReadback(); - //debugF(" draw g_PosPage", g_PosPage); + debugF(" draw g_PosPage", g_PosPage); // Draw the icons ======================================== @@ -357,6 +384,13 @@ main(int launchID) } + { + float mat1[16]; + matrixLoadIdentity(mat1); + vpLoadModelMatrix(mat1); + vpLoadTextureMatrix(mat1); + } + // Draw the home button ======================================== //draw_home_button(); diff --git a/res/raw/rollo3.c b/res/raw/rollo3.c new file mode 100644 index 0000000000..d793267374 --- /dev/null +++ b/res/raw/rollo3.c @@ -0,0 +1,493 @@ +#pragma version(1) +#pragma stateVertex(PV) +#pragma stateFragment(PFTexLinear) +#pragma stateStore(PSIcons) + +#define PI 3.14159f + + +// Attraction to center values from page edge to page center. +float g_AttractionTable[9]; +float g_FrictionTable[9]; +float g_PhysicsTableSize; + +float g_PosPage; +float g_PosVelocity; +float g_LastPositionX; +int g_LastTouchDown; +float g_DT; +int g_LastTime; +int g_PosMax; +float g_Zoom; +float g_OldPosPage; +float g_OldPosVelocity; +float g_OldZoom; + +// Drawing constants, should be parameters ====== +#define VIEW_ANGLE 1.28700222f + +int g_DrawLastFrame; +int lastFrame(int draw) { + // We draw one extra frame to work around the last frame post bug. + // We also need to track if we drew the last frame to deal with large DT + // in the physics. + int ret = g_DrawLastFrame | draw; + g_DrawLastFrame = draw; + return ret; // should return draw instead. +} + +void updateReadback() { + if ((g_OldPosPage != g_PosPage) || + (g_OldPosVelocity != g_PosVelocity) || + (g_OldZoom != g_Zoom)) { + + g_OldPosPage = g_PosPage; + g_OldPosVelocity = g_PosVelocity; + g_OldZoom = g_Zoom; + + int i[3]; + i[0] = g_PosPage * (1 << 16); + i[1] = g_PosVelocity * (1 << 16); + i[2] = g_OldZoom * (1 << 16); + sendToClient(&i[0], 1, 12, 1); + } +} + + +void init() { + g_AttractionTable[0] = 6.5f; + g_AttractionTable[1] = 6.5f; + g_AttractionTable[2] = 7.0f; + g_AttractionTable[3] = 6.0f; + g_AttractionTable[4] = -6.0f; + g_AttractionTable[5] = -7.0f; + g_AttractionTable[6] = -6.5f; + g_AttractionTable[7] = -6.5f; + g_AttractionTable[8] = -6.5f; // dup 7 to avoid a clamp later + g_FrictionTable[0] = 3.5f; + g_FrictionTable[1] = 3.6f; + g_FrictionTable[2] = 4.0f; + g_FrictionTable[3] = 5.0f; + g_FrictionTable[4] = 5.0f; + g_FrictionTable[5] = 4.0f; + g_FrictionTable[6] = 3.6f; + g_FrictionTable[7] = 3.5f; + g_FrictionTable[8] = 3.5f; // dup 7 to avoid a clamp later + g_PhysicsTableSize = 7; + + g_PosVelocity = 0; + g_PosPage = 0; + g_LastTouchDown = 0; + g_LastPositionX = 0; + g_Zoom = 0; +} + +void move() { + if (g_LastTouchDown) { + float dx = -(state->newPositionX - g_LastPositionX); + g_PosVelocity = 0; + g_PosPage += dx * 4; + + float pmin = -0.25f; + float pmax = g_PosMax + 0.25f; + g_PosPage = clampf(g_PosPage, pmin, pmax); + } + g_LastTouchDown = state->newTouchDown; + g_LastPositionX = state->newPositionX; + //debugF("Move P", g_PosPage); +} + +void fling() { + g_LastTouchDown = 0; + g_PosVelocity = -state->flingVelocityX * 2; + float av = fabsf(g_PosVelocity); + float minVel = 3.5f; + + minVel *= 1.f - (fabsf(fracf(g_PosPage + 0.5f) - 0.5f) * 0.45f); + + if (av < minVel && av > 0.2f) { + if (g_PosVelocity > 0) { + g_PosVelocity = minVel; + } else { + g_PosVelocity = -minVel; + } + } + + if (g_PosPage <= 0) { + g_PosVelocity = maxf(0, g_PosVelocity); + } + if (g_PosPage > g_PosMax) { + g_PosVelocity = minf(0, g_PosVelocity); + } +} + +void touchUp() { + g_LastTouchDown = 0; +} + +int +count_pages(int iconCount) +{ + int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE; + int pages = iconCount / iconsPerPage; + if (pages*iconsPerPage != iconCount) { + pages++; + } + return pages; +} + +float +modf(float x, float y) +{ + return x-(y*floorf(x/y)); +} + +void updatePos() { + if (g_LastTouchDown) { + return; + } + + int outOfRange = 0; + float tablePosNorm = fracf(g_PosPage + 0.5f); + float tablePosF = tablePosNorm * g_PhysicsTableSize; + int tablePosI = tablePosF; + float tablePosFrac = tablePosF - tablePosI; + float accel = lerpf(g_AttractionTable[tablePosI], + g_AttractionTable[tablePosI + 1], + tablePosFrac) * g_DT; + float friction = lerpf(g_FrictionTable[tablePosI], + g_FrictionTable[tablePosI + 1], + tablePosFrac) * g_DT; + + if (g_PosPage < -0.5f) { + accel = g_AttractionTable[0] * g_DT; + friction = g_FrictionTable[0] * g_DT; + outOfRange = 1; + } + if ((g_PosPage - g_PosMax) > 0.5f) { + accel = g_AttractionTable[(int)g_PhysicsTableSize] * g_DT; + friction = g_FrictionTable[(int)g_PhysicsTableSize] * g_DT; + outOfRange = 1; + } + + // If our velocity is low OR acceleration is opposing it, apply it. + if (fabsf(g_PosVelocity) < 1.0f || (g_PosVelocity * accel) < 0) { + g_PosVelocity += accel; + } + + if ((friction > fabsf(g_PosVelocity)) && + (friction > fabsf(accel)) && + !outOfRange) { + // Special get back to center and overcome friction physics. + float t = tablePosNorm - 0.5f; + if (fabsf(t) < (friction * g_DT)) { + // really close, just snap + g_PosPage = roundf(g_PosPage); + g_PosVelocity = 0; + } else { + if (t > 0) { + g_PosVelocity = -friction; + } else { + g_PosVelocity = friction; + } + } + } else { + // Normal physics + if (g_PosVelocity > 0) { + g_PosVelocity -= friction; + g_PosVelocity = maxf(g_PosVelocity, 0); + } else { + g_PosVelocity += friction; + g_PosVelocity = minf(g_PosVelocity, 0); + } + } + g_PosPage += g_PosVelocity * g_DT; + + // Check for out of boundry conditions. + if (g_PosPage < 0 && g_PosVelocity < 0) { + g_PosPage = maxf(g_PosPage, -0.49); + float damp = 1.0 + (g_PosPage * 4); + damp = clampf(damp, 0.f, 0.9f); + g_PosVelocity *= damp; + } + if (g_PosPage > g_PosMax && g_PosVelocity > 0) { + g_PosPage = minf(g_PosPage, g_PosMax + 0.49); + float damp = 1.0 - ((g_PosPage - g_PosMax) * 4); + damp = clampf(damp, 0.f, 0.9f); + g_PosVelocity *= damp; + } +} + +int positionStrip(float row, float column, int isTop) +{ + float mat1[16]; + + float x = 0.5f * (column - 1.5f); + + float scale = 72.f * 3 / getWidth(); + //float xscale = scale * 4.55 / 1.8f / 2; + + if (isTop) { + matrixLoadTranslate(mat1, x, 0.8f, 0.f); + matrixScale(mat1, scale, scale, 1.f); + } else { + matrixLoadTranslate(mat1, x, -0.9f, 0.f); + matrixScale(mat1, scale, -scale, 1.f); + } + vpLoadModelMatrix(mat1); + + float soff = row; + if (isTop) { + matrixLoadScale(mat1, 1.f, -0.85f, 1.f); + matrixTranslate(mat1, 0, -(row * 1.4) - 0.97, 0); + } else { + matrixLoadScale(mat1, 1.f, 0.85f, 1.f); + matrixTranslate(mat1, 0, -(row * 1.4) - 0.45, 0); + } + vpLoadTextureMatrix(mat1); + + return 0;//- soff * 10.f; +} + +void +draw_home_button() +{ + color(1.0f, 1.0f, 1.0f, 1.0f); + bindTexture(NAMED_PFTexLinear, 0, params->homeButtonId); + + float scale = 2.0f / SCREEN_WIDTH_PX; + + float x = 0.0f; + + float y = -(SCREEN_HEIGHT_PX / (float)SCREEN_WIDTH_PX); + y += g_Zoom * (scale * params->homeButtonTextureHeight / 2); + + float z = 0.0f; + drawSprite(x, y, z, params->homeButtonTextureWidth, params->homeButtonTextureHeight); +} + +void drawFrontGrid(float rowOffset) +{ + float h = getHeight(); + float w = getWidth(); + + int intRowOffset = rowOffset; + float rowFrac = rowOffset - intRowOffset; + float colWidth = getWidth() / 4; + float rowHeight = colWidth + 25.f; + float yoff = h - ((h - (rowHeight * 4.f)) / 2); + + yoff -= 110; + + int row, col; + int iconNum = intRowOffset * 4; + float ymax = yoff; + float ymin = yoff - (3 * rowHeight) - 70; + + for (row = 0; row < 5; row++) { + float y = yoff - ((-rowFrac + row) * rowHeight); + + for (col=0; col < 4; col++) { + if (iconNum >= state->iconCount) { + return; + } + + if (iconNum >= 0) { + float x = colWidth * col - ((128 - colWidth) / 2); + + if ((y >= ymin) && (y <= ymax)) { + color(1.f, 1.f, 1.f, 1.f); + bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, iconNum)); + drawSpriteScreenspace(x, y, 0, 128, 128); + } + + float y2 = y - 44; + float a = 1.f; + if (y2 < ymin) { + a = 1.f - (ymin - y2) * 0.02f; + } + if (y > (ymax + 40)) { + a = 1.f - (y - (ymax + 40)) * 0.02f; + } + a = clampf(a, 0, 1); + + color(1, 1, 1, a); + bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_LABEL_IDS, iconNum)); + drawSpriteScreenspace(x, y - 44, 0, + params->bubbleBitmapWidth, params->bubbleBitmapHeight); + } + iconNum++; + } + } +} + +void drawTop(float rowOffset) +{ + int intRowOffset = rowOffset; + + int row, col; + int iconNum = 0; + for (row = 0; row < rowOffset; row++) { + for (col=0; col < 4; col++) { + if (iconNum >= state->iconCount) { + return; + } + + int ps = positionStrip(rowOffset - row, col, 1); + bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, iconNum)); + drawSimpleMesh(NAMED_SMMesh2); + iconNum++; + } + } +} + +void drawBottom(float rowOffset) +{ + float pos = -1.f; + int intRowOffset = rowOffset; + pos -= rowOffset - intRowOffset; + + int row, col; + int iconNum = (intRowOffset + 3) * 4; + while (1) { + for (col=0; col < 4; col++) { + if (iconNum >= state->iconCount) { + return; + } + if (pos > -1) { + int ps = positionStrip(pos, col, 0); + bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, iconNum)); + drawSimpleMesh(NAMED_SMMesh2); + } + iconNum++; + } + pos += 1.f; + } +} + +int +main(int launchID) +{ + // Compute dt in seconds. + int newTime = uptimeMillis(); + g_DT = (newTime - g_LastTime) / 1000.f; + g_LastTime = newTime; + + if (!g_DrawLastFrame) { + // If we stopped rendering we cannot use DT. + // assume 30fps in this case. + g_DT = 0.033f; + } + if (g_DT > 0.2f) { + // physics may break if DT is large. + g_DT = 0.2f; + } + + if (g_Zoom != state->zoomTarget) { + float dz = (state->zoomTarget - g_Zoom) * g_DT * 5; + if (dz && (fabsf(dz) < 0.03f)) { + if (dz > 0) { + dz = 0.03f; + } else { + dz = -0.03f; + } + } + if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) { + g_Zoom = state->zoomTarget; + } else { + g_Zoom += dz; + } + updateReadback(); + } + + // Set clear value to dim the background based on the zoom position. + if ((g_Zoom < 0.001f) && (state->zoomTarget < 0.001f)) { + pfClearColor(0.0f, 0.0f, 0.0f, 0.0f); + // When we're zoomed out and not tracking motion events, reset the pos to 0. + if (!g_LastTouchDown) { + g_PosPage = 0; + } + return lastFrame(0); + } else if (g_Zoom < 0.85f) { + pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom); + } else { + pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom); + } + + // icons & labels + int iconCount = state->iconCount; + g_PosMax = ((iconCount + 3) / 4) - 4; + if (g_PosMax < 0) g_PosMax = 0; + + updatePos(0.1f); + updateReadback(); + + //debugF(" draw g_PosPage", g_PosPage); + + // Draw the icons ======================================== + + //bindProgramFragment(NAMED_PFColor); + //positionStrip(1, 0, 0); + //drawSimpleMesh(NAMED_SMMesh2); + //positionStrip(1, 1); + //drawSimpleMesh(NAMED_SMMesh2); + //positionStrip(1, 2); + //drawSimpleMesh(NAMED_SMMesh2); + //positionStrip(1, 3); + //drawSimpleMesh(NAMED_SMMesh2); + + bindProgramFragment(NAMED_PFTexLinear); + + + int lastIcon = iconCount-1; + + int page = g_PosPage; + float currentPagePosition = g_PosPage - page; + + int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE; + float scale = (1 / g_Zoom); + + float pageAngle = VIEW_ANGLE * 1.2f; + + float zoomOffset = 40 * (1 - g_Zoom); + + drawTop(g_PosPage); + drawBottom(g_PosPage); + drawFrontGrid(g_PosPage); + + { + float mat1[16]; + matrixLoadIdentity(mat1); + vpLoadModelMatrix(mat1); + vpLoadTextureMatrix(mat1); + } + + if (0) { + float h = getHeight(); + + color(1, 1, 1, 1); + bindProgramFragment(NAMED_PFColor); + bindProgramVertex(NAMED_PVOrtho); + float dy = 145.f; + float y = h - ((h - (dy * 4.f)) / 2); + + drawLine(0, y, 0, 480, y, 0); + y -= dy; + drawLine(0, y, 0, 480, y, 0); + y -= dy; + drawLine(0, y, 0, 480, y, 0); + y -= dy; + drawLine(0, y, 0, 480, y, 0); + y -= dy; + drawLine(0, y, 0, 480, y, 0); + } + + + // Draw the home button ======================================== + //draw_home_button(); + + // Bug workaround where the last frame is not always displayed + // So we keep rendering until the bug is fixed. + return lastFrame((g_PosVelocity != 0) || fracf(g_PosPage) || g_Zoom != state->zoomTarget); +} + diff --git a/res/raw/rollo4.c b/res/raw/rollo4.c new file mode 100644 index 0000000000..ac158de4e3 --- /dev/null +++ b/res/raw/rollo4.c @@ -0,0 +1,429 @@ +#pragma version(1) +#pragma stateVertex(PV) +#pragma stateFragment(PFTexLinear) +#pragma stateStore(PSIcons) + +#define PI 3.14159f + + +// Attraction to center values from page edge to page center. +float g_AttractionTable[9]; +float g_FrictionTable[9]; +float g_PhysicsTableSize; + +float g_PosPage; +float g_PosVelocity; +float g_LastPositionX; +int g_LastTouchDown; +float g_DT; +int g_LastTime; +int g_PageCount; +float g_Zoom; + +// Drawing constants, should be parameters ====== +#define VIEW_ANGLE 1.28700222f + +float g_OldPosPage; +float g_OldPosVelocity; +float g_OldZoom; + +int g_DrawLastFrame; +int lastFrame(int draw) { + // We draw one extra frame to work around the last frame post bug. + // We also need to track if we drew the last frame to deal with large DT + // in the physics. + int ret = g_DrawLastFrame | draw; + g_DrawLastFrame = draw; + return ret; // should return draw instead. +} + +void updateReadback() { + if ((g_OldPosPage != g_PosPage) || + (g_OldPosVelocity != g_PosVelocity) || + (g_OldZoom != g_Zoom)) { + + g_OldPosPage = g_PosPage; + g_OldPosVelocity = g_PosVelocity; + g_OldZoom = g_Zoom; + + int i[3]; + i[0] = g_PosPage * (1 << 16); + i[1] = g_PosVelocity * (1 << 16); + i[2] = g_OldZoom * (1 << 16); + sendToClient(&i[0], 1, 12, 1); + } +} + +void init() { + g_AttractionTable[0] = 6.5f; + g_AttractionTable[1] = 6.5f; + g_AttractionTable[2] = 7.0f; + g_AttractionTable[3] = 6.0f; + g_AttractionTable[4] = -6.0f; + g_AttractionTable[5] = -7.0f; + g_AttractionTable[6] = -6.5f; + g_AttractionTable[7] = -6.5f; + g_AttractionTable[8] = -6.5f; // dup 7 to avoid a clamp later + g_FrictionTable[0] = 3.5f; + g_FrictionTable[1] = 3.6f; + g_FrictionTable[2] = 4.0f; + g_FrictionTable[3] = 5.0f; + g_FrictionTable[4] = 5.0f; + g_FrictionTable[5] = 4.0f; + g_FrictionTable[6] = 3.6f; + g_FrictionTable[7] = 3.5f; + g_FrictionTable[8] = 3.5f; // dup 7 to avoid a clamp later + g_PhysicsTableSize = 7; + + g_PosVelocity = 0; + g_PosPage = 0; + g_LastTouchDown = 0; + g_LastPositionX = 0; + g_Zoom = 0; +} + +void move() { + if (g_LastTouchDown) { + float dx = -(state->newPositionX - g_LastPositionX); + g_PosVelocity = 0; + g_PosPage += dx; + + float pmin = -0.25f; + float pmax = (g_PageCount - 1) + 0.25f; + g_PosPage = clampf(g_PosPage, pmin, pmax); + } + g_LastTouchDown = state->newTouchDown; + g_LastPositionX = state->newPositionX; + //debugF("Move P", g_PosPage); +} + +void fling() { + g_LastTouchDown = 0; + g_PosVelocity = -state->flingVelocityX; + float av = fabsf(g_PosVelocity); + float minVel = 3.5f; + + minVel *= 1.f - (fabsf(fracf(g_PosPage + 0.5f) - 0.5f) * 0.45f); + + if (av < minVel && av > 0.2f) { + if (g_PosVelocity > 0) { + g_PosVelocity = minVel; + } else { + g_PosVelocity = -minVel; + } + } + + if (g_PosPage <= 0) { + g_PosVelocity = maxf(0, g_PosVelocity); + } + if (g_PosPage > (g_PageCount - 1)) { + g_PosVelocity = minf(0, g_PosVelocity); + } + //debugF("fling v", g_PosVelocity); +} + +void touchUp() { + g_LastTouchDown = 0; +} + +int +count_pages(int iconCount) +{ + int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE; + int pages = iconCount / iconsPerPage; + if (pages*iconsPerPage != iconCount) { + pages++; + } + return pages; +} + +float +modf(float x, float y) +{ + return x-(y*floorf(x/y)); +} + +void updatePos() { + if (g_LastTouchDown) { + return; + } + + float tablePosNorm = fracf(g_PosPage + 0.5f); + float tablePosF = tablePosNorm * g_PhysicsTableSize; + int tablePosI = tablePosF; + float tablePosFrac = tablePosF - tablePosI; + float accel = lerpf(g_AttractionTable[tablePosI], + g_AttractionTable[tablePosI + 1], + tablePosFrac) * g_DT; + float friction = lerpf(g_FrictionTable[tablePosI], + g_FrictionTable[tablePosI + 1], + tablePosFrac) * g_DT; + //debugF(" accel", accel); + //debugF(" friction", friction); + + // If our velocity is low OR acceleration is opposing it, apply it. + if (fabsf(g_PosVelocity) < 1.0f || (g_PosVelocity * accel) < 0) { + g_PosVelocity += accel; + } + + if ((friction > fabsf(g_PosVelocity)) && (friction > fabsf(accel))) { + // Special get back to center and overcome friction physics. + float t = tablePosNorm - 0.5f; + if (fabsf(t) < (friction * g_DT)) { + // really close, just snap + g_PosPage = roundf(g_PosPage); + g_PosVelocity = 0; + } else { + if (t > 0) { + g_PosVelocity = -friction; + } else { + g_PosVelocity = friction; + } + } + } else { + // Normal physics + if (g_PosVelocity > 0) { + g_PosVelocity -= friction; + g_PosVelocity = maxf(g_PosVelocity, 0); + } else { + g_PosVelocity += friction; + g_PosVelocity = minf(g_PosVelocity, 0); + } + } + g_PosPage += g_PosVelocity * g_DT; + + // Check for out of boundry conditions. + if (g_PosPage < 0 && g_PosVelocity < 0) { + float damp = 1.0 + (g_PosPage * 4); + damp = clampf(damp, 0.f, 0.9f); + g_PosVelocity *= damp; + } + if (g_PosPage > (g_PageCount-1) && g_PosVelocity > 0) { + float damp = 1.0 - ((g_PosPage - g_PageCount + 1) * 4); + damp = clampf(damp, 0.f, 0.9f); + g_PosVelocity *= damp; + } +} + +float +far_size(float sizeAt0) +{ + return sizeAt0 * (RADIUS+2) / 2; // -2 is the camera z=(z-camZ)/z +} + +void +draw_page(int icon, int lastIcon, float centerAngle, float scale) +{ + int row; + int col; + + //debugF("center angle", centerAngle); + + float iconTextureWidth = ICON_WIDTH_PX / (float)ICON_TEXTURE_WIDTH_PX; + float iconTextureHeight = ICON_HEIGHT_PX / (float)ICON_TEXTURE_HEIGHT_PX; + + float iconWidthAngle = VIEW_ANGLE * ICON_WIDTH_PX / SCREEN_WIDTH_PX; + float columnGutterAngle = iconWidthAngle * 0.9f; + + float farIconSize = FAR_ICON_SIZE; + float iconGutterHeight = farIconSize * 1.3f; + + float farIconTextureSize = far_size(2 * ICON_TEXTURE_WIDTH_PX / (float)SCREEN_WIDTH_PX); + + float normalizedLabelWidth = 2 * params->bubbleWidth / (float)SCREEN_WIDTH_PX; + float farLabelHeight = far_size(params->bubbleHeight * (normalizedLabelWidth / params->bubbleWidth)); + + for (row=0; row 1.f) { + centerX *= scale; + } + + float iconLeftX = centerX - (cosine * farIconTextureSize * .5); + float iconRightX = centerX + (cosine * farIconTextureSize * .5); + float iconLeftZ = centerZ + (sine * farIconTextureSize * .5); + float iconRightZ = centerZ - (sine * farIconTextureSize * .5); + + color(1.0f, 1.0f, 1.0f, 0.99f); + if (state->selectedIconIndex == icon) { + bindTexture(NAMED_PFTexLinear, 0, state->selectedIconTexture); + drawQuadTexCoords( + iconLeftX, iconTextureTop, iconLeftZ, 0.0f, 0.0f, + iconRightX, iconTextureTop, iconRightZ, 1.0f, 0.0f, + iconRightX, iconTextureBottom, iconRightZ, 1.0f, 1.0f, + iconLeftX, iconTextureBottom, iconLeftZ, 0.0f, 1.0f); + } else { + bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_ICON_IDS, icon)); + drawQuadTexCoords( + iconLeftX, iconTextureTop, iconLeftZ, 0.0f, 0.0f, + iconRightX, iconTextureTop, iconRightZ, 1.0f, 0.0f, + iconRightX, iconTextureBottom, iconRightZ, 1.0f, 1.0f, + iconLeftX, iconTextureBottom, iconLeftZ, 0.0f, 1.0f); + } + + // label + if (scale < 1.2f) { + float a = (1.2f - maxf(scale, 1.0f)) * 5; + color(1.0f, 1.0f, 1.0f, a); + bindTexture(NAMED_PFTexLinear, 0, loadI32(ALLOC_LABEL_IDS, icon)); + drawSprite(centerX, labelY, centerZ, + params->bubbleBitmapWidth, params->bubbleBitmapHeight); + } + + angle += columnGutterAngle + iconWidthAngle; + icon++; + } + } +} + +void +draw_home_button() +{ + color(1.0f, 1.0f, 1.0f, 1.0f); + bindTexture(NAMED_PFTexLinear, 0, params->homeButtonId); + + float scale = 2.0f / SCREEN_WIDTH_PX; + + float x = 0.0f; + + float y = -(SCREEN_HEIGHT_PX / (float)SCREEN_WIDTH_PX); + y += g_Zoom * (scale * params->homeButtonTextureHeight / 2); + + float z = 0.0f; + drawSprite(x, y, z, params->homeButtonTextureWidth, params->homeButtonTextureHeight); +} + +int +main(int launchID) +{ + // Compute dt in seconds. + int newTime = uptimeMillis(); + g_DT = (newTime - g_LastTime) / 1000.f; + g_LastTime = newTime; + + if (!g_DrawLastFrame) { + // If we stopped rendering we cannot use DT. + // assume 30fps in this case. + g_DT = 0.033f; + } + if (g_DT > 0.2f) { + // physics may break if DT is large. + g_DT = 0.2f; + } + + //debugF("zoom", g_Zoom); + if (g_Zoom != state->zoomTarget) { + float dz = (state->zoomTarget - g_Zoom) * g_DT * 5; + if (dz && (fabsf(dz) < 0.03f)) { + if (dz > 0) { + dz = 0.03f; + } else { + dz = -0.03f; + } + } + if (fabsf(g_Zoom - state->zoomTarget) < fabsf(dz)) { + g_Zoom = state->zoomTarget; + } else { + g_Zoom += dz; + } + updateReadback(); + } + + // Set clear value to dim the background based on the zoom position. + if ((g_Zoom < 0.001f) && (state->zoomTarget < 0.001f)) { + pfClearColor(0.0f, 0.0f, 0.0f, 0.0f); + // When we're zoomed out and not tracking motion events, reset the pos to 0. + if (!g_LastTouchDown) { + g_PosPage = 0; + } + return lastFrame(0); + } else if (g_Zoom < 0.85f) { + pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom); + } else { + pfClearColor(0.0f, 0.0f, 0.0f, g_Zoom); + } + + // icons & labels + int iconCount = state->iconCount; + g_PageCount = count_pages(iconCount); + + updatePos(0.1f); + updateReadback(); + + //debugF(" draw g_PosPage", g_PosPage); + + // Draw the icons ======================================== + + // Bug makes 1.0f alpha fail. + color(1.0f, 1.0f, 1.0f, 0.99f); + + if (iconCount <= 0) { + return lastFrame(0); + } + int lastIcon = iconCount-1; + + int page = g_PosPage; + float currentPagePosition = g_PosPage - page; + + int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE; + int icon = clamp(iconsPerPage * page, 0, lastIcon); + + float scale = (1 / g_Zoom); + + float pageAngle = VIEW_ANGLE * 1.2f; + draw_page(icon, lastIcon, -pageAngle*currentPagePosition, scale); + draw_page(icon+iconsPerPage, lastIcon, (-pageAngle*currentPagePosition)+pageAngle, scale); + + // Draw the border lines for debugging ======================================== + /* + bindProgramVertex(NAMED_PVOrtho); + bindProgramFragment(NAMED_PFOrtho); + bindProgramFragmentStore(NAMED_PFSText); + + color(1.0f, 1.0f, 0.0f, 0.99f); + int i; + for (i=0; izoomTarget)); +} +