/*============================================================================= * * Filename: GMatObj.cpp * Version: 1.0 * Date: 06/11/96 * Author: B.G. * * Description: implementation of editor material class * *===========================================================================*/ #include "stdafx.h" #include "Acp_base.h" #include "itf.h" #include "gmt.h" #include "incgam.h" #include "dpt.h" #include "_interf.hpp" #include "GMatObj.hpp" #include "VMatObj.hpp" #include "MMatObj.hpp" #include "CMatObj.hpp" #include "x:\cpa\main\inc\_editid.h" //ROMTEAM WorldEditor (Cristi Petrescu 22/12/97) #include "ozo.h" //ENDROMTEAM WorldEditor (Cristi Petrescu) extern Material_Interface *gs_p_oMaterialInterface; //================================================================================= //constructor. the object is name with the following rules //1. it is not a clone but will directly handle the engine material // -> will take the name from the section for the engine material //2. it is a clone, and a name is specified // -> an underscore is added to the original's name, // because someday the base constructor will add a number there //3. it is a clone, and no name is specified // -> the default name is given by the base constructor //================================================================================= tdoEditorGameMaterial::tdoEditorGameMaterial( CPA_FileObject *_p_oOwnerFile, CString _csId, BOOL _bSectionAlreadyExists, GMT_tdxHandleToGameMaterial _hTemplateMaterial ) : CPA_SaveObject( gs_p_oMaterialInterface, //editor C_szGameMaterialTypeName, //type E_ss_Responsible, //responsibility _p_oOwnerFile, //owner (the file containing the section) FALSE, //availability (char*)LPCTSTR(_p_oOwnerFile->GetCompletionPath(gs_p_oMaterialInterface, C_szFileReferencedNameKey)), //data path to complete the referenced section name m_vCallBackSaveGMT//callback ) { //tell the file object that an object exists for its section g_oCoherenceManager.m_fn_vAddALink(_p_oOwnerFile, this); GMT_fn_vInvalidate(&m_hGameMaterial); //set with a default value before rename for first list sorting // construct section name (hack: szSectionName is here as an anti-bug for ...Split... char szSectionName[SCR_CV_ui_Cfg_MaxLenName]; SCR_fn_v_RdL0_ComputeSectionName( szSectionName, (char*)LPCTSTR(_p_oOwnerFile->GetReferencedName(gs_p_oMaterialInterface, C_szFileReferencedNameKey)), C_SectionGameMaterial, (char*)LPCTSTR(_csId) ); // section object if ( _bSectionAlreadyExists ) fn_vSectionSaved(); //the section is saved, and has no pending notification else fn_vSectionDeleted(); //the section does not exist, and has no pending nofitication SetSectionData(this); SetReferencedSectionName(szSectionName); // name if ( fn_eRename(_csId) != E_mc_None ) SetDefaultValidName() ; fn_vUpdateSectionName(); if ( fn_bCanBeNotified() && !fn_bSectionExists() ) fn_vNotifySave(); //if the handle is invalid, the engine material is not loaded yet //SetAvailable(GMT_fn_b_ulIsValid(_hTemplateMaterial)); //done in m_vAssociateEngineMaterial() //associate the material and create associated editor sub-materials as well m_vAssociateEngineMaterial(_hTemplateMaterial, _bSectionAlreadyExists); } //================================================================================= //================================================================================= tdoEditorGameMaterial::~tdoEditorGameMaterial() { //remove myself totally from the coherence manager database if ( !fn_bSectionExists() ) g_oCoherenceManager.m_fn_vRemoveAllLinks(this, C_cLinkedAsChildAndFather); } //================================================================================= //================================================================================= void tdoEditorGameMaterial::m_vAssociateEngineMaterial( GMT_tdxHandleToGameMaterial _hGameMaterial, BOOL _bSectionAlreadyExists ) { if ( m_hGameMaterial == _hGameMaterial ) return; BOOL bIsAssociatedMaterialValid = GMT_fn_b_ulIsValid(_hGameMaterial); //a section exists for this object, since we use it directly if ( _bSectionAlreadyExists ) fn_vSectionSaved(); //the section is saved, and has no pending notification else fn_vSectionDeleted(); //the section does not exist, and has no pending nofitication //if the handle is invalid, the engine material is not loaded yet SetAvailable(bIsAssociatedMaterialValid); //the editor object directly handles the engine object fn_vUpdateData(_hGameMaterial); m_hGameMaterial = _hGameMaterial; //if the game material is valid, create editor materials for its sub-materials as well if ( bIsAssociatedMaterialValid ) { ACP_tdxHandleOfMaterial hMaterialVisual = GMT_fn_hGetVisualMaterial(m_hGameMaterial); DNM_tdxHandleToMecMatCharacteristics hMaterialMechanics = GMT_fn_hGetMechanicsMaterial(m_hGameMaterial); GMT_tdxHandleToCollideMaterial hMaterialCollide = GMT_fn_hGetCollideMaterial(m_hGameMaterial); //now create editor objects for the materials that are in the handled engine game material CPA_BaseObject *p_oEditorMaterial; //create an editor visual material //but verify that each game material references uniquely a visual material ASSERT(hMaterialVisual); if ( !(p_oEditorMaterial = gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hMaterialVisual)) ) { CPA_FileObject *p_oFileObject; char szVisualMaterialName[SCR_CV_ui_Cfg_MaxLenName]; //get the link table entry for the engine visual material SCR_tdst_Link_Table *p_stVisualLinkTable = GLI_p_stGetLinkTableOfVisualMaterial(); //char *pszLinkName = GLI_p_cSearchValueInLinkTableOfGeometric((unsigned long) hMaterialVisual); SCR_tdst_Link_Value *p_stVisualEntry = SCR_fnp_st_Link_SearchValue(p_stVisualLinkTable, (unsigned long) hMaterialVisual); if ( p_stVisualEntry ) { char szVisualMaterialFile[SCR_CV_ui_Cfg_MaxLenName]; //get the file and object name from the entry char *pszLinkName = SCR_M_p_sz_Link_GetKey(p_stVisualEntry); SCR_fn_v_RdL0_SplitSectionName(pszLinkName, szVisualMaterialFile, NULL, szVisualMaterialName); //get the file object for this referenced path p_oFileObject = p_oGetFileObjectForReferencedPath(szVisualMaterialFile, ""); } else //this is a new game material -> we choose the file for the visual material from the game material's file name { char szVisualMaterialFile[SCR_CV_ui_Cfg_MaxLenName]; //get the minimal name of the game material's file p_oFileObject = (CPA_FileObject *) GetOwner(); strcpy(szVisualMaterialFile, (char*)LPCTSTR(p_oFileObject->GetReferencedName(gs_p_oMaterialInterface, C_szFileMinimalNameKey))); //change extension from gmt to vmt strcpy(strrchr(szVisualMaterialFile, '.'), LPCTSTR(tdoEditorVisualMaterial::m_csGetScriptExtension())); //find the file object with this minimal name p_oFileObject = p_oGetFileObjectForReferencedPath(szVisualMaterialFile, C_szFileMinimalNameKey); //the visual material will attempt to have the same name than its owner game material strcpy(szVisualMaterialName, (char *)LPCTSTR(GetName())); } //create a new editor visual material that will be saved in this file p_oEditorMaterial = new tdoEditorVisualMaterial( p_oFileObject, //p_oGetFileObjectForReferencedPath(szVisualMaterialFile), szVisualMaterialName, _bSectionAlreadyExists, hMaterialVisual ); } //there MUST exist an editor material for each referenced visual material! ASSERT(p_oEditorMaterial); //tell the cohemngr that the created game material uses the visual material if ( p_oEditorMaterial ) g_oCoherenceManager.m_fn_vAddALink(this, p_oEditorMaterial); //create an editor mechanics material if none exists for this handle p_oEditorMaterial = NULL; if ( DNM_fn_bIsMatCharacteristicsValid(hMaterialMechanics) && !(p_oEditorMaterial = gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hMaterialMechanics)) ) { char *pszKey = DNM_fn_p_cSearchValueInLinkTableOfMecMatCharacteristics((unsigned long) hMaterialMechanics); SCR_tdst_Link_Value *p_stEntry = SCR_fnp_st_Link_SearchValue(DNM_fn_p_stGetLinkTableOfMecMatCharacteristics(), (unsigned long) hMaterialMechanics); CString csName, csReferencedFileName; CPA_FileObject *p_oFileObject; if ( pszKey ) { csReferencedFileName = gs_p_oMaterialInterface->m_csGetFilePartOfSectionName(pszKey + SCR_M_ul_Link_GetAdditionalLong(p_stEntry, 1)); csName = gs_p_oMaterialInterface->m_csGetIdPartOfSectionName(pszKey); } else { csReferencedFileName = CString("ED") + tdoEditorMechanicsMaterial::m_csGetScriptExtension(); csName = GetName(); } p_oFileObject = p_oGetFileObjectForReferencedPath(csReferencedFileName); //try to find an editor material based upon the name before creating a new one p_oEditorMaterial = (tdoEditorMechanicsMaterial *) gs_p_oMaterialInterface->GetBaseObject( csName, C_szMechanicsMaterialTypeName, p_oFileObject ); if ( p_oEditorMaterial ) // give the engine material to the editor material ((tdoEditorMechanicsMaterial *) p_oEditorMaterial)->m_vAssociateEngineMaterial(hMaterialMechanics, TRUE); else //we have to create an editor mechanics material to handle this engine mechanics material p_oEditorMaterial = new tdoEditorMechanicsMaterial( p_oFileObject, //p_oGetFileObjectForCompletePath(csFullPath), csName, _bSectionAlreadyExists, hMaterialMechanics ); //there MUST exist an editor material after the creation! ASSERT(p_oEditorMaterial); } //tell the cohemngr that the created game material uses the mechanics material if ( p_oEditorMaterial ) g_oCoherenceManager.m_fn_vAddALink(this, p_oEditorMaterial); //create an editor collide material if none exists for this handle p_oEditorMaterial = NULL; if ( hMaterialCollide != GMT_C_InvalidCollideMaterial && !(p_oEditorMaterial = gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hMaterialCollide)) ) { SCR_tdst_Link_Table *p_stLinkTable = GMT_fn_p_stGetZoneLinkTable(); SCR_tdst_Link_Value *p_stEntry = SCR_fnp_st_Link_SearchValue(p_stLinkTable, (unsigned long) hMaterialCollide); char *pszKey = SCR_M_p_sz_Link_GetKey(p_stEntry); CString csName, csReferencedFileName; CPA_FileObject *p_oFileObject; if ( pszKey ) { csReferencedFileName = gs_p_oMaterialInterface->m_csGetFilePartOfSectionName(pszKey + SCR_M_ul_Link_GetAdditionalLong(p_stEntry, 1)); csName = gs_p_oMaterialInterface->m_csGetIdPartOfSectionName(pszKey); } else { csReferencedFileName = CString("ED") + tdoEditorCollideMaterial::m_csGetScriptExtension(); csName = GetName(); } p_oFileObject = p_oGetFileObjectForReferencedPath(csReferencedFileName); //try to find an editor material based upon the name before creating a new one p_oEditorMaterial = (tdoEditorCollideMaterial *) gs_p_oMaterialInterface->GetBaseObject( csName, C_szCollideMaterialTypeName, p_oFileObject ); if ( p_oEditorMaterial ) // give the engine material to the editor material ((tdoEditorCollideMaterial *) p_oEditorMaterial)->m_vAssociateEngineMaterial(hMaterialCollide, TRUE); else //we have to create an editor mechanics material to handle this engine mechanics material p_oEditorMaterial = new tdoEditorCollideMaterial( p_oFileObject, //p_oGetFileObjectForCompletePath(csFullPath), csName, _bSectionAlreadyExists, hMaterialCollide ); //there MUST exist an editor material after the creation! ASSERT(p_oEditorMaterial); } //tell the cohemngr that the created game material uses the collide material if ( p_oEditorMaterial ) g_oCoherenceManager.m_fn_vAddALink(this, p_oEditorMaterial); } } //================================================================================= //================================================================================= void tdoEditorGameMaterial::m_vLoadAssociatedEngineMaterial(BOOL _bEndOfLoad /*= TRUE*/) { //if the section name is not in the linktable, analyse the section SCR_tdst_Cxt_Values *p_stAnalyzeResult = SCR_fnp_st_RdL0_AnalyseSection( (char *) LPCTSTR(GetReferencedSectionName()), SCR_CDF_uw_Anl_Normal ); //load the texture in the graphic board vram, if not told otherwise (because we want to group analyzes before the upload) if ( _bEndOfLoad ) GLI_vEndofGeometricLoad(); GMT_tdxHandleToGameMaterial hGameMaterial = (GMT_tdxHandleToGameMaterial) p_stAnalyzeResult->a_ulValues[0]; //there must not already exist an editor material for the loaded game material! ASSERT(!gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hGameMaterial)); //create the association m_vAssociateEngineMaterial(hGameMaterial, TRUE); } //================================================================================ //================================================================================ BOOL tdoEditorGameMaterial::m_bIsReferenced() { return g_oCoherenceManager.m_fn_iGetFatherCount(this) > 1; } //================================================================================ //================================================================================ void tdoEditorGameMaterial::m_vCallBackSaveGMT( SCR_tdst_File_Description *_p_stFile, char *_p_szSectionName, void *_p_vData, SCR_tde_Ntfy_Action _eAction ) { tdoEditorGameMaterial *p_oEditorMaterial = (tdoEditorGameMaterial *) _p_vData; if ( _eAction == SCR_EA_Ntfy_DeleteSection ) //now the section exists, if this was not the case p_oEditorMaterial->fn_vSectionDeleted(); // the section no longer exists, and has no pending notification if ( _eAction != SCR_EA_Ntfy_AddSection && _eAction != SCR_EA_Ntfy_RebuildSection ) return; if ( _eAction == SCR_EA_Ntfy_AddSection ) { // go to end of file (we need all file directive to load this section) SCR_fn_v_SvL1_ToEndSection(_p_stFile); SCR_M_SvL0_SaveBlankLine (_p_stFile); } GMT_tdxHandleToGameMaterial hEngineMaterial = p_oEditorMaterial->m_hGetEngineMaterial(); // construct section name (hack: szSectionName is here as an anti-bug for ...Split... char szSectionName[SCR_CV_ui_Cfg_MaxLenName],szAction[SCR_CV_ui_Cfg_MaxLenName],szId[SCR_CV_ui_Cfg_MaxLenName]; SCR_fn_v_RdL0_SplitSectionName(_p_szSectionName, szSectionName, szAction, szId); SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szAction, szId); // save begin section for the game material SCR_M_SvL0_SaveBeginSection(_p_stFile, szSectionName, SCR_CC_C_Cfg_EOL); // save each ministructure ACP_tdxHandleOfMaterial hMaterialVisual = GMT_fn_hGetVisualMaterial(hEngineMaterial); if ( hMaterialVisual ) { CString csKey; /*char *pszKey = GLI_p_cSearchValueInLinkTableOfGeometric((unsigned long) hMaterialVisual); if ( pszKey ) csKey = pszKey; else*/ csKey = gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hMaterialVisual)->GetReferencedSectionName(); SCR_M_SvL0_SaveEntry(_p_stFile, C_EntryVisualGameMaterialToLoad, SCR_CC_C_Cfg_NoChar); SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Normal, 1, (char *)LPCTSTR(csKey)); } DNM_tdxHandleToMecMatCharacteristics hMaterialMechanics = GMT_fn_hGetMechanicsMaterial(hEngineMaterial); if ( DNM_fn_bIsMatCharacteristicsValid(hMaterialMechanics) ) { CString csKey; /*char *pszKey = DNM_fn_p_cSearchValueInLinkTableOfMecMatCharacteristics((unsigned long) hMaterialMechanics); if ( pszKey ) csKey = pszKey; else*/ csKey = gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hMaterialMechanics)->GetReferencedSectionName(); SCR_M_SvL0_SaveEntry(_p_stFile, C_EntryMechanicalMaterialToLoad, SCR_CC_C_Cfg_NoChar); SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Normal, 1, (char *)LPCTSTR(csKey)); } GMT_tdxHandleToCollideMaterial hMaterialCollide = GMT_fn_hGetCollideMaterial(hEngineMaterial); if ( hMaterialCollide != GMT_C_InvalidCollideMaterial ) { CString csKey; /*SCR_tdst_Link_Table *p_stLinkTable = GMT_fn_p_stGetZoneLinkTable(); char *pszKey = SCR_M_p_sz_Link_GetKey(SCR_fnp_st_Link_SearchValue(p_stLinkTable, (unsigned long) hMaterialCollide)); if ( pszKey ) csKey = pszKey; else*/ csKey = gs_p_oMaterialInterface->m_p_oGetEditorObjectForEngine(hMaterialCollide)->GetReferencedSectionName(); SCR_M_SvL0_SaveEntry(_p_stFile, C_EntryCollideMaterialToLoad, SCR_CC_C_Cfg_NoChar); SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Normal, 1, (char *)LPCTSTR(csKey)); } SND_tdxHandleToSoundMaterial hMaterialSound = GMT_fn_hGetSoundMaterial(hEngineMaterial); if ( hMaterialSound != GMT_C_InvalidSoundMaterial ) { SCR_M_SvL0_SaveEntry(_p_stFile, C_EntrySoundMaterial, SCR_CC_C_Cfg_NoChar); SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_ArrayLong, 2, 1, &hMaterialSound); } // End Section SCR_M_SvL0_SaveEndSection(_p_stFile, SCR_CC_C_Cfg_EOL); // update Section name //now the section exists, if this was not the case p_oEditorMaterial->fn_vSectionSaved(); // the section is saved and has no pending notification } //================================================================================= //================================================================================= //================================================================================= // static functions for the class //================================================================================= //================================================================================= //================================================================================= SCR_tdst_Link_Table *tdoEditorGameMaterial::m_p_stGetAssociatedLinkTable() { return GMT_fn_p_stGetLinkTable(); } BOOL tdoEditorGameMaterial::m_bIsEngineMaterialValid(GMT_tdxHandleToGameMaterial _hGameMaterial) { return GMT_fn_b_ulIsValid(_hGameMaterial); } /*CString tdoEditorGameMaterial::m_csGetBaseDataPath() { return fn_szGetGameMaterialDataPath(); }*/ void tdoEditorGameMaterial::m_vInvalidateEngineMaterial(GMT_tdxHandleToGameMaterial &r_hGameMaterial) { GMT_fn_vInvalidate(&r_hGameMaterial); } CString tdoEditorGameMaterial::m_csGetMaterialType() { return C_szGameMaterialTypeName; } CString tdoEditorGameMaterial::m_csGetScriptExtension() { return ".gmt"; } //ROMTEAM WorldEditor (Cristi Petrescu 11/12/97) ////////////////////////////////////////////////////////////////////////////////////////////////////// // Method : word tdoEditorGameMaterial::m_uwTypeOfZonesUsingMe (void) // Date : 97.12.11 ////////////////////////////////////////////////////////////////////////////////////////////////////// // Description : // Tells which zone types are using this material // The result is a word of bit flags // Uses the coherence manager to find the objects using the material // Author : Cristi Petrescu ////////////////////////////////////////////////////////////////////////////////////////////////////// // Modification : // Date : // By : ////////////////////////////////////////////////////////////////////////////////////////////////////// WORD tdoEditorGameMaterial::m_uwTypeOfZonesUsingMe (void) { CList< CPA_BaseObject *, CPA_BaseObject *> oFatherList; int iNoObjects; WORD uwResult = 0; iNoObjects = g_oCoherenceManager . m_fn_iGetFatherList (this, & oFatherList); if (iNoObjects) { POSITION xPos; CPA_BaseObject* poBaseObject; //quite useless to do this inside the loop, eh ? CPA_EditorBase *poZoneEditor = gs_p_oMaterialInterface -> GetMainWorld () -> GetEditorByName ("Zone"); ASSERT (poZoneEditor); for ( xPos=oFatherList.GetHeadPosition(); xPos; oFatherList.GetNext(xPos) ) { poBaseObject = oFatherList.GetAt (xPos); // see Material_ApplyMaterialModif::Material_ApplyMaterialModif for comments long lEngineType = poZoneEditor -> OnQueryAction (gs_p_oMaterialInterface, C_uiQueryTypeOfZoneByGeometricObject, (long) poBaseObject); switch (lEngineType) { case C_lZDE: uwResult |= GMT_C_uwZDE; break; case C_lZDM: uwResult |= GMT_C_uwZDM; break; case C_lZDR: uwResult |= GMT_C_uwZDR; break; // those last three are unused by the collision materials, but just in case... case C_lZDD: uwResult |= GMT_C_uwZDD; break; case C_lBoundingVolume: uwResult |= GMT_C_uwBoundingVolume; break; } } } return uwResult; } //ENDROMTEAM WorldEditor (Cristi Petrescu)