/* ** 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 . */ /*********************************************************************************************** *** 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/ObjectNode.cpp $* * * * Author:: Patrick Smith * * * * $Modtime:: 5/22/01 11:17a $* * * * $Revision:: 20 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "stdafx.h" #include "objectnode.h" #include "sceneeditor.h" #include "tiledefinition.h" #include "filemgr.h" #include "_assetmgr.h" #include "editorassetmgr.h" #include "w3d_file.h" #include "cameramgr.h" #include "collisiongroups.h" #include "persistfactory.h" #include "editorchunkids.h" #include "preset.h" #include "editscript.h" #include "nodeinfopage.h" #include "nodescriptsproppage.h" #include "editorpropsheet.h" #include "positionpage.h" #include "modelutils.h" ////////////////////////////////////////////////////////////////////////////// // Persist factory ////////////////////////////////////////////////////////////////////////////// SimplePersistFactoryClass _ObjectNodePersistFactory; enum { CHUNKID_VARIABLES = 0x10271102, CHUNKID_BASE_CLASS, CHUNKID_SCRIPT }; ////////////////////////////////////////////////////////////////////////////// // // ObjectNodeClass // ////////////////////////////////////////////////////////////////////////////// ObjectNodeClass::ObjectNodeClass (PresetClass *preset) : m_GameObj (NULL), NodeClass (preset) { return ; } ////////////////////////////////////////////////////////////////////////////// // // ObjectNodeClass // ////////////////////////////////////////////////////////////////////////////// ObjectNodeClass::ObjectNodeClass (const ObjectNodeClass &src) : m_GameObj (NULL), NodeClass (NULL) { *this = src; return ; } ////////////////////////////////////////////////////////////////////////////// // // ~ObjectNodeClass // ////////////////////////////////////////////////////////////////////////////// ObjectNodeClass::~ObjectNodeClass (void) { Remove_From_Scene (); Destroy_Game_Obj (); Free_Scripts (); return ; } ////////////////////////////////////////////////////////////////////////////// // // Initialize // // Note: This may be called more than once. It is used as an 'initialize' // and a 're-initialize'. // ////////////////////////////////////////////////////////////////////////////// void ObjectNodeClass::Initialize (void) { Destroy_Game_Obj (); if (m_Preset != NULL) { m_Preset->Load_All_Assets (); Create_Game_Obj (); } return ; } //////////////////////////////////////////////////////////////// // // Get_Factory // //////////////////////////////////////////////////////////////// const PersistFactoryClass & ObjectNodeClass::Get_Factory (void) const { return _ObjectNodePersistFactory; } //////////////////////////////////////////////////////////////// // // Show_Settings_Dialog // //////////////////////////////////////////////////////////////// bool ObjectNodeClass::Show_Settings_Dialog (void) { NodeInfoPageClass info_tab (this); PositionPageClass pos_tab (this); NodeScriptsPropPage scripts_tab (&m_Scripts); EditorPropSheetClass prop_sheet; prop_sheet.Add_Page (&info_tab); prop_sheet.Add_Page (&pos_tab); prop_sheet.Add_Page (&scripts_tab); // Show the property sheet UINT ret_code = prop_sheet.DoModal (); if (ret_code == IDOK) { // // If the scripts changed, then we need to // reload the object and assign it the new // set of scripts. // Reload (); } // Return true if the user clicked OK return (ret_code == IDOK); } ///////////////////////////////////////////////////////////////// // // Save // ///////////////////////////////////////////////////////////////// bool ObjectNodeClass::Save (ChunkSaveClass &csave) { csave.Begin_Chunk (CHUNKID_BASE_CLASS); NodeClass::Save (csave); csave.End_Chunk (); // // Save the list of scripts // for (int index = 0; index < m_Scripts.Count (); index ++) { EditScriptClass *script = m_Scripts[index]; // // Have this script save itself // csave.Begin_Chunk (CHUNKID_SCRIPT); script->Save (csave); csave.End_Chunk (); } return true; } ///////////////////////////////////////////////////////////////// // // Load // ///////////////////////////////////////////////////////////////// bool ObjectNodeClass::Load (ChunkLoadClass &cload) { Free_Scripts (); while (cload.Open_Chunk ()) { switch (cload.Cur_Chunk_ID ()) { case CHUNKID_BASE_CLASS: NodeClass::Load (cload); break; case CHUNKID_SCRIPT: { EditScriptClass *script = new EditScriptClass; if (script->Load (cload)) { m_Scripts.Add (script); } } break; } cload.Close_Chunk (); } return true; } ///////////////////////////////////////////////////////////////// // // Free_Scripts // ///////////////////////////////////////////////////////////////// void ObjectNodeClass::Free_Scripts (void) { for (int index = 0; index < m_Scripts.Count (); index ++) { EditScriptClass *script = m_Scripts[index]; SAFE_DELETE (script); } m_Scripts.Delete_All (); return ; } ///////////////////////////////////////////////////////////////// // // Assign_Scripts // ///////////////////////////////////////////////////////////////// void ObjectNodeClass::Assign_Scripts (void) { if (m_GameObj != NULL) { for (int index = 0; index < m_Scripts.Count (); index ++) { EditScriptClass *script = m_Scripts[index]; // // Create the game script and pass it onto the game obj // ScriptClass *game_script = script->Create_Script (); if (game_script != NULL) { m_GameObj->Add_Observer (game_script); } } } return ; } ///////////////////////////////////////////////////////////////// // // Copy_Scripts // ///////////////////////////////////////////////////////////////// void ObjectNodeClass::Copy_Scripts (const ObjectNodeClass &src) { Free_Scripts (); // // Loop over all the scripts in the src object and copy them. // for (int index = 0; index < src.m_Scripts.Count (); index ++) { EditScriptClass *script = src.m_Scripts[index]; if (script != NULL) { // // Make ourselves a copy of the script // EditScriptClass *our_copy = new EditScriptClass (*script); m_Scripts.Add (our_copy); } } Assign_Scripts (); return ; } ///////////////////////////////////////////////////////////////// // // operator= // ///////////////////////////////////////////////////////////////// const ObjectNodeClass & ObjectNodeClass::operator= (const ObjectNodeClass &src) { // // Copy the script list from the source object // Copy_Scripts (src); NodeClass::operator= (src); return *this; } ////////////////////////////////////////////////////////////////////// // // Add_To_Scene // ////////////////////////////////////////////////////////////////////// void ObjectNodeClass::Add_To_Scene (void) { Create_Game_Obj (); NodeClass::Add_To_Scene (); return ; } ////////////////////////////////////////////////////////////////////// // // Remove_From_Scene // ////////////////////////////////////////////////////////////////////// void ObjectNodeClass::Remove_From_Scene (void) { Destroy_Game_Obj (); NodeClass::Remove_From_Scene (); return ; } ////////////////////////////////////////////////////////////////////// // // Create_Game_Obj // ////////////////////////////////////////////////////////////////////// void ObjectNodeClass::Create_Game_Obj (void) { if (m_GameObj == NULL) { DefinitionClass *definition = m_Preset->Get_Definition (); if (definition != NULL) { // // Create the game object // m_GameObj = (ScriptableGameObj *)::Instance_Definition (definition); // // Assign 'hit-test' information to this game object // if (m_GameObj != NULL) { PhysClass *phys_obj = Peek_Physics_Obj (); RenderObjClass *render_obj = phys_obj->Peek_Model (); if (render_obj != NULL) { render_obj->Set_User_Data ((PVOID)&m_HitTestInfo, FALSE); ::Set_Model_Collision_Type (render_obj, COLLISION_TYPE_6); } // // Make sure the physics object has the correct position // Set_Transform (m_Transform); m_GameObj->Set_ID (m_ID); PhysicalGameObj *game_obj = Peek_Game_Obj (); if (game_obj != NULL) { game_obj->Startup (); } // // Make sure we don't put the object into the scene prematurely // if (phys_obj->Get_Culling_System () != NULL) { ::Get_Scene_Editor ()->Remove_Object (phys_obj); } } Assign_Scripts (); } } return ; } ////////////////////////////////////////////////////////////////////// // // Destroy_Game_Obj // ////////////////////////////////////////////////////////////////////// void ObjectNodeClass::Destroy_Game_Obj (void) { if (m_GameObj != NULL) { m_GameObj->Set_Delete_Pending (); m_GameObj = NULL; } return ; } ///////////////////////////////////////////////////////////////// // // Set_ID // ///////////////////////////////////////////////////////////////// void ObjectNodeClass::Set_ID (uint32 id) { NodeClass::Set_ID (id); if (m_GameObj != NULL) { m_GameObj->Set_ID (m_ID); } return ; }