OpenClonk
C4Viewport.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* A viewport to each player */
19 
20 #include "C4Include.h"
22 #include "game/C4Viewport.h"
23 
24 #include "editor/C4Console.h"
26 #include "game/C4FullScreen.h"
27 #include "game/C4GraphicsSystem.h"
28 #include "graphics/C4Draw.h"
30 #include "gui/C4GameMessage.h"
31 #include "gui/C4MouseControl.h"
32 #include "gui/C4ScriptGuiWindow.h"
33 #include "landscape/C4Landscape.h"
34 #include "landscape/C4PXS.h"
35 #include "landscape/C4Particles.h"
36 #include "landscape/C4Sky.h"
38 #include "lib/C4Stat.h"
39 #include "network/C4Network2.h"
40 #include "object/C4Def.h"
41 #include "object/C4GameObjects.h"
42 #include "object/C4Object.h"
43 #include "object/C4ObjectMenu.h"
44 #include "player/C4Player.h"
45 #include "player/C4PlayerList.h"
46 
47 void C4Viewport::DropFile(const char* filename, float x, float y)
48 {
49  Game.DropFile(filename, GetViewX()+x/Zoom, GetViewY()+y/Zoom);
50 }
51 
52 bool C4Viewport::UpdateOutputSize(int32_t new_width, int32_t new_height)
53 {
54  if (!pWindow)
55  {
56  return false;
57  }
58  // Output size
59  C4Rect rect;
60  if (new_width)
61  {
62  rect.x = rect.y = 0;
63  rect.Wdt = new_width;
64  rect.Hgt = new_height;
65  }
66  else
67  {
68 #if defined(WITH_QT_EDITOR)
69  // Never query the window - size is always passed from Qt.
70  return false;
71 #else
72  if (!pWindow->GetSize(&rect))
73  {
74  return false;
75  }
76 #endif
77  }
78  OutX = rect.x;
79  OutY = rect.y;
80  ViewWdt = rect.Wdt;
81  ViewHgt = rect.Hgt;
82  ScrollView(0,0);
83  // Scroll bars
85  // Reset menus
86  ResetMenuPositions = true;
87  // update internal GL size
88  if (pWindow && pWindow->pSurface)
89  {
90  pWindow->pSurface->UpdateSize(ViewWdt, ViewHgt);
91  }
92  // Update zoom limits based on new size
94  if (player)
95  {
96  player->ZoomLimitsToViewport(this);
97  }
98  // Done
99  return true;
100 }
101 
103 {
104  Player = 0;
105  viewX = viewY = 0;
106  targetViewX = targetViewY = 0;
107  ViewWdt = ViewHgt = 0;
109  OutX = OutY = ViewWdt = ViewHgt = 0;
110  DrawX = DrawY = 0;
111  Zoom = 1.0;
112  ZoomTarget = 0.0;
113  ViewportOpenFrame = 0;
114  ZoomLimitMin = ZoomLimitMax = 0; // no limit
115  Next = nullptr;
116  PlayerLock = true;
117  ResetMenuPositions = false;
118  viewOffsX = viewOffsY = 0;
119  fIsNoOwnerViewport = false;
120 }
121 
123 {
124  DisableFoW();
125  if (pWindow)
126  {
127  delete pWindow->pSurface;
128  pWindow->Clear();
129  }
130 }
131 
132 void C4Viewport::DrawOverlay(C4TargetFacet &cgo, const ZoomData &GameZoom)
133 {
134  if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay)
135  {
136  // Player info
137  C4ST_STARTNEW(PInfoStat, "C4Viewport::DrawOverlay: Player Info")
138  DrawPlayerInfo(cgo);
139  C4ST_STOP(PInfoStat)
140  C4ST_STARTNEW(MenuStat, "C4Viewport::DrawOverlay: Menu")
141  DrawMenu(cgo);
142  C4ST_STOP(MenuStat)
143  }
144 
145  // Control overlays (if not film/replay)
146  if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay)
147  {
148  // Mouse control
149  if (::MouseControl.IsViewport(this))
150  {
151  C4ST_STARTNEW(MouseStat, "C4Viewport::DrawOverlay: Mouse")
152  ::MouseControl.Draw(cgo, GameZoom);
153  // Draw GUI-mouse in EM if active
154  if (pWindow)
155  {
156  ::pGUI->RenderMouse(cgo);
157  }
158  C4ST_STOP(MouseStat)
159  }
160  }
161 }
162 
164 {
165  // Get player
167 
168  // for menus, cgo is using GUI-syntax: TargetX/Y marks the drawing offset; x/y/Wdt/Hgt marks the offset rect
169  C4TargetFacet cgo; cgo.Set(cgo0);
170  cgo.X = 0;
171  cgo.Y = 0;
172  cgo.Wdt = cgo0.Wdt * cgo0.Zoom;
173  cgo.Hgt = cgo0.Hgt * cgo0.Zoom;
174  cgo.TargetX = float(cgo0.X);
175  cgo.TargetY = float(cgo0.Y);
176  cgo.Zoom = 1;
177  pDraw->SetZoom(cgo.X, cgo.Y, cgo.Zoom);
178 
179  // Player eliminated
180  if (player && player->Eliminated)
181  {
182  pDraw->TextOut(FormatString(LoadResStr(player->Surrendered ? "IDS_PLR_SURRENDERED" : "IDS_PLR_ELIMINATED"),player->GetName()).getData(),
183  ::GraphicsResource.FontRegular, 1.0, cgo.Surface,cgo.TargetX+cgo.Wdt/2,cgo.TargetY+2*cgo.Hgt/3,0xfaFF0000,ACenter);
184  return;
185  }
186 
187  // Player cursor object menu
188  if (player && player->Cursor && player->Cursor->Menu)
189  {
190  if (ResetMenuPositions)
191  {
192  player->Cursor->Menu->ResetLocation();
193  }
194  // if mouse is dragging, make it transparent to easy construction site drag+drop
195  bool mouse_dragging = false;
196  if (::MouseControl.IsDragging() && ::MouseControl.IsViewport(this))
197  {
198  mouse_dragging = true;
199  pDraw->ActivateBlitModulation(0x4fffffff);
200  }
201  // draw menu
202  player->Cursor->Menu->Draw(cgo);
203  // reset modulation for dragging
204  if (mouse_dragging)
205  {
207  }
208  }
209  // Player menu
210  if (player && player->Menu.IsActive())
211  {
212  if (ResetMenuPositions)
213  {
214  player->Menu.ResetLocation();
215  }
216  player->Menu.Draw(cgo);
217  }
218  // Fullscreen menu
220  {
221  if (ResetMenuPositions)
222  {
224  }
225  FullScreen.MainMenu->Draw(cgo);
226  }
227 
228  // Flag done
229  ResetMenuPositions = false;
230 
231  // restore Zoom
232  pDraw->SetZoom(cgo0.X, cgo0.Y, cgo0.Zoom);
233 }
234 
235 void C4Viewport::Draw(C4TargetFacet &cgo0, bool draw_game, bool draw_overlay)
236 {
237 #ifdef USE_CONSOLE
238  // No drawing in console mode
239  return;
240 #endif
241  C4TargetFacet cgo; cgo.Set(cgo0);
242  ZoomData GameZoom;
243  GameZoom.X = cgo.X;
244  GameZoom.Y = cgo.Y;
245  GameZoom.Zoom = cgo.Zoom;
246 
247  // Draw landscape borders
252 
253  // Compute non-bordered viewport area
254  cgo.X += BorderLeft;
255  cgo.Y += BorderTop;
256  cgo.Wdt -= (BorderLeft + BorderRight) / cgo.Zoom;
257  cgo.Hgt -= (BorderTop + BorderBottom) / cgo.Zoom;
258  cgo.TargetX += BorderLeft / Zoom;
259  cgo.TargetY += BorderTop / Zoom;
260 
261  // Apply Zoom
262  GameZoom.X = cgo.X;
263  GameZoom.Y = cgo.Y;
264  pDraw->SetZoom(GameZoom);
265 
266  // Set clipper to integer bounds around floating point viewport region
268  const C4Rect& clipRectInt(clipRect);
269  pDraw->SetPrimaryClipper(clipRectInt.x, clipRectInt.y, clipRectInt.x + clipRectInt.Wdt - 1, clipRectInt.y + clipRectInt.Hgt - 1);
270 
271  last_game_draw_cgo = cgo;
272 
273  if (draw_game)
274  {
275  // --- activate FoW here ---
276 
277  // Render FoW only if active for player
279  C4FoWRegion* FoW = nullptr;
280  if (player && player->fFogOfWar)
281  {
282  FoW = this->pFoW.get();
283  }
284 
285  // Update FoW
286  if (FoW)
287  {
288  // Viewport region in landscape coordinates
289  const FLOAT_RECT vpRect = { cgo.TargetX, cgo.TargetX + cgo.Wdt, cgo.TargetY, cgo.TargetY + cgo.Hgt };
290  // Region in which the light is calculated
291  // At the moment, just choose integer coordinates to surround the viewport
292  const C4Rect lightRect(vpRect);
293  if (!lightRect.Wdt || !lightRect.Hgt)
294  {
295  // Do not bother initializing FoW on empty region; would cause errors in drawing proc
296  FoW = nullptr;
297  }
298  else
299  {
300  FoW->Update(lightRect, vpRect);
301 
302  if (!FoW->Render())
303  {
304  // If FoW init fails, do not set it for further drawing
305  FoW = nullptr;
306  }
307  }
308  }
309 
310  pDraw->SetFoW(FoW);
311 
312  C4ST_STARTNEW(SkyStat, "C4Viewport::Draw: Sky")
313  ::Landscape.GetSky().Draw(cgo);
314  C4ST_STOP(SkyStat)
315 
316  ::Objects.Draw(cgo, Player, -2147483647 - 1 /* INT32_MIN */, 0);
317 
318  // Draw Landscape
319  C4ST_STARTNEW(LandStat, "C4Viewport::Draw: Landscape")
320  ::Landscape.Draw(cgo, FoW);
321  C4ST_STOP(LandStat)
322 
323  // draw PXS (unclipped!)
324  C4ST_STARTNEW(PXSStat, "C4Viewport::Draw: PXS")
325  ::PXS.Draw(cgo);
326  C4ST_STOP(PXSStat)
327 
328  // Draw objects which are behind the particle plane.
329  const int particlePlane = 900;
330  C4ST_STARTNEW(ObjStat, "C4Viewport::Draw: Objects (1)")
331  ::Objects.Draw(cgo, Player, 1, particlePlane);
332  C4ST_STOP(ObjStat)
333 
334  // Draw global dynamic particles on a specific Plane
335  // to enable scripters to put objects both behind and in front of particles.
336  C4ST_STARTNEW(PartStat, "C4Viewport::Draw: Dynamic Particles")
338  C4ST_STOP(PartStat)
339 
340  // Now the remaining objects in front of the particles (e.g. GUI elements)
341  C4ST_STARTNEW(Obj2Stat, "C4Viewport::Draw: Objects (2)")
342  ::Objects.Draw(cgo, Player, particlePlane + 1, 2147483647 /* INT32_MAX */);
343  C4ST_STOP(Obj2Stat)
344 
345  // Draw everything else without FoW
346  pDraw->SetFoW(nullptr);
347  }
348  else
349  {
350  pDraw->DrawBoxDw(cgo.Surface, cgo.X, cgo.Y, cgo.X + cgo.Wdt, cgo.Y + cgo.Hgt, 0xff000000);
351  }
352 
353  // Draw PathFinder
355  {
356  Game.PathFinder.Draw(cgo);
357  }
358 
359  // Draw overlay
360  if (!Game.C4S.Head.Film || !Game.C4S.Head.Replay)
361  {
363  }
364 
365  // Lights overlay
366  if (::GraphicsSystem.ShowLights && pFoW)
367  {
368  pFoW->Render(&cgo);
369  }
370 
371  if (draw_overlay)
372  {
373  // Determine zoom of overlay
374  float gui_zoom = GetGUIZoom();
375  // now restore complete cgo range for overlay drawing
376  pDraw->SetZoom(DrawX, DrawY, gui_zoom);
378  C4TargetFacet gui_cgo;
379  gui_cgo.Set(cgo0);
380 
381  gui_cgo.X = DrawX;
382  gui_cgo.Y = DrawY;
383  gui_cgo.Zoom = gui_zoom;
384  gui_cgo.Wdt = int(float(ViewWdt)/gui_zoom);
385  gui_cgo.Hgt = int(float(ViewHgt)/gui_zoom);
386  gui_cgo.TargetX = GetViewX();
387  gui_cgo.TargetY = GetViewY();
388 
389  last_gui_draw_cgo = gui_cgo;
390 
391  // draw custom GUI objects
393 
394  // Draw overlay
395  C4ST_STARTNEW(OvrStat, "C4Viewport::Draw: Overlay")
396 
397  if (Application.isEditor)
398  {
400  }
401 
402  // Game messages
403  C4ST_STARTNEW(MsgStat, "C4Viewport::DrawOverlay: Messages")
404  pDraw->SetZoom(0, 0, 1.0);
405  ::Messages.Draw(gui_cgo, cgo, Player);
406  C4ST_STOP(MsgStat)
407 
408  // ingame menus
409  C4ST_STARTNEW(GuiWindowStat, "C4Viewport::DrawOverlay: Menus")
410  pDraw->SetZoom(0, 0, 1.0);
411  ::Game.ScriptGuiRoot->DrawAll(gui_cgo, Player);
412  C4ST_STOP(GuiWindowStat)
413 
414  DrawOverlay(gui_cgo, GameZoom);
415 
416  // Netstats
418  {
419  ::Network.DrawStatus(gui_cgo);
420  }
421 
422  C4ST_STOP(OvrStat)
423 
424  }
425 
426  // Remove zoom n clippers
427  pDraw->SetZoom(0, 0, 1.0);
429 
430 }
431 
433 {
434  if (pWindow)
435  {
436  C4Rect src, dst;
437  src.x = DrawX; src.y = DrawY; src.Wdt = ViewWdt; src.Hgt = ViewHgt;
438  dst.x = OutX; dst.y = OutY; dst.Wdt = ViewWdt; dst.Hgt = ViewHgt;
439  pWindow->pSurface->PageFlip(&src, &dst);
440  }
441 }
442 
444 {
445  // Adjust position
447  // Current graphics output
448  C4TargetFacet cgo;
449  C4Surface *target = pWindow ? pWindow->pSurface : FullScreen.pSurface;
450  cgo.Set(target,DrawX,DrawY,float(ViewWdt)/Zoom,float(ViewHgt)/Zoom,GetViewX(),GetViewY(),Zoom);
451  pDraw->PrepareRendering(target);
452  // Load script uniforms from Global.Uniforms
453  auto uniform_pop = pDraw->scriptUniform.Push(::GameScript.ScenPropList.getPropList());
454  // Do not spoil game contents on owner-less viewport
455  bool draw_game = true;
456  if (Player == NO_OWNER)
457  {
458  if (!::Application.isEditor && !::Game.DebugMode)
459  {
461  {
462  if (::Game.PlayerInfos.GetJoinIssuedPlayerCount() > 0) // free scrolling allowed if the scenario was started explicitely without players to inspect the landscape
463  {
464  if (Game.C4S.Landscape.Secret)
465  {
466  draw_game = false;
467  }
468  }
469  }
470  }
471  }
472  // Draw
473  Draw(cgo, draw_game, true);
474  // Blit output
475  BlitOutput();
476 }
477 
478 /* This method is called whenever the viewport size is changed. Thus, its job
479  is to recalculate the zoom and zoom limits with the new values for ViewWdt
480  and ViewHgt. */
482 {
483  // Zoom is only initialized by player or global setting during viewport creation time, because after that
484  // the player may have changed to another preferred zoom.
485  // However, viewports may change multiple times during startup (because of NO_OWNER viewport being deleted
486  // and possible other player joins). So check by frame counter. Zoom changes done in paused mode on the
487  // player init frame will be lost, but that should not be a problem.
489  {
490  InitZoom();
491  }
492 
494  if (player)
495  {
496  player->ZoomLimitsToViewport(this);
497  }
498  else
499  {
500  SetZoomLimits(0.8*std::min<float>(float(ViewWdt)/::Landscape.GetWidth(),float(ViewHgt)/::Landscape.GetHeight()), 8);
501  }
502 
503 }
504 
506 {
508  if (player)
509  {
510  player->ZoomToViewport(this, true);
511  }
512  else
513  {
514  ZoomTarget = std::max<float>(float(ViewWdt)/::Landscape.GetWidth(), 1.0f);
515  Zoom = ZoomTarget;
516  }
517 }
518 
519 void C4Viewport::ChangeZoom(float by_factor)
520 {
521  ZoomTarget *= by_factor;
524 }
525 
526 void C4Viewport::SetZoom(float to_value, bool direct)
527 {
528  ZoomTarget = to_value;
529  if (Player != NO_OWNER || !::Application.isEditor)
530  {
532  {
534  }
536  {
538  }
539  }
540  // direct: Set zoom without scrolling to it
541  if (direct)
542  {
543  Zoom = ZoomTarget;
544  }
545 }
546 
547 void C4Viewport::SetZoomLimits(float to_min_zoom, float to_max_zoom)
548 {
549  ZoomLimitMin = to_min_zoom;
550  ZoomLimitMax = to_max_zoom;
552  {
554  }
555  ChangeZoom(1); // Constrains zoom to limit.
556 }
557 
558 float C4Viewport::GetZoomByViewRange(int32_t size_x, int32_t size_y) const
559 {
560  // set zoom such that both size_x and size_y are guarantueed to fit into the viewport range
561  // determine whether zoom is to be calculated by x or by y
562  bool zoom_by_y = false;
563  if (size_x && size_y)
564  {
565  zoom_by_y = (size_y * ViewWdt > size_x * ViewHgt);
566  }
567  else if (size_y)
568  {
569  // no x size passed - zoom by y
570  zoom_by_y = true;
571  }
572  else
573  {
574  // 0/0 size passed - zoom to default
575  if (!size_x)
576  {
577  size_x = C4VP_DefViewRangeX * 2;
578  }
579  zoom_by_y = false;
580  }
581  // zoom calculation
582  if (zoom_by_y)
583  {
584  return float(ViewHgt) / size_y;
585  }
586  else
587  {
588  return float(ViewWdt) / size_x;
589  }
590 }
591 
592 void C4Viewport::SetZoom(float zoom_value)
593 {
594  Zoom = zoom_value;
595  // also set target to prevent zoom from changing back
596  ZoomTarget = zoom_value;
597 }
598 
600 {
601  // Move zoom towards target zoom
602  if (ZoomTarget < 0.000001f)
603  {
604  CalculateZoom();
605  }
606  // Change Zoom
607 
608  if (Zoom != ZoomTarget)
609  {
610  float DeltaZoom = Zoom / ZoomTarget;
611  if (DeltaZoom < 1)
612  {
613  DeltaZoom = 1 / DeltaZoom;
614  }
615 
616  // Minimal Zoom change factor
617  static const float Z0 = pow(C4GFX_ZoomStep, 1.0f / 8.0f);
618 
619  // We change zoom based on (logarithmic) distance of current zoom
620  // to target zoom. The greater the distance the more we adjust the
621  // zoom in one frame. There is a minimal zoom change Z0 to make sure
622  // we reach ZoomTarget in finite time.
623  float ZoomAdjustFactor = Z0 * pow(DeltaZoom, 1.0f / 8.0f);
624 
625  if (Zoom == 0)
626  {
627  Zoom = ZoomTarget;
628  }
629  else
630  {
631  // Remember old viewport center
632  float view_mid_x = this->viewX + float(this->ViewWdt) / Zoom / 2.0f;
633  float view_mid_y = this->viewY + float(this->ViewHgt) / Zoom / 2.0f;
634 
635  if (Zoom < ZoomTarget)
636  {
637  Zoom = std::min(Zoom * ZoomAdjustFactor, ZoomTarget);
638  }
639  if (Zoom > ZoomTarget)
640  {
641  Zoom = std::max(Zoom / ZoomAdjustFactor, ZoomTarget);
642  }
643 
644  // Restore new viewport center
645  this->viewX = view_mid_x - float(this->ViewWdt) / Zoom / 2.0f;
646  this->viewY = view_mid_y - float(this->ViewHgt) / Zoom / 2.0f;
647  }
648  }
649  // Adjust position
650  AdjustPosition(false);
651 }
652 
653 void C4Viewport::AdjustPosition(bool immediate)
654 {
655  if (ViewWdt == 0 || ViewHgt == 0)
656  {
657  // zero-sized viewport, possibly minimized editor window
658  // don't do anything then
659  return;
660  }
661 
662  assert(Zoom > 0);
663  assert(ZoomTarget > 0);
664 
665  float ViewportScrollBorder = fIsNoOwnerViewport ? 0 : float(C4ViewportScrollBorder);
667 
668  // View position
669  if (PlayerLock && ValidPlr(Player))
670  {
671  float scrollRange = 0;
672  float extraBoundsX = 0;
673  float extraBoundsY = 0;
674 
675  // target view position (landscape coordinates)
676  float targetCenterViewX = fixtof(player->ViewX);
677  float targetCenterViewY = fixtof(player->ViewY);
678 
679  if (player->ViewMode == C4PVM_Scrolling)
680  {
681  extraBoundsX = extraBoundsY = ViewportScrollBorder;
682  }
683  else
684  {
685  scrollRange = std::min(ViewWdt/(10*Zoom),ViewHgt/(10*Zoom));
686 
687  // if view is close to border, allow scrolling
688  if (targetCenterViewX < ViewportScrollBorder)
689  {
690  extraBoundsX = std::min<float>(ViewportScrollBorder - targetCenterViewX, ViewportScrollBorder);
691  }
692  else if (targetCenterViewX >= ::Landscape.GetWidth() - ViewportScrollBorder)
693  {
694  extraBoundsX = std::min<float>(targetCenterViewX - ::Landscape.GetWidth(), 0) + ViewportScrollBorder;
695  }
696  if (targetCenterViewY < ViewportScrollBorder)
697  {
698  extraBoundsY = std::min<float>(ViewportScrollBorder - targetCenterViewY, ViewportScrollBorder);
699  }
700  else if (targetCenterViewY >= ::Landscape.GetHeight() - ViewportScrollBorder)
701  {
702  extraBoundsY = std::min<float>(targetCenterViewY - ::Landscape.GetHeight(), 0) + ViewportScrollBorder;
703  }
704  }
705 
706  extraBoundsX = std::max(extraBoundsX, (ViewWdt/Zoom - ::Landscape.GetWidth())/2 + 1);
707  extraBoundsY = std::max(extraBoundsY, (ViewHgt/Zoom - ::Landscape.GetHeight())/2 + 1);
708 
709  // add mouse auto scroll
711  {
712  float strength = Config.Controls.MouseAutoScroll/100.0f;
713  targetCenterViewX += strength*(::MouseControl.VpX - ViewWdt/2.0f)/Zoom;
714  targetCenterViewY += strength*(::MouseControl.VpY - ViewHgt/2.0f)/Zoom;
715  }
716 
717  // scroll range
718  if (!immediate)
719  {
720  targetCenterViewX = Clamp(targetCenterViewX, targetCenterViewX - scrollRange, targetCenterViewX + scrollRange);
721  targetCenterViewY = Clamp(targetCenterViewY, targetCenterViewY - scrollRange, targetCenterViewY + scrollRange);
722  }
723  // bounds
724  targetCenterViewX = Clamp(targetCenterViewX, ViewWdt/Zoom/2 - extraBoundsX, ::Landscape.GetWidth() - ViewWdt/Zoom/2 + extraBoundsX);
725  targetCenterViewY = Clamp(targetCenterViewY, ViewHgt/Zoom/2 - extraBoundsY, ::Landscape.GetHeight() - ViewHgt/Zoom/2 + extraBoundsY);
726 
727  targetViewX = targetCenterViewX - ViewWdt/Zoom/2 + viewOffsX;
728  targetViewY = targetCenterViewY - ViewHgt/Zoom/2 + viewOffsY;
729 
730  if (immediate)
731  {
732  // immediate scroll
733  SetViewX(targetViewX);
734  SetViewY(targetViewY);
735  }
736  else
737  {
738  // smooth scroll
739  int32_t smooth = Clamp<int32_t>(Config.General.ScrollSmooth, 1, 50);
740  ScrollView((targetViewX - viewX) / smooth, (targetViewY - viewY) / smooth);
741  }
742  }
743 
744  UpdateBordersX();
745  UpdateBordersY();
746 
747  // NO_OWNER can't scroll
748  if (fIsNoOwnerViewport)
749  {
750  viewOffsX = 0;
751  viewOffsY = 0;
752  }
753 }
754 
756 {
757  // center viewport position on map
758  // set center position
761 }
762 
763 void C4Viewport::UpdateBordersX()
764 {
765  BorderLeft = std::max(-GetViewX() * Zoom, 0.0f);
766  BorderRight = std::max(ViewWdt - ::Landscape.GetWidth() * Zoom + GetViewX() * Zoom, 0.0f);
767 }
768 
769 void C4Viewport::UpdateBordersY()
770 {
771  BorderTop = std::max(-GetViewY() * Zoom, 0.0f);
772  BorderBottom = std::max(ViewHgt - ::Landscape.GetHeight() * Zoom + GetViewY() * Zoom, 0.0f);
773 }
774 
776 {
777  C4Facet ccgo;
778  if (!ValidPlr(Player))
779  {
780  return;
781  }
782  // Controls
783  DrawPlayerStartup(cgo);
784 }
785 
786 bool C4Viewport::Init(int32_t for_player, bool set_temporary_only)
787 {
788  // Fullscreen viewport initialization
789  // Set Player
790  if (!ValidPlr(for_player))
791  {
792  for_player = NO_OWNER;
793  }
794  Player = for_player;
796  if (!set_temporary_only) fIsNoOwnerViewport = (for_player == NO_OWNER);
797  if (Application.isEditor)
798  {
799  // Console viewport initialization
800  // Create window
801  pWindow = std::make_unique<C4ViewportWindow>(this);
802  if (!pWindow->Init(Player))
803  {
804  return false;
805  }
807  // Disable player lock on unowned viewports
808  if (!ValidPlr(Player))
809  {
811  }
812  // Don't call Execute right away since it is not yet guaranteed that
813  // the Player has set this as its Viewport, and the drawing routines rely
814  // on that.
815  }
816  else
817  {
818  // Owned viewport: clear any flash message explaining observer menu
819  if (ValidPlr(for_player))
820  {
822  }
823  }
824 
825  EnableFoW();
826  return true;
827 }
828 
830 {
831  pFoW.reset();
832 }
833 
835 {
836  if (::Landscape.HasFoW() && Player != NO_OWNER)
837  {
838  pFoW = std::make_unique<C4FoWRegion>(::Landscape.GetFoW(), ::Players.Get(Player));
839  }
840  else
841  {
842  DisableFoW();
843  }
844 }
845 
846 extern int32_t DrawMessageOffset;
847 
849 {
850  C4Player *player;
851  if (!(player = ::Players.Get(Player)))
852  {
853  return;
854  }
855  if (!player->LocalControl || !player->ShowStartup)
856  {
857  return;
858  }
859  int32_t name_height_offset = 0;
860 
861  // Control
862  // unnecessary with the current control sets
863  if (player && player->ControlSet)
864  {
865  C4Facet controlset_facet = player->ControlSet->GetPicture();
866  if (controlset_facet.Wdt)
867  {
868  controlset_facet.Draw(cgo.Surface,
869  cgo.X + (cgo.Wdt - controlset_facet.Wdt)/2,
870  cgo.Y + cgo.Hgt * 2/3 + DrawMessageOffset,
871  0, 0);
872  }
873  name_height_offset = GfxR->fctKeyboard.Hgt;
874  }
875 
876  // Name
877  pDraw->TextOut(player->GetName(), ::GraphicsResource.FontRegular, 1.0, cgo.Surface,
878  cgo.X+cgo.Wdt/2, cgo.Y+cgo.Hgt*2/3+name_height_offset + DrawMessageOffset,
879  player->ColorDw | 0xff000000, ACenter);
880 }
881 
882 void C4Viewport::ScrollView(float by_x, float by_y)
883 {
884  SetViewX(viewX + by_x);
885  SetViewY(viewY + by_y);
886 }
887 
888 void C4Viewport::SetViewX(float x)
889 {
890  viewX = x;
891 
892  if (fIsNoOwnerViewport)
893  {
894  if(::Landscape.GetWidth() < ViewWdt / Zoom)
895  {
896  viewX = ::Landscape.GetWidth()/2 - ViewWdt / Zoom / 2;
897  }
898  else
899  {
900  viewX = Clamp(x, 0.0f, ::Landscape.GetWidth() - ViewWdt / Zoom);
901  }
902  }
903 
904  UpdateBordersX();
905 }
906 
907 void C4Viewport::SetViewY(float y)
908 {
909  viewY = y;
910 
911  if (fIsNoOwnerViewport)
912  {
913  if(::Landscape.GetHeight() < ViewHgt / Zoom)
914  {
915  viewY = ::Landscape.GetHeight()/2 - ViewHgt / Zoom / 2;
916  }
917  else
918  {
919  viewY = Clamp(y, 0.0f, ::Landscape.GetHeight() - ViewHgt / Zoom);
920  }
921  }
922 
923  UpdateBordersY();
924 }
925 
926 void C4Viewport::SetOutputSize(int32_t draw_x, int32_t draw_y, int32_t out_x, int32_t out_y, int32_t out_wdt, int32_t out_hgt)
927 {
928  int32_t deltaWidth = ViewWdt - out_wdt;
929  int32_t deltaHeight = ViewHgt - out_hgt;
930 
931  // update output parameters
932  DrawX = draw_x;
933  DrawY = draw_y;
934  OutX = out_x;
935  OutY = out_y;
936  ViewWdt = out_wdt;
937  ViewHgt = out_hgt;
938  // update view position: Remain centered at previous position
939  // scrolling the view must be done after setting the new view width and height
940  ScrollView(deltaWidth/2, deltaHeight/2);
941  CalculateZoom();
942  // Reset menus
943  ResetMenuPositions = true;
944  // player uses mouse control? then clip the cursor
945  C4Player *player;
946  if ((player = ::Players.Get(Player)))
947  {
948  if (player->MouseControl)
949  {
951  // and inform GUI
952  ::pGUI->SetPreferredDlgRect(C4Rect(out_x, out_y, out_wdt, out_hgt));
953  }
954  }
955 }
956 
958 {
959 
960 }
961 
963 {
964  C4Player *player;
965  int32_t player_nr;
966  if (!(player = ::Players.Get(Player)))
967  {
968  if (!(player = ::Players.First))
969  {
970  return;
971  }
972  }
973  else if (!(player = player->Next))
974  {
975  if (Game.C4S.Head.Film && Game.C4S.Head.Replay)
976  {
977  player = ::Players.First; // cycle to first in film mode only; in network obs mode allow NO_OWNER-view
978  }
979  }
980  if (player)
981  {
982  player_nr = player->Number;
983  }
984  else
985  {
986  player_nr = NO_OWNER;
987  }
988  if (player_nr != Player)
989  {
990  Init(player_nr, true);
991  }
992 }
993 
995 {
996  // check all associated menus
997  // Get player
999  // Player eliminated: No menu
1000  if (player && player->Eliminated)
1001  {
1002  return false;
1003  }
1004  // Player cursor object menu
1005  if (player && player->Cursor && player->Cursor->Menu == menu)
1006  {
1007  return true;
1008  }
1009  // Player menu
1010  if (player && player->Menu.IsActive() && &(player->Menu) == menu)
1011  {
1012  return true;
1013  }
1014  // Fullscreen menu (if active, only one viewport can exist)
1016  {
1017  return true;
1018  }
1019  // no match
1020  return false;
1021 }
1022 
1023 // C4ViewportList
1024 
1026 
1028 {
1030 }
1033 {
1034  C4Viewport *next;
1035  while (FirstViewport)
1036  {
1037  next = FirstViewport->Next;
1038  delete FirstViewport;
1039  FirstViewport = next;
1040  }
1041  FirstViewport = nullptr;
1042 }
1043 
1044 void C4ViewportList::Execute(bool draw_background)
1045 {
1046  // Background redraw
1047  if (draw_background)
1048  {
1050  }
1051  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1052  {
1053  if (viewport->GetWindow())
1054  {
1055  viewport->GetWindow()->RequestUpdate();
1056  }
1057  else
1058  {
1059  viewport->Execute();
1060  }
1061  }
1062 }
1063 
1065 {
1066  for (int i = 0, num = BackgroundAreas.GetCount(); i < num; ++i)
1067  {
1068  const C4Rect &rc = BackgroundAreas.Get(i);
1069  pDraw->BlitSurfaceTile(::GraphicsResource.fctBackground.Surface, FullScreen.pSurface, rc.x, rc.y, rc.Wdt, rc.Hgt, -rc.x, -rc.y, nullptr);
1070  }
1071 }
1072 
1074 {
1075  if (!viewport)
1076  {
1077  return false;
1078  }
1079  // Chop the start of the chain off
1080  if (FirstViewport == viewport)
1081  {
1082  FirstViewport = viewport->Next;
1083  delete viewport;
1084  StartSoundEffect("UI::CloseViewport");
1085  }
1086  // Take out of the chain
1087  else for (C4Viewport * prev = FirstViewport; prev; prev = prev->Next)
1088  {
1089  if (prev->Next == viewport)
1090  {
1091  prev->Next = viewport->Next;
1092  delete viewport;
1093  StartSoundEffect("UI::CloseViewport");
1094  }
1095  }
1096  // Deleting a viewport may leave us with no context selected
1097  if (pDraw)
1098  {
1100  }
1101  // Recalculate viewports
1103  // Done
1104  return true;
1105 }
1106 #ifdef USE_WIN32_WINDOWS
1108 {
1109  for (C4Viewport *cvp=FirstViewport; cvp; cvp=cvp->Next)
1110  {
1111  if (cvp->pWindow->hWindow==hwnd)
1112  {
1113  return cvp;
1114  }
1115  }
1116  return nullptr;
1117 }
1118 #endif
1119 bool C4ViewportList::CreateViewport(int32_t player_nr, bool silent)
1120 {
1121  // Create and init new viewport, add to viewport list
1122  int32_t last_count = GetViewportCount();
1123  C4Viewport *viewport = new C4Viewport;
1124  bool is_okay = viewport->Init(player_nr, false);
1125  if (!is_okay)
1126  {
1127  delete viewport;
1128  return false;
1129  }
1130  C4Viewport *last;
1131  for (last = FirstViewport; last && last->Next; last = last->Next)
1132  {
1133 
1134  }
1135  if (last)
1136  {
1137  last->Next = viewport;
1138  }
1139  else
1140  {
1141  FirstViewport = viewport;
1142  }
1143  // Recalculate viewports
1145  // Viewports start off at centered position
1146  viewport->CenterPosition();
1147  // Initial player zoom values to viewport (in case they were set early in InitializePlayer, loaded from savegame, etc.)
1148  C4Player *player = ::Players.Get(player_nr);
1149  if (player)
1150  {
1151  player->ZoomToViewport(viewport, true, false, false);
1152  player->ZoomLimitsToViewport(viewport);
1153  }
1154  // Action sound
1155  if (!silent && GetViewportCount() != last_count)
1156  {
1157  StartSoundEffect("UI::CloseViewport");
1158  }
1159  return true;
1160 }
1161 
1163 {
1164  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1165  {
1166  viewport->DisableFoW();
1167  }
1168 }
1169 
1171 {
1172  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1173  {
1174  viewport->EnableFoW();
1175  }
1176 }
1177 
1179 {
1180  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1181  {
1182  viewport->ClearPointers(obj);
1183  }
1184 }
1185 
1186 bool C4ViewportList::CloseViewport(int32_t player_nr, bool silent)
1187 {
1188  // Close all matching viewports
1189  int32_t last_count = GetViewportCount();
1190  C4Viewport *next;
1191  C4Viewport *prev = nullptr;
1192  for (C4Viewport *viewport = FirstViewport; viewport; viewport = next)
1193  {
1194  next = viewport->Next;
1195  if (viewport->Player == player_nr || (player_nr == NO_OWNER && viewport->fIsNoOwnerViewport))
1196  {
1197  delete viewport;
1198  if (prev)
1199  {
1200  prev->Next = next;
1201  }
1202  else
1203  {
1204  FirstViewport = next;
1205  }
1206  }
1207  else
1208  {
1209  prev = viewport;
1210  }
1211  }
1212  // Anything was done?
1213  if (GetViewportCount() != last_count)
1214  {
1215  // Recalculate viewports
1217  // Action sound
1218  if (!silent)
1219  {
1220  StartSoundEffect("UI::CloseViewport");
1221  }
1222  }
1223  return true;
1224 }
1225 
1227 {
1228 
1229  // Fullscreen only
1230  if (Application.isEditor) return;
1231 
1232  // Sort viewports
1234 
1235  // Viewport area
1236  int32_t border_top = 0;
1238  {
1239  border_top = C4UpperBoardHeight;
1240  }
1241  ViewportArea.Set(FullScreen.pSurface, 0, border_top, C4GUI::GetScreenWdt(), C4GUI::GetScreenHgt() - border_top);
1242 
1243  // Redraw flag
1245 #ifdef _WIN32
1246  // reset mouse clipping
1247  ClipCursor(nullptr);
1248 #else
1249  // StdWindow handles this.
1250 #endif
1251  // reset GUI dlg pos
1253 
1254  // fullscreen background: First, cover all of screen
1257 
1258  // Viewports
1259  C4Viewport *viewport;
1260  int32_t view_count = 0;
1261  for (viewport = FirstViewport; viewport; viewport = viewport->Next)
1262  {
1263  view_count++;
1264  }
1265  if (!view_count)
1266  {
1267  return;
1268  }
1269  int32_t iViewsH = (int32_t) sqrt(float(view_count));
1270  int32_t iViewsX = view_count / iViewsH;
1271  int32_t iViewsL = view_count % iViewsH;
1272  int32_t cViewH, cViewX, ciViewsX;
1273  int32_t cViewWdt, cViewHgt, cOffWdt, cOffHgt, cOffX, cOffY;
1274  viewport=FirstViewport;
1275  for (cViewH = 0; cViewH < iViewsH; cViewH++)
1276  {
1277  ciViewsX = iViewsX;
1278  if (cViewH < iViewsL)
1279  {
1280  ciViewsX++;
1281  }
1282  for (cViewX=0; cViewX < ciViewsX; cViewX++)
1283  {
1284  cViewWdt = ViewportArea.Wdt/ciViewsX;
1285  cViewHgt = ViewportArea.Hgt/iViewsH;
1286  cOffX = ViewportArea.X;
1287  cOffY = ViewportArea.Y;
1288  cOffWdt = cOffHgt = 0;
1289  if (ciViewsX * cViewWdt < ViewportArea.Wdt)
1290  {
1291  cOffX = (ViewportArea.Wdt - ciViewsX * cViewWdt) / 2;
1292  }
1293  if (iViewsH * cViewHgt < ViewportArea.Hgt)
1294  {
1295  cOffY = (ViewportArea.Hgt - iViewsH * cViewHgt) / 2 + ViewportArea.Y;
1296  }
1298  {
1299  if (cViewX < ciViewsX - 1) cOffWdt=4;
1300  if (cViewH < iViewsH - 1) cOffHgt=4;
1301  }
1302  int32_t coViewWdt = cViewWdt-cOffWdt;
1303  int32_t coViewHgt = cViewHgt-cOffHgt;
1304  C4Rect rcOut(cOffX+cViewX*cViewWdt, cOffY+cViewH*cViewHgt, coViewWdt, coViewHgt);
1305  viewport->SetOutputSize(rcOut.x,rcOut.y,rcOut.x,rcOut.y,rcOut.Wdt,rcOut.Hgt);
1306  viewport = viewport->Next;
1307  // clip down area avaiable for background drawing
1308  BackgroundAreas.ClipByRect(rcOut);
1309  }
1310  }
1311  // and finally recalculate script menus
1312  if (::Game.ScriptGuiRoot)
1313  {
1314  ::Game.ScriptGuiRoot->RequestLayoutUpdate();
1315  }
1316 }
1317 
1319 {
1320  int32_t amount = 0;
1321  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1322  {
1323  amount++;
1324  }
1325  return amount;
1326 }
1327 
1329 {
1330  for (C4Viewport *viewport = prev ? prev->Next : FirstViewport; viewport ; viewport = viewport ->Next)
1331  {
1332  if (viewport->Player == player || (player == NO_OWNER && viewport ->fIsNoOwnerViewport))
1333  {
1334  return viewport;
1335  }
1336  }
1337  return nullptr;
1338 }
1339 
1340 int32_t C4ViewportList::GetAudibility(int32_t x, int32_t y, int32_t *pan, int32_t audibility_radius, int32_t *out_player)
1341 {
1342  // default audibility radius
1343  if (!audibility_radius)
1344  {
1345  audibility_radius = C4AudibilityRadius;
1346  }
1347  // Accumulate audibility by viewports
1348  int32_t audible = 0;
1349  *pan = 0;
1350  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1351  {
1352  float distanceToCenterOfViewport = Distance(viewport->GetViewCenterX(), viewport->GetViewCenterY(), x, y);
1353  int32_t audibility = Clamp<int32_t>(100 - 100 * distanceToCenterOfViewport / C4AudibilityRadius, 0, 100);
1354  if (audibility > audible)
1355  {
1356  audible = audibility;
1357  if (out_player)
1358  {
1359  *out_player = viewport->Player;
1360  }
1361  }
1362  *pan += (x-(viewport->GetViewCenterX())) / 5;
1363  }
1364  *pan = Clamp<int32_t>(*pan, -100, 100);
1365  return audible;
1366 }
1367 
1369 {
1370 
1371  // Sort
1372  bool is_sorted;
1373  C4Player *player_a, *player_b;
1374  C4Viewport *viewport, *next, *prev;
1375  do
1376  {
1377  is_sorted = true;
1378  for (prev = nullptr, viewport = FirstViewport; viewport && (next = viewport->Next); viewport=next)
1379  {
1380  // Get players
1381  player_a = ::Players.Get(viewport->Player);
1382  player_b = ::Players.Get(next->Player);
1383  // Swap order
1384  if (player_a && player_b && player_a->ControlSet && player_b->ControlSet && ( player_a->ControlSet->GetLayoutOrder() > player_b->ControlSet->GetLayoutOrder() ))
1385  {
1386  if (prev) prev->Next = next; else FirstViewport = next;
1387  viewport->Next = next->Next;
1388  next->Next = viewport;
1389  prev = next;
1390  next = viewport;
1391  is_sorted = false;
1392  }
1393  // Don't swap
1394  else
1395  {
1396  prev = viewport;
1397  }
1398  }
1399  }
1400  while (!is_sorted);
1401 
1402 }
1403 
1405 {
1406  // safety: switch valid?
1407  if ((!Game.C4S.Head.Film || !Game.C4S.Head.Replay) && !GetViewport(NO_OWNER))
1408  {
1409  return false;
1410  }
1411  // do switch then
1412  C4Viewport *viewport = GetFirstViewport();
1413  if (!viewport)
1414  {
1415  return false;
1416  }
1417  viewport->NextPlayer();
1418  return true;
1419 }
1420 
1422 {
1423  // safety: move valid?
1424  if ((!Game.C4S.Head.Replay || !Game.C4S.Head.Film) && !GetViewport(NO_OWNER))
1425  {
1426  return false;
1427  }
1428  C4Viewport *viewport = GetFirstViewport();
1429  if (!viewport)
1430  {
1431  return false;
1432  }
1433  // move then (old static code crap...)
1434  static int32_t vp_vx = 0;
1435  static int32_t vp_vy = 0;
1436  static int32_t vp_vf = 0;
1437  int32_t dx = scroll_by.x;
1438  int32_t dy = scroll_by.y;
1439  if (Game.FrameCounter-vp_vf < 5)
1440  {
1441  dx += vp_vx;
1442  dy += vp_vy;
1443  }
1444  vp_vx = dx;
1445  vp_vy = dy;
1446  vp_vf = Game.FrameCounter;
1447  viewport->ScrollView(dx, dy);
1448  return true;
1449 }
1450 
1452 {
1453  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next) viewport->ChangeZoom(1.0f/C4GFX_ZoomStep);
1454  return true;
1455 }
1456 
1458 {
1459  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next) viewport->ChangeZoom(C4GFX_ZoomStep);
1460  return true;
1461 }
1462 
1463 void C4ViewportList::MouseMoveToViewport(int32_t button, int32_t x, int32_t y, DWORD key_param)
1464 {
1465  // Pass on to mouse controlled viewport
1466  for (C4Viewport *viewport = FirstViewport; viewport; viewport = viewport->Next)
1467  {
1468  if (::MouseControl.IsViewport(viewport))
1469  {
1470  ::MouseControl.Move( button,
1471  Clamp<int32_t>(x-viewport->OutX,0,viewport->ViewWdt-1),
1472  Clamp<int32_t>(y-viewport->OutY,0,viewport->ViewHgt-1),
1473  key_param );
1474  }
1475  }
1476 }
C4Config Config
Definition: C4Config.cpp:930
const int C4ViewportScrollBorder
Definition: C4Constants.h:65
const int C4UpperBoardHeight
Definition: C4Constants.h:59
const int NO_OWNER
Definition: C4Constants.h:137
const int32_t C4D_Foreground
Definition: C4Def.h:53
C4Draw * pDraw
Definition: C4Draw.cpp:42
C4GameMessageList Messages
C4Game Game
Definition: C4Globals.cpp:52
C4Console Console
Definition: C4Globals.cpp:45
C4Application Application
Definition: C4Globals.cpp:44
C4GameObjects Objects
Definition: C4Globals.cpp:48
C4Network2 Network
Definition: C4Globals.cpp:53
C4MouseControl MouseControl
Definition: C4Globals.cpp:47
C4FullScreen FullScreen
Definition: C4Globals.cpp:46
C4GraphicsSystem GraphicsSystem
Definition: C4Globals.cpp:51
C4GraphicsResource GraphicsResource
#define GfxR
C4GUIScreen * pGUI
Definition: C4Gui.cpp:1191
C4Landscape Landscape
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
C4PXSSystem PXS
Definition: C4PXS.cpp:423
C4ParticleSystem Particles
const int32_t C4PVM_Scrolling
Definition: C4Player.h:33
const float C4GFX_ZoomStep
C4PlayerList Players
int32_t ValidPlr(int32_t plr)
float fixtof(const C4Fixed &x)
Definition: C4Real.h:257
C4GameScriptHost GameScript
C4SoundInstance * StartSoundEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance, int32_t iPitch, C4SoundModifier *modifier)
const int32_t C4AudibilityRadius
Definition: C4SoundSystem.h:30
#define C4ST_STOP(StatName)
Definition: C4Stat.h:153
#define C4ST_STARTNEW(StatName, strName)
Definition: C4Stat.h:150
const int ACenter
Definition: C4Surface.h:41
int32_t DrawMessageOffset
C4ViewportList Viewports
uint32_t DWORD
int32_t Distance(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2)
Definition: Standard.cpp:25
T Clamp(T bval, T lbound, T rbound)
Definition: Standard.h:44
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
int32_t MouseAutoScroll
Definition: C4Config.h:234
int32_t ScrollSmooth
Definition: C4Config.h:51
int32_t SplitscreenDividers
Definition: C4Config.h:98
int32_t UpperBoard
Definition: C4Config.h:102
C4ConfigGeneral General
Definition: C4Config.h:255
C4ConfigControls Controls
Definition: C4Config.h:263
C4ConfigGraphics Graphics
Definition: C4Config.h:257
C4EditCursor EditCursor
Definition: C4Console.h:90
void SetFoW(const C4FoWRegion *fow)
Definition: C4Draw.h:193
bool NoPrimaryClipper()
Definition: C4Draw.cpp:237
void DeactivateBlitModulation()
Definition: C4Draw.h:189
void DrawBoxDw(C4Surface *sfcDest, int iX1, int iY1, int iX2, int iY2, DWORD dwClr)
Definition: C4Draw.cpp:840
virtual bool EnsureMainContextSelected()=0
void SetZoom(float X, float Y, float Zoom)
Definition: C4Draw.cpp:773
bool SetPrimaryClipper(int iX1, int iY1, int iX2, int iY2)
Definition: C4Draw.cpp:217
void ActivateBlitModulation(DWORD dwWithClr)
Definition: C4Draw.h:188
C4ScriptUniform scriptUniform
Definition: C4Draw.h:100
virtual bool PrepareRendering(C4Surface *sfcToSurface)=0
bool BlitSurfaceTile(C4Surface *sfcSurface, C4Surface *sfcTarget, float iToX, float iToY, float iToWdt, float iToHgt, float iOffsetX, float iOffsetY, C4ShaderCall *shader_call)
Definition: C4Draw.cpp:529
bool TextOut(const char *szText, CStdFont &rFont, float fZoom, C4Surface *sfcDest, float iTx, float iTy, DWORD dwFCol=0xffffffff, BYTE byForm=ALeft, bool fDoMarkup=true)
Definition: C4Draw.cpp:561
void Draw(C4TargetFacet &cgo)
void Set(C4Surface &rSfc)
Definition: C4Facet.cpp:459
C4Surface * Surface
Definition: C4Facet.h:117
float Hgt
Definition: C4Facet.h:118
float Wdt
Definition: C4Facet.h:118
void Draw(C4Facet &cgo, bool fAspect=true, int32_t iPhaseX=0, int32_t iPhaseY=0, bool fTransparent=true)
Definition: C4Facet.cpp:154
void Default()
Definition: C4Facet.cpp:31
float Y
Definition: C4Facet.h:118
float X
Definition: C4Facet.h:118
void Update(C4Rect r, const FLOAT_RECT &vp)
bool Render(const C4TargetFacet *pOnScreen=nullptr)
C4MainMenu * MainMenu
Definition: C4FullScreen.h:30
void SetPreferredDlgRect(const C4Rect &rtNewPref)
Definition: C4Gui.h:2651
void RenderMouse(C4TargetFacet &cgo)
Definition: C4Gui.cpp:739
C4Scenario C4S
Definition: C4Game.h:74
void DrawCrewOverheadText(C4TargetFacet &cgo, int32_t player_nr)
Definition: C4Game.cpp:1897
C4PathFinder PathFinder
Definition: C4Game.h:84
std::unique_ptr< C4ScriptGuiWindow > ScriptGuiRoot
Definition: C4Game.h:234
C4PlayerInfoList & PlayerInfos
Definition: C4Game.h:71
bool DropFile(const char *filename, float x, float y)
Definition: C4Game.cpp:1722
int32_t FrameCounter
Definition: C4Game.h:129
bool DebugMode
Definition: C4Game.h:145
void Draw(C4TargetFacet &gui_cgo, C4TargetFacet &cgo, int32_t iPlayer)
C4ObjectList ForeObjects
Definition: C4GameObjects.h:44
C4Value ScenPropList
Definition: C4ScriptHost.h:164
void FlashMessage(const char *message)
bool HasFoW() const
int32_t GetWidth() const
class C4Sky & GetSky()
int32_t GetHeight() const
class C4FoW * GetFoW()
void Draw(C4TargetFacet &cgo, class C4FoWRegion *pLight=nullptr)
Definition: C4Menu.h:123
void ResetLocation()
Definition: C4Menu.h:195
void Draw(C4TargetFacet &cgo) override
Definition: C4Menu.cpp:775
bool IsActive()
Definition: C4Menu.cpp:480
void Draw(C4TargetFacet &cgo, const ZoomData &GameZoom)
bool IsViewport(C4Viewport *pViewport)
void Move(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyFlags, bool fCenter=false)
bool isObserver() const
C4Network2Client * GetLocal() const
void DrawStatus(C4TargetFacet &cgo)
bool isEnabled() const
Definition: C4Network2.h:203
C4Network2ClientList Clients
Definition: C4Network2.h:116
void Draw(C4TargetFacet &cgo, int player, int MinPlane, int MaxPlane)
void DrawIfCategory(C4TargetFacet &cgo, int player, uint32_t dwCategory, bool invert)
void Draw(C4TargetFacet &cgo)
Definition: C4PXS.cpp:198
void DrawGlobalParticles(C4TargetFacet cgo)
Definition: C4Particles.h:489
void Draw(C4TargetFacet &cgo)
class C4PlayerControlAssignmentSet * ControlSet
Definition: C4Player.h:90
int32_t GetJoinIssuedPlayerCount() const
C4Player * Get(int iPlayer) const
C4Player * First
Definition: C4PlayerList.h:31
Definition: C4Rect.h:28
int32_t y
Definition: C4Rect.h:30
int32_t Hgt
Definition: C4Rect.h:30
int32_t Wdt
Definition: C4Rect.h:30
int32_t x
Definition: C4Rect.h:30
void AddRect(const C4Rect &rNewRect)
Definition: C4Rect.h:101
void ClipByRect(const C4Rect &rClip)
Definition: C4Rect.cpp:173
size_t GetCount() const
Definition: C4Rect.h:106
void Clear()
Definition: C4Rect.h:105
C4Rect & Get(size_t idx)
Definition: C4Rect.h:107
bool Replay
Definition: C4Scenario.h:72
int32_t Film
Definition: C4Scenario.h:73
C4SLandscape Landscape
Definition: C4Scenario.h:236
C4SHead Head
Definition: C4Scenario.h:232
std::unique_ptr< Popper > Push(C4PropList *proplist)
Definition: C4Shader.cpp:757
void Draw(C4TargetFacet &cgo)
Definition: C4Sky.cpp:180
float TargetY
Definition: C4Facet.h:165
float TargetX
Definition: C4Facet.h:165
float Zoom
Definition: C4Facet.h:165
void Set(const C4Facet &cpy)
Definition: C4Facet.h:182
C4PropList * getPropList() const
Definition: C4Value.h:116
float BorderTop
Definition: C4Viewport.h:39
float Zoom
Definition: C4Viewport.h:104
void ChangeZoom(float by_factor)
Definition: C4Viewport.cpp:519
float ZoomTarget
Definition: C4Viewport.h:105
C4TargetFacet last_gui_draw_cgo
Definition: C4Viewport.h:44
void CalculateZoom()
Definition: C4Viewport.cpp:481
int32_t ViewWdt
Definition: C4Viewport.h:36
void EnableFoW()
Definition: C4Viewport.cpp:834
float GetZoomByViewRange(int32_t size_x, int32_t size_y) const
Definition: C4Viewport.cpp:558
bool UpdateOutputSize(int32_t new_width=0, int32_t new_height=0)
Definition: C4Viewport.cpp:52
bool Init(int32_t for_player, bool set_temporary_only)
Definition: C4Viewport.cpp:786
int32_t ViewportOpenFrame
Definition: C4Viewport.h:107
std::unique_ptr< C4ViewportWindow > pWindow
Definition: C4Viewport.h:113
float BorderRight
Definition: C4Viewport.h:39
float GetViewY()
Definition: C4Viewport.h:78
int32_t OutY
Definition: C4Viewport.h:110
void CenterPosition()
Definition: C4Viewport.cpp:755
void SetViewX(float x)
Definition: C4Viewport.cpp:888
int32_t OutX
Definition: C4Viewport.h:110
void DrawMenu(C4TargetFacet &cgo)
Definition: C4Viewport.cpp:163
void DrawPlayerInfo(C4TargetFacet &cgo)
Definition: C4Viewport.cpp:775
int32_t ViewHgt
Definition: C4Viewport.h:37
bool ScrollBarsByViewPosition()
Definition: C4Console.cpp:710
void ScrollView(float by_x, float by_y)
Definition: C4Viewport.cpp:882
void SetZoomLimits(float to_min_zoom, float to_max_zoom)
Definition: C4Viewport.cpp:547
void DisableFoW()
Definition: C4Viewport.cpp:829
float BorderLeft
Definition: C4Viewport.h:39
void SetViewY(float y)
Definition: C4Viewport.cpp:907
void InitZoom()
Definition: C4Viewport.cpp:505
C4TargetFacet last_game_draw_cgo
Definition: C4Viewport.h:43
void DrawPlayerStartup(C4TargetFacet &cgo)
Definition: C4Viewport.cpp:848
bool ResetMenuPositions
Definition: C4Viewport.h:111
float GetGUIZoom() const
Definition: C4Viewport.h:50
void NextPlayer()
Definition: C4Viewport.cpp:962
void SetOutputSize(int32_t draw_x, int32_t draw_y, int32_t out_x, int32_t out_y, int32_t out_wdt, int32_t out_hgt)
Definition: C4Viewport.cpp:926
void AdjustZoomAndPosition()
Definition: C4Viewport.cpp:599
float ZoomLimitMax
Definition: C4Viewport.h:106
float GetViewX()
Definition: C4Viewport.h:76
bool TogglePlayerLock()
Definition: C4Console.cpp:711
void DropFile(const char *filename, float x, float y)
Definition: C4Viewport.cpp:47
std::unique_ptr< C4FoWRegion > pFoW
Definition: C4Viewport.h:114
float ZoomLimitMin
Definition: C4Viewport.h:106
bool PlayerLock
Definition: C4Viewport.h:109
int32_t DrawY
Definition: C4Viewport.h:41
void Execute()
Definition: C4Viewport.cpp:443
int32_t Player
Definition: C4Viewport.h:108
void BlitOutput()
Definition: C4Viewport.cpp:432
int32_t DrawX
Definition: C4Viewport.h:40
C4Viewport * Next
Definition: C4Viewport.h:112
void AdjustPosition(bool immediate=false)
Definition: C4Viewport.cpp:653
void Draw(C4TargetFacet &cgo, bool draw_game, bool draw_overlay)
Definition: C4Viewport.cpp:235
void DrawOverlay(C4TargetFacet &cgo, const ZoomData &GameZoom)
Definition: C4Viewport.cpp:132
bool fIsNoOwnerViewport
Definition: C4Viewport.h:46
bool IsViewportMenu(class C4Menu *menu)
Definition: C4Viewport.cpp:994
void SetZoom(float zoom_value)
Definition: C4Viewport.cpp:592
float BorderBottom
Definition: C4Viewport.h:39
void ClearPointers(C4Object *obj)
Definition: C4Viewport.cpp:957
bool FreeScroll(C4Vec2D scroll_by)
bool ViewportNextPlayer()
C4Viewport * FirstViewport
Definition: C4Viewport.h:173
int32_t GetViewportCount()
C4Viewport * GetFirstViewport()
Definition: C4Viewport.h:159
void RecalculateViewports()
C4Viewport * GetViewport(int32_t player_nr, C4Viewport *prev=nullptr)
C4RectList BackgroundAreas
Definition: C4Viewport.h:175
void DrawFullscreenBackground()
void Execute(bool DrawBackground)
bool CloseViewport(int32_t player_nr, bool silent)
bool CreateViewport(int32_t player_nr, bool silent=false)
C4Facet ViewportArea
Definition: C4Viewport.h:174
bool ViewportZoomOut()
int32_t GetAudibility(int32_t x, int32_t y, int32_t *pan, int32_t audibility_radius=0, int32_t *out_player=nullptr)
bool ViewportZoomIn()
void MouseMoveToViewport(int32_t button, int32_t x, int32_t y, DWORD key_param)
void ClearPointers(C4Object *obj)
void SortViewportsByPlayerControl()
C4Surface * pSurface
Definition: C4Window.h:275
const char * getData() const
Definition: StdBuf.h:442
int32_t GetScreenHgt()
Definition: C4Gui.h:2825
int32_t GetScreenWdt()
Definition: C4Gui.h:2824
int32_t x
Definition: C4Facet.h:42
int32_t y
Definition: C4Facet.h:42
float Zoom
Definition: C4Draw.h:70
float X
Definition: C4Draw.h:71
float Y
Definition: C4Draw.h:71