2320 lines
77 KiB
C++
2320 lines
77 KiB
C++
//
|
|
// camera/system/CameraManager.cpp
|
|
//
|
|
// Copyright (C) 1999-2011 Rockstar Games. All Rights Reserved.
|
|
//
|
|
|
|
#include "camera/system/CameraManager.h"
|
|
|
|
#include "bank/bkmgr.h"
|
|
|
|
#include "fwanimation/directorcomponentmotiontree.h"
|
|
#include "grcore/debugdraw.h"
|
|
#include "grcore/quads.h"
|
|
#include "fwsys/gameskeleton.h"
|
|
#include "fwsys/timer.h"
|
|
#include "system/bootmgr.h"
|
|
|
|
#include "audio/frontendaudioentity.h"
|
|
#include "debug/Bar.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/base/BaseDirector.h"
|
|
#include "camera/cinematic/CinematicDirector.h"
|
|
#include "camera/cinematic/camera/animated/CinematicAnimatedCamera.h"
|
|
#include "camera/cinematic/camera/mounted/CinematicMountedCamera.h"
|
|
#include "camera/cinematic/camera/tracking/CinematicTrainTrackCamera.h"
|
|
#include "camera/cinematic/camera/tracking/CinematicFirstPersonIdleCamera.h"
|
|
#include "camera/cutscene/CutsceneDirector.h"
|
|
#include "camera/debug/FreeCamera.h"
|
|
#include "camera/gameplay/GameplayDirector.h"
|
|
#include "camera/gameplay/ThirdPersonCamera.h"
|
|
#include "camera/gameplay/aim/FirstPersonShooterCamera.h"
|
|
#include "camera/helpers/ControlHelper.h"
|
|
#include "camera/helpers/Envelope.h"
|
|
#include "camera/helpers/FrameInterpolator.h"
|
|
#include "camera/helpers/FramePropagator.h"
|
|
#include "camera/helpers/FrameShaker.h"
|
|
#include "camera/helpers/NearClipScanner.h"
|
|
#include "camera/replay/ReplayDirector.h"
|
|
#include "camera/scripted/ScriptDirector.h"
|
|
#include "camera/scripted/ScriptedCamera.h"
|
|
#include "camera/system/CameraFactory.h"
|
|
#include "camera/system/CameraMetadata.h"
|
|
#include "camera/viewports/ViewportManager.h"
|
|
#include "cutscene/CutSceneManagerNew.h"
|
|
#include "peds/ped.h"
|
|
#include "renderer/PostProcessFXHelper.h"
|
|
#include "script/script.h"
|
|
#include "system/controlMgr.h"
|
|
#include "scene/EntityIterator.h"
|
|
#include "scene/playerswitch/PlayerSwitchInterface.h"
|
|
#include "text/TextConversion.h"
|
|
#include "weapons/Weapon.h"
|
|
#include "vehicles/MetaData/VehicleSeatInfo.h"
|
|
|
|
bool DebugDisplayHangingCamera(void* pItem, void* UNUSED_PARAM(data));
|
|
|
|
CAMERA_OPTIMISATIONS()
|
|
|
|
#if __BANK
|
|
PARAM(cameraWidgets, "[camManager] Create camera widget bank on game launch");
|
|
#endif // __BANK
|
|
|
|
//NOTE: These thresholds are intended to reject invalid cut reports, rather than detect cuts.
|
|
const float g_MinTranslation2ForPositionCut = (0.01f * 0.01f);
|
|
const float g_MinRotationForOrientationCut = (0.5f * DtoR);
|
|
|
|
atArray<RegdCamBaseDirector> camManager::ms_Directors;
|
|
atArray<tRenderedCameraObjectSettings> camManager::ms_RenderedDirectors;
|
|
atArray<tRenderedCameraObjectSettings> camManager::ms_RenderedCameras;
|
|
RegdConstCamBaseDirector camManager::ms_DominantRenderedDirector;
|
|
RegdConstCamBaseCamera camManager::ms_DominantRenderedCamera;
|
|
|
|
RegdPed camManager::ms_PedMadeInvisible;
|
|
RegdVeh camManager::ms_VehicleMadeInvisible;
|
|
|
|
camFramePropagator camManager::ms_FramePropagator;
|
|
|
|
#if FPS_MODE_SUPPORTED
|
|
atHashString camManager::ms_FirstPersonFlashEffectName[camManager::FIRST_PERSON_FLASH_EFFECT_COUNT] =
|
|
{
|
|
atHashString("CamPushInNeutral", 0x15b714f1), // CAM_PUSH_IN_FX_NEUTRAL
|
|
atHashString("CamPushInMichael", 0xb040f488), // CAM_PUSH_IN_FX_MICHAEL
|
|
atHashString("CamPushInFranklin", 0xee41dacb), // CAM_PUSH_IN_FX_FRANKLIN
|
|
atHashString("CamPushInTrevor", 0xe3bb0589) // CAM_PUSH_IN_FX_TREVOR
|
|
};
|
|
|
|
camManager::eFirstPersonFlashEffectType camManager::ms_CurrentFirstPersonFlashEffect = camManager::CAM_PUSH_IN_FX_NEUTRAL;
|
|
camManager::eFirstPersonFlashEffectType camManager::ms_PendingFirstPersonFlashEffect = camManager::CAM_PUSH_IN_FX_NEUTRAL;
|
|
|
|
bool camManager::ms_IsRenderingFirstPersonShooterCamera = false;
|
|
bool camManager::ms_IsRenderingFirstPersonShooterCustomFallBackCamera = false;
|
|
bool camManager::ms_SuppressFirstPersonFlashEffectThisFrame = false;
|
|
u32 camManager::ms_TriggerFirstPersonFlashEffectTime = 0;
|
|
bool camManager::ms_WasInFirstPersonMode = false;
|
|
|
|
#if __BANK
|
|
atHashString camManager::ms_FirstPersonFlashEffectCallingContext;
|
|
atHashString camManager::ms_LastFirstPersonFlashContext;
|
|
u32 camManager::ms_LastFirstPersonFlashTime=0;
|
|
atHashString camManager::ms_LastFirstPersonFlashAbortReason;
|
|
u32 camManager::ms_LastFirstPersonFlashAbortTime=0;
|
|
#endif //__BANK
|
|
#endif // FPS_MODE_SUPPORTED
|
|
|
|
#if __BANK
|
|
RegdConstCamBaseCamera camManager::ms_DebugSelectedCamera;
|
|
RegdConstCamBaseDirector camManager::ms_DebugSelectedDirector;
|
|
camEnvelopeMetadata camManager::ms_DebugFullScreenBlurEffectEnvelopeMetadata;
|
|
camEnvelope* camManager::ms_DebugFullScreenBlurEffectEnvelope = NULL;
|
|
bool camManager::ms_ShouldDebugFullScreenBlurEffectUseGameTime = true;
|
|
bool camManager::ms_ShouldDebugRenderCameraTable = false;
|
|
bool camManager::ms_ShouldDebugRenderCameras = false;
|
|
bool camManager::ms_ShouldDebugRenderCameraFarClip = false;
|
|
bool camManager::ms_ShouldDebugRenderCameraNearDof = false;
|
|
bool camManager::ms_ShouldDebugRenderCameraFarDof = false;
|
|
bool camManager::ms_ShouldDebugRenderThirdLines = false;
|
|
bool camManager::ms_ShouldRenderCameraInfo = false;
|
|
bool camManager::ms_ShouldRenderUnapprovedAnimatedCameraText = false;
|
|
float camManager::ms_UnapprovedAnimatedCameraTextTimer = 0.0f;
|
|
u8 camManager::ms_DebugRenderOption = 0;
|
|
|
|
rage::atVector<camManager::DebugScriptCommand> camManager::ms_DebugRegisteredScriptCommands;
|
|
|
|
#if GTA_REPLAY
|
|
bool camManager::ms_DebugReplayCameraMovementDisabledThisFrame = false;
|
|
bool camManager::ms_DebugReplayCameraMovementDisabledThisFrameScript = false;
|
|
#endif // GTA_REPLAY
|
|
#endif // __BANK
|
|
|
|
#if __BANK
|
|
camShakeDebugger camManager::ms_ShakeDebugger;
|
|
#endif
|
|
|
|
#if __BANK
|
|
const u8 g_DebugRenderTableRowOffset = 3;
|
|
const u8 g_DebugRenderTableColumnOffset = 14;
|
|
const u8 g_DebugRenderTableColumnWidths[22] =
|
|
{
|
|
6, // DIRECTOR_NAME_COLUMN
|
|
3, // DIRECTOR_BLEND_COLUMN
|
|
3, // SELECTED_COLUMN
|
|
45, // CAMERA_NAME_COLUMN
|
|
3, // UPDATING_COLUMN
|
|
3, // BLEND_COLUMN
|
|
8, // POSITION_X_COLUMN
|
|
8, // POSITION_Y_COLUMN
|
|
7, // POSITION_Z_COLUMN
|
|
7, // ORIENTATION_P_COLUMN
|
|
8, // ORIENTATION_R_COLUMN
|
|
7, // ORIENTATION_Y_COLUMN
|
|
7, // NEAR_CLIP_COLUMN
|
|
7, // FAR_CLIP_COLUMN
|
|
7, // FLAGS_COLUMN
|
|
8, // DOF_1_COLUMN
|
|
8, // DOF_2_COLUMN
|
|
8, // DOF_3_COLUMN
|
|
8, // DOF_4_COLUMN
|
|
6, // FOV_COLUMN
|
|
6, // MOTION_BLUR_COLUMN
|
|
6, // INFO_COLUMN
|
|
};
|
|
const Color32 g_DebugRenderTableColumnColors[22] =
|
|
{
|
|
Color_black, // DIRECTOR_NAME_COLUMN
|
|
Color_black, // DIRECTOR_BLEND_COLUMN
|
|
Color_black, // SELECTED_COLUMN
|
|
Color_black, // CAMERA_NAME_COLUMN
|
|
Color_black, // UPDATING_COLUMN
|
|
Color_black, // BLEND_COLUMN
|
|
Color_grey30,// POSITION_X_COLUMN
|
|
Color_grey30,// POSITION_Y_COLUMN
|
|
Color_grey30,// POSITION_Z_COLUMN
|
|
Color_black, // ORIENTATION_P_COLUMN
|
|
Color_black, // ORIENTATION_R_COLUMN
|
|
Color_black, // ORIENTATION_Y_COLUMN
|
|
Color_grey30,// NEAR_CLIP_COLUMN
|
|
Color_grey30,// FAR_CLIP_COLUMN
|
|
Color_black, // FLAGS_COLUMN
|
|
Color_grey30,// DOF_1_COLUMN
|
|
Color_grey30,// DOF_2_COLUMN
|
|
Color_grey30,// DOF_3_COLUMN
|
|
Color_grey30,// DOF_4_COLUMN
|
|
Color_black, // FOV_COLUMN
|
|
Color_grey30,// MOTION_BLUR_COLUMN
|
|
Color_black, // INFO_COLUMN
|
|
};
|
|
#endif // __BANK
|
|
|
|
#if RSG_PC
|
|
float camManager::ms_fStereoConvergence = 1.0f;
|
|
#endif
|
|
|
|
void camManager::Init(unsigned initMode)
|
|
{
|
|
USE_MEMBUCKET(MEMBUCKET_GAMEPLAY);
|
|
|
|
if(initMode == INIT_SESSION)
|
|
{
|
|
camFactory::Init();
|
|
|
|
//Create the directors.
|
|
const camMetadataStore* metadataStore = camFactory::GetMetadataStore();
|
|
if(metadataStore)
|
|
{
|
|
const int numDirectors = metadataStore->m_DirectorList.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
const camBaseDirectorMetadata* metadata = metadataStore->m_DirectorList[i];
|
|
if(metadata)
|
|
{
|
|
camBaseDirector* director = camFactory::CreateObject<camBaseDirector>(*metadata);
|
|
if(cameraVerifyf(director, "Failed to create a camera director (name: %s, hash: %u)",
|
|
SAFE_CSTRING(metadata->m_Name.GetCStr()), metadata->m_Name.GetHash()))
|
|
{
|
|
ms_Directors.Grow() = director;
|
|
}
|
|
}
|
|
}
|
|
#if __BANK
|
|
ms_ShakeDebugger.Initialise(*metadataStore);
|
|
#endif
|
|
}
|
|
#if __BANK
|
|
LoadUnapprovedList();
|
|
|
|
DebugInitFullScreenBlurEffect();
|
|
#endif // __BANK
|
|
|
|
camInterface::Init();
|
|
|
|
ms_RenderedDirectors.Reset();
|
|
ms_RenderedCameras.Reset();
|
|
ms_DominantRenderedDirector = NULL;
|
|
ms_DominantRenderedCamera = NULL;
|
|
|
|
ms_FramePropagator.Init();
|
|
}
|
|
}
|
|
|
|
void camManager::Shutdown(unsigned shutdownMode)
|
|
{
|
|
USE_MEMBUCKET(MEMBUCKET_GAMEPLAY);
|
|
|
|
if(shutdownMode == SHUTDOWN_SESSION)
|
|
{
|
|
camInterface::Shutdown();
|
|
|
|
//Clean up the directors.
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
camBaseDirector* director = ms_Directors[i];
|
|
if(director)
|
|
{
|
|
delete director;
|
|
}
|
|
}
|
|
|
|
ms_Directors.Reset();
|
|
ms_RenderedDirectors.Reset();
|
|
ms_RenderedCameras.Reset();
|
|
ms_DominantRenderedDirector = NULL;
|
|
ms_DominantRenderedCamera = NULL;
|
|
ms_FramePropagator.Shutdown();
|
|
#if __BANK
|
|
ms_UnapprovedCameraLists.m_UnapprovedAnimatedCameras.Reset();
|
|
|
|
DebugAbortFullScreenBlurEffect();
|
|
|
|
ms_ShakeDebugger.Shutdown();
|
|
#endif // __BANK
|
|
|
|
#if __DEV
|
|
camBaseCamera::GetPool()->ForAll(DebugDisplayHangingCamera, NULL);
|
|
#endif // __DEV
|
|
|
|
camBaseCamera::GetPool()->DeleteAll(); //Guarantee the pool is empty.
|
|
|
|
camFactory::Shutdown();
|
|
}
|
|
}
|
|
|
|
void camManager::Update()
|
|
{
|
|
PF_PUSH_TIMEBAR_DETAIL("Camera Manager Update");
|
|
|
|
const CPed* followPed = camInterface::FindFollowPed();
|
|
bool isPlayerPed = followPed && followPed->GetPlayerInfo();
|
|
bool wasInFirstPersonMode = false;
|
|
|
|
#if FPS_MODE_SUPPORTED
|
|
if(isPlayerPed)
|
|
{
|
|
wasInFirstPersonMode = ms_WasInFirstPersonMode;
|
|
}
|
|
#endif
|
|
|
|
UpdateInternal();
|
|
|
|
bool inFirstPersonMode = false;
|
|
bool secondUpdateOnPlayerPed = false;
|
|
bool secondUpdateOnPlayerWeapon = false;
|
|
CWeapon* pWeapon = NULL;
|
|
CPed* followPedNonConst = NULL;
|
|
|
|
if(isPlayerPed)
|
|
{
|
|
followPedNonConst = const_cast<CPed*>(followPed);
|
|
inFirstPersonMode = followPed->IsFirstPersonShooterModeEnabledForPlayer(false, false, true);
|
|
secondUpdateOnPlayerPed = followPed->GetIsInCover() || followPed->GetPedResetFlag(CPED_RESET_FLAG_CheckFPSSwitchInCameraUpdate);
|
|
|
|
pWeapon = followPedNonConst->GetWeaponManager() ? followPedNonConst->GetWeaponManager()->GetEquippedWeapon() : NULL;
|
|
if(pWeapon)
|
|
{
|
|
if(pWeapon->GetWeaponHash() == ATSTRINGHASH("WEAPON_MICROSMG", 0x13532244) &&
|
|
camInterface::GetGameplayDirector().IsFirstPersonModeEnabled() &&
|
|
(camInterface::GetGameplayDirector().GetFirstPersonShooterCamera() == NULL ||
|
|
camInterface::IsDominantRenderedDirector(camInterface::GetScriptDirector()) ||
|
|
camInterface::GetScriptDirector().IsRendering()))
|
|
{
|
|
secondUpdateOnPlayerWeapon = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if((inFirstPersonMode != wasInFirstPersonMode) && followPedNonConst)
|
|
{
|
|
if(secondUpdateOnPlayerPed)
|
|
{
|
|
// We need to set this so CTaskMotionInCover::ShouldRestartStateDueToCameraSwitch restarts the anims this frame
|
|
followPedNonConst->SetPlayerResetFlag(CPlayerResetFlags::PRF_CAMERA_VIEW_MODE_SWITCHED_TO_OR_FROM_FIRST_PERSON);
|
|
if(inFirstPersonMode)
|
|
followPedNonConst->SetPlayerResetFlag(CPlayerResetFlags::PRF_CAMERA_VIEW_MODE_SWITCHED_TO_FIRST_PERSON);
|
|
|
|
followPedNonConst->InstantAIUpdate();
|
|
|
|
fwAnimDirectorComponentMotionTree::SetLockedGlobal(true, fwAnimDirectorComponent::kPhasePrePhysics);
|
|
followPedNonConst->InstantAnimUpdateStart();
|
|
followPedNonConst->InstantAnimUpdateEnd();
|
|
fwAnimDirectorComponentMotionTree::SetLockedGlobal(false, fwAnimDirectorComponent::kPhasePrePhysics);
|
|
|
|
// Second camera update, now the ped should be posed correctly
|
|
UpdateInternal();
|
|
}
|
|
|
|
if(secondUpdateOnPlayerWeapon)
|
|
{
|
|
CWeapon* pWeapon = followPedNonConst->GetWeaponManager() ? followPedNonConst->GetWeaponManager()->GetEquippedWeapon() : NULL;
|
|
if(pWeapon)
|
|
{
|
|
pWeapon->ProcessAnimation(followPedNonConst);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if FPS_MODE_SUPPORTED
|
|
if(isPlayerPed)
|
|
{
|
|
ms_WasInFirstPersonMode = inFirstPersonMode;
|
|
}
|
|
#endif
|
|
|
|
#if __BANK
|
|
DebugFlushScriptCommands();
|
|
#endif //__BANK
|
|
|
|
PF_POP_TIMEBAR_DETAIL();
|
|
}
|
|
|
|
void camManager::UpdateInternal()
|
|
{
|
|
USE_MEMBUCKET(MEMBUCKET_GAMEPLAY);
|
|
|
|
camInterface::GetCutsceneDirector().UpdateGameplayCameraForFirstPersonBlendOut();
|
|
|
|
PreUpdateCameras();
|
|
|
|
//NOTE: We use a safe reference to ensure that deletion is tracked during the director updates.
|
|
RegdConstCamBaseCamera dominantRenderedCameraOnPreviousUpdate(ms_DominantRenderedCamera);
|
|
|
|
atArray<tRenderedCameraObjectSettings> tempRenderedDirectors;
|
|
atArray<tRenderedCameraObjectSettings> tempRenderedCameras;
|
|
camFrame gameplayFrame;
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
camBaseDirector* director = ms_Directors[i];
|
|
if(!director)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
director->BaseUpdate(gameplayFrame);
|
|
|
|
const float blendLevelOfDirector = director->GetInterpolationBlendLevel();
|
|
if(blendLevelOfDirector < SMALL_FLOAT)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//This director is rendering, so add it to the director list.
|
|
|
|
//First we must appropriately scale the blend levels of all directors that rendered earlier in the update.
|
|
const float blendLevelOfExistingRenderedObjects = 1.0f - blendLevelOfDirector;
|
|
|
|
const s32 numRenderedDirectors = tempRenderedDirectors.GetCount();
|
|
for(s32 directorIndex=0; directorIndex<numRenderedDirectors; directorIndex++)
|
|
{
|
|
tempRenderedDirectors[directorIndex].m_BlendLevel *= blendLevelOfExistingRenderedObjects;
|
|
}
|
|
|
|
tRenderedCameraObjectSettings* directorSettings = &tempRenderedDirectors.Grow();
|
|
directorSettings->m_Object = director;
|
|
directorSettings->m_BlendLevel = blendLevelOfDirector;
|
|
|
|
const camBaseCamera* renderedCamera = director->GetRenderedCamera();
|
|
if(!renderedCamera)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//This director is rendering a camera, so add it (and any interpolation source cameras) to the camera list.
|
|
|
|
//First we must appropriately scale the blend levels of all cameras that rendered earlier in the update.
|
|
const s32 numRenderedCameras = tempRenderedCameras.GetCount();
|
|
for(s32 cameraIndex=0; cameraIndex<numRenderedCameras; cameraIndex++)
|
|
{
|
|
tempRenderedCameras[cameraIndex].m_BlendLevel *= blendLevelOfExistingRenderedObjects;
|
|
}
|
|
|
|
tRenderedCameraObjectSettings* settings = &tempRenderedCameras.Grow();
|
|
settings->m_Object = renderedCamera;
|
|
settings->m_BlendLevel = blendLevelOfDirector;
|
|
|
|
//Now deal with any interpolation source cameras.
|
|
|
|
const camBaseCamera* interpolationDestinationCamera = renderedCamera;
|
|
while(true)
|
|
{
|
|
const camFrameInterpolator* frameInterpolator = interpolationDestinationCamera->GetFrameInterpolator();
|
|
const camBaseCamera* interpolationSourceCamera = frameInterpolator ? frameInterpolator->GetSourceCamera() : NULL;
|
|
if(!interpolationSourceCamera)
|
|
{
|
|
break;
|
|
}
|
|
|
|
const float overallBlendLevelForInterpolation = settings->m_BlendLevel;
|
|
const float blendLevelForDestinationCamera = frameInterpolator->GetBlendLevel();
|
|
const float blendLevelForSourceCamera = 1.0f - blendLevelForDestinationCamera;
|
|
if(blendLevelForSourceCamera < SMALL_FLOAT)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//Update the blend level for the interpolation destination camera, previously processed.
|
|
settings->m_BlendLevel *= blendLevelForDestinationCamera;
|
|
|
|
//Add the interpolation source camera to the list, with an appropriate blend level (ignoring any further interpolation stages for now.)
|
|
settings = &tempRenderedCameras.Grow();
|
|
settings->m_Object = interpolationSourceCamera;
|
|
settings->m_BlendLevel = overallBlendLevelForInterpolation * blendLevelForSourceCamera;
|
|
|
|
interpolationDestinationCamera = interpolationSourceCamera;
|
|
};
|
|
}
|
|
|
|
RemoveBlendedOutRenderedObjects(tempRenderedDirectors);
|
|
RemoveBlendedOutRenderedObjects(tempRenderedCameras);
|
|
|
|
ms_RenderedDirectors = tempRenderedDirectors;
|
|
ms_DominantRenderedDirector = static_cast<const camBaseDirector*>(ComputeDominantRenderedObject(ms_RenderedDirectors));
|
|
|
|
ms_RenderedCameras = tempRenderedCameras;
|
|
ms_DominantRenderedCamera = static_cast<const camBaseCamera*>(ComputeDominantRenderedObject(ms_RenderedCameras));
|
|
|
|
const camFrame& gameplayFrameOnPreviousUpdate = camInterface::GetFrame();
|
|
|
|
UpdateCutFlags(dominantRenderedCameraOnPreviousUpdate.Get(), gameplayFrameOnPreviousUpdate, gameplayFrame);
|
|
|
|
UpdatePedVisibility();
|
|
UpdateVehicleVisibility();
|
|
|
|
#if FPS_MODE_SUPPORTED
|
|
UpdateCustomFirstPersonShooterBehaviour();
|
|
#endif // FPS_MODE_SUPPORTED
|
|
|
|
#if __BANK
|
|
DebugUpdateFullScreenBlurEffect(gameplayFrame);
|
|
#endif // __BANK
|
|
|
|
CViewport* gameViewport = gVpMan.GetGameViewport();
|
|
if(gameViewport != NULL)
|
|
{
|
|
ms_FramePropagator.Propagate(gameplayFrame, ms_DominantRenderedCamera, *gameViewport);
|
|
|
|
gVpMan.CacheGameGrcViewport(gameViewport->GetGrcViewport());
|
|
gVpMan.CacheGameViewportFrame(gameViewport->GetFrame());
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
// Current camera has tracking entity
|
|
if( ms_DominantRenderedCamera )
|
|
{
|
|
camInterface::CacheCameraAttachParent(ms_DominantRenderedCamera->GetAttachParent());
|
|
}
|
|
else
|
|
{
|
|
camInterface::CacheCameraAttachParent(NULL);
|
|
}
|
|
#endif //GTA_REPLAY
|
|
|
|
|
|
camInterface::CacheFrame(gameplayFrame);
|
|
camInterface::ClearAutoResetVariables();
|
|
|
|
//NOTE: We must clear the cut states of the cameras at the end of the camera system update, rather than the start, as cuts can be reported
|
|
//prior to the camera update, such as during the script update.
|
|
ClearCameraAutoResetFlags();
|
|
|
|
camBaseFrameShaker::CleanupUnreferencedFrameShakers();
|
|
camOscillatingFrameShaker::PostUpdateClass();
|
|
|
|
#if __BANK
|
|
ms_ShouldRenderUnapprovedAnimatedCameraText = ShouldRenderUnapprovedCamerasDebugText();
|
|
|
|
if(PARAM_cameraWidgets.Get())
|
|
{
|
|
//Ensure the camera widgets have been added.
|
|
AddWidgets();
|
|
}
|
|
#endif
|
|
|
|
#if REGREF_VALIDATION
|
|
DebugDeleteUnreferencedCameras();
|
|
#endif // REGREF_VALIDATION
|
|
|
|
//NOTE: We have a fundamental update order/dependency issue between the time cycle and camera system updates. The time cycle update is
|
|
//dependent upon an up-to-date viewport (amongst other things) and the far-clip of the viewport is dependent upon the time cycle being up-to-date.
|
|
// - To work around this issue, we force an additional update of the time cycle here whenever we detect that the camera has cut position,
|
|
// as this should allow the time cycle system to take account of any change in modifiers. We then propagate the revised far-clip distance.
|
|
|
|
if((gameViewport != NULL) && gameplayFrame.GetFlags().IsFlagSet(camFrame::Flag_HasCutPosition))
|
|
{
|
|
const bool hasRevisedFarClip = ms_FramePropagator.ComputeAndPropagateRevisedFarClipFromTimeCycle(gameplayFrame, *gameViewport);
|
|
if(hasRevisedFarClip)
|
|
{
|
|
//Cache the revised viewport and camera frame.
|
|
|
|
gVpMan.CacheGameGrcViewport(gameViewport->GetGrcViewport());
|
|
gVpMan.CacheGameViewportFrame(gameViewport->GetFrame());
|
|
|
|
camInterface::SetCachedFrameOnly(gameplayFrame);
|
|
}
|
|
}
|
|
|
|
#if RSG_PC
|
|
if (GRCDEVICE.IsStereoEnabled() && GRCDEVICE.CanUseStereo())
|
|
{
|
|
CViewport* pGameViewport = gVpMan.GetGameViewport();
|
|
if (pGameViewport)
|
|
{
|
|
/*
|
|
* Don't throw this out ... needed for the future reference
|
|
*/
|
|
const grcViewport &vp = pGameViewport->GetGrcViewport();
|
|
|
|
static float g_fminValidDistance = 2.0f; // where convergence becomes 1.0
|
|
static float fmaxValidDistance = 4.0f;//GRCDEVICE.GetDefaultConvergenceDistance();
|
|
bool bSpecialCam = false;
|
|
Vector3 vCamPos = (RCC_MATRIX44(vp.GetCameraMtx44()).d.GetVector3());
|
|
Vec3V vIteratorPos = VECTOR3_TO_VEC3V(vCamPos);
|
|
CEntityIterator entityIterator(IterateAllTypes, NULL, &vIteratorPos, fmaxValidDistance);
|
|
float fClosestDist = fmaxValidDistance;
|
|
s32 vpId = pGameViewport->GetId();
|
|
static float g_prevSpecialCamConvergence = GRCDEVICE.GetDefaultConvergenceDistance();
|
|
|
|
// if playing cutscene, use special cam
|
|
if (CutSceneManager::GetInstance()->IsCutscenePlayingBack())
|
|
{
|
|
while(true)
|
|
{
|
|
CEntity* nearbyEntity = entityIterator.GetNext();
|
|
if(!nearbyEntity)
|
|
{
|
|
break;
|
|
}
|
|
else if (nearbyEntity->GetIsVisibleInViewport(vpId))
|
|
{
|
|
float fDist = vCamPos.Dist(VEC3V_TO_VECTOR3(nearbyEntity->GetTransform().GetPosition()));
|
|
if (fDist < fClosestDist)
|
|
fClosestDist = fDist;
|
|
|
|
bSpecialCam = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if in first person mode or vehicle interior cam, use special cam
|
|
if (FindPlayerPed()->IsFirstPersonShooterModeEnabledForPlayer() ||
|
|
camInterface::GetCinematicDirector().IsRenderingAnyInVehicleFirstPersonCinematicCamera())
|
|
{
|
|
bSpecialCam = true;
|
|
fClosestDist = g_fminValidDistance;
|
|
}
|
|
|
|
bSpecialCam = false;
|
|
if (bSpecialCam)
|
|
{
|
|
float t = 1.0f - ClampRange(fClosestDist, g_fminValidDistance, fmaxValidDistance);
|
|
ms_fStereoConvergence = Lerp(t,GRCDEVICE.GetDefaultConvergenceDistance(),0.0f);
|
|
}
|
|
else
|
|
{
|
|
ms_fStereoConvergence = GRCDEVICE.GetDefaultConvergenceDistance();
|
|
}
|
|
|
|
if (g_prevSpecialCamConvergence != ms_fStereoConvergence)
|
|
{
|
|
static float g_fConvergenceStep = 10.0f;//0.025f;
|
|
float fConvergenceStep = g_fConvergenceStep * (g_prevSpecialCamConvergence > ms_fStereoConvergence ? -1.0f : 1.0f);
|
|
|
|
if (g_prevSpecialCamConvergence > ms_fStereoConvergence)
|
|
ms_fStereoConvergence = Clamp(g_prevSpecialCamConvergence + fConvergenceStep, ms_fStereoConvergence, g_prevSpecialCamConvergence);
|
|
else
|
|
ms_fStereoConvergence = Clamp(g_prevSpecialCamConvergence + fConvergenceStep, g_prevSpecialCamConvergence, ms_fStereoConvergence);
|
|
}
|
|
|
|
g_prevSpecialCamConvergence = ms_fStereoConvergence;
|
|
|
|
// force convergence to be 0.0
|
|
//ms_fStereoConvergence = 0.0f;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if FPS_MODE_SUPPORTED
|
|
ms_SuppressFirstPersonFlashEffectThisFrame = false;
|
|
#endif // FPS_MODE_SUPPORTED
|
|
}
|
|
|
|
void camManager::PreUpdateCameras()
|
|
{
|
|
const s32 maxNumCameras = camBaseCamera::GetPool()->GetSize();
|
|
for(s32 i=0; i<maxNumCameras; i++)
|
|
{
|
|
camBaseCamera* camera = camBaseCamera::GetPool()->GetSlot(i);
|
|
if(camera)
|
|
{
|
|
camera->PreUpdate();
|
|
}
|
|
}
|
|
}
|
|
#if __BANK
|
|
bool camManager::ShouldRenderUnapprovedCamerasDebugText()
|
|
{
|
|
// Check cutscene is not playing
|
|
CutSceneManager *pManager = CutSceneManager::GetInstance();
|
|
if(!pManager || (pManager && !pManager->IsCutscenePlayingBack()))
|
|
{
|
|
// Check dominant camera is an animated camera
|
|
const camBaseCamera *pCamera = GetDominantRenderedCamera();
|
|
if(pCamera && pCamera->GetIsClassId(camAnimatedCamera::GetStaticClassId()))
|
|
{
|
|
// Check animated camera is not approved
|
|
const camAnimatedCamera *pAnimatedCamera = static_cast< const camAnimatedCamera * >(pCamera);
|
|
|
|
if (pAnimatedCamera->IsAnimatedCameraAnimUnapproved())
|
|
{
|
|
ms_UnapprovedAnimatedCameraTextTimer += fwTimer::GetSystemTimeStep();
|
|
if (ms_UnapprovedAnimatedCameraTextTimer <= 10.0f)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ms_UnapprovedAnimatedCameraTextTimer = 0.0f;
|
|
return false;
|
|
}
|
|
#endif // __BANK
|
|
|
|
void camManager::RemoveBlendedOutRenderedObjects(atArray<tRenderedCameraObjectSettings>& renderedObjects)
|
|
{
|
|
//Remove any objects with negligible blend levels.
|
|
for(s32 i=0; i<renderedObjects.GetCount(); )
|
|
{
|
|
tRenderedCameraObjectSettings& settings = renderedObjects[i];
|
|
if(settings.m_BlendLevel < SMALL_FLOAT)
|
|
{
|
|
//NOTE: We must NULL the object reference for safety, as Delete just shuffles the array elements.
|
|
settings.m_Object = NULL;
|
|
renderedObjects.Delete(i);
|
|
}
|
|
else
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
const camBaseObject* camManager::ComputeDominantRenderedObject(const atArray<tRenderedCameraObjectSettings>& renderedObjects)
|
|
{
|
|
//Find the rendered object with the highest blend level.
|
|
|
|
const s32 numRenderedObjects = renderedObjects.GetCount();
|
|
if(numRenderedObjects == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
const tRenderedCameraObjectSettings* dominantRenderedObjectSettings = &renderedObjects[0];
|
|
for(s32 objectIndex=1; objectIndex<numRenderedObjects; objectIndex++)
|
|
{
|
|
if(renderedObjects[objectIndex].m_BlendLevel > (dominantRenderedObjectSettings->m_BlendLevel + SMALL_FLOAT))
|
|
{
|
|
dominantRenderedObjectSettings = &renderedObjects[objectIndex];
|
|
}
|
|
}
|
|
|
|
return dominantRenderedObjectSettings->m_Object;
|
|
}
|
|
|
|
void camManager::UpdateCutFlags(const camBaseCamera* dominantRenderedCameraOnPreviousUpdate, const camFrame& renderedFrameOnPreviousUpdate,
|
|
camFrame& renderedFrame)
|
|
{
|
|
bool hasCutBetweenCameras = (ms_DominantRenderedCamera != dominantRenderedCameraOnPreviousUpdate) && (!dominantRenderedCameraOnPreviousUpdate ||
|
|
!(ms_DominantRenderedCamera && ms_DominantRenderedCamera->IsInterpolating(dominantRenderedCameraOnPreviousUpdate)));
|
|
if(hasCutBetweenCameras)
|
|
{
|
|
//Check if the dominant rendering director in interpolating from the previous camera.
|
|
const s32 numRenderedCameras = ms_RenderedCameras.GetCount();
|
|
for(s32 cameraIndex=0; cameraIndex<numRenderedCameras; cameraIndex++)
|
|
{
|
|
if(ms_RenderedCameras[cameraIndex].m_Object.Get() == dominantRenderedCameraOnPreviousUpdate)
|
|
{
|
|
hasCutBetweenCameras = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(hasCutBetweenCameras)
|
|
{
|
|
//NOTE: We have to assume that both position and orientation have cut when a camera changes occurs without interpolation, but we
|
|
//sanity-check this below.
|
|
renderedFrame.GetFlags().SetFlag(camFrame::Flag_HasCutPosition | camFrame::Flag_HasCutOrientation);
|
|
}
|
|
}
|
|
|
|
//Finally, sanity-check that the rendered position and orientation have actually changed since the previous update.
|
|
|
|
const bool hasCutPosition = renderedFrame.GetFlags().IsFlagSet(camFrame::Flag_HasCutPosition);
|
|
if(hasCutPosition)
|
|
{
|
|
const Vector3& positionOnPreviousUpdate = renderedFrameOnPreviousUpdate.GetPosition();
|
|
const Vector3& position = renderedFrame.GetPosition();
|
|
const float translation2 = positionOnPreviousUpdate.Dist2(position);
|
|
const bool hasPositionChanged = (translation2 >= g_MinTranslation2ForPositionCut);
|
|
if(!hasPositionChanged)
|
|
{
|
|
renderedFrame.GetFlags().ClearFlag(camFrame::Flag_HasCutPosition);
|
|
}
|
|
}
|
|
|
|
const bool hasCutOrientation = renderedFrame.GetFlags().IsFlagSet(camFrame::Flag_HasCutOrientation);
|
|
if(hasCutOrientation)
|
|
{
|
|
const Matrix34& worldMatrixOnPreviousUpdate = renderedFrameOnPreviousUpdate.GetWorldMatrix();
|
|
Quaternion orientationOnPreviousUpdate;
|
|
orientationOnPreviousUpdate.FromMatrix34(worldMatrixOnPreviousUpdate);
|
|
|
|
const Matrix34& worldMatrix = renderedFrame.GetWorldMatrix();
|
|
Quaternion orientation;
|
|
orientation.FromMatrix34(worldMatrix);
|
|
|
|
const float rotationAngle = orientationOnPreviousUpdate.RelAngle(orientation);
|
|
const bool hasOrientationChanged = (Abs(rotationAngle) >= g_MinRotationForOrientationCut);
|
|
if(!hasOrientationChanged)
|
|
{
|
|
renderedFrame.GetFlags().ClearFlag(camFrame::Flag_HasCutOrientation);
|
|
}
|
|
}
|
|
}
|
|
|
|
void camManager::ClearCameraAutoResetFlags()
|
|
{
|
|
const s32 maxNumCameras = camBaseCamera::GetPool()->GetSize();
|
|
for(s32 i=0; i<maxNumCameras; i++)
|
|
{
|
|
camBaseCamera* camera = camBaseCamera::GetPool()->GetSlot(i);
|
|
if(camera)
|
|
{
|
|
camera->GetFrameNonConst().GetFlags().ClearFlag(camFrame::Flag_HasCutPosition | camFrame::Flag_HasCutOrientation | camFrame::Flag_BypassNearClipScanner);
|
|
camera->GetFrameNonConst().SetCameraTimeScaleThisUpdate(1.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
void camManager::UpdatePedVisibility()
|
|
{
|
|
//NOTE: We break with the convention of treating all game entities as const in the camera update here for the purposes of optimisation.
|
|
|
|
//NOTE: We always reset the (camera) visibility state of any ped we made invisible on the previous update. This is an auto-reset mechanism for hiding
|
|
//peds in the camera system, given that the entity visibility masks are persistent.
|
|
if(ms_PedMadeInvisible.Get())
|
|
{
|
|
ModifyPedVisibility(*ms_PedMadeInvisible.Get(), true);
|
|
ms_PedMadeInvisible = NULL;
|
|
}
|
|
|
|
if(!ms_DominantRenderedCamera)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const CPed* pedToMakeInvisible = NULL;
|
|
bool includeShadows = false;
|
|
|
|
if(ms_DominantRenderedCamera->GetIsClassId(camFirstPersonAimCamera::GetStaticClassId()))
|
|
{
|
|
const camFirstPersonAimCamera* pFirstPersonAimCamera = static_cast<const camFirstPersonAimCamera*>(ms_DominantRenderedCamera.Get());
|
|
if (pFirstPersonAimCamera->ShouldMakeAttachedEntityInvisible())
|
|
{
|
|
const CEntity* entityToMakeInvisible = pFirstPersonAimCamera->GetAttachParent();
|
|
if(entityToMakeInvisible && entityToMakeInvisible->GetIsTypePed())
|
|
{
|
|
pedToMakeInvisible = static_cast<const CPed*>(entityToMakeInvisible);
|
|
}
|
|
}
|
|
}
|
|
else if(ms_DominantRenderedCamera->GetIsClassId(camCinematicMountedCamera::GetStaticClassId()))
|
|
{
|
|
pedToMakeInvisible = static_cast<const camCinematicMountedCamera*>(ms_DominantRenderedCamera.Get())->GetPedToMakeInvisible();
|
|
}
|
|
else if(ms_DominantRenderedCamera->GetIsClassId(camCinematicFirstPersonIdleCamera::GetStaticClassId()))
|
|
{
|
|
pedToMakeInvisible = static_cast<const camCinematicFirstPersonIdleCamera*>(ms_DominantRenderedCamera.Get())->GetPedToMakeInvisible();
|
|
}
|
|
#if !__FINAL //No debug cameras in final builds.
|
|
else if(ms_DominantRenderedCamera->GetIsClassId(camFreeCamera::GetStaticClassId()))
|
|
{
|
|
//Hide the follow ped if they are being carried by the debug free camera.
|
|
const bool isCarryingFollowPed = static_cast<const camFreeCamera*>(ms_DominantRenderedCamera.Get())->ComputeIsCarryingFollowPed();
|
|
if(isCarryingFollowPed)
|
|
{
|
|
pedToMakeInvisible = camInterface::FindFollowPed();
|
|
}
|
|
}
|
|
#endif // !__FINAL
|
|
|
|
if(pedToMakeInvisible)
|
|
{
|
|
ms_PedMadeInvisible = const_cast<CPed*>(pedToMakeInvisible);
|
|
ModifyPedVisibility(*ms_PedMadeInvisible.Get(), false, includeShadows);
|
|
}
|
|
}
|
|
|
|
void camManager::ModifyPedVisibility(CPed& ped, bool isVisible, bool includeShadows)
|
|
{
|
|
if(!isVisible)
|
|
{
|
|
// Assume because we're in first-person that PreRender will not be called on the attached physical, so force the physical to be
|
|
// updated in the later PreRender
|
|
ped.SetIsVisibleInSomeViewportThisFrame(true);
|
|
}
|
|
|
|
// Don't render the ped in the gbuffer, but do render in mirror reflection etc.
|
|
u16 visibilityFlags = VIS_PHASE_MASK_GBUF|VIS_PHASE_MASK_SEETHROUGH_MAP;
|
|
if (includeShadows || isVisible)
|
|
{
|
|
visibilityFlags |= VIS_PHASE_MASK_SHADOWS;
|
|
}
|
|
ped.ChangeVisibilityMask(visibilityFlags, isVisible, true);
|
|
|
|
CObject* weapon = ped.GetWeaponManager()->GetEquippedWeaponObject();
|
|
if (weapon)
|
|
{
|
|
weapon->ChangeVisibilityMask(visibilityFlags, isVisible, true);
|
|
}
|
|
}
|
|
|
|
void camManager::UpdateVehicleVisibility()
|
|
{
|
|
//NOTE: We break with the convention of treating all game entities as const in the camera update here for the purposes of optimisation and safety.
|
|
|
|
//NOTE: We always reset the (camera) visibility state of any vehicle we made invisible on the previous update. This is an auto-reset mechanism for hiding
|
|
//vehicles in the camera system, given that the entity visibility modules are persistent.
|
|
if(ms_VehicleMadeInvisible)
|
|
{
|
|
ms_VehicleMadeInvisible->SetIsVisibleForModule(SETISVISIBLE_MODULE_CAMERA, true);
|
|
ms_VehicleMadeInvisible = NULL;
|
|
}
|
|
|
|
if(!ms_DominantRenderedCamera)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if !__FINAL //No debug cameras in final builds.
|
|
if(ms_DominantRenderedCamera->GetIsClassId(camFreeCamera::GetStaticClassId()))
|
|
{
|
|
//Hide the follow ped's vehicle if they are being carried by the debug free camera.
|
|
const bool isCarryingFollowPed = static_cast<const camFreeCamera*>(ms_DominantRenderedCamera.Get())->ComputeIsCarryingFollowPed();
|
|
if(isCarryingFollowPed)
|
|
{
|
|
const CPed* followPed = camInterface::FindFollowPed();
|
|
if(followPed && followPed->GetPedConfigFlag(CPED_CONFIG_FLAG_InVehicle))
|
|
{
|
|
ms_VehicleMadeInvisible = followPed->GetMyVehicle();
|
|
}
|
|
}
|
|
}
|
|
#endif // !__FINAL
|
|
|
|
if(ms_VehicleMadeInvisible)
|
|
{
|
|
ms_VehicleMadeInvisible->SetIsVisibleForModule(SETISVISIBLE_MODULE_CAMERA, false);
|
|
}
|
|
}
|
|
|
|
#if FPS_MODE_SUPPORTED
|
|
|
|
atHashString timeElapsedString("Delay timer elapsed");
|
|
|
|
void camManager::UpdateCustomFirstPersonShooterBehaviour()
|
|
{
|
|
ms_IsRenderingFirstPersonShooterCamera = false;
|
|
ms_IsRenderingFirstPersonShooterCustomFallBackCamera = false;
|
|
|
|
const camGameplayDirector& gameplayDirector = camInterface::GetGameplayDirector();
|
|
|
|
const atArray<tRenderedCameraObjectSettings>& renderedCameras = GetRenderedCameras();
|
|
const s32 numRenderedCameras = renderedCameras.GetCount();
|
|
|
|
for(s32 cameraIndex=0; cameraIndex<numRenderedCameras; cameraIndex++)
|
|
{
|
|
const camBaseObject* object = renderedCameras[cameraIndex].m_Object;
|
|
if(object && object->GetIsClassId(camBaseCamera::GetStaticClassId()))
|
|
{
|
|
const camBaseCamera* camera = static_cast<const camBaseCamera*>(object);
|
|
if(camera->GetIsClassId(camFirstPersonShooterCamera::GetStaticClassId()))
|
|
{
|
|
ms_IsRenderingFirstPersonShooterCamera = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!ms_IsRenderingFirstPersonShooterCamera && camInterface::IsRenderingDirector(gameplayDirector) && gameplayDirector.IsFallingBackToThirdPersonForDirectorBlendCatchUpOrSwitch())
|
|
{
|
|
ms_IsRenderingFirstPersonShooterCustomFallBackCamera = true;
|
|
}
|
|
|
|
if (ms_TriggerFirstPersonFlashEffectTime>0 && ms_TriggerFirstPersonFlashEffectTime<=fwTimer::GetTimeInMilliseconds())
|
|
{
|
|
const char * contextString = "";
|
|
#if !__FINAL && !__NO_OUTPUT
|
|
contextString = SAFE_CSTRING(timeElapsedString.GetCStr());
|
|
#else // !__FINAL && !__NO_OUTPUT
|
|
contextString = "";
|
|
#endif // !__FINAL && !__NO_OUTPUT
|
|
|
|
TriggerFirstPersonFlashEffect(ms_PendingFirstPersonFlashEffect, 0 , contextString);
|
|
}
|
|
}
|
|
|
|
const char * camManager::GetFirstPersonFlashEffectName(eFirstPersonFlashEffectType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case CAM_PUSH_IN_FX_NEUTRAL:
|
|
return "NEUTRAL";
|
|
case CAM_PUSH_IN_FX_MICHAEL:
|
|
return "MICHAEL";
|
|
case CAM_PUSH_IN_FX_FRANKLIN:
|
|
return "FRANKLIN";
|
|
case CAM_PUSH_IN_FX_TREVOR:
|
|
return "TREVOR";
|
|
case FIRST_PERSON_FLASH_EFFECT_COUNT:
|
|
return "INVALID!";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
void camManager::TriggerFirstPersonFlashEffect(eFirstPersonFlashEffectType flashType, u32 delay, const char * BANK_ONLY(debugContext))
|
|
{
|
|
if (ms_SuppressFirstPersonFlashEffectThisFrame)
|
|
{
|
|
// Flashes suppressed by an external system. Early out now
|
|
if (ms_TriggerFirstPersonFlashEffectTime<=fwTimer::GetTimeInMilliseconds())
|
|
{
|
|
// clear the pendign flash, if appropriate
|
|
AbortPendingFirstPersonFlashEffect("Flashes suppressed");
|
|
}
|
|
return;
|
|
}
|
|
|
|
#if __BANK
|
|
atHashString oldContext = ms_FirstPersonFlashEffectCallingContext;
|
|
ms_FirstPersonFlashEffectCallingContext.SetFromString(debugContext);
|
|
#endif // __BANK
|
|
|
|
BANK_ONLY(cameraDisplayf("[%d|%d] First person flash triggered from %s, type:%s delay:%d", fwTimer::GetFrameCount(), fwTimer::GetTimeInMilliseconds(), debugContext, GetFirstPersonFlashEffectName(flashType), delay));
|
|
#if __BANK
|
|
ms_LastFirstPersonFlashAbortTime = 0;
|
|
#endif //__BANK
|
|
// we're going to trigger the flash in the future.
|
|
// set the timer so we'll trigger it later
|
|
if (delay>0)
|
|
{
|
|
ms_PendingFirstPersonFlashEffect = flashType;
|
|
ms_TriggerFirstPersonFlashEffectTime = fwTimer::GetTimeInMilliseconds()+delay;
|
|
}
|
|
else
|
|
{
|
|
// trigger
|
|
ANIMPOSTFXMGR.Stop(ms_FirstPersonFlashEffectName[ms_CurrentFirstPersonFlashEffect],AnimPostFXManager::kCameraFlash);
|
|
ms_CurrentFirstPersonFlashEffect = flashType;
|
|
ANIMPOSTFXMGR.Start(ms_FirstPersonFlashEffectName[ms_CurrentFirstPersonFlashEffect], 0, false, false, false, 0, AnimPostFXManager::kCameraFlash);
|
|
// Trigger woosh audio
|
|
g_FrontendAudioEntity.PlaySound(ATSTRINGHASH("1st_Person_Transition", 0xC8FFEA2F),"PLAYER_SWITCH_CUSTOM_SOUNDSET");
|
|
|
|
#if __BANK
|
|
// remmeber the time and the context of the last flash so we can debug render it.
|
|
ms_LastFirstPersonFlashTime = fwTimer::GetTimeInMilliseconds();
|
|
if (ms_FirstPersonFlashEffectCallingContext.GetHash()==timeElapsedString.GetHash())
|
|
{
|
|
ms_LastFirstPersonFlashContext = oldContext;
|
|
}
|
|
else
|
|
{
|
|
ms_LastFirstPersonFlashContext = ms_FirstPersonFlashEffectCallingContext;
|
|
}
|
|
#endif // __BANK
|
|
|
|
ms_PendingFirstPersonFlashEffect = camManager::CAM_PUSH_IN_FX_NEUTRAL;
|
|
ms_TriggerFirstPersonFlashEffectTime = 0;
|
|
camInterface::GetGameplayDirector().UseSwitchCustomFovBlend();
|
|
}
|
|
}
|
|
|
|
void camManager::AbortPendingFirstPersonFlashEffect(const char * BANK_ONLY(abortReason))
|
|
{
|
|
if (ms_TriggerFirstPersonFlashEffectTime>0)
|
|
{
|
|
#if __BANK
|
|
ms_LastFirstPersonFlashAbortReason = abortReason;
|
|
ms_LastFirstPersonFlashAbortTime=fwTimer::GetTimeInMilliseconds();
|
|
cameraDisplayf("[%d|%d] First person flash ABORTED by %s (started by %s)", fwTimer::GetFrameCount(), fwTimer::GetTimeInMilliseconds(), abortReason, SAFE_CSTRING(ms_FirstPersonFlashEffectCallingContext.GetCStr()));
|
|
#endif // __BANK
|
|
ms_PendingFirstPersonFlashEffect = camManager::CAM_PUSH_IN_FX_NEUTRAL;
|
|
ms_TriggerFirstPersonFlashEffectTime = 0;
|
|
}
|
|
}
|
|
|
|
|
|
bool camManager::IsRenderingFirstPersonCamera()
|
|
{
|
|
return CGame::IsSessionInitialized() && (ms_IsRenderingFirstPersonShooterCamera || camInterface::GetCinematicDirector().IsRenderingAnyInVehicleFirstPersonCinematicCamera());
|
|
}
|
|
#endif // FPS_MODE_SUPPORTED
|
|
|
|
camBaseDirector* camManager::FindDirector(const atHashWithStringNotFinal& classIdToFind)
|
|
{
|
|
camBaseDirector* requestedDirector = NULL;
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
camBaseDirector* director = ms_Directors[i];
|
|
if(director && (director->GetClassId() == classIdToFind.GetHash()))
|
|
{
|
|
requestedDirector = director;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return requestedDirector;
|
|
}
|
|
|
|
u32 camManager::ComputeNumDirectorsInterpolating()
|
|
{
|
|
u32 numDirectorsInterpolating = 0;
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
camBaseDirector* director = ms_Directors[i];
|
|
if(director && director->IsInterpolating())
|
|
{
|
|
numDirectorsInterpolating++;
|
|
}
|
|
}
|
|
|
|
return numDirectorsInterpolating;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Debug support
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if REGREF_VALIDATION
|
|
void camManager::DebugDeleteUnreferencedCameras()
|
|
{
|
|
const s32 maxNumCameras = camBaseCamera::GetPool()->GetSize();
|
|
for(s32 i=0; i<maxNumCameras; i++)
|
|
{
|
|
camBaseCamera* camera = camBaseCamera::GetPool()->GetSlot(i);
|
|
if(camera && (camera->CountAllKnownRefs() == 0))
|
|
{
|
|
cameraWarningf("Found and deleted an unreferenced camera (%s)", SAFE_CSTRING(camera->GetName()));
|
|
delete camera;
|
|
}
|
|
}
|
|
}
|
|
#endif // REGREF_VALIDATION
|
|
|
|
#if __BANK
|
|
void camManager::DebugRender()
|
|
{
|
|
//keyboard input
|
|
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_C, KEYBOARD_MODE_DEBUG_ALT, "Cycle through camera debug displays"))
|
|
DebugCycleRenderOptions();
|
|
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_C, KEYBOARD_MODE_DEBUG_CNTRL_ALT, "Turn camera debug display off"))
|
|
DebugClearDisplay();
|
|
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_UP, KEYBOARD_MODE_DEBUG_ALT, "Select previous camera"))
|
|
DebugSelectPreviousCamera();
|
|
if (CControlMgr::GetKeyboard().GetKeyJustDown(KEY_DOWN, KEYBOARD_MODE_DEBUG_ALT, "Select next camera"))
|
|
DebugSelectNextCamera();
|
|
|
|
//NOTE: We sanity check our selected camera and director prior to anything,
|
|
//so that it will work regardless of the camera table being rendered or not.
|
|
if (ms_DebugSelectedDirector == NULL || ms_DebugSelectedCamera == NULL)
|
|
{
|
|
DebugSelectValidation();
|
|
}
|
|
|
|
grcDebugDraw::TextFontPush(grcSetup::GetMiniFixedWidthFont());
|
|
|
|
if(ms_ShouldDebugRenderCameraTable)
|
|
{
|
|
DebugRenderCameraTable();
|
|
}
|
|
|
|
grcDebugDraw::TextFontPop();
|
|
|
|
if(ms_ShouldDebugRenderThirdLines)
|
|
{
|
|
DebugRenderThirdLines();
|
|
}
|
|
|
|
if(ms_ShouldDebugRenderCameras)
|
|
{
|
|
DebugRenderCameras();
|
|
}
|
|
}
|
|
|
|
void camManager::ResetDebugVariables()
|
|
{
|
|
#if GTA_REPLAY
|
|
ms_DebugReplayCameraMovementDisabledThisFrame = false;
|
|
ms_DebugReplayCameraMovementDisabledThisFrameScript = false;
|
|
#endif // GTA_REPLAY
|
|
}
|
|
|
|
void camManager::Render()
|
|
{
|
|
// Check debug text should be displayed
|
|
if(CDebugBar::GetDisplayReleaseDebugText() == DEBUG_DISPLAY_STATE_STANDARD && ms_ShouldRenderUnapprovedAnimatedCameraText == true)
|
|
{
|
|
float CameraUnapproved_X = 0.800f;
|
|
float CameraUnapproved_Y = 0.90f;
|
|
float scaleX = 0.40f;
|
|
float scaleY = 0.40f;
|
|
|
|
CTextLayout DebugText;
|
|
DebugText.SetScale(Vector2(scaleX, scaleY));
|
|
DebugText.SetColor(CRGBA(255,255,255,255));
|
|
DebugText.SetDropShadow(true);
|
|
|
|
DebugText.Render(Vector2(CameraUnapproved_X, CameraUnapproved_Y), "Camera anim not approved" );
|
|
}
|
|
}
|
|
|
|
void camManager::DebugRenderCameraTable()
|
|
{
|
|
u8 rowIndex = 0;
|
|
|
|
//Draw column titles.
|
|
DebugRenderTableEntry(DIRECTOR_NAME_COLUMN, rowIndex, "");
|
|
DebugRenderTableEntry(DIRECTOR_BLEND_COLUMN, rowIndex, "B");
|
|
DebugRenderTableEntry(SELECTED_COLUMN, rowIndex, "");
|
|
DebugRenderTableEntry(CAMERA_NAME_COLUMN, rowIndex, "Name");
|
|
DebugRenderTableEntry(UPDATING_COLUMN, rowIndex, "U");
|
|
DebugRenderTableEntry(BLEND_COLUMN, rowIndex, "B");
|
|
DebugRenderTableEntry(POSITION_X_COLUMN, rowIndex, "Position", g_DebugRenderTableColumnColors[POSITION_X_COLUMN], ORIENTATION_P_COLUMN);
|
|
DebugRenderTableEntry(ORIENTATION_P_COLUMN, rowIndex, "Orientation P-R-Y", g_DebugRenderTableColumnColors[ORIENTATION_P_COLUMN], NEAR_CLIP_COLUMN);
|
|
DebugRenderTableEntry(NEAR_CLIP_COLUMN, rowIndex, "Clip", g_DebugRenderTableColumnColors[NEAR_CLIP_COLUMN], FLAGS_COLUMN);
|
|
DebugRenderTableEntry(FLAGS_COLUMN, rowIndex, "Flags");
|
|
DebugRenderTableEntry(DOF_1_COLUMN, rowIndex, "DOF", g_DebugRenderTableColumnColors[DOF_1_COLUMN], FOV_COLUMN);
|
|
DebugRenderTableEntry(FOV_COLUMN, rowIndex, "FOV");
|
|
DebugRenderTableEntry(MOTION_BLUR_COLUMN, rowIndex, "MBlur");
|
|
DebugRenderTableEntry(INFO_COLUMN, rowIndex, "Info");
|
|
|
|
//Draw rows for each director, in order of update.
|
|
rowIndex = rowIndex + 2; //blank row after headings
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
const camBaseDirector* director = ms_Directors[i];
|
|
if(director)
|
|
{
|
|
DebugRenderDirectorText(director, rowIndex);
|
|
}
|
|
}
|
|
|
|
++rowIndex;
|
|
DebugRenderFinalFrameText(rowIndex);
|
|
|
|
rowIndex += 2; //Blank row after final row
|
|
DebugRenderGlobalState(rowIndex);
|
|
|
|
DebugRenderScriptCommands(rowIndex);
|
|
}
|
|
|
|
void camManager::DebugRenderDirectorText(const camBaseDirector* director, u8& rowIndex)
|
|
{
|
|
Color32 blendTextColour = Color_default;
|
|
|
|
//Draw the director name
|
|
atString directorName = atString(director->GetName());
|
|
directorName.Set(directorName, 0, g_DebugRenderTableColumnWidths[DIRECTOR_NAME_COLUMN] - 1); //trimming it down
|
|
DebugRenderTableEntry(DIRECTOR_NAME_COLUMN, rowIndex, SAFE_CSTRING(directorName.c_str()));
|
|
|
|
//Draw the director blend
|
|
char blendText[5] = "X";
|
|
float blendValue = GetBlendValueForDirector(director);
|
|
if ( blendValue > -SMALL_FLOAT )
|
|
{
|
|
const Color32 textRedColour = Color_red3;
|
|
const Color32 textOrangeColour = Color_orange;
|
|
const Color32 textGreenColour = Color_ForestGreen;
|
|
|
|
blendTextColour =
|
|
(blendValue < 0.5f) ? Lerp(blendValue/0.5f, textRedColour, textOrangeColour)
|
|
: Lerp((blendValue-0.5f)/0.5f, textOrangeColour, textGreenColour);
|
|
|
|
if (!AreNearlyEqual(blendValue, 1.0f))
|
|
sprintf(blendText, "%02u", (unsigned int)FloorfFast(blendValue*100));
|
|
else
|
|
sprintf(blendText, "F");
|
|
}
|
|
DebugRenderTableEntry(DIRECTOR_BLEND_COLUMN, rowIndex, blendText, blendTextColour);
|
|
|
|
//Get all cameras owned by this director
|
|
atArray<camBaseCamera*> cameras;
|
|
cameras.Reset();
|
|
director->DebugGetCameras(cameras);
|
|
const int numCameras = cameras.GetCount();
|
|
|
|
//Draw camera columns
|
|
for(int i=0; i<numCameras; i++)
|
|
{
|
|
DebugRenderCameraText(cameras[i], rowIndex);
|
|
}
|
|
|
|
if (numCameras == 0)
|
|
{
|
|
//if there's no cameras here, we draw a blank selected column (unless we're the selected director!)
|
|
DebugRenderTableEntry(SELECTED_COLUMN, rowIndex, (ms_DebugSelectedDirector == director) ? "*" : "");
|
|
|
|
for (u8 i = CAMERA_NAME_COLUMN; i < NUM_DEBUG_RENDER_COLUMNS; ++i)
|
|
{
|
|
DebugRenderTableEntry(i, rowIndex, "");
|
|
}
|
|
|
|
++rowIndex;
|
|
}
|
|
}
|
|
|
|
void camManager::DebugRenderCameraText(const camBaseCamera* camera, u8& rowIndex, bool isFinal)
|
|
{
|
|
const camFrame frame = isFinal ? camInterface::GetFrame() : camera->GetFrame();
|
|
char debugText[10];
|
|
|
|
const Color32 textRedColour = Color_red3;
|
|
const Color32 textOrangeColour = Color_orange;
|
|
const Color32 textGreenColour = Color_ForestGreen;
|
|
Color32 blendTextColour = Color_default;
|
|
|
|
//Get blend value for this camera
|
|
float blendValue = GetBlendValueForCamera(camera);
|
|
if ( blendValue > -SMALL_FLOAT && !isFinal )
|
|
{
|
|
blendTextColour =
|
|
(blendValue < 0.5f) ? Lerp(blendValue/0.5f, textRedColour, textOrangeColour)
|
|
: Lerp((blendValue-0.5f)/0.5f, textOrangeColour, textGreenColour);
|
|
}
|
|
|
|
//Draw the selected column.
|
|
if (!isFinal)
|
|
{
|
|
DebugRenderTableEntry(SELECTED_COLUMN, rowIndex, (ms_DebugSelectedCamera == camera) ? "*" : "");
|
|
}
|
|
|
|
//Draw the name column.
|
|
atString name = atString(camera->GetName());
|
|
//remove _CAMERA if it's at the end
|
|
if (name.length() > 7)
|
|
{
|
|
atString endOfName;
|
|
endOfName.Set(name, name.length() - 7, name.length());
|
|
if (endOfName == "_CAMERA")
|
|
{
|
|
name.Set(name, 0, name.length() - 7);
|
|
}
|
|
}
|
|
|
|
//cut down to max size
|
|
const int maxLength = Min((int)name.length(), g_DebugRenderTableColumnWidths[CAMERA_NAME_COLUMN] - 1); //trimming it down
|
|
name.Set(name, 0, maxLength);
|
|
DebugRenderTableEntry(CAMERA_NAME_COLUMN, rowIndex, SAFE_CSTRING(name.c_str()), blendTextColour);
|
|
|
|
//Draw the updating column.
|
|
const bool isUpdating = camera->WasUpdated();
|
|
const Color32 updatingTextColour = isUpdating ? textGreenColour : textRedColour;
|
|
const char* updatingText = isUpdating ? "Y" : "N";
|
|
DebugRenderTableEntry(UPDATING_COLUMN, rowIndex, isFinal ? "" : updatingText, isFinal ? blendTextColour : updatingTextColour);
|
|
|
|
//Draw the blend column.
|
|
if ( AreNearlyEqual(blendValue, 1.0f) )
|
|
sprintf(debugText, "F");
|
|
else if (blendValue > -SMALL_FLOAT)
|
|
sprintf(debugText, "%02u", (unsigned int)FloorfFast(blendValue*100));
|
|
else
|
|
sprintf(debugText, "X");
|
|
DebugRenderTableEntry(BLEND_COLUMN, rowIndex, isFinal ? "" : debugText, blendTextColour);
|
|
|
|
//Draw the position column.
|
|
const Vector3 &position = frame.GetPosition();
|
|
sprintf(debugText, "%.1f,", IsNearZero(position.x) ? 0.0f : position.x);
|
|
DebugRenderTableEntry(POSITION_X_COLUMN, rowIndex, debugText);
|
|
sprintf(debugText, "%.1f,", IsNearZero(position.y) ? 0.0f : position.y);
|
|
DebugRenderTableEntry(POSITION_Y_COLUMN, rowIndex, debugText);
|
|
sprintf(debugText, "%.1f", IsNearZero(position.z) ? 0.0f : position.z);
|
|
DebugRenderTableEntry(POSITION_Z_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the orientation column.
|
|
Vector3 orientation;
|
|
frame.GetWorldMatrix().ToEulersYXZ(orientation);
|
|
orientation *= RtoD;
|
|
sprintf(debugText, "%.1f,", IsNearZero(orientation.x) ? 0.0f : orientation.x);
|
|
DebugRenderTableEntry(ORIENTATION_P_COLUMN, rowIndex, debugText);
|
|
sprintf(debugText, "%.1f,", IsNearZero(orientation.y) ? 0.0f : orientation.y);
|
|
DebugRenderTableEntry(ORIENTATION_R_COLUMN, rowIndex, debugText);
|
|
sprintf(debugText, "%.1f", IsNearZero(orientation.z) ? 0.0f : orientation.z);
|
|
DebugRenderTableEntry(ORIENTATION_Y_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the clip column.
|
|
sprintf(debugText, "%.2f,", frame.GetNearClip());
|
|
DebugRenderTableEntry(NEAR_CLIP_COLUMN, rowIndex, debugText);
|
|
sprintf(debugText, "%.1f", frame.GetFarClip());
|
|
DebugRenderTableEntry(FAR_CLIP_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the flags column.
|
|
u16 flags = frame.GetFlags();
|
|
sprintf(debugText, "%05u", flags);
|
|
DebugRenderTableEntry(FLAGS_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the DOF column.
|
|
Vector4 dofPlanes;
|
|
frame.ComputeDofPlanes(dofPlanes);
|
|
|
|
for(u8 i = DOF_1_COLUMN; i < DOF_4_COLUMN; ++i)
|
|
{
|
|
sprintf(debugText, "%.2f,", dofPlanes[i - DOF_1_COLUMN]);
|
|
DebugRenderTableEntry(i, rowIndex, debugText);
|
|
}
|
|
sprintf(debugText, "%.2f", dofPlanes[3]); //no comma
|
|
DebugRenderTableEntry(DOF_4_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the FOV column.
|
|
sprintf(debugText, "%.1f", frame.GetFov());
|
|
DebugRenderTableEntry(FOV_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the motion blur column.
|
|
sprintf(debugText, "%.2f", frame.GetMotionBlurStrength());
|
|
DebugRenderTableEntry(MOTION_BLUR_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the info column.
|
|
const int iInfoSize = 32;
|
|
char szInfo[iInfoSize]; szInfo[0] = '\0';
|
|
int iInfoLength = 0;
|
|
if(camera->GetIsClassId(camThirdPersonCamera::GetStaticClassId()))
|
|
{
|
|
const camThirdPersonCamera *thirdPersonCamera = static_cast< const camThirdPersonCamera * >(camera);
|
|
|
|
if(thirdPersonCamera->GetCatchUpHelper())
|
|
{
|
|
formatf(&szInfo[iInfoLength], iInfoSize - iInfoLength, "C");
|
|
iInfoLength = istrlen(szInfo);
|
|
}
|
|
|
|
if(thirdPersonCamera->GetHintHelper())
|
|
{
|
|
formatf(&szInfo[iInfoLength], iInfoSize - iInfoLength, "H");
|
|
iInfoLength = istrlen(szInfo);
|
|
}
|
|
}
|
|
#if GTA_REPLAY
|
|
else if (camera->GetIsClassId(camReplayBaseCamera::GetStaticClassId()))
|
|
{
|
|
const camReplayBaseCamera* replayCamera = static_cast<const camReplayBaseCamera*>(camera);
|
|
|
|
formatf(&szInfo[iInfoLength], iInfoSize - iInfoLength, "[%i]", replayCamera->GetMarkerIndex());
|
|
iInfoLength = istrlen(szInfo);
|
|
}
|
|
#endif // GTA_REPLAY
|
|
sprintf(debugText, "%s", szInfo);
|
|
DebugRenderTableEntry(INFO_COLUMN, rowIndex, debugText);
|
|
|
|
//Draw the optional script source.
|
|
if (camera->GetIsClassId(camScriptedCamera::GetStaticClassId()))
|
|
{
|
|
const camScriptedCamera* scriptedCamera = static_cast<const camScriptedCamera*>(camera);
|
|
const s32 cameraPoolIndex = scriptedCamera->GetPoolIndex();
|
|
if(const scriptHandler* ownerScriptHandler = CTheScripts::GetScriptHandlerMgr().GetScriptHandlerForResource(CGameScriptResource::SCRIPT_RESOURCE_CAMERA, cameraPoolIndex))
|
|
{
|
|
if(const GtaThread* ownerScriptThread = static_cast<const GtaThread*>(ownerScriptHandler->GetThread()))
|
|
{
|
|
const char* ownerScriptName = const_cast<GtaThread*>(ownerScriptThread)->GetScriptName();
|
|
DebugRenderTableEntry(CAMERA_NAME_COLUMN, ++rowIndex, ownerScriptName, blendTextColour);
|
|
}
|
|
}
|
|
}
|
|
|
|
++rowIndex;
|
|
}
|
|
|
|
float camManager::GetBlendValueForCamera(const camBaseCamera* camera)
|
|
{
|
|
const int num = ms_RenderedCameras.GetCount();
|
|
for(int i=0; i<num; i++)
|
|
{
|
|
if (ms_RenderedCameras[i].m_Object.Get() == camera)
|
|
{
|
|
return ms_RenderedCameras[i].m_BlendLevel;
|
|
}
|
|
}
|
|
return -1.0f;
|
|
}
|
|
|
|
float camManager::GetBlendValueForDirector(const camBaseDirector* director)
|
|
{
|
|
const int num = ms_RenderedDirectors.GetCount();
|
|
for(int i=0; i<num; i++)
|
|
{
|
|
if (ms_RenderedDirectors[i].m_Object.Get() == director)
|
|
{
|
|
return ms_RenderedDirectors[i].m_BlendLevel;
|
|
}
|
|
}
|
|
return -1.0f;
|
|
}
|
|
|
|
void camManager::DebugRenderFinalFrameText(u8 rowIndex)
|
|
{
|
|
DebugRenderTableEntry(DIRECTOR_NAME_COLUMN, rowIndex, "FINAL", g_DebugRenderTableColumnColors[DIRECTOR_NAME_COLUMN], CAMERA_NAME_COLUMN);
|
|
|
|
const camBaseCamera* renderedCamera = GetDominantRenderedCamera();
|
|
if (renderedCamera)
|
|
{
|
|
DebugRenderCameraText(renderedCamera, rowIndex, true);
|
|
}
|
|
}
|
|
|
|
void camManager::DebugRenderGlobalState(u8 rowIndex)
|
|
{
|
|
#if GTA_REPLAY
|
|
if (CReplayMgr::IsEditModeActive())
|
|
{
|
|
char replayDirectorText[512];
|
|
replayDirectorText[0] = '\0';
|
|
|
|
camInterface::GetReplayDirector().GetDebugText(replayDirectorText);
|
|
|
|
DebugRenderTableEntry(0, rowIndex, replayDirectorText, Color_black, NUM_DEBUG_RENDER_COLUMNS);
|
|
return;
|
|
}
|
|
#endif // GTA_REPLAY
|
|
|
|
const int iSize = 512;
|
|
char szGlobalState[iSize]; szGlobalState[0] = '\0';
|
|
int iLength = 0;
|
|
|
|
if (CPauseMenu::GetPauseRenderPhasesStatus())
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "RENDER_PHASES_PAUSED");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
if(camInterface::GetCinematicDirector().IsFirstPersonInVehicleDisabledThisUpdate())
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "DISABLE_CINEMATIC_BONNET_CAMERA_THIS_UPDATE");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
if(camInterface::GetGameplayDirector().DebugWasFirstPersonDisabledThisUpdate())
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE - %s",
|
|
camInterface::GetGameplayDirector().DebugWasFirstPersonDisabledThisUpdateFromScript() ? "SCRIPT" : "CODE");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
if(ms_DebugReplayCameraMovementDisabledThisFrame)
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "REPLAY_DISABLE_CAMERA_MOVEMENT_THIS_FRAME - %s",
|
|
ms_DebugReplayCameraMovementDisabledThisFrameScript ? "SCRIPT" : "CODE");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
#endif // GTA_REPLAY
|
|
|
|
s32 contextIndex, viewModeForContext;
|
|
if(camControlHelper::DebugHadSetViewModeForContext(contextIndex, viewModeForContext))
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "SET_CAM_VIEW_MODE_FOR_CONTEXT (context:%d, view mode:%d)", contextIndex, viewModeForContext);
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
camControlHelper::DebugResetHadSetViewModeForContext();
|
|
|
|
TUNE_GROUP_BOOL(CAMERA_MANAGER, renderCameraVelocitiesToCameraTable, false);
|
|
const camThirdPersonCamera* thirdPersonCamera = camInterface::GetGameplayDirector().GetThirdPersonCamera();
|
|
if (renderCameraVelocitiesToCameraTable && thirdPersonCamera)
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
const Vector3& baseAttachVelocity = thirdPersonCamera->GetBaseAttachVelocityToConsider();
|
|
const camFollowCamera* followCamera = thirdPersonCamera->GetIsClassId(camFollowCamera::GetStaticClassId()) ? static_cast<const camFollowCamera*>(thirdPersonCamera) : NULL;
|
|
Vector3 pullAroundVelocity = Vector3(VEC3_ZERO);
|
|
if (followCamera)
|
|
{
|
|
followCamera->DebugComputeAttachParentVelocityToConsiderForPullAround(pullAroundVelocity);
|
|
}
|
|
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "Velocity = (%.2f, %.2f, %.2f) | Pull Around Velocity = (%.2f, %.2f, %.2f)",
|
|
baseAttachVelocity.x, baseAttachVelocity.y, baseAttachVelocity.z,
|
|
pullAroundVelocity.x, pullAroundVelocity.y, pullAroundVelocity.z);
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
TUNE_GROUP_BOOL(CAMERA_MANAGER, renderStuntSettingsToCameraTable, false);
|
|
if (renderStuntSettingsToCameraTable)
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "STUNT? %s | REQUESTED? %s | FORCED? %s",
|
|
camInterface::GetGameplayDirector().IsVehicleCameraUsingStuntSettingsThisUpdate(camInterface::GetGameplayDirector().GetRenderedCamera()) ? "ACTIVE" : "NOT ACTIVE",
|
|
camInterface::GetGameplayDirector().IsScriptRequestingVehicleCamStuntSettingsThisUpdate() ? "YES" : "NO",
|
|
camInterface::GetGameplayDirector().IsScriptForcingVehicleCamStuntSettingsThisUpdate() ? "YES" : "NO");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
const char* scriptEnabledShakeName = camInterface::GetScriptDirector().DebugGetScriptEnabledShakeName();
|
|
float scriptEnabledShakeAmplitude = camInterface::GetScriptDirector().DebugGetScriptEnabledShakeAmplitude();
|
|
if(scriptEnabledShakeAmplitude > SMALL_FLOAT)
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "SCRIPT ENABLED SHAKE (name:%s, amplitude:%.2f)", scriptEnabledShakeName, scriptEnabledShakeAmplitude);
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
if (ms_TriggerFirstPersonFlashEffectTime>0)
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "FPS Flash (%s): %dms %s%s", SAFE_CSTRING(ms_FirstPersonFlashEffectCallingContext.GetCStr()), fwTimer::GetTimeInMilliseconds() - ms_TriggerFirstPersonFlashEffectTime, GetFirstPersonFlashEffectName(ms_PendingFirstPersonFlashEffect), ms_SuppressFirstPersonFlashEffectThisFrame ? " SUPPRESSED" : " Not suppressed");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
else if (ms_LastFirstPersonFlashAbortTime>0 && ((fwTimer::GetTimeInMilliseconds() - ms_LastFirstPersonFlashAbortTime) < 5000))
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "FPS Flash (%s): ABORTED - %s", SAFE_CSTRING(ms_FirstPersonFlashEffectCallingContext.GetCStr()), SAFE_CSTRING(ms_LastFirstPersonFlashAbortReason.GetCStr()));
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
if (ms_LastFirstPersonFlashTime>0 && ((fwTimer::GetTimeInMilliseconds() - ms_LastFirstPersonFlashTime) < 5000))
|
|
{
|
|
if(iLength > 0)
|
|
{
|
|
formatf(&szGlobalState[iLength], iSize - iLength, ", ");
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
formatf(&szGlobalState[iLength], iSize - iLength, "Last FPS Flash (%s, %d)", SAFE_CSTRING(ms_LastFirstPersonFlashContext.GetCStr()), ms_LastFirstPersonFlashTime);
|
|
iLength = istrlen(szGlobalState);
|
|
}
|
|
|
|
DebugRenderTableEntry(0, rowIndex, szGlobalState, Color_black, NUM_DEBUG_RENDER_COLUMNS);
|
|
|
|
if (iLength > 0)
|
|
{
|
|
cameraDebugf3("%s", szGlobalState);
|
|
}
|
|
}
|
|
|
|
void camManager::DebugRenderTableEntry(const u8 columnIndex, const u8 rowIndex, const char* text, const Color32 colour, const u8 endColumnIndex)
|
|
{
|
|
if (!cameraVerifyf(columnIndex < NUM_DEBUG_RENDER_COLUMNS && endColumnIndex <= NUM_DEBUG_RENDER_COLUMNS, "A column index is out of range when trying to render the debug table!"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//get column colour
|
|
const Color32 backgroundColour = colour != Color_default ? colour : g_DebugRenderTableColumnColors[columnIndex];
|
|
|
|
//get vertical and horizontal offsets
|
|
const u8 verticalOffset = g_DebugRenderTableRowOffset + rowIndex;
|
|
u8 horizontalOffset = g_DebugRenderTableColumnOffset;
|
|
for (int i = DIRECTOR_NAME_COLUMN; i < columnIndex; ++i)
|
|
{
|
|
horizontalOffset += g_DebugRenderTableColumnWidths[i];
|
|
}
|
|
|
|
//get background box width and heights
|
|
const u8 backgroundBoxHeight = 1;
|
|
u8 backgroundBoxWidth = 0;
|
|
const u8 validEndColumnIndex = endColumnIndex > columnIndex ? endColumnIndex : columnIndex + 1;
|
|
for (int i = columnIndex; i < validEndColumnIndex; ++i)
|
|
{
|
|
backgroundBoxWidth += g_DebugRenderTableColumnWidths[i];
|
|
}
|
|
|
|
const float fontWidth = 0.005f;
|
|
const float fontHeight = 0.025f;
|
|
|
|
//render background and text
|
|
float boxX = (float)( (horizontalOffset - 0.6) * fontWidth);
|
|
float boxY = (float)( (verticalOffset - 0.2) * fontHeight );
|
|
float boxWidth = (float)( (backgroundBoxWidth - 0.6) * fontWidth );
|
|
float boxHeight = (float)( (backgroundBoxHeight - 0.2) * fontHeight );
|
|
const Color32 quadColor(backgroundColour.GetRed(), backgroundColour.GetGreen(), backgroundColour.GetBlue(), backgroundColour.GetAlpha()/2);
|
|
grcDebugDraw::Quad(Vec2V(boxX, boxY), Vec2V(boxX+boxWidth, boxY), Vec2V(boxX+boxWidth, boxY+boxHeight), Vec2V(boxX, boxY+boxHeight), quadColor);
|
|
|
|
if (*text != '\0')
|
|
{
|
|
const Color32 textColour = Color_white;
|
|
grcDebugDraw::Text(Vector2(horizontalOffset * fontWidth, verticalOffset * fontHeight), textColour, text, false);
|
|
}
|
|
}
|
|
|
|
void camManager::DebugClearDisplay()
|
|
{
|
|
ms_DebugRenderOption = DEFAULT_RENDER_NONE;
|
|
ms_ShouldDebugRenderCameraTable = false;
|
|
ms_ShouldDebugRenderCameras = false;
|
|
}
|
|
|
|
void camManager::DebugCycleRenderOptions()
|
|
{
|
|
ms_DebugRenderOption = (ms_DebugRenderOption + 1) % NUM_RENDER_OPTIONS;
|
|
|
|
switch (ms_DebugRenderOption)
|
|
{
|
|
case RENDER_TABLE_ONLY:
|
|
ms_ShouldDebugRenderCameraTable = true;
|
|
ms_ShouldDebugRenderCameras = false;
|
|
break;
|
|
case RENDER_TABLE_AND_CAMERAS:
|
|
ms_ShouldDebugRenderCameraTable = true;
|
|
ms_ShouldDebugRenderCameras = true;
|
|
break;
|
|
case RENDER_CAMERAS_ONLY:
|
|
ms_ShouldDebugRenderCameraTable = false;
|
|
ms_ShouldDebugRenderCameras = true;
|
|
break;
|
|
default:
|
|
ms_ShouldDebugRenderCameraTable = false;
|
|
ms_ShouldDebugRenderCameras = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void camManager::DebugSelectPreviousCamera()
|
|
{
|
|
atArray<camBaseCamera*> cameras;
|
|
int directorIndex = -1;
|
|
int cameraIndex = -1;
|
|
DebugSelectValidation(cameras, directorIndex, cameraIndex);
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
int numCameras = cameras.GetCount();
|
|
|
|
//we can safely assume cameraIndex and directorIndex >= 0
|
|
if (cameraIndex == 0 || numCameras == 0)
|
|
{
|
|
if (directorIndex == 0)
|
|
directorIndex = numDirectors - 1; //select the last director
|
|
else
|
|
directorIndex--;
|
|
|
|
ms_DebugSelectedDirector = ms_Directors[directorIndex];
|
|
|
|
//get list of this director's cameras
|
|
cameras.Reset();
|
|
ms_DebugSelectedDirector->DebugGetCameras(cameras);
|
|
numCameras = cameras.GetCount();
|
|
|
|
//use last camera for selected camera
|
|
cameraIndex = Max(numCameras - 1, 0);
|
|
}
|
|
else
|
|
{
|
|
cameraIndex--;
|
|
}
|
|
|
|
ms_DebugSelectedCamera = cameras.GetCount() ? cameras[cameraIndex] : NULL;
|
|
}
|
|
|
|
void camManager::DebugSelectNextCamera()
|
|
{
|
|
atArray<camBaseCamera*> cameras;
|
|
int directorIndex = -1;
|
|
int cameraIndex = -1;
|
|
DebugSelectValidation(cameras, directorIndex, cameraIndex);
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
int numCameras = cameras.GetCount();
|
|
|
|
if (cameraIndex == numCameras - 1 || numCameras == 0)
|
|
{
|
|
if (directorIndex == numDirectors - 1)
|
|
directorIndex = 0; //select the first director
|
|
else
|
|
directorIndex++;
|
|
|
|
ms_DebugSelectedDirector = ms_Directors[directorIndex];
|
|
|
|
//get list of this director's cameras
|
|
cameras.Reset();
|
|
ms_DebugSelectedDirector->DebugGetCameras(cameras);
|
|
numCameras = cameras.GetCount();
|
|
|
|
//use first camera for selected camera
|
|
cameraIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
cameraIndex++;
|
|
}
|
|
|
|
ms_DebugSelectedCamera = (numCameras > 0) ? cameras[cameraIndex] : NULL;
|
|
}
|
|
|
|
void camManager::DebugSelectValidation()
|
|
{
|
|
atArray<camBaseCamera*> cameras;
|
|
int directorIndex = -1;
|
|
int cameraIndex = -1;
|
|
|
|
DebugSelectValidation(cameras, directorIndex, cameraIndex);
|
|
}
|
|
|
|
void camManager::DebugSelectValidation(atArray<camBaseCamera*> &cameras, int &directorIndex, int &cameraIndex)
|
|
{
|
|
cameras.Reset();
|
|
if (ms_DebugSelectedDirector)
|
|
{
|
|
//find out the index of the current director
|
|
directorIndex = ms_Directors.Find(RegdCamBaseDirector(const_cast<camBaseDirector*>(ms_DebugSelectedDirector.Get())));
|
|
ms_DebugSelectedDirector->DebugGetCameras(cameras);
|
|
}
|
|
else
|
|
{
|
|
//invalid! select the first director
|
|
directorIndex = 0;
|
|
ms_DebugSelectedDirector = ms_Directors[directorIndex];
|
|
if (ms_DebugSelectedDirector)
|
|
{
|
|
ms_DebugSelectedDirector->DebugGetCameras(cameras);
|
|
}
|
|
}
|
|
|
|
if (ms_DebugSelectedCamera)
|
|
{
|
|
//find out the index of the current camera
|
|
cameraIndex = cameras.Find(RegdCamBaseCamera(const_cast<camBaseCamera*>(ms_DebugSelectedCamera.Get())));
|
|
}
|
|
|
|
if (cameraIndex == -1)
|
|
{
|
|
//invalid! select the first camera
|
|
cameraIndex = 0;
|
|
ms_DebugSelectedCamera = cameras.GetCount() ? cameras[cameraIndex] : NULL;
|
|
}
|
|
}
|
|
void camManager::DebugRenderThirdLines()
|
|
{
|
|
const Color32 colour = Color_white;
|
|
const float third = (1.0f/3.0f);
|
|
const float twoThirds = (2.0f/3.0f);
|
|
|
|
//Vertical lines
|
|
grcDebugDraw::Line(Vector2(third, 0.0f), Vector2(third, 1.0f), colour);
|
|
grcDebugDraw::Line(Vector2(twoThirds, 0.0f), Vector2(twoThirds, 1.0f), colour);
|
|
|
|
//Horizontal lines
|
|
grcDebugDraw::Line(Vector2(0.0f, third), Vector2(1.0f, third), colour);
|
|
grcDebugDraw::Line(Vector2(0.0f, twoThirds), Vector2(1.0f, twoThirds), colour);
|
|
}
|
|
|
|
void camManager::DebugRenderCameras()
|
|
{
|
|
const s32 maxNumCameras = camBaseCamera::GetPool()->GetSize();
|
|
for(s32 i=0; i<maxNumCameras; i++)
|
|
{
|
|
camBaseCamera* camera = camBaseCamera::GetPool()->GetSlot(i);
|
|
if(camera)
|
|
{
|
|
camera->DebugRender();
|
|
}
|
|
}
|
|
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
camBaseDirector* director = ms_Directors[i];
|
|
if(director)
|
|
{
|
|
director->DebugRender();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool DebugDisplayHangingCamera(void* pItem, void* UNUSED_PARAM(data))
|
|
{
|
|
cameraWarningf("Camera not freed prior to session shutdown: %s (type hash: %u)", static_cast<camBaseCamera*>(pItem)->GetName(), static_cast<camBaseCamera*>(pItem)->GetClassId().GetHash());
|
|
return true;
|
|
}
|
|
|
|
void camManager::DebugOutputNewVehicleMetadata()
|
|
{
|
|
bool success = false;
|
|
const camBaseCamera* activeCamera = camInterface::GetDominantRenderedCamera();
|
|
if (activeCamera && activeCamera->GetIsClassId(camCinematicMountedCamera::GetStaticClassId()))
|
|
{
|
|
const camCinematicMountedCamera* cinematicCamera = static_cast<const camCinematicMountedCamera*>(activeCamera);
|
|
const CEntity* attachParent = cinematicCamera->GetAttachParent();
|
|
const CVehicle* vehicle = attachParent && attachParent->GetIsTypeVehicle() ? static_cast<const CVehicle*>(attachParent) : NULL;
|
|
if (vehicle)
|
|
{
|
|
cameraDisplayf("%s", vehicle->GetModelName());
|
|
success = true;
|
|
}
|
|
|
|
cameraDisplayf("<povCameraName>%s</povCameraName>", activeCamera->GetName());
|
|
|
|
const camCinematicMountedCameraMetadata& metadata = static_cast<const camCinematicMountedCameraMetadata&>(cinematicCamera->GetMetadata());
|
|
const CVehicleModelInfo* modelInfo = vehicle ? vehicle->GetVehicleModelInfo() : NULL;
|
|
|
|
const CPed* followPed = camInterface::FindFollowPed();
|
|
const bool isFollowPedDriver = followPed && followPed->GetIsDrivingVehicle();
|
|
|
|
Vector3 relativeAttachPosition = metadata.m_RelativeAttachPosition;
|
|
if (modelInfo)
|
|
{
|
|
if (isFollowPedDriver)
|
|
{
|
|
relativeAttachPosition += modelInfo->GetPovCameraOffset();
|
|
cameraDisplayf("<PovCameraOffset x=\"%.6f\" y=\"%.6f\" z=\"%.6f\" />", relativeAttachPosition.x, relativeAttachPosition.y, relativeAttachPosition.z);
|
|
}
|
|
else
|
|
{
|
|
|
|
const CVehicleSeatInfo* seatInfo = vehicle ? vehicle->GetSeatInfo(followPed) : NULL;
|
|
if (!seatInfo->GetIsFrontSeat())
|
|
{
|
|
relativeAttachPosition += modelInfo->GetPovRearPassengerCameraOffset();
|
|
cameraDisplayf("<PovRearPassengerCameraOffset x=\"%.6f\" y=\"%.6f\" z=\"%.6f\" />", relativeAttachPosition.x, relativeAttachPosition.y, relativeAttachPosition.z);
|
|
}
|
|
else
|
|
{
|
|
relativeAttachPosition += modelInfo->GetPovPassengerCameraOffset();
|
|
cameraDisplayf("<PovPassengerCameraOffset x=\"%.6f\" y=\"%.6f\" z=\"%.6f\" />", relativeAttachPosition.x, relativeAttachPosition.y, relativeAttachPosition.z);
|
|
}
|
|
|
|
relativeAttachPosition += modelInfo->GetPovCameraOffset();
|
|
cameraDisplayf("(Abs x=\"%.3f\" y=\"%.3f\" z=\"%.3f\")", relativeAttachPosition.x, relativeAttachPosition.y, relativeAttachPosition.z);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!success)
|
|
{
|
|
cameraDisplayf("DEFAULTS");
|
|
cameraDisplayf("<povCameraName>DEFAULT_POV_CAMERA</povCameraName>");
|
|
cameraDisplayf("<PovCameraOffset x=\"0.000000\" y=\"0.000000\" z=\"0.680000\" />");
|
|
cameraDisplayf("<PovCameraVerticalAdjustmentForRollCage value=\"0.000000\" />");
|
|
}
|
|
}
|
|
|
|
void camManager::InitWidgets()
|
|
{
|
|
//Create the camera bank.
|
|
bkBank& bank = BANKMGR.CreateBank("Camera", 0, 0, false);
|
|
bank.AddButton("Create camera widgets", datCallback(CFA1(camManager::AddWidgets), &bank));
|
|
}
|
|
|
|
void camManager::AddWidgets()
|
|
{
|
|
//Destroy first widget which is the create button.
|
|
bkWidget* widget = BANKMGR.FindWidget("Camera/Create camera widgets");
|
|
if(widget == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
widget->Destroy();
|
|
|
|
//Find the top-level camera bank.
|
|
bkBank* bank = BANKMGR.FindBank("Camera");
|
|
if(bank == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bank->PushGroup("Debug rendering", false);
|
|
{
|
|
bank->AddButton("Cycle through camera debug displays", datCallback(CFA(DebugCycleRenderOptions)), "Cycles through camera debug displays");
|
|
bank->AddButton("^", datCallback(CFA(DebugSelectPreviousCamera)), "Selects the previous camera in the table");
|
|
bank->AddButton("v", datCallback(CFA(DebugSelectNextCamera)), "Selects the next camera in the table");
|
|
|
|
bank->AddToggle("Render cameras info", &ms_ShouldRenderCameraInfo);
|
|
bank->PushGroup("Rendering options for selected camera", false);
|
|
{
|
|
bank->AddToggle("Render far clip", &ms_ShouldDebugRenderCameraFarClip);
|
|
bank->AddToggle("Render near DOF", &ms_ShouldDebugRenderCameraNearDof);
|
|
bank->AddToggle("Render far DOF", &ms_ShouldDebugRenderCameraFarDof);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
bank->AddButton("Output new vehicle metadata", datCallback(CFA(DebugOutputNewVehicleMetadata)));
|
|
bank->AddToggle("Render third lines", &ms_ShouldDebugRenderThirdLines);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
ms_ShakeDebugger.AddWidgets(*bank);
|
|
|
|
camFactory::AddWidgets(*bank);
|
|
|
|
camInterface::AddWidgets(*bank);
|
|
|
|
AddWidgetsForFullScreenBlurEffect(*bank);
|
|
|
|
ms_FramePropagator.AddWidgets(*bank);
|
|
|
|
bank->PushGroup("Renderer", false);
|
|
{
|
|
CViewport* gameViewport = gVpMan.GetGameViewport();
|
|
bank->PushGroup("CamMtx", false);
|
|
{
|
|
const Matrix34 *pMat34 = (Matrix34*)&gameViewport->GetGrcViewport().GetCameraMtx();
|
|
bank->AddSlider("WorldMtx a", (Vector3*)&pMat34->a, -9999.0f, 9999.0f, 0.01f);
|
|
bank->AddSlider("WorldMtx b", (Vector3*)&pMat34->b, -9999.0f, 9999.0f, 0.01f);
|
|
bank->AddSlider("WorldMtx c", (Vector3*)&pMat34->c, -9999.0f, 9999.0f, 0.01f);
|
|
bank->AddSlider("WorldMtx d", (Vector3*)&pMat34->d, -9999.0f, 9999.0f, 0.01f);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
bank->PushGroup("WorldMtx", false);
|
|
{
|
|
const Matrix34 *pMat34 = (Matrix34*)&gameViewport->GetGrcViewport().GetWorldMtx();
|
|
bank->AddSlider("CamMtx a", (Vector3*)&pMat34->a, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("CamMtx b", (Vector3*)&pMat34->b, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("CamMtx c", (Vector3*)&pMat34->c, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("CamMtx d", (Vector3*)&pMat34->d, -9999.0f, 9999.0f, 0.001f);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
bank->PushGroup("ViewMtx", false);
|
|
{
|
|
const Matrix44 *pMat44 = (Matrix44*)&gameViewport->GetGrcViewport().GetViewMtx();
|
|
bank->AddSlider("ViewMtx a", (Vector4*)&pMat44->a, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ViewMtx b", (Vector4*)&pMat44->b, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ViewMtx c", (Vector4*)&pMat44->c, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ViewMtx d", (Vector4*)&pMat44->d, -9999.0f, 9999.0f, 0.001f);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
bank->PushGroup("ScreenMtx", false);
|
|
{
|
|
const Matrix44 *pMat44 = (Matrix44*)&gameViewport->GetGrcViewport().GetScreenMtx();
|
|
bank->AddSlider("ScreenMtx a", (Vector4*)&pMat44->a, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ScreenMtx b", (Vector4*)&pMat44->b, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ScreenMtx c", (Vector4*)&pMat44->c, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ScreenMtx d", (Vector4*)&pMat44->d, -9999.0f, 9999.0f, 0.001f);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
bank->PushGroup("CompositeMtx", false);
|
|
{
|
|
const Matrix44 *pMat44 = (Matrix44*)&gameViewport->GetGrcViewport().GetCompositeMtx();
|
|
bank->AddSlider("CompositeMtx a", (Vector4*)&pMat44->a, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("CompositeMtx b", (Vector4*)&pMat44->b, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("CompositeMtx c", (Vector4*)&pMat44->c, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("CompositeMtx d", (Vector4*)&pMat44->d, -9999.0f, 9999.0f, 0.001f);
|
|
}
|
|
bank->PopGroup();
|
|
|
|
bank->PushGroup("ModelViewMtx", false);
|
|
{
|
|
const Matrix44 *pMat44 = (Matrix44*)&gameViewport->GetGrcViewport().GetModelViewMtx();
|
|
bank->AddSlider("ModelViewMtx a", (Vector4*)&pMat44->a, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ModelViewMtx b", (Vector4*)&pMat44->b, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ModelViewMtx c", (Vector4*)&pMat44->c, -9999.0f, 9999.0f, 0.001f);
|
|
bank->AddSlider("ModelViewMtx d", (Vector4*)&pMat44->d, -9999.0f, 9999.0f, 0.001f);
|
|
}
|
|
bank->PopGroup();
|
|
}
|
|
bank->PopGroup();
|
|
|
|
//Add widgets for directors.
|
|
const int numDirectors = ms_Directors.GetCount();
|
|
for(int i=0; i<numDirectors; i++)
|
|
{
|
|
camBaseDirector* director = ms_Directors[i];
|
|
if(director)
|
|
{
|
|
director->AddWidgetsForInstance();
|
|
}
|
|
}
|
|
|
|
//Add widgets for cameras.
|
|
const int maxNumCameras = camBaseCamera::GetPool()->GetSize();
|
|
for(int i=0; i<maxNumCameras; i++)
|
|
{
|
|
camBaseCamera* camera = camBaseCamera::GetPool()->GetSlot(i);
|
|
if(camera)
|
|
{
|
|
camera->AddWidgetsForInstance();
|
|
}
|
|
}
|
|
}
|
|
|
|
void camManager::AddWidgetsForFullScreenBlurEffect(bkBank& bank)
|
|
{
|
|
bank.PushGroup("Full-screen blur effect", false);
|
|
{
|
|
bank.AddButton("Start", datCallback(CFA(DebugStartFullScreenBlurEffect)));
|
|
bank.AddButton("Release", datCallback(CFA(DebugReleaseFullScreenBlurEffect)));
|
|
bank.AddButton("Abort", datCallback(CFA(DebugAbortFullScreenBlurEffect)));
|
|
|
|
bank.AddSlider("Max strength", &(ms_DebugFullScreenBlurEffectEnvelopeMetadata.m_SustainLevel), 0.0f, 1.0f, 0.01f);
|
|
|
|
parStructure* structure = ms_DebugFullScreenBlurEffectEnvelopeMetadata.parser_GetStructure();
|
|
if(structure)
|
|
{
|
|
rage::parBuildWidgetsVisitor buildWidgetsVisitor;
|
|
buildWidgetsVisitor.m_CurrBank = &bank;
|
|
|
|
rage::parPtrToStructure ptrToStructure = ms_DebugFullScreenBlurEffectEnvelopeMetadata.parser_GetPointer();
|
|
|
|
parMember* member = structure->FindMember("AttackDuration");
|
|
if(member)
|
|
{
|
|
buildWidgetsVisitor.VisitMember(ptrToStructure, *member);
|
|
}
|
|
|
|
member = structure->FindMember("HoldDuration");
|
|
if(member)
|
|
{
|
|
buildWidgetsVisitor.VisitMember(ptrToStructure, *member);
|
|
}
|
|
|
|
member = structure->FindMember("ReleaseDuration");
|
|
if(member)
|
|
{
|
|
buildWidgetsVisitor.VisitMember(ptrToStructure, *member);
|
|
}
|
|
|
|
member = structure->FindMember("AttackCurveType");
|
|
if(member)
|
|
{
|
|
buildWidgetsVisitor.VisitMember(ptrToStructure, *member);
|
|
}
|
|
|
|
member = structure->FindMember("ReleaseCurveType");
|
|
if(member)
|
|
{
|
|
buildWidgetsVisitor.VisitMember(ptrToStructure, *member);
|
|
}
|
|
}
|
|
|
|
bank.AddToggle("Should use game (vs camera) time", &ms_ShouldDebugFullScreenBlurEffectUseGameTime);
|
|
}
|
|
bank.PopGroup(); //Full-screen blur effect.
|
|
}
|
|
|
|
UnapprovedCameraLists camManager::ms_UnapprovedCameraLists;
|
|
bool camManager::ms_UnapprovedCameraListsLoaded = false;
|
|
|
|
void camManager::LoadUnapprovedList()
|
|
{
|
|
if (!sysBootManager::IsPackagedBuild() && !ms_UnapprovedCameraListsLoaded)
|
|
{
|
|
ASSET.PushFolder("common:/non_final/anim");
|
|
|
|
if (!PARSER.LoadObject("UnapprovedCameraLists", "meta", ms_UnapprovedCameraLists))
|
|
{
|
|
Assertf(0, "Failed to load UnapprovedCameraLists");
|
|
}
|
|
|
|
ASSET.PopFolder();
|
|
|
|
ms_UnapprovedCameraListsLoaded = true;
|
|
}
|
|
}
|
|
|
|
void camManager::DebugInitFullScreenBlurEffect()
|
|
{
|
|
//Assign sensible defaults to the local envelope metadata. This is non-final data and is therefore not in the camera metadata.
|
|
ms_DebugFullScreenBlurEffectEnvelopeMetadata.m_AttackDuration = 100;
|
|
ms_DebugFullScreenBlurEffectEnvelopeMetadata.m_HoldDuration = 100;
|
|
ms_DebugFullScreenBlurEffectEnvelopeMetadata.m_ReleaseDuration = 500;
|
|
ms_DebugFullScreenBlurEffectEnvelopeMetadata.m_AttackCurveType = CURVE_TYPE_SLOW_IN_OUT;
|
|
ms_DebugFullScreenBlurEffectEnvelopeMetadata.m_ReleaseCurveType = CURVE_TYPE_SLOW_IN_OUT;
|
|
}
|
|
|
|
void camManager::DebugStartFullScreenBlurEffect()
|
|
{
|
|
//Kill any existing effect.
|
|
DebugAbortFullScreenBlurEffect();
|
|
|
|
ms_DebugFullScreenBlurEffectEnvelope = camFactory::CreateObject<camEnvelope>(ms_DebugFullScreenBlurEffectEnvelopeMetadata);
|
|
if(ms_DebugFullScreenBlurEffectEnvelope)
|
|
{
|
|
ms_DebugFullScreenBlurEffectEnvelope->SetUseGameTime(ms_ShouldDebugFullScreenBlurEffectUseGameTime);
|
|
ms_DebugFullScreenBlurEffectEnvelope->Start();
|
|
}
|
|
}
|
|
|
|
void camManager::DebugReleaseFullScreenBlurEffect()
|
|
{
|
|
if(ms_DebugFullScreenBlurEffectEnvelope)
|
|
{
|
|
ms_DebugFullScreenBlurEffectEnvelope->Release();
|
|
}
|
|
}
|
|
|
|
void camManager::DebugAbortFullScreenBlurEffect()
|
|
{
|
|
if(ms_DebugFullScreenBlurEffectEnvelope)
|
|
{
|
|
delete ms_DebugFullScreenBlurEffectEnvelope;
|
|
ms_DebugFullScreenBlurEffectEnvelope = NULL;
|
|
}
|
|
}
|
|
|
|
void camManager::DebugUpdateFullScreenBlurEffect(camFrame& renderedFrame)
|
|
{
|
|
if(!ms_DebugFullScreenBlurEffectEnvelope)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const float envelopeLevel = ms_DebugFullScreenBlurEffectEnvelope->Update();
|
|
float fullScreenBlurBlendLevel = renderedFrame.GetDofFullScreenBlurBlendLevel();
|
|
fullScreenBlurBlendLevel = Lerp(envelopeLevel, fullScreenBlurBlendLevel, 1.0f);
|
|
|
|
renderedFrame.SetDofFullScreenBlurBlendLevel(fullScreenBlurBlendLevel);
|
|
}
|
|
|
|
void camManager::DebugFlushScriptCommands()
|
|
{
|
|
for (int index = 0; index < ms_DebugRegisteredScriptCommands.GetCount(); ++index)
|
|
{
|
|
TUNE_GROUP_INT(CAMERA_MANAGER, iDebugScriptCommandFramesToLive, 30, 1, 9999, 1);
|
|
if (fwTimer::GetFrameCount() - ms_DebugRegisteredScriptCommands[index].time >= (u32)iDebugScriptCommandFramesToLive)
|
|
{
|
|
ms_DebugRegisteredScriptCommands.Delete(index);
|
|
--index;
|
|
}
|
|
}
|
|
}
|
|
|
|
void camManager::DebugRenderScriptCommands(u8& rowIndex)
|
|
{
|
|
const int registeredCommandsCount = ms_DebugRegisteredScriptCommands.GetCount();
|
|
if (registeredCommandsCount == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
++rowIndex;
|
|
|
|
DebugRenderTableEntry(DIRECTOR_NAME_COLUMN, rowIndex, "Script Commands", g_DebugRenderTableColumnColors[DIRECTOR_NAME_COLUMN], CAMERA_NAME_COLUMN);
|
|
|
|
// Render back to front, so we see newest commands first.
|
|
for (int index = registeredCommandsCount - 1; index >= 0; index--)
|
|
{
|
|
rowIndex++;
|
|
atVarString frameText("F:%d", ms_DebugRegisteredScriptCommands[index].time);
|
|
const bool isThisFrame = ms_DebugRegisteredScriptCommands[index].time == fwTimer::GetFrameCount();
|
|
DebugRenderTableEntry(DIRECTOR_BLEND_COLUMN, rowIndex, frameText, isThisFrame ? Color_red : Color_default, CAMERA_NAME_COLUMN);
|
|
|
|
atVarString commandText("%s", ms_DebugRegisteredScriptCommands[index].text.c_str());
|
|
DebugRenderTableEntry(CAMERA_NAME_COLUMN, rowIndex, commandText.c_str(), Color_default, FLAGS_COLUMN);
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
#if __NO_OUTPUT
|
|
void CameraScriptPrintFunc(const char* UNUSED_PARAM(fmt), ...) {}
|
|
#else
|
|
void CameraScriptPrintFunc(const char* fmt, ...)
|
|
{
|
|
va_list args;
|
|
va_start(args, fmt);
|
|
diagLogDefault(Channel_camera, DIAG_SEVERITY_DEBUG3, __FILE__, __LINE__, fmt, args);
|
|
va_end(args);
|
|
}
|
|
#endif // !__NO_OUTPUT
|
|
}
|
|
|
|
void camManager::DebugRegisterScriptCommand(const char* callerName, const char* format, ...)
|
|
{
|
|
scrThread* pThread = rage::scrThread::GetActiveThread();
|
|
|
|
char argumentsBuffer[512];
|
|
va_list args;
|
|
va_start(args, format);
|
|
vformatf(argumentsBuffer, sizeof(argumentsBuffer), format, args);
|
|
va_end(args);
|
|
|
|
atVarString fullText("Script(%s) %s(%s)", pThread ? pThread->GetScriptName() : "Console", callerName, argumentsBuffer);
|
|
|
|
//print the script command full text in the output
|
|
TUNE_GROUP_BOOL(CAMERA_MANAGER, bPrintCameraScriptCommands, true);
|
|
if (bPrintCameraScriptCommands)
|
|
{
|
|
cameraDebugf2("%s", fullText.c_str());
|
|
}
|
|
|
|
TUNE_GROUP_BOOL(CAMERA_MANAGER, bPrintCameraScriptCommandsCallstack, true);
|
|
if (bPrintCameraScriptCommandsCallstack)
|
|
{
|
|
if (pThread)
|
|
{
|
|
pThread->PrintStackTrace(CameraScriptPrintFunc);
|
|
}
|
|
}
|
|
|
|
for (int index = 0; index < ms_DebugRegisteredScriptCommands.GetCount(); ++index)
|
|
{
|
|
DebugScriptCommand& entry = ms_DebugRegisteredScriptCommands[index];
|
|
if (entry.text == fullText)
|
|
{
|
|
//if we find a command entry with the same debug string, we just update the timer and return
|
|
entry.time = fwTimer::GetFrameCount();
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
//allocating a new command
|
|
DebugScriptCommand& entry = ms_DebugRegisteredScriptCommands.Grow();
|
|
entry.text = fullText;
|
|
entry.time = fwTimer::GetFrameCount();
|
|
}
|
|
|
|
#endif // __BANK
|