You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/LandscapeCanvas/Code/Source/LandscapeCanvasSystemCompon...

339 lines
17 KiB
C++

/*
* 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 <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl>
#include <AzToolsFramework/API/ViewPaneOptions.h>
#include <LyViewPaneNames.h>
// LmbrCentral
#include <LmbrCentral/Shape/BoxShapeComponentBus.h>
#include <LmbrCentral/Shape/CapsuleShapeComponentBus.h>
#include <LmbrCentral/Shape/CompoundShapeComponentBus.h>
#include <LmbrCentral/Shape/CylinderShapeComponentBus.h>
#include <LmbrCentral/Shape/DiskShapeComponentBus.h>
#include <LmbrCentral/Shape/PolygonPrismShapeComponentBus.h>
#include <LmbrCentral/Shape/SphereShapeComponentBus.h>
#include <LmbrCentral/Shape/TubeShapeComponentBus.h>
// Gradient Signal
#include <GradientSignal/Editor/EditorGradientTypeIds.h>
// Vegetation
#include <Vegetation/Editor/EditorVegetationComponentTypeIds.h>
// Graph Model
#include <GraphModel/Integration/NodePalette/StandardNodePaletteItem.h>
// Landscape Canvas
#include "LandscapeCanvasSystemComponent.h"
#include <Editor/MainWindow.h>
#include <Editor/Core/GraphContext.h>
#include <Editor/Nodes/Areas/AreaBlenderNode.h>
#include <Editor/Nodes/Areas/BlockerAreaNode.h>
#include <Editor/Nodes/Areas/MeshBlockerAreaNode.h>
#include <Editor/Nodes/Areas/SpawnerAreaNode.h>
#include <Editor/Nodes/AreaFilters/AltitudeFilterNode.h>
#include <Editor/Nodes/AreaFilters/DistanceBetweenFilterNode.h>
#include <Editor/Nodes/AreaFilters/DistributionFilterNode.h>
#include <Editor/Nodes/AreaFilters/ShapeIntersectionFilterNode.h>
#include <Editor/Nodes/AreaFilters/SlopeFilterNode.h>
#include <Editor/Nodes/AreaFilters/SurfaceMaskDepthFilterNode.h>
#include <Editor/Nodes/AreaFilters/SurfaceMaskFilterNode.h>
#include <Editor/Nodes/AreaModifiers/PositionModifierNode.h>
#include <Editor/Nodes/AreaModifiers/RotationModifierNode.h>
#include <Editor/Nodes/AreaModifiers/ScaleModifierNode.h>
#include <Editor/Nodes/AreaModifiers/SlopeAlignmentModifierNode.h>
#include <Editor/Nodes/AreaSelectors/AssetWeightSelectorNode.h>
#include <Editor/Nodes/Gradients/AltitudeGradientNode.h>
#include <Editor/Nodes/Gradients/ConstantGradientNode.h>
#include <Editor/Nodes/Gradients/FastNoiseGradientNode.h>
#include <Editor/Nodes/Gradients/ImageGradientNode.h>
#include <Editor/Nodes/Gradients/PerlinNoiseGradientNode.h>
#include <Editor/Nodes/Gradients/RandomNoiseGradientNode.h>
#include <Editor/Nodes/Gradients/ShapeAreaFalloffGradientNode.h>
#include <Editor/Nodes/Gradients/SlopeGradientNode.h>
#include <Editor/Nodes/Gradients/SurfaceMaskGradientNode.h>
#include <Editor/Nodes/GradientModifiers/DitherGradientModifierNode.h>
#include <Editor/Nodes/GradientModifiers/GradientMixerNode.h>
#include <Editor/Nodes/GradientModifiers/InvertGradientModifierNode.h>
#include <Editor/Nodes/GradientModifiers/LevelsGradientModifierNode.h>
#include <Editor/Nodes/GradientModifiers/PosterizeGradientModifierNode.h>
#include <Editor/Nodes/GradientModifiers/SmoothStepGradientModifierNode.h>
#include <Editor/Nodes/GradientModifiers/ThresholdGradientModifierNode.h>
#include <Editor/Nodes/Shapes/BoxShapeNode.h>
#include <Editor/Nodes/Shapes/CapsuleShapeNode.h>
#include <Editor/Nodes/Shapes/CompoundShapeNode.h>
#include <Editor/Nodes/Shapes/CylinderShapeNode.h>
#include <Editor/Nodes/Shapes/DiskShapeNode.h>
#include <Editor/Nodes/Shapes/PolygonPrismShapeNode.h>
#include <Editor/Nodes/Shapes/SphereShapeNode.h>
#include <Editor/Nodes/Shapes/TubeShapeNode.h>
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<AreaBlenderNode>(Vegetation::EditorAreaBlenderComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<BlockerAreaNode>(Vegetation::EditorBlockerComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<MeshBlockerAreaNode>(Vegetation::EditorMeshBlockerComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SpawnerAreaNode>(Vegetation::EditorSpawnerComponentTypeId, ##__VA_ARGS__); \
/* Area filter nodes */ \
VISITOR_FUNCTION<AltitudeFilterNode>(Vegetation::EditorSurfaceAltitudeFilterComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<DistanceBetweenFilterNode>(Vegetation::EditorDistanceBetweenFilterComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<DistributionFilterNode>(Vegetation::EditorDistributionFilterComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<ShapeIntersectionFilterNode>(Vegetation::EditorShapeIntersectionFilterComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SlopeFilterNode>(Vegetation::EditorSurfaceSlopeFilterComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SurfaceMaskDepthFilterNode>(Vegetation::EditorSurfaceMaskDepthFilterComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SurfaceMaskFilterNode>(Vegetation::EditorSurfaceMaskFilterComponentTypeId, ##__VA_ARGS__); \
/* Area modifier nodes */ \
VISITOR_FUNCTION<PositionModifierNode>(Vegetation::EditorPositionModifierComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<RotationModifierNode>(Vegetation::EditorRotationModifierComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<ScaleModifierNode>(Vegetation::EditorScaleModifierComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SlopeAlignmentModifierNode>(Vegetation::EditorSlopeAlignmentModifierComponentTypeId, ##__VA_ARGS__); \
/* Area selector nodes */ \
VISITOR_FUNCTION<AssetWeightSelectorNode>(Vegetation::EditorDescriptorWeightSelectorComponentTypeId, ##__VA_ARGS__); \
/* Shape nodes */ \
VISITOR_FUNCTION<BoxShapeNode>(LmbrCentral::EditorBoxShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<CapsuleShapeNode>(LmbrCentral::EditorCapsuleShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<CompoundShapeNode>(LmbrCentral::EditorCompoundShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<CylinderShapeNode>(LmbrCentral::EditorCylinderShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<DiskShapeNode>(LmbrCentral::EditorDiskShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<PolygonPrismShapeNode>(LmbrCentral::EditorPolygonPrismShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SphereShapeNode>(LmbrCentral::EditorSphereShapeComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<TubeShapeNode>(LmbrCentral::EditorTubeShapeComponentTypeId, ##__VA_ARGS__); \
/* Gradient generator nodes */ \
VISITOR_FUNCTION<FastNoiseGradientNode>(EditorFastNoiseGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<PerlinNoiseGradientNode>(GradientSignal::EditorPerlinGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<RandomNoiseGradientNode>(GradientSignal::EditorRandomGradientComponentTypeId, ##__VA_ARGS__); \
/* Gradient nodes */ \
VISITOR_FUNCTION<AltitudeGradientNode>(GradientSignal::EditorSurfaceAltitudeGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<ConstantGradientNode>(GradientSignal::EditorConstantGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<ImageGradientNode>(GradientSignal::EditorImageGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<ShapeAreaFalloffGradientNode>(GradientSignal::EditorShapeAreaFalloffGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SlopeGradientNode>(GradientSignal::EditorSurfaceSlopeGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SurfaceMaskGradientNode>(GradientSignal::EditorSurfaceMaskGradientComponentTypeId, ##__VA_ARGS__); \
/* Gradient modifier nodes */ \
VISITOR_FUNCTION<DitherGradientModifierNode>(GradientSignal::EditorDitherGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<GradientMixerNode>(GradientSignal::EditorMixedGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<InvertGradientModifierNode>(GradientSignal::EditorInvertGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<LevelsGradientModifierNode>(GradientSignal::EditorLevelsGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<PosterizeGradientModifierNode>(GradientSignal::EditorPosterizeGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<SmoothStepGradientModifierNode>(GradientSignal::EditorSmoothStepGradientComponentTypeId, ##__VA_ARGS__); \
VISITOR_FUNCTION<ThresholdGradientModifierNode>(GradientSignal::EditorThresholdGradientComponentTypeId, ##__VA_ARGS__); \
template<typename NodeType>
void RegisterNode([[maybe_unused]] const AZ::TypeId& typeId, AZ::ReflectContext* context)
{
GraphModelIntegration::ReflectAndCreateNodeMimeEvent<NodeType>(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<LandscapeCanvasEditor::MainWindow>(LyViewPane::LandscapeCanvas, LyViewPane::CategoryTools, options);
}
LandscapeCanvasSystemComponent::LandscapeCanvasSystemComponent()
{
LandscapeCanvas::GraphContext::SetInstance(AZStd::make_shared<LandscapeCanvas::GraphContext>());
// 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<AZ::SerializeContext*>(context))
{
serialize->Class<LandscapeCanvasSystemComponent, AZ::Component>()
->Version(0)
;
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec->Class<LandscapeCanvasSystemComponent>("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<AZ::BehaviorContext*>(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>("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>("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<GraphModel::Node>(
[&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<AZ::EntityId, AZ::Entity*>& 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<AZ::EntityId, AZ::EntityId>& entities)
{
m_serialization.m_deserializedEntities = entities;
}
}