From 5be3a777f9b68464b25d6e89df832d10ae5d6182 Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Fri, 10 Apr 2026 21:28:24 +0200 Subject: [PATCH] Add selection outline post-process setup (material pending) - PostProcessComponent on Pawn (unbound, applies to entire scene) - Auto-loads M_PS_Editor_SelectionOutline material at BeginPlay - Removed debug bounding box from Tick - Custom depth stencil already toggled on selected actors - Material needs to be created in UE editor (edge detection on CustomStencil) - Instructions: use TexCoord + Constant2Vector offsets for 4-neighbor sampling Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/memory/project_ps_editor.md | 45 ++++++++++-------- .../M_PS_Editor_SelectionOutline.uasset | Bin 0 -> 61627 bytes .../PS_Editor/GameMode/PS_Editor_Pawn.cpp | 35 +++++++------- .../PS_Editor/GameMode/PS_Editor_Pawn.h | 4 ++ 4 files changed, 48 insertions(+), 36 deletions(-) create mode 100644 Unreal/Plugins/PS_Editor/Content/M_PS_Editor_SelectionOutline.uasset diff --git a/.claude/memory/project_ps_editor.md b/.claude/memory/project_ps_editor.md index eddcbbd..3560e87 100644 --- a/.claude/memory/project_ps_editor.md +++ b/.claude/memory/project_ps_editor.md @@ -4,39 +4,44 @@ description: Runtime editor plugin for UE 5.5 - object placement, scene editing, type: project --- -PS_Editor is a runtime editor plugin for Unreal Engine 5.5 that will be integrated into the PROSERVE project. - -**Why:** Enable runtime scene editing in packaged builds - place objects, configure properties, define scenarios, manipulate splines, modify lighting, and save/load scenes as JSON. +PS_Editor is a runtime editor plugin for Unreal Engine 5.5 for the PROSERVE project. Key decisions: - UI: UMG driven by C++ (Slate) -- Gizmos: Custom actor with BasicShapes + unlit material (InteractiveToolsFramework is editor-only) -- Serialization: JSON via Json/JsonUtilities modules (future) +- Gizmos: Custom actor with BasicShapes + unlit material (ITF is editor-only) +- Serialization: JSON via Json/JsonUtilities (FJsonObjectConverter) - Naming: PS_Editor_ prefix on all files/classes - Plugin path: Unreal/Plugins/PS_Editor/ -- AZERTY keyboard layout: arrows + A/Q for movement, E/R/T for modes +- AZERTY keyboard: arrows + A/Q for movement, E/R/T for modes ## Completed Phases ### Phase 1 - GameMode + Camera -- PS_Editor_GameMode, PS_Editor_Pawn, PS_Editor_PlayerController, PS_Editor_HUD - Camera: Fly (RMB), Pan (LMB drag), Orbit (Alt+LMB / MMB) - Movement: arrows + A (up) / Q (down) ### Phase 2 - Selection + Transform + Undo -- SelectionManager: raycast click-to-select, Ctrl+click multi-select, Movable actors only -- Gizmo: custom actor with colored arrows (R/G/B), cones, SDPG_Foreground, constant screen size +- Click-to-select (Movable actors only), Ctrl+click multi-select +- Custom gizmo (R/G/B arrows + cones, SDPG_Foreground, constant screen size) - Translate/Rotate/Scale via gizmo drag, hotkeys E/R/T -- Snap to ground (End key), soft-delete (Delete key) -- Undo/Redo system: custom UndoManager, Ctrl+Z / Ctrl+Y, 50 action stack -- Properties panel: editable Location/Rotation/Scale fields -- Toolbar: mode buttons + snap ground -- Material: M_PS_Editor_Gizmo (Unlit, Vector Parameter "Color" → Emissive, Translucent, Disable Depth Test) +- Snap to ground (End), soft-delete (Delete + confirmation dialog) +- Undo/Redo (Ctrl+Z/Y, 50 action stack) +- Properties panel + toolbar UI +- Material: M_PS_Editor_Gizmo (Unlit, "Color" param, Translucent, Disable Depth Test) -## Next: Phase 3 - Object Spawning -- Catalog/list of objects to place -- Drag & drop or click to spawn -- Duplication of existing objects +### Phase 3 - Object Spawning +- SpawnableComponent: marker on BPs (name, category, thumbnail) +- SpawnCatalog DataAsset + Factory for easy creation +- SpawnManager: spawns in front of camera, tracks all spawned actors +- Catalogue UI: thumbnail cards, click to spawn, grouped by category +- CaptureAllThumbnails on DataAsset: auto-generates from UE thumbnails +- Spawn undo/redo, auto-deselect hidden actors -## Next: Phase 4 - JSON Serialization -- Save/load scenes as JSON +### Phase 4 - JSON Serialization +- SceneData USTRUCT (Version, SceneName, Timestamp, Actors[ClassPath, Location, Rotation, Scale]) +- SceneSerializer: Save/Load/Clear/GetSavedSceneNames +- Files in Saved/PS_Editor/Scenes/{name}.json +- UI: Save field + button, New Scene, saved scenes list with click-to-load + +## Next: Phase 5 - Advanced Editing +- Splines, lighting, AI characters, property editing diff --git a/Unreal/Plugins/PS_Editor/Content/M_PS_Editor_SelectionOutline.uasset b/Unreal/Plugins/PS_Editor/Content/M_PS_Editor_SelectionOutline.uasset new file mode 100644 index 0000000000000000000000000000000000000000..39b747f0eeac88551fb3f9858b7745a6406f4c29 GIT binary patch literal 61627 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 literal 0 HcmV?d00001 diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.cpp b/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.cpp index 773438e..f3b8ae5 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.cpp +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.cpp @@ -1,6 +1,7 @@ #include "PS_Editor_Pawn.h" #include "Camera/CameraComponent.h" #include "GameFramework/SpringArmComponent.h" +#include "Components/PostProcessComponent.h" #include "EnhancedInputComponent.h" #include "EnhancedInputSubsystems.h" #include "InputAction.h" @@ -31,11 +32,29 @@ APS_Editor_Pawn::APS_Editor_Pawn() Camera = CreateDefaultSubobject(TEXT("Camera")); Camera->SetupAttachment(SpringArm); + + OutlinePostProcess = CreateDefaultSubobject(TEXT("OutlinePostProcess")); + OutlinePostProcess->SetupAttachment(RootScene); + OutlinePostProcess->bUnbound = true; // Apply to entire scene } void APS_Editor_Pawn::BeginPlay() { Super::BeginPlay(); + + // Load outline post-process material + UMaterialInterface* OutlineMat = LoadObject( + nullptr, TEXT("/PS_Editor/M_PS_Editor_SelectionOutline.M_PS_Editor_SelectionOutline")); + if (OutlineMat && OutlinePostProcess) + { + OutlinePostProcess->Settings.WeightedBlendables.Array.Add(FWeightedBlendable(1.0f, OutlineMat)); + UE_LOG(LogTemp, Log, TEXT("PS_Editor: Selection outline material loaded")); + } + else + { + UE_LOG(LogTemp, Warning, TEXT("PS_Editor: Outline material /PS_Editor/M_PS_Editor_SelectionOutline not found. " + "Create a Post Process material in Plugins/PS_Editor/Content/")); + } } void APS_Editor_Pawn::Tick(float DeltaTime) @@ -53,22 +72,6 @@ void APS_Editor_Pawn::Tick(float DeltaTime) UpdateGizmoHover(); } - // Draw debug bounding box around selected actors - if (APS_Editor_PlayerController* EditorPC = Cast(PC)) - { - if (UPS_Editor_SelectionManager* SM = EditorPC->GetSelectionManager()) - { - for (const TWeakObjectPtr& Weak : SM->GetSelectedActors()) - { - if (AActor* Actor = Weak.Get()) - { - FVector Origin, Extent; - Actor->GetActorBounds(false, Origin, Extent); - DrawDebugBox(GetWorld(), Origin, Extent, FColor::Orange, false, -1.0f, 0, 2.0f); - } - } - } - } } } diff --git a/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.h b/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.h index 4ca2b3c..5980099 100644 --- a/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.h +++ b/Unreal/Plugins/PS_Editor/Source/PS_Editor/GameMode/PS_Editor_Pawn.h @@ -8,6 +8,7 @@ class UCameraComponent; class USpringArmComponent; +class UPostProcessComponent; class UInputAction; class UInputMappingContext; @@ -73,6 +74,9 @@ protected: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera") TObjectPtr Camera; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera") + TObjectPtr OutlinePostProcess; + // ---- Camera Settings ---- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera|Fly")