CARLA
Loading...
Searching...
No Matches
CarlaSettingsDelegate.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
8#include "Carla.h"
11
12#include <util/ue-header-guard-begin.h>
14#include "Async/Async.h"
15#include "Components/StaticMeshComponent.h"
16#include "Engine/DirectionalLight.h"
17#include "Engine/Engine.h"
18#include "Engine/LocalPlayer.h"
19#include "Engine/PostProcessVolume.h"
20#include "Engine/StaticMesh.h"
21#include "Engine/GameViewportClient.h"
22#include "GameFramework/HUD.h"
23#include "InstancedFoliageActor.h"
24#include "Kismet/GameplayStatics.h"
25#include "Landscape.h"
26#include "Scalability.h"
27#include <util/ue-header-guard-end.h>
28
29static constexpr float CARLA_SETTINGS_MAX_SCALE_SIZE = 50.0f;
30
31/// quality settings configuration between runs
33
35
40
42{
43 CheckCarlaSettings(InWorld);
44}
45
47{
48 CheckCarlaSettings(nullptr);
49 UWorld *InWorld = CarlaSettings->GetWorld();
50
51 const EQualityLevel QualityLevel = CarlaSettings->GetQualityLevel();
52
53 if (AppliedLowPostResetQualityLevel == QualityLevel)
54 {
55 return;
56 }
57
58 // enable temporal changes of quality (prevent saving last quality settings to file)
59 Scalability::ToggleTemporaryQualityLevels(true);
60
61 SetAllRoads(InWorld, 0, CarlaSettings->EpicRoadMaterials);
62 ApplyPerActorQualitySettings(InWorld, 0.0f, true, false, 0);
63 SetPostProcessEffectsEnabled(InWorld, true);
65}
66
68{
69 CheckCarlaSettings(nullptr);
70 UWorld *InWorld = CarlaSettings->GetWorld();
71 if (!IsValid(InWorld))
72 {
73 return;
74 }
75 // enable or disable world and hud rendering
76 APlayerController *playercontroller = UGameplayStatics::GetPlayerController(InWorld, 0);
77 if (playercontroller)
78 {
79 ULocalPlayer *player = playercontroller->GetLocalPlayer();
80 if (player)
81 player->ViewportClient->bDisableWorldRendering = CarlaSettings->bDisableRendering;
82 // if we already have a hud class:
83 AHUD *hud = playercontroller->GetHUD();
84 if (hud)
85 {
86 hud->bShowHUD = !CarlaSettings->bDisableRendering;
87 }
88 }
89
90}
91
93{
94 return GEngine->GetWorldFromContextObjectChecked(this);
95}
96
98{
100 {
101 return;
102 }
103 if (!IsValid(world))
104 {
105 world = GetLocalWorld();
106 }
107 check(world != nullptr);
108 auto GameInstance = Cast<UCarlaGameInstance>(world->GetGameInstance());
109 check(GameInstance != nullptr);
110 CarlaSettings = &GameInstance->GetCarlaSettings();
111 check(CarlaSettings != nullptr);
112}
113
115 UWorld *world,
116 const float max_draw_distance,
117 const TArray<FStaticMaterial> &road_pieces_materials) const
118{
119 if (!IsValid(world))
120 {
121 return;
122 }
123 AsyncTask(ENamedThreads::GameThread, [=]() {
124 if (!IsValid(world))
125 {
126 return;
127 }
128 TArray<AActor *> actors;
129 UGameplayStatics::GetAllActorsWithTag(world, UCarlaSettings::CARLA_ROAD_TAG, actors);
130
131 for (int32 i = 0; i < actors.Num(); i++)
132 {
133 AActor *actor = actors[i];
134 if (!IsValid(actor))
135 {
136 continue;
137 }
138 TArray<UStaticMeshComponent *> components;
139 actor->GetComponents(components);
140 for (int32 j = 0; j < components.Num(); j++)
141 {
142 UStaticMeshComponent *staticmeshcomponent = Cast<UStaticMeshComponent>(components[j]);
143 if (staticmeshcomponent)
144 {
145 staticmeshcomponent->bAllowCullDistanceVolume = (max_draw_distance > 0);
146 staticmeshcomponent->bUseAsOccluder = false;
147 staticmeshcomponent->LDMaxDrawDistance = max_draw_distance;
148 staticmeshcomponent->CastShadow = (max_draw_distance == 0);
149 if (road_pieces_materials.Num() > 0)
150 {
151 TArray<FName> meshslotsnames = staticmeshcomponent->GetMaterialSlotNames();
152 for (int32 k = 0; k < meshslotsnames.Num(); k++)
153 {
154 const FName &slotname = meshslotsnames[k];
155 (void)road_pieces_materials.ContainsByPredicate(
156 [staticmeshcomponent, slotname](const FStaticMaterial &material)
157 {
158 if (material.MaterialSlotName.IsEqual(slotname))
159 {
160 staticmeshcomponent->SetMaterial(
161 staticmeshcomponent->GetMaterialIndex(slotname),
162 material.MaterialInterface);
163 return true;
164 }
165 else
166 {
167 return false;
168 }
169 });
170 }
171 }
172 }
173 }
174 }
175 }); // ,DELAY_TIME_TO_SET_ALL_ROADS, false);
176}
177
179 AActor *actor,
180 const float max_draw_distance) const
181{
182 if (!actor)
183 {
184 return;
185 }
186 TArray<UPrimitiveComponent *> components;
187 actor->GetComponents(components, false);
188 float dist = max_draw_distance;
189 const float maxscale = actor->GetActorScale().GetMax();
190 if (maxscale > CARLA_SETTINGS_MAX_SCALE_SIZE)
191 {
192 dist *= 100.0f;
193 }
194 for (int32 j = 0; j < components.Num(); j++)
195 {
196 UPrimitiveComponent *primitivecomponent = Cast<UPrimitiveComponent>(components[j]);
197 if (IsValid(primitivecomponent))
198 {
199 primitivecomponent->SetCullDistance(dist);
200 primitivecomponent->bAllowCullDistanceVolume = dist > 0;
201 }
202 }
203}
204
205void UCarlaSettingsDelegate::SetAllActorsDrawDistance(UWorld *world, const float max_draw_distance) const
206{
207 /// @TODO: use semantics to grab all actors by type
208 /// (vehicles,ground,people,props) and set different distances configured in
209 /// the global properties
210 if (!IsValid(world))
211 {
212 return;
213 }
214 AsyncTask(ENamedThreads::GameThread, [=, this]() {
215 if (!IsValid(world))
216 {
217 return;
218 }
219 TArray<AActor *> actors;
220 // set the lower quality - max draw distance
221 UGameplayStatics::GetAllActorsOfClass(world, AActor::StaticClass(), actors);
222 for (int32 i = 0; i < actors.Num(); i++)
223 {
224 AActor *actor = actors[i];
225 if (!IsValid(actor) ||
226 actor->IsA<AInstancedFoliageActor>() || // foliage culling is controlled
227 // per instance
228 actor->IsA<ALandscape>() || // dont touch landscapes nor roads
229 actor->ActorHasTag(UCarlaSettings::CARLA_ROAD_TAG) ||
230 actor->ActorHasTag(UCarlaSettings::CARLA_SKY_TAG))
231 {
232 continue;
233 }
234 SetActorComponentsDrawDistance(actor, max_draw_distance);
235 }
236 });
237}
238
239void UCarlaSettingsDelegate::SetPostProcessEffectsEnabled(UWorld *world, const bool enabled) const
240{
241 TArray<AActor *> actors;
242 UGameplayStatics::GetAllActorsOfClass(world, APostProcessVolume::StaticClass(), actors);
243 for (int32 i = 0; i < actors.Num(); i++)
244 {
245 AActor *actor = actors[i];
246 if (!IsValid(actor))
247 {
248 continue;
249 }
250 APostProcessVolume *postprocessvolume = Cast<APostProcessVolume>(actor);
251 if (postprocessvolume)
252 {
253 postprocessvolume->bEnabled = enabled;
254 }
255 }
256}
257
259 UWorld *world,
260 const float max_distance_fade,
261 const bool cast_shadows,
262 const bool hide_non_directional) const
263{
264 if (!IsValid(world))
265 {
266 return;
267 }
268 AsyncTask(ENamedThreads::GameThread, [=]() {
269 if (!IsValid(world))
270 {
271 return;
272 }
273 TArray<AActor *> actors;
274 UGameplayStatics::GetAllActorsOfClass(world, ALight::StaticClass(), actors);
275 for (int32 i = 0; i < actors.Num(); i++)
276 {
277 if (!IsValid(actors[i]))
278 {
279 continue;
280 }
281 // tweak directional lights
282 ADirectionalLight *directionallight = Cast<ADirectionalLight>(actors[i]);
283 if (directionallight)
284 {
285 directionallight->SetCastShadows(cast_shadows);
286 directionallight->SetLightFunctionFadeDistance(max_distance_fade);
287 continue;
288 }
289 // disable any other type of light
290 actors[i]->SetActorHiddenInGame(hide_non_directional);
291 }
292 });
293
294}
295
297 UWorld *world,
298 const float light_fade_distance,
299 const bool cast_directional_shadows,
300 const bool hide_non_directional_lights,
301 const float draw_distance) const
302{
303 if (!IsValid(world))
304 {
305 return;
306 }
307 AsyncTask(ENamedThreads::GameThread, [=, this]() {
308 if (!IsValid(world))
309 {
310 return;
311 }
312 TArray<AActor *> actors;
313 UGameplayStatics::GetAllActorsOfClass(world, AActor::StaticClass(), actors);
314 for (int32 i = 0; i < actors.Num(); i++)
315 {
316 AActor *actor = actors[i];
317 if (!IsValid(actor))
318 {
319 continue;
320 }
321
322 if (ADirectionalLight *directional = Cast<ADirectionalLight>(actor))
323 {
324 directional->SetCastShadows(cast_directional_shadows);
325 directional->SetLightFunctionFadeDistance(light_fade_distance);
326 continue;
327 }
328 if (actor->IsA<ALight>())
329 {
330 actor->SetActorHiddenInGame(hide_non_directional_lights);
331 continue;
332 }
333
334 if (actor->IsA<AInstancedFoliageActor>() ||
335 actor->IsA<ALandscape>() ||
336 actor->ActorHasTag(UCarlaSettings::CARLA_ROAD_TAG) ||
337 actor->ActorHasTag(UCarlaSettings::CARLA_SKY_TAG))
338 {
339 continue;
340 }
341
342 SetActorComponentsDrawDistance(actor, draw_distance);
343 }
344 });
345}
static constexpr float CARLA_SETTINGS_MAX_SCALE_SIZE
EQualityLevel
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
void SetAllRoads(UWorld *world, float max_draw_distance, const TArray< FStaticMaterial > &road_pieces_materials) const
void SetPostProcessEffectsEnabled(UWorld *world, bool enabled) const
void ApplyQualityLevelPreRestart()
Before loading a level, apply the current settings.
void ApplyQualityLevelPostRestart()
After loading a level, apply the current settings.
void Reset()
Reset settings to default.
void CheckCarlaSettings(UWorld *world)
Check that the world, instance and settings are valid and save the CarlaSettings instance.
void ApplyPerActorQualitySettings(UWorld *world, float light_fade_distance, bool cast_directional_shadows, bool hide_non_directional_lights, float draw_distance) const
Single-pass replacement for SetAllLights + SetAllActorsDrawDistance when applying a quality tier.
void SetAllActorsDrawDistance(UWorld *world, float max_draw_distance) const
void RegisterSpawnHandler(UWorld *World)
Create the event trigger handler for all the newly spawned actors to be processed with a custom funct...
static EQualityLevel AppliedLowPostResetQualityLevel
Currently applied quality level after level is restarted.
void SetAllLights(UWorld *world, float max_distance_fade, bool cast_shadows, bool hide_non_directional) const
void SetActorComponentsDrawDistance(AActor *actor, float max_draw_distance) const
bool bDisableRendering
Enable or disable the viewport rendering of the world.
EQualityLevel GetQualityLevel() const
static const FName CARLA_SKY_TAG
CARLA_SKY name to tag the sky sphere (BPS) actors in the scenes.
static const FName CARLA_ROAD_TAG
CARLA_ROAD name to tag road mesh actors.