* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <core/property/property_types.h>
CORE_BEGIN_NAMESPACE()
DECLARE_PROPERTY_TYPE(BASE_NS::string);
CORE_END_NAMESPACE()
#include <scene/ext/intf_ecs_context.h>
#include <3d/ecs/components/render_configuration_component.h>
#include <3d/ecs/systems/intf_render_preprocessor_system.h>
#include <core/ecs/entity.h>
#include <core/property/property_handle_util.h>
#include <render/datastore/intf_render_data_store_manager.h>
#include <meta/api/metadata_util.h>
#include "entity_converting_value.h"
#include "render_configuration.h"
SCENE_BEGIN_NAMESPACE()
static constexpr auto SHADOW_RESOLUTION_PROP_NAME = "ShadowResolution";
static constexpr auto SHADOW_QUALITY_PROP_NAME = "ShadowQuality";
CORE_NS::Entity RenderConfiguration::CreateEntity(const IInternalScene::Ptr& scene)
{
CORE_NS::Entity entity{};
if (!scene) {
return entity;
}
if (auto rootNode = scene->GetRootNode()) {
if (auto access = interface_cast<IEcsObjectAccess>(rootNode)) {
if (auto ecso = access->GetEcsObject()) {
entity = ecso->GetEntity();
}
}
}
if (!CORE_NS::EntityUtil::IsValid(entity)) {
auto& ecs = scene->GetEcsContext();
if (auto rconfig = ecs.FindComponent<CORE3D_NS::RenderConfigurationComponent>()) {
if (auto necs = ecs.GetNativeEcs()) {
entity = necs->GetEntityManager().Create();
rconfig->Create(entity);
}
}
}
return entity;
}
bool RenderConfiguration::InitDynamicProperty(const META_NS::IProperty::Ptr& p, BASE_NS::string_view path)
{
if (p->GetName() == "Environment") {
auto ep = object_->CreateProperty(path).GetResult();
return PushForwardingValueInstance(ep,
interface_cast<META_NS::IStackProperty>(p),
META_NS::IValue::Ptr(
new InterfacePtrEntityValue<IEnvironment>(ep, {GetInternalScene(), ClassId::Environment})));
}
return AttachEngineProperty(p, path);
}
BASE_NS::string RenderConfiguration::GetName() const
{
return "RenderConfigurationComponent";
}
BASE_NS::Math::UVec2 RenderConfiguration::GetDefaultShadowResolution() const
{
constexpr CORE3D_NS::IRenderDataStoreDefaultLight::ShadowQualityResolutions defaults;
BASE_NS::Math::UVec2 resolution = defaults.normal;
auto quality = GetProperty<SceneShadowQuality>(SHADOW_QUALITY_PROP_NAME, META_NS::MetadataQuery::EXISTING);
if (quality) {
switch (META_NS::GetValue(quality)) {
case SceneShadowQuality::LOW:
resolution = defaults.low;
break;
case SceneShadowQuality::NORMAL:
resolution = defaults.normal;
break;
case SceneShadowQuality::HIGH:
resolution = defaults.high;
break;
case SceneShadowQuality::ULTRA:
resolution = defaults.ultra;
break;
}
}
return resolution;
}
void RenderConfiguration::OnMetadataConstructed(const META_NS::StaticMetadata& m, CORE_NS::IInterface& i)
{
auto p = interface_cast<META_NS::IProperty>(&i);
if (p && p->GetName() == SHADOW_RESOLUTION_PROP_NAME) {
auto typed = META_NS::TypedPropertyLock<BASE_NS::Math::UVec2>(p);
if (typed) {
typed->SetDefaultValue(GetDefaultShadowResolution());
}
}
}
void RenderConfiguration::OnPropertyChanged(const META_NS::IProperty& property)
{
const auto name = property.GetName();
if (name == SHADOW_RESOLUTION_PROP_NAME) {
bool isset = META_NS::IsValueSet(property);
auto value = META_NS::GetValue<BASE_NS::Math::UVec2>(property.GetValue());
if (isset) {
value = META_NS::GetValue<BASE_NS::Math::UVec2>(property.GetValue());
}
isset &= value.x > 0 && value.y > 0;
auto scene = GetInternalScene();
if (scene) {
scene->RunDirectlyOrInTask(
[this, scene, isset, value = BASE_NS::move(value)]() { UpdateShadowResolution(*scene, isset, value); });
}
} else if (name == SHADOW_QUALITY_PROP_NAME) {
auto resolution =
GetProperty<BASE_NS::Math::UVec2>(SHADOW_RESOLUTION_PROP_NAME, META_NS::MetadataQuery::EXISTING);
if (resolution) {
resolution->SetDefaultValue(GetDefaultShadowResolution());
}
}
}
BASE_NS::refcnt_ptr<CORE3D_NS::IRenderDataStoreDefaultLight> RenderConfiguration::GetDefaultLightRenderDataStore(
IInternalScene& scene)
{
const auto ecs = scene.GetEcsContext().GetNativeEcs();
if (ecs) {
const auto preprocessor = CORE_NS::GetSystem<CORE3D_NS::IRenderPreprocessorSystem>(*ecs);
if (preprocessor) {
const auto dsLightName =
CORE_NS::GetPropertyValue<BASE_NS::string>(preprocessor->GetProperties(), "dataStoreLight");
const auto& manager = scene.GetRenderContext().GetRenderDataStoreManager();
return manager.GetRenderDataStore(dsLightName);
}
}
return {};
}
void RenderConfiguration::UpdateShadowResolution(IInternalScene& scene, bool isset, BASE_NS::Math::UVec2 value)
{
if (const auto store = GetDefaultLightRenderDataStore(scene)) {
CORE3D_NS::IRenderDataStoreDefaultLight::ShadowQualityResolutions resolutions;
if (isset) {
resolutions.low = value;
resolutions.normal = value;
resolutions.high = value;
resolutions.ultra = value;
}
store->SetShadowQualityResolutions(resolutions, {});
}
}
SCENE_END_NAMESPACE()