Files
GTASource/game/camera/marketing/MarketingAToBCamera.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

298 lines
9.8 KiB
C++

//
// camera/marketing/MarketingAToBCamera.cpp
//
// Copyright (C) 1999-2011 Rockstar Games. All Rights Reserved.
//
#if __BANK //Marketing tools are only available in BANK builds.
#include "camera/marketing/MarketingAToBCamera.h"
#include "input/pad.h"
#include "camera/scripted/TimedSplineCamera.h"
#include "camera/system/CameraFactory.h"
#include "camera/system/CameraMetadata.h"
#include "system/pad.h"
#include "text/messages.h"
CAMERA_OPTIMISATIONS()
INSTANTIATE_RTTI_CLASS(camMarketingAToBCamera,0xF83B144B)
static const char* g_SmoothingStyleNames[camBaseSplineCamera::NUM_SMOOTHING_STYLES] =
{
"No smoothing", // camSplineCamera::NO_SMOOTHING
"Slow in", // camSplineCamera::SLOW_IN
"Slow out", // camSplineCamera::SLOW_OUT
"Slow in & out" // camSplineCamera::SLOW_IN_OUT
};
camMarketingAToBCamera::camMarketingAToBCamera(const camBaseObjectMetadata& metadata)
: camMarketingFreeCamera(metadata)
, m_Metadata(static_cast<const camMarketingAToBCameraMetadata&>(metadata))
, m_SplineNodeWidgetGroup(NULL)
, m_SplineTransitionTimes(NULL)
, m_MaxSplineNodes(m_Metadata.m_MaxSplineNodes)
, m_OverallSmoothingStyle(camBaseSplineCamera::SLOW_IN_OUT)
, m_IsSplineActive(false)
, m_ShouldUseFreeLookAroundMode(false)
, m_ShouldSmoothRotation(true)
, m_ShouldSmoothLensParameters(true)
{
m_SplineCamera = camFactory::CreateObject<camTimedSplineCamera>(m_Metadata.m_SplineCameraRef.GetHash());
cameraAssertf(m_SplineCamera, "A marketing A-B camera (name: %s, hash: %u) failed to create a spline camera (name: %s, hash: %u)",
GetName(), GetNameHash(), SAFE_CSTRING(m_Metadata.m_SplineCameraRef.GetCStr()), m_Metadata.m_SplineCameraRef.GetHash());
m_SplineTransitionTimes = rage_new float[m_Metadata.m_MaxSplineNodes];
if(m_SplineTransitionTimes)
{
for(u32 i=0; i<m_Metadata.m_MaxSplineNodes; i++)
{
m_SplineTransitionTimes[i] = static_cast<float>(m_Metadata.m_DefaultNodeTransitionTime) / 1000.0f;
}
}
}
camMarketingAToBCamera::~camMarketingAToBCamera()
{
if(m_SplineTransitionTimes)
{
delete[] m_SplineTransitionTimes;
}
if(m_SplineCamera)
{
delete m_SplineCamera;
}
}
bool camMarketingAToBCamera::Update()
{
bool hasSucceeded = camMarketingFreeCamera::Update(); //Fall-back to the base class behavior.
if(m_IsSplineActive && m_SplineCamera && m_SplineCamera->GetIsClassId(camTimedSplineCamera::GetStaticClassId()))
{
camTimedSplineCamera& splineCamera = static_cast<camTimedSplineCamera&>(*m_SplineCamera);
Matrix34 worldMatrix = m_Frame.GetWorldMatrix();
//Overwrite our frame with the result of the spline camera update.
hasSucceeded = splineCamera.BaseUpdate(m_Frame);
//NOTE: We must explicitly overwrite our local FOV setting in order to prevent a zoom glitch at the end of playback.
m_Fov = m_Frame.GetFov();
if(m_ShouldUseFreeLookAroundMode)
{
//Restore the free camera orientation that was computed prior to the spline update.
m_Frame.SetWorldMatrix(worldMatrix, true);
}
//Automatically deactivate playback once the spline is finished.
if(splineCamera.HasReachedEnd())
{
m_IsSplineActive = false;
}
}
return hasSucceeded;
}
void camMarketingAToBCamera::UpdateMiscControl(CPad& pad)
{
camMarketingFreeCamera::UpdateMiscControl(pad);
if(m_SplineCamera && m_SplineCamera->GetIsClassId(camTimedSplineCamera::GetStaticClassId()))
{
camTimedSplineCamera& splineCamera = static_cast<camTimedSplineCamera&>(*m_SplineCamera);
const u32 numSplineNodes = static_cast<u32>(splineCamera.GetNumNodes());
if(pad.GetPressedDebugButtons() & ioPad::L2)
{
if(numSplineNodes < m_MaxSplineNodes)
{
//Add a new spline node.
u32 transitionTimeMs;
if(m_SplineTransitionTimes && (numSplineNodes > 0))
{
//NOTE: The transition time specified when adding a spline node describes the time taken to transition from the previous node,
//so we must offset the array of times exposed to RAG.
//NOTE: The widgets display the transition times in seconds, so we need to convert to milliseconds for the nodes.
transitionTimeMs = static_cast<u32>(Floorf(m_SplineTransitionTimes[numSplineNodes - 1] * 1000.0f));
}
else
{
transitionTimeMs = m_Metadata.m_DefaultNodeTransitionTime;
}
int nodeFlags = 0;
if(m_ShouldSmoothRotation)
{
nodeFlags |= camSplineNode::SHOULD_SMOOTH_ROTATION;
}
if(m_ShouldSmoothLensParameters)
{
nodeFlags |= camSplineNode::SHOULD_SMOOTH_LENS_PARAMS;
}
splineCamera.AddNode(m_Frame, transitionTimeMs, camSplineNode::eFlags(nodeFlags));
//Reset the duration to ensure that it will be recomputed based upon the node transition times.
splineCamera.SetDuration(0);
//Display confirmation debug text (if the HUD is enabled.)
char *string = TheText.Get("MKT_AB_ADD");
CNumberWithinMessage NumberArray[1];
NumberArray[0].Set(numSplineNodes + 1);
CHelpMessage::SetMessageText(HELP_TEXT_SLOT_STANDARD, string, NumberArray, 1);
}
}
else if(pad.GetPressedDebugButtons() & ioPad::R2)
{
if(numSplineNodes >= 2) //We need a minimum of two spline nodes in order to activate playback.
{
//Toggle playback of the spline.
m_IsSplineActive = !m_IsSplineActive;
//Reset/rewind the spline progress.
splineCamera.SetPhase(0.0f);
}
}
}
}
void camMarketingAToBCamera::ClearAllSplineNodes()
{
//NOTE: We do not allow the spline nodes to be cleared when playback is active.
if(!m_IsSplineActive && m_SplineCamera && m_SplineCamera->GetIsClassId(camTimedSplineCamera::GetStaticClassId()))
{
camTimedSplineCamera& splineCamera = static_cast<camTimedSplineCamera&>(*m_SplineCamera);
splineCamera.ClearAllNodes();
}
}
void camMarketingAToBCamera::OnOverallSmoothingChange()
{
//Update all the spline camera smoothing style to reflect the latest values in RAG.
if(m_SplineCamera && m_SplineCamera->GetIsClassId(camTimedSplineCamera::GetStaticClassId()))
{
camTimedSplineCamera& splineCamera = static_cast<camTimedSplineCamera&>(*m_SplineCamera);
splineCamera.SetSmoothingStyle(camBaseSplineCamera::eSmoothingStyle(m_OverallSmoothingStyle));
}
}
void camMarketingAToBCamera::OnSmoothingChange()
{
//Update all the spline node smoothing settings to reflect the latest values in RAG.
if(m_SplineCamera && m_SplineCamera->GetIsClassId(camTimedSplineCamera::GetStaticClassId()))
{
camTimedSplineCamera& splineCamera = static_cast<camTimedSplineCamera&>(*m_SplineCamera);
const u32 numSplineNodes = static_cast<u32>(splineCamera.GetNumNodes());
for(u32 i=0; i<numSplineNodes - 1; i++)
{
camSplineNode* splineNode = splineCamera.DebugGetNode(i);
if(splineNode)
{
int nodeFlags = 0;
if(m_ShouldSmoothRotation)
{
nodeFlags |= camSplineNode::SHOULD_SMOOTH_ROTATION;
}
if(m_ShouldSmoothLensParameters)
{
nodeFlags |= camSplineNode::SHOULD_SMOOTH_LENS_PARAMS;
}
splineNode->SetFlags(camSplineNode::eFlags(nodeFlags));
}
}
}
}
void camMarketingAToBCamera::OnTransitionTimeChange()
{
//Update all the spline node transition times to reflect the latest values in RAG.
if(m_SplineCamera && m_SplineCamera->GetIsClassId(camTimedSplineCamera::GetStaticClassId()) && m_SplineTransitionTimes)
{
camTimedSplineCamera& splineCamera = static_cast<camTimedSplineCamera&>(*m_SplineCamera);
const u32 numSplineNodes = static_cast<u32>(splineCamera.GetNumNodes());
if(numSplineNodes > 0)
{
float totalNodeTimeMs = 0.0f;
for(u32 i=0; i<numSplineNodes - 1; i++)
{
camSplineNode* splineNode = splineCamera.DebugGetNode(i);
if(splineNode)
{
//NOTE: The widgets display the transition times in seconds, so we need to convert to milliseconds for the nodes.
const float transitionTimeMs = m_SplineTransitionTimes[i] * 1000.0f;
splineNode->SetTransitionDelta(transitionTimeMs);
totalNodeTimeMs += transitionTimeMs;
}
}
//Update the total time and duration of the spline to reflect the new node transition times.
splineCamera.DebugSetTotalDelta(totalNodeTimeMs);
splineCamera.SetDuration(static_cast<u32>(Floorf(totalNodeTimeMs)));
//NOTE: We must force a rebuild of the spline, as we have altered the internal nodes.
splineCamera.DebugForceSplineRebuild();
}
}
}
void camMarketingAToBCamera::AddWidgetsForInstance()
{
camMarketingFreeCamera::AddWidgetsForInstance();
if(m_WidgetGroup)
{
//Extend the widget group created by the base implementation.
bkBank* bank = BANKMGR.FindBank("Marketing Tools");
if(bank)
{
bank->SetCurrentGroup(*m_WidgetGroup);
{
bank->AddSeparator();
bank->AddTitle("A-B key frames");
bank->AddButton("Clear all key frames", datCallback(MFA(camMarketingAToBCamera::ClearAllSplineNodes), this));
bank->AddSlider("Max number of key frames", &m_MaxSplineNodes, 2, m_Metadata.m_MaxSplineNodes, 1);
bank->AddCombo("Overall smoothing style", &m_OverallSmoothingStyle, camBaseSplineCamera::NUM_SMOOTHING_STYLES, g_SmoothingStyleNames,
datCallback(MFA(camMarketingAToBCamera::OnOverallSmoothingChange), this), "Select a smoothing style for overall playback");
bank->AddToggle("Use free aim mode", &m_ShouldUseFreeLookAroundMode);
bank->AddSeparator();
bank->AddTitle("Key frame smoothing");
bank->AddToggle("Smooth rotation", &m_ShouldSmoothRotation, datCallback(MFA(camMarketingAToBCamera::OnSmoothingChange), this));
bank->AddToggle("Smooth lens parameters", &m_ShouldSmoothLensParameters, datCallback(MFA(camMarketingAToBCamera::OnSmoothingChange), this));
bank->AddSeparator();
bank->AddTitle("Transition times (secs)");
const int maxTitleLength = 10;
char title[maxTitleLength];
for(u32 i=0; i<m_Metadata.m_MaxSplineNodes; i++)
{
formatf(title, maxTitleLength, "%u->%u", i + 1, i + 2);
bank->AddSlider(title, m_SplineTransitionTimes + i, 0.0f, 600.0f, 0.1f, datCallback(MFA(camMarketingAToBCamera::OnTransitionTimeChange),
this));
}
}
bank->UnSetCurrentGroup(*m_WidgetGroup);
}
}
}
#endif // __BANK