/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Data/Samples/RTS/CppSource/RTSPlugin/GameState/RTSGameState.cpp
439 строк
13 KB
C-Core
Try to find the preload collection for the startup scene (#1720)
23 ноя 2025, 13:22
Не верифицирован
23 ноя 2025, 13:22
911d5a8
Код
Авторство
О чём код?
#include <RTSPlugin/RTSPluginPCH.h> #include <Core/Input/InputManager.h> #include <Core/System/Window.h> #include <Core/World/World.h> #include <RTSPlugin/Components/ComponentMessages.h> #include <RTSPlugin/Components/SelectableComponent.h> #include <RTSPlugin/GameMode/BattleMode/BattleMode.h> #include <RTSPlugin/GameMode/EditLevelMode/EditLevelMode.h> #include <RTSPlugin/GameMode/GameMode.h> #include <RTSPlugin/GameMode/MainMenuMode/MainMenuMode.h> #include <RTSPlugin/GameMode/SettingsMenuMode/SettingsMenuMode.h> #include <RTSPlugin/GameState/RTSGameState.h> EZ_BEGIN_DYNAMIC_REFLECTED_TYPE(RTSGameState, 1, ezRTTIDefaultAllocator<RTSGameState>) EZ_END_DYNAMIC_REFLECTED_TYPE; RTSGameState* RTSGameState::s_pSingleton = nullptr; RTSGameState::RTSGameState() { s_pSingleton = this; } RTSGameState::~RTSGameState() = default; void RTSGameState::RequestQuit(ezStringView sRequestedBy) { if (sRequestedBy == "window") { SUPER::RequestQuit(sRequestedBy); return; } if (sRequestedBy == "editor-esc") { SwitchToGameMode(RtsActiveGameMode::MainMenuMode); return; } SUPER::RequestQuit(sRequestedBy); } void RTSGameState::GetStartupOptions(ezString& out_sScene, ezString& out_sPreloadCollection) { // replace this to load a certain scene at startup // the default implementation looks at the command line "-scene" argument // if we have a "-scene" command line argument, it was launched from the editor and we should load that if (ezCommandLineUtils::GetGlobalInstance()->HasOption("-scene")) { out_sScene = ezCommandLineUtils::GetGlobalInstance()->GetStringOption("-scene"); } else { // otherwise, we use the hardcoded 'Main.ezScene' // if that doesn't exist, this function has to be adjusted // note that you can return an asset GUID here, instead of a path out_sScene = "AssetCache/Common/Scenes/Main.ezBinScene"; } } float RTSGameState::GetCameraZoom() const { return m_fCameraZoom; } float RTSGameState::SetCameraZoom(float fZoom) { m_fCameraZoom = ezMath::Clamp(fZoom, 1.0f, 50.0f); return m_fCameraZoom; } void RTSGameState::OnActivation(ezWorld* pWorld, ezStringView sStartPosition, const ezTransform& startPositionOffset) { EZ_LOG_BLOCK("GameState::Activate"); SUPER::OnActivation(pWorld, sStartPosition, startPositionOffset); PreloadAssets(); m_pMainMenuMode = EZ_DEFAULT_NEW(RtsMainMenuMode); m_pSettingsMenuMode = EZ_DEFAULT_NEW(RtsSettingsMenuMode); m_pBattleMode = EZ_DEFAULT_NEW(RtsBattleMode); m_pEditLevelMode = EZ_DEFAULT_NEW(RtsEditLevelMode); SwitchToGameMode(RtsActiveGameMode::EditLevelMode); } void RTSGameState::OnDeactivation() { EZ_LOG_BLOCK("GameState::Deactivate"); SetActiveGameMode(RtsActiveGameMode::None); SUPER::OnDeactivation(); } void RTSGameState::PreloadAssets() { // Load all assets that are referenced in some Collections m_hCollectionSpace = ezResourceManager::LoadResource<ezCollectionResource>("{ 7cd0dfa6-d2bb-433e-9fa2-b17bfae42b6b }"); m_hCollectionFederation = ezResourceManager::LoadResource<ezCollectionResource>("{ 1edd3af8-6d59-4825-b853-ee8d7a60cb03 }"); m_hCollectionKlingons = ezResourceManager::LoadResource<ezCollectionResource>("{ c683d049-0e54-4c42-9764-a122f9dbc69d }"); // Register the loaded assets with the names defined in the collections // This allows to easily spawn those objects with human readable names instead of GUIDs { ezResourceLock<ezCollectionResource> pCollection(m_hCollectionSpace, ezResourceAcquireMode::BlockTillLoaded); pCollection->RegisterNames(); } { ezResourceLock<ezCollectionResource> pCollection(m_hCollectionFederation, ezResourceAcquireMode::BlockTillLoaded); pCollection->RegisterNames(); } { ezResourceLock<ezCollectionResource> pCollection(m_hCollectionKlingons, ezResourceAcquireMode::BlockTillLoaded); pCollection->RegisterNames(); } } void RTSGameState::BeforeWorldUpdate() { if (IsLoadingSceneInBackground()) return; EZ_LOCK(m_pMainWorld->GetWriteMarker()); ezGameObject* pGameUiObject = nullptr; if (m_pMainWorld->TryGetObjectWithGlobalKey(ezTempHashedString("game-ui"), pGameUiObject)) { ezRmlUiCanvas2DComponent* pGameUiComponent = nullptr; if (pGameUiObject->TryGetComponentOfBaseType(pGameUiComponent)) { pGameUiComponent->SetCustomScale(m_fUiScale); } } SetActiveGameMode(m_GameModeToSwitchTo); m_SelectedUnits.RemoveDeadObjects(); if (m_pActiveGameMode) { m_pActiveGameMode->BeforeWorldUpdate(); } // update the sound listener position to be the same as the camera position if (ezSoundInterface* pSoundInterface = ezSingletonRegistry::GetSingletonInstance<ezSoundInterface>()) { const ezVec3 pos = m_MainCamera.GetCenterPosition(); const ezVec3 dir = m_MainCamera.GetCenterDirForwards(); const ezVec3 up = m_MainCamera.GetCenterDirUp(); pSoundInterface->SetListener(0, pos, dir, up, ezVec3::MakeZero()); } } void RTSGameState::ConfigureMainCamera() { SUPER::ConfigureMainCamera(); m_fCameraZoom = 20.0f; ezVec3 vCameraPos = ezVec3(0.0f, 0.0f, m_fCameraZoom); ezCoordinateSystem coordSys; if (m_pMainWorld) { m_pMainWorld->GetCoordinateSystem(vCameraPos, coordSys); } else { coordSys.m_vForwardDir.Set(1, 0, 0); coordSys.m_vRightDir.Set(0, 1, 0); coordSys.m_vUpDir.Set(0, 0, 1); } m_MainCamera.SetCameraMode(ezCameraMode::PerspectiveFixedFovY, 45.0f, 0.1f, 100); m_MainCamera.LookAt(vCameraPos, vCameraPos - coordSys.m_vUpDir, coordSys.m_vForwardDir); } void RTSGameState::OnChangedMainWorld(ezWorld* pPrevWorld, ezWorld* pNewWorld, ezStringView sStartPosition, const ezTransform& startPositionOffset) { SUPER::OnChangedMainWorld(pPrevWorld, pNewWorld, sStartPosition, startPositionOffset); m_SelectedUnits.Clear(); m_SelectedUnits.SetWorld(pNewWorld); } void RTSGameState::SwitchToGameMode(RtsActiveGameMode mode) { // can't just switch game modes in the middle of a frame, so delay this to the next frame m_GameModeToSwitchTo = mode; } void RTSGameState::SetActiveGameMode(RtsActiveGameMode mode) { if (m_ActiveGameMode == mode) return; if (m_pActiveGameMode) { m_pActiveGameMode->DeactivateMode(); } m_PrevGameMode = m_ActiveGameMode; m_ActiveGameMode = mode; switch (m_ActiveGameMode) { case RtsActiveGameMode::None: m_pActiveGameMode = nullptr; break; case RtsActiveGameMode::MainMenuMode: m_pActiveGameMode = m_pMainMenuMode.Borrow(); break; case RtsActiveGameMode::SettingsMenuMode: m_pActiveGameMode = m_pSettingsMenuMode.Borrow(); break; case RtsActiveGameMode::BattleMode: m_pActiveGameMode = m_pBattleMode.Borrow(); break; case RtsActiveGameMode::EditLevelMode: m_pActiveGameMode = m_pEditLevelMode.Borrow(); break; } if (m_pActiveGameMode) { m_pActiveGameMode->ActivateMode(m_pMainWorld, m_hMainView, &m_MainCamera); } } ezGameObject* RTSGameState::DetectHoveredSelectable() { m_hHoveredSelectable.Invalidate(); ezGameObject* pSelected = PickSelectableObject(); if (pSelected != nullptr) { m_hHoveredSelectable = pSelected->GetHandle(); return pSelected; } return nullptr; } void RTSGameState::SelectUnits() { ezGameObject* pSelected = PickSelectableObject(); if (pSelected != nullptr) { if (ezInputManager::GetInputSlotState(ezInputSlot_KeyLeftCtrl) == ezKeyState::Down || ezInputManager::GetInputSlotState(ezInputSlot_KeyRightCtrl) == ezKeyState::Down) { m_SelectedUnits.ToggleSelection(pSelected->GetHandle()); } else { m_SelectedUnits.Clear(); m_SelectedUnits.AddObject(pSelected->GetHandle()); } } else { m_SelectedUnits.Clear(); } } void RTSGameState::RenderUnitSelection() const { ezBoundingBox bbox; for (ezUInt32 i = 0; i < m_SelectedUnits.GetCount(); ++i) { ezGameObjectHandle hObject = m_SelectedUnits.GetObject(i); ezGameObject* pObject; if (!m_pMainWorld->TryGetObject(hObject, pObject)) continue; RtsSelectableComponent* pSelectable; if (!pObject->TryGetComponentOfBaseType(pSelectable)) continue; const float fRadius = pSelectable->m_fSelectionRadius * 1.1f; ezTransform t = pObject->GetGlobalTransform(); t.m_vScale.Set(1.0f); t.m_qRotation.SetIdentity(); bbox = ezBoundingBox::MakeFromCenterAndHalfExtents(ezVec3::MakeZero(), ezVec3(fRadius, fRadius, 0)); ezDebugRenderer::DrawLineBoxCorners(m_pMainWorld, bbox, 0.1f, ezColor::White, t); RenderUnitHealthbar(pObject, fRadius); } // hovered unit { ezGameObject* pObject; if (m_pMainWorld->TryGetObject(m_hHoveredSelectable, pObject)) { RtsSelectableComponent* pSelectable; if (pObject->TryGetComponentOfBaseType(pSelectable)) { const float fRadius = pSelectable->m_fSelectionRadius * 1.1f; ezTransform t = pObject->GetGlobalTransform(); t.m_vScale.Set(1.0f); t.m_qRotation.SetIdentity(); bbox = ezBoundingBox::MakeFromCenterAndHalfExtents(ezVec3::MakeZero(), ezVec3(fRadius, fRadius, 0)); ezDebugRenderer::DrawLineBoxCorners(m_pMainWorld, bbox, 0.1f, ezColor::DodgerBlue, t); RenderUnitHealthbar(pObject, fRadius); } } } } void RTSGameState::RenderUnitHealthbar(ezGameObject* pObject, float fSelectableRadius) const { RtsMsgGatherUnitStats msgStats; pObject->SendMessageRecursive(msgStats); if (msgStats.m_uiMaxHealth > 0) { const float percentage = msgStats.m_uiCurHealth / (float)msgStats.m_uiMaxHealth; const float fOffset = 0.01f; ezVec3 pos = pObject->GetGlobalPosition(); pos.x += fSelectableRadius - 0.04f - fOffset; ezColor c = ezColor::Lime; if (percentage < 0.3f) c = ezColor::Red; else if (percentage < 0.6f) c = ezColor::Orange; else if (percentage < 0.8f) c = ezColor::Yellow; ezBoundingBox bbox = ezBoundingBox::MakeFromCenterAndHalfExtents(ezVec3::MakeZero(), ezVec3(0.04f, fSelectableRadius * percentage - fOffset, 0)); ezDebugRenderer::DrawSolidBox(m_pMainWorld, bbox, c, ezTransform(pos)); } } ezResult RTSGameState::ComputePickingRay() { ezView* pView = nullptr; if (!ezRenderWorld::TryGetView(m_hMainView, pView)) return EZ_FAILURE; ezVec3 vMousePos((float)m_MouseInputState.m_MousePos.x, (float)m_MouseInputState.m_MousePos.y, 0); pView->ConvertScreenPixelPosToNormalizedPos(vMousePos); return pView->ComputePickingRay(vMousePos.x, vMousePos.y, m_vCurrentPickingRayStart, m_vCurrentPickingRayDir); } ezResult RTSGameState::PickGroundPlanePosition(ezVec3& out_vPositon) const { ezPlane p; p = ezPlane::MakeFromNormalAndPoint(ezVec3(0, 0, 1), ezVec3(0)); return p.GetRayIntersection(m_vCurrentPickingRayStart, m_vCurrentPickingRayDir, nullptr, &out_vPositon) ? EZ_SUCCESS : EZ_FAILURE; } ezGameObject* RTSGameState::PickSelectableObject() const { struct Payload { ezGameObject* pBestObject = nullptr; float fBestDistSQR = ezMath::Square(1000.0f); ezVec3 vGroundPos; }; Payload pl; if (PickGroundPlanePosition(pl.vGroundPos).Failed()) return nullptr; ezSpatialSystem::QueryCallback cb = [&pl](ezGameObject* pObject) { RtsSelectableComponent* pSelectable = nullptr; if (pObject->TryGetComponentOfBaseType(pSelectable)) { const float dist = (pObject->GetGlobalTransform().m_vPosition - pl.vGroundPos).GetLengthSquared(); if (dist < pl.fBestDistSQR && dist <= ezMath::Square(pSelectable->m_fSelectionRadius)) { pl.fBestDistSQR = dist; pl.pBestObject = pObject; } } return ezVisitorExecution::Continue; }; InspectObjectsInArea(pl.vGroundPos.GetAsVec2(), 1.0f, cb); return pl.pBestObject; } // BEGIN-DOCS-CODE-SNIPPET: spatial-query void RTSGameState::InspectObjectsInArea(const ezVec2& vPosition, float fRadius, ezSpatialSystem::QueryCallback callback) const { ezBoundingSphere sphere = ezBoundingSphere::MakeFromCenterAndRadius(vPosition.GetAsVec3(0), fRadius); ezSpatialSystem::QueryParams queryParams; queryParams.m_uiCategoryBitmask = RtsSelectableComponent::s_SelectableCategory.GetBitmask(); m_pMainWorld->GetSpatialSystem()->FindObjectsInSphere(sphere, queryParams, callback); } // END-DOCS-CODE-SNIPPET ezGameObject* RTSGameState::SpawnNamedObjectAt(const ezTransform& transform, const char* szObjectName, ezUInt16 uiTeamID) { ezPrefabResourceHandle hPrefab = ezResourceManager::LoadResource<ezPrefabResource>(szObjectName); ezResourceLock<ezPrefabResource> pPrefab(hPrefab, ezResourceAcquireMode::BlockTillLoaded); ezHybridArray<ezGameObject*, 8> CreatedRootObjects; ezPrefabInstantiationOptions options; options.m_pCreatedRootObjectsOut = &CreatedRootObjects; options.m_pOverrideTeamID = &uiTeamID; pPrefab->InstantiatePrefab(*m_pMainWorld, transform, options); return CreatedRootObjects[0]; }