PrimeWorldEditor/src/Core/Scene/CScriptAttachNode.cpp

160 lines
4.8 KiB
C++

#include "CScriptAttachNode.h"
#include "CScriptNode.h"
#include "Core/Render/CRenderer.h"
#include "Core/Resource/Script/Property/IProperty.h"
#include <Common/Macros.h>
CScriptAttachNode::CScriptAttachNode(CScene *pScene, const SAttachment& rkAttachment, CScriptNode *pParent)
: CSceneNode(pScene, -1, pParent)
, mpScriptNode(pParent)
, mAttachType(rkAttachment.AttachType)
, mLocatorName(rkAttachment.LocatorName)
{
CStructProperty* pBaseStruct = pParent->Template()->Properties();
mpAttachAssetProp = pBaseStruct->ChildByIDString(rkAttachment.AttachProperty);
mAttachAssetRef = CAssetRef(pParent->Instance()->PropertyData(), mpAttachAssetProp);
mAttachAnimSetRef = CAnimationSetRef(pParent->Instance()->PropertyData(), mpAttachAssetProp);
if (mpAttachAssetProp) AttachPropertyModified();
ParentDisplayAssetChanged(mpScriptNode->DisplayAsset());
}
void CScriptAttachNode::AttachPropertyModified()
{
if (mpAttachAssetProp)
{
if (mAttachAssetRef.IsValid())
mpAttachAsset = gpResourceStore->LoadResource<CModel>(mAttachAssetRef.Get());
else if (mAttachAnimSetRef.IsValid())
mpAttachAsset = mAttachAnimSetRef.Get().AnimSet();
CModel* pModel = Model();
if (pModel && pModel->Type() == EResourceType::Model)
mLocalAABox = pModel->AABox();
else
mLocalAABox = CAABox::skInfinite;
MarkTransformChanged();
}
}
void CScriptAttachNode::ParentDisplayAssetChanged(CResource* pNewDisplayAsset)
{
if (pNewDisplayAsset->Type() == EResourceType::AnimSet)
{
CSkeleton* pSkel = mpScriptNode->ActiveSkeleton();
mpLocator = pSkel->BoneByName(mLocatorName);
}
else
{
mpLocator = nullptr;
}
MarkTransformChanged();
}
CModel* CScriptAttachNode::Model() const
{
if (mpAttachAsset)
{
if (mpAttachAsset->Type() == EResourceType::Model)
return static_cast<CModel*>(mpAttachAsset.RawPointer());
else if (mpAttachAsset->Type() == EResourceType::AnimSet)
return mAttachAnimSetRef.Get().GetCurrentModel();
}
return nullptr;
}
void CScriptAttachNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo)
{
CModel *pModel = Model();
if (!pModel) return;
if (rkViewInfo.ViewFrustum.BoxInFrustum(AABox()))
{
AddModelToRenderer(pRenderer, pModel, 0);
if (mpParent->IsSelected() && !rkViewInfo.GameMode)
pRenderer->AddMesh(this, -1, AABox(), false, ERenderCommand::DrawSelection);
}
}
void CScriptAttachNode::Draw(FRenderOptions Options, int /*ComponentIndex*/, ERenderCommand Command, const SViewInfo& rkViewInfo)
{
LoadModelMatrix();
mpParent->LoadLights(rkViewInfo);
CGraphics::SetupAmbientColor();
CGraphics::UpdateVertexBlock();
CGraphics::sPixelBlock.TintColor = mpParent->TintColor(rkViewInfo);
CGraphics::sPixelBlock.SetAllTevColors(CColor::skWhite);
CGraphics::UpdatePixelBlock();
DrawModelParts(Model(), Options, 0, Command);
}
void CScriptAttachNode::DrawSelection()
{
LoadModelMatrix();
glBlendFunc(GL_ONE, GL_ZERO);
Model()->DrawWireframe(ERenderOption::None, mpParent->WireframeColor());
}
void CScriptAttachNode::RayAABoxIntersectTest(CRayCollisionTester& rTester, const SViewInfo& /*rkViewInfo*/)
{
CModel *pModel = Model();
if (!pModel) return;
const CRay& rkRay = rTester.Ray();
std::pair<bool,float> BoxResult = AABox().IntersectsRay(rkRay);
if (BoxResult.first)
rTester.AddNodeModel(this, pModel);
}
SRayIntersection CScriptAttachNode::RayNodeIntersectTest(const CRay& rkRay, uint32 AssetID, const SViewInfo& rkViewInfo)
{
FRenderOptions Options = rkViewInfo.pRenderer->RenderOptions();
SRayIntersection Out;
Out.pNode = mpParent;
Out.ComponentIndex = AssetID;
CRay TransformedRay = rkRay.Transformed(Transform().Inverse());
std::pair<bool,float> Result = Model()->GetSurface(AssetID)->IntersectsRay(TransformedRay, Options.HasFlag(ERenderOption::EnableBackfaceCull));
if (Result.first)
{
Out.Hit = true;
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second);
CVector3f WorldHitPoint = Transform() * HitPoint;
Out.Distance = rkRay.Origin().Distance(WorldHitPoint);
}
else Out.Hit = false;
return Out;
}
// ************ PROTECTED ************
void CScriptAttachNode::CalculateTransform(CTransform4f& rOut) const
{
// Apply our local transform
rOut.Scale(LocalScale());
rOut.Rotate(LocalRotation());
rOut.Translate(LocalPosition());
// Apply bone transform
if (mpLocator)
rOut = mpScriptNode->BoneTransform(mpLocator->ID(), mAttachType, false) * rOut;
// Apply parent transform
if (mpParent)
rOut = mpParent->Transform() * rOut;
}