-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
STimeOfDayManager.cpp
165 lines (130 loc) · 4.62 KB
/
STimeOfDayManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "World/STimeOfDayManager.h"
#include "World/SGameState.h"
#include "Components/AudioComponent.h"
#include "Engine/DirectionalLight.h"
#include "Engine/SkyLight.h"
#include "Kismet/GameplayStatics.h"
#include "Sound/SoundCue.h"
#include "Components/SkyLightComponent.h"
#include "Curves/CurveVector.h"
ASTimeOfDayManager::ASTimeOfDayManager()
{
AmbientAudioComp = CreateDefaultSubobject<UAudioComponent>(TEXT("AmbientAudioComp"));
AmbientAudioComp->bAutoActivate = false;
/*
Content/Base/BP_TimeOfDayManager extends this class and fetches all required object references from the current level.
SkyLight, DirectionalLight (& BP_SkySphere which is controlled in Blueprint only to update sun direction in the skybox)
*/
}
void ASTimeOfDayManager::BeginPlay()
{
Super::BeginPlay();
if (PrimarySunLight)
{
OriginalSunBrightness = PrimarySunLight->GetBrightness();
TargetSunBrightness = OriginalSunBrightness;
}
PlayAmbientLoop();
}
void ASTimeOfDayManager::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
ASGameState* MyGameState = Cast<ASGameState>(GetWorld()->GetGameState());
if (MyGameState)
{
/* Update the position of the sun. */
if (PrimarySunLight)
{
if (LastTimeOfDay == MyGameState->ElapsedGameMinutes)
{
TimeSinceLastIncrement += DeltaSeconds;
}
else
{
/* Reset prediction */
TimeSinceLastIncrement = 0;
}
/* Predict the movement of the sun to smooth out the rotations between replication updates of the actual time of day */
const float PredictedIncrement = MyGameState->GetTimeOfDayIncrement() * TimeSinceLastIncrement;
/* TimeOfDay is expressed in minutes, we need to convert this into a pitch rotation */
const float MinutesInDay = 24 * 60;
const float PitchOffset = 90; // The offset to account for time of day 0 should equal midnight
const float PitchRotation = 360 * ((MyGameState->ElapsedGameMinutes + PredictedIncrement) / MinutesInDay);
FRotator NewSunRotation = FRotator(PitchRotation + PitchOffset, 45.0f, 0);
PrimarySunLight->SetActorRelativeRotation(NewSunRotation);
LastTimeOfDay = MyGameState->ElapsedGameMinutes;
}
bool CurrentNightState = MyGameState->GetIsNight();
if (CurrentNightState != LastNightState)
{
if (CurrentNightState)
{
UGameplayStatics::PlaySound2D(this, SoundNightStarted);
TargetSunBrightness = 0.01f;
}
else
{
UGameplayStatics::PlaySound2D(this, SoundNightEnded);
TargetSunBrightness = OriginalSunBrightness;
}
/* Change to a new ambient loop */
PlayAmbientLoop();
}
/* Update sun brightness to transition between day and night
(Note: We cannot disable the sunlight because BP_SkySphere depends on an enabled light to update the skydome) */
const float LerpSpeed = 0.1f * GetWorldSettings()->GetEffectiveTimeDilation();
float CurrentSunBrightness = PrimarySunLight->GetBrightness();
float NewSunBrightness = FMath::Lerp(CurrentSunBrightness, TargetSunBrightness, LerpSpeed);
PrimarySunLight->SetBrightness(NewSunBrightness);
LastNightState = CurrentNightState;
}
UpdateSkylight();
}
void ASTimeOfDayManager::UpdateSkylight()
{
if (SkyLightActor)
{
ASGameState* MyGameState = Cast<ASGameState>(GetWorld()->GetGameState());
if (MyGameState)
{
const float MinutesInDay = 24 * 60;
const float PredictedIncrement = MyGameState->GetTimeOfDayIncrement() * TimeSinceLastIncrement;
float CurrentTime = MyGameState->GetElapsedMinutesCurrentDay() + PredictedIncrement;
/* Map the intensity from 0 - 12 - 24 hours into 0 - 1 - 0 alpha */
const float Alpha = FMath::Sin((CurrentTime / MinutesInDay) * 3.14);
/* Update Intensity */
float NewIntensity = FMath::Lerp(0.1, 1.0, Alpha);
if (SkylightIntensityCurve)
{
// If curve is specified, override the basic interp from above
NewIntensity = SkylightIntensityCurve->GetFloatValue(Alpha);
}
SkyLightActor->GetLightComponent()->SetIntensity(NewIntensity);
//UE_LOG(LogTemp, Warning, TEXT("Time of day alpha: %s"), *FString::SanitizeFloat(Alpha));
FVector LightColor = SkyLightActor->GetLightComponent()->GetLightColor();
if (SkylightColorCurve)
{
LightColor = SkylightColorCurve->GetVectorValue(Alpha);
}
SkyLightActor->GetLightComponent()->SetLightColor(LightColor);
}
}
}
void ASTimeOfDayManager::PlayAmbientLoop()
{
AmbientAudioComp->Stop();
ASGameState* MyGameState = Cast<ASGameState>(GetWorld()->GetGameState());
if (MyGameState)
{
if (MyGameState->GetIsNight())
{
AmbientAudioComp->SetSound(AmbientNight);
}
else
{
AmbientAudioComp->SetSound(AmbientDaytime);
}
}
AmbientAudioComp->Play();
}