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#include "dotfield/ecs/systems/dotfield_system.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <PropertyTools/property_api_impl.h> 198bf80f4bSopenharmony_ci#include <PropertyTools/property_api_impl.inl> 208bf80f4bSopenharmony_ci#include <PropertyTools/property_data.h> 218bf80f4bSopenharmony_ci#include <PropertyTools/property_macros.h> 228bf80f4bSopenharmony_ci#include <cmath> 238bf80f4bSopenharmony_ci#include <random> 248bf80f4bSopenharmony_ci 258bf80f4bSopenharmony_ci#include <3d/ecs/components/transform_component.h> 268bf80f4bSopenharmony_ci#include <3d/ecs/components/world_matrix_component.h> 278bf80f4bSopenharmony_ci#include <base/containers/fixed_string.h> 288bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 298bf80f4bSopenharmony_ci#include <base/math/matrix_util.h> 308bf80f4bSopenharmony_ci#include <base/math/quaternion_util.h> 318bf80f4bSopenharmony_ci#include <base/math/vector_util.h> 328bf80f4bSopenharmony_ci#include <core/ecs/intf_component_manager.h> 338bf80f4bSopenharmony_ci#include <core/ecs/intf_ecs.h> 348bf80f4bSopenharmony_ci#include <core/implementation_uids.h> 358bf80f4bSopenharmony_ci#include <core/intf_engine.h> 368bf80f4bSopenharmony_ci#include <core/plugin/intf_class_factory.h> 378bf80f4bSopenharmony_ci#include <core/property/intf_property_api.h> 388bf80f4bSopenharmony_ci#include <core/property/intf_property_handle.h> 398bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_manager.h> 408bf80f4bSopenharmony_ci#include <render/implementation_uids.h> 418bf80f4bSopenharmony_ci 428bf80f4bSopenharmony_ci#include "dotfield/ecs/components/dotfield_component.h" 438bf80f4bSopenharmony_ci#include "render/render_data_store_default_dotfield.h" 448bf80f4bSopenharmony_ci 458bf80f4bSopenharmony_cinamespace { 468bf80f4bSopenharmony_ci#include "app/shaders/common/dotfield_struct_common.h" 478bf80f4bSopenharmony_ci} // namespace 488bf80f4bSopenharmony_ci 498bf80f4bSopenharmony_ciusing namespace BASE_NS; 508bf80f4bSopenharmony_ciusing namespace CORE_NS; 518bf80f4bSopenharmony_ciusing namespace RENDER_NS; 528bf80f4bSopenharmony_ciusing namespace CORE3D_NS; 538bf80f4bSopenharmony_ciusing namespace Dotfield; 548bf80f4bSopenharmony_cinamespace { 558bf80f4bSopenharmony_ci 568bf80f4bSopenharmony_ciclass DotfieldSystem final : public IDotfieldSystem, private IEcs::ComponentListener { 578bf80f4bSopenharmony_cipublic: 588bf80f4bSopenharmony_ci DotfieldSystem(IEcs& aECS); 598bf80f4bSopenharmony_ci ~DotfieldSystem(); 608bf80f4bSopenharmony_ci 618bf80f4bSopenharmony_ci // ISystem 628bf80f4bSopenharmony_ci string_view GetName() const override; 638bf80f4bSopenharmony_ci Uid GetUid() const override; 648bf80f4bSopenharmony_ci 658bf80f4bSopenharmony_ci IPropertyHandle* GetProperties() override; 668bf80f4bSopenharmony_ci const IPropertyHandle* GetProperties() const override; 678bf80f4bSopenharmony_ci void SetProperties(const IPropertyHandle&) override; 688bf80f4bSopenharmony_ci 698bf80f4bSopenharmony_ci bool IsActive() const override; 708bf80f4bSopenharmony_ci void SetActive(bool state) override; 718bf80f4bSopenharmony_ci 728bf80f4bSopenharmony_ci void Initialize() override; 738bf80f4bSopenharmony_ci void Uninitialize() override; 748bf80f4bSopenharmony_ci bool Update(bool frameRenderingQueued, uint64_t time, uint64_t delta) override; 758bf80f4bSopenharmony_ci 768bf80f4bSopenharmony_ci const IEcs& GetECS() const override; 778bf80f4bSopenharmony_ci 788bf80f4bSopenharmony_ci void OnComponentEvent( 798bf80f4bSopenharmony_ci EventType type, const IComponentManager& componentManager, array_view<const Entity> entities) override; 808bf80f4bSopenharmony_ci 818bf80f4bSopenharmony_ciprivate: 828bf80f4bSopenharmony_ci struct PropertyData { 838bf80f4bSopenharmony_ci float speed { 1.f }; 848bf80f4bSopenharmony_ci }; 858bf80f4bSopenharmony_ci 868bf80f4bSopenharmony_ci BEGIN_PROPERTY(PropertyData, ComponentMetadata) 878bf80f4bSopenharmony_ci DECL_PROPERTY2(PropertyData, speed, "Simulation speed", 0) 888bf80f4bSopenharmony_ci END_PROPERTY(); 898bf80f4bSopenharmony_ci 908bf80f4bSopenharmony_ci bool active_ { true }; 918bf80f4bSopenharmony_ci IEcs& ecs_; 928bf80f4bSopenharmony_ci IRenderDataStoreManager& renderDataStoreManager_; 938bf80f4bSopenharmony_ci IWorldMatrixComponentManager& worldMatrixManager_; 948bf80f4bSopenharmony_ci IDotfieldComponentManager& dotfieldManager_; 958bf80f4bSopenharmony_ci 968bf80f4bSopenharmony_ci PropertyData props_ { 1.f }; 978bf80f4bSopenharmony_ci 988bf80f4bSopenharmony_ci PropertyApiImpl<PropertyData> propertyApi_ = PropertyApiImpl<PropertyData>(&props_, ComponentMetadata); 998bf80f4bSopenharmony_ci}; 1008bf80f4bSopenharmony_ci 1018bf80f4bSopenharmony_ciDotfieldSystem::DotfieldSystem(IEcs& ecs) 1028bf80f4bSopenharmony_ci : ecs_(ecs), renderDataStoreManager_(GetInstance<IRenderContext>( 1038bf80f4bSopenharmony_ci *ecs.GetClassFactory().GetInterface<IClassRegister>(), UID_RENDER_CONTEXT) 1048bf80f4bSopenharmony_ci ->GetRenderDataStoreManager()), 1058bf80f4bSopenharmony_ci worldMatrixManager_(*GetManager<IWorldMatrixComponentManager>(ecs)), 1068bf80f4bSopenharmony_ci dotfieldManager_(*GetManager<IDotfieldComponentManager>(ecs)) 1078bf80f4bSopenharmony_ci{ 1088bf80f4bSopenharmony_ci ecs.AddListener(dotfieldManager_, *this); 1098bf80f4bSopenharmony_ci} 1108bf80f4bSopenharmony_ci 1118bf80f4bSopenharmony_ciDotfieldSystem ::~DotfieldSystem() 1128bf80f4bSopenharmony_ci{ 1138bf80f4bSopenharmony_ci ecs_.RemoveListener(dotfieldManager_, *this); 1148bf80f4bSopenharmony_ci} 1158bf80f4bSopenharmony_ci 1168bf80f4bSopenharmony_civoid DotfieldSystem::SetActive(bool state) 1178bf80f4bSopenharmony_ci{ 1188bf80f4bSopenharmony_ci active_ = state; 1198bf80f4bSopenharmony_ci} 1208bf80f4bSopenharmony_ci 1218bf80f4bSopenharmony_cibool DotfieldSystem::IsActive() const 1228bf80f4bSopenharmony_ci{ 1238bf80f4bSopenharmony_ci return active_; 1248bf80f4bSopenharmony_ci} 1258bf80f4bSopenharmony_ci 1268bf80f4bSopenharmony_cistring_view DotfieldSystem::GetName() const 1278bf80f4bSopenharmony_ci{ 1288bf80f4bSopenharmony_ci return Dotfield::GetName(this); 1298bf80f4bSopenharmony_ci} 1308bf80f4bSopenharmony_ci 1318bf80f4bSopenharmony_ciUid DotfieldSystem::GetUid() const 1328bf80f4bSopenharmony_ci{ 1338bf80f4bSopenharmony_ci return UID; 1348bf80f4bSopenharmony_ci} 1358bf80f4bSopenharmony_ci 1368bf80f4bSopenharmony_ciIPropertyHandle* DotfieldSystem::GetProperties() 1378bf80f4bSopenharmony_ci{ 1388bf80f4bSopenharmony_ci return propertyApi_.GetData(); 1398bf80f4bSopenharmony_ci} 1408bf80f4bSopenharmony_ci 1418bf80f4bSopenharmony_ciconst IPropertyHandle* DotfieldSystem::GetProperties() const 1428bf80f4bSopenharmony_ci{ 1438bf80f4bSopenharmony_ci return propertyApi_.GetData(); 1448bf80f4bSopenharmony_ci} 1458bf80f4bSopenharmony_ci 1468bf80f4bSopenharmony_civoid DotfieldSystem::SetProperties(const IPropertyHandle& dataHandle) 1478bf80f4bSopenharmony_ci{ 1488bf80f4bSopenharmony_ci if (dataHandle.Owner() != &propertyApi_) { 1498bf80f4bSopenharmony_ci return; 1508bf80f4bSopenharmony_ci } 1518bf80f4bSopenharmony_ci if (auto data = ScopedHandle<const PropertyData>(&dataHandle); data) { 1528bf80f4bSopenharmony_ci props_ = *data; 1538bf80f4bSopenharmony_ci } 1548bf80f4bSopenharmony_ci} 1558bf80f4bSopenharmony_ci 1568bf80f4bSopenharmony_ciconst IEcs& DotfieldSystem::GetECS() const 1578bf80f4bSopenharmony_ci{ 1588bf80f4bSopenharmony_ci return ecs_; 1598bf80f4bSopenharmony_ci} 1608bf80f4bSopenharmony_ci 1618bf80f4bSopenharmony_civoid DotfieldSystem::Initialize() {} 1628bf80f4bSopenharmony_ci 1638bf80f4bSopenharmony_civoid DotfieldSystem::Uninitialize() {} 1648bf80f4bSopenharmony_ci 1658bf80f4bSopenharmony_cibool DotfieldSystem::Update(bool frameRenderingQueued, uint64_t time, uint64_t delta) 1668bf80f4bSopenharmony_ci{ 1678bf80f4bSopenharmony_ci if (!active_) { 1688bf80f4bSopenharmony_ci return false; 1698bf80f4bSopenharmony_ci } 1708bf80f4bSopenharmony_ci 1718bf80f4bSopenharmony_ci RenderDataStoreDefaultDotfield* dsDefaultDotfield = static_cast<RenderDataStoreDefaultDotfield*>( 1728bf80f4bSopenharmony_ci renderDataStoreManager_.GetRenderDataStore("RenderDataStoreDefaultDotfield")); 1738bf80f4bSopenharmony_ci if (dsDefaultDotfield) { 1748bf80f4bSopenharmony_ci const auto timeStep = delta * 0.000001f * props_.speed; 1758bf80f4bSopenharmony_ci dsDefaultDotfield->SetTimeStep(timeStep); 1768bf80f4bSopenharmony_ci dsDefaultDotfield->SetTime(time * 0.000001f); 1778bf80f4bSopenharmony_ci 1788bf80f4bSopenharmony_ci array_view<RenderDataDefaultDotfield::DotfieldPrimitive> dotfieldPrimitives = 1798bf80f4bSopenharmony_ci dsDefaultDotfield->GetDotfieldPrimitives(); 1808bf80f4bSopenharmony_ci 1818bf80f4bSopenharmony_ci for (auto& prim : dotfieldPrimitives) { 1828bf80f4bSopenharmony_ci const auto& dfc = dotfieldManager_.Get(prim.entity); 1838bf80f4bSopenharmony_ci prim.touch = dfc.touchPosition; 1848bf80f4bSopenharmony_ci prim.touchDirection = dfc.touchDirection; 1858bf80f4bSopenharmony_ci prim.touchRadius = dfc.touchRadius; 1868bf80f4bSopenharmony_ci prim.pointScale = dfc.pointScale; 1878bf80f4bSopenharmony_ci if (worldMatrixManager_.HasComponent(prim.entity)) { 1888bf80f4bSopenharmony_ci WorldMatrixComponent wc = worldMatrixManager_.Get(prim.entity); 1898bf80f4bSopenharmony_ci prim.matrix = wc.matrix; 1908bf80f4bSopenharmony_ci } 1918bf80f4bSopenharmony_ci } 1928bf80f4bSopenharmony_ci } 1938bf80f4bSopenharmony_ci return frameRenderingQueued; 1948bf80f4bSopenharmony_ci} 1958bf80f4bSopenharmony_ci 1968bf80f4bSopenharmony_civoid DotfieldSystem::OnComponentEvent( 1978bf80f4bSopenharmony_ci EventType type, const IComponentManager& componentManager, array_view<const Entity> entities) 1988bf80f4bSopenharmony_ci{ 1998bf80f4bSopenharmony_ci RenderDataStoreDefaultDotfield* dsDefaultDotfield = static_cast<RenderDataStoreDefaultDotfield*>( 2008bf80f4bSopenharmony_ci renderDataStoreManager_.GetRenderDataStore("RenderDataStoreDefaultDotfield")); 2018bf80f4bSopenharmony_ci switch (type) { 2028bf80f4bSopenharmony_ci case EventType::CREATED: 2038bf80f4bSopenharmony_ci for (const auto& entity : entities) { 2048bf80f4bSopenharmony_ci if (worldMatrixManager_.HasComponent(entity)) { 2058bf80f4bSopenharmony_ci WorldMatrixComponent wc = worldMatrixManager_.Get(entity); 2068bf80f4bSopenharmony_ci DotfieldComponent dfc = dotfieldManager_.Get(entity); 2078bf80f4bSopenharmony_ci 2088bf80f4bSopenharmony_ci RenderDataDefaultDotfield::DotfieldPrimitive prim; 2098bf80f4bSopenharmony_ci prim.entity = entity; 2108bf80f4bSopenharmony_ci prim.matrix = wc.matrix; 2118bf80f4bSopenharmony_ci prim.touch = dfc.touchPosition; 2128bf80f4bSopenharmony_ci prim.touchDirection = dfc.touchDirection; 2138bf80f4bSopenharmony_ci prim.touchRadius = dfc.touchRadius; 2148bf80f4bSopenharmony_ci prim.colors = { dfc.color0, dfc.color1, dfc.color2, dfc.color3 }; 2158bf80f4bSopenharmony_ci prim.size = { static_cast<uint32_t>(dfc.size.x), static_cast<uint32_t>(dfc.size.y) }; 2168bf80f4bSopenharmony_ci dsDefaultDotfield->AddDotfieldPrimitive(prim); 2178bf80f4bSopenharmony_ci } 2188bf80f4bSopenharmony_ci } 2198bf80f4bSopenharmony_ci break; 2208bf80f4bSopenharmony_ci 2218bf80f4bSopenharmony_ci case EventType::DESTROYED: 2228bf80f4bSopenharmony_ci for (const auto& entity : entities) { 2238bf80f4bSopenharmony_ci dsDefaultDotfield->RemoveDotfieldPrimitive(entity); 2248bf80f4bSopenharmony_ci } 2258bf80f4bSopenharmony_ci break; 2268bf80f4bSopenharmony_ci 2278bf80f4bSopenharmony_ci case EventType::MODIFIED: 2288bf80f4bSopenharmony_ci break; 2298bf80f4bSopenharmony_ci } 2308bf80f4bSopenharmony_ci} 2318bf80f4bSopenharmony_ci 2328bf80f4bSopenharmony_ci} // namespace 2338bf80f4bSopenharmony_ci 2348bf80f4bSopenharmony_cinamespace Dotfield { 2358bf80f4bSopenharmony_ciCORE_NS::ISystem* IDotfieldSystemInstance(IEcs& ecs) 2368bf80f4bSopenharmony_ci{ 2378bf80f4bSopenharmony_ci return new DotfieldSystem(ecs); 2388bf80f4bSopenharmony_ci} 2398bf80f4bSopenharmony_civoid IDotfieldSystemDestroy(CORE_NS::ISystem* instance) 2408bf80f4bSopenharmony_ci{ 2418bf80f4bSopenharmony_ci delete static_cast<DotfieldSystem*>(instance); 2428bf80f4bSopenharmony_ci} 2438bf80f4bSopenharmony_ci} // namespace Dotfield 244