The pod hall stood the finishers on a numbered platform when the race ended. All of it shipped in this repo and none of it ever ran here: the stand geometry, the eight ranked dropzones win1-win8 in every one of the 11 maps, and the sequence that places the racers on them. The sequence lived on RPL4PlaybackApplication - the mission-review build - behind a spool file, so the app the pods actually race has never called it. RPL4Application now has its own StopMission handler that ranks the finishers, drops each onto their spot, freezes them, re-sorts the name plates into finishing order and frames a camera on the stand. It fires once: StopMission arrives twice, from the console at the buzzer and again from the player when the ending fade expires, and only the first is the end of the race. Ranking works in football as well as a race. CalcFootballRanking ranks only the RunnerPlayers group, which would have placed the runners and stopped - but nothing calls it. What runs is Player::CalcRanking, every frame, over every scoring player by score. Three pieces of the original had been stubbed out in the D3D9 port and are restored: SetViewAngle was an empty function, so the 45 degrees the sequence asks for did nothing. It now rebuilds the projection the way DPLReadINIPage does and pushes it, and sets viewRatio, which nothing had written since the DPL body was commented out. winnersCircleFogStyle was an empty case. The stand sits far off the track in open ground where the track's own fog leaves it dark; this is the blue-violet the original used, with the fog pushed back to 100/1050 and the clip plane pulled to 1100. The end-of-mission fade had to be told to stand down. It multiplies the fog colour and both fog distances toward zero every frame - correct when a race just ends, fatal to anything shown afterwards. That fade is what made the podium a black screen, and it took a while to find because every frame was being built and presented correctly the whole time. The presentation camera overrides D3DTS_VIEW between the eye renderable writing it and ExecuteImplementation reading it back for the draw calls, so no CameraShip is needed. It builds with LookAt LH, not RH: the projection is LH, and RH aims the camera the opposite way - ask to look down at the stand and you get the sky behind you. The engine's own eye renderable is right to use RH, because its forward and up come out of the entity matrix already in that convention. The mission is held open 11 seconds rather than 3. That fade timer is the only thing keeping the simulation and the renderer alive once the race is over, and it has no upper bound on the ending path. Switches, all off-by-default behaviour aside: RP412PODIUM=0 skips it, RP412PODIUMCAM=0 keeps the cockpit view, RP412PODIUMSTANDOFF/HEIGHT/AIM frame the shot, RP412MISSIONSECONDS overrides the menu game length (the shortest it offers is 3:00, a long wait when what you are testing is the buzzer), and RP412RENDERDIAG=1 reports what a frame is made of. Verified end to end on Wiseguy's Wake: the stand, its tiers, the blue 2 and 3, the red 4 through 8 and all eight name bays, held steady for the full 11 seconds and then handing off to the results screen. Known gaps: the name plates are blank, because the player1-8 textures are runtime name bitmaps that do not resolve as files in this port, and your own vehicle has no exterior model - you see the others, not yourself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
667 lines
19 KiB
C++
667 lines
19 KiB
C++
#include "rpl4.h"
|
|
#pragma hdrstop
|
|
|
|
#include "rpl4app.h"
|
|
#include "rpl4vid.h"
|
|
#include "rpl4arnd.h"
|
|
#include "rpl4grnd.h"
|
|
#include "rpl4mssn.h"
|
|
#include "..\munga_l4\l4gauge.h"
|
|
#include "..\rp\rpreg.h"
|
|
#include "..\munga_l4\l4ctrl.h"
|
|
#include "..\munga_l4\l4mppr.h"
|
|
#include "..\munga\appmgr.h"
|
|
#include "rpl4mode.h"
|
|
#include "..\rp\vtv.h"
|
|
#include "rpl4mppr.h"
|
|
#include "..\rp\rpplayer.h"
|
|
#include "..\munga_l4\l4video.h"
|
|
#include "..\munga\dropzone.h"
|
|
#include "..\munga\director.h"
|
|
#include "..\munga\nttmgr.h"
|
|
|
|
//
|
|
//#############################################################################
|
|
// RPL4Application
|
|
//#############################################################################
|
|
//
|
|
const Receiver::HandlerEntry
|
|
RPL4Application::MessageHandlerEntries[]=
|
|
{
|
|
MESSAGE_ENTRY(RPL4Application, StopMission)
|
|
};
|
|
|
|
Receiver::MessageHandlerSet& RPL4Application::GetMessageHandlers()
|
|
{
|
|
static Receiver::MessageHandlerSet messageHandlers(
|
|
ELEMENTS(RPL4Application::MessageHandlerEntries),
|
|
RPL4Application::MessageHandlerEntries,
|
|
L4Application::GetMessageHandlers());
|
|
return messageHandlers;
|
|
}
|
|
|
|
Derivation* RPL4Application::GetClassDerivations()
|
|
{
|
|
static Derivation classDerivations(
|
|
L4Application::GetClassDerivations(), "RPL4Application");
|
|
return &classDerivations;
|
|
}
|
|
|
|
RPL4Application::SharedData
|
|
RPL4Application::DefaultData(
|
|
RPL4Application::GetClassDerivations(),
|
|
RPL4Application::GetMessageHandlers()
|
|
);
|
|
|
|
RPL4Application::RPL4Application(
|
|
HINSTANCE hInstance,
|
|
HWND hWnd,
|
|
ResourceFile *resource_file,
|
|
ClassID class_ID,
|
|
SharedData &shared_data
|
|
):
|
|
L4Application(hInstance, hWnd, resource_file, RPL4, class_ID, shared_data)
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ~RPL4Application
|
|
//#############################################################################
|
|
//
|
|
RPL4Application::~RPL4Application()
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// ShowWinnersCircle
|
|
//#############################################################################
|
|
//
|
|
// The pod hall's award platform. Every map carries a "wcircle" stand at
|
|
// (1200,0,0) with eight ranked dropzones named win1..win8 on it - rank 1 at
|
|
// the front on the low tier, ranks 4-8 across the back on the high one. All
|
|
// this shipped; only the mission-review build ever drove it.
|
|
//
|
|
// Stand the finishers on their spots in finishing order, freeze them, and
|
|
// look back at the stand from in front of it.
|
|
//
|
|
void
|
|
RPL4Application::ShowWinnersCircle()
|
|
{
|
|
Check(this);
|
|
|
|
// RP412PODIUM=0 skips the whole thing
|
|
const char *podium_mode = getenv("RP412PODIUM");
|
|
if (podium_mode != NULL && atoi(podium_mode) == 0)
|
|
{
|
|
DEBUG_STREAM << "WinnersCircle: disabled\n" << std::flush;
|
|
return;
|
|
}
|
|
|
|
EntityManager *entity_manager = GetEntityManager();
|
|
if (entity_manager == NULL)
|
|
{
|
|
return;
|
|
}
|
|
EntityGroup *dropzones = entity_manager->FindGroup("DropZones");
|
|
if (dropzones == NULL)
|
|
{
|
|
DEBUG_STREAM << "WinnersCircle: no DropZones group\n" << std::flush;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Walk the finishing order. Player::CalcRanking has been ranking every
|
|
// scoring player by score each frame, in football as much as in a race
|
|
// (CalcFootballRanking exists but is never called), so rank order is
|
|
// meaningful in both.
|
|
//---------------------------------------------------------------------
|
|
//
|
|
char winners_spot[] = "win?";
|
|
char *place = winners_spot + 3;
|
|
int placed = 0;
|
|
Point3D standFront(0.0f, 0.0f, 0.0f);
|
|
Point3D standCentre(0.0f, 0.0f, 0.0f);
|
|
|
|
Player *p;
|
|
for (int rank = 0; (p = CameraDirector::FindPlayerByRank(rank)) != NULL; ++rank)
|
|
{
|
|
if (rank > 7)
|
|
{
|
|
break; // only eight spots exist on the stand
|
|
}
|
|
*place = (char) ('1' + rank);
|
|
|
|
ChainIteratorOf<Node*> iterator(dropzones->groupMembers);
|
|
DropZone *dropzone;
|
|
while ((dropzone = (DropZone*) iterator.ReadAndNext()) != NULL)
|
|
{
|
|
if (!strcmp(dropzone->GetDropZoneName(), winners_spot))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (dropzone == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Entity *vehicle = p->GetPlayerVehicle();
|
|
if (vehicle == NULL || vehicle->GetClassID() != VTVClassID)
|
|
{
|
|
continue;
|
|
}
|
|
VTV *vtv = (VTV*) vehicle;
|
|
vtv->Reset(dropzone->localOrigin, VTV::MissionReviewReset);
|
|
vtv->SetPerformance(&VTV::DoNothing);
|
|
vtv->FlushEvents();
|
|
|
|
Point3D spot = dropzone->localOrigin.linearPosition;
|
|
if (placed == 0)
|
|
{
|
|
// remember where the front of the stand is - the shot is framed
|
|
// off it rather than off hardcoded map coordinates
|
|
standFront = spot;
|
|
}
|
|
standCentre += spot;
|
|
DEBUG_STREAM << "WinnersCircle: " << winners_spot << " at "
|
|
<< spot.x << "," << spot.y << "," << spot.z << "\n" << std::flush;
|
|
++placed;
|
|
}
|
|
|
|
if (placed == 0)
|
|
{
|
|
DEBUG_STREAM << "WinnersCircle: nobody to place\n" << std::flush;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Switch the world back on.
|
|
//
|
|
// Dying collapses the view and sets the application "dead" until the
|
|
// pilot reincarnates - while that flag is up the renderer skips every
|
|
// static object, which is the whole map. A pilot killed near the buzzer
|
|
// is still waiting for a respawn that will never come, so the flag is
|
|
// still up and the podium would play out against a black screen.
|
|
//
|
|
// The mission-review build never hit this: it watches from a CameraShip,
|
|
// which cannot die, so nothing ever set the flag there.
|
|
//
|
|
// Standing the finishers up IS the resurrection, so clear it.
|
|
//---------------------------------------------------------------------
|
|
//
|
|
SetIsDead(false);
|
|
|
|
DPLRenderer *dpl_renderer = GetVideoRenderer();
|
|
if (dpl_renderer == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// The name plates are drawn per rank slot, so they have to be re-sorted
|
|
// now that the finishing order is final - otherwise the signs read in
|
|
// whatever order the players were created.
|
|
//---------------------------------------------------------------------
|
|
//
|
|
dpl_renderer->SortAndReloadNameBitmaps();
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Widen to 45 degrees and pull back in front of the stand so the whole
|
|
// line-up frames up. The stand runs from z~3 (rank 1, low) to z~39
|
|
// (ranks 4-8, high) and x~1180..1219; at 45 degrees that needs roughly
|
|
// 30 units of standoff. Eye is above the top tier looking slightly
|
|
// down at the middle of the group.
|
|
//---------------------------------------------------------------------
|
|
//
|
|
standCentre.x /= (Scalar) placed;
|
|
standCentre.y /= (Scalar) placed;
|
|
standCentre.z /= (Scalar) placed;
|
|
|
|
//
|
|
// Stand off along the line from the middle of the group out through the
|
|
// front spot, so the shot faces the stand however the map has it turned,
|
|
// and lift the eye above the top tier to look down on the line-up.
|
|
//
|
|
Vector3D facing;
|
|
facing.x = standFront.x - standCentre.x;
|
|
facing.y = 0.0f;
|
|
facing.z = standFront.z - standCentre.z;
|
|
Scalar reach = (Scalar) sqrt(facing.x * facing.x + facing.z * facing.z);
|
|
if (reach < 0.01f)
|
|
{
|
|
facing.x = 0.0f; facing.z = -1.0f; reach = 1.0f;
|
|
}
|
|
//
|
|
// Framing is tunable while the shot is being dialled in:
|
|
// RP412PODIUMSTANDOFF distance out in front of the stand
|
|
// RP412PODIUMHEIGHT eye height above the group
|
|
// RP412PODIUMAIM height of the aim point above the group
|
|
//
|
|
// framed off the stand itself: far enough back for all eight bays and
|
|
// the numbers above them, high enough to look down the tiers
|
|
Scalar standoff = 45.0f;
|
|
Scalar height = 18.0f;
|
|
Scalar aim_lift = 2.0f;
|
|
const char *tune = getenv("RP412PODIUMSTANDOFF");
|
|
if (tune != NULL && atof(tune) != 0.0) standoff = (Scalar) atof(tune);
|
|
tune = getenv("RP412PODIUMHEIGHT");
|
|
if (tune != NULL && atof(tune) != 0.0) height = (Scalar) atof(tune);
|
|
tune = getenv("RP412PODIUMAIM");
|
|
if (tune != NULL) aim_lift = (Scalar) atof(tune);
|
|
|
|
Point3D eye;
|
|
eye.x = standCentre.x + (facing.x / reach) * standoff;
|
|
eye.y = standCentre.y + height;
|
|
eye.z = standCentre.z + (facing.z / reach) * standoff;
|
|
standCentre.y += aim_lift;
|
|
|
|
//
|
|
// RP412PODIUMCAM=0 leaves the view in the cockpit, which is also the
|
|
// way to tell a bad camera from a scene that is not drawing at all.
|
|
//
|
|
//
|
|
// Fog first: it pulls the clip plane in to 1100, and SetViewAngle is what
|
|
// rebuilds the projection that reads it.
|
|
//
|
|
dpl_renderer->SetFogStyle(DPLRenderer::winnersCircleFogStyle);
|
|
|
|
const char *camera_mode = getenv("RP412PODIUMCAM");
|
|
if (camera_mode == NULL || atoi(camera_mode) != 0)
|
|
{
|
|
dpl_renderer->SetViewAngle(Degree(45.0f));
|
|
dpl_renderer->SetPresentationCamera(eye, standCentre);
|
|
}
|
|
else
|
|
{
|
|
// still rebuild the projection so the new clip plane takes effect
|
|
dpl_renderer->SetViewAngle(Degree(40.0f));
|
|
}
|
|
if (camera_mode != NULL && atoi(camera_mode) == 0)
|
|
{
|
|
DEBUG_STREAM << "WinnersCircle: presentation camera disabled\n"
|
|
<< std::flush;
|
|
}
|
|
|
|
DEBUG_STREAM << "WinnersCircle: " << placed << " placed; centre "
|
|
<< standCentre.x << "," << standCentre.y << "," << standCentre.z
|
|
<< " eye " << eye.x << "," << eye.y << "," << eye.z
|
|
<< "\n" << std::flush;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// StopMissionMessageHandler
|
|
//#############################################################################
|
|
//
|
|
// The mission is over. Show the podium, then let the base handler run - it
|
|
// puts the player into MissionEndingState, whose fade timer is what actually
|
|
// keeps the sim and the renderer alive until teardown.
|
|
//
|
|
void
|
|
RPL4Application::StopMissionMessageHandler(StopMissionMessage *message)
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
// StopMission arrives twice: once from the console at the buzzer, and
|
|
// again from the player when the ending fade runs out - that second one
|
|
// is what actually retires the application. Only the first is the end of
|
|
// the race, so only the first stands anybody up.
|
|
//
|
|
if (GetApplicationState() != Application::EndingMission)
|
|
{
|
|
DEBUG_STREAM << "WinnersCircle: mission stopped, standing the finishers up\n"
|
|
<< std::flush;
|
|
ShowWinnersCircle();
|
|
}
|
|
|
|
L4Application::StopMissionMessageHandler(message);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// MakeRegistry
|
|
//#############################################################################
|
|
//
|
|
Registry*
|
|
RPL4Application::MakeRegistry()
|
|
{
|
|
Check_Fpu();
|
|
return new RPRegistry(GetResourceFile());
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// MakeVideoRenderer
|
|
//#############################################################################
|
|
//
|
|
VideoRenderer*
|
|
RPL4Application::MakeVideoRenderer()
|
|
{
|
|
if (divisionParameters)
|
|
{
|
|
return
|
|
new RPL4VideoRenderer(
|
|
ghWnd,
|
|
L4Application::mScreenWidth,
|
|
L4Application::mScreenHeight,
|
|
L4Application::mFullscreen,
|
|
VisualInterestType,
|
|
DefaultInterestDepth
|
|
);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// MakeAudioRenderer
|
|
//#############################################################################
|
|
//
|
|
AudioRenderer*
|
|
RPL4Application::MakeAudioRenderer()
|
|
{
|
|
Check_Fpu();
|
|
// char *blaster1, *blaster2;
|
|
|
|
// blaster1 = getenv(FRONT_CARD_ENV_VAR);
|
|
// blaster2 = getenv(REAR_CARD_ENV_VAR);
|
|
|
|
//if (blaster1 != NULL && blaster2 != NULL)
|
|
//{
|
|
return new RPL4AudioRenderer(
|
|
1000.0f,
|
|
GetMissionReviewMode()
|
|
);
|
|
//}
|
|
// return NULL;
|
|
}
|
|
|
|
//#############################################################################
|
|
// MakeModeManager
|
|
//#############################################################################
|
|
ModeManager*
|
|
RPL4Application::MakeModeManager()
|
|
{
|
|
RPL4ModeManager
|
|
*manager = new RPL4ModeManager(RPL4ModeManager::ModeInitial);
|
|
Check(manager);
|
|
return manager;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// MakeGaugeRenderer
|
|
//#############################################################################
|
|
//
|
|
GaugeRenderer*
|
|
RPL4Application::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index)
|
|
{
|
|
char *mode_string = getenv("L4GAUGE");
|
|
if (mode_string != NULL && (secondaryIndex != NULL || aux1Index != NULL || aux2Index != NULL))
|
|
{
|
|
return new RPL4GaugeRenderer(!L4Application::mFullscreen, secondaryIndex, aux1Index, aux2Index);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// MakeMission
|
|
//#############################################################################
|
|
//
|
|
Mission*
|
|
RPL4Application::MakeMission(
|
|
NotationFile *notation_file,
|
|
ResourceFile *resources
|
|
)
|
|
{
|
|
Check(this);
|
|
Check(notation_file);
|
|
Check(resources);
|
|
|
|
Check_Fpu();
|
|
return new RPL4Mission(notation_file, resources);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// MakeViewpointEntity
|
|
//#############################################################################
|
|
//
|
|
Entity*
|
|
RPL4Application::MakeViewpointEntity(Entity::MakeMessage *message)
|
|
{
|
|
Check(this);
|
|
|
|
// Entity
|
|
// *viewing_entity = L4Application::MakeViewpointEntity(message);
|
|
//
|
|
// if(viewing_entity)
|
|
// {
|
|
// Check_Fpu();
|
|
// return viewing_entity;
|
|
// }
|
|
|
|
LBE4ControlsManager* controls =
|
|
(LBE4ControlsManager *)GetControlsManager();
|
|
Check(controls);
|
|
|
|
Entity
|
|
*viewing_entity = NULL;
|
|
char
|
|
*primary_mapping_name = NULL;
|
|
|
|
switch(message->classToCreate)
|
|
{
|
|
case CameraShipClassID:
|
|
//=======================================================================
|
|
// Create Camera ship
|
|
//=======================================================================
|
|
{
|
|
CameraShip
|
|
*viewing_camera =
|
|
CameraShip::Make((CameraShip::MakeMessage*)message);
|
|
Check(viewing_camera);
|
|
|
|
viewing_entity = viewing_camera;
|
|
//--------------------------------------------------
|
|
// Create controls mapping object
|
|
//--------------------------------------------------
|
|
CameraControlsMapper::SubsystemResource
|
|
control_subsystem_resource;
|
|
|
|
Str_Copy(
|
|
control_subsystem_resource.subsystemName,
|
|
"ControlsMapper",
|
|
sizeof(control_subsystem_resource.subsystemName)
|
|
);
|
|
control_subsystem_resource.classID = TrivialSubsystemClassID;
|
|
control_subsystem_resource.subsystemModelSize =
|
|
sizeof(control_subsystem_resource);
|
|
|
|
CameraControlsMapper
|
|
*camera_mapper;
|
|
|
|
switch (controls->primaryControlType)
|
|
{
|
|
case LBE4ControlsManager::PrimaryThrustMaster:
|
|
Tell("RPL4Application, CameraShip using ThrustMaster\n");
|
|
camera_mapper = new CameraThrustmasterMapper(
|
|
viewing_camera,
|
|
CameraShip::ControlsMapperSubsystem,
|
|
&control_subsystem_resource
|
|
);
|
|
primary_mapping_name = "Thrustmaster";
|
|
break;
|
|
|
|
case LBE4ControlsManager::PrimaryRIO:
|
|
Tell("RPL4Application, CameraShip using RIO\n");
|
|
camera_mapper = new CameraRIOMapper(
|
|
viewing_camera,
|
|
CameraShip::ControlsMapperSubsystem,
|
|
&control_subsystem_resource
|
|
);
|
|
primary_mapping_name = "L4";
|
|
break;
|
|
|
|
default:
|
|
Tell("RPL4Application, CameraShip using default mapper\n");
|
|
camera_mapper = new CameraL4Mapper(
|
|
viewing_camera,
|
|
CameraShip::ControlsMapperSubsystem,
|
|
&control_subsystem_resource
|
|
);
|
|
// primary mapping name is NULL
|
|
break;
|
|
}
|
|
|
|
//-------------------------------------------
|
|
// Set mapping subsystem for this entity
|
|
//-------------------------------------------
|
|
Register_Object(camera_mapper);
|
|
viewing_camera->SetMappingSubsystem(camera_mapper);
|
|
}
|
|
break;
|
|
|
|
case VTVClassID:
|
|
//=======================================================================
|
|
// Create VTV
|
|
//=======================================================================
|
|
{
|
|
VTV
|
|
*viewing_VTV = VTV::Make((VTV::MakeMessage*)message);
|
|
Check(viewing_VTV);
|
|
|
|
viewing_entity = viewing_VTV;
|
|
//--------------------------------------------------
|
|
// Set control deadbanding
|
|
//--------------------------------------------------
|
|
controls->SetJoystickDeadBand(.1);
|
|
controls->SetThrottleDeadBand(.1);
|
|
controls->SetPedalsDeadBand(.1);
|
|
//--------------------------------------------------
|
|
// Create controls mapping object
|
|
//--------------------------------------------------
|
|
VTVControlsMapper::SubsystemResource
|
|
control_subsystem_resource;
|
|
Str_Copy(
|
|
control_subsystem_resource.subsystemName,
|
|
"ControlsMapper",
|
|
sizeof(control_subsystem_resource.subsystemName)
|
|
);
|
|
control_subsystem_resource.classID = TrivialSubsystemClassID;
|
|
control_subsystem_resource.subsystemModelSize =
|
|
sizeof(control_subsystem_resource);
|
|
control_subsystem_resource.segmentIndex = -1;
|
|
control_subsystem_resource.subsystemFlags = 0;
|
|
|
|
VTVControlsMapper
|
|
*vtv_mapper;
|
|
|
|
switch (controls->primaryControlType)
|
|
{
|
|
case LBE4ControlsManager::PrimaryThrustMaster:
|
|
Tell("RPL4Application, VTV using ThrustMaster\n");
|
|
vtv_mapper = new VTVThrustmasterMapper(
|
|
viewing_VTV,
|
|
VTV::ControlsMapperSubsystem,
|
|
&control_subsystem_resource
|
|
);
|
|
primary_mapping_name = "Thrustmaster";
|
|
break;
|
|
|
|
case LBE4ControlsManager::PrimaryRIO:
|
|
Tell("RPL4Application, VTV using RIO\n");
|
|
vtv_mapper = new VTVRIOMapper(
|
|
viewing_VTV,
|
|
VTV::ControlsMapperSubsystem,
|
|
&control_subsystem_resource
|
|
);
|
|
primary_mapping_name = "L4";
|
|
break;
|
|
|
|
default:
|
|
DEBUG_STREAM << "*****VTV has no controls mapping!*****" << std::flush;
|
|
Fail("RPL4Application::MakeViewpointEntity");
|
|
vtv_mapper = NULL;
|
|
// primary mapping name is NULL
|
|
break;
|
|
}
|
|
|
|
//-------------------------------------------
|
|
// Set mapping subsystem for this entity
|
|
//-------------------------------------------
|
|
Register_Object(vtv_mapper);
|
|
viewing_VTV->SetMappingSubsystem(vtv_mapper);
|
|
//-------------------------------------------
|
|
// Enable collision detection for this entity
|
|
//-------------------------------------------
|
|
viewing_VTV->StartCollisionAssistant();
|
|
}
|
|
break;
|
|
}
|
|
Check(viewing_entity);
|
|
|
|
//------------------------------------------------------------------------
|
|
// Load up the control mapping stream for the entity
|
|
//------------------------------------------------------------------------
|
|
if (primary_mapping_name != NULL)
|
|
{
|
|
ResourceDescription
|
|
*resource_description =
|
|
application->GetResourceFile()->SearchList(
|
|
viewing_entity->GetResourceID(),
|
|
ResourceDescription::ControlMappingsListResourceType
|
|
);
|
|
|
|
if (resource_description != NULL)
|
|
{
|
|
Check(resource_description);
|
|
|
|
Check(GetResourceFile());
|
|
resource_description =
|
|
GetResourceFile()->SearchList(
|
|
resource_description->resourceID,
|
|
primary_mapping_name
|
|
);
|
|
|
|
if (resource_description != NULL)
|
|
{
|
|
Check(resource_description);
|
|
|
|
resource_description->Lock();
|
|
controls->CreateStreamedMappings(
|
|
viewing_entity,
|
|
(int*)resource_description->resourceAddress
|
|
);
|
|
resource_description->Unlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// Create gauges for this entity
|
|
//------------------------------------------------------------------------
|
|
RPL4GaugeRenderer
|
|
*gauge_renderer = (RPL4GaugeRenderer *) GetGaugeRenderer();
|
|
|
|
if (gauge_renderer != NULL)
|
|
{
|
|
Check(gauge_renderer);
|
|
gauge_renderer->ConfigureForModel("Init", viewing_entity);
|
|
}
|
|
|
|
Check_Fpu();
|
|
return viewing_entity;
|
|
}
|