This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View File

@@ -0,0 +1,495 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
// File name: PrefabObject.cpp
// Version: v1.00
// Created: 13/11/2003 by Timur.
// Compilers: Visual Studio.NET 2003
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "PrefabObject.h"
#include "ObjectManager.h"
#include "Prefabs\PrefabManager.h"
#include "Prefabs\PrefabItem.h"
#include "PrefabPanel.h"
#include "..\Viewport.h"
#include "..\DisplaySettings.h"
#include "Settings.h"
//////////////////////////////////////////////////////////////////////////
// CPrefabObject implementation.
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CPrefabObject,CBaseObject)
namespace
{
int s_rollupId = 0;
CPrefabPanel *s_panel = 0;
}
//////////////////////////////////////////////////////////////////////////
CPrefabObject::CPrefabObject()
{
SetColor( RGB(255,220,0) ); // Yellowish
ZeroStruct(m_prefabGUID);
m_bbox.min = m_bbox.max = Vec3(0,0,0);
m_bBBoxValid = false;
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::Done()
{
GetIEditor()->SuspendUndo();
DeleteAllPrefabObjects();
GetIEditor()->ResumeUndo();
CBaseObject::Done();
ZeroStruct(m_prefabGUID);
m_prefabName = "";
m_pPrefabItem = 0;
}
//////////////////////////////////////////////////////////////////////////
bool CPrefabObject::Init( IEditor *ie,CBaseObject *prev,const CString &file )
{
bool res = CBaseObject::Init( ie,prev,file );
if (prev)
{
// Cloning.
SetPrefab( ((CPrefabObject*)prev)->m_pPrefabItem,false );
}
else if (!file.IsEmpty())
{
SetPrefab( GuidUtil::FromString(file),false );
}
return res;
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::BeginEditParams( IEditor *ie,int flags )
{
CBaseObject::BeginEditParams( ie,flags );
if (!s_panel)
{
s_panel = new CPrefabPanel;
s_rollupId = ie->AddRollUpPage( ROLLUP_OBJECTS,"Prefab Parameters",s_panel );
}
if (s_panel)
s_panel->SetObject( this );
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::EndEditParams( IEditor *ie )
{
if (s_panel)
{
ie->RemoveRollUpPage( ROLLUP_OBJECTS,s_rollupId );
}
s_rollupId = 0;
s_panel = 0;
CBaseObject::EndEditParams( ie );
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::GetBoundBox( BBox &box )
{
if (!m_bBBoxValid)
CalcBoundBox();
box = m_bbox;
box.Transform( GetWorldTM() );
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::GetLocalBounds( BBox &box )
{
if (!m_bBBoxValid)
CalcBoundBox();
box = m_bbox;
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::Display( DisplayContext &dc )
{
DrawDefault(dc,GetColor());
dc.PushMatrix( GetWorldTM() );
bool bSelected = IsSelected();
if (bSelected)
{
dc.SetSelectedColor();
dc.DrawWireBox( m_bbox.min,m_bbox.max );
int rstate = dc.ClearStateFlag( GS_DEPTHWRITE );
dc.SetSelectedColor( 0.2f );
dc.DrawSolidBox( m_bbox.min,m_bbox.max );
dc.SetState( rstate );
}
else
{
if (gSettings.viewports.bAlwaysDrawPrefabBox)
{
if (IsFrozen())
dc.SetFreezeColor();
else
dc.SetColor( GetColor(),0.2f );
int rstate = dc.ClearStateFlag( GS_DEPTHWRITE );
dc.DrawSolidBox( m_bbox.min,m_bbox.max );
dc.SetState( rstate );
}
if (IsFrozen())
dc.SetFreezeColor();
else
dc.SetColor( GetColor() );
dc.DrawWireBox( m_bbox.min,m_bbox.max );
}
dc.PopMatrix();
if (bSelected || gSettings.viewports.bAlwaysDrawPrefabInternalObjects || IsHighlighted())
{
if (HaveChilds())
{
int numObjects = GetChildCount();
for (int i = 0; i < numObjects; i++)
{
RecursivelyDisplayObject( GetChild(i),dc );
}
}
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::RecursivelyDisplayObject( CBaseObject *obj,DisplayContext &dc )
{
if (!obj->CheckFlags(OBJFLAG_PREFAB))
return;
BBox bbox;
obj->GetBoundBox( bbox );
if (dc.flags & DISPLAY_2D)
{
if (dc.box.IsIntersectBox( bbox ))
{
obj->Display( dc );
}
}
else
{
if (dc.camera && dc.camera->IsAABBVisibleFast( AABB(bbox.min,bbox.max) ))
//if (camera.CheckOverlap(AABB(bbox.min,bbox.max)) != CULL_EXCLUSION)
{
obj->Display( dc );
}
}
//////////////////////////////////////////////////////////////////////////
int numObjects = obj->GetChildCount();
for (int i = 0; i < numObjects; i++)
{
RecursivelyDisplayObject( obj->GetChild(i),dc );
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::Serialize( CObjectArchive &ar )
{
CBaseObject::Serialize( ar );
if (ar.bLoading)
{
// Loading.
CString prefabName = m_prefabName;
GUID prefabGUID = m_prefabGUID;
ar.node->getAttr( "PrefabName",prefabName );
ar.node->getAttr( "PrefabGUID",prefabGUID );
SetPrefab( prefabGUID,false );
}
else
{
ar.node->setAttr( "PrefabGUID",m_prefabGUID );
ar.node->setAttr( "PrefabName",m_prefabName );
}
}
//////////////////////////////////////////////////////////////////////////
XmlNodeRef CPrefabObject::Export( const CString &levelPath,XmlNodeRef &xmlNode )
{
// Do not export.
return 0;
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::OnEvent( ObjectEvent event )
{
switch (event)
{
case EVENT_PREFAB_REMAKE:
if (m_pPrefabItem)
SetPrefab( m_pPrefabItem,true );
break;
};
CBaseObject::OnEvent( event );
}
//////////////////////////////////////////////////////////////////////////
inline void RecursivelyGetAllPrefabChilds( CBaseObject *obj,std::vector<CBaseObjectPtr> &childs )
{
for (int i = 0; i < obj->GetChildCount(); i++)
{
CBaseObject *c = obj->GetChild(i);
if (c->CheckFlags(OBJFLAG_PREFAB))
{
childs.push_back(c);
RecursivelyGetAllPrefabChilds( c,childs );
}
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::DeleteAllPrefabObjects()
{
std::vector<CBaseObjectPtr> childs;
RecursivelyGetAllPrefabChilds( this,childs );
for (int i = 0; i < childs.size(); i++)
{
GetObjectManager()->DeleteObject(childs[i]);
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::SetPrefab( REFGUID guid,bool bForceReload )
{
if (m_prefabGUID == guid && bForceReload == false)
return;
m_prefabGUID = guid;
//m_fullPrototypeName = prototypeName;
CPrefabManager *pManager = GetIEditor()->GetPrefabManager();
CPrefabItem *pPrefab = (CPrefabItem*)pManager->FindItem( guid );
if (pPrefab)
{
SetPrefab( pPrefab,bForceReload );
}
else
{
if (m_prefabName.IsEmpty())
m_prefabName = "Unknown Prefab";
CErrorRecord err;
err.error.Format( "Cannot find Prefab %s with GUID: %s for Object %s",(const char*)m_prefabName,GuidUtil::ToString(guid),(const char*)GetName() );
err.pObject = this;
err.severity = CErrorRecord::ESEVERITY_WARNING;
GetIEditor()->GetErrorReport()->ReportError(err);
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::SetPrefab( CPrefabItem *pPrefab,bool bForceReload )
{
assert( pPrefab );
if (pPrefab == m_pPrefabItem && !bForceReload)
return;
StoreUndo( "Set Prefab" );
// Delete all child objects.
DeleteAllPrefabObjects();
m_pPrefabItem = pPrefab;
m_prefabGUID = pPrefab->GetGUID();
m_prefabName = pPrefab->GetFullName();
// Make objects from this prefab.
XmlNodeRef objects = pPrefab->GetObjectsNode();
if (!objects)
{
CErrorRecord err;
err.error.Format( "Prefab %s does not contain objects",(const char*)m_prefabName );
err.pObject = this;
err.severity = CErrorRecord::ESEVERITY_WARNING;
GetIEditor()->GetErrorReport()->ReportError(err);
return;
}
CObjectLayer *pThisLayer = GetLayer();
//////////////////////////////////////////////////////////////////////////
// Spawn objects.
//////////////////////////////////////////////////////////////////////////
CObjectArchive ar( GetObjectManager(),objects,true );
ar.MakeNewIds( true );
int numObjects = objects->getChildCount();
for (int i = 0; i < numObjects; i++)
{
ar.node = objects->getChild(i);
CBaseObject *obj = ar.LoadObject( ar.node );
if (obj)
{
AttachChild( obj,false );
RecursivelySetObjectInPrefab( obj );
}
}
InvalidateBBox();
}
//////////////////////////////////////////////////////////////////////////
CPrefabItem* CPrefabObject::GetPrefab() const
{
return m_pPrefabItem;
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::RecursivelySetObjectInPrefab( CBaseObject *object )
{
object->SetFlags( OBJFLAG_PREFAB );
object->SetLayer( GetLayer() );
int numChilds = object->GetChildCount();
for (int i = 0; i < numChilds; i++)
{
RecursivelySetObjectInPrefab( object->GetChild(i) );
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::PostClone( CBaseObject *pFromObject,CObjectCloneContext &ctx )
{
CBaseObject *pFromParent = pFromObject->GetParent();
if (pFromParent)
{
CBaseObject *pChildParent = ctx.FindClone( pFromParent );
if (pChildParent)
pChildParent->AttachChild( this,false );
else
pFromParent->AttachChild( this,false );
}
}
//////////////////////////////////////////////////////////////////////////
bool CPrefabObject::HitTest( HitContext &hc )
{
Vec3 pnt;
Vec3 raySrc = hc.raySrc;
Vec3 rayDir = hc.rayDir;
Matrix44 invertTM = GetWorldTM();
invertTM.Invert44();
raySrc = invertTM.TransformPointOLD( raySrc );
rayDir = GetNormalized( invertTM.TransformVectorOLD( rayDir ) );
if (m_bbox.IsIntersectRay( raySrc,rayDir,pnt ))
{
// World space distance.
float dist = GetDistance(hc.raySrc, GetWorldTM().TransformPointOLD(pnt));
hc.dist = dist;
hc.object = this;
return true;
}
return false;
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::ExtractAll()
{
int i;
// Clone all child objects.
CSelectionGroup sel;
for (i = 0; i < GetChildCount(); i++)
{
sel.AddObject( GetChild(i) );
}
CSelectionGroup newSel;
sel.Clone( newSel );
GetIEditor()->ClearSelection();
for (i = 0; i < newSel.GetCount(); i++)
{
CBaseObject *pClone = newSel.GetObject(i);
pClone->DetachThis(); // Detach from parent.
GetIEditor()->SelectObject( pClone );
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::ExtractObject( CBaseObject *pObj )
{
int i;
// Clone all child objects.
CSelectionGroup sel;
sel.AddObject( pObj );
CSelectionGroup newSel;
sel.Clone( newSel );
GetIEditor()->ClearSelection();
for (i = 0; i < newSel.GetCount(); i++)
{
CBaseObject *pClone = newSel.GetObject(i);
pClone->DetachThis(); // Detach from parent.
GetIEditor()->SelectObject( pClone );
}
}
//////////////////////////////////////////////////////////////////////////
inline void RecursivelyGetPrefabBoundBox( CBaseObject *object,BBox &box )
{
BBox b;
object->GetBoundBox( b );
box.Add(b.min);
box.Add(b.max);
int numChilds = object->GetChildCount();
for (int i = 0; i < numChilds; i++)
{
if (object->GetChild(i)->CheckFlags(OBJFLAG_PREFAB))
RecursivelyGetPrefabBoundBox( object->GetChild(i),box );
}
}
//////////////////////////////////////////////////////////////////////////
void CPrefabObject::CalcBoundBox()
{
Matrix44 ltm = GetLocalTM();
Matrix44 tm;
tm.SetIdentity();
SetWorldTM(tm);
// Calc local bounds box..
BBox box;
box.Reset();
int numChilds = GetChildCount();
for (int i = 0; i < numChilds; i++)
{
if (GetChild(i)->CheckFlags(OBJFLAG_PREFAB))
RecursivelyGetPrefabBoundBox( GetChild(i),box );
}
if (numChilds == 0)
{
box.min = Vec3(-1,-1,-1);
box.max = Vec3(1,1,1);
}
SetLocalTM(ltm);
m_bbox = box;
m_bBBoxValid = true;
}