the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 3140 lines 103 kB view raw
1#include "stdafx.h" 2#include "UIController.h" 3#include "UI.h" 4#include "UIScene.h" 5#include "..\..\..\Minecraft.World\StringHelpers.h" 6#include "..\..\LocalPlayer.h" 7#include "..\..\DLCTexturePack.h" 8#include "..\..\TexturePackRepository.h" 9#include "..\..\Minecraft.h" 10#include "..\..\..\Minecraft.World\net.minecraft.world.entity.boss.enderdragon.h" 11#include "..\..\EnderDragonRenderer.h" 12#include "..\..\MultiPlayerLocalPlayer.h" 13#include "UIFontData.h" 14#ifdef __PSVITA__ 15#include <message_dialog.h> 16#endif 17 18// 4J Stu - Enable this to override the Iggy Allocator 19//#define ENABLE_IGGY_ALLOCATOR 20//#define EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR 21 22//#define ENABLE_IGGY_EXPLORER 23#ifdef ENABLE_IGGY_EXPLORER 24#include "Windows64\Iggy\include\iggyexpruntime.h" 25#endif 26 27//#define ENABLE_IGGY_PERFMON 28#ifdef ENABLE_IGGY_PERFMON 29 30#define PM_ORIGIN_X 24 31#define PM_ORIGIN_Y 34 32 33#ifdef __ORBIS__ 34#include "Orbis\Iggy\include\iggyperfmon.h" 35#include "Orbis\Iggy\include\iggyperfmon_orbis.h" 36#elif defined _DURANGO 37#include "Durango\Iggy\include\iggyperfmon.h" 38#elif defined __PS3__ 39#include "PS3\Iggy\include\iggyperfmon.h" 40#include "PS3\Iggy\include\iggyperfmon_ps3.h" 41#elif defined __PSVITA__ 42#include "PSVita\Iggy\include\iggyperfmon.h" 43#include "PSVita\Iggy\include\iggyperfmon_psp2.h" 44#elif defined __WINDOWS64 45#include "Windows64\Iggy\include\iggyperfmon.h" 46#endif 47 48#endif 49 50CRITICAL_SECTION UIController::ms_reloadSkinCS; 51bool UIController::ms_bReloadSkinCSInitialised = false; 52 53DWORD UIController::m_dwTrialTimerLimitSecs=DYNAMIC_CONFIG_DEFAULT_TRIAL_TIME; 54 55static void RADLINK WarningCallback(void *user_callback_data, Iggy *player, IggyResult code, const char *message) 56{ 57 //enum IggyResult{ IGGY_RESULT_SUCCESS = 0, IGGY_RESULT_Warning_None = 0, 58 // IGGY_RESULT_Warning_Misc = 100, IGGY_RESULT_Warning_GDraw = 101, 59 // IGGY_RESULT_Warning_ProgramFlow = 102, 60 // IGGY_RESULT_Warning_Actionscript = 103, 61 // IGGY_RESULT_Warning_Graphics = 104, IGGY_RESULT_Warning_Font = 105, 62 // IGGY_RESULT_Warning_Timeline = 106, IGGY_RESULT_Warning_Library = 107, 63 // IGGY_RESULT_Warning_CannotSustainFrameRate = 201, 64 // IGGY_RESULT_Warning_ThrewException = 202, 65 // IGGY_RESULT_Error_Threshhold = 400, IGGY_RESULT_Error_Misc = 400, 66 // IGGY_RESULT_Error_GDraw = 401, IGGY_RESULT_Error_ProgramFlow = 402, 67 // IGGY_RESULT_Error_Actionscript = 403, IGGY_RESULT_Error_Graphics = 404, 68 // IGGY_RESULT_Error_Font = 405, IGGY_RESULT_Error_Create = 406, 69 // IGGY_RESULT_Error_Library = 407, IGGY_RESULT_Error_ValuePath = 408, 70 // IGGY_RESULT_Error_Audio = 409, IGGY_RESULT_Error_Internal = 499, 71 // IGGY_RESULT_Error_InvalidIggy = 501, 72 // IGGY_RESULT_Error_InvalidArgument = 502, 73 // IGGY_RESULT_Error_InvalidEntity = 503, 74 // IGGY_RESULT_Error_UndefinedEntity = 504, 75 // IGGY_RESULT_Error_OutOfMemory = 1001,}; 76 77 switch(code) 78 { 79 case IGGY_RESULT_Warning_CannotSustainFrameRate: 80 // Ignore warning 81 break; 82 default: 83 /* Normally, we'd want to issue this warning to some kind of 84 logging system or error reporting system, but since this is a 85 tutorial app, we just use Win32's default error stream. Since 86 ActionScript 3 exceptions are routed through this warning 87 callback, it's definitely a good idea to make sure these 88 warnings get printed somewhere that's easy for you to read and 89 use for debugging, otherwise debugging errors in the 90 ActionScript 3 code in your Flash content will be very 91 difficult! */ 92 app.DebugPrintf(app.USER_SR, message); 93 app.DebugPrintf(app.USER_SR, "\n"); 94 break; 95 }; 96} 97 98 99/* Flash provides a way for ActionScript 3 code to print debug output 100using a function called "trace". It's very useful for debugging 101Flash programs, so ideally, when using Iggy, we'd like to see any 102trace output alongside our own debugging output. To facilitate 103this, Iggy allows us to install a callback that will be called 104any time ActionScript code calls trace. */ 105static void RADLINK TraceCallback(void *user_callback_data, Iggy *player, char const *utf8_string, S32 length_in_bytes) 106{ 107 app.DebugPrintf(app.USER_UI, (char *)utf8_string); 108} 109 110#ifdef ENABLE_IGGY_PERFMON 111static void *RADLINK perf_malloc(void *handle, U32 size) 112{ 113 return malloc(size); 114} 115 116static void RADLINK perf_free(void *handle, void *ptr) 117{ 118 return free(ptr); 119} 120#endif 121 122#ifdef EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR 123extern "C" void *__real_malloc(size_t t); 124extern "C" void __real_free(void *t); 125#endif 126 127__int64 UIController::iggyAllocCount = 0; 128static unordered_map<void *,size_t> allocations; 129static void * RADLINK AllocateFunction ( void * alloc_callback_user_data , size_t size_requested , size_t * size_returned ) 130{ 131 UIController *controller = (UIController *)alloc_callback_user_data; 132 EnterCriticalSection(&controller->m_Allocatorlock); 133#ifdef EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR 134 void *alloc = __real_malloc(size_requested); 135#else 136 void *alloc = malloc(size_requested); 137#endif 138 *size_returned = size_requested; 139 UIController::iggyAllocCount += size_requested; 140 allocations[alloc] = size_requested; 141 app.DebugPrintf(app.USER_SR, "Allocating %d, new total: %d\n", size_requested, UIController::iggyAllocCount); 142 LeaveCriticalSection(&controller->m_Allocatorlock); 143 return alloc; 144} 145 146static void RADLINK DeallocateFunction ( void * alloc_callback_user_data , void * ptr ) 147{ 148 UIController *controller = (UIController *)alloc_callback_user_data; 149 EnterCriticalSection(&controller->m_Allocatorlock); 150 size_t size = allocations[ptr]; 151 UIController::iggyAllocCount -= size; 152 allocations.erase(ptr); 153 app.DebugPrintf(app.USER_SR, "Freeing %d, new total %d\n", size, UIController::iggyAllocCount); 154#ifdef EXCLUDE_IGGY_ALLOCATIONS_FROM_HEAP_INSPECTOR 155 __real_free(ptr); 156#else 157 free(ptr); 158#endif 159 LeaveCriticalSection(&controller->m_Allocatorlock); 160} 161 162UIController::UIController() 163{ 164 m_uiDebugConsole = NULL; 165 m_reloadSkinThread = NULL; 166 167 m_navigateToHomeOnReload = false; 168 169 m_bCleanupOnReload = false; 170 m_mcTTFFont = NULL; 171 m_moj7 = NULL; 172 m_moj11 = NULL; 173 174 // 4J-JEV: It's important that these remain the same, unless updateCurrentLanguage is going to be called. 175 m_eCurrentFont = m_eTargetFont = eFont_NotLoaded; 176 177#ifdef ENABLE_IGGY_ALLOCATOR 178 InitializeCriticalSection(&m_Allocatorlock); 179#endif 180 181 // 4J Stu - This is a bit of a hack until we change the Minecraft initialisation to store the proper screen size for other platforms 182#if defined _WINDOWS64 || defined _DURANGO || defined __ORBIS__ 183 m_fScreenWidth = 1920.0f; 184 m_fScreenHeight = 1080.0f; 185 m_bScreenWidthSetup = false; 186#else 187 m_fScreenWidth = 1280.0f; 188 m_fScreenHeight = 720.0f; 189 m_bScreenWidthSetup = false; 190#endif 191 192 for(unsigned int i = 0; i < eLibrary_Count; ++i) 193 { 194 m_iggyLibraries[i] = IGGY_INVALID_LIBRARY; 195 } 196 197 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) 198 { 199 m_bMenuDisplayed[i] = false; 200 m_iCountDown[i]=0; 201 m_bMenuToBeClosed[i]=false; 202 203 for(unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) 204 { 205 m_actionRepeatTimer[i][key] = 0; 206 } 207 } 208 209 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 210 { 211 m_bCloseAllScenes[i] = false; 212 } 213 214 m_iPressStartQuadrantsMask = 0; 215 216 m_currentRenderViewport = C4JRender::VIEWPORT_TYPE_FULLSCREEN; 217 m_bCustomRenderPosition = false; 218 m_winUserIndex = 0; 219 m_accumulatedTicks = 0; 220 m_lastUiSfx = 0; 221 222 InitializeCriticalSection(&m_navigationLock); 223 InitializeCriticalSection(&m_registeredCallbackScenesCS); 224 //m_bSysUIShowing=false; 225 m_bSystemUIShowing=false; 226#ifdef __PSVITA__ 227 m_bTouchscreenPressed=false; 228#endif 229 230 if(!ms_bReloadSkinCSInitialised) 231 { 232 // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded 233 InitializeCriticalSection(&ms_reloadSkinCS); 234 ms_bReloadSkinCSInitialised = true; 235 } 236} 237 238void UIController::SetSysUIShowing(bool bVal) 239{ 240 if(bVal) app.DebugPrintf("System UI showing\n"); 241 else app.DebugPrintf("System UI stopped showing\n"); 242 m_bSystemUIShowing=bVal; 243} 244 245void UIController::SetSystemUIShowing(LPVOID lpParam,bool bVal) 246{ 247 UIController *pClass=(UIController *)lpParam; 248 pClass->SetSysUIShowing(bVal); 249} 250 251// SETUP 252void UIController::preInit(S32 width, S32 height) 253{ 254 m_fScreenWidth = width; 255 m_fScreenHeight = height; 256 m_bScreenWidthSetup = true; 257 258#ifdef ENABLE_IGGY_ALLOCATOR 259 IggyAllocator allocator; 260 allocator.user_callback_data = this; 261 allocator.mem_alloc = &AllocateFunction; 262 allocator.mem_free = &DeallocateFunction; 263 IggyInit(&allocator); 264#else 265 IggyInit(0); 266#endif 267 268 IggySetWarningCallback(WarningCallback, 0); 269 IggySetTraceCallbackUTF8(TraceCallback, 0); 270 271 setFontCachingCalculationBuffer(-1); 272} 273 274void UIController::postInit() 275{ 276 // set up a custom rendering callback 277 IggySetCustomDrawCallback(&UIController::CustomDrawCallback, this); 278 IggySetAS3ExternalFunctionCallbackUTF16 ( &UIController::ExternalFunctionCallback, this ); 279 IggySetTextureSubstitutionCallbacks ( &UIController::TextureSubstitutionCreateCallback , &UIController::TextureSubstitutionDestroyCallback, this ); 280 281 SetupFont(); 282 // 283 loadSkins(); 284 285 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 286 { 287 m_groups[i] = new UIGroup((EUIGroup)i,i-1); 288 } 289 290 291#ifdef ENABLE_IGGY_EXPLORER 292 iggy_explorer = IggyExpCreate("127.0.0.1", 9190, malloc(IGGYEXP_MIN_STORAGE), IGGYEXP_MIN_STORAGE); 293 if ( iggy_explorer == NULL ) 294 { 295 // not normally an error, just an error for this demo! 296 app.DebugPrintf( "Couldn't connect to Iggy Explorer, did you run it first?" ); 297 } 298 else 299 { 300 IggyUseExplorer( m_groups[1]->getHUD()->getMovie(), iggy_explorer); 301 } 302#endif 303 304#ifdef ENABLE_IGGY_PERFMON 305 m_iggyPerfmonEnabled = false; 306 iggy_perfmon = IggyPerfmonCreate(perf_malloc, perf_free, NULL); 307 IggyInstallPerfmon(iggy_perfmon); 308#endif 309 310 NavigateToScene(0, eUIScene_Intro); 311} 312 313 314UIController::EFont UIController::getFontForLanguage(int language) 315 { 316 switch(language) 317 { 318 case XC_LANGUAGE_JAPANESE: return eFont_Japanese; 319#ifdef _DURANGO 320 case XC_LANGUAGE_SCHINESE: return eFont_SimpChinese; 321#endif 322 case XC_LANGUAGE_TCHINESE: return eFont_TradChinese; 323 case XC_LANGUAGE_KOREAN: return eFont_Korean; 324 default: return eFont_Bitmap; 325 } 326} 327 328UITTFFont *UIController::createFont(EFont fontLanguage) 329 { 330 switch(fontLanguage) 331 { 332#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 333 case eFont_Japanese: return new UITTFFont("Mojangles_TTF_jaJP", "Common/Media/font/JPN/DF-DotDotGothic16.ttf", 0x203B); // JPN 334 // case eFont_SimpChinese: Simplified Chinese is unsupported. 335 case eFont_TradChinese: return new UITTFFont("Mojangles_TTF_cnTD", "Common/Media/font/CHT/DFTT_R5.TTC", 0x203B); // CHT 336 case eFont_Korean: return new UITTFFont("Mojangles_TTF_koKR", "Common/Media/font/KOR/candadite2.ttf", 0x203B); // KOR 337#else 338 case eFont_Japanese: return new UITTFFont("Mojangles_TTF_jaJP", "Common/Media/font/JPN/DFGMaruGothic-Md.ttf", 0x2022); // JPN 339#ifdef _DURANGO 340 case eFont_SimpChinese: return new UITTFFont("Mojangled_TTF_cnCN", "Common/Media/font/CHS/MSYH.ttf", 0x2022); // CHS 341#endif 342 case eFont_TradChinese: return new UITTFFont("Mojangles_TTF_cnTD", "Common/Media/font/CHT/DFHeiMedium-B5.ttf", 0x2022); // CHT 343 case eFont_Korean: return new UITTFFont("Mojangles_TTF_koKR", "Common/Media/font/KOR/BOKMSD.ttf", 0x2022); // KOR 344#endif 345 // 4J-JEV, Cyrillic characters have been added to this font now, (4/July/14) 346 // XC_LANGUAGE_RUSSIAN and XC_LANGUAGE_GREEK: 347 default: return NULL; 348 } 349} 350 351void UIController::SetupFont() 352{ 353 // 4J-JEV: Language hasn't changed or is already changing. 354 if ( (m_eCurrentFont != m_eTargetFont) || !UIString::setCurrentLanguage() ) return; 355 356 DWORD nextLanguage = UIString::getCurrentLanguage(); 357 m_eTargetFont = getFontForLanguage(nextLanguage); 358 359 // flag a language change to reload the string tables in the DLC 360 app.m_dlcManager.LanguageChanged(); 361 362 app.loadStringTable(); // Switch to use new string table, 363 364 if (m_eTargetFont == m_eCurrentFont) 365 { 366 // 4J-JEV: If we're ingame, reload the font to update all the text. 367 if (app.GetGameStarted()) app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ReloadFont); 368 return; 369 } 370 371 if (m_eCurrentFont != eFont_NotLoaded) app.DebugPrintf("[UIController] Font switch required for language transition to %i.\n", nextLanguage); 372 else app.DebugPrintf("[UIController] Initialising font for language %i.\n", nextLanguage); 373 374 if (m_mcTTFFont != NULL) 375 { 376 delete m_mcTTFFont; 377 m_mcTTFFont = NULL; 378 } 379 380 if(m_eTargetFont == eFont_Bitmap) 381 { 382 // these may have been set up by a previous language being chosen 383 if (m_moj7 == NULL) m_moj7 = new UIBitmapFont(SFontData::Mojangles_7); 384 if (m_moj11 == NULL) m_moj11 = new UIBitmapFont(SFontData::Mojangles_11); 385 386 // 4J-JEV: Ensure we redirect to them correctly, even if the objects were previously initialised. 387 m_moj7->registerFont(); 388 m_moj11->registerFont(); 389 } 390 else if (m_eTargetFont != eFont_NotLoaded) 391 { 392 m_mcTTFFont = createFont(m_eTargetFont); 393 394 app.DebugPrintf("[Iggy] Set font indirect to '%hs'.\n", m_mcTTFFont->getFontName().c_str()); 395 IggyFontSetIndirectUTF8( "Mojangles7", -1, IGGY_FONTFLAG_all, m_mcTTFFont->getFontName().c_str(), -1, IGGY_FONTFLAG_none ); 396 IggyFontSetIndirectUTF8( "Mojangles11", -1, IGGY_FONTFLAG_all, m_mcTTFFont->getFontName().c_str(), -1, IGGY_FONTFLAG_none ); 397 } 398 else 399 { 400 assert(false); 401 } 402 403 // Reload ui to set new font. 404 if (m_eCurrentFont != eFont_NotLoaded) 405 { 406 app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ReloadFont); 407 } 408 else 409 { 410 updateCurrentFont(); 411 } 412} 413 414bool UIController::PendingFontChange() 415{ 416 return getFontForLanguage( XGetLanguage() ) != m_eCurrentFont; 417} 418 419void UIController::setCleanupOnReload() 420{ 421 m_bCleanupOnReload = true; 422} 423 424void UIController::updateCurrentFont() 425{ 426 m_eCurrentFont = m_eTargetFont; 427} 428 429bool UIController::UsingBitmapFont() 430{ 431 return m_eCurrentFont == eFont_Bitmap; 432} 433 434// TICKING 435void UIController::tick() 436{ 437 SetupFont(); // If necessary, change font. 438 439 if ( (m_navigateToHomeOnReload || m_bCleanupOnReload) && !ui.IsReloadingSkin() ) 440 { 441 ui.CleanUpSkinReload(); 442 443 if (m_navigateToHomeOnReload || !g_NetworkManager.IsInSession()) 444 { 445 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MainMenu); 446 } 447 else 448 { 449 ui.CloseAllPlayersScenes(); 450 } 451 452 updateCurrentFont(); 453 454 m_navigateToHomeOnReload = false; 455 m_bCleanupOnReload = false; 456 } 457 458 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 459 { 460 if(m_bCloseAllScenes[i]) 461 { 462 m_groups[i]->closeAllScenes(); 463 m_groups[i]->getTooltips()->SetTooltips(-1); 464 m_bCloseAllScenes[i] = false; 465 } 466 } 467 468 if(m_accumulatedTicks == 0) tickInput(); 469 m_accumulatedTicks = 0; 470 471 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 472 { 473 m_groups[i]->tick(); 474 475 // TODO: May wish to skip ticking other groups here 476 } 477 478 // Clear out the cached movie file data 479 __int64 currentTime = System::currentTimeMillis(); 480 for(AUTO_VAR(it, m_cachedMovieData.begin()); it != m_cachedMovieData.end();) 481 { 482 if(it->second.m_expiry < currentTime) 483 { 484 delete [] it->second.m_ba.data; 485 it = m_cachedMovieData.erase(it); 486 } 487 else 488 { 489 ++it; 490 } 491 } 492} 493 494void UIController::loadSkins() 495{ 496 wstring platformSkinPath = L""; 497 498#ifdef __PS3__ 499 platformSkinPath = L"skinPS3.swf"; 500#elif defined __PSVITA__ 501 platformSkinPath = L"skinVita.swf"; 502#elif defined _WINDOWS64 503 if(m_fScreenHeight>720.0f) 504 { 505 platformSkinPath = L"skinHDWin.swf"; 506 } 507 else 508 { 509 platformSkinPath = L"skinWin.swf"; 510 } 511#elif defined _DURANGO 512 if(m_fScreenHeight>720.0f) 513 { 514 platformSkinPath = L"skinHDDurango.swf"; 515 } 516 else 517 { 518 platformSkinPath = L"skinDurango.swf"; 519 } 520#elif defined __ORBIS__ 521 if(m_fScreenHeight>720.0f) 522 { 523 platformSkinPath = L"skinHDOrbis.swf"; 524 } 525 else 526 { 527 platformSkinPath = L"skinOrbis.swf"; 528 } 529 530#endif 531 // Every platform has one of these, so nothing shared 532 if(m_fScreenHeight>720.0f) 533 { 534 m_iggyLibraries[eLibrary_Platform] = loadSkin(platformSkinPath, L"platformskinHD.swf"); 535 } 536 else 537 { 538 m_iggyLibraries[eLibrary_Platform] = loadSkin(platformSkinPath, L"platformskin.swf"); 539 } 540 541#if defined(__PS3__) || defined(__PSVITA__) 542 m_iggyLibraries[eLibrary_GraphicsDefault] = loadSkin(L"skinGraphics.swf", L"skinGraphics.swf"); 543 m_iggyLibraries[eLibrary_GraphicsHUD] = loadSkin(L"skinGraphicsHud.swf", L"skinGraphicsHud.swf"); 544 m_iggyLibraries[eLibrary_GraphicsInGame] = loadSkin(L"skinGraphicsInGame.swf", L"skinGraphicsInGame.swf"); 545 m_iggyLibraries[eLibrary_GraphicsTooltips] = loadSkin(L"skinGraphicsTooltips.swf", L"skinGraphicsTooltips.swf"); 546 m_iggyLibraries[eLibrary_GraphicsLabels] = loadSkin(L"skinGraphicsLabels.swf", L"skinGraphicsLabels.swf"); 547 m_iggyLibraries[eLibrary_Labels] = loadSkin(L"skinLabels.swf", L"skinLabels.swf"); 548 m_iggyLibraries[eLibrary_InGame] = loadSkin(L"skinInGame.swf", L"skinInGame.swf"); 549 m_iggyLibraries[eLibrary_HUD] = loadSkin(L"skinHud.swf", L"skinHud.swf"); 550 m_iggyLibraries[eLibrary_Tooltips] = loadSkin(L"skinTooltips.swf", L"skinTooltips.swf"); 551 m_iggyLibraries[eLibrary_Default] = loadSkin(L"skin.swf", L"skin.swf"); 552#endif 553 554#if ( defined(_WINDOWS64) || defined(_DURANGO) || defined(__ORBIS__) ) 555 556#if defined(_WINDOWS64) 557 // 4J Stu - Load the 720/480 skins so that we have something to fallback on during development 558#ifndef _FINAL_BUILD 559 m_iggyLibraries[eLibraryFallback_GraphicsDefault] = loadSkin(L"skinGraphics.swf", L"skinGraphics.swf"); 560 m_iggyLibraries[eLibraryFallback_GraphicsHUD] = loadSkin(L"skinGraphicsHud.swf", L"skinGraphicsHud.swf"); 561 m_iggyLibraries[eLibraryFallback_GraphicsInGame] = loadSkin(L"skinGraphicsInGame.swf", L"skinGraphicsInGame.swf"); 562 m_iggyLibraries[eLibraryFallback_GraphicsTooltips] = loadSkin(L"skinGraphicsTooltips.swf", L"skinGraphicsTooltips.swf"); 563 m_iggyLibraries[eLibraryFallback_GraphicsLabels] = loadSkin(L"skinGraphicsLabels.swf", L"skinGraphicsLabels.swf"); 564 m_iggyLibraries[eLibraryFallback_Labels] = loadSkin(L"skinLabels.swf", L"skinLabels.swf"); 565 m_iggyLibraries[eLibraryFallback_InGame] = loadSkin(L"skinInGame.swf", L"skinInGame.swf"); 566 m_iggyLibraries[eLibraryFallback_HUD] = loadSkin(L"skinHud.swf", L"skinHud.swf"); 567 m_iggyLibraries[eLibraryFallback_Tooltips] = loadSkin(L"skinTooltips.swf", L"skinTooltips.swf"); 568 m_iggyLibraries[eLibraryFallback_Default] = loadSkin(L"skin.swf", L"skin.swf"); 569#endif 570#endif 571 572 m_iggyLibraries[eLibrary_GraphicsDefault] = loadSkin(L"skinHDGraphics.swf", L"skinHDGraphics.swf"); 573 m_iggyLibraries[eLibrary_GraphicsHUD] = loadSkin(L"skinHDGraphicsHud.swf", L"skinHDGraphicsHud.swf"); 574 m_iggyLibraries[eLibrary_GraphicsInGame] = loadSkin(L"skinHDGraphicsInGame.swf", L"skinHDGraphicsInGame.swf"); 575 m_iggyLibraries[eLibrary_GraphicsTooltips] = loadSkin(L"skinHDGraphicsTooltips.swf", L"skinHDGraphicsTooltips.swf"); 576 m_iggyLibraries[eLibrary_GraphicsLabels] = loadSkin(L"skinHDGraphicsLabels.swf", L"skinHDGraphicsLabels.swf"); 577 m_iggyLibraries[eLibrary_Labels] = loadSkin(L"skinHDLabels.swf", L"skinHDLabels.swf"); 578 m_iggyLibraries[eLibrary_InGame] = loadSkin(L"skinHDInGame.swf", L"skinHDInGame.swf"); 579 m_iggyLibraries[eLibrary_HUD] = loadSkin(L"skinHDHud.swf", L"skinHDHud.swf"); 580 m_iggyLibraries[eLibrary_Tooltips] = loadSkin(L"skinHDTooltips.swf", L"skinHDTooltips.swf"); 581 m_iggyLibraries[eLibrary_Default] = loadSkin(L"skinHD.swf", L"skinHD.swf"); 582#endif // HD platforms 583} 584 585IggyLibrary UIController::loadSkin(const wstring &skinPath, const wstring &skinName) 586{ 587 IggyLibrary lib = IGGY_INVALID_LIBRARY; 588 // 4J Stu - We need to load the platformskin before the normal skin, as the normal skin requires some elements from the platform skin 589 if(!skinPath.empty() && app.hasArchiveFile(skinPath)) 590 { 591 byteArray baFile = app.getArchiveFile(skinPath); 592 lib = IggyLibraryCreateFromMemoryUTF16( (IggyUTF16 *)skinName.c_str() , (void *)baFile.data, baFile.length, NULL ); 593 594 delete[] baFile.data; 595#ifdef _DEBUG 596 IggyMemoryUseInfo memoryInfo; 597 rrbool res; 598 int iteration = 0; 599 __int64 totalStatic = 0; 600 while(res = IggyDebugGetMemoryUseInfo ( NULL , 601 lib , 602 "" , 603 0 , 604 iteration , 605 &memoryInfo )) 606 { 607 totalStatic += memoryInfo.static_allocation_bytes; 608 app.DebugPrintf(app.USER_SR, "%ls - %.*s, static: %dB, dynamic: %dB\n", skinPath.c_str(), memoryInfo.subcategory_stringlen, memoryInfo.subcategory, memoryInfo.static_allocation_bytes, memoryInfo.dynamic_allocation_bytes); 609 ++iteration; 610 } 611 612 app.DebugPrintf(app.USER_SR, "%ls - Total static: %dB (%dKB)\n", skinPath.c_str(), totalStatic, totalStatic/1024); 613#endif 614 } 615 return lib; 616} 617 618void UIController::ReloadSkin() 619{ 620 // Destroy all scene swf 621 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 622 { 623 //m_bCloseAllScenes[i] = true; 624 m_groups[i]->DestroyAll(); 625 } 626 627 // Unload the current libraries 628 // Some libraries reference others, so we destroy in reverse order 629 for(int i = eLibrary_Count - 1; i >= 0; --i) 630 { 631 if(m_iggyLibraries[i] != IGGY_INVALID_LIBRARY) IggyLibraryDestroy(m_iggyLibraries[i]); 632 m_iggyLibraries[i] = IGGY_INVALID_LIBRARY; 633 } 634 635#ifdef _WINDOWS64 636 // 4J Stu - Don't load on a thread on windows. I haven't investigated this in detail, so a quick fix 637 reloadSkinThreadProc(this); 638#else 639 640 m_reloadSkinThread = new C4JThread(reloadSkinThreadProc, (void*)this, "Reload skin thread"); 641 m_reloadSkinThread->SetProcessor(CPU_CORE_UI_SCENE); 642 643 // Navigate to the timer scene so that we can display something while the loading is happening 644 ui.NavigateToScene(0,eUIScene_Timer,(void *)1,eUILayer_Tooltips,eUIGroup_Fullscreen); 645 //m_reloadSkinThread->Run(); 646 647 //// Load new skin 648 //loadSkins(); 649 650 //// Reload all scene swf 651 //for(int i = eUIGroup_Player1; i <= eUIGroup_Player4; ++i) 652 //{ 653 // m_groups[i]->ReloadAll(); 654 //} 655 656 //// Always reload the fullscreen group 657 //m_groups[eUIGroup_Fullscreen]->ReloadAll(); 658#endif 659} 660 661void UIController::StartReloadSkinThread() 662{ 663 if(m_reloadSkinThread) m_reloadSkinThread->Run(); 664} 665 666int UIController::reloadSkinThreadProc(void* lpParam) 667{ 668 EnterCriticalSection(&ms_reloadSkinCS); // MGH - added to prevent crash loading Iggy movies while the skins were being reloaded 669 UIController *controller = (UIController *)lpParam; 670 // Load new skin 671 controller->loadSkins(); 672 673 // Reload all scene swf 674 for(int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) 675 { 676 controller->m_groups[i]->ReloadAll(); 677 } 678 679 // Always reload the fullscreen group 680 controller->m_groups[eUIGroup_Fullscreen]->ReloadAll(); 681 682 // 4J Stu - Don't do this on windows, as we never navigated forwards to start with 683#ifndef _WINDOW64 684 controller->NavigateBack(0, false, eUIScene_COUNT, eUILayer_Tooltips); 685#endif 686 LeaveCriticalSection(&ms_reloadSkinCS); 687 688 return 0; 689} 690 691bool UIController::IsReloadingSkin() 692{ 693 return m_reloadSkinThread && (!m_reloadSkinThread->hasStarted() || m_reloadSkinThread->isRunning()); 694} 695 696bool UIController::IsExpectingOrReloadingSkin() 697{ 698 return Minecraft::GetInstance()->skins->getSelected()->isLoadingData() || Minecraft::GetInstance()->skins->needsUIUpdate() || IsReloadingSkin() || PendingFontChange(); 699} 700 701void UIController::CleanUpSkinReload() 702{ 703 delete m_reloadSkinThread; 704 m_reloadSkinThread = NULL; 705 706 if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) 707 { 708 if(!Minecraft::GetInstance()->skins->getSelected()->hasAudio()) 709 { 710#ifdef _DURANGO 711 DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK"); 712#else 713 DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); 714#endif 715 } 716 } 717 718 for(AUTO_VAR(it,m_queuedMessageBoxData.begin()); it != m_queuedMessageBoxData.end(); ++it) 719 { 720 QueuedMessageBoxData *queuedData = *it; 721 ui.NavigateToScene(queuedData->iPad, eUIScene_MessageBox, &queuedData->info, queuedData->layer, eUIGroup_Fullscreen); 722 delete queuedData->info.uiOptionA; 723 delete queuedData; 724 } 725 m_queuedMessageBoxData.clear(); 726} 727 728byteArray UIController::getMovieData(const wstring &filename) 729{ 730 // Cache everything we load in the current tick 731 __int64 targetTime = System::currentTimeMillis() + (1000LL * 60); 732 AUTO_VAR(it,m_cachedMovieData.find(filename)); 733 if(it == m_cachedMovieData.end() ) 734 { 735 byteArray baFile = app.getArchiveFile(filename); 736 CachedMovieData cmd; 737 cmd.m_ba = baFile; 738 cmd.m_expiry = targetTime; 739 m_cachedMovieData[filename] = cmd; 740 return baFile; 741 } 742 else 743 { 744 it->second.m_expiry = targetTime; 745 return it->second.m_ba; 746 } 747} 748 749// INPUT 750void UIController::tickInput() 751{ 752 // If system/commerce UI up, don't handle input 753 //if(!m_bSysUIShowing && !m_bSystemUIShowing) 754 if(!m_bSystemUIShowing) 755 { 756#ifdef ENABLE_IGGY_PERFMON 757 if (m_iggyPerfmonEnabled) 758 { 759 if(InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(), ACTION_MENU_STICK_PRESS)) m_iggyPerfmonEnabled = !m_iggyPerfmonEnabled; 760 } 761 else 762#endif 763 { 764 handleInput(); 765 ++m_accumulatedTicks; 766 } 767 } 768} 769 770void UIController::handleInput() 771{ 772 // For each user, loop over each key type and send messages based on the state 773 for(unsigned int iPad = 0; iPad < XUSER_MAX_COUNT; ++iPad) 774 { 775#ifdef _DURANGO 776 // 4J-JEV: Added exception for primary play who migh've uttered speech commands. 777 if(iPad != ProfileManager.GetPrimaryPad() 778 && (!InputManager.IsPadConnected(iPad) || !InputManager.IsPadLocked(iPad)) ) continue; 779#endif 780 for(unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) 781 { 782 handleKeyPress(iPad, key); 783 } 784 785#ifdef __PSVITA__ 786 //CD - Vita requires key press 40 - select [MINECRAFT_ACTION_GAME_INFO] 787 handleKeyPress(iPad, MINECRAFT_ACTION_GAME_INFO); 788#endif 789 } 790 791#ifdef _DURANGO 792 if(!app.GetGameStarted()) 793 { 794 bool repeat = false; 795 int firstUnfocussedUnhandledPad = -1; 796 797 // For durango, check for unmapped controllers 798 for(unsigned int iPad = XUSER_MAX_COUNT; iPad < (XUSER_MAX_COUNT + InputManager.MAX_GAMEPADS); ++iPad) 799 { 800 if(InputManager.IsPadLocked(iPad) || !InputManager.IsPadConnected(iPad) ) continue; 801 802 for(unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) 803 { 804 805 bool pressed = InputManager.ButtonPressed(iPad,key); // Toggle 806 bool released = InputManager.ButtonReleased(iPad,key); // Toggle 807 808 if(pressed || released) 809 { 810 bool handled = false; 811 812 // Send the key to the fullscreen group first 813 m_groups[(int)eUIGroup_Fullscreen]->handleInput(iPad, key, repeat, pressed, released, handled); 814 815 if(firstUnfocussedUnhandledPad < 0 && !m_groups[(int)eUIGroup_Fullscreen]->HasFocus(iPad)) 816 { 817 firstUnfocussedUnhandledPad = iPad; 818 } 819 } 820 } 821 } 822 823 if(ProfileManager.GetLockedProfile() >= 0 && !InputManager.IsPadLocked( ProfileManager.GetLockedProfile() ) && firstUnfocussedUnhandledPad >= 0) 824 { 825 ProfileManager.RequestSignInUI(false, false, false, false, true, NULL, NULL, firstUnfocussedUnhandledPad ); 826 } 827 } 828#endif 829} 830 831void UIController::handleKeyPress(unsigned int iPad, unsigned int key) 832{ 833 834 bool down = false; 835 bool pressed = false; // Toggle 836 bool released = false; // Toggle 837 bool repeat = false; 838 839#ifdef __PSVITA__ 840 if(key==ACTION_MENU_OK) 841 { 842 bool bTouchScreenInput=false; 843 844 // check the touchscreen 845 846 // 4J-PB - use the touchscreen for quickselect 847 SceTouchData* pTouchData = InputManager.GetTouchPadData(iPad,false); 848 849 if((m_bTouchscreenPressed==false) && pTouchData->reportNum==1) 850 { 851 // no active touch? clear active and highlighted touch UI elements 852 m_ActiveUIElement = NULL; 853 m_HighlightedUIElement = NULL; 854 855 // fullscreen first 856 UIScene *pScene=m_groups[(int)eUIGroup_Fullscreen]->getCurrentScene(); 857 // also check tooltip scene if we're not touching anything in the main scene 858 UIScene *pToolTips=m_groups[(int)eUIGroup_Fullscreen]->getTooltips(); 859 if(pScene) 860 { 861 // scene touch check 862 if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) 863 { 864 down=pressed=m_bTouchscreenPressed=true; 865 bTouchScreenInput=true; 866 } 867 // tooltip touch check 868 else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) 869 { 870 down=pressed=m_bTouchscreenPressed=true; 871 bTouchScreenInput=true; 872 } 873 } 874 else 875 { 876 pScene=m_groups[(EUIGroup)(iPad+1)]->getCurrentScene(); 877 pToolTips=m_groups[(int)iPad+1]->getTooltips(); 878 if(pScene) 879 { 880 // scene touch check 881 if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) 882 { 883 down=pressed=m_bTouchscreenPressed=true; 884 bTouchScreenInput=true; 885 } 886 // tooltip touch check (if scene exists but not component has been touched) 887 else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) 888 { 889 down=pressed=m_bTouchscreenPressed=true; 890 bTouchScreenInput=true; 891 } 892 } 893 else if(pToolTips) 894 { 895 // tooltip touch check (if scene does not exist) 896 if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) 897 { 898 down=pressed=m_bTouchscreenPressed=true; 899 bTouchScreenInput=true; 900 } 901 } 902 } 903 } 904 else if(m_bTouchscreenPressed && pTouchData->reportNum==1) 905 { 906 // fullscreen first 907 UIScene *pScene=m_groups[(int)eUIGroup_Fullscreen]->getCurrentScene(); 908 // also check tooltip scene if we're not touching anything in the main scene 909 UIScene *pToolTips=m_groups[(int)eUIGroup_Fullscreen]->getTooltips(); 910 if(pScene) 911 { 912 // scene touch check 913 if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) 914 { 915 down=true; 916 bTouchScreenInput=true; 917 } 918 // tooltip touch check (if scene exists but not component has been touched) 919 else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) 920 { 921 down=true; 922 bTouchScreenInput=true; 923 } 924 } 925 else 926 { 927 pScene=m_groups[(EUIGroup)(iPad+1)]->getCurrentScene(); 928 pToolTips=m_groups[(int)iPad+1]->getTooltips(); 929 if(pScene) 930 { 931 // scene touch check 932 if(TouchBoxHit(pScene,pTouchData->report[0].x,pTouchData->report[0].y)) 933 { 934 down=true; 935 bTouchScreenInput=true; 936 } 937 // tooltip touch check (if scene exists but not component has been touched) 938 else if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) 939 { 940 down=true; 941 bTouchScreenInput=true; 942 } 943 } 944 else if(pToolTips) 945 { 946 // tooltip touch check (if scene does not exist) 947 if(TouchBoxHit(pToolTips,pTouchData->report[0].x,pTouchData->report[0].y)) 948 { 949 down=true; 950 bTouchScreenInput=true; 951 } 952 } 953 } 954 } 955 else if(m_bTouchscreenPressed && pTouchData->reportNum==0) 956 { 957 // released 958 bTouchScreenInput=true; 959 m_bTouchscreenPressed=false; 960 released=true; 961 } 962 963 if(pressed) 964 { 965 // Start repeat timer 966 m_actionRepeatTimer[iPad][key] = GetTickCount() + UI_REPEAT_KEY_DELAY_MS; 967 } 968 else if (released) 969 { 970 // Stop repeat timer 971 m_actionRepeatTimer[iPad][key] = 0; 972 } 973 else if (down) 974 { 975 // Check is enough time has elapsed to be a repeat key 976 DWORD currentTime = GetTickCount(); 977 if(m_actionRepeatTimer[iPad][key] > 0 && currentTime > m_actionRepeatTimer[iPad][key]) 978 { 979 repeat = true; 980 pressed = true; 981 m_actionRepeatTimer[iPad][key] = currentTime + UI_REPEAT_KEY_REPEAT_RATE_MS; 982 } 983 } 984 985 // handle touch input 986 HandleTouchInput(iPad, key, pressed, repeat, released); 987 988 // ignore any other presses if the touchscreen has been used 989 if(bTouchScreenInput) return; 990 } 991#endif 992 993 down = InputManager.ButtonDown(iPad,key); 994 pressed = InputManager.ButtonPressed(iPad,key); // Toggle 995 released = InputManager.ButtonReleased(iPad,key); // Toggle 996 997#ifdef _WINDOWS64 998 // Keyboard menu input for player 0 999 if (iPad == 0) 1000 { 1001 bool kbDown = false, kbPressed = false, kbReleased = false; 1002 switch(key) 1003 { 1004 case ACTION_MENU_UP: kbDown = KMInput.IsKeyDown(VK_UP); kbPressed = KMInput.IsKeyPressed(VK_UP); kbReleased = KMInput.IsKeyReleased(VK_UP); break; 1005 case ACTION_MENU_DOWN: kbDown = KMInput.IsKeyDown(VK_DOWN); kbPressed = KMInput.IsKeyPressed(VK_DOWN); kbReleased = KMInput.IsKeyReleased(VK_DOWN); break; 1006 case ACTION_MENU_LEFT: kbDown = KMInput.IsKeyDown(VK_LEFT); kbPressed = KMInput.IsKeyPressed(VK_LEFT); kbReleased = KMInput.IsKeyReleased(VK_LEFT); break; 1007 case ACTION_MENU_RIGHT: kbDown = KMInput.IsKeyDown(VK_RIGHT); kbPressed = KMInput.IsKeyPressed(VK_RIGHT); kbReleased = KMInput.IsKeyReleased(VK_RIGHT); break; 1008 case ACTION_MENU_OK: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break; 1009 case ACTION_MENU_A: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break; 1010 case ACTION_MENU_CANCEL: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break; 1011 case ACTION_MENU_B: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break; 1012 case ACTION_MENU_PAUSEMENU: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break; 1013 case ACTION_MENU_LEFT_SCROLL: kbDown = KMInput.IsKeyDown('Q'); kbPressed = KMInput.IsKeyPressed('Q'); kbReleased = KMInput.IsKeyReleased('Q'); break; 1014 case ACTION_MENU_RIGHT_SCROLL: kbDown = KMInput.IsKeyDown('E'); kbPressed = KMInput.IsKeyPressed('E'); kbReleased = KMInput.IsKeyReleased('E'); break; 1015 } 1016 pressed = pressed || kbPressed; 1017 released = released || kbReleased; 1018 down = down || kbDown; 1019 } 1020#endif 1021 1022 if(pressed) app.DebugPrintf("Pressed %d\n",key); 1023 if(released) app.DebugPrintf("Released %d\n",key); 1024 // Repeat handling 1025 if(pressed) 1026 { 1027 // Start repeat timer 1028 m_actionRepeatTimer[iPad][key] = GetTickCount() + UI_REPEAT_KEY_DELAY_MS; 1029 } 1030 else if (released) 1031 { 1032 // Stop repeat timer 1033 m_actionRepeatTimer[iPad][key] = 0; 1034 } 1035 else if (down) 1036 { 1037 // Check is enough time has elapsed to be a repeat key 1038 DWORD currentTime = GetTickCount(); 1039 if(m_actionRepeatTimer[iPad][key] > 0 && currentTime > m_actionRepeatTimer[iPad][key]) 1040 { 1041 repeat = true; 1042 pressed = true; 1043 m_actionRepeatTimer[iPad][key] = currentTime + UI_REPEAT_KEY_REPEAT_RATE_MS; 1044 } 1045 } 1046 1047#ifndef _CONTENT_PACKAGE 1048 1049#ifdef ENABLE_IGGY_PERFMON 1050 if ( pressed && !repeat && key == ACTION_MENU_STICK_PRESS) 1051 { 1052 m_iggyPerfmonEnabled = !m_iggyPerfmonEnabled; 1053 } 1054#endif 1055 1056 // 4J Stu - Removed this function 1057#if 0 1058#ifdef __PS3__ 1059 //if ( pressed && 1060 // !repeat && 1061 // //app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_ToggleFont) && 1062 // key == ACTION_MENU_STICK_PRESS) 1063 //{ 1064 // static bool whichFont = true; 1065 // if (whichFont) 1066 // { 1067 // IggyFontSetIndirectUTF8( "Mojangles_7", -1, IGGY_FONTFLAG_all, "Mojangles_TTF",-1 ,IGGY_FONTFLAG_none ); 1068 // IggyFontSetIndirectUTF8( "Mojangles_11", -1, IGGY_FONTFLAG_all, "Mojangles_TTF",-1 ,IGGY_FONTFLAG_none ); 1069 // whichFont = false; 1070 // } 1071 // else 1072 // { 1073 // IggyFontSetIndirectUTF8( "Mojangles_7", -1, IGGY_FONTFLAG_all, "Mojangles_7",-1 ,IGGY_FONTFLAG_none ); 1074 // IggyFontSetIndirectUTF8( "Mojangles_11", -1, IGGY_FONTFLAG_all, "Mojangles_11",-1 ,IGGY_FONTFLAG_none ); 1075 // whichFont = true; 1076 // } 1077 //} 1078 //else 1079 if ( pressed && 1080 !repeat && 1081 //!(app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_ToggleFont)) && 1082 key == ACTION_MENU_STICK_PRESS) 1083 { 1084 __int64 totalStatic = 0; 1085 __int64 totalDynamic = 0; 1086 app.DebugPrintf(app.USER_SR, "********************************\n"); 1087 app.DebugPrintf(app.USER_SR, "BEGIN TOTAL SWF MEMORY USAGE\n\n"); 1088 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 1089 { 1090 m_groups[i]->PrintTotalMemoryUsage(totalStatic, totalDynamic); 1091 } 1092 for(unsigned int i = 0; i < eLibrary_Count; ++i) 1093 { 1094 __int64 libraryStatic = 0; 1095 __int64 libraryDynamic = 0; 1096 1097 if(m_iggyLibraries[i] != IGGY_INVALID_LIBRARY) 1098 { 1099 1100 IggyMemoryUseInfo memoryInfo; 1101 rrbool res; 1102 int iteration = 0; 1103 while(res = IggyDebugGetMemoryUseInfo ( NULL , 1104 m_iggyLibraries[i] , 1105 "" , 1106 0 , 1107 iteration , 1108 &memoryInfo )) 1109 { 1110 libraryStatic += memoryInfo.static_allocation_bytes; 1111 libraryDynamic += memoryInfo.dynamic_allocation_bytes; 1112 totalStatic += memoryInfo.static_allocation_bytes; 1113 totalDynamic += memoryInfo.dynamic_allocation_bytes; 1114 ++iteration; 1115 } 1116 } 1117 1118 app.DebugPrintf(app.USER_SR, "Library static: %dB , Library dynamic: %d, ID: %d\n", libraryStatic, libraryDynamic, i); 1119 } 1120 app.DebugPrintf(app.USER_SR, "Total static: %d , Total dynamic: %d\n", totalStatic, totalDynamic); 1121 app.DebugPrintf(app.USER_SR, "\n\nEND TOTAL SWF MEMORY USAGE\n"); 1122 app.DebugPrintf(app.USER_SR, "********************************\n\n"); 1123 } 1124 else 1125#endif 1126#endif 1127#endif 1128 //#endif 1129 if(repeat || pressed || released) 1130 { 1131 bool handled = false; 1132 1133 // Send the key to the fullscreen group first 1134 m_groups[(int)eUIGroup_Fullscreen]->handleInput(iPad, key, repeat, pressed, released, handled); 1135 if(!handled) 1136 { 1137 // If it's not been handled yet, then pass the event onto the players specific group 1138 m_groups[(iPad+1)]->handleInput(iPad, key, repeat, pressed, released, handled); 1139 } 1140 } 1141} 1142 1143rrbool RADLINK UIController::ExternalFunctionCallback( void * user_callback_data , Iggy * player , IggyExternalFunctionCallUTF16 * call) 1144{ 1145 UIScene *scene = (UIScene *)IggyPlayerGetUserdata(player); 1146 1147 if(scene != NULL) 1148 { 1149 scene->externalCallback(call); 1150 } 1151 1152 return true; 1153} 1154 1155// RENDERING 1156void UIController::renderScenes() 1157{ 1158 PIXBeginNamedEvent(0, "Rendering Iggy scenes"); 1159 // Only render player scenes if the game is started 1160 if(app.GetGameStarted() && !m_groups[eUIGroup_Fullscreen]->hidesLowerScenes()) 1161 { 1162 for(int i = eUIGroup_Player1; i < eUIGroup_COUNT; ++i) 1163 { 1164 PIXBeginNamedEvent(0, "Rendering layer %d scenes", i); 1165 m_groups[i]->render(); 1166 PIXEndNamedEvent(); 1167 } 1168 } 1169 1170 // Always render the fullscreen group 1171 PIXBeginNamedEvent(0, "Rendering fullscreen scenes"); 1172 m_groups[eUIGroup_Fullscreen]->render(); 1173 PIXEndNamedEvent(); 1174 1175 PIXEndNamedEvent(); 1176 1177#ifdef ENABLE_IGGY_PERFMON 1178 if (m_iggyPerfmonEnabled) 1179 { 1180 IggyPerfmonPad pm_pad; 1181 1182 pm_pad.bits = 0; 1183 pm_pad.field.dpad_up = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_UP); 1184 pm_pad.field.dpad_down = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_DOWN); 1185 pm_pad.field.dpad_left = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_LEFT); 1186 pm_pad.field.dpad_right = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_RIGHT); 1187 pm_pad.field.button_up = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_Y); 1188 pm_pad.field.button_down = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_A); 1189 pm_pad.field.button_left = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_X); 1190 pm_pad.field.button_right = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_B); 1191 pm_pad.field.shoulder_left_hi = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_LEFT_SCROLL); 1192 pm_pad.field.shoulder_right_hi = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_RIGHT_SCROLL); 1193 pm_pad.field.trigger_left_low = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_PAGEUP); 1194 pm_pad.field.trigger_right_low = InputManager.ButtonPressed(ProfileManager.GetPrimaryPad(),ACTION_MENU_PAGEDOWN); 1195 //IggyPerfmonPadFromXInputStatePointer(pm_pad, &xi_pad); 1196 1197 //gdraw_D3D_SetTileOrigin( fb, 1198 // zb, 1199 // PM_ORIGIN_X, 1200 // PM_ORIGIN_Y ); 1201 IggyPerfmonTickAndDraw(iggy_perfmon, gdraw_funcs, &pm_pad, 1202 PM_ORIGIN_X, PM_ORIGIN_Y, getScreenWidth(), getScreenHeight()); // perfmon draw area in window coords 1203 } 1204#endif 1205} 1206 1207void UIController::getRenderDimensions(C4JRender::eViewportType viewport, S32 &width, S32 &height) 1208{ 1209 switch( viewport ) 1210 { 1211 case C4JRender::VIEWPORT_TYPE_FULLSCREEN: 1212 width = (S32)(getScreenWidth()); 1213 height = (S32)(getScreenHeight()); 1214 break; 1215 case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: 1216 case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: 1217 width = (S32)(getScreenWidth() / 2); 1218 height = (S32)(getScreenHeight() / 2); 1219 break; 1220 case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: 1221 case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: 1222 width = (S32)(getScreenWidth() / 2); 1223 height = (S32)(getScreenHeight() / 2); 1224 break; 1225 case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: 1226 case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: 1227 case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: 1228 case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: 1229 width = (S32)(getScreenWidth() / 2); 1230 height = (S32)(getScreenHeight() / 2); 1231 break; 1232 } 1233} 1234 1235void UIController::setupRenderPosition(C4JRender::eViewportType viewport) 1236{ 1237 if(m_bCustomRenderPosition || m_currentRenderViewport != viewport) 1238 { 1239 m_currentRenderViewport = viewport; 1240 m_bCustomRenderPosition = false; 1241 S32 xPos = 0; 1242 S32 yPos = 0; 1243 switch( viewport ) 1244 { 1245 case C4JRender::VIEWPORT_TYPE_SPLIT_TOP: 1246 xPos = (S32)(getScreenWidth() / 4); 1247 break; 1248 case C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM: 1249 xPos = (S32)(getScreenWidth() / 4); 1250 yPos = (S32)(getScreenHeight() / 2); 1251 break; 1252 case C4JRender::VIEWPORT_TYPE_SPLIT_LEFT: 1253 yPos = (S32)(getScreenHeight() / 4); 1254 break; 1255 case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT: 1256 xPos = (S32)(getScreenWidth() / 2); 1257 yPos = (S32)(getScreenHeight() / 4); 1258 break; 1259 case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT: 1260 break; 1261 case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT: 1262 xPos = (S32)(getScreenWidth() / 2); 1263 break; 1264 case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT: 1265 yPos = (S32)(getScreenHeight() / 2); 1266 break; 1267 case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT: 1268 xPos = (S32)(getScreenWidth() / 2); 1269 yPos = (S32)(getScreenHeight() / 2); 1270 break; 1271 } 1272 m_tileOriginX = xPos; 1273 m_tileOriginY = yPos; 1274 setTileOrigin(xPos, yPos); 1275 } 1276} 1277 1278void UIController::setupRenderPosition(S32 xOrigin, S32 yOrigin) 1279{ 1280 m_bCustomRenderPosition = true; 1281 m_tileOriginX = xOrigin; 1282 m_tileOriginY = yOrigin; 1283 setTileOrigin(xOrigin, yOrigin); 1284} 1285 1286void UIController::setupCustomDrawGameState() 1287{ 1288 // Rest the clear rect 1289 m_customRenderingClearRect.left = LONG_MAX; 1290 m_customRenderingClearRect.right = LONG_MIN; 1291 m_customRenderingClearRect.top = LONG_MAX; 1292 m_customRenderingClearRect.bottom = LONG_MIN; 1293 1294#if defined _WINDOWS64 || _DURANGO 1295 PIXBeginNamedEvent(0,"StartFrame"); 1296 RenderManager.StartFrame(); 1297 PIXEndNamedEvent(); 1298 gdraw_D3D11_setViewport_4J(); 1299#elif defined __PS3__ 1300 RenderManager.StartFrame(); 1301#elif defined __PSVITA__ 1302 RenderManager.StartFrame(); 1303#elif defined __ORBIS__ 1304 RenderManager.StartFrame(false); 1305 // Set up a viewport for the render that matches Iggy's own viewport, apart form using an opengl-style z-range (Iggy uses a DX-style range on PS4), so 1306 // that the renderer orthographic projection will work 1307 gdraw_orbis_setViewport_4J(); 1308#endif 1309 RenderManager.Set_matrixDirty(); 1310 1311 // 4J Stu - We don't need to clear this here as iggy hasn't written anything to the depth buffer. 1312 // We DO however clear after we render which is why we still setup the rectangle here 1313 //RenderManager.Clear(GL_DEPTH_BUFFER_BIT, &m_customRenderingClearRect); 1314 //glClear(GL_DEPTH_BUFFER_BIT); 1315 1316 PIXBeginNamedEvent(0,"Final setup"); 1317 glMatrixMode(GL_PROJECTION); 1318 glLoadIdentity(); 1319 glOrtho(0, m_fScreenWidth, m_fScreenHeight, 0, 1000, 3000); 1320 glMatrixMode(GL_MODELVIEW); 1321 glEnable(GL_ALPHA_TEST); 1322 glAlphaFunc(GL_GREATER, 0.1f); 1323 glEnable(GL_DEPTH_TEST); 1324 glDepthFunc(GL_LEQUAL); 1325 glDepthMask(true); 1326 PIXEndNamedEvent(); 1327} 1328 1329void UIController::setupCustomDrawMatrices(UIScene *scene, CustomDrawData *customDrawRegion) 1330{ 1331 Minecraft *pMinecraft=Minecraft::GetInstance(); 1332 1333 // Clear just the region required for this control. 1334 float sceneWidth = (float)scene->getRenderWidth(); 1335 float sceneHeight = (float)scene->getRenderHeight(); 1336 1337 LONG left, right, top, bottom; 1338#ifdef __PS3__ 1339 if(!RenderManager.IsHiDef() && !RenderManager.IsWidescreen()) 1340 { 1341 // 4J Stu - Our SD target on PS3 is double width 1342 left = m_tileOriginX + (sceneWidth + customDrawRegion->mat[(0*4)+3]*sceneWidth); 1343 right = left + ( (sceneWidth * customDrawRegion->mat[0]) ) * customDrawRegion->x1; 1344 } 1345 else 1346#endif 1347 { 1348 left = m_tileOriginX + (sceneWidth + customDrawRegion->mat[(0*4)+3]*sceneWidth)/2; 1349 right = left + ( (sceneWidth * customDrawRegion->mat[0])/2 ) * customDrawRegion->x1; 1350 } 1351 1352 top = m_tileOriginY + (sceneHeight - customDrawRegion->mat[(1*4)+3]*sceneHeight)/2; 1353 bottom = top + (sceneHeight * -customDrawRegion->mat[(1*4) + 1])/2 * customDrawRegion->y1; 1354 1355 m_customRenderingClearRect.left = min(m_customRenderingClearRect.left, left); 1356 m_customRenderingClearRect.right = max(m_customRenderingClearRect.right, right);; 1357 m_customRenderingClearRect.top = min(m_customRenderingClearRect.top, top); 1358 m_customRenderingClearRect.bottom = max(m_customRenderingClearRect.bottom, bottom); 1359 1360 if(!m_bScreenWidthSetup) 1361 { 1362 Minecraft *pMinecraft=Minecraft::GetInstance(); 1363 if(pMinecraft != NULL) 1364 { 1365 m_fScreenWidth=(float)pMinecraft->width_phys; 1366 m_fScreenHeight=(float)pMinecraft->height_phys; 1367 m_bScreenWidthSetup = true; 1368 } 1369 } 1370 1371 glLoadIdentity(); 1372 glTranslatef(0, 0, -2000); 1373 // Iggy translations are based on a double-size target, with the origin in the centre 1374 glTranslatef((m_fScreenWidth + customDrawRegion->mat[(0*4)+3]*m_fScreenWidth)/2,(m_fScreenHeight - customDrawRegion->mat[(1*4)+3]*m_fScreenHeight)/2,0); 1375 // Iggy scales are based on a double-size target 1376 glScalef( (m_fScreenWidth * customDrawRegion->mat[0])/2,(m_fScreenHeight * -customDrawRegion->mat[(1*4) + 1])/2,1.0f); 1377} 1378 1379void UIController::setupCustomDrawGameStateAndMatrices(UIScene *scene, CustomDrawData *customDrawRegion) 1380{ 1381 setupCustomDrawGameState(); 1382 setupCustomDrawMatrices(scene, customDrawRegion); 1383} 1384 1385void UIController::endCustomDrawGameState() 1386{ 1387#ifdef __ORBIS__ 1388 // TO BE IMPLEMENTED 1389 RenderManager.Clear(GL_DEPTH_BUFFER_BIT); 1390#else 1391 RenderManager.Clear(GL_DEPTH_BUFFER_BIT, &m_customRenderingClearRect); 1392#endif 1393 //glClear(GL_DEPTH_BUFFER_BIT); 1394 glDepthMask(false); 1395 glDisable(GL_ALPHA_TEST); 1396} 1397 1398void UIController::endCustomDrawMatrices() 1399{ 1400} 1401 1402void UIController::endCustomDrawGameStateAndMatrices() 1403{ 1404 endCustomDrawMatrices(); 1405 endCustomDrawGameState(); 1406} 1407 1408void RADLINK UIController::CustomDrawCallback(void *user_callback_data, Iggy *player, IggyCustomDrawCallbackRegion *region) 1409{ 1410 UIScene *scene = (UIScene *)IggyPlayerGetUserdata(player); 1411 1412 if(scene != NULL) 1413 { 1414 scene->customDraw(region); 1415 } 1416} 1417 1418//Description 1419//Callback to create a user-defined texture to replace SWF-defined textures. 1420//Parameters 1421//width - Input value: optional number of pixels wide specified from AS3, or -1 if not defined. Output value: the number of pixels wide to pretend to Iggy that the bitmap is. SWF and AS3 scales bitmaps based on their pixel dimensions, so you can use this to substitute a texture that is higher or lower resolution that ActionScript thinks it is. 1422//height - Input value: optional number of pixels high specified from AS3, or -1 if not defined. Output value: the number of pixels high to pretend to Iggy that the bitmap is. SWF and AS3 scales bitmaps based on their pixel dimensions, so you can use this to substitute a texture that is higher or lower resolution that ActionScript thinks it is. 1423//destroy_callback_data - Optional additional output value you can set; the value will be passed along to the corresponding Iggy_TextureSubstitutionDestroyCallback (e.g. you can store the pointer to your own internal structure here). 1424//return - A platform-independent wrapped texture handle provided by GDraw, or NULL (NULL with throw an ActionScript 3 ArgumentError that the Flash developer can catch) Use by calling IggySetTextureSubstitutionCallbacks. 1425// 1426//Discussion 1427// 1428//If your texture includes an alpha channel, you must use a premultiplied alpha (where the R,G, and B channels have been multiplied by the alpha value); all Iggy shaders assume premultiplied alpha (and it looks better anyway). 1429GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void * user_callback_data , IggyUTF16 * texture_name , S32 * width , S32 * height , void * * destroy_callback_data ) 1430{ 1431 UIController *uiController = (UIController *)user_callback_data; 1432 AUTO_VAR(it,uiController->m_substitutionTextures.find((wchar_t *)texture_name)); 1433 1434 if(it != uiController->m_substitutionTextures.end()) 1435 { 1436 app.DebugPrintf("Found substitution texture %ls, with %d bytes\n", (wchar_t *)texture_name,it->second.length); 1437 1438 BufferedImage image(it->second.data, it->second.length); 1439 if( image.getData() != NULL ) 1440 { 1441 image.preMultiplyAlpha(); 1442 Textures *t = Minecraft::GetInstance()->textures; 1443 int id = t->getTexture(&image,C4JRender::TEXTURE_FORMAT_RxGyBzAw,false); 1444 1445 // 4J Stu - All our flash controls that allow replacing textures use a special 64x64 symbol 1446 // Force this size here so that our images don't get scaled wildly 1447 #if (defined __ORBIS__ || defined _DURANGO ) 1448 *width = 96; 1449 *height = 96; 1450 #else 1451 *width = 64; 1452 *height = 64; 1453 1454 #endif 1455 *destroy_callback_data = (void *)id; 1456 1457 app.DebugPrintf("Found substitution texture %ls (%d) - %dx%d\n", (wchar_t *)texture_name, id, image.getWidth(), image.getHeight()); 1458 return ui.getSubstitutionTexture(id); 1459 } 1460 else 1461 { 1462 return NULL; 1463 } 1464 } 1465 else 1466 { 1467 app.DebugPrintf("Could not find substitution texture %ls\n", (wchar_t *)texture_name); 1468 return NULL; 1469 } 1470} 1471 1472//Description 1473//Callback received from Iggy when it stops using a user-defined texture. 1474void RADLINK UIController::TextureSubstitutionDestroyCallback ( void * user_callback_data , void * destroy_callback_data , GDrawTexture * handle ) 1475{ 1476 // Orbis complains about casting a pointer to an int 1477 LONGLONG llVal=(LONGLONG)destroy_callback_data; 1478 int id=(int)llVal; 1479 app.DebugPrintf("Destroying iggy texture %d\n", id); 1480 1481 ui.destroySubstitutionTexture(user_callback_data, handle); 1482 1483 Textures *t = Minecraft::GetInstance()->textures; 1484 t->releaseTexture( id ); 1485} 1486 1487void UIController::registerSubstitutionTexture(const wstring &textureName, PBYTE pbData, DWORD dwLength) 1488{ 1489 // Remove it if it already exists 1490 unregisterSubstitutionTexture(textureName,false); 1491 1492 m_substitutionTextures[textureName] = byteArray(pbData, dwLength); 1493} 1494 1495void UIController::unregisterSubstitutionTexture(const wstring &textureName, bool deleteData) 1496{ 1497 AUTO_VAR(it,m_substitutionTextures.find(textureName)); 1498 1499 if(it != m_substitutionTextures.end()) 1500 { 1501 if(deleteData) delete [] it->second.data; 1502 m_substitutionTextures.erase(it); 1503 } 1504} 1505 1506// NAVIGATION 1507bool UIController::NavigateToScene(int iPad, EUIScene scene, void *initData, EUILayer layer, EUIGroup group) 1508{ 1509 static bool bSeenUpdateTextThisSession = false; 1510 // If you're navigating to the multigamejoinload, and the player hasn't seen the updates message yet, display it now 1511 // display this message the first 3 times 1512 if((scene==eUIScene_LoadOrJoinMenu) && (bSeenUpdateTextThisSession==false) && ( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplayUpdateMessage)!=0)) 1513 { 1514 scene=eUIScene_NewUpdateMessage; 1515 bSeenUpdateTextThisSession=true; 1516 } 1517 1518 // if you're trying to navigate to the inventory,the crafting, pause or game info or any of the trigger scenes and there's already a menu up (because you were pressing a few buttons at the same time) then ignore the navigate 1519 if(GetMenuDisplayed(iPad)) 1520 { 1521 switch(scene) 1522 { 1523 case eUIScene_PauseMenu: 1524 case eUIScene_Crafting2x2Menu: 1525 case eUIScene_Crafting3x3Menu: 1526 case eUIScene_FurnaceMenu: 1527 case eUIScene_ContainerMenu: 1528 case eUIScene_LargeContainerMenu: 1529 case eUIScene_InventoryMenu: 1530 case eUIScene_CreativeMenu: 1531 case eUIScene_DispenserMenu: 1532 case eUIScene_SignEntryMenu: 1533 case eUIScene_InGameInfoMenu: 1534 case eUIScene_EnchantingMenu: 1535 case eUIScene_BrewingStandMenu: 1536 case eUIScene_AnvilMenu: 1537 case eUIScene_TradingMenu: 1538 case eUIScene_BeaconMenu: 1539 case eUIScene_HorseMenu: 1540 app.DebugPrintf("IGNORING NAVIGATE - we're trying to navigate to a user selected scene when there's already a scene up: pad:%d, scene:%d\n", iPad, scene); 1541 return false; 1542 break; 1543 } 1544 } 1545 1546 switch(scene) 1547 { 1548 case eUIScene_FullscreenProgress: 1549 { 1550 // 4J Stu - The fullscreen progress scene should not interfere with any other scene stack, so should be placed in it's own group/layer 1551 layer = eUILayer_Fullscreen; 1552 group = eUIGroup_Fullscreen; 1553 } 1554 break; 1555 case eUIScene_ConnectingProgress: 1556 { 1557 // The connecting progress scene shouldn't interfere with other scenes 1558 layer = eUILayer_Fullscreen; 1559 } 1560 break; 1561 case eUIScene_EndPoem: 1562 { 1563 // The end poem scene shouldn't interfere with other scenes, but will be underneath the autosave progress 1564 group = eUIGroup_Fullscreen; 1565 layer = eUILayer_Scene; 1566 } 1567 break; 1568 }; 1569 int menuDisplayedPad = XUSER_INDEX_ANY; 1570 if(group == eUIGroup_PAD) 1571 { 1572 if( app.GetGameStarted() ) 1573 { 1574 // If the game isn't running treat as user 0, otherwise map index directly from pad 1575 if( ( iPad != 255 ) && ( iPad >= 0 ) ) 1576 { 1577 menuDisplayedPad = iPad; 1578 group = (EUIGroup)(iPad+1); 1579 } 1580 else group = eUIGroup_Fullscreen; 1581 } 1582 else 1583 { 1584 layer = eUILayer_Fullscreen; 1585 group = eUIGroup_Fullscreen; 1586 } 1587 } 1588 1589 PerformanceTimer timer; 1590 1591 EnterCriticalSection(&m_navigationLock); 1592 SetMenuDisplayed(menuDisplayedPad,true); 1593 bool success = m_groups[(int)group]->NavigateToScene(iPad, scene, initData, layer); 1594 if(success && group == eUIGroup_Fullscreen) setFullscreenMenuDisplayed(true); 1595 LeaveCriticalSection(&m_navigationLock); 1596 1597 timer.PrintElapsedTime(L"Navigate to scene"); 1598 1599 return success; 1600 //return true; 1601} 1602 1603bool UIController::NavigateBack(int iPad, bool forceUsePad, EUIScene eScene, EUILayer eLayer) 1604{ 1605 bool navComplete = false; 1606 if( app.GetGameStarted() ) 1607 { 1608 bool navComplete = m_groups[(int)eUIGroup_Fullscreen]->NavigateBack(iPad, eScene, eLayer); 1609 1610 if(!navComplete && ( iPad != 255 ) && ( iPad >= 0 ) ) 1611 { 1612 EUIGroup group = (EUIGroup)(iPad+1); 1613 navComplete = m_groups[(int)group]->NavigateBack(iPad, eScene, eLayer); 1614 if(!m_groups[(int)group]->GetMenuDisplayed())SetMenuDisplayed(iPad,false); 1615 } 1616 // 4J-PB - autosave in fullscreen doesn't clear the menuDisplayed flag 1617 else 1618 { 1619 if(!m_groups[(int)eUIGroup_Fullscreen]->GetMenuDisplayed()) 1620 { 1621 setFullscreenMenuDisplayed(false); 1622 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) 1623 { 1624 SetMenuDisplayed(i,m_groups[i+1]->GetMenuDisplayed()); 1625 } 1626 } 1627 } 1628 } 1629 else 1630 { 1631 navComplete = m_groups[(int)eUIGroup_Fullscreen]->NavigateBack(iPad, eScene, eLayer); 1632 if(!m_groups[(int)eUIGroup_Fullscreen]->GetMenuDisplayed()) SetMenuDisplayed(XUSER_INDEX_ANY,false); 1633 } 1634 return navComplete; 1635} 1636 1637void UIController::NavigateToHomeMenu() 1638{ 1639 ui.CloseAllPlayersScenes(); 1640 1641 // Alert the app the we no longer want to be informed of ethernet connections 1642 app.SetLiveLinkRequired( false ); 1643 1644 Minecraft *pMinecraft = Minecraft::GetInstance(); 1645 1646 // 4J-PB - just about to switched to the default texture pack , so clean up anything texture pack related here 1647 1648 // unload any texture pack audio 1649 // if there is audio in use, clear out the audio, and unmount the pack 1650 TexturePack *pTexPack=Minecraft::GetInstance()->skins->getSelected(); 1651 1652 1653 DLCTexturePack *pDLCTexPack=NULL; 1654 if(pTexPack->hasAudio()) 1655 { 1656 // get the dlc texture pack, and store it 1657 pDLCTexPack=(DLCTexturePack *)pTexPack; 1658 } 1659 1660 // change to the default texture pack 1661 pMinecraft->skins->selectTexturePackById(TexturePackRepository::DEFAULT_TEXTURE_PACK_ID); 1662 1663 1664 if(pTexPack->hasAudio()) 1665 { 1666 // need to stop the streaming audio - by playing streaming audio from the default texture pack now 1667 // reset the streaming sounds back to the normal ones 1668 pMinecraft->soundEngine->SetStreamingSounds(eStream_Overworld_Calm1,eStream_Overworld_piano3, 1669 eStream_Nether1,eStream_Nether4, 1670 eStream_end_dragon,eStream_end_end, 1671 eStream_CD_1); 1672 pMinecraft->soundEngine->playStreaming(L"", 0, 0, 0, 1, 1); 1673 1674 // if(pDLCTexPack->m_pStreamedWaveBank!=NULL) 1675 // { 1676 // pDLCTexPack->m_pStreamedWaveBank->Destroy(); 1677 // } 1678 // if(pDLCTexPack->m_pSoundBank!=NULL) 1679 // { 1680 // pDLCTexPack->m_pSoundBank->Destroy(); 1681 // } 1682#ifdef _XBOX_ONE 1683 DWORD result = StorageManager.UnmountInstalledDLC(L"TPACK"); 1684#else 1685 DWORD result = StorageManager.UnmountInstalledDLC("TPACK"); 1686#endif 1687 1688 app.DebugPrintf("Unmount result is %d\n",result); 1689 } 1690 1691 g_NetworkManager.ForceFriendsSessionRefresh(); 1692 1693 if(pMinecraft->skins->needsUIUpdate()) 1694 { 1695 m_navigateToHomeOnReload = true; 1696 } 1697 else 1698 { 1699 ui.NavigateToScene(ProfileManager.GetPrimaryPad(),eUIScene_MainMenu); 1700 } 1701} 1702 1703UIScene *UIController::GetTopScene(int iPad, EUILayer layer, EUIGroup group) 1704{ 1705 if(group == eUIGroup_PAD) 1706 { 1707 if( app.GetGameStarted() ) 1708 { 1709 // If the game isn't running treat as user 0, otherwise map index directly from pad 1710 if( ( iPad != 255 ) && ( iPad >= 0 ) ) 1711 { 1712 group = (EUIGroup)(iPad+1); 1713 } 1714 else group = eUIGroup_Fullscreen; 1715 } 1716 else 1717 { 1718 layer = eUILayer_Fullscreen; 1719 group = eUIGroup_Fullscreen; 1720 } 1721 } 1722 return m_groups[(int)group]->GetTopScene(layer); 1723} 1724 1725size_t UIController::RegisterForCallbackId(UIScene *scene) 1726{ 1727 EnterCriticalSection(&m_registeredCallbackScenesCS); 1728 size_t newId = GetTickCount(); 1729 newId &= 0xFFFFFF; // Chop off the top byte, we don't need any more accuracy than that 1730 newId |= (scene->getSceneType() << 24); // Add in the scene's type to help keep this unique 1731 m_registeredCallbackScenes[newId] = scene; 1732 LeaveCriticalSection(&m_registeredCallbackScenesCS); 1733 return newId; 1734} 1735 1736void UIController::UnregisterCallbackId(size_t id) 1737{ 1738 EnterCriticalSection(&m_registeredCallbackScenesCS); 1739 AUTO_VAR(it, m_registeredCallbackScenes.find(id) ); 1740 if(it != m_registeredCallbackScenes.end() ) 1741 { 1742 m_registeredCallbackScenes.erase(it); 1743 } 1744 LeaveCriticalSection(&m_registeredCallbackScenesCS); 1745} 1746 1747UIScene *UIController::GetSceneFromCallbackId(size_t id) 1748{ 1749 UIScene *scene = NULL; 1750 AUTO_VAR(it, m_registeredCallbackScenes.find(id) ); 1751 if(it != m_registeredCallbackScenes.end() ) 1752 { 1753 scene = it->second; 1754 } 1755 return scene; 1756} 1757 1758void UIController::EnterCallbackIdCriticalSection() 1759{ 1760 EnterCriticalSection(&m_registeredCallbackScenesCS); 1761} 1762 1763void UIController::LeaveCallbackIdCriticalSection() 1764{ 1765 LeaveCriticalSection(&m_registeredCallbackScenesCS); 1766} 1767 1768void UIController::CloseAllPlayersScenes() 1769{ 1770 m_groups[(int)eUIGroup_Fullscreen]->getTooltips()->SetTooltips(-1); 1771 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 1772 { 1773 //m_bCloseAllScenes[i] = true; 1774 m_groups[i]->closeAllScenes(); 1775 m_groups[i]->getTooltips()->SetTooltips(-1); 1776 } 1777 1778 if (!m_groups[eUIGroup_Fullscreen]->GetMenuDisplayed()) { 1779 for(unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) 1780 { 1781 SetMenuDisplayed(i,false); 1782 } 1783 } 1784 setFullscreenMenuDisplayed(false); 1785} 1786 1787void UIController::CloseUIScenes(int iPad, bool forceIPad) 1788{ 1789 EUIGroup group; 1790 if( app.GetGameStarted() || forceIPad ) 1791 { 1792 // If the game isn't running treat as user 0, otherwise map index directly from pad 1793 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 1794 else group = eUIGroup_Fullscreen; 1795 } 1796 else 1797 { 1798 group = eUIGroup_Fullscreen; 1799 } 1800 1801 m_groups[(int)group]->closeAllScenes(); 1802 m_groups[(int)group]->getTooltips()->SetTooltips(-1); 1803 1804 // This should cause the popup to dissappear 1805 TutorialPopupInfo popupInfo; 1806 if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->SetTutorialDescription(&popupInfo); 1807 1808 if(group==eUIGroup_Fullscreen) setFullscreenMenuDisplayed(false); 1809 1810 SetMenuDisplayed((group == eUIGroup_Fullscreen ? XUSER_INDEX_ANY : iPad), m_groups[(int)group]->GetMenuDisplayed()); 1811} 1812 1813void UIController::setFullscreenMenuDisplayed(bool displayed) 1814{ 1815 // Show/hide the tooltips for the fullscreen group 1816 m_groups[(int)eUIGroup_Fullscreen]->showComponent(ProfileManager.GetPrimaryPad(),eUIComponent_Tooltips,eUILayer_Tooltips,displayed); 1817 1818 // Show/hide tooltips for the other layers 1819 for(unsigned int i = (eUIGroup_Fullscreen+1); i < eUIGroup_COUNT; ++i) 1820 { 1821 m_groups[i]->showComponent(i,eUIComponent_Tooltips,eUILayer_Tooltips,!displayed); 1822 } 1823} 1824 1825bool UIController::IsPauseMenuDisplayed(int iPad) 1826{ 1827 EUIGroup group; 1828 if( app.GetGameStarted() ) 1829 { 1830 // If the game isn't running treat as user 0, otherwise map index directly from pad 1831 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 1832 else group = eUIGroup_Fullscreen; 1833 } 1834 else 1835 { 1836 group = eUIGroup_Fullscreen; 1837 } 1838 return m_groups[(int)group]->IsPauseMenuDisplayed(); 1839} 1840 1841bool UIController::IsContainerMenuDisplayed(int iPad) 1842{ 1843 EUIGroup group; 1844 if( app.GetGameStarted() ) 1845 { 1846 // If the game isn't running treat as user 0, otherwise map index directly from pad 1847 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 1848 else group = eUIGroup_Fullscreen; 1849 } 1850 else 1851 { 1852 group = eUIGroup_Fullscreen; 1853 } 1854 return m_groups[(int)group]->IsContainerMenuDisplayed(); 1855} 1856 1857bool UIController::IsIgnorePlayerJoinMenuDisplayed(int iPad) 1858{ 1859 EUIGroup group; 1860 if( app.GetGameStarted() ) 1861 { 1862 // If the game isn't running treat as user 0, otherwise map index directly from pad 1863 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 1864 else group = eUIGroup_Fullscreen; 1865 } 1866 else 1867 { 1868 group = eUIGroup_Fullscreen; 1869 } 1870 return m_groups[(int)group]->IsIgnorePlayerJoinMenuDisplayed(); 1871} 1872 1873bool UIController::IsIgnoreAutosaveMenuDisplayed(int iPad) 1874{ 1875 EUIGroup group; 1876 if( app.GetGameStarted() ) 1877 { 1878 // If the game isn't running treat as user 0, otherwise map index directly from pad 1879 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 1880 else group = eUIGroup_Fullscreen; 1881 } 1882 else 1883 { 1884 group = eUIGroup_Fullscreen; 1885 } 1886 return m_groups[(int)eUIGroup_Fullscreen]->IsIgnoreAutosaveMenuDisplayed() || (group != eUIGroup_Fullscreen && m_groups[(int)group]->IsIgnoreAutosaveMenuDisplayed()); 1887} 1888 1889void UIController::SetIgnoreAutosaveMenuDisplayed(int iPad, bool displayed) 1890{ 1891 app.DebugPrintf(app.USER_SR, "UIController::SetIgnoreAutosaveMenuDisplayed is not implemented\n"); 1892} 1893 1894bool UIController::IsSceneInStack(int iPad, EUIScene eScene) 1895{ 1896 EUIGroup group; 1897 if( app.GetGameStarted() ) 1898 { 1899 // If the game isn't running treat as user 0, otherwise map index directly from pad 1900 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 1901 else group = eUIGroup_Fullscreen; 1902 } 1903 else 1904 { 1905 group = eUIGroup_Fullscreen; 1906 } 1907 return m_groups[(int)group]->IsSceneInStack(eScene); 1908} 1909 1910bool UIController::GetMenuDisplayed(int iPad) 1911{ 1912 return m_bMenuDisplayed[iPad]; 1913} 1914 1915void UIController::SetMenuDisplayed(int iPad,bool bVal) 1916{ 1917 if(bVal) 1918 { 1919 if(iPad==XUSER_INDEX_ANY) 1920 { 1921 for(int i=0;i<XUSER_MAX_COUNT;i++) 1922 { 1923 InputManager.SetMenuDisplayed(i,true); 1924 m_bMenuDisplayed[i]=true; 1925 // 4J Stu - Fix for #11018 - Functional: When the controller is unplugged during active gameplay and plugged back in at the resulting pause menu, it will demonstrate dual-functionality. 1926 m_bMenuToBeClosed[i]=false; 1927 } 1928 } 1929 else 1930 { 1931 InputManager.SetMenuDisplayed(iPad,true); 1932 m_bMenuDisplayed[iPad]=true; 1933 // 4J Stu - Fix for #11018 - Functional: When the controller is unplugged during active gameplay and plugged back in at the resulting pause menu, it will demonstrate dual-functionality. 1934 m_bMenuToBeClosed[iPad]=false; 1935 } 1936 } 1937 else 1938 { 1939 if(iPad==XUSER_INDEX_ANY) 1940 { 1941 for(int i=0;i<XUSER_MAX_COUNT;i++) 1942 { 1943 m_bMenuToBeClosed[i]=true; 1944 m_iCountDown[i]=10; 1945 } 1946 } 1947 else 1948 { 1949 m_bMenuToBeClosed[iPad]=true; 1950 m_iCountDown[iPad]=10; 1951 1952#ifdef _DURANGO 1953 // 4J-JEV: When in-game, allow player to toggle the 'Pause' and 'IngameInfo' menus via Kinnect. 1954 if (Minecraft::GetInstance()->running) 1955 InputManager.SetEnabledGtcButtons(_360_GTC_MENU | _360_GTC_PAUSE | _360_GTC_VIEW); 1956#endif 1957 } 1958 } 1959} 1960 1961void UIController::CheckMenuDisplayed() 1962{ 1963 for(int iPad=0;iPad<XUSER_MAX_COUNT;iPad++) 1964 { 1965 if(m_bMenuToBeClosed[iPad]) 1966 { 1967 if(m_iCountDown[iPad]!=0) 1968 { 1969 m_iCountDown[iPad]--; 1970 } 1971 else 1972 { 1973 m_bMenuToBeClosed[iPad]=false; 1974 m_bMenuDisplayed[iPad]=false; 1975 InputManager.SetMenuDisplayed(iPad,false); 1976 } 1977 1978 } 1979 } 1980} 1981 1982void UIController::SetTooltipText( unsigned int iPad, unsigned int tooltip, int iTextID ) 1983{ 1984 EUIGroup group; 1985 if( app.GetGameStarted() ) 1986 { 1987 // If the game isn't running treat as user 0, otherwise map index directly from pad 1988 if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); 1989 else group = eUIGroup_Fullscreen; 1990 } 1991 else 1992 { 1993 group = eUIGroup_Fullscreen; 1994 } 1995 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->SetTooltipText(tooltip, iTextID); 1996} 1997 1998void UIController::SetEnableTooltips( unsigned int iPad, BOOL bVal ) 1999{ 2000 EUIGroup group; 2001 if( app.GetGameStarted() ) 2002 { 2003 // If the game isn't running treat as user 0, otherwise map index directly from pad 2004 if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); 2005 else group = eUIGroup_Fullscreen; 2006 } 2007 else 2008 { 2009 group = eUIGroup_Fullscreen; 2010 } 2011 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->SetEnableTooltips(bVal); 2012} 2013 2014void UIController::ShowTooltip( unsigned int iPad, unsigned int tooltip, bool show ) 2015{ 2016 EUIGroup group; 2017 if( app.GetGameStarted() ) 2018 { 2019 // If the game isn't running treat as user 0, otherwise map index directly from pad 2020 if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); 2021 else group = eUIGroup_Fullscreen; 2022 } 2023 else 2024 { 2025 group = eUIGroup_Fullscreen; 2026 } 2027 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->ShowTooltip(tooltip,show); 2028} 2029 2030void UIController::SetTooltips( unsigned int iPad, int iA, int iB, int iX, int iY, int iLT, int iRT, int iLB, int iRB, int iLS, int iRS, int iBack, bool forceUpdate) 2031{ 2032 EUIGroup group; 2033 2034 // 4J-PB - strip out any that are not applicable on the platform 2035#ifndef _XBOX 2036 if(iX==IDS_TOOLTIPS_SELECTDEVICE) iX=-1; 2037 if(iX==IDS_TOOLTIPS_CHANGEDEVICE) iX=-1; 2038 2039#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 2040 if(iY==IDS_TOOLTIPS_VIEW_GAMERCARD) iY=-1; 2041 if(iY==IDS_TOOLTIPS_VIEW_GAMERPROFILE) iY=-1; 2042 2043#endif 2044#endif 2045 2046 if( app.GetGameStarted() ) 2047 { 2048 // If the game isn't running treat as user 0, otherwise map index directly from pad 2049 if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); 2050 else group = eUIGroup_Fullscreen; 2051 } 2052 else 2053 { 2054 group = eUIGroup_Fullscreen; 2055 } 2056 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->SetTooltips(iA, iB, iX, iY, iLT, iRT, iLB, iRB, iLS, iRS, iBack, forceUpdate); 2057} 2058 2059void UIController::EnableTooltip( unsigned int iPad, unsigned int tooltip, bool enable ) 2060{ 2061 EUIGroup group; 2062 if( app.GetGameStarted() ) 2063 { 2064 // If the game isn't running treat as user 0, otherwise map index directly from pad 2065 if( ( iPad != 255 ) ) group = (EUIGroup)(iPad+1); 2066 else group = eUIGroup_Fullscreen; 2067 } 2068 else 2069 { 2070 group = eUIGroup_Fullscreen; 2071 } 2072 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->EnableTooltip(tooltip,enable); 2073} 2074 2075void UIController::RefreshTooltips(unsigned int iPad) 2076{ 2077 app.DebugPrintf(app.USER_SR, "UIController::RefreshTooltips is not implemented\n"); 2078} 2079 2080void UIController::AnimateKeyPress(int iPad, int iAction, bool bRepeat, bool bPressed, bool bReleased) 2081{ 2082 EUIGroup group; 2083 if(bPressed==false) 2084 { 2085 // only animating button press 2086 return; 2087 } 2088 if( app.GetGameStarted() ) 2089 { 2090 // If the game isn't running treat as user 0, otherwise map index directly from pad 2091 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2092 else group = eUIGroup_Fullscreen; 2093 } 2094 else 2095 { 2096 group = eUIGroup_Fullscreen; 2097 } 2098 bool handled = false; 2099 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->handleInput(iPad, iAction, bRepeat, bPressed, bReleased, handled); 2100} 2101 2102void UIController::OverrideSFX(int iPad, int iAction,bool bVal) 2103{ 2104 EUIGroup group; 2105 2106 if( app.GetGameStarted() ) 2107 { 2108 // If the game isn't running treat as user 0, otherwise map index directly from pad 2109 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2110 else group = eUIGroup_Fullscreen; 2111 } 2112 else 2113 { 2114 group = eUIGroup_Fullscreen; 2115 } 2116 bool handled = false; 2117 if(m_groups[(int)group]->getTooltips()) m_groups[(int)group]->getTooltips()->overrideSFX(iPad, iAction,bVal); 2118} 2119 2120void UIController::PlayUISFX(ESoundEffect eSound) 2121{ 2122 __uint64 time = System::currentTimeMillis(); 2123 2124 // Don't play multiple SFX on the same tick 2125 // (prevents horrible sounds when programmatically setting multiple checkboxes) 2126 if (time - m_lastUiSfx < 10) { return; } 2127 m_lastUiSfx = time; 2128 2129 Minecraft::GetInstance()->soundEngine->playUI(eSound,1.0f,1.0f); 2130} 2131 2132void UIController::DisplayGamertag(unsigned int iPad, bool show) 2133{ 2134 // The host decides whether these are on or off 2135 if( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplaySplitscreenGamertags) == 0) 2136 { 2137 show = false; 2138 } 2139 EUIGroup group = (EUIGroup)(iPad+1); 2140 if(m_groups[(int)group]->getHUD()) m_groups[(int)group]->getHUD()->ShowDisplayName(show); 2141 2142 // Update TutorialPopup in Splitscreen if no container is displayed (to make sure the Popup does not overlap with the Gamertag!) 2143 if(app.GetLocalPlayerCount() > 1 && m_groups[(int)group]->getTutorialPopup() && !m_groups[(int)group]->IsContainerMenuDisplayed()) 2144 { 2145 m_groups[(int)group]->getTutorialPopup()->UpdateTutorialPopup(); 2146 } 2147} 2148 2149void UIController::SetSelectedItem(unsigned int iPad, const wstring &name) 2150{ 2151 EUIGroup group; 2152 2153 if( app.GetGameStarted() ) 2154 { 2155 // If the game isn't running treat as user 0, otherwise map index directly from pad 2156 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2157 else group = eUIGroup_Fullscreen; 2158 } 2159 else 2160 { 2161 group = eUIGroup_Fullscreen; 2162 } 2163 bool handled = false; 2164 if(m_groups[(int)group]->getHUD()) m_groups[(int)group]->getHUD()->SetSelectedLabel(name); 2165} 2166 2167void UIController::UpdateSelectedItemPos(unsigned int iPad) 2168{ 2169 app.DebugPrintf(app.USER_SR, "UIController::UpdateSelectedItemPos not implemented\n"); 2170} 2171 2172void UIController::HandleDLCMountingComplete() 2173{ 2174 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 2175 { 2176 app.DebugPrintf("UIController::HandleDLCMountingComplete - m_groups[%d]\n",i); 2177 m_groups[i]->HandleDLCMountingComplete(); 2178 } 2179} 2180 2181void UIController::HandleDLCInstalled(int iPad) 2182{ 2183 //app.DebugPrintf(app.USER_SR, "UIController::HandleDLCInstalled not implemented\n"); 2184 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 2185 { 2186 m_groups[i]->HandleDLCInstalled(); 2187 } 2188} 2189 2190 2191#ifdef _XBOX_ONE 2192void UIController::HandleDLCLicenseChange() 2193{ 2194 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 2195 { 2196 app.DebugPrintf("UIController::HandleDLCLicenseChange - m_groups[%d]\n",i); 2197 m_groups[i]->HandleDLCLicenseChange(); 2198 } 2199} 2200#endif 2201 2202void UIController::HandleTMSDLCFileRetrieved(int iPad) 2203{ 2204 app.DebugPrintf(app.USER_SR, "UIController::HandleTMSDLCFileRetrieved not implemented\n"); 2205} 2206 2207void UIController::HandleTMSBanFileRetrieved(int iPad) 2208{ 2209 app.DebugPrintf(app.USER_SR, "UIController::HandleTMSBanFileRetrieved not implemented\n"); 2210} 2211 2212void UIController::HandleInventoryUpdated(int iPad) 2213{ 2214 EUIGroup group = eUIGroup_Fullscreen; 2215 if( app.GetGameStarted() && ( iPad != 255 ) && ( iPad >= 0 ) ) 2216 { 2217 group = (EUIGroup)(iPad+1); 2218 } 2219 2220 m_groups[group]->HandleMessage(eUIMessage_InventoryUpdated, NULL); 2221} 2222 2223void UIController::HandleGameTick() 2224{ 2225 tickInput(); 2226 2227 for(unsigned int i = 0; i < eUIGroup_COUNT; ++i) 2228 { 2229 if(m_groups[i]->getHUD()) m_groups[i]->getHUD()->handleGameTick(); 2230 } 2231} 2232 2233void UIController::SetTutorial(int iPad, Tutorial *tutorial) 2234{ 2235 EUIGroup group; 2236 if( app.GetGameStarted() ) 2237 { 2238 // If the game isn't running treat as user 0, otherwise map index directly from pad 2239 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2240 else group = eUIGroup_Fullscreen; 2241 } 2242 else 2243 { 2244 group = eUIGroup_Fullscreen; 2245 } 2246 if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->SetTutorial(tutorial); 2247} 2248 2249void UIController::SetTutorialDescription(int iPad, TutorialPopupInfo *info) 2250{ 2251 EUIGroup group; 2252 if( app.GetGameStarted() ) 2253 { 2254 // If the game isn't running treat as user 0, otherwise map index directly from pad 2255 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2256 else group = eUIGroup_Fullscreen; 2257 } 2258 else 2259 { 2260 group = eUIGroup_Fullscreen; 2261 } 2262 2263 if(m_groups[(int)group]->getTutorialPopup()) 2264 { 2265 // tutorial popup needs to know if a container menu is being displayed 2266 m_groups[(int)group]->getTutorialPopup()->SetContainerMenuVisible(m_groups[(int)group]->IsContainerMenuDisplayed()); 2267 m_groups[(int)group]->getTutorialPopup()->SetTutorialDescription(info); 2268 } 2269} 2270 2271#ifndef _XBOX 2272void UIController::RemoveInteractSceneReference(int iPad, UIScene *scene) 2273{ 2274 EUIGroup group; 2275 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2276 else group = eUIGroup_Fullscreen; 2277 if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->RemoveInteractSceneReference(scene); 2278} 2279#endif 2280 2281void UIController::SetTutorialVisible(int iPad, bool visible) 2282{ 2283 EUIGroup group; 2284 if( app.GetGameStarted() ) 2285 { 2286 // If the game isn't running treat as user 0, otherwise map index directly from pad 2287 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2288 else group = eUIGroup_Fullscreen; 2289 } 2290 else 2291 { 2292 group = eUIGroup_Fullscreen; 2293 } 2294 if(m_groups[(int)group]->getTutorialPopup()) m_groups[(int)group]->getTutorialPopup()->SetVisible(visible); 2295} 2296 2297bool UIController::IsTutorialVisible(int iPad) 2298{ 2299 EUIGroup group; 2300 if( app.GetGameStarted() ) 2301 { 2302 // If the game isn't running treat as user 0, otherwise map index directly from pad 2303 if( ( iPad != 255 ) && ( iPad >= 0 ) ) group = (EUIGroup)(iPad+1); 2304 else group = eUIGroup_Fullscreen; 2305 } 2306 else 2307 { 2308 group = eUIGroup_Fullscreen; 2309 } 2310 bool visible = false; 2311 if(m_groups[(int)group]->getTutorialPopup()) visible = m_groups[(int)group]->getTutorialPopup()->IsVisible(); 2312 return visible; 2313} 2314 2315void UIController::UpdatePlayerBasePositions() 2316{ 2317 Minecraft *pMinecraft = Minecraft::GetInstance(); 2318 2319 for( BYTE idx = 0; idx < XUSER_MAX_COUNT; ++idx) 2320 { 2321 if(pMinecraft->localplayers[idx] != NULL) 2322 { 2323 if(pMinecraft->localplayers[idx]->m_iScreenSection==C4JRender::VIEWPORT_TYPE_FULLSCREEN) 2324 { 2325 DisplayGamertag(idx,false); 2326 } 2327 else 2328 { 2329 DisplayGamertag(idx,true); 2330 } 2331 m_groups[idx+1]->SetViewportType((C4JRender::eViewportType)pMinecraft->localplayers[idx]->m_iScreenSection); 2332 } 2333 else 2334 { 2335 // 4J Stu - This is a legacy thing from our XUI implementation that we don't need 2336 // Changing the viewport to fullscreen for users that no longer exist is SLOW 2337 // This should probably be on all platforms, but I don't have time to test them all just now! 2338#ifndef __ORBIS__ 2339 m_groups[idx+1]->SetViewportType(C4JRender::VIEWPORT_TYPE_FULLSCREEN); 2340#endif 2341 DisplayGamertag(idx,false); 2342 } 2343 } 2344} 2345 2346void UIController::SetEmptyQuadrantLogo(int iSection) 2347{ 2348 // 4J Stu - We shouldn't need to implement this 2349} 2350 2351void UIController::HideAllGameUIElements() 2352{ 2353 // 4J Stu - We might not need to implement this 2354 app.DebugPrintf(app.USER_SR, "UIController::HideAllGameUIElements not implemented\n"); 2355} 2356 2357void UIController::ShowOtherPlayersBaseScene(unsigned int iPad, bool show) 2358{ 2359 // 4J Stu - We shouldn't need to implement this 2360} 2361 2362void UIController::ShowTrialTimer(bool show) 2363{ 2364 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showTrialTimer(show); 2365} 2366 2367void UIController::SetTrialTimerLimitSecs(unsigned int uiSeconds) 2368{ 2369 UIController::m_dwTrialTimerLimitSecs = uiSeconds; 2370} 2371 2372void UIController::UpdateTrialTimer(unsigned int iPad) 2373{ 2374 WCHAR wcTime[20]; 2375 2376 DWORD dwTimeTicks=(DWORD)app.getTrialTimer(); 2377 2378 if(dwTimeTicks>m_dwTrialTimerLimitSecs) 2379 { 2380 dwTimeTicks=m_dwTrialTimerLimitSecs; 2381 } 2382 2383 dwTimeTicks=m_dwTrialTimerLimitSecs-dwTimeTicks; 2384 2385#ifndef _CONTENT_PACKAGE 2386 if(true) 2387#else 2388 // display the time - only if there's less than 3 minutes 2389 if(dwTimeTicks<180) 2390#endif 2391 { 2392 int iMins=dwTimeTicks/60; 2393 int iSeconds=dwTimeTicks%60; 2394 swprintf( wcTime, 20, L"%d:%02d",iMins,iSeconds); 2395 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->setTrialTimer(wcTime); 2396 } 2397 else 2398 { 2399 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->setTrialTimer(L""); 2400 } 2401 2402 // are we out of time? 2403 if((dwTimeTicks==0)) 2404 { 2405 // Trial over 2406 // bring up the pause menu to stop the trial over message box being called again? 2407 if(!ui.GetMenuDisplayed( iPad ) ) 2408 { 2409 ui.NavigateToScene(iPad, eUIScene_PauseMenu, NULL, eUILayer_Scene); 2410 2411 app.SetAction(iPad,eAppAction_TrialOver); 2412 } 2413 } 2414} 2415 2416void UIController::ReduceTrialTimerValue() 2417{ 2418 DWORD dwTimeTicks=(int)app.getTrialTimer(); 2419 2420 if(dwTimeTicks>m_dwTrialTimerLimitSecs) 2421 { 2422 dwTimeTicks=m_dwTrialTimerLimitSecs; 2423 } 2424 2425 m_dwTrialTimerLimitSecs-=dwTimeTicks; 2426} 2427 2428void UIController::ShowAutosaveCountdownTimer(bool show) 2429{ 2430 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showTrialTimer(show); 2431} 2432 2433void UIController::UpdateAutosaveCountdownTimer(unsigned int uiSeconds) 2434{ 2435#if !(defined(_XBOX_ONE) || defined(__ORBIS__)) 2436 WCHAR wcAutosaveCountdown[100]; 2437 swprintf( wcAutosaveCountdown, 100, app.GetString(IDS_AUTOSAVE_COUNTDOWN),uiSeconds); 2438 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->setTrialTimer(wcAutosaveCountdown); 2439#endif 2440} 2441 2442void UIController::ShowSavingMessage(unsigned int iPad, C4JStorage::ESavingMessage eVal) 2443{ 2444 bool show = false; 2445 switch(eVal) 2446 { 2447 case C4JStorage::ESavingMessage_None: 2448 show = false; 2449 break; 2450 case C4JStorage::ESavingMessage_Short: 2451 case C4JStorage::ESavingMessage_Long: 2452 show = true; 2453 break; 2454 } 2455 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showSaveIcon(show); 2456} 2457 2458void UIController::ShowPlayerDisplayname(bool show) 2459{ 2460 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showPlayerDisplayName(show); 2461} 2462 2463void UIController::SetWinUserIndex(unsigned int iPad) 2464{ 2465 m_winUserIndex = iPad; 2466} 2467 2468unsigned int UIController::GetWinUserIndex() 2469{ 2470 return m_winUserIndex; 2471} 2472 2473void UIController::ShowUIDebugConsole(bool show) 2474{ 2475#ifndef _CONTENT_PACKAGE 2476 2477 if(show) 2478 { 2479 m_uiDebugConsole = (UIComponent_DebugUIConsole *)m_groups[eUIGroup_Fullscreen]->addComponent(0, eUIComponent_DebugUIConsole, eUILayer_Debug); 2480 } 2481 else 2482 { 2483 m_groups[eUIGroup_Fullscreen]->removeComponent(eUIComponent_DebugUIConsole, eUILayer_Debug); 2484 m_uiDebugConsole = NULL; 2485 } 2486#endif 2487} 2488 2489void UIController::ShowUIDebugMarketingGuide(bool show) 2490{ 2491#ifndef _CONTENT_PACKAGE 2492 2493 if(show) 2494 { 2495 m_uiDebugMarketingGuide = (UIComponent_DebugUIMarketingGuide *)m_groups[eUIGroup_Fullscreen]->addComponent(0, eUIComponent_DebugUIMarketingGuide, eUILayer_Debug); 2496 } 2497 else 2498 { 2499 m_groups[eUIGroup_Fullscreen]->removeComponent(eUIComponent_DebugUIMarketingGuide, eUILayer_Debug); 2500 m_uiDebugMarketingGuide = NULL; 2501 } 2502#endif 2503} 2504 2505void UIController::logDebugString(const string &text) 2506{ 2507 if(m_uiDebugConsole) m_uiDebugConsole->addText(text); 2508} 2509 2510bool UIController::PressStartPlaying(unsigned int iPad) 2511{ 2512 return m_iPressStartQuadrantsMask&(1<<iPad)?true:false; 2513} 2514 2515void UIController::ShowPressStart(unsigned int iPad) 2516{ 2517 m_iPressStartQuadrantsMask|=1<<iPad; 2518 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showPressStart(iPad, true); 2519} 2520 2521void UIController::HidePressStart() 2522{ 2523 ClearPressStart(); 2524 if(m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()) m_groups[(int)eUIGroup_Fullscreen]->getPressStartToPlay()->showPressStart(0, false); 2525} 2526 2527void UIController::ClearPressStart() 2528{ 2529 m_iPressStartQuadrantsMask = 0; 2530} 2531 2532C4JStorage::EMessageResult UIController::RequestAlertMessage(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult),LPVOID lpParam, WCHAR *pwchFormatString) 2533{ 2534 return RequestMessageBox(uiTitle, uiText, uiOptionA, uiOptionC, dwPad, Func, lpParam, pwchFormatString, 0, false); 2535} 2536 2537C4JStorage::EMessageResult UIController::RequestErrorMessage(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult),LPVOID lpParam, WCHAR *pwchFormatString) 2538{ 2539 return RequestMessageBox(uiTitle, uiText, uiOptionA, uiOptionC, dwPad, Func, lpParam, pwchFormatString, 0, true); 2540} 2541 2542C4JStorage::EMessageResult UIController::RequestMessageBox(UINT uiTitle, UINT uiText, UINT *uiOptionA,UINT uiOptionC, DWORD dwPad, 2543 int( *Func)(LPVOID,int,const C4JStorage::EMessageResult),LPVOID lpParam, WCHAR *pwchFormatString,DWORD dwFocusButton, bool bIsError) 2544 2545{ 2546 MessageBoxInfo param; 2547 param.uiTitle = uiTitle; 2548 param.uiText = uiText; 2549 param.uiOptionA = uiOptionA; 2550 param.uiOptionC = uiOptionC; 2551 param.dwPad = dwPad; 2552 param.Func = Func; 2553 param.lpParam = lpParam; 2554 param.pwchFormatString = pwchFormatString; 2555 param.dwFocusButton = dwFocusButton; 2556 2557 EUILayer layer = bIsError?eUILayer_Error:eUILayer_Alert; 2558 2559 bool completed = false; 2560 if(ui.IsReloadingSkin()) 2561 { 2562 // Queue this message box 2563 QueuedMessageBoxData *queuedData = new QueuedMessageBoxData(); 2564 queuedData->info = param; 2565 queuedData->info.uiOptionA = new UINT[param.uiOptionC]; 2566 memcpy(queuedData->info.uiOptionA, param.uiOptionA, param.uiOptionC * sizeof(UINT)); 2567 queuedData->iPad = dwPad; 2568 queuedData->layer = eUILayer_Error; // Ensures that these don't get wiped out by a CloseAllScenes call 2569 m_queuedMessageBoxData.push_back(queuedData); 2570 } 2571 else 2572 { 2573 completed = ui.NavigateToScene(dwPad, eUIScene_MessageBox, &param, layer, eUIGroup_Fullscreen); 2574 } 2575 2576 if( completed ) 2577 { 2578 // This may happen if we had to queue the message box, or there was already a message box displaying and so the NavigateToScene returned false; 2579 return C4JStorage::EMessage_Pending; 2580 } 2581 else 2582 { 2583 return C4JStorage::EMessage_Busy; 2584 } 2585} 2586 2587C4JStorage::EMessageResult UIController::RequestUGCMessageBox(UINT title/* = -1 */, UINT message/* = -1 */, int iPad/* = -1*/, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult)/* = NULL*/, LPVOID lpParam/* = NULL*/) 2588{ 2589 // Default title / messages 2590 if (title == -1) 2591 { 2592 title = IDS_FAILED_TO_CREATE_GAME_TITLE; 2593 } 2594 2595 if (message == -1) 2596 { 2597 message = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE; 2598 } 2599 2600 // Default pad to primary player 2601 if (iPad == -1) iPad = ProfileManager.GetPrimaryPad(); 2602 2603#ifdef __ORBIS__ 2604 // Show the vague UGC system message in addition to our message 2605 ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_UGC_RESTRICTION, iPad ); 2606 return C4JStorage::EMessage_ResultAccept; 2607#elif defined(__PSVITA__) 2608 ProfileManager.ShowSystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, iPad ); 2609 UINT uiIDA[1]; 2610 uiIDA[0]=IDS_CONFIRM_OK; 2611 return ui.RequestAlertMessage( title, IDS_CHAT_RESTRICTION_UGC, uiIDA, 1, iPad, Func, lpParam); 2612#else 2613 UINT uiIDA[1]; 2614 uiIDA[0]=IDS_CONFIRM_OK; 2615 return ui.RequestAlertMessage( title, message, uiIDA, 1, iPad, Func, lpParam); 2616#endif 2617} 2618 2619C4JStorage::EMessageResult UIController::RequestContentRestrictedMessageBox(UINT title/* = -1 */, UINT message/* = -1 */, int iPad/* = -1*/, int( *Func)(LPVOID,int,const C4JStorage::EMessageResult)/* = NULL*/, LPVOID lpParam/* = NULL*/) 2620{ 2621 // Default title / messages 2622 if (title == -1) 2623 { 2624 title = IDS_FAILED_TO_CREATE_GAME_TITLE; 2625 } 2626 2627 if (message == -1) 2628 { 2629#if defined(_XBOX_ONE) || defined(_WINDOWS64) 2630 // IDS_CONTENT_RESTRICTION doesn't exist on XB1 2631 message = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_CREATE; 2632#else 2633 message = IDS_CONTENT_RESTRICTION; 2634#endif 2635 } 2636 2637 // Default pad to primary player 2638 if (iPad == -1) iPad = ProfileManager.GetPrimaryPad(); 2639 2640#ifdef __ORBIS__ 2641 // Show the vague UGC system message in addition to our message 2642 ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_UGC_RESTRICTION, iPad ); 2643 return C4JStorage::EMessage_ResultAccept; 2644#elif defined(__PSVITA__) 2645 ProfileManager.ShowSystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_AGE_RESTRICTION, iPad ); 2646 return C4JStorage::EMessage_ResultAccept; 2647#else 2648 UINT uiIDA[1]; 2649 uiIDA[0]=IDS_CONFIRM_OK; 2650 return ui.RequestAlertMessage( title, message, uiIDA, 1, iPad, Func, lpParam); 2651#endif 2652} 2653 2654void UIController::setFontCachingCalculationBuffer(int length) 2655{ 2656 /* 4J-JEV: As described in an email from Sean. 2657 If your `optional_temp_buffer` is NULL, Iggy will allocate the temp 2658 buffer on the stack during Iggy draw calls. The size of the buffer it 2659 will allocate is 16 bytes times `max_chars` in 32-bit, and 24 bytes 2660 times `max_chars` in 64-bit. If the stack of the thread making the 2661 draw call is not large enough, Iggy will crash or otherwise behave 2662 incorrectly. 2663 */ 2664#if defined __ORBIS__ || defined _DURANGO || defined _WIN64 2665 static const int CHAR_SIZE = 24; 2666#else 2667 static const int CHAR_SIZE = 16; 2668#endif 2669 2670 if (m_tempBuffer != NULL) delete [] m_tempBuffer; 2671 if (length<0) 2672 { 2673 if (m_defaultBuffer == NULL) m_defaultBuffer = new char[CHAR_SIZE*5000]; 2674 IggySetFontCachingCalculationBuffer(5000, m_defaultBuffer, CHAR_SIZE*5000); 2675 } 2676 else 2677 { 2678 m_tempBuffer = new char[CHAR_SIZE*length]; 2679 IggySetFontCachingCalculationBuffer(length, m_tempBuffer, CHAR_SIZE*length); 2680 } 2681} 2682 2683// Returns the first scene of given type if it exists, NULL otherwise 2684UIScene *UIController::FindScene(EUIScene sceneType) 2685{ 2686 UIScene *pScene = NULL; 2687 2688 for (int i = 0; i < eUIGroup_COUNT; i++) 2689 { 2690 pScene = m_groups[i]->FindScene(sceneType); 2691#ifdef __PS3__ 2692 if (pScene != NULL) return pScene; 2693#else 2694 if (pScene != nullptr) return pScene; 2695#endif 2696 } 2697 2698 return pScene; 2699} 2700 2701#ifdef __PSVITA__ 2702 2703void UIController::TouchBoxAdd(UIControl *pControl,UIScene *pUIScene) 2704{ 2705 EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); 2706 EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; 2707 EUIScene eUIscene=pUIScene->getSceneType(); 2708 2709 TouchBoxAdd(pControl,eUIGroup,eUILayer,eUIscene, pUIScene->GetMainPanel()); 2710} 2711 2712void UIController::TouchBoxAdd(UIControl *pControl,EUIGroup eUIGroup,EUILayer eUILayer,EUIScene eUIscene, UIControl *pMainPanelControl) 2713{ 2714 UIELEMENT *puiElement = new UIELEMENT; 2715 puiElement->pControl = pControl; 2716 2717 S32 iControlWidth = pControl->getWidth(); 2718 S32 iControlHeight = pControl->getHeight(); 2719 S32 iMainPanelOffsetX = 0; 2720 S32 iMainPanelOffsetY= 0; 2721 2722 // 4J-TomK add main panel offset if controls do not live in the root scene 2723 if(pMainPanelControl) 2724 { 2725 iMainPanelOffsetX = pMainPanelControl->getXPos(); 2726 iMainPanelOffsetY = pMainPanelControl->getYPos(); 2727 } 2728 2729 // 4J-TomK override control width / height where needed 2730 if(puiElement->pControl->getControlType() == UIControl::eSlider) 2731 { 2732 // Sliders are never scaled but masked, so we have to get the real width from AS 2733 UIControl_Slider *pSlider = (UIControl_Slider *)puiElement->pControl; 2734 iControlWidth = pSlider->GetRealWidth(); 2735 } 2736 else if(puiElement->pControl->getControlType() == UIControl::eTexturePackList) 2737 { 2738 // The origin of the TexturePackList is NOT in the top left corner but where the slot area starts. therefore we need the height of the slot area itself. 2739 UIControl_TexturePackList *pTexturePackList = (UIControl_TexturePackList *)puiElement->pControl; 2740 iControlHeight = pTexturePackList->GetRealHeight(); 2741 } 2742 else if(puiElement->pControl->getControlType() == UIControl::eDynamicLabel) 2743 { 2744 // The height and width of this control changes per how to play page 2745 UIControl_DynamicLabel *pDynamicLabel = (UIControl_DynamicLabel *)puiElement->pControl; 2746 iControlWidth = pDynamicLabel->GetRealWidth(); 2747 iControlHeight = pDynamicLabel->GetRealHeight(); 2748 } 2749 else if(puiElement->pControl->getControlType() == UIControl::eHTMLLabel) 2750 { 2751 // The height and width of this control changes per how to play page 2752 UIControl_HTMLLabel *pHtmlLabel = (UIControl_HTMLLabel *)puiElement->pControl; 2753 iControlWidth = pHtmlLabel->GetRealWidth(); 2754 iControlHeight = pHtmlLabel->GetRealHeight(); 2755 } 2756 2757 puiElement->x1=(S32)((float)pControl->getXPos() + (float)iMainPanelOffsetX); 2758 puiElement->y1=(S32)((float)pControl->getYPos() + (float)iMainPanelOffsetY); 2759 puiElement->x2=(S32)(((float)pControl->getXPos() + (float)iControlWidth + (float)iMainPanelOffsetX)); 2760 puiElement->y2=(S32)(((float)pControl->getYPos() + (float)iControlHeight + (float)iMainPanelOffsetY)); 2761 2762 if(puiElement->pControl->getControlType() == UIControl::eNoControl) 2763 { 2764 app.DebugPrintf("NO CONTROL!"); 2765 } 2766 2767 if(puiElement->x1 == puiElement->x2 || puiElement->y1 == puiElement->y2) 2768 { 2769 app.DebugPrintf("NOT adding touchbox %d,%d,%d,%d\n",puiElement->x1,puiElement->y1,puiElement->x2,puiElement->y2); 2770 } 2771 else 2772 { 2773 app.DebugPrintf("Adding touchbox %d,%d,%d,%d\n",puiElement->x1,puiElement->y1,puiElement->x2,puiElement->y2); 2774 m_TouchBoxes[eUIGroup][eUILayer][eUIscene].push_back(puiElement); 2775 } 2776} 2777 2778void UIController::TouchBoxRebuild(UIScene *pUIScene) 2779{ 2780 EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); 2781 EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; 2782 EUIScene eUIscene=pUIScene->getSceneType(); 2783 2784 // if we delete an element, it's possible that the scene has re-arranged all the elements, so we need to rebuild the boxes 2785 ui.TouchBoxesClear(pUIScene); 2786 2787 // rebuild boxes 2788 AUTO_VAR(itEnd, pUIScene->GetControls()->end()); 2789 for (AUTO_VAR(it, pUIScene->GetControls()->begin()); it != itEnd; it++) 2790 { 2791 UIControl *control=(UIControl *)*it; 2792 2793 if(control->getControlType() == UIControl::eButton || 2794 control->getControlType() == UIControl::eSlider || 2795 control->getControlType() == UIControl::eCheckBox || 2796 control->getControlType() == UIControl::eTexturePackList || 2797 control->getControlType() == UIControl::eButtonList || 2798 control->getControlType() == UIControl::eTextInput || 2799 control->getControlType() == UIControl::eDynamicLabel || 2800 control->getControlType() == UIControl::eHTMLLabel || 2801 control->getControlType() == UIControl::eLeaderboardList || 2802 control->getControlType() == UIControl::eTouchControl) 2803 { 2804 if(control->getVisible()) 2805 { 2806 // 4J-TomK update the control (it might have been moved by flash / AS) 2807 control->UpdateControl(); 2808 2809 ui.TouchBoxAdd(control,eUIGroup,eUILayer,eUIscene, pUIScene->GetMainPanel()); 2810 } 2811 } 2812 } 2813} 2814 2815void UIController::TouchBoxesClear(UIScene *pUIScene) 2816{ 2817 EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); 2818 EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; 2819 EUIScene eUIscene=pUIScene->getSceneType(); 2820 2821 AUTO_VAR(itEnd, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].end()); 2822 for (AUTO_VAR(it, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].begin()); it != itEnd; it++) 2823 { 2824 UIELEMENT *element=(UIELEMENT *)*it; 2825 delete element; 2826 } 2827 m_TouchBoxes[eUIGroup][eUILayer][eUIscene].clear(); 2828} 2829 2830bool UIController::TouchBoxHit(UIScene *pUIScene,S32 x, S32 y) 2831{ 2832 EUIGroup eUIGroup=pUIScene->GetParentLayerGroup(); 2833 EUILayer eUILayer=pUIScene->GetParentLayer()->m_iLayer; 2834 EUIScene eUIscene=pUIScene->getSceneType(); 2835 2836 // 4J-TomK let's do the transformation from touch resolution to screen resolution here, so our touchbox values always are in screen resolution! 2837 x *= (m_fScreenWidth/1920.0f); 2838 y *= (m_fScreenHeight/1080.0f); 2839 2840 if(m_TouchBoxes[eUIGroup][eUILayer][eUIscene].size()>0) 2841 { 2842 AUTO_VAR(itEnd, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].end()); 2843 for (AUTO_VAR(it, m_TouchBoxes[eUIGroup][eUILayer][eUIscene].begin()); it != itEnd; it++) 2844 { 2845 UIELEMENT *element=(UIELEMENT *)*it; 2846 if(element->pControl->getHidden() == false && element->pControl->getVisible()) // ignore removed controls 2847 { 2848 if((x>=element->x1) &&(x<=element->x2) && (y>=element->y1) && (y<=element->y2)) 2849 { 2850 if(!m_bTouchscreenPressed) 2851 { 2852 app.DebugPrintf("SET m_ActiveUIElement (Layer: %i) at x = %i y = %i\n", (int)eUILayer, (int)x, (int)y); 2853 m_ActiveUIElement = element; 2854 } 2855 // remember the currently highlighted element 2856 m_HighlightedUIElement = element; 2857 2858 return true; 2859 } 2860 } 2861 } 2862 } 2863 2864 //app.DebugPrintf("MISS at x = %i y = %i\n", (int)x, (int)y); 2865 m_HighlightedUIElement = NULL; 2866 return false; 2867} 2868 2869// 2870// Handle Touch Input 2871// 2872void UIController::HandleTouchInput(unsigned int iPad, unsigned int key, bool bPressed, bool bRepeat, bool bReleased) 2873{ 2874 // no input? no handling! 2875 if(!bPressed && !bRepeat && !bReleased) 2876 { 2877 // override for instand repeat without delay! 2878 if(m_bTouchscreenPressed && m_ActiveUIElement && ( 2879 m_ActiveUIElement->pControl->getControlType() == UIControl::eSlider || 2880 m_ActiveUIElement->pControl->getControlType() == UIControl::eButtonList || 2881 m_ActiveUIElement->pControl->getControlType() == UIControl::eTexturePackList || 2882 m_ActiveUIElement->pControl->getControlType() == UIControl::eDynamicLabel || 2883 m_ActiveUIElement->pControl->getControlType() == UIControl::eHTMLLabel || 2884 m_ActiveUIElement->pControl->getControlType() == UIControl::eLeaderboardList || 2885 m_ActiveUIElement->pControl->getControlType() == UIControl::eTouchControl)) 2886 bRepeat = true; // the above controls need to be controllable without having the finger over them 2887 else 2888 return; 2889 } 2890 2891 SceTouchData* pTouchData = InputManager.GetTouchPadData(iPad,false); 2892 S32 x = pTouchData->report[0].x * (m_fScreenWidth/1920.0f); 2893 S32 y = pTouchData->report[0].y * (m_fScreenHeight/1080.0f); 2894 2895 if(bPressed && !bRepeat && !bReleased) // PRESSED HANDLING 2896 { 2897 app.DebugPrintf("touch input pressed\n"); 2898 switch(m_ActiveUIElement->pControl->getControlType()) 2899 { 2900 case UIControl::eButton: 2901 // set focus 2902 UIControl_Button *pButton=(UIControl_Button *)m_ActiveUIElement->pControl; 2903 pButton->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); 2904 // override bPressed to false. we only want the button to trigger on touch release! 2905 bPressed = false; 2906 break; 2907 case UIControl::eSlider: 2908 // set focus 2909 UIControl_Slider *pSlider=(UIControl_Slider *)m_ActiveUIElement->pControl; 2910 pSlider->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); 2911 break; 2912 case UIControl::eCheckBox: 2913 // set focus 2914 UIControl_CheckBox *pCheckbox=(UIControl_CheckBox *)m_ActiveUIElement->pControl; 2915 pCheckbox->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); 2916 // override bPressed. we only want the checkbox to trigger on touch release! 2917 bPressed = false; 2918 break; 2919 case UIControl::eButtonList: 2920 // set focus to list 2921 UIControl_ButtonList *pButtonList=(UIControl_ButtonList *)m_ActiveUIElement->pControl; 2922 //pButtonList->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); 2923 // tell list where we tapped it so it can set focus to the correct button 2924 pButtonList->SetTouchFocus((float)x, (float)y, false); 2925 // override bPressed. we only want the ButtonList to trigger on touch release! 2926 bPressed = false; 2927 break; 2928 case UIControl::eTexturePackList: 2929 // set focus to list 2930 UIControl_TexturePackList *pTexturePackList=(UIControl_TexturePackList *)m_ActiveUIElement->pControl; 2931 pTexturePackList->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); 2932 // tell list where we tapped it so it can set focus to the correct texture pack 2933 pTexturePackList->SetTouchFocus((float)x - (float)m_ActiveUIElement->x1, (float)y - (float)m_ActiveUIElement->y1, false); 2934 // override bPressed. we only want the TexturePack List to trigger on touch release! 2935 bPressed = false; 2936 break; 2937 case UIControl::eTextInput: 2938 // set focus 2939 UIControl_TextInput *pTextInput=(UIControl_TextInput *)m_ActiveUIElement->pControl; 2940 pTextInput->getParentScene()->SetFocusToElement(m_ActiveUIElement->pControl->getId()); 2941 // override bPressed to false. we only want the textinput to trigger on touch release! 2942 bPressed = false; 2943 break; 2944 case UIControl::eDynamicLabel: 2945 // handle dynamic label scrolling 2946 UIControl_DynamicLabel *pDynamicLabel=(UIControl_DynamicLabel *)m_ActiveUIElement->pControl; 2947 pDynamicLabel->TouchScroll(y, true); 2948 // override bPressed to false 2949 bPressed = false; 2950 break; 2951 case UIControl::eHTMLLabel: 2952 // handle dynamic label scrolling 2953 UIControl_HTMLLabel *pHtmlLabel=(UIControl_HTMLLabel *)m_ActiveUIElement->pControl; 2954 pHtmlLabel->TouchScroll(y, true); 2955 // override bPressed to false 2956 bPressed = false; 2957 break; 2958 case UIControl::eLeaderboardList: 2959 // set focus to list 2960 UIControl_LeaderboardList *pLeaderboardList=(UIControl_LeaderboardList *)m_ActiveUIElement->pControl; 2961 // tell list where we tapped it so it can set focus to the correct button 2962 pLeaderboardList->SetTouchFocus((float)x, (float)y, false); 2963 // override bPressed. we only want the ButtonList to trigger on touch release! 2964 bPressed = false; 2965 break; 2966 case UIControl::eTouchControl: 2967 // pass on touch input to relevant parent scene so we can handle it there! 2968 m_ActiveUIElement->pControl->getParentScene()->handleTouchInput(iPad, x, y, m_ActiveUIElement->pControl->getId(), bPressed, bRepeat, bReleased); 2969 // override bPressed to false 2970 bPressed = false; 2971 break; 2972 default: 2973 app.DebugPrintf("PRESSED - UNHANDLED UI ELEMENT\n"); 2974 break; 2975 } 2976 } 2977 else if(bRepeat) // REPEAT HANDLING 2978 { 2979 switch(m_ActiveUIElement->pControl->getControlType()) 2980 { 2981 case UIControl::eButton: 2982 /* no action */ 2983 break; 2984 case UIControl::eSlider: 2985 // handle slider movement 2986 UIControl_Slider *pSlider=(UIControl_Slider *)m_ActiveUIElement->pControl; 2987 float fNewSliderPos = ((float)x - (float)m_ActiveUIElement->x1) / (float)pSlider->GetRealWidth(); 2988 pSlider->SetSliderTouchPos(fNewSliderPos); 2989 break; 2990 case UIControl::eCheckBox: 2991 /* no action */ 2992 bRepeat = false; 2993 bPressed = false; 2994 break; 2995 case UIControl::eButtonList: 2996 // handle button list scrolling 2997 UIControl_ButtonList *pButtonList=(UIControl_ButtonList *)m_ActiveUIElement->pControl; 2998 pButtonList->SetTouchFocus((float)x, (float)y, true); 2999 break; 3000 case UIControl::eTexturePackList: 3001 // handle texturepack list scrolling 3002 UIControl_TexturePackList *pTexturePackList=(UIControl_TexturePackList *)m_ActiveUIElement->pControl; 3003 pTexturePackList->SetTouchFocus((float)x - (float)m_ActiveUIElement->x1, (float)y - (float)m_ActiveUIElement->y1, true); 3004 break; 3005 case UIControl::eTextInput: 3006 /* no action */ 3007 bRepeat = false; 3008 bPressed = false; 3009 break; 3010 case UIControl::eDynamicLabel: 3011 // handle dynamic label scrolling 3012 UIControl_DynamicLabel *pDynamicLabel=(UIControl_DynamicLabel *)m_ActiveUIElement->pControl; 3013 pDynamicLabel->TouchScroll(y, true); 3014 // override bPressed & bRepeat to false 3015 bPressed = false; 3016 bRepeat = false; 3017 break; 3018 case UIControl::eHTMLLabel: 3019 // handle dynamic label scrolling 3020 UIControl_HTMLLabel *pHtmlLabel=(UIControl_HTMLLabel *)m_ActiveUIElement->pControl; 3021 pHtmlLabel->TouchScroll(y, true); 3022 // override bPressed & bRepeat to false 3023 bPressed = false; 3024 bRepeat = false; 3025 break; 3026 case UIControl::eLeaderboardList: 3027 // handle button list scrolling 3028 UIControl_LeaderboardList *pLeaderboardList=(UIControl_LeaderboardList *)m_ActiveUIElement->pControl; 3029 pLeaderboardList->SetTouchFocus((float)x, (float)y, true); 3030 break; 3031 case UIControl::eTouchControl: 3032 // override bPressed to false 3033 bPressed = false; 3034 // pass on touch input to relevant parent scene so we can handle it there! 3035 m_ActiveUIElement->pControl->getParentScene()->handleTouchInput(iPad, x, y, m_ActiveUIElement->pControl->getId(), bPressed, bRepeat, bReleased); 3036 // override bRepeat to false 3037 bRepeat = false; 3038 break; 3039 default: 3040 app.DebugPrintf("REPEAT - UNHANDLED UI ELEMENT\n"); 3041 break; 3042 } 3043 } 3044 if(bReleased) // RELEASED HANDLING 3045 { 3046 app.DebugPrintf("touch input released\n"); 3047 switch(m_ActiveUIElement->pControl->getControlType()) 3048 { 3049 case UIControl::eButton: 3050 // trigger button on release (ONLY if the finger is still on it!) 3051 if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) 3052 bPressed = true; 3053 break; 3054 case UIControl::eSlider: 3055 /* no action */ 3056 break; 3057 case UIControl::eCheckBox: 3058 // trigger checkbox on release (ONLY if the finger is still on it!) 3059 if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) 3060 { 3061 UIControl_CheckBox *pCheckbox=(UIControl_CheckBox *)m_ActiveUIElement->pControl; 3062 if(pCheckbox->IsEnabled()) // only proceed if checkbox is enabled! 3063 pCheckbox->TouchSetCheckbox(!pCheckbox->IsChecked()); 3064 } 3065 bReleased = false; 3066 break; 3067 case UIControl::eButtonList: 3068 // trigger buttonlist on release (ONLY if the finger is still on it!) 3069 if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) 3070 { 3071 UIControl_ButtonList *pButtonList=(UIControl_ButtonList *)m_ActiveUIElement->pControl; 3072 if(pButtonList->CanTouchTrigger(x,y)) 3073 bPressed = true; 3074 } 3075 break; 3076 case UIControl::eTexturePackList: 3077 // trigger texturepack list on release (ONLY if the finger is still on it!) 3078 if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) 3079 { 3080 UIControl_TexturePackList *pTexturePackList=(UIControl_TexturePackList *)m_ActiveUIElement->pControl; 3081 if(pTexturePackList->CanTouchTrigger((float)x - (float)m_ActiveUIElement->x1, (float)y - (float)m_ActiveUIElement->y1)) 3082 bPressed = true; 3083 } 3084 break; 3085 case UIControl::eTextInput: 3086 // trigger TextInput on release (ONLY if the finger is still on it!) 3087 if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) 3088 bPressed = true; 3089 break; 3090 case UIControl::eDynamicLabel: 3091 // handle dynamic label scrolling 3092 UIControl_DynamicLabel *pDynamicLabel=(UIControl_DynamicLabel *)m_ActiveUIElement->pControl; 3093 pDynamicLabel->TouchScroll(y, false); 3094 break; 3095 case UIControl::eHTMLLabel: 3096 // handle dynamic label scrolling 3097 UIControl_HTMLLabel *pHtmlLabel=(UIControl_HTMLLabel *)m_ActiveUIElement->pControl; 3098 pHtmlLabel->TouchScroll(y, false); 3099 break; 3100 case UIControl::eLeaderboardList: 3101 /* no action */ 3102 break; 3103 case UIControl::eTouchControl: 3104 // trigger only if touch is released over the same component! 3105 if(m_HighlightedUIElement && m_ActiveUIElement->pControl == m_HighlightedUIElement->pControl) 3106 { 3107 // pass on touch input to relevant parent scene so we can handle it there! 3108 m_ActiveUIElement->pControl->getParentScene()->handleTouchInput(iPad, x, y, m_ActiveUIElement->pControl->getId(), bPressed, bRepeat, bReleased); 3109 } 3110 // override bReleased to false 3111 bReleased = false; 3112 break; 3113 default: 3114 app.DebugPrintf("RELEASED - UNHANDLED UI ELEMENT\n"); 3115 break; 3116 } 3117 } 3118 3119 // only proceed if there's input to be handled 3120 if(bPressed || bRepeat || bReleased) 3121 { 3122 SendTouchInput(iPad, key, bPressed, bRepeat, bReleased); 3123 } 3124} 3125 3126void UIController::SendTouchInput(unsigned int iPad, unsigned int key, bool bPressed, bool bRepeat, bool bReleased) 3127{ 3128 bool handled = false; 3129 3130 // Send the key to the fullscreen group first 3131 m_groups[(int)eUIGroup_Fullscreen]->handleInput(iPad, key, bRepeat, bPressed, bReleased, handled); 3132 if(!handled) 3133 { 3134 // If it's not been handled yet, then pass the event onto the players specific group 3135 m_groups[(iPad+1)]->handleInput(iPad, key, bRepeat, bPressed, bReleased, handled); 3136 } 3137} 3138 3139 3140#endif