• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #ifndef CORE3D_UTIL_PROPERTY_UTIL_H
17 #define CORE3D_UTIL_PROPERTY_UTIL_H
18 
19 #include <3d/namespace.h>
20 #include <base/containers/string.h>
21 #include <base/containers/vector.h>
22 #include <core/ecs/entity_reference.h>
23 #include <core/json/json.h>
24 #include <core/property/intf_property_api.h>
25 #include <core/property/intf_property_handle.h>
26 #include <core/property/property_handle_util.h>
27 #include <core/property/property_types.h>
28 
CORE3D_BEGIN_NAMESPACE()29 CORE3D_BEGIN_NAMESPACE()
30 /*
31  * Simple signaller class
32  */
33 class CustomPropertyWriteSignal {
34 public:
35     CustomPropertyWriteSignal() = default;
36     virtual ~CustomPropertyWriteSignal() = default;
37 
38     virtual void Signal() = 0;
39 };
40 
41 /*
42  * Implements a custom property blob for simple PODs e.g. shader custom shader properties which are stored in a single
43  * byte data.
44  * Supports float -> vec4 with u/i -variants
45  * - Single byte data blob
46  * - Multiple offsets customized properties for that data
47  * - Can only hold simple data within a single byte-blob
48  *
49  * NOTE: One must use Reserve(propertyCount) before adding properties
50  */
51 class CustomPropertyPodContainer final : public CORE_NS::IPropertyHandle, CORE_NS::IPropertyApi {
52 public:
53     /* Reserve a predefined byte size to hold the property data */
54     CustomPropertyPodContainer(CustomPropertyWriteSignal& writeSignal, size_t reserveByteSize);
55 
56     ~CustomPropertyPodContainer() override = default;
57 
58     CustomPropertyPodContainer(const CustomPropertyPodContainer& other) = delete;
59     CustomPropertyPodContainer(CustomPropertyPodContainer&& other) = delete;
60     CustomPropertyPodContainer& operator=(const CustomPropertyPodContainer& other) = delete;
61     CustomPropertyPodContainer& operator=(CustomPropertyPodContainer&& other) = delete;
62 
63     // IPropertyHandle
64     const CORE_NS::IPropertyApi* Owner() const override;
65     size_t Size() const override;
66     const void* RLock() const override;
67     void RUnlock() const override;
68     void* WLock() override;
69     void WUnlock() override;
70 
71     // IPropertyApi
72     size_t PropertyCount() const override;
73     const CORE_NS::Property* MetaData(size_t index) const override;
74     BASE_NS::array_view<const CORE_NS::Property> MetaData() const override;
75     uint64_t Type() const override;
76     CORE_NS::IPropertyHandle* Create() const override;
77     CORE_NS::IPropertyHandle* Clone(const CORE_NS::IPropertyHandle* src) const override;
78     void Release(CORE_NS::IPropertyHandle* handle) const override;
79 
80     // Reset, to remove old properties
81     void Reset();
82     // Reserve before adding any properties
83     void ReservePropertyCount(size_t propertyCount);
84 
85     void AddOffsetProperty(BASE_NS::string_view propertyName, BASE_NS::string_view displayName, uintptr_t offset,
86         const CORE_NS::PropertyTypeDecl& typeDecl);
87     void AddOffsetProperty(BASE_NS::string_view propertyName, BASE_NS::string_view displayName, uintptr_t offset,
88         const CORE_NS::PropertyTypeDecl& typeDecl, BASE_NS::array_view<const uint8_t> data);
89     bool SetValue(BASE_NS::string_view propertyName, BASE_NS::array_view<const uint8_t> data);
90     bool SetValue(size_t byteOffset, BASE_NS::array_view<const uint8_t> data);
91     BASE_NS::array_view<const uint8_t> GetValue(BASE_NS::string_view name) const;
92     // byte size of the data container
93     size_t GetByteSize() const;
94 
95     void CopyValues(const CustomPropertyPodContainer& other);
96 
97     // Uses property handle util
98     template<typename T>
SetValue(BASE_NS::string_view propertyName,T && propertyValue)99     bool SetValue(BASE_NS::string_view propertyName, T&& propertyValue)
100     {
101         return CORE_NS::SetPropertyValue(*this, propertyName, BASE_NS::forward<T>(propertyValue));
102     }
103     template<typename T>
GetValue(BASE_NS::string_view propertyName)104     T GetValue(BASE_NS::string_view propertyName)
105     {
106         return CORE_NS::GetPropertyValue<T>(*this, propertyName);
107     }
108     void UpdateSignal(CustomPropertyWriteSignal& writeSignal);
109 
110 private:
111     struct Strings {
112         BASE_NS::string name;
113         BASE_NS::string displayName;
114     };
115 
116     // signal when value is written
117     CustomPropertyWriteSignal* writeSignal_;
118     BASE_NS::vector<Strings> metaStrings_;
119     BASE_NS::vector<CORE_NS::Property> metaData_;
120     BASE_NS::vector<uint8_t> data_;
121 
122     size_t reservePropertyCount_ { 0 };
123 };
124 
125 /*
126  * CustomPropertyDataHelper
127  */
128 class CustomPropertyPodHelper final {
129 public:
130     CustomPropertyPodHelper() = default;
131     ~CustomPropertyPodHelper() = default;
132 
133     static CORE_NS::PropertyTypeDecl GetPropertyTypeDeclaration(const BASE_NS::string_view type);
134     static size_t GetPropertyTypeAlignment(const CORE_NS::PropertyTypeDecl& propertyType);
135     static void SetCustomPropertyBlobValue(const CORE_NS::PropertyTypeDecl& propertyType,
136         const CORE_NS::json::value* value, CustomPropertyPodContainer& customProperties, const size_t offset);
137 };
138 
139 /*
140  * Implements a custom binding properties.
141  *
142  * NOTE: One must use Reserve(propertyCount) before adding properties
143  */
144 class CustomPropertyBindingContainer final : public CORE_NS::IPropertyHandle, CORE_NS::IPropertyApi {
145 public:
146     explicit CustomPropertyBindingContainer(CustomPropertyWriteSignal& writeSignal);
147     ~CustomPropertyBindingContainer() override;
148 
149     CustomPropertyBindingContainer(const CustomPropertyBindingContainer& other) = delete;
150     CustomPropertyBindingContainer(CustomPropertyBindingContainer&& other) noexcept;
151     CustomPropertyBindingContainer& operator=(const CustomPropertyBindingContainer& other) = delete;
152     CustomPropertyBindingContainer& operator=(CustomPropertyBindingContainer&& other) noexcept;
153 
154     // IPropertyHandle
155     const CORE_NS::IPropertyApi* Owner() const override;
156     size_t Size() const override;
157     const void* RLock() const override;
158     void RUnlock() const override;
159     void* WLock() override;
160     void WUnlock() override;
161 
162     // IPropertyApi
163     size_t PropertyCount() const override;
164     const CORE_NS::Property* MetaData(size_t index) const override;
165     BASE_NS::array_view<const CORE_NS::Property> MetaData() const override;
166     uint64_t Type() const override;
167     CORE_NS::IPropertyHandle* Create() const override;
168     CORE_NS::IPropertyHandle* Clone(const CORE_NS::IPropertyHandle* src) const override;
169     void Release(CORE_NS::IPropertyHandle* handle) const override;
170 
171     // Reserve before adding any properties
172     void ReservePropertyCount(size_t propertyCount);
173 
174     void AddOffsetProperty(const BASE_NS::string_view propertyName, const BASE_NS::string_view displayName,
175         const uintptr_t offset, const CORE_NS::PropertyTypeDecl& typeDecl);
176     // byte size of the data container
177     size_t GetByteSize() const;
178 
179     // Uses property handle util
180     template<typename T>
SetValue(const BASE_NS::string_view propertyName,T && propertyValue)181     bool SetValue(const BASE_NS::string_view propertyName, T&& propertyValue)
182     {
183         return CORE_NS::SetPropertyValue<T>(*this, propertyName, propertyValue);
184     }
185     template<typename T>
GetValue(const BASE_NS::string_view propertyName)186     T GetValue(const BASE_NS::string_view propertyName) const
187     {
188         return CORE_NS::GetPropertyValue<T>(*this, propertyName);
189     }
190     template<typename T>
GetValue(size_t index)191     T GetValue(size_t index) const
192     {
193         // the casting type needs to be known
194         constexpr size_t ptrSize = sizeof(CORE_NS::EntityReference);
195         static_assert(sizeof(T) == ptrSize);
196         if ((index < metaData_.size())) {
197             const auto& meta = metaData_[index];
198             CORE_ASSERT(meta.offset < data_.size_in_bytes());
199             if (void* ptr = (void*)(data_.data() + meta.offset); ptr) {
200                 return *((T*)(ptr));
201             }
202         }
203         return {};
204     }
205 
206     void CopyValues(const CustomPropertyBindingContainer& other);
207 
208     void UpdateSignal(CustomPropertyWriteSignal& writeSignal);
209 
210 private:
211     // signal when value is written
212     CustomPropertyWriteSignal* writeSignal_;
213 
214     struct Strings {
215         BASE_NS::string name;
216         BASE_NS::string displayName;
217     };
218     BASE_NS::vector<Strings> metaStrings_;
219     BASE_NS::vector<CORE_NS::Property> metaData_;
220     BASE_NS::vector<uint8_t> data_;
221     size_t reservePropertyCount_ { 0 };
222 };
223 
224 /*
225  * CustomBindingPropertyHelper
226  */
227 namespace CustomPropertyBindingHelper {
228 CORE_NS::PropertyTypeDecl GetPropertyTypeDeclaration(const BASE_NS::string_view type);
229 size_t GetPropertyTypeAlignment(const CORE_NS::PropertyTypeDecl& propertyType);
230 } // namespace CustomPropertyBindingHelper
231 CORE3D_END_NAMESPACE()
232 
233 #endif // CORE3D_UTIL_PROPERTY_UTIL_H
234