1 /*
2   Copyright (C) 2009 Facundo Domínguez
3 
4   This file is part of Spacejunk.
5 
6   Spacejunk 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   Foobar 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.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "editorcontrol.h"
21 #include "resourcemanager.h"
22 #include "serializer.h"
23 
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <dirent.h>
27 #include <iostream>
28 #include <sstream>
29 #include <fstream>
30 #include <unistd.h>
31 #include "gcnlayouts.h"
32 #include "starship.h"
33 #include "debugmsg.h"
34 
35 #define BASECOLOR (gcn::Color(90,90,90))
36 #define BACKCOLOR (gcn::Color(120,120,120))
37 #define SELECTIONCOLOR (gcn::Color(90,90,90))
38 #define BORDERCOLOR (gcn::Color(255,255,255))
39 #define FORECOLOR BORDERCOLOR
40 
41 
action(const gcn::ActionEvent & e)42 void  EditObjectControl::action (const gcn::ActionEvent & e) {
43     action(e.getId());
44 }
45 
action(const std::string & eventId)46 void  EditObjectControl::action (const std::string& eventId) {
47     if (eventId=="setmass") {
48         if (ec->canvas.selected) {
49             char b[10];
50             double v=sldMass.getValue();
51             if (sldMass.getScaleEnd()<v) v=sldMass.getScaleEnd();
52             else if (v<sldMass.getScaleStart()) v=sldMass.getScaleStart();
53             snprintf(b,10,"%i",int(v));
54             lsetmass.setCaption(string("1e")+b);
55             ec->canvas.setMass(ec->canvas.selected,pow(10,v));
56             if (!updating && dynamic_cast<Starship*>(ec->canvas.selected))
57                 update(ec->canvas.selected);
58         }
59     } else if (eventId=="setfuelcapacity") {
60         Starship * ship=dynamic_cast<Starship*>(ec->canvas.selected);
61         if (ship) {
62             char b[10];
63             double v=sldFuelCapacity.getValue();
64             if (sldFuelCapacity.getScaleEnd()<v)
65                 v=sldFuelCapacity.getScaleEnd();
66             else if (v<sldFuelCapacity.getScaleStart())
67                 v=sldFuelCapacity.getScaleStart();
68             snprintf(b,10,"%.2f",v);
69             lsetfuelcap.setCaption(b);
70             ship->maxFuel=v;
71         }
72     } else if (eventId=="setfuel") {
73         Starship * ship=dynamic_cast<Starship*>(ec->canvas.selected);
74         if (ship) {
75             char b[10];
76             double v=sldFuel.getValue();
77             if (ship && ship->maxFuel<v)
78                 v=ship->maxFuel;
79             else if (v<sldFuel.getScaleStart())
80                 v=sldFuel.getScaleStart();
81             snprintf(b,10,"%.2f",v);
82             lsetfuel.setCaption(b);
83             ship->setFuel(v);
84             if (!updating)
85                 update(ship);
86         }
87     } else if (eventId=="setfixed") {
88         if (ec->canvas.selected) {
89             if (cbFixed.isSelected())
90                 ec->canvas.selected->flags|=PhysicBody::FIXED;
91             else
92                 ec->canvas.selected->flags&=~PhysicBody::FIXED;
93 
94             ec->canvas.level->retrace();
95             ec->canvas.level->step(0);
96         }
97     } else {
98         CHERROR<<"Warning: Do not know anything about "<<eventId<<ENDL;
99         exit(1);
100     }
101 }
102 
103 
EditObjectControl(EditorControl * ec)104 EditObjectControl::EditObjectControl(EditorControl * ec) :
105         ec(ec),l1("Mass"),lsetmass("1e000"),lsetfuelcap("00000"),lsetfuel("00000"),
106         fuelcapacity("Fuel capacity"),fuel("Fuel"),
107         sl(5,5),sldMass(0,40),sldFuelCapacity(0,1000),sldFuel(0,1000),
108         cbFixed("Fixed"), updating(false) {
109     setOpaque(false);
110     sldMass.setDimension(gcn::Rectangle(0,0,Graphic::toScreenw(70),Graphic::toScreenh(10)));
111     sldMass.setBaseColor(BASECOLOR);
112     sldFuelCapacity.setDimension(gcn::Rectangle(0,0,Graphic::toScreenw(70),Graphic::toScreenh(10)));
113     sldFuelCapacity.setBaseColor(BASECOLOR);
114     sldFuel.setDimension(gcn::Rectangle(0,0,Graphic::toScreenw(70),Graphic::toScreenh(10)));
115     sldFuel.setBaseColor(BASECOLOR);
116     sldMass.setValue(0);
117     sldMass.addKeyListener(&ec->canvas);
118     sldFuelCapacity.addKeyListener(&ec->canvas);
119     sldFuel.addKeyListener(&ec->canvas);
120     cbFixed.addKeyListener(&ec->canvas);
121 
122     sl.l=5;
123     clvl.add(&l1);
124     clvl.add(&sldMass);
125     sldMass.setActionEventId("setmass");
126     sldMass.addActionListener(this);
127     clvl.add(&lsetmass);
128     clvl.add(&cbFixed);
129     cbFixed.setActionEventId("setfixed");
130     cbFixed.addActionListener(this);
131     cbFixed.setBackgroundColor(BACKCOLOR);
132     cbFixed.setForegroundColor(FORECOLOR);
133 
134     shipcl.add(&fuelcapacity);
135     shipcl.add(&sldFuelCapacity);
136     sldFuelCapacity.setActionEventId("setfuelcapacity");
137     sldFuelCapacity.addActionListener(this);
138     shipcl.add(&lsetfuelcap);
139     shipcl.setVisible(false);
140     shipcl.fitWidgets();
141     clvl.add(&shipcl);
142     shiptrashcl.add(&fuel);
143     shiptrashcl.add(&sldFuel);
144     sldFuel.setActionEventId("setfuel");
145     sldFuel.addActionListener(this);
146     shiptrashcl.add(&lsetfuel);
147     shiptrashcl.setVisible(false);
148     shiptrashcl.fitWidgets();
149     clvl.add(&shiptrashcl);
150     sl.setContainer(&clvl);
151 
152     sl.fitWidgets();
153     setContent(&sl);
154 
155     setFrameSize(1);
156     int w=getScrollbarWidth()+sl.getWidth();
157     setWidth(Graphic::toScreenw(115<w?115:w));
158     setHeight(Graphic::toScreenh(300));
159     sl.setOpaque(false);
160     clvl.setOpaque(false);
161     shipcl.setOpaque(false);
162     shiptrashcl.setOpaque(false);
163     setBaseColor(BASECOLOR);
164 }
165 
update(GameBody * selected)166 void EditObjectControl::update(GameBody * selected) {
167     updating=true;
168     Starship * sh=dynamic_cast<Starship*>(selected);
169     if (sh) {
170         sldFuelCapacity.setValue(sh->maxFuel);
171         action(sldFuelCapacity.getActionEventId());
172         sldFuel.setValue(sh->getFuel());
173         action(sldFuel.getActionEventId());
174     }
175     shipcl.setVisible(sh);
176     shiptrashcl.setVisible(sh);
177 
178     sldMass.setValue(log10(selected->mass));
179     action(sldMass.getActionEventId());
180     cbFixed.setSelected(selected->flags & PhysicBody::FIXED);
181     updating=false;
182 };
183 
requestFocus()184 void PromptWindow::requestFocus() {
185     tb.requestFocus();
186 };
187 
PromptWindow(string * text)188 PromptWindow::PromptWindow(string * text) : text(text), btDone("Done") {
189     tb.setText(*text);
190     tb.setBackgroundColor(BACKCOLOR);
191     tb.setBaseColor(BASECOLOR);
192     tb.setForegroundColor(FORECOLOR);
193 
194     btDone.setBackgroundColor(BACKCOLOR);
195     btDone.setBaseColor(BASECOLOR);
196     btDone.setForegroundColor(FORECOLOR);
197 
198     setBackgroundColor(BACKCOLOR);
199     setBaseColor(BASECOLOR);
200     setForegroundColor(FORECOLOR);
201 
202     sa.setBackgroundColor(BACKCOLOR);
203     sa.setBaseColor(BASECOLOR);
204     sa.setForegroundColor(FORECOLOR);
205 
206     vl.setBackgroundColor(BACKCOLOR);
207     vl.setBaseColor(BASECOLOR);
208     vl.setForegroundColor(FORECOLOR);
209 
210     btDone.addActionListener(this);
211     sa.setContent(&tb);
212     sa.setWidth(Graphic::toScreenw(250));
213     sa.setHeight(Graphic::toScreenh(100));
214     vl.add(&sa);
215     vl.add(&btDone);
216     vl.fitWidgets();
217     add(&vl);
218     setWidth(vl.getWidth());
219     setHeight(vl.getHeight()+getTitleBarHeight());
220 }
action(const gcn::ActionEvent &)221 void PromptWindow::action(const gcn::ActionEvent& ) {
222     *text=tb.getText();
223     setVisible(false);
224 }
225 
refresh()226 void PromptWindow::refresh() {
227     tb.setText(*text);
228 }
229 
action(const gcn::ActionEvent & e)230 void  EditorControl::action (const gcn::ActionEvent & e) {
231     action(e.getId());
232 }
233 
action(const string & eventId)234 void  EditorControl::action (const string & eventId) {
235     if (eventId=="save") {
236         ofstream f(patht.getText().c_str());
237         f<<canvas;
238     } else if (eventId=="load") {
239         if (!exists(patht.getText())) {
240             canvas.clear();
241             return;
242         }
243         ifstream f(patht.getText().c_str());
244         f>>canvas;
245         ostringstream s;
246         s<<canvas.level->getBonusTime();
247         txtTime->setText(s.str());
248     } else if (eventId=="play") {
249         canvas.play = true;
250         canvas.initTime();
251     } else if (eventId=="delete") {
252         if (d.isSelected()) canvas.mode=Canvas::DELETE;
253     } else if (eventId=="edit") {
254         if (e.isSelected()) {
255             canvas.mode=Canvas::EDIT;
256             ctlEdit->setVisible(true);
257             ddObjects.setVisible(true);
258         } else {
259             canvas.selected=NULL;
260             ctlEdit->setVisible(false);
261             ddObjects.setVisible(false);
262         }
263     } else if (eventId=="describe") {
264         desc.setVisible(true);
265         desc.requestFocus();
266         desc.refresh();
267         moveToTop(&desc);
268     } else if (eventId=="ddObjects") {
269         canvas.selectedType=lobjects[ddObjects.getSelected()];
270     }
271 }
272 
exists(const string & f)273 bool EditorControl::exists(const string & f) {
274     return !access(f.c_str(),F_OK);
275     /*    DIR * d=opendir(".");
276         struct dirent *ep;
277         while ((ep=readdir(d)) && ep->d_name!=f);
278         closedir(d);
279         return ep;
280     */
281 }
282 
setTxtTime(EditorControl * ec,int n)283 void setTxtTime(EditorControl * ec,int n) {
284     ec->canvas.level->setBonusTime(n);
285 }
286 
287 
initializeAddButtons(int x,int y)288 void EditorControl::initializeAddButtons(int x,int y) {
289     //  const int rbCount=13;
290     lobjects.push_back("player1");
291     lobjects.push_back("asteroid1");
292     lobjects.push_back("asteroid2");
293     lobjects.push_back("asteroid3");
294     lobjects.push_back("asteroid4");
295     lobjects.push_back("moon1");
296     lobjects.push_back("moon2");
297     lobjects.push_back("moon3");
298     lobjects.push_back("moon4");
299     lobjects.push_back("planet1");
300     lobjects.push_back("planet2");
301     lobjects.push_back("planet3");
302     lobjects.push_back("planet4");
303     lobjects.push_back("planet5");
304     lobjects.push_back("planet6");
305     lobjects.push_back("planet7");
306     lobjects.push_back("planet8");
307     lobjects.push_back("planet9");
308     lobjects.push_back("star1");
309     lobjects.push_back("star2");
310     lobjects.push_back("star3");
311     lobjects.push_back("galaxia0");
312     lobjects.push_back("galaxia0grande");
313     lobjects.push_back("galaxia1");
314     lobjects.push_back("galaxia2");
315     lobjects.push_back("galaxia3");
316     lobjects.push_back("galaxia4");
317     lobjects.push_back("galaxia4chica");
318     lobjects.push_back("galaxia4grande");
319     lobjects.push_back("nebula1");
320     lobjects.push_back("nebula2");
321     lobjects.push_back("nebula3");
322     lobjects.push_back("farstar1");
323     lobjects.push_back("farstar2");
324     lobjects.push_back("farstar3");
325     lobjects.push_back("farstargroup1");
326     lobjects.push_back("farstargroup2");
327     lobjects.push_back("farstargroup3");
328     lobjects.push_back("trash1");
329     lobjects.push_back("trash2");
330     lobjects.push_back("trash3");
331     lobjects.push_back("trash4");
332     lobjects.push_back("trash5");
333     lobjects.push_back("trash6");
334     lobjects.push_back("trash7");
335     lobjects.push_back("trash8");
336     lobjects.push_back("trash9");
337 
338     ddObjects.setWidth(Graphic::toScreenw(90));
339     ddObjects.setBackgroundColor(BACKCOLOR);
340     ddObjects.setSelectionColor(SELECTIONCOLOR);
341     ddObjects.setBaseColor(BASECOLOR);
342     ddObjects.setListModel(&lobjects);
343     ddObjects.addKeyListener(&canvas);
344     ddObjects.addActionListener(this);
345     ddObjects.setActionEventId("ddObjects");
346     action("ddObjects");
347     add(&ddObjects,x,y);
348 }
349 
350 
initializeModeButtons(int x,int y)351 void EditorControl::initializeModeButtons(int x,int y) {
352     rbsMode.spacing=3;
353     txtTime->setWidth(Graphic::toScreenw(40));
354     txtTime->setHeight(Graphic::toScreenh(15));
355     txtTime->setText("300");
356     txtTime->setBackgroundColor(BACKCOLOR);
357     txtTime->setForegroundColor(FORECOLOR);
358     ltime.add(&*txtTime);
359     ltime.fitWidgets();
360     ltime.setBaseColor(BASECOLOR);
361     save.addActionListener(this);
362     save.setActionEventId("save");
363     save.setBaseColor(BASECOLOR);
364     load.addActionListener(this);
365     load.setActionEventId("load");
366     load.setBaseColor(BASECOLOR);
367     btDesc.setActionEventId("describe");
368     btDesc.setBaseColor(BASECOLOR);
369     btDesc.addActionListener(this);
370     play.setAlignment(gcn::Graphics::CENTER);
371     play.adjustSize();
372     play.setActionEventId("play");
373     play.addActionListener(this);
374     play.setBaseColor(BASECOLOR);
375     d.setActionEventId("delete");
376     d.addKeyListener(&canvas);
377     d.addActionListener(this);
378     e.setActionEventId("edit");
379     e.addKeyListener(&canvas);
380     e.addActionListener(this);
381     play.addKeyListener(&canvas);
382     save.addKeyListener(&canvas);
383     load.addKeyListener(&canvas);
384 
385     d.setBackgroundColor(BACKCOLOR);
386     d.setForegroundColor(FORECOLOR);
387     e.setBackgroundColor(BACKCOLOR);
388     e.setForegroundColor(FORECOLOR);
389 
390     rbsMode.add(&d);
391     rbsMode.add(&e);
392     rbsMode.setBackgroundColor(BASECOLOR);
393     rbsMode.setBaseColor(BORDERCOLOR);
394     bts1.add(&btDesc);
395     bts1.add(&play);
396     bts1.fitWidgets();
397     rbsMode.add(&bts1);
398     bts2.add(&save);
399     bts2.add(&load);
400     bts2.fitWidgets();
401     rbsMode.add(&bts2);
402     rbsMode.add(&patht);
403     patht.setBackgroundColor(BACKCOLOR);
404     patht.setForegroundColor(FORECOLOR);
405     rbsMode.add(&ltime);
406     rbsMode.fitWidgets();
407     rbsMode.setFrameSize(1);
408     rbsMode.setX(x);
409     rbsMode.setY(y);
410     rbsMode.setOpaque(false);
411 }
412 
initializeEditButtons(int x,int y)413 void EditorControl::initializeEditButtons(int x,int y) {
414     ctlEdit=new EditObjectControl(this);
415     ctlEdit->setX(x);
416     ctlEdit->setY(y);
417 }
418 
EditorControl()419 EditorControl::EditorControl():
420         SpacingLayout(5,5,5,5),
421         d("Delete","mode"),
422         e("Edit","mode"),play("Play"),btDesc("Describe"),save("Save"),load("Load"),
423         patht("unamedlevel"), txtTime(numTextField(this,setTxtTime)),
424         ltime("Btime: "),
425         canvas(this), desc(&canvas.level->description) { //, backgroundFill(*(new gcn::Container()))
426     setBaseColor(BASECOLOR);
427 
428     desc.setCaption("Brief level description");
429     add(&desc,Graphic::toScreenw(50),Graphic::toScreenh(50));
430     desc.setVisible(false);
431     setOpaque(false);
432 
433     setDimension(gcn::Rectangle(Graphic::toScreenx(0), Graphic::toScreeny(0),
434                                 Graphic::toScreenw(LOGICAL_WIDTH), Graphic::toScreenh(LOGICAL_HEIGHT)));
435 
436     canvas.setBaseColor(gcn::Color(0,0,0));
437     canvas.setDimension(gcn::Rectangle(0,0,Graphic::toScreenw(LOGICAL_WIDTH), Graphic::toScreenh(LOGICAL_HEIGHT)));
438     //  canvas.setDimension(gcn::Rectangle(125, 10, 510, 465));
439     add(&canvas);
440 
441     addKeyListener(&canvas);
442 
443     initializeModeButtons(Graphic::toScreenw(5),Graphic::toScreenh(10));
444     initializeAddButtons(Graphic::toScreenw(5),rbsMode.getHeight()+rbsMode.getY()+Graphic::toScreenh(5));
445     initializeEditButtons(Graphic::toScreenw(5),rbsMode.getHeight()+rbsMode.getY()+Graphic::toScreenh(5)+ddObjects.getHeight());
446 
447     add(&rbsMode);
448     add(ctlEdit);
449 
450     e.setSelected(true),
451     setFocusable(true);
452 }
453 
~EditorControl()454 EditorControl::~EditorControl() {
455 };
456