mirror of
https://github.com/nitraiolo/CfgUSBLoader.git
synced 2025-01-09 09:49:26 +01:00
2934 lines
107 KiB
C
2934 lines
107 KiB
C
|
// by usptactical
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <string.h>
|
||
|
#include <malloc.h>
|
||
|
#include <unistd.h>
|
||
|
#include <math.h>
|
||
|
#include <ogcsys.h>
|
||
|
#include <ogc/conf.h>
|
||
|
#include <gccore.h>
|
||
|
#include <fat.h>
|
||
|
#include <wiiuse/wpad.h>
|
||
|
#include "coverflow.h"
|
||
|
#include "cfg.h"
|
||
|
#include "gui.h"
|
||
|
#include "cache.h"
|
||
|
#include "wpad.h"
|
||
|
#include "my_GRRLIB.h"
|
||
|
#include "xml.h"
|
||
|
#include "gettext.h"
|
||
|
|
||
|
//defines for the mouseover detection
|
||
|
#define MOUSEOVER_COVER_OFFSCREEN 0xFFFFFFFF
|
||
|
|
||
|
//defines for default background alpha levels
|
||
|
#define BACKGROUND_REFLECTION_ALPHA 0xFFFFFF44
|
||
|
#define BACKGROUND_REFLECTION_ALPHA2 0xFFFFFFAA
|
||
|
|
||
|
//defines for how many Cover structs to allocate
|
||
|
#define MAX_COVERFLOW_COVERS 10
|
||
|
#define MAX_COVERFLOW_COVERS_TOTAL 12
|
||
|
|
||
|
//maximum length of the drawn title text
|
||
|
#define TITLE_MAX 54
|
||
|
|
||
|
//position at which the wiimote starts scrolling right/left on x axis
|
||
|
#define WIIMOTE_SIDE_SCROLL_WIDTH 100
|
||
|
|
||
|
//defines used for setting final cover positioning during transitions
|
||
|
#define COVERPOS_FLIP_TO_BACK 0
|
||
|
#define COVERPOS_CENTER_THEME 1
|
||
|
#define COVERPOS_CONSOLE_2D 2
|
||
|
#define COVERPOS_CONSOLE_3D 3
|
||
|
#define COVERPOS_GAME_LOAD 4
|
||
|
|
||
|
//defines for fading the background (for flip to back)
|
||
|
#define BACKGROUND_FADE_NONE 0
|
||
|
#define BACKGROUND_FADE_DARK 1
|
||
|
#define BACKGROUND_FADE_LIGHT 2
|
||
|
|
||
|
//easing type used for the last rotation in a right/left transition
|
||
|
#define EASING_TYPE_SLOW 3
|
||
|
#define EASING_TYPE_LINEAR 0
|
||
|
|
||
|
#define DML_MAGIC 0x444D4C00
|
||
|
#define DML_MAGIC_HDD DML_MAGIC + 1
|
||
|
|
||
|
extern struct discHdr *gameList;
|
||
|
extern s32 gameCnt;
|
||
|
extern bool loadGame;
|
||
|
extern bool suppressCoverDrawing;
|
||
|
|
||
|
//AA
|
||
|
extern struct GRRLIB_texImg aa_texBuffer[4];
|
||
|
|
||
|
bool coverflow_test_grid = false;
|
||
|
|
||
|
struct settings_cf_global CFG_cf_global;
|
||
|
struct settings_cf_theme CFG_cf_theme[CF_THEME_NUM];
|
||
|
|
||
|
//struct for the cover coords and color levels
|
||
|
typedef struct CoverPos {
|
||
|
float x,y,z; // screen co-ordinates
|
||
|
float xrot, yrot, zrot; // rotation
|
||
|
int alpha; // alpha level of cover
|
||
|
u32 reflection_bottom; // color of the bottom portion of the reflection (bottom of the cover box)
|
||
|
u32 reflection_top; // color of the top portion of the reflection (top of the cover box)
|
||
|
} CoverPos;
|
||
|
|
||
|
//struct to store the game cover properties
|
||
|
typedef struct Cover {
|
||
|
CoverPos themePos;
|
||
|
CoverPos startPos;
|
||
|
CoverPos endPos;
|
||
|
CoverPos currentPos;
|
||
|
int gi; // game index
|
||
|
int state; // current loading state of the cover image
|
||
|
bool selected; // set to true if cover is being pointed at
|
||
|
u32 stencil_color; // the stencil cover (for pointer-over detection)
|
||
|
int hidden; // is cover is hidden?
|
||
|
GRRLIB_texImg tx; // cover image data
|
||
|
} Cover;
|
||
|
|
||
|
Cover coverCoords_center;
|
||
|
Cover coverCoords_left[MAX_COVERFLOW_COVERS_TOTAL];
|
||
|
Cover coverCoords_right[MAX_COVERFLOW_COVERS_TOTAL];
|
||
|
|
||
|
extern unsigned char cover_top[];
|
||
|
extern unsigned char cover_front[];
|
||
|
extern unsigned char cover_side[];
|
||
|
extern unsigned char coverImg_full[];
|
||
|
|
||
|
GRRLIB_texImg *tx_cover_top;
|
||
|
GRRLIB_texImg *tx_cover_front;
|
||
|
GRRLIB_texImg *tx_cover_side;
|
||
|
GRRLIB_texImg tx_nocover_full_CMPR;
|
||
|
GRRLIB_texImg tx_hourglass_full;
|
||
|
GRRLIB_texImg tx_screenshot;
|
||
|
|
||
|
GXTexObj texCoverTop;
|
||
|
GXTexObj texCoverFront;
|
||
|
GXTexObj texCoverSide;
|
||
|
|
||
|
WPADData wpad_data;
|
||
|
|
||
|
static int background_fade_status = 0;
|
||
|
static int grx_cover_init = 0;
|
||
|
static int cover_init = 0;
|
||
|
bool showingFrontCover = true;
|
||
|
static bool spinCover_dpad_used = false;
|
||
|
u32 selectedColor;
|
||
|
|
||
|
//vars for the floating cover functionality
|
||
|
f32 float_speed_increment = 0.03;
|
||
|
f32 float_max_xrot = 5; //10
|
||
|
f32 float_max_yrot = 5; //10
|
||
|
f32 float_max_zrot = 3; //3
|
||
|
f32 float_xrot;
|
||
|
f32 float_yrot;
|
||
|
f32 float_zrot;
|
||
|
bool float_xrot_up = true;
|
||
|
bool float_yrot_up = false;
|
||
|
bool float_zrot_up = true;
|
||
|
|
||
|
static int rotation_start_index = 0;
|
||
|
int rotating_with_wiimote = 0;
|
||
|
|
||
|
Mtx GXview2D;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Retrieves the current data for wiimote 1
|
||
|
* @return void
|
||
|
*/
|
||
|
#if 0
|
||
|
void getWiiMoteInfo() {
|
||
|
u32 ext; //Extension type
|
||
|
//u32 ret=0; //remote probe return
|
||
|
|
||
|
WPAD_ScanPads();
|
||
|
ret=WPAD_Probe(WPAD_CHAN_0,&ext); //probe remote 1 with extension
|
||
|
WPADData *Data = WPAD_Data(WPAD_CHAN_0); //store data from remote 1
|
||
|
wpad_data = *Data;
|
||
|
|
||
|
WPAD_IR(WPAD_CHAN_0, &wpad_data.ir); //get IR data
|
||
|
WPAD_Orientation(WPAD_CHAN_0, &wpad_data.orient); //get rotation data
|
||
|
WPAD_GForce(WPAD_CHAN_0, &wpad_data.gforce); //get "speed" data
|
||
|
WPAD_Accel(WPAD_CHAN_0, &wpad_data.accel); //get accelerometer data
|
||
|
WPAD_Expansion(WPAD_CHAN_0, &wpad_data.exp); //get expansion data
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/**
|
||
|
* Initilaizes all the common cover images (top, side, front, back)
|
||
|
* @return void
|
||
|
*/
|
||
|
void Coverflow_Grx_Init() {
|
||
|
GRRLIB_texImg tx_tmp;
|
||
|
showingFrontCover = true;
|
||
|
|
||
|
if (!grx_cover_init) {
|
||
|
tx_cover_top = GRRLIB_LoadTexture(cover_top);
|
||
|
tx_cover_front = GRRLIB_LoadTexture(cover_front);
|
||
|
tx_cover_side = GRRLIB_LoadTexture(cover_side);
|
||
|
|
||
|
GX_InitTexObj(&texCoverTop,
|
||
|
tx_cover_top->data, tx_cover_top->w, tx_cover_top->h,
|
||
|
GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
GX_InitTexObj(&texCoverFront,
|
||
|
tx_cover_front->data, tx_cover_front->w, tx_cover_front->h,
|
||
|
GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
GX_InitTexObj(&texCoverSide,
|
||
|
tx_cover_side->data, tx_cover_side->w, tx_cover_side->h,
|
||
|
GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
|
||
|
if (CFG.gui_compress_covers) {
|
||
|
//store a CMPR version of the full cover
|
||
|
tx_tmp = Gui_LoadTexture_CMPR(coverImg_full, 0, 0, NULL, NULL);
|
||
|
GRRLIB_TextureMEM2(&tx_nocover_full_CMPR, &tx_tmp);
|
||
|
}
|
||
|
}
|
||
|
grx_cover_init = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Frees image resources
|
||
|
* @return void
|
||
|
*/
|
||
|
void Coverflow_Close() {
|
||
|
if (grx_cover_init) {
|
||
|
GRRLIB_FREE_TEX(tx_cover_top);
|
||
|
GRRLIB_FREE_TEX(tx_cover_front);
|
||
|
GRRLIB_FREE_TEX(tx_cover_side);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Sets the image load state, and if the image is in the cache it adds it to
|
||
|
* the cover struct.
|
||
|
*
|
||
|
* @param *cover Cover struct representing a game
|
||
|
* @return void
|
||
|
*/
|
||
|
void update_cover_state2(Cover *cover, int cstyle)
|
||
|
{
|
||
|
int gi = cover->gi;
|
||
|
|
||
|
//make sure this is a valid cover index
|
||
|
if (gi < 0) return;
|
||
|
|
||
|
//set the current image state for this cover
|
||
|
GRRLIB_texImg *tx;
|
||
|
int fmt = CC_COVERFLOW_FMT;
|
||
|
tx = cache_request_cover(gi, cstyle, fmt, CC_PRIO_MED, &cover->state);
|
||
|
if (cover->state == CS_PRESENT) {
|
||
|
cover->tx = *tx;
|
||
|
} else if (cover->state == CS_IDLE) {
|
||
|
cover->tx = tx_hourglass_full;
|
||
|
} else if (cover->state == CS_LOADING) {
|
||
|
cover->tx = tx_hourglass_full;
|
||
|
} else { // CS_MISSING
|
||
|
if (CFG.gui_compress_covers)
|
||
|
cover->tx = tx_nocover_full_CMPR;
|
||
|
else
|
||
|
cover->tx = tx_nocover_full;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void update_cover_state(Cover *cover)
|
||
|
{
|
||
|
update_cover_state2(cover, CFG_COVER_STYLE_FULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks the loading status of the covers.
|
||
|
* @return void
|
||
|
*/
|
||
|
void Coverflow_update_state() {
|
||
|
int i;
|
||
|
struct Cover *cover;
|
||
|
|
||
|
//center cover
|
||
|
if (showingFrontCover) {
|
||
|
update_cover_state(&coverCoords_center);
|
||
|
} else {
|
||
|
update_cover_state2(&coverCoords_center, CFG_COVER_STYLE_HQ_OR_FULL);
|
||
|
}
|
||
|
|
||
|
//check left side
|
||
|
for (i=0; i < CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers + 1; i++) {
|
||
|
cover = &coverCoords_left[i];
|
||
|
update_cover_state(cover);
|
||
|
}
|
||
|
|
||
|
//check right side
|
||
|
for (i=0; i < CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers + 1; i++) {
|
||
|
cover = &coverCoords_right[i];
|
||
|
update_cover_state(cover);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Sets the projection matrix for 2D display
|
||
|
* @return void
|
||
|
*/
|
||
|
void set2DProjectionMatrix() {
|
||
|
Mtx44 GXprojection2D;
|
||
|
|
||
|
guMtxIdentity(GXmodelView2D);
|
||
|
guMtxTransApply (GXmodelView2D, GXmodelView2D, 0.0F, 0.0F, -50.0F);
|
||
|
GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
|
||
|
guOrtho(GXprojection2D, 0, 480, 0, 640, 0, 300.0F);
|
||
|
GX_LoadProjectionMtx(GXprojection2D, GX_ORTHOGRAPHIC);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Used to set the camera position
|
||
|
* @param aaStep int position in the array to store the created tex
|
||
|
* @return void
|
||
|
*/
|
||
|
void set_camera() {
|
||
|
//set the view
|
||
|
guVector cam = {CFG_cf_theme[CFG_cf_global.theme].cam_pos_x,
|
||
|
CFG_cf_theme[CFG_cf_global.theme].cam_pos_y,
|
||
|
CFG_cf_theme[CFG_cf_global.theme].cam_pos_z},
|
||
|
|
||
|
up = {0.0F, 1.0F, 0.0F},
|
||
|
|
||
|
look = {CFG_cf_theme[CFG_cf_global.theme].cam_look_x,
|
||
|
CFG_cf_theme[CFG_cf_global.theme].cam_look_y,
|
||
|
CFG_cf_theme[CFG_cf_global.theme].cam_look_z};
|
||
|
|
||
|
guLookAt(GXview2D, &cam, &up, &look);
|
||
|
}
|
||
|
|
||
|
|
||
|
//Easing routines from http://www.robertpenner.com/easing/
|
||
|
// t = time
|
||
|
// c = change in position
|
||
|
// d = duration
|
||
|
// b = beginning position
|
||
|
float linearOut(float t, float b , float c, float d) {
|
||
|
return c*t/d + b;
|
||
|
}
|
||
|
|
||
|
float easeOutQuad(float t, float b , float c, float d) {
|
||
|
t /= d;
|
||
|
return -c * t*(t-2) + b;
|
||
|
}
|
||
|
|
||
|
float easeOutCubic(float t, float b , float c, float d) {
|
||
|
t = t/d - 1;
|
||
|
return c*(t*t*t + 1) + b;
|
||
|
}
|
||
|
|
||
|
float easeOutQuart(float t, float b , float c, float d) {
|
||
|
t = t/d - 1;
|
||
|
return -c * (t*t*t*t - 1) + b;
|
||
|
}
|
||
|
|
||
|
float easeOutQuint(float t, float b , float c, float d) {
|
||
|
t = t/d - 1;
|
||
|
return c*(t*t*t*t*t + 1) + b; //Quint
|
||
|
}
|
||
|
|
||
|
float easeOutExpo(float t, float b , float c, float d) {
|
||
|
return (t==d) ? b+c : c * (-pow(2, -10 * t/d) + 1) + b;
|
||
|
}
|
||
|
|
||
|
float ease_x(int type, float t, float b, float c, float d)
|
||
|
{
|
||
|
switch (type) {
|
||
|
default:
|
||
|
case 0: return linearOut(t, b, c, d);
|
||
|
case 1: return easeOutQuad(t, b, c, d);
|
||
|
case 2: return easeOutCubic(t, b, c, d);
|
||
|
case 3: return easeOutQuart(t, b, c, d);
|
||
|
case 4: return easeOutQuint(t, b, c, d);
|
||
|
case 5: return easeOutExpo(t, b, c, d);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method used to calculate the new position when moving an object. Can be used for moving on any axis (x,y,z)
|
||
|
* E.g. moving a cover from the right side to the center.
|
||
|
* The basic equation is:
|
||
|
* current pos = starting point - ((starting point - end point) * index / number of total frames)
|
||
|
*
|
||
|
* @param startPos f32 representing the original starting point of the object
|
||
|
* @param endPos f32 representing the ending point (where you want the object to ultimately end up).
|
||
|
* @param index int representing the current index in the loop
|
||
|
* @param totalFrames int representing the total number of frames in your loop
|
||
|
* @param ease_type int representing the type of easing to use in the calculation
|
||
|
* @return f32 next position
|
||
|
*/
|
||
|
f32 calculateNewPosition(f32 startPos, f32 endPos, int index, int totalFrames, int ease_type) {
|
||
|
if (index >= totalFrames || totalFrames==0 || startPos==endPos)
|
||
|
return endPos;
|
||
|
switch (ease_type) {
|
||
|
case 0: return linearOut(index, startPos, endPos - startPos, totalFrames);
|
||
|
case 1: return easeOutQuad(index, startPos, endPos - startPos, totalFrames);
|
||
|
case 2: return easeOutCubic(index, startPos, endPos - startPos, totalFrames);
|
||
|
case 3: return easeOutQuart(index, startPos, endPos - startPos, totalFrames);
|
||
|
case 4: return easeOutQuint(index, startPos, endPos - startPos, totalFrames);
|
||
|
case 5: return easeOutExpo(index, startPos, endPos - startPos, totalFrames);
|
||
|
}
|
||
|
return endPos;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method used to calculate the new alpha level when moving a color.
|
||
|
*
|
||
|
* @param startPos u32 representing the original starting color of the object
|
||
|
* @param endPos u32 representing the ending color (where you want the color to ultimately end up).
|
||
|
* @param index int representing the current index in the loop
|
||
|
* @param totalFrames into representing the total number of frames in your loop
|
||
|
* @param ease_type int representing the type of easing to use in the calculation
|
||
|
* @return u32 next color in the iteration
|
||
|
*/
|
||
|
u32 calculateNewColor(u32 startPos, u32 endPos, int index, int totalFrames, int ease_type)
|
||
|
{
|
||
|
u32 color;
|
||
|
int a, a1, a2;
|
||
|
int i;
|
||
|
|
||
|
if (index > totalFrames || totalFrames==0 || startPos==endPos)
|
||
|
return endPos;
|
||
|
|
||
|
// each component
|
||
|
color = 0;
|
||
|
for (i=0; i<4; i++) {
|
||
|
a1 = (startPos >> (i*8)) & 0xFF;
|
||
|
a2 = (endPos >> (i*8)) & 0xFF;
|
||
|
a = ease_x(ease_type, index, a1, a2 - a1, totalFrames);
|
||
|
// range check, just in case..
|
||
|
if (a < 0) a = 0;
|
||
|
if (a > 0xFF) a = 0xFF;
|
||
|
color |= (a << (i*8));
|
||
|
}
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initializes the cover image layout in the current CFG_cf_theme[CFG_cf_global.theme].
|
||
|
* @param coverCount total number of covers
|
||
|
* @param index represents the cover index of the center cover
|
||
|
* @return int of the selected cover
|
||
|
*/
|
||
|
int setCoverIndexing(int coverCount, int index) {
|
||
|
int i, img, selectedCover;
|
||
|
|
||
|
img = index;
|
||
|
//set the center to the first cover if the index is bad
|
||
|
if (img < 1 || img >= coverCount)
|
||
|
img = 0;
|
||
|
selectedCover = img;
|
||
|
|
||
|
//set the right covers
|
||
|
coverCoords_center.gi = img;
|
||
|
img++;
|
||
|
if (img >= coverCount)
|
||
|
img = 0;
|
||
|
for (i=0; i < CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers + 1; i++) {
|
||
|
coverCoords_right[i].gi = img;
|
||
|
img++;
|
||
|
if (img >= coverCount)
|
||
|
img = 0;
|
||
|
}
|
||
|
|
||
|
//set the left covers
|
||
|
img = selectedCover-1;
|
||
|
if (img < 0)
|
||
|
img = coverCount - 1;
|
||
|
if (img < 0) img = 0;
|
||
|
for (i=0; i < CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers + 1; i++) {
|
||
|
coverCoords_left[i].gi = img;
|
||
|
img--;
|
||
|
if (img < 0)
|
||
|
img = coverCount - 1;
|
||
|
if (img < 0) img = 0;
|
||
|
}
|
||
|
return selectedCover;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Converts degrees to radians:
|
||
|
* angle = index * ((Math.PI * 2) / numOfItems);
|
||
|
* @param degree the degree to convert
|
||
|
* @return f32 representing the radian
|
||
|
*/
|
||
|
f32 degToRad (f32 degree) {
|
||
|
return (degree * M_PI) / 180.f;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Initializes a cover positioned to the left of center
|
||
|
* @param *cover Cover struct object of the cover to set up
|
||
|
* @param index represents the cover's index in the coverCoords_left array
|
||
|
* @return void
|
||
|
*/
|
||
|
void setCoverPosition_Left(CoverPos *cover, int index) {
|
||
|
f32 angle_deg, angle_rad, radius;
|
||
|
int alpha;
|
||
|
|
||
|
cover->x = CFG_cf_theme[CFG_cf_global.theme].cover_left_xpos + CFG_cf_theme[CFG_cf_global.theme].cover_distance_from_center_left_x;
|
||
|
cover->y = CFG_cf_theme[CFG_cf_global.theme].cover_left_ypos + CFG_cf_theme[CFG_cf_global.theme].cover_distance_from_center_left_y;
|
||
|
cover->z = CFG_cf_theme[CFG_cf_global.theme].cover_left_zpos + CFG_cf_theme[CFG_cf_global.theme].cover_distance_from_center_left_z;
|
||
|
|
||
|
cover->xrot = CFG_cf_theme[CFG_cf_global.theme].cover_left_xrot;
|
||
|
cover->yrot = CFG_cf_theme[CFG_cf_global.theme].cover_left_yrot;
|
||
|
cover->zrot = CFG_cf_theme[CFG_cf_global.theme].cover_left_zrot;
|
||
|
|
||
|
if (CFG_cf_theme[CFG_cf_global.theme].cover_rolloff_y != 0) {
|
||
|
angle_deg = CFG_cf_theme[CFG_cf_global.theme].cover_rolloff_y * index;
|
||
|
radius = CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_left_x * index;
|
||
|
//convert rolloff degree to radians
|
||
|
angle_rad = degToRad(angle_deg);
|
||
|
|
||
|
// x = Math.cos(mc.angle) * radiusX + centerX;
|
||
|
// y = Math.sin(mc.angle) * radiusY + centerY;
|
||
|
cover->x += cosf(angle_rad) * radius;
|
||
|
cover->z -= sinf(angle_rad) * radius;
|
||
|
cover->yrot += angle_deg;
|
||
|
} else {
|
||
|
cover->x += (CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_left_x * index);
|
||
|
cover->y += (CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_left_y * index);
|
||
|
cover->z += (CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_left_z * index);
|
||
|
}
|
||
|
|
||
|
cover->alpha = coverCoords_center.themePos.alpha - CFG_cf_theme[CFG_cf_global.theme].alpha_rolloff * (index+1);
|
||
|
if (cover->alpha < 0) {
|
||
|
cover->alpha = 0;
|
||
|
cover->reflection_bottom = 0x00000000;
|
||
|
cover->reflection_top = 0x00000000;
|
||
|
} else {
|
||
|
alpha = (CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom & 0xFF) - (CFG_cf_theme[CFG_cf_global.theme].alpha_rolloff/2) * (index+1);
|
||
|
if (alpha <= 0) {
|
||
|
cover->reflection_bottom = 0x00000000;
|
||
|
} else {
|
||
|
cover->reflection_bottom = ((CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom & 0xFFFFFF00) | alpha);
|
||
|
}
|
||
|
//cover->reflection_bottom = CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom;
|
||
|
|
||
|
alpha = (CFG_cf_theme[CFG_cf_global.theme].reflections_color_top & 0xFF) - (CFG_cf_theme[CFG_cf_global.theme].alpha_rolloff/2) * (index+1);
|
||
|
if (alpha <= 0) {
|
||
|
cover->reflection_top = 0x00000000;
|
||
|
} else {
|
||
|
cover->reflection_top = ((CFG_cf_theme[CFG_cf_global.theme].reflections_color_top & 0xFFFFFF00) | alpha);
|
||
|
}
|
||
|
//cover->reflection_top = CFG_cf_theme[CFG_cf_global.theme].reflections_color_top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Initializes a cover positioned to the right of center
|
||
|
* @param *cover CoverPos struct object of the cover to set up
|
||
|
* @param index represents the cover's index in the coverCoords_right array
|
||
|
* @return void
|
||
|
*/
|
||
|
void setCoverPosition_Right(CoverPos *cover, int index) {
|
||
|
f32 angle_deg, angle_rad, radius;
|
||
|
int alpha;
|
||
|
|
||
|
cover->x = CFG_cf_theme[CFG_cf_global.theme].cover_right_xpos + CFG_cf_theme[CFG_cf_global.theme].cover_distance_from_center_right_x;
|
||
|
cover->y = CFG_cf_theme[CFG_cf_global.theme].cover_right_ypos + CFG_cf_theme[CFG_cf_global.theme].cover_distance_from_center_right_y;
|
||
|
cover->z = CFG_cf_theme[CFG_cf_global.theme].cover_right_zpos + CFG_cf_theme[CFG_cf_global.theme].cover_distance_from_center_right_z;
|
||
|
|
||
|
cover->xrot = CFG_cf_theme[CFG_cf_global.theme].cover_right_xrot;
|
||
|
cover->yrot = CFG_cf_theme[CFG_cf_global.theme].cover_right_yrot;
|
||
|
cover->zrot = CFG_cf_theme[CFG_cf_global.theme].cover_right_zrot;
|
||
|
|
||
|
if (CFG_cf_theme[CFG_cf_global.theme].cover_rolloff_y != 0) {
|
||
|
angle_deg = CFG_cf_theme[CFG_cf_global.theme].cover_rolloff_y * index * -1;
|
||
|
radius = CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_right_x * index;
|
||
|
//convert rolloff degree to radians
|
||
|
angle_rad = degToRad(angle_deg);
|
||
|
|
||
|
// x = Math.cos(mc.angle) * radiusX + centerX;
|
||
|
// y = Math.sin(mc.angle) * radiusY + centerY;
|
||
|
cover->x += cosf(angle_rad) * radius;
|
||
|
cover->z -= sinf(angle_rad) * radius;
|
||
|
cover->yrot += angle_deg;
|
||
|
} else {
|
||
|
cover->x += (CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_right_x * index);
|
||
|
cover->y += (CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_right_y * index);
|
||
|
cover->z += (CFG_cf_theme[CFG_cf_global.theme].cover_distance_between_covers_right_z * index);
|
||
|
}
|
||
|
|
||
|
cover->alpha = coverCoords_center.themePos.alpha - CFG_cf_theme[CFG_cf_global.theme].alpha_rolloff * (index+1);
|
||
|
if (cover->alpha < 0) {
|
||
|
cover->alpha = 0;
|
||
|
cover->reflection_bottom = 0x00000000;
|
||
|
cover->reflection_top = 0x00000000;
|
||
|
} else {
|
||
|
alpha = (CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom & 0xFF) - (CFG_cf_theme[CFG_cf_global.theme].alpha_rolloff/2) * (index+1);
|
||
|
if (alpha <= 0) {
|
||
|
cover->reflection_bottom = 0x00000000;
|
||
|
} else {
|
||
|
cover->reflection_bottom = ((CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom & 0xFFFFFF00) | alpha);
|
||
|
}
|
||
|
//cover->reflection_bottom = CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom;
|
||
|
|
||
|
alpha = (CFG_cf_theme[CFG_cf_global.theme].reflections_color_top & 0xFF) - (CFG_cf_theme[CFG_cf_global.theme].alpha_rolloff/2) * (index+1);
|
||
|
if (alpha <= 0) {
|
||
|
cover->reflection_top = 0x00000000;
|
||
|
} else {
|
||
|
cover->reflection_top = ((CFG_cf_theme[CFG_cf_global.theme].reflections_color_top & 0xFFFFFF00) | alpha);
|
||
|
}
|
||
|
//cover->reflection_top = CFG_cf_theme[CFG_cf_global.theme].reflections_color_top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method to set GX Position and Color
|
||
|
*/
|
||
|
void drawPosCol(f32 x, f32 y, f32 z, u32 c) {
|
||
|
GX_Position3f32(x, y, z);
|
||
|
GX_Color1u32(c);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Method to set GX Position, Color and Texture coords
|
||
|
*/
|
||
|
void drawPosColTex(f32 x, f32 y, f32 z, u32 c, f32 tx, f32 ty) {
|
||
|
GX_Position3f32(x, y, z);
|
||
|
GX_Color1u32(c);
|
||
|
GX_TexCoord2f32(tx, ty);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method to draw a flat 2D cover image with perspective-based (3D) viewpoint.
|
||
|
*
|
||
|
* @param tex cover image to draw
|
||
|
* @param xpos x axis position for the image
|
||
|
* @param ypos y axis position for the image
|
||
|
* @param zpos z axis position for the image
|
||
|
* @param xrot degrees to rotate the image on the x axis. For example a value of 90 will rotate it 90 degrees so it would appear flat on it's cover to the viewer.
|
||
|
* @param yrot degrees to rotate the image on the y axis. For example a value of 90 will rotate it 90 degrees on it's side so the front will be facing right to the viewer
|
||
|
* @param zrot degrees to rotate the image. For example a value of 90 will rotate it 90 degrees counter-clockwise
|
||
|
* @param color the color to make the cover
|
||
|
* @param reflectionColorBottom the color (including alpha) of the bottom portion of the reflection (bottom of the cover). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorTop the color (including alpha) of the top portion of the reflection (top of the cover). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param isFavorite bool represents if the favorite image should be drawn over the cover
|
||
|
* @return void
|
||
|
*/
|
||
|
void draw_2dcover_image(GRRLIB_texImg *tex, f32 xpos, f32 ypos, f32 zpos, f32 xrot, f32 yrot, f32 zrot, u32 color, u32 reflectionColorBottom, u32 reflectionColorTop, bool isFavorite) {
|
||
|
Mtx44 GXprojection2D;
|
||
|
//Mtx GXview2D;
|
||
|
Mtx GXmodel2D;
|
||
|
Mtx GXModelTemp;
|
||
|
//Mtx GXmodelView2D;
|
||
|
GXTexObj texObj;
|
||
|
f32 width, height;
|
||
|
|
||
|
guVector xaxis = (guVector) {1, 0, 0};
|
||
|
guVector yaxis = (guVector) {0, 1, 0};
|
||
|
guVector zaxis = (guVector) {0, 0, 1};
|
||
|
|
||
|
//set the view
|
||
|
set_camera();
|
||
|
|
||
|
guMtxIdentity(GXmodel2D);
|
||
|
GX_LoadTexMtxImm(GXmodel2D, GX_TEXMTX0, GX_MTX2x4);
|
||
|
|
||
|
//get the objects size
|
||
|
//width = COVER_WIDTH * 0.0625;
|
||
|
//height = COVER_HEIGHT * 0.0625;
|
||
|
width = 10.0;
|
||
|
height = 14.0;
|
||
|
|
||
|
//set rotation
|
||
|
if (xrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &xaxis, xrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (yrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &yaxis, yrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (zrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &zaxis, zrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
|
||
|
// set the XYZ position
|
||
|
guMtxTransApply(GXmodel2D, GXmodel2D, xpos, ypos, zpos);
|
||
|
guMtxConcat (GXview2D, GXmodel2D, GXmodelView2D);
|
||
|
|
||
|
// load the modelview matrix into matrix memory
|
||
|
GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
|
||
|
|
||
|
if (CFG.widescreen) {
|
||
|
guPerspective(GXprojection2D, 45, 1.778F, 0.1F, 500.0F);
|
||
|
} else {
|
||
|
guPerspective(GXprojection2D, 45, (f32)4/3, 0.1F, 500.0F);
|
||
|
}
|
||
|
GX_LoadProjectionMtx(GXprojection2D, GX_PERSPECTIVE);
|
||
|
|
||
|
GX_SetZMode(GX_ENABLE, GX_ALWAYS, GX_TRUE);
|
||
|
|
||
|
//set blend mode
|
||
|
GX_SetColorUpdate(GX_ENABLE);
|
||
|
GX_SetAlphaUpdate(GX_ENABLE);
|
||
|
|
||
|
//don't enable this or images look crappy - disables aa
|
||
|
// GX_InitTexObjLOD(&texObjects[index], GX_NEAR, GX_NEAR, 0, 0, 0, GX_FALSE, GX_FALSE, GX_ANISO_1);
|
||
|
|
||
|
GX_InitTexObj(&texObj, tex->data, tex->w, tex->h, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
|
||
|
//front blank cover
|
||
|
GX_LoadTexObj(&texCoverFront, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, height, 0, color, 0.0f, 0.0f);
|
||
|
drawPosColTex(width, height, 0, color, 1.0f, 0.0f);
|
||
|
drawPosColTex(width, -height, 0, color, 1.0f, 1.0f);
|
||
|
drawPosColTex(-width, -height, 0, color, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//front cover image
|
||
|
GX_LoadTexObj(&texObj, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, height-0.5, 0, color, 0.0f, 0.0f);
|
||
|
drawPosColTex(width-0.5, height-0.5, 0, color, 1.0f, 0.0f);
|
||
|
drawPosColTex(width-0.5, -height+0.5, 0, color, 1.0f, 1.0f);
|
||
|
drawPosColTex(-width, -height+0.5, 0, color, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//draw the favorites star
|
||
|
if (isFavorite) {
|
||
|
//calculate the size
|
||
|
f32 star_scale = .125;
|
||
|
f32 starw = tx_star.w * star_scale;
|
||
|
f32 starh = tx_star.h * star_scale;
|
||
|
//init the texture
|
||
|
GXTexObj texStar;
|
||
|
GX_InitTexObj(&texStar, tx_star.data, tx_star.w, tx_star.h, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
GX_LoadTexObj(&texStar, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width-starw, height, 0, color, 0.0f, 0.0f);
|
||
|
drawPosColTex(width, height, 0, color, 1.0f, 0.0f);
|
||
|
drawPosColTex(width, height-starh, 0, color, 1.0f, 1.0f);
|
||
|
drawPosColTex(width-starw, height-starh, 0, color, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
}
|
||
|
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
|
||
|
if (reflectionColorBottom > 0 || reflectionColorTop > 0) {
|
||
|
|
||
|
//Draw the reflection image upside down. Set the RGBA color
|
||
|
//near the bottom of the cover (top of the reflection) to the passed
|
||
|
//in alpha level. The RGBA for the lowest part of the reflection is
|
||
|
//set to zero, which gives us a fade-to-black appearance.
|
||
|
GX_LoadTexObj(&texObj, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, -height-1, 0, reflectionColorBottom, 0.0f, 1.0f);
|
||
|
drawPosColTex(width, -height-1, 0, reflectionColorBottom, 1.0f, 1.0f);
|
||
|
drawPosColTex(width, -height*2.5, 0, reflectionColorTop, 1.0f, 0.0f);
|
||
|
drawPosColTex(-width, -height*2.5, 0, reflectionColorTop, 0.0f, 0.0f);
|
||
|
GX_End();
|
||
|
}
|
||
|
|
||
|
GX_LoadPosMtxImm (GXview2D, GX_PNMTX0);
|
||
|
//set TevOp to GX_PASSCLR so that we get the color's alpha level
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
|
||
|
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
|
||
|
|
||
|
//reset the viewpoint to 2D
|
||
|
set2DProjectionMatrix();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method to draw cover image with perspective-based (3D) viewpoint.
|
||
|
*
|
||
|
* @param tex cover image to draw
|
||
|
* @param xpos x axis position for the image
|
||
|
* @param ypos y axis position for the image
|
||
|
* @param zpos z axis position for the image
|
||
|
* @param xrot degrees to rotate the image on the x axis. For example a value of 90 will rotate it 90 degrees so it would appear flat on it's cover to the viewer.
|
||
|
* @param yrot degrees to rotate the image on the y axis. For example a value of 90 will rotate it 90 degrees on it's side so the front will be facing right to the viewer
|
||
|
* @param zrot degrees to rotate the image. For example a value of 90 will rotate it 90 degrees counter-clockwise
|
||
|
* @param color the color to make the cover (where the game image is)
|
||
|
* @param edgecolor the color to make the boxcover edges
|
||
|
* @param isFavorite bool represents if the favorite image should be drawn over the cover
|
||
|
* @return void
|
||
|
*/
|
||
|
|
||
|
// lod bias: at -1.0 looks best, lower values get slow, higher loose quality
|
||
|
float lod_bias_a[] = { -2.0, -1.5, -1.0, -0.5, -0.3, 0, +0.5, +1 };
|
||
|
int lod_bias_idx = 2;
|
||
|
|
||
|
void draw_fullcover_image(GRRLIB_texImg *tex, f32 xpos, f32 ypos, f32 zpos, f32 xrot, f32 yrot, f32 zrot, u32 color, u32 edgecolor, bool isFavorite) {
|
||
|
Mtx44 GXprojection2D;
|
||
|
//Mtx GXview2D;
|
||
|
Mtx GXmodel2D;
|
||
|
Mtx GXModelTemp;
|
||
|
//Mtx GXmodelView2D;
|
||
|
GXTexObj texCoverImage;
|
||
|
|
||
|
//cover width and height
|
||
|
f32 width = 10.0;
|
||
|
f32 height = 14.0;
|
||
|
|
||
|
//fullcover tex positioning
|
||
|
f32 front_start = 0.525;
|
||
|
f32 spine_start = 0.475;
|
||
|
|
||
|
//distance between front and back covers
|
||
|
f32 COVER_BOX_DEPTH = 2.0;
|
||
|
//depth of the edge
|
||
|
f32 COVER_EDGE_DEPTH = 0.3;
|
||
|
//depth of side panel (closest / farthest wrt the viewpoint)
|
||
|
f32 COVER_SIDE_NEAR_DEPTH = COVER_BOX_DEPTH - COVER_EDGE_DEPTH;
|
||
|
f32 COVER_SIDE_FAR_DEPTH = COVER_EDGE_DEPTH;
|
||
|
|
||
|
guVector xaxis = (guVector) {1, 0, 0};
|
||
|
guVector yaxis = (guVector) {0, 1, 0};
|
||
|
guVector zaxis = (guVector) {0, 0, 1};
|
||
|
|
||
|
set_camera();
|
||
|
|
||
|
guMtxIdentity(GXmodel2D);
|
||
|
GX_LoadTexMtxImm(GXmodel2D, GX_TEXMTX0, GX_MTX2x4);
|
||
|
|
||
|
//get the objects size
|
||
|
//width = COVER_WIDTH * 0.0625;
|
||
|
//height = COVER_HEIGHT * 0.0625;
|
||
|
|
||
|
//set rotation
|
||
|
if (xrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &xaxis, xrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (yrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &yaxis, yrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (zrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &zaxis, zrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
|
||
|
// set the XYZ position
|
||
|
guMtxTransApply(GXmodel2D, GXmodel2D, xpos, ypos, zpos);
|
||
|
guMtxConcat (GXview2D, GXmodel2D, GXmodelView2D);
|
||
|
|
||
|
// load the modelview matrix into matrix memory
|
||
|
GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
|
||
|
|
||
|
if (CFG.widescreen) {
|
||
|
guPerspective(GXprojection2D, 45, 1.778F, 0.1F, 500.0F);
|
||
|
} else {
|
||
|
guPerspective(GXprojection2D, 45, (f32)4/3, 0.1F, 500.0F);
|
||
|
}
|
||
|
GX_LoadProjectionMtx(GXprojection2D, GX_PERSPECTIVE);
|
||
|
|
||
|
GX_SetZMode(GX_ENABLE, GX_ALWAYS, GX_TRUE);
|
||
|
//GX_SetZMode (GX_ENABLE, GX_LEQUAL, GX_TRUE);
|
||
|
|
||
|
//set blend mode
|
||
|
GX_SetColorUpdate(GX_ENABLE);
|
||
|
GX_SetAlphaUpdate(GX_ENABLE);
|
||
|
|
||
|
int tx_fmt = GX_TF_RGBA8;
|
||
|
if (tex->tex_format) tx_fmt = tex->tex_format;
|
||
|
GX_InitTexObj(&texCoverImage, tex->data, tex->w, tex->h, tx_fmt, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
|
||
|
//don't enable this or images look crappy - disables aa
|
||
|
//GX_InitTexObjLOD(&texCoverImage, GX_NEAR, GX_NEAR, 0, 0, 0, GX_FALSE, GX_FALSE, GX_ANISO_1);
|
||
|
if (tex->tex_lod) {
|
||
|
// mipmap
|
||
|
float lod_bias = lod_bias_a[lod_bias_idx];
|
||
|
GX_InitTexObjLOD(&texCoverImage, GX_LIN_MIP_LIN, GX_LINEAR,
|
||
|
0.f, // lod min
|
||
|
(float)tex->tex_lod, // lod max
|
||
|
lod_bias, // lod bias
|
||
|
GX_FALSE,
|
||
|
GX_FALSE, // edge lod
|
||
|
GX_ANISO_1); //GX_ANISO_2 GX_ANISO_4); // _1 seems sharper
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------------
|
||
|
// draw the edges
|
||
|
//-------------------------------------------------
|
||
|
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
|
||
|
//top front edge
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, COVER_BOX_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//top front corner
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(width, height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//right front edge (opening)
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width, height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height, COVER_BOX_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom front corner (opening)
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(width, -height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom front edge
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, -height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//-------------------------------------------
|
||
|
|
||
|
//top right edge (between top and opening)
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom right edge (between bottom and opening)
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//-------------------------------------------
|
||
|
|
||
|
//top left edge (between top and spine)
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(-width, height, 0.0f, edgecolor);
|
||
|
drawPosCol(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//top left edge (between top and spine)
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//top left edge (between top and spine)
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom left edge (between bottom and spine)
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(-width, -height, 0.0f, edgecolor);
|
||
|
drawPosCol(-width, -height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom left edge (between bottom and spine)
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, -height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom left edge (between bottom and spine)
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(-width, -height, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height, COVER_BOX_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//-------------------------------------------
|
||
|
|
||
|
//top back edge
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(-width, height, 0.0f, edgecolor);
|
||
|
drawPosCol(width, height, 0.0f, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//top back corner
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(width, height, 0.0f, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//right back edge
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, height, 0.0f, edgecolor);
|
||
|
drawPosCol(width, -height, 0.0f, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom back corner
|
||
|
GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 3);
|
||
|
drawPosCol(width, -height, 0.0f, edgecolor);
|
||
|
drawPosCol(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom back edge
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width, -height, 0.0f, edgecolor);
|
||
|
drawPosCol(-width, -height, 0.0f, edgecolor);
|
||
|
drawPosCol(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
drawPosCol(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor);
|
||
|
GX_End();
|
||
|
|
||
|
|
||
|
//--------------------------------
|
||
|
// draw generic no cover image top and right side (cover opening)
|
||
|
//--------------------------------
|
||
|
|
||
|
//top
|
||
|
GX_LoadTexObj(&texCoverTop, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_FRONT);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor, 0.0f, 0.0f);
|
||
|
drawPosColTex(width, height + COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor, 1.0f, 0.0f);
|
||
|
drawPosColTex(width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor, 1.0f, 1.0f);
|
||
|
drawPosColTex(-width, height + COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//right - cover opening
|
||
|
GX_LoadTexObj(&texCoverSide, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, height, COVER_SIDE_NEAR_DEPTH, edgecolor, 0.0f, 0.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, height, COVER_SIDE_FAR_DEPTH, edgecolor, 1.0f, 0.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_FAR_DEPTH, edgecolor, 1.0f, 1.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height, COVER_SIDE_NEAR_DEPTH, edgecolor, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom
|
||
|
GX_LoadTexObj(&texCoverTop, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor, 0.0f, 0.0f);
|
||
|
drawPosColTex(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_NEAR_DEPTH, edgecolor, 1.0f, 0.0f);
|
||
|
drawPosColTex(width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor, 1.0f, 1.0f);
|
||
|
drawPosColTex(-width, -height - COVER_EDGE_DEPTH, COVER_SIDE_FAR_DEPTH, edgecolor, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
|
||
|
//--------------------------------
|
||
|
// draw cover image
|
||
|
//--------------------------------
|
||
|
|
||
|
//Wrap the full cover
|
||
|
GX_LoadTexObj(&texCoverImage, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
|
||
|
//fullcover back
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width, height, 0.0f, color, 0.0f, 0.0f);
|
||
|
drawPosColTex(-width, height, 0.0f, color, spine_start, 0.0f);
|
||
|
drawPosColTex(-width, -height, 0.0f, color, spine_start, 1.0f);
|
||
|
drawPosColTex(width, -height, 0.0f, color, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//fullcover spine
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, height, 0.0f, color, spine_start, 0.0f);
|
||
|
drawPosColTex(-width, height, COVER_BOX_DEPTH, color, front_start, 0.0f);
|
||
|
drawPosColTex(-width, -height, COVER_BOX_DEPTH, color, front_start, 1.0f);
|
||
|
drawPosColTex(-width, -height, 0.0f, color, spine_start, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//fullcover front
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width, height, COVER_BOX_DEPTH, color, front_start, 0.0f);
|
||
|
drawPosColTex(width, height, COVER_BOX_DEPTH, color, 1.0f, 0.0f);
|
||
|
drawPosColTex(width, -height, COVER_BOX_DEPTH, color, 1.0f, 1.0f);
|
||
|
drawPosColTex(-width, -height, COVER_BOX_DEPTH, color, front_start, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
|
||
|
//--------------------------------
|
||
|
// favorites star
|
||
|
//--------------------------------
|
||
|
|
||
|
if (isFavorite) {
|
||
|
//calculate the size
|
||
|
f32 star_scale = .125;
|
||
|
f32 starw = tx_star.w * star_scale;
|
||
|
f32 starh = tx_star.h * star_scale;
|
||
|
//init the texture
|
||
|
GXTexObj texStar;
|
||
|
GX_InitTexObj(&texStar, tx_star.data, tx_star.w, tx_star.h, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
GX_LoadTexObj(&texStar, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width-starw, height, COVER_BOX_DEPTH, color, 0.0f, 0.0f);
|
||
|
drawPosColTex(width, height, COVER_BOX_DEPTH, color, 1.0f, 0.0f);
|
||
|
drawPosColTex(width, height-starh, COVER_BOX_DEPTH, color, 1.0f, 1.0f);
|
||
|
drawPosColTex(width-starw, height-starh, COVER_BOX_DEPTH, color, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
}
|
||
|
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_LoadPosMtxImm (GXview2D, GX_PNMTX0);
|
||
|
//set TevOp to GX_PASSCLR so that we get the color's alpha level
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
|
||
|
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
|
||
|
|
||
|
//reset the viewpoint to 2D
|
||
|
set2DProjectionMatrix();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method to draw cover image reflection with perspective-based (3D) viewpoint.
|
||
|
*
|
||
|
* @param tex cover image to draw
|
||
|
* @param xpos x axis position for the image
|
||
|
* @param ypos y axis position for the image
|
||
|
* @param zpos z axis position for the image
|
||
|
* @param xrot degrees to rotate the image on the x axis. For example a value of 90 will rotate it 90 degrees so it would appear flat on it's cover to the viewer.
|
||
|
* @param yrot degrees to rotate the image on the y axis. For example a value of 90 will rotate it 90 degrees on it's side so the front will be facing right to the viewer
|
||
|
* @param zrot degrees to rotate the image. For example a value of 90 will rotate it 90 degrees counter-clockwise
|
||
|
* @param reflectionColorBottom the color (including alpha) of the bottom portion of the reflection (bottom of the cover). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorTop the color (including alpha) of the top portion of the reflection (top of the cover). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorBottomEdge the color (including alpha) of the bottom portion of the reflection (bottom of the boxcover). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorTopEdge the color (including alpha) of the top portion of the reflection (top of the boxcover). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param isFavorite bool represents if the favorite image should be drawn over the cover
|
||
|
* @return void
|
||
|
*/
|
||
|
void draw_fullcover_image_reflection(GRRLIB_texImg *tex, f32 xpos, f32 ypos, f32 zpos, f32 xrot, f32 yrot, f32 zrot,
|
||
|
u32 reflectionColorBottom, u32 reflectionColorTop, u32 reflectionColorBottomEdge, u32 reflectionColorTopEdge, bool isFavorite) {
|
||
|
Mtx44 GXprojection2D;
|
||
|
//Mtx GXview2D;
|
||
|
Mtx GXmodel2D;
|
||
|
Mtx GXModelTemp;
|
||
|
//Mtx GXmodelView2D;
|
||
|
GXTexObj texCoverImage;
|
||
|
|
||
|
//cover width and height
|
||
|
f32 width = 10.0;
|
||
|
f32 height = 14.0;
|
||
|
|
||
|
//fullcover tex positioning
|
||
|
f32 front_start = 0.525;
|
||
|
f32 spine_start = 0.475;
|
||
|
|
||
|
//distance between the cover and its reflection
|
||
|
f32 COVER_REFLECTION_DISTANCE = 2.0;
|
||
|
//distance between front and back covers
|
||
|
f32 COVER_BOX_DEPTH = 2.0;
|
||
|
//depth of the edge
|
||
|
f32 COVER_EDGE_DEPTH = 0.3;
|
||
|
|
||
|
guVector xaxis = (guVector) {1, 0, 0};
|
||
|
guVector yaxis = (guVector) {0, 1, 0};
|
||
|
guVector zaxis = (guVector) {0, 0, 1};
|
||
|
|
||
|
set_camera();
|
||
|
|
||
|
guMtxIdentity(GXmodel2D);
|
||
|
GX_LoadTexMtxImm(GXmodel2D, GX_TEXMTX0, GX_MTX2x4);
|
||
|
|
||
|
//get the objects size
|
||
|
//width = COVER_WIDTH * 0.0625;
|
||
|
//height = COVER_HEIGHT * 0.0625;
|
||
|
|
||
|
//set rotation
|
||
|
if (xrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &xaxis, xrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (yrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &yaxis, yrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (zrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &zaxis, zrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
|
||
|
// set the XYZ position
|
||
|
guMtxTransApply(GXmodel2D, GXmodel2D, xpos, ypos, zpos);
|
||
|
guMtxConcat (GXview2D, GXmodel2D, GXmodelView2D);
|
||
|
|
||
|
// load the modelview matrix into matrix memory
|
||
|
GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
|
||
|
|
||
|
if (CFG.widescreen) {
|
||
|
guPerspective(GXprojection2D, 45, 1.778F, 0.1F, 500.0F);
|
||
|
} else {
|
||
|
guPerspective(GXprojection2D, 45, (f32)4/3, 0.1F, 500.0F);
|
||
|
}
|
||
|
GX_LoadProjectionMtx(GXprojection2D, GX_PERSPECTIVE);
|
||
|
|
||
|
//GX_SetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
|
||
|
GX_SetZMode (GX_ENABLE, GX_LEQUAL, GX_TRUE);
|
||
|
//GX_SetZMode(GX_ENABLE, GX_ALWAYS, GX_TRUE);
|
||
|
|
||
|
//set blend mode
|
||
|
GX_SetColorUpdate(GX_ENABLE);
|
||
|
GX_SetAlphaUpdate(GX_ENABLE);
|
||
|
|
||
|
int tx_fmt = GX_TF_RGBA8;
|
||
|
if (tex->tex_format) tx_fmt = tex->tex_format;
|
||
|
GX_InitTexObj(&texCoverImage, tex->data, tex->w, tex->h, tx_fmt, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
if (tex->tex_lod) {
|
||
|
// mipmap
|
||
|
float lod_bias = lod_bias_a[lod_bias_idx];
|
||
|
GX_InitTexObjLOD(&texCoverImage, GX_LIN_MIP_LIN, GX_LINEAR,
|
||
|
0.f, // lod min
|
||
|
(float)tex->tex_lod, // lod max
|
||
|
lod_bias, // lod bias
|
||
|
GX_FALSE,
|
||
|
GX_FALSE, // edge lod
|
||
|
GX_ANISO_1); //GX_ANISO_2 GX_ANISO_4); // _1 seems sharper
|
||
|
}
|
||
|
|
||
|
//--------------------------------
|
||
|
// Reflection
|
||
|
//--------------------------------
|
||
|
|
||
|
if (reflectionColorBottom > 0 || reflectionColorTop > 0) {
|
||
|
//Draw the reflection image upside down. Set the RGBA color
|
||
|
//near the bottom of the cover (top of the reflection) to the passed
|
||
|
//in alpha level. The RGBA for the lowest part of the reflection is
|
||
|
//set to zero, which gives us a fade-to-black appearance.
|
||
|
|
||
|
//right side - cover opening
|
||
|
GX_LoadTexObj(&texCoverSide, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorBottomEdge, 0.0f, 1.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, 0.0, reflectionColorBottomEdge, 1.0f, 1.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height*2.5 - COVER_REFLECTION_DISTANCE, 0.0, reflectionColorTopEdge, 1.0f, 0.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height*2.5 - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorTopEdge, 0.0f, 0.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//bottom
|
||
|
GX_LoadTexObj(&texCoverTop, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, 0.0, reflectionColorBottomEdge, 0.0f, 0.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, 0.0, reflectionColorBottomEdge, 1.0f, 0.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorBottomEdge, 1.0f, 1.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorBottomEdge, 0.0f, 1.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//draw the game cover image
|
||
|
GX_LoadTexObj(&texCoverImage, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
|
||
|
//fullcover back
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, 0.0f, reflectionColorBottom, 0.0f, 1.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, 0.0f, reflectionColorBottom, spine_start, 1.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height *2.5 - COVER_REFLECTION_DISTANCE, 0.0f, reflectionColorTop, spine_start, 0.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height *2.5 - COVER_REFLECTION_DISTANCE, 0.0f, reflectionColorTop, 0.0f, 0.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//front cover reflection
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorBottom, front_start, 1.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorBottom, 1.0f, 1.0f);
|
||
|
drawPosColTex(width + COVER_EDGE_DEPTH, -height*2.5 - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorTop, 1.0f, 0.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height*2.5 - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorTop, front_start, 0.0f);
|
||
|
GX_End();
|
||
|
|
||
|
//left - cover spine
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, 0.0f, reflectionColorBottom, spine_start, 1.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorBottom, front_start, 1.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height*2.5 - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorTop, front_start, 0.0f);
|
||
|
drawPosColTex(-width - COVER_EDGE_DEPTH, -height*2.5 - COVER_REFLECTION_DISTANCE, 0.0f, reflectionColorTop, spine_start, 0.0f);
|
||
|
GX_End();
|
||
|
}
|
||
|
|
||
|
//--------------------------------
|
||
|
// favorites star
|
||
|
//--------------------------------
|
||
|
|
||
|
if (isFavorite) {
|
||
|
//calculate the size
|
||
|
f32 starw = tx_star.w * .125;
|
||
|
f32 starh = tx_star.h * .062;
|
||
|
//init the texture
|
||
|
GXTexObj texStar;
|
||
|
GX_InitTexObj(&texStar, tx_star.data, tx_star.w, tx_star.h, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||
|
GX_LoadTexObj(&texStar, GX_TEXMAP0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_SetCullMode (GX_CULL_BACK);
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosColTex(width-starw, -height*2.5 + starh, COVER_BOX_DEPTH, reflectionColorTop, 0.0f, 1.0f);
|
||
|
drawPosColTex(width, -height*2.5 + starh, COVER_BOX_DEPTH, reflectionColorTop, 1.0f, 1.0f);
|
||
|
drawPosColTex(width, -height*2.5 - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorTop, 1.0f, 0.0f);
|
||
|
drawPosColTex(width-starw, -height*2.5 - COVER_REFLECTION_DISTANCE, COVER_BOX_DEPTH, reflectionColorTop, 0.0f, 0.0f);
|
||
|
GX_End();
|
||
|
}
|
||
|
|
||
|
GX_LoadPosMtxImm (GXmodelView2D, GX_PNMTX0);
|
||
|
GX_LoadPosMtxImm (GXview2D, GX_PNMTX0);
|
||
|
//set TevOp to GX_PASSCLR so that we get the color's alpha level
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
|
||
|
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
|
||
|
|
||
|
//reset the viewpoint to 2D
|
||
|
set2DProjectionMatrix();
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that draws the passed in Cover in the specified color. This is used by the
|
||
|
* capture_cover_positions() method for the cover mouseover detection.
|
||
|
* @param *cover CoverPos object to draw
|
||
|
* @param color the color to make the entire cover object. (e.g. 0x888888FF)
|
||
|
* @return void
|
||
|
*/
|
||
|
void draw_phantom_cover (CoverPos *cover, u32 color) {
|
||
|
Mtx44 GXprojection2D;
|
||
|
Mtx GXview2D;
|
||
|
Mtx GXmodel2D;
|
||
|
Mtx GXModelTemp;
|
||
|
//Mtx GXmodelView2D;
|
||
|
f32 width, height;
|
||
|
f32 COVER_BOX_DEPTH = 1.7;
|
||
|
|
||
|
guVector xaxis = (guVector) {1, 0, 0};
|
||
|
guVector yaxis = (guVector) {0, 1, 0};
|
||
|
guVector zaxis = (guVector) {0, 0, 1};
|
||
|
|
||
|
//set the view
|
||
|
guVector cam = {CFG_cf_theme[CFG_cf_global.theme].cam_pos_x, CFG_cf_theme[CFG_cf_global.theme].cam_pos_y, CFG_cf_theme[CFG_cf_global.theme].cam_pos_z},
|
||
|
up = {0.0F, 1.0F, 0.0F},
|
||
|
look = {CFG_cf_theme[CFG_cf_global.theme].cam_look_x, CFG_cf_theme[CFG_cf_global.theme].cam_look_y, CFG_cf_theme[CFG_cf_global.theme].cam_look_z};
|
||
|
guLookAt(GXview2D, &cam, &up, &look);
|
||
|
|
||
|
if (CFG.widescreen) {
|
||
|
guPerspective(GXprojection2D, 45, 1.778F, 0.1F, 500.0F);
|
||
|
} else {
|
||
|
guPerspective(GXprojection2D, 45, (f32)4/3, 0.1F, 500.0F);
|
||
|
}
|
||
|
GX_LoadProjectionMtx(GXprojection2D, GX_PERSPECTIVE);
|
||
|
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
|
||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
|
||
|
|
||
|
guMtxIdentity(GXmodel2D);
|
||
|
|
||
|
//get the objects size
|
||
|
width = 10.0;
|
||
|
height = 14.0;
|
||
|
|
||
|
//set rotation
|
||
|
if (cover->xrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &xaxis, cover->xrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (cover->yrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &yaxis, cover->yrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
if (cover->zrot != 0) {
|
||
|
guMtxRotAxisDeg(GXModelTemp, &zaxis, cover->zrot);
|
||
|
guMtxConcat (GXmodel2D, GXModelTemp, GXmodel2D);
|
||
|
}
|
||
|
|
||
|
// set the XYZ position
|
||
|
guMtxTransApply(GXmodel2D, GXmodel2D, cover->x, cover->y, cover->z);
|
||
|
guMtxConcat (GXview2D, GXmodel2D, GXmodelView2D);
|
||
|
|
||
|
// load the modelview matrix into matrix memory
|
||
|
GX_LoadPosMtxImm(GXmodelView2D, GX_PNMTX0);
|
||
|
|
||
|
//top
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(width, height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(width, height, 0.0f, color);
|
||
|
drawPosCol(-width, height, 0.0f, color);
|
||
|
GX_End();
|
||
|
|
||
|
//right - cover opening
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width, height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(width, height, 0.0f, color);
|
||
|
drawPosCol(width, -height, 0.0f, color);
|
||
|
drawPosCol(width, -height, COVER_BOX_DEPTH, color);
|
||
|
GX_End();
|
||
|
|
||
|
//back
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(width, height, 0.0f, color);
|
||
|
drawPosCol(-width, height, 0.0f, color);
|
||
|
drawPosCol(-width, -height, 0.0f, color);
|
||
|
drawPosCol(width, -height, 0.0f, color);
|
||
|
GX_End();
|
||
|
|
||
|
//spine
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, height, 0.0f, color);
|
||
|
drawPosCol(-width, height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(-width, -height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(-width, -height, 0.0f, color);
|
||
|
GX_End();
|
||
|
|
||
|
//front
|
||
|
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||
|
drawPosCol(-width, height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(width, height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(width, -height, COVER_BOX_DEPTH, color);
|
||
|
drawPosCol(-width, -height, COVER_BOX_DEPTH, color);
|
||
|
GX_End();
|
||
|
GX_LoadPosMtxImm (GXview2D, GX_PNMTX0);
|
||
|
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR);
|
||
|
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that sets the stencil colors
|
||
|
* @return void
|
||
|
*/
|
||
|
void set_cover_stencil_colors() {
|
||
|
int i;
|
||
|
for (i=1; i<=CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers; i++) {
|
||
|
coverCoords_left[i-1].stencil_color = GRRLIB_GetColor((u8)i, 0xFF, 0xFF, 0xFF);
|
||
|
coverCoords_right[i-1].stencil_color = GRRLIB_GetColor((u8)255-i, 0xFF, 0xFF, 0xFF);
|
||
|
}
|
||
|
coverCoords_center.stencil_color = MOUSEOVER_COVER_OFFSCREEN;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that draws each cover in a different color and then takes a snapshot of the buffer
|
||
|
* @return void
|
||
|
*/
|
||
|
void capture_cover_positions() {
|
||
|
int i;
|
||
|
|
||
|
if (tx_screenshot.data == NULL) {
|
||
|
// first time, allocate
|
||
|
// only 8 bits per pixel (R8)
|
||
|
int src_size = 128 * 128; // 16384
|
||
|
tx_screenshot.data = LARGE_alloc(src_size);
|
||
|
tx_screenshot.w = 128;
|
||
|
tx_screenshot.h = 128;
|
||
|
}
|
||
|
|
||
|
GRRLIB_prepareStencil();
|
||
|
//draw the covers with different colors
|
||
|
for (i=CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers-1; i>=0; i--) {
|
||
|
draw_phantom_cover(&coverCoords_left[i].currentPos, coverCoords_left[i].stencil_color);
|
||
|
draw_phantom_cover(&coverCoords_right[i].currentPos, coverCoords_right[i].stencil_color);
|
||
|
}
|
||
|
draw_phantom_cover(&coverCoords_center.currentPos, coverCoords_center.stencil_color);
|
||
|
GRRLIB_renderStencil_buf(&tx_screenshot);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that updates the Cover.selected attribute of all the covers. The
|
||
|
* selectedIndex param is used to tell which cover should be set to true - all
|
||
|
* others will be marked false.
|
||
|
*
|
||
|
* Valid selectedIndex values:
|
||
|
* Center cover index = 0
|
||
|
* Left covers are < 0 -> so the left cover next to the center is -1
|
||
|
* Right covers are > 0 -> so the right cover next to the center is 1
|
||
|
*
|
||
|
* @param selectedIndex the index of the cover that should be marked as selected
|
||
|
* @return void
|
||
|
*/
|
||
|
void set_selected_state(int selectedIndex) {
|
||
|
int i;
|
||
|
for (i=0; i<MAX_COVERFLOW_COVERS; i++) {
|
||
|
if (selectedIndex < 0 && selectedIndex == -i - 1)
|
||
|
coverCoords_left[i].selected = true;
|
||
|
else
|
||
|
coverCoords_left[i].selected = false;
|
||
|
|
||
|
if (selectedIndex > 0 && selectedIndex == i + 1)
|
||
|
coverCoords_right[i].selected = true;
|
||
|
else
|
||
|
coverCoords_right[i].selected = false;
|
||
|
}
|
||
|
if (selectedIndex == 0)
|
||
|
coverCoords_center.selected = true;
|
||
|
else
|
||
|
coverCoords_center.selected = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that returns the game index (gi) of the currently selected cover
|
||
|
* based on the Cover.selected attribute
|
||
|
*
|
||
|
* @return int representing game index
|
||
|
*/
|
||
|
int get_selected_cover_index() {
|
||
|
int i, selection;
|
||
|
|
||
|
for (i=0; i<MAX_COVERFLOW_COVERS; i++) {
|
||
|
if (coverCoords_left[i].selected) {
|
||
|
selection = coverCoords_left[i].gi;
|
||
|
goto out;
|
||
|
}
|
||
|
if (coverCoords_right[i].selected) {
|
||
|
selection = coverCoords_right[i].gi;
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
selection = coverCoords_center.gi;
|
||
|
set_selected_state(0);
|
||
|
out:;
|
||
|
return selection;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that determines if the current WiiMote sx/sy coord is over a cover. This method uses
|
||
|
* the screenshot taken in the capture_cover_positions() method and interrogates the color
|
||
|
* under the pointer. If the color matches one of the covers then we found a match.
|
||
|
*
|
||
|
* @param *ir IR info from the WiiMote
|
||
|
* @return int representing the index of the currently selected cover
|
||
|
*/
|
||
|
int is_over_cover(ir_t *ir) {
|
||
|
int selected_gi, i;
|
||
|
|
||
|
capture_cover_positions();
|
||
|
//grab the color under the pointer
|
||
|
i = GRRLIB_stencilVal(ir->sx, ir->sy, tx_screenshot);
|
||
|
selectedColor = GRRLIB_GetColor((u8)i, 0xFF, 0xFF, 0xFF);
|
||
|
if (selectedColor == coverCoords_center.stencil_color) {
|
||
|
set_selected_state(0);
|
||
|
selected_gi = coverCoords_center.gi;
|
||
|
goto out;
|
||
|
}
|
||
|
for (i=0; i<CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers; i++) {
|
||
|
if (selectedColor == coverCoords_left[i].stencil_color) {
|
||
|
set_selected_state(-i - 1);
|
||
|
selected_gi = coverCoords_left[i].gi;
|
||
|
goto out;
|
||
|
}
|
||
|
if (selectedColor == coverCoords_right[i].stencil_color) {
|
||
|
set_selected_state(i + 1);
|
||
|
selected_gi = coverCoords_right[i].gi;
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
selected_gi = get_selected_cover_index();
|
||
|
out:;
|
||
|
GRRLIB_ResetVideo();
|
||
|
return selected_gi;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Translates 2D x/y coords into 3D x/y coords based on the camera positioning and z position of the object.
|
||
|
*
|
||
|
* @param x_2d the 2d x coord to convert
|
||
|
* @param y_2d the 2d y coord to convert
|
||
|
* @param zpos z axis position of the 3d object to convert
|
||
|
* @param x_3d the converted 3d x coord
|
||
|
* @param y_3d the converted 3d y coord
|
||
|
* @return void
|
||
|
*/
|
||
|
void convert_2dCoords_into_3dCoords(float x_2d, float y_2d, float zpos, f32 *x_3d, f32 *y_3d)
|
||
|
{
|
||
|
Mtx44 GXprojection2D;
|
||
|
Mtx GXview2D, GXView2D_Inverse;
|
||
|
guVector v1, v1_direction;
|
||
|
f32 k;
|
||
|
|
||
|
//set the view
|
||
|
guVector cam = {CFG_cf_theme[CFG_cf_global.theme].cam_pos_x, CFG_cf_theme[CFG_cf_global.theme].cam_pos_y, CFG_cf_theme[CFG_cf_global.theme].cam_pos_z},
|
||
|
up = {0.0F, 1.0F, 0.0F},
|
||
|
look = {CFG_cf_theme[CFG_cf_global.theme].cam_look_x, CFG_cf_theme[CFG_cf_global.theme].cam_look_y, CFG_cf_theme[CFG_cf_global.theme].cam_look_z};
|
||
|
guLookAt(GXview2D, &cam, &up, &look);
|
||
|
|
||
|
//get the view matrix inverse
|
||
|
guMtxInverse (GXview2D, GXView2D_Inverse);
|
||
|
|
||
|
if (CFG.widescreen) {
|
||
|
guPerspective(GXprojection2D, 45, 1.778F, 0.1F, 500.0F);
|
||
|
} else {
|
||
|
guPerspective(GXprojection2D, 45, (f32)4/3, 0.1F, 500.0F);
|
||
|
}
|
||
|
GX_LoadProjectionMtx(GXprojection2D, GX_PERSPECTIVE);
|
||
|
|
||
|
//calculate the 3d vector based on the passed in 2d points and the perspective
|
||
|
v1.x = -(((2.0f * x_2d) / 640.0) - 1.0) / GXprojection2D[0][0];
|
||
|
v1.y = (((2.0f * y_2d ) / 480.0) - 1.0) / GXprojection2D[1][1];
|
||
|
v1.z = 1.0f;
|
||
|
//calculate the vector direction into the inverse world
|
||
|
v1_direction.x = v1.x * GXView2D_Inverse[0][0] + v1.y * GXView2D_Inverse[1][0] + v1.z * GXView2D_Inverse[2][0];
|
||
|
v1_direction.y = v1.x * GXView2D_Inverse[0][1] + v1.y * GXView2D_Inverse[1][1] + v1.z * GXView2D_Inverse[2][1];
|
||
|
v1_direction.z = v1.x * GXView2D_Inverse[0][2] + v1.y * GXView2D_Inverse[1][2] + v1.z * GXView2D_Inverse[2][2];
|
||
|
guVecNormalize (&v1_direction);
|
||
|
|
||
|
//calculate the final 2d position based on the z position of the 3d object
|
||
|
// and the direction into the inverse world
|
||
|
k = (zpos - cam.z) / v1_direction.z;
|
||
|
*x_3d = cam.x + k * v1_direction.x;
|
||
|
*y_3d = cam.y + k * v1_direction.y;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Calculates the max difference between two u32 colors (comparing RGB separately) and
|
||
|
* applies the max difference to the RGB values of the first u32. Then the u32 val is
|
||
|
* added to the end result.
|
||
|
*
|
||
|
* @param col the color to change
|
||
|
* @param col2 the color to compare the difference and apply to col
|
||
|
* @param val the color to add to col
|
||
|
* @param neg (1 or -1) to determine if val should be added or subtracted
|
||
|
*/
|
||
|
u32 addU32Value(u32 col, u32 col2, u32 val, int neg)
|
||
|
{
|
||
|
int r = (int)R(col);
|
||
|
int g = (int)G(col);
|
||
|
int b = (int)B(col);
|
||
|
int rv = (int)R(val);
|
||
|
int gv = (int)G(val);
|
||
|
int bv = (int)B(val);
|
||
|
//get diff between col and col2 RGB
|
||
|
int rdiff = r - (int)R(col2);
|
||
|
int gdiff = g - (int)G(col2);
|
||
|
int bdiff = b - (int)B(col2);
|
||
|
//who's got the largest diff?
|
||
|
int diff1 = (rdiff > bdiff) ? rdiff : bdiff;
|
||
|
int diff = (gdiff > diff1) ? gdiff : diff1;
|
||
|
diff = (diff > 0) ? diff : 0;
|
||
|
//subtract diff from each color and add val
|
||
|
r = r - diff + (rv * neg);
|
||
|
r = (r > 255) ? 255 : ((r < 0) ? 0 : r);
|
||
|
g = g - diff + (gv * neg);
|
||
|
g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
|
||
|
b = b - diff + (bv * neg);
|
||
|
b = (b > 255) ? 255 : ((b < 0) ? 0 : b);
|
||
|
return ((u8)r << 24) | ((u8)g << 16) | ((u8)b << 8) | A(col2);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that calculates the boxcover edge color
|
||
|
*
|
||
|
* @param gi the game image id number
|
||
|
* @param selected boolean that represents if the cover should be dimmed (selected=false) or normal (selected=true)
|
||
|
* @param alpha the alpha level of the cover. 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param color the color (including alpha) of the game image
|
||
|
* @param reflectionColorBottom the color (including alpha) of the bottom portion of the reflection (bottom of the game image). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorTop the color (including alpha) of the top portion of the reflection (top of the game image). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param edgecolor the color (including alpha) of the boxcover
|
||
|
* @param reflectionBottomEdge the color (including alpha) of the bottom portion of the reflection (bottom of the boxcover).
|
||
|
* @param reflectionTopEdge the color (including alpha) of the top portion of the reflection (top of the boxcover).
|
||
|
* @return void
|
||
|
*/
|
||
|
void get_boxcover_edge_color(int gi, bool selected, u8 alpha, u32 color, u32 reflectionColorBottom, u32 reflectionColorTop,
|
||
|
u32 *edgecolor, u32 *reflectionBottomEdge, u32 *reflectionTopEdge) {
|
||
|
u32 col;
|
||
|
bool dbColorFound = false;
|
||
|
char *gameid;
|
||
|
gameid = (char*)gameList[gi].id;
|
||
|
|
||
|
//check xml database for color
|
||
|
if (xml_getCaseColor(&col, (u8 *)gameid)) {
|
||
|
dbColorFound = true;
|
||
|
col |= alpha;
|
||
|
} else {
|
||
|
col = color;
|
||
|
}
|
||
|
|
||
|
//New Super Mario Bros
|
||
|
if (strncmp(gameid, "SMN", 3) == 0) col = 0xFF000000 | alpha;
|
||
|
|
||
|
//GameCube Games
|
||
|
if(gameList[gi].magic == DML_MAGIC || gameList[gi].magic == DML_MAGIC_HDD) col = 0x32323200 | alpha;
|
||
|
|
||
|
if (selected) {
|
||
|
*edgecolor = col;
|
||
|
*reflectionBottomEdge = addU32Value(col, reflectionColorBottom, 0x11111100, 1);
|
||
|
*reflectionTopEdge = addU32Value(col, reflectionColorTop, 0x11111100, 1);
|
||
|
} else {
|
||
|
if (dbColorFound)
|
||
|
*edgecolor = addU32Value(col, col, 0x22222200, -1);
|
||
|
else
|
||
|
*edgecolor = col;
|
||
|
*reflectionBottomEdge = addU32Value(col, reflectionColorBottom, 0x11111100, -1);
|
||
|
*reflectionTopEdge = addU32Value(col, reflectionColorTop, 0x11111100, -1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method draws a cover image. Used when the cover structure isn't fully populated (in rotation loops, etc.)
|
||
|
* and you need to pass in every value.
|
||
|
*
|
||
|
* @param tex image of the game cover
|
||
|
* @param xpos x axis position for the image
|
||
|
* @param ypos y axis position for the image
|
||
|
* @param zpos z axis position for the image
|
||
|
* @param xrot degrees to rotate the image on the x axis. For example a value of 90 will rotate it 90 degrees so it would appear flat on it's cover to the viewer.
|
||
|
* @param yrot degrees to rotate the image on the y axis. For example a value of 90 will rotate it 90 degrees on it's side so the front will be facing right to the viewer
|
||
|
* @param zrot degrees to rotate the image. For example a value of 90 will rotate it 90 degrees counter-clockwise
|
||
|
* @param alpha the alpha level of the cover. 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorBottom the color (including alpha) of the bottom portion of the reflection (bottom of the game image). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param reflectionColorTop the color (including alpha) of the top portion of the reflection (top of the game image). 255 will be a solid image. 0 will be fully transparent.
|
||
|
* @param draw3DCover boolean to determine if we should we draw the 3D cover object
|
||
|
* @param favorite boolean that represents if the favorites image should be drawn on the cover
|
||
|
* @param selected boolean that represents if the cover should be dimmed (selected=false) or normal (selected=true)
|
||
|
* @param drawReflection if true the cover reflection is drawn, else the cover itself
|
||
|
* @param gi the game image id number
|
||
|
* @return void
|
||
|
*/
|
||
|
void draw_cover_image(GRRLIB_texImg *tex,
|
||
|
f32 xpos, f32 ypos, f32 zpos, f32 xrot, f32 yrot, f32 zrot,
|
||
|
u8 alpha, u32 reflectionColorBottom, u32 reflectionColorTop,
|
||
|
bool draw3DCover, bool favorite, bool selected, bool drawReflection, int gi)
|
||
|
{
|
||
|
u32 color, edgecolor, reflectionBottom, reflectionTop, reflectionBottomEdge, reflectionTopEdge;
|
||
|
|
||
|
//is this cover selected?
|
||
|
if (selected) {
|
||
|
//light up selected game image
|
||
|
color = 0xFFFFFF00 | alpha;
|
||
|
reflectionBottom = color_add(reflectionColorBottom, 0x11111100, 1);
|
||
|
reflectionTop = color_add(reflectionColorTop, 0x11111100, 1);
|
||
|
} else {
|
||
|
//dim not selected game image
|
||
|
color = 0xDDDDDD00 | alpha;
|
||
|
reflectionBottom = color_add(reflectionColorBottom, 0x11111100, -1);
|
||
|
reflectionTop = color_add(reflectionColorTop, 0x11111100, -1);
|
||
|
}
|
||
|
//boxcover color
|
||
|
get_boxcover_edge_color(gi, selected, alpha, color, reflectionColorBottom, reflectionColorTop, &edgecolor, &reflectionBottomEdge, &reflectionTopEdge);
|
||
|
|
||
|
if (draw3DCover) {
|
||
|
if (drawReflection)
|
||
|
draw_fullcover_image_reflection(tex, xpos, ypos, zpos, xrot, yrot, zrot, reflectionBottom, reflectionTop, reflectionBottomEdge, reflectionTopEdge, favorite);
|
||
|
else
|
||
|
draw_fullcover_image(tex, xpos, ypos, zpos, xrot, yrot, zrot, color, edgecolor, favorite);
|
||
|
} else {
|
||
|
draw_2dcover_image(tex, xpos, ypos, zpos, xrot, yrot, zrot, color, reflectionBottom, reflectionTop, favorite);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that fades the background
|
||
|
* @return void
|
||
|
*/
|
||
|
void fadeBackground() {
|
||
|
int background_alpha = 0;
|
||
|
switch (background_fade_status) {
|
||
|
case BACKGROUND_FADE_DARK:
|
||
|
if (CFG_cf_global.transition == CF_TRANS_FLIP_TO_BACK && CFG_cf_global.frameCount > 0 && CFG_cf_global.frameIndex <= CFG_cf_global.frameCount) {
|
||
|
background_alpha = calculateNewPosition(0, CFG_cf_global.screen_fade_alpha, CFG_cf_global.frameIndex, CFG_cf_global.frameCount, EASING_TYPE_LINEAR);
|
||
|
} else {
|
||
|
background_alpha = CFG_cf_global.screen_fade_alpha;
|
||
|
}
|
||
|
break;
|
||
|
case BACKGROUND_FADE_LIGHT:
|
||
|
if (CFG_cf_global.transition == CF_TRANS_FLIP_TO_BACK && CFG_cf_global.frameCount > 0 && CFG_cf_global.frameIndex <= CFG_cf_global.frameCount) {
|
||
|
background_alpha = calculateNewPosition(CFG_cf_global.screen_fade_alpha, 0, CFG_cf_global.frameIndex, CFG_cf_global.frameCount, EASING_TYPE_LINEAR);
|
||
|
} else {
|
||
|
background_fade_status = BACKGROUND_FADE_NONE;
|
||
|
background_alpha = 0;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
case BACKGROUND_FADE_NONE: return;
|
||
|
}
|
||
|
if (background_alpha > 0 && background_alpha <= 255) {
|
||
|
GRRLIB_FillScreen(0x00000000 | background_alpha);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that gets the next position in an arc.
|
||
|
* parabola calculation:
|
||
|
* y = a(x-h)2+k
|
||
|
* a < 0 means opening is down (shaped like n)
|
||
|
* h = distance to vertex
|
||
|
* k = height
|
||
|
* for Excel: vertex = -0.8 * (POWER(B3 - (-10), 2)) + 10
|
||
|
*
|
||
|
* @param a represents the opening - usually generated from the getAparam() method
|
||
|
* @param height represents the height of the arc. So if you want the vertex to stop at 10 on the x axis, pass in a 10
|
||
|
* @param vertex represents the distance to the vertex from the starting point
|
||
|
* @param index represents the current index in your drawing loop
|
||
|
* @return f32 representing your next position
|
||
|
*/
|
||
|
f32 getArcPos(f32 a, f32 height, f32 vertex, f32 index) {
|
||
|
return a * (pow(index - vertex, 2)) + height;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that gets the A param for the getArcPos() method
|
||
|
* parabola calculation:
|
||
|
* y = a(x-h)2+k
|
||
|
* a < 0 means opening is down (shaped like n)
|
||
|
* h = distance to vertex
|
||
|
* k = height
|
||
|
*
|
||
|
* @param height represents the height of the arc. So if you want the vertex to stop at 10 on the x axis, pass in a 10
|
||
|
* @param vertex represents the distance to the vertex from the starting point
|
||
|
* @param finalIndexPos your last index value in your drawing loop (max loop value)
|
||
|
* @param finalArcPos represents where you want to end on the straight axis - so if you're arcing from left to right on the
|
||
|
* screen and you want the arc to be on the y axis, you pass in where you want to end on the x axis.
|
||
|
* @return f32 representing the A value
|
||
|
*/
|
||
|
f32 getAparam(f32 height, f32 vertex, f32 finalIndexPos, f32 finalArcPos) {
|
||
|
return (-height + finalArcPos) / (pow(finalIndexPos - vertex, 2));
|
||
|
}
|
||
|
|
||
|
extern char action_string[40];
|
||
|
extern int action_alpha;
|
||
|
|
||
|
/**
|
||
|
* Draws the selected cover's title
|
||
|
*
|
||
|
* @param selectedCover int representing the currently selected cover index
|
||
|
* @return void
|
||
|
*/
|
||
|
void Coverflow_draw_title(int selectedCover, int xpos, ir_t *ir) {
|
||
|
f32 title_y, title_x;
|
||
|
char gameTitle[TITLE_MAX] = "";
|
||
|
static time_t last_time = 0;
|
||
|
bool do_clock = false;
|
||
|
FontColor font_color = CFG.gui_text2;
|
||
|
time_t t = 0;
|
||
|
|
||
|
//game title stub.....
|
||
|
if (ir->smooth_valid || CFG_cf_global.frameCount || !CFG.clock_style) {
|
||
|
last_time = 0;
|
||
|
L_title:
|
||
|
if (action_alpha) {
|
||
|
font_color.color = (font_color.color & 0xFFFFFF00) | action_alpha;
|
||
|
if (action_alpha > 0) action_alpha -= 3;
|
||
|
if (action_alpha < 0) action_alpha = 0;
|
||
|
last_time = 0;
|
||
|
strncpy(gameTitle, action_string, TITLE_MAX);
|
||
|
} else {
|
||
|
if (!gameCnt) {
|
||
|
strcpy(gameTitle, gt("No games found!"));
|
||
|
} else if (selectedCover < 0 || selectedCover >= gameCnt) {
|
||
|
sprintf(gameTitle, "error %d", selectedCover);
|
||
|
} else {
|
||
|
snprintf(gameTitle, TITLE_MAX, "%s", get_title(&gameList[selectedCover]));
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// clock
|
||
|
t = time(NULL);
|
||
|
// wait 5 seconds before showing clock
|
||
|
if (last_time == 0) { last_time = t; goto L_title; }
|
||
|
if (t - last_time < 5) goto L_title;
|
||
|
do_clock = true;
|
||
|
}
|
||
|
|
||
|
//if xpos>0 then we are overriding the theme's settings
|
||
|
if (xpos > 0) {
|
||
|
title_x = xpos;
|
||
|
} else {
|
||
|
//Get x pos -> -1 means center it
|
||
|
if (CFG_cf_theme[CFG_cf_global.theme].title_text_xpos == -1)
|
||
|
title_x = (BACKGROUND_WIDTH/2) - (strlen(gameTitle)*(tx_font.tilew))/2;
|
||
|
else
|
||
|
title_x = CFG_cf_theme[CFG_cf_global.theme].title_text_xpos;
|
||
|
}
|
||
|
|
||
|
//Get y pos -> -1 means center it
|
||
|
if (CFG_cf_theme[CFG_cf_global.theme].title_text_ypos == -1) {
|
||
|
title_y = BACKGROUND_HEIGHT/2;
|
||
|
} else {
|
||
|
title_y = CFG_cf_theme[CFG_cf_global.theme].title_text_ypos;
|
||
|
}
|
||
|
|
||
|
//check if we're showing the back cover
|
||
|
if (!showingFrontCover) {
|
||
|
title_y = 436.f;
|
||
|
}
|
||
|
if (CFG.gui_title_top) {
|
||
|
title_y = 24.f + 2.f; // 24 = overscan
|
||
|
}
|
||
|
if (CFG.gui_title_area.w) {
|
||
|
if (xpos > 0) {
|
||
|
title_x = CFG.gui_title_area.x + CFG.gui_title_area.w/4;
|
||
|
} else {
|
||
|
title_x = CFG.gui_title_area.x + CFG.gui_title_area.w/2
|
||
|
- (strlen(gameTitle)*(tx_font.tilew))/2;
|
||
|
}
|
||
|
title_y = CFG.gui_title_area.y;
|
||
|
}
|
||
|
// clock
|
||
|
if (CFG.gui_clock_pos.x >= 0) {
|
||
|
Gui_Print_Clock(CFG.gui_clock_pos.x, CFG.gui_clock_pos.y, CFG.gui_text2, -1);
|
||
|
do_clock = false;
|
||
|
}
|
||
|
if (do_clock) {
|
||
|
int x = BACKGROUND_WIDTH/2;
|
||
|
int y = title_y + tx_font.tileh/2;
|
||
|
Gui_Print_Clock(x, y, CFG.gui_text2, 0);
|
||
|
} else {
|
||
|
Gui_PrintEx(title_x, title_y, &tx_font, font_color, gameTitle);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* resets the floating cover postions
|
||
|
*/
|
||
|
void resetFloatingCover() {
|
||
|
//reset the floating cover vars
|
||
|
float_xrot = 0;
|
||
|
float_yrot = 0;
|
||
|
float_zrot = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Calculates next position for floating covers
|
||
|
*/
|
||
|
void calculate_floating_cover() {
|
||
|
//do the floating cover thing if the theme wants it or we're showing the back cover
|
||
|
if (CFG_cf_theme[CFG_cf_global.theme].floating_cover || !showingFrontCover) {
|
||
|
//calculate xrot for float
|
||
|
if (float_xrot_up && float_xrot >= float_max_xrot) {
|
||
|
float_xrot -= float_speed_increment;
|
||
|
float_xrot_up = false;
|
||
|
} else if (float_xrot_up) {
|
||
|
float_xrot += float_speed_increment;
|
||
|
} else if (!float_xrot_up && float_xrot <= -float_max_xrot) {
|
||
|
float_xrot += float_speed_increment;
|
||
|
float_xrot_up = true;
|
||
|
} else {
|
||
|
float_xrot -= float_speed_increment;
|
||
|
}
|
||
|
|
||
|
//calculate yrot for float
|
||
|
if (float_yrot_up && float_yrot >= float_max_yrot) {
|
||
|
float_yrot -= float_speed_increment;
|
||
|
float_yrot_up = false;
|
||
|
} else if (float_yrot_up) {
|
||
|
float_yrot += float_speed_increment;
|
||
|
} else if (!float_yrot_up && float_yrot <= -float_max_yrot) {
|
||
|
float_yrot += float_speed_increment;
|
||
|
float_yrot_up = true;
|
||
|
} else {
|
||
|
float_yrot -= float_speed_increment;
|
||
|
}
|
||
|
|
||
|
//calculate zrot for float
|
||
|
if (float_zrot_up && float_zrot >= float_max_zrot) {
|
||
|
float_zrot -= float_speed_increment;
|
||
|
float_zrot_up = false;
|
||
|
} else if (float_zrot_up) {
|
||
|
float_zrot += float_speed_increment;
|
||
|
} else if (!float_zrot_up && float_zrot <= -float_max_zrot) {
|
||
|
float_zrot += float_speed_increment;
|
||
|
float_zrot_up = true;
|
||
|
} else {
|
||
|
float_zrot -= float_speed_increment;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Main method used to draw rotated covers.
|
||
|
* The basic equation is:
|
||
|
* current pos = starting point - ((starting point - end point) * index / number of total frames)
|
||
|
* @param *cover Cover object to rotate
|
||
|
* @param index int representing the current index in the rotation loop
|
||
|
* @param frames int representing the total frame count of the rotation
|
||
|
* @param floating if true the cover floats
|
||
|
* @param drawReflection if true the cover reflection is drawn, else the cover itself
|
||
|
* @param ease int representing the easing level to use: e.g. 0=linear
|
||
|
* @return void
|
||
|
*/
|
||
|
void Coverflow_rotate(struct Cover *cover, int index, int frames, bool floating, bool drawReflection, int ease) {
|
||
|
//calculate the new positions
|
||
|
cover->currentPos.x = calculateNewPosition(cover->startPos.x, cover->endPos.x, index, frames, ease);
|
||
|
cover->currentPos.y = calculateNewPosition(cover->startPos.y, cover->endPos.y, index, frames, ease);
|
||
|
cover->currentPos.z = calculateNewPosition(cover->startPos.z, cover->endPos.z, index, frames, ease);
|
||
|
cover->currentPos.xrot = calculateNewPosition(cover->startPos.xrot, cover->endPos.xrot, index, frames, ease);
|
||
|
cover->currentPos.yrot = calculateNewPosition(cover->startPos.yrot, cover->endPos.yrot, index, frames, ease);
|
||
|
cover->currentPos.zrot = calculateNewPosition(cover->startPos.zrot, cover->endPos.zrot, index, frames, ease);
|
||
|
cover->currentPos.alpha = calculateNewPosition(cover->startPos.alpha, cover->endPos.alpha, index, frames, ease);
|
||
|
cover->currentPos.reflection_bottom = calculateNewColor(cover->startPos.reflection_bottom, cover->endPos.reflection_bottom, index, frames, ease);
|
||
|
cover->currentPos.reflection_top = calculateNewColor(cover->startPos.reflection_top, cover->endPos.reflection_top, index, frames, ease);
|
||
|
bool favorite = is_favorite(gameList[cover->gi].id);
|
||
|
|
||
|
if (floating) {
|
||
|
//draw the cover image
|
||
|
draw_cover_image(&cover->tx, cover->currentPos.x, cover->currentPos.y, cover->currentPos.z,
|
||
|
cover->currentPos.xrot + float_xrot, cover->currentPos.yrot + float_yrot, cover->currentPos.zrot + float_zrot,
|
||
|
cover->currentPos.alpha, cover->currentPos.reflection_bottom, cover->currentPos.reflection_top,
|
||
|
CFG_cf_global.covers_3d, favorite, cover->selected, drawReflection, cover->gi);
|
||
|
} else {
|
||
|
//draw the cover image
|
||
|
draw_cover_image(&cover->tx, cover->currentPos.x, cover->currentPos.y, cover->currentPos.z,
|
||
|
cover->currentPos.xrot, cover->currentPos.yrot, cover->currentPos.zrot,
|
||
|
cover->currentPos.alpha, cover->currentPos.reflection_bottom, cover->currentPos.reflection_top,
|
||
|
CFG_cf_global.covers_3d, favorite, cover->selected, drawReflection, cover->gi);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that calculates the new frameIndex when switching easing types. This gets called when rotation is stopping.
|
||
|
*
|
||
|
* @param ease_type the easing type that is being switch to
|
||
|
* @param new_framecount int representing the new frame count
|
||
|
* @return void
|
||
|
*/
|
||
|
void calculate_new_easing_frameindex(int ease_type, int new_framecount) {
|
||
|
int i = 0;
|
||
|
f32 xpos = 0;
|
||
|
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
CFG_cf_global.frameCount = new_framecount;
|
||
|
//find the closest matching frame index for the new ease type
|
||
|
if (coverCoords_center.startPos.x > coverCoords_center.endPos.x) {
|
||
|
for (i=0; i<=CFG_cf_global.frameCount; i++) {
|
||
|
xpos = calculateNewPosition(coverCoords_center.startPos.x, coverCoords_center.endPos.x, i, new_framecount, ease_type);
|
||
|
if (xpos <= coverCoords_center.currentPos.x) {
|
||
|
CFG_cf_global.frameIndex = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (i=0; i<CFG_cf_global.frameCount; i++) {
|
||
|
xpos = calculateNewPosition(coverCoords_center.startPos.x, coverCoords_center.endPos.x, i, new_framecount, ease_type);
|
||
|
if (xpos >= coverCoords_center.currentPos.x) {
|
||
|
CFG_cf_global.frameIndex = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that resets the startPos to the currentPos for all right and left covers.
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
void reset_rotation_startPosition() {
|
||
|
int i = 0;
|
||
|
|
||
|
//let the side covers keep rotating...
|
||
|
if (CFG_cf_global.transition==CF_TRANS_ROTATE_RIGHT) {
|
||
|
coverCoords_left[0].startPos = coverCoords_left[0].currentPos;
|
||
|
for (i=0; i<CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers; i++) {
|
||
|
coverCoords_left[i+1].startPos = coverCoords_left[i+1].currentPos;
|
||
|
coverCoords_right[CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers-i-1].startPos = coverCoords_right[CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers-i-1].currentPos;
|
||
|
}
|
||
|
} else if (CFG_cf_global.transition==CF_TRANS_ROTATE_LEFT) {
|
||
|
coverCoords_right[0].startPos = coverCoords_right[0].currentPos;
|
||
|
for (i=0; i<CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers; i++) {
|
||
|
coverCoords_right[i+1].startPos = coverCoords_right[i+1].currentPos;
|
||
|
coverCoords_left[CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers-i-1].startPos = coverCoords_left[CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers-i-1].currentPos;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that repaints the static covers. This gets called when nothing is really going on (no rotating)
|
||
|
*
|
||
|
* @param *ir pointer to current wiimote data
|
||
|
* @param coverCount total number of games
|
||
|
* @param draw_title boolean to determine if the game title should be drawn
|
||
|
* @return int representing the index of the currently selected cover
|
||
|
*/
|
||
|
int Coverflow_drawCovers(ir_t *ir, int coverCount, bool draw_title) {
|
||
|
int i, j, alpha;
|
||
|
int ease;
|
||
|
int selectedCover = -1;
|
||
|
|
||
|
cache_release_all();
|
||
|
cache_request_before_and_after(coverCoords_center.gi, 5, 1);
|
||
|
|
||
|
//update the floating cover data
|
||
|
calculate_floating_cover();
|
||
|
|
||
|
//update the cover images from the cache
|
||
|
Coverflow_update_state();
|
||
|
|
||
|
//check if the pointer is over a cover
|
||
|
if (showingFrontCover) {
|
||
|
selectedCover = is_over_cover(ir);
|
||
|
} else {
|
||
|
//showing the back cover so force to the center cover
|
||
|
set_selected_state(0);
|
||
|
selectedCover = coverCoords_center.gi;
|
||
|
}
|
||
|
//set easing based on rotation speed
|
||
|
if (CFG_cf_global.frameCount < CFG_cf_theme[CFG_cf_global.theme].rotation_frames)
|
||
|
ease = EASING_TYPE_LINEAR; //linear
|
||
|
else
|
||
|
ease = EASING_TYPE_SLOW;
|
||
|
|
||
|
for(j=0; j<CFG.gui_antialias; j++) {
|
||
|
|
||
|
if (CFG.gui_antialias > 1)
|
||
|
GRRLIB_prepareAAPass(CFG.gui_antialias, j);
|
||
|
else
|
||
|
GRRLIB_ResetVideo();
|
||
|
|
||
|
//if moving to/from console mode then fade the backgrounds
|
||
|
if (CFG_cf_global.transition == CF_TRANS_MOVE_TO_CONSOLE || CFG_cf_global.transition == CF_TRANS_MOVE_FROM_CONSOLE) {
|
||
|
alpha = 255 * CFG_cf_global.frameIndex / CFG_cf_global.frameCount;
|
||
|
Gui_set_camera(NULL, 0);
|
||
|
if (CFG_cf_global.transition == CF_TRANS_MOVE_TO_CONSOLE) {
|
||
|
GRRLIB_DrawImg(0, 0, &tx_bg, 0, 1, 1, 0xFFFFFF00 | (255-alpha));
|
||
|
GRRLIB_DrawImg(0, 0, &tx_bg_con, 0, 1, 1, 0xFFFFFF00 | (alpha));
|
||
|
} else {
|
||
|
GRRLIB_DrawImg(0, 0, &tx_bg_con, 0, 1, 1, 0xFFFFFF00 | (255-alpha));
|
||
|
GRRLIB_DrawImg(0, 0, &tx_bg, 0, 1, 1, 0xFFFFFF00 | (alpha));
|
||
|
}
|
||
|
Gui_set_camera(NULL, 1);
|
||
|
} else {
|
||
|
Gui_draw_background();
|
||
|
}
|
||
|
|
||
|
// reflections
|
||
|
Coverflow_rotate(&coverCoords_center, CFG_cf_global.frameIndex, CFG_cf_global.frameCount, false, true, ease);
|
||
|
for (i=0; i<CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers + 1; i++) {
|
||
|
Coverflow_rotate(&coverCoords_right[i], CFG_cf_global.frameIndex, CFG_cf_global.frameCount, false, true, ease);
|
||
|
Coverflow_rotate(&coverCoords_left[i], CFG_cf_global.frameIndex, CFG_cf_global.frameCount, false, true, ease);
|
||
|
}
|
||
|
|
||
|
// covers
|
||
|
for (i=CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers; i>=0; i--) {
|
||
|
Coverflow_rotate(&coverCoords_left[i], CFG_cf_global.frameIndex, CFG_cf_global.frameCount, false, false, ease);
|
||
|
Coverflow_rotate(&coverCoords_right[i], CFG_cf_global.frameIndex, CFG_cf_global.frameCount, false, false, ease);
|
||
|
}
|
||
|
|
||
|
fadeBackground();
|
||
|
|
||
|
//center cover
|
||
|
if (!showingFrontCover || CFG_cf_theme[CFG_cf_global.theme].floating_cover)
|
||
|
//float the cover
|
||
|
Coverflow_rotate(&coverCoords_center, CFG_cf_global.frameIndex, CFG_cf_global.frameCount, true, false, ease);
|
||
|
else
|
||
|
Coverflow_rotate(&coverCoords_center, CFG_cf_global.frameIndex, CFG_cf_global.frameCount, false, false, ease);
|
||
|
|
||
|
if (CFG.gui_antialias > 1)
|
||
|
Gui_RenderAAPass(j);
|
||
|
}
|
||
|
|
||
|
if (CFG.gui_antialias > 1) {
|
||
|
GRRLIB_drawAAScene(CFG.gui_antialias, aa_texBuffer);
|
||
|
GRRLIB_ResetVideo();
|
||
|
}
|
||
|
|
||
|
|
||
|
if (draw_title) {
|
||
|
//if rotating fast then left align title for easier readability
|
||
|
if ((CFG_cf_global.frameCount < CFG_cf_theme[CFG_cf_global.theme].rotation_frames)
|
||
|
&& (CFG_cf_global.transition==CF_TRANS_ROTATE_RIGHT || CFG_cf_global.transition==CF_TRANS_ROTATE_LEFT))
|
||
|
Coverflow_draw_title(selectedCover, 180, ir);
|
||
|
else
|
||
|
Coverflow_draw_title(selectedCover, -1, ir);
|
||
|
}
|
||
|
|
||
|
//check if we're done transitioning
|
||
|
if (CFG_cf_global.transition > 0) {
|
||
|
if (CFG_cf_global.frameIndex >= CFG_cf_global.frameCount) {
|
||
|
//rotations should always end at the default (slow) speed
|
||
|
if (CFG_cf_global.frameCount < CFG_cf_theme[CFG_cf_global.theme].rotation_frames
|
||
|
&& (CFG_cf_global.transition==CF_TRANS_ROTATE_RIGHT || CFG_cf_global.transition==CF_TRANS_ROTATE_LEFT)) {
|
||
|
Coverflow_init_transition(CFG_cf_global.transition, 0, coverCount, true);
|
||
|
} else {
|
||
|
//done with this transition so set the cover positions
|
||
|
coverCoords_center.currentPos = coverCoords_center.endPos;
|
||
|
coverCoords_center.startPos = coverCoords_center.endPos;
|
||
|
for (i=0; i < CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers + 1; i++) {
|
||
|
coverCoords_left[i].currentPos = coverCoords_left[i].endPos;
|
||
|
coverCoords_left[i].startPos = coverCoords_left[i].endPos;
|
||
|
coverCoords_right[i].currentPos = coverCoords_right[i].endPos;
|
||
|
coverCoords_right[i].startPos = coverCoords_right[i].endPos;
|
||
|
}
|
||
|
//reset the transition params
|
||
|
CFG_cf_global.frameIndex = 0;
|
||
|
CFG_cf_global.frameCount = 0;
|
||
|
CFG_cf_global.transition = 0;
|
||
|
}
|
||
|
} else {
|
||
|
//if we're rotating fast but we stopped pressing the dpad (or rotating via wiimote) then
|
||
|
// we need to recalculate the frameIndex so the easing switchover is smooth
|
||
|
if (CFG_cf_global.frameCount < CFG_cf_theme[CFG_cf_global.theme].rotation_frames
|
||
|
&& (CFG_cf_global.transition==CF_TRANS_ROTATE_RIGHT || CFG_cf_global.transition==CF_TRANS_ROTATE_LEFT)) {
|
||
|
if (!rotating_with_wiimote && !Wpad_Held(0) && CFG_cf_global.frameIndex < CFG_cf_global.frameCount * .75) {
|
||
|
calculate_new_easing_frameindex(EASING_TYPE_SLOW, CFG_cf_theme[CFG_cf_global.theme].rotation_frames);
|
||
|
}
|
||
|
}
|
||
|
//not done so increase the frame index
|
||
|
CFG_cf_global.frameIndex++;
|
||
|
}
|
||
|
rotating_with_wiimote = 0;
|
||
|
}
|
||
|
|
||
|
if (CFG.debug == 3) {
|
||
|
GRRLIB_Printf(50, 10, &tx_font, CFG.gui_text.color, 1, "center start.x:%f end.x:%f", coverCoords_center.startPos.x, coverCoords_center.endPos.x);
|
||
|
GRRLIB_Printf(50, 25, &tx_font, CFG.gui_text.color, 1, "center start.y:%f end.y:%f", coverCoords_center.startPos.y, coverCoords_center.endPos.y);
|
||
|
GRRLIB_Printf(50, 40, &tx_font, CFG.gui_text.color, 1, "center start.z:%f end.z:%f", coverCoords_center.startPos.z, coverCoords_center.endPos.z);
|
||
|
GRRLIB_Printf(50, 55, &tx_font, CFG.gui_text.color, 1, "center start.yrot:%f end.yrot:%f", coverCoords_center.startPos.yrot, coverCoords_center.endPos.yrot);
|
||
|
GRRLIB_Printf(50, 70, &tx_font, CFG.gui_text.color, 1, "trans? %i, framecount: %i, frameindex: %i ease: %i", CFG_cf_global.transition, CFG_cf_global.frameCount, CFG_cf_global.frameIndex, ease);
|
||
|
//to see the mouseover screenshot image:
|
||
|
//GRRLIB_DrawImg_format(0, 0, tx_screenshot, GX_TF_I8, 0, 1, 1, 0xFFFFFFFF);
|
||
|
//currently selected color and cover index:
|
||
|
GRRLIB_Printf(200, 410, &tx_font, CFG.gui_text.color, 1.0, "cover(gi): %i color: %X", selectedCover, selectedColor);
|
||
|
//mouse pointer position:
|
||
|
//GRRLIB_Printf(50, 430, &tx_font, CFG.gui_text.color, 1.0, "sx: %.2f sy: %.2f angle: %.2f v: %d %d %d", ir->sx, ir->sy, ir->angle, ir->raw_valid, ir->smooth_valid, ir->valid);
|
||
|
orient_t o;
|
||
|
WPAD_Orientation(0, &o);
|
||
|
GRRLIB_Printf(50, 450, &tx_font, CFG.gui_text.color, 1.0, "yaw:%.2f pitch: %.2f roll: %.2f ", o.yaw, o.pitch, o.roll);
|
||
|
}
|
||
|
|
||
|
return selectedCover;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that populates a CoverPos (cover position) struct based on the passed in position type.
|
||
|
*
|
||
|
* @param type int representing the cover position type to use
|
||
|
* @param *coverPos the CoverPos to populate
|
||
|
* @return void
|
||
|
*/
|
||
|
void build_coverPos_type(int type, CoverPos *coverPos) {
|
||
|
f32 x, y;
|
||
|
|
||
|
switch(type){
|
||
|
//position for when viewing the back cover
|
||
|
case COVERPOS_FLIP_TO_BACK:
|
||
|
coverPos->xrot = 0;
|
||
|
coverPos->yrot = 180;
|
||
|
coverPos->zrot = 0;
|
||
|
coverPos->x = CFG_cf_global.cover_back_xpos;
|
||
|
coverPos->y = CFG_cf_global.cover_back_ypos;
|
||
|
coverPos->z = CFG_cf_global.cover_back_zpos;
|
||
|
coverPos->reflection_bottom = CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom & 0xFFFFFF00;
|
||
|
coverPos->reflection_top = CFG_cf_theme[CFG_cf_global.theme].reflections_color_top & 0xFFFFFF00;
|
||
|
coverPos->alpha = 255;
|
||
|
break;
|
||
|
|
||
|
//position of the center cover based on the current theme
|
||
|
case COVERPOS_CENTER_THEME:
|
||
|
coverPos->xrot = coverCoords_center.themePos.xrot;
|
||
|
coverPos->yrot = coverCoords_center.themePos.yrot;
|
||
|
coverPos->zrot = coverCoords_center.themePos.zrot;
|
||
|
coverPos->x = coverCoords_center.themePos.x;
|
||
|
coverPos->y = coverCoords_center.themePos.y;
|
||
|
coverPos->z = coverCoords_center.themePos.z;
|
||
|
coverPos->reflection_bottom = coverCoords_center.themePos.reflection_bottom;
|
||
|
coverPos->reflection_top = coverCoords_center.themePos.reflection_top;
|
||
|
coverPos->alpha = coverCoords_center.themePos.alpha;
|
||
|
break;
|
||
|
|
||
|
//position of the console image (2D cover)
|
||
|
case COVERPOS_CONSOLE_2D:
|
||
|
//calculate the 3d x and y position of the console cover
|
||
|
convert_2dCoords_into_3dCoords(COVER_XCOORD + 80, COVER_YCOORD + 112, -73, &x, &y);
|
||
|
coverPos->xrot = 0;
|
||
|
coverPos->yrot = 0;
|
||
|
coverPos->zrot = 0;
|
||
|
coverPos->x = x;
|
||
|
coverPos->y = y;
|
||
|
coverPos->z = -73;
|
||
|
coverPos->reflection_bottom = 0x00000000;
|
||
|
coverPos->reflection_top = 0x00000000;
|
||
|
coverPos->alpha = 255;
|
||
|
break;
|
||
|
|
||
|
//position of the console image (fake 3D cover)
|
||
|
case COVERPOS_CONSOLE_3D:
|
||
|
//calculate the 3d x and y position of the console cover
|
||
|
convert_2dCoords_into_3dCoords(COVER_XCOORD + 80, COVER_YCOORD + 112, -80, &x, &y);
|
||
|
coverPos->xrot = 0;
|
||
|
coverPos->yrot = 33;
|
||
|
coverPos->zrot = 0;
|
||
|
coverPos->x = x;
|
||
|
coverPos->y = y;
|
||
|
coverPos->z = -82;
|
||
|
coverPos->reflection_bottom = 0x00000000;
|
||
|
coverPos->reflection_top = 0x00000000;
|
||
|
coverPos->alpha = 255;
|
||
|
break;
|
||
|
|
||
|
//position of the game loading screen cover
|
||
|
case COVERPOS_GAME_LOAD:
|
||
|
coverPos->xrot = 0;
|
||
|
coverPos->yrot = 0; //33;
|
||
|
coverPos->zrot = 0;
|
||
|
coverPos->x = 0;
|
||
|
coverPos->y = 0;
|
||
|
coverPos->z = -50; //-73;
|
||
|
coverPos->alpha = 255;
|
||
|
coverPos->reflection_bottom = 0x00000000;
|
||
|
coverPos->reflection_top = 0x00000000;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method that draws the center cover for the game options screen
|
||
|
*
|
||
|
* @param game_sel int representing the index of the selected game to draw
|
||
|
* @param x int X position of the cover
|
||
|
* @param y int Y position of the cover
|
||
|
* @param z int Z position of the cover
|
||
|
* @param xrot f32 the X-axis rotation of the cover
|
||
|
* @param yrot f32 the Y-axis rotation of the cover
|
||
|
* @param zrot f32 the Z-axis rotation of the cover
|
||
|
* @return void
|
||
|
*/
|
||
|
void Coverflow_drawCoverForGameOptions(int game_sel,
|
||
|
float x, float y, float z, f32 xrot, f32 yrot, f32 zrot, int cstyle)
|
||
|
{
|
||
|
Cover cover;
|
||
|
bool favorite;
|
||
|
int aa, j;
|
||
|
GRRLIB_texImg bg_tx;
|
||
|
long long t1, t11, t12, t2;
|
||
|
|
||
|
if (!grx_cover_init) Coverflow_Grx_Init();
|
||
|
|
||
|
t1 = gettime();
|
||
|
// reset cover indexing to the selected cover
|
||
|
setCoverIndexing(gameCnt, game_sel);
|
||
|
cache_request_before_and_after(game_sel, 5, 1);
|
||
|
// update the cover images from the cache
|
||
|
//Coverflow_update_state();
|
||
|
update_cover_state2(&coverCoords_center, cstyle);
|
||
|
|
||
|
favorite = is_favorite(gameList[coverCoords_center.gi].id);
|
||
|
// init the positioning
|
||
|
build_coverPos_type(COVERPOS_GAME_LOAD, &cover.currentPos);
|
||
|
// scale the passed in x and y coords to 3d space
|
||
|
convert_2dCoords_into_3dCoords(x+80, y+112, -40, &cover.currentPos.x, &cover.currentPos.y);
|
||
|
|
||
|
t11 = gettime();
|
||
|
//GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||
|
//GX_SetViewport(0, 0, rmode->fbWidth, rmode->efbHeight, 0, 1);
|
||
|
//GX_InvVtxCache();
|
||
|
//GX_InvalidateTexAll();
|
||
|
// capture the background for aa
|
||
|
bg_tx = GRRLIB_AAScreen2Texture();
|
||
|
GRRLIB_AAScreen2Texture_buf(&bg_tx, GX_FALSE);
|
||
|
t12 = gettime();
|
||
|
|
||
|
aa = (CFG.gui_antialias < 1) ? 1 : CFG.gui_antialias;
|
||
|
for(j=0; j < aa; j++) {
|
||
|
|
||
|
GRRLIB_prepareAAPass(aa, j);
|
||
|
|
||
|
Gui_set_camera(NULL, 0);
|
||
|
if (j) Gui_DrawImgFullScreen(&bg_tx, 0xFFFFFFFF, false);
|
||
|
Gui_set_camera(NULL, 1);
|
||
|
|
||
|
// debug bench
|
||
|
if (coverflow_test_grid)
|
||
|
{
|
||
|
int mx=8, my=4;
|
||
|
int nx, ny;
|
||
|
for (ny = 0; ny < my; ny++) {
|
||
|
for (nx = 0; nx < mx; nx++) {
|
||
|
if (ny == my-1 && nx < 2) continue;
|
||
|
float x, y, z;
|
||
|
float px, py; //, pz;
|
||
|
x = (0.5+nx + 0.1*ny) * 640 / mx;
|
||
|
y = (0.5+ny) * 480 / my;
|
||
|
z = -150;
|
||
|
convert_2dCoords_into_3dCoords(x, y, z, &px, &py);
|
||
|
draw_cover_image(&coverCoords_center.tx,
|
||
|
px, py, z,
|
||
|
//cover.currentPos.xrot, yrot, cover.currentPos.zrot,
|
||
|
xrot, yrot, zrot,
|
||
|
cover.currentPos.alpha,
|
||
|
cover.currentPos.reflection_bottom,
|
||
|
cover.currentPos.reflection_top,
|
||
|
true, favorite, true, false, coverCoords_center.gi);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//draw the cover image
|
||
|
draw_cover_image(&coverCoords_center.tx,
|
||
|
cover.currentPos.x, cover.currentPos.y, cover.currentPos.z + z,
|
||
|
//cover.currentPos.xrot, yrot, cover.currentPos.zrot,
|
||
|
xrot, yrot, zrot,
|
||
|
cover.currentPos.alpha,
|
||
|
cover.currentPos.reflection_bottom,
|
||
|
cover.currentPos.reflection_top,
|
||
|
true, favorite, true, false, coverCoords_center.gi);
|
||
|
|
||
|
Gui_RenderAAPass(j);
|
||
|
}
|
||
|
GRRLIB_drawAAScene(aa, aa_texBuffer);
|
||
|
GRRLIB_ResetVideo();
|
||
|
SAFE_FREE(bg_tx.data);
|
||
|
t2 = gettime();
|
||
|
if (CFG.debug == 3)
|
||
|
{
|
||
|
GRRLIB_Printf(20, 60, &tx_font, 0xFF00FFFF, 1,
|
||
|
"ms:%6.2f %6.2f %6.2f %6.2f",
|
||
|
(float)diff_usec(t1,t2)/1000.0,
|
||
|
(float)diff_usec(t1,t11)/1000.0,
|
||
|
(float)diff_usec(t11,t12)/1000.0,
|
||
|
(float)diff_usec(t12,t2)/1000.0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Method used to inititate a new coverflow transition (rotate right/left, spin, etc).
|
||
|
*
|
||
|
* @param trans_type int representing the transition type to initiate (rotate right/left, spin, etc)
|
||
|
* @param speed int representing the transition speed. Set to 0 for the "default" slow speed.
|
||
|
* @param coverCount total number of games
|
||
|
* @param speed_rampup bool representing if each iteration of the transition should increase in speed
|
||
|
* @return int representing the index of the currently selected cover
|
||
|
*/
|
||
|
int Coverflow_init_transition(int trans_type, int speed, int coverCount, bool speed_rampup) {
|
||
|
int numSideCovers, covertype, idx;
|
||
|
int i=0;
|
||
|
ir_t ir;
|
||
|
int slow_rotation_speed = 20;
|
||
|
|
||
|
//set the framecount for the transition
|
||
|
if (trans_type == CF_TRANS_ROTATE_RIGHT || trans_type == CF_TRANS_ROTATE_LEFT) {
|
||
|
//are we already performing this action?
|
||
|
if (CFG_cf_global.transition == trans_type && speed > 0) {
|
||
|
//check if we're allowed to perform the transition yet
|
||
|
if (CFG_cf_global.frameIndex < rotation_start_index) {
|
||
|
return -1;
|
||
|
} else {
|
||
|
if (speed_rampup) {
|
||
|
CFG_cf_global.frameCount = CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast;
|
||
|
if (rotation_start_index > CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast)
|
||
|
rotation_start_index = CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast;
|
||
|
else
|
||
|
rotation_start_index = 7; //final rotation start - increase to slow it down
|
||
|
} else {
|
||
|
rotation_start_index = (int)round(calculateNewPosition(slow_rotation_speed, CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast, speed, 100, EASING_TYPE_LINEAR));
|
||
|
CFG_cf_global.frameCount = (int)round(calculateNewPosition(slow_rotation_speed, CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast, speed, 100, EASING_TYPE_LINEAR));
|
||
|
}
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
}
|
||
|
} else {
|
||
|
//new transition - reset the rotation vars
|
||
|
if (speed_rampup) {
|
||
|
//first iteration, start at the default (slow) speed. We'll ramp up from here next time.
|
||
|
rotation_start_index = 20; //determines when fast rotation starts when holding down the dpad
|
||
|
CFG_cf_global.frameCount = CFG_cf_theme[CFG_cf_global.theme].rotation_frames;
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
} else {
|
||
|
//calculate framerate based on passed in speed level
|
||
|
rotation_start_index = (int)round(calculateNewPosition(slow_rotation_speed, CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast, speed, 100, EASING_TYPE_LINEAR));
|
||
|
idx = (int)round(calculateNewPosition(slow_rotation_speed, CFG_cf_theme[CFG_cf_global.theme].rotation_frames_fast, speed, 100, EASING_TYPE_LINEAR));
|
||
|
if (idx == CFG_cf_theme[CFG_cf_global.theme].rotation_frames) {
|
||
|
//rotating from slow to fast so find our new position for linear easing
|
||
|
calculate_new_easing_frameindex(EASING_TYPE_LINEAR, idx);
|
||
|
} else {
|
||
|
CFG_cf_global.frameCount = idx;
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//store the number of side covers
|
||
|
numSideCovers = CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers;
|
||
|
|
||
|
//set the cover start and end positions for the transition
|
||
|
switch(trans_type){
|
||
|
case CF_TRANS_ROTATE_RIGHT:
|
||
|
//move the img index to the right
|
||
|
setCoverIndexing(coverCount, coverCoords_right[0].gi);
|
||
|
if (numSideCovers > 0) {
|
||
|
//right[0] to center
|
||
|
coverCoords_center.startPos = coverCoords_right[0].currentPos;
|
||
|
//center to left[0]
|
||
|
coverCoords_left[0].startPos = coverCoords_center.currentPos;
|
||
|
//side covers
|
||
|
for (i=0; i<numSideCovers; i++) {
|
||
|
coverCoords_left[i+1].startPos = coverCoords_left[i].currentPos;
|
||
|
coverCoords_right[numSideCovers-i-1].startPos = coverCoords_right[numSideCovers-i].currentPos;
|
||
|
}
|
||
|
coverCoords_right[numSideCovers].startPos = coverCoords_right[numSideCovers].themePos;
|
||
|
coverCoords_right[numSideCovers].currentPos = coverCoords_right[numSideCovers].themePos;
|
||
|
}
|
||
|
CFG_cf_global.transition = CF_TRANS_ROTATE_RIGHT;
|
||
|
break;
|
||
|
|
||
|
case CF_TRANS_ROTATE_LEFT:
|
||
|
//move the img index to the left
|
||
|
setCoverIndexing(coverCount, coverCoords_left[0].gi);
|
||
|
if (numSideCovers > 0) {
|
||
|
//left[0] to center
|
||
|
coverCoords_center.startPos = coverCoords_left[0].currentPos;
|
||
|
//center to right[0]
|
||
|
coverCoords_right[0].startPos = coverCoords_center.currentPos;
|
||
|
//side covers
|
||
|
for (i=0; i<numSideCovers; i++) {
|
||
|
coverCoords_right[i+1].startPos = coverCoords_right[i].currentPos;
|
||
|
coverCoords_left[numSideCovers-i-1].startPos = coverCoords_left[numSideCovers-i].currentPos;
|
||
|
}
|
||
|
coverCoords_left[numSideCovers].startPos = coverCoords_left[numSideCovers].themePos;
|
||
|
coverCoords_left[numSideCovers].currentPos = coverCoords_left[numSideCovers].themePos;
|
||
|
}
|
||
|
CFG_cf_global.transition = CF_TRANS_ROTATE_LEFT;
|
||
|
break;
|
||
|
|
||
|
case CF_TRANS_FLIP_TO_BACK:
|
||
|
rotation_start_index = 20;
|
||
|
|
||
|
if (CFG_cf_global.transition == trans_type)
|
||
|
CFG_cf_global.frameCount = CFG_cf_global.frameIndex;
|
||
|
else
|
||
|
CFG_cf_global.frameCount = 30;
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
|
||
|
coverCoords_center.startPos = coverCoords_center.currentPos;
|
||
|
//let the side covers keep rotating...
|
||
|
reset_rotation_startPosition();
|
||
|
//set the positions
|
||
|
if (showingFrontCover) {
|
||
|
build_coverPos_type(COVERPOS_FLIP_TO_BACK, &coverCoords_center.endPos);
|
||
|
background_fade_status = BACKGROUND_FADE_DARK;
|
||
|
showingFrontCover = false;
|
||
|
} else {
|
||
|
build_coverPos_type(COVERPOS_CENTER_THEME, &coverCoords_center.endPos);
|
||
|
background_fade_status = BACKGROUND_FADE_LIGHT;
|
||
|
showingFrontCover = true;
|
||
|
}
|
||
|
CFG_cf_global.transition = CF_TRANS_FLIP_TO_BACK;
|
||
|
break;
|
||
|
|
||
|
case CF_TRANS_MOVE_TO_CENTER:
|
||
|
break;
|
||
|
|
||
|
case CF_TRANS_MOVE_TO_POSITION:
|
||
|
rotation_start_index = 20;
|
||
|
CFG_cf_global.frameCount = 20;
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
if (background_fade_status == BACKGROUND_FADE_DARK)
|
||
|
background_fade_status = BACKGROUND_FADE_LIGHT;
|
||
|
CFG_cf_global.transition = CF_TRANS_MOVE_TO_POSITION;
|
||
|
break;
|
||
|
|
||
|
case CF_TRANS_MOVE_TO_CONSOLE:
|
||
|
case CF_TRANS_MOVE_TO_CONSOLE_3D:
|
||
|
rotation_start_index = 16 - CFG.gui_antialias * 2;
|
||
|
CFG_cf_global.frameCount = 16 - CFG.gui_antialias * 2;
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
|
||
|
|
||
|
if (trans_type == CF_TRANS_MOVE_TO_CONSOLE)
|
||
|
covertype = COVERPOS_CONSOLE_2D;
|
||
|
else
|
||
|
covertype = COVERPOS_CONSOLE_3D;
|
||
|
|
||
|
//check if the pointer is over a cover
|
||
|
Wpad_getIR(&ir);
|
||
|
if (showingFrontCover) {
|
||
|
i = is_over_cover(&ir);
|
||
|
} else {
|
||
|
//showing the back cover so force to the center cover
|
||
|
set_selected_state(0);
|
||
|
}
|
||
|
//set the positions
|
||
|
for (i=0; i<numSideCovers; i++) {
|
||
|
if (coverCoords_left[i].selected) {
|
||
|
build_coverPos_type(covertype, &coverCoords_left[i].endPos);
|
||
|
} else {
|
||
|
coverCoords_left[i].endPos.alpha = 0;
|
||
|
coverCoords_left[i].endPos.reflection_bottom = coverCoords_left[i].currentPos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_left[i].endPos.reflection_top = coverCoords_left[i].currentPos.reflection_top & 0xFFFFFF00;
|
||
|
}
|
||
|
if (coverCoords_right[i].selected) {
|
||
|
build_coverPos_type(covertype, &coverCoords_right[i].endPos);
|
||
|
} else {
|
||
|
coverCoords_right[i].endPos.alpha = 0;
|
||
|
coverCoords_right[i].endPos.reflection_bottom = coverCoords_right[i].currentPos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_right[i].endPos.reflection_top = coverCoords_right[i].currentPos.reflection_top & 0xFFFFFF00;
|
||
|
}
|
||
|
}
|
||
|
if (coverCoords_center.selected) {
|
||
|
build_coverPos_type(covertype, &coverCoords_center.endPos);
|
||
|
} else {
|
||
|
coverCoords_center.endPos.alpha = 0;
|
||
|
coverCoords_center.endPos.reflection_bottom = coverCoords_center.currentPos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_center.endPos.reflection_top = coverCoords_center.currentPos.reflection_top & 0xFFFFFF00;
|
||
|
}
|
||
|
|
||
|
if (background_fade_status == BACKGROUND_FADE_DARK)
|
||
|
background_fade_status = BACKGROUND_FADE_LIGHT;
|
||
|
CFG_cf_global.transition = CF_TRANS_MOVE_TO_CONSOLE;
|
||
|
//we have to loop the rendering here since we're leaving gui mode
|
||
|
for (i=0; i<CFG_cf_global.frameCount; i++) {
|
||
|
Wpad_getIR(&ir);
|
||
|
Coverflow_drawCovers(&ir, coverCount, false);
|
||
|
Gui_draw_pointer(&ir);
|
||
|
Gui_Render();
|
||
|
}
|
||
|
//reset the transition params
|
||
|
CFG_cf_global.frameIndex = 0;
|
||
|
CFG_cf_global.frameCount = 0;
|
||
|
break;
|
||
|
|
||
|
case CF_TRANS_MOVE_FROM_CONSOLE:
|
||
|
case CF_TRANS_MOVE_FROM_CONSOLE_3D:
|
||
|
rotation_start_index = 16 - CFG.gui_antialias * 2;
|
||
|
CFG_cf_global.frameCount = 16 - CFG.gui_antialias * 2;
|
||
|
CFG_cf_global.frameIndex = 1;
|
||
|
|
||
|
|
||
|
if (trans_type == CF_TRANS_MOVE_FROM_CONSOLE)
|
||
|
covertype = COVERPOS_CONSOLE_2D;
|
||
|
else
|
||
|
covertype = COVERPOS_CONSOLE_3D;
|
||
|
|
||
|
//set the positions
|
||
|
for (i=0; i<numSideCovers; i++) {
|
||
|
coverCoords_left[i].startPos.alpha = 0;
|
||
|
coverCoords_left[i].startPos.reflection_bottom = coverCoords_left[i].currentPos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_left[i].startPos.reflection_top = coverCoords_left[i].currentPos.reflection_top & 0xFFFFFF00;
|
||
|
coverCoords_right[i].startPos.alpha = 0;
|
||
|
coverCoords_right[i].startPos.reflection_bottom = coverCoords_right[i].currentPos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_right[i].startPos.reflection_top = coverCoords_right[i].currentPos.reflection_top & 0xFFFFFF00;
|
||
|
}
|
||
|
build_coverPos_type(covertype, &coverCoords_center.startPos);
|
||
|
CFG_cf_global.transition = CF_TRANS_MOVE_FROM_CONSOLE;
|
||
|
//loop the transition rendering...
|
||
|
for (i=0; i<CFG_cf_global.frameCount; i++) {
|
||
|
Wpad_getIR(&ir);
|
||
|
Coverflow_drawCovers(&ir, coverCount, false);
|
||
|
Gui_draw_pointer(&ir);
|
||
|
Gui_Render();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
case CF_TRANS_NONE:
|
||
|
break;
|
||
|
}
|
||
|
return coverCoords_center.gi;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Method that flips the center cover 180 degrees from it's current position to either
|
||
|
* a fullscreen view (on it's back cover) or back to where it should be (on it's front
|
||
|
* cover). If showBackCover is true, it will flip to the back.
|
||
|
*
|
||
|
* @param showBackCover boolean to tell if back cover should be shown
|
||
|
* @param TypeUsed if 1 then wiimote if 2 then dpad if 0 then just flip it with no checks
|
||
|
* @return int representing the index of the currently selected cover
|
||
|
*/
|
||
|
int Coverflow_flip_cover_to_back(bool showBackCover, int typeUsed) {
|
||
|
if (typeUsed == 2) { //DPad
|
||
|
if (showingFrontCover) {
|
||
|
spinCover_dpad_used = true;
|
||
|
} else {
|
||
|
spinCover_dpad_used = false;
|
||
|
}
|
||
|
Coverflow_init_transition(CF_TRANS_FLIP_TO_BACK, 0, 0, true);
|
||
|
} else if (typeUsed == 1) { //wiimote
|
||
|
if (spinCover_dpad_used) {
|
||
|
if (showBackCover && !showingFrontCover) {
|
||
|
spinCover_dpad_used = false;
|
||
|
}
|
||
|
} else {
|
||
|
if (showingFrontCover && showBackCover) {
|
||
|
Coverflow_init_transition(CF_TRANS_FLIP_TO_BACK, 0, 0, true);
|
||
|
} else if (!showingFrontCover && !showBackCover) {
|
||
|
Coverflow_init_transition(CF_TRANS_FLIP_TO_BACK, 0, 0, true);
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
//somebody just wants it flipped so flip it
|
||
|
spinCover_dpad_used = false;
|
||
|
Coverflow_init_transition(CF_TRANS_FLIP_TO_BACK, 0, 0, true);
|
||
|
}
|
||
|
return coverCoords_center.gi;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Checks the current wiimote params to determine if an action needs to be performed
|
||
|
* e.g. rotate the center cover, scroll right/left, etc.
|
||
|
*
|
||
|
* @param *ir IR info from the WiiMote
|
||
|
* @param coverCount total number of games
|
||
|
* @return int representing the index of the currently selected cover
|
||
|
*/
|
||
|
int Coverflow_process_wiimote_events(ir_t *ir, int coverCount) {
|
||
|
int selected = coverCoords_center.gi;
|
||
|
int speed = 0;
|
||
|
int ret = 0;
|
||
|
|
||
|
// check if pointing within screen
|
||
|
if ((ir->sy >= 0 && ir->sy <= BACKGROUND_HEIGHT) &&
|
||
|
(ir->sx >= -160 && ir->sx <= BACKGROUND_WIDTH+160)) {
|
||
|
|
||
|
//get rotation data
|
||
|
int ir_rot = (int)ir->angle;
|
||
|
if (ir_rot < 0) ir_rot += 360;
|
||
|
//flip the cover over if they're rotating the wiimote
|
||
|
if (ir_rot > 80 && ir_rot < 280){
|
||
|
selected = Coverflow_flip_cover_to_back(true, 1);
|
||
|
goto out;
|
||
|
} else {
|
||
|
selected = Coverflow_flip_cover_to_back(false, 1);
|
||
|
}
|
||
|
|
||
|
// jump out if pointer scroll disabled
|
||
|
if (!CFG.gui_pointer_scroll) goto out;
|
||
|
if (CFG.gui_cover_area.h) {
|
||
|
if (ir->sy < CFG.gui_cover_area.y
|
||
|
|| ir->sy > CFG.gui_cover_area.y + CFG.gui_cover_area.h) {
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//scroll left or right
|
||
|
if (ir->sx >= -80 && ir->sx < WIIMOTE_SIDE_SCROLL_WIDTH - 1) {
|
||
|
//LEFT
|
||
|
if (ir->sx > 20 && ir->sx < WIIMOTE_SIDE_SCROLL_WIDTH - 1) {
|
||
|
//speed = (100 / (WIIMOTE_SIDE_SCROLL_WIDTH - 20)) * (WIIMOTE_SIDE_SCROLL_WIDTH - ir->sx);
|
||
|
speed = (int)round(1.25 * (f32)(WIIMOTE_SIDE_SCROLL_WIDTH - ir->sx));
|
||
|
} else if (ir->sx <= 20 && ir->sx >= -80) {
|
||
|
//max speed
|
||
|
speed = 100;
|
||
|
}
|
||
|
if (speed < 0) speed = 0;
|
||
|
rotating_with_wiimote = 1;
|
||
|
ret = Coverflow_init_transition(CF_TRANS_ROTATE_LEFT, speed, coverCount, false);
|
||
|
if (ret > 0) {
|
||
|
cache_release_all();
|
||
|
cache_request_before_and_after(ret, 5, 1);
|
||
|
}
|
||
|
|
||
|
} else if ((ir->sx > BACKGROUND_WIDTH - WIIMOTE_SIDE_SCROLL_WIDTH + 1) && (ir->sx <= BACKGROUND_WIDTH + 80)) {
|
||
|
//RIGHT
|
||
|
if ((ir->sx > BACKGROUND_WIDTH - WIIMOTE_SIDE_SCROLL_WIDTH + 1) && (ir->sx < BACKGROUND_WIDTH - 20)) {
|
||
|
speed = (int)round(1.25 * (f32)(ir->sx - (BACKGROUND_WIDTH - WIIMOTE_SIDE_SCROLL_WIDTH)));
|
||
|
} else if ((ir->sx <= BACKGROUND_WIDTH + 80) && (ir->sx >= BACKGROUND_WIDTH - 20)) {
|
||
|
//max speed
|
||
|
speed = 100;
|
||
|
}
|
||
|
if (speed < 0) speed = 0;
|
||
|
rotating_with_wiimote = 1;
|
||
|
ret = Coverflow_init_transition(CF_TRANS_ROTATE_RIGHT, speed, coverCount, false);
|
||
|
if (ret > 0) {
|
||
|
cache_release_all();
|
||
|
cache_request_before_and_after(ret, 5, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
out:;
|
||
|
return selected;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Initializes the cover coordinates based on the currently selected theme
|
||
|
* @param coverCount total number of games
|
||
|
* @param selectedCoverIndex index of the currently selected cover
|
||
|
* @param themeChange boolean to determine if a coverflow gui theme change is being performed
|
||
|
* @return int representing the index of the currently selected cover
|
||
|
*/
|
||
|
int Coverflow_initCoverObjects(int coverCount, int selectedCoverIndex, bool themeChange) {
|
||
|
int selectedCover, i, numSideCovers;
|
||
|
|
||
|
//set the global number of covers
|
||
|
CFG_cf_global.number_of_covers = coverCount;
|
||
|
|
||
|
if (!themeChange) {
|
||
|
memset(coverCoords_left, 0, sizeof(coverCoords_left));
|
||
|
memset(coverCoords_right, 0, sizeof(coverCoords_right));
|
||
|
memset(&coverCoords_center, 0, sizeof(coverCoords_center));
|
||
|
}
|
||
|
|
||
|
//if they tried to get crazy with the number of side covers then max them out
|
||
|
if (CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers > MAX_COVERFLOW_COVERS) {
|
||
|
CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers = MAX_COVERFLOW_COVERS;
|
||
|
}
|
||
|
|
||
|
numSideCovers = CFG_cf_theme[CFG_cf_global.theme].number_of_side_covers;
|
||
|
|
||
|
//center positioning
|
||
|
coverCoords_center.themePos.x = CFG_cf_theme[CFG_cf_global.theme].cover_center_xpos;
|
||
|
coverCoords_center.themePos.y = CFG_cf_theme[CFG_cf_global.theme].cover_center_ypos;
|
||
|
coverCoords_center.themePos.z = CFG_cf_theme[CFG_cf_global.theme].cover_center_zpos;
|
||
|
coverCoords_center.themePos.xrot = CFG_cf_theme[CFG_cf_global.theme].cover_center_xrot;
|
||
|
coverCoords_center.themePos.yrot = CFG_cf_theme[CFG_cf_global.theme].cover_center_yrot;
|
||
|
coverCoords_center.themePos.zrot = CFG_cf_theme[CFG_cf_global.theme].cover_center_zrot;
|
||
|
coverCoords_center.themePos.alpha = 255;
|
||
|
coverCoords_center.themePos.reflection_bottom = CFG_cf_theme[CFG_cf_global.theme].reflections_color_bottom;
|
||
|
coverCoords_center.themePos.reflection_top = CFG_cf_theme[CFG_cf_global.theme].reflections_color_top;
|
||
|
|
||
|
if (!themeChange) {
|
||
|
coverCoords_center.currentPos = coverCoords_center.themePos;
|
||
|
coverCoords_center.startPos = coverCoords_center.themePos;
|
||
|
} else {
|
||
|
coverCoords_center.startPos = coverCoords_center.currentPos;
|
||
|
}
|
||
|
coverCoords_center.endPos = coverCoords_center.themePos;
|
||
|
|
||
|
//side covers
|
||
|
for (i=0; i < numSideCovers; i++) {
|
||
|
setCoverPosition_Left(&coverCoords_left[i].themePos, i);
|
||
|
if (!themeChange) {
|
||
|
coverCoords_left[i].currentPos = coverCoords_left[i].themePos;
|
||
|
coverCoords_left[i].startPos = coverCoords_left[i].themePos;
|
||
|
} else {
|
||
|
coverCoords_left[i].startPos = coverCoords_left[i].currentPos;
|
||
|
}
|
||
|
coverCoords_left[i].endPos = coverCoords_left[i].themePos;
|
||
|
coverCoords_left[i].selected = false;
|
||
|
coverCoords_left[i].gi = 0;
|
||
|
|
||
|
setCoverPosition_Right(&coverCoords_right[i].themePos, i);
|
||
|
if (!themeChange) {
|
||
|
coverCoords_right[i].currentPos = coverCoords_right[i].themePos;
|
||
|
coverCoords_right[i].startPos = coverCoords_right[i].themePos;
|
||
|
} else {
|
||
|
coverCoords_right[i].startPos = coverCoords_right[i].currentPos;
|
||
|
}
|
||
|
coverCoords_right[i].endPos = coverCoords_right[i].themePos;
|
||
|
coverCoords_right[i].selected = false;
|
||
|
coverCoords_right[i].gi = 0;
|
||
|
}
|
||
|
|
||
|
//hide the far right and left covers - only shown when rotating
|
||
|
setCoverPosition_Right(&coverCoords_right[numSideCovers].themePos, i);
|
||
|
coverCoords_right[numSideCovers].hidden = 1;
|
||
|
coverCoords_right[numSideCovers].themePos.alpha = 0;
|
||
|
coverCoords_right[numSideCovers].themePos.reflection_bottom = coverCoords_right[numSideCovers].themePos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_right[numSideCovers].themePos.reflection_top = coverCoords_right[numSideCovers].themePos.reflection_top & 0xFFFFFF00;
|
||
|
coverCoords_right[numSideCovers].currentPos = coverCoords_right[numSideCovers].themePos;
|
||
|
coverCoords_right[numSideCovers].startPos = coverCoords_right[numSideCovers].themePos;
|
||
|
coverCoords_right[numSideCovers].endPos = coverCoords_right[numSideCovers].themePos;
|
||
|
|
||
|
setCoverPosition_Left(&coverCoords_left[numSideCovers].themePos, i);
|
||
|
coverCoords_left[numSideCovers].hidden = 1;
|
||
|
coverCoords_left[numSideCovers].themePos.alpha = 0;
|
||
|
coverCoords_left[numSideCovers].themePos.reflection_bottom = coverCoords_left[numSideCovers].themePos.reflection_bottom & 0xFFFFFF00;
|
||
|
coverCoords_left[numSideCovers].themePos.reflection_top = coverCoords_left[numSideCovers].themePos.reflection_top & 0xFFFFFF00;
|
||
|
coverCoords_left[numSideCovers].currentPos = coverCoords_left[numSideCovers].themePos;
|
||
|
coverCoords_left[numSideCovers].startPos = coverCoords_left[numSideCovers].themePos;
|
||
|
coverCoords_left[numSideCovers].endPos = coverCoords_left[numSideCovers].themePos;
|
||
|
|
||
|
//init the cover indexing
|
||
|
if (!themeChange)
|
||
|
//use the passed in cover index when coming from console or grid
|
||
|
selectedCover = setCoverIndexing(coverCount, selectedCoverIndex);
|
||
|
else
|
||
|
//use the current center cover index if changing coverflow themes
|
||
|
selectedCover = setCoverIndexing(coverCount, coverCoords_center.gi);
|
||
|
|
||
|
//screenshot the new cover positions for the mouseover detection
|
||
|
set_cover_stencil_colors();
|
||
|
capture_cover_positions();
|
||
|
|
||
|
//reset the floating cover vars
|
||
|
resetFloatingCover();
|
||
|
|
||
|
showingFrontCover = true;
|
||
|
background_fade_status = BACKGROUND_FADE_NONE;
|
||
|
cover_init = 1;
|
||
|
|
||
|
return selectedCover;
|
||
|
}
|