Files
FC1/Editor/SoundPresetMgr.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

412 lines
10 KiB
C++

#include "StdAfx.h"
#include <ctype.h>
#include <IScriptSystem.h>
#include <IEntitySystem.h>
#include "soundpresetmgr.h"
CSoundPresetMgr::CSoundPresetMgr()
{
XmlNodeRef pPropNode;
m_pSoundTemplateNode=new CXmlNode("UndefinedSound");
pPropNode=new CXmlNode("Sound");
pPropNode->setAttr("type", "sound");
pPropNode->setAttr("value", "");
m_pSoundTemplateNode->addChild(pPropNode);
pPropNode=new CXmlNode("Centered");
pPropNode->setAttr("type", "bool");
pPropNode->setAttr("value", "0");
m_pSoundTemplateNode->addChild(pPropNode);
pPropNode=new CXmlNode("Chance");
pPropNode->setAttr("type", "int");
pPropNode->setAttr("value", "0");
pPropNode->setAttr("min", "0");
pPropNode->setAttr("max", "1000");
m_pSoundTemplateNode->addChild(pPropNode);
pPropNode=new CXmlNode("NoOverlap");
pPropNode->setAttr("type", "bool");
pPropNode->setAttr("value", "1");
m_pSoundTemplateNode->addChild(pPropNode);
pPropNode=new CXmlNode("Streaming");
pPropNode->setAttr("type", "bool");
pPropNode->setAttr("value", "0");
m_pSoundTemplateNode->addChild(pPropNode);
pPropNode=new CXmlNode("Timeout");
pPropNode->setAttr("type", "float");
pPropNode->setAttr("value", "0");
pPropNode->setAttr("min", "0");
pPropNode->setAttr("max", "1000");
m_pSoundTemplateNode->addChild(pPropNode);
pPropNode=new CXmlNode("Volume");
pPropNode->setAttr("type", "int");
pPropNode->setAttr("value", "255");
pPropNode->setAttr("min", "0");
pPropNode->setAttr("max", "255");
m_pSoundTemplateNode->addChild(pPropNode);
/*
pPropNode=new CXmlNode("AreaID");
pPropNode->setAttr("type", "int");
pPropNode->setAttr("value", "-1");
pPropNode->setAttr("min", "-1");
m_pSoundTemplateNode->addChild(pPropNode);
*/
m_pRootNode=new CXmlNode("SoundPresetDB");
}
CSoundPresetMgr::~CSoundPresetMgr()
{
}
bool CSoundPresetMgr::AddPreset(CString sName)
{
if (sName.GetLength()<=0)
return false;
// check if name is valid
for (int i=0;i<sName.GetLength();i++)
{
char c=sName[i];
if (!i)
{
if (!isalpha(c))
return false;
}else
{
if (!isalnum(c))
return false;
}
}
if (m_pRootNode->findChild(sName))
return false;
XmlNodeRef pPresetNode=new CXmlNode(sName);
m_pRootNode->addChild(pPresetNode);
return true;
}
bool CSoundPresetMgr::DelPreset(CString sName)
{
XmlNodeRef pPresetNode=m_pRootNode->findChild(sName);
if (!pPresetNode)
return false;
m_pRootNode->removeChild(pPresetNode);
Reload();
return true;
}
bool CSoundPresetMgr::AddSound(CString sPreset)
{
XmlNodeRef pPresetNode=m_pRootNode->findChild(sPreset);
if (!pPresetNode)
return false;
XmlNodeRef pSoundNode=m_pSoundTemplateNode->clone();
MakeTagUnique(pPresetNode, pSoundNode);
pPresetNode->addChild(pSoundNode);
return true;
}
bool CSoundPresetMgr::DelSound(CString sPreset, XmlNodeRef pNode)
{
XmlNodeRef pPresetNode=m_pRootNode->findChild(sPreset);
if (!pPresetNode)
return false;
while (pNode->getParent()!=pPresetNode)
{
pNode=pNode->getParent();
if (!pNode)
return false;
}
pPresetNode->removeChild(pNode);
Reload();
return true;
}
void CSoundPresetMgr::MakeTagUnique(XmlNodeRef pParent, XmlNodeRef pNode)
{
CString NodeTag=pNode->getTag();
// make name valid
for (int i=0;i<NodeTag.GetLength();i++)
{
char c=NodeTag[i];
if (!i)
{
if (!isalpha(c))
c='_';
}else
{
if (!isalnum(c))
c='_';
}
NodeTag.SetAt(i, c);
}
int nCounter=2;
char sCounter[5];
bool bUnique=false;
XmlNodeRef pCheckNode;
do {
pCheckNode=pParent->findChild(NodeTag);
if ((pCheckNode!=NULL) && (pCheckNode!=pNode))
{
sprintf(sCounter, "%d", nCounter);
NodeTag=CString(pNode->getTag())+sCounter;
nCounter++;
}else
bUnique=true;
}while(!bUnique);
pNode->setTag(NodeTag);
}
bool CSoundPresetMgr::Reload(CString sFilename)
{
if (!Save() || !Load())
{
AfxMessageBox("An error occured while reloading sound-presets. Is Database read-only ?", MB_ICONEXCLAMATION | MB_OK);
return false;
}
return true;
}
bool CSoundPresetMgr::DumpTableRecursive(FILE *pFile, XmlNodeRef pNode, int nTabs)
{
for (int i=0;i<nTabs;i++) if (fprintf(pFile, "\t")<=0) return false;
CString sValue;
if (pNode->getAttr("value", sValue))
{
for (int i=0;i<sValue.GetLength();i++)
{
if (sValue[i]=='\\')
sValue.SetAt(i, '/');
}
if (fprintf(pFile, "%s = \"%s\"", pNode->getTag(), (const char*)sValue)<=0) return false;
}else
{
if (fprintf(pFile, "%s = {\r\n", pNode->getTag())<=0) return false;
for (int i=0;i<pNode->getChildCount();i++)
{
XmlNodeRef pChild=pNode->getChild(i);
if (!DumpTableRecursive(pFile, pChild, nTabs+1)) return false;
}
for (int i=0;i<nTabs;i++) if (fprintf(pFile, "\t")<=0) return false;
if (fprintf(pFile, "}")<=0) return false;
}
if (nTabs)
if (fprintf(pFile, ",\r\n")<=0) return false;
return true;
}
bool CSoundPresetMgr::Save(CString sFilename)
{
FILE *pFile=fopen(sFilename, "wb");
if (!pFile)
return false;
bool bRes=true;
bRes=DumpTableRecursive(pFile, m_pRootNode);
fclose(pFile);
return bRes;
}
class CSoundPresetSODump : public IScriptObjectDumpSink
{
private:
IScriptSystem *m_pScriptSystem;
_SmartScriptObject m_pObj;
XmlNodeRef m_pNode;
XmlNodeRef m_pSoundTemplateNode;
int m_nLevel;
public:
CSoundPresetSODump(IScriptSystem *pScriptSystem, _SmartScriptObject &pObj, XmlNodeRef pNode, XmlNodeRef pSoundTemplateNode, int nLevel=0) : m_pObj(pScriptSystem,pObj)
{
m_pScriptSystem=pScriptSystem;
m_pNode=pNode;
m_pSoundTemplateNode=pSoundTemplateNode;
m_nLevel=nLevel;
}
private:
void OnElementFound(const char *sName, ScriptVarType type)
{
switch (type)
{
case svtObject:
{
_SmartScriptObject pObj(m_pScriptSystem, true);
m_pObj->GetValue(sName, pObj);
XmlNodeRef pNode;
if (!m_nLevel)
{
pNode=new CXmlNode(sName);
}else
{
pNode=m_pSoundTemplateNode->clone();
pNode->setTag(sName);
}
m_pNode->addChild(pNode);
CSoundPresetSODump Sink(m_pScriptSystem, pObj, pNode, m_pSoundTemplateNode, m_nLevel+1);
pObj->Dump(&Sink);
break;
}
case svtString:
case svtNumber:
{
const char *pszValue;
m_pObj->GetValue(sName, pszValue);
XmlNodeRef pNode=m_pNode->findChild(sName);
//ASSERT(pNode!=NULL);
if (pNode)
pNode->setAttr("value", pszValue);
}
}
}
void OnElementFound(int nIdx, ScriptVarType type)
{
}
};
bool CSoundPresetMgr::Load(CString sFilename)
{
ISystem *pSystem=GetIEditor()->GetSystem();
if (!pSystem)
return false;
IScriptSystem *pScriptSystem=pSystem->GetIScriptSystem();
if (!pScriptSystem)
return false;
pScriptSystem->SetGlobalToNull("SoundPresetDB");
pScriptSystem->ExecuteFile(sFilename, true, true);
_SmartScriptObject pObj(pScriptSystem, true);
if (!pScriptSystem->GetGlobalValue("SoundPresetDB", pObj))
return false;
m_pRootNode=new CXmlNode("SoundPresetDB");
CSoundPresetSODump Sink(pScriptSystem, pObj, m_pRootNode, m_pSoundTemplateNode);
pObj->Dump(&Sink);
return true;
}
class CSoundPresetUpdateSODump : public IScriptObjectDumpSink
{
private:
IScriptSystem *m_pScriptSystem;
_SmartScriptObject m_pObj;
CString m_sPresetName;
CString m_sSoundName;
CString m_sPropName;
CString m_sPropValue;
bool m_bCorrectPreset;
bool m_bCorrectSound;
public:
CSoundPresetUpdateSODump(IScriptSystem *pScriptSystem, _SmartScriptObject &pObj, CString &sPresetName, CString &sSoundName, CString &sPropName, CString &sPropValue, bool bCorrectPreset=false, bool bCorrectSound=false) : m_pObj(pScriptSystem, pObj)
{
m_pScriptSystem=pScriptSystem;
m_sPresetName=sPresetName;
m_sSoundName=sSoundName;
m_sPropName=sPropName;
m_sPropValue=sPropValue;
m_bCorrectPreset=bCorrectPreset;
m_bCorrectSound=bCorrectSound;
}
private:
void OnElementFound(const char *sName, ScriptVarType type)
{
switch (type)
{
case svtObject:
{
_SmartScriptObject pObj(m_pScriptSystem, true);
m_pObj->GetValue(sName, pObj);
if (m_bCorrectPreset && (strcmp(sName, m_sSoundName)==0))
{
CSoundPresetUpdateSODump Sink(m_pScriptSystem, pObj, m_sPresetName, m_sSoundName, m_sPropName, m_sPropValue, true, true);
pObj->Dump(&Sink);
}else
{
if (strcmp(sName, m_sPresetName)==0)
{
CSoundPresetUpdateSODump Sink(m_pScriptSystem, pObj, m_sPresetName, m_sSoundName, m_sPropName, m_sPropValue, true);
pObj->Dump(&Sink);
}else
{
CSoundPresetUpdateSODump Sink(m_pScriptSystem, pObj, m_sPresetName, m_sSoundName, m_sPropName, m_sPropValue, false);
pObj->Dump(&Sink);
}
}
break;
}
case svtString:
case svtNumber:
{
if (m_bCorrectPreset && m_bCorrectSound && strcmp(sName, m_sPropName)==0)
{
for (int i=0;i<m_sPropValue.GetLength();i++)
{
if (m_sPropValue[i]=='\\')
m_sPropValue.SetAt(i, '/');
}
m_pObj->SetValue(sName, m_sPropValue);
}
}
}
}
void OnElementFound(int nIdx, ScriptVarType type)
{
}
};
bool CSoundPresetMgr::UpdateParameter(XmlNodeRef pNode)
{
CString sPresetName;
CString sSoundName;
CString sPropName;
CString sPropValue;
XmlNodeRef pParent=pNode->getParent();
if (!pParent)
return false;
if (pParent->getParent())
sPresetName=pParent->getParent()->getTag();
else
sPresetName="";
sSoundName=pParent->getTag();
sPropName=pNode->getTag();
if (!pNode->getAttr("value", sPropValue))
return false;
IScriptSystem *pScriptSystem=GetIEditor()->GetSystem()->GetIScriptSystem();
_SmartScriptObject pObj(pScriptSystem, true);
if (!pScriptSystem->GetGlobalValue("SoundPresetDB", pObj))
return false;
CSoundPresetUpdateSODump Sink(pScriptSystem, pObj, sPresetName, sSoundName, sPropName, sPropValue);
pObj->Dump(&Sink);
// lets call OnPropertyChange on every entity-script which uses presets
IEntitySystem *pEntSys=GetIEditor()->GetSystem()->GetIEntitySystem();
if (pEntSys)
{
IEntityIt *pEntIt=pEntSys->GetEntityIterator();
if (pEntIt)
{
pEntIt->MoveFirst();
IEntity *pEnt;
while (pEnt=pEntIt->Next())
{
IScriptObject *pScriptObject=pEnt->GetScriptObject();
if (pScriptObject)
{
_SmartScriptObject pObj(pScriptSystem, true);
if (pScriptObject->GetValue("Properties", pObj))
{
const char *pszPreset;
if (pObj->GetValue("sndpresetSoundPreset", pszPreset))
{
if (strcmp(pszPreset, sPresetName)==0)
{
pScriptSystem->BeginCall(pEnt->GetEntityClassName(),"OnPropertyChange");
pScriptSystem->PushFuncParam(pScriptObject);
pScriptSystem->EndCall();
}
}
}
}
}
}
}
return true;
}