1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 
21 #include "object/auto/auto.h"
22 
23 #include "app/app.h"
24 
25 #include "common/event.h"
26 #include "common/make_unique.h"
27 
28 #include "level/robotmain.h"
29 
30 #include "level/parser/parserline.h"
31 #include "level/parser/parserparam.h"
32 
33 #include "object/old_object.h"
34 
35 #include "sound/sound.h"
36 
37 #include "ui/controls/gauge.h"
38 #include "ui/controls/interface.h"
39 #include "ui/controls/window.h"
40 
41 
42 // Object's constructor.
43 
CAuto(COldObject * object)44 CAuto::CAuto(COldObject* object)
45 {
46     m_object      = object;
47     m_engine      = Gfx::CEngine::GetInstancePointer();
48     m_main        = CRobotMain::GetInstancePointer();
49     m_eventQueue  = CApplication::GetInstancePointer()->GetEventQueue();
50     m_sound       = CApplication::GetInstancePointer()->GetSound();
51     m_particle    = m_engine->GetParticle();
52     m_terrain     = m_engine->GetTerrain();
53     m_water       = m_engine->GetWater();
54     m_cloud       = m_engine->GetCloud();
55     m_planet      = m_engine->GetPlanet();
56     m_lightning   = m_engine->GetLightning();
57     m_camera      = m_main->GetCamera();
58     m_interface   = m_main->GetInterface();
59 
60     m_type = m_object->GetType();
61     m_time = 0.0f;
62     m_lastUpdateTime = 0.0f;
63     m_bMotor = false;
64     m_progressTime = 0.0f;
65     m_progressTotal = 1.0f;
66 
67     Init();
68 }
69 
70 // Object's destructor.
71 
~CAuto()72 CAuto::~CAuto()
73 {
74     m_object      = nullptr;
75     m_engine      = nullptr;
76     m_main        = nullptr;
77     m_eventQueue  = nullptr;
78     m_sound       = nullptr;
79     m_particle    = nullptr;
80     m_terrain     = nullptr;
81     m_water       = nullptr;
82     m_cloud       = nullptr;
83     m_planet      = nullptr;
84     m_lightning   = nullptr;
85     m_camera      = nullptr;
86     m_interface   = nullptr;
87 }
88 
89 
90 // Destroys the object.
91 
DeleteObject(bool bAll)92 void CAuto::DeleteObject(bool bAll)
93 {
94 }
95 
96 
97 // Initialize the object.
98 
Init()99 void CAuto::Init()
100 {
101     m_bBusy = false;
102 }
103 
104 // Starts the object.
105 
Start(int param)106 void CAuto::Start(int param)
107 {
108 }
109 
110 // Starts an action
111 
StartAction(int param)112 Error CAuto::StartAction(int param)
113 {
114     return ERR_UNKNOWN;
115 }
116 
117 // Gete a type.
118 
SetType(ObjectType type)119 bool CAuto::SetType(ObjectType type)
120 {
121     return false;
122 }
123 
124 // Getes a value.
125 
SetValue(int rank,float value)126 bool CAuto::SetValue(int rank, float value)
127 {
128     return false;
129 }
130 
131 // Getes the string.
132 
SetString(char * string)133 bool CAuto::SetString(char *string)
134 {
135     return false;
136 }
137 
138 
139 // Management of an event.
140 
EventProcess(const Event & event)141 bool CAuto::EventProcess(const Event &event)
142 {
143     if ( event.type == EVENT_FRAME &&
144          !m_engine->GetPause() )
145     {
146         m_time += event.rTime;
147         UpdateInterface(event.rTime);
148     }
149 
150     if ( !m_object->GetSelect() )  // robot not selected?
151     {
152         return true;
153     }
154 
155     return true;
156 }
157 
158 // Indicates whether the controller has finished its activity.
159 
IsEnded()160 Error CAuto::IsEnded()
161 {
162     return ERR_CONTINUE;
163 }
164 
165 // Stops the controller
166 
Abort()167 bool CAuto::Abort()
168 {
169     return false;
170 }
171 
172 
173 // Creates all the interface when the object is selected.
174 
CreateInterface(bool bSelect)175 bool CAuto::CreateInterface(bool bSelect)
176 {
177     Ui::CWindow*    pw;
178     Math::Point     pos, dim, ddim;
179     float       ox, oy, sx, sy;
180 
181     pw = static_cast<Ui::CWindow*>(m_interface->SearchControl(EVENT_WINDOW0));
182     if ( pw != nullptr )
183     {
184         pw->Flush();  // destroys the window buttons
185         m_interface->DeleteControl(EVENT_WINDOW0);  // destroys the window
186     }
187 
188     if ( !bSelect )  return true;
189 
190     pos.x = 0.0f;
191     pos.y = 0.0f;
192     dim.x = 540.0f/640.0f;
193 //? dim.y = 70.0f/480.0f;
194     dim.y = 86.0f/480.0f;
195     m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
196     pw = static_cast<Ui::CWindow*>(m_interface->SearchControl(EVENT_WINDOW0));
197     if ( pw == nullptr )  return false;
198 
199     pos.x = 0.0f;
200     pos.y = 64.0f/480.0f;
201     ddim.x = 540.0f/640.0f;
202     ddim.y = 16.0f/480.0f;
203     pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, m_object->GetTooltipText());
204 
205     dim.x = 33.0f/640.0f;
206     dim.y = 33.0f/480.0f;
207     ox = 3.0f/640.0f;
208     oy = 3.0f/480.0f;
209     sx = 33.0f/640.0f;
210     sy = 33.0f/480.0f;
211 
212     pos.x = ox+sx*7.0f;
213     pos.y = oy+sy*0.6f;
214     ddim.x = 160.0f/640.0f;
215     ddim.y =  26.0f/480.0f;
216     pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GPROGRESS);
217 
218     if ( m_type != OBJECT_BASE   &&
219          m_type != OBJECT_SAFE   &&
220          m_type != OBJECT_HUSTON )
221     {
222         pos.x = ox+sx*2.1f;
223         pos.y = oy+sy*0;
224         ddim.x = dim.x*0.6f;
225         ddim.y = dim.y*0.6f;
226         pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_DELETE);
227     }
228 
229     pos.x = ox+sx*12.3f;
230     pos.y = oy+sy*-0.1f;
231     ddim.x = dim.x*1.0f;
232     ddim.y = dim.y*2.1f;
233     pw->CreateGroup(pos, ddim, 20, EVENT_NULL);  // solid blue background
234 
235     pos.x = ox+sx*12.3f;
236     pos.y = oy+sy*1;
237     pw->CreateGroup(pos, dim, 19, EVENT_NULL);  // sign SatCom
238 
239     pos.x = ox+sx*12.4f;
240     pos.y = oy+sy*0.5f;
241     ddim.x = dim.x*0.8f;
242     ddim.y = dim.y*0.5f;
243     pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
244     pos.y = oy+sy*0.0f;
245     pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
246 
247     pos.x = ox+sx*13.4f;
248     pos.y = oy+sy*0;
249     pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
250 
251     if ( m_object->Implements(ObjectInterfaceType::Shielded) )
252     {
253         pos.x = ox+sx*14.9f;
254         pos.y = oy+sy*0;
255         ddim.x = 14.0f/640.0f;
256         ddim.y = 66.0f/480.0f;
257         pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
258     }
259 
260     UpdateInterface();
261     m_lastUpdateTime = 0.0f;
262     UpdateInterface(0.0f);
263 
264     return true;
265 }
266 
267 // Change the state of a button interface.
268 
CheckInterface(Ui::CWindow * pw,EventType event,bool bState)269 void CAuto::CheckInterface(Ui::CWindow *pw, EventType event, bool bState)
270 {
271     Ui::CControl*   control;
272 
273     control = pw->SearchControl(event);
274     if ( control == nullptr )  return;
275 
276     control->SetState(Ui::STATE_CHECK, bState);
277 }
278 
279 // Change the state of a button interface.
280 
EnableInterface(Ui::CWindow * pw,EventType event,bool bState)281 void CAuto::EnableInterface(Ui::CWindow *pw, EventType event, bool bState)
282 {
283     Ui::CControl*   control;
284 
285     control = pw->SearchControl(event);
286     if ( control == nullptr )  return;
287 
288     control->SetState(Ui::STATE_ENABLE, bState);
289 }
290 
291 // Change the state of a button interface.
292 
VisibleInterface(Ui::CWindow * pw,EventType event,bool bState)293 void CAuto::VisibleInterface(Ui::CWindow *pw, EventType event, bool bState)
294 {
295     Ui::CControl*   control;
296 
297     control = pw->SearchControl(event);
298     if ( control == nullptr )  return;
299 
300     control->SetState(Ui::STATE_VISIBLE, bState);
301 }
302 
303 // Change the state of a button interface.
304 
DeadInterface(Ui::CWindow * pw,EventType event,bool bState)305 void CAuto::DeadInterface(Ui::CWindow *pw, EventType event, bool bState)
306 {
307     Ui::CControl*   control;
308 
309     control = pw->SearchControl(event);
310     if ( control == nullptr )  return;
311 
312     control->SetState(Ui::STATE_DEAD, !bState);
313 }
314 
315 // Change the state of a button interface.
316 
UpdateInterface()317 void CAuto::UpdateInterface()
318 {
319     Ui::CWindow*    pw;
320 
321     if ( !m_object->GetSelect() )  return;
322 
323     pw = static_cast<Ui::CWindow*>(m_interface->SearchControl(EVENT_WINDOW0));
324     if ( pw == nullptr )  return;
325 
326     VisibleInterface(pw, EVENT_OBJECT_GPROGRESS, m_bBusy);
327 }
328 
329 // Updates the state of all buttons on the interface,
330 // following the time that elapses ...
331 
UpdateInterface(float rTime)332 void CAuto::UpdateInterface(float rTime)
333 {
334     Ui::CWindow*    pw;
335     Ui::CGauge*     pg;
336 
337     if ( m_time < m_lastUpdateTime+0.1f )  return;
338     m_lastUpdateTime = m_time;
339 
340     if ( !m_object->GetSelect() )  return;
341 
342     pw = static_cast<Ui::CWindow*>(m_interface->SearchControl(EVENT_WINDOW0));
343     if ( pw == nullptr )  return;
344 
345     pg = static_cast<Ui::CGauge*>(pw->SearchControl(EVENT_OBJECT_GSHIELD));
346     if ( pg != nullptr )
347     {
348         assert(m_object->Implements(ObjectInterfaceType::Shielded));
349         pg->SetLevel(dynamic_cast<CShieldedObject*>(m_object)->GetShield());
350     }
351 
352     pg = static_cast<Ui::CGauge*>(pw->SearchControl(EVENT_OBJECT_GPROGRESS));
353     if ( pg != nullptr )
354     {
355         pg->SetLevel(m_progressTime);
356     }
357 }
358 
359 
360 // Returns an error due the state of the automation.
361 
GetError()362 Error CAuto::GetError()
363 {
364     return ERR_OK;
365 }
366 
367 
368 // Management of the occupation.
369 
GetBusy()370 bool CAuto::GetBusy()
371 {
372     return m_bBusy;
373 }
374 
SetBusy(bool busy)375 void CAuto::SetBusy(bool busy)
376 {
377     m_bBusy = busy;
378 }
379 
InitProgressTotal(float total)380 void CAuto::InitProgressTotal(float total)
381 {
382     m_progressTime = 0.0f;
383     m_progressTotal = total;
384 }
385 
EventProgress(float rTime)386 void CAuto::EventProgress(float rTime)
387 {
388     m_progressTime += rTime/m_progressTotal;
389 }
390 
391 
392 // Engine management.
393 
GetMotor()394 bool CAuto::GetMotor()
395 {
396     return m_bMotor;
397 }
398 
SetMotor(bool bMotor)399 void CAuto::SetMotor(bool bMotor)
400 {
401     m_bMotor = bMotor;
402 }
403 
404 
405 // Saves all parameters of the controller.
406 
Write(CLevelParserLine * line)407 bool CAuto::Write(CLevelParserLine* line)
408 {
409     line->AddParam("aType", MakeUnique<CLevelParserParam>(m_type));
410     line->AddParam("aBusy", MakeUnique<CLevelParserParam>(m_bBusy));
411     line->AddParam("aTime", MakeUnique<CLevelParserParam>(m_time));
412     line->AddParam("aProgressTime", MakeUnique<CLevelParserParam>(m_progressTime));
413     line->AddParam("aProgressTotal", MakeUnique<CLevelParserParam>(m_progressTotal));
414 
415     return false;
416 }
417 
418 // Return all settings to the controller.
419 
Read(CLevelParserLine * line)420 bool CAuto::Read(CLevelParserLine* line)
421 {
422     m_type = line->GetParam("aType")->AsObjectType(m_type);
423     m_bBusy = line->GetParam("aBusy")->AsBool(m_bBusy);
424     m_time = line->GetParam("aTime")->AsFloat(m_time);
425     m_progressTime = line->GetParam("aProgressTime")->AsFloat(m_progressTime);
426     m_progressTotal = line->GetParam("aProgressTotal")->AsFloat(m_progressTotal);
427 
428     return false;
429 }
430