9347 lines
280 KiB
C++
9347 lines
280 KiB
C++
|
|
#include "Cutscene/CutSceneManagerNew.h"
|
|
|
|
//Rage Headers
|
|
#include "audiohardware/device.h"
|
|
#include "audiohardware/driver.h"
|
|
#include "bank/bank.h"
|
|
#include "bank/bkmgr.h"
|
|
#include "bank/combo.h"
|
|
#include "bank/slider.h"
|
|
#include "cranimation/vcrwidget.h"
|
|
#include "crmetadata/tag.h"
|
|
#include "crmetadata/tagiterators.h"
|
|
#include "cutfile/cutfevent.h"
|
|
#include "cutfile/cutfobject.h"
|
|
#include "cutfile/cutfeventargs.h"
|
|
#include "cutfile/cutfile2.h"
|
|
#include "cutscene/cutsevent.h"
|
|
#include "cutscene/cutsanimentity.h"
|
|
#include "event/ShockingEvents.h"
|
|
#include "grcore/debugdraw.h"
|
|
#include "grcore/edgeExtractgeomspu.h"
|
|
#include "grcore/indexbuffer.h"
|
|
#include "grcore/matrix43.h"
|
|
#include "grprofile/timebars.h"
|
|
#include "file/default_paths.h"
|
|
#include "phbound/boundcomposite.h"
|
|
#include "streaming/streaming_channel.h"
|
|
|
|
//fw headers
|
|
#include "fwscene/stores/mapdatastore.h"
|
|
#include "fwsys/fileExts.h"
|
|
|
|
//Game Headers
|
|
#include "animation/debug/AnimDebug.h"
|
|
#include "animation/MoveVehicle.h"
|
|
#include "audio/cutsceneaudioentity.h"
|
|
#include "audio/radioaudioentity.h"
|
|
#include "camera/CamInterface.h"
|
|
#include "camera/cutscene/CutsceneDirector.h"
|
|
#include "camera/debug/DebugDirector.h"
|
|
#include "camera/viewports/ViewportManager.h"
|
|
#include "control/replay/ReplayBufferMarker.h"
|
|
#include "core/game.h"
|
|
#include "cutscene/AnimatedModelEntity.h"
|
|
#include "cutscene/CutsceneCustomEvents.h"
|
|
#include "cutscene/CutSceneAnimManager.h"
|
|
#include "cutscene/CutSceneBoundsEntity.h"
|
|
#include "cutscene/CutSceneCameraEntity.h"
|
|
#include "cutscene/CutSceneFadeEntity.h"
|
|
#include "cutscene/CutSceneLightEntity.h"
|
|
#include "cutscene/CutSceneParticleEffectEntity.h"
|
|
#include "cutscene/CutSceneOverlayEntity.h"
|
|
#include "cutscene/CutSceneSoundEntity.h"
|
|
|
|
#include "debug/Debug.h"
|
|
#include "debug/Bar.h"
|
|
#include "debug/DebugScene.h"
|
|
#include "debug/FrameDump.h"
|
|
#include "debug/Editing/CutsceneEditing.h"
|
|
#include "debug/Rendering/DebugLights.h"
|
|
#include "debug/TextureViewer/TextureViewer.h"
|
|
#include "frontend/PauseMenu.h"
|
|
#include "frontend/MiniMap.h"
|
|
#include "frontend/MobilePhone.h"
|
|
#include "frontend/HudTools.h"
|
|
#include "game/clock.h"
|
|
#include "modelinfo/PedModelInfo.h"
|
|
#include "objects/object.h"
|
|
#include "objects/objectintelligence.h"
|
|
#include "network/Live/NetworkTelemetry.h"
|
|
#include "pathserver/pathserver.h"
|
|
#include "peds/Ped.h"
|
|
#include "peds/rendering/PedVariationPack.h"
|
|
#include "peds/rendering/PedVariationDS.h"
|
|
#include "peds/rendering/PedVariationStream.h"
|
|
#include "renderer/Debug/EntitySelect.h"
|
|
#include "renderer/lights/lights.h"
|
|
#include "renderer/lights/LightEntity.h"
|
|
#include "renderer/PlantsGrassRenderer.h"
|
|
#include "renderer/PostProcessFX.h"
|
|
#include "renderer/RenderTargetMgr.h"
|
|
#include "script/script.h"
|
|
#include "script/script_helper.h"
|
|
#include "scene/debug/ObjExporter.h"
|
|
#include "scene/streamer/SceneStreamerMgr.h"
|
|
#include "scene/world/GameWorld.h"
|
|
#include "scene/portals/Portal.h"
|
|
#include "streaming/streaming.h" // For CStreaming::LoadAllRequestedObjects(), etc.
|
|
#include "streaming/streamingrequestlist.h"
|
|
#include "system/bootmgr.h"
|
|
#include "system/controlMgr.h"
|
|
#include "text/messages.h"
|
|
#include "text/TextConversion.h"
|
|
#include "vfx/misc/Fire.h"
|
|
|
|
#include "Network/Live/NetworkDebugTelemetry.h"
|
|
#include "string/stringutil.h"
|
|
|
|
#if __BANK
|
|
#include "cutscene/CutsceneDebugMetadata_parser.h"
|
|
#endif
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
#include "cutscene/AuthorizedCutsceneMetadata_parser.h"
|
|
#endif
|
|
|
|
//channel
|
|
#include "Cutscene/cutscene_channel.h"
|
|
|
|
ANIM_OPTIMISATIONS ()
|
|
RAGE_DEFINE_CHANNEL(cutscene)
|
|
|
|
PARAM(nocuttext, "[cutscene] Don't display debug text during cutscenes");
|
|
PARAM(nocutarrowkeys, "[cutscene] Enable keyboard arrow keys for cutscene playback control");
|
|
PARAM(rawcutsceneauthorizeddata, "[cutscene] Ignore the script preappoval list");
|
|
PARAM(nocutsceneauthorization, "[cutscene] Ignore the script authorized list");
|
|
PARAM(cutscenecallstacklogging, "add call stacks set matrix, visibilty and deletion calls");
|
|
PARAM(cutsceneverboseexitstatelogging, "Enable verbose logging to help debug exit state issues.");
|
|
|
|
#if __BANK
|
|
|
|
#define OBJ_CAPTURE_PATH "x:/gta5/art/animation/resources/sets/obj/"
|
|
|
|
bool CutSceneManager::m_displayActiveLightsOnly = true;
|
|
bool CutSceneManager::m_bRenderCutsceneStaticLight = true;
|
|
bool CutSceneManager::m_bRenderAnimatedLights = true;
|
|
|
|
CutSceneManager::DebugRenderState CutSceneManager::ms_DebugState;
|
|
#endif
|
|
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
bool CutSceneManager::m_RenderUnauthorizedScreen;
|
|
bool CutSceneManager::m_RenderUnauthorizedWaterMark = false;
|
|
bool CutSceneManager::m_IsAuthorizedForPlayback = false;
|
|
u32 CutSceneManager::m_RenderUnauthorizedScreenTimer;
|
|
#endif
|
|
|
|
#if USE_MULTIHEAD_FADE
|
|
bool CutSceneManager::m_bBlindersUp = false;
|
|
bool CutSceneManager::m_bManualControl = false;
|
|
int CutSceneManager:: m_iBlinderDelay = 0;
|
|
#endif // USE_MULTIHEAD_FADE
|
|
|
|
int CutSceneManager::m_RenderBufferIndex = 0;
|
|
sysCriticalSectionToken CutSceneManager::sm_CutsceneLock;
|
|
|
|
bank_float g_TweakTimeStep = -100.0f;
|
|
|
|
#if __WIN32PC
|
|
namespace rage {
|
|
XPARAM(frameLimit);
|
|
}
|
|
#endif
|
|
|
|
#if ENABLE_CUTSCENE_TELEMETRY
|
|
|
|
//////////////////////////////////////
|
|
// CutsceneLightsTelemetry
|
|
//////////////////////////////////////
|
|
|
|
CutsceneLightsTelemetry g_CutSceneLightTelemetryCollector;
|
|
|
|
void CutsceneLightsTelemetry::CutSceneStart(const char *pName, bool bIsCutsceneCameraApproved, bool bIsCutsceneLightingApproved)
|
|
{
|
|
m_Name = pName; // Set name
|
|
Reset(); // Reset timing stat var
|
|
m_CameraApproved = bIsCutsceneCameraApproved;
|
|
m_LightingApproved = bIsCutsceneLightingApproved;
|
|
m_Started = true; // Tell class we've started
|
|
}
|
|
|
|
void CutsceneLightsTelemetry::CutSceneStop()
|
|
{
|
|
m_Started = false;
|
|
}
|
|
|
|
// Get data from the budget display class
|
|
void CutsceneLightsTelemetry::Update(CutSceneManager *pManager)
|
|
{
|
|
if(m_Started && pManager->IsPlaying()) // Only capture when playing, not paused
|
|
{
|
|
#if RAGE_TIMEBARS
|
|
float totalTime;
|
|
float time;
|
|
int count;
|
|
|
|
// Directional Lights
|
|
::rage::g_pfTB.GetGpuBar().GetFunctionTotals("Directional/Ambient/Reflections", count, time);
|
|
m_DirectionalLightsTimeSample.AddSample(time);
|
|
totalTime = time;
|
|
|
|
// Scene Lights
|
|
::rage::g_pfTB.GetGpuBar().GetFunctionTotals("Scene Lights", count, time);
|
|
m_SceneLightsTimeSample.AddSample(time);
|
|
totalTime += time;
|
|
|
|
// LOD Lights
|
|
::rage::g_pfTB.GetGpuBar().GetFunctionTotals("LOD Lights", count, time);
|
|
m_LODLightsTimeSample.AddSample(time);
|
|
totalTime += time;
|
|
|
|
// Total Time
|
|
m_TotalLightsTimeSample.AddSample(totalTime);
|
|
#endif // RAGE_TIMEBARS
|
|
m_DOFWasActive |= pManager->IsDepthOfFieldEnabled();
|
|
}
|
|
|
|
// Did we just stop?
|
|
if(m_WasStarted && !m_Started)
|
|
{
|
|
m_OutputNow = true;
|
|
}
|
|
|
|
m_WasStarted = m_Started;
|
|
}
|
|
|
|
// NOTE: Resets after returning true
|
|
// If the calling code doesn't act on this, then it's unlucky
|
|
bool CutsceneLightsTelemetry::ShouldOutputTelemetry()
|
|
{
|
|
bool retVal = m_OutputNow;
|
|
m_OutputNow = false;
|
|
return retVal;
|
|
}
|
|
|
|
|
|
#endif // ENABLE_CUTSCENE_TELEMETRY
|
|
|
|
|
|
#if USE_MULTIHEAD_FADE
|
|
namespace fade
|
|
{
|
|
static bool bFadingIn = true;
|
|
static bool bInstant = false;
|
|
static u32 uEndTime = 0;
|
|
static u32 uDuration = 1;
|
|
static float fAcceleration = 1.f;
|
|
static float fWaveSize = 0.0f;
|
|
static float fAlphaOffset = 0.5f;
|
|
static u32 uLastMonitorSyncTimestamp = 0;
|
|
|
|
#if __BANK
|
|
static void bankFadeIn() { CutSceneManager::StartMultiheadFade(true, bInstant); CutSceneManager::SetManualBlinders(true);}
|
|
static void bankFadeOut() { CutSceneManager::StartMultiheadFade(false);}
|
|
|
|
static void addWidgets(bkBank &bank)
|
|
{
|
|
bank.PushGroup("Multi-head Fade", false);
|
|
bank.AddToggle("Instant", &bInstant);
|
|
bank.AddSlider("Duration", &uDuration, 0, 10, 1);
|
|
bank.AddSlider("Acceleration", &fAcceleration, 0.1f, 10.f, 0.1f);
|
|
bank.AddSlider("Wave Size", &fWaveSize, 0.0f, 1.f, 0.01f);
|
|
bank.AddSlider("Alpha Offset", &fAlphaOffset, 0.f, 2.f, 0.1f);
|
|
bank.AddButton("Fade In", datCallback(bankFadeIn));
|
|
bank.AddButton("Fade Out", datCallback(bankFadeOut));
|
|
bank.PopGroup();
|
|
}
|
|
#endif //__BANK
|
|
}
|
|
PARAM(cutscene_multihead,"[cutscene] Expand cutscenes on all of the screens in multi-head configuration");
|
|
#endif //USE_MULTIHEAD_FADE
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Registers a game that the cutscene will use instead of creating
|
|
void CutSceneManager::RegisterGameEntity(CDynamicEntity* pEntity, atHashString& SceneHandleHash, atHashString& ModelNameHash, bool bDeleteBeforeEnd, bool bCreatedForScript, bool bAppearInScene, u32 options)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pAnimModelEnt = NULL;
|
|
|
|
// Currently only allow forced replacement of the ped animated by the cutscene.
|
|
if (!bAppearInScene)
|
|
{
|
|
#if !__NO_OUTPUT
|
|
if ((options&CCutsceneAnimatedModelEntity::CEO_IGNORE_MODEL_NAME)!=0)
|
|
{
|
|
cutsceneManagerDebugf1("Removing flag CEO_IGNORE_MODEL_NAME - Entity %s(%s) is registered not to appear in the scene", SceneHandleHash.TryGetCStr() ? SceneHandleHash.TryGetCStr() : "null", ModelNameHash.TryGetCStr() ? ModelNameHash.TryGetCStr() : "null");
|
|
}
|
|
#endif //!__NO_OUTPUT
|
|
options&=(~CCutsceneAnimatedModelEntity::CEO_IGNORE_MODEL_NAME);
|
|
}
|
|
|
|
pAnimModelEnt = GetAnimatedModelEntityFromSceneHandle(SceneHandleHash, ModelNameHash);
|
|
|
|
//store the frame count of the first register call to make sure that we have not registered.
|
|
if(!m_bHasScriptRegisteredAnEntity)
|
|
{
|
|
m_uFrameCountOfFirstRegisterCall = fwTimer::GetFrameCount();
|
|
m_bHasScriptRegisteredAnEntity = true;
|
|
}
|
|
|
|
if(pAnimModelEnt)
|
|
{
|
|
#if __ASSERT
|
|
if(bCreatedForScript)
|
|
{
|
|
if(pAnimModelEnt->IsBlockingVariationStreamingAndApplication())
|
|
{
|
|
cutsceneAssertf(0, "Entity %s(%s): Variation streaming has been blocked so the cut scene cannot succesfully create a game object", SceneHandleHash.TryGetCStr() ? SceneHandleHash.TryGetCStr() : "null", ModelNameHash.TryGetCStr() ? ModelNameHash.TryGetCStr() : "null");
|
|
}
|
|
}
|
|
if (NetworkInterface::IsGameInProgress() && bAppearInScene && (options&CCutsceneAnimatedModelEntity::CEO_IGNORE_MODEL_NAME)!=0 && pEntity && pEntity->GetIsTypeVehicle())
|
|
{
|
|
// if script is asking us to animate a specific vehicle model, check that the model they passed in matches the one the cutscene was made with.
|
|
// Since vehicle skeletons aren't standardised, we can't share animations between them so we need to catch cases where this happens.
|
|
SCRIPT_ASSERTF(pEntity->GetModelNameHash()==pAnimModelEnt->GetModelNameHash(), "Script has registered a mismatched vehicle model '%s' to the cutscene handle'%s'. Expecting model '%s'. The vehicle animation will likely look broken.", pEntity->GetModelName(), pAnimModelEnt->GetSceneHandleHash().GetCStr(), pAnimModelEnt->GetModelName());
|
|
}
|
|
#endif
|
|
|
|
pAnimModelEnt->m_RegisteredEntityFromScript.SceneNameHash = SceneHandleHash;
|
|
pAnimModelEnt->m_RegisteredEntityFromScript.ModelNameHash = ModelNameHash;
|
|
pAnimModelEnt->m_RegisteredEntityFromScript.pEnt = pEntity;
|
|
pAnimModelEnt->m_RegisteredEntityFromScript.bDeleteBeforeEnd = bDeleteBeforeEnd;
|
|
pAnimModelEnt->m_RegisteredEntityFromScript.bCreatedForScript = bCreatedForScript;
|
|
pAnimModelEnt->m_RegisteredEntityFromScript.bAppearInScene = bAppearInScene;
|
|
|
|
// Respect options flags if already set
|
|
if (pAnimModelEnt->GetOptionFlags() == 0)
|
|
{
|
|
pAnimModelEnt->SetOptionFlags(options);
|
|
}
|
|
cutsceneManagerDebugf1("RegisterGameEntity: pEntity (%s) SceneHandleHash (%d) ModelNameHash (%d) bDeleteBeforeEnd (%d) bCreatedForScript (%d) bAppearInScene (%d)\n", pAnimModelEnt->GetModelName(), SceneHandleHash.GetHash(), ModelNameHash.GetHash(), bDeleteBeforeEnd, bCreatedForScript, bAppearInScene);
|
|
}
|
|
#if !__NO_OUTPUT
|
|
else
|
|
{
|
|
Assertf(pAnimModelEnt, "CUTSCENE: Could not find model entity (\"%s\" %u) from scene handle (\"%s\" %u), scripters please check the scene handle is correct!", ModelNameHash.TryGetCStr(), ModelNameHash.GetHash(), SceneHandleHash.TryGetCStr(), SceneHandleHash.GetHash());
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CutSceneManager::ChangeCutSceneModel(atHashString& sceneHashString, atHashString& modelNameHash, atHashString& newModelNameHash)
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
const atArray<cutfObject*>& ObjectList = GetCutfFile()->GetObjectList();
|
|
|
|
for(int i=0; i < ObjectList.GetCount(); i++ )
|
|
{
|
|
if(ObjectList[i] && ObjectList[i]->GetType() == CUTSCENE_MODEL_OBJECT_TYPE)
|
|
{
|
|
cutfModelObject* pModel = static_cast<cutfModelObject*>(ObjectList[i]);
|
|
|
|
if(pModel && pModel->GetHandle() == sceneHashString.GetHash() && (modelNameHash.GetHash() == 0 || pModel->GetStreamingName() == modelNameHash.GetHash()))
|
|
{
|
|
cutsceneManagerDebugf1("Changing model for scene handle: %s (model: %s) to %s", sceneHashString.TryGetCStr() ? sceneHashString.TryGetCStr() : "null", modelNameHash.TryGetCStr() ? modelNameHash.TryGetCStr() : "null", newModelNameHash.TryGetCStr() ? newModelNameHash.TryGetCStr() : "null");
|
|
pModel->OverrideStreamingName(newModelNameHash);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SetCutSceneEntityStreamingFlags(atHashString& sceneHashString, atHashString& modelNameHash, u32 flags)
|
|
{
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
cutsEntity* pEntity = entry.GetData().pEntity;
|
|
if(pEntity && (pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY || pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY))
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntity);
|
|
if(pModel && pModel->GetSceneHandleHash() == sceneHashString.GetHash() && (modelNameHash.GetHash() == 0 || pModel->GetModelNameHash() == modelNameHash.GetHash()))
|
|
{
|
|
pModel->SetStreamingOptionFlags(flags);
|
|
cutsceneManagerDebugf1("SetCutSceneEntityStreamingFlags: Scene handle: %s, Model: %s, flags: %d",sceneHashString.TryGetCStr(), modelNameHash.TryGetCStr(), flags);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SetCutScenePedVariationFromPed(atHashString& sceneHashString, const CPed* pPed, atHashString& modelNameHash)
|
|
{
|
|
if (pPed)
|
|
{
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariationFromPed: Searching for ped (%s) and model (%s)", pPed->GetModelName(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : modelNameHash.TryGetCStr());
|
|
|
|
// If ModelHash is defined sets the variation on the given model otherwise sets the variation on all matching handles
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
cutsEntity* pEntity = entry.GetData().pEntity;
|
|
if(pEntity && pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntity);
|
|
if(pModel && pModel->GetSceneHandleHash() == sceneHashString.GetHash() && (modelNameHash.GetHash() == 0 || pModel->GetModelNameHash() == modelNameHash.GetHash()))
|
|
{
|
|
CCutsceneAnimatedActorEntity* pActorManager = static_cast<CCutsceneAnimatedActorEntity*>(pModel);
|
|
if(pActorManager)
|
|
{
|
|
/*if(pActorManager->GetGameEntity())
|
|
{
|
|
pActorManager->CopyPedVariations(pPed, pActorManager->GetGameEntity());
|
|
cutsceneManagerVariationDebugf("CutSceneManager::SetCutScenePedVariationFromPed::CopyPedVariations");
|
|
}
|
|
else
|
|
{*/
|
|
for(int iComponent=0; iComponent < PV_MAX_COMP; iComponent++)
|
|
{
|
|
u32 iDrawableId = CPedVariationPack::GetCompVar(pPed, static_cast<ePedVarComp>(iComponent));
|
|
u8 TextureVarId = CPedVariationPack::GetTexVar(pPed, static_cast<ePedVarComp>(iComponent));
|
|
pActorManager->SetScriptActorVariationData(iComponent, iDrawableId, TextureVarId);
|
|
}
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariationFromPed::SetInitialActorVariation");
|
|
//}
|
|
|
|
// Early out if we have found the specific handle
|
|
if (pModel->GetModelNameHash().GetHash() == modelNameHash.GetHash())
|
|
{
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariationFromPed: Matched ped (%s) and specific model (%s)", pPed->GetModelName(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : modelNameHash.TryGetCStr() );
|
|
return;
|
|
}
|
|
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariationFromPed: Matched ped (%s) and wildcard model (%s)", pPed->GetModelName(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : modelNameHash.TryGetCStr() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SetCutScenePedVariation(atHashString& sceneHashString, int ComponentID, int DrawableID, int TextureID, atHashString& modelNameHash)
|
|
{
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariation: Searching for handle (%s) and model (%s)", sceneHashString.TryGetCStr(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : modelNameHash.TryGetCStr() );
|
|
|
|
// If ModelHash is defined sets the variation on the given model otherwise sets the variation on all matching handles
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
cutsEntity* pEntity = entry.GetData().pEntity;
|
|
if(pEntity && pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntity);
|
|
if(pModel && pModel->GetSceneHandleHash() == sceneHashString.GetHash() && (modelNameHash.GetHash() == 0 || pModel->GetModelNameHash() == modelNameHash.GetHash()))
|
|
{
|
|
CCutsceneAnimatedActorEntity* pActorManager = static_cast<CCutsceneAnimatedActorEntity*>(pModel);
|
|
if(pActorManager)
|
|
{
|
|
pActorManager->SetScriptActorVariationData(ComponentID, DrawableID, TextureID);
|
|
|
|
// Early out if we have found the specific handle
|
|
if (pModel->GetModelNameHash() == modelNameHash.GetHash())
|
|
{
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariation::SetInitialActorVariation: Matched handle (%s) and specific model (%s)", sceneHashString.TryGetCStr(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : pModel->GetModelName() );
|
|
return;
|
|
}
|
|
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedVariation::SetInitialActorVariation Matched handle (%s) and wildcard model (%s))", sceneHashString.TryGetCStr(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : pModel->GetModelName() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SetCutScenePedPropVariation(atHashString& sceneHashString, int Position, int NewPropIndex, int NewTextIndex, atHashString& modelNameHash)
|
|
{
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedPropVariation: Searching for handle (%s) and model (%s)", sceneHashString.TryGetCStr(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : modelNameHash.TryGetCStr() );
|
|
|
|
// If ModelHash is defined sets the variation on the given model otherwise sets the variation on all matching handles
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
cutsEntity* pEntity = entry.GetData().pEntity;
|
|
if(pEntity && pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntity);
|
|
if(pModel && pModel->GetSceneHandleHash() == sceneHashString.GetHash() && (modelNameHash.GetHash() == 0 || pModel->GetModelNameHash() == modelNameHash.GetHash()))
|
|
{
|
|
CCutsceneAnimatedActorEntity* pActorManager = static_cast<CCutsceneAnimatedActorEntity*>(pModel);
|
|
if(pActorManager)
|
|
{
|
|
// the cut scene data adds this offset to make them prop specific
|
|
pActorManager->SetScriptActorVariationData(Position + PV_MAX_COMP, NewPropIndex, NewTextIndex);
|
|
|
|
// Early out if we have found the specific handle
|
|
if (pModel->GetModelNameHash() == modelNameHash.GetHash())
|
|
{
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedPropVariation::SetInitialActorVariation Matched handle (%s) and specific model (%s)", sceneHashString.TryGetCStr(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : pModel->GetModelName());
|
|
return;
|
|
}
|
|
|
|
cutsceneManagerVariationDebugf3("CutSceneManager::SetCutScenePedPropVariation::SetInitialActorVariation Matched handle (%s) and wildcard model (%s))", sceneHashString.TryGetCStr(), modelNameHash.GetHash() == 0 ? "Wildcard Model" : pModel->GetModelName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CCutsceneAnimatedModelEntity* CutSceneManager::GetAnimatedModelEntityFromSceneHandle(atHashString& sceneHandleHash, atHashString& ModelHash)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pFinalModel = NULL;
|
|
atArray<const cutfObject *> modelObjects;
|
|
|
|
if(GetCutfFile())
|
|
{
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_MODEL_OBJECT_TYPE, modelObjects );
|
|
|
|
for(int i =0; i < modelObjects.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(modelObjects[i]->GetObjectId());
|
|
|
|
if(pEntityObject)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && pModel->GetSceneHandleHash().GetHash() == sceneHandleHash.GetHash() )
|
|
{
|
|
pFinalModel = pModel;
|
|
}
|
|
|
|
if(pModel && pModel->GetSceneHandleHash().GetHash() == sceneHandleHash.GetHash() && pModel->GetModelNameHash().GetHash() == ModelHash.GetHash())
|
|
{
|
|
pFinalModel = pModel;
|
|
return pFinalModel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return pFinalModel;
|
|
}
|
|
|
|
void CutSceneManager::HideNonRegisteredModelEntities()
|
|
{
|
|
atArray<const cutfObject *> modelObjects;
|
|
|
|
if(GetCutfFile())
|
|
{
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_MODEL_OBJECT_TYPE, modelObjects );
|
|
|
|
for(int i =0; i < modelObjects.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(modelObjects[i]->GetObjectId());
|
|
|
|
if(pEntityObject)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = smart_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if (!pModel->IsRegisteredWithScript())
|
|
{
|
|
if (pModel->GetGameEntity())
|
|
{
|
|
pModel->GetGameEntity()->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, false);
|
|
cutsceneManagerVisibilityDebugf3("CutSceneManager::HideNonRegisteredModelEntities: Hiding GetGameEntity (%s)", pModel->GetGameEntity()->GetModelName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool CutSceneManager::HasScriptVisibleTagPassedForEntity(const CEntity *pEntity, s32 EventHash)
|
|
{
|
|
atArray<const cutfObject *> modelObjects;
|
|
if(GetCutfFile())
|
|
{
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_MODEL_OBJECT_TYPE, modelObjects );
|
|
|
|
for(int i =0; i < modelObjects.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(modelObjects[i]->GetObjectId());
|
|
|
|
if(pEntityObject && pEntityObject->pEntity)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY|| pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && pModel->GetGameEntity() == pEntity )
|
|
{
|
|
return pModel->HasScriptVisibleTagPassed(EventHash);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
CCutsceneAnimatedModelEntity* CutSceneManager::GetAnimatedModelEntityFromModelHash(atHashString& ModelNameHash)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pFinalModel = NULL;
|
|
atArray<const cutfObject *> modelObjects;
|
|
if(GetCutfFile())
|
|
{
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_MODEL_OBJECT_TYPE, modelObjects );
|
|
|
|
for(int i =0; i < modelObjects.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(modelObjects[i]->GetObjectId());
|
|
|
|
if(pEntityObject && pEntityObject->pEntity)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY|| pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && pModel->GetModelNameHash().GetHash() == ModelNameHash.GetHash() )
|
|
{
|
|
pFinalModel = pModel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return pFinalModel;
|
|
}
|
|
|
|
CCutsceneAnimatedModelEntity* CutSceneManager::GetAnimatedModelEntityFromEntity(const CEntity *pEntity)
|
|
{
|
|
atArray<const cutfObject *> modelObjects;
|
|
if(GetCutfFile())
|
|
{
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_MODEL_OBJECT_TYPE, modelObjects );
|
|
|
|
for(int i =0; i < modelObjects.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(modelObjects[i]->GetObjectId());
|
|
|
|
if(pEntityObject && pEntityObject->pEntity)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY|| pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && (pModel->GetGameEntity() == pEntity || pModel->GetGameRepositionOnlyEntity() == pEntity))
|
|
{
|
|
return pModel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void CutSceneManager::GetEntityByType(s32 EntityType, atArray<cutsEntity*> &pEntityList)
|
|
{
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
SEntityObject *pEntityObject = m_cutsceneEntityObjects.Access(entry.GetKey());
|
|
|
|
if(pEntityObject && pEntityObject->pEntity->GetType() == EntityType)
|
|
{
|
|
if(pEntityObject->pEntity)
|
|
{
|
|
pEntityList.Grow() = pEntityObject->pEntity;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//check that the phase of cut scene is 1.0, the final frame of the scene
|
|
|
|
bool CutSceneManager::CanSetCutSceneExitStateForEntity(atHashString& SceneHandleHash, atHashString& ModelNameHash)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pAnimModelEnt = CutSceneManager::GetInstance()->GetAnimatedModelEntityFromSceneHandle(SceneHandleHash, ModelNameHash);
|
|
|
|
bool rv = false;
|
|
int reason = 0;
|
|
if(pAnimModelEnt)
|
|
{
|
|
reason = 1;
|
|
if ( pAnimModelEnt->m_RegisteredEntityFromScript.pEnt)
|
|
{
|
|
reason = 2;
|
|
if (!pAnimModelEnt->IsRegisteredGameEntityUnderScriptControl())
|
|
{
|
|
reason = 3;
|
|
if(pAnimModelEnt->m_RegisteredEntityFromScript.SceneNameHash.GetHash() == SceneHandleHash.GetHash())
|
|
{
|
|
reason = 4;
|
|
if (pAnimModelEnt->HasStoppedBeenCalled())
|
|
{
|
|
reason = 5;
|
|
if (!pAnimModelEnt->m_RegisteredEntityFromScript.bDeleteBeforeEnd)
|
|
{
|
|
reason = 6;
|
|
s32 type = pAnimModelEnt->GetType();
|
|
if( type == CUTSCENE_PROP_GAME_ENITITY || type == CUTSCENE_ACTOR_GAME_ENITITY || type == CUTSCENE_VEHICLE_GAME_ENITITY || type == CUTSCENE_WEAPON_GAME_ENTITY )
|
|
{
|
|
reason = -1;
|
|
|
|
pAnimModelEnt->SetRegisteredGameEntityIsUnderScriptControl(true);
|
|
if(!pAnimModelEnt->IsGameEntityReadyForGame())
|
|
{
|
|
pAnimModelEnt->SetGameEntityReadyForGame(this);
|
|
}
|
|
|
|
if (type==CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
// must do at least a post camera ai update on the ped, or we'll get a bind pose next frame.
|
|
CCutsceneAnimatedActorEntity* pActorEnt = static_cast<CCutsceneAnimatedActorEntity*>(pAnimModelEnt);
|
|
if (pActorEnt->GetGameEntity())
|
|
{
|
|
pActorEnt->GetGameEntity()->SetPedResetFlag(CPED_RESET_FLAG_ForcePreCameraAIUpdate, true);
|
|
pActorEnt->GetGameEntity()->SetPedResetFlag(CPED_RESET_FLAG_ForcePreCameraAiAnimUpdateIfFirstPerson, true);
|
|
}
|
|
}
|
|
rv = true;
|
|
#if __BANK
|
|
if (!m_bVerboseExitStateLogging)
|
|
{
|
|
cutsceneManagerDebugf3("CanSetCutSceneExitStateForEntity: pAnimModelEnt (%s) result (%s) SceneHandleHash (%d) ModelNameHash (%d)\n", pAnimModelEnt ? pAnimModelEnt->GetModelName() : "NULL", rv ? "TRUE" : "FALSE", SceneHandleHash.GetHash(), ModelNameHash.GetHash());
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if (m_bVerboseExitStateLogging)
|
|
{
|
|
cutsceneManagerDebugf3("CanSetCutSceneExitStateForEntity: pAnimModelEnt (%s) result (%s) reason (%d) SceneHandleHash (%d) ModelNameHash (%d)\n", pAnimModelEnt ? pAnimModelEnt->GetModelName() : "NULL", rv ? "TRUE" : "FALSE", reason, SceneHandleHash.GetHash(), ModelNameHash.GetHash());
|
|
}
|
|
#endif // __BANK
|
|
|
|
return rv;
|
|
}
|
|
|
|
bool CutSceneManager::CanSetCutSceneExitStateForCamera(bool bHideNonRegisteredEntities)
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
atArray<const cutfObject *> modelObjects;
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_CAMERA_OBJECT_TYPE, modelObjects );
|
|
|
|
for(int i =0; i < modelObjects.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(modelObjects[i]->GetObjectId());
|
|
|
|
if(pEntityObject && pEntityObject->pEntity)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_CAMERA_GAME_ENITITY)
|
|
{
|
|
CCutSceneCameraEntity* pCam = static_cast<CCutSceneCameraEntity*>(pEntityObject->pEntity);
|
|
|
|
if(!pCam->IsRegisteredGameEntityUnderScriptControl())
|
|
{
|
|
if(pCam->CanBlendOutThisFrame())
|
|
{
|
|
pCam->SetRegisteredGameEntityIsUnderScriptControl(true);
|
|
pCam->SetCameraReadyForGame(this, CCutSceneCameraEntity::SCRIPT_REQUSTED_RETURN);
|
|
|
|
if (GetCutfFile()->GetBlendOutCutsceneDuration() == 0)
|
|
{
|
|
cutsceneManagerDebugf3("CanSetCutSceneExitStateForCamera - Camera has instantly cut back to game");
|
|
m_bCameraWillCameraBlendBackToGame = false;
|
|
}
|
|
|
|
if (bHideNonRegisteredEntities)
|
|
{
|
|
HideNonRegisteredModelEntities();
|
|
cutsceneManagerDebugf3("CanSetCutSceneExitStateForCamera - hiding non registered entities (specified by script)");
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Check that that we can mess with the ped just before the scene starts.
|
|
|
|
bool CutSceneManager::CanSetCutSceneEnterStateForEntity(atHashString& SceneNameHash, atHashString& ModelNameHash)
|
|
{
|
|
if (IsRunning())
|
|
{
|
|
CCutsceneAnimatedModelEntity* pAnimModelEnt = CutSceneManager::GetInstance()->GetAnimatedModelEntityFromSceneHandle(SceneNameHash, ModelNameHash);
|
|
|
|
if(pAnimModelEnt)
|
|
{
|
|
if(pAnimModelEnt->m_RegisteredEntityFromScript.SceneNameHash == SceneNameHash)
|
|
{
|
|
if(pAnimModelEnt->m_RegisteredEntityFromScript.pEnt && (pAnimModelEnt->m_RegisteredEntityFromScript.iEnterStatePhase >= GetCutScenePhase()))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CutSceneManager::HasSceneStartedInTheSameFrameAsObjectsAreRegistered()
|
|
{
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
SEntityObject *pEntityObject = m_cutsceneEntityObjects.Access(entry.GetKey());
|
|
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY|| pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && pModel->m_RegisteredEntityFromScript.SceneNameHash > 0)
|
|
{
|
|
if(fwTimer::GetFrameCount() != m_uFrameCountOfFirstRegisterCall)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Skip blocked by anim tag on the player clip functionality
|
|
|
|
bool CutSceneManager::IsSkipBlockedByCameraAnimTag() const
|
|
{
|
|
bool bSkipBlocked = false;
|
|
|
|
if (m_fSkipBlockedCameraAnimTagTime >= 0.0f)
|
|
{
|
|
if (GetCutSceneCurrentTime() >= m_fSkipBlockedCameraAnimTagTime)
|
|
{
|
|
bSkipBlocked = true;
|
|
}
|
|
}
|
|
|
|
return bSkipBlocked;
|
|
}
|
|
|
|
void CutSceneManager::SetSkippedBlockedByCameraAnimTagTime(float fAnimTagTime)
|
|
{
|
|
if (m_fSkipBlockedCameraAnimTagTime == -1.0f)
|
|
{
|
|
m_fSkipBlockedCameraAnimTagTime = fAnimTagTime;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Set the seamless trigger origin of the scene
|
|
|
|
void CutSceneManager::SetSeamlessTriggerOrigin( const Vector3 &vTriggerCoord, bool bOverRide )
|
|
{
|
|
sSeamlessTrigger.TriggerMat.Identity();
|
|
if (bOverRide)
|
|
{
|
|
sSeamlessTrigger.TriggerMat.d = vTriggerCoord;
|
|
}
|
|
else
|
|
{
|
|
sSeamlessTrigger.TriggerMat.d = sSeamlessTrigger.vTriggerOffset;
|
|
}
|
|
|
|
sSeamlessTrigger.TriggerMat.RotateZ(sSeamlessTrigger.fTriggerOrient);
|
|
|
|
//Get the scene matrix
|
|
Matrix34 SceneMat(M34_IDENTITY);
|
|
GetSceneOrientationMatrix(SceneMat);
|
|
SceneMat.d = GetSceneOffset();
|
|
|
|
//set our trigger into scene space
|
|
sSeamlessTrigger.TriggerMat.Dot(SceneMat);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Set the seamless trigger area of the scene
|
|
|
|
void CutSceneManager::SetSeamlessTriggerArea(const Vector3 &TriggerPoint, float fTriggerRadius, float fTriggerOrientation, float fTriggerAngle )
|
|
{
|
|
SetSeamlessTriggerOrigin(TriggerPoint, true);
|
|
|
|
sSeamlessTrigger.fTriggerOrient = DtoR * fTriggerOrientation;
|
|
sSeamlessTrigger.fTriggerAngle = DtoR * fTriggerAngle;
|
|
sSeamlessTrigger.fTriggerRadius = fTriggerRadius;
|
|
sSeamlessTrigger.vTriggerOffset = TriggerPoint;
|
|
sSeamlessTrigger.bScriptOveride = true;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Check if the ped can trigger the seamless scene
|
|
|
|
bool CutSceneManager::CanPedTriggerSCS()
|
|
{
|
|
CPed* pPlayer=CGameWorld::FindLocalPlayer();
|
|
|
|
if (pPlayer)
|
|
{
|
|
//Set a unit vector down the y axis
|
|
Vector3 vVector (0.0, 1.0f, 0.0f);
|
|
|
|
//Set it into trigger space
|
|
sSeamlessTrigger.TriggerMat.Transform3x3(vVector);
|
|
|
|
Matrix34 mPlayer = MAT34V_TO_MATRIX34(pPlayer->GetMatrix());
|
|
|
|
Vector3 vPlayer = mPlayer.d;
|
|
|
|
vPlayer = vPlayer - sSeamlessTrigger.TriggerMat.d;
|
|
|
|
float fPlayerDist = vPlayer.Mag();
|
|
|
|
if(fPlayerDist < sSeamlessTrigger.fTriggerRadius)
|
|
{
|
|
//calculate the angle between the player and the scene origin only if we have a angle > 0.0
|
|
if (sSeamlessTrigger.fTriggerAngle > 0.0f)
|
|
{
|
|
float fPlayerAngle = 0.0f;
|
|
vPlayer.Normalize();
|
|
fPlayerAngle = vPlayer.AngleZ(vVector);
|
|
|
|
if (fPlayerAngle > 0.0f)
|
|
{
|
|
if ( fPlayerAngle > sSeamlessTrigger.fTriggerAngle * 0.5 )
|
|
{
|
|
sSeamlessTrigger.fPlayerAngle = sSeamlessTrigger.fTriggerAngle * 0.5f;
|
|
|
|
}
|
|
else
|
|
{
|
|
sSeamlessTrigger.fPlayerAngle = fPlayerAngle;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fPlayerAngle < 0.0f)
|
|
{
|
|
if(fPlayerAngle > sSeamlessTrigger.fTriggerAngle * -0.5f)
|
|
{
|
|
sSeamlessTrigger.fPlayerAngle = fPlayerAngle;
|
|
}
|
|
else
|
|
{
|
|
sSeamlessTrigger.fPlayerAngle = sSeamlessTrigger.fTriggerAngle * -0.5f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sSeamlessTrigger.fPlayerAngle = 0.0f;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//Gets the entity around the passed position
|
|
|
|
CEntity* CutSceneManager::GetEntityToAtPosition(const Vector3 &vPos, float fRadius, s32 iObjectModelIndex)
|
|
{
|
|
ClosestObjectToHideDataStruct ClosestObjectData;
|
|
ClosestObjectData.fClosestDistanceSquared = fRadius * fRadius * 4.0f; // set this to larger than the scan range (remember it's squared distance)
|
|
ClosestObjectData.pClosestObject = NULL;
|
|
|
|
ClosestObjectData.CoordToCalculateDistanceFrom = vPos;
|
|
|
|
ClosestObjectData.ModelIndexToCheck = iObjectModelIndex;
|
|
|
|
// used to do a 2d distance check with FindObjectsOfTypeInRange
|
|
spdSphere testSphere(RCC_VEC3V(ClosestObjectData.CoordToCalculateDistanceFrom), ScalarV(fRadius));
|
|
fwIsSphereIntersecting searchSphere(testSphere);
|
|
CGameWorld::ForAllEntitiesIntersecting(&searchSphere, GetClosestObjectCB, (void*) &ClosestObjectData,
|
|
(ENTITY_TYPE_MASK_BUILDING|ENTITY_TYPE_MASK_OBJECT|ENTITY_TYPE_MASK_DUMMY_OBJECT), (SEARCH_LOCATION_EXTERIORS|SEARCH_LOCATION_INTERIORS));
|
|
|
|
return ClosestObjectData.pClosestObject;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//Callback function when an object is found
|
|
|
|
bool CutSceneManager::GetClosestObjectCB(CEntity* pEntity, void* data)
|
|
{
|
|
Assert(pEntity);
|
|
ClosestObjectToHideDataStruct* pClosestObjectData = reinterpret_cast<ClosestObjectToHideDataStruct*>(data);
|
|
|
|
//reject objects animated by the cut scene.
|
|
if(pEntity && pEntity->GetIsTypeObject())
|
|
{
|
|
const CObject* pObject = static_cast<const CObject*>(pEntity);
|
|
|
|
if(pObject->GetObjectIntelligence())
|
|
{
|
|
CTask* pTask = pObject->GetObjectIntelligence()->FindTaskByType(CTaskTypes::TASK_CUTSCENE);
|
|
|
|
if(pTask)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (pObject->GetOwnedBy()==ENTITY_OWNEDBY_CUTSCENE)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//Make sure that the model index is the same as the object we passed in
|
|
if (pEntity->GetModelIndex() != pClosestObjectData->ModelIndexToCheck) // not the same model
|
|
return true;
|
|
|
|
//Get the distance between the centre of the locate and the entities position
|
|
Vector3 DiffVector = VEC3V_TO_VECTOR3(pEntity->GetTransform().GetPosition()) - pClosestObjectData->CoordToCalculateDistanceFrom;
|
|
|
|
float ObjDistanceSquared = DiffVector.Mag2();
|
|
|
|
//If the the distance is less than the radius store this as our entity
|
|
if (ObjDistanceSquared < pClosestObjectData->fClosestDistanceSquared)
|
|
{
|
|
pClosestObjectData->pClosestObject = pEntity; // we have found our model
|
|
pClosestObjectData->fClosestDistanceSquared = ObjDistanceSquared;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//Sets the objects visibility
|
|
|
|
void CutSceneManager::SetObjectInAreaVisibility(const Vector3 &vPos, float fRadius, s32 iModelIndex, bool bVisble)
|
|
{
|
|
CEntity* pFoundEntity = CutSceneManager::GetEntityToAtPosition(vPos, fRadius,iModelIndex);
|
|
|
|
if(pFoundEntity && pFoundEntity->GetType() == ENTITY_TYPE_OBJECT)
|
|
{
|
|
CPhysical* pObject = static_cast<CPhysical*>(pFoundEntity);
|
|
pObject->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, bVisble);
|
|
if (bVisble)
|
|
{
|
|
cutsceneManagerVisibilityDebugf3("CutSceneManager::SetObjectInAreaVisibility: Showing object (%p, %s)", pObject, pObject->GetModelName());
|
|
}
|
|
else
|
|
{
|
|
cutsceneManagerVisibilityDebugf3("CutSceneManager::SetObjectInAreaVisibility: Hiding object (%p, %s)", pObject, pObject->GetModelName());
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//Fixup requested object
|
|
|
|
void CutSceneManager::FixupRequestedObjects(const Vector3 &vPos, float fRadius, s32 iModelIndex)
|
|
{
|
|
if (iModelIndex != -1)
|
|
{
|
|
CEntity* pFoundEntity = GetEntityToAtPosition(vPos, fRadius, iModelIndex);
|
|
|
|
if(pFoundEntity && pFoundEntity->GetType() == ENTITY_TYPE_OBJECT)
|
|
{
|
|
CObject* pObject = static_cast<CObject*>(pFoundEntity);
|
|
|
|
if(pObject->GetOwnedBy() == ENTITY_OWNEDBY_TEMP || pObject->GetOwnedBy() == ENTITY_OWNEDBY_FRAGMENT_CACHE)
|
|
{
|
|
CObjectPopulation::DestroyObject(pObject);
|
|
}
|
|
else
|
|
{
|
|
CObjectPopulation::ConvertToDummyObject(pObject);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Assertf(0, "CUTSCENE: couldn't find objectwithin radius to fix up!");
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Render the seamless trigger area
|
|
|
|
#if __BANK
|
|
fwEntity* CutSceneManager::GetIsolatedPedEntity() const
|
|
{
|
|
int index = m_iSelectedIsolatePedIndex - 1; // Subtract 1, because SetFace goes from [0, GetNumFaces())
|
|
if(index != -1)
|
|
{
|
|
s32 objectId = m_pedModelObjectList[index]->GetObjectId();
|
|
|
|
cutsEntity *pEntity = GetEntityByObjectId(objectId);
|
|
|
|
if(pEntity && pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedActorEntity *pActor = static_cast< CCutsceneAnimatedActorEntity * >(pEntity);
|
|
CPed *pPed = pActor->GetGameEntity();
|
|
|
|
return pPed;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void CutSceneManager::RenderCutSceneTriggerArea()
|
|
{
|
|
//Draw a sphere round the trigger radius
|
|
grcDebugDraw::Sphere(sSeamlessTrigger.TriggerMat.d, sSeamlessTrigger.fTriggerRadius, Color32(255, 0, 0,255), false);
|
|
|
|
Vector3 vVector (0.0, 1.0f, 0.0f);
|
|
|
|
sSeamlessTrigger.TriggerMat.Transform3x3(vVector);
|
|
|
|
//draw a line to represent the orientation of the trigger zone
|
|
grcDebugDraw::Line(sSeamlessTrigger.TriggerMat.d, sSeamlessTrigger.TriggerMat.d + (vVector * sSeamlessTrigger.fTriggerRadius) , Color32(255, 0, 0,255));
|
|
|
|
Vector3 vVectorMin (0.0f, 1.0f, 0.0f);
|
|
Vector3 vVectorMax (0.0f, 1.0f, 0.0f);
|
|
|
|
vVectorMin.RotateZ(sSeamlessTrigger.fTriggerAngle * -0.5f);
|
|
vVectorMax.RotateZ(sSeamlessTrigger.fTriggerAngle * 0.5f);
|
|
|
|
sSeamlessTrigger.TriggerMat.Transform3x3(vVectorMin);
|
|
sSeamlessTrigger.TriggerMat.Transform3x3(vVectorMax);
|
|
|
|
//Draw a the min and max angles of the trigger zone
|
|
grcDebugDraw::Line(sSeamlessTrigger.TriggerMat.d, sSeamlessTrigger.TriggerMat.d +(vVectorMax* sSeamlessTrigger.fTriggerRadius), Color32(0, 0, 255,255));
|
|
grcDebugDraw::Line(sSeamlessTrigger.TriggerMat.d, sSeamlessTrigger.TriggerMat.d +(vVectorMin* sSeamlessTrigger.fTriggerRadius), Color32(0, 0, 255,255));
|
|
|
|
|
|
grcDebugDraw::Axis(sSeamlessTrigger.TriggerMat, 1.0, true);
|
|
}
|
|
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
bool CutSceneManager::m_bShouldPausePlaybackForAudioLoad = false;
|
|
|
|
#if __BANK
|
|
bool CutSceneManager::m_bIsFinalApproved = false;
|
|
bool CutSceneManager::m_bIsCutsceneAnimationApproved = false;
|
|
bool CutSceneManager::m_bIsCutsceneCameraApproved = false;
|
|
bool CutSceneManager::m_bIsCutsceneFacialApproved = false;
|
|
bool CutSceneManager::m_bIsCutsceneLightingApproved = false;
|
|
bool CutSceneManager::m_bIsCutsceneDOFApproved = false;
|
|
float CutSceneManager::m_fApprovalMessagesOnScreenTimer = 0.0f;
|
|
bool CutSceneManager::m_IsDlcScene = false;
|
|
#endif
|
|
CutSceneManager::CutSceneManager()
|
|
{
|
|
Init();
|
|
cutsManager::InitClass();
|
|
crClip::InitClass();
|
|
m_iScriptRefCount = 0;
|
|
m_fValidFrameStep = false;
|
|
m_bIsPlayerInScene = false;
|
|
m_bIsSeamless = false;
|
|
m_bRequestedScriptAssetsForEndOfScene = false;
|
|
m_bAreScriptReservedEntitiesLoaded = false;
|
|
m_bIsSeamlessSkipping = false;
|
|
m_SeamlessSkipState = SS_DEFAULT;
|
|
//m_fLastFrameTime = 0.0f;
|
|
m_iNextLoadEvent = 0;
|
|
m_iNextUnloadEvent = 0;
|
|
m_iNextAudioLoadEvent = 0;
|
|
m_bApplyTargetSkipTime = false;
|
|
m_bFadeOnSeamlessSkip = true;
|
|
m_fTargetSkipTime = 0.0f;
|
|
m_fFinalAudioPlayEventTime = 0.0f;
|
|
m_SkipFrame = 0;
|
|
m_ScriptThread = THREAD_INVALID;
|
|
m_uFrameCountOfFirstRegisterCall = 0;
|
|
m_VehicleModelThePlayerExitsTheSceneIn = 0;
|
|
m_iPlayerObjectId = -1;
|
|
m_bCutsceneWasSkipped = false;
|
|
m_bSkipCallBackSetup = false;
|
|
m_ValidConcatSectionFlags = INVALID_PLAYBACK_FLAG;
|
|
m_PlaybackFlags = 0;
|
|
m_bCanVibratePad = false;
|
|
m_bAllowCargenToUpdate = false;
|
|
m_bCanUseMobilePhone = false;
|
|
m_HasScriptOverridenFadeValues = false;
|
|
m_CanSkipCutSceneInMultiplayerGame = false;
|
|
m_bCanSkipScene = true;
|
|
m_fSkipBlockedCameraAnimTagTime = -1.0f;
|
|
m_bHasScriptRegisteredAnEntity = false;
|
|
m_bShouldRestoreCutsceneAtEnd = false;
|
|
m_bShouldStopNow = false;
|
|
m_bCanStartCutscene = false;
|
|
m_bDelayTerminatingAFrame = false;
|
|
m_bWasDelayedTerminating = false;
|
|
m_bDeleteAllRegisteredEntites = false;
|
|
m_bCanScriptSetupEntitiesPreUpdateLoading = false;
|
|
m_bHasScriptSetupEntitiesPreUpdateLoadingFlagBeenSet = false;
|
|
m_bCanScriptChangeEntitiesModel = false;
|
|
m_bHasScriptChangeEntitiesModelFlagBeenSet = false;
|
|
m_bFailedToLoadBeforePlayWasRequested = false;
|
|
m_bWasSingledStepped = false;
|
|
m_IsResumingPlayBackFromSkipping = false;
|
|
m_bHasCutThisFrame = false;
|
|
m_bDisplayMiniMapThisUpdate = false;
|
|
m_bAllowGameToPauseForStreaming = true;
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
LoadAuthorizedCutsceneList();
|
|
#endif
|
|
#if __BANK
|
|
m_bStreamObjectsWhileSceneIsPlaying = true; //Is there a reason for this to not be true in BANK? CW
|
|
m_pCutSceneBank = NULL;
|
|
m_bRenderCutSceneBorders = false;
|
|
//m_Frame = 0;
|
|
m_pSkipToFrameSlider = NULL;
|
|
m_iSkipToFrame = 0;
|
|
m_pCaptureRadiusSlider = NULL;
|
|
m_pObjsCombo = NULL;
|
|
m_iCaptureRadius = 10;
|
|
formatf(m_capturePath, "%s", "x:/gta5/art/animation/resources/sets/obj/entername.obj");
|
|
m_captureMap = true;
|
|
m_captureProps = true;
|
|
m_captureVehicles = true;
|
|
m_capturePeds = true;
|
|
m_useSceneOrigin = false;
|
|
m_showCaptureSphere = false;
|
|
m_capturePedCapsules = false;
|
|
//m_bWasPausedForScrubbing = false;
|
|
m_bScrubbingFromLooping = false;
|
|
m_bStartedFromWidget = false;
|
|
m_uRenderMBFrame[0] = static_cast< u32 >(-1);
|
|
m_uRenderMBFrame[1] = static_cast< u32 >(-1);
|
|
m_bRenderMBFrameAndSceneName = false;
|
|
m_bVerboseExitStateLogging = false;
|
|
m_LogUsingCallStacks = PARAM_cutscenecallstacklogging.Get();
|
|
m_bVerboseExitStateLogging = PARAM_cutsceneverboseexitstatelogging.Get();
|
|
m_RunSoakTest = false;
|
|
m_SoakTestPlaybackRateIdx = 0;
|
|
m_selectedObj = -1;
|
|
m_bUseExternalTimeStep = false;
|
|
m_ExternalTimeStep = 0.0f;
|
|
m_iExternalFrame = 0;
|
|
m_searchText[0] = '\0';
|
|
m_sceneNameCombo = NULL;
|
|
m_lightSaveStatus[0] = '\0';
|
|
m_pSaveLightStatusText = NULL;
|
|
XPARAM(EnableCutsceneTuning);
|
|
XPARAM(EnableCutSceneGameDataTuning);
|
|
m_fDuration = 0.0f;
|
|
m_fPlayTime = 0.0f;
|
|
|
|
if(PARAM_EnableCutsceneTuning.Get())
|
|
{
|
|
CutfileNonParseData::m_FileTuningFlags.SetFlag(CutfileNonParseData::CUTSCENE_LIGHT_TUNING_FILE);
|
|
}
|
|
|
|
if(PARAM_EnableCutSceneGameDataTuning.Get())
|
|
{
|
|
CutfileNonParseData::m_FileTuningFlags.SetFlag(CutfileNonParseData::CUTSCENE_GAMEDATA_TUNING_FILE);
|
|
}
|
|
|
|
#else
|
|
m_bStreamObjectsWhileSceneIsPlaying = true;
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CutSceneManager::~CutSceneManager()
|
|
{
|
|
cutsManager::ShutdownClass();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Initialise cut scene vars for the constructor, only called once when the cut scene manager is initalised
|
|
|
|
void CutSceneManager::Init()
|
|
{
|
|
m_fDeltaTime = 0.0f;
|
|
m_fPreviousTime = 0.0f;
|
|
m_fPlayTime = 0.0f;
|
|
m_fDuration = 0.0f;
|
|
m_fFinalAudioPlayEventTime = 0.0f;
|
|
m_pAssetManger = NULL;
|
|
m_pAnimManager = NULL;
|
|
m_bIsCutSceneActive = false;
|
|
m_CutSceneHashString.Clear();
|
|
m_bStreamedCutScene = false;
|
|
m_IsCutscenePlayingBack = false;
|
|
m_bCameraWillCameraBlendBackToGame = false;
|
|
m_ShouldEnablePlayerControlPostScene = false;
|
|
m_bPostSceneUpdateEventCalled = false;
|
|
m_pInteriorProxy = NULL;
|
|
sSeamlessTrigger.bScriptOveride = false;
|
|
sSeamlessTrigger.fPlayerAngle = 0.0f;
|
|
sSeamlessTrigger.fTriggerAngle = 0.0f;
|
|
sSeamlessTrigger.fTriggerOrient = 0.0f;
|
|
sSeamlessTrigger.vTriggerOffset = Vector3(0.0f, 0.0f, 0.0f);
|
|
m_EndFadeTime=0;
|
|
m_bAllowGameToPauseForStreaming = true;
|
|
m_HasSetCutsceneToGameStatePostScene = false;
|
|
m_bUpdateCutsceneTimer = false;
|
|
m_bPreSceneUpdateEventCalled = false;
|
|
m_bPresceneLightUpdateEvent = false;
|
|
m_vPlayerPositionBeforeScene = VEC3_ZERO;
|
|
m_RenderBufferIndex = 0;
|
|
m_bEnableReplayRecord = true;
|
|
m_bReplayRecording = false;
|
|
m_ShutDownMode = 0;
|
|
m_bHasProccessedEarlyCutEventForSinglePlayerExits = false;
|
|
m_bShouldProcessEarlyCameraCutEventsForSinglePlayerExits = false;
|
|
|
|
#if __BANK
|
|
m_ActivateMapObjectEditing = false;
|
|
m_FixupMapObject = false;
|
|
m_bActivateBlockingObjectEditing = false;
|
|
m_bRenderBlockingBoundObjects = false;
|
|
m_fBoundingBoxWidth = 1.0f;
|
|
m_vBlockingBoundPos = VEC3_ZERO;
|
|
m_vBlockingBoundRot = VEC3_ZERO;
|
|
m_fBoundingBoxHeight = 10.0f;
|
|
m_fBoundingBoxLength = 1.0f;
|
|
m_fShadowBlur = 0.0f;
|
|
m_CanSaveLightAuthoringFile = false;
|
|
m_pDataLightXml = NULL;
|
|
m_AllowScrubbingToZero = true;
|
|
m_bSnapCameraToLights = false;
|
|
DebugEditing::CutsceneEditing::InitCommands();
|
|
|
|
PushAssetFolder("assets:/cuts");
|
|
#endif
|
|
|
|
#if GTA_REPLAY
|
|
//In replay we dont have a cutscene camera so store these values here;
|
|
m_ReplayCharacterLightParams.Reset();
|
|
#endif
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::ShutDown()
|
|
{
|
|
ShutDownCutscene();
|
|
|
|
#if __BANK
|
|
DeleteAllAssetFolders();
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Initialise static pointer definition
|
|
|
|
CutSceneManager* CutSceneManager::sm_pInstance = NULL;
|
|
|
|
void CutSceneManager::CreateInstance()
|
|
{
|
|
if (Verifyf(sm_pInstance == NULL, "A cutscene manager aready exists, only one can exist"))
|
|
{
|
|
sm_pInstance = rage_new CutSceneManager();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Get a pointer to the instance of the cut scene manager
|
|
|
|
CutSceneManager* CutSceneManager::GetInstance()
|
|
{
|
|
Assertf(sm_pInstance, "Cutscene manager pointer has been nulled");
|
|
return sm_pInstance;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Delete instance of cut scene manager
|
|
|
|
void CutSceneManager::DeleteInstance()
|
|
{
|
|
Assertf(sm_pInstance, "Cutscene manager is already null");
|
|
|
|
if(sm_pInstance)
|
|
{
|
|
delete sm_pInstance;
|
|
}
|
|
sm_pInstance = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::ShutDownCutscene()
|
|
{
|
|
//FILL IN STATS
|
|
SetCutSceneToGameState(true);
|
|
|
|
//CHECK ON FUNCTIONALITY
|
|
//ShutdownAudio(true);
|
|
//Don't allow this to be called if scene is not active at all.
|
|
if (m_bIsCutSceneActive)
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
// Immediately stop any audio, do it now as the default stop will fade out the audio
|
|
g_CutsceneAudioEntity.StopCutscene(true, 0);
|
|
|
|
Stop(SKIP_FADE, SKIP_FADE);
|
|
DoStoppedState();
|
|
}
|
|
else
|
|
{
|
|
TerminateLoadedOnlyScene();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::AddScriptResource(scrThreadId ScriptId)
|
|
{
|
|
if(!GetPlayBackFlags().IsFlagSet(CUTSCENE_REQUESTED_FROM_WIDGET) )
|
|
{
|
|
scrThread *pScriptThread = scrThread::GetThread(ScriptId);
|
|
if(Verifyf(pScriptThread, "Could not get the script thread!"))
|
|
{
|
|
CGameScriptId gameScriptId(*pScriptThread);
|
|
scriptHandler *pScriptHandler = CTheScripts::GetScriptHandlerMgr().GetScriptHandler(gameScriptId);
|
|
if(Verifyf(pScriptHandler, "Could not get the script handler!"))
|
|
{
|
|
CScriptResource_CutScene cutScene(m_CutSceneHashString);
|
|
bool bResourceAdded = false; pScriptHandler->RegisterScriptResource(cutScene, &bResourceAdded);
|
|
if(bResourceAdded)
|
|
{
|
|
m_iScriptRefCount ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::ReleaseScriptResource(u32 cutSceneNameHash)
|
|
{
|
|
if(Verifyf(cutSceneNameHash == m_CutSceneHashString, "Cutscene is not the one being released by the script resource!"))
|
|
{
|
|
if(Verifyf(m_iScriptRefCount > 0, "Cutscene has no script resources to release!"))
|
|
{
|
|
m_iScriptRefCount --;
|
|
if(m_iScriptRefCount == 0)
|
|
{
|
|
SetDeleteAllRegisteredEntites(true);
|
|
|
|
ShutDownCutscene();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::Load( const char* UNUSED_PARAM(pFilename), const char* UNUSED_PARAM(pExtension), bool bPlayNow, EScreenFadeOverride fadeOutGameAtBeginning, EScreenFadeOverride fadeInCutsceneAtBeginning, EScreenFadeOverride fadeOutCutsceneAtEnd, EScreenFadeOverride fadeInGameAtEnd, bool bJustCutfile )
|
|
{
|
|
cutsceneManagerDebugf3 ("Cutscene manager: Load");
|
|
|
|
m_bPlayNow = bPlayNow;
|
|
|
|
m_fadeOutGameAtBeginning = fadeOutGameAtBeginning;
|
|
m_fadeInCutsceneAtBeginning = fadeInCutsceneAtBeginning;
|
|
m_fadeOutCutsceneAtEnd = fadeOutCutsceneAtEnd;
|
|
m_fadeInGameAtEnd = fadeInGameAtEnd;
|
|
m_fadeInGameAtEndWhenStopping = fadeInGameAtEnd;
|
|
m_bJustLoadCutfile = bJustCutfile;
|
|
m_HasScriptOverridenFadeValues = false; // make sure script can't override the fade values before they are set.
|
|
|
|
//Updates pre scene update to load cutfile
|
|
m_cutsceneState = CUTSCENE_LOAD_CUTFILE_STATE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Make a request to the streaming system
|
|
|
|
bool CutSceneManager::LoadCutFile(const char* UNUSED_PARAM (pFileName))
|
|
{
|
|
//Make a request to the streaming system with a hash of the cut scene name
|
|
strLocalIndex iIndex = g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash());
|
|
|
|
if (Verifyf((iIndex != -1), "Cut scene doesn't exist, and will not be loaded"))
|
|
{
|
|
g_CutSceneStore.StreamingRequest(iIndex, STRFLAG_PRIORITY_LOAD|STRFLAG_CUTSCENE_REQUIRED);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CutSceneManager::FadeOut( const Color32 &color, float fDuration )
|
|
{
|
|
m_EndFadeTime = fwTimer::GetTimeInMilliseconds()+(u32)(fDuration*1000.0f);
|
|
return cutsManager::FadeOut(color, fDuration);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CutSceneManager::IsFadeTimerComplete()
|
|
{
|
|
return m_EndFadeTime>0 && fwTimer::GetTimeInMilliseconds()>m_EndFadeTime;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CutSceneManager::SetEnableReplayRecord(bool bEnable)
|
|
{
|
|
if(!Verifyf(!(bEnable && GetPlayBackFlags().IsFlagSet(CUTSCENE_REQUESTED_FROM_WIDGET)), "Can't enable cutscene replay record for cutscenes played through RAG!"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(!Verifyf(!IsCutscenePlayingBack(), "Can't enable/disable cutscene replay record once the cutscene has started playing!"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_bEnableReplayRecord = bEnable;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CutSceneManager::GetEnableReplayRecord() const
|
|
{
|
|
return m_bEnableReplayRecord;
|
|
}
|
|
|
|
#if GTA_REPLAY
|
|
bool CutSceneManager::ReplayLoadCutFile()
|
|
{
|
|
if(CutSceneManager::GetInstance()->GetCutfFile() == NULL)
|
|
{
|
|
//make sure that the cut file has been created
|
|
cutfCutsceneFile2Def* pDef = g_CutSceneStore.GetSlot(strLocalIndex(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())));
|
|
replayAssertf(pDef, "No object at this slot");
|
|
|
|
if (replayVerifyf(pDef->m_pObject, "%s:Object is not in memory", pDef->m_name.GetCStr()))
|
|
{
|
|
//Pass the pointer of the cutfile2 object to the cut scene manager so it can be referred to later.
|
|
CutSceneManager::GetInstance()->SetCutfFile(pDef->m_pObject);
|
|
g_CutSceneStore.AddRef(strLocalIndex(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())), REF_OTHER);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CutSceneManager::ReplayCleanup()
|
|
{
|
|
if(m_CutSceneHashString.IsNotNull() && GetCutfFile() && g_CutSceneStore.HasObjectLoaded(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())))
|
|
{
|
|
if (Verifyf(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash() != -1).Get(), "Cut scene doesn't exist, and will not be loaded"))
|
|
{
|
|
g_CutSceneStore.RemoveRef(strLocalIndex(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())), REF_OTHER);
|
|
g_CutSceneStore.ClearRequiredFlag(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash()).Get(),STRFLAG_CUTSCENE_REQUIRED);
|
|
g_CutSceneStore.StreamingRemove(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash()));
|
|
m_CutSceneHashString.Clear();
|
|
SetCutfFile(NULL);
|
|
}
|
|
}
|
|
|
|
g_CutsceneAudioEntity.StopCutscene(true, 0);
|
|
|
|
g_CutsceneAudioEntity.StopSyncScene();
|
|
|
|
ShutDownCutscene();
|
|
}
|
|
|
|
#endif // GTA_REPLAY
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Virtual override of the cut scene system
|
|
|
|
void CutSceneManager::DoLoadingCutfileState()
|
|
{
|
|
bool bIsLoaded = false;
|
|
|
|
//wait for our streaming system to stream in the files
|
|
if(g_CutSceneStore.HasObjectLoaded(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())) )
|
|
{
|
|
//wait for audio to not be prepared
|
|
if(!g_CutsceneAudioEntity.IsCutsceneTrackPrepared())
|
|
{
|
|
if(GetCutfFile() == NULL)
|
|
{
|
|
//make sure that the cut file has been created
|
|
cutfCutsceneFile2Def* pDef = g_CutSceneStore.GetSlot(strLocalIndex(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())));
|
|
Assertf(pDef, "No object at this slot");
|
|
|
|
if (Verifyf(pDef->m_pObject, "%s:Object is not in memory", pDef->m_name.GetCStr()))
|
|
{
|
|
//Pass the pointer of the cutfile2 object to the cut scene manager so it can be referred to later.
|
|
SetCutfFile(pDef->m_pObject);
|
|
g_CutSceneStore.AddRef(strLocalIndex(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())), REF_OTHER);
|
|
|
|
//used to add adaption events here
|
|
|
|
m_streamingState = STREAMING_IDLE_STATE; //set this so the cut scene manager doesn't think its loading anything
|
|
bIsLoaded = true;
|
|
}
|
|
else
|
|
{
|
|
//reset the manager
|
|
m_cutsceneState = CUTSCENE_UNLOAD_STATE;
|
|
m_streamingState = STREAMING_IDLE_STATE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_streamingState = STREAMING_IDLE_STATE; //set this so the cut scene manager doesn't think its loading anything
|
|
bIsLoaded = true;
|
|
}
|
|
}
|
|
#if !__NO_OUTPUT
|
|
else
|
|
{
|
|
cutsceneManagerDebugf3("Loading cutfile state - Waiting for existing audio to finish");
|
|
}
|
|
#endif
|
|
}
|
|
//Call the base function to fill out member variables now that the cut scene has loaded.
|
|
if (bIsLoaded)
|
|
{
|
|
#if __BANK
|
|
GetModelObjectsOfType(m_DebugManager.m_VehicleModelObjectList, CUTSCENE_VEHICLE_MODEL_TYPE);
|
|
m_DebugManager.PopulateSelectorList(m_DebugManager.m_pVehicleSelectCombo, "Vehicle Selector", m_DebugManager.m_iVehicleModelIndex, m_DebugManager.m_VehicleModelObjectList,datCallback(MFA(CCutSceneDebugManager::GetSelectedVehicleEntityCallBack), (datBase*)&m_DebugManager) );
|
|
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_OVERLAY_OBJECT_TYPE, m_DebugManager.m_OverlayObjectList );
|
|
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_CAMERA_OBJECT_TYPE, m_DebugManager.m_CameraObjectList);
|
|
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_ANIMATED_PARTICLE_EFFECT_OBJECT_TYPE, m_DebugManager.m_PtfxList);
|
|
|
|
m_DebugManager.PopulateSelectorList(m_DebugManager.m_pPTFXSelectCombo, "Prop Selector", m_DebugManager.m_iPtfxIndex, m_DebugManager.m_PtfxList, datCallback(MFA(CCutSceneDebugManager::GetSelectedPtfxEntityCallBack), (datBase*)&m_DebugManager));
|
|
|
|
m_DebugManager.PopulateSelectorList(m_DebugManager.m_pOverlaySelectCombo, "Overlay Selector", m_DebugManager.m_iOverlayIndex, m_DebugManager.m_OverlayObjectList,datCallback(MFA(CCutSceneDebugManager::GetSelectedOverlayEntityCallBack), (datBase*)&m_DebugManager) );
|
|
|
|
GetModelObjectsOfType(m_DebugManager.m_PropList, CUTSCENE_PROP_MODEL_TYPE);
|
|
m_DebugManager.PopulateSelectorList(m_DebugManager.m_pPropSelectCombo, "Vehicle Selector", m_DebugManager.m_iPropModelIndex, m_DebugManager.m_PropList,datCallback(MFA(CCutSceneDebugManager::GetSelectedPropEntityCallBack), (datBase*)&m_DebugManager) );
|
|
|
|
GetCutfFile()->FindObjectsOfType( CUTSCENE_ASSET_MANAGER_OBJECT_TYPE, m_DebugManager.m_pAssetManagerList );
|
|
|
|
if(m_DebugManager.m_CameraObjectList.GetCount() > 0)
|
|
{
|
|
m_DebugManager.PopulateCameraCutEventList(m_DebugManager.m_CameraObjectList[0], m_DebugManager.m_pTimeCycleCameraCutCombo, m_DebugManager.m_iTimecycleEventsIndexId, datCallback(MFA(CCutSceneDebugManager::UpdateTimeCycleParamsCB), (datBase*)&m_DebugManager));
|
|
m_DebugManager.PopulateCameraCutEventList(m_DebugManager.m_CameraObjectList[0], m_DebugManager.m_pCoCModifiersCameraCutCombo, m_DebugManager.m_iCoCModifiersCamerCutComboIndexId, datCallback(MFA(CCutSceneDebugManager::UpdateCoCModifierEventOverridesCB), (datBase*)&m_DebugManager) );
|
|
m_DebugManager.UpdateFirstPersonEventList();
|
|
m_DebugManager.m_CascadeBounds.PopulateSetShadowBoundsEventList(m_DebugManager.m_CameraObjectList[0]);
|
|
}
|
|
|
|
#endif
|
|
cutsManager::DoLoadingCutfileState();
|
|
|
|
if(GetSectionStartTimeList().GetCount() == 0)
|
|
{
|
|
cutsceneAssertf(0, "Scene %s will not play because there is no section time list which is required for anim streaming", GetCutsceneName());
|
|
m_cutsceneState = CUTSCENE_UNLOAD_STATE;
|
|
m_streamingState = STREAMING_IDLE_STATE;
|
|
return;
|
|
}
|
|
|
|
|
|
if(GetCutfFile()->GetCutsceneFlags().IsSet(cutfCutsceneFile2::CUTSCENE_FADE_IN_GAME_FLAG))
|
|
{
|
|
m_fadeInGameAtEnd = DEFAULT_FADE;
|
|
}
|
|
if(GetCutfFile()->GetCutsceneFlags().IsSet(cutfCutsceneFile2::CUTSCENE_FADE_OUT_GAME_FLAG))
|
|
{
|
|
m_fadeOutGameAtBeginning = DEFAULT_FADE;
|
|
}
|
|
if(GetCutfFile()->GetCutsceneFlags().IsSet(cutfCutsceneFile2::CUTSCENE_FADE_IN_FLAG))
|
|
{
|
|
m_fadeInCutsceneAtBeginning = DEFAULT_FADE;
|
|
}
|
|
if(GetCutfFile()->GetCutsceneFlags().IsSet(cutfCutsceneFile2::CUTSCENE_FADE_OUT_FLAG))
|
|
{
|
|
m_fadeOutCutsceneAtEnd = DEFAULT_FADE;
|
|
}
|
|
|
|
|
|
|
|
//create the concat playback list now we have the list of concatenated scenes
|
|
//if the script passes an invalid list ie with no valid sections stop the cutscene running.
|
|
if(!CreateConcatSectionPlayBackList(m_ValidConcatSectionFlags))
|
|
{
|
|
m_cutsceneState = CUTSCENE_UNLOAD_STATE;
|
|
m_streamingState = STREAMING_IDLE_STATE;
|
|
return;
|
|
}
|
|
|
|
//check that and sections have been updated need to modify the start and end times
|
|
SetStartAndEndTimeBasedOnPlayBackList(m_ValidConcatSectionFlags);
|
|
|
|
#if __BANK
|
|
m_IsDlcScene = IsDLCCutscene();
|
|
#endif
|
|
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
UpdateAuthorization();
|
|
#endif
|
|
|
|
#if __BANK
|
|
if (m_bStartedFromWidget)
|
|
{
|
|
CPed* pPed = FindPlayerPed();
|
|
pPed->SetPosition(m_vSceneOffset);
|
|
}
|
|
#endif
|
|
LoadCutSceneSectionMapCollision(!IsCutSceneSeamless());
|
|
|
|
cutsceneManagerDebugf3("Loading cutfile state - Initing cutscene audio track");
|
|
g_CutsceneAudioEntity.InitCutsceneTrack();
|
|
|
|
if(!m_bHasScriptChangeEntitiesModelFlagBeenSet && !m_bCanScriptChangeEntitiesModel)
|
|
{
|
|
cutsceneManagerDebugf3("Loading cutfile state - Script can change cutfile models (m_bCanScriptSetupEntitiesModel = true)");
|
|
m_bCanScriptChangeEntitiesModel = true;
|
|
m_bHasScriptChangeEntitiesModelFlagBeenSet = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::RequestScriptReservedAssetsForSkip()
|
|
{
|
|
//DispatchEventToAllEntities(CUTSCENE_PAUSE_EVENT);
|
|
if(!m_bRequestedScriptAssetsForEndOfScene)
|
|
{
|
|
atArray< CCutsceneAnimatedActorEntity * > actors;
|
|
|
|
//get a list of object ids reserved for end
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
SEntityObject *pEntityObject = m_cutsceneEntityObjects.Access(entry.GetKey());
|
|
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && pModel->m_RegisteredEntityFromScript.SceneNameHash > 0)
|
|
{
|
|
if(pModel->m_RegisteredEntityFromScript.bCreatedForScript || (!pModel->m_RegisteredEntityFromScript.bDeleteBeforeEnd && pModel->m_RegisteredEntityFromScript.bAppearInScene) )
|
|
{
|
|
m_ObjectIdsReserevedForPostScene.PushAndGrow(pModel->m_RegisteredEntityFromScript.iSceneId);
|
|
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedActorEntity* pActor = static_cast<CCutsceneAnimatedActorEntity*>(pModel);
|
|
|
|
actors.PushAndGrow(pActor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//create load events for these object cause we need them now
|
|
if(m_ObjectIdsReserevedForPostScene.GetCount() > 0 )
|
|
{
|
|
m_streamingState = STREAMING_ASSETS_STATE;
|
|
|
|
//cutfObjectIdListEvent* pLoadEvent = rage_new cutfObjectIdListEvent( m_ObjectIdsReserevedForPostScene, 0.0, );
|
|
//need to preserve this list so lets create a local copy because the constructor will destroy this list
|
|
atArray<s32> tempList;
|
|
|
|
for(int i =0; i < m_ObjectIdsReserevedForPostScene.GetCount(); i++)
|
|
{
|
|
tempList.PushAndGrow(m_ObjectIdsReserevedForPostScene[i]);
|
|
}
|
|
|
|
cutfObjectIdListEventArgs LoadList(tempList);
|
|
|
|
cutfObjectIdEvent LoadEvent(GetAssetManager()->GetObject()->GetObjectId(), 0.0f, CUTSCENE_LOAD_MODELS_EVENT, &LoadList );
|
|
|
|
SetIsLoading(GetAssetManager()->GetObject()->GetObjectId(), true);
|
|
|
|
//GetAssetManager()->SetShouldCreateEntities(true);
|
|
|
|
DispatchEvent(&LoadEvent);
|
|
|
|
// This needs to be done after dispatching the load events or the cutscene will stall
|
|
|
|
m_bRequestedScriptAssetsForEndOfScene = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::DoLoadingBeforeResumingState()
|
|
{
|
|
if ( !IsLoading() && AreReservedEntitiesReady())
|
|
{
|
|
//skipped to the end
|
|
m_streamingState = STREAMING_IDLE_STATE;
|
|
m_bAssetsStreamed = true;
|
|
|
|
// we need to be in this state in order for Play() to resume the scene
|
|
m_cutsceneState = CUTSCENE_PAUSED_STATE;
|
|
|
|
#if __BANK
|
|
if(m_bScrubbingFromLooping)
|
|
{
|
|
if(m_PlayBackState == PLAY_STATE_BACKWARDS)
|
|
{
|
|
BankPlayBackwardsCallback();
|
|
}
|
|
else
|
|
{
|
|
//make sure we requeue this
|
|
m_PlayBackState = PLAY_STATE_PAUSED;
|
|
BankPlayForwardsCallback();
|
|
}
|
|
m_bScrubbingFromLooping = false;
|
|
}
|
|
|
|
if(GetScrubbingState() == SCRUBBING_NONE)
|
|
{
|
|
//want to call
|
|
Play();
|
|
//DispatchEventToObjectsOfType( CUTSCENE_ANIMATION_MANAGER_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT );
|
|
}
|
|
else
|
|
{
|
|
m_cutsceneState = CUTSCENE_PLAY_STATE;
|
|
|
|
if (GetScrubbingState() == SCRUBBING_STEPPING_FORWARDS || GetScrubbingState() == SCRUBBING_STEPPING_BACKWARDS ||
|
|
GetScrubbingState() == SCRUBBING_FORWARDS_FROM_TIME_LINE_BAR || GetScrubbingState() == SCRUBBING_BACKWARDS_FROM_TIME_LINE_BAR)
|
|
{
|
|
DispatchEventToAllEntities(CUTSCENE_PAUSE_EVENT);
|
|
}
|
|
//DispatchEventToObjectsOfType( CUTSCENE_ANIMATION_MANAGER_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT );
|
|
}
|
|
#else
|
|
//DispatchEventToObjectsOfType( CUTSCENE_ANIMATION_MANAGER_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT );
|
|
Play();
|
|
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
DispatchEventToAllEntities(CUTSCENE_PAUSE_EVENT);
|
|
DispatchEventToAllEntities(CUTSCENE_UPDATE_LOADING_EVENT );
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::DictionaryLoadedCB(crClipDictionary* pDictionary, s32 section)
|
|
{
|
|
cutsDictionaryLoadedEventArgs args(pDictionary, section);
|
|
DispatchEventToAllEntities(CUTSCENE_DICTIONARY_LOADED_EVENT, &args );
|
|
}
|
|
|
|
void CutSceneManager::DoAuthorizedState()
|
|
{
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
if(!m_RenderUnauthorizedScreen)
|
|
{
|
|
m_RenderUnauthorizedScreenTimer = 0;
|
|
m_RenderUnauthorizedScreen = true;
|
|
}
|
|
else
|
|
{
|
|
m_RenderUnauthorizedScreenTimer += fwTimer::GetSystemTimeStepInMilliseconds();
|
|
|
|
if(m_RenderUnauthorizedScreenTimer > 3000)
|
|
{
|
|
ShutDownCutscene();
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CutSceneManager::ValidateAudioLoadAndPlayEvents()
|
|
{
|
|
u32 LoadAudioEvents = 0;
|
|
u32 PlayAudioEvents = 0;
|
|
u32 StopAudioEvents = 0;
|
|
|
|
const atArray<cutfEvent*>& pLoadEventList = GetCutfFile()->GetLoadEventList();
|
|
|
|
for(int i =0; i < pLoadEventList.GetCount(); i++)
|
|
{
|
|
if(pLoadEventList[i]->GetEventId() == CUTSCENE_LOAD_AUDIO_EVENT)
|
|
{
|
|
|
|
LoadAudioEvents++;
|
|
}
|
|
}
|
|
|
|
const atArray<cutfEvent*>& pEventList = GetCutfFile()->GetEventList();
|
|
|
|
for(int i =0; i < pEventList.GetCount(); i++)
|
|
{
|
|
if(pEventList[i]->GetEventId() == CUTSCENE_PLAY_AUDIO_EVENT)
|
|
{
|
|
PlayAudioEvents++;
|
|
|
|
s32 section = GetConcatSectionForTime(pEventList[i]->GetTime() + 0.1f);
|
|
|
|
if(section != -1 && IsConcatSectionValidForPlayBack(section))
|
|
{
|
|
m_fFinalAudioPlayEventTime = pEventList[i]->GetTime();
|
|
}
|
|
}
|
|
|
|
if(pEventList[i]->GetEventId() == CUTSCENE_STOP_AUDIO_EVENT)
|
|
{
|
|
StopAudioEvents++;
|
|
}
|
|
}
|
|
|
|
|
|
#if __ASSERT
|
|
cutsceneAssertf(LoadAudioEvents == PlayAudioEvents, "Cutscene %s requires to be re-exported as the number of Load Audio (%d) and Play Audio(%d) events dont match, may result in audio playback issues", GetCutsceneName(), LoadAudioEvents, PlayAudioEvents);
|
|
cutsceneAssertf(StopAudioEvents == PlayAudioEvents, "Cutscene %s requires to be re-exported as the number of Play Audio (%d) and Stop Audio(%d) events dont match, may result in audio playback issues", GetCutsceneName(), PlayAudioEvents, StopAudioEvents);
|
|
#endif
|
|
}
|
|
|
|
|
|
void CutSceneManager::DoLoadState()
|
|
{
|
|
if(!cutsceneVerifyf(GetCutfFile(),"DoLoadState: No cutfile object loaded"))
|
|
{
|
|
m_cutsceneState = CUTSCENE_UNLOAD_STATE;
|
|
m_streamingState = STREAMING_IDLE_STATE;
|
|
return;
|
|
}
|
|
|
|
m_bCanScriptChangeEntitiesModel = false;
|
|
|
|
if(IsConcatted())
|
|
{
|
|
m_bStreamObjectsWhileSceneIsPlaying = true;
|
|
}
|
|
|
|
ValidateAudioLoadAndPlayEvents();
|
|
|
|
//the scene has been skipped, need to deal with the streaming of models that have been reserved for the end but may not be loaded.
|
|
|
|
m_streamingState = STREAMING_ASSETS_STATE;
|
|
|
|
GetCutfFile()->SortLoadEvents();
|
|
|
|
const atArray<cutfEvent*>& pLoadEventList = GetCutfFile()->GetLoadEventList();
|
|
|
|
// create the entities we need for loading purposes
|
|
atArray<s32> iObjectIdsToReserve;
|
|
GetObjectIdsInEventList( pLoadEventList, iObjectIdsToReserve );
|
|
|
|
const atArray<cutfObject*>& pObjectList = GetCutfFile()->GetObjectList();
|
|
|
|
//Create AnimatedModelEntityManagers because the streaming of cut scene peds has changed.
|
|
//A ped pointer is required to know which variation is required, this is a change to only having
|
|
//the peds model in memory.
|
|
for(int j=0; j < pObjectList.GetCount(); ++j)
|
|
{
|
|
if(pObjectList[j]->GetType() == CUTSCENE_MODEL_OBJECT_TYPE)
|
|
{
|
|
const cutfModelObject* pModelObject = static_cast<const cutfModelObject*>(pObjectList[j]);
|
|
|
|
if(pModelObject->GetModelType() == CUTSCENE_PED_MODEL_TYPE)
|
|
{
|
|
iObjectIdsToReserve.PushAndGrow(pObjectList[j]->GetObjectId());
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( int i = 0; i < iObjectIdsToReserve.GetCount(); ++i )
|
|
{
|
|
GetEntityObject( pObjectList[iObjectIdsToReserve[i]] );
|
|
}
|
|
|
|
iObjectIdsToReserve.Reset();
|
|
|
|
//decide if need to stream objects
|
|
if(m_bStreamObjectsWhileSceneIsPlaying BANK_ONLY(&& !m_bLoop))
|
|
{
|
|
if(IsConcatted() && !IsConcatSectionValidForPlayBack(0))
|
|
{
|
|
fwFlags32 StreamingFlags;
|
|
StreamingFlags.SetFlag(CS_LOAD_MODELS_EVENT | CS_LOAD_ANIM_DICT_EVENT | CS_LOAD_PARTICLE_EFFECTS_EVENT
|
|
| CS_LOAD_SCENE_EVENT | CS_LOAD_OVERLAYS_EVENT | CS_LOAD_RAYFIRE_EVENT | CS_LOAD_INTERIORS_EVENT | CS_LOAD_SUBTITLES_EVENT);
|
|
|
|
SyncLoadIndicesToStartTime(m_iNextLoadEvent, StreamingFlags, GetStartTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
StreamingFlags.SetFlag(CS_LOAD_AUDIO_EVENT);
|
|
SyncLoadIndicesToStartTime(m_iNextAudioLoadEvent, StreamingFlags, GetStartTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
StreamingFlags.SetFlag(CS_UNLOAD_MODELS_EVENT | CS_UNLOAD_ANIM_DICT_EVENT | CS_UNLOAD_PARTICLE_EFFECTS_EVENT | CS_UNLOAD_SCENE_EVENT
|
|
| CS_UNLOAD_AUDIO_EVENT| CS_UNLOAD_OVERLAYS_EVENT | CS_UNLOAD_RAYFIRE_EVENT | CS_UNLOAD_SUBTITLES_EVENT);
|
|
|
|
SyncLoadIndicesToStartTime(m_iNextUnloadEvent, StreamingFlags, GetStartTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
//this is because we know this is unique event and always needs to be dispatched at the beginning
|
|
for ( int i = 0; i < pLoadEventList.GetCount(); ++i )
|
|
{
|
|
if(pLoadEventList[i]->GetEventId() == CUTSCENE_LOAD_ANIM_DICT_EVENT)
|
|
{
|
|
DispatchEvent( pLoadEventList[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//this is because we know this is unique event and always needs to be dispatched at the beginning
|
|
for ( int i = 0; i < pLoadEventList.GetCount(); ++i )
|
|
{
|
|
if(pLoadEventList[i]->GetEventId() == CUTSCENE_LOAD_SUBTITLES_EVENT)
|
|
{
|
|
DispatchEvent( pLoadEventList[i]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//IMPORTANT:Dispatch the unload events first, because they will do nothing otherwise they will just unload something we just loaded
|
|
StreamingFlags.SetFlag(CS_UNLOAD_MODELS_EVENT | CS_UNLOAD_ANIM_DICT_EVENT | CS_UNLOAD_PARTICLE_EFFECTS_EVENT | CS_UNLOAD_SCENE_EVENT
|
|
| CS_UNLOAD_AUDIO_EVENT| CS_UNLOAD_OVERLAYS_EVENT | CS_UNLOAD_RAYFIRE_EVENT | CS_UNLOAD_SUBTITLES_EVENT);
|
|
|
|
UpdateStreaming(0.0f, m_iNextUnloadEvent, StreamingFlags, GetStartTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
StreamingFlags.SetFlag(CS_LOAD_MODELS_EVENT | CS_LOAD_ANIM_DICT_EVENT | CS_LOAD_PARTICLE_EFFECTS_EVENT
|
|
| CS_LOAD_SCENE_EVENT | CS_LOAD_OVERLAYS_EVENT | CS_LOAD_RAYFIRE_EVENT | CS_LOAD_INTERIORS_EVENT | CS_LOAD_SUBTITLES_EVENT);
|
|
|
|
UpdateStreaming(DEFAULT_STREAMING_OFFSET, m_iNextLoadEvent, StreamingFlags, GetStartTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
StreamingFlags.SetFlag(CS_LOAD_AUDIO_EVENT);
|
|
UpdateStreaming(DEFAULT_AUDIO_STREAMING_OFFSET, m_iNextAudioLoadEvent, StreamingFlags, GetStartTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
}
|
|
else
|
|
{
|
|
fwFlags32 StreamingFlags;
|
|
StreamingFlags.SetFlag(CS_LOAD_MODELS_EVENT | CS_LOAD_ANIM_DICT_EVENT | CS_LOAD_PARTICLE_EFFECTS_EVENT
|
|
| CS_LOAD_SCENE_EVENT | CS_LOAD_OVERLAYS_EVENT | CS_LOAD_RAYFIRE_EVENT | CS_LOAD_INTERIORS_EVENT | CS_LOAD_SUBTITLES_EVENT);
|
|
|
|
UpdateStreaming(DEFAULT_STREAMING_OFFSET, m_iNextLoadEvent, StreamingFlags, GetTime());
|
|
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
StreamingFlags.SetFlag(CS_LOAD_AUDIO_EVENT);
|
|
UpdateStreaming(0.0f, m_iNextAudioLoadEvent, StreamingFlags, GetTime());
|
|
|
|
StreamingFlags.ClearAllFlags();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( int i = 0; i < pLoadEventList.GetCount(); ++i )
|
|
{
|
|
//dispatch the load events but check the types because they now contain unload events
|
|
fwFlags32 StreamingFlags;
|
|
StreamingFlags.SetFlag(CS_LOAD_MODELS_EVENT | CS_LOAD_ANIM_DICT_EVENT | CS_LOAD_PARTICLE_EFFECTS_EVENT
|
|
| CS_LOAD_AUDIO_EVENT| CS_LOAD_SCENE_EVENT | CS_LOAD_OVERLAYS_EVENT | CS_LOAD_RAYFIRE_EVENT | CS_LOAD_INTERIORS_EVENT | CS_LOAD_SUBTITLES_EVENT);
|
|
|
|
if(ValidateEvent(pLoadEventList[i]->GetEventId(), StreamingFlags))
|
|
{
|
|
DispatchEvent( pLoadEventList[i] );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Also load the streaming request list file.
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.SetTime(GetCutSceneCurrentTime()*1000.0f);
|
|
gStreamingRequestList.BeginPrestream(GetCutsceneName(), false);
|
|
}
|
|
|
|
// HACK HACK HACK
|
|
// See B* 3705257 for more details. Basically some scenes are missing (or skipping due to concat play back) the
|
|
// load audio event that would normally inform the cutscene manager that it needs to wait on the audio loading in.
|
|
// The audio gets requested by a call to InitCutsceneTrack in DoLoadingCutfileState, but without a LOAD_AUDIO_EVENT
|
|
// we don't track that it's still being loaded. As a result, we can end up trying to start the audio before it's ready,
|
|
// if the audio happens to be the last asset to load.
|
|
// For some reason this has only come up in one specific scene in GTA (more than 2 years after release!)
|
|
// so we're limiting the fix to that one specific scene for now.
|
|
if (GetPlayBackFlags().IsFlagSet(CUTSCENE_PLAYBACK_FORCE_LOAD_AUDIO_EVENT))
|
|
{
|
|
cutsceneManagerDebugf3("Setting audio entity to loading for scene %s ( flagged from script using CUTSCENE_PLAYBACK_FORCE_LOAD_AUDIO_EVENT - see b* 3705257", GetCutsceneName());
|
|
SetIsLoading(FindAudioObjectId(), true);
|
|
}
|
|
|
|
Displayf("Do load State Frame:%d, beginning at time %f", fwTimer::GetFrameCount(), GetCutSceneCurrentTime());
|
|
if(!m_bCanScriptSetupEntitiesPreUpdateLoading && !m_bHasScriptSetupEntitiesPreUpdateLoadingFlagBeenSet)
|
|
{
|
|
cutsceneManagerDebugf3("Script can request assets this frame");
|
|
m_bCanScriptSetupEntitiesPreUpdateLoading = true;
|
|
m_bHasScriptSetupEntitiesPreUpdateLoadingFlagBeenSet = true;
|
|
}
|
|
m_cutsceneState = CUTSCENE_LOADING_STATE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
bool CutSceneManager::ValidateEvent(s32 type, fwFlags32 StreamingFlags)
|
|
{
|
|
switch(type)
|
|
{
|
|
case CUTSCENE_LOAD_SCENE_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_SCENE_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_MODELS_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_MODELS_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_ANIM_DICT_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_ANIM_DICT_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_PARTICLE_EFFECTS_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_PARTICLE_EFFECTS_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_AUDIO_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_AUDIO_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_RAYFIRE_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_RAYFIRE_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_OVERLAYS_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_OVERLAYS_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_MODELS_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_MODELS_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_ANIM_DICT_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_ANIM_DICT_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_PARTICLE_EFFECTS_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_PARTICLE_EFFECTS_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_SCENE_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_SCENE_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_AUDIO_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_AUDIO_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_RAYFIRE_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_RAYFIRE_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_UNLOAD_OVERLAYS_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_OVERLAYS_EVENT);
|
|
}
|
|
break;
|
|
case CUTSCENE_LOAD_SUBTITLES_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_SUBTITLES_EVENT);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_UNLOAD_SUBTITLES_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_UNLOAD_SUBTITLES_EVENT);
|
|
}
|
|
break;
|
|
|
|
case CutSceneCustomEvents::CUTSCENE_LOAD_INTERIOR_EVENT:
|
|
{
|
|
return StreamingFlags.IsFlagSet(CS_LOAD_INTERIORS_EVENT);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
bool CutSceneManager::ValidateEventTime(float fEventTime)
|
|
{
|
|
s32 section = GetConcatSectionForTime(fEventTime);
|
|
if (IsConcatSectionValidForPlayBack(section))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
float CutSceneManager::CalculateStreamingOffset(float Buffer, float currentTime) const
|
|
{
|
|
//Set the streaming offset time to be
|
|
float StreamingOffsetBuffer = Min(Buffer, GetCutfFile()->GetTotalDuration() );
|
|
|
|
//Only modify the streaming buffer if its shorter than the scene duration.
|
|
//Take into account any invalid sections for playback and ensure that effective steaming buffer is always constant.
|
|
|
|
if(GetCutfFile()->GetTotalDuration() > Buffer)
|
|
{
|
|
s32 CurrentPlayBackSection = GetConcatSectionForTime(currentTime);
|
|
s32 StreamingSection = GetConcatSectionForTime(currentTime + Buffer);
|
|
|
|
float InvalidSectionTime = 0.0f; //hold the values of invalid sections
|
|
|
|
if(IsConcatSectionValid(CurrentPlayBackSection) && IsConcatSectionValid(StreamingSection)) //both sections are valid
|
|
{
|
|
if(CurrentPlayBackSection != StreamingSection) //the play back section is different from th streaming section
|
|
{
|
|
//start by looking in the next section to the play section, this might not be the same as the streaming section
|
|
//need to look through all the sections as there may be multiple sequential invalid sections.
|
|
for(s32 i= CurrentPlayBackSection + 1; i < m_concatDataList.GetCount(); i++)
|
|
{
|
|
//float startTime = m_concatDataList[i].fStartTime;
|
|
|
|
//only interested in sections that are invalid for playback as these are dead time
|
|
if(!IsConcatSectionValidForPlayBack(i))
|
|
{
|
|
if( (currentTime + Buffer + InvalidSectionTime) > m_concatDataList[i].fStartTime)
|
|
{
|
|
InvalidSectionTime += GetConcatSectionDuration(i); //add the duration of the invalid section
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
StreamingOffsetBuffer += InvalidSectionTime;
|
|
}
|
|
|
|
return StreamingOffsetBuffer;
|
|
}
|
|
|
|
void CutSceneManager::UpdateStreaming(float Buffer, s32 &LoadIndex, fwFlags32 StreamingFlags, float CurrentTime)
|
|
{
|
|
//this will be active in final and release builds
|
|
if (m_bStreamObjectsWhileSceneIsPlaying BANK_ONLY(&& !m_bLoop))
|
|
{
|
|
float StreamingOffsetBuffer = CalculateStreamingOffset(Buffer, CurrentTime);
|
|
|
|
//cutsceneManagerDebugf("UpdateStreaming - Current Time (%6.4f) -> Streaming time(%6.4f)", CurrentTime, CurrentTime + StreamingOffsetBuffer);
|
|
|
|
//need to dispatch load events as the scene is playing
|
|
const atArray<cutfEvent*>& pLoadEventList = GetCutfFile()->GetLoadEventList();
|
|
|
|
//Load events are dispatched with respect to the streaming time, which is the current time + the streaming offset buffer
|
|
while ( (LoadIndex < pLoadEventList.GetCount()) && pLoadEventList[LoadIndex]->GetTime() <= CurrentTime + StreamingOffsetBuffer)
|
|
{
|
|
if(!(pLoadEventList[LoadIndex]->GetTime() < 0.0f))
|
|
{
|
|
//Only call load type events
|
|
if (ValidateEvent(pLoadEventList[LoadIndex]->GetEventId(),StreamingFlags))
|
|
{
|
|
if(IsConcatted())
|
|
{
|
|
cutfEvent* pCutfEvent = const_cast<cutfEvent*>(pLoadEventList[LoadIndex]);
|
|
float fEventTime = pCutfEvent->GetTime();
|
|
|
|
if (pCutfEvent->GetEventId() == CUTSCENE_UNLOAD_MODELS_EVENT)
|
|
{
|
|
// Only adjust unload events between the scene start and end time
|
|
float fEpsilon = 0.0001f;
|
|
if (fEventTime>m_fStartTime && fEventTime<m_fEndTime)
|
|
{
|
|
fEventTime=fEventTime-fEpsilon;
|
|
}
|
|
}
|
|
|
|
if (ValidateEventTime(fEventTime))
|
|
{
|
|
DispatchEvent( pLoadEventList[LoadIndex]); //refs are added to the model requests.
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DispatchEvent( pLoadEventList[LoadIndex] );
|
|
}
|
|
}
|
|
}
|
|
|
|
++LoadIndex;
|
|
}
|
|
}
|
|
};
|
|
|
|
void CutSceneManager::SyncLoadIndicesToStartTime(s32 &LoadIndex, fwFlags32 StreamingFlags, float CurrentTime)
|
|
{
|
|
//this will be active in final and release builds
|
|
if (m_bStreamObjectsWhileSceneIsPlaying BANK_ONLY(&& !m_bLoop))
|
|
{
|
|
//need to dispatch load events as the scene is playing
|
|
const atArray<cutfEvent*>& pLoadEventList = GetCutfFile()->GetLoadEventList();
|
|
|
|
s32 Index = 0;
|
|
|
|
//Load events are dispatched with respect to the streaming time, which is the current time + the streaming offset buffer
|
|
while ( (Index < pLoadEventList.GetCount()) && pLoadEventList[Index]->GetTime() < CurrentTime)
|
|
{
|
|
if (ValidateEvent(pLoadEventList[Index]->GetEventId(),StreamingFlags))
|
|
{
|
|
LoadIndex = Index;
|
|
}
|
|
|
|
Index ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CutSceneManager::DoPlayState()
|
|
{
|
|
if(m_bDelayTerminatingAFrame && !m_bWasDelayedTerminating)
|
|
{
|
|
#if __BANK
|
|
if(!m_bStepped)
|
|
#endif
|
|
{
|
|
DispatchEventToAllEntities(CUTSCENE_UPDATE_EVENT);
|
|
|
|
m_bDelayTerminatingAFrame = false;
|
|
m_bWasDelayedTerminating = true;
|
|
return;
|
|
}
|
|
}
|
|
|
|
fwFlags32 StreamingFlags;
|
|
StreamingFlags.SetFlag(CS_LOAD_MODELS_EVENT | CS_LOAD_ANIM_DICT_EVENT | CS_LOAD_PARTICLE_EFFECTS_EVENT
|
|
| CS_LOAD_SCENE_EVENT | CS_LOAD_OVERLAYS_EVENT | CS_LOAD_RAYFIRE_EVENT | CS_LOAD_INTERIORS_EVENT | CS_LOAD_SUBTITLES_EVENT);
|
|
|
|
UpdateStreaming(DEFAULT_STREAMING_OFFSET, m_iNextLoadEvent, StreamingFlags, GetTime());
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
StreamingFlags.SetFlag(CS_LOAD_AUDIO_EVENT);
|
|
UpdateStreaming(DEFAULT_AUDIO_STREAMING_OFFSET, m_iNextAudioLoadEvent, StreamingFlags, GetTime());
|
|
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
cutsManager::DoPlayState();
|
|
|
|
StreamingFlags.SetFlag(CS_UNLOAD_MODELS_EVENT | CS_UNLOAD_ANIM_DICT_EVENT | CS_UNLOAD_PARTICLE_EFFECTS_EVENT | CS_UNLOAD_SCENE_EVENT
|
|
| CS_UNLOAD_AUDIO_EVENT| CS_UNLOAD_OVERLAYS_EVENT | CS_UNLOAD_RAYFIRE_EVENT | CS_UNLOAD_SUBTITLES_EVENT);
|
|
|
|
UpdateStreaming(0.0f, m_iNextUnloadEvent, StreamingFlags, GetTime());
|
|
|
|
StreamingFlags.ClearAllFlags();
|
|
|
|
if(IsSkippingPlayback())
|
|
{
|
|
//we are skipping
|
|
if( m_bFadeOnSeamlessSkip && (m_SkipFrame != m_iEndFrame && m_SkipFrame != m_iEndFrame -1) )
|
|
{
|
|
FadeInGameAtEnd(m_fadeInGameAtEndWhenStopping);
|
|
}
|
|
|
|
SetIsSkipping(false);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DoLoadingState()
|
|
{
|
|
cutsceneManagerDebugf3("Do DoLoadingState Frame:%d", fwTimer::GetFrameCount());
|
|
|
|
cutsManager::DoLoadingState();
|
|
|
|
if(cutsManager::IsLoading())
|
|
{
|
|
for(atMap<s32, SEntityObject>::Iterator It = m_cutsceneEntityObjects.CreateIterator(); !It.AtEnd(); It.Next())
|
|
{
|
|
SEntityObject &entityObject = It.GetData();
|
|
if(entityObject.bIsLoading)
|
|
{
|
|
if(entityObject.pObject)
|
|
{
|
|
cutsceneManagerDebugf3("Do DoLoadingState Loading: %s", entityObject.pObject->GetDisplayName().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
|
|
if(m_pAssetManger)
|
|
{
|
|
m_pAssetManger->PrintStreamingRequests();
|
|
}
|
|
|
|
if(m_pAnimManager)
|
|
{
|
|
m_pAnimManager->PrintStreamingRequests();
|
|
}
|
|
|
|
#endif // __BANK
|
|
}
|
|
#if __BANK
|
|
else
|
|
{
|
|
SyncLightData();
|
|
}
|
|
#endif
|
|
#if __BANK
|
|
m_DebugManager.PopulateSelectorList(m_DebugManager.m_pPedSelectCombo, "Ped Selector", m_DebugManager.m_iPedModelIndex, m_pedModelObjectList,datCallback(MFA(CCutSceneDebugManager::GetSelectedPedEntityCallBack), (datBase*)&m_DebugManager) );
|
|
SetFrameRangeForPlayBackSliders();
|
|
#endif
|
|
}
|
|
|
|
|
|
bool CutSceneManager::AreReservedEntitiesReady()
|
|
{
|
|
if(m_bAreScriptReservedEntitiesLoaded)
|
|
{
|
|
return true;
|
|
}
|
|
bool AllEntitiesAreReady = true;
|
|
|
|
if(m_ObjectIdsReserevedForPostScene.GetCount() > 0)
|
|
{
|
|
for(int i =0; i < m_ObjectIdsReserevedForPostScene.GetCount(); i++)
|
|
{
|
|
SEntityObject* pEntityObject = m_cutsceneEntityObjects.Access(m_ObjectIdsReserevedForPostScene[i]);
|
|
|
|
if(pEntityObject)
|
|
{
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedActorEntity* pActor = static_cast<CCutsceneAnimatedActorEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pActor)
|
|
{
|
|
if(pActor->GetGameEntity())
|
|
{
|
|
if(!pActor->GetGameEntity()->HaveAllStreamingReqsCompleted() || !GetAssetManager()->HaveAllVariationsLoaded(PED_VARIATION_TYPE))
|
|
{
|
|
AllEntitiesAreReady = false;
|
|
}
|
|
}
|
|
else if(pActor->GetGameRepositionOnlyEntity())
|
|
{
|
|
if(!pActor->GetGameRepositionOnlyEntity()->HaveAllStreamingReqsCompleted() )
|
|
{
|
|
AllEntitiesAreReady = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cutfObjectIdEvent UpdateEvent(m_ObjectIdsReserevedForPostScene[i], 0.0f, CUTSCENE_UPDATE_EVENT );
|
|
DispatchEvent(&UpdateEvent);
|
|
AllEntitiesAreReady = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(AllEntitiesAreReady)
|
|
{
|
|
return m_bAreScriptReservedEntitiesLoaded = true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DoPausedState()
|
|
{
|
|
// this is only for debug pause
|
|
#if __BANK
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
DispatchEventToObjectsOfType(CUTSCENE_MODEL_OBJECT_TYPE, CUTSCENE_PAUSE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_CAMERA_OBJECT_TYPE, CUTSCENE_PAUSE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATED_PARTICLE_EFFECT_OBJECT_TYPE, CUTSCENE_PAUSE_EVENT);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//This function is called when scene fades out. Primarily this is done when the scene first starts and also when skipping.
|
|
//The fade out state is also called for a seamless scene whose assets have not loaded yet, need a fade to cover this. Need also to cover when a
|
|
//cut file hasn't loaded yet.
|
|
|
|
void CutSceneManager::DoFadingOutState()
|
|
{
|
|
// wait for the fade to complete
|
|
if (camInterface::IsFadedOut() || !m_bFadeOnSeamlessSkip || IsFadeTimerComplete()) //this is a change from checking the cut scene timer, lets just look at the camera system.
|
|
{
|
|
if ( m_bIsStoppingForEndFadeOut )
|
|
{
|
|
m_cutsceneState = CUTSCENE_STOPPED_STATE;
|
|
|
|
DispatchEventToAllEntities( CUTSCENE_STOP_EVENT );
|
|
}
|
|
else
|
|
{
|
|
if(IsSkippingPlayback())
|
|
{
|
|
//we are loading so we cant skip
|
|
|
|
m_cutsceneState = CUTSCENE_SKIPPING_STATE;
|
|
}
|
|
else
|
|
{
|
|
|
|
if(m_streamingState == STREAMING_ASSETS_STATE)
|
|
{
|
|
m_cutsceneState = CUTSCENE_LOADING_STATE; // the cut scene is already loading but a fade has been called
|
|
}
|
|
else
|
|
{
|
|
if(m_streamingState == STREAMING_CUTFILE_STATE)
|
|
{
|
|
m_cutsceneState = CUTSCENE_LOADING_CUTFILE_STATE; //some has called play even before cutfile has loaded
|
|
}
|
|
else if(m_streamingState == STREAMING_IDLE_STATE && !GetCutfFile())
|
|
{
|
|
m_cutsceneState = CUTSCENE_LOAD_CUTFILE_STATE; // load
|
|
}
|
|
else
|
|
{
|
|
m_cutsceneState = CUTSCENE_LOAD_STATE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (m_cutsceneState!= CUTSCENE_FADING_OUT_STATE)
|
|
m_EndFadeTime = 0;
|
|
}
|
|
else
|
|
{
|
|
if(IsSkippingPlayback())
|
|
{
|
|
//specifically calling the base class method as there is no code related to skipping like the derived class.
|
|
//This ensures we keep dispatching events correctly.
|
|
cutsManager::UpdatePlayBackEvents();
|
|
}
|
|
else
|
|
{
|
|
// otherwise, keep updating
|
|
cutsUpdateEventArgs updateEventArgs( GetTime(), m_fDeltaTime, m_fSectionStartTime, m_fSectionDuration );
|
|
DispatchEventToAllEntities( m_bIsStoppingForEndFadeOut ? CUTSCENE_UPDATE_EVENT : CUTSCENE_UPDATE_FADING_OUT_AT_BEGINNING_EVENT,
|
|
&updateEventArgs );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DoUnloadState()
|
|
{
|
|
if(!GetCutfFile())
|
|
{
|
|
m_cutsceneState = CUTSCENE_IDLE_STATE;
|
|
m_streamingState = STREAMING_IDLE_STATE;
|
|
ResetCutSceneVars();
|
|
return;
|
|
}
|
|
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
streamDisplayf("Cutscene unloaded - removing SRL");
|
|
gStreamingRequestList.Finish();
|
|
}
|
|
|
|
const atArray<cutfEvent*>& pLoadEventList = GetCutfFile()->GetLoadEventList();
|
|
const atArray<cutfObject*>& pObjectList = GetCutfFile()->GetObjectList();
|
|
|
|
// release all entities, except for those that we need to dispatch the unload events. That way if we unload
|
|
// a model, for example, the entity won't still have control over it.
|
|
atArray<s32> iObjectIdsToRelease;
|
|
GetObjectIdsInEventList( pLoadEventList, iObjectIdsToRelease, true );
|
|
|
|
for ( int i = 0; i < iObjectIdsToRelease.GetCount(); ++i )
|
|
{
|
|
if ( (pObjectList[iObjectIdsToRelease[i]]->GetType() == CUTSCENE_SCREEN_FADE_OBJECT_TYPE)
|
|
&& (((m_fadeInGameAtEnd == DEFAULT_FADE) && GetCutfFile()->GetCutsceneFlags().IsSet( cutfCutsceneFile2::CUTSCENE_FADE_IN_GAME_FLAG ))
|
|
|| (m_fadeInGameAtEnd == FORCE_FADE)) )
|
|
{
|
|
// If we need to do a fade in, don't delete the Screen Fade Object just yet.
|
|
continue;
|
|
}
|
|
|
|
DeleteEntityObject( pObjectList[iObjectIdsToRelease[i]] );
|
|
|
|
#if __BANK
|
|
//need to cleanup the entity lists for debugging
|
|
m_DebugManager.m_pActorEntity = NULL;
|
|
#endif
|
|
}
|
|
|
|
|
|
//Remove all remaining requests from the streaming system
|
|
if (m_bStreamObjectsWhileSceneIsPlaying BANK_ONLY(&& !m_bLoop))
|
|
{
|
|
for (;m_iNextLoadEvent < pLoadEventList.GetCount(); m_iNextLoadEvent++ )
|
|
{
|
|
fwFlags32 StreamingFlags;
|
|
|
|
StreamingFlags.SetFlag(CS_UNLOAD_MODELS_EVENT | CS_UNLOAD_ANIM_DICT_EVENT | CS_UNLOAD_PARTICLE_EFFECTS_EVENT | CS_UNLOAD_SCENE_EVENT
|
|
| CS_UNLOAD_AUDIO_EVENT| CS_UNLOAD_OVERLAYS_EVENT | CS_UNLOAD_RAYFIRE_EVENT);
|
|
|
|
if (ValidateEvent(pLoadEventList[m_iNextLoadEvent]->GetEventId(), StreamingFlags))
|
|
{
|
|
DispatchEvent(pLoadEventList[m_iNextLoadEvent]);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Dispatch all unload events, dont know what we have loaded
|
|
for (int i = 0; i < pLoadEventList.GetCount(); i++ )
|
|
{
|
|
fwFlags32 StreamingFlags;
|
|
|
|
StreamingFlags.SetFlag(CS_UNLOAD_MODELS_EVENT | CS_UNLOAD_ANIM_DICT_EVENT | CS_UNLOAD_PARTICLE_EFFECTS_EVENT | CS_UNLOAD_SCENE_EVENT
|
|
| CS_UNLOAD_AUDIO_EVENT| CS_UNLOAD_OVERLAYS_EVENT | CS_UNLOAD_RAYFIRE_EVENT);
|
|
|
|
if (ValidateEvent(pLoadEventList[i]->GetEventId(), StreamingFlags))
|
|
{
|
|
DispatchEvent(pLoadEventList[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
m_cutsceneState = CUTSCENE_UNLOADING_STATE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//dispatch the load dictionary events
|
|
|
|
void CutSceneManager::DoSkippingState()
|
|
{
|
|
// If we are skipping the entire cutscene, unload the SRL now so we have enough memory left over for the final state.
|
|
if (WasSkipped())
|
|
{
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
streamDisplayf("Cutscene skipped - removing SRL");
|
|
gStreamingRequestList.Finish();
|
|
}
|
|
}
|
|
|
|
//we are faded out pause all the anims playing
|
|
DispatchEventToAllEntities(CUTSCENE_PAUSE_EVENT);
|
|
|
|
// dispatch the skipped event to our cutscene entities
|
|
DispatchEventToAllEntities(CUTSCENE_SKIPPED_EVENT);
|
|
|
|
//Store the section before the skip
|
|
m_SectionBeforeSkip = GetSectionForTime( m_fPreviousTime );
|
|
|
|
//calculate the time change
|
|
m_fTargetSkipTime = CalculateSkipTargetTime (m_SkipFrame);
|
|
|
|
if(m_fTargetSkipTime != GetTime())
|
|
{
|
|
m_bApplyTargetSkipTime = true;
|
|
}
|
|
|
|
int iTargetSkipSectionSection = GetSectionForTime( m_fTargetSkipTime );
|
|
|
|
if(m_bFadeOnSeamlessSkip && (m_SkipFrame == m_iEndFrame || m_SkipFrame == m_iEndFrame -1) )
|
|
{
|
|
if(!m_HasScriptOverridenFadeValues)
|
|
{
|
|
m_fadeInGameAtEnd = FORCE_FADE;
|
|
m_fadeInGameAtEndWhenStopping = FORCE_FADE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_fadeInGameAtEndWhenStopping = FORCE_FADE;
|
|
}
|
|
|
|
if(m_SectionBeforeSkip != iTargetSkipSectionSection)
|
|
{
|
|
cutfTwoFloatValuesEventArgs UpdateEventArgs((float)m_SectionBeforeSkip, (float)iTargetSkipSectionSection);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATION_MANAGER_OBJECT_TYPE , CUTSCENE_LOAD_ANIM_DICT_EVENT, &UpdateEventArgs);
|
|
m_streamingState = STREAMING_ASSETS_STATE;
|
|
}
|
|
|
|
//if(m_bApplyTargetSkipTime)
|
|
{
|
|
RequestScriptReservedAssetsForSkip();
|
|
|
|
m_cutsceneState = CUTSCENE_LOADING_BEFORE_RESUMING_STATE;
|
|
// DoLoadingBeforeResumingState();
|
|
}
|
|
|
|
// simulate time passing on the radio
|
|
g_RadioAudioEntity.SkipStationsForward();
|
|
}
|
|
|
|
void CutSceneManager::DoStoppedState()
|
|
{
|
|
cutsManager::DoStoppedState();
|
|
|
|
//update the the unload states immediately don't need to wait
|
|
DoUnloadState();
|
|
DoUnloadingState();
|
|
|
|
cutsceneManagerDebugf3("DoStoppedState CUTSCENE_END_OF_SCENE_EVENT");
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CutSceneManager::IsLoading() const
|
|
{
|
|
if (cutsManager::IsLoading())
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (m_cutsceneState == CUTSCENE_LOADING_STATE)
|
|
{
|
|
return !gStreamingRequestList.AreAllAssetsLoaded();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Updates the cut scene timer and dispatched all the vents for the scene
|
|
|
|
void CutSceneManager::PreSceneUpdate()
|
|
{
|
|
SYS_CS_SYNC(sm_CutsceneLock);
|
|
|
|
#if GTA_REPLAY
|
|
//we don't need to process the cutscenes in replay so we can skip this
|
|
if(CReplayMgr::IsReplayInControlOfWorld())
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
DIAG_CONTEXT_MESSAGE("Cutscene pre scene update: %s", GetCutsceneName());
|
|
|
|
m_bHasCutThisFrame = false;
|
|
|
|
TriggerCutsceneSkip();
|
|
|
|
if(m_bShouldStopNow)
|
|
{
|
|
Stop( SKIP_FADE , m_fadeInGameAtEnd);
|
|
m_bShouldStopNow = false;
|
|
return;
|
|
}
|
|
|
|
if(!fwTimer::IsGamePaused() )
|
|
{
|
|
StartCutscene();
|
|
|
|
#if __BANK
|
|
SoakTest();
|
|
#endif
|
|
}
|
|
|
|
#if !__FINAL
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
if(fwTimer::GetSingleStepThisFrame() && !m_bWasSingledStepped)
|
|
{
|
|
m_bWasSingledStepped = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if(!fwTimer::IsGamePaused() )
|
|
{
|
|
//need to resync audio after stepping in game
|
|
#if !__FINAL
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
if(m_bWasSingledStepped && !fwTimer::GetSingleStepThisFrame())
|
|
{
|
|
if(m_PlayBackState == PLAY_STATE_FORWARDS_NORMAL_SPEED)
|
|
{
|
|
PauseResume();
|
|
m_bWasSingledStepped = false;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
UpdateCutSceneTimer();
|
|
|
|
CleanupTerminatedScriptCutSceneAssets();
|
|
|
|
cutsManager::PreSceneUpdate();
|
|
|
|
#if ENABLE_CUTSCENE_TELEMETRY
|
|
g_CutSceneLightTelemetryCollector.Update(this);
|
|
#endif
|
|
|
|
}
|
|
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
CShockingEventsManager::SuppressAllShockingEvents();
|
|
}
|
|
//RemoveIncorrectlyRegisteredScriptObjects();
|
|
|
|
// Minimap rendering during cutscene
|
|
if (IsCutscenePlayingBack())
|
|
{
|
|
if (GetDisplayMiniMapThisUpdate())
|
|
{
|
|
CMiniMap::SetVisible(true);
|
|
}
|
|
else
|
|
{
|
|
CMiniMap::SetVisible(false);
|
|
}
|
|
}
|
|
SetDisplayMiniMapThisUpdate(false); // Reset
|
|
|
|
#if SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
if(!IsPlaying() && !IsPaused())
|
|
{
|
|
grcDebugDraw::SetDisplayDebugText(true);
|
|
}
|
|
else
|
|
{
|
|
grcDebugDraw::SetDisplayDebugText(false);
|
|
|
|
|
|
}
|
|
#endif
|
|
|
|
#if __BANK
|
|
if (IsCutscenePlayingBack())
|
|
{
|
|
if(!fwTimer::IsGamePaused() && !fwTimer::GetSingleStepThisFrame() )
|
|
{
|
|
if(!PARAM_nocutarrowkeys.Get())
|
|
{
|
|
if(!IsLoading() && !WasSkipped())
|
|
{
|
|
m_DebugManager.RightArrowFastForward();
|
|
m_DebugManager.LeftArrowRewind();
|
|
m_DebugManager.UpArrowPause();
|
|
m_DebugManager.DownArrowPlay();
|
|
m_DebugManager.CtrlRightArrowStep();
|
|
m_DebugManager.CtrlLeftArrowStep();
|
|
}
|
|
}
|
|
}
|
|
OverrideGameTime();
|
|
|
|
UpdateLightDebugging();
|
|
}
|
|
|
|
cutsManager::DebugDraw();
|
|
DebugDraw();
|
|
|
|
m_bAllowAudioSyncFromRag = m_bAudioSyncWhenJogging;
|
|
|
|
if (IsRunning())
|
|
{
|
|
m_DebugManager.Update();
|
|
|
|
if (IsCutscenePlayingBack())
|
|
{
|
|
if(!fwTimer::IsGamePaused() )
|
|
{
|
|
if(m_bActivateBlockingObjectEditing)
|
|
{
|
|
m_DebugManager.UpdateMouseCursorPosition(m_vBlockingBoundPos, m_vBlockingBoundPos, m_DebugManager.m_vWorldZOffset);
|
|
}
|
|
m_DebugManager.GetMapObject();
|
|
}
|
|
|
|
if(m_DebugManager.m_bDisplayLoadedModels)
|
|
{
|
|
grcDebugDraw::AddDebugOutput("- Loaded Models -");
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
SEntityObject *pEntityObject = m_cutsceneEntityObjects.Access(entry.GetKey());
|
|
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
|
|
if(pModel && pModel->GetGameEntity())
|
|
{
|
|
if(pModel->GetCutfObject())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Loaded: %s", pModel->GetCutfObject()->GetDisplayName().c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_DebugManager.DisplayAndEditBlockingBounds();
|
|
m_DebugManager.DisplayHiddenObject();
|
|
m_DebugManager.FixupSelectedObject();
|
|
|
|
//cutsceneDisplayf("Cutscene time:%f, Section:%d, Frame:%d ", GetCutSceneCurrentTime(), GetCurrentSection(), GetCutSceneCurrentFrame() + m_iStartFrame);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if USE_MULTIHEAD_FADE
|
|
if(!m_bManualControl)
|
|
{
|
|
const bool bCutIsActive = IsPlaying();
|
|
u32 uCurrentTime = fwTimer::GetSystemTimeInMilliseconds();
|
|
if(uCurrentTime > fade::uEndTime)
|
|
{
|
|
if (bCutIsActive && !m_bBlindersUp)
|
|
{
|
|
StartMultiheadFade(true);
|
|
}
|
|
|
|
if(!bCutIsActive && m_bBlindersUp)
|
|
{
|
|
StartMultiheadFade(false);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Applies post scene update
|
|
|
|
void SetPlayerControl(bool ActivateControl)
|
|
{
|
|
CPed * pPlayerPed = CGameWorld::FindLocalPlayer();
|
|
|
|
if(pPlayerPed)
|
|
{
|
|
if(ActivateControl)
|
|
{
|
|
pPlayerPed->GetPlayerInfo()->EnableControlsCutscenes();
|
|
pPlayerPed->GetPlayerInfo()->EnableControlsCamera();
|
|
}
|
|
else
|
|
{
|
|
pPlayerPed->GetPlayerInfo()->DisableControlsCutscenes();
|
|
pPlayerPed->GetPlayerInfo()->DisableControlsCamera();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::PostSceneUpdate(float UNUSED_PARAM(fDelta))
|
|
{
|
|
#if GTA_REPLAY
|
|
//we don't need to process the cutscenes in replay so we can skip this
|
|
if(CReplayMgr::IsEditModeActive())
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
DIAG_CONTEXT_MESSAGE("Cutscene post scene update: %s", GetCutsceneName());
|
|
|
|
DispatchUpdateEventPostScene();
|
|
|
|
if (IsCutscenePlayingBack())
|
|
{
|
|
SetGameToCutSceneStatePostScene();
|
|
|
|
if(!fwTimer::IsGamePaused())
|
|
{
|
|
if(!NetworkInterface::IsGameInProgress())
|
|
{
|
|
// To make sure the world is always being streamed in correctly,
|
|
// when the player is invisible, move them to the scene origin.
|
|
if(m_iPlayerObjectId != -1)
|
|
{
|
|
int iPreviousConcatSection = GetConcatSectionForTime(GetCutScenePreviousTime());
|
|
int iCurrentConcatStection = GetConcatSectionForTime(GetCutSceneCurrentTime());
|
|
if(iPreviousConcatSection != iCurrentConcatStection)
|
|
{
|
|
cutsEntity *pEntity = GetEntityByObjectId(m_iPlayerObjectId);
|
|
if(pEntity && pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY)
|
|
{
|
|
CCutsceneAnimatedActorEntity *pActor = static_cast< CCutsceneAnimatedActorEntity * >(pEntity);
|
|
CPed *pPed = pActor->GetGameEntity();
|
|
if(pPed && pPed->IsLocalPlayer() && !pPed->GetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE) && !pActor->IsGameEntityReadyForGame())
|
|
{
|
|
cutsceneManagerDebugf3("Setting player '%s' to the scene origin (cos he's invisible)", pPed->GetModelName());
|
|
pPed->SetPosition(GetSceneOffset(), true, false, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//because lights keep updating even though the game is paused, crazy i know.
|
|
SetPostSceneUpdate(true);
|
|
DispatchEventToObjectsOfType(CUTSCENE_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
}
|
|
}
|
|
|
|
|
|
if(m_ShouldEnablePlayerControlPostScene)
|
|
{
|
|
SetPlayerControl(true);
|
|
m_ShouldEnablePlayerControlPostScene = false;
|
|
}
|
|
|
|
#if __BANK
|
|
if(!fwTimer::IsGamePaused() )
|
|
{
|
|
//we have called a step forward set the flags to say we have finished skipping
|
|
//if ( m_bIsStepping )
|
|
//{
|
|
// m_bIsStepping = false;
|
|
// m_bStepped = true;
|
|
//}
|
|
|
|
//if you are playing a scene backwards and then want to stop, it the fade will fail so set to 1.0 so it will fade out.
|
|
if(IsFadingOutAtEnd() && GetPlayBackState() == PLAY_STATE_BACKWARDS)
|
|
{
|
|
m_PlayBackState = PLAY_STATE_FORWARDS_NORMAL_SPEED;
|
|
}
|
|
|
|
if(GetHasCutThisFrame())
|
|
{
|
|
PopulateActiveLightList();
|
|
BankActiveLightSelectedCallBack();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if __BANK
|
|
if(!fwTimer::IsGamePaused() )
|
|
{
|
|
if(m_bStartedFromWidget)
|
|
{
|
|
if(IsLoaded())
|
|
{
|
|
m_DebugManager.UpdateTimeCycleParamsCB();
|
|
|
|
PlaySeamlessCutScene(THREAD_INVALID);
|
|
m_bStartedFromWidget = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
bool CutSceneManager::AreAllAudioAssetsLoaded()
|
|
{
|
|
//mangers to the cuts class
|
|
//atArray<cutsEntity*> AudioEntities;
|
|
|
|
//GetEntityByType(CUTSCENE_SOUND_GAME_ENTITY, AudioEntities);
|
|
//
|
|
//for(int i =0; i < AudioEntities.GetCount(); i++)
|
|
//{
|
|
// CCutSceneAudioEntity* pAudioEnt = static_cast<CCutSceneAudioEntity*>(AudioEntities[i]);
|
|
|
|
// if(/*pAudioEnt->IsAudioRequested() &&*/ !pAudioEnt->IsAudioLoaded())
|
|
// {
|
|
// return false;
|
|
// }
|
|
//}
|
|
|
|
return true;
|
|
};
|
|
|
|
//void CutSceneManager::CheckAudioAssetsAreReadyThisFrame()
|
|
//{
|
|
// if(IsCutscenePlayingBack() && !m_bShouldPausePlaybackForAudioLoad && !m_bCutsceneWasSkipped)
|
|
// {
|
|
// if(GetCutfFile())
|
|
// {
|
|
// atArray<cutfEvent*> AllEventList;
|
|
// AllEventList = GetCutfFile()->GetEventList();
|
|
//
|
|
// if(m_iNextEventIndex >= 0)
|
|
// {
|
|
// for(int i = m_iNextEventIndex; i < AllEventList.GetCount(); i++)
|
|
// {
|
|
// if(AllEventList[i])
|
|
// {
|
|
// //check for play audio events
|
|
// if(AllEventList[i]->GetEventId() == CUTSCENE_PLAY_AUDIO_EVENT && AllEventList[i]->GetTime() <= GetSeconds() + m_fClockTimeStep)
|
|
// {
|
|
// //check that the object that this event is meant for is ready to play the event, if not then pause.
|
|
// const cutfObjectIdEvent* pObjectEvent = static_cast<const cutfObjectIdEvent*>(AllEventList[i]);
|
|
//
|
|
// if(pObjectEvent)
|
|
// {
|
|
// const cutfObject* pAudioObj = GetObjectById(pObjectEvent->GetObjectId());
|
|
//
|
|
// if(pAudioObj)
|
|
// {
|
|
// SEntityObject* pEnt = GetEntityObject(pAudioObj, false);
|
|
//
|
|
// if(pEnt&& pEnt->pEntity)
|
|
// {
|
|
// cutsEntity* pEntity = pEnt->pEntity;
|
|
//
|
|
// if(pEntity->GetType() == CUTSCENE_SOUND_GAME_ENTITY)
|
|
// {
|
|
// CCutSceneAudioEntity* pAudioEnt = static_cast<CCutSceneAudioEntity*>(pEntity);
|
|
//
|
|
// if((!pAudioEnt->IsAudioLoaded()) && pAudioEnt->IsAudioRequested())
|
|
// {
|
|
// m_bShouldPausePlaybackForAudioLoad = true;
|
|
// Pause();
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
//}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DispatchEventToAllEntities(s32 iEventId, const cutfEventArgs *pEventArgs )
|
|
{
|
|
cutsManager::DispatchEventToAllEntities(iEventId, pEventArgs );
|
|
|
|
switch (iEventId)
|
|
{
|
|
case CUTSCENE_START_OF_SCENE_EVENT:
|
|
{
|
|
//cutsceneDisplayf("Start cutscene playback");
|
|
//defaulted to 0 this sets the cut scene time to zero at the start of the play back.
|
|
cutsceneManagerDebugf2("DispatchEventToAllEntities CUTSCENE_START_OF_SCENE_EVENT %s", GetCutsceneName());
|
|
InitialiseCutSceneTimer();
|
|
UpdateSectionInfo();
|
|
m_IsCutscenePlayingBack = true;
|
|
m_bCameraWillCameraBlendBackToGame = true;
|
|
m_bShouldRestoreCutsceneAtEnd = true;
|
|
m_ShouldEnablePlayerControlPostScene = false;
|
|
m_bPresceneLightUpdateEvent = false;
|
|
m_bShouldProcessEarlyCameraCutEventsForSinglePlayerExits = true;
|
|
m_ScriptThread = THREAD_INVALID; //set to invalid because if the script dies the scene can will clean itself up.
|
|
|
|
if(NetworkInterface::IsGameInProgress() && !m_OptionFlags.IsFlagSet(CUTSCENE_DO_NOT_REPOSITION_PLAYER_TO_SCENE_ORIGIN))
|
|
{
|
|
m_OptionFlags.SetFlag(CUTSCENE_DO_NOT_REPOSITION_PLAYER_TO_SCENE_ORIGIN);
|
|
}
|
|
|
|
//Move the player to the scene origin to stream in the collision if not in the scene.
|
|
CPed * pPlayer = CGameWorld::FindLocalPlayer();
|
|
if(!GetIsPlayerInScene() && !m_OptionFlags.IsFlagSet(CUTSCENE_DO_NOT_REPOSITION_PLAYER_TO_SCENE_ORIGIN) && !NetworkInterface::IsGameInProgress())
|
|
{
|
|
if (pPlayer)
|
|
{
|
|
m_vPlayerPositionBeforeScene = VEC3V_TO_VECTOR3(pPlayer->GetTransform().GetPosition());
|
|
pPlayer->Teleport(GetSceneOffset(), 0.0f);
|
|
pPlayer->RemovePhysics();
|
|
pPlayer->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, false, true);
|
|
cutsceneManagerVisibilityDebugf3("CUTSCENE_START_OF_SCENE_EVENT: Hiding player (%s)", pPlayer->GetModelName());
|
|
}
|
|
}
|
|
|
|
if (pPlayer && !GetOptionFlags().IsFlagSet(CUTSCENE_PLAYER_TARGETABLE))
|
|
{
|
|
CPlayerInfo* pPlayerInfo = pPlayer->GetPlayerInfo();
|
|
if (pPlayerInfo)
|
|
{
|
|
if (pPlayerInfo->GetWanted().m_EverybodyBackOff)
|
|
{
|
|
// if the flag is already set, leav eit as it is, and
|
|
// set the CUTSCENE_PLAYER_TARGETABLE flag so that we don't
|
|
// try to turn it back off again at the end
|
|
GetOptionFlags().SetFlag(CUTSCENE_PLAYER_TARGETABLE);
|
|
}
|
|
else
|
|
{
|
|
// set the everybody back off flag if requested
|
|
// to stop hostile peds attacking the player
|
|
pPlayerInfo->GetWanted().m_EverybodyBackOff = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(GetOptionFlags().IsFlagSet(CUTSCENE_PROCGRASS_FORCE_HD))
|
|
{
|
|
CPlantMgr::SetForceHDGrass(true);
|
|
}
|
|
|
|
// Begin playback of the streaming request list recording
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.Start();
|
|
}
|
|
|
|
#if __BANK
|
|
IsSceneApproved();
|
|
m_fApprovalMessagesOnScreenTimer = 0.0f;
|
|
#endif
|
|
if(FindAudioObjectId() == -1)
|
|
{
|
|
if(g_CutsceneAudioEntity.GetNumCutsceneEvents() == 0 )
|
|
{
|
|
cutsceneManagerDebugf1("No audio entity in data - Triggering cutscene audio");
|
|
g_CutsceneAudioEntity.TriggerCutscene();
|
|
}
|
|
else
|
|
{
|
|
cutsceneManagerWarningf("No audio entity in data, but cutscene audio entity has events! Will the audio start!?");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_PAUSE_EVENT:
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.Pause();
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_PLAY_EVENT:
|
|
{
|
|
cutsceneManagerDebugf2 ("Cutscene manager: CUTSCENE_PLAY_EVENT");
|
|
|
|
// Begin/resume playback of the streaming request list recording
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.Start();
|
|
}
|
|
m_bUpdateCutsceneTimer = true;
|
|
}
|
|
break;
|
|
|
|
|
|
case CUTSCENE_STOP_EVENT:
|
|
{
|
|
streamDisplayf("Cutscene stopped - removing SRL");
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.Finish();
|
|
}
|
|
|
|
CPed * pPlayer = CGameWorld::FindLocalPlayer();
|
|
//Return the player to the point he was at when the scene began
|
|
if(!GetIsPlayerInScene() && IsCutscenePlayingBack() && !m_OptionFlags.IsFlagSet(CUTSCENE_DO_NOT_REPOSITION_PLAYER_TO_SCENE_ORIGIN) && !NetworkInterface::IsGameInProgress())
|
|
{
|
|
if (pPlayer)
|
|
{
|
|
if (pPlayer->GetUsingRagdoll())
|
|
{
|
|
pPlayer->SwitchToAnimated();
|
|
}
|
|
else
|
|
{
|
|
if(!pPlayer->GetCurrentPhysicsInst()->IsInLevel())
|
|
{
|
|
pPlayer->AddPhysics();
|
|
}
|
|
}
|
|
|
|
pPlayer->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, true, true);
|
|
cutsceneManagerVisibilityDebugf3("CUTSCENE_STOP_EVENT: Showing player (%s)", pPlayer->GetModelName());
|
|
|
|
pPlayer->Teleport(m_vPlayerPositionBeforeScene, 0.0f, true);
|
|
}
|
|
}
|
|
|
|
if (pPlayer && !GetOptionFlags().IsFlagSet(CUTSCENE_PLAYER_TARGETABLE))
|
|
{
|
|
CPlayerInfo* pPlayerInfo = pPlayer->GetPlayerInfo();
|
|
if (pPlayerInfo)
|
|
{
|
|
pPlayerInfo->GetWanted().m_EverybodyBackOff = false;
|
|
}
|
|
}
|
|
|
|
if(GetOptionFlags().IsFlagSet(CUTSCENE_PROCGRASS_FORCE_HD))
|
|
{
|
|
CPlantMgr::SetForceHDGrass(false);
|
|
}
|
|
|
|
if(!WasSkipped())
|
|
{
|
|
CNetworkTelemetry::CutSceneEnded(atStringHash(GetCutsceneName()), (u32)(GetCutSceneCurrentTime() * 1000.0f));
|
|
}
|
|
|
|
//m_bCutSceneUpdating = false;
|
|
|
|
if(m_bShouldRestoreCutsceneAtEnd)
|
|
{
|
|
if(m_OptionFlags.IsFlagSet(CUTSCENE_DELAY_ENABLING_PLAYER_CONTROL_FOR_UP_TO_DATE_GAMEPLAY_CAMERA))
|
|
{
|
|
SetCutSceneToGameState(false);
|
|
}
|
|
else
|
|
{
|
|
SetCutSceneToGameState(true);
|
|
}
|
|
m_bShouldRestoreCutsceneAtEnd = false;
|
|
}
|
|
|
|
m_IsCutscenePlayingBack = false;
|
|
m_bCameraWillCameraBlendBackToGame = false;
|
|
m_bUpdateCutsceneTimer = false;
|
|
SetLightPresceneUpdate(true);
|
|
|
|
if(m_bReplayRecording)
|
|
{
|
|
m_bReplayRecording = false;
|
|
|
|
// !!TODO!! Stop replay recording...
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_END_OF_SCENE_EVENT:
|
|
{
|
|
if(m_OptionFlags.IsFlagSet(CUTSCENE_DELAY_ENABLING_PLAYER_CONTROL_FOR_UP_TO_DATE_GAMEPLAY_CAMERA))
|
|
{
|
|
if(GetCamEntity() && GetCamEntity()->IsRegisteredGameEntityUnderScriptControl())
|
|
{
|
|
SetPlayerControl(true);
|
|
}
|
|
else
|
|
{
|
|
m_ShouldEnablePlayerControlPostScene = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
//case CUTSCENE_STOP_EVENT:
|
|
// {
|
|
// m_bWaitingToFinish = true;
|
|
//
|
|
// cutsceneDisplayf("MANAGER CUTSCENE_STOP_EVENT %d", fwTimer::GetFrameCount());
|
|
// }
|
|
// break;
|
|
|
|
case CUTSCENE_UPDATE_EVENT:
|
|
{
|
|
SetPreSceneUpdate(true);
|
|
|
|
//Check that the cut scene can be skipped
|
|
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.SetTime(GetCutSceneCurrentTime()*1000.0f);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_START_REPLAY_RECORD:
|
|
{
|
|
if (m_bEnableReplayRecord && Verifyf(!m_bReplayRecording, "We are already replay recording!"))
|
|
{
|
|
m_bReplayRecording = true;
|
|
|
|
// !!TODO!! Start replay recording...
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_STOP_REPLAY_RECORD:
|
|
{
|
|
if (m_bEnableReplayRecord && Verifyf(m_bReplayRecording, "We are not replay recording!"))
|
|
{
|
|
m_bReplayRecording = false;
|
|
|
|
// !!TODO!! Stop replay recording...
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DispatchUpdateEventPostScene()
|
|
{
|
|
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
|
|
#if __BANK
|
|
bool updatedThisFrame = false;
|
|
#endif
|
|
//check that the pre scen update has been called.
|
|
if (GetPreSceneUpdate())
|
|
{
|
|
//tell our post scene systems to update
|
|
SetPostSceneUpdate(true);
|
|
DispatchEventToObjectsOfType(CUTSCENE_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_PARTICLE_EFFECT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATED_PARTICLE_EFFECT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_DECAL_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_OVERLAY_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
|
|
#if __BANK
|
|
updatedThisFrame = true;
|
|
#endif
|
|
//reset our update flags to be set next time round.
|
|
SetPostSceneUpdate(false);
|
|
SetPreSceneUpdate(false);
|
|
}
|
|
|
|
if(IsPlaying() || IsLoadingBeforeResuming())
|
|
{
|
|
//this is to unload the unused dictionaries
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATION_MANAGER_OBJECT_TYPE, CUTSCENE_UNLOAD_ANIM_DICT_EVENT);
|
|
}
|
|
|
|
//Lights need to be updated even if paused so we dispatch the update event. Particle effects an other systems are updated outside
|
|
// by other game systems.
|
|
#if __BANK
|
|
if (IsPaused() && !updatedThisFrame)
|
|
{
|
|
SetPostSceneUpdate(true);
|
|
DispatchEventToObjectType( CUTSCENE_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectType( CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_PARTICLE_EFFECT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATED_PARTICLE_EFFECT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
|
|
SetPostSceneUpdate(false);
|
|
}
|
|
#endif
|
|
}
|
|
else if(GetLightPresceneUpdateOnly())
|
|
{
|
|
if(GetCamEntity() && !GetCamEntity()->IsRegisteredGameEntityUnderScriptControl())
|
|
{
|
|
SetPostSceneUpdate(true);
|
|
DispatchEventToObjectsOfType(CUTSCENE_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
DispatchEventToObjectsOfType(CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE, CUTSCENE_UPDATE_EVENT);
|
|
|
|
SetPostSceneUpdate(false);
|
|
}
|
|
|
|
SetLightPresceneUpdate(false);
|
|
}
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DispatchEventToObjectsOfType( s32 iObjectType, s32 iEventId, cutfEventArgs *pEventArgs )
|
|
{
|
|
if(!Verifyf(GetCutfFile(), "DispatchEventToObjectType: No cutf file object loaded to find objects of type "))
|
|
{
|
|
return;
|
|
}
|
|
|
|
atArray<cutfObject*> objectList;
|
|
GetCutfFile()->FindObjectsOfType( iObjectType, objectList );
|
|
|
|
cutfObjectIdEvent evt( 0, GetTime(), iEventId, pEventArgs );
|
|
|
|
for ( int i = 0; i < objectList.GetCount(); ++i )
|
|
{
|
|
evt.SetObjectId( objectList[i]->GetObjectId() );
|
|
DispatchEvent( &evt );
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::SetNewStartPos(const Vector3 &vPos)
|
|
{
|
|
SetSceneOffset(vPos);
|
|
}
|
|
|
|
void CutSceneManager::OverrideConcatSectionPosition(const Vector3 &vPos, s32 concatsection)
|
|
{
|
|
if(IsConcatSectionValid(concatsection))
|
|
{
|
|
m_concatDataList[concatsection].vOffset = vPos;
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::OverrideConcatSectionHeading(const float& heading, s32 concatsection)
|
|
{
|
|
if(IsConcatSectionValid(concatsection))
|
|
{
|
|
m_concatDataList[concatsection].fRotation = heading;
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::OverrideConcatSectionPitch(const float& pitch, s32 concatsection)
|
|
{
|
|
if(IsConcatSectionValid(concatsection))
|
|
{
|
|
m_concatDataList[concatsection].fPitch = pitch;
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::OverrideConcatSectionRoll(const float& roll, s32 concatsection)
|
|
{
|
|
if(IsConcatSectionValid(concatsection))
|
|
{
|
|
m_concatDataList[concatsection].fRoll = roll;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::SetNewStartHeading(const float &fHeading)
|
|
{
|
|
SetSceneRotation(fHeading);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//search the entities for a blocking bound and see if the point is in it
|
|
|
|
bool CutSceneManager::IsPointInBlockingBound(const Vector3 &vVec)
|
|
{
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
if (entry.GetData().pEntity->GetType() == CUTSCENE_BLOCKING_BOUND_GAME_ENTITY)
|
|
{
|
|
CCutSceneBlockingBoundsEntity* pBounds = static_cast<CCutSceneBlockingBoundsEntity*>(entry.GetData().pEntity);
|
|
if (pBounds->IsInside(vVec))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Calculate the time step from a unified audio timer.
|
|
|
|
void CutSceneManager::ComputeTimeStep()
|
|
{
|
|
// double fMixerTimer = 0.0;
|
|
//
|
|
//#if __BANK
|
|
//
|
|
// if (m_bUseAudioTimeStep)
|
|
// {
|
|
// if(audDriver::GetMixer())
|
|
// {
|
|
// fMixerTimer = g_CutsceneAudioEntity.GetCutsceneTime()/1000.f;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// fMixerTimer = fwTimer::GetTimeInMilliseconds() / 1000.0f;
|
|
// }
|
|
//
|
|
//#else
|
|
// if(audDriver::GetMixer())
|
|
// {
|
|
// fMixerTimer= audDriver::GetMixer()->GetMixerTimeS();
|
|
// }
|
|
// else
|
|
// {
|
|
// fMixerTimer = fwTimer::GetTimeInMilliseconds() / 1000.0f ;
|
|
// }
|
|
//#endif
|
|
//
|
|
// m_fClockTimeStep = static_cast<float>(fMixerTimer - m_fLastFrameTime);
|
|
//
|
|
// m_fLastFrameTime = fMixerTimer;
|
|
|
|
//m_fTime = = g_CutsceneAudioEntity.GetCutsceneTime()/1000.f;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Get the phase of the cut scene.
|
|
|
|
float CutSceneManager::GetCutScenePhase() const
|
|
{
|
|
if (GetCutfFile())
|
|
{
|
|
float fPhase = Clamp(GetCutSceneCurrentTime()/ GetCutfFile()->GetTotalDuration(), 0.0f, 1.0f);
|
|
return fPhase;
|
|
}
|
|
else
|
|
{
|
|
return 0.0f;
|
|
}
|
|
}
|
|
|
|
|
|
bool CutSceneManager::CreateConcatSectionPlayBackList(s32 PlayBackList)
|
|
{
|
|
if(PlayBackList != INVALID_PLAYBACK_FLAG && IsConcatDataValid())
|
|
{
|
|
const atFixedArray<cutfCutsceneFile2::SConcatData, CUTSCENE_MAX_CONCAT> &concatDataList = GetConcatDataList();
|
|
|
|
s32 NumberOfInvalidSections = 0;
|
|
|
|
for( int i = 0; i < concatDataList.GetCount(); i++ )
|
|
{
|
|
if(!(PlayBackList & BIT(i)))
|
|
{
|
|
m_concatDataList[i].bValidForPlayBack = false;
|
|
NumberOfInvalidSections++;
|
|
|
|
}
|
|
}
|
|
|
|
#if __ASSERT
|
|
char PlayBackSections[256];
|
|
char Section[16];
|
|
formatf(PlayBackSections, sizeof(PlayBackSections)-1, "Sections:" );
|
|
|
|
for( int i = 0; i < 32; i++ )
|
|
{
|
|
if(PlayBackList & BIT(i))
|
|
{
|
|
formatf(Section, sizeof(Section)-1, " %d ,", i + 1);
|
|
|
|
strcat_s(PlayBackSections, sizeof(PlayBackSections), Section);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
if(cutsceneVerifyf(NumberOfInvalidSections < concatDataList.GetCount(), "%s: The script playback list is requesting %s but scene has %d sections. The scene will not play", GetCutsceneName(), PlayBackSections, concatDataList.GetCount()) )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CutSceneManager::SetStartAndEndTimeBasedOnPlayBackList(s32 PlayBackList)
|
|
{
|
|
if(PlayBackList != INVALID_PLAYBACK_FLAG && IsConcatted())
|
|
{
|
|
//update the start time if the first section is invalid.
|
|
if(!IsConcatSectionValidForPlayBack(0))
|
|
{
|
|
s32 nextValidsection = GetNextValidConcatSection(0);
|
|
|
|
if(IsConcatSectionValid(nextValidsection))
|
|
{
|
|
m_fStartTime = m_concatDataList[nextValidsection].fStartTime;
|
|
IntialiseTimers(m_fStartTime, m_fStartTime);
|
|
}
|
|
|
|
const atArray<cutfEvent*>& pEventList = GetCutfFile()->GetEventList();
|
|
while ( (m_iNextEventIndex < pEventList.GetCount()) && pEventList[m_iNextEventIndex]->GetTime() < m_fStartTime )
|
|
{
|
|
++m_iNextEventIndex;
|
|
}
|
|
}
|
|
|
|
//update the end frame if the final section is invalid for playback.
|
|
for ( int j = m_concatDataList.GetCount() - 1; j >= 0; --j )
|
|
{
|
|
if(m_concatDataList[j].bValidForPlayBack)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
m_fEndTime = m_concatDataList[j].fStartTime;
|
|
}
|
|
}
|
|
|
|
m_iStartFrame = (s32)(m_fStartTime*CUTSCENE_FPS);
|
|
m_iEndFrame = (s32)(m_fEndTime*CUTSCENE_FPS);
|
|
|
|
m_fDuration = GetPlayTime(m_fEndTime);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//gets the local phase of that anim for this section
|
|
|
|
float CutSceneManager::GetAnimPhaseForSection(float fDuration, float fSectionStartTime, float fCurrentTime) const
|
|
{
|
|
float fPhase = 0.0f;
|
|
|
|
float fAnimCurrentTime = fCurrentTime - fSectionStartTime;
|
|
|
|
fPhase = fAnimCurrentTime / fDuration;
|
|
|
|
fPhase = Clamp (fPhase, 0.0f, 1.0f);
|
|
|
|
return fPhase;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//Get the phase update for the anim
|
|
|
|
float CutSceneManager::GetPhaseUpdateAmount(const crClip* pClip, float fEventDispatchTime) const
|
|
{
|
|
//check for a blocking tag for a jump cut and set the phase accordingly
|
|
float fPhase = 0.0f;
|
|
if (pClip)
|
|
{
|
|
|
|
float fDuration = pClip->GetDuration();
|
|
|
|
//get the current phase and previous frame to work out any blocking tags for jump cuts
|
|
fPhase = GetAnimPhaseForSection(fDuration, fEventDispatchTime,GetCutSceneCurrentTime());
|
|
|
|
float time = pClip->ConvertPhaseToTime(fPhase);
|
|
float blockTime = pClip->CalcBlockedTime(time);
|
|
|
|
fPhase = pClip->ConvertTimeToPhase(blockTime);
|
|
|
|
}
|
|
return fPhase;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//Tell the cut scene manager the name of the cut scene file we want to load
|
|
void CutSceneManager::RequestCutscene(const char* pFileName, bool bPlayNow, EScreenFadeOverride fadeOutGameAtBeginning, EScreenFadeOverride fadeInCutsceneAtBeginning, EScreenFadeOverride fadeOutCutsceneAtEnd, EScreenFadeOverride fadeInGameAtEnd, scrThreadId ScriptId, s32 sPlayBackContextFlags )
|
|
{
|
|
#if __BANK
|
|
CDebugTextureViewerInterface::Close(true);
|
|
#endif // __BANK
|
|
#if ENTITYSELECT_ENABLED_BUILD
|
|
CEntitySelect::DisableEntitySelectPass(); // turn off entityselect, this seems to fix BS#351756
|
|
#endif // ENTITYSELECT_ENABLED_BUILD
|
|
|
|
//allow the scripts to call request multiple times without asserting.
|
|
if(ScriptId !=0)
|
|
{
|
|
if(ScriptId == m_ScriptThread)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (Verifyf(!m_bIsCutSceneActive, "Cutscene: %s is already active, must be stopped before starting a new cutscene", m_CutSceneHashString.GetCStr()))
|
|
{
|
|
//Check that we have a valid slot
|
|
if (Verifyf(g_CutSceneStore.FindSlot(pFileName) != -1, "Cut scene %s doesn't exist, and will not be loaded", pFileName ))
|
|
{
|
|
cutsceneManagerDebugf1("RequestCutscene: filename - %s playNow - %d fadeOutGameAtBeginning - %d fadeInCutsceneAtBeginning - %d fadeOutCutsceneAtEnd - %d fadeInGameAtEnd - %d ScriptId - %d sPlayBackContextFlags - %d", pFileName, bPlayNow, fadeOutGameAtBeginning, fadeInCutsceneAtBeginning, fadeOutCutsceneAtEnd, fadeInGameAtEnd, ScriptId, sPlayBackContextFlags);
|
|
|
|
SetPlaybackFlags(sPlayBackContextFlags);
|
|
|
|
//starting a new cut scene reset all member variables
|
|
SetUpCutSceneData();
|
|
|
|
if(GetPlayBackFlags().IsFlagSet(CUTSCENE_REQUESTED_FROM_WIDGET))
|
|
{
|
|
SetEnableReplayRecord(false);
|
|
}
|
|
|
|
//Set the game ready for a cut scene, disable radar, set player controls false etc
|
|
if ( bPlayNow )
|
|
{
|
|
SetGameToCutSceneState();
|
|
}
|
|
else
|
|
{
|
|
m_bIsSeamless = true;
|
|
}
|
|
|
|
//store the script id so if the script terminates and the scene hasn't played yet but is loaded, the assets can be streamed out.
|
|
m_ScriptThread = ScriptId;
|
|
|
|
#if __BANK
|
|
if(m_ScriptThread > 0)
|
|
{
|
|
m_bStreamObjectsWhileSceneIsPlaying = true;
|
|
}
|
|
#endif
|
|
//store the hash of the cut scene
|
|
|
|
m_CutSceneHashString.SetFromString(pFileName);
|
|
|
|
AddScriptResource(ScriptId);
|
|
|
|
m_bStreamedCutScene = !bPlayNow;
|
|
|
|
//call the load on the cut scene
|
|
Load(pFileName, NULL, bPlayNow, fadeOutGameAtBeginning, fadeInCutsceneAtBeginning, fadeOutCutsceneAtEnd, fadeInGameAtEnd);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
bool CutSceneManager::IsSceneAuthorized(atHashString& CutSceneHashString)
|
|
{
|
|
for(int i = 0; i < m_AuthorizedCutscenes.m_AuthorizedCutsceneList.GetCount(); i++)
|
|
{
|
|
if(CutSceneHashString.GetHash() == m_AuthorizedCutscenes.m_AuthorizedCutsceneList[i].GetHash())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
void CutSceneManager::UpdateAuthorization()
|
|
{
|
|
m_RenderUnauthorizedWaterMark = false;
|
|
|
|
#if __BANK
|
|
if(IsDLCCutscene())
|
|
{
|
|
m_IsAuthorizedForPlayback = IsSceneAuthorized(m_CutSceneHashString);
|
|
}
|
|
else
|
|
#endif // __BANK
|
|
{
|
|
m_IsAuthorizedForPlayback = true;
|
|
}
|
|
|
|
#if __BANK
|
|
if(!m_IsAuthorizedForPlayback && m_bStartedFromWidget)
|
|
{
|
|
if(!m_IsAuthorizedForPlayback)
|
|
{
|
|
cutsceneDisplayf("WARNING CUTSCENE %s IS NOT AUTHORIZED, NO BUGS ARE VALID FOR THIS SCENE", m_CutSceneHashString.TryGetCStr());
|
|
}
|
|
|
|
m_IsAuthorizedForPlayback = true;
|
|
|
|
if(!CFrameDump::GetBinkMode() && !CFrameDump::GetCutsceneMode())
|
|
{
|
|
m_RenderUnauthorizedWaterMark = true;
|
|
}
|
|
}
|
|
#endif //__BANK
|
|
};
|
|
#endif
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//When a cut scene starts make sure that all member variables are reset
|
|
|
|
void CutSceneManager::SetUpCutSceneData()
|
|
{
|
|
//once a cut scene has been started set true and only set false at end
|
|
m_IsCutscenePlayingBack = false;
|
|
m_bCameraWillCameraBlendBackToGame = false;
|
|
m_bIsCutSceneActive = true;
|
|
m_CutSceneHashString.Clear();
|
|
m_bStreamedCutScene = false;
|
|
SetDeleteAllRegisteredEntites(false);
|
|
#if __BANK
|
|
m_bRenderHiddenObjects = false;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Call a cleanup on the cut scene
|
|
|
|
void CutSceneManager::Clear()
|
|
{
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.Finish();
|
|
}
|
|
|
|
#if __BANK
|
|
//make sure we turn all objects back on before we clear up the cut scene
|
|
m_ActivateMapObjectEditing = false;
|
|
m_bRenderHiddenObjects = true;
|
|
m_bActivateBlockingObjectEditing = false;
|
|
m_FixupMapObject = false;
|
|
m_fPlaybackRate = 1.0f;
|
|
cOrignalSceneName.Clear();
|
|
//render any objects we decided to hide on the way
|
|
m_DebugManager.DisplayHiddenObject();
|
|
//Reset the vehicle list.
|
|
|
|
m_DebugManager.Clear();
|
|
|
|
#endif
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
m_RenderUnauthorizedScreen = false;
|
|
m_RenderUnauthorizedWaterMark = false;
|
|
#endif
|
|
|
|
// PURPOSE: Clears all of the data as both an initialization and cleanup step "Rage quote"
|
|
cutsManager::Clear();
|
|
#if __BANK
|
|
//PopulatePedVariationList();
|
|
m_DebugManager.PopulatePedVariationEventList(NULL);
|
|
m_DebugManager.PopulateVehicleVariationEventList(NULL);
|
|
m_DebugManager.PopulateOverlayEventList(NULL);
|
|
//m_DebugManager.m_CascadeBounds.PopulateSetShadowBoundsPropertyEventList(NULL);
|
|
m_DebugManager.m_CascadeBounds.PopulateSetShadowBoundsEventList(NULL);
|
|
|
|
|
|
#endif
|
|
if(g_CutSceneStore.HasObjectLoaded(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())) && GetCutfFile())
|
|
{
|
|
if (Verifyf(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash() != -1).Get(), "Cut scene doesn't exist, and will not be loaded"))
|
|
{
|
|
g_CutSceneStore.RemoveRef(strLocalIndex(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash())), REF_OTHER);
|
|
g_CutSceneStore.ClearRequiredFlag(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash()).Get(),STRFLAG_CUTSCENE_REQUIRED);
|
|
g_CutSceneStore.StreamingRemove(g_CutSceneStore.FindSlotFromHashKey(m_CutSceneHashString.GetHash()));
|
|
SetCutfFile(NULL);
|
|
}
|
|
}
|
|
Assertf (m_pAnimManager == NULL, "The pointer to the anim manager is valid this could lead to memory leak, object should be deleted and pointer nulled");
|
|
Assertf (m_pAssetManger == NULL, "The pointer to the asset manager is valid this could lead to memory leak, object should be deleted and pointer nulled ");
|
|
|
|
CTheScripts::GetScriptHandlerMgr().RemoveScriptResource(CGameScriptResource::SCRIPT_RESOURCE_CUT_SCENE, m_CutSceneHashString);
|
|
Assertf(m_iScriptRefCount == 0, "There are still outstanding script resources for this cutscene!");
|
|
m_iScriptRefCount = 0;
|
|
|
|
//Reset the cut scene vars
|
|
ResetCutSceneVars();
|
|
|
|
if(m_bShouldRestoreCutsceneAtEnd)
|
|
{
|
|
ShutDown();
|
|
}
|
|
|
|
#if SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
|
|
CPed *pLocalPlayer = CGameWorld::FindLocalPlayer();
|
|
|
|
if(pLocalPlayer)
|
|
{
|
|
Vector3 StartPos(14.7f, 0.5f, 0.0f);
|
|
pLocalPlayer->Teleport(StartPos, 0.0f, false);
|
|
}
|
|
#endif
|
|
|
|
m_bShouldRestoreCutsceneAtEnd = false;
|
|
|
|
cutsceneManagerDebugf1("Cutscene has fully terminated");
|
|
|
|
|
|
#if ENABLE_CUTSCENE_TELEMETRY
|
|
g_CutSceneLightTelemetryCollector.CutSceneStop();
|
|
#endif
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
const CEntity* CutSceneManager::GetCascadeShadowFocusEntity()
|
|
{
|
|
if (GetCamEntity())
|
|
{
|
|
return GetCamEntity()->GetCascadeShadowFocusEntityForSeamlessExit();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Restore stuff that we saved before cutscene started
|
|
|
|
void CutSceneManager::SetCutSceneToGameState(bool forcePlayerControlOn)
|
|
{
|
|
//MINIMAP
|
|
CMiniMap::SetVisible(true);
|
|
|
|
//VIEWPORT CHECK FUNCTIONALITY WITH CtotheE
|
|
if (!GetOptionFlags().IsFlagSet(CUTSCENE_NO_WIDESCREEN_BORDERS))
|
|
{
|
|
gVpMan.SetWidescreenBorders(false,0);
|
|
}
|
|
|
|
SetAllowGameToPauseForStreaming(true);
|
|
|
|
// CLEAR ANY SUBTITLES
|
|
CSubtitleText::ClearMessage();
|
|
|
|
// re-enable the player again:
|
|
CPed * pPlayerPed = CGameWorld::FindLocalPlayer();
|
|
|
|
if (pPlayerPed)
|
|
{
|
|
|
|
pPlayerPed->SetIsVisibleForModule(SETISVISIBLE_MODULE_CUTSCENE, true);
|
|
cutsceneManagerVisibilityDebugf3("CutSceneManager::SetCutSceneToGameState: Showing player (%s)", pPlayerPed->GetModelName());
|
|
|
|
if(forcePlayerControlOn)
|
|
{
|
|
SetPlayerControl(true);
|
|
}
|
|
}
|
|
|
|
CClock::Pause(false);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Checks the cut scene is not in the idle state
|
|
|
|
bool CutSceneManager::IsRunning()
|
|
{
|
|
return m_bPlayNow;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Checks that the cut scene is streaming
|
|
|
|
bool CutSceneManager::IsStreaming()
|
|
{
|
|
if (m_pAssetManger)
|
|
{
|
|
return m_pAssetManger->GetLoadState() == LOAD_STATE_STREAMING;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::ResetCutSceneVars()
|
|
{
|
|
m_fTime = 0.0f;
|
|
m_fInternalTime = 0.0f;
|
|
m_fDeltaTime = 0.0f;
|
|
m_bStreamedCutScene = false;
|
|
m_CutSceneHashString.Clear();
|
|
m_bIsCutSceneActive = false;
|
|
m_fValidFrameStep = false;
|
|
m_bIsPlayerInScene = false;
|
|
m_bIsSeamless = false;
|
|
m_bRequestedScriptAssetsForEndOfScene = false;
|
|
m_bAreScriptReservedEntitiesLoaded = false;
|
|
m_bIsSeamlessSkipping = false;
|
|
m_iPlayerObjectId = -1;
|
|
m_SeamlessSkipState = SS_DEFAULT;
|
|
sSeamlessTrigger.bScriptOveride = false;
|
|
sSeamlessTrigger.fPlayerAngle = 0.0f;
|
|
sSeamlessTrigger.fTriggerAngle = 0.0f;
|
|
sSeamlessTrigger.fTriggerOrient = 0.0f;
|
|
sSeamlessTrigger.vTriggerOffset = Vector3(0.0f, 0.0f, 0.0f);
|
|
m_iNextLoadEvent = 0;
|
|
m_iNextUnloadEvent = 0;
|
|
m_iNextAudioLoadEvent = 0;
|
|
m_uFrameCountOfFirstRegisterCall = 0;
|
|
m_VehicleModelThePlayerExitsTheSceneIn = 0;
|
|
m_ObjectIdsReserevedForPostScene.Reset();
|
|
m_bCutsceneWasSkipped = false;
|
|
m_ValidConcatSectionFlags = INVALID_PLAYBACK_FLAG;
|
|
m_PlaybackFlags = 0;
|
|
m_ScriptThread = THREAD_INVALID;
|
|
m_bCanVibratePad = false;
|
|
m_bAllowCargenToUpdate = false;
|
|
m_bCanUseMobilePhone = false;
|
|
m_HasScriptOverridenFadeValues = false;
|
|
m_CanSkipCutSceneInMultiplayerGame = false;
|
|
m_bCanSkipScene = true;
|
|
m_fSkipBlockedCameraAnimTagTime = -1.0f;
|
|
m_bHasScriptRegisteredAnEntity = false;
|
|
m_bShouldPausePlaybackForAudioLoad = false;
|
|
m_bShouldStopNow = false;
|
|
m_bApplyTargetSkipTime = false;
|
|
m_fTargetSkipTime = 0.0f;
|
|
m_fFinalAudioPlayEventTime = 0.0f;
|
|
m_bCanStartCutscene = false;
|
|
m_IsCutscenePlayingBack = false;
|
|
m_bCameraWillCameraBlendBackToGame = false;
|
|
m_bDelayTerminatingAFrame = false;
|
|
m_bWasDelayedTerminating = false;
|
|
m_bDeleteAllRegisteredEntites = false;
|
|
m_bCanScriptSetupEntitiesPreUpdateLoading = false;
|
|
m_bHasScriptSetupEntitiesPreUpdateLoadingFlagBeenSet = false;
|
|
m_bCanScriptChangeEntitiesModel = false;
|
|
m_bHasScriptChangeEntitiesModelFlagBeenSet = false;
|
|
m_bFadeOnSeamlessSkip = true;
|
|
m_bFailedToLoadBeforePlayWasRequested = false;
|
|
m_bWasSingledStepped = false;
|
|
m_IsResumingPlayBackFromSkipping = false;
|
|
m_bHasCutThisFrame = false;
|
|
m_bDisplayMiniMapThisUpdate = false;
|
|
m_bAllowGameToPauseForStreaming = true;
|
|
m_SkipFrame = 0;
|
|
m_HasSetCutsceneToGameStatePostScene = false;
|
|
m_bUpdateCutsceneTimer = false;
|
|
m_bEnableReplayRecord = true;
|
|
m_bReplayRecording = false;
|
|
m_ShutDownMode = 0;
|
|
m_bShouldProcessEarlyCameraCutEventsForSinglePlayerExits = false;
|
|
m_bHasProccessedEarlyCutEventForSinglePlayerExits = false;
|
|
|
|
|
|
#if __BANK
|
|
m_DebugManager.Clear();
|
|
m_bStartedFromWidget = false;
|
|
m_bIsFinalApproved = false;
|
|
m_bIsCutsceneAnimationApproved = false;
|
|
m_bIsCutsceneCameraApproved = false;
|
|
m_bIsCutsceneFacialApproved = false;
|
|
m_bIsCutsceneLightingApproved = false;
|
|
m_bIsCutsceneDOFApproved = false;
|
|
m_fApprovalMessagesOnScreenTimer = 0.0f;
|
|
m_ApprovedCutsceneList.m_ApprovalStatuses.Reset();
|
|
m_IsDlcScene = false;
|
|
m_fCurrentAudioTime = 0.0f;
|
|
m_fLastAudioTime = 0.0f;
|
|
m_CanSaveLightAuthoringFile = false;
|
|
m_fCurrentAudioTime = 0.0f;
|
|
m_fLastAudioTime = 0.0f;
|
|
m_iExternalFrame = 0;
|
|
|
|
if(m_pDataLightXml)
|
|
{
|
|
delete m_pDataLightXml;
|
|
}
|
|
m_pDataLightXml = NULL;
|
|
|
|
ms_DebugState.Reset();
|
|
m_AllowScrubbingToZero = true;
|
|
m_bSnapCameraToLights = false;
|
|
#endif
|
|
}
|
|
|
|
//void CutSceneManager::RemoveIncorrectlyRegisteredScriptObjects()
|
|
//{
|
|
// if(!m_bCutSceneUpdating && !m_bWaitingToFinish)
|
|
// {
|
|
// if(m_RegisteredGameEntities.GetCount()>0)
|
|
// {
|
|
// cutsceneAssertf(0,"Objects have been registered but the scene has not started, Removing all registerd objects");
|
|
// ResetRegisteredGameEntities();
|
|
// }
|
|
// }
|
|
//}
|
|
|
|
void CutSceneManager::ForceFade()
|
|
{
|
|
//something very wrong has happened we have no cutfile loaded but a play has been called and we are loading
|
|
s32 iFadeTime = (s32) (GetDefaultFadeOutDuration() * 1000.0f);
|
|
|
|
Color32 FadeColor = GetDefaultFadeColor();
|
|
|
|
//this fixes a problem in the fade system where is does not deal with colours that have alphas less than 200
|
|
FadeColor.SetAlpha(255);
|
|
camInterface::FadeOut(iFadeTime, true, FadeColor);
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//unload a pre-streamed scene because the script that called this has been terminated.
|
|
void CutSceneManager::CleanupTerminatedScriptCutSceneAssets()
|
|
{
|
|
//Scene is active but not playing, if playing m_ScriptThread would be null
|
|
if( m_bIsCutSceneActive && m_ScriptThread)
|
|
{
|
|
scrThread* pThread = scrThread::GetThread(m_ScriptThread);
|
|
|
|
if(!pThread)
|
|
{
|
|
//clear the list of registered entities
|
|
m_ScriptThread = THREAD_INVALID;
|
|
UnloadPreStreamedScene(THREAD_INVALID);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Terminates the current scene.
|
|
|
|
void CutSceneManager::UnloadPreStreamedScene(scrThreadId ScriptId)
|
|
{
|
|
//Don't allow this to be called if scene is not active at all.
|
|
if (m_bIsCutSceneActive)
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
if(!IsRunning())
|
|
{
|
|
if(ScriptId == m_ScriptThread)
|
|
{
|
|
TerminateLoadedOnlyScene();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
streamDisplayf("Cutscene prestreaming canceled - removing SRL");
|
|
if (!gStreamingRequestList.IsRunFromScript())
|
|
{
|
|
gStreamingRequestList.Finish();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::TerminateLoadedOnlyScene()
|
|
{
|
|
if(m_bIsCutSceneActive && !IsRunning())
|
|
{
|
|
//tell all the entities to remove all the loading.
|
|
DispatchEventToAllEntities(CUTSCENE_CANCEL_LOAD_EVENT);
|
|
|
|
g_CutsceneAudioEntity.StopCutscene(true);
|
|
|
|
//delete all the entity manager objects
|
|
if(GetCutfFile())
|
|
{
|
|
const atArray<cutfObject*>& pObjectList = GetCutfFile()->GetObjectList();
|
|
for ( int i = 0; i < pObjectList.GetCount(); ++i )
|
|
{
|
|
DeleteEntityObject( pObjectList[i] );
|
|
}
|
|
}
|
|
|
|
//reset all the vars
|
|
Clear();
|
|
}
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//At the start of the scene set the timer variables
|
|
void CutSceneManager::InitialiseCutSceneTimer()
|
|
{
|
|
m_fDeltaTime = 0.0f;
|
|
|
|
#if __BANK
|
|
m_iExternalFrame = 0;
|
|
#endif // __BANK
|
|
}
|
|
|
|
|
|
float CutSceneManager::AdjustTimeForBlockingTags(float DesiredTime)
|
|
{
|
|
const CCutSceneCameraEntity* pCamEntity = GetCamEntity();
|
|
|
|
const crClip* pClip = m_pAnimManager->GetCameraAnimForTime( pCamEntity->GetCameraObject(), DesiredTime, this );
|
|
|
|
if(pClip)
|
|
{
|
|
//return the end time here because the desired time is past the end of the scene.
|
|
//dont need to process any blocking tags
|
|
if(DesiredTime >= m_fEndTime)
|
|
{
|
|
return m_fEndTime;
|
|
}
|
|
|
|
u32 section = GetSectionForTime(DesiredTime);
|
|
|
|
float startSectionTime = GetSectionStartTime(section);
|
|
|
|
float clampedCurrentTime = DesiredTime;
|
|
|
|
clampedCurrentTime = Clamp(clampedCurrentTime, m_fStartTime, m_fEndTime);
|
|
|
|
float CurrentAnimTime = clampedCurrentTime - startSectionTime;
|
|
|
|
float BlockingTagTime = 0.0f;
|
|
|
|
BlockingTagTime = pClip->CalcBlockedTime(CurrentAnimTime);
|
|
|
|
//cut scene time
|
|
float blockAdjustedCutSceneTime = BlockingTagTime + startSectionTime;
|
|
|
|
//For concat boundaries where the start time is in an invalid concat section then move the time to the end of the blocking tag
|
|
if(blockAdjustedCutSceneTime != DesiredTime)
|
|
{
|
|
float TagStartTime = 0.0f;
|
|
float TagEndTime = 0.0f;
|
|
bool HasTag = false;
|
|
|
|
if(pClip)
|
|
{
|
|
const float duration = pClip->GetDuration();
|
|
const float durationInv = 1.f / duration;
|
|
|
|
static const crTag::Key TagKeyBlock = crTag::CalcKey("Block", 0xE433D77D);
|
|
crTagIterator it(*pClip->GetTags(), TagKeyBlock);
|
|
while(*it)
|
|
{
|
|
const crTag* tagBlock = static_cast<const crTag*>(*it);
|
|
|
|
float phase = BlockingTagTime * durationInv;
|
|
|
|
if(tagBlock->Contains(phase))
|
|
{
|
|
//compute the times in cutscene times.
|
|
TagStartTime = (tagBlock->GetStart() * duration) + startSectionTime;
|
|
TagEndTime = (tagBlock->GetEnd() * duration) + startSectionTime;
|
|
HasTag = true;
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
|
|
//the start tag is in an invalid concat section so lets push forward, like having a 0 property blocking tag
|
|
int concatSection = GetConcatSectionForTime(TagStartTime);
|
|
if(concatSection > -1 && HasTag)
|
|
{
|
|
if(!IsConcatSectionValidForPlayBack(concatSection))
|
|
{
|
|
blockAdjustedCutSceneTime = TagEndTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(DesiredTime != blockAdjustedCutSceneTime)
|
|
{
|
|
cutsceneManagerDebugf3("Aligning to blocking tag time from %f to %f", DesiredTime, blockAdjustedCutSceneTime);
|
|
}
|
|
|
|
#if __BANK
|
|
if(m_bUseExternalTimeStep && blockAdjustedCutSceneTime >= m_fEndTime)
|
|
{
|
|
if(pClip)
|
|
{
|
|
const float duration = pClip->GetDuration();
|
|
const float durationInv = 1.f / duration;
|
|
|
|
static const crTag::Key TagKeyBlock = crTag::CalcKey("Block", 0xE433D77D);
|
|
crTagIterator it(*pClip->GetTags(), TagKeyBlock);
|
|
while(*it)
|
|
{
|
|
const crTag* tagBlock = static_cast<const crTag*>(*it);
|
|
|
|
float phase = BlockingTagTime * durationInv;
|
|
|
|
if(tagBlock->Contains(phase))
|
|
{
|
|
m_fEndTime = startSectionTime + ((tagBlock->GetStart() * duration) - 0.0001f);
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
return blockAdjustedCutSceneTime;
|
|
}
|
|
|
|
return DesiredTime;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//Applies the time step for the last frame and applies it this frame
|
|
|
|
void CutSceneManager::UpdateCutSceneTimer()
|
|
{
|
|
if(m_bUpdateCutsceneTimer)
|
|
{
|
|
//cache the previous time
|
|
m_fPreviousTime = GetTime();
|
|
|
|
#if __BANK
|
|
if(IsCutscenePlayingBack() && m_bLoop && !m_bScrubbingFromLooping)
|
|
{
|
|
if(GetPlayBackState() == PLAY_STATE_BACKWARDS)
|
|
{
|
|
if(m_iCurrentFrameWithFrameRanges < m_iLoopStartFrame)
|
|
{
|
|
m_bScrubbingFromLooping = true;
|
|
m_iCurrentFrameWithFrameRanges = m_iLoopEndFrame;
|
|
BankFrameScrubbingCallback();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_iCurrentFrameWithFrameRanges > m_iLoopEndFrame)
|
|
{
|
|
m_bScrubbingFromLooping = true;
|
|
m_iCurrentFrameWithFrameRanges = m_iLoopStartFrame;
|
|
BankFrameScrubbingCallback();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif //__BANK
|
|
|
|
//update the timer
|
|
#if !__FINAL
|
|
m_PreviousPlayBackState = m_PlayBackState;
|
|
|
|
switch(GetScrubbingState())
|
|
{
|
|
case SCRUBBING_STEPPING_FORWARDS:
|
|
case SCRUBBING_STEPPING_BACKWARDS:
|
|
case SCRUBBING_FORWARDS_FROM_TIME_LINE_BAR:
|
|
case SCRUBBING_BACKWARDS_FROM_TIME_LINE_BAR:
|
|
case SCRUBBING_PAUSING:
|
|
{
|
|
float ftime = float(m_SkipFrame) / CUTSCENE_FPS;
|
|
|
|
#if __BANK
|
|
if(m_AllowScrubbingToZero)
|
|
{
|
|
ftime = Clamp(ftime, 0.0f, GetCutfFile()->GetTotalDuration());
|
|
}
|
|
else
|
|
{
|
|
ftime = Clamp(ftime, 0.00001f, GetCutfFile()->GetTotalDuration());
|
|
}
|
|
#endif // __BANK
|
|
SetInternalTime(ftime);
|
|
}
|
|
break;
|
|
|
|
case SCRUBBING_FAST_FORWARDING:
|
|
case SCRUBBING_PLAYING_BACKWARDS:
|
|
case SCRUBBING_REWINDING:
|
|
{
|
|
float ftime = GetInternalTime();
|
|
|
|
ftime += fwTimer::GetTimeStep_ScaledNonClipped() * m_fPlaybackRate;
|
|
#if __BANK
|
|
if(m_AllowScrubbingToZero)
|
|
{
|
|
ftime = Clamp(ftime, 0.0f, GetCutfFile()->GetTotalDuration());
|
|
}
|
|
else
|
|
{
|
|
ftime = Clamp(ftime, 0.00001f, GetCutfFile()->GetTotalDuration());
|
|
}
|
|
#endif // __BANK
|
|
|
|
SetInternalTime(ftime);
|
|
|
|
}
|
|
break;
|
|
|
|
case SCRUBBING_NONE:
|
|
{
|
|
UpdateTime();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
UpdateTime();
|
|
}
|
|
|
|
}
|
|
#else //
|
|
UpdateTime();
|
|
#endif // !__FINAL
|
|
|
|
// Apply any time change due to entering blocking tags
|
|
float BlockAdjustedTime = AdjustTimeForBlockingTags(m_fInternalTime);
|
|
|
|
// sanity clamp to scene end
|
|
BlockAdjustedTime = (Clamp(BlockAdjustedTime, m_fStartTime, m_fEndTime));
|
|
|
|
// Handle the case where we hit a blocking tag (moving forward in time) and it's moved us into the next concat section in time
|
|
// but this section is not valid for playback, we need to jump a further on section.
|
|
if (BlockAdjustedTime > m_fInternalTime && IsConcatted())
|
|
{
|
|
s32 newSection = GetConcatSectionForTime(BlockAdjustedTime);
|
|
if (newSection != -1 && !(IsConcatSectionValid(newSection) && IsConcatSectionValidForPlayBack(newSection)))
|
|
{
|
|
s32 nextValidSection = GetNextValidConcatSection(newSection);
|
|
if (nextValidSection != -1)
|
|
{
|
|
float fNextValidStartTime = GetConcatSectionStartTime(nextValidSection);
|
|
BlockAdjustedTime = AdjustTimeForBlockingTags(fNextValidStartTime);
|
|
cutsceneDisplayf("Gone into invalid section %d. Adjusting to section %d time %f ", newSection, nextValidSection, BlockAdjustedTime );
|
|
}
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(m_HoldAtEnd && !m_bCutsceneWasSkipped && GetPlayBackState() == PLAY_STATE_FORWARDS_NORMAL_SPEED && BlockAdjustedTime >= GetEndTime())
|
|
{
|
|
BankPauseCallback();
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
cutsceneDisplayf("Updating cutscene time. finalTime: %.4f", BlockAdjustedTime);
|
|
// Update the time
|
|
SetTime(BlockAdjustedTime);
|
|
}
|
|
|
|
// Update the section
|
|
if (IsConcatted())
|
|
{
|
|
u32 CurrentSection = GetConcatSectionForTime(GetTime());
|
|
if(IsConcatSectionValid(CurrentSection) && IsConcatSectionValidForPlayBack(CurrentSection))
|
|
{
|
|
m_iCurrentConcatSection = CurrentSection;
|
|
}
|
|
}
|
|
|
|
//update the section info for jumps
|
|
UpdateSectionInfo();
|
|
}
|
|
|
|
#if !__NO_OUTPUT
|
|
//update the frame count
|
|
if(GetCutfFile())
|
|
{
|
|
m_iCurrentFrame = u32(rage::round(GetTime()*CUTSCENE_FPS));
|
|
BANK_ONLY(m_iCurrentFrameWithFrameRanges = m_iCurrentFrame + GetCutfFile()->GetRangeStart();)
|
|
BANK_ONLY(m_fCurrentPhase = GetCutSceneCurrentTime() / GetCutfFile()->GetTotalDuration();)
|
|
}
|
|
|
|
#endif //!__NO_OUTPUT
|
|
|
|
#if __BANK
|
|
if(GetCutfFile())
|
|
{
|
|
if(m_uRenderMBFrame[0] == static_cast< u32 >(-1))
|
|
{
|
|
m_uRenderMBFrame[0] = GetMBFrame();
|
|
}
|
|
else
|
|
{
|
|
m_uRenderMBFrame[1] = GetMBFrame();
|
|
}
|
|
}
|
|
#endif //__BANK
|
|
}
|
|
|
|
void CutSceneManager::UpdateTime()
|
|
{
|
|
bool useAudioTime = true;
|
|
|
|
cutsceneDisplayf("Updating cutscene time. state: %d, initalTime: %.4f, IsPaused:%s, WasSkipped:%s", m_cutsceneState, m_fInternalTime, IsPaused() ? "yes" : "no", WasSkipped() ? "yes" : "no");
|
|
|
|
if(WasSkipped())
|
|
{
|
|
if(m_cutsceneState == CUTSCENE_LOADING_BEFORE_RESUMING_STATE || m_cutsceneState == CUTSCENE_SKIPPING_STATE)
|
|
{
|
|
m_fInternalTime = (float)(m_SkipFrame) / CUTSCENE_FPS;
|
|
useAudioTime = false;
|
|
m_IsResumingPlayBackFromSkipping = true;
|
|
cutsceneDebugf1("Skipping to time %.3f. State:%d", m_fInternalTime, m_cutsceneState);
|
|
}
|
|
else
|
|
{
|
|
if(IsPlaying())
|
|
{
|
|
if(m_IsResumingPlayBackFromSkipping)
|
|
{
|
|
m_fInternalTime = (float)(m_SkipFrame) / CUTSCENE_FPS;
|
|
m_IsResumingPlayBackFromSkipping = false;
|
|
cutsceneDebugf1("Resuming from skipping to time %.3f.", m_fInternalTime);
|
|
useAudioTime = false;
|
|
}
|
|
else
|
|
{
|
|
#if !__NO_OUTPUT
|
|
if (fwTimer::GetTimeStep_ScaledNonClipped()<=0.0f && !IsPaused())
|
|
{
|
|
cutsceneWarningf("Cutscene is using the game time step instead of audio (post skipping) but the timer isn't progressing. If this continues for a number of frames it could indicate a bug. timeStep:%.4f", fwTimer::GetTimeStep_ScaledNonClipped());
|
|
}
|
|
#endif // !__NO_OUTPUT
|
|
m_fInternalTime += fwTimer::GetTimeStep_ScaledNonClipped();
|
|
useAudioTime = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(useAudioTime)
|
|
{
|
|
if(FindAudioObjectId() == -1 || fwTimer::GetSingleStepThisFrame() BANK_ONLY(|| m_bUseExternalTimeStep))
|
|
{
|
|
#if __BANK
|
|
if(m_bUseExternalTimeStep)
|
|
|
|
{
|
|
m_fInternalTime = (m_iExternalFrame * m_ExternalTimeStep);
|
|
m_iExternalFrame ++;
|
|
#if !__NO_OUTPUT
|
|
if (m_fInternalTime<=m_fPreviousTime && !IsPaused())
|
|
{
|
|
cutsceneWarningf("Cutscene timer isn't progressing as the external timestep is holding us back! If this continues for a number of frames it could indicate a bug.");
|
|
}
|
|
#endif // !__NO_OUTPUT
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
m_fInternalTime += fwTimer::GetTimeStep_ScaledNonClipped();
|
|
#if !__NO_OUTPUT
|
|
if (fwTimer::GetTimeStep_ScaledNonClipped()<=0.0f && !IsPaused())
|
|
{
|
|
cutsceneWarningf("Cutscene is using the game time step instead of audio (Due to no audio object or single stepping) but the timer isn't progressing. If this continues for a number of frames it could indicate a bug. timeStep:%.4f, AudioObjectId:%d, Stepping:%s", fwTimer::GetTimeStep_ScaledNonClipped(), FindAudioObjectId(), fwTimer::GetSingleStepThisFrame() ? "yes" : "no");
|
|
}
|
|
#endif // !__NO_OUTPUT
|
|
}
|
|
|
|
#if __BANK
|
|
if(m_fInternalTime < GetEndTime())
|
|
{
|
|
s32 section = GetConcatSectionForTime(m_fInternalTime);
|
|
|
|
if(IsConcatSectionValid(section) && !IsConcatSectionValidForPlayBack(section))
|
|
{
|
|
for(int i = section + 1; i < m_concatDataList.GetCount(); i++)
|
|
{
|
|
if(IsConcatSectionValidForPlayBack(i))
|
|
{
|
|
m_fInternalTime = m_concatDataList[i].fStartTime;
|
|
#if !__NO_OUTPUT
|
|
if (m_fInternalTime<=m_fPreviousTime && !IsPaused())
|
|
{
|
|
cutsceneWarningf("Cutscene timer isn't progressing as the code to move to the next concat section is holding us back! If this continues for a number of frames it could indicate a bug.");
|
|
}
|
|
#endif // !__NO_OUTPUT
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
else
|
|
{
|
|
float newTime = g_CutsceneAudioEntity.GetCutsceneTime()/1000.f;
|
|
|
|
#if __BANK
|
|
m_fLastAudioTime = m_fCurrentAudioTime;
|
|
m_fCurrentAudioTime = newTime;
|
|
cutsceneAssertf(m_fCurrentAudioTime>=m_fLastAudioTime || IsClose(m_fCurrentAudioTime, m_fLastAudioTime, 0.015f), "Audio time has gone backwards! Last time=%.3f, new time=%.3f", m_fLastAudioTime, m_fCurrentAudioTime);
|
|
//cutsceneAssertf(newTime>=m_fInternalTime || IsClose(newTime, m_fInternalTime, 0.015f), "Cutscene adjusted time has gone backwards! Last time=%.3f, new time=%.3f, Last audio time=%.3f ", m_fInternalTime, newTime, m_fLastAudioTime);
|
|
#endif // __BANK
|
|
#if !__NO_OUTPUT
|
|
if (newTime<=m_fInternalTime && !IsPaused())
|
|
{
|
|
cutsceneManagerWarningf("Audio time isn't progressing. If this continues for a number of frames it could indicate a bug. newTime:%.4f, lastTime:%.4f", newTime, m_fInternalTime);
|
|
}
|
|
#endif // !__NO_OUTPUT
|
|
m_fInternalTime = newTime;
|
|
|
|
// if the new time is in an invalid section, clamp to the last valid section.
|
|
s32 section = GetConcatSectionForTime(m_fInternalTime);
|
|
if (section>=0 && !(IsConcatSectionValid(section) && IsConcatSectionValidForPlayBack(section)))
|
|
{
|
|
cutsceneManagerErrorf("Audio returned a time in an invalid concat section! newTime:%.6f. Clamping to the end of the last valid section...", m_fInternalTime);
|
|
s32 lastValidSection = GetPreviousValidConcatSection(section);
|
|
if (lastValidSection>=0)
|
|
{
|
|
m_fInternalTime = GetConcatSectionStartTime(lastValidSection) + GetConcatSectionDuration(lastValidSection) - SMALL_FLOAT;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Dont allow the internal time go backwards
|
|
m_fInternalTime = Max(m_fInternalTime, m_fPreviousTime);
|
|
m_fPlayTime = GetPlayTime(m_fInternalTime);
|
|
}
|
|
};
|
|
|
|
float CutSceneManager::GetPlayTime(float sceneTime)
|
|
{
|
|
if(IsConcatDataValid())
|
|
{
|
|
s32 sceneSection = GetConcatSectionForTime(sceneTime);
|
|
float playTime = 0.0f;
|
|
for (s32 i=0; i<m_concatDataList.GetCount() && i<sceneSection; i++)
|
|
{
|
|
if (IsConcatSectionValidForPlayBack(i))
|
|
{
|
|
playTime+=GetConcatSectionDuration(i);
|
|
}
|
|
}
|
|
playTime+=sceneTime - GetConcatSectionStartTime(sceneSection);
|
|
return playTime;
|
|
}
|
|
return sceneTime;
|
|
}
|
|
|
|
void CutSceneManager::UpdateEventsForInvalidSections(float NewTime)
|
|
{
|
|
if (IsConcatted())
|
|
{
|
|
//need the ability to jump an arbitrary section without dispatching those events
|
|
//so we will need to update the event index before dispatching new events
|
|
u32 CurrentSection = GetConcatSectionForTime(NewTime);
|
|
float sectionStartTime = GetConcatSectionStartTime(CurrentSection);
|
|
|
|
const atArray<cutfEvent*>& pEventList = GetCutfFile()->GetEventList();
|
|
while ( (m_iNextEventIndex < pEventList.GetCount()) && pEventList[m_iNextEventIndex]->GetTime() < sectionStartTime )
|
|
{
|
|
++m_iNextEventIndex;
|
|
}
|
|
|
|
if(IsConcatSectionValid(CurrentSection) && IsConcatSectionValidForPlayBack(CurrentSection))
|
|
{
|
|
m_iCurrentConcatSection = CurrentSection;
|
|
}
|
|
else
|
|
{
|
|
cutsceneAssertf(0, "Audio has jumped to an invalid concat section. Time: %.6f, New concat section: %d, current section: %d", NewTime, CurrentSection, m_iCurrentConcatSection );
|
|
}
|
|
}
|
|
|
|
// if(
|
|
// {
|
|
// float TargetTime = 0.0f;
|
|
// bool ValidTarget = false;
|
|
// //look through the next sections and until we find a valid one
|
|
// if (CurrentSection == (u32)m_concatDataList.GetCount() - 1 )
|
|
// {
|
|
// StopCutsceneAndDontProgressAnim();
|
|
// //cutsceneAssertf(0, "We are in the final concat section and its invalid for play back we need to terminate now");
|
|
// }
|
|
// else
|
|
// {
|
|
// for(int i = CurrentSection + 1; i < m_concatDataList.GetCount(); i++)
|
|
// {
|
|
// if(IsConcatSectionValidForPlayBack(i))
|
|
// {
|
|
// TargetTime = m_concatDataList[i].fStartTime;
|
|
// ValidTarget = true;
|
|
// m_iCurrentConcatSection = i;
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
//
|
|
// if(ValidTarget)
|
|
// {
|
|
// //update the events so that they are ready for the play state.
|
|
//
|
|
|
|
// //we need to skip the time onwards immediately this section is invalid for play back
|
|
// m_bApplyTargetSkipTime = true;
|
|
//
|
|
// //float DeltaTime = NewTime - m_concatDataList[CurrentSection].fStartTime;
|
|
// m_fTargetSkipTime = TargetTime; // + DeltaTime;
|
|
//
|
|
|
|
//
|
|
// }
|
|
// }
|
|
//}
|
|
}
|
|
|
|
|
|
void CutSceneManager::UpdateSkip()
|
|
{
|
|
switch(m_SeamlessSkipState)
|
|
{
|
|
case SS_SET_SEAMLESS_SKIP:
|
|
{
|
|
if(!m_bFadedOutCutsceneAtEnd && !IsSkippingPlayback() && !m_bShouldStopNow) //only set if not fading
|
|
{
|
|
SetIsSkipping(true);
|
|
#if __BANK
|
|
if(GetCutfFile())
|
|
{
|
|
if(m_bFadeOnSeamlessSkip && !camInterface::IsFadedOut() && !camInterface::IsFadingOut())
|
|
{
|
|
FadeOutCutsceneAtEnd( FORCE_FADE, true );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ForceFade();
|
|
}
|
|
#else
|
|
FadeOutCutsceneAtEnd( FORCE_FADE, true ); //fade out screen
|
|
|
|
#endif
|
|
m_bFadedOutCutsceneAtEnd = true;
|
|
m_cutsceneState = CUTSCENE_FADING_OUT_STATE;
|
|
}
|
|
m_SeamlessSkipState = SS_DEFAULT;
|
|
}
|
|
break;
|
|
|
|
case SS_STOP_CUTSCENE_NOW:
|
|
{
|
|
m_bShouldStopNow = true;
|
|
m_SeamlessSkipState = SS_DEFAULT;
|
|
}
|
|
break;
|
|
|
|
case SS_DEFAULT:
|
|
{
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//add the ability to skip a cut scene
|
|
void CutSceneManager::TriggerCutsceneSkip(bool bForceSkip)
|
|
{
|
|
if (IsCutscenePlayingBack())
|
|
{
|
|
if(!bForceSkip)
|
|
{
|
|
float fStartTime = GetStartTime();
|
|
float fEndTime = GetEndTime();
|
|
|
|
if (GetCutSceneCurrentTime() < (fStartTime + MIN_CUTSCENE_SKIP_TIME) || GetCutSceneCurrentTime() >= fEndTime - GetCutfFile()->GetFadeOutCutsceneAtEndDuration() )//&& GetCutSceneCurrentTime() < m_end)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool bSkip = false;
|
|
|
|
bSkip = bForceSkip;
|
|
|
|
if(NetworkInterface::IsGameInProgress())
|
|
{
|
|
bSkip = m_CanSkipCutSceneInMultiplayerGame;
|
|
}
|
|
else
|
|
{
|
|
// We pass false into GetMainPlayerControl() in case player controls are disabled but we still need to read the input.
|
|
if( !CPauseMenu::IsActive() && CControlMgr::GetMainPlayerControl(false).GetCustsceneSkip().IsPressed() && !CPhoneMgr::IsDisplayed() && m_bCanSkipScene && !IsSkipBlockedByCameraAnimTag())
|
|
{
|
|
bSkip = true;
|
|
}
|
|
}
|
|
|
|
if(bSkip && !m_bCutsceneWasSkipped)
|
|
{
|
|
m_bCutsceneWasSkipped = true;
|
|
|
|
m_bFadeOnSeamlessSkip = true;
|
|
|
|
m_SeamlessSkipState = SS_SET_SEAMLESS_SKIP;
|
|
|
|
SetSkipFrame(m_iEndFrame - 1);
|
|
|
|
CNetworkTelemetry::CutSceneSkipped(atStringHash(GetCutsceneName()), (u32)(GetCutSceneCurrentTime() * 1000.0f));
|
|
}
|
|
|
|
UpdateSkip();
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::StopCutsceneAndDontProgressAnim()
|
|
{
|
|
m_SeamlessSkipState = SS_STOP_CUTSCENE_NOW;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::StartCutscene()
|
|
{
|
|
CPed * pPlayerPed = CGameWorld::FindLocalPlayer();
|
|
|
|
if(pPlayerPed && !pPlayerPed->IsInjured())
|
|
{
|
|
if(m_bCanStartCutscene)
|
|
{
|
|
if (cutsManager::IsRunning())
|
|
{
|
|
if(!cutsManager::IsLoading())
|
|
{
|
|
if(!IsPlaying())
|
|
{
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
SetGameToCutSceneState();
|
|
|
|
if(m_IsAuthorizedForPlayback)
|
|
{
|
|
Play();
|
|
|
|
#if ENABLE_CUTSCENE_TELEMETRY
|
|
g_CutSceneLightTelemetryCollector.CutSceneStart(GetCutsceneName(), m_bIsCutsceneCameraApproved, m_bIsCutsceneLightingApproved);
|
|
#endif //ENABLE_CUTSCENE_TELEMETRY
|
|
m_bPlayNow = true;
|
|
}
|
|
else
|
|
{
|
|
m_cutsceneState = CUTSCENE_AUTHORIZED_STATE;
|
|
}
|
|
#else
|
|
//set the cut scene state for the start of the scene
|
|
SetGameToCutSceneState();
|
|
|
|
m_bPlayNow = true;
|
|
|
|
Play();
|
|
|
|
#if ENABLE_CUTSCENE_TELEMETRY
|
|
g_CutSceneLightTelemetryCollector.CutSceneStart(GetCutsceneName(), m_bIsCutsceneCameraApproved, m_bIsCutsceneLightingApproved);
|
|
#endif //ENABLE_CUTSCENE_TELEMETRY
|
|
#endif //CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//pre-streaming has failed we must fade because the script has called play but we are not ready yet
|
|
if(GetPlayBackFlags().IsFlagSet(CUTSCENE_REQUESTED_IN_MISSION))
|
|
{
|
|
cutsceneAssertf(0, "Cutscene %s started before it has loaded properly, script must wait for a scene to be loaded to avoid fading", GetCutsceneName());
|
|
}
|
|
|
|
SetGameToCutSceneState();
|
|
m_fadeInCutsceneAtBeginning = FORCE_FADE;
|
|
m_cutsceneState = CUTSCENE_FADING_OUT_STATE;
|
|
|
|
//play soon as when we finish loading
|
|
if(GetCutfFile())
|
|
{
|
|
cutsManager::FadeOutGameAtBeginning( FORCE_FADE );
|
|
if(GetAssetManager())
|
|
{
|
|
GetAssetManager()->ResetStreamingTime();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ForceFade();
|
|
}
|
|
|
|
m_bPlayNow = true;
|
|
m_bFailedToLoadBeforePlayWasRequested = true;
|
|
}
|
|
m_bCanStartCutscene = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CutSceneManager::PlaySeamlessCutScene(scrThreadId ScriptId, u32 OptionFlags)
|
|
{
|
|
if(ScriptId != m_ScriptThread && m_bCanStartCutscene == false)
|
|
{
|
|
const char* pScriptName = NULL;
|
|
scrThread* pThread = scrThread::GetThread(m_ScriptThread);
|
|
if(pThread)
|
|
{
|
|
pScriptName = pThread->GetScriptName();
|
|
}
|
|
cutsceneAssertf(ScriptId == m_ScriptThread, "Script %s (%d) has already loaded cutscene %s. This Script cannot start a scene loaded by another script, unless allowed" ,pScriptName,m_ScriptThread, m_CutSceneHashString.GetCStr());
|
|
|
|
}
|
|
|
|
CPed * pPlayerPed = CGameWorld::FindLocalPlayer();
|
|
|
|
if(pPlayerPed && !pPlayerPed->IsInjured())
|
|
{
|
|
if(ScriptId == m_ScriptThread)
|
|
{
|
|
m_OptionFlags.SetAllFlags(OptionFlags);
|
|
m_bCanStartCutscene = true;
|
|
|
|
AddScriptResource(ScriptId);
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::LoadCutSceneSectionMapCollision(bool bLoad)
|
|
{
|
|
if (bLoad)
|
|
{
|
|
g_SceneStreamerMgr.LoadScene(m_vSceneOffset);
|
|
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Work out which type of to create and also set the model index, depending if the object has been streamed in or not.
|
|
|
|
cutsEntity* CutSceneManager::ReserveEntity(const cutfObject* pObject)
|
|
{
|
|
if (!pObject)
|
|
{
|
|
//Add assert here
|
|
return NULL;
|
|
}
|
|
|
|
cutsEntity* pEntity = NULL;
|
|
|
|
//associate the object on the rage side derived from the data with a entity/delegate on the game side, will need to write an entity/delegate class
|
|
// per instance
|
|
|
|
switch ( pObject->GetType() )
|
|
{
|
|
case CUTSCENE_ASSET_MANAGER_OBJECT_TYPE:
|
|
{
|
|
m_pAssetManger = rage_new CCutSceneAssetMgrEntity( pObject );
|
|
pEntity = m_pAssetManger;
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_ANIMATION_MANAGER_OBJECT_TYPE:
|
|
{
|
|
m_pAnimManager = rage_new CCutSceneAnimMgrEntity ( pObject );
|
|
pEntity = m_pAnimManager;
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_MODEL_OBJECT_TYPE:
|
|
{
|
|
//We have no asset manager so we cant stream any game objects
|
|
if (!m_pAssetManger)
|
|
{
|
|
Assertf(0, "Trying to load assests but there is no assest manager to have streamed our object" );
|
|
return NULL;
|
|
}
|
|
|
|
const cutfModelObject* pModelObject = static_cast<const cutfModelObject*>(pObject);
|
|
|
|
if (pModelObject)
|
|
{
|
|
switch (pModelObject->GetModelType())
|
|
{
|
|
case CUTSCENE_PED_MODEL_TYPE:
|
|
{
|
|
pEntity = rage_new CCutsceneAnimatedActorEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_VEHICLE_MODEL_TYPE:
|
|
{
|
|
pEntity = rage_new CCutsceneAnimatedVehicleEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_PROP_MODEL_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneAnimatedPropEntity(pObject);
|
|
}
|
|
break;
|
|
case CUTSCENE_WEAPON_MODEL_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneAnimatedWeaponEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_CAMERA_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneCameraEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_AUDIO_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneAudioEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_FIXUP_MODEL_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneFixupBoundsEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_LIGHT_OBJECT_TYPE:
|
|
case CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneLightEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_ANIMATED_PARTICLE_EFFECT_OBJECT_TYPE:
|
|
case CUTSCENE_PARTICLE_EFFECT_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneParticleEffectsEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_SUBTITLE_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneSubtitleEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_SCREEN_FADE_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneFadeEntity(pObject->GetObjectId(), pObject );
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_BLOCKING_BOUNDS_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneBlockingBoundsEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_REMOVAL_BOUNDS_OBJECT_TYPE:
|
|
{
|
|
cutsceneAssertf(0, "CUTSCENE_REMOVAL_BOUNDS_OBJECT_TYPE not supported");
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_HIDDEN_MODEL_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneHiddenBoundsEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_OVERLAY_OBJECT_TYPE:
|
|
{
|
|
const cutfOverlayObject* pOverlayObject = static_cast<const cutfOverlayObject*>(pObject);
|
|
|
|
if(pOverlayObject->GetOverlayType() == CUTSCENE_SCALEFORM_OVERLAY_TYPE)
|
|
{
|
|
pEntity = rage_new CCutSceneScaleformOverlayEntity(pObject);
|
|
}
|
|
else if(pOverlayObject->GetOverlayType() == CUTSCENE_BINK_OVERLAY_TYPE)
|
|
{
|
|
pEntity = rage_new CCutSceneBinkOverlayEntity(pObject);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_RAYFIRE_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneRayFireEntity(pObject);
|
|
}
|
|
break;
|
|
|
|
case CUTSCENE_DECAL_OBJECT_TYPE:
|
|
{
|
|
pEntity = rage_new CCutSceneDecalEntity(pObject);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(pEntity)
|
|
{
|
|
if(pObject->GetType() == CUTSCENE_MODEL_OBJECT_TYPE)
|
|
{
|
|
#if !__NO_OUTPUT
|
|
const cutfModelObject* pModel = static_cast<const cutfModelObject*>(pObject);
|
|
#endif // !__NO_OUTPUT
|
|
cutsceneManagerDebugf2("Created %s: %s with Scene Handle: %s", pObject->GetTypeName(), pObject->GetDisplayName().c_str(), pModel->GetHandle().TryGetCStr());
|
|
}
|
|
else
|
|
{
|
|
cutsceneManagerDebugf2("Created '%s' entity for object '%s'.", pObject->GetTypeName(), pObject->GetDisplayName().c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cutsceneAssertf(0, "Object of type '%s' not supported.", pObject->GetTypeName());
|
|
}
|
|
|
|
return pEntity;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Release the entities and delete the game side object.
|
|
|
|
void CutSceneManager::ReleaseEntity(cutsEntity* pEntity, const cutfObject* pObject)
|
|
{
|
|
if ( !pEntity )
|
|
{
|
|
cutsceneDebugf1( "cutsEntity is NULL. Unable to release entity." );
|
|
return;
|
|
}
|
|
|
|
if ( !pObject )
|
|
{
|
|
cutsceneDebugf1( "cutfObject is NULL. Unable to release entity." );
|
|
return;
|
|
}
|
|
|
|
switch ( pEntity->GetType() )
|
|
{
|
|
case CUTSCENE_SINGLETON_ENTITY_TYPE:
|
|
{
|
|
//make sure that the type checking is correct
|
|
cutsSingletonEntity* pSingletonEntity = dynamic_cast<cutsSingletonEntity*>( pEntity );
|
|
if (pSingletonEntity)
|
|
{
|
|
pSingletonEntity->RemoveObject( pObject );
|
|
|
|
if ( pSingletonEntity->GetObjectList().GetCount() == 0 )
|
|
{
|
|
delete pSingletonEntity;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
//Null the cut scene managers pointer to the anim manager
|
|
if (pEntity == m_pAnimManager)
|
|
{
|
|
m_pAnimManager = NULL;
|
|
}
|
|
|
|
//Null the cut scene managers pointer to the asset manager
|
|
if (pEntity == m_pAssetManger)
|
|
{
|
|
m_pAssetManger = NULL;
|
|
}
|
|
|
|
delete pEntity;
|
|
pEntity = NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Patches the skeleton data for the cut scene objects
|
|
|
|
void CutSceneManager::GetInteriorInfo(bool bForceLoading)
|
|
{
|
|
// NEED TO IMPLEMENT BACK IN
|
|
if(camInterface::GetCutsceneDirector().GetJumpCutStatus() == camAnimatedCamera::POST_JUMP_CUT)
|
|
{
|
|
Vector3 camStartPos = VEC3_ZERO;
|
|
if (camInterface::GetCutsceneDirector().GetCameraPosition(camStartPos))
|
|
{
|
|
CInteriorInst* pIntInst = NULL;
|
|
s32 roomIdx = -1;
|
|
CPortalTracker::ProbeForInterior(camStartPos, pIntInst, roomIdx, NULL, CPortalTracker::NEAR_PROBE_DIST);
|
|
|
|
|
|
if (pIntInst && (m_pInteriorProxy != pIntInst->GetProxy()) && roomIdx >= 0)
|
|
{
|
|
m_pInteriorProxy = pIntInst->GetProxy();
|
|
pIntInst->RequestRoom(0, STRFLAG_PRIORITY_LOAD);
|
|
pIntInst->RequestRoom(roomIdx, STRFLAG_PRIORITY_LOAD);
|
|
|
|
if (bForceLoading)
|
|
{
|
|
CStreaming::LoadAllRequestedObjects();
|
|
pIntInst->ForceFadeIn();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CutSceneManager::SetGameToCutSceneStatePostScene()
|
|
{
|
|
if(!m_HasSetCutsceneToGameStatePostScene)
|
|
{
|
|
//Fire manager
|
|
g_fireMan.ExtinguishAll(true);
|
|
m_HasSetCutsceneToGameStatePostScene = true;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Purpose: Responsible for the general state of the cut scene before we start playing
|
|
//Player control, Hud, Player health etc etc
|
|
void CutSceneManager::SetGameToCutSceneState()
|
|
{
|
|
cutsceneManagerDebugf3("SetGameToCutSceneState");
|
|
|
|
//decide if the player is in the scene, do at the start event as the player can change at any point
|
|
if (!NetworkInterface::IsGameInProgress())
|
|
SetPlayerIsInScene();
|
|
|
|
//Setup the trigger heading
|
|
float newHeading = m_fSceneRotation - (sSeamlessTrigger.fPlayerAngle * RtoD) + (sSeamlessTrigger.fTriggerOrient * RtoD);
|
|
|
|
if (newHeading < 0.0)
|
|
{
|
|
newHeading = newHeading + 360.0f;
|
|
}
|
|
else
|
|
{
|
|
if (newHeading > 360.0f)
|
|
{
|
|
newHeading = newHeading - 360.0f;
|
|
}
|
|
}
|
|
|
|
this->SetNewStartHeading(newHeading);
|
|
|
|
|
|
//may remove this
|
|
|
|
//Hud and MINIMAP
|
|
if (!GetDisplayMiniMapThisUpdate())
|
|
{
|
|
CMiniMap::SetVisible(false);
|
|
}
|
|
|
|
SetAllowGameToPauseForStreaming(false);
|
|
|
|
// CHud::SetUniqueDisplay(CHud::HudData[HUD_MISSION_NAME].iItemId, 1);
|
|
|
|
// switch off any existing subtitles:
|
|
CMessages::ClearMessages();
|
|
|
|
// // fade off the mission title if its there
|
|
// if (CHud::Component[CHud::HudData[HUD_MISSION_NAME].iItemId]->IsActive())
|
|
// {
|
|
// CHud::Component[CHud::HudData[HUD_MISSION_NAME].iItemId]->SetActive(false); // switch off (it should fade out as the scene fades in)
|
|
// }
|
|
|
|
CMessages::ClearMessages(); // clear any messages in the queue
|
|
|
|
if (!GetOptionFlags().IsFlagSet(CUTSCENE_NO_WIDESCREEN_BORDERS))
|
|
{
|
|
gVpMan.SetWidescreenBorders(true,0);
|
|
}
|
|
|
|
//Player
|
|
SetPlayerControl(false);
|
|
|
|
//NEED TO STORE THE NAME OF THE SCENE
|
|
//CPlayStats::CutSceneStarted(ms_cName);
|
|
|
|
//Pad
|
|
if(CControlMgr::GetPlayerPad())
|
|
CControlMgr::GetPlayerPad()->Clear();
|
|
CControlMgr::StopPadsShaking(); // stop pads shaking
|
|
|
|
|
|
|
|
//Time
|
|
m_GameTimeHours = CClock::GetHour();
|
|
m_GameTimeMinutes = CClock::GetMinute();
|
|
m_GameTimeSeconds = CClock::GetSecond();
|
|
|
|
CClock::Pause(true);
|
|
|
|
#if __BANK
|
|
m_DebugManager.m_fTimeCycleOverrideTime = m_GameTimeHours*60;
|
|
m_DebugManager.m_fTimeCycleOverrideTime += m_GameTimeMinutes;
|
|
#endif
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
grcRasterizerStateHandle CutSceneManager::ms_LetterBoxPrevRSHandle = grcStateBlock::RS_Invalid;
|
|
grcDepthStencilStateHandle CutSceneManager::ms_LetterBoxPrevDSSHandle = grcStateBlock::DSS_Invalid;
|
|
grcBlendStateHandle CutSceneManager::ms_LetterBoxPrevBSHandle = grcStateBlock::BS_Invalid;
|
|
|
|
void CutSceneManager::LetterBoxRenderingPrologue()
|
|
{
|
|
// Just keep whatever render state is now active after we render the letterbox...
|
|
ms_LetterBoxPrevBSHandle = grcStateBlock::BS_Active;
|
|
ms_LetterBoxPrevDSSHandle = grcStateBlock::DSS_Active;
|
|
ms_LetterBoxPrevRSHandle = grcStateBlock::RS_Active;
|
|
|
|
// ...And render the letterbox without testing nor writing depth, which happens to be invalid
|
|
// (i.e.: depth/stencil buffer might have random stuff on it...) when the game is paused.
|
|
grcStateBlock::SetStates(grcStateBlock::RS_Default, grcStateBlock::DSS_IgnoreDepth, grcStateBlock::BS_Default);
|
|
}
|
|
|
|
void CutSceneManager::LetterBoxRenderingEpilogue()
|
|
{
|
|
// Set back the previous render states - ideally we'd set them to default states -, but just to avoid changing too much
|
|
grcStateBlock::SetStates(ms_LetterBoxPrevRSHandle, ms_LetterBoxPrevDSSHandle, ms_LetterBoxPrevBSHandle);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::RenderCutsceneBorders()
|
|
{
|
|
if (!CHudTools::GetWideScreen())
|
|
{
|
|
bool bBuildDrawList = gDrawListMgr->IsBuildingDrawList();
|
|
|
|
#define SIZE_OF_LETTERBOX_BORDER (0.125f) // size of letterbox border
|
|
|
|
if (bBuildDrawList)
|
|
{
|
|
DLC_Add(CutSceneManager::LetterBoxRenderingPrologue);
|
|
DLC ( CDrawRectDC, ( fwRect(0.0f, 0.0f, 1.0f, SIZE_OF_LETTERBOX_BORDER), CRGBA(0,0,0, 255)) );
|
|
DLC ( CDrawRectDC, ( fwRect(0.0f, (1.0f-SIZE_OF_LETTERBOX_BORDER), 1.0f, 1.0f), CRGBA(0,0,0, 255)) );
|
|
DLC_Add(CutSceneManager::LetterBoxRenderingEpilogue);
|
|
}
|
|
else
|
|
{
|
|
CutSceneManager::LetterBoxRenderingPrologue();
|
|
CSprite2d::DrawRect( fwRect(0.0f, 0.0f, 1.0f, SIZE_OF_LETTERBOX_BORDER), CRGBA(0,0,0, 255));
|
|
CSprite2d::DrawRect( fwRect(0.0f, (1.0f-SIZE_OF_LETTERBOX_BORDER), 1.0f, 1.0f), CRGBA(0,0,0, 255));
|
|
CutSceneManager::LetterBoxRenderingEpilogue();
|
|
}
|
|
}
|
|
}
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
void CutSceneManager::RenderAuthorizedForScriptScreen()
|
|
{
|
|
if(!m_IsAuthorizedForPlayback && m_RenderUnauthorizedScreen)
|
|
{
|
|
CTextLayout CutsceneDebugText;
|
|
char gxtDebugString[128];
|
|
|
|
float scale = 0.5f;
|
|
|
|
formatf(gxtDebugString, 128, "%s : %s", CutSceneManager::GetInstance()->GetCutsceneName(), "Not Authorized For Playback");
|
|
|
|
CutsceneDebugText.SetScale(Vector2(scale, scale));
|
|
|
|
float strWidth = CutsceneDebugText.GetStringWidthOnScreen(gxtDebugString, true);
|
|
float strHeight = CutsceneDebugText.GetCharacterHeight();
|
|
|
|
Vector2 vTextPos = Vector2(0.5f - (strWidth/2.0f), 0.5f - (strHeight/2.0f));
|
|
|
|
CutsceneDebugText.SetColor(CRGBA(255,255,255,255));
|
|
CutsceneDebugText.SetDropShadow(true);
|
|
|
|
CutsceneDebugText.Render(vTextPos, &gxtDebugString[0]);
|
|
|
|
bool bBuildDrawList = gDrawListMgr->IsBuildingDrawList();
|
|
|
|
if (bBuildDrawList)
|
|
{
|
|
DLC ( CDrawRectDC, ( fwRect(0.0f, 0.0f, 1.0f, 1.0f), CRGBA(0,0,0, 255)) );
|
|
}
|
|
else
|
|
{
|
|
CSprite2d::DrawRect( fwRect(0.0f, 0.0f, 1.0f, 1.0f), CRGBA(0,0,0, 255));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void CutSceneManager::RenderOverlayToMainRenderTarget(bool bIsCutscenePlayingBack)
|
|
{
|
|
SYS_CS_SYNC(sm_CutsceneLock);
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
RenderAuthorizedForScriptScreen();
|
|
#if __BANK
|
|
if(m_IsAuthorizedForPlayback && m_RenderUnauthorizedWaterMark)
|
|
{
|
|
RenderWatermark();
|
|
}
|
|
#endif // __BANK
|
|
#endif
|
|
|
|
#if __BANK
|
|
|
|
RenderCameraInfo();
|
|
|
|
#if SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
RenderContentRestrictedData(true);
|
|
#else
|
|
|
|
RenderContentRestrictedData(false);
|
|
|
|
#if ALLOW_APPROVAL_RENDER
|
|
bool RenderAuthorisedWaterMark = false;
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
RenderAuthorisedWaterMark = m_RenderUnauthorizedWaterMark;
|
|
#endif //CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
|
|
if(!PARAM_nocuttext.Get() && m_IsDlcScene && !RenderAuthorisedWaterMark)
|
|
{
|
|
// Only render approval messages for 10 seconds max.
|
|
if (m_fApprovalMessagesOnScreenTimer <= 10.0f)
|
|
{
|
|
RenderUnapprovedSceneInfoCallback(m_bIsFinalApproved, m_bIsCutsceneAnimationApproved, m_bIsCutsceneCameraApproved, m_bIsCutsceneFacialApproved, m_bIsCutsceneLightingApproved, m_bIsCutsceneDOFApproved);
|
|
}
|
|
m_fApprovalMessagesOnScreenTimer += fwTimer::GetSystemTimeStep();
|
|
}
|
|
RenderStreamingPausedForAudio(m_bShouldPausePlaybackForAudioLoad);
|
|
#endif // ALLOW_APPROVAL_RENDER
|
|
|
|
#endif // SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
#endif // __BANK
|
|
|
|
//search the entity list and call the render function
|
|
//can optimise by storing the entity list as a member variable and iterating
|
|
if(bIsCutscenePlayingBack)
|
|
{
|
|
if(CutSceneManager::GetInstance()->m_cutsceneEntityObjects.GetNumUsed() > 0 )
|
|
{
|
|
atMap<s32,SEntityObject>::Iterator entry = CutSceneManager::GetInstance()->m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
if (entry.GetData().pEntity && entry.GetData().pEntity->GetType() == CUTSCENE_SCALEFORM_OVERLAY_GAME_ENTITY)
|
|
{
|
|
const CCutSceneScaleformOverlayEntity* pOverlay = static_cast<const CCutSceneScaleformOverlayEntity*>(entry.GetData().pEntity);
|
|
|
|
if(pOverlay && pOverlay->GetOverlayObject() && pOverlay->GetOverlayObject()->GetOverlayType() == CUTSCENE_SCALEFORM_OVERLAY_TYPE)
|
|
{
|
|
pOverlay->RenderOverlayToMainRenderTarget();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RenderCutsceneBorders();
|
|
}
|
|
|
|
#if USE_MULTIHEAD_FADE
|
|
if (fade::uEndTime)
|
|
CSprite2d::DrawMultiFade(!fade::bInstant);
|
|
#endif
|
|
}
|
|
|
|
void CutSceneManager::RenderBinkMovieAndUpdateRenderTargets()
|
|
{
|
|
if(CutSceneManager::GetInstance()&& CutSceneManager::GetInstance()->IsCutscenePlayingBack())
|
|
{
|
|
if(CutSceneManager::GetInstance()->m_cutsceneEntityObjects.GetNumUsed() > 0 )
|
|
{
|
|
atMap<s32,SEntityObject>::Iterator entry = CutSceneManager::GetInstance()->m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
if (entry.GetData().pEntity && entry.GetData().pEntity->GetType() == CUTSCENE_BINK_OVERLAY_GAME_ENTITY)
|
|
{
|
|
const CCutSceneBinkOverlayEntity* pOverlay = static_cast<const CCutSceneBinkOverlayEntity*>(entry.GetData().pEntity);
|
|
|
|
if(pOverlay->GetOverlayObject()->GetOverlayType() == CUTSCENE_BINK_OVERLAY_TYPE)
|
|
{
|
|
pOverlay->RenderBinkMovie();
|
|
}
|
|
}
|
|
else if (entry.GetData().pEntity && entry.GetData().pEntity->GetType() == CUTSCENE_SCALEFORM_OVERLAY_GAME_ENTITY)
|
|
{
|
|
const CCutSceneScaleformOverlayEntity* pOverlay = static_cast<const CCutSceneScaleformOverlayEntity*>(entry.GetData().pEntity);
|
|
|
|
if (pOverlay->GetRenderId())
|
|
{
|
|
gRenderTargetMgr.UseRenderTarget((CRenderTargetMgr::RenderTargetId)pOverlay->GetRenderId());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RenderOverlayToRenderTarget(unsigned int targetId)
|
|
{
|
|
SYS_CS_SYNC(sm_CutsceneLock);
|
|
if(CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->IsCutscenePlayingBack())
|
|
{
|
|
if(CutSceneManager::GetInstance()->m_cutsceneEntityObjects.GetNumUsed() > 0 )
|
|
{
|
|
atMap<s32,SEntityObject>::Iterator entry = CutSceneManager::GetInstance()->m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
if (entry.GetData().pEntity && entry.GetData().pEntity->GetType() == CUTSCENE_SCALEFORM_OVERLAY_GAME_ENTITY)
|
|
{
|
|
const CCutSceneScaleformOverlayEntity* pOverlay = static_cast<const CCutSceneScaleformOverlayEntity*>(entry.GetData().pEntity);
|
|
|
|
// Render scaleform now if it's the same render target id
|
|
if (pOverlay->GetRenderId() == targetId)
|
|
{
|
|
pOverlay->RenderOverlayToRenderTarget();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SetPlayerIsInScene()
|
|
{
|
|
CPedModelInfo* pModelInfo = CGameWorld::FindLocalPlayer()->GetPedModelInfo();
|
|
|
|
if(pModelInfo)
|
|
{
|
|
atHashString playerHash(pModelInfo->GetHashKey());
|
|
|
|
CCutsceneAnimatedModelEntity* pAnimEntity = GetAnimatedModelEntityFromModelHash(playerHash);
|
|
|
|
if (pAnimEntity && pAnimEntity->GetCutfObject())
|
|
{
|
|
m_bIsPlayerInScene = true;
|
|
|
|
m_iPlayerObjectId = pAnimEntity->GetCutfObject()->GetObjectId();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CutSceneManager::GetIsPedModel(u32 iModelIndex) const
|
|
{
|
|
if(iModelIndex != strLocalIndex::INVALID_INDEX)
|
|
{
|
|
CBaseModelInfo* pMI = CModelInfo::GetBaseModelInfo(fwModelId(strLocalIndex(iModelIndex)));
|
|
if(pMI && pMI->GetModelType() == MI_TYPE_PED)
|
|
{
|
|
//Note this used to check if the model was streamed as in the player
|
|
//but we are trying to remove support for creating objects that look like peds
|
|
//so now we just create peds
|
|
|
|
//CPedModelInfo* pPMI = static_cast<CPedModelInfo*>(pMI);
|
|
|
|
//if (pPMI->GetIsStreamedGfx())
|
|
//{
|
|
return true;
|
|
//}
|
|
//else
|
|
//{
|
|
// return false;
|
|
//}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
float CutSceneManager::CalculateSkipTargetTime(int frame)
|
|
{
|
|
//could convert this to a phase
|
|
int fFrameTime = frame;
|
|
|
|
//only apply for non concatenated scenes as concatenated scene offsets are always zero unless the scene is branched,
|
|
//but still want to calculate the absolute end frame.
|
|
|
|
if(!IsConcatted())
|
|
{
|
|
fFrameTime -= m_iStartFrame;
|
|
}
|
|
|
|
float ftime = float(fFrameTime) / CUTSCENE_FPS;
|
|
|
|
return ftime = Clamp(ftime, 0.0f, GetCutfFile()->GetTotalDuration());
|
|
}
|
|
|
|
#if __BANK
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void CutSceneManager::ScrubBackwardsCB()
|
|
{
|
|
FixUpEventIndicesForPlayBackDirectionChange();
|
|
|
|
m_ScrubbingState = SCRUBBING_BACKWARDS_FROM_TIME_LINE_BAR;
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::ScrubForwardsCB()
|
|
{
|
|
FixUpEventIndicesForPlayBackDirectionChange();
|
|
|
|
m_ScrubbingState = SCRUBBING_FORWARDS_FROM_TIME_LINE_BAR;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::SetScrubbingControl(u32 CurrentFrame)
|
|
{
|
|
if (IsCutscenePlayingBack() && !IsSkippingPlayback())
|
|
{
|
|
if (!IsPaused())
|
|
{
|
|
Pause();
|
|
}
|
|
|
|
if (IsPaused())
|
|
{
|
|
|
|
if ( CurrentFrame < GetCutSceneCurrentFrame()) //we are scrubbing so lets keep dispatching events by adjusting the playback rate
|
|
{
|
|
ScrubBackwardsCB();
|
|
}
|
|
else if( CurrentFrame > GetCutSceneCurrentFrame())
|
|
{
|
|
ScrubForwardsCB();
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_bFadeOnSeamlessSkip = false;
|
|
|
|
SetSkipFrame(CurrentFrame);
|
|
|
|
DoSkippingState();
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Save scene around the current view to obj
|
|
bool GatherEntities(CEntity* pEntity, void* data)
|
|
{
|
|
Assert(pEntity && data);
|
|
atArray<CEntity*>* entities = reinterpret_cast<atArray<CEntity*>*>(data);
|
|
|
|
entities->PushAndGrow(pEntity);
|
|
return true;
|
|
}
|
|
|
|
PS3_ONLY(namespace rage { extern u32 g_AllowVertexBufferVramLocks; })
|
|
|
|
#if USE_EDGE
|
|
static const int kGetGeometryMaxVertices = 32768;
|
|
static const int kGetGeometryMaxIndices = 49152;
|
|
static Vector4* sGetGeometryVertices = NULL;
|
|
static u16* sGetGeometryIndices = NULL;
|
|
#endif
|
|
void CutSceneManager::CaptureDrawable(CEntity* entity, rmcDrawable* drawable, FileHandle& objFile, FileHandle& pivotFile, Matrix34& entityMatrix, u32& nextIndex, Matrix43* ms, const Vector3& euler)
|
|
{
|
|
if (!drawable)
|
|
{
|
|
return;
|
|
}
|
|
|
|
rmcLodGroup* lodGroup = &drawable->GetLodGroup();
|
|
rmcLod* lod = &lodGroup->GetLod(LOD_HIGH);
|
|
if (!lod)
|
|
{
|
|
return;
|
|
}
|
|
|
|
grmModel* model = lod->GetModel(0);
|
|
if (!model)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CBaseModelInfo* mi = entity->GetBaseModelInfo();
|
|
if (!mi)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!mi->GetIsProp() && !entity->GetIsTypeVehicle() && !m_captureMap)
|
|
{
|
|
return;
|
|
}
|
|
else if ((mi->GetIsProp() && !m_captureProps) || (entity->GetIsTypeVehicle() && !m_captureVehicles))
|
|
{
|
|
return;
|
|
}
|
|
|
|
char str[256] = { 0 };
|
|
char str2[256] = { 0 };
|
|
|
|
if (mi->GetIsProp())
|
|
{
|
|
sprintf(str, "%s_prop", entity->GetModelName());
|
|
}
|
|
else if (entity->GetIsTypeVehicle())
|
|
{
|
|
sprintf(str, "%s_vehicle", entity->GetModelName());
|
|
}
|
|
else if (entity->GetIsTypePed())
|
|
{
|
|
sprintf(str, "%s_ped", entity->GetModelName());
|
|
}
|
|
else
|
|
{
|
|
sprintf(str, "%s_map", entity->GetModelName());
|
|
}
|
|
|
|
// output entity pivot point
|
|
if (!entity->GetIsTypePed())
|
|
{
|
|
formatf(str2, "%s %f %f %f %f %f %f\n", str, entityMatrix.d.x, entityMatrix.d.y, entityMatrix.d.z, euler.x, euler.y, euler.z);
|
|
CFileMgr::Write(pivotFile, str2, istrlen(str2));
|
|
|
|
CObjExporter::AddGroup(objFile, str);
|
|
}
|
|
|
|
u8 extractMask = CExtractGeomParams::extractPos | CExtractGeomParams::extractUv;
|
|
if (ms)
|
|
extractMask |= CExtractGeomParams::extractSkin;
|
|
|
|
PS3_ONLY(g_AllowVertexBufferVramLocks++;)
|
|
for (u32 f = 0; f < model->GetGeometryCount(); ++f)
|
|
{
|
|
grmGeometry* geometry = &model->GetGeometry(f);
|
|
if (geometry->GetType() == grmGeometry::GEOMETRYEDGE)
|
|
{
|
|
#if USE_EDGE
|
|
Assert(sGetGeometryVertices && sGetGeometryIndices);
|
|
grmGeometryEdge* edgeGeometry = static_cast<grmGeometryEdge*>(geometry);
|
|
|
|
// indices to outputBufferVertsPtrsEa
|
|
Vector4** pointers = rage_aligned_new(16) Vector4*[CExtractGeomParams::obvIdxMax];
|
|
u32 numVerts = 0;
|
|
|
|
const int numIndices = edgeGeometry->GetVertexAndIndex(
|
|
sGetGeometryVertices,
|
|
kGetGeometryMaxVertices,
|
|
pointers,
|
|
sGetGeometryIndices,
|
|
kGetGeometryMaxIndices,
|
|
NULL, 0, NULL, NULL, NULL, NULL, NULL,
|
|
&numVerts,
|
|
#if HACK_GTA4_MODELINFOIDX_ON_SPU
|
|
NULL,
|
|
#endif
|
|
ms,
|
|
extractMask);
|
|
|
|
if (numIndices == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
sprintf(str, "%d verts", numVerts);
|
|
CObjExporter::AddComment(objFile, str);
|
|
|
|
CObjExporter::AddVerticesTransformed(objFile, pointers[CExtractGeomParams::obvIdxPositions], numVerts, &entityMatrix);
|
|
CObjExporter::AddNewLine(objFile);
|
|
|
|
CObjExporter::AddUVs(objFile, pointers[CExtractGeomParams::obvIdxUVs], numVerts);
|
|
CObjExporter::AddNewLine(objFile);
|
|
|
|
sprintf(str, "%d indices - %d tris", numIndices, numIndices / 3);
|
|
CObjExporter::AddComment(objFile, str);
|
|
CObjExporter::AddTriangles(objFile, sGetGeometryIndices, numIndices, nextIndex, true);
|
|
|
|
nextIndex += numVerts;
|
|
|
|
delete[] pointers;
|
|
#endif // USE_EDGE...
|
|
}
|
|
else
|
|
{
|
|
grcVertexBuffer* vb = geometry->GetVertexBuffer(true);
|
|
grcIndexBuffer* ib = geometry->GetIndexBuffer(true);
|
|
|
|
Assert(geometry->GetPrimitiveType() == drawTris);
|
|
Assert(geometry->GetPrimitiveCount() * 3 == (u32)ib->GetIndexCount());
|
|
Assert(vb && ib);
|
|
|
|
sprintf(str, "%d verts", vb->GetVertexCount());
|
|
CObjExporter::AddComment(objFile, str);
|
|
CObjExporter::AddVerticesTransformed(objFile, vb, &entityMatrix, true);
|
|
CObjExporter::AddNewLine(objFile);
|
|
|
|
sprintf(str, "%d indices - %d tris", ib->GetIndexCount(), ib->GetIndexCount() / 3);
|
|
CObjExporter::AddComment(objFile, str);
|
|
CObjExporter::AddTriangles(objFile, ib, nextIndex, true);
|
|
|
|
nextIndex += vb->GetVertexCount();
|
|
}
|
|
}
|
|
PS3_ONLY(g_AllowVertexBufferVramLocks--;)
|
|
}
|
|
|
|
void CutSceneManager::CaptureSceneToObj()
|
|
{
|
|
// create target obj file
|
|
FileHandle objFile = CObjExporter::OpenFileForWriting(m_capturePath);
|
|
if (objFile == NULL)
|
|
return;
|
|
|
|
// create txt file to store list of pivot points for each model
|
|
char pivotFilename[256] = {0};
|
|
ASSET.RemoveExtensionFromPath(pivotFilename, sizeof(pivotFilename), m_capturePath);
|
|
safecat(pivotFilename, ".txt");
|
|
FileHandle pivotFile = CFileMgr::OpenFileForWriting(pivotFilename);
|
|
if (pivotFile == NULL)
|
|
return;
|
|
|
|
HANG_DETECT_SAVEZONE_ENTER();
|
|
|
|
char str[256] = { 0 };
|
|
|
|
Matrix34 sceneOrigin(M34_IDENTITY);
|
|
GetSceneOrientationMatrix(sceneOrigin);
|
|
|
|
// rotation and scale requested by artists
|
|
float xRotation = -PI / 2.f;
|
|
float scale = 100.f;
|
|
|
|
Vector3 cameraPos = camInterface::GetPos();
|
|
|
|
if (m_useSceneOrigin)
|
|
cameraPos = sceneOrigin.d;
|
|
|
|
formatf(str, "%f %f %f", cameraPos.GetX(), cameraPos.GetY(), cameraPos.GetZ());
|
|
CFileMgr::Write(pivotFile, str, istrlen(str));
|
|
CFileMgr::Write(pivotFile, "\n", istrlen("\n"));
|
|
|
|
#if USE_EDGE
|
|
sGetGeometryVertices = rage_aligned_new(16) Vector4[kGetGeometryMaxVertices*2]; // pos+UVs requested
|
|
sGetGeometryIndices = rage_aligned_new(16) u16[kGetGeometryMaxIndices];
|
|
#endif
|
|
|
|
// enumerate entities
|
|
spdSphere captureSphere(RCC_VEC3V(cameraPos), ScalarV((float)m_iCaptureRadius));
|
|
fwIsSphereIntersecting intersection(captureSphere);
|
|
|
|
u32 oldCapacity = fwSearch::GetDefaultSearch().GetResult().GetCapacity();
|
|
fwSearch::GetDefaultSearch().GetResult().ResizeGrow(oldCapacity * 3);
|
|
|
|
atArray<CEntity*> entities;
|
|
CGameWorld::ForAllEntitiesIntersecting(&intersection, GatherEntities, (void*)&entities,
|
|
(ENTITY_TYPE_MASK_BUILDING | ENTITY_TYPE_MASK_VEHICLE | ENTITY_TYPE_MASK_OBJECT | ENTITY_TYPE_MASK_DUMMY_OBJECT | ENTITY_TYPE_MASK_PED), (SEARCH_LOCATION_EXTERIORS | SEARCH_LOCATION_INTERIORS),
|
|
SEARCH_LODTYPE_ALL, SEARCH_OPTION_FORCE_PPU_CODEPATH | SEARCH_OPTION_LARGE, WORLDREP_SEARCHMODULE_DEBUG);
|
|
|
|
sprintf(str, "camera position: %f %f %f", cameraPos.GetX(), cameraPos.GetY(), cameraPos.GetZ());
|
|
CObjExporter::AddComment(objFile, str);
|
|
|
|
u32 nextIndex = 1;
|
|
|
|
// grab geometry
|
|
for (u32 i = 0; i < entities.GetCount(); ++i)
|
|
{
|
|
// account for camera translation, rotate and scale as requested
|
|
Matrix34 entityMatrix = MAT34V_TO_MATRIX34(entities[i]->GetMatrix());
|
|
Vector3 euler = entityMatrix.GetEulers();
|
|
entityMatrix.Translate(-cameraPos);
|
|
entityMatrix.RotateFullX(xRotation);
|
|
entityMatrix.ScaleFull(scale);
|
|
|
|
if (m_useSceneOrigin)
|
|
entityMatrix.Dot3x3(sceneOrigin);
|
|
|
|
rmcDrawable* drawable = NULL;
|
|
if (entities[i]->GetIsTypePed())
|
|
{
|
|
CPedModelInfo* modelInfo = (CPedModelInfo*)entities[i]->GetBaseModelInfo();
|
|
if (!modelInfo || !modelInfo->GetVarInfo())
|
|
continue;
|
|
|
|
CPed* ped = (CPed*)entities[i];
|
|
if (m_capturePeds)
|
|
{
|
|
// create matrix set
|
|
u32 numBones = ped->GetSkeleton()->GetBoneCount();
|
|
Matrix43* ms = rage_aligned_new(16) Matrix43[numBones];
|
|
ped->GetSkeleton()->Attach(true, ms);
|
|
|
|
formatf(str, "%s_ped %f %f %f %f %f %f\n", ped->GetModelName(), entityMatrix.d.x, entityMatrix.d.y, entityMatrix.d.z, euler.x, euler.y, euler.z);
|
|
CFileMgr::Write(pivotFile, str, istrlen(str));
|
|
formatf(str, "%s_ped", ped->GetModelName());
|
|
CObjExporter::AddGroup(objFile, str);
|
|
|
|
for (s32 f = 0; f < PV_MAX_COMP; ++f)
|
|
{
|
|
if (ped->GetPedDrawHandler().GetPedRenderGfx())
|
|
{
|
|
drawable = ped->GetPedDrawHandler().GetPedRenderGfx()->GetDrawable(f);
|
|
}
|
|
else
|
|
{
|
|
CPedVariationData& varData = ped->GetPedDrawHandler().GetVarData();
|
|
|
|
s32 drawableIdx = varData.GetPedCompIdx((ePedVarComp)f);
|
|
if (drawableIdx == PV_NULL_DRAWBL)
|
|
continue;
|
|
|
|
if (!modelInfo->GetVarInfo())
|
|
continue;
|
|
|
|
if (!modelInfo->GetVarInfo()->IsValidDrawbl(f, drawableIdx))
|
|
continue;
|
|
|
|
Dwd* dwd = g_DwdStore.Get(strLocalIndex(modelInfo->GetPedComponentFileIndex()));
|
|
drawable = CPedVariationPack::ExtractComponent(dwd, (ePedVarComp)f, drawableIdx, varData.GetPedCompHashPtr((ePedVarComp)f), varData.GetPedCompAltIdx((ePedVarComp)f));
|
|
}
|
|
|
|
CaptureDrawable(ped, drawable, objFile, pivotFile, entityMatrix, nextIndex, ms, euler);
|
|
}
|
|
|
|
// free matrices
|
|
delete[] ms;
|
|
}
|
|
|
|
// capture mover capsule
|
|
if (m_capturePedCapsules)
|
|
{
|
|
phInst* inst = entities[i]->GetCurrentPhysicsInst();
|
|
if (inst)
|
|
{
|
|
phBound* bound = inst->GetArchetype()->GetBound();
|
|
if (bound)
|
|
{
|
|
if (bound->GetType() == phBound::CAPSULE)
|
|
GenerateCapsule(inst->GetMatrix(), (phBoundCapsule*)bound, objFile, nextIndex, -cameraPos, xRotation, scale);
|
|
else if (bound->GetType() == phBound::COMPOSITE)
|
|
{
|
|
phBoundComposite* composite = (phBoundComposite*)bound;
|
|
for (s32 i = 0; i < composite->GetNumBounds(); ++i)
|
|
{
|
|
if (composite->GetBound(i)->GetType() == phBound::CAPSULE)
|
|
GenerateCapsule(inst->GetMatrix(), (phBoundCapsule*)composite->GetBound(i), objFile, nextIndex, -cameraPos, xRotation, scale);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
drawable = entities[i]->GetDrawable();
|
|
CaptureDrawable(entities[i], drawable, objFile, pivotFile, entityMatrix, nextIndex, NULL, euler);
|
|
}
|
|
}
|
|
|
|
#if USE_EDGE
|
|
delete[] sGetGeometryVertices;
|
|
delete[] sGetGeometryIndices;
|
|
#endif
|
|
|
|
CObjExporter::CloseFile(objFile);
|
|
CFileMgr::CloseFile(pivotFile);
|
|
|
|
RefreshObjList();
|
|
|
|
fwSearch::GetDefaultSearch().GetResult().ResizeGrow(oldCapacity);
|
|
|
|
HANG_DETECT_SAVEZONE_EXIT(NULL);
|
|
}
|
|
|
|
void CutSceneManager::SnapCamToSceneOrigin()
|
|
{
|
|
Matrix34 sceneOrigin(M34_IDENTITY);
|
|
GetSceneOrientationMatrix(sceneOrigin);
|
|
|
|
if (sceneOrigin.d.x < 0.0001f && sceneOrigin.d.x > -0.0001 &&
|
|
sceneOrigin.d.y < 0.0001f && sceneOrigin.d.y > -0.0001 &&
|
|
sceneOrigin.d.z < 0.0001f && sceneOrigin.d.z > -0.0001)
|
|
return;
|
|
|
|
Vector3* camPos = (Vector3*)&camInterface::GetDebugDirector().GetFreeCamFrameNonConst().GetPosition();
|
|
camPos->x = sceneOrigin.d.x;
|
|
camPos->y = sceneOrigin.d.y;
|
|
camPos->z = sceneOrigin.d.z;
|
|
}
|
|
|
|
void CutSceneManager::GenerateCapsule(Mat34V_In mtxIn, phBoundCapsule* capsule, FileHandle& objFile, u32& nextIndex, const Vector3& translation, float rotation, float scale)
|
|
{
|
|
const int STEPS = 16;
|
|
const Matrix34 mtx = RCC_MATRIX34(mtxIn);
|
|
Matrix34 offsetMtx = mtx;
|
|
|
|
float capsuleLength = capsule->GetLength();
|
|
float capsuleRadius = capsule->GetRadius();
|
|
|
|
mtx.Transform(VEC3V_TO_VECTOR3(capsule->GetCentroidOffset()), offsetMtx.d);
|
|
|
|
offsetMtx.Translate(translation);
|
|
offsetMtx.RotateFullX(rotation);
|
|
offsetMtx.RotateLocalX(-rotation); // our coordinate system uses +z as up so need to fix the capsule orientation
|
|
offsetMtx.ScaleFull(scale);
|
|
|
|
const u32 numVerts = (STEPS >> 1) * (STEPS * 2) + (STEPS * 2);
|
|
Vector4 verts[numVerts];
|
|
u32 vertCount = 0;
|
|
|
|
const u32 numIndices = (STEPS >> 1) * (STEPS * 6) + (STEPS * 6);
|
|
u16 indices[numIndices];
|
|
u32 indexCount = 0;
|
|
|
|
{
|
|
float halflength = capsuleLength * 0.5f;
|
|
|
|
for (s32 i = 0; i < (STEPS >> 1); ++i)
|
|
{
|
|
float y0 = capsuleRadius * cosf(PI * float(i) / float(STEPS >> 1));
|
|
float y1 = capsuleRadius * cosf(PI * float(i + 1) / float(STEPS >> 1));
|
|
float deltay;
|
|
if (i < (STEPS >> 2))
|
|
{
|
|
deltay = halflength;
|
|
}
|
|
else
|
|
{
|
|
deltay = -halflength;
|
|
}
|
|
|
|
float s0 = sinf(PI * float(i) / float(STEPS >> 1));
|
|
float s1 = sinf(PI * float(i + 1) / float(STEPS >> 1));
|
|
|
|
u32 wrapVertCount = vertCount;
|
|
for (s32 f = 0; f < STEPS; ++f)
|
|
{
|
|
float x0 = capsuleRadius * s0 * sinf(2.0f * PI * float(f) / float(STEPS));
|
|
float x1 = capsuleRadius * s1 * sinf(2.0f * PI * float(f + 1) / float(STEPS));
|
|
float z0 = capsuleRadius * s0 * cosf(2.0f * PI * float(f) / float(STEPS));
|
|
float z1 = capsuleRadius * s1 * cosf(2.0f * PI * float(f + 1) / float(STEPS));
|
|
|
|
// on last iteration make sure to wrap the indices
|
|
if (f == (STEPS - 1))
|
|
{
|
|
indices[indexCount + 0] = (u16)(vertCount + 0);
|
|
indices[indexCount + 1] = (u16)(vertCount + 1);
|
|
indices[indexCount + 2] = (u16)wrapVertCount;
|
|
|
|
indices[indexCount + 3] = (u16)(vertCount + 1);
|
|
indices[indexCount + 4] = (u16)(wrapVertCount + 1);
|
|
indices[indexCount + 5] = (u16)wrapVertCount;
|
|
}
|
|
else
|
|
{
|
|
indices[indexCount + 0] = (u16)(vertCount + 0);
|
|
indices[indexCount + 1] = (u16)(vertCount + 1);
|
|
indices[indexCount + 2] = (u16)(vertCount + 2);
|
|
|
|
indices[indexCount + 3] = (u16)(vertCount + 1);
|
|
indices[indexCount + 4] = (u16)(vertCount + 3);
|
|
indices[indexCount + 5] = (u16)(vertCount + 2);
|
|
}
|
|
indexCount += 6;
|
|
|
|
verts[vertCount++] = Vector4(x0, y0 + deltay, z0, 0.f);
|
|
verts[vertCount++] = Vector4(x1, y1 + deltay, z1, 0.f);
|
|
}
|
|
}
|
|
|
|
u32 wrapVertCount = vertCount;
|
|
for (s32 f = 0; f < STEPS; ++f)
|
|
{
|
|
Vector3 normal(cosf(2.0f * PI * float(f) / float(STEPS)), 0.0f, sinf(2.0f * PI * float(f) / float(STEPS)));
|
|
float x = capsuleRadius * normal.x;
|
|
float z = capsuleRadius * normal.z;
|
|
|
|
verts[vertCount + 0] = Vector4(x, -halflength, z, 0.f);
|
|
verts[vertCount + 1] = Vector4(x, halflength, z, 0.f);
|
|
|
|
if (f == (STEPS - 1))
|
|
{
|
|
indices[indexCount + 0] = (u16)(vertCount + 0);
|
|
indices[indexCount + 1] = (u16)(vertCount + 1);
|
|
indices[indexCount + 2] = (u16)wrapVertCount;
|
|
|
|
indices[indexCount + 3] = (u16)(vertCount + 1);
|
|
indices[indexCount + 4] = (u16)(wrapVertCount + 1);
|
|
indices[indexCount + 5] = (u16)wrapVertCount;
|
|
}
|
|
else
|
|
{
|
|
indices[indexCount + 0] = (u16)(vertCount + 0);
|
|
indices[indexCount + 1] = (u16)(vertCount + 1);
|
|
indices[indexCount + 2] = (u16)(vertCount + 2);
|
|
|
|
indices[indexCount + 3] = (u16)(vertCount + 1);
|
|
indices[indexCount + 4] = (u16)(vertCount + 3);
|
|
indices[indexCount + 5] = (u16)(vertCount + 2);
|
|
}
|
|
|
|
vertCount += 2;
|
|
indexCount += 6;
|
|
}
|
|
}
|
|
|
|
Assertf(numVerts == vertCount, "numVerts: %d - vertCount: %d", numVerts, vertCount);
|
|
Assertf(numIndices == indexCount, "numIndices: %d - indexCount: %d", numIndices, indexCount);
|
|
|
|
CObjExporter::AddVerticesTransformed(objFile, verts, numVerts, &offsetMtx);
|
|
CObjExporter::AddNewLine(objFile);
|
|
CObjExporter::AddUVs(objFile, verts, numVerts); // dummy uvs to not mess upp the indexing
|
|
CObjExporter::AddNewLine(objFile);
|
|
CObjExporter::AddTriangles(objFile, indices, numIndices, nextIndex, false);
|
|
nextIndex += numVerts;
|
|
}
|
|
#endif
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// This wrapper class is used to provide an interface consistent with the rest
|
|
// of the game for initialising the cutscene manager
|
|
|
|
void CutSceneManagerWrapper::Init(unsigned initMode)
|
|
{
|
|
if(initMode == INIT_CORE)
|
|
{
|
|
CutSceneManager::CreateInstance();
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManagerWrapper::Shutdown(unsigned shutdownMode)
|
|
{
|
|
if(shutdownMode == SHUTDOWN_CORE)
|
|
{
|
|
CutSceneManager::GetInstance()->SetShutDownMode(shutdownMode);
|
|
CutSceneManager::GetInstance()->ShutDown();
|
|
}
|
|
else if(shutdownMode == SHUTDOWN_SESSION)
|
|
{
|
|
CutSceneManager::GetInstance()->SetShutDownMode(shutdownMode);
|
|
CutSceneManager::GetInstance()->SetDeleteAllRegisteredEntites(true);
|
|
CutSceneManager::GetInstance()->ShutDownCutscene();
|
|
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManagerWrapper::PreSceneUpdate()
|
|
{
|
|
CutSceneManager::GetInstance()->PreSceneUpdate();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManagerWrapper::PostSceneUpdate()
|
|
{
|
|
CutSceneManager::GetInstance()->PostSceneUpdate(fwTimer::GetTimeStep());
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
const CCutSceneCameraEntity* CutSceneManager::GetCamEntity()
|
|
{
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
if (entry.GetData().pEntity->GetType() == CUTSCENE_CAMERA_GAME_ENITITY)
|
|
{
|
|
return static_cast<const CCutSceneCameraEntity*>(entry.GetData().pEntity);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool CutSceneManager::HasCameraCutEarlyFromCutsceneInFirstPerson()
|
|
{
|
|
if(m_bShouldProcessEarlyCameraCutEventsForSinglePlayerExits)
|
|
{
|
|
if(!m_bHasProccessedEarlyCutEventForSinglePlayerExits)
|
|
{
|
|
const CCutSceneCameraEntity* pcam = GetCamEntity();
|
|
if(pcam && pcam->IsCuttingBackEarlyForScript() && pcam->IsInFirstPerson())
|
|
{
|
|
m_bHasProccessedEarlyCutEventForSinglePlayerExits = true;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
void CutSceneManager::LoadAuthorizedCutsceneList()
|
|
{
|
|
if(m_AuthorizedCutscenes.m_AuthorizedCutsceneList.GetCount() == 0)
|
|
{
|
|
char metadataFilename[RAGE_MAX_PATH];
|
|
|
|
formatf(metadataFilename, RAGE_MAX_PATH, "%s", "common:/data/debug/authorizedcutscene.pso.meta");
|
|
bool hasSucceeded = PARSER.InitAndLoadObject(metadataFilename, "", m_AuthorizedCutscenes);
|
|
if(!hasSucceeded)
|
|
{
|
|
cutsceneWarningf("Failed to load the authorized cutscene list (%s)", metadataFilename);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if !__FINAL
|
|
bool CutSceneManager::IsDLCCutscene()
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
const char* facedir = GetCutfFile()->GetFaceDirectory();
|
|
|
|
atString filePath(facedir);
|
|
|
|
if(stristr(filePath.c_str(), "dlc") != NULL)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endif //!__FINAL
|
|
|
|
|
|
#if CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
void CutSceneManager::RenderWatermark()
|
|
{
|
|
if (CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->IsCutscenePlayingBack() && (CutSceneManager::GetInstance()->IsPlaying() || CutSceneManager::GetInstance()->IsPaused()))
|
|
{
|
|
const char *text = "Not Authorized";
|
|
const float scale = 8.0f;
|
|
const Vector2 pos(0.04f, 0.925f);
|
|
const Color32 col(255, 255, 255, 63);
|
|
|
|
CTextLayout textLayout;
|
|
|
|
NetworkUtils::SetFontSettingsForNetworkOHD(&textLayout, scale, false);
|
|
textLayout.SetColor(col);
|
|
|
|
textLayout.SetWrap(Vector2(pos.x, pos.x + textLayout.GetStringWidthOnScreen(text, true)));
|
|
textLayout.SetEdge(0.0f);
|
|
textLayout.SetBackground(false, false);
|
|
textLayout.SetBackgroundColor(Color32(0,0,0,150));
|
|
textLayout.SetRenderUpwards(true);
|
|
|
|
textLayout.Render(pos, text);
|
|
}
|
|
}
|
|
#endif //CUTSCENE_AUTHORIZED_FOR_PLAYBACK
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//BANK
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#if __BANK
|
|
|
|
int CutSceneManager::ms_AssetFoldersCount = 0;
|
|
const char* CutSceneManager::ms_AssetFolders[CutSceneManager::ms_AssetFoldersMax];
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Add an asset folder to the array of asset folders
|
|
|
|
bool CutSceneManager::PushAssetFolder(const char *szAssetFolder)
|
|
{
|
|
if(szAssetFolder && ms_AssetFoldersCount < ms_AssetFoldersMax)
|
|
{
|
|
const size_t length = strlen(szAssetFolder);
|
|
if(length > 0)
|
|
{
|
|
// Don't add duplicate paths
|
|
for(int i = 0; i < ms_AssetFoldersCount; i ++)
|
|
{
|
|
if(stricmp(ms_AssetFolders[i], szAssetFolder) == 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Copy path
|
|
char *szCopy = rage_new char[length + 1];
|
|
strncpy(szCopy, szAssetFolder, length);
|
|
szCopy[length] = '\0';
|
|
|
|
// Lowercase path
|
|
strlwr(szCopy);
|
|
|
|
// Add path
|
|
ms_AssetFolders[ms_AssetFoldersCount ++] = szCopy;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Remove all asset folders from the array of asset folders
|
|
|
|
void CutSceneManager::DeleteAllAssetFolders()
|
|
{
|
|
for(int i = 0; i < ms_AssetFoldersCount; i ++)
|
|
{
|
|
if(ms_AssetFolders[i])
|
|
{
|
|
delete ms_AssetFolders[i];
|
|
|
|
ms_AssetFolders[i] = NULL;
|
|
}
|
|
}
|
|
|
|
ms_AssetFoldersCount = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Find an asset folder for the given scene name
|
|
|
|
const char *CutSceneManager::FindAssetFolderForCutfile(const char *sceneName)
|
|
{
|
|
int iFoundAssetFolder = -1;
|
|
|
|
if(cutsceneVerifyf(sceneName && sceneName[0] != '\0', "Scene name must exist!"))
|
|
{
|
|
for(int i = 0; i < ms_AssetFoldersCount; i ++)
|
|
{
|
|
if(ms_AssetFolders[i])
|
|
{
|
|
ASSET.PushFolder(ms_AssetFolders[i]);
|
|
|
|
bool bFound = ASSET.Exists(sceneName, "");
|
|
|
|
ASSET.PopFolder();
|
|
|
|
if(bFound)
|
|
{
|
|
if(cutsceneVerifyf(iFoundAssetFolder == -1, "Found more than one asset folder for scene %s! %s %s", sceneName, ms_AssetFolders[iFoundAssetFolder], ms_AssetFolders[i]))
|
|
{
|
|
iFoundAssetFolder = i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return iFoundAssetFolder != -1 ? ms_AssetFolders[iFoundAssetFolder] : NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Save the file to be saved so that it can be read into the MB scene.
|
|
|
|
void CutSceneManager::SaveCutfile()
|
|
{
|
|
cutsceneAssertf(!IsConcatted(), "Cannot save cutxml file if the scene is concatenated. Save event in correct section");
|
|
|
|
if(!IsConcatted() && GetCutfFile())
|
|
{
|
|
if (cOrignalSceneName.GetLength() == 0 )
|
|
{
|
|
cOrignalSceneName = GetCutfFile()->GetSceneName();
|
|
}
|
|
|
|
atString sceneName = cOrignalSceneName;
|
|
|
|
atString folder = GetCutfFile()->GetAssetPathForScene(sceneName, false);
|
|
|
|
if(folder.GetLength() > 0 )
|
|
{
|
|
bool bFound = ASSET.Exists(folder, "");
|
|
|
|
if (cutsceneVerifyf(bFound, "Could not find asset folder %s!", folder.c_str()))
|
|
{
|
|
atString file = GetCutfFile()->GetAssetPathForScene(sceneName);
|
|
GetCutfFile()->SaveFile(file.c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SaveGameDataCutfile()
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
if (cOrignalSceneName.GetLength() == 0 )
|
|
{
|
|
cOrignalSceneName = GetCutfFile()->GetSceneName();
|
|
}
|
|
char cFullPath[256];
|
|
|
|
if(IsDLCCutscene())
|
|
{
|
|
const char* facedir = GetCutfFile()->GetFaceDirectory();
|
|
|
|
atString filePath(facedir);
|
|
filePath.Lowercase();
|
|
atArray<atString> stringResults;
|
|
|
|
if(stristr(filePath, "/cache/") != NULL)
|
|
{
|
|
filePath.Split(stringResults, "cache/");
|
|
|
|
atString RootFile(stringResults[0]);
|
|
#ifdef RS_BRANCHSUFFIX
|
|
formatf(cFullPath, sizeof(cFullPath)-1, "%sassets_ng/cuts/!!game_data/%s", RootFile.c_str(), cOrignalSceneName.c_str());
|
|
#else
|
|
formatf(cFullPath, sizeof(cFullPath)-1, "%sassets/cuts/!!game_data/%s", RootFile.c_str(), cOrignalSceneName.c_str());
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
atString TempSceneName(cOrignalSceneName);
|
|
TempSceneName.Lowercase();
|
|
|
|
filePath.Split(stringResults, TempSceneName.c_str());
|
|
|
|
atString RootFile(stringResults[0]);
|
|
|
|
formatf(cFullPath, sizeof(cFullPath)-1, "%s!!game_data/%s", RootFile.c_str(), cOrignalSceneName.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
formatf(cFullPath, sizeof(cFullPath)-1, "assets:/cuts/!!game_data/%s", cOrignalSceneName.c_str());
|
|
}
|
|
|
|
GetCutfFile()->SaveFile(cFullPath);
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::UpdateDebugRenderState()
|
|
{
|
|
CutSceneManager* pThis = CutSceneManager::GetInstance();
|
|
if(pThis && pThis->IsRunning())
|
|
{
|
|
ms_DebugState.isRunning = true;
|
|
ms_DebugState.cutSceneCurrentTime = pThis->m_fTime;
|
|
ms_DebugState.cutScenePreviousTime = pThis->m_fPreviousTime;
|
|
ms_DebugState.cutscenePlayTime = pThis->m_fPlayTime;
|
|
ms_DebugState.cutsceneDuration = pThis->m_fDuration;
|
|
ms_DebugState.totalSeconds = pThis->GetTotalSeconds();
|
|
ms_DebugState.currentConcatSectionIdx = pThis->GetCurrentConcatSection();
|
|
ms_DebugState.concatSectionCount = pThis->GetConcatDataList().GetCount();
|
|
formatf(ms_DebugState.cutsceneName, "%s", pThis->GetCutsceneName());
|
|
if(ms_DebugState.concatSectionCount > 0 && pThis->IsConcatSectionValid(ms_DebugState.currentConcatSectionIdx))
|
|
{
|
|
formatf(ms_DebugState.concatDataSceneName, "%s", pThis->GetConcatDataList()[ms_DebugState.currentConcatSectionIdx].cSceneName.GetCStr());
|
|
}
|
|
else
|
|
{
|
|
ms_DebugState.currentConcatSectionIdx = -1;
|
|
ms_DebugState.concatDataSceneName[0] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ms_DebugState.Reset();
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SaveDrawDistanceFromWidget()
|
|
{
|
|
cutsManager::SaveDrawDistances();
|
|
SaveGameDataCutfile();
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
// Adds the initial cut scene widget
|
|
|
|
void CutSceneManager::InitLevelWidgets()
|
|
{
|
|
if (AssertVerify(!m_pCutSceneBank))
|
|
{
|
|
m_pCutSceneBank = fwDebugBank::CreateBank("Cut Scene Debug", MakeFunctor(*sm_pInstance,&CutSceneManager::ActivateBank), MakeFunctor(*sm_pInstance, &CutSceneManager::DeactivateBank));
|
|
}
|
|
}
|
|
|
|
void EnumObjsCb(const fiFindData& data, void* user)
|
|
{
|
|
Assert(user);
|
|
const char* ext = ASSET.FindExtensionInPath(data.m_Name);
|
|
if (ext && strcmp(ext, ".obj") == 0)
|
|
{
|
|
atArray<atString>* results = reinterpret_cast<atArray<atString>*>(user);
|
|
atString& newEntry = results->Grow();
|
|
newEntry.Set(ASSET.FileName(data.m_Name), istrlen(data.m_Name), 0);
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SelectNewObjCb()
|
|
{
|
|
if (m_selectedObj > -1 && m_pObjsCombo)
|
|
{
|
|
safecpy(m_capturePath, OBJ_CAPTURE_PATH);
|
|
const char* itemString = m_pObjsCombo->GetString(m_selectedObj);
|
|
if (!itemString)
|
|
return;
|
|
safecat(m_capturePath, itemString);
|
|
|
|
char buf[256] = {0};
|
|
ASSET.RemoveExtensionFromPath(buf, sizeof(buf), m_capturePath);
|
|
safecat(buf, ".txt");
|
|
FileHandle fh = CFileMgr::OpenFile(buf);
|
|
if (fh != NULL)
|
|
{
|
|
if (CFileMgr::ReadLine(fh, buf, sizeof(buf)))
|
|
{
|
|
// we just read the first line which should be of the format "%f %f %f"
|
|
// try to get three floats out of it
|
|
char* ptr = buf;
|
|
|
|
float x = (float)atof(ptr);
|
|
|
|
ptr = strchr(ptr, ' ');
|
|
if (!ptr)
|
|
return;
|
|
|
|
float y = (float)atof(ptr);
|
|
|
|
ptr = strchr(ptr + 1, ' ');
|
|
if (!ptr)
|
|
return;
|
|
|
|
float z = (float)atof(ptr);
|
|
((Vector3*)&camInterface::GetDebugDirector().GetFreeCamFrameNonConst().GetPosition())->Set(x, y, z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RefreshObjList()
|
|
{
|
|
atArray<atString> m_capturedObjs;
|
|
atArray<const char*> m_capturedObjsPtrs;
|
|
ASSET.EnumFiles(OBJ_CAPTURE_PATH, EnumObjsCb, &m_capturedObjs);
|
|
|
|
for (s32 i = 0; i < m_capturedObjs.GetCount(); ++i)
|
|
{
|
|
m_capturedObjsPtrs.PushAndGrow(m_capturedObjs[i].c_str());
|
|
}
|
|
|
|
if (m_selectedObj >= m_capturedObjsPtrs.GetCount())
|
|
m_selectedObj = m_capturedObjsPtrs.GetCount() - 1;
|
|
|
|
if (m_pObjsCombo && m_capturedObjsPtrs.GetCount() > 0)
|
|
m_pObjsCombo->UpdateCombo("Objs", &m_selectedObj, m_capturedObjsPtrs.GetCount(), m_capturedObjsPtrs.GetCount() > 0 ? &m_capturedObjsPtrs[0] : NULL, datCallback(MFA(CutSceneManager::SelectNewObjCb), this));
|
|
}
|
|
|
|
void CutSceneManager::ActivateBank()
|
|
{
|
|
XPARAM(enablecutscenelightauthoring);
|
|
|
|
m_pCutSceneBank->AddButton("Start or End Selected Cut scene", datCallback(MFA(CutSceneManager::StartEndCutsceneButton), (datBase*)this));
|
|
m_BankFileNameSelected = 0;
|
|
m_BankFileNames.Reset();
|
|
|
|
for (s32 c = 0; c < g_CutSceneStore.GetSize(); c++)
|
|
{
|
|
cutfCutsceneFile2Def* pDef = g_CutSceneStore.GetSlot(strLocalIndex(c));
|
|
if(pDef)
|
|
{
|
|
m_BankFileNames.PushAndGrow(pDef->m_name.GetCStr());
|
|
}
|
|
}
|
|
|
|
if(m_BankFileNames.GetCount() == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
std::sort(&m_BankFileNames[0], &m_BankFileNames[0] + m_BankFileNames.size(), AlphabeticalSort());
|
|
|
|
if( m_BankFileNames.GetCount() > 0 )
|
|
m_sceneNameCombo = m_pCutSceneBank->AddCombo("Cut Scenes", &m_BankFileNameSelected, m_BankFileNames.GetCount(), &m_BankFileNames[0]);
|
|
m_pCutSceneBank->AddText("Search:", m_searchText, 260, datCallback(MFA(CutSceneManager::OnSearchTextChanged), (datBase*)this));
|
|
m_pCutSceneBank->AddToggle("Enable audio sync when jogging", &m_bAllowAudioSyncFromRag, datCallback(MFA(CutSceneManager::EnableAudioSyncing), (datBase*)this));
|
|
#if __WIN32PC
|
|
m_pCutSceneBank->AddSlider("Anim Time Tweak", &g_TweakTimeStep, -1000.0, 1000.0, 1.0f);
|
|
#endif
|
|
m_pCutSceneBank->AddToggle("Stream Cutscene models", &m_bStreamObjectsWhileSceneIsPlaying, NullCB, "Stream Cutscene Models");
|
|
m_pCutSceneBank->AddToggle("Show MB frame and scene name", &m_bRenderMBFrameAndSceneName, NullCB, "");
|
|
m_pCutSceneBank->AddButton("Check for cutscene existance using the approval list", datCallback(MFA(CutSceneManager::CheckForCutsceneExistanceUsingApprovedList), (datBase*)this));
|
|
m_pCutSceneBank->AddButton("Validate cutscene", datCallback(MFA(CutSceneManager::ValidateCutscene), (datBase*)this));
|
|
m_pCutSceneBank->AddToggle("Use External Time Step", &m_bUseExternalTimeStep, NullCB, "");
|
|
m_pCutSceneBank->AddSlider("External Time Step", &m_ExternalTimeStep, 0.0, 1.0, 0.1f);
|
|
m_pCutSceneBank->AddSlider("PlayBackflags", &m_ValidConcatSectionFlags, -1, 1073741824, 1);
|
|
m_pCutSceneBank->AddToggle("Log Using Call Stacks", &m_LogUsingCallStacks, NullCB, "");
|
|
if(PARAM_enablecutscenelightauthoring.Get())
|
|
{
|
|
m_HoldAtEnd = true;
|
|
}
|
|
m_pCutSceneBank->AddToggle("Hold at end", &m_HoldAtEnd, NullCB, "");
|
|
m_pCutSceneBank->AddToggle("Allow Scrubbing To Frame 0", &m_AllowScrubbingToZero, NullCB, "");
|
|
m_pCutSceneBank->AddToggle("Snap debug cam to lights", &m_bSnapCameraToLights, NullCB, "");
|
|
|
|
#if SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
m_bRenderMBFrameAndSceneName = true;
|
|
#endif //SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
|
|
AddWidgets(*m_pCutSceneBank); // Add the rage widgets
|
|
|
|
bkBank* Ragebank = BANKMGR.FindBank("Cut Scene Debug");
|
|
bkGroup* PlayBackGrp = static_cast<bkGroup*>(BANKMGR.FindWidget("Cut Scene Debug/Current Scene/Play Back"));
|
|
if(Ragebank)
|
|
{
|
|
if(PlayBackGrp)
|
|
{
|
|
Ragebank->SetCurrentGroup(*PlayBackGrp);
|
|
Ragebank->AddToggle("Fade on skips", &m_bFadeOnSeamlessSkip , NullCB, "no fade on skips");
|
|
Ragebank->UnSetCurrentGroup(*PlayBackGrp);
|
|
}
|
|
}
|
|
|
|
m_DebugManager.InitWidgets();
|
|
|
|
#if !SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
|
|
|
|
//add the lights debug functionality
|
|
bkGroup* group = static_cast<bkGroup*>(BANKMGR.FindWidget("Cut Scene Debug/Current Scene/Light Editing"));
|
|
if(Ragebank)
|
|
{
|
|
if(group)
|
|
{
|
|
// initialise this var to a valid range for the widget, on reset the light vars get initialized after the cut scene
|
|
if(EditLightSource::GetIndex() < 0)
|
|
{
|
|
EditLightSource::SetIndex(-1);
|
|
}
|
|
|
|
Ragebank->SetCurrentGroup(*group);
|
|
|
|
|
|
|
|
Ragebank->AddToggle("Freeze lights update", &DebugLights::m_freeze, NullCB, "light fix");
|
|
Ragebank->AddToggle("Debug Draw", &m_bDisplayLightLines, datCallback(MFA(CutSceneManager::RenderCutsceneLightsInfo), (datBase*)this));
|
|
Ragebank->AddToggle("Show only active lights", &m_displayActiveLightsOnly , datCallback(MFA(CutSceneManager::ShowOnlyActiveCutsceneLights), (datBase*)this));
|
|
Ragebank->AddToggle("Show animated lights", &m_bRenderAnimatedLights , NullCB, "render only animated lights");
|
|
Ragebank->AddToggle("Show static lights", &m_bRenderCutsceneStaticLight , NullCB, "render only static lights");
|
|
Ragebank->AddToggle("Display All Lights", &DebugLights::m_debug , NullCB, "render all lights");
|
|
Ragebank->AddSlider("Scene Light", EditLightSource::GetIndexPtr(), -1, MAX_STORED_LIGHTS - 1, 1);
|
|
Ragebank->AddToggle("Enable z-test for debug draw", &grcDebugDraw::g_doDebugZTest);
|
|
Ragebank->AddButton("Save cutfile", datCallback(MFA(CutSceneManager::SaveMaxLightXml), (datBase*)this));
|
|
m_pSaveLightStatusText = Ragebank->AddText("Save Status:",&m_lightSaveStatus[0], 256, true);
|
|
Ragebank->UnSetCurrentGroup(*group);
|
|
}
|
|
}
|
|
|
|
SetFrameRangeForPlayBackSliders();
|
|
gStreamingRequestList.InitWidgets(*m_pCutSceneBank);
|
|
m_pCutSceneBank->PushGroup("Map Capture", false);
|
|
m_pObjsCombo = m_pCutSceneBank->AddCombo("Objs", &m_selectedObj, 0, NULL, datCallback(MFA(CutSceneManager::SelectNewObjCb), this));
|
|
m_pCaptureRadiusSlider = m_pCutSceneBank->AddSlider("Scene capture radius", &m_iCaptureRadius, 10, 500, 1, NullCB);
|
|
m_pCutSceneBank->AddText("Save path", m_capturePath, sizeof(m_capturePath));
|
|
m_pCutSceneBank->AddToggle("Capture map", &m_captureMap);
|
|
m_pCutSceneBank->AddToggle("Capture props", &m_captureProps);
|
|
m_pCutSceneBank->AddToggle("Capture vehicles", &m_captureVehicles);
|
|
m_pCutSceneBank->AddToggle("Capture peds", &m_capturePeds);
|
|
m_pCutSceneBank->AddToggle("Capture ped capsules", &m_capturePedCapsules);
|
|
m_pCutSceneBank->AddButton("Capture scene to OBJ", datCallback(MFA(CutSceneManager::CaptureSceneToObj), (datBase*)this));
|
|
m_pCutSceneBank->AddToggle("Use scene origin", &m_useSceneOrigin);
|
|
m_pCutSceneBank->AddButton("Snap free cam to scene origin", datCallback(MFA(CutSceneManager::SnapCamToSceneOrigin), (datBase*)this));
|
|
m_pCutSceneBank->AddToggle("Show capture sphere", &m_showCaptureSphere);
|
|
m_pCutSceneBank->AddSlider("FreeCam Position", (Vector3*)&camInterface::GetDebugDirector().GetFreeCamFrameNonConst().GetPosition(), -99999.f, 99999.f, 0.01f);
|
|
m_pCutSceneBank->PopGroup();
|
|
m_pCutSceneBank->PushGroup("Code", false);
|
|
m_pCutSceneBank->AddToggle("Run Soak Test", &m_RunSoakTest);
|
|
const char *playbackRates[] = { "1x", "2x", "4x", "8x" };
|
|
m_pBank->AddCombo( "Soak Test Playback Rate", &m_SoakTestPlaybackRateIdx, 4, playbackRates);
|
|
m_pCutSceneBank->AddToggle("Use verbose exit state logging", &m_bVerboseExitStateLogging, NullCB, "");
|
|
m_pCutSceneBank->AddButton("Dump Cutfile", datCallback(MFA(CutSceneManager::DumpCutFile), (datBase*)this));
|
|
m_pCutSceneBank->PopGroup();
|
|
|
|
#if USE_MULTIHEAD_FADE
|
|
fade::addWidgets(*m_pCutSceneBank);
|
|
#endif
|
|
|
|
RefreshObjList();
|
|
#endif
|
|
}
|
|
|
|
void CutSceneManager::RenderCutsceneLightsInfo()
|
|
{
|
|
BankDisplayLightLinesChangedCallback();
|
|
}
|
|
|
|
void CutSceneManager::EnableAudioSyncing()
|
|
{
|
|
if(!IsActive())
|
|
{
|
|
m_bAudioSyncWhenJogging = m_bAllowAudioSyncFromRag;
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::ShowOnlyActiveCutsceneLights()
|
|
{
|
|
if(m_displayActiveLightsOnly)
|
|
{
|
|
DebugLights::m_debug = false;
|
|
m_bDisplayLightLines = m_displayActiveLightsOnly;
|
|
}
|
|
RenderCutsceneLightsInfo();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DeactivateBank()
|
|
{
|
|
m_DebugManager.DestroyWidgets();
|
|
m_pCutSceneBank->RemoveAllMainWidgets();
|
|
m_pCurrentSceneGroup = NULL; //null the base group pointer so in add widgets its doesnt try to remove them again
|
|
s_bIsBankOpen = false;
|
|
m_sceneNameCombo = NULL;
|
|
// remove the base cutsmanager widgets
|
|
RemoveWidgets();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::ShutdownLevelWidgets()
|
|
{
|
|
m_pCutSceneBank->Shutdown();
|
|
m_pCutSceneBank = NULL;
|
|
m_pBank = NULL; //null the base class bank pointer
|
|
m_pCurrentSceneGroup = NULL;
|
|
s_bIsBankOpen = false;
|
|
// remove the base cutsmanager widgets
|
|
RemoveWidgets();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
u32 CutSceneManager::GetMBFrame()
|
|
{
|
|
if (!GetCutfFile())
|
|
{
|
|
return 0;
|
|
}
|
|
const atFixedArray<cutfCutsceneFile2::SConcatData, CUTSCENE_MAX_CONCAT> &concatDataList = GetConcatDataList();
|
|
|
|
u32 frame = 0;
|
|
if(concatDataList.GetCount() > 0)
|
|
{
|
|
u32 StartFrame = 0;
|
|
|
|
if(m_concatDataList.GetCount() > 0)
|
|
{
|
|
u32 currentConcatSection = 0;
|
|
//compute the current section for an internal concat
|
|
if(GetCutfFile()->GetCutsceneFlags().IsSet(cutfCutsceneFile2::CUTSCENE_INTERNAL_CONCAT_FLAG))
|
|
{
|
|
for ( int i = m_concatDataList.GetCount() - 1; i >= 0; --i )
|
|
{
|
|
if ( GetCutSceneCurrentTime() >= m_concatDataList[i].fStartTime && GetCutSceneCurrentTime() <= GetEndTime() )
|
|
{
|
|
currentConcatSection = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
currentConcatSection = GetCurrentConcatSection();
|
|
}
|
|
|
|
u32 totaldiscardedFrames = 0;
|
|
StartFrame = concatDataList[currentConcatSection].iRangeStart;
|
|
|
|
if(GetCutfFile()->GetDiscardedFrameList().GetCount() > 0 && GetCutfFile()->GetDiscardedFrameList().GetCount() >= currentConcatSection)
|
|
{
|
|
for(int j =0; j<GetCutfFile()->GetDiscardedFrameList()[currentConcatSection].frames.GetCount();)
|
|
{
|
|
if((m_iCurrentFrameWithFrameRanges - (u32)(concatDataList[currentConcatSection].fStartTime * CUTSCENE_FPS)) + totaldiscardedFrames + concatDataList[currentConcatSection].iRangeStart >= GetCutfFile()->GetDiscardedFrameList()[currentConcatSection].frames[j])
|
|
{
|
|
totaldiscardedFrames += GetCutfFile()->GetDiscardedFrameList()[currentConcatSection].frames[j+1] - GetCutfFile()->GetDiscardedFrameList()[currentConcatSection].frames[j];
|
|
}
|
|
j = j+2;
|
|
}
|
|
}
|
|
|
|
frame = (m_iCurrentFrameWithFrameRanges - (u32)(concatDataList[currentConcatSection].fStartTime * CUTSCENE_FPS)) + StartFrame + totaldiscardedFrames;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
frame = m_iCurrentFrameWithFrameRanges;
|
|
}
|
|
return frame;
|
|
}
|
|
|
|
u32 CutSceneManager::GetRenderMBFrame()
|
|
{
|
|
u32 uRenderMBFrame = m_uRenderMBFrame[0];
|
|
m_uRenderMBFrame[0] = m_uRenderMBFrame[1];
|
|
m_uRenderMBFrame[1] = static_cast< u32 >(-1);
|
|
return uRenderMBFrame;
|
|
}
|
|
|
|
const char* CutSceneManager::GetPlaybackFlagName()
|
|
{
|
|
u32 myflags = GetPlayBackFlags().GetAllFlags();
|
|
u32 flagBit = 0;
|
|
|
|
while (myflags >>= 1)
|
|
{
|
|
flagBit++;
|
|
}
|
|
|
|
static const char *c_cutscenePlayBackNames[] =
|
|
{
|
|
"CUTSCENE_REQUESTED_FROM_WIDGET",
|
|
"CUTSCENE_REQUESTED_DIRECTLY_FROM_SKIP",
|
|
"CUTSCENE_REQUESTED_FROM_Z_SKIP",
|
|
"CUTSCENE_REQUESTED_IN_MISSION",
|
|
"CUTSCENE_PLAYBACK_FORCE_LOAD_AUDIO_EVENT"
|
|
};
|
|
|
|
return c_cutscenePlayBackNames[flagBit];
|
|
|
|
}
|
|
|
|
void CutSceneManager::DebugDraw()
|
|
{
|
|
#if SETUP_CUTSCENE_WIDGET_FOR_CONTENT_CONTROLLED_BUILD
|
|
return;
|
|
#else
|
|
if(IsActive() && GetCutfFile())
|
|
{
|
|
const atFixedArray<cutfCutsceneFile2::SConcatData, CUTSCENE_MAX_CONCAT> &concatDataList = GetConcatDataList();
|
|
|
|
u32 finalFrame = (u32) (GetCutfFile()->GetTotalDuration() * CUTSCENE_FPS);
|
|
float phase = GetCutSceneCurrentTime() / GetCutfFile()->GetTotalDuration();
|
|
grcDebugDraw::AddDebugOutput("Cutscene Name: %s - %s", GetCutsceneName(), GetPlaybackFlagName());
|
|
grcDebugDraw::AddDebugOutput("Cutscene State: %s", GetStateName(GetState()));
|
|
grcDebugDraw::AddDebugOutput("");
|
|
|
|
/*
|
|
if(IsLoaded())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Scene Name: %s (Loaded)", GetCutsceneName());
|
|
}
|
|
else
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Scene Name: %s (Loading)", GetCutsceneName());
|
|
}*/
|
|
|
|
if(IsCutscenePlayingBack())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Cutscene Time: Current - Previous = delta (%f - %f = %f)", GetCutSceneCurrentTime(), GetCutScenePreviousTime(), GetCutSceneCurrentTime()-GetCutScenePreviousTime());
|
|
grcDebugDraw::AddDebugOutput("Audio Time: Current - Previous = delta (%f - %f = %f)", m_fCurrentAudioTime, m_fLastAudioTime, m_fCurrentAudioTime - m_fLastAudioTime);
|
|
grcDebugDraw::AddDebugOutput("");
|
|
grcDebugDraw::AddDebugOutput("Anim Section: %d of %d", GetCurrentSection()+1, m_fSectionStartTimeList.GetCount());
|
|
grcDebugDraw::AddDebugOutput("Current Frames: %f of %d", (GetCutSceneCurrentTime() * CUTSCENE_FPS), finalFrame);
|
|
grcDebugDraw::AddDebugOutput("Phase: %f", phase);
|
|
|
|
grcDebugDraw::AddDebugOutput("MB Frame: %d", GetMBFrame());
|
|
|
|
if(concatDataList.GetCount() > 0 && IsConcatDataValid())
|
|
{
|
|
grcDebugDraw::AddDebugOutput("ConcatName: %s Concat Section: %d of %d",concatDataList[GetCurrentConcatSection()].cSceneName.GetCStr() , GetCurrentConcatSection()+1, GetConcatDataList().GetCount());
|
|
}
|
|
else
|
|
{
|
|
grcDebugDraw::AddDebugOutput("Not concatenated");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (m_showCaptureSphere)
|
|
{
|
|
Vector3 cameraPos = camInterface::GetPos();
|
|
grcDebugDraw::Sphere(cameraPos, (float)m_iCaptureRadius, Color32(255, 0, 0), false, 1, 64);
|
|
}
|
|
grcDebugDraw::AddDebugOutput("");
|
|
#endif
|
|
}
|
|
|
|
void CutSceneManager::ActivateCameraTrackingCB()
|
|
{
|
|
if(!CControlMgr::IsDebugPadOn())
|
|
{
|
|
CControlMgr::SetDebugPadOn(true);
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::BankLightSelectedCallback()
|
|
{
|
|
cutsManager::BankLightSelectedCallback();
|
|
{
|
|
if ( (m_iSelectedLightIndex > 0) && (m_iSelectedLightIndex <= m_editLightList.GetCount() ) )
|
|
{
|
|
SEditCutfLightInfo *pEditLightInfo = GetSelectedLightInfo();
|
|
|
|
//need to postion the camera to a newly selected light but only if we are driving the light from the otherwise all tyhe lights might
|
|
//just end up here
|
|
if(camInterface::GetDebugDirector().IsFreeCamActive() && pEditLightInfo && m_bUpdateLightWithCamera )
|
|
{
|
|
UpdateCameraToLight(pEditLightInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SnapCameraToLight()
|
|
{
|
|
if(!camInterface::GetDebugDirector().IsFreeCamActive())
|
|
{
|
|
camInterface::GetDebugDirector().ActivateFreeCam();
|
|
CControlMgr::SetDebugPadOn(true);
|
|
}
|
|
|
|
if(camInterface::GetDebugDirector().IsFreeCamActive())
|
|
{
|
|
if ( (m_iSelectedLightIndex > 0) && (m_iSelectedLightIndex <= m_editLightList.GetCount() ) )
|
|
{
|
|
SEditCutfLightInfo *pEditLightInfo = GetSelectedLightInfo();
|
|
if(pEditLightInfo)
|
|
{
|
|
UpdateCameraToLight(pEditLightInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SnapLightToCamera()
|
|
{
|
|
if ( (m_iSelectedLightIndex > 0) && (m_iSelectedLightIndex <= m_editLightList.GetCount() ) )
|
|
{
|
|
SEditCutfLightInfo *pEditLightInfo = GetSelectedLightInfo();
|
|
|
|
if(pEditLightInfo && pEditLightInfo->pObject && pEditLightInfo->pObject->GetType() == CUTSCENE_LIGHT_OBJECT_TYPE)
|
|
{
|
|
pEditLightInfo->bOverridePosition = true;
|
|
pEditLightInfo->bOverrideDirection = true;
|
|
|
|
SetLightToCamera(pEditLightInfo, camInterface::GetFrame());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SetLightToCamera(SEditCutfLightInfo *pEditLightInfo, const camFrame& frame)
|
|
{
|
|
if(pEditLightInfo)
|
|
{
|
|
Matrix34 sceneMat(M34_IDENTITY);
|
|
GetSceneOrientationMatrix(sceneMat);
|
|
Matrix34 lightLocal(M34_IDENTITY);
|
|
|
|
lightLocal = frame.GetWorldMatrix();
|
|
lightLocal.RotateLocalX(HALF_PI);
|
|
|
|
lightLocal.DotTranspose(sceneMat);
|
|
|
|
pEditLightInfo->AuthoringPos = lightLocal.d;
|
|
lightLocal.ToQuaternion(pEditLightInfo->AuthoringQuat);
|
|
|
|
// const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
//
|
|
// if(pLightObject->GetLightType() == CUTSCENE_SPOT_LIGHT_TYPE)
|
|
// {
|
|
// float ConeAngle;
|
|
// if(pEditLightInfo->bOverrideConeAngle)
|
|
// {
|
|
// pEditLightInfo->fConeAngle = frame.GetFov() * 2.0f;
|
|
// }
|
|
// else
|
|
// {
|
|
// ConeAngle = pEditLightInfo->fOriginalConeAngle;
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::UpdateLightWithCamera(SEditCutfLightInfo *pEditLightInfo)
|
|
{
|
|
if(camInterface::GetDebugDirector().IsFreeCamActive() && m_bUpdateLightWithCamera)
|
|
{
|
|
SetLightToCamera(pEditLightInfo, camInterface::GetDebugDirector().GetFreeCamFrame());
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::UpdateCameraToLight(SEditCutfLightInfo *pEditLightInfo)
|
|
{
|
|
if(pEditLightInfo && pEditLightInfo->pObject)
|
|
{
|
|
Matrix34 LocalAuthoringHelper(M34_IDENTITY);
|
|
Matrix34 SceneAuthoringHelper(M34_IDENTITY);
|
|
|
|
camFrame &freeCamFrame = camInterface::GetDebugDirector().GetFreeCamFrameNonConst();
|
|
|
|
if(pEditLightInfo->pObject->GetType() == CUTSCENE_LIGHT_OBJECT_TYPE )
|
|
{
|
|
pEditLightInfo->AuthoringQuat.Normalize();
|
|
LocalAuthoringHelper.FromQuaternion(pEditLightInfo->AuthoringQuat);
|
|
LocalAuthoringHelper.d = pEditLightInfo->AuthoringPos;
|
|
BankOriginalSceneSpaceToWorldSpace(LocalAuthoringHelper, SceneAuthoringHelper);
|
|
|
|
freeCamFrame.SetWorldMatrix(SceneAuthoringHelper, false);
|
|
freeCamFrame.SetPosition(SceneAuthoringHelper.d);
|
|
Vector3 dir = pEditLightInfo->vDirection;
|
|
dir.Normalize();
|
|
freeCamFrame.SetWorldMatrixFromFront(dir);
|
|
}
|
|
else if(pEditLightInfo->pObject->GetType() == CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE )
|
|
{
|
|
SEntityObject* pEntityObject = GetEntityObject(pEditLightInfo->pObject, false);
|
|
|
|
if(pEntityObject && pEntityObject->pEntity && pEntityObject->pEntity->GetType() == CUTSCENE_LIGHT_GAME_ENITITY)
|
|
{
|
|
Matrix34 mat = (static_cast<CCutSceneLightEntity*>(pEntityObject->pEntity))->GetCutSceneLight()->GetLightMatWorld();
|
|
freeCamFrame.SetWorldMatrix(mat, false);
|
|
}
|
|
}
|
|
|
|
const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
|
|
if(pLightObject->GetLightType() == CUTSCENE_SPOT_LIGHT_TYPE)
|
|
{
|
|
float ConeAngle;
|
|
if(pEditLightInfo->bOverrideConeAngle)
|
|
{
|
|
ConeAngle = pEditLightInfo->fConeAngle;
|
|
}
|
|
else
|
|
{
|
|
ConeAngle = pEditLightInfo->fOriginalConeAngle;
|
|
}
|
|
|
|
freeCamFrame.SetFov(ConeAngle * 2.0f);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CutSceneManager::UpdateLightDebugging()
|
|
{
|
|
if ( (m_iSelectedLightIndex > 0) && (m_iSelectedLightIndex <= m_editLightList.GetCount()) && m_bSnapCameraToLights )
|
|
{
|
|
SEditCutfLightInfo *pEditLightInfo = GetSelectedLightInfo();
|
|
|
|
if(pEditLightInfo)
|
|
{
|
|
const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
|
|
char LightType[32];
|
|
bool isSpot = false;
|
|
|
|
switch ( pLightObject->GetLightType() )
|
|
{
|
|
case CUTSCENE_DIRECTIONAL_LIGHT_TYPE:
|
|
strcpy( LightType, "Directional" );
|
|
break;
|
|
case CUTSCENE_POINT_LIGHT_TYPE:
|
|
strcpy( LightType, "Point" );
|
|
break;
|
|
case CUTSCENE_SPOT_LIGHT_TYPE:
|
|
isSpot = true;
|
|
strcpy( LightType, "Spot" );
|
|
break;
|
|
default:
|
|
strcpy( LightType, "(unknown)" );
|
|
break;
|
|
}
|
|
|
|
char active[16];
|
|
|
|
if(pEditLightInfo->IsActive)
|
|
{
|
|
strcpy( active, "Active" );
|
|
}
|
|
else
|
|
{
|
|
strcpy( active, "Not Active" );
|
|
}
|
|
|
|
grcDebugDraw::AddDebugOutput("%s: %s ", LightType, pLightObject->GetDisplayName().c_str());
|
|
grcDebugDraw::AddDebugOutput("%s: Intensity: %f ", active, pEditLightInfo->fIntensity);
|
|
|
|
|
|
//track the debug state s
|
|
if(!m_debugActiveState && camInterface::GetDebugDirector().IsFreeCamActive())
|
|
{
|
|
UpdateCameraToLight(pEditLightInfo);
|
|
}
|
|
|
|
m_debugActiveState = camInterface::GetDebugDirector().IsFreeCamActive();
|
|
//allow the light to driven by teh camera,unless its a animated light
|
|
if(pEditLightInfo && pLightObject->GetType() == CUTSCENE_LIGHT_OBJECT_TYPE)
|
|
{
|
|
if(m_bUpdateLightWithCamera && CControlMgr::IsDebugPadOn())
|
|
{
|
|
UpdateLightWithCamera(pEditLightInfo);
|
|
}
|
|
}
|
|
else if(pEditLightInfo && pLightObject->GetType() == CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE && m_debugActiveState)
|
|
{
|
|
UpdateCameraToLight(pEditLightInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::CreateLightAuthoringMat(SEditCutfLightInfo *pEditLightInfo )
|
|
{
|
|
if(pEditLightInfo)
|
|
{
|
|
const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
|
|
Matrix34 LightMat;
|
|
Vector3 ltan;
|
|
Vector3 Direction = -pLightObject->GetLightDirection();
|
|
ltan.Cross(Direction, FindMinAbsAxis(Direction));
|
|
ltan.Normalize();
|
|
Vector3 front;
|
|
front.Cross(Direction, ltan);
|
|
LightMat.Set(ltan, front, Direction, pEditLightInfo->vOriginalPosition);
|
|
LightMat.ToQuaternion(pEditLightInfo->AuthoringQuat);
|
|
pEditLightInfo->OrginalAuthoringQuat = pEditLightInfo->AuthoringQuat;
|
|
pEditLightInfo->OriginaAuthoringPos = pEditLightInfo->vOriginalPosition;
|
|
pEditLightInfo->AuthoringPos = pEditLightInfo->vOriginalPosition;
|
|
}
|
|
}
|
|
|
|
bool CutSceneManager::ValidateLightObjects(const cutfLightObject* pFirstLight, const cutfLightObject* pSecondLight)
|
|
{
|
|
if(pFirstLight && pSecondLight)
|
|
{
|
|
bool isValid = true;
|
|
|
|
if(pFirstLight->GetLightPosition() != pSecondLight->GetLightPosition())
|
|
{
|
|
// errorMessage = " Positions dont match";
|
|
Displayf("%s - positions dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightDirection() != pSecondLight->GetLightDirection())
|
|
{
|
|
Displayf("%s - direction dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightFallOff() != pSecondLight->GetLightFallOff())
|
|
{
|
|
Displayf("%s - falloff dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightIntensity() != pSecondLight->GetLightIntensity())
|
|
{
|
|
Displayf("%s - intensity dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightConeAngle() != pSecondLight->GetLightConeAngle())
|
|
{
|
|
Displayf("%s - coneangle dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightColour() != pSecondLight->GetLightColour())
|
|
{
|
|
Displayf("%s - colour dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightFlags() != pSecondLight->GetLightFlags())
|
|
{
|
|
Displayf("%s - flags dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetLightHourFlags() != pSecondLight->GetLightHourFlags())
|
|
{
|
|
Displayf("%s - hour flags dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetVolumeIntensity() != pSecondLight->GetVolumeIntensity())
|
|
{
|
|
Displayf("%s - volume intensity dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
//if(pFirstLight->IsLightStatic() != pSecondLight->IsLightStatic())
|
|
//{
|
|
// return false;
|
|
//}
|
|
|
|
if(pFirstLight->GetVolumeSizeScale() != pSecondLight->GetVolumeSizeScale())
|
|
{
|
|
Displayf("%s - volume size scale dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetVolumeOuterColourAndIntensity() != pSecondLight->GetVolumeOuterColourAndIntensity())
|
|
{
|
|
Displayf("%s - volume outer colour intensity dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetCoronaSize() != pSecondLight->GetCoronaSize())
|
|
{
|
|
Displayf("%s - corona size dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetCoronaIntensity() != pSecondLight->GetCoronaIntensity())
|
|
{
|
|
Displayf("%s - corona intensity dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
if(pFirstLight->GetCoronaZBias() != pSecondLight->GetCoronaZBias())
|
|
{
|
|
Displayf("%s - corona z bias dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
|
|
if(pFirstLight->GetExponentialFallOff() != pSecondLight->GetExponentialFallOff())
|
|
{
|
|
Displayf("%s - exp fall off dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
|
|
|
|
if(pFirstLight->GetInnerConeAngle() != pSecondLight->GetInnerConeAngle())
|
|
{
|
|
Displayf("%s - inner cone dont match", pFirstLight->GetDisplayName().c_str());
|
|
isValid = false;
|
|
}
|
|
return isValid;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::DeleteLightCB()
|
|
{
|
|
if(m_iSelectedLightIndex < 1 || m_iSelectedLightIndex > m_editLightList.GetCount())
|
|
{
|
|
return;
|
|
}
|
|
|
|
SEditCutfLightInfo *pEditLightInfo = GetSelectedLightInfo();
|
|
|
|
if(pEditLightInfo && pEditLightInfo->pObject && !pEditLightInfo->markedForDelete)
|
|
{
|
|
const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
|
|
if(pLightObject)
|
|
{
|
|
atHashString LightName = pLightObject->GetName();
|
|
|
|
//just mark for delete and set it not active.
|
|
pEditLightInfo->markedForDelete = true;
|
|
pEditLightInfo->IsActive = false;
|
|
|
|
//remove from our list of lights
|
|
m_editLightList.Delete(m_iSelectedLightIndex - 1);
|
|
|
|
if(m_iSelectedLightIndex > m_editLightList.GetCount())
|
|
{
|
|
m_iSelectedLightIndex --;
|
|
}
|
|
|
|
if(m_deletedLightList.Find(LightName) == -1)
|
|
{
|
|
m_deletedLightList.PushAndGrow(LightName);
|
|
}
|
|
|
|
UpdateLightCombo();
|
|
|
|
PopulateActiveLightList(true);
|
|
|
|
BankActiveLightSelectedCallBack();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RenameLightCB()
|
|
{
|
|
if(strlen(m_LightNewName) == 0)
|
|
{
|
|
Displayf("LIGHT EDITING: Failed to rename light because the Light name was empty");
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
for(int i=0; i < m_editLightList.GetCount(); i++)
|
|
{
|
|
if(m_editLightList[i]->pObject)
|
|
{
|
|
if(m_editLightList[i]->pObject->GetDisplayName() == m_LightNewName)
|
|
{
|
|
Displayf("LIGHT EDITING: Failed to rename light %s because its a duplicate name", m_editLightList[i]->pObject->GetDisplayName().c_str() );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
SEditCutfLightInfo *pEditCutfLightInfo = m_editLightList[m_iSelectedLightIndex - 1];
|
|
|
|
if(pEditCutfLightInfo && pEditCutfLightInfo->pObject->GetType() == CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE )
|
|
{
|
|
Displayf("LIGHT EDITING: CANNOT RENAME AN ANIMATED LIGHT" );
|
|
|
|
if(m_pEditLightStatusText)
|
|
{
|
|
m_pEditLightStatusText->SetString("LIGHT EDITING: CANNOT RENAME AN ANIMATED LIGHT");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(pEditCutfLightInfo && pEditCutfLightInfo->pObject)
|
|
{
|
|
cutfLightObject* pLight = static_cast<cutfLightObject*>(pEditCutfLightInfo->pObject);
|
|
atHashString newName(m_LightNewName);
|
|
pLight->SetName(newName);
|
|
pEditCutfLightInfo->HasBeenRenamed = true;
|
|
}
|
|
|
|
UpdateLightCombo();
|
|
|
|
UpdateActiveLightListCombo();
|
|
|
|
}
|
|
|
|
void CutSceneManager::UpdateActiveLightSelectionHistory()
|
|
{
|
|
s32 EventIndex;
|
|
atHashString name = GetDebugManager().FindCameraCutNameForTime(GetDebugManager().m_CameraCutsIndexEvents, GetTime(), EventIndex);
|
|
|
|
bool containsEntry = false;
|
|
for(int i=0; i < ActiveLightSelectionList.GetCount(); i++)
|
|
{
|
|
if(ActiveLightSelectionList[i].camCut == name)
|
|
{
|
|
ActiveLightSelectionList[i].selectionIndex = m_iActiveLightIndex;
|
|
containsEntry = true;
|
|
}
|
|
}
|
|
|
|
if(!containsEntry)
|
|
{
|
|
SelectionIndexCamCuts& Selection = ActiveLightSelectionList.Grow();
|
|
Selection.camCut = name;
|
|
Selection.selectionIndex = m_iActiveLightIndex;
|
|
}
|
|
}
|
|
|
|
s32 CutSceneManager::GetActiveLightSelectionIndex()
|
|
{
|
|
s32 EventIndex;
|
|
atHashString name = GetDebugManager().FindCameraCutNameForTime(GetDebugManager().m_CameraCutsIndexEvents, GetTime(), EventIndex);
|
|
|
|
for(int i=0; i < ActiveLightSelectionList.GetCount(); i++)
|
|
{
|
|
if(ActiveLightSelectionList[i].camCut == name)
|
|
{
|
|
if(ActiveLightSelectionList[i].selectionIndex > m_activeLightList.GetCount())
|
|
{
|
|
ActiveLightSelectionList[i].selectionIndex = 0;
|
|
}
|
|
|
|
return ActiveLightSelectionList[i].selectionIndex;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void CutSceneManager::PopulateActiveLightList( bool forceRepopulateList)
|
|
{
|
|
if(m_pActiveLightCombo)
|
|
{
|
|
bool repopulateList = false;
|
|
|
|
if(!forceRepopulateList)
|
|
{
|
|
if(m_activeLightList.GetCount() == 0)
|
|
{
|
|
repopulateList = true;
|
|
}
|
|
else
|
|
{
|
|
for(int i = 0; i < m_activeLightList.GetCount(); i++)
|
|
{
|
|
if(!m_activeLightList[i]->IsActive)
|
|
{
|
|
repopulateList = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
repopulateList = forceRepopulateList;
|
|
}
|
|
|
|
if(repopulateList)
|
|
{
|
|
m_activeLightList.Reset(false);
|
|
m_iActiveLightIndex = 0;
|
|
|
|
for ( int i = 0; i < m_editLightList.GetCount(); ++i )
|
|
{
|
|
if(m_editLightList[i]->IsActive)
|
|
{
|
|
m_activeLightList.Grow() = m_editLightList[i];
|
|
}
|
|
}
|
|
|
|
m_iActiveLightIndex = GetActiveLightSelectionIndex();
|
|
|
|
|
|
UpdateActiveLightListCombo();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::DuplicateLightFromCameraCB()
|
|
{
|
|
//return if there is a light with this name
|
|
for(int i=0; i < m_editLightList.GetCount(); i++)
|
|
{
|
|
if(m_editLightList[i]->pObject)
|
|
{
|
|
if(m_editLightList[i]->pObject->GetDisplayName() == m_duplicatedLightName)
|
|
{
|
|
Displayf("LIGHT EDITING: Failed to duplicate light %s because the name is a duplicate", m_editLightList[i]->pObject->GetDisplayName().c_str() );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
SEditCutfLightInfo *pEditCutfLightInfo = GetSelectedLightInfo();
|
|
|
|
if(pEditCutfLightInfo && pEditCutfLightInfo->pObject->GetType() == CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE )
|
|
{
|
|
Displayf("LIGHT EDITING: CANNOT DUPLICATE AN ANIMATED LIGHT" );
|
|
|
|
if(m_pEditLightStatusText)
|
|
{
|
|
m_pEditLightStatusText->SetString("LIGHT EDITING: CANNOT DUPLICATE AN ANIMATED LIGHT");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(pEditCutfLightInfo && pEditCutfLightInfo->pObject)
|
|
{
|
|
const cutfLightObject* pLight = static_cast<const cutfLightObject*>(pEditCutfLightInfo->pObject);
|
|
|
|
cutfLightObject* pNewLight = static_cast<cutfLightObject*>(pLight->Clone());
|
|
|
|
//now set the light data from the cameras position
|
|
|
|
Matrix34 sceneMat(M34_IDENTITY);
|
|
GetSceneOrientationMatrix(sceneMat);
|
|
Vector3 lightLocal(VEC3_ZERO);
|
|
|
|
camFrame frame = camInterface::GetFrame();
|
|
|
|
sceneMat.UnTransform(frame.GetPosition(), lightLocal);
|
|
|
|
pNewLight->SetLightDirection(frame.GetWorldMatrix().b);
|
|
|
|
if(pNewLight->GetType() == CUTSCENE_SPOT_LIGHT_TYPE)
|
|
{
|
|
pNewLight->SetLightConeAngle(frame.GetFov());
|
|
}
|
|
|
|
pNewLight->SetLightPosition(lightLocal);
|
|
pNewLight->SetName(m_duplicatedLightName);
|
|
atHashString camCut;
|
|
|
|
if(AddLightWithEvents(pNewLight, camCut))
|
|
{
|
|
SEditCutfLightInfo* lightInfo = DuplicateLightEditInfo(pNewLight, pEditCutfLightInfo);
|
|
|
|
lightInfo->vOriginalPosition = lightLocal;
|
|
lightInfo->vPosition = lightLocal;
|
|
|
|
CreateLightAuthoringMat(lightInfo);
|
|
|
|
SEntityObject* pEntityObject = GetEntityObject(pNewLight);
|
|
|
|
if(pEntityObject && pEntityObject->pEntity && pEntityObject->pEntity->GetType() == CUTSCENE_LIGHT_GAME_ENITITY)
|
|
{
|
|
(static_cast<CCutSceneLightEntity*>(pEntityObject->pEntity))->GetCutSceneLight()->SetLightInfo(lightInfo);
|
|
}
|
|
|
|
AddLightToActiveList(lightInfo);
|
|
|
|
UpdateLightCombo();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::DuplicateLightCB()
|
|
{
|
|
|
|
//return if there is a light with this name
|
|
for(int i=0; i < m_editLightList.GetCount(); i++)
|
|
{
|
|
if(m_editLightList[i]->pObject)
|
|
{
|
|
if(m_editLightList[i]->pObject->GetDisplayName() == m_duplicatedLightName)
|
|
{
|
|
atVarString message("LIGHT EDITING: Failed to duplicate light %s because the name is a duplicate", m_editLightList[i]->pObject->GetDisplayName().c_str() );
|
|
atString debugMessage(message);
|
|
|
|
if(m_pEditLightStatusText)
|
|
{
|
|
m_pEditLightStatusText->SetString(debugMessage.c_str());
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
SEditCutfLightInfo *pEditCutfLightInfo = GetSelectedLightInfo();
|
|
|
|
if(pEditCutfLightInfo && pEditCutfLightInfo->pObject->GetType() == CUTSCENE_ANIMATED_LIGHT_OBJECT_TYPE )
|
|
{
|
|
if(m_pEditLightStatusText)
|
|
{
|
|
m_pEditLightStatusText->SetString("LIGHT EDITING: CANNOT DUPLICATE AN ANIMATED LIGHT");
|
|
}
|
|
|
|
Displayf("LIGHT EDITING: CANNOT DUPLICATE AN ANIMATED LIGHT" );
|
|
return;
|
|
}
|
|
|
|
if(pEditCutfLightInfo && pEditCutfLightInfo->pObject)
|
|
{
|
|
const cutfLightObject* pLight = static_cast<const cutfLightObject*>(pEditCutfLightInfo->pObject);
|
|
|
|
cutfLightObject* pNewLight = static_cast<cutfLightObject*>(pLight->Clone());
|
|
|
|
pNewLight->SetName(m_duplicatedLightName);
|
|
atHashString camCut;
|
|
if(AddLightWithEvents(pNewLight, camCut))
|
|
{
|
|
SEditCutfLightInfo* lightInfo = DuplicateLightEditInfo(pNewLight, pEditCutfLightInfo);
|
|
lightInfo->OriginalLightName = m_duplicatedLightName;
|
|
|
|
lightInfo->CamCutName = camCut;
|
|
|
|
SEntityObject* pEntityObject = GetEntityObject(pNewLight);
|
|
|
|
if(pEntityObject && pEntityObject->pEntity && pEntityObject->pEntity->GetType() == CUTSCENE_LIGHT_GAME_ENITITY)
|
|
{
|
|
(static_cast<CCutSceneLightEntity*>(pEntityObject->pEntity))->GetCutSceneLight()->SetLightInfo(lightInfo);
|
|
}
|
|
|
|
AddLightToActiveList(lightInfo);
|
|
|
|
UpdateLightCombo();
|
|
|
|
BankActiveLightSelectedCallBack();
|
|
|
|
UpdateActiveLightSelectionHistory();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CutSceneManager::AddLightWithEvents(cutfLightObject* pLight, atHashString& camerHashName)
|
|
{
|
|
bool addedlight = false;
|
|
|
|
GetCutfFile()->AddObject(pLight);
|
|
|
|
atArray<const cutfObject*> cameraObjectList;
|
|
s32 CameraObjectId = -1;
|
|
GetCutfFile()->FindObjectsOfType(CUTSCENE_CAMERA_OBJECT_TYPE, cameraObjectList);
|
|
|
|
if(cameraObjectList.GetCount() > 0)
|
|
{
|
|
CameraObjectId = cameraObjectList[0]->GetObjectId();
|
|
}
|
|
|
|
if(CameraObjectId > -1)
|
|
{
|
|
//create a list with all the camera cuts
|
|
atArray<cutfEvent *>cameraCutEventList;
|
|
GetCutfFile()->FindObjectIdEventsForObjectIdOnly( CameraObjectId, GetCutfFile()->GetEventList(), cameraCutEventList, true, (u32)CUTSCENE_CAMERA_CUT_EVENT_ARGS_TYPE);
|
|
|
|
//store the index for the camera cut for the set light anim event;
|
|
int iSetLightOnEventindex = -1;
|
|
for ( int i = cameraCutEventList.GetCount() - 1; i >= 0; --i )
|
|
{
|
|
if ( GetTime() >= cameraCutEventList[i]->GetTime())
|
|
{
|
|
if (cameraCutEventList[i]->GetEventId() == CUTSCENE_CAMERA_CUT_EVENT)
|
|
{
|
|
iSetLightOnEventindex = i;
|
|
|
|
const cutfCameraCutEventArgs* pEventArgs = static_cast<const cutfCameraCutEventArgs*>(cameraCutEventList[i]->GetEventArgs());
|
|
camerHashName = pEventArgs->GetName();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
cutfEvent* pSetLightEvent = NULL;
|
|
cutfEvent* pClearLightEvent = NULL;
|
|
|
|
if(iSetLightOnEventindex > -1 && iSetLightOnEventindex < cameraCutEventList.GetCount())
|
|
{
|
|
//create the set light event
|
|
pSetLightEvent = rage_new cutfObjectIdEvent(pLight->GetObjectId(), cameraCutEventList[iSetLightOnEventindex]->GetTime(), CUTSCENE_SET_LIGHT_EVENT, NULL);
|
|
|
|
int iClearLightEventIndex = iSetLightOnEventindex + 1;
|
|
|
|
if(iClearLightEventIndex < cameraCutEventList.GetCount())
|
|
{
|
|
pClearLightEvent = rage_new cutfObjectIdEvent(pLight->GetObjectId(), cameraCutEventList[iClearLightEventIndex]->GetTime(), CUTSCENE_CLEAR_LIGHT_EVENT, NULL);
|
|
}
|
|
else if(iSetLightOnEventindex == cameraCutEventList.GetCount() - 1)
|
|
{
|
|
pClearLightEvent = rage_new cutfObjectIdEvent(pLight->GetObjectId(), GetCutfFile()->GetTotalDuration(), CUTSCENE_CLEAR_LIGHT_EVENT, NULL);
|
|
}
|
|
|
|
if(pSetLightEvent && pClearLightEvent)
|
|
{
|
|
GetEntityObject(pLight, true);
|
|
|
|
GetCutfFile()->AddEvent(pClearLightEvent);
|
|
GetCutfFile()->AddEvent(pSetLightEvent);
|
|
GetCutfFile()->SortEvents();
|
|
|
|
DispatchEvent(pSetLightEvent);
|
|
|
|
addedlight = true;
|
|
}
|
|
else
|
|
{
|
|
GetCutfFile()->RemoveObject(pLight);
|
|
if(pSetLightEvent)
|
|
{
|
|
delete pSetLightEvent;
|
|
pSetLightEvent = NULL;
|
|
}
|
|
|
|
if(pClearLightEvent)
|
|
{
|
|
delete pClearLightEvent;
|
|
pClearLightEvent = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetCutfFile()->RemoveObject(pLight);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetCutfFile()->RemoveObject(pLight);
|
|
}
|
|
|
|
return addedlight;
|
|
}
|
|
|
|
void CutSceneManager::CreateLightCB()
|
|
{
|
|
if(!Verifyf(m_createdLightName[0] != '\0', "Light Name is empty!"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
u32 uCreatedLightNameHash = atStringHash(m_createdLightName);
|
|
for(int i = 0; i < m_editLightList.GetCount(); i ++)
|
|
{
|
|
SEditCutfLightInfo *pEditCutfLightInfo = m_editLightList[i];
|
|
if(pEditCutfLightInfo)
|
|
{
|
|
const cutfLightObject *pCutfLightObject = static_cast< const cutfLightObject * >(pEditCutfLightInfo->pObject);
|
|
if(pCutfLightObject)
|
|
{
|
|
if(!Verifyf(pCutfLightObject->GetName().GetHash() != uCreatedLightNameHash, "Cannot create a light with the same name as an existing light!"))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//create the light
|
|
cutfLightObject* pLight = rage_new cutfLightObject(-1, m_createdLightName, m_createdLightTypeIndex, 0); //( 0, m_createdLightName, frame.GetPosition(), frame.GetWorldMatrix().b, m_createdLightTypeIndex, 0, VEC3_ZERO, 0.0f, frame.GetFov()*2.0f, 1.0f, NULL);
|
|
if(!pLight)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Matrix34 sceneMat(M34_IDENTITY);
|
|
GetSceneOrientationMatrix(sceneMat);
|
|
Vector3 lightLocal(VEC3_ZERO);
|
|
|
|
camFrame frame = camInterface::GetFrame();
|
|
sceneMat.UnTransform(frame.GetPosition(), lightLocal);
|
|
|
|
pLight->SetLightPosition(lightLocal);
|
|
|
|
pLight->SetLightDirection(frame.GetWorldMatrix().b);
|
|
pLight->SetLightConeAngle(frame.GetFov());
|
|
|
|
pLight->SetLightIntensity(5.0f);
|
|
pLight->SetLightFallOff(5.0f);
|
|
pLight->SetExponentialFallOff(2.0f);
|
|
pLight->SetLightColour(Vector3(1.0f, 1.0f, 1.0f));
|
|
pLight->SetLightConeAngle(50.0f);
|
|
pLight->SetShadowBlur(2.0f);
|
|
pLight->SetLightFlag(CUTSCENE_LIGHTFLAG_CAST_DYNAMIC_GEOM_SHADOWS);
|
|
pLight->SetLightFlag(CUTSCENE_LIGHTFLAG_DONT_LIGHT_ALPHA);
|
|
pLight->SetLightFlag(CUTSCENE_LIGHTFLAG_NOT_IN_REFLECTION);
|
|
|
|
atHashString CutName;
|
|
|
|
//add it to the cutfile
|
|
if(AddLightWithEvents(pLight, CutName))
|
|
{
|
|
AddLightEditInfo(pLight);
|
|
|
|
SEditCutfLightInfo* pEditInfo = GetEditLightInfo(pLight->GetObjectId());
|
|
|
|
if(pEditInfo)
|
|
{
|
|
SEntityObject* pEntityObject = GetEntityObject(pLight);
|
|
|
|
if(pEntityObject && pEntityObject->pEntity && pEntityObject->pEntity->GetType() == CUTSCENE_LIGHT_GAME_ENITITY)
|
|
{
|
|
(static_cast<CCutSceneLightEntity*>(pEntityObject->pEntity))->GetCutSceneLight()->SetLightInfo(pEditInfo);
|
|
}
|
|
//set active so so the active light list is correct
|
|
pEditInfo->WasCreatedInGame = true;
|
|
pEditInfo->CamCutName = CutName;
|
|
pEditInfo->IsActive = true;
|
|
CreateLightAuthoringMat(pEditInfo);
|
|
|
|
AddLightToActiveList(pEditInfo);
|
|
|
|
UpdateLightCombo();
|
|
|
|
BankActiveLightSelectedCallBack();
|
|
UpdateActiveLightSelectionHistory();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//next time editing rewrite to return a state of failure
|
|
void CutSceneManager::SyncLightData()
|
|
{
|
|
XPARAM(enablecutscenelightauthoring);
|
|
bool IsTheFileDataValid = true;
|
|
bool containsDuplicateLights = false;
|
|
bool containsTheSameNumberOfLights = true;
|
|
atHashString duplicateLightName;
|
|
char filePath[RAGE_MAX_PATH];
|
|
atString sceneName(GetCutsceneName());
|
|
|
|
if(GetCutfFile())
|
|
{
|
|
formatf(filePath, RAGE_MAX_PATH, "%s%s", GetCutfFile()->GetAssetPathForScene(sceneName).c_str(), ".lightxml");
|
|
}
|
|
|
|
|
|
if(PARAM_enablecutscenelightauthoring.Get() && !IsConcatted())
|
|
{
|
|
m_AllowScrubbingToZero = false;
|
|
m_bSnapCameraToLights = true;
|
|
|
|
if(m_pDataLightXml == NULL)
|
|
{
|
|
m_pDataLightXml = rage_new cutfCutsceneFile2();
|
|
|
|
if(GetCutfFile() && m_pDataLightXml)
|
|
{
|
|
m_pDataLightXml->SetFaceDirectory(GetCutfFile()->GetFaceDirectory());
|
|
}
|
|
|
|
m_CanSaveLightAuthoringFile = m_pDataLightXml->LoadMaxLightFile(GetCutsceneName());
|
|
}
|
|
else
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
m_pDataLightXml->SetFaceDirectory(GetCutfFile()->GetFaceDirectory());
|
|
}
|
|
m_CanSaveLightAuthoringFile = m_pDataLightXml->LoadMaxLightFile(GetCutsceneName());
|
|
}
|
|
|
|
if(m_pDataLightXml == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(m_CanSaveLightAuthoringFile)
|
|
{
|
|
cutsceneDisplayf("LIGHT EDITING: Validating the light data in %s against the light data in the cutfile", filePath);
|
|
}
|
|
|
|
atArray<cutfObject *> maxlightObjectList;
|
|
m_pDataLightXml->FindObjectsOfType( CUTSCENE_LIGHT_OBJECT_TYPE, maxlightObjectList );
|
|
|
|
//check this incoming light file duplicate light names
|
|
for(int maxLightObjectIndex = 0; maxLightObjectIndex < maxlightObjectList.GetCount(); maxLightObjectIndex++)
|
|
{
|
|
cutfLightObject *pMaxLightObject = static_cast<cutfLightObject *>( maxlightObjectList[maxLightObjectIndex]);
|
|
|
|
if(pMaxLightObject)
|
|
{
|
|
for(int secondMaxLightObjectIndex = 0; secondMaxLightObjectIndex < maxlightObjectList.GetCount(); secondMaxLightObjectIndex++)
|
|
{
|
|
if(maxLightObjectIndex != secondMaxLightObjectIndex)
|
|
{
|
|
cutfLightObject *pSecondMaxLightObject = static_cast<cutfLightObject *>( maxlightObjectList[secondMaxLightObjectIndex]);
|
|
|
|
if(pSecondMaxLightObject)
|
|
{
|
|
if(pMaxLightObject->GetName() == pSecondMaxLightObject->GetName())
|
|
{
|
|
duplicateLightName = pMaxLightObject->GetName();
|
|
Displayf("data.lightxml contains duplicate light name %s. Please ensure the data.lightxml from Max has unique names", duplicateLightName.GetCStr());
|
|
containsDuplicateLights = true;
|
|
m_CanSaveLightAuthoringFile = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// improve validation rewrite validation function to return a fail state.
|
|
//if(m_editLightList.GetCount() != maxlightObjectList.GetCount())
|
|
//{
|
|
// containsTheSameNumberOfLights = false;
|
|
// m_CanSaveLightAuthoringFile = false;
|
|
//}
|
|
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
bool haveFoundLight = false;
|
|
|
|
//look at the override flags and update only the edited data
|
|
SEditCutfLightInfo *pEditLightInfo = m_editLightList[lightListIndex];
|
|
|
|
if(pEditLightInfo->pObject && pEditLightInfo->pObject->GetType() == CUTSCENE_LIGHT_OBJECT_TYPE)
|
|
{
|
|
const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
|
|
atHashString LightName = pLightObject->GetName();
|
|
|
|
//now look in the loaded light data and find the light
|
|
if(m_CanSaveLightAuthoringFile)
|
|
{
|
|
for(int i =0; i < maxlightObjectList.GetCount(); i++)
|
|
{
|
|
cutfLightObject *pMaxLightObject = static_cast<cutfLightObject *>( maxlightObjectList[i]);
|
|
|
|
if(pMaxLightObject->GetName() == LightName)
|
|
{
|
|
haveFoundLight = true;
|
|
|
|
if(!ValidateLightObjects(pMaxLightObject, pLightObject))
|
|
{
|
|
m_CanSaveLightAuthoringFile = false;
|
|
IsTheFileDataValid = false;
|
|
break;
|
|
}
|
|
|
|
parAttributeList& attList = const_cast<parAttributeList &>(pMaxLightObject->GetAttributeList());
|
|
|
|
parAttribute* camAtt = attList.FindAttribute("camera");
|
|
|
|
if(camAtt)
|
|
{
|
|
pEditLightInfo->CamCutName = camAtt->GetStringValue();
|
|
}
|
|
|
|
parAttribute* BoneAtt = attList.FindAttribute("bonename");
|
|
|
|
if(BoneAtt == NULL)
|
|
{
|
|
parAttribute* rotAtt = attList.FindAttribute("maxrelrotation");
|
|
parAttribute* posAtt = attList.FindAttribute("maxrelposition");
|
|
|
|
if(rotAtt)
|
|
{
|
|
Quaternion qLightRotation(0,0,0,0);
|
|
|
|
atString strRotation(rotAtt->GetStringValue());
|
|
|
|
atArray<atString> atSplit;
|
|
strRotation.Split(atSplit, "," ,true);
|
|
|
|
qLightRotation.x = (float)atof(atSplit[0]);
|
|
qLightRotation.y = (float)atof(atSplit[1]);
|
|
qLightRotation.z = (float)atof(atSplit[2]);
|
|
qLightRotation.w = (float)atof(atSplit[3]);
|
|
|
|
pEditLightInfo->AuthoringQuat = qLightRotation;
|
|
pEditLightInfo->OrginalAuthoringQuat = qLightRotation;
|
|
|
|
}
|
|
|
|
//if(BoneAtt == NULL)
|
|
//{
|
|
if(posAtt)
|
|
{
|
|
Vector3 vlightPos(VEC3_ZERO);
|
|
|
|
atString strPos(posAtt->GetStringValue());
|
|
|
|
atArray<atString> atSplit;
|
|
strPos.Split(atSplit, "," ,true);
|
|
|
|
vlightPos.x = (float)atof(atSplit[0]);
|
|
vlightPos.y = (float)atof(atSplit[1]);
|
|
vlightPos.z = (float)atof(atSplit[2]);
|
|
|
|
pEditLightInfo->AuthoringPos = vlightPos;
|
|
pEditLightInfo->OriginaAuthoringPos = vlightPos;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pEditLightInfo->IsAttached = true;
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
CreateLightAuthoringMat(m_editLightList[lightListIndex]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!haveFoundLight)
|
|
{
|
|
Displayf("Cannot find light %s", LightName.GetCStr());
|
|
m_CanSaveLightAuthoringFile = false;
|
|
IsTheFileDataValid = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
CreateLightAuthoringMat(m_editLightList[lightListIndex]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
CreateLightAuthoringMat(m_editLightList[lightListIndex]);
|
|
}
|
|
}
|
|
|
|
if(m_pLightHotloadingStatusText)
|
|
{
|
|
if(!CutfileNonParseData::m_FileTuningFlags.IsFlagSet(CutfileNonParseData::CUTSCENE_LIGHT_TUNING_FILE))
|
|
{
|
|
m_pLightHotloadingStatusText->SetString("Hot Loading Not Enabled");
|
|
}
|
|
else if(CutfileNonParseData::m_FileTuningStatusFlags.IsFlagSet(CutfileNonParseData::CUTSCENE_LIGHT_TUNING_FILE_LOADED))
|
|
{
|
|
m_pLightHotloadingStatusText->SetString("Hot Loading Successful");
|
|
}
|
|
else
|
|
{
|
|
char info[256];
|
|
formatf(info, 256, "Hot Loading Failed: Requires: %s", filePath);
|
|
m_pLightHotloadingStatusText->SetString(info);
|
|
}
|
|
}
|
|
|
|
if(m_pEditLightStatusText)
|
|
{
|
|
if(IsConcatted())
|
|
{
|
|
m_pEditLightStatusText->SetString("CANNOT EDIT LIGHTS ON CONCATENATTED SCENES - USE THE PART");
|
|
}
|
|
else if(!PARAM_enablecutscenelightauthoring.Get())
|
|
{
|
|
m_pEditLightStatusText->SetString("CANNOT EDIT LIGHTS: use commandline -enablecutscenelightauthoring");
|
|
}
|
|
else if(containsDuplicateLights)
|
|
{
|
|
char info[256];
|
|
formatf(info, 256, "CANNOT EDIT LIGHTS - data.lightxml contains duplicate light name %s. Please ensure the data.lightxml from Max has unique names", duplicateLightName.GetCStr());
|
|
m_pEditLightStatusText->SetString(info);
|
|
}
|
|
else if(!containsTheSameNumberOfLights)
|
|
{
|
|
m_pEditLightStatusText->SetString("CANNOT EDIT LIGHTS - The lights in light.dataxml do not match the same number of lights in the cutfile. Try building locally or try hotloading");
|
|
}
|
|
else if(!IsTheFileDataValid)
|
|
{
|
|
m_pEditLightStatusText->SetString("CANNOT EDIT LIGHTS - The lights in data.lightxml do not match the lights in the cutfile, get latest or build locally or try hotloading");
|
|
}
|
|
else if(PARAM_enablecutscenelightauthoring.Get() && !m_CanSaveLightAuthoringFile)
|
|
{
|
|
char info[128];
|
|
formatf(info, 128, "CANNOT EDIT LIGHTS: failed to load from: %s", filePath);
|
|
m_pEditLightStatusText->SetString(info);
|
|
}
|
|
else
|
|
{
|
|
m_pEditLightStatusText->SetString("LIGHTS AVAILIBLE FOR EDIT");
|
|
cutsceneDisplayf("LIGHT EDITING: Validation success, the lights in the data.lightxml match those in the cut file");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CutSceneManager::AddMaxProperties(cutfLightObject *pMaxLightObject, SEditCutfLightInfo *pEditLightInfo)
|
|
{
|
|
parAttributeList& attList = const_cast<parAttributeList &>(pMaxLightObject->GetAttributeList());
|
|
|
|
atVarString pos("%f,%f,%f", pEditLightInfo->AuthoringPos.x, pEditLightInfo->AuthoringPos.y, pEditLightInfo->AuthoringPos.z);
|
|
atVarString rot("%f,%f,%f,%f", pEditLightInfo->AuthoringQuat.x, pEditLightInfo->AuthoringQuat.y, pEditLightInfo->AuthoringQuat.z, pEditLightInfo->AuthoringQuat.w);
|
|
|
|
attList.AddAttribute("maxrelposition", pos.c_str());
|
|
|
|
attList.AddAttribute("maxrelrotation", rot.c_str());
|
|
|
|
attList.AddAttribute("camera", pEditLightInfo->CamCutName.TryGetCStr());
|
|
}
|
|
|
|
void CutSceneManager::ModifyMaxLightObject(cutfLightObject *pMaxLightObject, SEditCutfLightInfo *pEditLightInfo)
|
|
{
|
|
if(!pEditLightInfo->IsAttached)
|
|
{
|
|
Matrix34 sceneMat;
|
|
Vector3 Position;
|
|
|
|
if(pEditLightInfo->bOverridePosition)
|
|
{
|
|
Position = pEditLightInfo->AuthoringPos;
|
|
}
|
|
else
|
|
{
|
|
Position = pEditLightInfo->OriginaAuthoringPos;
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedPosition)
|
|
{
|
|
pMaxLightObject->SetLightPosition(Position);
|
|
|
|
char cPosition[RAGE_MAX_PATH];
|
|
//char cRotation[RAGE_MAX_PATH];
|
|
sprintf(cPosition, "%f,%f,%f", Position.x,Position.y,Position.z );
|
|
//sprintf(cRotation, "%f,%f,%f,%f", qRotation.x,qRotation.y,qRotation.z,qRotation.w );
|
|
|
|
parAttributeList& attList = const_cast<parAttributeList &>(pMaxLightObject->GetAttributeList());
|
|
|
|
parAttribute* posAtt = attList.FindAttribute("maxrelposition");
|
|
|
|
if(posAtt)
|
|
{
|
|
posAtt->SetValue(cPosition);
|
|
}
|
|
}
|
|
|
|
|
|
if(pEditLightInfo->bHaveEditedDirection)
|
|
{
|
|
//rotation
|
|
Quaternion Rot;
|
|
parAttributeList& attList = const_cast<parAttributeList &>(pMaxLightObject->GetAttributeList());
|
|
|
|
if(pEditLightInfo->bOverrideDirection)
|
|
{
|
|
Rot = pEditLightInfo->AuthoringQuat;
|
|
}
|
|
else
|
|
{
|
|
Rot = pEditLightInfo->OrginalAuthoringQuat;
|
|
}
|
|
|
|
char cRotation[RAGE_MAX_PATH];
|
|
|
|
sprintf(cRotation, "%f,%f,%f,%f", Rot.x, Rot.y, Rot.z, Rot.w );
|
|
|
|
parAttribute* rotAtt = attList.FindAttribute("maxrelrotation");
|
|
|
|
if(rotAtt)
|
|
{
|
|
rotAtt->SetValue(cRotation);
|
|
}
|
|
|
|
if(!pEditLightInfo->IsAttached)
|
|
{
|
|
Matrix34 lightMat(M34_IDENTITY);
|
|
lightMat.FromQuaternion(Rot);
|
|
lightMat.d = Position;
|
|
|
|
Matrix34 OriginalSceneMat(M34_IDENTITY);
|
|
GetOriginalSceneOrientationMatrix(OriginalSceneMat);
|
|
|
|
lightMat.Dot(OriginalSceneMat);
|
|
|
|
Vector3 LightDirWorld;
|
|
lightMat.Transform3x3(Vector3(0.0f, 0.0f, -1.0f), LightDirWorld);
|
|
|
|
pMaxLightObject->SetLightDirection(LightDirWorld);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedIntensity)
|
|
{
|
|
if(pEditLightInfo->bOverrideIntensity)
|
|
{
|
|
pMaxLightObject->SetLightIntensity(pEditLightInfo->fIntensity);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetLightIntensity(pEditLightInfo->fOriginalIntensity);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedFalloff)
|
|
{
|
|
if(pEditLightInfo->bOverrideFallOff )
|
|
{
|
|
pMaxLightObject->SetLightFallOff(pEditLightInfo->fFallOff);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetLightFallOff(pEditLightInfo->fOriginalFallOff);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedConeAngle)
|
|
{
|
|
if(pEditLightInfo->bOverrideConeAngle )
|
|
{
|
|
pMaxLightObject->SetLightConeAngle(pEditLightInfo->fConeAngle);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetLightConeAngle(pEditLightInfo->fOriginalConeAngle);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedInnerConeAngle)
|
|
{
|
|
if(pEditLightInfo->bOverrideInnerConeAngle )
|
|
{
|
|
pMaxLightObject->SetInnerConeAngle(pEditLightInfo->InnerConeAngle);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetInnerConeAngle(pEditLightInfo->OriginalInnerConeAngle);
|
|
}
|
|
}
|
|
|
|
|
|
if(pEditLightInfo->bHaveEditedShadowBlur)
|
|
{
|
|
if(pEditLightInfo->bOverrideShadowBlur )
|
|
{
|
|
pMaxLightObject->SetShadowBlur(pEditLightInfo->ShadowBlur);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetShadowBlur(pEditLightInfo->OriginalShadowBlur);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedColor)
|
|
{
|
|
if(pEditLightInfo->bOverrideColor )
|
|
{
|
|
pMaxLightObject->SetLightColour(pEditLightInfo->vColor);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetLightColour(pEditLightInfo->vOriginalColor);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedFlags)
|
|
{
|
|
if(pEditLightInfo->bOverrideLightFlags )
|
|
{
|
|
pMaxLightObject->SetLightFlags((ECutsceneLightFlag)pEditLightInfo->LightFlags);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetLightFlags((ECutsceneLightFlag)pEditLightInfo->OriginalLightFlags);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedTimeFlags)
|
|
{
|
|
if(pEditLightInfo->bOverrideTimeFlags )
|
|
{
|
|
pMaxLightObject->SetLightHourFlags(pEditLightInfo->TimeFlags);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetLightHourFlags(pEditLightInfo->OriginalTimeFlags);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedVolumeIntensity)
|
|
{
|
|
if(pEditLightInfo->bOverrideVolumeIntensity )
|
|
{
|
|
pMaxLightObject->SetVolumeIntensity(pEditLightInfo->VolumeIntensity);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetVolumeIntensity(pEditLightInfo->OriginalVolumeIntensity);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedVolumeSizeScale)
|
|
{
|
|
if(pEditLightInfo->bOverrideVolumeSizeScale)
|
|
{
|
|
pMaxLightObject->SetVolumeSizeScale(pEditLightInfo->VolumeSizeScale);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetVolumeSizeScale(pEditLightInfo->OriginalVolumeSizeScale);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedOuterColourAndIntensity)
|
|
{
|
|
if(pEditLightInfo->bOverrideOuterColourAndIntensity )
|
|
{
|
|
pMaxLightObject->SetVolumeOuterColourAndIntensity(pEditLightInfo->OuterColourAndIntensity);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetVolumeOuterColourAndIntensity(pEditLightInfo->OriginalOuterColourAndIntensity);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedCoronaIntensity)
|
|
{
|
|
if(pEditLightInfo->bOverrideCoronaIntensity )
|
|
{
|
|
pMaxLightObject->SetCoronaIntensity(pEditLightInfo->CoronaIntensity);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetCoronaIntensity(pEditLightInfo->OriginalCoronaIntensity);
|
|
}
|
|
}
|
|
|
|
|
|
if(pEditLightInfo->bHaveEditedCoronaSize)
|
|
{
|
|
if(pEditLightInfo->bOverrideCoronaSize )
|
|
{
|
|
pMaxLightObject->SetCoronaSize(pEditLightInfo->CoronaSize);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetCoronaSize(pEditLightInfo->OriginalCoronaSize);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedCoronaZBias)
|
|
{
|
|
if(pEditLightInfo->bOverrideCoronaZbias )
|
|
{
|
|
pMaxLightObject->SetCoronaZBias(pEditLightInfo->CoronaZbias);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetCoronaZBias(pEditLightInfo->OriginalCoronaZbias);
|
|
}
|
|
}
|
|
|
|
if(pEditLightInfo->bHaveEditedExpoFallOff)
|
|
{
|
|
if(pEditLightInfo->bOverrideExpoFallOff )
|
|
{
|
|
pMaxLightObject->SetExponentialFallOff(pEditLightInfo->ExpoFallOff);
|
|
}
|
|
else
|
|
{
|
|
pMaxLightObject->SetExponentialFallOff(pEditLightInfo->OriginalExpoFallOff);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::SaveMaxLightXml()
|
|
{
|
|
XPARAM(enablecutscenelightauthoring);
|
|
if(PARAM_enablecutscenelightauthoring.Get() && m_CanSaveLightAuthoringFile && !IsConcatted())
|
|
{
|
|
//cutfCutsceneFile2 LightMaxXml;
|
|
//LightMaxXml.LoadMaxLightFile(GetCutsceneName());
|
|
if(m_pDataLightXml == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
atArray<cutfObject *> maxlightObjectList;
|
|
m_pDataLightXml->FindObjectsOfType( CUTSCENE_LIGHT_OBJECT_TYPE, maxlightObjectList );
|
|
|
|
//upgrade our max light list with renamed lights
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
//look at the override flags and update only the edited data
|
|
SEditCutfLightInfo *pEditLightInfo = m_editLightList[lightListIndex];
|
|
|
|
if(pEditLightInfo->HasBeenRenamed && !pEditLightInfo->WasCreatedInGame && !pEditLightInfo->markedForDelete)
|
|
{
|
|
for(int i =0; i < maxlightObjectList.GetCount(); i++)
|
|
{
|
|
cutfLightObject *pMaxLightObject = static_cast<cutfLightObject *>( maxlightObjectList[i]);
|
|
|
|
if(pMaxLightObject->GetName().GetHash() == pEditLightInfo->OriginalLightName.GetHash())
|
|
{
|
|
cutfLightObject* pLight = static_cast<cutfLightObject*>(m_editLightList[lightListIndex]->pObject);
|
|
|
|
pMaxLightObject->SetName(pLight->GetName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//lets look at the edited data and only change that
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
//look at the override flags and update only the edited data
|
|
SEditCutfLightInfo *pEditLightInfo = m_editLightList[lightListIndex];
|
|
|
|
const cutfLightObject *pLightObject = static_cast<const cutfLightObject *>( pEditLightInfo->pObject );
|
|
|
|
atHashString LightName = pLightObject->GetName();
|
|
bool FoundLight = false;
|
|
//now look in the loaded light data and find the light
|
|
for(int i =0; i < maxlightObjectList.GetCount(); i++)
|
|
{
|
|
cutfLightObject *pMaxLightObject = static_cast<cutfLightObject *>( maxlightObjectList[i]);
|
|
|
|
if(pMaxLightObject->GetName().GetHash() == LightName.GetHash())
|
|
{
|
|
ModifyMaxLightObject(pMaxLightObject, pEditLightInfo);
|
|
FoundLight = true;
|
|
}
|
|
}
|
|
|
|
if(!FoundLight && pEditLightInfo->WasCreatedInGame && !pEditLightInfo->markedForDelete)
|
|
{
|
|
cutfLightObject* pNewMaxLight = static_cast<cutfLightObject*>(pLightObject->Clone());
|
|
AddMaxProperties(pNewMaxLight, pEditLightInfo);
|
|
ModifyMaxLightObject(pNewMaxLight, pEditLightInfo);
|
|
|
|
//get our light events
|
|
atArray<cutfEvent*> LightEvents;
|
|
GetCutfFile()->FindEventsForObjectIdOnly(pNewMaxLight->GetObjectId(), GetCutfFile()->GetEventList(), LightEvents);
|
|
|
|
//add them
|
|
m_pDataLightXml->AddObject(pNewMaxLight);
|
|
|
|
for(int i=0; i<LightEvents.GetCount(); i++)
|
|
{
|
|
if(LightEvents[i]->GetType() == CUTSCENE_OBJECT_ID_EVENT_TYPE)
|
|
{
|
|
cutfEvent* pEvent = LightEvents[i]->Clone();
|
|
|
|
static_cast<cutfObjectIdEvent*>(pEvent)->SetObjectId(pNewMaxLight->GetObjectId());
|
|
|
|
m_pDataLightXml->AddEvent(pEvent);
|
|
}
|
|
}
|
|
|
|
m_pDataLightXml->SortEvents();
|
|
}
|
|
}
|
|
|
|
for(int deletedLightListIndex = 0; deletedLightListIndex < m_deletedLightList.GetCount(); deletedLightListIndex ++)
|
|
{
|
|
atHashString deletedLightName = m_deletedLightList[deletedLightListIndex];
|
|
|
|
for(int i = 0; i < maxlightObjectList.GetCount(); i ++)
|
|
{
|
|
cutfLightObject *pMaxLightObject = static_cast<cutfLightObject *>( maxlightObjectList[i]);
|
|
|
|
if(pMaxLightObject->GetName().GetHash() == deletedLightName.GetHash())
|
|
{
|
|
m_pDataLightXml->RemoveObject(pMaxLightObject);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//save to the max file
|
|
if(GetCutfFile())
|
|
{
|
|
atString SceneName(GetCutsceneName());
|
|
atString scenePath = GetCutfFile()-> GetAssetPathForScene(SceneName);
|
|
|
|
m_pDataLightXml->SaveFile(scenePath, PI_CUTSCENE_LIGHTFILE_EXT);
|
|
|
|
//we have saved so we have transfered the info across, the data version is now up to date.
|
|
for(int lightListIndex = 0; lightListIndex < m_editLightList.GetCount(); lightListIndex++)
|
|
{
|
|
SEditCutfLightInfo *pEditLightInfo = m_editLightList[lightListIndex];
|
|
|
|
if(pEditLightInfo && !pEditLightInfo->markedForDelete)
|
|
{
|
|
pEditLightInfo->WasCreatedInGame = false;
|
|
pEditLightInfo->HasBeenRenamed = false;
|
|
}
|
|
}
|
|
|
|
if(m_pSaveLightStatusText)
|
|
{
|
|
m_pSaveLightStatusText->SetString("SAVE SUCCESS: Saved Max and Tune File");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(m_pSaveLightStatusText)
|
|
{
|
|
if(!PARAM_enablecutscenelightauthoring.Get())
|
|
{
|
|
m_pSaveLightStatusText->SetString("SAVE FAILED: Need commandLine -enablecutscenelightauthoring");
|
|
}
|
|
else if(!m_CanSaveLightAuthoringFile)
|
|
{
|
|
char saveFileStatus[256];
|
|
|
|
formatf(saveFileStatus, 256, "SAVE FAILED: failed to load assets_ng/cuts/%s/data.lightxml, make sure you have latest", GetCutsceneName());
|
|
|
|
m_pSaveLightStatusText->SetString(saveFileStatus);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::StartEndCutsceneButton()
|
|
{
|
|
CutSceneManager* pManager = CutSceneManager::GetInstance();
|
|
|
|
if (!CGameWorld::FindLocalPlayer())
|
|
return;
|
|
|
|
|
|
if (pManager->IsRunning())
|
|
{
|
|
if(pManager->GetCutfFile())
|
|
{
|
|
m_PlayBackState = PLAY_STATE_FORWARDS_NORMAL_SPEED;
|
|
|
|
m_bLoop = false;
|
|
pManager->StopCutsceneAndDontProgressAnim();
|
|
if (IsCutscenePlayingBack())
|
|
{
|
|
UpdateSkip();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cutsceneWarningf("The cutscene is loading but something is taking a long time we havnt loaded the cutfile yet.");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(pManager->IsLoading())
|
|
{
|
|
TerminateLoadedOnlyScene();
|
|
}
|
|
else if (pManager->m_BankFileNames.GetCount() > 0)
|
|
{
|
|
if(pManager->m_BankFileNames[pManager->m_BankFileNameSelected])
|
|
{
|
|
#if __BANK
|
|
if(!m_bStartedFromWidget)
|
|
{
|
|
m_bStartedFromWidget = true;
|
|
}
|
|
#endif
|
|
|
|
pManager->RequestCutscene(pManager->m_BankFileNames[pManager->m_BankFileNameSelected], false, SKIP_FADE, SKIP_FADE, SKIP_FADE, SKIP_FADE, THREAD_INVALID, CUTSCENE_REQUESTED_FROM_WIDGET); // last param set to false so we dont fade in/out
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::OnSearchTextChanged()
|
|
{
|
|
bool FoundMatch = false;
|
|
m_BankFileNameSelected = 0;
|
|
|
|
for(int i =0; i <m_BankFileNames.GetCount(); i++)
|
|
{
|
|
m_BankFileNames[i] = NULL;
|
|
}
|
|
|
|
m_BankFileNames.Reset();
|
|
|
|
if(m_searchText && strlen(m_searchText) > 0)
|
|
{
|
|
for (s32 c = 0; c < g_CutSceneStore.GetSize(); c++)
|
|
{
|
|
cutfCutsceneFile2Def* pDef = g_CutSceneStore.GetSlot(strLocalIndex(c));
|
|
if(pDef)
|
|
{
|
|
if(stristr(pDef->m_name.GetCStr(), m_searchText) != NULL)
|
|
{
|
|
m_BankFileNames.PushAndGrow(pDef->m_name.GetCStr());
|
|
FoundMatch = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!FoundMatch)
|
|
{
|
|
for (s32 c = 0; c < g_CutSceneStore.GetSize(); c++)
|
|
{
|
|
cutfCutsceneFile2Def* pDef = g_CutSceneStore.GetSlot(strLocalIndex(c));
|
|
if(pDef)
|
|
{
|
|
m_BankFileNames.PushAndGrow(pDef->m_name.GetCStr());
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_BankFileNames.GetCount() > 1)
|
|
{
|
|
std::sort(&m_BankFileNames[0], &m_BankFileNames[0] + m_BankFileNames.size(), AlphabeticalSort());
|
|
}
|
|
|
|
m_sceneNameCombo->UpdateCombo( "Cut Scenes", &m_BankFileNameSelected, m_BankFileNames.GetCount(), &m_BankFileNames[0] );
|
|
|
|
}
|
|
|
|
|
|
void CutSceneManager::DumpCutFile()
|
|
{
|
|
if(GetCutfFile())
|
|
{
|
|
if (cOrignalSceneName.GetLength() == 0 )
|
|
{
|
|
cOrignalSceneName = GetCutfFile()->GetSceneName();
|
|
}
|
|
|
|
char cFullPath[256];
|
|
formatf(cFullPath, sizeof(cFullPath)-1, "assets:/cuts/%s/dumpedfromgamedata", cOrignalSceneName.c_str());
|
|
GetCutfFile()->SaveFile(cFullPath);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//Creates a pointer to our selected hidden object.
|
|
|
|
SEditCutfObjectLocationInfo* CutSceneManager::GetHiddenObjectInfo()
|
|
{
|
|
return m_DebugManager.GetHiddenObjectInfo();
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
SEditCutfObjectLocationInfo* CutSceneManager::GetFixupObjectInfo()
|
|
{
|
|
return m_DebugManager.GetFixupObjectInfo();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
sEditCutfBlockingBoundsInfo* CutSceneManager::GetBlockingBoundObjectInfo()
|
|
{
|
|
return m_DebugManager.GetBlockingBoundObjectInfo();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CutSceneManager::DrawSceneOrigin()
|
|
{
|
|
Matrix34 mMat;
|
|
GetSceneOrientationMatrix(0, mMat);
|
|
|
|
grcDebugDraw::Axis(mMat ,0.5, true);
|
|
grcDebugDraw::Text(mMat.d, CRGBA(0,0,0,255),0, grcDebugDraw::GetScreenSpaceTextHeight(), m_cCurrentSceneName );
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//Call back when a new cutscene ped has been selected.
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//Update the slider to the current frame range
|
|
|
|
void CutSceneManager::SetFrameRangeForPlayBackSliders()
|
|
{
|
|
float fStartFrame = float(m_iStartFrame);
|
|
float fEndFrame = float(m_iEndFrame);
|
|
|
|
if(m_DebugManager.m_pVarFrameSlider)
|
|
{
|
|
m_DebugManager.m_pVarFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pVarPedFrameSlider)
|
|
{
|
|
m_DebugManager.m_pVarPedFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pVarDebugFrameSlider)
|
|
{
|
|
m_DebugManager.m_pVarDebugFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pVarSkipFrameSlider)
|
|
{
|
|
m_DebugManager.m_pVarSkipFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pPedVarPlayBackSlider)
|
|
{
|
|
m_DebugManager.m_pPedVarPlayBackSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pVehicleVarPlayBackSlider)
|
|
{
|
|
m_DebugManager.m_pVehicleVarPlayBackSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pOverlayPlayBackSlider)
|
|
{
|
|
m_DebugManager.m_pOverlayPlayBackSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_pWaterIndexFrameSlider)
|
|
{
|
|
m_DebugManager.m_pWaterIndexFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_pSkipToFrameSlider)
|
|
{
|
|
m_pSkipToFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
|
|
if(m_DebugManager.m_CascadeBounds.m_pShadowFrameSlider)
|
|
{
|
|
m_DebugManager.m_CascadeBounds.m_pShadowFrameSlider->SetRange(fStartFrame, fEndFrame);
|
|
}
|
|
cutsManager::SetFrameRangeForPlayBackSliders();
|
|
}
|
|
|
|
void CutSceneManager::LoadApprovedList()
|
|
{
|
|
bool bfileLoaded;
|
|
|
|
if (!sysBootManager::IsPackagedBuild())
|
|
{
|
|
USE_DEBUG_MEMORY();
|
|
|
|
ASSET.PushFolder("common:/non_final/cutscene");
|
|
|
|
// Camera
|
|
if (PARSER.LoadObject("ApprovedCutsceneList", "meta", m_ApprovedCutsceneList))
|
|
{
|
|
bfileLoaded = true;
|
|
}
|
|
else
|
|
{
|
|
Assertf(0, "Failed to load ApprovedCutsceneList.meta");
|
|
}
|
|
|
|
ASSET.PopFolder();
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::IsSceneApproved()
|
|
{
|
|
LoadApprovedList();
|
|
|
|
// Defaults
|
|
m_bIsFinalApproved = false;
|
|
m_bIsCutsceneAnimationApproved = false;
|
|
m_bIsCutsceneCameraApproved = false;
|
|
m_bIsCutsceneFacialApproved = false;
|
|
m_bIsCutsceneLightingApproved = false;
|
|
m_bIsCutsceneDOFApproved = false;
|
|
|
|
// Find the cutscene in the approved list
|
|
const u32 uCsHash = m_CutSceneHashString.GetHash();
|
|
const int iApprovedCsCount = m_ApprovedCutsceneList.m_ApprovalStatuses.GetCount();
|
|
bool bFound = false;
|
|
for (int i=0; i < iApprovedCsCount; i++)
|
|
{
|
|
if (uCsHash == m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_CutsceneName.GetHash())
|
|
{
|
|
m_bIsFinalApproved = m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_FinalApproved;
|
|
m_bIsCutsceneAnimationApproved = m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_CameraApproved;
|
|
m_bIsCutsceneCameraApproved = m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_AnimationApproved;
|
|
m_bIsCutsceneFacialApproved = m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_FacialApproved;
|
|
m_bIsCutsceneLightingApproved = m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_LightingApproved;
|
|
m_bIsCutsceneDOFApproved = m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_DofApproved;
|
|
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (!bFound)
|
|
{
|
|
// Cutscene is missing from the approved list
|
|
cutsceneWarningf("Cutscene '%s' missing from ApprovedCutsceneList.meta. Assuming unapproved.", m_CutSceneHashString.GetCStr());
|
|
}
|
|
}
|
|
|
|
|
|
void CutSceneManager::CheckForCutsceneExistanceUsingApprovedList()
|
|
{
|
|
#if __ASSERT
|
|
LoadApprovedList();
|
|
|
|
cutsceneDisplayf("Started checking for cutscene existance using the approaval list");
|
|
const int iApprovedCsCount = m_ApprovedCutsceneList.m_ApprovalStatuses.GetCount();
|
|
for (int i=0; i < iApprovedCsCount; i++)
|
|
{
|
|
//Make a request to the streaming system with a hash of the cut scene name
|
|
strLocalIndex iIndex = g_CutSceneStore.FindSlotFromHashKey(m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_CutsceneName.GetHash());
|
|
if (iIndex.Get() == -1)
|
|
{
|
|
cutsceneDisplayf("Failed to find Cutscene : %s ", m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_CutsceneName.TryGetCStr());
|
|
}
|
|
else
|
|
{
|
|
//cutsceneDisplayf("Succeeded to find Cutscene : %s ", m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_CutsceneName.TryGetCStr());
|
|
}
|
|
cutsceneAssertf((iIndex.Get() != -1), "Cutscene is missing : %s ", m_ApprovedCutsceneList.m_ApprovalStatuses[i].m_CutsceneName.TryGetCStr());
|
|
|
|
}
|
|
cutsceneDisplayf("Finished checking for cutscene existance using the approaval list");
|
|
|
|
m_ApprovedCutsceneList.m_ApprovalStatuses.Reset();
|
|
|
|
#endif //__ASSERT
|
|
}
|
|
|
|
void CutSceneManager::ValidateCutscene()
|
|
{
|
|
m_DebugManager.ValidateCutscene();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
//update the frame number if the scene is playing otherwise let this be manually overridden.
|
|
|
|
//void CutSceneManager::BankUpdateFrameNumber(u32 uFrame)
|
|
//{
|
|
// if (IsPlaying())
|
|
// {
|
|
// m_iCurrentFrameWithFrameRanges = uFrame + GetCutfFile()->GetRangeStart(); //need to offset with the start frame number
|
|
// }
|
|
//}
|
|
|
|
void CutSceneManager::OutputMoveNetworkForEntities()
|
|
{
|
|
TUNE_GROUP_BOOL(CUTSCENE, DisplayMoveNetwork, false);
|
|
if(DisplayMoveNetwork)
|
|
{
|
|
if(m_cutsceneEntityObjects.GetNumUsed() > 0)
|
|
{
|
|
atMap<s32, SEntityObject>::Iterator entry = m_cutsceneEntityObjects.CreateIterator();
|
|
for ( entry.Start(); !entry.AtEnd(); entry.Next() )
|
|
{
|
|
SEntityObject *pEntityObject = m_cutsceneEntityObjects.Access(entry.GetKey());
|
|
|
|
if(pEntityObject->pEntity->GetType() == CUTSCENE_ACTOR_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_VEHICLE_GAME_ENITITY
|
|
|| pEntityObject->pEntity->GetType() == CUTSCENE_PROP_GAME_ENITITY || pEntityObject->pEntity->GetType() == CUTSCENE_WEAPON_GAME_ENTITY)
|
|
{
|
|
CCutsceneAnimatedModelEntity* pModel = static_cast<CCutsceneAnimatedModelEntity*>(pEntityObject->pEntity);
|
|
CEntity* pEnt =pModel->GetGameEntity();
|
|
if(pEnt)
|
|
{
|
|
/*if(pEnt->GetIsTypePed())
|
|
{
|
|
CPed* pPed = (CPed*)pEnt;
|
|
pPed->GetMovePed().Dump();
|
|
}*/
|
|
|
|
if(pEnt->GetIsTypeVehicle())
|
|
{
|
|
CVehicle* pVeh = (CVehicle*)pEnt;
|
|
pVeh->GetMoveVehicle().Dump();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RenderCameraInfo()
|
|
{
|
|
if(CCutSceneCameraEntity::m_RenderCameraStatus)
|
|
{
|
|
if (CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->IsCutscenePlayingBack() && (CutSceneManager::GetInstance()->IsPlaying() || CutSceneManager::GetInstance()->IsPaused()))
|
|
{
|
|
|
|
TUNE_GROUP_FLOAT ( DOF Info, BlendingX, 0.02f, 0.0f, 1.0f,0.01f);
|
|
TUNE_GROUP_FLOAT ( DOF Info, BlendingY, 0.76f, 0.0f, 1.0f,0.01f);
|
|
|
|
TUNE_GROUP_FLOAT ( DOF Info, DOfStateX, 0.02f, 0.0f, 1.0f,0.01f);
|
|
TUNE_GROUP_FLOAT ( DOF Info, DOfStateY, 0.78f, 0.0f, 1.0f,0.01f);
|
|
|
|
TUNE_GROUP_FLOAT ( DOF Info, DOfPlaneX, 0.02f, 0.0f, 1.0f,0.01f);
|
|
TUNE_GROUP_FLOAT ( DOF Info, DOfPlaneY, 0.8f, 0.0f, 1.0f,0.01f);
|
|
|
|
TUNE_GROUP_FLOAT ( DOF Info, CoCX, 0.02f, 0.0f, 1.0f,0.01f);
|
|
TUNE_GROUP_FLOAT ( DOF Info, CoCY, 0.82f, 0.0f, 1.0f,0.01f);
|
|
|
|
TUNE_GROUP_FLOAT ( DOF Info, DOfEffectX, 0.02f, 0.0f, 1.0f,0.01f);
|
|
TUNE_GROUP_FLOAT ( DOF Info, DOfEffectY, 0.84f, 0.0f, 1.0f,0.01f);
|
|
|
|
TUNE_GROUP_FLOAT ( DOF Info, scaleX, 0.4f, 0.0f, 1.0f,0.1f);
|
|
TUNE_GROUP_FLOAT ( DOF Info, scaleY, 0.4f, 0.0f, 1.0f,0.1f);
|
|
|
|
if (CDebugBar::GetDisplayReleaseDebugText() == DEBUG_DISPLAY_STATE_STANDARD)
|
|
{
|
|
CTextLayout CutsceneDebugText;
|
|
CutsceneDebugText.SetScale(Vector2(scaleX, scaleY));
|
|
CutsceneDebugText.SetColor(CRGBA(255,255,255,255));
|
|
CutsceneDebugText.SetDropShadow(true);
|
|
|
|
CutsceneDebugText.Render(Vector2(DOfStateX,DOfStateY), CCutSceneCameraEntity::ms_DofState.c_str());
|
|
|
|
CutsceneDebugText.Render(Vector2(DOfPlaneX,DOfPlaneY), CCutSceneCameraEntity::ms_DofPlanes.c_str());
|
|
|
|
CutsceneDebugText.Render(Vector2(CoCX,CoCY), CCutSceneCameraEntity::ms_CoCMod.c_str());
|
|
|
|
CutsceneDebugText.Render(Vector2(DOfEffectX,DOfEffectY), CCutSceneCameraEntity::ms_DofEffect.c_str());
|
|
CutsceneDebugText.Render(Vector2(BlendingX,BlendingY), CCutSceneCameraEntity::ms_Blending.c_str());
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RenderUnapprovedSceneInfoCallback(bool UNUSED_PARAM(FinalApproved), bool AnimationApproved, bool CameraApproved, bool FacialApproved, bool LightingApproved, bool DOFApproved)
|
|
{
|
|
if (CutSceneManager::GetInstance() && CutSceneManager::GetInstance()->IsCutscenePlayingBack() && (CutSceneManager::GetInstance()->IsPlaying() || CutSceneManager::GetInstance()->IsPaused()))
|
|
{
|
|
float AnimationApproved_X = 0.825f;
|
|
float AnimationApproved_Y = 0.78f;
|
|
float CameraApproved_X = 0.825f;
|
|
float CameraApproved_Y = 0.81f;
|
|
float FacialApproved_X = 0.825f;
|
|
float FacialApproved_Y = 0.84f;
|
|
float LightingApproved_X = 0.825f;
|
|
float LightingApproved_Y = 0.87f;
|
|
float DOFApproved_X = 0.825f;
|
|
float DOFApproved_Y = 0.90f;
|
|
float scaleX = 0.40f;
|
|
float scaleY = 0.40f;
|
|
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, FinalApproved_X, 0.825f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, FinalApproved_Y, 0.75f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, AnimationApproved_X, 0.825f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, AnimationApproved_Y, 0.78f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, CameraApproved_X, 0.825f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, CameraApproved_Y, 0.81f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, FacialApproved_X, 0.825f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, FacialApproved_Y, 0.84f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, LightingApproved_X, 0.825f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, LightingApproved_Y, 0.87f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, DOFApproved_X, 0.825f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, DOFApproved_Y, 0.90f, 0.0f,10.0f,0.001f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, scaleX, 0.40f, 0.0f, 10.0f,0.01f);
|
|
//TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, scaleY, 0.40f, 0.0f, 10.0f,0.01f);
|
|
|
|
if (CDebugBar::GetDisplayReleaseDebugText() == DEBUG_DISPLAY_STATE_STANDARD)
|
|
{
|
|
CTextLayout CutsceneDebugText;
|
|
CutsceneDebugText.SetScale(Vector2(scaleX, scaleY));
|
|
CutsceneDebugText.SetColor(CRGBA(255,255,255,255));
|
|
CutsceneDebugText.SetDropShadow(true);
|
|
|
|
CutsceneDebugText.Render(Vector2(AnimationApproved_X,AnimationApproved_Y), AnimationApproved ? "Animation Approved" : "Animation Not Approved");
|
|
|
|
CutsceneDebugText.Render(Vector2(CameraApproved_X,CameraApproved_Y), CameraApproved ? "Camera Approved" : "Camera Not Approved" );
|
|
|
|
CutsceneDebugText.Render(Vector2(FacialApproved_X, FacialApproved_Y), FacialApproved ? "Facial Approved" : "Facial Not Approved" );
|
|
|
|
CutsceneDebugText.Render(Vector2(LightingApproved_X, LightingApproved_Y), LightingApproved ? "Lighting Approved" : "Lighting Not Approved" );
|
|
|
|
CutsceneDebugText.Render(Vector2(DOFApproved_X,DOFApproved_Y), DOFApproved ? "DOF Approved" : "DOF Not Approved" );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RenderStreamingPausedForAudio(bool AudioPaused)
|
|
{
|
|
float AudioPaused_X = 0.039f;
|
|
float AudioPaused_Y = 0.816f;
|
|
float AudioSize_x = 0.533f;
|
|
float AudioSize_y = 0.6f;
|
|
|
|
/*
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, AudioPaused_X, 0.039f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, AudioPaused_Y, 0.816f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, AudioSize_x, 0.533f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, AudioSize_y, 0.6f, 0.0f,10.0f,0.001f);
|
|
*/
|
|
|
|
if(AudioPaused)
|
|
{
|
|
CTextLayout CutscneDebugText;
|
|
|
|
CutscneDebugText.SetScale(Vector2(AudioSize_x, AudioSize_y));
|
|
CutscneDebugText.SetColor(CRGBA(255,0,0,255));
|
|
CutscneDebugText.Render(Vector2(AudioPaused_X,AudioPaused_Y), "CUTSCENE PAUSED DUE TO AUDIO STREAMING");
|
|
//CText::Flush();
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::RenderContentRestrictedData(bool bRestictedBuild)
|
|
{
|
|
float MBFrame_x = 0.900f;
|
|
float MBFrame_y = 0.870f;
|
|
float MBFrame_scale_x = 0.14f;
|
|
float MBFrame_scale_y = 1.0f;
|
|
|
|
float CutsceneName_x = 0.032f;
|
|
float CutsceneName_y = 0.870f;
|
|
float CutsceneName_scale_x = 0.14f;
|
|
float CutsceneName_scale_y = 1.0f;
|
|
|
|
/*
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, MBFrame_x, 0.470f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, MBFrame_y, 0.870f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, MBFrame_scale_x, 0.14f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, MBFrame_scale_y, 1.0f, 0.0f,10.0f,0.001f);
|
|
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, CutsceneName_x, 0.032f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, CutsceneName_y, 0.870f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, CutsceneName_scale_x, 0.14f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, CutsceneName_scale_y, 1.0f, 0.0f,10.0f,0.001f);
|
|
*/
|
|
|
|
if((CutSceneManager::GetInstance()->IsPlaying() || CutSceneManager::GetInstance()->IsPaused())&& CutSceneManager::GetInstance()->m_bRenderMBFrameAndSceneName)
|
|
{
|
|
CTextLayout CutscneDebugText;
|
|
char debugString[550];
|
|
|
|
formatf(debugString, 550, "%d", CutSceneManager::GetInstance()->GetRenderMBFrame());
|
|
CutscneDebugText.SetScale(Vector2(MBFrame_scale_x, MBFrame_scale_y));
|
|
CutscneDebugText.SetColor(CRGBA(255,255,255,255));
|
|
CutscneDebugText.SetBackground(TRUE, FALSE);
|
|
CutscneDebugText.SetBackgroundColor(CRGBA(0,0,0,255));
|
|
CutscneDebugText.Render(Vector2(MBFrame_x,MBFrame_y), &debugString[0]);
|
|
|
|
formatf(debugString, 550, "%s", CutSceneManager::GetInstance()->GetCutsceneName());
|
|
CutscneDebugText.SetScale(Vector2(CutsceneName_scale_x, CutsceneName_scale_y));
|
|
CutscneDebugText.SetColor(CRGBA(255,255,255,255));
|
|
CutscneDebugText.SetBackground(TRUE, FALSE);
|
|
CutscneDebugText.SetBackgroundColor(CRGBA(0,0,0,255));
|
|
CutscneDebugText.Render(Vector2(CutsceneName_x,CutsceneName_y), &debugString[0]);
|
|
//CText::Flush();
|
|
}
|
|
|
|
if (bRestictedBuild)
|
|
{
|
|
float WaterMark_X = 0.747f;
|
|
float WaterMark_Y = 0.045f;
|
|
float WaterMarkScale_X = 0.53f;
|
|
float WaterMarkScale_Y = 0.53f;
|
|
|
|
/*
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, WaterMark_X, 0.747f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, WaterMark_Y, 0.045f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, WaterMarkScale_X, 0.53f, 0.0f,10.0f,0.001f);
|
|
TUNE_GROUP_FLOAT ( CUTSCENE_DEBUG, WaterMarkScale_Y, 0.53f, 0.0f,10.0f,0.001f);
|
|
*/
|
|
|
|
CTextLayout WaterMarkText;
|
|
|
|
WaterMarkText.SetScale(Vector2(WaterMarkScale_X, WaterMarkScale_Y));
|
|
WaterMarkText.SetColor(CRGBA(0,0,0,255));
|
|
WaterMarkText.Render(Vector2(WaterMark_X,WaterMark_Y), "TECHNICOLOR BUILD");
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Set the game time every frame stored at the start of the scene
|
|
void CutSceneManager::OverrideGameTime()
|
|
{
|
|
if (m_DebugManager.m_bOverrideTimeCycle)
|
|
{
|
|
s32 numHours = m_DebugManager.m_fTimeCycleOverrideTime / 60;
|
|
s32 numMins = m_DebugManager.m_fTimeCycleOverrideTime - (numHours*60);
|
|
|
|
formatf(m_DebugManager.m_cGameTime, sizeof(m_DebugManager.m_cGameTime), "%d:%d:0",numHours, numMins );
|
|
m_DebugManager.m_vTimeClock.x = (float) numHours;
|
|
m_DebugManager.m_vTimeClock.y = (float) numMins;
|
|
m_DebugManager.m_vTimeClock.z = 0.0f;
|
|
CClock::SetTime(numHours, numMins, 0);
|
|
}
|
|
}
|
|
|
|
|
|
void CutSceneManager::SoakTest()
|
|
{
|
|
if(m_RunSoakTest)
|
|
{
|
|
if(!IsActive())
|
|
{
|
|
if (m_BankFileNameSelected < 0 || m_BankFileNameSelected == m_BankFileNames.GetCount())
|
|
{
|
|
m_BankFileNameSelected = 0;
|
|
}
|
|
|
|
StartEndCutsceneButton();
|
|
m_BankFileNameSelected ++;
|
|
}
|
|
else
|
|
{
|
|
// Cutscene active, does it need speeding up?
|
|
if (IsPlaying())
|
|
{
|
|
// Current playback rate
|
|
const float fCurrentPlaybackRate = GetPlayBackRate();
|
|
|
|
// What speedup do we want?
|
|
float fDesiredPlaybackRate = 1.0f;
|
|
switch (m_SoakTestPlaybackRateIdx)
|
|
{
|
|
case 0: fDesiredPlaybackRate = 1.0f; break;
|
|
case 1: fDesiredPlaybackRate = 2.0f; break;
|
|
case 2: fDesiredPlaybackRate = 4.0f; break;
|
|
case 3: fDesiredPlaybackRate = 8.0f; break;
|
|
default: fDesiredPlaybackRate = 1.0f; break;
|
|
}
|
|
|
|
if (fDesiredPlaybackRate == 1.0f)
|
|
{
|
|
if (fCurrentPlaybackRate != 1.0f)
|
|
{
|
|
// Play normally
|
|
BankPlayForwardsCallback();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (fCurrentPlaybackRate != fDesiredPlaybackRate)
|
|
{
|
|
BankFastForwardCallback();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CutSceneManager::CutsceneSmokeTest()
|
|
{
|
|
if (!CGameWorld::FindLocalPlayer())
|
|
return;
|
|
|
|
if(!IsActive())
|
|
{
|
|
int numberOfCutscenes = g_CutSceneStore.GetCount();
|
|
strLocalIndex chosenCutscene = strLocalIndex((u32)fwRandom::GetRandomNumberInRange(0, numberOfCutscenes));
|
|
|
|
if(g_CutSceneStore.IsValidSlot(chosenCutscene))
|
|
{
|
|
cutfCutsceneFile2Def* pDef = g_CutSceneStore.GetSlot(chosenCutscene);
|
|
if(pDef)
|
|
{
|
|
if (IsRunning() && GetCutfFile())
|
|
{
|
|
StopCutsceneAndDontProgressAnim();
|
|
}
|
|
else
|
|
{
|
|
if(IsLoading())
|
|
{
|
|
TerminateLoadedOnlyScene();
|
|
}
|
|
else
|
|
{
|
|
CPed * pPlayer = CGameWorld::FindLocalPlayer();
|
|
if (pPlayer)
|
|
{
|
|
pPlayer->m_nPhysicalFlags.bNotDamagedByAnything = true;
|
|
pPlayer->RemovePhysics();
|
|
}
|
|
|
|
#if __BANK
|
|
if(!m_bStartedFromWidget)
|
|
{
|
|
// If m_bStartedFromWidget is set to true once the cutscene is loaded (inside CutSceneManager::DoLoadingCutfileState)
|
|
// the player position will be moved to the cutscene origin this is needed for rayfire cutscenes
|
|
m_bStartedFromWidget = true;
|
|
}
|
|
#endif
|
|
// last param set to false so we dont fade in/out
|
|
RequestCutscene(pDef->m_name.GetCStr(), true, SKIP_FADE, SKIP_FADE, SKIP_FADE, SKIP_FADE, THREAD_INVALID, CUTSCENE_REQUESTED_FROM_WIDGET);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif //__BANK
|
|
|
|
#if !__NO_OUTPUT
|
|
void CutSceneManager::CommonDebugStr(char * debugStr)
|
|
{
|
|
if (!CutSceneManager::GetInstance()->m_bIsCutSceneActive)
|
|
{
|
|
sprintf(debugStr, "Cutscene not requested yet - ");
|
|
return;
|
|
}
|
|
|
|
sprintf(debugStr, "%s(%s): %6.2f(%u) - ",
|
|
CutSceneManager::GetInstance()->GetCutsceneName(), CutSceneManager::GetInstance()->GetStateName(CutSceneManager::GetInstance()->GetState()),
|
|
CutSceneManager::GetInstance()->GetCutSceneCurrentTime(), CutSceneManager::GetInstance()->GetCutSceneCurrentFrame());
|
|
}
|
|
#endif //!__NO_OUTPUT
|
|
|
|
|
|
|
|
#if USE_MULTIHEAD_FADE
|
|
bool CutSceneManager::StartMultiheadFade(bool bFadeIn, bool bInstant, bool bFullscreenMovie)
|
|
{
|
|
// Don't try to fade out if the blinders aren't up
|
|
if(!bFadeIn && !m_bBlindersUp)
|
|
return false;
|
|
|
|
u32 endTime = 0;
|
|
const float SIXTEEN_BY_NINE = 16.0f/9.0f;
|
|
const float BLINDER_EPSILON = 0.001f; // Offset to slightly bring in the blinders by 1 pixel to compensate for inaccuracies.
|
|
|
|
if (GRCDEVICE.GetMonitorConfig().isMultihead())
|
|
{
|
|
const fwRect area = GRCDEVICE.GetMonitorConfig().getLandscapeMonitor().getArea();
|
|
if(CHudTools::GetAspectRatio() > SIXTEEN_BY_NINE)
|
|
{
|
|
float fAspect = CHudTools::GetAspectRatio(true);
|
|
|
|
float fDifference = ( (SIXTEEN_BY_NINE / fAspect) * 0.5f ) - BLINDER_EPSILON;
|
|
fwRect area(0.5f - fDifference, 0, 0.5f + fDifference, 1.0f);
|
|
endTime = CSprite2d::SetMultiFadeParams(area, bFadeIn,
|
|
fade::uDuration, fade::fAcceleration, fade::fWaveSize, fade::fAlphaOffset, bInstant, m_iBlinderDelay );
|
|
}
|
|
else
|
|
{
|
|
const fwRect area = GRCDEVICE.GetMonitorConfig().getLandscapeMonitor().getArea();
|
|
endTime = CSprite2d::SetMultiFadeParams(area, bFadeIn,
|
|
fade::uDuration, fade::fAcceleration, fade::fWaveSize, fade::fAlphaOffset, bInstant, m_iBlinderDelay );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const GridMonitor &monitor = GRCDEVICE.GetMonitorConfig().getLandscapeMonitor();
|
|
float fAspect = monitor.fPhysicalAspect;
|
|
if (!GRCDEVICE.IsWindowed())
|
|
{
|
|
fAspect = monitor.fActualPhysicalAspect;
|
|
}
|
|
if(CHudTools::IsSuperWideScreen(false))
|
|
{
|
|
float fDifference = ( (SIXTEEN_BY_NINE / fAspect) * 0.5f ) - BLINDER_EPSILON;
|
|
fwRect area(0.5f - fDifference, 0, 0.5f + fDifference, 1.0f);
|
|
endTime = CSprite2d::SetMultiFadeParams(area, bFadeIn,
|
|
fade::uDuration, fade::fAcceleration, fade::fWaveSize, fade::fAlphaOffset, bInstant, m_iBlinderDelay );
|
|
}
|
|
else if (fAspect > monitor.getLogicalAspect() && !bFullscreenMovie)
|
|
{
|
|
float fDifference = ( (monitor.getLogicalAspect() / fAspect) * 0.5f ) - BLINDER_EPSILON;
|
|
fwRect area(0.5f - fDifference, 0, 0.5f + fDifference, 1.0f);
|
|
endTime = CSprite2d::SetMultiFadeParams(area, bFadeIn,
|
|
fade::uDuration, fade::fAcceleration, fade::fWaveSize, fade::fAlphaOffset, bInstant, m_iBlinderDelay );
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if(bInstant && !bFadeIn)
|
|
{
|
|
fade::uEndTime = 0;
|
|
}
|
|
else
|
|
{
|
|
fade::uEndTime = MAX( endTime, CSprite2d::GetFadeCurrentTime() );
|
|
}
|
|
fade::bInstant = bInstant;
|
|
|
|
fade::bFadingIn = bFadeIn;
|
|
|
|
m_bBlindersUp = bFadeIn;
|
|
if(!bFadeIn)
|
|
{
|
|
if(m_bManualControl)
|
|
m_bManualControl = false;
|
|
|
|
m_iBlinderDelay = 0;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif //USE_MULTIHEAD_FADE
|
|
//eof
|