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