#include #include namespace XCEngine { namespace UI { namespace Runtime { UISystem::UISystem(IUIScreenDocumentHost& documentHost) : m_documentHost(&documentHost) { } UIScreenPlayer& UISystem::CreatePlayer(const UIScreenLayerOptions& options) { m_players.push_back(std::make_unique(*m_documentHost)); m_layerIds.push_back(m_nextLayerId++); m_layerOptions.push_back(options); return *m_players.back(); } UIScreenLayerId UISystem::PushScreen( const UIScreenAsset& asset, const UIScreenLayerOptions& options) { UIScreenPlayer& player = CreatePlayer(options); if (!player.Load(asset)) { m_players.pop_back(); m_layerIds.pop_back(); m_layerOptions.pop_back(); return 0; } return m_layerIds.empty() ? 0 : m_layerIds.back(); } bool UISystem::RemoveLayer(UIScreenLayerId layerId) { const std::size_t index = FindLayerIndex(layerId); if (index >= m_players.size()) { return false; } m_players.erase(m_players.begin() + static_cast(index)); m_layerIds.erase(m_layerIds.begin() + static_cast(index)); m_layerOptions.erase(m_layerOptions.begin() + static_cast(index)); return true; } bool UISystem::SetLayerVisibility(UIScreenLayerId layerId, bool visible) { const std::size_t index = FindLayerIndex(layerId); if (index >= m_layerOptions.size()) { return false; } m_layerOptions[index].visible = visible; return true; } bool UISystem::SetLayerOptions( UIScreenLayerId layerId, const UIScreenLayerOptions& options) { const std::size_t index = FindLayerIndex(layerId); if (index >= m_layerOptions.size()) { return false; } m_layerOptions[index] = options; return true; } const UIScreenLayerOptions* UISystem::FindLayerOptions(UIScreenLayerId layerId) const { const std::size_t index = FindLayerIndex(layerId); return index < m_layerOptions.size() ? &m_layerOptions[index] : nullptr; } UIScreenLayerId UISystem::GetLayerId(std::size_t index) const { return index < m_layerIds.size() ? m_layerIds[index] : 0; } void UISystem::DestroyAllPlayers() { m_players.clear(); m_layerIds.clear(); m_layerOptions.clear(); m_lastFrame = {}; } std::size_t UISystem::GetPlayerCount() const { return m_players.size(); } std::size_t UISystem::GetLayerCount() const { return m_layerIds.size(); } const UISystemFrameResult& UISystem::Update(const UIScreenFrameInput& input) { m_lastFrame = {}; m_lastFrame.frameIndex = input.frameIndex; std::vector presentedIndices; presentedIndices.reserve(m_players.size()); for (std::size_t index = m_players.size(); index > 0; --index) { const std::size_t layerIndex = index - 1; if (!m_layerOptions[layerIndex].visible) { continue; } presentedIndices.push_back(layerIndex); if (m_layerOptions[layerIndex].blocksLayersBelow) { break; } } std::reverse(presentedIndices.begin(), presentedIndices.end()); std::size_t interactiveLayerIndex = m_players.size(); for (std::size_t index = presentedIndices.size(); index > 0; --index) { const std::size_t layerIndex = presentedIndices[index - 1]; if (m_layerOptions[layerIndex].acceptsInput) { interactiveLayerIndex = layerIndex; break; } } for (const std::size_t layerIndex : presentedIndices) { UIScreenFrameInput layerInput = input; if (layerIndex != interactiveLayerIndex) { layerInput.events.clear(); } const UIScreenFrameResult& frame = m_players[layerIndex]->Update(layerInput); for (const UIDrawList& drawList : frame.drawData.GetDrawLists()) { m_lastFrame.drawData.AddDrawList(drawList); } UISystemPresentedLayer presentedLayer = {}; presentedLayer.layerId = m_layerIds[layerIndex]; if (const UIScreenAsset* asset = m_players[layerIndex]->GetAsset(); asset != nullptr) { presentedLayer.asset = *asset; } presentedLayer.options = m_layerOptions[layerIndex]; presentedLayer.stats = frame.stats; m_lastFrame.layers.push_back(std::move(presentedLayer)); if (m_lastFrame.errorMessage.empty() && !frame.errorMessage.empty()) { m_lastFrame.errorMessage = frame.errorMessage; } } m_lastFrame.presentedLayerCount = m_lastFrame.layers.size(); m_lastFrame.skippedLayerCount = m_players.size() > m_lastFrame.presentedLayerCount ? m_players.size() - m_lastFrame.presentedLayerCount : 0; return m_lastFrame; } void UISystem::Tick(const UIScreenFrameInput& input) { for (const std::unique_ptr& player : m_players) { if (player) { player->Update(input); } } } const UISystemFrameResult& UISystem::GetLastFrame() const { return m_lastFrame; } const std::vector>& UISystem::GetPlayers() const { return m_players; } std::size_t UISystem::FindLayerIndex(UIScreenLayerId layerId) const { for (std::size_t index = 0; index < m_layerIds.size(); ++index) { if (m_layerIds[index] == layerId) { return index; } } return m_layerIds.size(); } } // namespace Runtime } // namespace UI } // namespace XCEngine