diff --git a/Core/CSceneManager.cpp b/Core/CSceneManager.cpp index febef633..5753d6f9 100644 --- a/Core/CSceneManager.cpp +++ b/Core/CSceneManager.cpp @@ -219,7 +219,7 @@ void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& Vi { ERenderOptions Options = pRenderer->RenderOptions(); - if (Options & eDrawWorld) + if (Options & eDrawWorld || ViewInfo.GameMode) { for (u32 n = 0; n < mModelNodes.size(); n++) if (mModelNodes[n]->IsVisible()) @@ -230,21 +230,21 @@ void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& Vi mStaticNodes[n]->AddToRenderer(pRenderer, ViewInfo); } - if (Options & eDrawWorldCollision) + if (Options & eDrawWorldCollision && !ViewInfo.GameMode) { for (u32 n = 0; n < mCollisionNodes.size(); n++) if (mCollisionNodes[n]->IsVisible()) mCollisionNodes[n]->AddToRenderer(pRenderer, ViewInfo); } - if (Options & eDrawLights) + if (Options & eDrawLights && !ViewInfo.GameMode) { for (u32 n = 0; n < mLightNodes.size(); n++) if (mLightNodes[n]->IsVisible()) mLightNodes[n]->AddToRenderer(pRenderer, ViewInfo); } - if ((Options & eDrawObjects) || (Options & eDrawObjectCollision)) + if ((Options & eDrawObjects) || (Options & eDrawObjectCollision) || ViewInfo.GameMode) { for (u32 n = 0; n < mScriptNodes.size(); n++) if (mScriptNodes[n]->IsVisible()) @@ -271,6 +271,16 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, const SViewInfo& V ((renderOptions & ((ERenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0), ((renderOptions & eDrawLights) != 0) }; + // Override visibility for game mode + if (ViewInfo.GameMode) + { + NodesVisible[0] = false; + NodesVisible[1] = true; + NodesVisible[2] = false; + NodesVisible[3] = true; + NodesVisible[4] = false; + } + // Less hacky stuff CRayCollisionTester Tester(Ray); diff --git a/Core/SViewInfo.h b/Core/SViewInfo.h index cf520617..fb898966 100644 --- a/Core/SViewInfo.h +++ b/Core/SViewInfo.h @@ -11,6 +11,7 @@ struct SViewInfo class CRenderer *pRenderer; class CCamera *pCamera; + bool GameMode; CFrustumPlanes ViewFrustum; CMatrix4f RotationOnlyViewMatrix; }; diff --git a/Resource/script/CScriptObject.cpp b/Resource/script/CScriptObject.cpp index 4baa88ef..0f701f7a 100644 --- a/Resource/script/CScriptObject.cpp +++ b/Resource/script/CScriptObject.cpp @@ -12,6 +12,7 @@ CScriptObject::CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemp mpDisplayModel = nullptr; mpBillboard = nullptr; mpCollision = nullptr; + mHasInGameModel = false; } CScriptObject::~CScriptObject() @@ -36,6 +37,7 @@ void CScriptObject::EvaluateProperties() mpScale = mpTemplate->FindScale(mpProperties); mpActive = mpTemplate->FindActive(mpProperties); mpLightParameters = mpTemplate->FindLightParameters(mpProperties); + mHasInGameModel = mpTemplate->HasInGameModel(mpProperties); mVolumeShape = mpTemplate->VolumeShape(this); EvaluateDisplayModel(); EvaluateBillboard(); @@ -168,7 +170,12 @@ bool CScriptObject::IsActive() const if (mpActive) return mpActive->Get(); else - return true; + return false; +} + +bool CScriptObject::HasInGameModel() const +{ + return mHasInGameModel; } void CScriptObject::SetPosition(const CVector3f& newPos) diff --git a/Resource/script/CScriptObject.h b/Resource/script/CScriptObject.h index af44a6d4..3fe4264f 100644 --- a/Resource/script/CScriptObject.h +++ b/Resource/script/CScriptObject.h @@ -37,6 +37,8 @@ class CScriptObject CToken mModelToken; CToken mBillboardToken; CToken mCollisionToken; + bool mHasInGameModel; + EVolumeShape mVolumeShape; public: @@ -69,6 +71,7 @@ public: CVector3f Scale() const; TString InstanceName() const; bool IsActive() const; + bool HasInGameModel() const; void SetPosition(const CVector3f& newPos); void SetRotation(const CVector3f& newRot); void SetScale(const CVector3f& newScale); diff --git a/Resource/script/CScriptTemplate.cpp b/Resource/script/CScriptTemplate.cpp index 0dcb5c11..af3c3011 100644 --- a/Resource/script/CScriptTemplate.cpp +++ b/Resource/script/CScriptTemplate.cpp @@ -210,7 +210,7 @@ CPropertyStruct* CScriptTemplate::FindLightParameters(CPropertyStruct *pProperti return TFetchProperty(pProperties, mLightParametersIDString); } -// todo: merge these three functions, they have near-identical code +// todo: merge these four functions, they have near-identical code CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties) { for (auto it = mAssets.begin(); it != mAssets.end(); it++) @@ -319,6 +319,36 @@ CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties return nullptr; } +bool CScriptTemplate::HasInGameModel(CPropertyStruct *pProperties) +{ + for (auto it = mAssets.begin(); it != mAssets.end(); it++) + { + if ((it->AssetType != SEditorAsset::eModel) && (it->AssetType != SEditorAsset::eAnimParams)) continue; + if (it->AssetSource == SEditorAsset::eFile) continue; + CResource *pRes = nullptr; + + CPropertyBase *pProp = pProperties->PropertyByIDString(it->AssetLocation); + + if (pProp->Type() == eFileProperty) + { + CFileProperty *pFile = static_cast(pProp); + pRes = pFile->Get(); + } + + else if (pProp->Type() == eAnimParamsProperty) + { + CAnimParamsProperty *pParams = static_cast(pProp); + pRes = pParams->Get().GetCurrentModel(it->ForceNodeIndex); + } + + // Verify resource exists + is correct type + if (pRes && (pRes->Type() == eModel)) + return true; + } + + return false; +} + bool CScriptTemplate::HasPosition() { return (!mPositionIDString.IsEmpty()); diff --git a/Resource/script/CScriptTemplate.h b/Resource/script/CScriptTemplate.h index a316cd9c..78247d07 100644 --- a/Resource/script/CScriptTemplate.h +++ b/Resource/script/CScriptTemplate.h @@ -117,6 +117,7 @@ public: CModel* FindDisplayModel(CPropertyStruct *pProperties); CTexture* FindBillboardTexture(CPropertyStruct *pProperties); CCollisionMeshGroup* FindCollision(CPropertyStruct *pProperties); + bool HasInGameModel(CPropertyStruct *pProperties); bool HasPosition(); // Object Tracking diff --git a/Scene/CCollisionNode.cpp b/Scene/CCollisionNode.cpp index 004a2ddf..068264ba 100644 --- a/Scene/CCollisionNode.cpp +++ b/Scene/CCollisionNode.cpp @@ -19,6 +19,7 @@ void CCollisionNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewIn { if (!mpCollision) return; if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return; + if (ViewInfo.GameMode) return; pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); diff --git a/Scene/CLightNode.cpp b/Scene/CLightNode.cpp index bec63a1d..cec6cdd4 100644 --- a/Scene/CLightNode.cpp +++ b/Scene/CLightNode.cpp @@ -28,6 +28,7 @@ ENodeType CLightNode::NodeType() void CLightNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) { if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return; + if (ViewInfo.GameMode) return; pRenderer->AddOpaqueMesh(this, 0, CAABox(mPosition + 0.5f, mPosition - 0.5f), eDrawMesh); } diff --git a/Scene/CModelNode.cpp b/Scene/CModelNode.cpp index 71a54b21..76fa6dec 100644 --- a/Scene/CModelNode.cpp +++ b/Scene/CModelNode.cpp @@ -20,6 +20,7 @@ void CModelNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) { if (!mpModel) return; if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return; + if (ViewInfo.GameMode) return; if (!mpModel->HasTransparency(mActiveMatSet)) pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); diff --git a/Scene/CScriptNode.cpp b/Scene/CScriptNode.cpp index 32cd6dc2..1a5c09df 100644 --- a/Scene/CScriptNode.cpp +++ b/Scene/CScriptNode.cpp @@ -105,12 +105,20 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) { if (!mpInstance) return; + // If we're in game mode, then override other visibility settings. + if (ViewInfo.GameMode) + { + if (!mpInstance->IsActive() || !mpInstance->HasInGameModel()) + return; + } + + // Otherwise, we proceed as normal ERenderOptions options = pRenderer->RenderOptions(); - if (options & eDrawObjectCollision) + if ((options & eDrawObjectCollision) && (!ViewInfo.GameMode)) mpCollisionNode->AddToRenderer(pRenderer, ViewInfo); - if (options & eDrawObjects) + if (options & eDrawObjects || ViewInfo.GameMode) { if (ViewInfo.ViewFrustum.BoxInFrustum(AABox())) { @@ -145,7 +153,7 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) } } - if (IsSelected()) + if (IsSelected() && !ViewInfo.GameMode) { // Script nodes always draw their selections regardless of frustum planes // in order to ensure that script connection lines don't get improperly culled. @@ -286,7 +294,17 @@ SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay& Ray, u32 AssetID, out.pNode = this; out.AssetIndex = AssetID; - if (options & eDrawObjects) + // 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; + } + } + + if (options & eDrawObjects || ViewInfo.GameMode) { // Model test if (mpActiveModel || !mpBillboard) diff --git a/Scene/CStaticNode.cpp b/Scene/CStaticNode.cpp index ccf9722e..2493aa96 100644 --- a/Scene/CStaticNode.cpp +++ b/Scene/CStaticNode.cpp @@ -38,7 +38,7 @@ void CStaticNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo) } } - if (mSelected) + if (mSelected && !ViewInfo.GameMode) pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawSelection); } diff --git a/UI/CBasicViewport.cpp b/UI/CBasicViewport.cpp index d8ad81a6..6c4d8fff 100644 --- a/UI/CBasicViewport.cpp +++ b/UI/CBasicViewport.cpp @@ -15,6 +15,7 @@ CBasicViewport::CBasicViewport(QWidget *pParent) : setMouseTracking(true); mCamera.SetAspectRatio((float) width() / height()); mViewInfo.pCamera = &mCamera; + mViewInfo.GameMode = false; } CBasicViewport::~CBasicViewport() @@ -56,7 +57,8 @@ void CBasicViewport::paintGL() Paint(); // Finally, draw XYZ axes in the corner - DrawAxes(); + if (!mViewInfo.GameMode) + DrawAxes(); } void CBasicViewport::resizeGL(int w, int h) @@ -163,6 +165,11 @@ void CBasicViewport::contextMenuEvent(QContextMenuEvent *pEvent) ContextMenu(pEvent); } +void CBasicViewport::SetGameMode(bool Enabled) +{ + mViewInfo.GameMode = Enabled; +} + void CBasicViewport::SetCursorState(const QCursor &Cursor) { mCursorState = Cursor; diff --git a/UI/CBasicViewport.h b/UI/CBasicViewport.h index db533efd..63c3e06c 100644 --- a/UI/CBasicViewport.h +++ b/UI/CBasicViewport.h @@ -52,6 +52,7 @@ public: void focusOutEvent(QFocusEvent *pEvent); void contextMenuEvent(QContextMenuEvent *pEvent); + void SetGameMode(bool Enabled); void SetCursorState(const QCursor& Cursor); void SetCursorVisible(bool visible); bool IsCursorVisible(); diff --git a/UI/CSceneViewport.cpp b/UI/CSceneViewport.cpp index a7034160..5b28046f 100644 --- a/UI/CSceneViewport.cpp +++ b/UI/CSceneViewport.cpp @@ -132,15 +132,21 @@ void CSceneViewport::keyReleaseEvent(QKeyEvent* pEvent) // ************ PROTECTED SLOTS ************ void CSceneViewport::CheckUserInput() { - if (!underMouse() || IsMouseInputActive()) + bool MouseActive = (underMouse() && !IsMouseInputActive()); + + if (!MouseActive || mViewInfo.GameMode) { ResetHover(); mGizmoHovering = false; - return; + + if (!MouseActive) + return; } CRay ray = CastRay(); - CheckGizmoInput(ray); + + if (!mViewInfo.GameMode) + CheckGizmoInput(ray); if (!mpEditor->Gizmo()->IsTransforming()) SceneRayCast(ray); @@ -152,7 +158,7 @@ void CSceneViewport::Paint() mpRenderer->BeginFrame(); - if (mDrawSky) + if (mDrawSky || mViewInfo.GameMode) { CModel *pSky = mpScene->GetActiveSkybox(); if (pSky) mpRenderer->RenderSky(pSky, mViewInfo); @@ -163,7 +169,7 @@ void CSceneViewport::Paint() mpRenderer->RenderBuckets(mViewInfo); mpRenderer->RenderBloom(); - if (mpEditor->IsGizmoVisible()) + if (mpEditor->IsGizmoVisible() && !mViewInfo.GameMode) { CGizmo *pGizmo = mpEditor->Gizmo(); mCamera.LoadMatrices(); diff --git a/UI/CWorldEditor.cpp b/UI/CWorldEditor.cpp index dfc1db17..b132a0e3 100644 --- a/UI/CWorldEditor.cpp +++ b/UI/CWorldEditor.cpp @@ -467,3 +467,8 @@ void CWorldEditor::on_ActionDrawObjectCollision_triggered() { ui->MainViewport->Renderer()->ToggleObjectCollision(ui->ActionDrawObjectCollision->isChecked()); } + +void CWorldEditor::on_ActionGameMode_triggered() +{ + ui->MainViewport->SetGameMode(ui->ActionGameMode->isChecked()); +} diff --git a/UI/CWorldEditor.h b/UI/CWorldEditor.h index 53dc5565..815bf5b8 100644 --- a/UI/CWorldEditor.h +++ b/UI/CWorldEditor.h @@ -76,6 +76,7 @@ private slots: void on_ActionIncrementGizmo_triggered(); void on_ActionDecrementGizmo_triggered(); void on_ActionDrawObjectCollision_triggered(); + void on_ActionGameMode_triggered(); }; #endif // CWORLDEDITOR_H diff --git a/UI/CWorldEditor.ui b/UI/CWorldEditor.ui index 58548906..53312cc9 100644 --- a/UI/CWorldEditor.ui +++ b/UI/CWorldEditor.ui @@ -267,6 +267,8 @@ + + @@ -715,6 +717,17 @@ 4 + + + true + + + Game Mode + + + G + +