naev 0.11.5
dev_mapedit.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include "physfs.h"
11#include "SDL.h"
12
13#include "naev.h"
16#include "dev_mapedit.h"
17
18#include "conf.h"
19#include "array.h"
20#include "commodity.h"
21#include "dev_spob.h"
22#include "dev_uniedit.h"
23#include "dev_sysedit.h"
24#include "dev_system.h"
25#include "dialogue.h"
26#include "load.h"
27#include "map.h"
28#include "mapData.h"
29#include "ndata.h"
30#include "nfile.h"
31#include "nstring.h"
32#include "opengl.h"
33#include "outfit.h"
34#include "pause.h"
35#include "space.h"
36#include "tk/toolkit_priv.h"
37#include "toolkit.h"
38#include "unidiff.h"
39
40extern StarSystem *systems_stack;
41
42#define BUTTON_WIDTH 80
43#define BUTTON_HEIGHT 30
45#define MAPEDIT_EDIT_WIDTH 400
46#define MAPEDIT_EDIT_HEIGHT 450
48#define MAPEDIT_DRAG_THRESHOLD 300
49#define MAPEDIT_MOVE_THRESHOLD 10
51#define MAPEDIT_ZOOM_STEP 1.2
52#define MAPEDIT_ZOOM_MAX 5
53#define MAPEDIT_ZOOM_MIN -5
55#define MAPEDIT_OPEN_WIDTH 800
56#define MAPEDIT_OPEN_HEIGHT 500
57#define MAPEDIT_OPEN_TXT_WIDTH 300
59#define MAPEDIT_SAVE_WIDTH 800
60#define MAPEDIT_SAVE_HEIGHT 500
61#define MAPEDIT_SAVE_TXT_WIDTH 300
63typedef struct mapOutfitsList_s {
64 char *fileName;
65 char *mapName;
66 char *description;
67 char *gfx_store;
68 int numSystems;
69 credits_t price;
70 int rarity;
72
73static mapOutfitsList_t *mapList = NULL; /* Array of map outfits for displaying in the Open window. */
74
75static unsigned int mapedit_wid = 0;
76static double mapedit_xpos = 0.;
77static double mapedit_ypos = 0.;
78static double mapedit_zoom = 1.;
79static int mapedit_moved = 0;
80static unsigned int mapedit_dragTime = 0;
81static int mapedit_drag = 0;
82static StarSystem **mapedit_sys = NULL;
84static int mapedit_tadd = 0;
85static int mapedit_nsys = 0;
86static int mapedit_msys = 0;
87static double mapedit_mx = 0.;
88static double mapedit_my = 0.;
89static unsigned int mapedit_widLoad = 0;
90static char *mapedit_sLoadMapName = NULL;
91static int mapedit_nospob = 0;
92static int mapedit_hidden = 0;
94/*
95 * Universe editor Prototypes.
96 */
97/* Selection. */
98static void mapedit_deselect (void);
99static void mapedit_selectAdd( StarSystem *sys );
100static void mapedit_selectRm( StarSystem *sys );
101/* Custom system editor widget. */
102static void mapedit_buttonZoom( unsigned int wid, const char* str );
103static void mapedit_render( double bx, double by, double w, double h, void *data );
104static void mapedit_focusLose( unsigned int wid, const char* wgtname );
105static int mapedit_mouse( unsigned int wid, const SDL_Event* event, double mx, double my,
106 double w, double h, double xr, double yr, void *data );
107/* Button functions. */
108static void mapedit_close( unsigned int wid, const char *wgt );
109static void mapedit_btnOpen( unsigned int wid_unused, const char *unused );
110static void mapedit_btnSaveMapAs( unsigned int wid_unused, const char *unused );
111static void mapedit_clear( unsigned int wid_unused, const char *unused );
112static void mapedit_chkSpob( unsigned int wid, const char *wgtname );
113static void mapedit_chkHidden( unsigned int wid, const char *wgtname );
114/* Keybindings handling. */
115static int mapedit_keys( unsigned int wid, SDL_Keycode key, SDL_Keymod mod, int isrepeat );
116/* Loading of Map files. */
117static void mapedit_loadMapMenu_open (void);
118static void mapedit_loadMapMenu_close( unsigned int wdw, const char *str );
119static void mapedit_loadMapMenu_update( unsigned int wdw, const char *str );
120static void mapedit_loadMapMenu_load( unsigned int wdw, const char *str );
121/* Saving of Map files. */
122static int mapedit_saveMap( StarSystem** uniedit_sys, mapOutfitsList_t* ns );
123/* Management of last loaded/saved Map file. */
125/* Management of Map files list. */
126static int mapedit_mapsList_refresh (void);
127static void mapsList_free (void);
128
132void mapedit_open( unsigned int wid_unused, const char *unused )
133{
134 (void) wid_unused;
135 (void) unused;
136 unsigned int wid;
137 int buttonHPos = 0;
138 int buttonVPos = 1;
139 int textPos = 0;
140 int linesPos = 0;
141 int curLines = 0;
142 int lineHeight = gl_smallFont.h + 5;
143 int parHeight = 10;
144
145 /* Pause. */
146 pause_game();
147
148 /* Must have no diffs applied. */
149 diff_clear();
150
151 /* Reset some variables. */
152 mapedit_drag = 0;
153 mapedit_tadd = 0;
154 mapedit_zoom = 1.;
155 mapedit_xpos = 0.;
156 mapedit_ypos = 0.;
157
158 /* Create the window. */
159 wid = window_create( "wdwMapOutfitEditor", _("Map Outfit Editor"), -1, -1, -1, -1 );
161 mapedit_wid = wid;
162
163 /* Actual viewport. */
164 window_addCust( wid, 20, -40, SCREEN_W - 350, SCREEN_H - 100,
165 "cstSysEdit", 1, mapedit_render, mapedit_mouse, NULL, mapedit_focusLose, NULL );
166
167 /* Button : reset the current map. */
168 buttonHPos = 2;
169 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
170 "btnClear", _("Reset"), mapedit_clear, SDLK_r );
171 buttonHPos--;
172
173 /* Button : open map file. */
174 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
175 "btnOpen", _("Open"), mapedit_btnOpen, SDLK_o );
176 buttonHPos--;
177
178 /* Button : save current map to file. */
179 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
180 "btnSaveAs", _("Save"), mapedit_btnSaveMapAs, SDLK_s );
181 buttonHPos = 0;
182 buttonVPos--;
183
184 /* Button : exit editor. */
185 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
186 "btnClose", _("Exit"), mapedit_close, SDLK_x );
187
188 /* Filename. */
189 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, lineHeight, 0, "txtSFileName",
190 &gl_smallFont, NULL, _("File Name:") );
191 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpFileName",
192 1024, 1, &gl_smallFont );
193 textPos++;
194 linesPos++;
195
196 /* Map name. */
197 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, lineHeight, 0, "txtSMapName",
198 &gl_smallFont, NULL, _("Map Name:") );
199 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpMapName",
200 1024, 1, &gl_smallFont );
201 textPos++;
202 linesPos++;
203
204 /* Map description. */
205 curLines = 7;
206 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, lineHeight, 0, "txtSDescription",
207 &gl_smallFont, NULL, _("Description:") );
208 window_addInput( wid, -20, -40-textPos*parHeight-(linesPos+1)*lineHeight, 300-20, curLines*lineHeight, "inpDescription",
209 32768, 0, &gl_smallFont );
210 textPos++;
211 linesPos+=(curLines+1);
212
213 /* Current Map # of systems. */
214 curLines = 1;
215 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, 20, 0, "txtSCurrentNumSystems",
216 &gl_smallFont, NULL, _("Number of Systems (up to 100):") );
217 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 60, curLines*lineHeight, 0, "txtCurrentNumSystems",
218 &gl_smallFont, NULL, "N/A" );
219 textPos++;
220 linesPos++;
221
222 /* Presence. */
223 curLines = 5;
224 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, 20, 0, "txtSPresence",
225 &gl_smallFont, NULL, _("Presence:") );
226 window_addText( wid, -20, -40-textPos*parHeight-(linesPos+1)*lineHeight, 300-20, curLines*lineHeight, 0, "txtPresence",
227 &gl_smallFont, NULL, _("No selection") );
228 textPos++;
229 linesPos+=curLines+1;
230
231 /* Outift attributes. */
232 curLines = 1;
233 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, 20, 0, "txtSPrice",
234 &gl_smallFont, NULL, _("Price:") );
235 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpPrice",
236 64, 1, &gl_smallFont );
237 window_setInputFilter( wid, "inpPrice", INPUT_FILTER_NUMBER );
238 textPos++;
239 linesPos+=curLines;
240
241 curLines = 1;
242 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, 20, 0, "txtSGFX",
243 &gl_smallFont, NULL, _("Graphics:") );
244 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpGFX",
245 64, 1, &gl_smallFont );
246 textPos++;
247 linesPos+=curLines;
248
249 curLines = 1;
250 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, 20, 0, "txtSRarity",
251 &gl_smallFont, NULL, _("Rarity:") );
252 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpRarity",
253 64, 1, &gl_smallFont );
254 window_setInputFilter( wid, "inpRarity", INPUT_FILTER_NUMBER );
255 textPos++;
256 linesPos+=curLines+1;
257
258 curLines = 1;
259 mapedit_nospob = 0;
260 window_addCheckbox( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "chkSpob", _("Ignore Spobs"), mapedit_chkSpob, mapedit_nospob );
261 textPos++;
262 linesPos+=curLines+1;
263
264 curLines = 1;
265 mapedit_nospob = 0;
266 window_addCheckbox( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "chkHidden", _("Set Hidden Jumps"), mapedit_chkHidden, mapedit_nospob );
267 textPos++;
268 linesPos+=curLines+1;
269
270 curLines = 4;
271 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, curLines*lineHeight, 0, "txtSWarning",
272 &gl_smallFont, NULL,
273 _("Warning: Editor can't (yet) manage which details are mapped within a system. Review its changes before committing.") );
274 textPos++;
275 linesPos+=curLines+1;
276
277 /* Zoom buttons */
278 window_addButtonKey( wid, 40, 20, 30, 30, "btnZoomIn", "+", mapedit_buttonZoom, SDLK_EQUALS );
279 window_addButtonKey( wid, 80, 20, 30, 30, "btnZoomOut", "-", mapedit_buttonZoom, SDLK_MINUS );
280
281 /* Selected text. */
282 window_addText( wid, 140, 10, SCREEN_W - 350 - 30 - 30 - BUTTON_WIDTH - 20, 30, 0,
283 "txtSelected", &gl_smallFont, NULL, NULL );
284
285 /* Deselect everything. */
287}
288
292static int mapedit_keys( unsigned int wid, SDL_Keycode key, SDL_Keymod mod, int isrepeat )
293{
294 (void) mod;
295 (void) isrepeat;
296
297 switch (key) {
298 /* Mode changes. */
299 case SDLK_ESCAPE:
300 mapedit_close(wid, "Close");
301 return 1;
302
303 default:
304 return 0;
305 }
306}
307
311static void mapedit_close( unsigned int wid, const char *wgt )
312{
313 /* Frees some memory. */
316
317 /* Reconstruct jumps. */
319
320 /* Unpause. */
321 unpause_game();
322
323 /* Close the window. */
324 window_close( wid, wgt );
325}
326
330static void mapedit_clear( unsigned int wid, const char *unused )
331{
332 (void) wid;
333 (void) unused;
334
335 /* Clear the map. */
337}
338
339static void mapedit_chkSpob( unsigned int wid, const char *wgtname )
340{
341 mapedit_nospob = window_checkboxState( wid, wgtname );
342}
343
344static void mapedit_chkHidden( unsigned int wid, const char *wgtname )
345{
346 mapedit_hidden = window_checkboxState( wid, wgtname );
347}
348
352static void mapedit_btnOpen( unsigned int wid_unused, const char *unused )
353{
354 (void) wid_unused;
355 (void) unused;
356
358
359}
360
364static void mapedit_render( double bx, double by, double w, double h, void *data )
365{
366 (void) data;
367 double x, y, r;
368
369 /* Parameters. */
370 map_renderParams( bx, by, mapedit_xpos, mapedit_ypos, w, h, mapedit_zoom, &x, &y, &r );
371
372 uniedit_renderMap( bx, by, w, h, x, y, mapedit_zoom, r );
373
374 /* Render the selected system selections. */
375 for (int i=0; i<mapedit_nsys; i++) {
376 StarSystem *sys = mapedit_sys[i];
377 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
378 1.8*r, &cRed, 0 );
379 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
380 2.0*r, &cRed, 0 );
381 }
382
383 /* Render last clicked system */
385 StarSystem *sys = system_getIndex( mapedit_iLastClickedSystem );
386 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
387 2.4*r, &cBlue, 0 );
388 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
389 2.6*r, &cBlue, 0 );
390 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
391 2.8*r, &cBlue, 0 );
392 }
393}
394
398static void mapedit_focusLose( unsigned int wid, const char* wgtname )
399{
400 (void) wid;
401 (void) wgtname;
402 mapedit_drag = 0;
403}
404
408static int mapedit_mouse( unsigned int wid, const SDL_Event* event, double mx, double my,
409 double w, double h, double xr, double yr, void *data )
410{
411 (void) data;
412 const double t = 15.*15.; /* threshold */
413
414 switch (event->type) {
415 case SDL_MOUSEWHEEL:
416 /* Must be in bounds. */
417 if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
418 return 0;
419 if (event->wheel.y > 0)
420 mapedit_buttonZoom( 0, "btnZoomIn" );
421 else if (event->wheel.y < 0)
422 mapedit_buttonZoom( 0, "btnZoomOut" );
423 return 1;
424
425 case SDL_MOUSEBUTTONDOWN:
426 /* Must be in bounds. */
427 if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
428 return 0;
429 window_setFocus( wid, "cstSysEdit" );
430
431 /* Zooming */
432 if (event->button.button == SDL_BUTTON_X1) {
433 mapedit_buttonZoom( 0, "btnZoomIn" );
434 return 1;
435 }
436 else if (event->button.button == SDL_BUTTON_X2) {
437 mapedit_buttonZoom( 0, "btnZoomOut" );
438 return 1;
439 }
440
441 /* selecting star system */
442 else {
443 mx -= w/2 - mapedit_xpos;
444 my -= h/2 - mapedit_ypos;
445
446 for (int i=0; i<array_size(systems_stack); i++) {
447 double x,y;
448 StarSystem *sys = system_getIndex( i );
449
450 /* get position */
451 x = sys->pos.x * mapedit_zoom;
452 y = sys->pos.y * mapedit_zoom;
453
454 if ((pow2(mx-x)+pow2(my-y)) < t) {
455 int found = 0;
456
457 /* Set last clicked system */
459
460 /* Try to find in selected systems. */
461 for (int j=0; j<mapedit_nsys; j++) {
462 /* Must match. */
463 if (mapedit_sys[j] == sys) {
464 found = 1;
465 break;
466 } else
467 continue;
468 }
469
470 /* Toggle system selection. */
471 if (found)
472 mapedit_selectRm( sys );
473 else
474 mapedit_selectAdd( sys );
475 return 1;
476 }
477 }
478
479 /* Start dragging the viewport. */
480 mapedit_drag = 1;
481 mapedit_dragTime = SDL_GetTicks();
482 mapedit_moved = 0;
483 }
484 break;
485
486 case SDL_MOUSEBUTTONUP:
487 /* Handles dragging viewport around. */
488 mapedit_drag = 0;
489 break;
490
491 case SDL_MOUSEMOTION:
492 /* Update mouse positions. */
493 mapedit_mx = mx;
494 mapedit_my = my;
495
496 /* Handle dragging. */
497 if (mapedit_drag) {
498 /* axis is inverted */
499 mapedit_xpos -= xr;
500 mapedit_ypos += yr;
501
502 /* Update mouse movement. */
503 mapedit_moved += ABS(xr) + ABS(yr);
504 }
505 break;
506 }
507
508 return 0;
509}
510
514static void mapedit_deselect (void)
515{
516 if (mapedit_nsys > 0)
517 free( mapedit_sys );
518 mapedit_sys = NULL;
519 mapedit_nsys = 0;
520 mapedit_msys = 0;
521
522 /* Change window stuff. */
523 window_modifyText( mapedit_wid, "txtSelected", _("No selection") );
524 window_modifyText( mapedit_wid, "txtCurrentNumSystems", "0" );
525}
526
530static void mapedit_selectAdd( StarSystem *sys )
531{
532 /* Workaround for BUG found in memory allocation */
533 if (mapedit_nsys == 100)
534 return;
535
536 /* Allocate if needed. */
537 if (mapedit_msys < mapedit_nsys+1) {
538 if (mapedit_msys == 0)
539 mapedit_msys = 1;
540 mapedit_msys *= 2;
541 mapedit_sys = realloc( mapedit_sys, sizeof(StarSystem*) * mapedit_msys );
542 }
543
544 /* Add system. */
545 mapedit_sys[ mapedit_nsys ] = sys;
546 mapedit_nsys++;
547
548 /* Set text again. */
550}
551
555static void mapedit_selectRm( StarSystem *sys )
556{
557 for (int i=0; i<mapedit_nsys; i++) {
558 if (mapedit_sys[i] == sys) {
559 mapedit_nsys--;
560 memmove( &mapedit_sys[i], &mapedit_sys[i+1], sizeof(StarSystem*) * (mapedit_nsys - i) );
562 return;
563 }
564 }
565}
566
571{
572 int l;
573 char buf[STRMAX_SHORT];
574
575 /* Built list of all selected systems names */
576 l = 0;
577 for (int i=0; i<mapedit_nsys; i++) {
578 l += scnprintf( &buf[l], sizeof(buf)-l, "%s%s", mapedit_sys[i]->name,
579 (i == mapedit_nsys-1) ? "" : ", " );
580 }
581
582 if (l == 0)
583 /* Change display to reflect that no system is selected */
585 else {
586 /* Display list of selected systems */
587 window_modifyText( mapedit_wid, "txtSelected", buf );
588
589 /* Display number of selected systems */
590 snprintf( &buf[0], 4, "%i", mapedit_nsys);
591 window_modifyText( mapedit_wid, "txtCurrentNumSystems", buf );
592
593 /* Compute and display presence text. */
595 StarSystem *sys = system_getIndex( mapedit_iLastClickedSystem );
596 map_updateFactionPresence( mapedit_wid, "txtPresence", sys, 1 );
597 snprintf( &buf[0], sizeof(buf), _("Presence (%s)"), sys->name );
598 window_modifyText( mapedit_wid, "txtSPresence", buf );
599 } else {
600 window_modifyText( mapedit_wid, "txtSPresence", _("Presence") );
601 window_modifyText( mapedit_wid, "txtPresence", _("No system yet clicked") );
602 }
603 }
604}
605
612static void mapedit_buttonZoom( unsigned int wid, const char* str )
613{
614 (void) wid;
615 /* Transform coords to normal. */
618
619 /* Apply zoom. */
620 if (strcmp(str,"btnZoomIn")==0) {
623 }
624 else if (strcmp(str,"btnZoomOut")==0) {
627 }
628
629 /* Transform coords back. */
632}
633
638{
639 unsigned int wid;
640 char **names;
642 int n;
643
644 /* window */
645 wid = window_create( "wdwOpenMapOutfit", _("Open Map Outfit"), -1, -1, MAPEDIT_OPEN_WIDTH, MAPEDIT_OPEN_HEIGHT );
646 mapedit_widLoad = wid;
647
648 /* Default actions */
651
652 /* Load list of map outfits */
654
655 /* Load the maps */
656 n = array_size( mapList );
657 if (n > 0) {
658 names = malloc( sizeof(char*)*n );
659 for (int i=0; i<n; i++) {
660 ns = &mapList[i];
661 names[i] = strdup(ns->mapName);
662 }
663 }
664 /* case there are no files */
665 else {
666 names = malloc(sizeof(char*));
667 names[0] = strdup("None");
668 n = 1;
669 }
670
671 /* Map info text. */
672 window_addText( mapedit_widLoad, -20, -40, MAPEDIT_OPEN_TXT_WIDTH, MAPEDIT_OPEN_HEIGHT-40-20-2*(BUTTON_HEIGHT+20),
673 0, "txtMapInfo", NULL, NULL, NULL );
674
675 window_addList( mapedit_widLoad, 20, -50,
677 "lstMapOutfits", names, n, 0, mapedit_loadMapMenu_update, mapedit_loadMapMenu_load );
678
679 /* Buttons */
680 window_addButtonKey( mapedit_widLoad, -20, 20 + BUTTON_HEIGHT+20, BUTTON_WIDTH, BUTTON_HEIGHT,
681 "btnLoad", _("Load"), mapedit_loadMapMenu_load, SDLK_l );
682 window_addButton( mapedit_widLoad, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
683 "btnBack", _("Back"), mapedit_loadMapMenu_close );
684 window_addButton( mapedit_widLoad, 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
685 "btnDelete", _("Del"), mapedit_loadMapMenu_close );
686}
687
693static void mapedit_loadMapMenu_update( unsigned int wdw, const char *str )
694{
695 (void) str;
696 int pos;
698 const char *save;
699 char buf[STRMAX_SHORT];
700
701 /* Make sure list is ok. */
702 save = toolkit_getList( wdw, "lstMapOutfits" );
703 if (strcmp(save,"None") == 0)
704 return;
705
706 /* Get position. */
707 pos = toolkit_getListPos( wdw, "lstMapOutfits" );
708 ns = &mapList[pos];
709
710 /* Display text. */
711 snprintf( buf, sizeof(buf),
712 _("File Name:\n"
713 " %s\n"
714 "Map name:\n"
715 " %s\n"
716 "Description:\n"
717 " %s\n"
718 "Systems:\n"
719 " %i"),
720 ns->fileName, ns->mapName, ns->description, ns->numSystems
721 );
722
723 window_modifyText( wdw, "txtMapInfo", buf );
724}
725
731static void mapedit_loadMapMenu_close( unsigned int wdw, const char *str )
732{
733 (void) str;
734 window_destroy( wdw );
735}
736
740static void mapedit_loadMapMenu_load( unsigned int wdw, const char *str )
741{
742 (void)str;
743 int pos, len, compareLimit, i, found;
745 const char *save;
746 char *file, *name, *systemName;
747 xmlNodePtr node;
748 xmlDocPtr doc;
749 StarSystem *sys;
750
751 /* Debug log */
752
753 /* Make sure list is ok. */
754 save = toolkit_getList( wdw, "lstMapOutfits" );
755 if (strcmp(save,"None") == 0)
756 return;
757
758 /* Reset defaults. */
759 mapedit_nospob = 0;
760 mapedit_hidden = 0;
761
762 /* Get position. */
763 pos = toolkit_getListPos( wdw, "lstMapOutfits" );
764 ns = &mapList[pos];
765
766 /* Display text. */
767 len = strlen(MAP_DATA_PATH)+strlen(ns->fileName)+2;
768 file = malloc( len );
769 snprintf( file, len, "%s%s", MAP_DATA_PATH, ns->fileName );
770
771 doc = xml_parsePhysFS( file );
772
773 /* Get first node, normally "outfit" */
774 node = doc->xmlChildrenNode;
775 if (node == NULL) {
776 free(file);
777 xmlFreeDoc(doc);
778 return;
779 }
780
781 if (!xml_isNode(node,"outfit")) {
782 free(file);
783 xmlFreeDoc(doc);
784 return;
785 }
786
787 /* Get "name" property from the "outfit" node */
788 xmlr_attr_strd(node, "name", name);
789 if (strcmp(ns->mapName, name)!=0) {
790 free(name);
791 free(file);
792 xmlFreeDoc(doc);
793 return;
794 } else {
795 free(name);
796 name = NULL;
797 }
798
799 /* Loop on the nodes to find <specific> node */
800 node = node->xmlChildrenNode;
801 do {
802 xml_onlyNodes(node);
803
804 if (!xml_isNode(node,"specific"))
805 continue;
806
807 /* Break out of the loop, either with a correct outfitType or not */
808 break;
809 } while (xml_nextNode(node));
810
812
813 /* Loop on the nodes to find all <sys> node */
814 node = node->xmlChildrenNode;
815 do {
816 xml_onlyNodes(node);
817
818 if (!xml_isNode(node,"sys"))
819 continue;
820
821 /* Display "name" property from "sys" node and increment number of systems found */
822 xmlr_attr_strd(node, "name", systemName);
823
824 /* Find system */
825 found = 0;
826 for (i=0; i<array_size(systems_stack); i++) {
827 sys = system_getIndex( i );
828 compareLimit = strlen(systemName);
829 if (strncmp(systemName, sys->name, compareLimit)==0) {
830 found = 1;
831 break;
832 }
833 }
834
835 /* If system exists, select it */
836 if (found)
837 mapedit_selectAdd( sys );
838 free( systemName );
839 systemName = NULL;
840 } while (xml_nextNode(node));
841
843
844 free(file);
845 xmlFreeDoc(doc);
846
847 window_destroy( wdw );
848}
849
853static void mapedit_btnSaveMapAs( unsigned int wdw, const char *unused )
854{
855 (void)unused;
857
858 ns.fileName = strdup( window_getInput( wdw, "inpFileName" ) );
859 ns.mapName = strdup( window_getInput( wdw, "inpMapName" ) );
860 ns.description = strdup( window_getInput( wdw, "inpDescription" ) );
861 ns.gfx_store = strdup( window_getInput( wdw, "inpGFX" ) );
862 ns.numSystems = mapedit_nsys;
863 ns.price = atoll(window_getInput( wdw, "inpPrice" ));
864 ns.rarity = atoi(window_getInput( wdw, "inpRarity" ));
865
867
868 free( ns.fileName );
869 free( ns.mapName );
870 free( ns.description );
871 free( ns.gfx_store );
872}
873
878{
879 char buf[32];
880
881 /* Displaying info strings */
882 window_setInput( mapedit_wid, "inpFileName", ns->fileName );
883 window_setInput( mapedit_wid, "inpMapName", ns->mapName );
884 window_setInput( mapedit_wid, "inpDescription", ns->description );
885 window_setInput( mapedit_wid, "inpGFX", ns->gfx_store );
886 snprintf( buf, sizeof(buf), "%i", ns->numSystems );
887 window_modifyText( mapedit_wid, "txtCurrentNumSystems", buf );
888 snprintf( buf, sizeof(buf), "%"CREDITS_PRI, ns->price );
889 window_setInput( mapedit_wid, "inpPrice", buf );
890 snprintf( buf, sizeof(buf), "%i", ns->rarity );
891 window_setInput( mapedit_wid, "inpRarity", buf );
892
893 /* Local information. */
894 free( mapedit_sLoadMapName );
895 mapedit_sLoadMapName = strdup( ns->mapName );
896}
897
904{
905 int is_map, nSystems;
906 xmlNodePtr node, cur;
907 xmlDocPtr doc;
908 char **map_files;
909 char *file, *name, *outfitType;
910 mapOutfitsList_t *newMapItem;
911
913 mapList = array_create( mapOutfitsList_t );
914
915 map_files = PHYSFS_enumerateFiles( MAP_DATA_PATH );
916 newMapItem = NULL;
917 for (size_t i=0; map_files[i]!=NULL; i++) {
918 char *description = NULL;
919 char *gfx_store = NULL;
920 credits_t price = 1000;
921 int rarity = 0;
922
923 SDL_asprintf( &file, "%s%s", MAP_DATA_PATH, map_files[i] );
924
925 doc = xml_parsePhysFS( file );
926 if (doc == NULL) {
927 free(file);
928 continue;
929 }
930
931 /* Get first node, normally "outfit" */
932 node = doc->xmlChildrenNode;
933 if (node == NULL) {
934 free(file);
935 xmlFreeDoc(doc);
936 return -1;
937 }
938
939 if (!xml_isNode(node,"outfit")) {
940 free(file);
941 xmlFreeDoc(doc);
942 return -1;
943 }
944
945 /* Get "name" property from the "outfit" node */
946 xmlr_attr_strd( node, "name", name );
947
948 /* Loop on the nodes to find <specific> node */
949 node = node->xmlChildrenNode;
950 do {
951 is_map = 0;
952 xml_onlyNodes(node);
953
954 if (!xml_isNode(node,"specific")) {
955 if (xml_isNode(node,"general")) {
956 cur = node->children;
957 do {
958 xml_onlyNodes(cur);
959 xmlr_str(cur,"description",description);
960 xmlr_long(cur,"price",price);
961 xmlr_int(cur,"rarity",rarity);
962 xmlr_str(cur,"gfx_store",gfx_store);
963 } while (xml_nextNode(cur));
964 }
965 continue;
966 }
967
968 /* Get the "type" property from "specific" node */
969 xmlr_attr_strd( node, "type", outfitType );
970 is_map = outfitType == NULL ? 0 : !strncmp(outfitType, "map", 3);
971 free(outfitType);
972
973 /* Break out of the loop, either with a map or not */
974 break;
975 } while (xml_nextNode(node));
976
977 /* If it's not a map, we don't care. */
978 if (!is_map) {
979 free(name);
980 free(file);
981 xmlFreeDoc(doc);
982 continue;
983 }
984
985 /* Loop on the nodes to find all <sys> node */
986 nSystems = 0;
987 node = node->xmlChildrenNode;
988 do {
989 xml_onlyNodes(node);
990 if (!xml_isNode(node,"sys"))
991 continue;
992
993 /* Display "name" property from "sys" node and increment number of systems found */
994 nSystems++;
995 } while (xml_nextNode(node));
996
997 /* If the map is a regular one, then load it into the list */
998 if (nSystems > 0) {
999 newMapItem = &array_grow( &mapList );
1000 newMapItem->numSystems = nSystems;
1001 newMapItem->fileName = strdup( map_files[ i ] );
1002 newMapItem->mapName = strdup( name );
1003 newMapItem->description = strdup( (description != NULL) ? description : "" );
1004 newMapItem->gfx_store = strdup( (gfx_store != NULL) ? gfx_store : "" );
1005 newMapItem->price = price;
1006 newMapItem->rarity = rarity;
1007 }
1008
1009 /* Clean up. */
1010 free(name);
1011 free(file);
1012 free(description);
1013 free(gfx_store);
1014 }
1015
1016 /* Clean up. */
1017 PHYSFS_freeList( map_files );
1018
1019 return 0;
1020}
1021
1025static void mapsList_free (void)
1026{
1027 unsigned int n = array_size( mapList );
1028 for (unsigned int i=0; i<n; i++) {
1029 free( mapList[i].fileName );
1030 free( mapList[i].mapName );
1031 free( mapList[i].description );
1032 free( mapList[i].gfx_store );
1033 }
1034 array_free(mapList);
1035 mapList = NULL;
1036
1037 free( mapedit_sLoadMapName );
1038 mapedit_sLoadMapName = NULL;
1039}
1040
1046static int mapedit_saveMap( StarSystem **uniedit_sys, mapOutfitsList_t* ns )
1047{
1048 xmlDocPtr doc;
1049 xmlTextWriterPtr writer;
1050 char *file;
1051
1052 /* Create the writer. */
1053 writer = xmlNewTextWriterDoc(&doc, 0);
1054 if (writer == NULL) {
1055 WARN(_("testXmlwriterDoc: Error creating the xml writer"));
1056 return -1;
1057 }
1058
1059 /* Set the writer parameters. */
1060 xmlw_setParams( writer );
1061
1062 /* Start writer. */
1063 xmlw_start(writer);
1064 xmlw_startElem( writer, "outfit" );
1065
1066 /* Attributes. */
1067 xmlw_attr( writer, "name", "%s", ns->mapName );
1068
1069 /* General. */
1070 xmlw_startElem( writer, "general" );
1071 xmlw_elem( writer, "rarity", "%d", ns->rarity );
1072 xmlw_elem( writer, "mass", "%d", 0 );
1073 xmlw_elem( writer, "price", "%"CREDITS_PRI, ns->price );
1074 xmlw_elem( writer, "description", "%s", ns->description );
1075 xmlw_elem( writer, "gfx_store", "%s", ns->gfx_store );
1076 xmlw_endElem( writer ); /* "general" */
1077
1078 xmlw_startElem( writer, "specific" );
1079 xmlw_attr( writer, "type", "map" );
1080
1081 /* Iterate over all selected systems. Save said systems and any NORMAL jumps they might share. */
1082 for (int i=0; i < ns->numSystems; i++) {
1083 StarSystem *s = uniedit_sys[i];
1084 xmlw_startElem( writer, "sys" );
1085 xmlw_attr( writer, "name", "%s", s->name );
1086
1087 /* Iterate jumps and see if they lead to any other systems in our array. */
1088 for (int j=0; j < array_size(s->jumps); j++) {
1089 /* Ignore hidden and exit-only jumps. */
1090 if (jp_isFlag(&s->jumps[j], JP_EXITONLY ))
1091 continue;
1092 if (!mapedit_hidden && jp_isFlag(&s->jumps[j], JP_HIDDEN))
1093 continue;
1094 /* This is a normal jump. */
1095 for (int k=0; k < ns->numSystems; k++) {
1096 if (s->jumps[j].target == uniedit_sys[k]) {
1097 xmlw_elem( writer, "jump", "%s", uniedit_sys[k]->name );
1098 break;
1099 }
1100 }
1101 }
1102
1103 /* Iterate spobs and add them */
1104 if (!mapedit_nospob)
1105 for (int j=0; j < array_size(s->spobs); j++)
1106 xmlw_elem( writer, "spob", "%s", s->spobs[j]->name );
1107
1108 xmlw_endElem( writer ); /* "sys" */
1109 }
1110
1111 xmlw_endElem( writer ); /* "specific" */
1112 xmlw_endElem( writer ); /* "outfit" */
1113 xmlw_done(writer);
1114
1115 /* No need for writer anymore. */
1116 xmlFreeTextWriter(writer);
1117
1118 /* Actually write data */
1119 SDL_asprintf( &file, "%s/%s", conf.dev_save_map, ns->fileName );
1120 if (xmlSaveFileEnc( file, doc, "UTF-8" ) < 0)
1121 WARN(_("Failed writing '%s'!"), file);
1122 free( file );
1123
1124 /* Clean up. */
1125 xmlFreeDoc(doc);
1126
1127 return 0;
1128}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
Definition array.h:119
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
static int mapedit_mapsList_refresh(void)
Gets the list of all the maps names. from outfit_mapParse()
static void mapedit_focusLose(unsigned int wid, const char *wgtname)
Called when it's de-focused.
static int mapedit_msys
Definition dev_mapedit.c:86
static int mapedit_keys(unsigned int wid, SDL_Keycode key, SDL_Keymod mod, int isrepeat)
Handles keybindings.
static void mapedit_buttonZoom(unsigned int wid, const char *str)
Handles the button zoom clicks.
static void mapedit_selectRm(StarSystem *sys)
Removes a system from the selection.
static void mapedit_btnOpen(unsigned int wid_unused, const char *unused)
Opens up a map file.
void mapedit_open(unsigned int wid_unused, const char *unused)
Opens the system editor interface.
static unsigned int mapedit_wid
Definition dev_mapedit.c:75
static char * mapedit_sLoadMapName
Definition dev_mapedit.c:90
#define MAPEDIT_OPEN_WIDTH
Definition dev_mapedit.c:55
static StarSystem ** mapedit_sys
Definition dev_mapedit.c:82
static void mapedit_loadMapMenu_update(unsigned int wdw, const char *str)
Updates the load menu.
static int mapedit_tadd
Definition dev_mapedit.c:84
static int mapedit_nospob
Definition dev_mapedit.c:91
static int mapedit_moved
Definition dev_mapedit.c:79
#define MAPEDIT_ZOOM_MIN
Definition dev_mapedit.c:53
static void mapedit_loadMapMenu_load(unsigned int wdw, const char *str)
Load the selected Map.
static int mapedit_hidden
Definition dev_mapedit.c:92
static double mapedit_zoom
Definition dev_mapedit.c:78
static int mapedit_mouse(unsigned int wid, const SDL_Event *event, double mx, double my, double w, double h, double xr, double yr, void *data)
System editor custom widget mouse handling.
static int mapedit_saveMap(StarSystem **uniedit_sys, mapOutfitsList_t *ns)
Saves selected systems as a map outfit file.
static unsigned int mapedit_widLoad
Definition dev_mapedit.c:89
static void mapedit_btnSaveMapAs(unsigned int wid_unused, const char *unused)
Save the current Map to selected file.
#define MAPEDIT_OPEN_TXT_WIDTH
Definition dev_mapedit.c:57
void mapedit_selectText(void)
Sets the selected system text.
static double mapedit_xpos
Definition dev_mapedit.c:76
#define BUTTON_HEIGHT
Definition dev_mapedit.c:43
static double mapedit_my
Definition dev_mapedit.c:88
static void mapedit_loadMapMenu_close(unsigned int wdw, const char *str)
Closes the load map outfit menu.
StarSystem * systems_stack
Definition space.c:92
static void mapedit_selectAdd(StarSystem *sys)
Adds a system to the selection.
static void mapsList_free(void)
Frees the loaded map.
void mapedit_setGlobalLoadedInfos(mapOutfitsList_t *ns)
Set and display the global variables describing last loaded/saved file.
static void mapedit_loadMapMenu_open(void)
Opens the load map outfit menu.
static unsigned int mapedit_dragTime
Definition dev_mapedit.c:80
static int mapedit_iLastClickedSystem
Definition dev_mapedit.c:83
static void mapedit_clear(unsigned int wid_unused, const char *unused)
Closes the system editor widget.
#define MAPEDIT_ZOOM_MAX
Definition dev_mapedit.c:52
#define MAPEDIT_OPEN_HEIGHT
Definition dev_mapedit.c:56
static double mapedit_mx
Definition dev_mapedit.c:87
static void mapedit_deselect(void)
Deselects selected targets.
static double mapedit_ypos
Definition dev_mapedit.c:77
#define BUTTON_WIDTH
Definition dev_mapedit.c:42
static int mapedit_nsys
Definition dev_mapedit.c:85
static void mapedit_render(double bx, double by, double w, double h, void *data)
System editor custom widget rendering.
#define MAPEDIT_ZOOM_STEP
Definition dev_mapedit.c:51
static int mapedit_drag
Definition dev_mapedit.c:81
static void mapedit_close(unsigned int wid, const char *wgt)
Closes the system editor widget.
static StarSystem ** uniedit_sys
Definition dev_uniedit.c:99
glFont gl_smallFont
Definition font.c:154
Header file with generic functions and naev-specifics.
#define MIN(x, y)
Definition naev.h:40
#define ABS(x)
Definition naev.h:36
#define pow2(x)
Definition naev.h:46
#define MAX(x, y)
Definition naev.h:39
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Definition nstring.c:99
void xmlw_setParams(xmlTextWriterPtr writer)
Sets up the standard xml write parameters.
Definition nxml.c:64
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:75
void gl_renderCircle(double cx, double cy, double r, const glColour *c, int filled)
Draws a circle.
void pause_game(void)
Pauses the game.
Definition pause.c:28
void unpause_game(void)
Unpauses the game.
Definition pause.c:46
void systems_reconstructJumps(void)
Reconstructs the jumps.
Definition space.c:2738
StarSystem * system_getIndex(int id)
Get the system by its index.
Definition space.c:989
char * dev_save_map
Definition conf.h:171
int h
Definition font.h:18
unsigned int window_create(const char *name, const char *displayname, const int x, const int y, const int w, const int h)
Creates a window.
Definition toolkit.c:691
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition toolkit.c:2471
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition toolkit.c:847
void window_setCancel(unsigned int wid, void(*cancel)(unsigned int, const char *))
Sets the default cancel function of the window.
Definition toolkit.c:868
void window_handleKeys(unsigned int wid, int(*keyhandler)(unsigned int, SDL_Keycode, SDL_Keymod, int))
Sets the key handler for the window.
Definition toolkit.c:960
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition toolkit.c:1026
void window_destroy(unsigned int wid)
Kills the window.
Definition toolkit.c:1037
void diff_clear(void)
Removes all active diffs. (Call before economy_destroy().)
Definition unidiff.c:1522