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 #ifndef INC_C4Viewport
21 #define INC_C4Viewport
22 
23 #include "graphics/C4FacetEx.h"
24 
25 class C4ViewportWindow;
26 class C4FoWRegion;
27 struct ZoomData;
28 
29 class C4Viewport
30 {
31 	friend class C4MouseControl;
32 public:
33 	C4Viewport();
34 	~C4Viewport();
35 	// "display" coordinates
36 	int32_t ViewWdt,ViewHgt;
37 	// position of landscape border (left,top,right, bottom) in viewport. 0 if there is not border
38 	float BorderLeft, BorderTop, BorderRight, BorderBottom;
39 	int32_t DrawX,DrawY;
40 	// facets used for last drawing operations
41 	C4TargetFacet last_game_draw_cgo, last_gui_draw_cgo;
42 	// factor between "landscape" and "display"
43 	bool fIsNoOwnerViewport; // this viewport is found for searches of NO_OWNER-viewports; even if it has a player assigned (for network obs)
44 
GetZoom()45 	float GetZoom() { return Zoom; }
46 	void SetZoom(float zoomValue);
GetGUIZoom()47 	float GetGUIZoom() const { return Clamp<float>(float(ViewWdt)/1280,0.5f,1.0f); }
48 	void Execute();
49 	void ClearPointers(C4Object *pObj);
50 	void SetOutputSize(int32_t iDrawX, int32_t iDrawY, int32_t iOutX, int32_t iOutY, int32_t iOutWdt, int32_t iOutHgt);
51 	void CalculateZoom();
52 	void ChangeZoom(float by_factor);
53 	void SetZoom(float to_zoom, bool direct=false);
54 	void SetZoomLimits(float to_min_zoom, float to_max_zoom);
55 	float GetZoomByViewRange(int32_t size_x, int32_t size_y) const; // set zoom such that the supplied size is visible in the viewport
GetZoomLimitMin()56 	float GetZoomLimitMin() const { return ZoomLimitMin; }
GetZoomLimitMax()57 	float GetZoomLimitMax() const { return ZoomLimitMax; }
GetZoomTarget()58 	float GetZoomTarget() const { return ZoomTarget; }
59 	bool Init(int32_t iPlayer, bool fSetTempOnly);
60 	void DropFile(const char* fileName, float x, float y);
61 	bool TogglePlayerLock();
GetPlayerLock()62 	bool GetPlayerLock() { return PlayerLock; }
63 	void NextPlayer();
GetOutputRect()64 	C4Rect GetOutputRect() { return C4Rect(OutX, OutY, ViewWdt, ViewHgt); }
65 	bool IsViewportMenu(class C4Menu *pMenu);
GetNext()66 	C4Viewport *GetNext() { return Next; }
GetPlayer()67 	int32_t GetPlayer() { return Player; }
68 	void CenterPosition();
69 	void DisableFoW();
70 	void EnableFoW();
71 public:
72 	/** Return x-position of upper left corner of viewport in landscape coordinates */
GetViewX()73 	float GetViewX() { return viewX; }
74 	/** Return y-position of upper left corner of viewport in landscape coordinates */
GetViewY()75 	float GetViewY() { return viewY; }
76 	/** Return x-position of the center of viewport in landscape coordinates */
GetViewCenterX()77 	float GetViewCenterX() { return viewX + ViewWdt/Zoom/2; }
78 	/** Return y-position of the center of viewport in landscape coordinates */
GetViewCenterY()79 	float GetViewCenterY() { return viewY + ViewHgt/Zoom/2; }
80 
81 	// Convert window coordinates to game coordinates
WindowToGameX(int32_t win_x)82 	float WindowToGameX(int32_t win_x) { return GetViewX() + float(win_x) / Zoom; }
WindowToGameY(int32_t win_y)83 	float WindowToGameY(int32_t win_y) { return GetViewY() + float(win_y) / Zoom; }
84 
85 	/** Scroll the viewport by x,y */
86 	void ScrollView(float byX, float byY);
87 	/** Set the view position. */
88 	void SetViewX(float x);
89 	void SetViewY(float y);
90 	/** Set the view offset of the normal viewport center. Used by C4Script function SetViewOffset. */
SetViewOffset(int32_t x,int32_t y)91 	void SetViewOffset(int32_t x, int32_t y) { viewOffsX = x; viewOffsY = y; }
92 
93 private:
94 	float viewX,viewY;	// current view position in landscape coordinates (upper left corner)
95 	float targetViewX, targetViewY; // target view position for smooth scrolling
96 	int32_t viewOffsX, viewOffsY;	// desired view offset in landscape coordinates
97 
98 	void UpdateBordersX();
99 	void UpdateBordersY();
100 protected:
101 	float Zoom;
102 	float ZoomTarget;
103 	float ZoomLimitMin,ZoomLimitMax;
104 	int32_t ViewportOpenFrame; // Game FrameCounter in which viewport was opened. Used to init zoom during initial fullscreen viewport movement chaos, but not change it later e.g. when other local players join.
105 	int32_t Player;
106 	bool PlayerLock;
107 	int32_t OutX,OutY;
108 	bool ResetMenuPositions;
109 	C4Viewport *Next;
110 	std::unique_ptr<C4ViewportWindow> pWindow;
111 	std::unique_ptr<C4FoWRegion> pFoW;
112 	void DrawPlayerStartup(C4TargetFacet &cgo);
113 	void Draw(C4TargetFacet &cgo, bool fDrawGame, bool fDrawOverlay);
114 	void DrawOverlay(C4TargetFacet &cgo, const ZoomData &GameZoom);
115 	void DrawMenu(C4TargetFacet &cgo);
116 	void DrawPlayerInfo(C4TargetFacet &cgo);
117 	void InitZoom();
118 	void BlitOutput();
119 	void AdjustZoomAndPosition();
120 public:
GetZoom()121 	float GetZoom() const { return Zoom; }
122 	void AdjustPosition(bool immediate = false);
GetWindow()123 	C4ViewportWindow* GetWindow() {return pWindow.get();}
124 	bool UpdateOutputSize(int32_t new_width=0, int32_t new_height=0);
125 	bool ViewPositionByScrollBars();
126 	bool ScrollBarsByViewPosition();
127 
128 #ifdef WITH_QT_EDITOR
129 	class C4ConsoleQtViewportScrollArea *scrollarea;
130 #endif
131 
132 #ifdef _WIN32
133 	friend LRESULT APIENTRY ViewportWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
134 #endif
135 	friend class C4ViewportWindow;
136 	friend class C4ViewportList;
137 	friend class C4GraphicsSystem;
138 	friend class C4ConsoleQtViewportView;
139 };
140 
141 class C4ViewportList {
142 public:
143 	C4ViewportList();
144 	~C4ViewportList();
145 	void Clear();
146 	void ClearPointers(C4Object *pObj);
147 	void Execute(bool DrawBackground);
148 	void SortViewportsByPlayerControl();
149 	void RecalculateViewports();
150 	void DisableFoW();
151 	void EnableFoW();
152 	bool CreateViewport(int32_t iPlayer, bool fSilent=false);
153 	bool CloseViewport(int32_t iPlayer, bool fSilent);
154 	int32_t GetViewportCount();
155 	C4Viewport* GetViewport(int32_t iPlayer, C4Viewport* pPrev = nullptr);
GetFirstViewport()156 	C4Viewport* GetFirstViewport() { return FirstViewport; }
157 	bool CloseViewport(C4Viewport * cvp);
158 #ifdef USE_WIN32_WINDOWS
159 	C4Viewport* GetViewport(HWND hwnd);
160 #endif
161 	int32_t GetAudibility(int32_t iX, int32_t iY, int32_t *iPan, int32_t iAudibilityRadius = 0, int32_t *outPlayer = nullptr);
162 	bool ViewportNextPlayer();
163 
164 	bool FreeScroll(C4Vec2D vScrollBy); // key callback: Scroll ownerless viewport by some offset
165 	bool ViewportZoomOut();
166 	bool ViewportZoomIn();
167 protected:
168 	void MouseMoveToViewport(int32_t iButton, int32_t iX, int32_t iY, DWORD dwKeyParam);
169 	void DrawFullscreenBackground();
170 	C4Viewport *FirstViewport{nullptr};
171 	C4Facet ViewportArea;
172 	C4RectList BackgroundAreas; // rectangles covering background without viewports in fullscreen
173 	friend class C4GUI::Screen;
174 	friend class C4GraphicsSystem;
175 };
176 
177 extern C4ViewportList Viewports;
178 
179 #endif
180