/* * 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. * */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VEG_SPAWNER_ENABLE_CACHING 0 #define VEG_SPAWNER_ENABLE_RELATIVE 0 namespace LmbrCentral { template class EditorWrappedComponentBase; } namespace Vegetation { class SpawnerConfig : public AreaConfig { public: AZ_CLASS_ALLOCATOR(SpawnerConfig, AZ::SystemAllocator, 0); AZ_RTTI(SpawnerConfig, "{98A6B0CE-FAD0-4108-B019-6B01931E649F}", AreaConfig); static void Reflect(AZ::ReflectContext* context); bool m_inheritBehavior = true; bool m_allowEmptyMeshes = true; FilterStage m_filterStage = FilterStage::PreProcess; }; static const AZ::Uuid SpawnerComponentTypeId = "{14BD176C-2E44-4BA6-849A-258674179237}"; /** * Default placement logic for vegetation in an area */ class SpawnerComponent : public AreaComponentBase , private SpawnerRequestBus::Handler { public: friend class EditorSpawnerComponent; template friend class LmbrCentral::EditorWrappedComponentBase; AZ_COMPONENT(SpawnerComponent, SpawnerComponentTypeId, AreaComponentBase); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services); static void Reflect(AZ::ReflectContext* context); SpawnerComponent(const SpawnerConfig& configuration); SpawnerComponent() = default; ~SpawnerComponent() = default; ////////////////////////////////////////////////////////////////////////// // AZ::Component interface implementation void Activate() override; void Deactivate() override; bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override; bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; ////////////////////////////////////////////////////////////////////////// // AreaRequestBus bool PrepareToClaim(EntityIdStack& stackIds) override; void ClaimPositions(EntityIdStack& stackIds, ClaimContext& context) override; void UnclaimPosition(const ClaimHandle handle) override; ////////////////////////////////////////////////////////////////////////// // AreaInfoBus AZ::Aabb GetEncompassingAabb() const override; AZ::u32 GetProductCount() const override; ////////////////////////////////////////////////////////////////////////// // AreaNotificationBus void OnCompositionChanged() override; protected: ////////////////////////////////////////////////////////////////////////// // AreaComponentBase void OnRegisterArea() override; void OnUnregisterArea() override; ////////////////////////////////////////////////////////////////////////// // SpawnerRequestBus AZ::u32 GetAreaPriority() const override; void SetAreaPriority(AZ::u32 priority) override; AZ::u32 GetAreaLayer() const override; void SetAreaLayer(AZ::u32 type) override; AZ::u32 GetAreaProductCount() const override; bool GetInheritBehavior() const override; void SetInheritBehavior(bool value) override; bool GetAllowEmptyMeshes() const override; void SetAllowEmptyMeshes(bool value) override; FilterStage GetFilterStage() const override; void SetFilterStage(FilterStage filterStage) override; private: void ClearSelectableDescriptors(); void UpdateShapeParams(); bool CreateInstance(const ClaimPoint &point, InstanceData& instanceData); bool EvaluateFilters(EntityIdStack& processedIds, InstanceData& instanceData, const FilterStage intendedStage) const; bool ProcessInstance(EntityIdStack& processedIds, const ClaimPoint& point, InstanceData& instanceData, DescriptorPtr descriptorPtr); bool ClaimPosition(EntityIdStack& processedIds, const ClaimPoint& point, InstanceData& instanceData); void DestroyAllInstances(); void CalcInstanceDebugColor(const EntityIdStack& processedIds); SpawnerConfig m_configuration; //caching vector for reuse per point AZStd::recursive_mutex m_selectableDescriptorMutex; DescriptorPtrVec m_selectableDescriptorCache; DescriptorPtrVec m_selectedDescriptors; using ClaimInstanceMapping = AZStd::unordered_map; ClaimInstanceMapping m_claimInstanceMapping; mutable AZStd::recursive_mutex m_claimInstanceMappingMutex; #if VEG_SPAWNER_ENABLE_CACHING // cached data AZStd::unordered_map m_acceptedClaimCache; AZStd::unordered_set m_rejectedClaimCache; mutable AZStd::recursive_mutex m_cacheMutex; #endif mutable AZStd::recursive_mutex m_shapeMutex; AZ::Aabb m_shapeBounds = AZ::Aabb::CreateNull(); AZ::Transform m_shapeTransformInverse = AZ::Transform::CreateIdentity(); SurfaceData::SurfaceTagVector m_inclusiveTagsToConsider; SurfaceData::SurfaceTagVector m_exclusiveTagsToConsider; }; }