diff --git a/Unreal/PS_StratVision/Content/NewMap.umap b/Unreal/PS_StratVision/Content/NewMap.umap new file mode 100644 index 0000000..ba39b8a Binary files /dev/null and b/Unreal/PS_StratVision/Content/NewMap.umap differ diff --git a/Unreal/PS_StratVision/Content/testStatVis.uasset b/Unreal/PS_StratVision/Content/testStatVis.uasset new file mode 100644 index 0000000..7a04b8b Binary files /dev/null and b/Unreal/PS_StratVision/Content/testStatVis.uasset differ diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision b/Unreal/PS_StratVision/Plugins/PS_StrategicVision new file mode 160000 index 0000000..199c140 --- /dev/null +++ b/Unreal/PS_StratVision/Plugins/PS_StrategicVision @@ -0,0 +1 @@ +Subproject commit 199c14097e451995c57b4cc777c269f69ac01d02 diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/.gitignore b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/.gitignore deleted file mode 100644 index 156d316..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Artefacts de build du plugin (regeneres a la compilation) -Binaries/ -Intermediate/ diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/PS_StrategicVision.uplugin b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/PS_StrategicVision.uplugin deleted file mode 100644 index 3c1052a..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/PS_StrategicVision.uplugin +++ /dev/null @@ -1,30 +0,0 @@ -{ - "FileVersion": 3, - "Version": 1, - "VersionName": "0.1.0", - "FriendlyName": "PS Strategic Vision", - "Description": "Affichage strategique pour vues spectateur et replays : cones de vision, et autres visualisations a venir.", - "Category": "Visualization", - "CreatedBy": "j.foucher", - "CreatedByURL": "", - "DocsURL": "", - "MarketplaceURL": "", - "SupportURL": "", - "CanContainContent": true, - "IsBetaVersion": false, - "IsExperimentalVersion": false, - "Installed": false, - "Modules": [ - { - "Name": "PS_StrategicVision", - "Type": "Runtime", - "LoadingPhase": "Default" - } - ], - "Plugins": [ - { - "Name": "ProceduralMeshComponent", - "Enabled": true - } - ] -} diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/README.md b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/README.md deleted file mode 100644 index 61768f0..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# PS Strategic Vision - -Plugin Unreal Engine 5.7 d'affichage stratégique pour vues spectateur et replays : -cônes de vision des personnages, et d'autres visualisations à venir. - -## Installation dans un projet - -Copier (ou cloner) ce dossier dans `Plugins/PS_StrategicVision/` du projet, puis -activer le plugin dans le `.uproject` ou via *Edit > Plugins*. - -En submodule git : - -```bash -git submodule add Plugins/PS_StrategicVision -``` - -Le plugin est en C++ : le projet hôte doit être un projet C++ (il sera compilé -avec le projet). - -## Contenu - -| Classe | Rôle | -|---|---| -| `UPS_VisionConeComponent` | Component à poser sur un personnage : affiche son cône de vision (mesh procédural, bloqué par les murs). | -| `UPS_StrategicDisplayComponent` | Classe de base commune à tous les affichages stratégiques (camp, activation, couleur). Les futurs components en hériteront. | -| `UPS_StrategicVisionSubsystem` | Subsystem monde : interrupteurs globaux (tout, par catégorie, par camp). | -| `UPS_StrategicVisionSettings` | Réglages projet : couleurs des camps, matériau par défaut. | - -## Utilisation - -### 1. Poser le cône de vision - -Dans le Blueprint du personnage (ou en C++), ajouter le component **PS Vision Cone** -(idéalement attaché au root / à la capsule). Régler : - -- **Team** : `Player`, `Ally`, `Enemy` ou `Neutral` — détermine la couleur - (configurable dans *Project Settings > Plugins > PS Strategic Vision*). -- **View Distance** / **View Angle Degrees** : portée et ouverture du cône. -- **Trace Channel** : canal de collision utilisé pour bloquer le cône sur les murs - (`Visibility` par défaut). -- **Flatten On Ground** : le cône reste à plat et se projette au sol (recommandé - pour une vue spectateur top-down). - -Le cône suit automatiquement la position et le yaw du component. Pour qu'il suive -le regard de la tête plutôt que le corps, attacher le component au bone/socket voulu. - -### 2. Activer / désactiver selon l'état de jeu - -Par component : - -- `SetDisplayEnabled(bool)` — interrupteur local du component. - -Globalement, via le subsystem (Blueprint : nœud `Get PS_StrategicVisionSubsystem`, -ou `UPS_StrategicVisionSubsystem::Get(WorldContext)` en C++) : - -- `SetGlobalDisplayEnabled(bool)` — tout l'affichage stratégique (ex : entrée/sortie - du mode spectateur ou replay). -- `SetVisionConesEnabled(bool)` — uniquement les cônes de vision. -- `SetCategoryEnabled(FName, bool)` — par catégorie (pour les futurs components). -- `SetTeamEnabled(EPS_StrategicTeam, bool)` — par camp (ex : ne montrer que les ennemis). - -Un component n'est visible que si son interrupteur local ET les interrupteurs -globaux le permettent. Quand un cône est masqué, il ne fait plus aucune trace -(coût nul). - -### 3. Matériau (optionnel) - -Sans configuration, le cône utilise un matériau translucide du moteur -(`M_SimpleUnlitTranslucent`) teinté à la couleur du camp — fonctionnel -immédiatement, suffisant en développement. - -Pour un rendu personnalisé (dégradé, scanlines, bord lumineux...), créer un -matériau dans le Content du plugin à `/PS_StrategicVision/Materials/M_VisionCone` -(chemin par défaut des settings) ou l'assigner via **Material Override** sur le -component. Le component fournit au matériau : - -- paramètre vecteur `Color` : couleur du camp (alpha = opacité) ; -- paramètre scalaire `Opacity` : opacité ; -- vertex colors : couleur du camp ; -- UV : U = position angulaire (0..1), V = distance normalisée (0..1) — pratique - pour un fondu vers le bord du cône. - -Recette minimale : matériau *Translucent* / *Unlit*, node **VertexColor** → Emissive -Color, **VertexColor.A** → Opacity. Laisser *Two Sided* décoché (la géométrie est -déjà double face). - -> Note packaging : si le matériau n'est référencé que par les settings (soft -> reference), l'ajouter à la liste des assets toujours cookés, ou le référencer en -> dur via Material Override. - -### Performance - -- `ArcSegments` (48 par défaut) = nombre de line traces par mise à jour. -- `UpdateInterval` : 0 = chaque frame ; augmenter (ex : 0.05) si beaucoup de - personnages affichent leur cône simultanément. - -## Roadmap - -- [x] Cône de vision bloqué par les obstacles -- [ ] Autres affichages stratégiques (trajectoires, zones d'alerte, ...) sous forme - de components héritant de `UPS_StrategicDisplayComponent` diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/PS_StrategicVision.Build.cs b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/PS_StrategicVision.Build.cs deleted file mode 100644 index 0924c3e..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/PS_StrategicVision.Build.cs +++ /dev/null @@ -1,18 +0,0 @@ -using UnrealBuildTool; - -public class PS_StrategicVision : ModuleRules -{ - public PS_StrategicVision(ReadOnlyTargetRules Target) : base(Target) - { - PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; - - PublicDependencyModuleNames.AddRange(new string[] - { - "Core", - "CoreUObject", - "Engine", - "DeveloperSettings", - "ProceduralMeshComponent", - }); - } -} diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicDisplayComponent.cpp b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicDisplayComponent.cpp deleted file mode 100644 index 55acae4..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicDisplayComponent.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#include "PS_StrategicDisplayComponent.h" - -#include "Engine/World.h" -#include "PS_StrategicVisionSettings.h" -#include "PS_StrategicVisionSubsystem.h" - -UPS_StrategicDisplayComponent::UPS_StrategicDisplayComponent() -{ - PrimaryComponentTick.bCanEverTick = false; -} - -void UPS_StrategicDisplayComponent::SetTeam(EPS_StrategicTeam NewTeam) -{ - if (Team != NewTeam) - { - Team = NewTeam; - RefreshDisplayState(); - } -} - -void UPS_StrategicDisplayComponent::SetDisplayEnabled(bool bEnabled) -{ - if (bDisplayEnabled != bEnabled) - { - bDisplayEnabled = bEnabled; - RefreshDisplayState(); - } -} - -bool UPS_StrategicDisplayComponent::IsDisplayVisible() const -{ - if (!bDisplayEnabled) - { - return false; - } - - if (const UWorld* World = GetWorld()) - { - if (World->IsGameWorld()) - { - if (const UPS_StrategicVisionSubsystem* Subsystem = World->GetSubsystem()) - { - return Subsystem->ShouldDisplay(GetDisplayCategory(), Team); - } - } - } - - // Monde editeur (preview) : on suit uniquement l'activation locale. - return true; -} - -FLinearColor UPS_StrategicDisplayComponent::GetTeamColor() const -{ - return GetDefault()->GetTeamColor(Team); -} - -void UPS_StrategicDisplayComponent::BeginPlay() -{ - Super::BeginPlay(); - - if (UPS_StrategicVisionSubsystem* Subsystem = UPS_StrategicVisionSubsystem::Get(this)) - { - Subsystem->OnDisplayStateChanged.AddUniqueDynamic(this, &UPS_StrategicDisplayComponent::HandleGlobalDisplayStateChanged); - } - - RefreshDisplayState(); -} - -void UPS_StrategicDisplayComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) -{ - if (UPS_StrategicVisionSubsystem* Subsystem = UPS_StrategicVisionSubsystem::Get(this)) - { - Subsystem->OnDisplayStateChanged.RemoveDynamic(this, &UPS_StrategicDisplayComponent::HandleGlobalDisplayStateChanged); - } - - Super::EndPlay(EndPlayReason); -} - -#if WITH_EDITOR -void UPS_StrategicDisplayComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) -{ - Super::PostEditChangeProperty(PropertyChangedEvent); - RefreshDisplayState(); -} -#endif - -void UPS_StrategicDisplayComponent::RefreshDisplayState() -{ - OnDisplayStateChanged(); -} - -void UPS_StrategicDisplayComponent::HandleGlobalDisplayStateChanged() -{ - RefreshDisplayState(); -} diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionModule.cpp b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionModule.cpp deleted file mode 100644 index 2587551..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionModule.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#include "Modules/ModuleManager.h" - -IMPLEMENT_MODULE(FDefaultModuleImpl, PS_StrategicVision) diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionSettings.cpp b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionSettings.cpp deleted file mode 100644 index ac75bcd..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionSettings.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#include "PS_StrategicVisionSettings.h" - -#include "Materials/MaterialInterface.h" - -UPS_StrategicVisionSettings::UPS_StrategicVisionSettings() -{ - TeamColors.Add(EPS_StrategicTeam::Player, FLinearColor(0.05f, 0.45f, 1.0f)); - TeamColors.Add(EPS_StrategicTeam::Ally, FLinearColor(0.1f, 0.9f, 0.5f)); - TeamColors.Add(EPS_StrategicTeam::Enemy, FLinearColor(1.0f, 0.12f, 0.08f)); - TeamColors.Add(EPS_StrategicTeam::Neutral, FLinearColor(0.75f, 0.75f, 0.75f)); - - // Materiau optionnel a creer dans le Content du plugin (voir README). - DefaultConeMaterial = TSoftObjectPtr( - FSoftObjectPath(TEXT("/PS_StrategicVision/Materials/M_VisionCone.M_VisionCone"))); -} - -FLinearColor UPS_StrategicVisionSettings::GetTeamColor(EPS_StrategicTeam Team) const -{ - if (const FLinearColor* Color = TeamColors.Find(Team)) - { - return *Color; - } - return FLinearColor::White; -} diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionSubsystem.cpp b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionSubsystem.cpp deleted file mode 100644 index 575781c..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionSubsystem.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#include "PS_StrategicVisionSubsystem.h" - -#include "Engine/Engine.h" -#include "Engine/World.h" - -UPS_StrategicVisionSubsystem* UPS_StrategicVisionSubsystem::Get(const UObject* WorldContextObject) -{ - if (GEngine) - { - if (const UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull)) - { - return World->GetSubsystem(); - } - } - return nullptr; -} - -void UPS_StrategicVisionSubsystem::SetGlobalDisplayEnabled(bool bEnabled) -{ - if (bGlobalEnabled != bEnabled) - { - bGlobalEnabled = bEnabled; - NotifyStateChanged(); - } -} - -void UPS_StrategicVisionSubsystem::SetCategoryEnabled(FName Category, bool bEnabled) -{ - const bool bChanged = bEnabled ? (DisabledCategories.Remove(Category) > 0) : !DisabledCategories.Contains(Category); - if (!bEnabled) - { - DisabledCategories.Add(Category); - } - if (bChanged) - { - NotifyStateChanged(); - } -} - -void UPS_StrategicVisionSubsystem::SetTeamEnabled(EPS_StrategicTeam Team, bool bEnabled) -{ - const bool bChanged = bEnabled ? (DisabledTeams.Remove(Team) > 0) : !DisabledTeams.Contains(Team); - if (!bEnabled) - { - DisabledTeams.Add(Team); - } - if (bChanged) - { - NotifyStateChanged(); - } -} - -void UPS_StrategicVisionSubsystem::NotifyStateChanged() -{ - OnDisplayStateChanged.Broadcast(); -} diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionTypes.cpp b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionTypes.cpp deleted file mode 100644 index 1dd1cfb..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_StrategicVisionTypes.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#include "PS_StrategicVisionTypes.h" - -const FName FPS_StrategicDisplayCategories::VisionCone(TEXT("VisionCone")); diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_VisionConeComponent.cpp b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_VisionConeComponent.cpp deleted file mode 100644 index 5408364..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Private/PS_VisionConeComponent.cpp +++ /dev/null @@ -1,270 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#include "PS_VisionConeComponent.h" - -#include "CollisionQueryParams.h" -#include "Engine/HitResult.h" -#include "Engine/World.h" -#include "GameFramework/Actor.h" -#include "Materials/Material.h" -#include "Materials/MaterialInstanceDynamic.h" -#include "Materials/MaterialInterface.h" -#include "ProceduralMeshComponent.h" -#include "PS_StrategicVisionSettings.h" - -namespace -{ - // Materiaux moteur utilises en dernier recours si aucun materiau n'est configure. - const TCHAR* GFallbackTranslucentMaterialPath = TEXT("/Engine/EngineDebugMaterials/M_SimpleUnlitTranslucent.M_SimpleUnlitTranslucent"); - const TCHAR* GFallbackOpaqueMaterialPath = TEXT("/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial"); - - const FName GColorParamName(TEXT("Color")); - const FName GOpacityParamName(TEXT("Opacity")); -} - -UPS_VisionConeComponent::UPS_VisionConeComponent() -{ - PrimaryComponentTick.bCanEverTick = true; - PrimaryComponentTick.bStartWithTickEnabled = true; - // Apres le mouvement des acteurs, pour que le cone suive sans retard. - PrimaryComponentTick.TickGroup = TG_PostUpdateWork; - bTickInEditor = true; -} - -void UPS_VisionConeComponent::OnRegister() -{ - Super::OnRegister(); - - EnsureConeMesh(); - EnsureMaterial(); - ApplyTeamColor(); -} - -void UPS_VisionConeComponent::OnComponentDestroyed(bool bDestroyingHierarchy) -{ - if (ConeMesh) - { - ConeMesh->DestroyComponent(); - ConeMesh = nullptr; - } - - Super::OnComponentDestroyed(bDestroyingHierarchy); -} - -void UPS_VisionConeComponent::BeginPlay() -{ - Super::BeginPlay(); - SetComponentTickInterval(UpdateInterval); -} - -void UPS_VisionConeComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) -{ - Super::TickComponent(DeltaTime, TickType, ThisTickFunction); - - if (IsDisplayVisible()) - { - RebuildCone(); - } -} - -void UPS_VisionConeComponent::OnDisplayStateChanged() -{ - const bool bShouldDisplay = IsDisplayVisible(); - - if (ConeMesh) - { - ConeMesh->SetVisibility(bShouldDisplay); - } - - // Pas de traces ni de rebuild quand le cone est cache. - SetComponentTickEnabled(bShouldDisplay); - SetComponentTickInterval(UpdateInterval); - - if (bShouldDisplay) - { - EnsureMaterial(); - ApplyTeamColor(); - RebuildCone(); - } -} - -void UPS_VisionConeComponent::EnsureConeMesh() -{ - if (ConeMesh || !GetWorld()) - { - return; - } - - ConeMesh = NewObject(this, NAME_None, RF_Transient); - ConeMesh->SetupAttachment(this); - // Rotation absolue : le fan est construit en espace monde, seul le point - // d'ancrage suit le personnage entre deux mises a jour. - ConeMesh->SetUsingAbsoluteRotation(true); - ConeMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision); - ConeMesh->SetGenerateOverlapEvents(false); - ConeMesh->SetCastShadow(false); - ConeMesh->bReceivesDecals = false; - ConeMesh->SetTranslucentSortPriority(100); - ConeMesh->RegisterComponent(); - ConeMesh->SetWorldRotation(FQuat::Identity); -} - -void UPS_VisionConeComponent::EnsureMaterial() -{ - if (!ConeMesh) - { - return; - } - - UMaterialInterface* BaseMaterial = MaterialOverride; - - if (!BaseMaterial) - { - BaseMaterial = GetDefault()->DefaultConeMaterial.LoadSynchronous(); - } - if (!BaseMaterial) - { - BaseMaterial = LoadObject(nullptr, GFallbackTranslucentMaterialPath); - } - if (!BaseMaterial) - { - BaseMaterial = LoadObject(nullptr, GFallbackOpaqueMaterialPath); - } - if (!BaseMaterial) - { - return; - } - - if (!ConeMID || ConeMID->Parent != BaseMaterial) - { - ConeMID = UMaterialInstanceDynamic::Create(BaseMaterial, this); - } - ConeMesh->SetMaterial(0, ConeMID); -} - -void UPS_VisionConeComponent::ApplyTeamColor() -{ - if (!ConeMID) - { - return; - } - - FLinearColor Color = GetTeamColor(); - Color.A = Opacity; - ConeMID->SetVectorParameterValue(GColorParamName, Color); - ConeMID->SetScalarParameterValue(GOpacityParamName, Opacity); -} - -void UPS_VisionConeComponent::RebuildCone() -{ - UWorld* World = GetWorld(); - if (!World || !ConeMesh) - { - return; - } - - const FVector CompLocation = GetComponentLocation(); - const FRotator CompRotation = GetComponentRotation(); - - const FVector Forward = bFlattenOnGround - ? FRotator(0.f, CompRotation.Yaw, 0.f).Vector() - : GetForwardVector(); - const FVector Up = bFlattenOnGround ? FVector::UpVector : GetUpVector(); - - FCollisionQueryParams QueryParams(TEXT("PS_VisionCone"), bTraceComplex); - if (const AActor* Owner = GetOwner()) - { - QueryParams.AddIgnoredActor(Owner); - } - - // Hauteur de base du fan : projete au sol si demande, sinon a la hauteur du component. - float BaseZ = GroundOffset; - if (bFlattenOnGround) - { - FHitResult GroundHit; - const FVector GroundStart = CompLocation + FVector(0.f, 0.f, TraceHeight); - const FVector GroundEnd = CompLocation - FVector(0.f, 0.f, 500.f); - if (World->LineTraceSingleByChannel(GroundHit, GroundStart, GroundEnd, TraceChannel, QueryParams)) - { - BaseZ = (GroundHit.ImpactPoint.Z - CompLocation.Z) + GroundOffset; - } - } - - const int32 RayCount = FMath::Clamp(ArcSegments, 4, 256) + 1; - const float HalfAngle = FMath::Clamp(ViewAngleDegrees, 1.f, 360.f) * 0.5f; - const FVector TraceOrigin = CompLocation + FVector(0.f, 0.f, TraceHeight); - - FLinearColor VertexColor = GetTeamColor(); - VertexColor.A = Opacity; - - TArray Vertices; - TArray Normals; - TArray UVs; - TArray Colors; - Vertices.Reserve(RayCount + 1); - Normals.Reserve(RayCount + 1); - UVs.Reserve(RayCount + 1); - Colors.Reserve(RayCount + 1); - - // Sommet central (origine du cone). - Vertices.Add(bFlattenOnGround ? FVector(0.f, 0.f, BaseZ) : Up * GroundOffset); - Normals.Add(Up); - UVs.Add(FVector2D(0.5f, 0.f)); - Colors.Add(VertexColor); - - for (int32 RayIndex = 0; RayIndex < RayCount; ++RayIndex) - { - const float Alpha = static_cast(RayIndex) / static_cast(RayCount - 1); - const float AngleDeg = FMath::Lerp(-HalfAngle, HalfAngle, Alpha); - const FVector Direction = Forward.RotateAngleAxis(AngleDeg, Up); - - float HitDistance = ViewDistance; - FHitResult Hit; - if (World->LineTraceSingleByChannel(Hit, TraceOrigin, TraceOrigin + Direction * ViewDistance, TraceChannel, QueryParams)) - { - HitDistance = Hit.Distance; - } - - FVector LocalPoint = Direction * HitDistance; - if (bFlattenOnGround) - { - LocalPoint.Z = BaseZ; - } - else - { - LocalPoint += Up * GroundOffset; - } - - Vertices.Add(LocalPoint); - Normals.Add(Up); - UVs.Add(FVector2D(Alpha, HitDistance / ViewDistance)); - Colors.Add(VertexColor); - } - - const TArray NoTangents; - - if (Vertices.Num() == LastVertexCount) - { - // Meme topologie : mise a jour des sommets uniquement (moins couteux). - ConeMesh->UpdateMeshSection_LinearColor(0, Vertices, Normals, UVs, Colors, NoTangents); - } - else - { - // Triangles dans les deux sens pour rester visible sous tous les angles de camera. - TArray Triangles; - Triangles.Reserve((RayCount - 1) * 6); - for (int32 SegmentIndex = 0; SegmentIndex < RayCount - 1; ++SegmentIndex) - { - Triangles.Add(0); - Triangles.Add(1 + SegmentIndex); - Triangles.Add(2 + SegmentIndex); - - Triangles.Add(0); - Triangles.Add(2 + SegmentIndex); - Triangles.Add(1 + SegmentIndex); - } - - ConeMesh->CreateMeshSection_LinearColor(0, Vertices, Triangles, Normals, UVs, Colors, NoTangents, false); - LastVertexCount = Vertices.Num(); - } -} diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicDisplayComponent.h b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicDisplayComponent.h deleted file mode 100644 index 812ad99..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicDisplayComponent.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "Components/SceneComponent.h" -#include "PS_StrategicVisionTypes.h" -#include "PS_StrategicDisplayComponent.generated.h" - -/** - * Classe de base des affichages strategiques poses sur les personnages - * (cone de vision, et autres visualisations a venir). - * - * Gere le camp (couleur), l'activation locale du component et la - * synchronisation avec l'etat global du UPS_StrategicVisionSubsystem. - */ -UCLASS(Abstract, ClassGroup = (PS_StrategicVision), HideCategories = (Physics, Collision, Mobility)) -class PS_STRATEGICVISION_API UPS_StrategicDisplayComponent : public USceneComponent -{ - GENERATED_BODY() - -public: - UPS_StrategicDisplayComponent(); - - /** Change le camp (met a jour la couleur de l'affichage). */ - UFUNCTION(BlueprintCallable, Category = "Strategic Display") - void SetTeam(EPS_StrategicTeam NewTeam); - - UFUNCTION(BlueprintPure, Category = "Strategic Display") - EPS_StrategicTeam GetTeam() const { return Team; } - - /** Active / desactive cet affichage precis (independamment de l'etat global). */ - UFUNCTION(BlueprintCallable, Category = "Strategic Display") - void SetDisplayEnabled(bool bEnabled); - - UFUNCTION(BlueprintPure, Category = "Strategic Display") - bool IsDisplayEnabled() const { return bDisplayEnabled; } - - /** Visibilite effective : activation locale ET etat global du subsystem. */ - UFUNCTION(BlueprintPure, Category = "Strategic Display") - bool IsDisplayVisible() const; - - /** Couleur du camp courant, lue dans les settings du plugin. */ - UFUNCTION(BlueprintPure, Category = "Strategic Display") - FLinearColor GetTeamColor() const; - - /** Categorie declaree par chaque type d'affichage (cf. FPS_StrategicDisplayCategories). */ - virtual FName GetDisplayCategory() const { return NAME_None; } - -protected: - virtual void BeginPlay() override; - virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; - -#if WITH_EDITOR - virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override; -#endif - - /** Appele quand la visibilite effective ou le camp change. */ - virtual void OnDisplayStateChanged() {} - - /** Reevalue la visibilite effective et previent la classe fille. */ - void RefreshDisplayState(); - - /** Camp du personnage porteur, determine la couleur de l'affichage. */ - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Strategic Display") - EPS_StrategicTeam Team = EPS_StrategicTeam::Enemy; - - /** Etat d'activation local de cet affichage. */ - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Strategic Display") - bool bDisplayEnabled = true; - -private: - UFUNCTION() - void HandleGlobalDisplayStateChanged(); -}; diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionSettings.h b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionSettings.h deleted file mode 100644 index 67dc7bc..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionSettings.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "Engine/DeveloperSettings.h" -#include "PS_StrategicVisionTypes.h" -#include "PS_StrategicVisionSettings.generated.h" - -class UMaterialInterface; - -/** - * Reglages du plugin PS Strategic Vision. - * Accessibles dans Project Settings > Plugins > PS Strategic Vision. - */ -UCLASS(Config = Game, DefaultConfig, meta = (DisplayName = "PS Strategic Vision")) -class PS_STRATEGICVISION_API UPS_StrategicVisionSettings : public UDeveloperSettings -{ - GENERATED_BODY() - -public: - UPS_StrategicVisionSettings(); - - virtual FName GetCategoryName() const override { return TEXT("Plugins"); } - - /** Couleur associee a chaque camp. */ - UPROPERTY(EditAnywhere, Config, BlueprintReadOnly, Category = "Teams") - TMap TeamColors; - - /** - * Materiau par defaut des cones de vision. La couleur est appliquee via le - * parametre vecteur "Color" (et le parametre scalaire "Opacity" s'il existe), - * ainsi que via les vertex colors du mesh. - * Si vide ou introuvable, un materiau translucide du moteur est utilise. - */ - UPROPERTY(EditAnywhere, Config, BlueprintReadOnly, Category = "Rendering") - TSoftObjectPtr DefaultConeMaterial; - - /** Couleur du camp demande (blanc si non configuree). */ - UFUNCTION(BlueprintPure, Category = "PS Strategic Vision") - FLinearColor GetTeamColor(EPS_StrategicTeam Team) const; -}; diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionSubsystem.h b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionSubsystem.h deleted file mode 100644 index b59c383..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionSubsystem.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "Subsystems/WorldSubsystem.h" -#include "PS_StrategicVisionTypes.h" -#include "PS_StrategicVisionSubsystem.generated.h" - -DECLARE_DYNAMIC_MULTICAST_DELEGATE(FPS_StrategicDisplayStateChanged); - -/** - * Subsystem monde pilotant l'affichage strategique global. - * Permet d'activer / desactiver tous les affichages, une categorie (ex : cones - * de vision) ou un camp entier selon l'etat de jeu (vue spectateur, replay...). - * Tous les UPS_StrategicDisplayComponent s'y abonnent automatiquement. - */ -UCLASS() -class PS_STRATEGICVISION_API UPS_StrategicVisionSubsystem : public UWorldSubsystem -{ - GENERATED_BODY() - -public: - /** Raccourci d'acces au subsystem depuis n'importe quel contexte monde. */ - UFUNCTION(BlueprintPure, Category = "PS Strategic Vision", meta = (WorldContext = "WorldContextObject")) - static UPS_StrategicVisionSubsystem* Get(const UObject* WorldContextObject); - - /** Interrupteur general de tous les affichages strategiques. */ - UFUNCTION(BlueprintCallable, Category = "PS Strategic Vision") - void SetGlobalDisplayEnabled(bool bEnabled); - - UFUNCTION(BlueprintPure, Category = "PS Strategic Vision") - bool IsGlobalDisplayEnabled() const { return bGlobalEnabled; } - - /** Active / desactive une categorie d'affichage (ex : "VisionCone"). */ - UFUNCTION(BlueprintCallable, Category = "PS Strategic Vision") - void SetCategoryEnabled(FName Category, bool bEnabled); - - UFUNCTION(BlueprintPure, Category = "PS Strategic Vision") - bool IsCategoryEnabled(FName Category) const { return !DisabledCategories.Contains(Category); } - - /** Active / desactive les affichages d'un camp (ex : ne montrer que les ennemis). */ - UFUNCTION(BlueprintCallable, Category = "PS Strategic Vision") - void SetTeamEnabled(EPS_StrategicTeam Team, bool bEnabled); - - UFUNCTION(BlueprintPure, Category = "PS Strategic Vision") - bool IsTeamEnabled(EPS_StrategicTeam Team) const { return !DisabledTeams.Contains(Team); } - - /** Raccourci : active / desactive tous les cones de vision. */ - UFUNCTION(BlueprintCallable, Category = "PS Strategic Vision|Vision Cone") - void SetVisionConesEnabled(bool bEnabled) { SetCategoryEnabled(FPS_StrategicDisplayCategories::VisionCone, bEnabled); } - - UFUNCTION(BlueprintPure, Category = "PS Strategic Vision|Vision Cone") - bool AreVisionConesEnabled() const { return IsCategoryEnabled(FPS_StrategicDisplayCategories::VisionCone); } - - /** Etat combine utilise par les components pour savoir s'ils doivent s'afficher. */ - bool ShouldDisplay(FName Category, EPS_StrategicTeam Team) const - { - return bGlobalEnabled && IsCategoryEnabled(Category) && IsTeamEnabled(Team); - } - - /** Notifie a chaque changement d'etat global (les components s'y abonnent). */ - UPROPERTY(BlueprintAssignable, Category = "PS Strategic Vision") - FPS_StrategicDisplayStateChanged OnDisplayStateChanged; - -private: - void NotifyStateChanged(); - - bool bGlobalEnabled = true; - TSet DisabledCategories; - TSet DisabledTeams; -}; diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionTypes.h b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionTypes.h deleted file mode 100644 index 21c0d3f..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_StrategicVisionTypes.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "PS_StrategicVisionTypes.generated.h" - -/** Camp d'un personnage, utilise pour colorer / filtrer les affichages strategiques. */ -UENUM(BlueprintType) -enum class EPS_StrategicTeam : uint8 -{ - Player, - Ally, - Enemy, - Neutral -}; - -/** - * Categories d'affichage strategique. Chaque type de component declare sa categorie, - * ce qui permet de l'activer / desactiver globalement via le subsystem. - */ -struct PS_STRATEGICVISION_API FPS_StrategicDisplayCategories -{ - static const FName VisionCone; -}; diff --git a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_VisionConeComponent.h b/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_VisionConeComponent.h deleted file mode 100644 index 9191d11..0000000 --- a/Unreal/PS_StratVision/Plugins/PS_StrategicVision/Source/PS_StrategicVision/Public/PS_VisionConeComponent.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2026 j.foucher. All rights reserved. - -#pragma once - -#include "CoreMinimal.h" -#include "Engine/EngineTypes.h" -#include "PS_StrategicDisplayComponent.h" -#include "PS_VisionConeComponent.generated.h" - -class UMaterialInstanceDynamic; -class UMaterialInterface; -class UProceduralMeshComponent; - -/** - * Affiche le cone de vision d'un personnage sous forme de mesh procedural. - * Le cone est decoupe par les obstacles (murs) via des line traces, colore - * selon le camp, et activable / desactivable localement ou globalement - * (vue spectateur, replay) via le UPS_StrategicVisionSubsystem. - * - * A attacher sur le personnage : le cone suit la position du component et - * s'oriente selon son yaw (rotation horizontale). - */ -UCLASS(ClassGroup = (PS_StrategicVision), meta = (BlueprintSpawnableComponent, DisplayName = "PS Vision Cone")) -class PS_STRATEGICVISION_API UPS_VisionConeComponent : public UPS_StrategicDisplayComponent -{ - GENERATED_BODY() - -public: - UPS_VisionConeComponent(); - - virtual FName GetDisplayCategory() const override { return FPS_StrategicDisplayCategories::VisionCone; } - - /** Portee de vision, en cm. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone", meta = (ClampMin = "10.0", Units = "cm")) - float ViewDistance = 1500.f; - - /** Angle total du cone, en degres (ex : 90 = 45 de chaque cote). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone", meta = (ClampMin = "1.0", ClampMax = "360.0", Units = "deg")) - float ViewAngleDegrees = 90.f; - - /** Opacite du cone (0 = invisible, 1 = opaque). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone", meta = (ClampMin = "0.0", ClampMax = "1.0")) - float Opacity = 0.35f; - - /** - * Si vrai, le cone reste a plat au sol : seul le yaw du component est pris - * en compte et le mesh est projete a la hauteur du sol detecte. - */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone") - bool bFlattenOnGround = true; - - /** Decalage vertical du mesh au-dessus du sol, pour eviter le z-fighting. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone", meta = (Units = "cm")) - float GroundOffset = 3.f; - - /** Nombre de segments de l'arc : plus eleve = plus precis mais plus de traces. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone|Quality", meta = (ClampMin = "4", ClampMax = "256")) - int32 ArcSegments = 48; - - /** Intervalle de mise a jour en secondes (0 = chaque frame). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone|Quality", meta = (ClampMin = "0.0", Units = "s")) - float UpdateInterval = 0.f; - - /** Canal de collision utilise pour bloquer le cone sur les obstacles. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone|Collision") - TEnumAsByte TraceChannel = ECC_Visibility; - - /** Trace contre la geometrie complexe (plus precis, plus couteux). */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone|Collision") - bool bTraceComplex = false; - - /** Hauteur (relative au component) a laquelle les traces de vision sont lancees. */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone|Collision", meta = (Units = "cm")) - float TraceHeight = 50.f; - - /** - * Materiau du cone pour ce component (prioritaire sur celui des settings). - * La couleur du camp est envoyee dans le parametre vecteur "Color", l'opacite - * dans le parametre scalaire "Opacity", et dans les vertex colors du mesh. - */ - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Vision Cone|Rendering") - TObjectPtr MaterialOverride; - - virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; - -protected: - virtual void OnRegister() override; - virtual void OnComponentDestroyed(bool bDestroyingHierarchy) override; - virtual void BeginPlay() override; - virtual void OnDisplayStateChanged() override; - -private: - /** Mesh procedural interne portant le fan du cone. */ - UPROPERTY(Transient) - TObjectPtr ConeMesh; - - UPROPERTY(Transient) - TObjectPtr ConeMID; - - int32 LastVertexCount = 0; - - void EnsureConeMesh(); - void EnsureMaterial(); - void ApplyTeamColor(); - void RebuildCone(); -};