/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include "Vegetation_precompiled.h" #include "DescriptorWeightSelectorComponent.h" #include #include #include #include #include #include #include namespace Vegetation { void DescriptorWeightSelectorConfig::Reflect(AZ::ReflectContext* context) { AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) { serialize->Class() ->Version(0) ->Field("SortBehavior", &DescriptorWeightSelectorConfig::m_sortBehavior) ->Field("Gradient", &DescriptorWeightSelectorConfig::m_gradientSampler) ; AZ::EditContext* edit = serialize->GetEditContext(); if (edit) { edit->Class( "Vegetation Asset Weight Selector", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::ComboBox, &DescriptorWeightSelectorConfig::m_sortBehavior, "Sort By Weight", "Defines how descriptors will be sorted before gradient is used for selection") ->EnumAttribute(SortBehavior::Unsorted, "Unsorted") ->EnumAttribute(SortBehavior::Ascending, "Ascending (lowest first)") ->EnumAttribute(SortBehavior::Descending, "Descending (highest first)") ->DataElement(0, &DescriptorWeightSelectorConfig::m_gradientSampler, "Gradient", "Gradient mapped to range between 0 and total combined weight of all descriptors.") ; } } if (auto behaviorContext = azrtti_cast(context)) { behaviorContext->Class() ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview) ->Attribute(AZ::Script::Attributes::Category, "Vegetation") ->Constructor() ->Property("noiseType", [](DescriptorWeightSelectorConfig* config) { return (AZ::u8&)(config->m_sortBehavior); }, [](DescriptorWeightSelectorConfig* config, const AZ::u8& i) { config->m_sortBehavior = (SortBehavior)i; }) ->Property("gradientSampler", BehaviorValueProperty(&DescriptorWeightSelectorConfig::m_gradientSampler)) ; } } void DescriptorWeightSelectorComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services) { services.push_back(AZ_CRC("VegetationDescriptorSelectorService", 0xe684eeec)); } void DescriptorWeightSelectorComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services) { services.push_back(AZ_CRC("VegetationDescriptorSelectorService", 0xe684eeec)); } void DescriptorWeightSelectorComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services) { } void DescriptorWeightSelectorComponent::Reflect(AZ::ReflectContext* context) { DescriptorWeightSelectorConfig::Reflect(context); AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) { serialize->Class() ->Version(0) ->Field("Configuration", &DescriptorWeightSelectorComponent::m_configuration) ; } if (auto behaviorContext = azrtti_cast(context)) { behaviorContext->Constant("DescriptorWeightSelectorComponentTypeId", BehaviorConstant(DescriptorWeightSelectorComponentTypeId)); behaviorContext->Class()->RequestBus("DescriptorWeightSelectorRequestBus"); behaviorContext->EBus("DescriptorWeightSelectorRequestBus") ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview) ->Attribute(AZ::Script::Attributes::Category, "Vegetation") ->Event("GetSortBehavior", &DescriptorWeightSelectorRequestBus::Events::GetSortBehavior) ->Event("SetSortBehavior", &DescriptorWeightSelectorRequestBus::Events::SetSortBehavior) ->VirtualProperty("SortBehavior", "GetSortBehavior", "SetSortBehavior") ->Event("GetGradientSampler", &DescriptorWeightSelectorRequestBus::Events::GetGradientSampler) ; } } DescriptorWeightSelectorComponent::DescriptorWeightSelectorComponent(const DescriptorWeightSelectorConfig& configuration) : m_configuration(configuration) { } void DescriptorWeightSelectorComponent::Activate() { m_dependencyMonitor.Reset(); m_dependencyMonitor.ConnectOwner(GetEntityId()); m_dependencyMonitor.ConnectDependencies({ m_configuration.m_gradientSampler.m_gradientId }); DescriptorSelectorRequestBus::Handler::BusConnect(GetEntityId()); DescriptorWeightSelectorRequestBus::Handler::BusConnect(GetEntityId()); } void DescriptorWeightSelectorComponent::Deactivate() { m_dependencyMonitor.Reset(); DescriptorSelectorRequestBus::Handler::BusDisconnect(); DescriptorWeightSelectorRequestBus::Handler::BusDisconnect(); } bool DescriptorWeightSelectorComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) { if (auto config = azrtti_cast(baseConfig)) { m_configuration = *config; return true; } return false; } bool DescriptorWeightSelectorComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const { if (auto config = azrtti_cast(outBaseConfig)) { *config = m_configuration; return true; } return false; } void DescriptorWeightSelectorComponent::SelectDescriptors(const DescriptorSelectorParams& params, DescriptorPtrVec& descriptors) const { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Entity); switch (m_configuration.m_sortBehavior) { default: case SortBehavior::Unsorted: //defaulting to no sorting as an optimization since descriptors can be presorted break; case SortBehavior::Ascending: std::sort(descriptors.begin(), descriptors.end(), [](const auto& lhs, const auto& rhs) { return lhs->m_weight < rhs->m_weight; }); break; case SortBehavior::Descending: std::sort(descriptors.begin(), descriptors.end(), [](const auto& lhs, const auto& rhs) { return lhs->m_weight > rhs->m_weight; }); break; } float totalWeight = 0.0f; for (const auto& descriptor : descriptors) { totalWeight += descriptor->m_weight; } int count = 0; const GradientSignal::GradientSampleParams sampleParams(params.m_position); float minimumWeight = m_configuration.m_gradientSampler.GetValue(sampleParams) * totalWeight; float currentWeight = 0.0f; for (const auto& descriptor : descriptors) { currentWeight += descriptor->m_weight; if (currentWeight < minimumWeight) { ++count; } } if (count > 0) { descriptors.erase(descriptors.begin(), descriptors.begin() + count); } } SortBehavior DescriptorWeightSelectorComponent::GetSortBehavior() const { return m_configuration.m_sortBehavior; } void DescriptorWeightSelectorComponent::SetSortBehavior(SortBehavior behavior) { m_configuration.m_sortBehavior = behavior; LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged); } GradientSignal::GradientSampler& DescriptorWeightSelectorComponent::GetGradientSampler() { return m_configuration.m_gradientSampler; } }