1 /* Copyright (C) 2017 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "precompiled.h"
19 
20 #include <sstream>
21 #include <string>
22 
23 #include "graphics/CinemaManager.h"
24 
25 #include "graphics/Camera.h"
26 #include "graphics/GameView.h"
27 #include "gui/CGUI.h"
28 #include "gui/GUIutil.h"
29 #include "gui/GUIManager.h"
30 #include "gui/IGUIObject.h"
31 #include "lib/ogl.h"
32 #include "maths/MathUtil.h"
33 #include "maths/Quaternion.h"
34 #include "maths/Vector3D.h"
35 #include "maths/Vector4D.h"
36 #include "ps/CLogger.h"
37 #include "ps/ConfigDB.h"
38 #include "ps/CStr.h"
39 #include "ps/Game.h"
40 #include "ps/GameSetup/Config.h"
41 #include "ps/Hotkey.h"
42 #include "ps/World.h"
43 #include "simulation2/components/ICmpCinemaManager.h"
44 #include "simulation2/components/ICmpOverlayRenderer.h"
45 #include "simulation2/components/ICmpRangeManager.h"
46 #include "simulation2/components/ICmpSelectable.h"
47 #include "simulation2/components/ICmpTerritoryManager.h"
48 #include "simulation2/MessageTypes.h"
49 #include "simulation2/system/ComponentManager.h"
50 #include "simulation2/Simulation2.h"
51 #include "renderer/Renderer.h"
52 
53 
CCinemaManager()54 CCinemaManager::CCinemaManager()
55 	: m_DrawPaths(false)
56 {
57 }
58 
Update(const float deltaRealTime) const59 void CCinemaManager::Update(const float deltaRealTime) const
60 {
61 	CmpPtr<ICmpCinemaManager> cmpCinemaManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity());
62 	if (!cmpCinemaManager)
63 		return;
64 
65 	if (IsPlaying())
66 		cmpCinemaManager->PlayQueue(deltaRealTime, g_Game->GetView()->GetCamera());
67 }
68 
Render() const69 void CCinemaManager::Render() const
70 {
71 	if (IsEnabled())
72 		DrawBars();
73 	else if (m_DrawPaths)
74 		DrawPaths();
75 }
76 
DrawPaths() const77 void CCinemaManager::DrawPaths() const
78 {
79 	CmpPtr<ICmpCinemaManager> cmpCinemaManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity());
80 	if (!cmpCinemaManager)
81 		return;
82 
83 	for (const std::pair<CStrW, CCinemaPath>& p : cmpCinemaManager->GetPaths())
84 	{
85 		DrawSpline(p.second, CColor(0.2f, 0.2f, 1.f, 0.9f), 128, true);
86 		DrawNodes(p.second, CColor(0.1f, 1.f, 0.f, 1.f));
87 
88 		if (p.second.GetTargetSpline().GetAllNodes().empty())
89 			continue;
90 
91 		DrawSpline(p.second.GetTargetSpline(), CColor(1.f, 0.3f, 0.4f, 0.9f), 128, true);
92 		DrawNodes(p.second.GetTargetSpline(), CColor(1.f, 0.1f, 0.f, 1.f));
93 	}
94 }
95 
DrawSpline(const RNSpline & spline,const CColor & splineColor,int smoothness,bool lines) const96 void CCinemaManager::DrawSpline(const RNSpline& spline, const CColor& splineColor, int smoothness, bool lines) const
97 {
98 	if (spline.GetAllNodes().size() < 2)
99 		return;
100 	if (spline.GetAllNodes().size() == 2 && lines)
101 		smoothness = 2;
102 
103 	float start = spline.MaxDistance.ToFloat() / smoothness;
104 	float time = 0;
105 
106 #if CONFIG2_GLES
107 	#warning TODO : implement CCinemaPath on GLES
108 #else
109 
110 	glDisable(GL_DEPTH_TEST);
111 	glEnable(GL_BLEND);
112 	glColor4f(splineColor.r, splineColor.g, splineColor.b, splineColor.a);
113 	if (lines)
114 	{
115 		glLineWidth(1.8f);
116 		glEnable(GL_LINE_SMOOTH);
117 		glBegin(GL_LINE_STRIP);
118 		for (int i = 0; i <= smoothness; ++i)
119 		{
120 			time = start * i / spline.MaxDistance.ToFloat();
121 			CVector3D tmp = spline.GetPosition(time);
122 			glVertex3f(tmp.X, tmp.Y, tmp.Z);
123 		}
124 		glEnd();
125 
126 		// Height indicator
127 		if (g_Game && g_Game->GetWorld() && g_Game->GetWorld()->GetTerrain())
128 		{
129 			glLineWidth(1.1f);
130 			glBegin(GL_LINES);
131 			for (int i = 0; i <= smoothness; ++i)
132 			{
133 				time = start * i / spline.MaxDistance.ToFloat();
134 				CVector3D tmp = spline.GetPosition(time);
135 				float groundY = g_Game->GetWorld()->GetTerrain()->GetExactGroundLevel(tmp.X, tmp.Z);
136 				glVertex3f(tmp.X, tmp.Y, tmp.Z);
137 				glVertex3f(tmp.X, groundY, tmp.Z);
138 			}
139 			glEnd();
140 		}
141 
142 		glDisable(GL_LINE_SMOOTH);
143 		glLineWidth(1.0f);
144 	}
145 	else
146 	{
147 		smoothness /= 2;
148 		start = spline.MaxDistance.ToFloat() / smoothness;
149 		glEnable(GL_POINT_SMOOTH);
150 		glPointSize(3.0f);
151 		glBegin(GL_POINTS);
152 		for (int i = 0; i <= smoothness; ++i)
153 		{
154 			time = start * i / spline.MaxDistance.ToFloat();
155 			CVector3D tmp = spline.GetPosition(time);
156 			glVertex3f(tmp.X, tmp.Y, tmp.Z);
157 		}
158 		glEnd();
159 		glPointSize(1.0f);
160 		glDisable(GL_POINT_SMOOTH);
161 	}
162 	glDisable(GL_BLEND);
163 	glEnable(GL_DEPTH_TEST);
164 
165 #endif
166 }
167 
DrawNodes(const RNSpline & spline,const CColor & nodeColor) const168 void CCinemaManager::DrawNodes(const RNSpline& spline, const CColor& nodeColor) const
169 {
170 #if CONFIG2_GLES
171 	#warning TODO : implement CCinemaPath on GLES
172 #else
173 
174 	glDisable(GL_DEPTH_TEST);
175 	glEnable(GL_POINT_SMOOTH);
176 	glPointSize(7.0f);
177 	glColor4f(nodeColor.r, nodeColor.g, nodeColor.b, nodeColor.a);
178 	glBegin(GL_POINTS);
179 
180 	for (const SplineData& node : spline.GetAllNodes())
181 		glVertex3f(node.Position.X.ToFloat(), node.Position.Y.ToFloat(), node.Position.Z.ToFloat());
182 
183 	glEnd();
184 	glPointSize(1.0f);
185 	glDisable(GL_POINT_SMOOTH);
186 	glEnable(GL_DEPTH_TEST);
187 #endif
188 }
189 
DrawBars() const190 void CCinemaManager::DrawBars() const
191 {
192 	int height = (float)g_xres / 2.39f;
193 	int shift = (g_yres - height) / 2;
194 	if (shift <= 0)
195 		return;
196 
197 #if CONFIG2_GLES
198 	#warning TODO : implement bars for GLES
199 #else
200 	// Set up transform for GL bars
201 	glMatrixMode(GL_PROJECTION);
202 	glPushMatrix();
203 	glLoadIdentity();
204 	glMatrixMode(GL_MODELVIEW);
205 	glPushMatrix();
206 	glLoadIdentity();
207 	CMatrix3D transform;
208 	transform.SetOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);
209 	glLoadMatrixf(&transform._11);
210 
211 	glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
212 
213 	glEnable(GL_BLEND);
214 	glDisable(GL_DEPTH_TEST);
215 
216 	glBegin(GL_QUADS);
217 	glVertex2i(0, 0);
218 	glVertex2i(g_xres, 0);
219 	glVertex2i(g_xres, shift);
220 	glVertex2i(0, shift);
221 	glEnd();
222 
223 	glBegin(GL_QUADS);
224 	glVertex2i(0, g_yres - shift);
225 	glVertex2i(g_xres, g_yres - shift);
226 	glVertex2i(g_xres, g_yres);
227 	glVertex2i(0, g_yres);
228 	glEnd();
229 
230 	glDisable(GL_BLEND);
231 	glEnable(GL_DEPTH_TEST);
232 
233 	// Restore transform
234 	glMatrixMode(GL_PROJECTION);
235 	glPopMatrix();
236 	glMatrixMode(GL_MODELVIEW);
237 	glPopMatrix();
238 #endif
239 }
240 
IsEnabled() const241 bool CCinemaManager::IsEnabled() const
242 {
243 	CmpPtr<ICmpCinemaManager> cmpCinemaManager(g_Game->GetSimulation2()->GetSimContext().GetSystemEntity());
244 	return cmpCinemaManager && cmpCinemaManager->IsEnabled();
245 }
246 
IsPlaying() const247 bool CCinemaManager::IsPlaying() const
248 {
249 	return IsEnabled() && g_Game && !g_Game->m_Paused;
250 }
251 
GetPathsDrawing() const252 bool CCinemaManager::GetPathsDrawing() const
253 {
254 	return m_DrawPaths;
255 }
256 
SetPathsDrawing(const bool drawPath)257 void CCinemaManager::SetPathsDrawing(const bool drawPath)
258 {
259 	m_DrawPaths = drawPath;
260 }
261