Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1507 lines
44 KiB
C++
1507 lines
44 KiB
C++
//===========================================================================//
|
|
// File: Tool.cpp //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 08/25/97 JMA Infrastructure changes //
|
|
// 08/25/97 ECH Infrastructure changes //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-97, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "AdeptHeaders.hpp"
|
|
|
|
#include "Tool.hpp"
|
|
#include "RendererManager.hpp"
|
|
#include "Application.hpp"
|
|
#include "AudioRenderer.hpp"
|
|
#include <gosFX\EffectLibrary.hpp>
|
|
#include "ResourceImagePool.hpp"
|
|
#include "ResourceEffectLibrary.hpp"
|
|
#include "AudioSample.hpp"
|
|
#include <mbstring.h>
|
|
#define __mbsrchr(s,c) (char*)_mbsrchr((const unsigned char*)(s),(c))
|
|
|
|
Tool *Tool::Instance = NULL;
|
|
|
|
//#############################################################################
|
|
//######################## Tool #########################################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Tool::Tool()
|
|
{
|
|
//
|
|
//--------------------------------
|
|
// hook up the global tool pointer
|
|
//--------------------------------
|
|
//
|
|
Verify(Tool::Instance == NULL);
|
|
Tool::Instance = this;
|
|
Environment.HookGetFile = GetFileForGOS;
|
|
Environment.HookDoesFileExist = FindFileForGOS;
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Set up the path stack within the content
|
|
//-----------------------------------------
|
|
//
|
|
stackSize = 128;
|
|
filePathStack = new char*[stackSize];
|
|
Check_Pointer(filePathStack);
|
|
stackIndex = 1;
|
|
filePathStack[0] = "";
|
|
filePathStack[1] = "Content\\";
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Tool::~Tool()
|
|
{
|
|
Verify(stackIndex == 1);
|
|
Check_Pointer(filePathStack);
|
|
delete[] filePathStack;
|
|
|
|
Verify(Tool::Instance == this);
|
|
Tool::Instance = NULL;
|
|
Environment.HookDoesFileExist = NULL;
|
|
Environment.HookGetFile = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::TestInstance()
|
|
{
|
|
Verify(stackIndex >= 0 && stackIndex < stackSize);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::PushFilePath(Stuff::NotationFile *file)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(file);
|
|
|
|
char *dir = strdup(file->GetFileName());
|
|
Check_Pointer(dir);
|
|
char *p = __mbsrchr(dir, '\\');
|
|
if (p)
|
|
*++p = '\0';
|
|
else
|
|
*dir = '\0';
|
|
|
|
//
|
|
//---------------------------------
|
|
// Add the directory onto the stack
|
|
//---------------------------------
|
|
//
|
|
Check_Pointer(filePathStack);
|
|
if (++stackIndex == stackSize)
|
|
{
|
|
STOP(("Out of stack not handled"));
|
|
}
|
|
filePathStack[stackIndex] = dir;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::PushFilePath(Stuff::FileStream *file)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(file);
|
|
|
|
char *dir = strdup(file->GetFileName());
|
|
Check_Pointer(dir);
|
|
char *p = __mbsrchr(dir, '\\');
|
|
if (p)
|
|
*++p = '\0';
|
|
else
|
|
*dir = '\0';
|
|
|
|
//
|
|
//---------------------------------
|
|
// Add the directory onto the stack
|
|
//---------------------------------
|
|
//
|
|
Check_Pointer(filePathStack);
|
|
if (++stackIndex == stackSize)
|
|
{
|
|
STOP(("Out of stack not handled"));
|
|
}
|
|
filePathStack[stackIndex] = dir;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::PopFilePath()
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(filePathStack);
|
|
Verify(stackIndex > 0);
|
|
char *dir = filePathStack[stackIndex--];
|
|
Check_Pointer(dir);
|
|
free(dir);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void __stdcall
|
|
Tool::GetFileForGOS(
|
|
const char* file_name,
|
|
BYTE** memory,
|
|
DWORD* size
|
|
)
|
|
{
|
|
Check_Pointer(file_name);
|
|
Tool *tool = Tool::Instance;
|
|
Check_Object(tool);
|
|
#ifdef LAB_ONLY
|
|
strcpy(MWGameInfo::g_LastFileOpenRequest, "Tool::GetFileForGOS: ");
|
|
strcpy(MWGameInfo::g_LastFileOpenRequest + 22, file_name);
|
|
#endif
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// If this is a rom file, find it in the resources and return the pointer
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
if (!strncmp(file_name, "ROM\\", 4))
|
|
{
|
|
Resource texture(file_name+4);
|
|
texture.LoadData();
|
|
*memory = static_cast<BYTE*>(texture.GetPointer());
|
|
*size = texture.GetSize();
|
|
texture.AbandonData();
|
|
return;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// Only do the search if we don't start with content
|
|
//--------------------------------------------------
|
|
//
|
|
SPEW(("sagem", "file=%s", file_name));
|
|
if (_strnicmp(file_name, "content\\", 8))
|
|
{
|
|
Check_Pointer(tool->filePathStack);
|
|
Verify((unsigned)tool->stackIndex < (unsigned)tool->stackSize);
|
|
Check_Pointer(tool->filePathStack[tool->stackIndex]);
|
|
Str_Copy(
|
|
FileStream::RedirectedName,
|
|
tool->filePathStack[tool->stackIndex],
|
|
sizeof(FileStream::RedirectedName)
|
|
);
|
|
Verify(
|
|
*FileStream::RedirectedName == '\0'
|
|
|| FileStream::RedirectedName[strlen(FileStream::RedirectedName)-1] == '\\'
|
|
);
|
|
|
|
#ifdef LAB_ONLY
|
|
strcat(MWGameInfo::g_LastFileOpenRequest, " --Redirected-> ");
|
|
strcat(MWGameInfo::g_LastFileOpenRequest + 15, FileStream::RedirectedName);
|
|
#endif
|
|
//
|
|
//-----------------------------------------------------
|
|
// for each directory in the path, try to find the file
|
|
//-----------------------------------------------------
|
|
//
|
|
while (true)
|
|
{
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Find the separator character, and append the file name to the path
|
|
//-------------------------------------------------------------------
|
|
//
|
|
char *p = __mbsrchr((char*)FileStream::RedirectedName, '\\');
|
|
if (p)
|
|
Str_Copy(
|
|
p+1,
|
|
file_name,
|
|
sizeof(FileStream::RedirectedName) - (p - FileStream::RedirectedName) - 1
|
|
);
|
|
else
|
|
Str_Copy(
|
|
FileStream::RedirectedName,
|
|
file_name,
|
|
sizeof(FileStream::RedirectedName)
|
|
);
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// If the file exists, go ahead and open it
|
|
//-----------------------------------------
|
|
//
|
|
if (gos_DoesFileExist(FileStream::RedirectedName))
|
|
{
|
|
FileStream::IsRedirected=true;
|
|
gos_PushCurrentHeap(FileStream::s_Heap);
|
|
gos_GetFile(FileStream::RedirectedName, memory, size);
|
|
gos_PopCurrentHeap();
|
|
return;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Since it doesn't exist, we need to clip off the last directory and
|
|
// try again. If there was no separator, no file will be found
|
|
//-------------------------------------------------------------------
|
|
//
|
|
if (p)
|
|
*p = '\0';
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
FileStream::IsRedirected = false;
|
|
gos_PushCurrentHeap(FileStream::s_Heap);
|
|
gos_GetFile(file_name, memory, size);
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool __stdcall
|
|
Tool::FindFileForGOS(const char* file_name)
|
|
{
|
|
Check_Pointer(file_name);
|
|
Tool *tool = Tool::Instance;
|
|
Check_Object(tool);
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// Only do the search if we don't start with content
|
|
//--------------------------------------------------
|
|
//
|
|
if (_strnicmp(file_name, "content\\", 8))
|
|
{
|
|
Check_Pointer(tool->filePathStack);
|
|
Verify((unsigned)tool->stackIndex < (unsigned)tool->stackSize);
|
|
Check_Pointer(tool->filePathStack[tool->stackIndex]);
|
|
Str_Copy(
|
|
FileStream::RedirectedName,
|
|
tool->filePathStack[tool->stackIndex],
|
|
sizeof(FileStream::RedirectedName)
|
|
);
|
|
|
|
//
|
|
//-----------------------------------------------------
|
|
// for each directory in the path, try to find the file
|
|
//-----------------------------------------------------
|
|
//
|
|
while (true)
|
|
{
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Find the separator character, and append the file name to the path
|
|
//-------------------------------------------------------------------
|
|
//
|
|
char *p = __mbsrchr((char*)FileStream::RedirectedName, '\\');
|
|
if (p)
|
|
Str_Copy(
|
|
p+1,
|
|
file_name,
|
|
sizeof(FileStream::RedirectedName) - (p - FileStream::RedirectedName) - 1
|
|
);
|
|
else
|
|
Str_Copy(
|
|
FileStream::RedirectedName,
|
|
file_name,
|
|
sizeof(FileStream::RedirectedName)
|
|
);
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// If the file exists, go ahead and open it
|
|
//-----------------------------------------
|
|
//
|
|
if (gos_DoesFileExist(FileStream::RedirectedName))
|
|
{
|
|
FileStream::IsRedirected = true;
|
|
return true;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Since it doesn't exist, we need to clip off the last directory and
|
|
// try again. If there was no separator, no file will be found
|
|
//-------------------------------------------------------------------
|
|
//
|
|
if (p)
|
|
*p = '\0';
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
FileStream::IsRedirected = false;
|
|
return gos_DoesFileExist(file_name);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
const char*
|
|
Tool::GetToolFileName(const char* file_name)
|
|
{
|
|
Check_Pointer(file_name);
|
|
|
|
const char* result = strstr(file_name, "Content\\");
|
|
if (!result)
|
|
{
|
|
result = strstr(file_name, "content\\");
|
|
if (!result)
|
|
return file_name;
|
|
}
|
|
Check_Pointer(result);
|
|
return result+8;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Entity::ClassData*
|
|
Tool::ConstructGameModel(
|
|
MemoryStream *model_stream,
|
|
const char *model_class,
|
|
NotationFile *model_file
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(model_stream);
|
|
Check_Pointer(model_class);
|
|
Check_Object(model_file);
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//-----------------------------------
|
|
// Find the class data for this model
|
|
//-----------------------------------
|
|
//
|
|
RegisteredClass::ClassData *class_data;
|
|
Entity::ClassData *entity_class_data;
|
|
class_data = Entity::FindClassData(model_class);
|
|
Check_Object(class_data);
|
|
entity_class_data = Cast_Pointer(Entity::ClassData*, class_data);
|
|
Check_Object(entity_class_data);
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Create the game model parameters and call the creation method
|
|
//--------------------------------------------------------------
|
|
//
|
|
Entity::GameModel::Script
|
|
script(
|
|
model_stream,
|
|
model_file,
|
|
entity_class_data
|
|
);
|
|
Entity::GameModel::Factory game_model_factory =
|
|
entity_class_data->modelFactory;
|
|
Check_Pointer(game_model_factory);
|
|
(*game_model_factory)(&script);
|
|
Verify(stack_index == stackIndex);
|
|
return entity_class_data;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
ResourceID
|
|
Tool::MakeNewGameModel(
|
|
const char *model_name,
|
|
const char *model_class
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(model_name);
|
|
Check_Pointer(model_class);
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Create the New Model Resource. If it is already there return the ID
|
|
//---------------------------------------------------------------------
|
|
//
|
|
MString game_model_name = model_name;
|
|
game_model_name += "{GameModel}";
|
|
Resource model_resource(game_model_name);
|
|
if (model_resource.DoesResourceExist() && model_resource.IsResourceUpToDate())
|
|
{
|
|
Check_Object(&model_resource);
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// In order to deal with partial builds we have to give our parent
|
|
// our file dependencies
|
|
//----------------------------------------------------------------
|
|
//
|
|
if (Resource::ParentFileDependencies)
|
|
model_resource.AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
return model_resource.GetResourceID();
|
|
}
|
|
|
|
//
|
|
//-----------------------------------
|
|
// Find the class data for this model
|
|
//-----------------------------------
|
|
//
|
|
RegisteredClass::ClassData *class_data;
|
|
Entity::ClassData *entity_class_data;
|
|
class_data = Entity::FindClassData(model_class);
|
|
Check_Object(class_data);
|
|
entity_class_data = Cast_Pointer(Entity::ClassData*, class_data);
|
|
Check_Object(entity_class_data);
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Create the game model parameters and call the creation method
|
|
//--------------------------------------------------------------
|
|
//
|
|
DynamicMemoryStream model_stream;
|
|
|
|
Entity::GameModel::Script
|
|
script(
|
|
&model_stream,
|
|
NULL,
|
|
entity_class_data
|
|
);
|
|
|
|
Entity::GameModel::Factory game_model_factory =
|
|
entity_class_data->modelFactory;
|
|
Check_Pointer(game_model_factory);
|
|
(*game_model_factory)(&script);
|
|
|
|
//
|
|
//----------------------------------
|
|
//Save the GameModel Resource Stream
|
|
//----------------------------------
|
|
//
|
|
Check_Object(entity_class_data);
|
|
model_resource.Save(&model_stream, NULL);
|
|
STOP(("Not updated"));
|
|
Check_Object(&model_resource);
|
|
|
|
return model_resource.GetResourceID();
|
|
}
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Entity::ClassData*
|
|
Tool::ConstructDataList(
|
|
Resource *resource,
|
|
const char* model_name
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(resource);
|
|
Check_Pointer(model_name);
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//---------------------------------------------------------------------------------------
|
|
// First open this up as a filestream to get a clue on the name - no need to expand it if
|
|
// it already exists
|
|
//---------------------------------------------------------------------------------------
|
|
//
|
|
if (!gos_DoesFileExist(model_name))
|
|
STOP(("%s can't be found!"));
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// See if the data file can be found in the resources
|
|
//---------------------------------------------------
|
|
//
|
|
if (FileStream::IsRedirected)
|
|
{
|
|
model_name = FileStream::RedirectedName;
|
|
FileStream::IsRedirected = false;
|
|
}
|
|
Check_Pointer(model_name);
|
|
MString model_file_name = model_name;
|
|
resource->FindName(model_file_name);
|
|
if (resource->DoesResourceExist() && resource->IsResourceUpToDate())
|
|
{
|
|
Check_Object(resource);
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// In order to deal with partial builds we have to give our parent
|
|
// our file dependencies
|
|
//----------------------------------------------------------------
|
|
//
|
|
if (Resource::ParentFileDependencies && !resource->IsRegistered())
|
|
resource->AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
|
|
//
|
|
//-----------------------------------------------
|
|
// Figure out the class data object and return it
|
|
//-----------------------------------------------
|
|
//
|
|
RegisteredClass::ClassID class_id =
|
|
Entity::GetClassIDFromDataListID(resource->GetResourceID());
|
|
Entity::ClassData *class_data =
|
|
Cast_Pointer(
|
|
Entity::ClassData*,
|
|
RegisteredClass::FindClassData(class_id)
|
|
);
|
|
Check_Object(class_data);
|
|
Verify(stack_index == stackIndex);
|
|
return class_data;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// We are building this model, so set the file path to the model file,
|
|
// then setup our initial dependencies to match the model file
|
|
//--------------------------------------------------------------------
|
|
//
|
|
NotationFile model_file(model_file_name);
|
|
PushFilePath(&model_file);
|
|
FileDependencies *parent_dependencies = Resource::ParentFileDependencies;
|
|
FileDependencies data_dependencies(*model_file.GetFileDependencies());
|
|
|
|
//
|
|
//--------------------
|
|
// Find the class name
|
|
//--------------------
|
|
//
|
|
const char *model_class;
|
|
Page *page = model_file.GetPage("GameData");
|
|
Check_Object(page);
|
|
page->GetEntry("Class", &model_class, true);
|
|
|
|
//
|
|
//--------------------------------------------
|
|
// Create the memory stream for the game model
|
|
//--------------------------------------------
|
|
//
|
|
FileDependencies model_dependencies(*model_file.GetFileDependencies());
|
|
Resource::ParentFileDependencies = &model_dependencies;
|
|
MString game_model_name = model_file_name;
|
|
game_model_name += "{GameModel}";
|
|
Resource model_resource(game_model_name);
|
|
DynamicMemoryStream model_stream;
|
|
Entity::ClassData *entity_class_data =
|
|
ConstructGameModel(
|
|
&model_stream,
|
|
model_class,
|
|
&model_file
|
|
);
|
|
Check_Object(entity_class_data);
|
|
model_resource.Save(&model_stream, &model_dependencies);
|
|
Check_Object(&model_resource);
|
|
if (!model_resource.IsRegistered())
|
|
data_dependencies.AddDependencies(&model_dependencies);
|
|
|
|
//
|
|
//------------------------------------------------------
|
|
// Create a memory stream to hold data list resource IDs
|
|
//------------------------------------------------------
|
|
//
|
|
Check_Object(RendererManager::Instance);
|
|
int model_list_size = RendererManager::Instance->GetModelListSize();
|
|
Verify(model_list_size >= 1);
|
|
DynamicArrayOf<ResourceID> resource_ids(ResourceID::Null, model_list_size);
|
|
resource_ids[RendererManager::ReservedForGameModelRendererType] =
|
|
model_resource.GetResourceID();
|
|
int i;
|
|
for(i=(RendererManager::ReservedForGameModelRendererType + 1); i<model_list_size; i++)
|
|
resource_ids[i] = ResourceID::Null;
|
|
|
|
//
|
|
//---------------------------------------------------------
|
|
// Call the platform tool, and let it add the renderer data
|
|
//---------------------------------------------------------
|
|
//
|
|
Page *renderer_page = model_file.FindPage("Renderers");
|
|
if (renderer_page)
|
|
{
|
|
Page::NoteIterator *renderers = renderer_page->MakeNoteIterator();
|
|
Check_Object(renderers);
|
|
Note *renderer;
|
|
while ((renderer = renderers->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(renderer);
|
|
const char *renderer_name = renderer->GetName();
|
|
Check_Pointer(renderer_name);
|
|
Check_Object(RendererManager::Instance);
|
|
int renderer_type =
|
|
RendererManager::Instance->FindRendererType(renderer_name);
|
|
Verify(renderer_type > RendererManager::ReservedForGameModelRendererType);
|
|
Verify(renderer_type < model_list_size);
|
|
resource_ids[renderer_type] = ResourceID(resource->GetResourceID().m_fileID, 0);
|
|
NotationFile renderer_file;
|
|
renderer->GetEntry(&renderer_file);
|
|
FileDependencies renderer_dependencies(*renderer_file.GetFileDependencies());
|
|
Resource::ParentFileDependencies = &renderer_dependencies;
|
|
CreateRendererData(
|
|
&resource_ids[renderer_type],
|
|
entity_class_data,
|
|
&renderer_file,
|
|
renderer_type
|
|
);
|
|
data_dependencies.AddDependencies(&renderer_dependencies);
|
|
}
|
|
Check_Object(renderers);
|
|
delete renderers;
|
|
}
|
|
|
|
//
|
|
//-----------------------
|
|
// Save out the data list
|
|
//-----------------------
|
|
//
|
|
MemoryStream res_id_stream(resource_ids.GetData(), resource_ids.GetSize());
|
|
resource->Save(&res_id_stream, &data_dependencies);
|
|
Resource::ParentFileDependencies = parent_dependencies;
|
|
if (parent_dependencies && !resource->IsRegistered())
|
|
parent_dependencies->AddDependencies(&data_dependencies);
|
|
|
|
//
|
|
//---------
|
|
// Clean up
|
|
//---------
|
|
//
|
|
PopFilePath();
|
|
Verify(stack_index == stackIndex);
|
|
return entity_class_data;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Entity::CreateMessage*
|
|
Tool::ConstructCreateMessage(
|
|
Stuff::MemoryStream *message_stream,
|
|
Page *page,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message_stream);
|
|
Check_Object(page);
|
|
Check_Object(base_id);
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Remember where the id started so we can compute the span of id's used
|
|
// in this message
|
|
//----------------------------------------------------------------------
|
|
//
|
|
ReplicatorID original_id = *base_id;
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Locate the model file entry and make sure it is already in resources
|
|
//---------------------------------------------------------------------
|
|
//
|
|
const char* model_name;
|
|
page->GetEntry("Model", &model_name, true);
|
|
Entity::CreateMessage::Script script;
|
|
script.classData = ConstructDataList(&script.modelResource, model_name);
|
|
Check_Object(script.classData);
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Now that we have the data object for the model type, call the
|
|
// appropriate make message factory
|
|
//--------------------------------------------------------------
|
|
//
|
|
script.messageStream = message_stream;
|
|
script.instancePage = page;
|
|
script.baseID = base_id;
|
|
Entity::CreateMessage::Factory factory =
|
|
(Entity::CreateMessage::Factory)script.classData->messageFactory;
|
|
Check_Pointer(factory);
|
|
(*factory)(&script);
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Get the message, and set the span on the replicant ID to match the
|
|
// number of ids used by this and its children
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Entity::CreateMessage *message =
|
|
Cast_Pointer(
|
|
Entity::CreateMessage*,
|
|
message_stream->GetPointer()
|
|
);
|
|
Check_Object(message);
|
|
message->replicatorID.localID =
|
|
static_cast<WORD>(script.baseID->localID - original_id.localID);
|
|
Verify(stack_index == stackIndex);
|
|
return message;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::ConstructCreateMessage(
|
|
Resource *resource,
|
|
NotationFile *instance_file,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(resource);
|
|
Check_Object(instance_file);
|
|
Check_Object(base_id);
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//---------------------------------------------------------
|
|
// Open up the instance file and push the path on the stack
|
|
//---------------------------------------------------------
|
|
//
|
|
const char* instance_file_name = instance_file->GetFileName();
|
|
PushFilePath(instance_file);
|
|
|
|
//
|
|
//----------------------------------------
|
|
// See if the resource needs to be rebuilt
|
|
//----------------------------------------
|
|
//
|
|
resource->FindName(instance_file_name);
|
|
if (resource->DoesResourceExist() && resource->IsResourceUpToDate())
|
|
{
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// We need to bump the replicator ID, so cast the resource as a create
|
|
// message and apply the bump number to the base id
|
|
//--------------------------------------------------------------------
|
|
//
|
|
resource->LoadData();
|
|
Entity::CreateMessage *message =
|
|
Cast_Pointer(
|
|
Entity::CreateMessage*,
|
|
resource->GetPointer()
|
|
);
|
|
Check_Object(message);
|
|
*base_id += message->replicatorID.localID;
|
|
PopFilePath();
|
|
Verify(stack_index == stackIndex);
|
|
if (Resource::ParentFileDependencies && !resource->IsRegistered())
|
|
resource->AddFileDependenciesTo(Resource::ParentFileDependencies);
|
|
return;
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// For instances, assume the first page is our instance, so take whatever
|
|
// name it has
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
FileDependencies instance_dep(*instance_file->GetFileDependencies());
|
|
FileDependencies *parent = Resource::ParentFileDependencies;
|
|
Resource::ParentFileDependencies = &instance_dep;
|
|
NotationFile::PageIterator *instance_pages = instance_file->MakePageIterator();
|
|
Check_Object(instance_pages);
|
|
Page *instance = instance_pages->GetCurrent();
|
|
if (!instance)
|
|
STOP(("Error: %s has no instance pages!", instance_file->GetFileName()));
|
|
Check_Object(instance);
|
|
|
|
//
|
|
//------------------------------
|
|
// Put the message into a stream
|
|
//------------------------------
|
|
//
|
|
DynamicMemoryStream instance_stream;
|
|
ConstructCreateMessage(
|
|
&instance_stream,
|
|
instance,
|
|
base_id
|
|
);
|
|
resource->Save(&instance_stream, &instance_dep);
|
|
if (parent && !resource->IsRegistered())
|
|
parent->AddDependencies(&instance_dep);
|
|
Resource::ParentFileDependencies = parent;
|
|
|
|
//
|
|
//-------------
|
|
// Now clean up
|
|
//-------------
|
|
//
|
|
PopFilePath();
|
|
Check_Object(instance_pages);
|
|
delete instance_pages;
|
|
Verify(stack_index == stackIndex);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Entity::CreateMessage*
|
|
Tool::ConstructCreateMessage(
|
|
Stuff::MemoryStream *message_stream,
|
|
NotationFile *instance_file,
|
|
ReplicatorID *base_id
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(message_stream);
|
|
Check_Pointer(instance_file);
|
|
Check_Object(base_id);
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//---------------------------------------------------------
|
|
// Open up the instance file and push the path on the stack
|
|
//---------------------------------------------------------
|
|
//
|
|
PushFilePath(instance_file);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// For instances, assume the first page is our instance, so take whatever
|
|
// name it has
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
NotationFile::PageIterator *instance_pages = instance_file->MakePageIterator();
|
|
Check_Object(instance_pages);
|
|
Page *instance = instance_pages->GetCurrent();
|
|
Check_Object(instance);
|
|
|
|
//
|
|
//------------------------------
|
|
// Put the message into a stream
|
|
//------------------------------
|
|
//
|
|
Entity::CreateMessage *message =
|
|
ConstructCreateMessage(
|
|
message_stream,
|
|
instance,
|
|
base_id
|
|
);
|
|
|
|
//
|
|
//-------------
|
|
// Now clean up
|
|
//-------------
|
|
//
|
|
PopFilePath();
|
|
Check_Object(instance_pages);
|
|
delete instance_pages;
|
|
Verify(stack_index == stackIndex);
|
|
return message;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::BuildResources(
|
|
Stuff::NotationFile *build_file,
|
|
DWORD content_version,
|
|
Stuff::FileDependencies *dependencies,
|
|
short level,
|
|
__int64 parent_build_age
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(build_file);
|
|
Verify(Application::BuildOK);
|
|
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Create the resource directories (if they don't exist) and bump the
|
|
// file ID
|
|
//-------------------------------------------------------------------
|
|
//
|
|
if (level++ == -1)
|
|
{
|
|
if (!gos_DoesFileExist("Resource"))
|
|
gos_CreateDirectory("Resource");
|
|
FileStream::IsRedirected = false;
|
|
if (!gos_DoesFileExist("Resource\\Maps"))
|
|
gos_CreateDirectory("Resource\\Maps");
|
|
FileStream::IsRedirected = false;
|
|
if (!gos_DoesFileExist("Resource\\Missions"))
|
|
gos_CreateDirectory("Resource\\Missions");
|
|
FileStream::IsRedirected = false;
|
|
if (!gos_DoesFileExist("Resource\\Variants"))
|
|
gos_CreateDirectory("Resource\\Variants");
|
|
FileStream::IsRedirected = false;
|
|
PushFilePath(build_file);
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Spin through all the entries in the file
|
|
//-----------------------------------------
|
|
//
|
|
Page *null_page = build_file->FindPage("");
|
|
if (null_page)
|
|
{
|
|
Check_Object(null_page);
|
|
Page::NoteIterator *file_entries = null_page->MakeNoteIterator();
|
|
Check_Object(file_entries);
|
|
Note *file_entry;
|
|
while ((file_entry = file_entries->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file_entry);
|
|
|
|
//
|
|
//-------------------------------
|
|
// Open up the next file to parse
|
|
//-------------------------------
|
|
//
|
|
const char* parse_filename = file_entry->GetName();
|
|
Check_Pointer(parse_filename);
|
|
NotationFile parse_file(parse_filename, NotationFile::NonEmpty);
|
|
parse_filename = parse_file.GetFileName();
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// Figure out how old it is and push it on the path stack
|
|
//-------------------------------------------------------
|
|
//
|
|
__int64 build_age = gos_FileTimeStamp(parse_filename);
|
|
if (build_age < parent_build_age)
|
|
build_age = parent_build_age;
|
|
PushFilePath(&parse_file);
|
|
|
|
//
|
|
//------------------------------------------------------------
|
|
// Each page name will be the name of a resource file to build
|
|
//------------------------------------------------------------
|
|
//
|
|
NotationFile::PageIterator *resource_file_pages =
|
|
parse_file.MakePageIterator();
|
|
Check_Object(resource_file_pages);
|
|
Page *resource_file_entry = resource_file_pages->ReadAndNext();
|
|
Verify(!resource_file_pages->ReadAndNext());
|
|
Check_Object(resource_file_entry);
|
|
const char* resource_file_name = resource_file_entry->GetName();
|
|
|
|
//
|
|
//--------------------------------------------------------------------
|
|
// Delete the file if it is older than the build file, then open it up
|
|
//--------------------------------------------------------------------
|
|
//
|
|
__int64 res_file_age = 0;
|
|
if (gos_DoesFileExist(resource_file_name))
|
|
res_file_age = gos_FileTimeStamp(resource_file_name);
|
|
bool dirty = res_file_age < build_age;
|
|
FileStream::IsRedirected = false;
|
|
|
|
MString dep_filename = resource_file_name;
|
|
char *p = strrchr(dep_filename, '.');
|
|
if (p)
|
|
strcpy(p+1, "dep");
|
|
if (!gos_DoesFileExist(dep_filename))
|
|
dirty = true;
|
|
FileStream::IsRedirected = false;
|
|
|
|
ResourceFile *res_file =
|
|
ResourceManager::Instance->OpenResourceFile(
|
|
resource_file_name,
|
|
dep_filename,
|
|
level,
|
|
content_version,
|
|
true,
|
|
dirty
|
|
);
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// If we have dependencies, write them into resource zero
|
|
//-------------------------------------------------------
|
|
//
|
|
{
|
|
Resource build_dependencies(resource_file_name);
|
|
if (!build_dependencies.DoesResourceExist())
|
|
{
|
|
unsigned length = dependencies->m_fileNameStream.GetBytesUsed();
|
|
if (length>0)
|
|
{
|
|
MemoryStream chain(
|
|
static_cast<BYTE*>(dependencies->m_fileNameStream.GetPointer()) - length,
|
|
length,
|
|
length
|
|
);
|
|
build_dependencies.Save(&chain, dependencies);
|
|
}
|
|
else
|
|
{
|
|
MemoryStream chain("", 1, 1);
|
|
build_dependencies.Save(&chain, NULL);
|
|
}
|
|
}
|
|
Verify(build_dependencies.GetResourceID().GetRecordID() == ResourceID::BuildDependenciesRecordID);
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// Remember the state of the effect library prior to our build file
|
|
// so we can restore to it after our children are created
|
|
//-----------------------------------------------------------------
|
|
//
|
|
Check_Object(gosFX::EffectLibrary::Instance);
|
|
unsigned old_effect_count = gosFX::EffectLibrary::Instance->GetLength();
|
|
FileDependencies old_deps = gosFX::EffectLibrary::Instance->m_fileDependencies;
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Parse the build file and save it out
|
|
//-------------------------------------
|
|
//
|
|
bool core = ParseBuildFile(res_file, resource_file_entry);
|
|
Check_Object(resource_file_pages);
|
|
delete resource_file_pages;
|
|
res_file->Save();
|
|
res_file->UnloadRecordData();
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// If this is core, ignore the dependencies
|
|
//-----------------------------------------
|
|
//
|
|
if (core)
|
|
{
|
|
NotationFile children;
|
|
file_entry->GetEntry(&children);
|
|
BuildResources(
|
|
&children,
|
|
content_version,
|
|
dependencies,
|
|
level,
|
|
build_age
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
//--------------------------
|
|
// Otherwise, write them out
|
|
//--------------------------
|
|
//
|
|
else
|
|
{
|
|
Check_Object(dependencies);
|
|
FileDependencies deps(*dependencies);
|
|
deps.AddDependency(resource_file_name);
|
|
NotationFile children;
|
|
file_entry->GetEntry(&children);
|
|
BuildResources(
|
|
&children,
|
|
content_version,
|
|
&deps,
|
|
level,
|
|
build_age
|
|
);
|
|
}
|
|
delete res_file;
|
|
|
|
Check_Object(gosFX::EffectLibrary::Instance);
|
|
gosFX::EffectLibrary::Instance->SetLength(old_effect_count);
|
|
gosFX::EffectLibrary::Instance->m_fileDependencies = old_deps;
|
|
|
|
PopFilePath();
|
|
}
|
|
Check_Object(file_entries);
|
|
delete file_entries;
|
|
}
|
|
|
|
if (!level)
|
|
{
|
|
Check_Object(FileStreamManager::Instance);
|
|
FileStreamManager::Instance->PurgeFileCompareCache();
|
|
PopFilePath();
|
|
}
|
|
Verify(stack_index == stackIndex);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Tool::ParseBuildFile(
|
|
ResourceFile *res_file,
|
|
Stuff::Page *resource_file_entry
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(res_file);
|
|
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// Look for the effects entry. If one is there, build it
|
|
//-------------------------------------------------------
|
|
//
|
|
ResourceID last_id(res_file->GetFileID(),-1);
|
|
ResourceID res_id(res_file);
|
|
ChainOf<Note*>* effects = resource_file_entry->MakeNoteChain("effects");
|
|
if (!effects->IsEmpty())
|
|
{
|
|
Resource resource("{effects}");
|
|
if (!resource.DoesResourceExist())
|
|
resource.Save(NULL, NULL);
|
|
last_id = resource.GetResourceID();
|
|
}
|
|
|
|
//
|
|
//-----------------------------------------------------------------
|
|
// Make a list of all the entries within the page, and spin through
|
|
// them, constructing a single empty resource for each one
|
|
//-----------------------------------------------------------------
|
|
//
|
|
Page::NoteIterator *file_entries = resource_file_entry->MakeNoteIterator();
|
|
Check_Object(file_entries);
|
|
Note *file_entry;
|
|
while ((file_entry = file_entries->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file_entry);
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// Look at the type of entry to see what we should do
|
|
//---------------------------------------------------
|
|
//
|
|
const char* entry_type = file_entry->GetName();
|
|
Check_Pointer(entry_type);
|
|
const char* entry_filename = NULL;
|
|
file_entry->GetEntry(&entry_filename);
|
|
if (!entry_filename)
|
|
STOP((
|
|
"%s: [%s]%s is a bad entry!",
|
|
resource_file_entry->GetNotationFile()->GetFileName(),
|
|
resource_file_entry->GetName(),
|
|
entry_type
|
|
));
|
|
Check_Pointer(entry_filename);
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// If we are an instance, go ahead and build the make message into
|
|
// the resources
|
|
//----------------------------------------------------------------
|
|
//
|
|
if (IsRegisterable(entry_type))
|
|
{
|
|
Resource data_resource(entry_filename);
|
|
if (!data_resource.DoesResourceExist())
|
|
data_resource.Save(NULL, NULL);
|
|
if (last_id.GetRecordID() < 65535)
|
|
{
|
|
if (data_resource.GetResourceID().GetFileID() != last_id.GetFileID())
|
|
{
|
|
PAUSE((
|
|
"Error: Registered resource %s already appears in resource file %d",
|
|
data_resource.GetName(),
|
|
data_resource.GetResourceID().GetFileID()
|
|
));
|
|
}
|
|
else
|
|
Verify(data_resource.GetResourceID().GetRecordID() == last_id.GetRecordID()+1);
|
|
}
|
|
last_id = data_resource.GetResourceID();
|
|
}
|
|
}
|
|
res_file->SetLastRegisteredResourceID(last_id);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// Store each individual effect library in the resource file, concatenate
|
|
// them into the main library, and keep track of all effect libraries
|
|
// created
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Check_Object(gosFX::EffectLibrary::Instance);
|
|
DynamicArrayOf<ResourceID> effect_IDs(effects->GetSize());
|
|
unsigned i=0;
|
|
Check_Object(gosFX::EffectLibrary::Instance);
|
|
ChainIteratorOf<Note*> effect_iterator(effects);
|
|
while ((file_entry = effect_iterator.ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file_entry);
|
|
const char* effects_filename;
|
|
file_entry->GetEntry(&effects_filename);
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// Open up the effect file and gets its real filename
|
|
//---------------------------------------------------
|
|
//
|
|
FileStream stream(effects_filename);
|
|
effects_filename = stream.GetFileName();
|
|
Resource resource(effects_filename);
|
|
|
|
//
|
|
//--------------------------------------------------
|
|
// If the resource needs to be refreshed, refresh it
|
|
//--------------------------------------------------
|
|
//
|
|
if (!resource.DoesResourceExist() || !resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies effects_dependencies;
|
|
effects_dependencies.AddDependency(&stream);
|
|
resource.Save(&stream, &effects_dependencies);
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------
|
|
// Load the effects library and remember its ID
|
|
//---------------------------------------------
|
|
//
|
|
Verify(resource.DoesResourceExist());
|
|
gosFX::EffectLibrary::Instance->m_fileDependencies.AddDependency(effects_filename);
|
|
resource.LoadData();
|
|
gosFX::EffectLibrary::Instance->Load(&resource);
|
|
effect_IDs[i++] = resource.GetResourceID();
|
|
}
|
|
delete effects;
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// If we actually had effect libraries, save the list out to the resource
|
|
// file now
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
if (i>0)
|
|
{
|
|
Resource resource("{effects}");
|
|
if (!resource.DoesResourceExist())
|
|
{
|
|
MemoryStream stream(
|
|
&effect_IDs[0],
|
|
effect_IDs.GetSize(),
|
|
effect_IDs.GetSize()
|
|
);
|
|
resource.Save(&stream, &gosFX::EffectLibrary::Instance->m_fileDependencies);
|
|
}
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Look for the texture pool entry. We build the textures here so that
|
|
// the texture name lookups happen as quickly as possible
|
|
//---------------------------------------------------------------------
|
|
//
|
|
NotationFile audio_hint;
|
|
if (resource_file_entry->GetEntry("soundpool", &audio_hint))
|
|
AudioSample::BuildSoundPool(&audio_hint);
|
|
|
|
//
|
|
//--------------------------------
|
|
// Build each resource in the file
|
|
//--------------------------------
|
|
//
|
|
file_entries->First();
|
|
while ((file_entry = file_entries->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(file_entry);
|
|
const char* entry_type = file_entry->GetName();
|
|
Check_Pointer(entry_type);
|
|
const char* entry_filename = NULL;
|
|
file_entry->GetEntry(&entry_filename);
|
|
Check_Pointer(entry_filename);
|
|
BuildResource(entry_type, entry_filename);
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------------------------
|
|
// Look for the texture pool entry. We build the textures here so that
|
|
// the texture name lookups happen as quickly as possible
|
|
//---------------------------------------------------------------------
|
|
//
|
|
NotationFile hint_file;
|
|
if (resource_file_entry->GetEntry("texturepool", &hint_file))
|
|
ResourceImagePool::BuildTexturePool(&hint_file);
|
|
|
|
//
|
|
//---------
|
|
// Clean up
|
|
//---------
|
|
//
|
|
bool core=false;
|
|
resource_file_entry->GetEntry("Core", &core);
|
|
Check_Object(file_entries);
|
|
delete file_entries;
|
|
res_file->Save();
|
|
Verify(stack_index == stackIndex);
|
|
return core;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
Tool::IsRegisterable(const char* entry_type)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(entry_type);
|
|
|
|
return !_stricmp(entry_type, "instance") ||
|
|
!_stricmp(entry_type, "data") ||
|
|
!_stricmp(entry_type, "file") ||
|
|
!_stricmp(entry_type, "notation");
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::BuildResource(
|
|
const char* entry_type,
|
|
const char* entry_filename
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(entry_type);
|
|
Check_Pointer(entry_filename);
|
|
|
|
#if defined(_ARMOR)
|
|
int stack_index = stackIndex;
|
|
#endif
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// If we are an instance, go ahead and build the make message into
|
|
// the resources
|
|
//----------------------------------------------------------------
|
|
//
|
|
if (!_stricmp(entry_type, "instance"))
|
|
{
|
|
NotationFile instance_file(entry_filename, NotationFile::NonEmpty);
|
|
Resource instance_resource;
|
|
ReplicatorID base_id = ReplicatorID::Null;
|
|
ConstructCreateMessage(
|
|
&instance_resource,
|
|
&instance_file,
|
|
&base_id
|
|
);
|
|
}
|
|
|
|
//
|
|
//--------------------------------------
|
|
// If we are a data list, construct that
|
|
//--------------------------------------
|
|
//
|
|
else if (!_stricmp(entry_type, "data"))
|
|
{
|
|
Resource data_resource;
|
|
ConstructDataList(&data_resource, entry_filename);
|
|
}
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Put a notation file in the resources
|
|
//-------------------------------------
|
|
//
|
|
else if (!_stricmp(entry_type, "notation"))
|
|
{
|
|
NotationFile notation_file(entry_filename, NotationFile::NonEmpty);
|
|
const char* file_name = notation_file.GetFileName();
|
|
Check_Pointer(file_name);
|
|
Resource resource(file_name);
|
|
if (!resource.DoesResourceExist() || !resource.IsResourceUpToDate())
|
|
{
|
|
DynamicMemoryStream stream;
|
|
notation_file.Write(&stream);
|
|
resource.Save(&stream, notation_file.GetFileDependencies());
|
|
}
|
|
}
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Put a general file in the resources
|
|
//-------------------------------------
|
|
//
|
|
else if (!_stricmp(entry_type, "file"))
|
|
{
|
|
FileStream file(entry_filename);
|
|
const char* file_name = file.GetFileName();
|
|
Check_Pointer(file_name);
|
|
Resource resource(file_name);
|
|
if (!resource.DoesResourceExist() || !resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies file_dep;
|
|
file_dep.AddDependency(&file);
|
|
resource.Save(&file, &file_dep);
|
|
}
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------
|
|
// Put a whole directory of general files in the resources
|
|
//--------------------------------------------------------
|
|
//
|
|
else if (!_stricmp(entry_type, "directory"))
|
|
{
|
|
MString path = entry_filename;
|
|
path += '\\';
|
|
Directory directory(path + "*.*");
|
|
const char *file_name;
|
|
while ((file_name = directory.GetCurrentFileName()) != NULL)
|
|
{
|
|
FileStream file(path+file_name);
|
|
file_name = file.GetFileName();
|
|
Check_Pointer(file_name);
|
|
Resource resource(file_name);
|
|
if (!resource.DoesResourceExist() || !resource.IsResourceUpToDate())
|
|
{
|
|
FileDependencies file_dep;
|
|
file_dep.AddDependency(&file);
|
|
resource.Save(&file, &file_dep);
|
|
}
|
|
directory.AdvanceCurrentFile();
|
|
}
|
|
}
|
|
|
|
Verify(stack_index == stackIndex);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
Tool::CreateRendererData(
|
|
ResourceID *stream_resource,
|
|
Entity::ClassData *class_data,
|
|
NotationFile *renderer_file,
|
|
int renderer_type
|
|
)
|
|
{
|
|
Check_Object(stream_resource);
|
|
Check_Pointer(class_data);
|
|
Check_Object(renderer_file);
|
|
|
|
PushFilePath(renderer_file);
|
|
switch (renderer_type)
|
|
{
|
|
case RendererManager::VideoRendererType:
|
|
VideoRenderer::CreateRendererData(
|
|
stream_resource,
|
|
class_data,
|
|
renderer_file
|
|
);
|
|
break;
|
|
case RendererManager::AudioRendererType:
|
|
AudioRenderer::CreateRendererData(
|
|
stream_resource,
|
|
class_data,
|
|
renderer_file
|
|
);
|
|
break;
|
|
default:
|
|
STOP(("Unknown renderer type!"));
|
|
}
|
|
PopFilePath();
|
|
}
|