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/Preset.cpp

1389 lines
33 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/Preset.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/29/02 4:04p $*
* *
* $Revision:: 49 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "preset.h"
#include "presetgeneraltab.h"
#include "presetsettingstab.h"
#include "presetpropsheet.h"
#include "chunkio.h"
#include "persistfactory.h"
#include "editorchunkids.h"
#include "definition.h"
#include "definitionmgr.h"
#include "filemgr.h"
#include "parameter.h"
#include "terrainnode.h"
#include "terraindefinition.h"
#include "tilenode.h"
#include "objectnode.h"
#include "assetmgr.h"
#include "wwstring.h"
#include "combatchunkid.h"
#include "spawnernode.h"
#include "soundnode.h"
#include "vispointnode.h"
#include "presettransitiontab.h"
#include "vehicle.h"
#include "zonenode.h"
#include "damagezonenode.h"
#include "transitionnode.h"
#include "pathfindstartnode.h"
#include "dummyobjectnode.h"
#include "editoronlyobjectnode.h"
#include "presetmgr.h"
#include "lightnode.h"
#include "physobjedittab.h"
#include "definitionutils.h"
#include "waypathnode.h"
#include "utils.h"
#include "coverspotnode.h"
#include "presetdependencytab.h"
#include "presetzonetab.h"
#include "presetdialoguetab.h"
#include "buildingnode.h"
#include "nodescriptsproppage.h"
#include "nodemgr.h"
#include "sceneeditor.h"
#include "editorbuild.h"
///////////////////////////////////////////////////////////////////////
//
// Global persist factory for presets
//
///////////////////////////////////////////////////////////////////////
SimplePersistFactoryClass<PresetClass, CHUNKID_PRESET> _PresetPersistFactory;
//////////////////////////////////////////////////////////////////////////////////
// Constants
//////////////////////////////////////////////////////////////////////////////////
enum
{
CHUNKID_VARIABLES = 0x00000100,
CHUNKID_COMMENTS,
XXX_CHUNKID_NODES
};
enum
{
VARID_DEFINITIONID = 0x01,
VARID_ISTEMPORARY,
VARID_COMMENTS,
VARID_PARENTPTR,
VARID_THISPTR,
XXX_VARID_FILEDEPENDENCY,
VARID_PARENT_ID,
VARID_MANUALDEPENDENCY
};
///////////////////////////////////////////////////////////////////////
//
// PresetClass
//
///////////////////////////////////////////////////////////////////////
PresetClass::PresetClass (void)
: m_Definition (NULL),
m_DefinitionID (0),
m_Parent (NULL),
m_ParentID (0),
m_NextPreset (NULL),
m_PrevPreset (NULL),
m_IsTemporary (false),
m_IsValid (true)
{
return ;
}
///////////////////////////////////////////////////////////////////////
//
// ~PresetClass
//
///////////////////////////////////////////////////////////////////////
PresetClass::~PresetClass (void)
{
//
// Remove this preset from its parent (if possible or necessary)
//
PresetClass *parent = PresetMgrClass::Find_Preset (m_ParentID);
if (parent != NULL) {
parent->Remove_Child_Preset (m_DefinitionID);
}
//
// Unlink this definition from its preset (if possible or necessary)
//
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (m_DefinitionID, false);
if (definition != NULL && (definition->Get_User_Data () == (uint32)this)) {
definition->Set_User_Data (NULL);
}
Free_Node_List ();
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Show_Properties
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Show_Properties (bool read_only)
{
PresetGeneralTabClass general_tab (this);
PhysObjEditTabClass phys_model_tab;
PresetSettingsTabClass settings_tab (this);
PresetDependencyTabClass dependencies_tab (this);
PresetTransitionTabClass transition_tab (this);
PresetZoneTabClass zone_tab (this);
PresetDialogueTabClass dialogue_tab (this);
NodeScriptsPropPage scripts_tab;
//
// Add the general page first
//
PresetPropSheetClass prop_sheet;
prop_sheet.Set_Preset (this);
prop_sheet.Add_Page (&general_tab);
//
// Should we add a physics-definition page?
//
ModelDefParameterClass *phys_def_param = Get_Phys_Def_Param ();
if (phys_def_param != NULL) {
phys_model_tab.Set_PhysDef_Param (phys_def_param);
phys_model_tab.Set_Filter (phys_def_param->Get_Base_Class ());
phys_model_tab.Set_Is_Temp (m_IsTemporary);
phys_model_tab.Set_Definition_ID (phys_def_param->Get_Value ());
prop_sheet.Add_Page (&phys_model_tab);
}
//
// Add the settings and file dependencies page
//
prop_sheet.Add_Page (&settings_tab);
prop_sheet.Add_Page (&dependencies_tab);
//
// Should we add a scripts page?
//
ScriptListParameterClass *script_list_param = Get_Script_List_Param ();
if (script_list_param != NULL) {
scripts_tab.Set_Script_List_Parameter (script_list_param);
prop_sheet.Add_Page (&scripts_tab);
}
//
// Add a dialogue tab to the property sheet if this preset represents a human.
//
if (Is_Soldier_Preset ()) {
prop_sheet.Add_Page (&dialogue_tab);
}
//
// Should we add a transition-list page?
//
TRANSITION_DATA_LIST *transition_list = Get_Transition_List ();
if (transition_list != NULL && read_only == false) {
transition_tab.Set_Transition_List (transition_list);
prop_sheet.Add_Page (&transition_tab);
}
//
// Should we add a zone-list page?
//
ZONE_PARAM_LIST zone_list;
Build_Zone_List (m_Definition, zone_list);
if (zone_list.Count () > 0 && read_only == false) {
zone_tab.Set_Zone_Param_List (&zone_list);
prop_sheet.Add_Page (&zone_tab);
}
//
// Make sure things are read-only if needs be
//
prop_sheet.Set_Read_Only (read_only);
general_tab.Set_Read_Only (read_only);
settings_tab.Set_Read_Only (read_only);
dependencies_tab.Set_Read_Only (read_only);
phys_model_tab.Set_Read_Only (read_only);
dialogue_tab.Set_Read_Only (read_only);
//
// Show the property sheet
//
UINT ret_code = prop_sheet.DoModal ();
// Return true if the user clicked OK
return (ret_code == IDOK);
}
///////////////////////////////////////////////////////////////////////
//
// Get_Factory
//
///////////////////////////////////////////////////////////////////////
const PersistFactoryClass &
PresetClass::Get_Factory (void) const
{
return _PresetPersistFactory;
}
///////////////////////////////////////////////////////////////////////
//
// Save
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Save (ChunkSaveClass &csave)
{
bool retval = true;
//
// Save the comments to their own chunk
//
WRITE_WWSTRING_CHUNK (csave, CHUNKID_COMMENTS, m_Comments);
//
// Save the other variables to a micro chunk
//
csave.Begin_Chunk (CHUNKID_VARIABLES);
retval &= Save_Variables (csave);
csave.End_Chunk ();
return retval;
}
///////////////////////////////////////////////////////////////////////
//
// Save_Variables
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Save_Variables (ChunkSaveClass &csave)
{
bool retval = true;
//
// Write the ID of the definition to the chunk
//
ASSERT (m_Definition != NULL);
if (m_Definition != NULL) {
m_DefinitionID = m_Definition->Get_ID ();
WRITE_MICRO_CHUNK (csave, VARID_DEFINITIONID, m_DefinitionID);
}
WRITE_MICRO_CHUNK (csave, VARID_ISTEMPORARY, m_IsTemporary);
//
// Write the file dependencies to their own micro-chunks
//
for (int index = 0; index < m_ManualDependencies.Count (); index ++) {
StringClass filename = (LPCTSTR)m_ManualDependencies[index];
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_MANUALDEPENDENCY, filename);
}
//
// For pointer remapping
//
PresetClass *this_ptr = this;
WRITE_MICRO_CHUNK (csave, VARID_THISPTR, this_ptr);
if (m_Parent != NULL) {
m_ParentID = m_Parent->Get_ID ();
WRITE_MICRO_CHUNK (csave, VARID_PARENT_ID, m_ParentID);
}
return retval;
}
///////////////////////////////////////////////////////////////////////
//
// Load
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Load (ChunkLoadClass &cload)
{
bool retval = true;
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ())
{
READ_WWSTRING_CHUNK (cload, CHUNKID_COMMENTS, m_Comments);
case CHUNKID_VARIABLES:
retval &= Load_Variables (cload);
break;
}
cload.Close_Chunk ();
}
SaveLoadSystemClass::Register_Post_Load_Callback (this);
return retval;
}
///////////////////////////////////////////////////////////////////////
//
// Load_Variables
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Load_Variables (ChunkLoadClass &cload)
{
m_DefinitionID = 0;
PresetClass *old_this_ptr = NULL;
m_ManualDependencies.Delete_All ();
//
// Loop through all the microchunks that define the variables
//
while (cload.Open_Micro_Chunk ()) {
switch (cload.Cur_Micro_Chunk_ID ()) {
READ_MICRO_CHUNK (cload, VARID_DEFINITIONID, m_DefinitionID)
READ_MICRO_CHUNK (cload, VARID_ISTEMPORARY, m_IsTemporary)
READ_MICRO_CHUNK_WWSTRING (cload, VARID_COMMENTS, m_Comments);
READ_MICRO_CHUNK (cload, VARID_PARENTPTR, m_Parent)
READ_MICRO_CHUNK (cload, VARID_THISPTR, old_this_ptr)
READ_MICRO_CHUNK (cload, VARID_PARENT_ID, m_ParentID);
case VARID_MANUALDEPENDENCY:
{
StringClass filename;
cload.Read(filename.Get_Buffer(cload.Cur_Micro_Chunk_Length()),cload.Cur_Micro_Chunk_Length());
m_ManualDependencies.Add ((LPCTSTR)filename);
}
break;
}
cload.Close_Micro_Chunk ();
}
//
// Check for a recursive linkage (could happen with temp presets if the
// user deletes his registry)...
//
if (m_ParentID == Get_ID ()) {
m_IsValid = false;
}
//
// Handle pointer remapping. LEGACY CODE -- IS NOW OBSOLETE.
//
WWASSERT (old_this_ptr != NULL);
SaveLoadSystemClass::Register_Pointer (old_this_ptr, this);
if (m_Parent != NULL) {
REQUEST_POINTER_REMAP ((void **)&m_Parent);
}
//
// Lookup the definition pointer from the definition id
//
WWASSERT (m_DefinitionID != 0);
m_Definition = DefinitionMgrClass::Find_Definition (m_DefinitionID, false);
//
// Associate this preset with the definition
//
if (m_Definition != NULL) {
m_Definition->Set_User_Data ((uint32)this);
}
if (m_DefinitionID == 0 || m_Definition == NULL) {
int test = 0;
}
return true;
}
///////////////////////////////////////////////////////////////////////
//
// On_Post_Load
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::On_Post_Load (void)
{
PersistClass::On_Post_Load ();
//
// Lookup the parent based on its ID (instead of its pointer)
//
if (m_ParentID != 0) {
m_Parent = PresetMgrClass::Find_Preset (m_ParentID);
ASSERT (m_Parent != NULL);
//
// Add ourselves as a child of our parent
//
if (m_Parent != NULL) {
m_Parent->Add_Child_Preset (Get_ID ());
}
#ifdef _DEBUG
if (m_Parent == this || m_ParentID == Get_ID ()) {
CString message;
message.Format ("Preset %s is recursively linked to itself.\r\n", Get_Name ());
::Output_Message (message);
}
#endif // _DEBUG
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Create
//
///////////////////////////////////////////////////////////////////////
NodeClass *
PresetClass::Create (void)
{
NodeClass *node = NULL;
StringClass error_message;
if (m_Definition != NULL && m_Definition->Is_Valid_Config (error_message)) {
uint32 class_id = m_Definition->Get_Class_ID ();
switch (::SuperClassID_From_ClassID (class_id))
{
case CLASSID_TERRAIN:
node = new TerrainNodeClass (this);
break;
case CLASSID_TILE:
node = new TileNodeClass (this);
break;
case CLASSID_BUILDINGS:
node = new BuildingNodeClass (this);
break;
case CLASSID_GAME_OBJECTS:
if (class_id == CLASSID_SPAWNER_DEF) {
node = new SpawnerNodeClass (this);
} else if (class_id == CLASSID_GAME_OBJECT_DEF_BUILDING) {
node = new BuildingNodeClass (this);
} else if (class_id == CLASSID_GAME_OBJECT_DEF_SCRIPT_ZONE) {
node = new ZoneNodeClass (this);
} else if (class_id == CLASSID_GAME_OBJECT_DEF_DAMAGE_ZONE) {
node = new DamageZoneNodeClass (this);
} else if (class_id == CLASSID_GAME_OBJECT_DEF_TRANSITION) {
node = new TransitionNodeClass (this);
} else if (class_id == CLASSID_GAME_OBJECT_DEF_C4) {
::AfxGetMainWnd ()->MessageBox ("You cannot place C4 objects in the editor.", "Non-Placeable Object", MB_ICONEXCLAMATION | MB_OK);
} else {
node = new ObjectNodeClass (this);
}
break;
case CLASSID_LIGHT:
node = new LightNodeClass (this);
break;
case CLASSID_SOUND:
node = new SoundNodeClass (this);
break;
case CLASSID_WAYPATH:
node = new WaypathNodeClass (this);
break;
case CLASSID_DUMMY_OBJECTS:
node = new DummyObjectNodeClass (this);
break;
default:
if (class_id == CLASSID_VIS_POINT_DEF) {
node = new VisPointNodeClass (this);
} else if (class_id == CLASSID_PATHFIND_START_DEF) {
node = new PathfindStartNodeClass (this);
} else if (class_id == CLASSID_COVERSPOT) {
node = new CoverSpotNodeClass (this);
} else if (class_id == CLASSID_EDITOR_ONLY_OBJECTS) {
node = new EditorOnlyObjectNodeClass (this);
}
break;
}
} else if (m_Definition != NULL) {
//
// Warn the user
//
StringClass msg ("Unable to instantiate preset!\nReason: preset not configured correctly.\n\n");
msg += error_message;
::AfxGetMainWnd ()->MessageBox (msg, "Preset Error", MB_ICONEXCLAMATION | MB_OK);
}
return node;
}
///////////////////////////////////////////////////////////////////////
//
// Copy_Properties
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Copy_Properties (const PresetClass &preset)
{
DefinitionClass *src_def = preset.Get_Definition ();
if ((m_Definition != NULL) && (src_def != NULL)) {
//
// Simply copy the parameters from one definition to the other...
//
::Copy_Definition (src_def, m_Definition, m_IsTemporary);
//
// Copy the transitions as well
//
const TRANSITION_DATA_LIST *src_list = preset.Get_Transition_List ();
TRANSITION_DATA_LIST *dest_list = Get_Transition_List ();
if (src_list != NULL && dest_list != NULL) {
//
// Free any existing transitions
//
for (int index = 0; index < dest_list->Count (); index ++) {
TransitionDataClass *data = (*dest_list)[index];
SAFE_DELETE (data);
}
dest_list->Delete_All ();
//
// Now copy each of the transitions from the source list
//
for (index = 0; index < src_list->Count (); index ++) {
const TransitionDataClass *data = (*src_list)[index];
//
// Create a new transition object and copy the src's settings
//
TransitionDataClass *new_data = new TransitionDataClass;
new_data->Set_Type (data->Get_Type ());
new_data->Set_Zone (data->Get_Zone ());
new_data->Set_Animation_Name (data->Get_Animation_Name ());
new_data->Set_Ending_TM (data->Get_Ending_TM ());
//
// Add this new transition to our list
//
dest_list->Add (new_data);
}
}
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Load_All_Assets
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Load_All_Assets (void)
{
STRING_LIST dependencies;
Get_All_Dependencies (dependencies);
for (int index = 0; index < dependencies.Count (); index ++) {
CString filename = dependencies[index];
CString full_path = ::Get_File_Mgr ()->Make_Full_Path (filename);
CString path = ::Strip_Filename_From_Path (full_path);
//
// Load all the assets contained in this file
//
::Set_Current_Directory (path);
if (::Is_W3D_Filename (filename)) {
WW3DAssetManager::Get_Instance ()->Load_3D_Assets (full_path);
RenderObjClass *model = ::Create_Render_Obj (::Asset_Name_From_Filename (full_path));
REF_PTR_RELEASE (model);
} else {
#ifndef PUBLIC_EDITOR_VER
if (::GetFileAttributes (full_path) == 0xFFFFFFFF) {
::Get_File_Mgr ()->Update_File (full_path);
}
#endif //!PUBLIC_EDITOR_VER
}
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Get_All_Dependencies
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Get_All_Dependencies (STRING_LIST &list) const
{
//
// Start fresh
//
list.Delete_All ();
//
// Copy the manual dependencies to the list
//
list = m_ManualDependencies;
//
// Add the implicit dependencies to the list
//
Add_Definition_Dependencies (m_Definition, list);
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Get_Implicit_Dependencies
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Get_Implicit_Dependencies (STRING_LIST &list) const
{
//
// Start fresh
//
list.Delete_All ();
//
// Add the implicit dependencies to the list
//
Add_Definition_Dependencies (m_Definition, list);
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Add_Definition_Dependencies
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Add_Definition_Dependencies (DefinitionClass *definition, STRING_LIST &list)
{
if (definition != NULL) {
//
// Find all 'filename' parameters to this definition.
//
int count = definition->Get_Parameter_Count ();
for (int index = 0; index < count; index ++) {
ParameterClass *parameter = definition->Lock_Parameter (index);
if ( parameter->Get_Type () == ParameterClass::TYPE_FILENAME ||
parameter->Get_Type () == ParameterClass::TYPE_SOUND_FILENAME) {
//
// Add this filename dependency to the list
//
CString filename = ((FilenameParameterClass *)parameter)->Get_String ();
CString full_path = ::Get_File_Mgr ()->Make_Full_Path (filename);
if ( ::Get_File_Mgr ()->Is_Path_Valid (full_path) &&
::Get_File_Mgr ()->Is_Empty_Path (full_path) == false)
{
list.Add (::Get_File_Mgr ()->Make_Relative_Path (full_path));
}
} else if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
//
// If this is param references a physics-definition, then add all its dependencies as well..
//
DefinitionClass *phys_def = NULL;
phys_def = DefinitionMgrClass::Find_Definition (((ModelDefParameterClass *)parameter)->Get_Value (), false);
Add_Definition_Dependencies (phys_def, list);
}
}
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Get_Script_List_Param
//
///////////////////////////////////////////////////////////////////////
ScriptListParameterClass *
PresetClass::Get_Script_List_Param (void)
{
ScriptListParameterClass *param = NULL;
//
// Try to find a script list parameter somewhere in the preset...
//
int index = m_Definition->Get_Parameter_Count ();
while ((index --) && (param == NULL)) {
ParameterClass *parameter = m_Definition->Lock_Parameter (index);
//
// Is this the parameter we are looking for?
//
if (parameter->Get_Type () == ParameterClass::TYPE_SCRIPTLIST) {
param = (ScriptListParameterClass *)parameter;
}
m_Definition->Unlock_Parameter (index);
}
return param;
}
///////////////////////////////////////////////////////////////////////
//
// Get_Phys_Def_Param
//
///////////////////////////////////////////////////////////////////////
ModelDefParameterClass *
PresetClass::Get_Phys_Def_Param (void)
{
ModelDefParameterClass *param = NULL;
//
// Try to find a physics-def parameter somewhere in the preset...
//
int index = m_Definition->Get_Parameter_Count ();
while ((index --) && (param == NULL)) {
ParameterClass *parameter = m_Definition->Lock_Parameter (index);
//
// Is this the parameter we are looking for?
//
if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
param = (ModelDefParameterClass *)parameter;
}
m_Definition->Unlock_Parameter (index);
}
return param;
}
///////////////////////////////////////////////////////////////////////
//
// Get_Transition_List
//
///////////////////////////////////////////////////////////////////////
TRANSITION_DATA_LIST *
PresetClass::Get_Transition_List (void) const
{
TRANSITION_DATA_LIST *list = NULL;
if (m_Definition != NULL) {
switch (m_Definition->Get_Class_ID ()) {
//
// Vehicles from Combat Lib
//
case CLASSID_GAME_OBJECT_DEF_VEHICLE:
{
VehicleGameObjDef *vehicle_def = (VehicleGameObjDef *)m_Definition;
list = vehicle_def->Get_Transition_List ();
}
break;
case CLASSID_GAME_OBJECT_DEF_TRANSITION:
{
TransitionGameObjDef *trans_def = (TransitionGameObjDef *)m_Definition;
list = trans_def->Get_Transition_List ();
}
break;
}
}
return list;
}
///////////////////////////////////////////////////////////////////////
//
// Build_Zone_List
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Build_Zone_List (DefinitionClass *definition, ZONE_PARAM_LIST &zone_list) const
{
if (definition == NULL) {
definition = m_Definition;
}
if (definition != NULL) {
//
// Loop over all the parameters
//
int count = definition->Get_Parameter_Count ();
for (int index = 0; index < count; index ++) {
ParameterClass *parameter = definition->Lock_Parameter (index);
//
// If this is a zone parameter, then add it to the list
//
if (parameter->Get_Type () == ParameterClass::TYPE_ZONE) {
ZoneParameterClass *zone_param = (ZoneParameterClass *)parameter;
zone_list.Add (zone_param);
} else if (parameter->Get_Type () == ParameterClass::TYPE_MODELDEFINITIONID) {
//
// Recurse into the physics definition (if necessary)
//
int def_id = ((ModelDefParameterClass *)parameter)->Get_Value ();
DefinitionClass *model_def= DefinitionMgrClass::Find_Definition (def_id, false);
if (model_def != NULL) {
Build_Zone_List (model_def, zone_list);
}
}
definition->Unlock_Parameter (index);
}
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Add_Files_To_VSS
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Add_Files_To_VSS (void)
{
if (::Get_File_Mgr ()->Is_VSS_Read_Only () == false) {
HWND hdlg = Show_VSS_Update_Dialog (::AfxGetMainWnd ()->m_hWnd);
//
// Build a list of dependencies
//
STRING_LIST dependencies;
Get_All_Dependencies (dependencies);
//
// Loop over all the files and add them to VSS
//
for (int index = 0; index < dependencies.Count (); index ++) {
CString filename = dependencies[index];
CString full_path = ::Get_File_Mgr ()->Make_Full_Path (filename);
::Get_File_Mgr ()->Add_Files_To_Database (full_path);
}
::Kill_VSS_Update_Dialog (hdlg);
}
return ;
}
///////////////////////////////////////////////////////////////////////
//
// Is_Valid_Sound_Preset
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Is_Valid_Sound_Preset (void)
{
bool retval = false;
//
// First off, is this a sound preset at all?
//
if ( m_Definition != NULL &&
m_Definition->Get_Class_ID () == CLASSID_SOUND)
{
AudibleSoundDefinitionClass *definition = (AudibleSoundDefinitionClass *)m_Definition;
//
// Does this preset point to a file?
//
CString filename = definition->Get_Filename ();
DWORD file_attrs = ::GetFileAttributes (definition->Get_Filename ());
if ( filename.GetLength () > 0 &&
(file_attrs == 0xFFFFFFFF ||
file_attrs != FILE_ATTRIBUTE_DIRECTORY))
{
retval = true;
}
}
return retval;
}
///////////////////////////////////////////////////////////////////////
//
// Is_A_Parent
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Is_A_Parent (PresetClass *preset)
{
bool retval = false;
//
// Look over all the parents
//
for ( PresetClass *parent = this;
parent != NULL && !retval;
parent = parent->Get_Parent ())
{
retval = (parent == preset);
}
return retval;
}
///////////////////////////////////////////////////////////////////////
//
// Is_A_Parent
//
///////////////////////////////////////////////////////////////////////
bool
PresetClass::Is_A_Parent (LPCTSTR parent_name)
{
bool retval = false;
//
// Look over all the parents
//
for ( PresetClass *parent = this;
parent != NULL && !retval;
parent = parent->Get_Parent ())
{
retval = (::lstrcmpi (parent->Get_Name (), parent_name) == 0);
}
return retval;
}
///////////////////////////////////////////////////////////////////////
//
// Get_Icon_Index
//
///////////////////////////////////////////////////////////////////////
int
PresetClass::Get_Icon_Index (void) const
{
int index = 0;
//
// What type is it?
//
uint32 class_id = m_Definition->Get_Class_ID ();
switch (::SuperClassID_From_ClassID (class_id))
{
case CLASSID_TERRAIN:
index = TERRAIN_ICON;
break;
case CLASSID_TILE:
index = TILE_ICON;
break;
case CLASSID_MUNITIONS:
case CLASSID_DUMMY_OBJECTS:
case CLASSID_GAME_OBJECTS:
index = OBJECT_ICON;
break;
case CLASSID_LIGHT:
index = LIGHT_ICON;
break;
case CLASSID_SOUND:
index = SOUND_ICON;
break;
case CLASSID_WAYPATH:
index = WAYPATH_ICON;
break;
case CLASSID_ZONE:
index = ZONE_ICON;
break;
case CLASSID_TRANSITION:
index = TRANSITION_ICON;
break;
case CLASSID_BUILDINGS:
index = BUILDING_ICON;
break;
case CLASSID_TWIDDLERS:
index = RAND_ICON;
break;
default:
if (class_id == CLASSID_VIS_POINT_DEF) {
index = VIS_ICON;
} else if (class_id == CLASSID_PATHFIND_START_DEF) {
index = PATHFIND_ICON;
} else if (class_id == CLASSID_COVERSPOT) {
index = OBJECT_ICON;
}
break;
}
return index;
}
///////////////////////////////////////////////////////////////////////
//
// Collect_Definitions
//
///////////////////////////////////////////////////////////////////////
void
PresetClass::Collect_Definitions (DEFINITION_LIST &list)
{
if (m_Definition != NULL) {
list.Add (m_Definition);
//
// Get the physics definition that this definition embeds (if any)
//
::Build_Embedded_Definition_List (list, m_Definition);
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Is_Soldier_Preset
//
////////////////////////////////////////////////////////////////////
bool
PresetClass::Is_Soldier_Preset (void)
{
bool is_soldier = false;
if (m_Definition != NULL) {
is_soldier = (m_Definition->Get_Class_ID () == CLASSID_GAME_OBJECT_DEF_SOLDIER);
}
return is_soldier;
}
////////////////////////////////////////////////////////////////////
//
// Build_Node_List
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Build_Node_List (NodeClass *parent_node)
{
Free_Node_List ();
//
// Build a matrix that we can use to transform each
// node into the coordinate system of the parent node
//
Matrix3D parent_tm = parent_node->Get_Transform ();
Matrix3D world_to_parent_tm;
parent_tm.Get_Orthogonal_Inverse (world_to_parent_tm);
//
// Loop over all the nodes in the scene
//
for ( NodeClass *node = NodeMgrClass::Get_First ();
node != NULL;
node = NodeMgrClass::Get_Next (node))
{
//
// Is this a node we want to bind to this preset?
//
if ( node != parent_node &&
node->Is_Proxied () == false &&
node->Get_Parent_Node () == NULL &&
node->Get_Type () != NODE_TYPE_WAYPOINT)
{
//
// Make a copy of the node
//
NodeClass *new_node = node->Clone ();
if (new_node != NULL) {
//
// Transform the new node into the coordinate system
// of the parent node
//
Matrix3D curr_tm = node->Get_Transform ();
Matrix3D rel_tm = world_to_parent_tm * curr_tm;
new_node->Set_Transform (rel_tm);
new_node->Set_Needs_Save (false);
new_node->Set_Container_Preset_ID (Get_ID ());
//
// Add this node to our list
//
m_NodeList.Add (new_node);
}
}
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Free_Node_List
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Free_Node_List (void)
{
for (int index = 0; index < m_NodeList.Count (); index ++) {
REF_PTR_RELEASE (m_NodeList[index]);
}
m_NodeList.Delete_All ();
return ;
}
////////////////////////////////////////////////////////////////////
//
// Create_Linked_Nodes
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Create_Linked_Nodes (NodeClass *parent_node)
{
//
// Build a matrix that we can use to transform each
// node into the coordinate system of the parent node
//
Matrix3D parent_tm = parent_node->Get_Transform ();
for (int index = 0; index < m_NodeList.Count (); index ++) {
//
// Clone this node via the scene so it will get installed into
// all the appropriate systems
//
NodeClass *new_node = ::Get_Scene_Editor ()->Clone_Node (m_NodeList[index]);
//
// Transform the node into world space
//
Matrix3D rel_tm = m_NodeList[index]->Get_Transform ();
Matrix3D new_tm = parent_tm * rel_tm;
new_node->Set_Transform (new_tm);
new_node->Lock (true);
new_node->Set_Is_Proxied (true);
new_node->Set_Needs_Save (false);
new_node->Set_Container_Preset_ID (Get_ID ());
//
// Release our hold on the node
//
REF_PTR_RELEASE (new_node);
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Get_Child_Preset
//
////////////////////////////////////////////////////////////////////
PresetClass *
PresetClass::Get_Child_Preset (int index)
{
PresetClass *retval = NULL;
if (index >= 0 && index < m_ChildIDList.Count ()) {
retval = PresetMgrClass::Find_Preset (m_ChildIDList[index]);
}
return retval;
}
////////////////////////////////////////////////////////////////////
//
// Set_Definition
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Set_Definition (DefinitionClass *definition)
{
if (m_Definition != NULL) {
m_Definition->Set_User_Data (NULL);
}
m_Definition = definition;
m_DefinitionID = 0;
//
// Store our "this" pointer in the definition so we can
// quickly find the preset given its definition
//
if (m_Definition != NULL) {
m_Definition->Set_User_Data ((uint32)this);
m_DefinitionID = m_Definition->Get_ID ();
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Add_Child_Preset
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Add_Child_Preset (int child_id)
{
//
// Don't allow ourselves to become recursively linked
//
if (child_id == (int)Get_ID ()) {
return ;
}
//
// Make sure the child isn't already in our list
//
int index = m_ChildIDList.ID (child_id);
WWASSERT (index == -1);
//
// Add the child to the list
//
if (index == -1) {
m_ChildIDList.Add (child_id);
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Remove_Child_Preset
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Remove_Child_Preset (int child_id)
{
int index = m_ChildIDList.ID (child_id);
if (index != -1) {
m_ChildIDList.Delete (index);
}
return ;
}
////////////////////////////////////////////////////////////////////
//
// Set_Parent
//
////////////////////////////////////////////////////////////////////
void
PresetClass::Set_Parent (PresetClass *parent)
{
//
// If changing parents, unlink ourselves from our old parent
//
if (m_Parent != NULL) {
m_Parent->Remove_Child_Preset (Get_ID ());
}
m_Parent = parent;
//
// Cache the parent's ID
//
if (m_Parent != NULL) {
m_ParentID = m_Parent->Get_ID ();
} else {
m_ParentID = 0;
}
return ;
}