18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#ifndef CORE_UTIL_ECS_COMPONENT_QUERY_H 178bf80f4bSopenharmony_ci#define CORE_UTIL_ECS_COMPONENT_QUERY_H 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ci#include <cstddef> 208bf80f4bSopenharmony_ci#include <cstdint> 218bf80f4bSopenharmony_ci 228bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 238bf80f4bSopenharmony_ci#include <base/containers/vector.h> 248bf80f4bSopenharmony_ci#include <base/namespace.h> 258bf80f4bSopenharmony_ci#include <core/ecs/entity.h> 268bf80f4bSopenharmony_ci#include <core/ecs/intf_component_manager.h> 278bf80f4bSopenharmony_ci#include <core/ecs/intf_ecs.h> 288bf80f4bSopenharmony_ci#include <core/namespace.h> 298bf80f4bSopenharmony_ci 308bf80f4bSopenharmony_ciBASE_BEGIN_NAMESPACE() 318bf80f4bSopenharmony_citemplate<class T> 328bf80f4bSopenharmony_ciclass array_view; 338bf80f4bSopenharmony_ciBASE_END_NAMESPACE() 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE() 368bf80f4bSopenharmony_ci/** Executes queries to component managers and outputs a result set that can be used to speed-up component data access. 378bf80f4bSopenharmony_ci */ 388bf80f4bSopenharmony_ciclass ComponentQuery : private IEcs::EntityListener, private IEcs::ComponentListener { 398bf80f4bSopenharmony_cipublic: 408bf80f4bSopenharmony_ci ComponentQuery() = default; 418bf80f4bSopenharmony_ci ~ComponentQuery() override; 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_ci /** Operations for the component query that are being applied in to of the base component set. */ 448bf80f4bSopenharmony_ci struct Operation { 458bf80f4bSopenharmony_ci /** Method of operation. */ 468bf80f4bSopenharmony_ci enum Method : uint8_t { 478bf80f4bSopenharmony_ci /** Looks up a component of given type and filters out the entity from the base set if it doesn't contain 488bf80f4bSopenharmony_ci such component. */ 498bf80f4bSopenharmony_ci REQUIRE, 508bf80f4bSopenharmony_ci /** Looks up a component of given type, but never filters out the entity from the base set. */ 518bf80f4bSopenharmony_ci OPTIONAL 528bf80f4bSopenharmony_ci }; 538bf80f4bSopenharmony_ci const IComponentManager& target; 548bf80f4bSopenharmony_ci Method method { REQUIRE }; 558bf80f4bSopenharmony_ci }; 568bf80f4bSopenharmony_ci 578bf80f4bSopenharmony_ci /** Sets up a component query to component managers. 588bf80f4bSopenharmony_ci * @param baseComponentSet Components that are used as a base set for query, this should be the component manager 598bf80f4bSopenharmony_ci * that has least amount of components. 608bf80f4bSopenharmony_ci * @param operations Operations that are performed to base set when other component managers are merged to result. 618bf80f4bSopenharmony_ci * @param enableEntityLookup If true, allows to look up result row by using entity as a key (FindResultRow), this 628bf80f4bSopenharmony_ci * slightly slows down the look-up process. 638bf80f4bSopenharmony_ci */ 648bf80f4bSopenharmony_ci void SetupQuery(const IComponentManager& baseComponentSet, BASE_NS::array_view<const Operation> operations, 658bf80f4bSopenharmony_ci bool enableEntityLookup = false); 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_ci /** Executes the query. Assumes that the query has been set up earlier. 688bf80f4bSopenharmony_ci * @return True if there are possible changes in the query result since previous execute. 698bf80f4bSopenharmony_ci */ 708bf80f4bSopenharmony_ci bool Execute(); 718bf80f4bSopenharmony_ci 728bf80f4bSopenharmony_ci [[deprecated]] void Execute(const IComponentManager& baseComponentSet, 738bf80f4bSopenharmony_ci BASE_NS::array_view<const Operation> operations, bool enableEntityLookup = false); 748bf80f4bSopenharmony_ci 758bf80f4bSopenharmony_ci /** Enable or disable listening to ECS events. Enabling listeners will automatically invalidate this query when 768bf80f4bSopenharmony_ci * there are changes in the relevant component managers. 778bf80f4bSopenharmony_ci * @param enableListeners True to enable listening to ecs events to automatically invalidate the query. 788bf80f4bSopenharmony_ci */ 798bf80f4bSopenharmony_ci void SetEcsListenersEnabled(bool enableListeners); 808bf80f4bSopenharmony_ci 818bf80f4bSopenharmony_ci /** Check if the result of this query is still valid. Requires a call to RegisterEcsListeners after each execution. 828bf80f4bSopenharmony_ci * @return True if there have been no changes in listened component managers since previous execute that would 838bf80f4bSopenharmony_ci * affect the query result. 848bf80f4bSopenharmony_ci */ 858bf80f4bSopenharmony_ci bool IsValid() const; 868bf80f4bSopenharmony_ci 878bf80f4bSopenharmony_ci /** One row in a result set, describes the entity and its component ids. */ 888bf80f4bSopenharmony_ci struct ResultRow { 898bf80f4bSopenharmony_ci ResultRow() = default; 908bf80f4bSopenharmony_ci ~ResultRow() = default; 918bf80f4bSopenharmony_ci 928bf80f4bSopenharmony_ci ResultRow(const ResultRow& rhs) = delete; 938bf80f4bSopenharmony_ci ResultRow& operator=(const ResultRow& rhs) = delete; 948bf80f4bSopenharmony_ci ResultRow(ResultRow&& rhs) noexcept = default; 958bf80f4bSopenharmony_ci ResultRow& operator=(ResultRow&& rhs) noexcept = default; 968bf80f4bSopenharmony_ci 978bf80f4bSopenharmony_ci /** Checks whether component id in given index is valid. 988bf80f4bSopenharmony_ci * The component id can be invalid if the component was specified optional and it is not available) 998bf80f4bSopenharmony_ci * @param index Index of the component. 1008bf80f4bSopenharmony_ci * @return True if the component id is valid, false if the component id is invalid (optional components that is 1018bf80f4bSopenharmony_ci * not available). 1028bf80f4bSopenharmony_ci */ 1038bf80f4bSopenharmony_ci bool IsValidComponentId(size_t index) const; 1048bf80f4bSopenharmony_ci 1058bf80f4bSopenharmony_ci /** Entity that contains the components. */ 1068bf80f4bSopenharmony_ci Entity entity; 1078bf80f4bSopenharmony_ci 1088bf80f4bSopenharmony_ci /** List of component ids, in the same order that the component managers were specified in the Execute(...) 1098bf80f4bSopenharmony_ci * call. */ 1108bf80f4bSopenharmony_ci BASE_NS::vector<IComponentManager::ComponentId> components; 1118bf80f4bSopenharmony_ci }; 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ci /** Returns The result of the query, in form of rows. 1148bf80f4bSopenharmony_ci * @return Array of result rows, where each row describes an entity and its component ids. 1158bf80f4bSopenharmony_ci */ 1168bf80f4bSopenharmony_ci BASE_NS::array_view<const ResultRow> GetResults() const; 1178bf80f4bSopenharmony_ci 1188bf80f4bSopenharmony_ci /** Look up result row for a given entity. To enable this functionality, the Execute() function needs to be called 1198bf80f4bSopenharmony_ci * with enableEntityLookup parameter set as true. 1208bf80f4bSopenharmony_ci * @param entity Entity to use in look-up 1218bf80f4bSopenharmony_ci * @return Pointer to result row for given entity, or nullptr if there is no such row. 1228bf80f4bSopenharmony_ci */ 1238bf80f4bSopenharmony_ci const ResultRow* FindResultRow(Entity entity) const; 1248bf80f4bSopenharmony_ci 1258bf80f4bSopenharmony_ciprivate: 1268bf80f4bSopenharmony_ci void RegisterEcsListeners(); 1278bf80f4bSopenharmony_ci void UnregisterEcsListeners(); 1288bf80f4bSopenharmony_ci 1298bf80f4bSopenharmony_ci // IEcs::EntityListener 1308bf80f4bSopenharmony_ci void OnEntityEvent(IEcs::EntityListener::EventType type, BASE_NS::array_view<const Entity> entities) override; 1318bf80f4bSopenharmony_ci 1328bf80f4bSopenharmony_ci // IEcs::ComponentListener 1338bf80f4bSopenharmony_ci void OnComponentEvent(IEcs::ComponentListener::EventType type, const IComponentManager& componentManager, 1348bf80f4bSopenharmony_ci BASE_NS::array_view<const Entity> entities) override; 1358bf80f4bSopenharmony_ci 1368bf80f4bSopenharmony_ci CORE_NS::IEcs* ecs_ { nullptr }; 1378bf80f4bSopenharmony_ci BASE_NS::vector<ResultRow> result_; 1388bf80f4bSopenharmony_ci BASE_NS::vector<IComponentManager*> managers_; 1398bf80f4bSopenharmony_ci BASE_NS::vector<Operation::Method> operationMethods_; 1408bf80f4bSopenharmony_ci BASE_NS::unordered_map<Entity, size_t> mapping_; 1418bf80f4bSopenharmony_ci bool enableLookup_ { false }; 1428bf80f4bSopenharmony_ci bool enableListeners_ { false }; 1438bf80f4bSopenharmony_ci bool registered_ { false }; 1448bf80f4bSopenharmony_ci bool valid_ { false }; 1458bf80f4bSopenharmony_ci}; 1468bf80f4bSopenharmony_ciCORE_END_NAMESPACE() 1478bf80f4bSopenharmony_ci 1488bf80f4bSopenharmony_ci#endif // CORE_UTIL_ECS_COMPONENT_QUERY 149