/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include #include #include // LmbrCentral #include #include #include #include #include #include #include #include // Gradient Signal #include // Vegetation #include // Graph Model #include // Landscape Canvas #include "LandscapeCanvasSystemComponent.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace LandscapeCanvas { // Define all of our supported nodes with their corresponding Component TypeId // so we can use these mappings for registration and factory method creation #define LANDSCAPE_CANVAS_NODE_TABLE(VISITOR_FUNCTION, ...) \ /* Area nodes */ \ VISITOR_FUNCTION(Vegetation::EditorAreaBlenderComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorBlockerComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorMeshBlockerComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorSpawnerComponentTypeId, ##__VA_ARGS__); \ /* Area filter nodes */ \ VISITOR_FUNCTION(Vegetation::EditorSurfaceAltitudeFilterComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorDistanceBetweenFilterComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorDistributionFilterComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorShapeIntersectionFilterComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorSurfaceSlopeFilterComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorSurfaceMaskDepthFilterComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorSurfaceMaskFilterComponentTypeId, ##__VA_ARGS__); \ /* Area modifier nodes */ \ VISITOR_FUNCTION(Vegetation::EditorPositionModifierComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorRotationModifierComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorScaleModifierComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(Vegetation::EditorSlopeAlignmentModifierComponentTypeId, ##__VA_ARGS__); \ /* Area selector nodes */ \ VISITOR_FUNCTION(Vegetation::EditorDescriptorWeightSelectorComponentTypeId, ##__VA_ARGS__); \ /* Shape nodes */ \ VISITOR_FUNCTION(LmbrCentral::EditorBoxShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorCapsuleShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorCompoundShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorCylinderShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorDiskShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorPolygonPrismShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorSphereShapeComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(LmbrCentral::EditorTubeShapeComponentTypeId, ##__VA_ARGS__); \ /* Gradient generator nodes */ \ VISITOR_FUNCTION(EditorFastNoiseGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorPerlinGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorRandomGradientComponentTypeId, ##__VA_ARGS__); \ /* Gradient nodes */ \ VISITOR_FUNCTION(GradientSignal::EditorSurfaceAltitudeGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorConstantGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorImageGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorShapeAreaFalloffGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorSurfaceSlopeGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorSurfaceMaskGradientComponentTypeId, ##__VA_ARGS__); \ /* Gradient modifier nodes */ \ VISITOR_FUNCTION(GradientSignal::EditorDitherGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorMixedGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorInvertGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorLevelsGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorPosterizeGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorSmoothStepGradientComponentTypeId, ##__VA_ARGS__); \ VISITOR_FUNCTION(GradientSignal::EditorThresholdGradientComponentTypeId, ##__VA_ARGS__); \ template void RegisterNode([[maybe_unused]] const AZ::TypeId& typeId, AZ::ReflectContext* context) { GraphModelIntegration::ReflectAndCreateNodeMimeEvent(context); } void LandscapeCanvasSystemComponent::NotifyRegisterViews() { AzToolsFramework::ViewPaneOptions options; options.paneRect = QRect(100, 100, 1280, 1024); options.showOnToolsToolbar = true; options.toolbarIcon = ":/Menu/landscape_canvas_editor.svg"; AzToolsFramework::RegisterViewPane(LyViewPane::LandscapeCanvas, LyViewPane::CategoryTools, options); } LandscapeCanvasSystemComponent::LandscapeCanvasSystemComponent() { LandscapeCanvas::GraphContext::SetInstance(AZStd::make_shared()); // Register factory methods for creating for all supported nodes LANDSCAPE_CANVAS_NODE_TABLE(RegisterFactoryMethod); } LandscapeCanvasSystemComponent::~LandscapeCanvasSystemComponent() { LandscapeCanvas::GraphContext::SetInstance(nullptr); AzToolsFramework::CloseViewPane(LyViewPane::LandscapeCanvas); AzToolsFramework::UnregisterViewPane(LyViewPane::LandscapeCanvas); } void LandscapeCanvasSystemComponent::Reflect(AZ::ReflectContext* context) { // Reflect all our base node types so they can be serialized/deserialized, since // the below LANDSCAPE_CANVAS_NODE_TABLE macro only reflects the actual concrete classes BaseNode::Reflect(context); BaseAreaFilterNode::Reflect(context); BaseAreaModifierNode::Reflect(context); BaseAreaNode::Reflect(context); BaseGradientModifierNode::Reflect(context); BaseGradientNode::Reflect(context); BaseShapeNode::Reflect(context); // Reflect and create the node mime events for all our supported nodes LANDSCAPE_CANVAS_NODE_TABLE(RegisterNode, context); if (AZ::SerializeContext* serialize = azrtti_cast(context)) { serialize->Class() ->Version(0) ; if (AZ::EditContext* ec = serialize->GetEditContext()) { ec->Class("LandscapeCanvas", "Graph canvas representation of Dynamic Vegetation") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ; } } if (auto behaviorContext = azrtti_cast(context)) { behaviorContext->ConstantProperty("LANDSCAPE_CANVAS_EDITOR_ID", []() { return LANDSCAPE_CANVAS_EDITOR_ID; }) ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation); behaviorContext->EBus("LandscapeCanvasNodeFactoryRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "landscapecanvas") ->Event("CreateNodeForTypeName", &LandscapeCanvasNodeFactoryRequests::CreateNodeForTypeName) ; behaviorContext->EBus("LandscapeCanvasRequestBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "landscapecanvas") ->Event("OnGraphEntity", &LandscapeCanvasRequests::OnGraphEntity) ->Event("GetNodeMatchingEntityInGraph", &LandscapeCanvasRequests::GetNodeMatchingEntityInGraph) ->Event("GetNodeMatchingEntityComponentInGraph", &LandscapeCanvasRequests::GetNodeMatchingEntityComponentInGraph) ->Event("GetAllNodesMatchingEntity", &LandscapeCanvasRequests::GetAllNodesMatchingEntity) ->Event("GetAllNodesMatchingEntityComponent", &LandscapeCanvasRequests::GetAllNodesMatchingEntityComponent) ; } } #undef LANDSCAPE_CANVAS_NODE_TABLE void LandscapeCanvasSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { provided.push_back(AZ_CRC("LandscapeCanvasService", 0x31668887)); } void LandscapeCanvasSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) { incompatible.push_back(AZ_CRC("LandscapeCanvasService", 0x31668887)); } void LandscapeCanvasSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { AZ_UNUSED(required); } void LandscapeCanvasSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) { AZ_UNUSED(dependent); } void LandscapeCanvasSystemComponent::Init() { AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); } void LandscapeCanvasSystemComponent::Activate() { AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); LandscapeCanvasNodeFactoryRequestBus::Handler::BusConnect(); LandscapeCanvasSerializationRequestBus::Handler::BusConnect(); } void LandscapeCanvasSystemComponent::Deactivate() { LandscapeCanvasSerializationRequestBus::Handler::BusDisconnect(); LandscapeCanvasNodeFactoryRequestBus::Handler::BusDisconnect(); AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); } BaseNode::BaseNodePtr LandscapeCanvasSystemComponent::CreateNodeForType(GraphModel::GraphPtr graph, const AZ::TypeId& typeId) { auto it = m_nodeFactory.find(typeId); if (it == m_nodeFactory.end()) { return nullptr; } return it->second(graph); } GraphModel::NodePtr LandscapeCanvasSystemComponent::CreateNodeForTypeName(GraphModel::GraphPtr graph, AZStd::string_view nodeName) { AZ::TypeId nodeTypeId = AZ::TypeId::CreateNull(); // Search through all registered Nodes to find the TypeId for one that // matches the requested class name. m_serializeContext->EnumerateDerived( [&nodeTypeId, nodeName](const AZ::SerializeContext::ClassData* componentClass, const AZ::Uuid& knownType) -> bool { AZ_UNUSED(knownType); if (componentClass->m_name == nodeName) { nodeTypeId = componentClass->m_typeId; return false; } return true; }); if (!nodeTypeId.IsNull()) { AZ::TypeId componentTypeId = GetComponentTypeId(nodeTypeId); return CreateNodeForType(graph, componentTypeId); } return nullptr; } const AZ::TypeId LandscapeCanvasSystemComponent::GetComponentTypeId(const AZ::TypeId& nodeTypeId) { auto it = m_nodeComponentTypeIds.find(nodeTypeId); if (it == m_nodeComponentTypeIds.end()) { return AZ::TypeId(); } return it->second; } const LandscapeCanvasSerialization& LandscapeCanvasSystemComponent::GetSerializedMappings() { return m_serialization; } void LandscapeCanvasSystemComponent::SetSerializedNodeEntities(const AZStd::unordered_map& nodeEntities) { // Delete any entities we had previously serialized before updating our mappings for (auto it : m_serialization.m_serializedNodeEntities) { delete it.second; } m_serialization.m_serializedNodeEntities = nodeEntities; } void LandscapeCanvasSystemComponent::SetDeserializedEntities(const AZStd::unordered_map& entities) { m_serialization.m_deserializedEntities = entities; } }