Updated
This commit is contained in:
@@ -4,7 +4,20 @@
|
||||
#include "CanvasTypes.h"
|
||||
#include "Engine/SkeletalMesh.h"
|
||||
#include "Components/SkeletalMeshComponent.h"
|
||||
#include "Components/DirectionalLightComponent.h"
|
||||
#include "Components/SkyLightComponent.h"
|
||||
#include "Slate/SceneViewport.h"
|
||||
#include "PreviewScene.h"
|
||||
#include "EditorViewportClient.h"
|
||||
#include "EngineGlobals.h"
|
||||
#include "Engine/Engine.h"
|
||||
#include "Engine.h"
|
||||
#include "CanvasTypes.h"
|
||||
#include "SceneView.h"
|
||||
#include "InputCoreTypes.h"
|
||||
#include "Components/SplineComponent.h"
|
||||
#include "EditorModeManager.h"
|
||||
#include "UnrealWidget.h"
|
||||
|
||||
FFLESHViewportClient::FFLESHViewportClient(FFLESHEditor* InEditor)
|
||||
: FEditorViewportClient(nullptr)
|
||||
@@ -13,7 +26,7 @@ FFLESHViewportClient::FFLESHViewportClient(FFLESHEditor* InEditor)
|
||||
, bShowWireframe(false)
|
||||
, bShowBones(false)
|
||||
{
|
||||
// Create a valid viewport scene
|
||||
// Create a valid preview scene
|
||||
PreviewScene = MakeShareable(new FPreviewScene(FPreviewScene::ConstructionValues()));
|
||||
|
||||
// Set the scene for FEditorViewportClient - use constructor instead of SetPreviewScene
|
||||
@@ -41,6 +54,19 @@ FFLESHViewportClient::FFLESHViewportClient(FFLESHEditor* InEditor)
|
||||
|
||||
// Set default render mode
|
||||
SetViewMode(VMI_Lit);
|
||||
|
||||
// Set camera control options similar to asset editor
|
||||
SetRealtime(true);
|
||||
bSetListenerPosition = false;
|
||||
|
||||
// Enable standard editor camera controls
|
||||
if (Widget)
|
||||
{
|
||||
Widget->SetSnapEnabled(true);
|
||||
}
|
||||
|
||||
// Load and display objects from NodeTree
|
||||
LoadNodesFromNodeTree();
|
||||
}
|
||||
|
||||
FFLESHViewportClient::~FFLESHViewportClient()
|
||||
@@ -52,6 +78,23 @@ void FFLESHViewportClient::Draw(const FSceneView* View, FPrimitiveDrawInterface*
|
||||
{
|
||||
FEditorViewportClient::Draw(View, PDI);
|
||||
|
||||
// Draw navigation widget (coordinate axes)
|
||||
if (PDI)
|
||||
{
|
||||
// Draw coordinate system axes
|
||||
const float AxisLength = 50.0f;
|
||||
const float AxisThickness = 1.0f;
|
||||
|
||||
// Draw X axis (red)
|
||||
PDI->DrawLine(FVector::ZeroVector, FVector(AxisLength, 0.0f, 0.0f), FLinearColor::Red, SDPG_Foreground, AxisThickness);
|
||||
|
||||
// Draw Y axis (green)
|
||||
PDI->DrawLine(FVector::ZeroVector, FVector(0.0f, AxisLength, 0.0f), FLinearColor::Green, SDPG_Foreground, AxisThickness);
|
||||
|
||||
// Draw Z axis (blue)
|
||||
PDI->DrawLine(FVector::ZeroVector, FVector(0.0f, 0.0f, AxisLength), FLinearColor::Blue, SDPG_Foreground, AxisThickness);
|
||||
}
|
||||
|
||||
// Draw custom UI elements
|
||||
if (Viewport)
|
||||
{
|
||||
@@ -111,7 +154,7 @@ bool FFLESHViewportClient::InputKey(const FInputKeyEventArgs& EventArgs)
|
||||
else if (EventArgs.Key == EKeys::F)
|
||||
{
|
||||
// F key focuses on selected object
|
||||
// TODO: Add logic to focus on the selected object
|
||||
FocusOnSelectedNode();
|
||||
bHandled = true;
|
||||
}
|
||||
}
|
||||
@@ -134,6 +177,15 @@ bool FFLESHViewportClient::InputKey(FViewport* InViewport, int32 ControllerId, F
|
||||
return InputKey(Args);
|
||||
}
|
||||
|
||||
// This version of InputAxis is deprecated, but kept for compatibility
|
||||
bool FFLESHViewportClient::InputAxis(FViewport* InViewport, int32 ControllerId, FKey Key, float Delta, float DeltaTime, int32 NumSamples, bool bGamepad)
|
||||
{
|
||||
// Create InputKeyEventArgs for the new API
|
||||
FInputKeyEventArgs Args(InViewport, ControllerId, Key, IE_Axis);
|
||||
Args.AmountDepressed = Delta;
|
||||
return InputKey(Args);
|
||||
}
|
||||
|
||||
void FFLESHViewportClient::ResetCamera()
|
||||
{
|
||||
// Reset camera position and rotation
|
||||
@@ -173,3 +225,164 @@ void FFLESHViewportClient::ToggleBones()
|
||||
// Invalidate view
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void FFLESHViewportClient::LoadNodesFromNodeTree()
|
||||
{
|
||||
if (!PreviewScene.IsValid() || !Editor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear current preview scene components by creating a new one
|
||||
PreviewScene = MakeShareable(new FPreviewScene(FPreviewScene::ConstructionValues()));
|
||||
FEditorViewportClient::PreviewScene = PreviewScene.Get();
|
||||
|
||||
// Add a default light
|
||||
UDirectionalLightComponent* DirectionalLight = NewObject<UDirectionalLightComponent>();
|
||||
DirectionalLight->SetMobility(EComponentMobility::Movable);
|
||||
DirectionalLight->SetIntensity(1.0f);
|
||||
PreviewScene->AddComponent(DirectionalLight, FTransform(FRotator(-45.0f, 45.0f, 0.0f)));
|
||||
|
||||
// Add a skylight for ambient lighting
|
||||
USkyLightComponent* SkyLight = NewObject<USkyLightComponent>();
|
||||
SkyLight->SetMobility(EComponentMobility::Movable);
|
||||
SkyLight->SourceType = ESkyLightSourceType::SLS_CapturedScene;
|
||||
PreviewScene->AddComponent(SkyLight, FTransform::Identity);
|
||||
|
||||
// Add a second directional light from another angle
|
||||
UDirectionalLightComponent* BackLight = NewObject<UDirectionalLightComponent>();
|
||||
BackLight->SetMobility(EComponentMobility::Movable);
|
||||
BackLight->SetIntensity(0.6f);
|
||||
BackLight->SetLightColor(FLinearColor(0.8f, 0.8f, 1.0f)); // Slightly blue backlight
|
||||
PreviewScene->AddComponent(BackLight, FTransform(FRotator(45.0f, -135.0f, 0.0f)));
|
||||
|
||||
// Get all nodes from NodeTree
|
||||
const TArray<TSharedPtr<FVisceraNodeItem>>& NodeRoots = Editor->GetNodeTreeRoots();
|
||||
|
||||
// Recursively load all nodes
|
||||
for (const TSharedPtr<FVisceraNodeItem>& RootNode : NodeRoots)
|
||||
{
|
||||
if (RootNode.IsValid())
|
||||
{
|
||||
LoadNodeRecursive(RootNode, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Update viewport
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void FFLESHViewportClient::LoadNodeRecursive(TSharedPtr<FVisceraNodeItem> Node, USceneComponent* ParentComponent)
|
||||
{
|
||||
if (!Node.IsValid() || !PreviewScene.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
USceneComponent* NodeComponent = nullptr;
|
||||
|
||||
// Simplified node loading logic, use static mesh for all node types
|
||||
UStaticMeshComponent* MeshComponent = NewObject<UStaticMeshComponent>();
|
||||
|
||||
// Choose different mesh and color based on node type
|
||||
FString MeshPath;
|
||||
FLinearColor Color;
|
||||
|
||||
if (Node->NodeType.Equals(TEXT("SoftBody")))
|
||||
{
|
||||
MeshPath = TEXT("/Engine/BasicShapes/Sphere.Sphere");
|
||||
Color = FLinearColor(1.0f, 0.5f, 0.5f, 0.7f); // Translucent red
|
||||
}
|
||||
else if (Node->NodeType.Equals(TEXT("LineChain")))
|
||||
{
|
||||
MeshPath = TEXT("/Engine/BasicShapes/Cylinder.Cylinder");
|
||||
Color = FLinearColor(0.5f, 0.5f, 1.0f, 0.7f); // Translucent blue
|
||||
}
|
||||
else if (Node->NodeType.Equals(TEXT("Plane")))
|
||||
{
|
||||
MeshPath = TEXT("/Engine/BasicShapes/Plane.Plane");
|
||||
Color = FLinearColor(0.5f, 0.5f, 1.0f, 0.5f); // Translucent blue
|
||||
}
|
||||
else if (Node->NodeType.Equals(TEXT("Matrix")))
|
||||
{
|
||||
MeshPath = TEXT("/Engine/BasicShapes/Cube.Cube");
|
||||
Color = FLinearColor(0.5f, 1.0f, 0.5f, 0.7f); // Translucent green
|
||||
MeshComponent->SetWorldScale3D(FVector(0.25f, 0.25f, 0.25f)); // Scale down cube
|
||||
}
|
||||
else // Default to sphere
|
||||
{
|
||||
MeshPath = TEXT("/Engine/BasicShapes/Sphere.Sphere");
|
||||
Color = FLinearColor(1.0f, 1.0f, 1.0f, 0.7f); // Translucent white
|
||||
}
|
||||
|
||||
// Load static mesh
|
||||
UStaticMesh* StaticMesh = LoadObject<UStaticMesh>(nullptr, *MeshPath);
|
||||
if (StaticMesh)
|
||||
{
|
||||
MeshComponent->SetStaticMesh(StaticMesh);
|
||||
|
||||
// Set translucent material
|
||||
UMaterial* Material = LoadObject<UMaterial>(nullptr, TEXT("/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial"));
|
||||
if (Material)
|
||||
{
|
||||
UMaterialInstanceDynamic* DynamicMaterial = UMaterialInstanceDynamic::Create(Material, MeshComponent);
|
||||
if (DynamicMaterial)
|
||||
{
|
||||
DynamicMaterial->SetVectorParameterValue(TEXT("Color"), Color);
|
||||
MeshComponent->SetMaterial(0, DynamicMaterial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add to preview scene
|
||||
PreviewScene->AddComponent(MeshComponent, FTransform::Identity);
|
||||
NodeComponent = MeshComponent;
|
||||
|
||||
// If parent component exists, set parent-child relationship
|
||||
if (NodeComponent && ParentComponent)
|
||||
{
|
||||
NodeComponent->AttachToComponent(ParentComponent, FAttachmentTransformRules::KeepRelativeTransform);
|
||||
}
|
||||
|
||||
// Recursively load child nodes
|
||||
for (const TSharedPtr<FVisceraNodeItem>& ChildNode : Node->Children)
|
||||
{
|
||||
if (ChildNode.IsValid() && NodeComponent)
|
||||
{
|
||||
LoadNodeRecursive(ChildNode, NodeComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FFLESHViewportClient::UpdateVisibleNodes()
|
||||
{
|
||||
// Reload all nodes
|
||||
LoadNodesFromNodeTree();
|
||||
}
|
||||
|
||||
void FFLESHViewportClient::FocusOnSelectedNode()
|
||||
{
|
||||
if (!Editor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get currently selected node
|
||||
TSharedPtr<FVisceraNodeItem> SelectedNode = Editor->GetSelectedNodeItem();
|
||||
if (!SelectedNode.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Position camera at the selected node's location
|
||||
// Note: Here we use a default position since we don't have actual position information for the node
|
||||
// In a real implementation, we should find the component for this node and get its position
|
||||
FVector FocusLocation = FVector::ZeroVector;
|
||||
|
||||
// Set camera position and rotation
|
||||
SetViewLocation(FocusLocation + FVector(0.0f, 100.0f, 0.0f));
|
||||
SetViewRotation(FRotator(0.0f, -90.0f, 0.0f));
|
||||
|
||||
// Update view
|
||||
Invalidate();
|
||||
}
|
||||
|
Reference in New Issue
Block a user