1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dotfield/ecs/systems/dotfield_system.h"
17
18 #include <PropertyTools/property_api_impl.h>
19 #include <PropertyTools/property_api_impl.inl>
20 #include <PropertyTools/property_data.h>
21 #include <PropertyTools/property_macros.h>
22 #include <cmath>
23 #include <random>
24
25 #include <3d/ecs/components/transform_component.h>
26 #include <3d/ecs/components/world_matrix_component.h>
27 #include <base/containers/fixed_string.h>
28 #include <base/containers/unordered_map.h>
29 #include <base/math/matrix_util.h>
30 #include <base/math/quaternion_util.h>
31 #include <base/math/vector_util.h>
32 #include <core/ecs/intf_component_manager.h>
33 #include <core/ecs/intf_ecs.h>
34 #include <core/implementation_uids.h>
35 #include <core/intf_engine.h>
36 #include <core/plugin/intf_class_factory.h>
37 #include <core/property/intf_property_api.h>
38 #include <core/property/intf_property_handle.h>
39 #include <render/datastore/intf_render_data_store_manager.h>
40 #include <render/implementation_uids.h>
41
42 #include "dotfield/ecs/components/dotfield_component.h"
43 #include "render/render_data_store_default_dotfield.h"
44
45 namespace {
46 #include "app/shaders/common/dotfield_struct_common.h"
47 } // namespace
48
49 using namespace BASE_NS;
50 using namespace CORE_NS;
51 using namespace RENDER_NS;
52 using namespace CORE3D_NS;
53 using namespace Dotfield;
54 namespace {
55
56 class DotfieldSystem final : public IDotfieldSystem, private IEcs::ComponentListener {
57 public:
58 DotfieldSystem(IEcs& aECS);
59 ~DotfieldSystem();
60
61 // ISystem
62 string_view GetName() const override;
63 Uid GetUid() const override;
64
65 IPropertyHandle* GetProperties() override;
66 const IPropertyHandle* GetProperties() const override;
67 void SetProperties(const IPropertyHandle&) override;
68
69 bool IsActive() const override;
70 void SetActive(bool state) override;
71
72 void Initialize() override;
73 void Uninitialize() override;
74 bool Update(bool frameRenderingQueued, uint64_t time, uint64_t delta) override;
75
76 const IEcs& GetECS() const override;
77
78 void OnComponentEvent(
79 EventType type, const IComponentManager& componentManager, array_view<const Entity> entities) override;
80
81 private:
82 struct PropertyData {
83 float speed { 1.f };
84 };
85
86 BEGIN_PROPERTY(PropertyData, ComponentMetadata)
87 DECL_PROPERTY2(PropertyData, speed, "Simulation speed", 0)
88 END_PROPERTY();
89
90 bool active_ { true };
91 IEcs& ecs_;
92 IRenderDataStoreManager& renderDataStoreManager_;
93 IWorldMatrixComponentManager& worldMatrixManager_;
94 IDotfieldComponentManager& dotfieldManager_;
95
96 PropertyData props_ { 1.f };
97
98 PropertyApiImpl<PropertyData> propertyApi_ = PropertyApiImpl<PropertyData>(&props_, ComponentMetadata);
99 };
100
DotfieldSystem(IEcs& ecs)101 DotfieldSystem::DotfieldSystem(IEcs& ecs)
102 : ecs_(ecs), renderDataStoreManager_(GetInstance<IRenderContext>(
103 *ecs.GetClassFactory().GetInterface<IClassRegister>(), UID_RENDER_CONTEXT)
104 ->GetRenderDataStoreManager()),
105 worldMatrixManager_(*GetManager<IWorldMatrixComponentManager>(ecs)),
106 dotfieldManager_(*GetManager<IDotfieldComponentManager>(ecs))
107 {
108 ecs.AddListener(dotfieldManager_, *this);
109 }
110
~DotfieldSystem()111 DotfieldSystem ::~DotfieldSystem()
112 {
113 ecs_.RemoveListener(dotfieldManager_, *this);
114 }
115
SetActive(bool state)116 void DotfieldSystem::SetActive(bool state)
117 {
118 active_ = state;
119 }
120
IsActive() const121 bool DotfieldSystem::IsActive() const
122 {
123 return active_;
124 }
125
GetName() const126 string_view DotfieldSystem::GetName() const
127 {
128 return Dotfield::GetName(this);
129 }
130
GetUid() const131 Uid DotfieldSystem::GetUid() const
132 {
133 return UID;
134 }
135
GetProperties()136 IPropertyHandle* DotfieldSystem::GetProperties()
137 {
138 return propertyApi_.GetData();
139 }
140
GetProperties() const141 const IPropertyHandle* DotfieldSystem::GetProperties() const
142 {
143 return propertyApi_.GetData();
144 }
145
SetProperties(const IPropertyHandle& dataHandle)146 void DotfieldSystem::SetProperties(const IPropertyHandle& dataHandle)
147 {
148 if (dataHandle.Owner() != &propertyApi_) {
149 return;
150 }
151 if (auto data = ScopedHandle<const PropertyData>(&dataHandle); data) {
152 props_ = *data;
153 }
154 }
155
GetECS() const156 const IEcs& DotfieldSystem::GetECS() const
157 {
158 return ecs_;
159 }
160
Initialize()161 void DotfieldSystem::Initialize() {}
162
Uninitialize()163 void DotfieldSystem::Uninitialize() {}
164
Update(bool frameRenderingQueued, uint64_t time, uint64_t delta)165 bool DotfieldSystem::Update(bool frameRenderingQueued, uint64_t time, uint64_t delta)
166 {
167 if (!active_) {
168 return false;
169 }
170
171 RenderDataStoreDefaultDotfield* dsDefaultDotfield = static_cast<RenderDataStoreDefaultDotfield*>(
172 renderDataStoreManager_.GetRenderDataStore("RenderDataStoreDefaultDotfield"));
173 if (dsDefaultDotfield) {
174 const auto timeStep = delta * 0.000001f * props_.speed;
175 dsDefaultDotfield->SetTimeStep(timeStep);
176 dsDefaultDotfield->SetTime(time * 0.000001f);
177
178 array_view<RenderDataDefaultDotfield::DotfieldPrimitive> dotfieldPrimitives =
179 dsDefaultDotfield->GetDotfieldPrimitives();
180
181 for (auto& prim : dotfieldPrimitives) {
182 const auto& dfc = dotfieldManager_.Get(prim.entity);
183 prim.touch = dfc.touchPosition;
184 prim.touchDirection = dfc.touchDirection;
185 prim.touchRadius = dfc.touchRadius;
186 prim.pointScale = dfc.pointScale;
187 if (worldMatrixManager_.HasComponent(prim.entity)) {
188 WorldMatrixComponent wc = worldMatrixManager_.Get(prim.entity);
189 prim.matrix = wc.matrix;
190 }
191 }
192 }
193 return frameRenderingQueued;
194 }
195
OnComponentEvent( EventType type, const IComponentManager& componentManager, array_view<const Entity> entities)196 void DotfieldSystem::OnComponentEvent(
197 EventType type, const IComponentManager& componentManager, array_view<const Entity> entities)
198 {
199 RenderDataStoreDefaultDotfield* dsDefaultDotfield = static_cast<RenderDataStoreDefaultDotfield*>(
200 renderDataStoreManager_.GetRenderDataStore("RenderDataStoreDefaultDotfield"));
201 switch (type) {
202 case EventType::CREATED:
203 for (const auto& entity : entities) {
204 if (worldMatrixManager_.HasComponent(entity)) {
205 WorldMatrixComponent wc = worldMatrixManager_.Get(entity);
206 DotfieldComponent dfc = dotfieldManager_.Get(entity);
207
208 RenderDataDefaultDotfield::DotfieldPrimitive prim;
209 prim.entity = entity;
210 prim.matrix = wc.matrix;
211 prim.touch = dfc.touchPosition;
212 prim.touchDirection = dfc.touchDirection;
213 prim.touchRadius = dfc.touchRadius;
214 prim.colors = { dfc.color0, dfc.color1, dfc.color2, dfc.color3 };
215 prim.size = { static_cast<uint32_t>(dfc.size.x), static_cast<uint32_t>(dfc.size.y) };
216 dsDefaultDotfield->AddDotfieldPrimitive(prim);
217 }
218 }
219 break;
220
221 case EventType::DESTROYED:
222 for (const auto& entity : entities) {
223 dsDefaultDotfield->RemoveDotfieldPrimitive(entity);
224 }
225 break;
226
227 case EventType::MODIFIED:
228 break;
229 }
230 }
231
232 } // namespace
233
234 namespace Dotfield {
IDotfieldSystemInstance(IEcs& ecs)235 CORE_NS::ISystem* IDotfieldSystemInstance(IEcs& ecs)
236 {
237 return new DotfieldSystem(ecs);
238 }
IDotfieldSystemDestroy(CORE_NS::ISystem* instance)239 void IDotfieldSystemDestroy(CORE_NS::ISystem* instance)
240 {
241 delete static_cast<DotfieldSystem*>(instance);
242 }
243 } // namespace Dotfield
244