This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/EditorAssetMgr.cpp

666 lines
17 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : LevelEdit *
* *
* $Archive:: /Commando/Code/Tools/LevelEdit/EditorAssetMgr.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/29/02 3:16p $*
* *
* $Revision:: 29 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "editorassetmgr.h"
#include "texture.h"
#include "proto.h"
#include "editorini.h"
#include "ffactory.h"
#include "ww3d.h"
#include "utils.h"
#include "filemgr.h"
#include "rawfile.h"
#include "rcfile.h"
#include "filelocations.h"
#include "editorbuild.h"
#include "assetdatabase.h"
////////////////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////////////////
DynamicVectorClass<StringClass> EditorFileFactoryClass::SearchPathList;
////////////////////////////////////////////////////////////////////////
//
// EditorAssetMgrClass
//
////////////////////////////////////////////////////////////////////////
EditorAssetMgrClass::EditorAssetMgrClass (void)
{
Set_Activate_Fog_On_Load (true);
m_CurrentDir = ::Get_Startup_Directory ();
return ;
}
////////////////////////////////////////////////////////////////////////
//
// Reload_File
//
void
EditorAssetMgrClass::Reload_File (const char *filename)
{
// Param OK?
ASSERT (filename != NULL);
if (filename != NULL) {
CString extension = ::strrchr (filename, '.');
// Is this a W3D file?
if (extension.CompareNoCase (".W3D") == 0) {
CString asset_name = ::Asset_Name_From_Filename (filename);
Remove_Prototype (asset_name);
Load_3D_Assets (filename);
}
}
return ;
}
////////////////////////////////////////////////////////////////////////
//
// Is_File_Here
//
////////////////////////////////////////////////////////////////////////
bool
EditorAssetMgrClass::Is_File_Here (LPCTSTR full_path, bool get_from_vss)
{
//
// Output this file lookup to the message window
//
CString message;
message.Format ("Attempting to load: %s\r\n", full_path);
::Output_Message (message);
//
// Check to see if the file exists in this location
//
return ::Get_File_Mgr ()->Does_File_Exist (full_path, get_from_vss);
}
////////////////////////////////////////////////////////////////////////
//
// Determine_Real_Location
//
////////////////////////////////////////////////////////////////////////
bool
EditorAssetMgrClass::Determine_Real_Location
(
LPCTSTR path,
CString & real_location
)
{
bool retval = false;
TCHAR full_path[MAX_PATH];
//
// Did the caller supply a path?
//
if (Is_Full_Path (path)) {
::lstrcpy (full_path, path);
} else {
//
// Make a full path out of the filename
//
CString test_path = Make_Path (m_CurrentDir, path);
//
// If the file doesn't exist here, then try the search paths
//
if (::GetFileAttributes (test_path) == 0xFFFFFFFF) {
//
// Try to find the file in our search path list
//
DynamicVectorClass<StringClass> &path_list = EditorFileFactoryClass::Get_Search_Path ();
for (int index = 0; index < path_list.Count (); index ++) {
//
// Does the file exist in this directoy?
//
StringClass full_path = Make_Path (path_list[index], path);
if (::GetFileAttributes (full_path) != 0xFFFFFFFF) {
test_path = full_path;
break;
}
}
}
::lstrcpy (full_path, test_path);
}
//
// Find out if the file lives in the directory
//
if (Is_File_Here (full_path, true) == false) {
//
// Hmmm... not here, try up a directory level
//
CString parent_dir = ::Up_One_Directory (::Strip_Filename_From_Path (full_path));
CString filename = ::Get_Filename_From_Path (full_path);
parent_dir = ::Make_Path (parent_dir, filename);
//
// Does the file live in the parent directory?
//
if (Is_File_Here (parent_dir, true) == false) {
//
// Is this a texture file?
//
if (Is_Texture_Filename (full_path)) {
#ifndef PUBLIC_EDITOR_VER
//
// Does the file live in the global texture directory?
//
CString texture_path = ::Make_Path (GLOBAL_TEXTURE_PATH, filename);
if (Is_File_Here (texture_path, false)) {
real_location = texture_path;
retval = true;
}
#endif //!PUBLIC_EDITOR_VER
} else if (::strnicmp ("h_a_", filename, 4) == 0) {
//
// We are 'assuming' this is a human animation file, so
// try to find it in the human animation directory.
//
CString anim_path = ::Make_Path (CHAR_ANIMS_PATH, filename);
if (Is_File_Here (anim_path, true)) {
real_location = anim_path;
retval = true;
}
}
} else {
real_location = parent_dir;
retval = true;
}
} else {
real_location = full_path;
retval = true;
}
#ifdef PUBLIC_EDITOR_VER
//
// If the file does not exist locally, then use the one from the mix file
//
if (retval == false && ::Get_File_Mgr ()->Is_File_In_VSS (full_path)) {
real_location = full_path;
retval = true;
}
#endif //PUBLIC_EDITOR_VER
return retval;
}
////////////////////////////////////////////////////////////////////////
//
// Create_Render_Obj
//
RenderObjClass *
EditorAssetMgrClass::Create_Render_Obj (const char * name)
{
// Let windows do some processing
::Pump_Messages ();
// Assume failure
RenderObjClass *prenderobj = NULL;
// Try to find a prototype
PrototypeClass * proto = Find_Prototype(name);
if (WW3D_Load_On_Demand && proto == NULL) { // If we didn't find one, try to load on demand
char filename[ MAX_PATH ];
sprintf( filename, "%s.W3D", name);
char *mesh_name = ::strchr (name, '.');
if (mesh_name != NULL) {
::lstrcpyn (filename, name, ((int)mesh_name) - ((int)name) + 1);
::lstrcat (filename, ".W3D");
} else {
sprintf( filename, "%s.W3D", name);
}
// See if we can determine where this file exists
CString real_location;
if (Determine_Real_Location (filename, real_location)) {
::lstrcpy (filename, real_location);
} else {
TRACE ("Asset file not found!\n");
}
// Load the assets from this file into the manager
Load_3D_Assets (filename);
// Attempt to find the prototype loader now.
proto = Find_Prototype (name);
}
// If we found a prototype for this object, then
// use it to create a new instance of the requested asset.
if (proto != NULL) {
prenderobj = proto->Create ();
}
// Return a pointer to the render object
return prenderobj;
}
////////////////////////////////////////////////////////////////////////
//
// Get_HAnim
//
HAnimClass *
EditorAssetMgrClass::Get_HAnim (const char * name)
{
// Let windows do some processing
::Pump_Messages ();
// Try to find the animation
HAnimClass *panim = HAnimManager.Get_Anim(name);
if (WW3D_Load_On_Demand && panim == NULL) { // If we didn't find it, try to load on demand
char filename[ MAX_PATH ];
char *animname = strchr( name, '.');
if (animname != NULL) {
sprintf( filename, "%s.W3D", animname+1);
} else {
TRACE ("Animation has no . in the name\n");
return NULL;
}
// See if we can determine where this file exists
CString real_location;
if (Determine_Real_Location (filename, real_location)) {
::lstrcpy (filename, real_location);
} else {
TRACE ("Asset file not found!\n");
}
// Load the assets from this file into the manager
Load_3D_Assets (filename);
// Attempt to find the prototype loader now.
panim = HAnimManager.Get_Anim(name);
}
// Return a pointer to the animation
return panim;
}
////////////////////////////////////////////////////////////////////////
//
// Get_HTree
//
HTreeClass *
EditorAssetMgrClass::Get_HTree (const char * name)
{
// Let windows do some processing
::Pump_Messages ();
// Try to find the htree
HTreeClass *phtree = HTreeManager.Get_Tree(name);
if (WW3D_Load_On_Demand && phtree == NULL) { // If we didn't find it, try to load on demand
char filename[ MAX_PATH ];
sprintf( filename, "%s.W3D", name);
// See if we can determine where this file exists
CString real_location;
if (Determine_Real_Location (filename, real_location)) {
::lstrcpy (filename, real_location);
} else {
TRACE ("Asset file not found!\n");
}
// Load the assets from this file into the manager
Load_3D_Assets (filename);
// Attempt to find the object loader now.
phtree = HTreeManager.Get_Tree(name);
}
// Return a pointer to the animation
return phtree;
}
////////////////////////////////////////////////////////////////////////
//
// Get_INI
//
EditorINIClass *
EditorAssetMgrClass::Get_INI (const char *filename)
{
EditorINIClass *pini = NULL;
FileClass * pini_file = _TheFileFactory->Get_File (filename);
if (pini_file) {
pini = new EditorINIClass (*pini_file);
_TheFileFactory->Return_File (pini_file);
}
// Return a pointer to the INI file class
return pini;
}
////////////////////////////////////////////////////////////////////////
//
// Get_Texture
//
////////////////////////////////////////////////////////////////////////
TextureClass *
EditorAssetMgrClass::Get_Texture
(
const char * tga_filename,
TextureClass::MipCountType mip_level_count,
WW3DFormat texture_format,
bool allow_compression
)
{
//
// Let windows do some processing
//
::Pump_Messages ();
/*
** Bail if the user isn't really asking for anything
*/
if ((tga_filename == NULL) || (strlen(tga_filename) == 0)) {
return NULL;
}
//
// Determine what the texture's "name" should be
//
CString texture_name;
if (::strstr (tga_filename, "+\\") != NULL) {
texture_name = ::Get_Subdir_And_Filename_From_Path (tga_filename);
} else {
texture_name = ::Get_Filename_From_Path (tga_filename);
}
texture_name.MakeLower ();
/*
** See if the texture has already been loaded.
*/
TextureClass* tex = TextureHash.Get ((const char *)texture_name);
if (tex && texture_format!=WW3D_FORMAT_UNKNOWN) {
WWASSERT_PRINT(tex->Get_Texture_Format()==texture_format,("Texture %s has already been loaded witt different format",(const char *)texture_name));
}
/*
** Didn't have it so we have to create a new texture
*/
if (!tex) {
//
// See if we can determine where this file exists
//
CString real_location;
if (Determine_Real_Location (tga_filename, real_location) == false) {
CString message;
message.Format ("Texture file not found: %s\r\n", (LPCTSTR)texture_name);
::Output_Message (message);
real_location = tga_filename;
}
/*
** Didn't have it so we have to create a new texture
*/
tex = NEW_REF(TextureClass,(texture_name, real_location, mip_level_count, texture_format, allow_compression));
TextureHash.Insert(tex->Get_Texture_Name(),tex);
}
tex->Add_Ref();
return tex;
}
////////////////////////////////////////////////////////////////////////
//
// Load_Resource_Texture
//
////////////////////////////////////////////////////////////////////////
void
EditorAssetMgrClass::Load_Resource_Texture (const char *filename)
{
CString texture_path = ::Get_File_Mgr ()->Get_Texture_Cache_Path ();
CString texture_filename = ::Make_Path (texture_path, filename);
//
// Open the resource texture and create the
// real file.
//
ResourceFileClass res_texture (NULL, filename);
RawFileClass texture_file (texture_filename);
if (texture_file.Create () == 1) {
texture_file.Open (FileClass::WRITE);
//
// Copy the contents of the resource (memory) texture
// to a file.
//
BYTE buffer[2048];
int size = res_texture.Size ();
int total_written = 0;
while (total_written < size) {
int bytes_read = res_texture.Read (buffer, sizeof (buffer));
int bytes_written = texture_file.Write (buffer, bytes_read);
total_written += bytes_written;
if (bytes_written == 0) {
break;
}
}
texture_file.Close ();
//
// Force the texture to be loaded into memory
//
TextureClass *texture = Get_Texture (texture_filename);
REF_PTR_RELEASE (texture);
}
return ;
}
////////////////////////////////////////////////////////////////////////
//
// Load_3D_Assets
//
////////////////////////////////////////////////////////////////////////
bool
EditorAssetMgrClass::Load_3D_Assets (const char *path)
{
bool retval = true;
//
// Check to see if the asset is already in the asset manager
//
CString filename = ::Get_Filename_From_Path (path);
CString asset_name = ::Asset_Name_From_Filename (filename);
PrototypeClass *prototype = Find_Prototype (asset_name);
//
// Load the asset fresh if necessary
//
if (prototype == NULL) {
CString full_path = ::Get_File_Mgr ()->Make_Full_Path (path);
retval = false;
#ifdef PUBLIC_EDITOR_VER
//
// If the file exists locally, or its coming from the mix file
// then load it.
//
if ( ::Get_File_Mgr ()->Does_File_Exist (full_path) ||
::Get_File_Mgr ()->Is_File_In_VSS (full_path))
{
retval = WW3DAssetManager::Load_3D_Assets (full_path);
}
#else
//
// If the file exists, then load it.
//
if (::Get_File_Mgr ()->Does_File_Exist (full_path, true)) {
retval = WW3DAssetManager::Load_3D_Assets (full_path);
}
#endif //PUBLIC_EDITOR_VER
}
return retval;
}
////////////////////////////////////////////////////////////////////////
//
// Get_File
//
////////////////////////////////////////////////////////////////////////
FileClass *
EditorFileFactoryClass::Get_File (char const *filename)
{
CString path;
//
// If the filename contains a relative path, then
// turn it into an absolute path.
//
if (::Is_Path (filename)) {
path = ::Get_File_Mgr ()->Make_Full_Path (filename);
} else {
//
// Make a full path out of the filename
//
const char *curr_dir = _pThe3DAssetManager->Get_Current_Directory ();
path = Make_Path (curr_dir, filename);
//
// If the file doesn't exist here, then try the search paths
//
if (::GetFileAttributes (path) == 0xFFFFFFFF) {
//
// Try to find the file in our search path list
//
for (int index = 0; index < SearchPathList.Count (); index ++) {
//
// Does the file exist in this directoy?
//
StringClass full_path = Make_Path (SearchPathList[index], filename);
if (::GetFileAttributes (full_path) != 0xFFFFFFFF) {
path = full_path;
break;
}
}
}
}
//
// Get the file from the database
//
return ::Get_File_Mgr ()->Get_Database_Interface ().Get_File (path);
}
////////////////////////////////////////////////////////////////////////
//
// Return_File
//
////////////////////////////////////////////////////////////////////////
void
EditorFileFactoryClass::Return_File (FileClass *file)
{
if (file != NULL) {
delete file;
}
return ;
}
////////////////////////////////////////////////////////////////////////
//
// Open_Texture_File_Cache
//
////////////////////////////////////////////////////////////////////////
void
EditorAssetMgrClass::Open_Texture_File_Cache (const char * /*prefix*/)
{
return ;
}
////////////////////////////////////////////////////////////////////////
//
// Close_Texture_File_Cache
//
////////////////////////////////////////////////////////////////////////
void
EditorAssetMgrClass::Close_Texture_File_Cache (void)
{
return ;
}