From 9f7e304e41d20e01752e562a791edd94714d5e74 Mon Sep 17 00:00:00 2001 From: parax0 Date: Sat, 28 Nov 2015 11:37:22 -0700 Subject: [PATCH] Added CDamageableTriggerExtra --- Common/CRayCollisionTester.cpp | 6 +- Common/SRayIntersection.h | 6 +- Core/CSceneManager.cpp | 2 +- PrimeWorldEditor.pro | 6 +- Resource/CMaterial.cpp | 20 ++ Resource/CMaterial.h | 1 + Resource/CMaterialPass.cpp | 1 + Resource/CMaterialPass.h | 1 + Scene/CLightNode.cpp | 4 +- Scene/CLightNode.h | 2 +- Scene/CModelNode.cpp | 4 +- Scene/CModelNode.h | 2 +- Scene/CRootNode.h | 2 +- Scene/CSceneNode.cpp | 2 +- Scene/CSceneNode.h | 2 +- Scene/CScriptNode.cpp | 26 ++- Scene/CScriptNode.h | 2 +- Scene/CStaticNode.cpp | 4 +- Scene/CStaticNode.h | 2 +- Scene/script/CDamageableTriggerExtra.cpp | 259 +++++++++++++++++++++++ Scene/script/CDamageableTriggerExtra.h | 46 ++++ Scene/script/CDoorExtra.cpp | 6 +- Scene/script/CDoorExtra.h | 2 +- Scene/script/CScriptExtra.cpp | 5 + Scene/script/CScriptExtra.h | 1 + 25 files changed, 375 insertions(+), 39 deletions(-) create mode 100644 Scene/script/CDamageableTriggerExtra.cpp create mode 100644 Scene/script/CDamageableTriggerExtra.h diff --git a/Common/CRayCollisionTester.cpp b/Common/CRayCollisionTester.cpp index bce25130..b748db3d 100644 --- a/Common/CRayCollisionTester.cpp +++ b/Common/CRayCollisionTester.cpp @@ -10,12 +10,12 @@ CRayCollisionTester::~CRayCollisionTester() { } -void CRayCollisionTester::AddNode(CSceneNode *pNode, u32 AssetIndex, float Distance) +void CRayCollisionTester::AddNode(CSceneNode *pNode, u32 ComponentIndex, float Distance) { mBoxIntersectList.emplace_back(SRayIntersection()); SRayIntersection& Intersection = mBoxIntersectList.back(); Intersection.pNode = pNode; - Intersection.AssetIndex = AssetIndex; + Intersection.ComponentIndex = ComponentIndex; Intersection.Distance = Distance; } @@ -55,7 +55,7 @@ SRayIntersection CRayCollisionTester::TestNodes(const SViewInfo& ViewInfo) // Otherwise, more intersection tests... CSceneNode *pNode = Intersection.pNode; - SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex, ViewInfo); + SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.ComponentIndex, ViewInfo); if (MidResult.Hit) { diff --git a/Common/SRayIntersection.h b/Common/SRayIntersection.h index 23baeab4..7b92bcf9 100644 --- a/Common/SRayIntersection.h +++ b/Common/SRayIntersection.h @@ -9,11 +9,11 @@ struct SRayIntersection bool Hit; float Distance; CSceneNode *pNode; - u32 AssetIndex; + u32 ComponentIndex; SRayIntersection() {} - SRayIntersection(bool _Hit, float _Distance, CSceneNode *_pNode, u32 _AssetIndex) - : Hit(_Hit), Distance(_Distance), pNode(_pNode), AssetIndex(_AssetIndex) {} + SRayIntersection(bool _Hit, float _Distance, CSceneNode *_pNode, u32 _ComponentIndex) + : Hit(_Hit), Distance(_Distance), pNode(_pNode), ComponentIndex(_ComponentIndex) {} }; #endif // SRAYINTERSECTION diff --git a/Core/CSceneManager.cpp b/Core/CSceneManager.cpp index 5753d6f9..2e3d4407 100644 --- a/Core/CSceneManager.cpp +++ b/Core/CSceneManager.cpp @@ -292,7 +292,7 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, const SViewInfo& V for (u32 iNode = 0; iNode < vec.size(); iNode++) if (vec[iNode]->IsVisible()) - vec[iNode]->RayAABoxIntersectTest(Tester); + vec[iNode]->RayAABoxIntersectTest(Tester, ViewInfo); } return Tester.TestNodes(ViewInfo); diff --git a/PrimeWorldEditor.pro b/PrimeWorldEditor.pro index 58bef807..de7040bf 100644 --- a/PrimeWorldEditor.pro +++ b/PrimeWorldEditor.pro @@ -157,7 +157,8 @@ SOURCES += \ Scene/script/CScriptExtra.cpp \ Scene/script/CSpacePirateExtra.cpp \ Scene/script/CWaypointExtra.cpp \ - Scene/script/CDoorExtra.cpp + Scene/script/CDoorExtra.cpp \ + Scene/script/CDamageableTriggerExtra.cpp HEADERS += \ Common/AnimUtil.h \ @@ -330,7 +331,8 @@ HEADERS += \ Scene/script/CPointOfInterestExtra.h \ Scene/script/CSpacePirateExtra.h \ Scene/script/CWaypointExtra.h \ - Scene/script/CDoorExtra.h + Scene/script/CDoorExtra.h \ + Scene/script/CDamageableTriggerExtra.h FORMS += \ UI/CStartWindow.ui \ diff --git a/Resource/CMaterial.cpp b/Resource/CMaterial.cpp index a0b5870d..a1ce1415 100644 --- a/Resource/CMaterial.cpp +++ b/Resource/CMaterial.cpp @@ -324,6 +324,26 @@ void CMaterial::SetLightingEnabled(bool Enabled) mRecalcHash = true; } +void CMaterial::SetNumPasses(u32 NumPasses) +{ + if (NumPasses < mPasses.size()) + { + for (u32 iPass = NumPasses; iPass < mPasses.size(); iPass++) + delete mPasses[iPass]; + } + + u32 OldCount = mPasses.size(); + mPasses.resize(NumPasses); + + if (NumPasses > OldCount) + { + for (u32 iPass = OldCount; iPass < NumPasses; iPass++) + mPasses[iPass] = new CMaterialPass(this); + } + + mRecalcHash = true; +} + // ************ STATIC ************ void CMaterial::KillCachedMaterial() { diff --git a/Resource/CMaterial.h b/Resource/CMaterial.h index 04cf80ad..059bb18c 100644 --- a/Resource/CMaterial.h +++ b/Resource/CMaterial.h @@ -104,6 +104,7 @@ public: void SetKonst(CColor& Konst, u32 KIndex); void SetIndTexture(CTexture *pTex); void SetLightingEnabled(bool Enabled); + void SetNumPasses(u32 NumPasses); // Static static void KillCachedMaterial(); diff --git a/Resource/CMaterialPass.cpp b/Resource/CMaterialPass.cpp index e40b3b36..4492b307 100644 --- a/Resource/CMaterialPass.cpp +++ b/Resource/CMaterialPass.cpp @@ -6,6 +6,7 @@ CMaterialPass::CMaterialPass(CMaterial *pParent) { mPassType = "CUST"; + mSettings = eNoPassSettings; mpTexture = nullptr; mEnabled = true; mpParentMat = pParent; diff --git a/Resource/CMaterialPass.h b/Resource/CMaterialPass.h index 3d69ae78..01b6c5b4 100644 --- a/Resource/CMaterialPass.h +++ b/Resource/CMaterialPass.h @@ -18,6 +18,7 @@ class CMaterialPass public: enum EPassSettings { + eNoPassSettings = 0x0, eEmissiveBloom = 0x4, eInvertOpacityMap = 0x10 }; diff --git a/Scene/CLightNode.cpp b/Scene/CLightNode.cpp index ef9abeba..6eb76592 100644 --- a/Scene/CLightNode.cpp +++ b/Scene/CLightNode.cpp @@ -43,7 +43,7 @@ void CLightNode::Draw(ERenderOptions /*Options*/, int /*ComponentIndex*/, const pRenderer->DrawBoundingBox(mLight->GetColor(), AABB);*/ } -void CLightNode::RayAABoxIntersectTest(CRayCollisionTester &Tester) +void CLightNode::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& /*ViewInfo*/) { CVector2f BillScale = BillboardScale(); float ScaleXY = (BillScale.x > BillScale.y ? BillScale.x : BillScale.y); @@ -60,7 +60,7 @@ SRayIntersection CLightNode::RayNodeIntersectTest(const CRay& Ray, u32 AssetID, // todo: come up with a better way to share this code between CScriptNode and CLightNode SRayIntersection out; out.pNode = this; - out.AssetIndex = AssetID; + out.ComponentIndex = AssetID; CTexture *pBillboard = CDrawUtil::GetLightTexture(mpLight->GetType()); diff --git a/Scene/CLightNode.h b/Scene/CLightNode.h index e259640f..d5630a81 100644 --- a/Scene/CLightNode.h +++ b/Scene/CLightNode.h @@ -12,7 +12,7 @@ public: ENodeType NodeType(); void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); - void RayAABoxIntersectTest(CRayCollisionTester& Tester); + void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); CLight* Light(); CVector2f BillboardScale(); diff --git a/Scene/CModelNode.cpp b/Scene/CModelNode.cpp index 5f39ef51..8f579c08 100644 --- a/Scene/CModelNode.cpp +++ b/Scene/CModelNode.cpp @@ -66,7 +66,7 @@ void CModelNode::DrawSelection() mpModel->DrawWireframe(eNoRenderOptions, WireframeColor()); } -void CModelNode::RayAABoxIntersectTest(CRayCollisionTester &Tester) +void CModelNode::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& /*ViewInfo*/) { if (!mpModel) return; @@ -81,7 +81,7 @@ SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, { SRayIntersection out; out.pNode = this; - out.AssetIndex = AssetID; + out.ComponentIndex = AssetID; CRay TransformedRay = Ray.Transformed(Transform().Inverse()); ERenderOptions options = ViewInfo.pRenderer->RenderOptions(); diff --git a/Scene/CModelNode.h b/Scene/CModelNode.h index ab29978d..2989e277 100644 --- a/Scene/CModelNode.h +++ b/Scene/CModelNode.h @@ -19,7 +19,7 @@ public: virtual void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); virtual void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); virtual void DrawSelection(); - virtual void RayAABoxIntersectTest(CRayCollisionTester &Tester); + virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); void SetModel(CModel *pModel); diff --git a/Scene/CRootNode.h b/Scene/CRootNode.h index 6080a62f..15ee2999 100644 --- a/Scene/CRootNode.h +++ b/Scene/CRootNode.h @@ -15,7 +15,7 @@ public: return eRootNode; } - inline void RayAABoxIntersectTest(CRayCollisionTester &) {} + inline void RayAABoxIntersectTest(CRayCollisionTester&, const SViewInfo&) {} inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, const SViewInfo&) { return SRayIntersection(false, 0.f, nullptr, 0); diff --git a/Scene/CSceneNode.cpp b/Scene/CSceneNode.cpp index 6caad3f3..ab3ca52a 100644 --- a/Scene/CSceneNode.cpp +++ b/Scene/CSceneNode.cpp @@ -57,7 +57,7 @@ void CSceneNode::DrawSelection() CDrawUtil::DrawWireCube(AABox(), CColor::skWhite); } -void CSceneNode::RayAABoxIntersectTest(CRayCollisionTester& Tester) +void CSceneNode::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& /*ViewInfo*/) { // Default implementation for virtual function std::pair result = AABox().IntersectsRay(Tester.Ray()); diff --git a/Scene/CSceneNode.h b/Scene/CSceneNode.h index 42aca57b..740c3df3 100644 --- a/Scene/CSceneNode.h +++ b/Scene/CSceneNode.h @@ -56,7 +56,7 @@ public: virtual TString PrefixedName() const; virtual void AddToRenderer(CRenderer* /*pRenderer*/, const SViewInfo& /*ViewInfo*/) {} virtual void DrawSelection(); - virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester); + virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); virtual SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 AssetID, const SViewInfo& ViewInfo) = 0; virtual bool IsVisible() const; virtual CColor TintColor(const SViewInfo& ViewInfo) const; diff --git a/Scene/CScriptNode.cpp b/Scene/CScriptNode.cpp index 85bfd328..6631130b 100644 --- a/Scene/CScriptNode.cpp +++ b/Scene/CScriptNode.cpp @@ -235,7 +235,7 @@ void CScriptNode::DrawSelection() } } -void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester &Tester) +void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo) { if (!mpInstance) return; @@ -243,10 +243,18 @@ void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester &Tester) // Let script extra do ray check first if (mpExtra) { - mpExtra->RayAABoxIntersectTest(Tester); + mpExtra->RayAABoxIntersectTest(Tester, ViewInfo); // If the extra doesn't want us rendering, then don't do the ray test either - if (!mpExtra->ShouldDrawNormalAssets()) return; + if (!mpExtra->ShouldDrawNormalAssets()) + return; + } + + // If we're in game mode, then check whether we're visible before proceeding with the ray test. + if (ViewInfo.GameMode) + { + if (!mpInstance->IsActive() || !mpInstance->HasInGameModel()) + return; } // Otherwise, proceed with the ray test as normal... @@ -283,17 +291,7 @@ SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay& Ray, u32 AssetID, SRayIntersection out; out.pNode = this; - out.AssetIndex = AssetID; - - // If we're in game mode, then check whether we're visible before proceeding with the ray test. - if (ViewInfo.GameMode) - { - if (!mpInstance->IsActive() || !mpInstance->HasInGameModel()) - { - out.Hit = false; - return out; - } - } + out.ComponentIndex = AssetID; if (options & eDrawObjects || ViewInfo.GameMode) { diff --git a/Scene/CScriptNode.h b/Scene/CScriptNode.h index b4b0b7fd..bb1209a7 100644 --- a/Scene/CScriptNode.h +++ b/Scene/CScriptNode.h @@ -31,7 +31,7 @@ public: void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); void DrawSelection(); - void RayAABoxIntersectTest(CRayCollisionTester &Tester); + void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); bool IsVisible() const; CColor TintColor(const SViewInfo &ViewInfo) const; diff --git a/Scene/CStaticNode.cpp b/Scene/CStaticNode.cpp index a61672d5..b37f200e 100644 --- a/Scene/CStaticNode.cpp +++ b/Scene/CStaticNode.cpp @@ -69,7 +69,7 @@ void CStaticNode::DrawSelection() mpModel->DrawWireframe(eNoRenderOptions, WireframeColor()); } -void CStaticNode::RayAABoxIntersectTest(CRayCollisionTester &Tester) +void CStaticNode::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& /*ViewInfo*/) { if ((!mpModel) || (mpModel->IsOccluder())) return; @@ -93,7 +93,7 @@ SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, { SRayIntersection out; out.pNode = this; - out.AssetIndex = AssetID; + out.ComponentIndex = AssetID; CRay TransformedRay = Ray.Transformed(Transform().Inverse()); ERenderOptions options = ViewInfo.pRenderer->RenderOptions(); diff --git a/Scene/CStaticNode.h b/Scene/CStaticNode.h index 32609ca2..40a86c43 100644 --- a/Scene/CStaticNode.h +++ b/Scene/CStaticNode.h @@ -14,7 +14,7 @@ public: void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); void DrawSelection(); - void RayAABoxIntersectTest(CRayCollisionTester &Tester); + void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); }; diff --git a/Scene/script/CDamageableTriggerExtra.cpp b/Scene/script/CDamageableTriggerExtra.cpp new file mode 100644 index 00000000..7e86dc16 --- /dev/null +++ b/Scene/script/CDamageableTriggerExtra.cpp @@ -0,0 +1,259 @@ +#include "CDamageableTriggerExtra.h" +#include +#include + +CDamageableTriggerExtra::CDamageableTriggerExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent) + : CScriptExtra(pInstance, pScene, pParent) + , mpRenderSideProp(nullptr) + , mpMat(nullptr) +{ + for (u32 iTex = 0; iTex < 3; iTex++) + mpTextures[iTex] = nullptr; + + SetInheritance(true, false, false); + CreateMaterial(); + + CPropertyStruct *pBaseStruct = pInstance->Properties(); + + // Fetch render side + mpRenderSideProp = (CEnumProperty*) pBaseStruct->PropertyByIndex(0x5); + + if (mpRenderSideProp && mpRenderSideProp->Type() != eEnumProperty) + mpRenderSideProp = nullptr; + + if (mpRenderSideProp) PropertyModified(mpRenderSideProp); + + // Fetch scale + mpSizeProp = (CVector3Property*) pBaseStruct->PropertyByIndex(0x2); + + if (mpSizeProp && mpSizeProp->Type() != eVector3Property) + mpSizeProp = nullptr; + + if (mpSizeProp) PropertyModified (mpSizeProp); + + // Fetch textures + for (u32 iTex = 0; iTex < 3; iTex++) + { + mpTextureProps[iTex] = (CFileProperty*) pBaseStruct->PropertyByIndex(0x6 + iTex); + + if (mpTextureProps[iTex]) + { + if (mpTextureProps[iTex]->Type() == eFileProperty) + PropertyModified(mpTextureProps[iTex]); + else + mpTextureProps[iTex] = nullptr; + } + + else + mpTextures[iTex] = nullptr; + } +} + +CDamageableTriggerExtra::~CDamageableTriggerExtra() +{ + delete mpMat; +} + +void CDamageableTriggerExtra::CreateMaterial() +{ + if (mpMat) delete mpMat; + mpMat = new CMaterial(mGame, ePosition | eNormal | eTex0); + + // Most values/TEV setup were found from the executable + from graphics debuggers + // Animation parameters are estimates from eyeballing the values ingame + mpMat->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + mpMat->SetLightingEnabled(true); + mpMat->SetOptions(CMaterial::eTransparent); + mpMat->SetKonst(CColor((float) 1.f, 1.f, 1.f, 51.f / 255), 0); + mpMat->SetNumPasses(3); + + CMaterialPass *pPassA = mpMat->Pass(0); + pPassA->SetKColorSel(eKonst0_RGB); + pPassA->SetTexCoordSource(4); + pPassA->SetTexture(mpTextures[0]); + pPassA->SetColorInputs(eZeroRGB, eTextureRGB, eKonstRGB, eZeroRGB); + pPassA->SetAnimMode(eUVScroll); + pPassA->SetAnimParam(3, -0.48f); + + CMaterialPass *pPassB = mpMat->Pass(1); + pPassB->SetTexCoordSource(4); + pPassB->SetTexture(mpTextures[1]); + pPassB->SetColorInputs(eZeroRGB, eTextureRGB, ePrevRGB, eZeroRGB); + pPassB->SetAnimMode(eUVScroll); + pPassB->SetAnimParam(2, 0.25f); + pPassB->SetAnimParam(3, -0.3f); + + CMaterialPass *pPassC = mpMat->Pass(2); + pPassC->SetTexCoordSource(4); + pPassC->SetTexture(mpTextures[2]); + pPassC->SetRasSel(eRasColor0A0); + pPassC->SetKAlphaSel(eKonst0_A); + pPassC->SetColorInputs(eZeroRGB, eTextureRGB, eOneRGB, ePrevRGB); + pPassC->SetAlphaInputs(eZeroAlpha, eZeroAlpha, eZeroAlpha, eKonstAlpha); + pPassC->SetAnimMode(eUVScroll); + pPassC->SetAnimParam(3, -0.16f); +} + +void CDamageableTriggerExtra::UpdatePlaneTransform() +{ + CVector3f Extent = mPlaneSize / 2.f; + + switch (mRenderSide) + { + case eNorth: + case eSouth: + { + float Scalar = (mRenderSide == eNorth ? 1.f : -1.f); + + mPosition = CVector3f(0.f, Extent.y * Scalar, 0.f); + mRotation = CQuaternion::FromEuler(CVector3f(90.f * Scalar, 0.f, 0.f)); + mScale = CVector3f(Extent.x, Extent.z, 0.f); + mCoordScale = mPlaneSize.xz(); + break; + } + + case eWest: + case eEast: + { + float Scalar = (mRenderSide == eWest ? 1.f : -1.f); + + mPosition = CVector3f(-Extent.x * Scalar, 0.f, 0.f); + mRotation = CQuaternion::FromEuler(CVector3f(0.f, 90.f * Scalar, 0.f)); + mScale = CVector3f(Extent.z, Extent.y, 0.f); + mCoordScale = -mPlaneSize.yz(); + break; + } + + case eUp: + case eDown: + { + float Scalar = (mRenderSide == eUp ? 1.f : -1.f); + float RotAngle = (mRenderSide == eUp ? 180.f : 0.f); + + mPosition = CVector3f(0.f, 0.f, Extent.z * Scalar); + mRotation = CQuaternion::FromEuler(CVector3f(0.f, RotAngle, 0.f)); + mScale = CVector3f(Extent.x, Extent.y, 0.f); + mCoordScale = -mPlaneSize.xy(); + break; + } + + } + + if (mRenderSide == eNoRender) + mLocalAABox = CAABox::skZero; + else + mLocalAABox = CAABox(CVector3f(-1.f, -1.f, 0.f), CVector3f(1.f, 1.f, 0.f)); + + MarkTransformChanged(); +} + +void CDamageableTriggerExtra::PropertyModified(CPropertyBase *pProperty) +{ + if (pProperty == mpRenderSideProp) + { + mRenderSide = (ERenderSide) mpRenderSideProp->Get(); + UpdatePlaneTransform(); + } + + else if (pProperty == mpSizeProp) + { + mPlaneSize = mpSizeProp->Get(); + UpdatePlaneTransform(); + } + + else + { + for (u32 iTex = 0; iTex < 3; iTex++) + { + if (pProperty == mpTextureProps[iTex]) + { + mpTextures[iTex] = (CTexture*) mpTextureProps[iTex]->Get(); + + if (mpTextures[iTex] && mpTextures[iTex]->Type() != eTexture) + mpTextures[iTex] = nullptr; + + mpMat->Pass(iTex)->SetTexture(mpTextures[iTex]); + mTextureTokens[iTex] = CToken(mpTextures[iTex]); + break; + } + } + } +} + +bool CDamageableTriggerExtra::ShouldDrawNormalAssets() +{ + return (mRenderSide == eNoRender); +} + +void CDamageableTriggerExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) +{ + if (ViewInfo.GameMode && !mpInstance->IsActive()) + return; + + if (mRenderSide != eNoRender) + { + if (ViewInfo.ViewFrustum.BoxInFrustum(AABox())) + pRenderer->AddTransparentMesh(this, -1, AABox(), eDrawMesh); + if (mpParent->IsSelected()) + pRenderer->AddOpaqueMesh(this, -1, AABox(), eDrawSelection); + } +} + +void CDamageableTriggerExtra::Draw(ERenderOptions Options, int /*ComponentIndex*/, const SViewInfo& ViewInfo) +{ + LoadModelMatrix(); + CGraphics::sPixelBlock.TintColor = mpParent->TintColor(ViewInfo).ToVector4f(); + mpMat->SetCurrent(Options); + + CVector2f TexUL(0.f, mCoordScale.y / 4.5f); + CVector2f TexUR(mCoordScale.x / 5.f, mCoordScale.y / 4.5f); + CVector2f TexBR(mCoordScale.x / 5.f, 0.f); + CVector2f TexBL(0.f, 0.f); + CDrawUtil::DrawSquare(TexUL, TexUR, TexBR, TexBL); +} + +void CDamageableTriggerExtra::DrawSelection() +{ + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glBlendFunc(GL_ONE, GL_ZERO); + LoadModelMatrix(); + CDrawUtil::UseColorShader(WireframeColor()); + CDrawUtil::DrawSquare(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +} + +void CDamageableTriggerExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo) +{ + if (mRenderSide == eNoRender) return; + if (ViewInfo.GameMode && !mpInstance->IsActive()) return; + + const CRay& Ray = Tester.Ray(); + + if (ViewInfo.pRenderer->RenderOptions() & eEnableBackfaceCull) + { + // We're guaranteed to be axis-aligned, so we can take advantage of that + // to perform a very simple backface check. + switch (mRenderSide) + { + case eNorth: if (Ray.Origin().y > AbsolutePosition().y) return; break; + case eSouth: if (Ray.Origin().y < AbsolutePosition().y) return; break; + case eWest: if (Ray.Origin().x < AbsolutePosition().x) return; break; + case eEast: if (Ray.Origin().x > AbsolutePosition().x) return; break; + case eUp: if (Ray.Origin().z > AbsolutePosition().z) return; break; + case eDown: if (Ray.Origin().z < AbsolutePosition().z) return; break; + } + } + + std::pair Result = AABox().IntersectsRay(Ray); + + if (Result.first) + Tester.AddNode(this, -1, Result.second); +} + +SRayIntersection CDamageableTriggerExtra::RayNodeIntersectTest(const CRay& Ray, u32 /*ComponentIndex*/, const SViewInfo& /*ViewInfo*/) +{ + // The bounding box and all other tests already passed in RayAABoxIntersectTest, so we + // already know that we have a positive. We just need the distance again. + std::pair Result = AABox().IntersectsRay(Ray); + return SRayIntersection(true, Result.second, mpParent, -1); +} diff --git a/Scene/script/CDamageableTriggerExtra.h b/Scene/script/CDamageableTriggerExtra.h new file mode 100644 index 00000000..e1fcfb96 --- /dev/null +++ b/Scene/script/CDamageableTriggerExtra.h @@ -0,0 +1,46 @@ +#ifndef CDAMAGEABLETRIGGEREXTRA_H +#define CDAMAGEABLETRIGGEREXTRA_H + +#include "CScriptExtra.h" + +class CDamageableTriggerExtra : public CScriptExtra +{ + // Render fluid planes for doors in MP1 + enum ERenderSide + { + eNoRender = 0, + eNorth = 1, + eSouth = 2, + eWest = 3, + eEast = 4, + eUp = 5, + eDown = 6 + }; + + CVector3Property *mpSizeProp; + CEnumProperty *mpRenderSideProp; + CFileProperty *mpTextureProps[3]; + + CVector3f mPlaneSize; + ERenderSide mRenderSide; + CTexture *mpTextures[3]; + CToken mTextureTokens[3]; + + CMaterial *mpMat; + CVector2f mCoordScale; + +public: + explicit CDamageableTriggerExtra(CScriptObject *pInstance, CSceneManager *pScene, CSceneNode *pParent = 0); + ~CDamageableTriggerExtra(); + void CreateMaterial(); + void UpdatePlaneTransform(); + void PropertyModified(CPropertyBase *pProperty); + bool ShouldDrawNormalAssets(); + void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); + void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); + void DrawSelection(); + void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); + SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 ComponentIndex, const SViewInfo& ViewInfo); +}; + +#endif // CDAMAGEABLETRIGGEREXTRA_H diff --git a/Scene/script/CDoorExtra.cpp b/Scene/script/CDoorExtra.cpp index ace70114..3b74b2eb 100644 --- a/Scene/script/CDoorExtra.cpp +++ b/Scene/script/CDoorExtra.cpp @@ -47,6 +47,7 @@ void CDoorExtra::PropertyModified(CPropertyBase *pProperty) void CDoorExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) { if (!mpShieldModel) return; + if (ViewInfo.GameMode && !mpInstance->IsActive()) return; if (mpParent->IsVisible() && ViewInfo.ViewFrustum.BoxInFrustum(AABox())) { @@ -90,9 +91,10 @@ void CDoorExtra::DrawSelection() mpShieldModel->DrawWireframe(eNoRenderOptions, mpParent->WireframeColor()); } -void CDoorExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester) +void CDoorExtra::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo) { if (!mpShieldModel) return; + if (ViewInfo.GameMode && !mpInstance->IsActive()) return; const CRay& Ray = Tester.Ray(); std::pair BoxResult = AABox().IntersectsRay(Ray); @@ -107,7 +109,7 @@ SRayIntersection CDoorExtra::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, SRayIntersection out; out.pNode = mpParent; - out.AssetIndex = AssetID; + out.ComponentIndex = AssetID; CRay TransformedRay = Ray.Transformed(Transform().Inverse()); std::pair Result = mpShieldModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((Options & eEnableBackfaceCull) == 0)); diff --git a/Scene/script/CDoorExtra.h b/Scene/script/CDoorExtra.h index 96726978..8b0e48f7 100644 --- a/Scene/script/CDoorExtra.h +++ b/Scene/script/CDoorExtra.h @@ -18,7 +18,7 @@ public: void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo); void Draw(ERenderOptions Options, int ComponentIndex, const SViewInfo& ViewInfo); void DrawSelection(); - void RayAABoxIntersectTest(CRayCollisionTester &Tester); + void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo); }; diff --git a/Scene/script/CScriptExtra.cpp b/Scene/script/CScriptExtra.cpp index f4d9a79e..9338cd09 100644 --- a/Scene/script/CScriptExtra.cpp +++ b/Scene/script/CScriptExtra.cpp @@ -1,6 +1,7 @@ #include "CScriptExtra.h" #include "CWaypointExtra.h" +#include "CDamageableTriggerExtra.h" #include "CSpacePirateExtra.h" #include "CPointOfInterestExtra.h" #include "CDoorExtra.h" @@ -25,6 +26,10 @@ CScriptExtra* CScriptExtra::CreateExtra(CScriptNode *pNode) pExtra = new CWaypointExtra(pObj, pNode->Scene(), pNode); break; + case 0x1A: // DamageableTrigger (MP1) + pExtra = new CDamageableTriggerExtra(pObj, pNode->Scene(), pNode); + break; + case 0x24: // SpacePirate (MP1) pExtra = new CSpacePirateExtra(pObj, pNode->Scene(), pNode); break; diff --git a/Scene/script/CScriptExtra.h b/Scene/script/CScriptExtra.h index b4469bc8..da01c3d8 100644 --- a/Scene/script/CScriptExtra.h +++ b/Scene/script/CScriptExtra.h @@ -36,6 +36,7 @@ public: out.Hit = false; return out; } + virtual CColor WireframeColor() const { return mpParent->WireframeColor(); } // Virtual CScriptExtra functions virtual void InstanceTransformed() {}