Files
GTASource/game/frontend/Store/StoreAdvertScreen.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

1144 lines
32 KiB
C++

#include "Frontend/Store/StoreAdvertScreen.h"
#include "Frontend/BusySpinner.h"
#include "Frontend/Store/StoreMainScreen.h"
#include "Frontend/Store/StoreScreenMgr.h"
#include "Frontend/Store/StoreUIChannel.h"
#include "Frontend/Store/StoreTextureManager.h"
#include "Frontend/WarningScreen.h"
#include "Network/Live/livemanager.h"
#include "network/commerce/CommerceManager.h"
#include "system/controlMgr.h"
#include "system/pad.h"
#include "text/TextConversion.h"
#if RSG_PC
#include "rline/rlpc.h"
#endif // RSG_PC
#define STOREMENU_FILENAME "pause_menu_store_content"
#define BUTTONMENU_FILENAME "store_instructional_buttons"
PARAM(adDataLocalFile, "Local store advert data file");
FRONTEND_STORE_OPTIMISATIONS()
cStoreAdvertScreen::cStoreAdvertScreen() :
// m_ScreenMode(ADVERT_SCREEN_MODE_SINGLE),
m_MovieId(-1),
m_ButtonMovieId(-1),
m_bLoadingAssets(false),
m_bPendingAdvertSetup(false),
m_ButtonState(ONLY_CANCEL),
m_IsActive(false),
m_IsLoaded(false),
m_DisplayingErrorDialog(false),
m_ColumnRequestIndex(0),
m_CurrentColumn(0)
{
for ( int i = 0; i < NUM_COLUMNS; i++ )
{
m_ImageStates[i] = AD_IMAGE_STATE_NONE;
}
}
cStoreAdvertScreen::~cStoreAdvertScreen()
{
Shutdown();
}
void cStoreAdvertScreen::Init()
{
m_bPendingAdvertSetup = false;
m_IsActive = true;
if ( CScaleformMgr::FindMovieByFilename(BUTTONMENU_FILENAME) == -1 )
{
m_ButtonMovieId = CScaleformMgr::CreateMovie(BUTTONMENU_FILENAME, Vector2(0.0f, 0.0f), Vector2(1.0f, 1.0f));
CBusySpinner::RegisterInstructionalButtonMovie(m_ButtonMovieId); // register this "instructional button" movie with the spinner system
}
Vector2 pos(cStoreScreenMgr::GetMovieXPos(), cStoreScreenMgr::GetMovieYPos());
Vector2 size(cStoreScreenMgr::GetMovieWidth(), cStoreScreenMgr::GetMovieHeight());
m_MovieId = CScaleformMgr::CreateMovie(STOREMENU_FILENAME, pos, size);
m_bLoadingAssets = true;
m_IsLoaded = false;
for ( int i = 0; i < NUM_COLUMNS; i++ )
{
m_ImageStates[i] = AD_IMAGE_STATE_NONE;
}
m_DisplayingErrorDialog = false;
m_ColumnRequestIndex = 0;
m_CurrentColumn = 0;
}
void cStoreAdvertScreen::Shutdown()
{
if ( m_MovieId != -1 )
{
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
{
CScaleformMgr::EndMethod();
}
CScaleformMgr::RequestRemoveMovie(m_MovieId);
}
if ( m_ButtonMovieId != -1 )
{
CBusySpinner::UnregisterInstructionalButtonMovie(m_ButtonMovieId);
CScaleformMgr::RequestRemoveMovie(m_ButtonMovieId);
}
ReleaseLoadedImages();
m_MovieId = -1;
m_ButtonMovieId = -1;
m_IsActive = false;
m_IsLoaded = false;
}
void cStoreAdvertScreen::Update()
{
if ( m_bLoadingAssets )
{
if (AreAllAssetsActive())
{
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "MENU_STATE"))
{
s32 menuStateParam = 0; //0 is the value we pass for the ad screen.
CScaleformMgr::AddParamInt(menuStateParam);
CScaleformMgr::EndMethod();
}
m_bLoadingAssets = false;
}
return;
}
//We let asset loading proceed if the screen is not active, but otherwise we do not want to interfere with other screens.
if (!m_IsActive)
{
ReleaseLoadedImages();
return;
}
if (m_DisplayingErrorDialog)
{
CWarningScreen::SetMessage(WARNING_MESSAGE_STANDARD, "CMRC_GOTOSTORE");
if (CPauseMenu::CheckInput(FRONTEND_INPUT_ACCEPT, true, CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE | CHECK_INPUT_OVERRIDE_FLAG_WARNING_MESSAGE) ||
CPauseMenu::CheckInput(FRONTEND_INPUT_BACK, true, CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE | CHECK_INPUT_OVERRIDE_FLAG_WARNING_MESSAGE) )
{
m_DisplayingErrorDialog = false;
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
{
CScaleformMgr::EndMethod();
}
cStoreScreenMgr::RequestExit();
}
}
else
{
UpdateInput();
}
if ( m_bPendingAdvertSetup && cStoreScreenMgr::GetAdvertData()->HasValidData() )
{
m_bPendingAdvertSetup = false;
SetupAdverts();
RequestImages();
m_IsLoaded = true;
}
UpdateImageRequests();
//The current button help state does not reflect the current data state, re-setup the buttons.
if ( ( m_ButtonState == ONLY_CANCEL && CLiveManager::GetCommerceMgr().HasValidData() )
|| ( m_ButtonState == CANCEL_AND_CONFIRM && !CLiveManager::GetCommerceMgr().HasValidData() ) )
{
SetupButtons();
}
if ( m_ColumnRequestIndex != 0 )
{
if (CScaleformMgr::IsReturnValueSet(m_ColumnRequestIndex))
{
m_CurrentColumn = CScaleformMgr::GetReturnValueInt(m_ColumnRequestIndex);
m_ColumnRequestIndex = 0;
}
}
}
void cStoreAdvertScreen::SetupAdverts()
{
int numAdverts = 0;
if ( cStoreScreenMgr::GetAdvertData()->HasValidData() )
{
numAdverts = cStoreScreenMgr::GetAdvertData()->GetNumAdvertDataRecords();
}
if ( numAdverts > NUM_COLUMNS )
{
numAdverts = NUM_COLUMNS;
}
storeUIDebugf3("Setting up adverts with %d records." ,numAdverts);
for ( s32 iAds = 0; iAds < numAdverts; iAds++ )
{
SetupAd( iAds );
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_HEADER_COLOUR"))
{
CRGBA headerColour = CHudColour::GetRGBA(HUD_COLOUR_BLUE);
CScaleformMgr::AddParamInt(headerColour.GetRed());
CScaleformMgr::AddParamInt(headerColour.GetGreen());
CScaleformMgr::AddParamInt(headerColour.GetBlue());
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_COLUMN_TITLE"))
{
CScaleformMgr::AddParamInt(3);
CScaleformMgr::AddParamString("ADVERTISEMENTS");
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_SHOP_LOGO"))
{
CScaleformMgr::AddParamInt(cStoreScreenMgr::GetBranding());
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SHOW_SHOP_LOGO"))
{
CScaleformMgr::AddParamBool( cStoreScreenMgr::GetBranding() != 0 );
CScaleformMgr::EndMethod();
}
#if __PPU
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SHOW_PLAYSTATION_LOGO"))
{
CScaleformMgr::AddParamBool(true);
CScaleformMgr::EndMethod();
}
#endif
SetupButtons();
//Finally highlight column
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "HIGHLIGHT_COLUMN"))
{
CScaleformMgr::AddParamInt(0);
CScaleformMgr::EndMethod();
}
}
void cStoreAdvertScreen::SetupButtons()
{
//Setup the instructional buttons
if ( m_ButtonMovieId >= 0 )
{
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT_EMPTY"))
{
CScaleformMgr::EndMethod();
}
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "SET_CLEAR_SPACE"))
{
CScaleformMgr::AddParamInt(200);
CScaleformMgr::EndMethod();
}
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
{
CScaleformMgr::AddParamInt(0);
CScaleformMgr::AddParamInt(31);
CScaleformMgr::AddParamString(TheText.Get("CMRC_BACK"));
CScaleformMgr::EndMethod();
}
if ( CLiveManager::GetCommerceMgr().HasValidData() )
{
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
{
CScaleformMgr::AddParamInt(1);
CScaleformMgr::AddParamInt(30);
CScaleformMgr::AddParamString(TheText.Get("CMRC_SELECT"));
CScaleformMgr::EndMethod();
}
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "SET_DATA_SLOT"))
{
CScaleformMgr::AddParamInt(2);
CScaleformMgr::AddParamInt(33);
CScaleformMgr::AddParamString(TheText.Get("CMRC_CONT"));
CScaleformMgr::EndMethod();
}
m_ButtonState = CANCEL_AND_CONFIRM;
}
else
{
m_ButtonState = ONLY_CANCEL;
}
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "DRAW_INSTRUCTIONAL_BUTTONS"))
{
//CScaleformMgr::AddParamInt(1);
CScaleformMgr::EndMethod();
}
if ( CScaleformMgr::BeginMethod(m_ButtonMovieId, SF_BASE_CLASS_GENERIC, "SET_BACKGROUND_COLOUR"))
{
CScaleformMgr::AddParamInt(0);
CScaleformMgr::AddParamInt(0);
CScaleformMgr::AddParamInt(0);
CScaleformMgr::AddParamInt(80);
CScaleformMgr::EndMethod();
}
}
}
void cStoreAdvertScreen::UpdateInput()
{
if (!AreAllAssetsActive())
return;
if (CPauseMenu::CheckInput(FRONTEND_INPUT_UP,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(DPADUP);
CScaleformMgr::EndMethod();
}
if (CPauseMenu::CheckInput(FRONTEND_INPUT_DOWN,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(DPADDOWN);
CScaleformMgr::EndMethod();
}
if (CPauseMenu::CheckInput(FRONTEND_INPUT_LEFT,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(DPADLEFT);
CScaleformMgr::EndMethod();
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_COLUMN"))
{
m_ColumnRequestIndex = CScaleformMgr::EndMethodReturnValue(m_ColumnRequestIndex);
}
}
if (CPauseMenu::CheckInput(FRONTEND_INPUT_RIGHT,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT"))
{
CScaleformMgr::AddParamInt(DPADRIGHT);
CScaleformMgr::EndMethod();
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "GET_CURRENT_COLUMN"))
{
m_ColumnRequestIndex = CScaleformMgr::EndMethodReturnValue(m_ColumnRequestIndex);
}
}
if (CPauseMenu::CheckInput(FRONTEND_INPUT_BACK,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_CIRCLE"))
{
CScaleformMgr::EndMethod();
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SHUTDOWN_MOVIE"))
{
CScaleformMgr::EndMethod();
}
cStoreScreenMgr::RequestExit();
}
bool goToMainStoreScreen = false;
if ( CPauseMenu::CheckInput(FRONTEND_INPUT_ACCEPT,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_CROSS") )
{
if ( cStoreScreenMgr::GetAdvertData() && cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(m_CurrentColumn)->GetLinkedProductId().GetLength() > 0 )
{
cStoreScreenMgr::SetInitialItemID( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(m_CurrentColumn)->GetLinkedProductId() );
}
goToMainStoreScreen = true;
}
if ( CPauseMenu::CheckInput(FRONTEND_INPUT_Y,false,CHECK_INPUT_OVERRIDE_FLAG_STORAGE_DEVICE) && CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_INPUT_EVENT_CROSS") )
{
goToMainStoreScreen = true;
}
if ( goToMainStoreScreen )
{
CScaleformMgr::EndMethod();
if (CLiveManager::GetCommerceMgr().HasValidData())
{
//Clear the columns.
for (s32 iClearCols=0; iClearCols < NUM_COLUMNS; iClearCols++)
{
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT_EMPTY"))
{
CScaleformMgr::AddParamInt(iClearCols);
CScaleformMgr::EndMethod();
}
}
//We pass the movies to main screen initialisation here.
cStoreScreenMgr::GetStoreMainScreen()->Init( m_MovieId, m_ButtonMovieId );
//At this point we have handed off responsibility for shutting down the movies to the main store screen
m_MovieId = -1;
m_ButtonMovieId = -1;
//Having handed off, we do not want to remain active.
m_IsActive = false;
}
}
}
void cStoreAdvertScreen::Render()
{
float fTimeStep = fwTimer::GetSystemTimeStep();
if ( m_MovieId >= 0)
{
CScaleformMgr::RenderMovie( m_MovieId, fTimeStep, true );
}
#if RSG_PC
// hide instructional buttons if SCUI is showing ...hints are confusing
if (!g_rlPc.IsUiShowing())
#endif
{
if ( m_ButtonMovieId >= 0 )
{
CScaleformMgr::RenderMovie( m_ButtonMovieId, fTimeStep, true );
}
}
}
bool cStoreAdvertScreen::AreAllAssetsActive()
{
bool retVal = ( m_MovieId != -1 && CScaleformMgr::IsMovieActive(m_MovieId));
if ( m_ButtonMovieId != -1 && !CScaleformMgr::IsMovieActive(m_ButtonMovieId) )
{
retVal = false;
}
return retVal;
}
void cStoreAdvertScreen::CheckIncomingFunctions( atHashWithStringBank methodName, const GFxValue* /*args*/ )
{
if ( !m_IsActive )
{
return;
}
if (methodName == ATSTRINGHASH("LOAD_PAUSE_MENU_STORE_CONTENT",0x879bc589))
{
storeUIDebugf3("Store Advert screen callback recieved.\n");
m_bPendingAdvertSetup = true;
return;
}
}
void cStoreAdvertScreen::DumpDebugInfo()
{
}
void cStoreAdvertScreen::UpdateImageRequests()
{
storeUIAssert( cStoreScreenMgr::GetTextureManager() );
if ( cStoreScreenMgr::GetTextureManager() == NULL )
{
return;
}
for (int iAds = 0; iAds < NUM_COLUMNS; iAds++)
{
if ( m_ImageStates[ iAds ] == AD_IMAGE_STATE_REQUESTED )
{
if ( cStoreScreenMgr::GetTextureManager()->RequestTexture( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(iAds)->GetImagePath() ) )
{
m_ImageStates[ iAds ] = AD_IMAGE_STATE_LOADED;
SetupAd( iAds );
}
}
}
}
void cStoreAdvertScreen::RequestImages()
{
storeUIAssert( cStoreScreenMgr::GetTextureManager() );
if ( cStoreScreenMgr::GetTextureManager() == NULL )
{
return;
}
for (int iAds = 0; iAds < NUM_COLUMNS; iAds++)
{
storeUIAssertf( m_ImageStates[iAds] == AD_IMAGE_STATE_NONE, "Image is either already loaded or already requested" );
if ( m_ImageStates[iAds] == AD_IMAGE_STATE_LOADED )
{
cStoreScreenMgr::GetTextureManager()->ReleaseTexture( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(iAds)->GetImagePath() );
}
if ( m_ImageStates[iAds] == AD_IMAGE_STATE_REQUESTED )
{
continue;
}
if ( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(iAds)->GetImagePath().GetLength() > 0 )
{
m_ImageStates[iAds] = AD_IMAGE_STATE_REQUESTED;
}
}
}
void cStoreAdvertScreen::SetupAd( int aAdIndex )
{
storeUIAssertf(aAdIndex >= 0 && aAdIndex <= NUM_COLUMNS, "Invalid column index");
if ( aAdIndex < 0 || aAdIndex >= NUM_COLUMNS )
{
return;
}
//Clear the existing center data slot of items.
if ( CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT_EMPTY"))
{
CScaleformMgr::AddParamInt(aAdIndex);
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
{
atString cloudStrippedPath;
if ( m_ImageStates[aAdIndex] == AD_IMAGE_STATE_LOADED )
{
cloudStrippedPath = cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(aAdIndex)->GetImagePath();
cStoreTextureManager::ConvertPathToTextureName(cloudStrippedPath);
}
else
{
cloudStrippedPath = "";
}
CScaleformMgr::AddParamInt(aAdIndex);
CScaleformMgr::AddParamInt(0);
CScaleformMgr::AddParamString( cloudStrippedPath );
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
{
CScaleformMgr::AddParamInt(aAdIndex);
CScaleformMgr::AddParamInt(1);
CScaleformMgr::AddParamString( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(aAdIndex)->GetTitle() );
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "SET_DATA_SLOT"))
{
CScaleformMgr::AddParamInt(aAdIndex);
CScaleformMgr::AddParamInt(2);
CScaleformMgr::AddParamString( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(aAdIndex)->GetText() );
CScaleformMgr::EndMethod();
}
if (CScaleformMgr::BeginMethod(m_MovieId, SF_BASE_CLASS_STORE, "DISPLAY_DATA_SLOT"))
{
CScaleformMgr::AddParamInt(aAdIndex);
CScaleformMgr::EndMethod();
}
}
void cStoreAdvertScreen::ReleaseLoadedImages()
{
//We are not active, unload assets or cancel requests.
for ( int i = 0; i < NUM_COLUMNS; i++ )
{
if ( cStoreScreenMgr::GetTextureManager() && cStoreScreenMgr::GetAdvertData()->HasValidData() )
{
if ( m_ImageStates[i] == AD_IMAGE_STATE_LOADED )
{
cStoreScreenMgr::GetTextureManager()->ReleaseTexture( cStoreScreenMgr::GetAdvertData()->GetAdvertRecord(i)->GetImagePath() );
}
if ( m_ImageStates[i] == AD_IMAGE_STATE_REQUESTED )
{
//TODO: Get the cancel method from Luis A
}
}
m_ImageStates[i] = AD_IMAGE_STATE_NONE;
}
}
void cStoreAdvertData::cStoreAdSaxReader::Start( cStoreAdvertData* pAdData )
{
Assert(pAdData);
m_pAdvertData = pAdData;
m_State = STATE_EXPECT_ROOT;
Begin();
}
void cStoreAdvertData::cStoreAdSaxReader::startElement( const char* /*url*/, const char* /*localName*/, const char* qName )
{
switch( static_cast<int>(m_State) )
{
case STATE_EXPECT_ROOT:
if(0 == stricmp("AdData", qName))
{
m_State = STATE_EXPECT_ADVERT;
}
else
{
storeUIErrorf("Error parsing [STATE_EXPECT_ROOT] %s", qName);
}
break;
case STATE_EXPECT_ADVERT:
if(0 == stricmp("Advert", qName))
{
storeUIAssert( m_pCurrentAdvert == NULL );
m_pCurrentAdvert = rage_new cStoreAdvert;
m_pCurrentAdvert->Init();
m_State = STATE_EXPECT_ADVERT_SUB_ELEMENT;
}
else
{
storeUIErrorf("Error parsing [STATE_EXPECT_ADVERT] %s", qName);
}
break;
case STATE_EXPECT_ADVERT_SUB_ELEMENT:
if(0 == stricmp("Title", qName))
{
m_State = STATE_READING_ADVERT_TITLE;
}
else if(0 == stricmp("Text", qName))
{
m_State = STATE_READING_ADVERT_TEXT;
}
else if(0 == stricmp("ImagePath", qName))
{
m_State = STATE_READING_ADVERT_IMAGE_PATH;
}
else if(0 == stricmp("LinkedProductID", qName))
{
m_State = STATE_READING_ADVERT_LINKED_PRODUCT_ID;
}
else
{
storeUIErrorf("Error parsing [STATE_EXPECT_ADVERT_SUB_ELEMENT] %s", qName);
}
break;
default:
storeUIErrorf("Error parsing [STATE_EXPECT_CATEGORY_SUB_ELEMENT] %s", qName);
}
}
void cStoreAdvertData::cStoreAdSaxReader::endElement( const char* /*url*/, const char* /*localName*/, const char* qName )
{
switch( static_cast<int>(m_State) )
{
case(STATE_READING_ADVERT_TITLE):
if (0 == stricmp("Title", qName))
{
m_State = STATE_EXPECT_ADVERT_SUB_ELEMENT;
}
else
{
storeUIErrorf("Error parsing End Element [STATE_READING_ADVERT_TITLE] %s", qName);
}
break;
case(STATE_READING_ADVERT_TEXT):
if (0 == stricmp("Text", qName))
{
m_State = STATE_EXPECT_ADVERT_SUB_ELEMENT;
}
else
{
storeUIErrorf("Error parsing End Element [STATE_READING_ADVERT_TEXT] %s", qName);
}
break;
case(STATE_READING_ADVERT_IMAGE_PATH):
if (0 == stricmp("ImagePath", qName))
{
m_State = STATE_EXPECT_ADVERT_SUB_ELEMENT;
}
else
{
storeUIErrorf("Error parsing End Element [STATE_READING_ADVERT_IMAGE_PATH] %s", qName);
}
break;
case(STATE_READING_ADVERT_LINKED_PRODUCT_ID):
if (0 == stricmp("LinkedProductID", qName))
{
m_State = STATE_EXPECT_ADVERT_SUB_ELEMENT;
}
else
{
storeUIErrorf("Error parsing End Element [STATE_READING_ADVERT_LINKED_PRODUCT_ID] %s", qName);
}
break;
case(STATE_EXPECT_ADVERT_SUB_ELEMENT):
if (0 == stricmp("Advert", qName))
{
storeUIAssert( m_pCurrentAdvert != NULL );
m_pAdvertData->m_pAdvertDataArray.Grow() = m_pCurrentAdvert;
m_pCurrentAdvert = NULL;
m_State = STATE_EXPECT_ADVERT;
}
else
{
storeUIErrorf("Error parsing End Element [STATE_EXPECT_ADVERT_SUB_ELEMENT] %s", qName);
}
break;
case(STATE_EXPECT_ADVERT):
if (0 == stricmp("AdData", qName))
{
m_State = STATE_EXPECT_ROOT;
}
else
{
storeUIErrorf("Error parsing End Element [STATE_EXPECT_ADVERT] %s", qName);
}
break;
}
}
void cStoreAdvertData::cStoreAdSaxReader::attribute( const char* /*tagName*/, const char* attrName, const char* attrVal )
{
switch( static_cast<int>(m_State) )
{
case(STATE_EXPECT_ADVERT_SUB_ELEMENT):
if(0 == stricmp("id", attrName))
{
m_pCurrentAdvert->GetId() = attrVal;
}
break;
case(STATE_READING_ADVERT_LINKED_PRODUCT_ID):
if(0 == stricmp("id", attrName))
{
m_pCurrentAdvert->GetLinkedProductId() = attrVal;
}
break;
}
}
void cStoreAdvertData::cStoreAdSaxReader::characters( const char* ch, const int start, const int length )
{
atString temp;
temp.Set( ch, istrlen(ch) , start, length );
switch( static_cast<int>(m_State) )
{
case(STATE_READING_ADVERT_TITLE):
m_pCurrentAdvert->GetTitle() += temp;
storeUIDebugf3( "Set current advert title to: %s", m_pCurrentAdvert->GetTitle().c_str() );
break;
case(STATE_READING_ADVERT_TEXT):
m_pCurrentAdvert->GetText() += temp;
storeUIDebugf3( "Set current advert text to: %s", m_pCurrentAdvert->GetText().c_str() );
break;
case(STATE_READING_ADVERT_IMAGE_PATH):
m_pCurrentAdvert->GetImagePath() += temp;
storeUIDebugf3( "Set current advert image path to: %s", m_pCurrentAdvert->GetImagePath().c_str() );
break;
}
}
void cStoreAdvertData::cStoreAdSaxReader::ResetCurrentData()
{
if ( m_pCurrentAdvert )
{
m_pCurrentAdvert->Init();
}
}
cStoreAdvertData::cStoreAdvertData() :
m_ParserState( AD_DATA_XML_WAITING ),
m_bInitialised( false ),
m_LocalGamerIndex(-1),
m_bHasValidData( false ),
m_bIsInErrorState( false ),
m_bDataRefreshPending( false ),
m_pLocalFileStream(NULL)
{
}
cStoreAdvertData::~cStoreAdvertData()
{
ResetData();
}
void cStoreAdvertData::Init( int localUserIndex, const char* skuFolder )
{
if ( m_bInitialised )
{
storeUIAssert(false);
return;
}
ResetData();
m_bInitialised = true;
m_bHasValidData = false;
m_bIsInErrorState = false;
m_bDataRefreshPending = false;
m_SkuDirString.Reset();
if ( skuFolder != NULL )
{
m_SkuDirString = skuFolder;
}
m_LocalGamerIndex = localUserIndex;
}
void cStoreAdvertData::Shutdown()
{
if ( !m_bInitialised )
{
return;
}
ResetData();
m_bInitialised = false;
m_bHasValidData = false;
m_bIsInErrorState = false;
m_bDataRefreshPending = false;
m_LocalGamerIndex = -1;
m_ParserState = AD_DATA_XML_WAITING;
}
void cStoreAdvertData::Update()
{
switch( m_ParserState )
{
case(AD_DATA_XML_WAITING):
UpdateParserWaitingState();
break;
case(AD_DATA_XML_STARTUP):
UpdateParserStartupState();
break;
case(AD_DATA_XML_RECEIVING):
UpdateParserReceivingState();
break;
case(AD_DATA_XML_CLEANUP):
UpdateParserCleanupState();
break;
default:
storeUIAssert(false);
}
}
void cStoreAdvertData::UpdateParserWaitingState()
{
if(!RL_IS_VALID_LOCAL_GAMER_INDEX(m_LocalGamerIndex))
{
return;
}
//If we're loading a local file, we don't need credentials
BANK_ONLY(bool bNeedCredentials = !PARAM_adDataLocalFile.Get());
const rlRosCredentials& creds = rlRos::GetCredentials( m_LocalGamerIndex );
if(!creds.IsValid() BANK_ONLY(&& bNeedCredentials) )
{
return;
}
if (m_bDataRefreshPending)
{
ResetData();
m_bDataRefreshPending = false;
m_bIsInErrorState = false;
m_bHasValidData = false;
m_ParserState = AD_DATA_XML_STARTUP;
}
}
void cStoreAdvertData::UpdateParserStartupState()
{
if(!RL_IS_VALID_LOCAL_GAMER_INDEX(m_LocalGamerIndex))
{
//No valid gamer index, flee.
storeUIErrorf("No local gamer index for download of Commerce data xml");
m_ParserState = AD_DATA_XML_CLEANUP;
return;
}
m_GrowBuffer.Init(NULL, datGrowBuffer::NULL_TERMINATE);
m_GrowBuffer.Preallocate(1024);
atString cloudFilePath("store");
if ( m_SkuDirString.GetLength() != 0 )
{
cloudFilePath += "/";
cloudFilePath += m_SkuDirString;
}
cloudFilePath += "/advertdata";
cloudFilePath += "/adData.xml";
const char* fileName = NULL;
if(PARAM_adDataLocalFile.Get(fileName) && fileName && strlen(fileName) > 0)
{
storeUIDebugf1("Loading catalogue file from local source: %s", fileName);
m_pLocalFileStream = ASSET.Open(fileName, "");
if (storeUIVerifyf(m_pLocalFileStream, "Failed to open local catalogue file %s", fileName))
{
m_AdDataXMLFetchStatus.Reset();
m_AdDataXMLFetchStatus.SetPending();
m_saxReader.Start(this);
m_ParserState = AD_DATA_XML_RECEIVING;
}
else
{
m_AdDataXMLFetchStatus.Reset();
m_AdDataXMLFetchStatus.SetFailed();
m_ParserState = AD_DATA_XML_CLEANUP;
}
}
else if ( rlCloud::GetTitleFile( cloudFilePath,
RLROS_SECURITY_DEFAULT,
0, //ifModifiedSincePosixTime
NET_HTTP_OPTIONS_NONE,
m_GrowBuffer.GetFiDevice(),
m_GrowBuffer.GetFiHandle(),
NULL, //rlCloudFileInfo
NULL, //allocator
&m_AdDataXMLFetchStatus ) )
{
m_saxReader.Start(this);
m_ParserState = AD_DATA_XML_RECEIVING;
}
else
{
storeUIErrorf("Failed to start download of advert data data file.");
m_ParserState = AD_DATA_XML_CLEANUP;
m_bIsInErrorState = true;
}
}
void cStoreAdvertData::UpdateParserReceivingState()
{
UpdateParserLocalFileState();
if ( m_saxReader.Failed() )
{
//Something has gone wrong in the sax reader, probably an interuption or error code
m_bIsInErrorState = true;
m_ParserState = AD_DATA_XML_CLEANUP;
}
else if ( (m_AdDataXMLFetchStatus.Succeeded() || m_AdDataXMLFetchStatus.Pending()) )
{
if ( m_GrowBuffer.Length() != 0 )
{
const char* response = (const char*) m_GrowBuffer.GetBuffer();
const unsigned responseLen = m_GrowBuffer.Length();
if(response && responseLen)
{
storeUIDisplayf("Processing advert data of length %d: %s\n",responseLen,response);
const unsigned numConsumed = m_saxReader.Parse(response, 0, responseLen);
m_GrowBuffer.Remove(0, numConsumed);
}
}
}
else if ( m_AdDataXMLFetchStatus.Failed() )
{
storeUIErrorf("Ad data XML file fetch from cloud failed. Code: %d", m_AdDataXMLFetchStatus.GetResultCode());
//Get cunning: if we have specified a SKU specific file, try the base version.
if ( m_SkuDirString.GetLength() != 0 )
{
m_SkuDirString.Reset();
m_bDataRefreshPending = true;
}
else
{
m_bIsInErrorState = true;
}
m_ParserState = AD_DATA_XML_CLEANUP;
}
else if ( m_AdDataXMLFetchStatus.Canceled() )
{
m_bIsInErrorState = true;
}
if ( m_AdDataXMLFetchStatus.Succeeded() && m_GrowBuffer.Length() == 0 )
{
storeUIDebugf3("Store advert Data retrieved and parsed.");
m_bHasValidData = true;
m_ParserState = AD_DATA_XML_CLEANUP;
}
}
void cStoreAdvertData::UpdateParserCleanupState()
{
if ( !m_saxReader.Failed() )
{
m_saxReader.End();
}
m_GrowBuffer.Clear();
m_ParserState = AD_DATA_XML_WAITING;
}
void cStoreAdvertData::UpdateParserLocalFileState()
{
if(PARAM_adDataLocalFile.Get() && m_AdDataXMLFetchStatus.Pending())
{
if (m_pLocalFileStream)
{
//Read it in as chunks, just like the cloud file would.
static const int READ_LEN = 512;
char bounceBuffer[READ_LEN];
int numRead = m_pLocalFileStream->Read(bounceBuffer, READ_LEN);
if (numRead > 0)
{
storeUIDebugf3("%s", bounceBuffer);
m_GrowBuffer.Append(bounceBuffer, numRead);
}
//If we didn't read anything, or we didn't read as much as we aske for, it means we're done.
if (numRead == 0 || numRead < READ_LEN || m_AdDataXMLFetchStatus.Canceled())
{
storeUIDebugf3("Finished parsing local file %s", m_pLocalFileStream->GetName());
m_pLocalFileStream->Close();
m_pLocalFileStream = NULL;
if (m_AdDataXMLFetchStatus.Pending())
{
m_AdDataXMLFetchStatus.SetSucceeded();
}
}
}
}
}
bool cStoreAdvertData::StartDataFetch()
{
if ( m_ParserState == AD_DATA_XML_WAITING )
{
m_bDataRefreshPending = true;
return true;
}
else
{
storeUIDisplayf("Tried to call StartDataFetch when m_ParserState was not COMMERCE_XML_WAITING");
return false;
}
}
void cStoreAdvertData::AbortDataFetch()
{
if ( m_AdDataXMLFetchStatus.GetStatus() == netStatus::NET_STATUS_PENDING )
{
rlCloud::Cancel( &m_AdDataXMLFetchStatus );
m_AdDataXMLFetchStatus.SetCanceled();
}
}
const bool cStoreAdvertData::IsInDataFetchState() const
{
return ( m_AdDataXMLFetchStatus.GetStatus() == netStatus::NET_STATUS_PENDING );
}
void cStoreAdvertData::ResetData()
{
//Delete the actual data items
for ( int i = 0; i < m_pAdvertDataArray.GetCount(); i++ )
{
delete m_pAdvertDataArray[ i ];
}
//Clear up the array
m_pAdvertDataArray.Reset();
}
const cStoreAdvert* cStoreAdvertData::GetAdvertRecord( int adIndex ) const
{
if ( adIndex < 0 || adIndex > GetNumAdvertDataRecords() )
{
storeUIAssertf( false, "Invalid index to GetAdvertRecord" );
return NULL;
}
return m_pAdvertDataArray[ adIndex ];
}
int cStoreAdvertData::GetNumAdvertDataRecords() const
{
//storeUIDebugf3("GetNumAdvertDataRecords returning %d",m_pAdvertDataArray.GetCount());
return m_pAdvertDataArray.GetCount();
}