diff --git a/PrimeWorldEditor.pro b/PrimeWorldEditor.pro index aafb21bc..58bef807 100644 --- a/PrimeWorldEditor.pro +++ b/PrimeWorldEditor.pro @@ -156,7 +156,8 @@ SOURCES += \ Scene/script/CPointOfInterestExtra.cpp \ Scene/script/CScriptExtra.cpp \ Scene/script/CSpacePirateExtra.cpp \ - Scene/script/CWaypointExtra.cpp + Scene/script/CWaypointExtra.cpp \ + Scene/script/CDoorExtra.cpp HEADERS += \ Common/AnimUtil.h \ @@ -328,7 +329,8 @@ HEADERS += \ Scene/script/CScriptExtra.h \ Scene/script/CPointOfInterestExtra.h \ Scene/script/CSpacePirateExtra.h \ - Scene/script/CWaypointExtra.h + Scene/script/CWaypointExtra.h \ + Scene/script/CDoorExtra.h FORMS += \ UI/CStartWindow.ui \ diff --git a/Scene/script/CDoorExtra.cpp b/Scene/script/CDoorExtra.cpp new file mode 100644 index 00000000..ace70114 --- /dev/null +++ b/Scene/script/CDoorExtra.cpp @@ -0,0 +1,126 @@ +#include "CDoorExtra.h" +#include + +CDoorExtra::CDoorExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent) + : CScriptExtra(pInstance, pScene, pParent) + , mpShieldModelProp(nullptr) + , mpShieldColorProp(nullptr) + , mpShieldModel(nullptr) +{ + CPropertyStruct *pBaseStruct = pInstance->Properties(); + + mpShieldModelProp = (CFileProperty*) pBaseStruct->PropertyByID(0xB20CC271); + if (mpShieldModelProp && (mpShieldModelProp->Type() != eFileProperty)) + mpShieldModelProp = nullptr; + + mpShieldColorProp = (CColorProperty*) pBaseStruct->PropertyByID(0x47B4E863); + if (mpShieldColorProp && (mpShieldColorProp->Type() != eColorProperty)) + mpShieldColorProp = nullptr; + + if (mpShieldModelProp) + PropertyModified(mpShieldModelProp); +} + +void CDoorExtra::PropertyModified(CPropertyBase *pProperty) +{ + if (pProperty == mpShieldModelProp) + { + mpShieldModel = (CModel*) mpShieldModelProp->Get(); + + if (mpShieldModel && mpShieldModel->Type() == eModel) + { + mModelToken = CToken(mpShieldModel); + mLocalAABox = mpShieldModel->AABox(); + } + + else + { + mpShieldModel = nullptr; + mModelToken.Unlock(); + mLocalAABox = CAABox::skInfinite; + } + + MarkTransformChanged(); + } +} + +void CDoorExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) +{ + if (!mpShieldModel) return; + + if (mpParent->IsVisible() && ViewInfo.ViewFrustum.BoxInFrustum(AABox())) + { + if (mpShieldModel->HasTransparency(0)) + AddSurfacesToRenderer(pRenderer, mpShieldModel, 0, ViewInfo); + else + pRenderer->AddOpaqueMesh(this, -1, AABox(), eDrawMesh); + + if (mpParent->IsSelected()) + pRenderer->AddOpaqueMesh(this, -1, AABox(), eDrawSelection); + } +} + +void CDoorExtra::Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo) +{ + LoadModelMatrix(); + mpParent->LoadLights(ViewInfo); + + CGraphics::SetupAmbientColor(); + CGraphics::UpdateVertexBlock(); + + CColor Tint = mpParent->TintColor(ViewInfo); + + if (mpShieldColorProp) + Tint *= mpShieldColorProp->Get(); + + CGraphics::sPixelBlock.TintColor = Tint.ToVector4f(); + CGraphics::sPixelBlock.TevColor = CColor::skWhite.ToVector4f(); + CGraphics::UpdatePixelBlock(); + + if (ComponentIndex < 0) + mpShieldModel->Draw(Options, 0); + else + mpShieldModel->DrawSurface(Options, ComponentIndex, 0); +} + +void CDoorExtra::DrawSelection() +{ + LoadModelMatrix(); + glBlendFunc(GL_ONE, GL_ZERO); + mpShieldModel->DrawWireframe(eNoRenderOptions, mpParent->WireframeColor()); +} + +void CDoorExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester) +{ + if (!mpShieldModel) return; + + const CRay& Ray = Tester.Ray(); + std::pair BoxResult = AABox().IntersectsRay(Ray); + + if (BoxResult.first) + Tester.AddNodeModel(this, mpShieldModel); +} + +SRayIntersection CDoorExtra::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo) +{ + ERenderOptions Options = ViewInfo.pRenderer->RenderOptions(); + + SRayIntersection out; + out.pNode = mpParent; + out.AssetIndex = AssetID; + + CRay TransformedRay = Ray.Transformed(Transform().Inverse()); + std::pair Result = mpShieldModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((Options & eEnableBackfaceCull) == 0)); + + if (Result.first) + { + out.Hit = true; + CVector3f HitPoint = TransformedRay.PointOnRay(Result.second); + CVector3f WorldHitPoint = Transform() * HitPoint; + out.Distance = Ray.Origin().Distance(WorldHitPoint); + } + + else out.Hit = false; + + return out; +} diff --git a/Scene/script/CDoorExtra.h b/Scene/script/CDoorExtra.h new file mode 100644 index 00000000..96726978 --- /dev/null +++ b/Scene/script/CDoorExtra.h @@ -0,0 +1,25 @@ +#ifndef CDOOREXTRA_H +#define CDOOREXTRA_H + +#include "CScriptExtra.h" + +class CDoorExtra : public CScriptExtra +{ + // Render colored door shield in MP2/3 + CFileProperty *mpShieldModelProp; + CColorProperty *mpShieldColorProp; + + CModel *mpShieldModel; + CToken mModelToken; + +public: + explicit CDoorExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0); + void PropertyModified(CPropertyBase *pProperty); + void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); + void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); + void DrawSelection(); + void RayAABoxIntersectTest(CRayCollisionTester &Tester); + SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); +}; + +#endif // CDOOREXTRA_H diff --git a/Scene/script/CScriptExtra.cpp b/Scene/script/CScriptExtra.cpp index bba781da..f4d9a79e 100644 --- a/Scene/script/CScriptExtra.cpp +++ b/Scene/script/CScriptExtra.cpp @@ -3,6 +3,7 @@ #include "CWaypointExtra.h" #include "CSpacePirateExtra.h" #include "CPointOfInterestExtra.h" +#include "CDoorExtra.h" CScriptExtra* CScriptExtra::CreateExtra(CScriptNode *pNode) { @@ -32,6 +33,10 @@ CScriptExtra* CScriptExtra::CreateExtra(CScriptNode *pNode) case 0x504F494E: // "POIN" PointOfInterest (MP2/MP3) pExtra = new CPointOfInterestExtra(pObj, pNode->Scene(), pNode); break; + + case 0x444F4F52: // "DOOR" Door (MP2/MP3) + pExtra = new CDoorExtra(pObj, pNode->Scene(), pNode); + break; } }