Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.
Layout:
engine/ MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
models) + image codec; the minimal rp/ headers the audio HAL needs
game/ reconstructed BT logic + surviving-original BT source + fwd shims
+ WinMain launcher
content/ full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
docs/ format specs + reconstruction ledgers
reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
tools/ MP console emulator + map/resource scanners
One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
749 lines
17 KiB
C++
749 lines
17 KiB
C++
#include "munga.h"
|
|
#pragma hdrstop
|
|
|
|
#include "cammgr.h"
|
|
#include "mission.h"
|
|
#include "app.h"
|
|
#include "notation.h"
|
|
#include "namelist.h"
|
|
|
|
//##########################################################################
|
|
//##################### CameraInstanceManager #######################
|
|
//##########################################################################
|
|
|
|
//##########################################################################
|
|
// Construction and Destruction
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstanceManager::CameraInstanceManager() :
|
|
cameraList(NULL)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Initialize local member data
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
cameraIterator = new SChainIteratorOf<CameraInstance*>(cameraList);
|
|
Register_Object(cameraIterator);
|
|
InitializeCameraInstances();
|
|
Check_Fpu();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstanceManager::~CameraInstanceManager()
|
|
{
|
|
DeleteCameraList();
|
|
Unregister_Object(cameraIterator);
|
|
delete cameraIterator;
|
|
cameraIterator = NULL;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//##########################################################################
|
|
// CameraInstance Creation and Deletion Support
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int
|
|
CameraInstanceManager::FindUniqueCameraID()
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Finds a cameraID that has been freed up or the next sequential number
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
SChainIteratorOf<CameraInstance*> iterator(cameraList);
|
|
CameraInstance *camera_instance;
|
|
int camera_ID = 0;
|
|
Logical ID_exists = False;
|
|
|
|
while(1)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~
|
|
// Reset the iterator
|
|
//~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
iterator.First();
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Iterate through the list of all cameraInstances for every ID Chosen
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
if(camera_ID == camera_instance->GetCameraID())
|
|
{
|
|
ID_exists = True;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// If this cameraID not already used return the ID
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if(!ID_exists)
|
|
{
|
|
break;
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Otherwise increment the ID and reset the boolean
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
++camera_ID;
|
|
ID_exists = False;
|
|
}
|
|
|
|
Check_Fpu();
|
|
return camera_ID;
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraInstanceManager::SetCamera(
|
|
const Origin &new_origin,
|
|
CameraInstance *camera_instance
|
|
)
|
|
{
|
|
|
|
if(!camera_instance)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// No camera passed as an argument use cameraIterator
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
camera_instance = cameraIterator->GetCurrent();
|
|
if(!camera_instance)
|
|
{
|
|
CreateCameraInstance(new_origin);
|
|
}
|
|
else
|
|
{
|
|
camera_instance->SetLocalOrigin(new_origin);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Camera passed in set its origin
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
camera_instance->SetLocalOrigin(new_origin);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::CreateCameraInstance(const Origin &new_origin)
|
|
{
|
|
Check(this);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Find a Unique CameraID
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int camera_ID;
|
|
camera_ID = FindUniqueCameraID();
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the new cameraInstance
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance *camera_instance =
|
|
new CameraInstance(
|
|
camera_ID,
|
|
new_origin
|
|
);
|
|
Register_Object(camera_instance);
|
|
AddCameraInstance(camera_instance);
|
|
|
|
Check_Fpu();
|
|
return camera_instance;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::AddCameraInstance(CameraInstance *camera_instance)
|
|
{
|
|
Check(this);
|
|
Check(cameraIterator);
|
|
Check(&cameraList);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Insert the new Camera Instance into the cameraList
|
|
// & Point the cameraIterator to it
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
if (!cameraIterator->GetCurrent())
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// If nothing in the cameraList create the first element
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
cameraList.Add(camera_instance);
|
|
cameraIterator->First();
|
|
Tell("Created the First Camera Instance \n");
|
|
}
|
|
else
|
|
{
|
|
cameraList.Add(camera_instance);
|
|
cameraIterator->Next();
|
|
Tell("Created a Camera Instance \n");
|
|
}
|
|
Check_Fpu();
|
|
return camera_instance;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::DeleteCameraInstance()
|
|
{
|
|
CameraInstance *camera_instance = cameraIterator->GetCurrent();
|
|
if(!camera_instance)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cameraIterator->Remove();
|
|
if(!cameraIterator->GetCurrent())
|
|
{
|
|
cameraIterator->First();
|
|
}
|
|
Unregister_Object(camera_instance);
|
|
delete camera_instance;
|
|
return GetCurrent();
|
|
}
|
|
|
|
//##########################################################################
|
|
// CameraList Manipulator Functions
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraInstanceManager::DeleteCameraList()
|
|
{
|
|
while (cameraIterator->GetCurrent() != NULL)
|
|
{
|
|
DeleteCameraInstance();
|
|
}
|
|
}
|
|
|
|
//##########################################################################
|
|
// CameraList Iterator Manipulator Functions
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::IncrementIterator()
|
|
{
|
|
Check(this);
|
|
if (cameraIterator->GetCurrent())
|
|
{
|
|
Check(cameraIterator);
|
|
cameraIterator->ReadAndNext();
|
|
if (!cameraIterator->GetCurrent())
|
|
{
|
|
cameraIterator->First();
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
return GetCurrent();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::DecrementIterator()
|
|
{
|
|
Check(this);
|
|
if (cameraIterator->GetCurrent())
|
|
{
|
|
Check(cameraIterator);
|
|
cameraIterator->ReadAndPrevious();
|
|
if (!cameraIterator->GetCurrent())
|
|
{
|
|
cameraIterator->Last();
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
return GetCurrent();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::AdvanceIterator(const CameraInstance &camera_instance)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Search for the camera_instance in the cameraList
|
|
// Iterator points to camera_instance upon return
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(&camera_instance);
|
|
Check(&cameraList);
|
|
Check(cameraIterator);
|
|
|
|
CameraInstance *current_instance;
|
|
cameraIterator->First();
|
|
|
|
while((current_instance = cameraIterator->GetCurrent()) != NULL)
|
|
{
|
|
if(current_instance == &camera_instance)
|
|
{
|
|
Check_Fpu();
|
|
return current_instance;
|
|
}
|
|
cameraIterator->Next();
|
|
}
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// camera_instance not found return NULL
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check_Fpu();
|
|
return NULL;
|
|
}
|
|
|
|
//##########################################################################
|
|
// CameraList Searching and Query Functions
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance*
|
|
CameraInstanceManager::FindClosestCamera(const Point3D &point_3D)
|
|
{
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Use a Simple distance formula to find closest camera
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Check(this);
|
|
CameraInstance *closest_camera = NULL;
|
|
Scalar dist_to_goal, min_dist=1e8f;
|
|
|
|
SChainIteratorOf<CameraInstance*> iterator(cameraList);
|
|
CameraInstance *camera_instance;
|
|
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check(camera_instance);
|
|
if (camera_instance->CanCameraSee(point_3D))
|
|
{
|
|
Vector3D v;
|
|
v.Subtract(point_3D, camera_instance->GetPosition());
|
|
dist_to_goal = v.LengthSquared();
|
|
Check_Fpu();
|
|
if (dist_to_goal < min_dist)
|
|
{
|
|
min_dist = dist_to_goal;
|
|
closest_camera = camera_instance;
|
|
}
|
|
}
|
|
}
|
|
Check_Fpu();
|
|
return closest_camera;
|
|
}
|
|
|
|
//##########################################################################
|
|
// Test Support
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
CameraInstanceManager::TestInstance() const
|
|
{
|
|
return True;
|
|
}
|
|
|
|
//##########################################################################
|
|
// Tool Support
|
|
//
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraInstanceManager::InitializeCameraInstances()
|
|
{
|
|
Check(application);
|
|
ResourceDescription::ResourceID map_ID;
|
|
map_ID = application->GetCurrentMission()->GetMapID();
|
|
|
|
ResourceFile *res_file;
|
|
res_file = application->GetResourceFile();
|
|
Check(res_file);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create the camera filename from the map name
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceDescription *res = res_file->FindResourceDescription(map_ID);
|
|
Check(res);
|
|
Str_Copy(
|
|
cameraFilename,
|
|
"cameras\\",
|
|
sizeof(cameraFilename)
|
|
);
|
|
//
|
|
// cam name matches map name
|
|
//
|
|
Str_Cat(
|
|
cameraFilename,
|
|
res->resourceName,
|
|
sizeof(cameraFilename)
|
|
);
|
|
//
|
|
// trunc cam name to DOS filename size
|
|
//
|
|
int name_length = strlen(cameraFilename);
|
|
if(name_length > 17)
|
|
{
|
|
cameraFilename[17] = '\0';
|
|
}
|
|
|
|
//
|
|
// Add the extension
|
|
//
|
|
Str_Cat(
|
|
cameraFilename,
|
|
".cam",
|
|
sizeof(cameraFilename)
|
|
);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// See if the file exists
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
std::fstream cam_file;
|
|
//cam_file.open(cameraFilename, std::ios::nocreate | std::ios::in | std::ios::out);
|
|
// following alternate line created by Ryan Bunker on 1/6/07
|
|
cam_file.open(cameraFilename, std::ios::in);
|
|
if(cam_file) //NOTE: this appears broken (RB 1/6/07)
|
|
{
|
|
cam_file.close();
|
|
ReadNotationFile();
|
|
}
|
|
else
|
|
{
|
|
cam_file.close();
|
|
CreateStreamedCameraInstances(res_file, res->resourceName);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraInstanceManager::ReadNotationFile()
|
|
{
|
|
Check(this);
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create a Notation file out of the camera file
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
NotationFile *cam_file = new NotationFile(cameraFilename);
|
|
Register_Object(cam_file);
|
|
|
|
NameList* camera_namelist = cam_file->MakePageList();
|
|
Register_Object(camera_namelist);
|
|
|
|
NameList::Entry *camera_entry = camera_namelist->GetFirstEntry();
|
|
|
|
char
|
|
camera_page_name[128];
|
|
|
|
while (camera_entry)
|
|
{
|
|
Str_Copy(
|
|
camera_page_name,
|
|
camera_entry->GetName(),
|
|
sizeof(camera_page_name)
|
|
);
|
|
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// Create a new camera Instance for this page
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
CameraInstance *camera_instance;
|
|
const char *camera_data_entry;
|
|
int cam_type;
|
|
if(
|
|
!cam_file->GetEntry(
|
|
camera_page_name,
|
|
"cameraType",
|
|
&camera_data_entry
|
|
)
|
|
)
|
|
{
|
|
cam_type = CameraInstance::DefaultCameraType;
|
|
}
|
|
else
|
|
{
|
|
Check_Pointer(camera_data_entry);
|
|
cam_type = CameraInstance::FindCameraType(camera_data_entry);
|
|
}
|
|
switch (cam_type)
|
|
{
|
|
case CameraInstance::DefaultCameraType:
|
|
camera_instance = new CameraInstance(cam_file, camera_page_name);
|
|
break;
|
|
case CameraInstance::AlwaysSeesCameraType:
|
|
camera_instance =
|
|
new AlwaysSeesCameraInstance(cam_file, camera_page_name);
|
|
break;
|
|
}
|
|
Register_Object(camera_instance);
|
|
AddCameraInstance(camera_instance);
|
|
camera_entry = camera_entry->GetNextEntry();
|
|
}
|
|
Unregister_Object(camera_namelist);
|
|
delete camera_namelist;
|
|
Unregister_Object(cam_file);
|
|
delete cam_file;
|
|
Check_Fpu();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
#define PAGE_NAME_SIZE 128
|
|
|
|
void
|
|
CameraInstanceManager::CreateStreamedCameraInstances(
|
|
ResourceFile *res_file,
|
|
const char *map_name
|
|
)
|
|
{
|
|
Check(this);
|
|
Check_Pointer(res_file);
|
|
Check_Pointer(map_name);
|
|
|
|
ResourceDescription *res =
|
|
res_file->FindResourceDescription(
|
|
map_name,
|
|
ResourceDescription::CameraStreamResourceType
|
|
);
|
|
if (!res)
|
|
{
|
|
Check_Fpu();
|
|
return;
|
|
}
|
|
|
|
res->Lock();
|
|
|
|
MemoryStream camera_stream(res->resourceAddress, res->resourceSize);
|
|
int camera_count = *(int*)camera_stream.GetPointer();
|
|
camera_stream.AdvancePointer(sizeof(camera_count));
|
|
|
|
//
|
|
//--------------------
|
|
// Read in each camera
|
|
//--------------------
|
|
//
|
|
while (camera_count--)
|
|
{
|
|
Check(&camera_stream);
|
|
CameraInstance::StreamedInstance *model =
|
|
(CameraInstance::StreamedInstance*)camera_stream.GetPointer();
|
|
Check_Pointer(model);
|
|
CameraInstance *camera_instance;
|
|
switch (model->cameraType)
|
|
{
|
|
case CameraInstance::DefaultCameraType:
|
|
camera_instance = new CameraInstance(model);
|
|
break;
|
|
case CameraInstance::AlwaysSeesCameraType:
|
|
camera_instance = new AlwaysSeesCameraInstance(model);
|
|
break;
|
|
}
|
|
Register_Object(camera_instance);
|
|
AddCameraInstance(camera_instance);
|
|
camera_stream.AdvancePointer(model->instanceSize);
|
|
}
|
|
res->Unlock();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
CameraInstanceManager::WriteNotationFile()
|
|
{
|
|
Check(this);
|
|
Check(&cameraList);
|
|
|
|
NotationFile *camera_stream = new NotationFile();
|
|
Register_Object(camera_stream);
|
|
|
|
if(!camera_stream)
|
|
{
|
|
Fail("Error Opening Camera File\n");
|
|
}
|
|
SChainIteratorOf<CameraInstance*> iterator(cameraList);
|
|
CameraInstance *camera_instance;
|
|
|
|
iterator.First();
|
|
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
camera_instance->WriteNotationPage(camera_stream);
|
|
}
|
|
camera_stream->WriteFile(cameraFilename);
|
|
Unregister_Object(camera_stream);
|
|
delete camera_stream;
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
#define PAGE_NAME_SIZE 128
|
|
ResourceDescription::ResourceID
|
|
CameraInstanceManager::CreateCameraInstancesStream(
|
|
ResourceFile *resource_file,
|
|
const char *camera_name,
|
|
const ResourceDirectories *directories
|
|
)
|
|
{
|
|
Check_Pointer(camera_name);
|
|
Check_Pointer(directories);
|
|
|
|
//
|
|
//-------------------
|
|
// Open the .cam file
|
|
//-------------------
|
|
//
|
|
int length = strlen(camera_name) + strlen(directories->mapDirectory)+ 1;
|
|
|
|
char *filename = new char[length];
|
|
Register_Pointer(filename);
|
|
|
|
Str_Copy(filename, directories->mapDirectory, length);
|
|
strncat(filename, camera_name, strlen(camera_name)-3);
|
|
Str_Cat(filename, "cam", length);
|
|
|
|
NotationFile *camera_notation = new NotationFile(filename);
|
|
Register_Object(camera_notation);
|
|
|
|
if (camera_notation->PageCount() == 0)
|
|
{
|
|
DEBUG_STREAM << "Missing .cam file" << std::endl << std::flush;
|
|
Dump_And_Die:
|
|
Unregister_Object(camera_notation);
|
|
delete camera_notation;
|
|
Unregister_Pointer(filename);
|
|
delete[] filename;
|
|
return ResourceDescription::NullResourceID;
|
|
}
|
|
|
|
int camera_count = 0;
|
|
NameList *pagelist = camera_notation->MakePageList();
|
|
Register_Object(pagelist);
|
|
NameList::Entry *entry = pagelist->GetFirstEntry();
|
|
char page_name[PAGE_NAME_SIZE];
|
|
|
|
while (entry)
|
|
{
|
|
++camera_count;
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
|
|
size_t array_size =
|
|
sizeof(CameraInstance::StreamedInstance) * camera_count * 2;
|
|
long *camera_array = new long[(array_size+3) >> 2];
|
|
Register_Pointer(camera_array);
|
|
MemoryStream camera_stream(camera_array, array_size);
|
|
|
|
*(int*)camera_stream.GetPointer() = camera_count;
|
|
camera_stream.AdvancePointer(sizeof(camera_count));
|
|
|
|
entry = pagelist->GetFirstEntry();
|
|
while (entry)
|
|
{
|
|
Str_Copy(
|
|
page_name,
|
|
entry->GetName(),
|
|
sizeof(page_name)
|
|
);
|
|
|
|
if(strcmp(page_name, "CameraInfo") == 0)
|
|
{
|
|
entry = entry->GetNextEntry();
|
|
continue;
|
|
}
|
|
|
|
Check(&camera_stream);
|
|
CameraInstance::StreamedInstance *model =
|
|
(CameraInstance::StreamedInstance*)camera_stream.GetPointer();
|
|
Check_Pointer(model);
|
|
if (
|
|
!CameraInstance::CreateStreamedInstance(
|
|
model,
|
|
camera_notation,
|
|
page_name
|
|
)
|
|
)
|
|
{
|
|
Unregister_Pointer(camera_array);
|
|
delete[] camera_array;
|
|
Unregister_Object(pagelist);
|
|
delete pagelist;
|
|
goto Dump_And_Die;
|
|
}
|
|
camera_stream.AdvancePointer(model->instanceSize);
|
|
entry = entry->GetNextEntry();
|
|
}
|
|
|
|
//
|
|
//-------------------------------
|
|
// Write the stream out to disk.
|
|
//
|
|
|
|
Str_Copy(filename, camera_name, length);
|
|
filename[strlen(camera_name)-4] = '\0';
|
|
|
|
ResourceDescription *new_res =
|
|
resource_file->AddResource(
|
|
filename,
|
|
ResourceDescription::CameraStreamResourceType,
|
|
1,
|
|
ResourceDescription::LoadOnDemandFlag,
|
|
camera_array,
|
|
camera_stream.GetBytesUsed()
|
|
);
|
|
Check(new_res);
|
|
|
|
//-----------
|
|
// Free Mem
|
|
//
|
|
|
|
|
|
Unregister_Pointer(camera_array);
|
|
delete[] camera_array;
|
|
Unregister_Pointer(filename);
|
|
delete[] filename;
|
|
Unregister_Object(camera_notation);
|
|
delete camera_notation;
|
|
Unregister_Object(pagelist);
|
|
delete pagelist;
|
|
|
|
return new_res->resourceID;
|
|
}
|