// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION // // This software is supplied under the terms of a license agreement or // nondisclosure agreement with Emergent Game Technologies and may not // be copied or disclosed except in accordance with the terms of that // agreement. // // Copyright (c) 1996-2007 Emergent Game Technologies. // All Rights Reserved. // // Emergent Game Technologies, Chapel Hill, North Carolina 27517 // http://www.emergent.net // Precompiled Header #include "SceneDesignerFrameworkPCH.h" #include "MProxyManager.h" #include "MFramework.h" #include "MUtility.h" #include "ServiceProvider.h" #include "NiProxyComponent.h" #include "NiLightProxyComponent.h" #include "MTimeStamp.h" using namespace Emergent::Gamebryo::SceneDesigner::Framework; //--------------------------------------------------------------------------- void MProxyManager::Init() { if (ms_pmThis == NULL) { ms_pmThis = new MProxyManager(); ms_pmThis->m_pmSFXProxy = NULL; } } //--------------------------------------------------------------------------- void MProxyManager::Shutdown() { if (ms_pmThis->m_pmSFXProxy != NULL) { delete ms_pmThis->m_pmSFXProxy; ms_pmThis->m_pmSFXProxy = NULL; } if (ms_pmThis != NULL) { ms_pmThis->Dispose(); ms_pmThis = NULL; } } //--------------------------------------------------------------------------- bool MProxyManager::InstanceIsValid() { return (ms_pmThis != NULL); } //--------------------------------------------------------------------------- MProxyManager* MProxyManager::get_Instance() { return ms_pmThis; } //--------------------------------------------------------------------------- MProxyManager::MProxyManager() { m_pmProxyHandlers = new ArrayList(); } //--------------------------------------------------------------------------- void MProxyManager::Do_Dispose(bool bDisposing) { if (bDisposing) { m_pmProxyHandlers->Clear(); if (m_pmProxyScene != NULL) { MSceneFactory::Instance->Remove(m_pmProxyScene); m_pmProxyScene = NULL; } // For some reason, __unhook causes bogus compilation errors here. // Thus, the events are unhooked manually. MEventManager::Instance->remove_SceneClosing(new MEventManager::__Delegate_SceneClosing(this, &MProxyManager::OnSceneClosing)); MEventManager::Instance->remove_NewSceneLoaded(new MEventManager::__Delegate_NewSceneLoaded(this, &MProxyManager::OnNewSceneLoaded)); MEventManager::Instance->remove_EntityAddedToScene(new MEventManager::__Delegate_EntityAddedToScene(this, &MProxyManager::OnEntityAddedToScene)); MEventManager::Instance->remove_EntityRemovedFromScene(new MEventManager::__Delegate_EntityRemovedFromScene(this, &MProxyManager::OnEntityRemovedFromScene)); MEventManager::Instance->remove_EntityComponentAdded(new MEventManager::__Delegate_EntityComponentAdded(this, &MProxyManager::OnEntityComponentAdded)); MEventManager::Instance->remove_EntityComponentRemoved(new MEventManager::__Delegate_EntityComponentRemoved(this, &MProxyManager::OnEntityComponentRemoved)); MEventManager::Instance->remove_EntityHiddenStateChanged(new MEventManager::__Delegate_EntityHiddenStateChanged(this, &MProxyManager::OnEntityHiddenStateChanged)); MEventManager::Instance->remove_EntityFrozenStateChanged(new MEventManager::__Delegate_EntityFrozenStateChanged(this, &MProxyManager::OnEntityFrozenStateChanged)); } } //--------------------------------------------------------------------------- void MProxyManager::Startup() { MVerifyValidInstance; InitProxies(); __hook(&MEventManager::SceneClosing, MEventManager::Instance, &MProxyManager::OnSceneClosing); __hook(&MEventManager::NewSceneLoaded, MEventManager::Instance, &MProxyManager::OnNewSceneLoaded); __hook(&MEventManager::EntityAddedToScene, MEventManager::Instance, &MProxyManager::OnEntityAddedToScene); __hook(&MEventManager::EntityRemovedFromScene, MEventManager::Instance, &MProxyManager::OnEntityRemovedFromScene); __hook(&MEventManager::EntityComponentAdded, MEventManager::Instance, &MProxyManager::OnEntityComponentAdded); __hook(&MEventManager::EntityComponentRemoved, MEventManager::Instance, &MProxyManager::OnEntityComponentRemoved); __hook(&MEventManager::EntityHiddenStateChanged, MEventManager::Instance, &MProxyManager::OnEntityHiddenStateChanged); __hook(&MEventManager::EntityFrozenStateChanged, MEventManager::Instance, &MProxyManager::OnEntityFrozenStateChanged); } //--------------------------------------------------------------------------- void MProxyManager::InitProxies() { MVerifyValidInstance; m_pmEntityToProxy = new Hashtable(); m_pmProxyScene = MSceneFactory::Instance->Get(NiNew NiScene("Proxy Scene", 10)); InitSFXProxy(); } //--------------------------------------------------------------------------- void MProxyManager::BuildProxyScene(MScene* pmScene) { MVerifyValidInstance; CommandService->BeginUndoFrame("Rebuild scene proxies"); MEntity* amSceneEntities[] = pmScene->GetEntities(); for (int i = 0; i < amSceneEntities->Length; i++) { CreateAndAddProxy(amSceneEntities[i]); // Create and add sfx proxy if entity is sfx [7/7/2009 hemeng] CreateAndAddSFXProxy(amSceneEntities[i]); } CommandService->EndUndoFrame(false); } //--------------------------------------------------------------------------- void MProxyManager::OnSceneClosing(MScene* pmScene) { MVerifyValidInstance; if (MFramework::Instance->Scene == pmScene) { MFramework::Instance->SceneFactory->Remove(m_pmProxyScene); InitProxies(); } } //--------------------------------------------------------------------------- void MProxyManager::OnNewSceneLoaded(MScene* pmScene) { MVerifyValidInstance; if (pmScene == MFramework::Instance->Scene) { BuildProxyScene(pmScene); } } //--------------------------------------------------------------------------- void MProxyManager::OnEntityAddedToScene(MScene* pmScene, MEntity* pmEntity) { MVerifyValidInstance; #ifdef _DEBUG MTimeStamp::Instance->AddTimeStamp(new String("Enter MProxyManager::OnEntityAddedToScene")); #endif if (pmScene == MFramework::Instance->Scene) { CreateAndAddProxy(pmEntity); // add sfx proxy if entity is sfx [7/7/2009 hemeng] CreateAndAddSFXProxy(pmEntity); } #ifdef _DEBUG MTimeStamp::Instance->AddTimeStamp(new String("Quit MProxyManager::OnEntityAddedToScene")); #endif } //--------------------------------------------------------------------------- void MProxyManager::OnEntityRemovedFromScene(MScene* pmScene, MEntity* pmEntity, bool bResolveDependencies) { MVerifyValidInstance; if (pmScene == MFramework::Instance->Scene) { RemoveProxy(pmEntity); } } //--------------------------------------------------------------------------- void MProxyManager::OnEntityComponentAdded(MEntity* pmEntity, MComponent* pmComponent) { MVerifyValidInstance; if (MFramework::Instance->Scene->IsEntityInScene(pmEntity)) { RemoveProxy(pmEntity); CreateAndAddProxy(pmEntity); // add sfx proxy if entity is sfx [7/7/2009 hemeng] CreateAndAddSFXProxy(pmEntity); } } //--------------------------------------------------------------------------- void MProxyManager::OnEntityComponentRemoved(MEntity* pmEntity, MComponent* pmComponent) { MVerifyValidInstance; if (MFramework::Instance->Scene->IsEntityInScene(pmEntity)) { RemoveProxy(pmEntity); CreateAndAddProxy(pmEntity); // add sfx proxy if entity is sfx [7/7/2009 hemeng] CreateAndAddSFXProxy(pmEntity); } } //--------------------------------------------------------------------------- void MProxyManager::OnEntityHiddenStateChanged(MEntity* pmEntity, bool bHidden) { MVerifyValidInstance; if (MFramework::Instance->Scene->IsEntityInScene(pmEntity)) { ProcessHiddenStateChange(pmEntity, bHidden); } } //--------------------------------------------------------------------------- void MProxyManager::OnEntityFrozenStateChanged(MEntity* pmEntity, bool bFrozen) { MVerifyValidInstance; if (MFramework::Instance->Scene->IsEntityInScene(pmEntity)) { ProcessFrozenStateChange(pmEntity, bFrozen); } } //--------------------------------------------------------------------------- void MProxyManager::ProcessHiddenStateChange(MEntity* pmEntity, bool bHidden) { MVerifyValidInstance; MEntity* pmProxy = GetProxyForEntity(pmEntity); if (pmProxy != NULL) { pmProxy->Hidden = bHidden; } } //--------------------------------------------------------------------------- void MProxyManager::ProcessFrozenStateChange(MEntity* pmEntity, bool bFrozen) { MVerifyValidInstance; MEntity* pmProxy = GetProxyForEntity(pmEntity); if (pmProxy != NULL) { pmProxy->Frozen = bFrozen; } } //--------------------------------------------------------------------------- void MProxyManager::UpdateProxyScales(MViewport* pmViewport) { NiCamera* pkCamera = pmViewport->GetNiCamera(); // iterate through all known proxy components and call UpdateScale MEntity* amProxies[] = m_pmProxyScene->GetEntities(); for (int i = 0; i < amProxies->Count; i++) { MComponent* amComponents[] = amProxies[i]->GetComponents(); for (int j = 0; j < amComponents->Count; j++) { NiEntityComponentInterface* pkComponent = amComponents[j]->GetNiEntityComponentInterface(); if ((pkComponent->GetClassName() == NiProxyComponent::ClassName()) || (pkComponent->GetClassName() == NiLightProxyComponent::ClassName())) { NiProxyComponent* pkProxy = (NiProxyComponent*)pkComponent; if (pkProxy) { pkProxy->UpdateScale(pkCamera); } } } } } //--------------------------------------------------------------------------- MEntity* MProxyManager::CreateProxy(MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmEntity != NULL, "Null entity provided to function!"); MEntity* pmMasterProxy; for (int i = 0; i < m_pmProxyHandlers->get_Count(); i++) { IProxyHandler* pkHandler = dynamic_cast( m_pmProxyHandlers->get_Item(i)); if (pkHandler) { pmMasterProxy = pkHandler->GetMasterProxyEntity(pmEntity); if (pmMasterProxy) break; } } MEntity* pmProxy; if (pmMasterProxy != NULL) { String* strProxyName = m_pmProxyScene->GetUniqueEntityName( String::Format("{0} - {1}", pmMasterProxy->Name, pmEntity->Name)); pmProxy = pmMasterProxy->Clone(strProxyName, false); pmProxy->SetPropertyData(ms_strSourceEntityName, pmEntity, false); pmProxy->SetHidden(pmEntity->Hidden, false); pmProxy->SetFrozen(pmEntity->Frozen, false); } return pmProxy; } MEntity* MProxyManager::CreateSFXProxy(MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmEntity != NULL, "Null entity provided to function!"); if (!IsEntitySFX(pmEntity)) { return NULL; } MEntity* pmProxy = NULL; if (m_pmSFXProxy != NULL) { String* strProxyName = m_pmProxyScene->GetUniqueEntityName( String::Format("{0} - {1}", m_pmSFXProxy->Name, pmEntity->Name)); pmProxy = m_pmSFXProxy->Clone(strProxyName, false); pmProxy->SetPropertyData(ms_strSourceEntityName, pmEntity, false); pmProxy->SetHidden(pmEntity->Hidden, false); pmProxy->SetFrozen(pmEntity->Frozen, false); } return pmProxy; } //--------------------------------------------------------------------------- void MProxyManager::AddProxy(MEntity* pmProxy, MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmProxy != NULL, "Null proxy provided to function!"); MAssert(pmEntity != NULL, "Null entity provided to function!"); if (!m_pmEntityToProxy->Contains(pmEntity)) { // Add proxy to proxy scene. bool bSuccess = m_pmProxyScene->AddEntity(pmProxy, false); MAssert(bSuccess, "Add to proxy scene failed!"); // Add proxy to hashtable. m_pmEntityToProxy->Add(pmEntity, pmProxy); } } //--------------------------------------------------------------------------- void MProxyManager::CreateAndAddProxy(MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmEntity != NULL, "Null entity provided to function!"); MEntity* pmProxy = CreateProxy(pmEntity); if (pmProxy != NULL) { AddProxy(pmProxy, pmEntity); } } //--------------------------------------------------------------------------- void MProxyManager::CreateAndAddSFXProxy(MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmEntity != NULL, "Null entity provided to function!"); MEntity* pmProxy = CreateSFXProxy(pmEntity); if (pmProxy != NULL) { AddProxy(pmProxy, pmEntity); } } //--------------------------------------------------------------------------- bool MProxyManager::InitSFXProxy() { if (m_pmSFXProxy) { return true; } NiDefaultErrorHandlerPtr spErrors; NiUniqueID kTemplateID; MUtility::GuidToID(Guid::NewGuid(), kTemplateID); NiEntityInterfaceIPtr spDummyEntity = NULL; MUtility::GuidToID(Guid::NewGuid(), kTemplateID); NiEntityInterfaceIPtr spEntity = NiNew NiGeneralEntity("SFX Proxy", kTemplateID, 2); bool bSuccess = NIBOOL_IS_TRUE(spEntity->AddComponent(NiNew NiProxyComponent(spDummyEntity, NULL))); if (bSuccess) { const char* pcAppStartupPath = MStringToCharPointer(MFramework::Instance->AppStartupPath); char acAbsGeomPath[NI_MAX_PATH]; size_t stSize = NiPath::ConvertToAbsolute(acAbsGeomPath, NI_MAX_PATH, ".\\AppData\\sfx_sgin.nif", pcAppStartupPath); NIASSERT(stSize > 0); bSuccess = NIBOOL_IS_TRUE(spEntity->AddComponent(NiNew NiSceneGraphComponent(acAbsGeomPath))); if (bSuccess) { m_pmSFXProxy = MEntityFactory::Instance->Get(spEntity); m_pmSFXProxy->SetPropertyData("Source Entity", NULL, false); } else { if (!spErrors) { spErrors = NiNew NiDefaultErrorHandler(2); } spErrors->ReportError("Error creating sfx proxy entity;" " light proxy geometry will not be shown.", NULL, NULL, NULL); bSuccess = false; } MFreeCharPointer(pcAppStartupPath); } else { if (!spErrors) { spErrors = NiNew NiDefaultErrorHandler(2); } spErrors->ReportError("Error creating sfx proxy entity; light " "proxy geometry will not be shown.", NULL, NULL, NULL); bSuccess = false; } if (spErrors) { MUtility::AddErrorInterfaceMessages(MessageChannelType::Errors, spErrors); bSuccess = false; } return bSuccess; } //--------------------------------------------------------------------------- void MProxyManager::RemoveProxy(MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmEntity != NULL, "Null entity provided to function!"); if (m_pmEntityToProxy->Contains(pmEntity)) { MEntity* pmProxy = dynamic_cast(m_pmEntityToProxy->Item[ pmEntity]); MAssert(pmProxy != NULL, "Proxy not found in hashtable!"); // Remove proxy from proxy scene. m_pmProxyScene->RemoveEntity(pmProxy, false, false);//true // Remove proxy from hashtable. m_pmEntityToProxy->Remove(pmEntity); } } //--------------------------------------------------------------------------- MEntity* MProxyManager::GetProxyForEntity(MEntity* pmEntity) { MVerifyValidInstance; MAssert(pmEntity != NULL, "Null entity provided to function!"); return dynamic_cast(m_pmEntityToProxy->Item[pmEntity]); } //--------------------------------------------------------------------------- MScene* MProxyManager::get_ProxyScene() { MVerifyValidInstance; return m_pmProxyScene; } //--------------------------------------------------------------------------- void MProxyManager::AddProxyHandler(IProxyHandler* pkHandler) { MVerifyValidInstance; m_pmProxyHandlers->Add(pkHandler); } //--------------------------------------------------------------------------- void MProxyManager::RemoveProxyHandler(IProxyHandler* pkHandler) { MVerifyValidInstance; m_pmProxyHandlers->Remove(pkHandler); } //--------------------------------------------------------------------------- IProxyHandler* MProxyManager::GetProxyArray()[] { MVerifyValidInstance; return dynamic_cast( m_pmProxyHandlers->ToArray(__typeof(IProxyHandler))); } //--------------------------------------------------------------------------- MEntity* MProxyManager::CreateGenericMasterProxyEntity( String* pmFilename, String* pmEntityName, bool bSizeRelativeToCamera) { if (!pmFilename || !pmEntityName) return NULL; MEntity* pmMasterProxy = NULL; NiDefaultErrorHandlerPtr spErrors; NiUniqueID kTemplateID; MUtility::GuidToID(Guid::NewGuid(), kTemplateID); NiEntityInterfaceIPtr spEntity = NULL; bool bSuccess = false; MUtility::GuidToID(Guid::NewGuid(), kTemplateID); const char* pcEntityName = MStringToCharPointer(pmEntityName); spEntity = NiNew NiGeneralEntity(pcEntityName, kTemplateID, 2); MFreeCharPointer(pcEntityName); if (bSizeRelativeToCamera) { bSuccess = NIBOOL_IS_TRUE(spEntity->AddComponent(NiNew NiProxyComponent(NULL, NULL))); } else { bSuccess = NIBOOL_IS_TRUE(spEntity->AddComponent(NiNew NiInheritedTransformationComponent(NULL, NULL))); } if (bSuccess) { const char* pcFilename = MStringToCharPointer(pmFilename); if (!pcFilename) return false; char acAbsGeomPath[NI_MAX_PATH]; if (!NiPath::IsUniqueAbsolute(pcFilename)) { const char* pcAppStartupPath = MStringToCharPointer(MFramework::Instance->AppStartupPath); size_t stSize = NiPath::ConvertToAbsolute(acAbsGeomPath, NI_MAX_PATH, pcFilename, pcAppStartupPath); NIASSERT(stSize > 0); MFreeCharPointer(pcAppStartupPath); } else { NiStrcpy(acAbsGeomPath, NI_MAX_PATH, pcFilename); } MFreeCharPointer(pcFilename); bSuccess = NIBOOL_IS_TRUE(spEntity->AddComponent(NiNew NiSceneGraphComponent(acAbsGeomPath))); if (bSuccess) { pmMasterProxy = MEntityFactory::Instance->Get(spEntity); pmMasterProxy->SetPropertyData("Source Entity", NULL, false); } else { if (!spErrors) { spErrors = NiNew NiDefaultErrorHandler(1); } spErrors->ReportError("Error creating camera proxy entity; " "camera proxy geometry will not be shown.", NULL, NULL, NULL); } } else { if (!spErrors) { spErrors = NiNew NiDefaultErrorHandler(1); } spErrors->ReportError("Error creating camera proxy entity; camera " "proxy geometry will not be shown.", NULL, NULL, NULL); } if (spErrors) { MUtility::AddErrorInterfaceMessages(MessageChannelType::Errors, spErrors); } return pmMasterProxy; } //--------------------------------------------------------------------------- ICommandService* MProxyManager::get_CommandService() { if (ms_pmCommandService == NULL) { ms_pmCommandService = MGetService(ICommandService); MAssert(ms_pmCommandService != NULL, "Command service not found!"); } return ms_pmCommandService; } //----------------------------------------------------------------------------------------- bool MProxyManager::IsEntitySFX(MEntity* pmEntity) { NIASSERT(pmEntity); String* strEntityName = pmEntity->Name; if (strEntityName != NULL) { // 检查文件名5、6位是否为04 if (strEntityName->Length < 9) { return false; } String* strSub = strEntityName->Substring(4,2); if (strSub->Equals("04")) { return true; } else { return false; } } return false; }