thug/Code/Sk/Components/EditorCameraComponent.cpp
2016-02-14 08:39:12 +11:00

901 lines
27 KiB
C++

//****************************************************************************
//* MODULE: Sk/Components
//* FILENAME: EditorCameraComponent.cpp
//* OWNER: KSH
//* CREATION DATE: 26 Mar 2003
//****************************************************************************
#include <sk/components/editorcameracomponent.h>
#include <sk/components/raileditorcomponent.h>
#include <sk/modules/skate/skate.h>
#include <gel/components/inputcomponent.h>
#include <gel/object/compositeobject.h>
#include <gel/scripting/checksum.h>
#include <gel/scripting/script.h>
#include <gel/scripting/struct.h>
#include <gel/scripting/array.h>
#include <gel/scripting/parse.h>
#include <gel/scripting/symboltable.h>
#include <sk/engine/feeler.h>
#include <gfx/shadow.h>
#include <sk/scripting/nodearray.h>
#include <sys/config/config.h>
#include <sk/parkeditor2/parked.h>
//#define DEBUG_COLLISION
namespace Obj
{
static bool sHitKillPoly=false;
// If a poly's node's trigger script contains any of these then it is considered a Kill poly
static uint32 spKillScripts[]=
{
CRCC(0xdea3057b,"SK3_KillSkater"),
CRCC(0xb1058546,"SK3_KillSkater_Water"),
CRCC(0xb38ed6b,"SK3_KillSkater_Finish"),
CRCC(0x1310920e,"SK3_KillSkater_Pungee"),
CRCC(0x979a99ab,"NY_KillWater"),
CRCD(0x7aae1282,"RU_KillSkater"),
CRCD(0xcb1b1d9e,"RU_KillSkater2"),
CRCD(0x84e5c703,"NY_LeavingMessage"),
CRCD(0xf66fdf6e,"SJ_Televator"),
CRCD(0xb21175da,"HI_KillSkater_LittleDogs"),
CRCD(0xd9d60165,"VC_CAG_boundary"),
};
static void s_check_if_kill_poly ( CFeeler* p_feeler )
{
if (!p_feeler->GetTrigger() || !p_feeler->GetNodeChecksum())
{
#ifdef DEBUG_COLLISION
//printf("Not got trigger or not got node checksum\n");
#endif
return;
}
int node = SkateScript::FindNamedNode(p_feeler->GetNodeChecksum(), false);// false means don't assert
if (node < 0)
{
// Got a trigger, but no node, so assume it is a kill poly. This case arises in the park editor
// where a kill piece such as water or lava has been placed but the node array has not been generated yet.
//sHitKillPoly=true;
// Note: Commented out, to fix TT8832, where the cursor could get stuck on cars.
// The PE now allows the cursor to go anywhere, even onto kill polys.
return;
}
Script::CArray *p_node_array = Script::GetArray(CRCD(0xc472ecc5, "NodeArray"));
Script::CStruct *p_node = p_node_array->GetStructure(node);
uint32 trigger_script=0;
p_node->GetChecksum(CRCD(0x2ca8a299,"TriggerScript"),&trigger_script);
if (trigger_script)
{
//printf("trigger_script=%s\n",Script::FindChecksumName(trigger_script));
if (Script::ScriptContainsAnyOfTheNames(trigger_script,spKillScripts,sizeof(spKillScripts)/sizeof(uint32)))
{
sHitKillPoly=true;
}
}
}
// Checks whether the vector posA -> posB goes through any Kill polys.
// Does not check collidable polys.
static bool s_goes_through_kill_poly(const Mth::Vector &posA, const Mth::Vector &posB)
{
sHitKillPoly=false;
CFeeler feeler;
feeler.m_start = posA;
feeler.m_end = posB;
feeler.SetIgnore(0, mFD_NON_COLLIDABLE | mFD_TRIGGER);
feeler.SetCallback(s_check_if_kill_poly);
//feeler.DebugLine(0,255,0);
feeler.GetCollision();
return sHitKillPoly;
}
bool CEditorCameraComponent::find_y(Mth::Vector start, Mth::Vector end, float *p_y)
{
#ifdef DEBUG_COLLISION
//printf("s_find_y: ");
#endif
CFeeler feeler;
feeler.SetStart(start);
feeler.SetEnd(end);
// Ignore invisible polys, otherwise one can get stuck on top of the hotel in Hawaii,
// because it is surrounded by horizontal invisible polys.
//feeler.SetIgnore(mFD_INVISIBLE, 0);
if (feeler.GetCollision())
{
if (m_simple_collision)
{
#ifdef DEBUG_COLLISION
printf("Simple drop down\n");
#endif
sHitKillPoly=false;
Mth::Vector point=feeler.GetPoint();
*p_y=point[Y];
return true;
}
sHitKillPoly=false;
s_check_if_kill_poly(&feeler);
if (sHitKillPoly)
{
// Can't go onto collidable Kill polys
#ifdef DEBUG_COLLISION
printf("Kill poly!\n");
#endif
return false;
}
// Check the steepness
Mth::Vector normal=feeler.GetNormal();
// .087=max steepness of 85 degrees
if (normal[Y] < 0.087f/*sinf(Mth::DegToRad(90.0f-Script::GetFloat(CRCD(0x87b926b4,"MaxSteepness"))))*/)
{
// The ground is too steep!
// Need this check otherwise the skater can be placed halfway down the almost vertical
// riverbank in NJ
#ifdef DEBUG_COLLISION
printf("Too steep!\n");
#endif
return false;
}
#ifdef DEBUG_COLLISION
//printf("Found y=%f normal[Y]=%f\n",feeler.GetPoint()[Y],normal[Y]);
#endif
Mth::Vector point=feeler.GetPoint();
*p_y=point[Y];
// But, before returning true, check whether there are any kill polys between the start and the
// collision point.
if (s_goes_through_kill_poly(start, point))
{
#ifdef DEBUG_COLLISION
printf("Kill poly above found collision!\n");
#endif
return false;
}
return true;
}
#ifdef DEBUG_COLLISION
printf("No collision\n");
#endif
return false;
}
bool CEditorCameraComponent::find_collision_at_offset(Mth::Vector oldCursorPos, float upOffset)
{
Mth::Vector start=m_cursor_pos;
start[Y]+=upOffset;
Mth::Vector end=m_cursor_pos;
end[Y]+=Script::GetFloat(CRCD(0xf230d521,"EditorCam_CursorCollisionDownOffset"));
bool new_position_is_ok=false;
float y;
if (find_y(start,end,&y))
{
new_position_is_ok=true;
}
if (new_position_is_ok)
{
Mth::Vector from = oldCursorPos;
Mth::Vector to = m_cursor_pos;
to[Y]=y;
to[Y]+=72.0f; // 6 feet above the ground
// Make it really be horizontal to avoid steep collision check weirdness
from[Y]=to[Y];
if (!m_simple_collision)
{
// Do a horizontal collision check to see if the cursor
// is going to move through a kill poly
if (s_goes_through_kill_poly(from, to))
{
#ifdef DEBUG_COLLISION
printf("Goes through kill poly\n");
#endif
new_position_is_ok=false;
}
}
if (!m_allow_movement_through_walls)
{
// Also don't allow moving through walls
CFeeler feeler;
feeler.SetIgnore(mFD_NON_COLLIDABLE, 0);
feeler.SetStart(from);
feeler.SetEnd(to);
if (feeler.GetCollision())
{
#ifdef DEBUG_COLLISION
printf("oof\n");
#endif
new_position_is_ok=false;
}
}
}
if (new_position_is_ok)
{
m_cursor_pos[Y]=y;
return true;
}
return false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
CBaseComponent* CEditorCameraComponent::s_create()
{
return static_cast< CBaseComponent* >( new CEditorCameraComponent );
}
/******************************************************************/
/* */
/* */
/******************************************************************/
CEditorCameraComponent::CEditorCameraComponent() : CBaseComponent()
{
SetType( CRC_EDITORCAMERA );
m_camera_focus_pos.Set();
m_cam_pos.Set();
m_cursor_pos.Set();
m_cursor_u.Set();
m_cursor_v.Set();
m_radius=0.0f;
m_radius_min=0.0f;
m_radius_max=0.0f;
m_angle=0.0f;
m_tilt_angle=0.0f;
m_tilt_angle_min=0.0f;
m_tilt_angle_max=0.0f;
m_cursor_height=0.0f;
m_min_height=0.0f;
mp_shadow=NULL;
mp_input_component=NULL;
m_simple_collision=false;
m_allow_movement_through_walls=false;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
CEditorCameraComponent::~CEditorCameraComponent()
{
delete_shadow();
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// InitFromStructure is passed a Script::CStruct that contains a
// number of parameters to initialize this component
// this currently is the contents of a node
// but you can pass in anything you like.
void CEditorCameraComponent::InitFromStructure( Script::CStruct* pParams )
{
// ** Add code to parse the structure, and initialize the component
m_min_height=0.0f;
pParams->GetFloat(CRCD(0x9cdf40cd,"min_height"),&m_min_height);
m_radius_min=100.0f;
pParams->GetFloat(CRCD(0x52eecb98,"min_radius"),&m_radius_min);
m_radius_max=2000.0f;
pParams->GetFloat(CRCD(0x53e2512c,"max_radius"),&m_radius_max);
m_simple_collision=pParams->ContainsFlag(CRCD(0xa0d7fbab,"SimpleCollision"));
m_allow_movement_through_walls=pParams->ContainsFlag(CRCD(0xf5680def,"AllowMovementThroughWalls"));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// RefreshFromStructure is passed a Script::CStruct that contains a
// number of parameters to initialize this component
// this currently is the contents of a node
// but you can pass in anything you like.
void CEditorCameraComponent::RefreshFromStructure( Script::CStruct* pParams )
{
// Default to just calline InitFromStructure()
// but if that does not handle it, then will need to write a specific
// function here.
// The user might only want to update a single field in the structure
// and we don't want to be asserting becasue everything is missing
InitFromStructure(pParams);
}
void CEditorCameraComponent::Hide( bool shouldHide )
{
if (shouldHide)
{
delete_shadow();
}
else
{
create_shadow();
}
}
void CEditorCameraComponent::GetCursorOrientation(Mth::Vector *p_u, Mth::Vector *p_v)
{
*p_u=m_cursor_u;
*p_v=m_cursor_v;
}
void CEditorCameraComponent::create_shadow()
{
if (!mp_shadow)
{
mp_shadow = new Gfx::CSimpleShadow;
mp_shadow->SetScale( SHADOW_SCALE );
mp_shadow->SetModel( "Ped_Shadow" );
}
}
void CEditorCameraComponent::delete_shadow()
{
if (mp_shadow)
{
delete mp_shadow;
mp_shadow=NULL;
}
}
void CEditorCameraComponent::update_shadow()
{
Mth::Vector cursor_pos=m_cursor_pos;
cursor_pos[Y]+=m_cursor_height;
CFeeler feeler;
feeler.SetStart(cursor_pos);
feeler.SetEnd(cursor_pos + Mth::Vector(0.0f,SHADOW_COLLISION_CHECK_DISTANCE,0.0f,0.0f));
if (feeler.GetCollision())
{
create_shadow();
Mth::Matrix mat;
mat.Ident();
Mth::Vector shadow_pos=feeler.GetPoint();
Mth::Vector shadow_normal=feeler.GetNormal();
mp_shadow->UpdatePosition(shadow_pos,
mat,
shadow_normal);
}
else
{
delete_shadow();
}
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CEditorCameraComponent::Finalize()
{
// Get the pointers to the other required components.
Dbg_MsgAssert(mp_input_component==NULL,("mp_input_component not NULL ?"));
mp_input_component = GetInputComponentFromObject(GetObject());
Dbg_MsgAssert(mp_input_component,("CEditorCameraComponent requires parent object to have an input component!"));
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// The component's Update() function is called from the CCompositeObject's
// Update() function. That is called every game frame by the CCompositeObjectManager
// from the s_logic_code function that the CCompositeObjectManager registers
// with the task manger.
void CEditorCameraComponent::Update()
{
Dbg_MsgAssert(mp_input_component,("NULL mp_input_component"));
// TODO: When in park editor, use different values here, cos they'll need to be
// tweaked according to the shell geometry.
m_tilt_angle_min=Script::GetFloat(CRCD(0x7d16d113,"EditorCam_TiltMin"));
m_tilt_angle_max=Script::GetFloat(CRCD(0x411bee4a,"EditorCam_TiltMax"));
CControlPad& control_pad = mp_input_component->GetControlPad();
// Update m_angle
float angle_vel=Script::GetFloat(CRCD(0x8242d878,"EditorCam_TurnSpeed"))*control_pad.m_scaled_rightX;
m_angle+=angle_vel;
while (m_angle > 2*3.141592654f)
{
m_angle -= 2*3.141592654f;
}
while (m_angle < 0.0f)
{
m_angle += 2*3.141592654f;
}
// Update m_tilt_angle
angle_vel=-Script::GetFloat(CRCD(0x3cfa3a72,"EditorCam_TiltSpeed"))*control_pad.m_scaled_rightY;
m_tilt_angle+=angle_vel;
if (m_tilt_angle > m_tilt_angle_max)
{
m_tilt_angle = m_tilt_angle_max;
}
if (m_tilt_angle < m_tilt_angle_min)
{
m_tilt_angle = m_tilt_angle_min;
}
// Update m_radius
bool zoom_in_button_pressed=false;
bool zoom_out_button_pressed=false;
bool raise_pressed=false;
bool lower_pressed=false;
switch (Config::GetHardware())
{
case Config::HARDWARE_XBOX:
{
uint32 input_mask = mp_input_component->GetInputMask();
if (input_mask & Inp::Data::mA_BLACK)
{
zoom_out_button_pressed=true;
}
if (input_mask & Inp::Data::mA_WHITE)
{
zoom_in_button_pressed=true;
}
// Note: See p_siodev.cpp for the low level code that does the weird XBox buttons mappings
if (Ed::CParkEditor::Instance()->EditingCustomPark())
{
// When editing a park, XBox L gives L2, XBox R gives L1
// We want XBox L to lower, XBox R to raise
if (input_mask & Inp::Data::mA_L1)
{
raise_pressed=true;
}
if (input_mask & Inp::Data::mA_L2)
{
lower_pressed=true;
}
}
else
{
// When not editing a park, XBox L gives L1, XBox R gives R1
// We want XBox L to lower, XBox R to raise
if (input_mask & Inp::Data::mA_R1)
{
raise_pressed=true;
}
if (input_mask & Inp::Data::mA_L1)
{
lower_pressed=true;
}
}
break;
}
case Config::HARDWARE_NGC:
{
uint32 input_mask = mp_input_component->GetInputMask();
if (input_mask & Inp::Data::mA_Z)
{
if (input_mask & Inp::Data::mA_R1)
{
zoom_out_button_pressed=true;
}
if (input_mask & Inp::Data::mA_L1)
{
zoom_in_button_pressed=true;
}
}
else
{
if (input_mask & Inp::Data::mA_R1)
{
lower_pressed=true;
}
if (input_mask & Inp::Data::mA_L1)
{
raise_pressed=true;
}
}
break;
}
default:
{
zoom_out_button_pressed=control_pad.m_R1.GetPressed();
zoom_in_button_pressed=control_pad.m_R2.GetPressed();
raise_pressed=control_pad.m_L1.GetPressed();
lower_pressed=control_pad.m_L2.GetPressed();
break;
}
}
float radius_vel=Script::GetFloat(CRCD(0x4e58f829,"EditorCam_InOutSpeed"));
if (zoom_out_button_pressed)
{
}
else if (zoom_in_button_pressed)
{
radius_vel=-radius_vel;
}
else
{
radius_vel=0.0f;
}
// Make the speed proportional to the current radius so that the camera can be zoomed
// out to the max nice and quick.
radius_vel*=m_radius;
m_radius+=radius_vel;
if (m_radius < m_radius_min)
{
m_radius = m_radius_min;
}
if (m_radius > m_radius_max)
{
m_radius = m_radius_max;
}
float zoom_factor=(m_radius-m_radius_min)/(m_radius_max-m_radius_min);
// zoom_factor is between 0 and 1 and indicates how far out the camera is zoomed.
// 0 = closest to cursor, 1 = furthest away.
// Update the height
float height_vel_min=Script::GetFloat(CRCD(0x604961f4,"EditorCam_UpDownSpeedMin"));
float height_vel_max=Script::GetFloat(CRCD(0x5c445ead,"EditorCam_UpDownSpeedMax"));
float height_vel=height_vel_min + zoom_factor * (height_vel_max-height_vel_min);
// If very close in allow very fine movements, needed for rail placement in rail editor.
// TODO: Fix this so that the change in speed is not so sudden, make it linear like above.
if (m_radius < 100)
{
height_vel=0.2f;
}
if (raise_pressed)
{
}
else if (lower_pressed)
{
height_vel=-height_vel;
}
else
{
height_vel=0.0f;
}
m_cursor_height+=height_vel;
float max_height=Script::GetFloat(CRCD(0x61d56fa0,"EditorCam_MaxHeight"));
if (m_cursor_height > max_height)
{
m_cursor_height=max_height;
}
// Switch off collision on any created-rail sectors whilst doing collision checks.
// This is because the rail sectors have a vertical collidable poly, which occasionally does cause
// collisions, making the cursor ping up into the air. Must be some sort of floating point innaccuracy
// (or too much accuracy), probably because the collision check vector is straight down the vertical poly.
Mdl::Skate * p_skate_mod = Mdl::Skate::Instance();
if (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,"load_sk5ed"))
{
Obj::GetRailEditor()->SetSectorActiveStatus(false);
}
// Make sure that the cursor cannot be raised through a collidable poly, otherwise it
// can be raised through the stadium roof in slam city jam (TT3142)
CFeeler feeler;
feeler.SetStart(m_cursor_pos);
feeler.SetEnd(m_cursor_pos + Mth::Vector(0.0f, m_cursor_height+10.0f, 0.0f));
if (feeler.GetCollision())
{
m_cursor_height=feeler.GetPoint()[Y]-m_cursor_pos[Y]-10.0f;
}
// This allows the height to be less than m_min_height, but as soon as it goes
// over m_min_height it won't be able to go below it again.
// This is for the rail editor, where the min height needs to be limited whilst
// still allowing snapping to a vertex.
if (height_vel < 0.0f && m_cursor_height-height_vel+0.01 >= m_min_height)
{
if (m_cursor_height < m_min_height)
{
m_cursor_height=m_min_height;
}
}
if (m_cursor_height < 0.0f)
{
m_cursor_height=0.0f;
}
// Update m_cursor_pos ...
// First move it horizontally according to the left analogue stick
m_cursor_u.Set(cosf(m_angle),0.0f,-sinf(m_angle));
m_cursor_v.Set(sinf(m_angle),0.0f,cosf(m_angle));
float speed_min=Script::GetFloat(CRCD(0x83bde786,"EditorCam_MoveSpeedMin"));
float speed_max=Script::GetFloat(CRCD(0xbfb0d8df,"EditorCam_MoveSpeedMax"));
// Make the speed proportional to the zoom factor so that fine movements can be done
// when zoomed in, whilst fast movements can be made when zoomed out.
float speed = speed_min + zoom_factor * (speed_max-speed_min);
// If very close in allow very fine movements, needed for rail placement in rail editor.
// TODO: Fix this so that the change in speed is not so sudden, make it linear like above.
if (m_radius < 100)
{
speed=1.0f;
}
float horiz=control_pad.m_leftX / 128.0f;
float vert=control_pad.m_leftY / 128.0f;
if (fabs(horiz) < 0.01f)
{
if (control_pad.m_left.GetPressed())
{
horiz=-0.5f;
}
if (control_pad.m_right.GetPressed())
{
horiz=0.5f;
}
}
if (fabs(vert) < 0.01f)
{
if (control_pad.m_up.GetPressed())
{
vert=-0.5f;
}
if (control_pad.m_down.GetPressed())
{
vert=0.5f;
}
}
Mth::Vector vel = m_cursor_u * horiz*speed+
m_cursor_v * vert*speed;
Mth::Vector old_pos=m_cursor_pos;
m_cursor_pos+=vel;
// Now do a collision check to find the y.
if (!find_collision_at_offset(old_pos, Script::GetFloat(CRCD(0xc7210318,"EditorCam_CursorCollisionFirstUpOffset"))))
{
// Do an upwards collision check to check for a ceiling above the skater, and do not
// do the check for higher collision if there is a ceiling. This is to fix a bug where in Slam City
// the goal cursor would pop up into the stands if hitting the teleport poly in the escalator D corridor.
CFeeler feeler;
feeler.SetStart(old_pos);
Mth::Vector high=old_pos;
high[Y]+=120.0f;
feeler.SetEnd(high);
if (feeler.GetCollision())
{
// Undo the movement so that the cursor does not move.
m_cursor_pos=old_pos;
}
else if (!find_collision_at_offset(old_pos, Script::GetFloat(CRCD(0x56c2bff2,"EditorCam_CursorCollisionSecondUpOffset"))))
{
// Undo the movement so that the cursor does not move.
m_cursor_pos=old_pos;
}
else
{
// Did find higher collision, which is going to cause the cursor to pop to a high place, such
// as the roof of a building. In this case, zero the cursor height, because it seems weird to
// have it maintain it's hover height in that case. (TT10272)
m_cursor_height=m_min_height;
}
}
if (p_skate_mod->m_cur_level == CRCD(0xe8b4b836,"load_sk5ed"))
{
Obj::GetRailEditor()->SetSectorActiveStatus(true);
}
// Calculate the camera position, which equals the cursor position but has a lag
// applied so that as the cursor follows the contours of the ground it does not make
// the camera glitch.
m_camera_focus_pos[X]=m_cursor_pos[X];
m_camera_focus_pos[Z]=m_cursor_pos[Z];
m_camera_focus_pos[Y]+=(m_cursor_pos[Y]+m_cursor_height-m_camera_focus_pos[Y])*Script::GetFloat(CRCD(0x725ad02c,"EditorCam_YCatchUpFactor"));
Mth::Vector tilted_v;
tilted_v[X]=m_cursor_v[X]*cosf(m_tilt_angle);
tilted_v[Z]=m_cursor_v[Z]*cosf(m_tilt_angle);
tilted_v[Y]=sinf(m_tilt_angle);
Mth::Matrix mat;
mat[Z]=tilted_v;
mat[X]=m_cursor_u;
mat[Y]=Mth::CrossProduct(tilted_v,m_cursor_u);
mat[X][W]=0.0f;
mat[Y][W]=0.0f;
mat[Z][W]=0.0f;
mat[W].Set();
GetObject()->SetMatrix(mat);
Mth::Vector start=m_camera_focus_pos;
/*
Mth::Vector end;
float radius=m_radius;
while (true)
{
end=start+tilted_v*radius;
if (radius > Script::GetFloat(CRCD(0xf612c474,"EditorCam_CursorCollisionEnableDistMax")))
{
printf("Not checksing for collision\n");
break;
}
Mth::Vector p_rays[4];
p_rays[0]=start;
p_rays[1]=start-120*u+Mth::Vector(0.0f,70.0f,0.0f,0.0f);
p_rays[2]=start+Mth::Vector(0.0f,70.0f,0.0f,0.0f);
p_rays[3]=start+120*u+Mth::Vector(0.0f,70.0f,0.0f,0.0f);
if (cursor_occluded(p_rays,4,end))
{
radius=radius*0.9f; // TODO: Hmmm, should find out the exact distance ...
}
else
{
break;
}
}
m_cam_pos+=(end-m_cam_pos)*Script::GetFloat(CRCD(0xf151a64,"EditorCam_CameraCatchUpFactor"));
*/
// TODO: Fix the camera collision above, then comment out this line for it to have effect.
m_cam_pos=start + tilted_v*m_radius;
m_cam_pos[W]=1.0f;
GetObject()->SetPos(m_cam_pos);
update_shadow();
}
bool CEditorCameraComponent::cursor_occluded(Mth::Vector *p_ray_starts, int numRays, Mth::Vector end)
{
CFeeler feeler;
for (int i=0; i<numRays; ++i)
{
feeler.SetStart(p_ray_starts[i]);
feeler.SetEnd(end);
if (feeler.GetMovableCollision())
{
return false;
}
if (!feeler.GetCollision())
{
return false;
}
}
return true;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
// Given the "Checksum" of a script command, then possibly handle it
// if it's a command that this component will handle
CBaseComponent::EMemberFunctionResult CEditorCameraComponent::CallMemberFunction( uint32 Checksum, Script::CStruct* pParams, Script::CScript* pScript )
{
switch ( Checksum )
{
case 0xf362bbbf: // EditorCam_Initialise
pParams->GetVector(CRCD(0xb9d31b0a,"position"),&m_cursor_pos);
m_camera_focus_pos=m_cursor_pos;
m_radius=700.0f;
pParams->GetFloat(CRCD(0xc48391a5,"radius"),&m_radius);
m_tilt_angle=0.6f;
pParams->GetFloat(CRCD(0xe3c07609,"tilt"),&m_tilt_angle);
m_cursor_height=0.0f;
pParams->GetFloat(CRCD(0xb8d629ca,"cursor_height"),&m_cursor_height);
break;
case 0x69cb3ae1: // EditorCam_SetCursorPos
{
Mth::Vector pos;
pParams->GetVector(CRCD(0xb9d31b0a,"position"),&pos,Script::ASSERT);
m_cursor_pos=pos;
m_cursor_height=0.0f;
// Call update to do the ground collision check.
Update();
// That might have changed m_cursor_pos[Y], so adjust the height so that the cursor does
// appear at the required position.
m_cursor_height=pos[Y]-m_cursor_pos[Y];
// Note: If the above call to Update() followed by adjusting the height were not done, then it would not
// be possible to snap to rail vertices, because rails are uncollidable, so on the next frame the cursor
// would fall through the rail back to the ground.
break;
}
default:
return CBaseComponent::MF_NOT_EXECUTED;
}
// the "default" case of the switch statement handles
// unrecognized functions; if we make it down here,
// that means that the component already handled it
// somehow
return CBaseComponent::MF_TRUE;
}
/******************************************************************/
/* */
/* */
/******************************************************************/
void CEditorCameraComponent::GetDebugInfo(Script::CStruct *p_info)
{
#ifdef __DEBUG_CODE__
Dbg_MsgAssert(p_info,("NULL p_info sent to CEditorCameraComponent::GetDebugInfo"));
p_info->AddInteger("m_active",m_active);
p_info->AddVector("m_camera_focus_pos",m_camera_focus_pos.GetX(),m_camera_focus_pos.GetY(),m_camera_focus_pos.GetZ());
p_info->AddVector("m_cursor_pos",m_cursor_pos.GetX(),m_cursor_pos.GetY(),m_cursor_pos.GetZ());
p_info->AddFloat("m_cursor_height",m_cursor_height);
p_info->AddFloat("m_radius",m_radius);
p_info->AddFloat("m_radius_min",m_radius_min);
p_info->AddFloat("m_radius_max",m_radius_max);
p_info->AddFloat("m_angle",m_angle);
p_info->AddFloat("m_tilt_angle",m_tilt_angle);
p_info->AddFloat("m_tilt_angle_min",m_tilt_angle_min);
p_info->AddFloat("m_tilt_angle_max",m_tilt_angle_max);
// we call the base component's GetDebugInfo, so we can add info from the common base component
CBaseComponent::GetDebugInfo(p_info);
#endif
}
/******************************************************************/
/* */
/* */
/******************************************************************/
}