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#include <scene_plugin/api/material_uid.h>
16
17#include <meta/ext/concrete_base_object.h>
18
19#include "bind_templates.inl"
20#include "intf_proxy_object_holder.h"
21#include <meta/api/property/array_property_event_handler.h>
22
23using CORE3D_NS::MaterialComponent;
24META_BEGIN_NAMESPACE();
25META_TYPE(MaterialComponent::TextureInfo);
26META_END_NAMESPACE();
27
28namespace {
29using namespace SCENE_NS;
30class TextureInfoImpl
31    : public META_NS::ObjectFwd<TextureInfoImpl, ClassId::TextureInfo, META_NS::ClassId::Object,
32          ITextureInfo, IProxyObject, IProxyObjectHolder> {
33    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, uint32_t, TextureSlotIndex, ~0u)
34    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, BASE_NS::string, Name, "")
35    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, IBitmap::Ptr, Image, {})
36    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, uint8_t, Sampler, 0)
37    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, BASE_NS::Math::Vec4, Factor, Colors::TRANSPARENT)
38    META_IMPLEMENT_INTERFACE_PROPERTY(
39        ITextureInfo, BASE_NS::Math::Vec2, Translation, BASE_NS::Math::Vec2(0, 0))
40    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, float, Rotation, 0.f)
41    META_IMPLEMENT_INTERFACE_PROPERTY(ITextureInfo, BASE_NS::Math::Vec2, Scale, BASE_NS::Math::Vec2(1.f, 1.f))
42
43    BASE_NS::vector<PropertyPair> ListBoundProperties() const override
44    {
45        return holder_.GetBoundProperties();
46    }
47
48    PropertyHandlerArrayHolder& Holder() override
49    {
50        return holder_;
51    }
52
53    void SetTextureSlotIndex(uint32_t index) override
54    {
55        META_ACCESS_PROPERTY(TextureSlotIndex)->SetValue(index);
56    }
57
58    uint32_t GetTextureSlotIndex() const override
59    {
60        return GetValue(META_ACCESS_PROPERTY(TextureSlotIndex));
61    }
62
63    META_NS::ArrayProperty<CORE3D_NS::MaterialComponent::TextureInfo> array_;
64    uint32_t slotIndex_;
65
66    using ChangeInfo = META_NS::ArrayChanges<CORE3D_NS::MaterialComponent::TextureInfo>;
67    META_NS::PropertyChangedEventHandler handler_;
68    META_NS::PropertyChangedEventHandler handlers_[6];
69    bool Build(const IMetadata::Ptr& params) override
70    {
71        // okay.. collect the propery that contains the data, And the our index..
72	// slot names (unsure-what-they-were-before-but-matches-core3d-enum)
73	auto sh = params->GetPropertyByName<uintptr_t>("sceneHolder")->GetValue();
74	holder_.SetSceneHolder(*((SceneHolder::Ptr*)sh));
75
76	auto ip = params->GetPropertyByName<META_NS::IProperty::Ptr>("textureInfoArray")->GetValue();
77	array_= ip;
78	slotIndex_ = params->GetPropertyByName<uint32_t>("textureSlotIndex")->GetValue();
79	BASE_NS::string textureSlotName;
80	const char* TextureIndexName[] = { "BASE_COLOR", "NORMAL", "MATERIAL", "EMISSIVE", "AO", "CLEARCOAT",
81	    "CLEARCOAT_ROUGHNESS", "CLEARCOAT_NORMAL", "SHEEN", "TRANSMISSION", "SPECULAR" };
82	if (slotIndex_ < BASE_NS::countof(TextureIndexName)) {
83	    textureSlotName = TextureIndexName[slotIndex_];
84	} else {
85	    textureSlotName = "TextureSlot_" + BASE_NS::to_string(slotIndex_);
86	}
87	Name()->SetValue(textureSlotName);
88
89	using namespace META_NS;
90	handler_.Subscribe(array_, MakeCallback<IOnChanged>(this, &TextureInfoImpl::ArrayChanged));
91	ArrayChanged();
92	handlers_[0].Subscribe(Image(), MakeCallback<IOnChanged>(this, &TextureInfoImpl::ImageChanged));
93	handlers_[1].Subscribe(Sampler(), MakeCallback<IOnChanged>(this, &TextureInfoImpl::SamplerChanged));
94	handlers_[2].Subscribe(Factor(), MakeCallback<IOnChanged>(this, &TextureInfoImpl::FactorChanged)); // 2 index
95    // 3 index
96	handlers_[3].Subscribe(Translation(), MakeCallback<IOnChanged>(this, &TextureInfoImpl::TranslationChanged));
97	handlers_[4].Subscribe(Rotation(), MakeCallback<IOnChanged>(this, &TextureInfoImpl::RotationChanged)); // 4 index
98	handlers_[5].Subscribe(Scale(), MakeCallback<IOnChanged>(this, &TextureInfoImpl::ScaleChanged)); // 5 index
99	return true;
100    }
101
102    void ArrayChanged()
103    {
104        // change from ecs?>
105	const auto& curVal = array_->GetValueAt(slotIndex_);
106	if (curVal.image != curImage_) {
107	    curImage_ = curVal.image;
108	    auto sh = holder_.GetSceneHolder();
109	    auto bitmap = ImageConverter::ToUi(*sh, curVal.image);
110	    if (bitmap != curBitmap_) {
111	        Image()->SetValue(bitmap);
112                curBitmap_ = bitmap;
113	    }
114	}
115
116	Factor()->SetValue(curVal.factor);
117	Translation()->SetValue(curVal.transform.translation);
118	Rotation()->SetValue(curVal.transform.rotation);
119	Scale()->SetValue(curVal.transform.scale);
120    }
121
122    void ImageChanged()
123    {
124	auto bitmap = Image()->GetValue();
125	if (bitmap!= curBitmap_) {
126	    curBitmap_ = bitmap;
127	    auto curVal = array_->GetValueAt(slotIndex_);
128	    auto sh = holder_.GetSceneHolder();
129	    curVal.image = ImageConverter::ToEcs(*sh, Image()->GetValue());
130	    curImage_ = curVal.image;
131	    array_->SetValueAt(slotIndex_, curVal);
132	}
133    }
134
135    void SamplerChanged() {}
136    void FactorChanged()
137    {
138	auto curVal = array_->GetValueAt(slotIndex_);
139	curVal.factor = Factor()->GetValue();
140	array_->SetValueAt(slotIndex_, curVal);
141    }
142    void TranslationChanged() {}
143    void RotationChanged() {}
144    void ScaleChanged() {}
145    void Update(const ChangeInfo& changes) {}
146
147private:
148    SCENE_NS::IBitmap::Ptr curBitmap_;
149    CORE_NS::EntityReference curImage_;
150    PropertyHandlerArrayHolder holder_;
151};
152} // namespace
153SCENE_BEGIN_NAMESPACE()
154
155void RegisterTextureInfoImpl()
156{
157    META_NS::GetObjectRegistry().RegisterObjectType<TextureInfoImpl>();
158}
159void UnregisterTextureInfoImpl()
160{
161    META_NS::GetObjectRegistry().UnregisterObjectType<TextureInfoImpl>();
162}
163
164SCENE_END_NAMESPACE()
165