Client LuaCsForBarotrauma
CameraTransition.cs
1 using Microsoft.Xna.Framework;
2 using System;
3 using System.Collections.Generic;
4 
5 namespace Barotrauma
6 {
8  {
9  private static List<CameraTransition> activeTransitions = new List<CameraTransition>();
10 
11  public bool Running
12  {
13  get;
14  private set;
15  }
16 
18  private readonly Alignment? cameraStartPos;
19  private readonly Alignment? cameraEndPos;
20  private readonly float? startZoom;
21  private readonly float? endZoom;
22 
23  public readonly float WaitDuration;
24  public float EndWaitDuration = 0.1f;
25  public readonly float PanDuration;
26  public readonly bool FadeOut;
27  public readonly bool LosFadeIn;
28 
29  private readonly CoroutineHandle updateCoroutine;
30 
31  private Character prevControlled;
32 
33  public bool AllowInterrupt = false;
34  public bool RemoveControlFromCharacter = true;
35 
36  public bool RunWhilePaused = true;
37 
38  public CameraTransition(ISpatialEntity targetEntity, Camera cam, Alignment? cameraStartPos, Alignment? cameraEndPos, bool fadeOut = true, bool losFadeIn = false, float waitDuration = 0f, float panDuration = 10.0f, float? startZoom = null, float? endZoom = null)
39  {
40  WaitDuration = waitDuration;
41  PanDuration = panDuration;
42  FadeOut = fadeOut;
43  LosFadeIn = losFadeIn;
44  this.cameraStartPos = cameraStartPos;
45  this.cameraEndPos = cameraEndPos;
46  this.startZoom = startZoom;
47  this.endZoom = endZoom;
48  AssignedCamera = cam;
49 
50  if (targetEntity == null) { return; }
51 
52  Running = true;
53 
54  prevControlled = Character.Controlled;
55  activeTransitions.RemoveAll(a => !CoroutineManager.IsCoroutineRunning(a.updateCoroutine));
56  foreach (var activeTransition in activeTransitions)
57  {
58  if (activeTransition.prevControlled != null)
59  {
60  prevControlled ??= activeTransition.prevControlled;
61  }
62  activeTransition.Stop();
63  }
64  updateCoroutine = CoroutineManager.StartCoroutine(Update(targetEntity, cam), "CameraTransition");
65  activeTransitions.Add(this);
66  }
67 
68  public void Stop()
69  {
70  CoroutineManager.StopCoroutines(updateCoroutine);
71  Running = false;
72 #if CLIENT
73  if (FadeOut) { GUI.ScreenOverlayColor = Color.TransparentBlack; }
74  if (prevControlled != null && !prevControlled.Removed)
75  {
76  Character.Controlled = prevControlled;
77  }
78 #endif
79  }
80 
81  private float DeltaTime => CoroutineManager.Paused && !RunWhilePaused ? 0 : CoroutineManager.DeltaTime;
82 
83  private IEnumerable<CoroutineStatus> Update(ISpatialEntity targetEntity, Camera cam)
84  {
85  if (targetEntity == null || (targetEntity is Entity e && e.Removed)) { yield return CoroutineStatus.Success; }
86 
87  prevControlled ??= Character.Controlled;
89  {
90 #if CLIENT
91  GameMain.LightManager.LosEnabled = false;
92 #endif
93  Character.Controlled = null;
94  }
95  cam.TargetPos = Vector2.Zero;
96 
97  float startZoom = this.startZoom ?? cam.Zoom;
98  float endZoom = this.endZoom ?? 0.5f;
99  Vector2 initialCameraPos = cam.Position;
100  Vector2? initialTargetPos = targetEntity?.WorldPosition;
101  Vector2 endPos = cam.Position;
102 
103  float timer = -WaitDuration;
104 
105  while (timer < PanDuration)
106  {
107  float clampedTimer = Math.Max(timer, 0f);
108 
109  if (Screen.Selected != GameMain.GameScreen)
110  {
111  yield return new WaitForSeconds(0.1f);
112 #if CLIENT
113  if (FadeOut) { GUI.ScreenOverlayColor = Color.TransparentBlack; }
114 #endif
115  Running = false;
116  yield return CoroutineStatus.Success;
117  }
118 
119  //switched control to some other character during the transition -> remove control again
120  if (Character.Controlled != null)
121  {
122  prevControlled = Character.Controlled;
124  {
125 #if CLIENT
126  GameMain.LightManager.LosEnabled = false;
127 #endif
128  Character.Controlled = null;
129  }
130  }
131 
132  if (prevControlled != null && prevControlled.Removed)
133  {
134  prevControlled = null;
135  }
136 #if CLIENT
137  if (AllowInterrupt && PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape))
138  {
139  break;
140  }
141 #endif
142  Vector2 minPos = targetEntity.WorldPosition;
143  Vector2 maxPos = targetEntity.WorldPosition;
144  if (targetEntity is Submarine sub)
145  {
146  minPos = new Vector2(sub.WorldPosition.X - sub.Borders.Width / 2, sub.WorldPosition.Y - sub.Borders.Height / 2);
147  maxPos = new Vector2(sub.WorldPosition.X + sub.Borders.Width / 2, sub.WorldPosition.Y + sub.Borders.Height / 2);
148  }
149 
150  Vector2 startPos = cameraStartPos.HasValue ?
151  new Vector2(
152  MathHelper.Lerp(minPos.X, maxPos.X, (cameraStartPos.Value.ToVector2().X + 1.0f) / 2.0f),
153  MathHelper.Lerp(maxPos.Y, minPos.Y, (cameraStartPos.Value.ToVector2().Y + 1.0f) / 2.0f)) :
154  initialCameraPos;
155  if (!cameraStartPos.HasValue && initialTargetPos.HasValue)
156  {
157  startPos += targetEntity.WorldPosition - initialTargetPos.Value;
158  }
159  endPos = cameraEndPos.HasValue ?
160  new Vector2(
161  MathHelper.Lerp(minPos.X, maxPos.X, (cameraEndPos.Value.ToVector2().X + 1.0f) / 2.0f),
162  MathHelper.Lerp(maxPos.Y, minPos.Y, (cameraEndPos.Value.ToVector2().Y + 1.0f) / 2.0f)) :
163  prevControlled?.WorldPosition ?? targetEntity.WorldPosition;
164 
165  Vector2 cameraPos = Vector2.SmoothStep(startPos, endPos, clampedTimer / PanDuration) + cam.ShakePosition;
166  cam.Translate(cameraPos - cam.Position);
167 
168 #if CLIENT
169  cam.Zoom = MathHelper.SmoothStep(startZoom, endZoom, clampedTimer / PanDuration);
170  if (clampedTimer / PanDuration > 0.9f)
171  {
172  if (FadeOut) { GUI.ScreenOverlayColor = Color.Lerp(Color.TransparentBlack, Color.Black, ((clampedTimer / PanDuration) - 0.9f) * 10.0f); }
173  }
174  if (LosFadeIn && clampedTimer / PanDuration > 0.8f)
175  {
176  if (!GameMain.DevMode)
177  {
178  GameMain.LightManager.LosEnabled = true;
179  GameMain.LightManager.LosAlpha = ((clampedTimer / PanDuration) - 0.8f) * 5.0f;
180  }
181  Lights.LightManager.ViewTarget = prevControlled ?? (targetEntity as Entity);
182  }
183 #endif
184  timer += DeltaTime;
185 
186  yield return CoroutineStatus.Running;
187  }
188 
189  float endTimer = 0.0f;
190  while (endTimer <= EndWaitDuration)
191  {
192  cam.Translate(endPos - cam.Position);
193  cam.Zoom = endZoom;
194  endTimer += DeltaTime;
195  yield return CoroutineStatus.Running;
196  }
197 
198  Running = false;
199 
200 #if CLIENT
201  GUI.ScreenOverlayColor = Color.TransparentBlack;
202  if (!GameMain.DevMode)
203  {
204  GameMain.LightManager.LosEnabled = true;
205  GameMain.LightManager.LosAlpha = 1f;
206  }
207 #endif
208 
209  if (prevControlled != null && !prevControlled.Removed)
210  {
211  Character.Controlled = prevControlled;
212  }
213 
214  yield return CoroutineStatus.Success;
215  }
216  }
217 }
float? Zoom
Definition: Camera.cs:78
Vector2 ShakePosition
Definition: Camera.cs:66
Vector2 Position
Definition: Camera.cs:398
void Translate(Vector2 amount)
Definition: Camera.cs:164
Vector2 TargetPos
Definition: Camera.cs:156
CameraTransition(ISpatialEntity targetEntity, Camera cam, Alignment? cameraStartPos, Alignment? cameraEndPos, bool fadeOut=true, bool losFadeIn=false, float waitDuration=0f, float panDuration=10.0f, float? startZoom=null, float? endZoom=null)
static CoroutineStatus Success
static void RemoveAll()
Definition: Entity.cs:212
@ Character
Characters only