naev 0.10.4
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
63#define MAPEDIT_FILENAME_MAX 128
64#define MAPEDIT_NAME_MAX 128
65#define MAPEDIT_DESCRIPTION_MAX 1024
67typedef struct mapOutfitsList_s {
68 char *fileName;
69 char *mapName;
70 char *description;
71 int numSystems;
72 credits_t price;
73 int rarity;
75
76static mapOutfitsList_t *mapList = NULL; /* Array of map outfits for displaying in the Open window. */
77
78static unsigned int mapedit_wid = 0;
79static double mapedit_xpos = 0.;
80static double mapedit_ypos = 0.;
81static double mapedit_zoom = 1.;
82static int mapedit_moved = 0;
83static unsigned int mapedit_dragTime = 0;
84static int mapedit_drag = 0;
85static StarSystem **mapedit_sys = NULL;
87static int mapedit_tadd = 0;
88static int mapedit_nsys = 0;
89static int mapedit_msys = 0;
90static double mapedit_mx = 0.;
91static double mapedit_my = 0.;
92static unsigned int mapedit_widLoad = 0;
93static char *mapedit_sLoadMapName = NULL;
95/*
96 * Universe editor Prototypes.
97 */
98/* Selection. */
99static void mapedit_deselect (void);
100static void mapedit_selectAdd( StarSystem *sys );
101static void mapedit_selectRm( StarSystem *sys );
102/* Custom system editor widget. */
103static void mapedit_buttonZoom( unsigned int wid, const char* str );
104static void mapedit_render( double bx, double by, double w, double h, void *data );
105static void mapedit_focusLose( unsigned int wid, const char* wgtname );
106static int mapedit_mouse( unsigned int wid, SDL_Event* event, double mx, double my,
107 double w, double h, double xr, double yr, void *data );
108/* Button functions. */
109static void mapedit_close( unsigned int wid, const char *wgt );
110static void mapedit_btnOpen( unsigned int wid_unused, const char *unused );
111static void mapedit_btnSaveMapAs( unsigned int wid_unused, const char *unused );
112static void mapedit_clear( unsigned int wid_unused, const char *unused );
113/* Keybindings handling. */
114static int mapedit_keys( unsigned int wid, SDL_Keycode key, SDL_Keymod mod );
115/* Loading of Map files. */
116static void mapedit_loadMapMenu_open (void);
117static void mapedit_loadMapMenu_close( unsigned int wdw, const char *str );
118static void mapedit_loadMapMenu_update( unsigned int wdw, const char *str );
119static void mapedit_loadMapMenu_load( unsigned int wdw, const char *str );
120/* Saving of Map files. */
121static int mapedit_saveMap( StarSystem** uniedit_sys, mapOutfitsList_t* ns );
122/* Management of last loaded/saved Map file. */
124/* Management of Map files list. */
125static int mapedit_mapsList_refresh (void);
126static void mapsList_free (void);
127
131void mapedit_open( unsigned int wid_unused, const char *unused )
132{
133 (void) wid_unused;
134 (void) unused;
135 unsigned int wid;
136 int buttonHPos = 0;
137 int buttonVPos = 1;
138 int textPos = 0;
139 int linesPos = 0;
140 int curLines = 0;
141 int lineHeight = gl_smallFont.h + 5;
142 int parHeight = 10;
143
144 /* Pause. */
145 pause_game();
146
147 /* Must have no diffs applied. */
148 diff_clear();
149
150 /* Reset some variables. */
151 mapedit_drag = 0;
152 mapedit_tadd = 0;
153 mapedit_zoom = 1.;
154 mapedit_xpos = 0.;
155 mapedit_ypos = 0.;
156
157 /* Create the window. */
158 wid = window_create( "wdwMapOutfitEditor", _("Map Outfit Editor"), -1, -1, -1, -1 );
160 mapedit_wid = wid;
161
162 /* Actual viewport. */
163 window_addCust( wid, 20, -40, SCREEN_W - 350, SCREEN_H - 100,
164 "cstSysEdit", 1, mapedit_render, mapedit_mouse, NULL, mapedit_focusLose, NULL );
165
166 /* Button : reset the current map. */
167 buttonHPos = 2;
168 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
169 "btnClear", "Reset", mapedit_clear, SDLK_r );
170 buttonHPos--;
171
172 /* Button : open map file. */
173 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
174 "btnOpen", "Open", mapedit_btnOpen, SDLK_o );
175 buttonHPos--;
176
177 /* Button : save current map to file. */
178 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
179 "btnSaveAs", "Save", mapedit_btnSaveMapAs, SDLK_s );
180 buttonHPos = 0;
181 buttonVPos--;
182
183 /* Button : exit editor. */
184 window_addButtonKey( wid, -20-(BUTTON_WIDTH+20)*buttonHPos, 20+(BUTTON_HEIGHT+20)*buttonVPos, BUTTON_WIDTH, BUTTON_HEIGHT,
185 "btnClose", "Exit", mapedit_close, SDLK_x );
186
187 /* Filename. */
188 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, lineHeight, 0, "txtSFileName",
189 &gl_smallFont, NULL, "File Name:" );
190 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpFileName",
191 1024, 1, &gl_smallFont );
192 textPos++;
193 linesPos++;
194
195 /* Map name. */
196 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, lineHeight, 0, "txtSMapName",
197 &gl_smallFont, NULL, "Map Name:" );
198 window_addInput( wid, -30, -40-textPos*parHeight-(linesPos+1)*lineHeight, 170, lineHeight, "inpMapName",
199 1024, 1, &gl_smallFont );
200 textPos++;
201 linesPos++;
202
203 /* Map description. */
204 curLines = 7;
205 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, lineHeight, 0, "txtSDescription",
206 &gl_smallFont, NULL, "Description:" );
207 window_addInput( wid, -20, -40-textPos*parHeight-(linesPos+1)*lineHeight, 300-20, curLines*lineHeight, "inpDescription",
208 32768, 0, &gl_smallFont );
209 textPos++;
210 linesPos+=(curLines+1);
211
212 /* Current Map # of systems. */
213 curLines = 1;
214 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, 20, 0, "txtSCurrentNumSystems",
215 &gl_smallFont, NULL, "Number of Systems (up to 100):" );
216 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 60, curLines*lineHeight, 0, "txtCurrentNumSystems",
217 &gl_smallFont, NULL, "N/A" );
218 textPos++;
219 linesPos++;
220
221 /* Presence. */
222 curLines = 5;
223 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, 20, 0, "txtSPresence",
224 &gl_smallFont, NULL, "Presence:" );
225 window_addText( wid, -20, -40-textPos*parHeight-(linesPos+1)*lineHeight, 300-20, curLines*lineHeight, 0, "txtPresence",
226 &gl_smallFont, NULL, "No selection" );
227 textPos++;
228 linesPos+=curLines+1;
229
230 /* Outift attributes. */
231 curLines = 1;
232 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, 20, 0, "txtSPrice",
233 &gl_smallFont, NULL, "Price:" );
234 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpPrice",
235 64, 1, &gl_smallFont );
236 window_setInputFilter( wid, "inpPrice", INPUT_FILTER_NUMBER );
237 textPos++;
238 linesPos+=curLines+1;
239
240 curLines = 1;
241 window_addText( wid, -200, -40-textPos*parHeight-linesPos*lineHeight, 100, 20, 0, "txtSRarity",
242 &gl_smallFont, NULL, "Rarity:" );
243 window_addInput( wid, -30, -40-textPos*parHeight-linesPos*lineHeight, 170, lineHeight, "inpRarity",
244 64, 1, &gl_smallFont );
245 window_setInputFilter( wid, "inpRarity", INPUT_FILTER_NUMBER );
246 textPos++;
247 linesPos+=curLines+1;
248
249 curLines = 4;
250 window_addText( wid, -20, -40-textPos*parHeight-linesPos*lineHeight, 300-20, curLines*lineHeight, 0, "txtSWarning",
251 &gl_smallFont, NULL,
252 "Warning: Editor can't (yet) manage which details are mapped within a system. Review its changes before committing." );
253 textPos++;
254 linesPos+=curLines+1;
255
256 /* Zoom buttons */
257 window_addButtonKey( wid, 40, 20, 30, 30, "btnZoomIn", "+", mapedit_buttonZoom, SDLK_EQUALS );
258 window_addButtonKey( wid, 80, 20, 30, 30, "btnZoomOut", "-", mapedit_buttonZoom, SDLK_MINUS );
259
260 /* Selected text. */
261 window_addText( wid, 140, 10, SCREEN_W - 350 - 30 - 30 - BUTTON_WIDTH - 20, 30, 0,
262 "txtSelected", &gl_smallFont, NULL, NULL );
263
264 /* Deselect everything. */
266}
267
271static int mapedit_keys( unsigned int wid, SDL_Keycode key, SDL_Keymod mod )
272{
273 (void) mod;
274
275 switch (key) {
276 /* Mode changes. */
277 case SDLK_ESCAPE:
278 mapedit_close(wid, "Close");
279 return 1;
280
281 default:
282 return 0;
283 }
284}
285
289static void mapedit_close( unsigned int wid, const char *wgt )
290{
291 /* Frees some memory. */
294
295 /* Reconstruct jumps. */
297
298 /* Unpause. */
299 unpause_game();
300
301 /* Close the window. */
302 window_close( wid, wgt );
303}
304
308static void mapedit_clear( unsigned int wid, const char *unused )
309{
310 (void) wid;
311 (void) unused;
312
313 /* Clear the map. */
315}
316
320static void mapedit_btnOpen( unsigned int wid_unused, const char *unused )
321{
322 (void) wid_unused;
323 (void) unused;
324
326
327}
328
332static void mapedit_render( double bx, double by, double w, double h, void *data )
333{
334 (void) data;
335 double x, y, r;
336
337 /* Parameters. */
338 map_renderParams( bx, by, mapedit_xpos, mapedit_ypos, w, h, mapedit_zoom, &x, &y, &r );
339
340 uniedit_renderMap( bx, by, w, h, x, y, mapedit_zoom, r );
341
342 /* Render the selected system selections. */
343 for (int i=0; i<mapedit_nsys; i++) {
344 StarSystem *sys = mapedit_sys[i];
345 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
346 1.8*r, &cRed, 0 );
347 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
348 2.0*r, &cRed, 0 );
349 }
350
351 /* Render last clicked system */
353 StarSystem *sys = system_getIndex( mapedit_iLastClickedSystem );
354 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
355 2.4*r, &cBlue, 0 );
356 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
357 2.6*r, &cBlue, 0 );
358 gl_renderCircle( x + sys->pos.x * mapedit_zoom, y + sys->pos.y * mapedit_zoom,
359 2.8*r, &cBlue, 0 );
360 }
361}
362
366static void mapedit_focusLose( unsigned int wid, const char* wgtname )
367{
368 (void) wid;
369 (void) wgtname;
370 mapedit_drag = 0;
371}
372
376static int mapedit_mouse( unsigned int wid, SDL_Event* event, double mx, double my,
377 double w, double h, double xr, double yr, void *data )
378{
379 (void) data;
380 const double t = 15.*15.; /* threshold */
381
382 switch (event->type) {
383 case SDL_MOUSEWHEEL:
384 /* Must be in bounds. */
385 if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
386 return 0;
387 if (event->wheel.y > 0)
388 mapedit_buttonZoom( 0, "btnZoomIn" );
389 else if (event->wheel.y < 0)
390 mapedit_buttonZoom( 0, "btnZoomOut" );
391 return 1;
392
393 case SDL_MOUSEBUTTONDOWN:
394 /* Must be in bounds. */
395 if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
396 return 0;
397 window_setFocus( wid, "cstSysEdit" );
398
399 /* Zooming */
400 if (event->button.button == SDL_BUTTON_X1) {
401 mapedit_buttonZoom( 0, "btnZoomIn" );
402 return 1;
403 }
404 else if (event->button.button == SDL_BUTTON_X2) {
405 mapedit_buttonZoom( 0, "btnZoomOut" );
406 return 1;
407 }
408
409 /* selecting star system */
410 else {
411 mx -= w/2 - mapedit_xpos;
412 my -= h/2 - mapedit_ypos;
413
414 for (int i=0; i<array_size(systems_stack); i++) {
415 double x,y;
416 StarSystem *sys = system_getIndex( i );
417
418 /* get position */
419 x = sys->pos.x * mapedit_zoom;
420 y = sys->pos.y * mapedit_zoom;
421
422 if ((pow2(mx-x)+pow2(my-y)) < t) {
423 int found = 0;
424
425 /* Set last clicked system */
427
428 /* Try to find in selected systems. */
429 for (int j=0; j<mapedit_nsys; j++) {
430 /* Must match. */
431 if (mapedit_sys[j] == sys) {
432 found = 1;
433 break;
434 } else
435 continue;
436 }
437
438 /* Toggle system selection. */
439 if (found)
440 mapedit_selectRm( sys );
441 else
442 mapedit_selectAdd( sys );
443 return 1;
444 }
445 }
446
447 /* Start dragging the viewport. */
448 mapedit_drag = 1;
449 mapedit_dragTime = SDL_GetTicks();
450 mapedit_moved = 0;
451 }
452 break;
453
454 case SDL_MOUSEBUTTONUP:
455 /* Handles dragging viewport around. */
456 mapedit_drag = 0;
457 break;
458
459 case SDL_MOUSEMOTION:
460 /* Update mouse positions. */
461 mapedit_mx = mx;
462 mapedit_my = my;
463
464 /* Handle dragging. */
465 if (mapedit_drag) {
466 /* axis is inverted */
467 mapedit_xpos -= xr;
468 mapedit_ypos += yr;
469
470 /* Update mouse movement. */
471 mapedit_moved += ABS(xr) + ABS(yr);
472 }
473 break;
474 }
475
476 return 0;
477}
478
482static void mapedit_deselect (void)
483{
484 if (mapedit_nsys > 0)
485 free( mapedit_sys );
486 mapedit_sys = NULL;
487 mapedit_nsys = 0;
488 mapedit_msys = 0;
489
490 /* Change window stuff. */
491 window_modifyText( mapedit_wid, "txtSelected", "No selection" );
492 window_modifyText( mapedit_wid, "txtCurrentNumSystems", "0" );
493}
494
498static void mapedit_selectAdd( StarSystem *sys )
499{
500 /* Workaround for BUG found in memory allocation */
501 if (mapedit_nsys == 100)
502 return;
503
504 /* Allocate if needed. */
505 if (mapedit_msys < mapedit_nsys+1) {
506 if (mapedit_msys == 0)
507 mapedit_msys = 1;
508 mapedit_msys *= 2;
509 mapedit_sys = realloc( mapedit_sys, sizeof(StarSystem*) * mapedit_msys );
510 }
511
512 /* Add system. */
513 mapedit_sys[ mapedit_nsys ] = sys;
514 mapedit_nsys++;
515
516 /* Set text again. */
518}
519
523static void mapedit_selectRm( StarSystem *sys )
524{
525 for (int i=0; i<mapedit_nsys; i++) {
526 if (mapedit_sys[i] == sys) {
527 mapedit_nsys--;
528 memmove( &mapedit_sys[i], &mapedit_sys[i+1], sizeof(StarSystem*) * (mapedit_nsys - i) );
530 return;
531 }
532 }
533}
534
539{
540 int l;
541 char buf[STRMAX_SHORT];
542
543 /* Built list of all selected systems names */
544 l = 0;
545 for (int i=0; i<mapedit_nsys; i++) {
546 l += scnprintf( &buf[l], sizeof(buf)-l, "%s%s", mapedit_sys[i]->name,
547 (i == mapedit_nsys-1) ? "" : ", " );
548 }
549
550 if (l == 0)
551 /* Change display to reflect that no system is selected */
553 else {
554 /* Display list of selected systems */
555 window_modifyText( mapedit_wid, "txtSelected", buf );
556
557 /* Display number of selected systems */
558 snprintf( &buf[0], 4, "%i", mapedit_nsys);
559 window_modifyText( mapedit_wid, "txtCurrentNumSystems", buf );
560
561 /* Compute and display presence text. */
563 StarSystem *sys = system_getIndex( mapedit_iLastClickedSystem );
564 map_updateFactionPresence( mapedit_wid, "txtPresence", sys, 1 );
565 snprintf( &buf[0], sizeof(buf), "Presence (%s)", sys->name );
566 window_modifyText( mapedit_wid, "txtSPresence", buf );
567 } else {
568 window_modifyText( mapedit_wid, "txtSPresence", "Presence" );
569 window_modifyText( mapedit_wid, "txtPresence", "No system yet clicked" );
570 }
571 }
572}
573
580static void mapedit_buttonZoom( unsigned int wid, const char* str )
581{
582 (void) wid;
583 /* Transform coords to normal. */
586
587 /* Apply zoom. */
588 if (strcmp(str,"btnZoomIn")==0) {
591 }
592 else if (strcmp(str,"btnZoomOut")==0) {
595 }
596
597 /* Transform coords back. */
600}
601
606{
607 unsigned int wid;
608 char **names;
610 int n;
611
612 /* window */
613 wid = window_create( "wdwOpenMapOutfit", _("Open Map Outfit"), -1, -1, MAPEDIT_OPEN_WIDTH, MAPEDIT_OPEN_HEIGHT );
614 mapedit_widLoad = wid;
615
616 /* Default actions */
619
620 /* Load list of map outfits */
622
623 /* Load the maps */
624 n = array_size( mapList );
625 if (n > 0) {
626 names = malloc( sizeof(char*)*n );
627 for (int i=0; i<n; i++) {
628 ns = &mapList[i];
629 names[i] = strdup(ns->mapName);
630 }
631 }
632 /* case there are no files */
633 else {
634 names = malloc(sizeof(char*));
635 names[0] = strdup("None");
636 n = 1;
637 }
638
639 /* Map info text. */
640 window_addText( mapedit_widLoad, -20, -40, MAPEDIT_OPEN_TXT_WIDTH, MAPEDIT_OPEN_HEIGHT-40-20-2*(BUTTON_HEIGHT+20),
641 0, "txtMapInfo", NULL, NULL, NULL );
642
643 window_addList( mapedit_widLoad, 20, -50,
645 "lstMapOutfits", names, n, 0, mapedit_loadMapMenu_update, mapedit_loadMapMenu_load );
646
647 /* Buttons */
648 window_addButtonKey( mapedit_widLoad, -20, 20 + BUTTON_HEIGHT+20, BUTTON_WIDTH, BUTTON_HEIGHT,
649 "btnLoad", "Load", mapedit_loadMapMenu_load, SDLK_l );
650 window_addButton( mapedit_widLoad, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
651 "btnBack", "Back", mapedit_loadMapMenu_close );
652 window_addButton( mapedit_widLoad, 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
653 "btnDelete", "Del", mapedit_loadMapMenu_close );
654}
655
661static void mapedit_loadMapMenu_update( unsigned int wdw, const char *str )
662{
663 (void) str;
664 int pos;
666 const char *save;
667 char buf[STRMAX_SHORT];
668
669 /* Make sure list is ok. */
670 save = toolkit_getList( wdw, "lstMapOutfits" );
671 if (strcmp(save,"None") == 0)
672 return;
673
674 /* Get position. */
675 pos = toolkit_getListPos( wdw, "lstMapOutfits" );
676 ns = &mapList[pos];
677
678 /* Display text. */
679 snprintf( buf, sizeof(buf),
680 "File Name:\n"
681 " %s\n"
682 "Map name:\n"
683 " %s\n"
684 "Description:\n"
685 " %s\n"
686 "Systems:\n"
687 " %i",
688 ns->fileName, ns->mapName, ns->description, ns->numSystems
689 );
690
691 window_modifyText( wdw, "txtMapInfo", buf );
692}
693
699static void mapedit_loadMapMenu_close( unsigned int wdw, const char *str )
700{
701 (void) str;
702 window_destroy( wdw );
703}
704
708static void mapedit_loadMapMenu_load( unsigned int wdw, const char *str )
709{
710 (void)str;
711 int pos, len, compareLimit, i, found;
713 const char *save;
714 char *file, *name, *systemName;
715 xmlNodePtr node;
716 xmlDocPtr doc;
717 StarSystem *sys;
718
719 /* Debug log */
720
721 /* Make sure list is ok. */
722 save = toolkit_getList( wdw, "lstMapOutfits" );
723 if (strcmp(save,"None") == 0)
724 return;
725
726 /* Get position. */
727 pos = toolkit_getListPos( wdw, "lstMapOutfits" );
728 ns = &mapList[pos];
729
730 /* Display text. */
731 len = strlen(MAP_DATA_PATH)+strlen(ns->fileName)+2;
732 file = malloc( len );
733 snprintf( file, len, "%s%s", MAP_DATA_PATH, ns->fileName );
734
735 doc = xml_parsePhysFS( file );
736
737 /* Get first node, normally "outfit" */
738 node = doc->xmlChildrenNode;
739 if (node == NULL) {
740 free(file);
741 xmlFreeDoc(doc);
742 return;
743 }
744
745 if (!xml_isNode(node,"outfit")) {
746 free(file);
747 xmlFreeDoc(doc);
748 return;
749 }
750
751 /* Get "name" property from the "outfit" node */
752 xmlr_attr_strd(node, "name", name);
753 if (strcmp(ns->mapName, name)!=0) {
754 free(name);
755 free(file);
756 xmlFreeDoc(doc);
757 return;
758 } else {
759 free(name);
760 name = NULL;
761 }
762
763 /* Loop on the nodes to find <specific> node */
764 node = node->xmlChildrenNode;
765 do {
766 xml_onlyNodes(node);
767
768 if (!xml_isNode(node,"specific"))
769 continue;
770
771 /* Break out of the loop, either with a correct outfitType or not */
772 break;
773 } while (xml_nextNode(node));
774
776
777 /* Loop on the nodes to find all <sys> node */
778 node = node->xmlChildrenNode;
779 do {
780 xml_onlyNodes(node);
781
782 if (!xml_isNode(node,"sys"))
783 continue;
784
785 /* Display "name" property from "sys" node and increment number of systems found */
786 xmlr_attr_strd(node, "name", systemName);
787
788 /* Find system */
789 found = 0;
790 for (i=0; i<array_size(systems_stack); i++) {
791 sys = system_getIndex( i );
792 compareLimit = strlen(systemName);
793 if (strncmp(systemName, sys->name, compareLimit)==0) {
794 found = 1;
795 break;
796 }
797 }
798
799 /* If system exists, select it */
800 if (found)
801 mapedit_selectAdd( sys );
802 free( systemName );
803 systemName = NULL;
804 } while (xml_nextNode(node));
805
807
808 free(file);
809 xmlFreeDoc(doc);
810
811 window_destroy( wdw );
812}
813
817static void mapedit_btnSaveMapAs( unsigned int wdw, const char *unused )
818{
819 (void)unused;
821
822 ns.fileName = strdup( window_getInput( wdw, "inpFileName" ) );
823 ns.mapName = strdup( window_getInput( wdw, "inpMapName" ) );
824 ns.description = strdup( window_getInput( wdw, "inpDescription" ) );
825 ns.numSystems = mapedit_nsys;
826 ns.price = atoll(window_getInput( wdw, "inpPrice" ));
827 ns.rarity = atoi(window_getInput( wdw, "inpRarity" ));
828
830
831 free( ns.fileName );
832 free( ns.mapName );
833 free( ns.description );
834}
835
840{
841 char buf[32];
842
843 /* Displaying info strings */
844 window_setInput( mapedit_wid, "inpFileName", ns->fileName );
845 window_setInput( mapedit_wid, "inpMapName", ns->mapName );
846 window_setInput( mapedit_wid, "inpDescription", ns->description );
847 snprintf( buf, sizeof(buf), "%i", ns->numSystems );
848 window_modifyText( mapedit_wid, "txtCurrentNumSystems", buf );
849 snprintf( buf, sizeof(buf), "%"CREDITS_PRI, ns->price );
850 window_setInput( mapedit_wid, "inpPrice", buf );
851 snprintf( buf, sizeof(buf), "%i", ns->rarity );
852 window_setInput( mapedit_wid, "inpRarity", buf );
853
854 /* Local information. */
855 free( mapedit_sLoadMapName );
856 mapedit_sLoadMapName = strdup( ns->mapName );
857}
858
865{
866 int is_map, nSystems;
867 xmlNodePtr node, cur;
868 xmlDocPtr doc;
869 char **map_files;
870 char *file, *name, *outfitType;
871 mapOutfitsList_t *newMapItem;
872
874 mapList = array_create( mapOutfitsList_t );
875
876 map_files = PHYSFS_enumerateFiles( MAP_DATA_PATH );
877 newMapItem = NULL;
878 for (size_t i=0; map_files[i]!=NULL; i++) {
879 char *description = NULL;
880 credits_t price = 1000;
881 int rarity = 0;
882
883 asprintf( &file, "%s%s", MAP_DATA_PATH, map_files[i] );
884
885 doc = xml_parsePhysFS( file );
886 if (doc == NULL) {
887 free(file);
888 continue;
889 }
890
891 /* Get first node, normally "outfit" */
892 node = doc->xmlChildrenNode;
893 if (node == NULL) {
894 free(file);
895 xmlFreeDoc(doc);
896 return -1;
897 }
898
899 if (!xml_isNode(node,"outfit")) {
900 free(file);
901 xmlFreeDoc(doc);
902 return -1;
903 }
904
905 /* Get "name" property from the "outfit" node */
906 xmlr_attr_strd( node, "name", name );
907
908 /* Loop on the nodes to find <specific> node */
909 node = node->xmlChildrenNode;
910 do {
911 is_map = 0;
912 xml_onlyNodes(node);
913
914 if (!xml_isNode(node,"specific")) {
915 if (xml_isNode(node,"general")) {
916 cur = node->children;
917 do {
918 xml_onlyNodes(cur);
919 xmlr_str(cur,"description",description);
920 xmlr_long(cur,"price",price);
921 xmlr_int(cur,"rarity",rarity);
922 } while (xml_nextNode(cur));
923 }
924 continue;
925 }
926
927 /* Get the "type" property from "specific" node */
928 xmlr_attr_strd( node, "type", outfitType );
929 is_map = outfitType == NULL ? 0 : !strncmp(outfitType, "map", 3);
930 free(outfitType);
931
932 /* Break out of the loop, either with a map or not */
933 break;
934 } while (xml_nextNode(node));
935
936 /* If it's not a map, we don't care. */
937 if (!is_map) {
938 free(name);
939 free(file);
940 xmlFreeDoc(doc);
941 continue;
942 }
943
944 /* Loop on the nodes to find all <sys> node */
945 nSystems = 0;
946 node = node->xmlChildrenNode;
947 do {
948 xml_onlyNodes(node);
949 if (!xml_isNode(node,"sys"))
950 continue;
951
952 /* Display "name" property from "sys" node and increment number of systems found */
953 nSystems++;
954 } while (xml_nextNode(node));
955
956 /* If the map is a regular one, then load it into the list */
957 if (nSystems > 0) {
958 newMapItem = &array_grow( &mapList );
959 newMapItem->numSystems = nSystems;
960 newMapItem->fileName = strdup( map_files[ i ] );
961 newMapItem->mapName = strdup( name );
962 newMapItem->description = strdup( description != NULL ? description : "" );
963 newMapItem->price = price;
964 newMapItem->rarity = rarity;
965 }
966
967 /* Clean up. */
968 free(name);
969 free(file);
970 }
971
972 /* Clean up. */
973 PHYSFS_freeList( map_files );
974
975 return 0;
976}
977
981static void mapsList_free (void)
982{
983 unsigned int n = array_size( mapList );
984 for (unsigned int i=0; i<n; i++) {
985 free( mapList[i].fileName );
986 free( mapList[i].mapName );
987 free( mapList[i].description );
988 }
989 array_free(mapList);
990 mapList = NULL;
991
992 free( mapedit_sLoadMapName );
994}
995
1001static int mapedit_saveMap( StarSystem **uniedit_sys, mapOutfitsList_t* ns )
1002{
1003 xmlDocPtr doc;
1004 xmlTextWriterPtr writer;
1005 char *file;
1006
1007 /* Create the writer. */
1008 writer = xmlNewTextWriterDoc(&doc, 0);
1009 if (writer == NULL) {
1010 WARN(_("testXmlwriterDoc: Error creating the xml writer"));
1011 return -1;
1012 }
1013
1014 /* Set the writer parameters. */
1015 xmlw_setParams( writer );
1016
1017 /* Start writer. */
1018 xmlw_start(writer);
1019 xmlw_startElem( writer, "outfit" );
1020
1021 /* Attributes. */
1022 xmlw_attr( writer, "name", "%s", ns->mapName );
1023
1024 /* General. */
1025 xmlw_startElem( writer, "general" );
1026 xmlw_elem( writer, "rarity", "%d", ns->rarity );
1027 xmlw_elem( writer, "mass", "%d", 0 );
1028 xmlw_elem( writer, "price", "%"CREDITS_PRI, ns->price );
1029 xmlw_elem( writer, "description", "%s", ns->description );
1030 xmlw_elem( writer, "gfx_store", "%s", "map.webp" );
1031 xmlw_endElem( writer ); /* "general" */
1032
1033 xmlw_startElem( writer, "specific" );
1034 xmlw_attr( writer, "type", "map" );
1035
1036 /* Iterate over all selected systems. Save said systems and any NORMAL jumps they might share. */
1037 for (int i=0; i < ns->numSystems; i++) {
1038 StarSystem *s = uniedit_sys[i];
1039 xmlw_startElem( writer, "sys" );
1040 xmlw_attr( writer, "name", "%s", s->name );
1041
1042 /* Iterate jumps and see if they lead to any other systems in our array. */
1043 for (int j=0; j < array_size(s->jumps); j++) {
1044 /* Ignore hidden and exit-only jumps. */
1045 if (jp_isFlag(&s->jumps[j], JP_EXITONLY ))
1046 continue;
1047 if (jp_isFlag(&s->jumps[j], JP_HIDDEN))
1048 continue;
1049 /* This is a normal jump. */
1050 for (int k=0; k < ns->numSystems; k++) {
1051 if (s->jumps[j].target == uniedit_sys[k]) {
1052 xmlw_elem( writer, "jump", "%s", uniedit_sys[k]->name );
1053 break;
1054 }
1055 }
1056 }
1057
1058 /* Iterate spobs and add them */
1059 for (int j=0; j < array_size(s->spobs); j++)
1060 xmlw_elem( writer, "spob", "%s", s->spobs[j]->name );
1061
1062 xmlw_endElem( writer ); /* "sys" */
1063 }
1064
1065 xmlw_endElem( writer ); /* "specific" */
1066 xmlw_endElem( writer ); /* "outfit" */
1067 xmlw_done(writer);
1068
1069 /* No need for writer anymore. */
1070 xmlFreeTextWriter(writer);
1071
1072 /* Actually write data */
1073 asprintf( &file, "%s/%s", conf.dev_save_map, ns->fileName );
1074 if (xmlSaveFileEnc( file, doc, "UTF-8" ) < 0)
1075 WARN("Failed writing '%s'!", file);
1076 free( file );
1077
1078 /* Clean up. */
1079 xmlFreeDoc(doc);
1080
1081 return 0;
1082}
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()
Definition: dev_mapedit.c:864
static void mapedit_focusLose(unsigned int wid, const char *wgtname)
Called when it's de-focused.
Definition: dev_mapedit.c:366
static int mapedit_msys
Definition: dev_mapedit.c:89
static void mapedit_buttonZoom(unsigned int wid, const char *str)
Handles the button zoom clicks.
Definition: dev_mapedit.c:580
static void mapedit_selectRm(StarSystem *sys)
Removes a system from the selection.
Definition: dev_mapedit.c:523
static int mapedit_keys(unsigned int wid, SDL_Keycode key, SDL_Keymod mod)
Handles keybindings.
Definition: dev_mapedit.c:271
static void mapedit_btnOpen(unsigned int wid_unused, const char *unused)
Opens up a map file.
Definition: dev_mapedit.c:320
void mapedit_open(unsigned int wid_unused, const char *unused)
Opens the system editor interface.
Definition: dev_mapedit.c:131
static unsigned int mapedit_wid
Definition: dev_mapedit.c:78
static char * mapedit_sLoadMapName
Definition: dev_mapedit.c:93
#define MAPEDIT_OPEN_WIDTH
Definition: dev_mapedit.c:55
static StarSystem ** mapedit_sys
Definition: dev_mapedit.c:85
static void mapedit_loadMapMenu_update(unsigned int wdw, const char *str)
Updates the load menu.
Definition: dev_mapedit.c:661
static int mapedit_tadd
Definition: dev_mapedit.c:87
static int mapedit_moved
Definition: dev_mapedit.c:82
#define MAPEDIT_ZOOM_MIN
Definition: dev_mapedit.c:53
static void mapedit_loadMapMenu_load(unsigned int wdw, const char *str)
Load the selected Map.
Definition: dev_mapedit.c:708
static double mapedit_zoom
Definition: dev_mapedit.c:81
static int mapedit_saveMap(StarSystem **uniedit_sys, mapOutfitsList_t *ns)
Saves selected systems as a map outfit file.
Definition: dev_mapedit.c:1001
static unsigned int mapedit_widLoad
Definition: dev_mapedit.c:92
static void mapedit_btnSaveMapAs(unsigned int wid_unused, const char *unused)
Save the current Map to selected file.
Definition: dev_mapedit.c:817
#define MAPEDIT_OPEN_TXT_WIDTH
Definition: dev_mapedit.c:57
void mapedit_selectText(void)
Sets the selected system text.
Definition: dev_mapedit.c:538
static double mapedit_xpos
Definition: dev_mapedit.c:79
#define BUTTON_HEIGHT
Definition: dev_mapedit.c:43
static double mapedit_my
Definition: dev_mapedit.c:91
static void mapedit_loadMapMenu_close(unsigned int wdw, const char *str)
Closes the load map outfit menu.
Definition: dev_mapedit.c:699
StarSystem * systems_stack
Definition: space.c:92
static void mapedit_selectAdd(StarSystem *sys)
Adds a system to the selection.
Definition: dev_mapedit.c:498
static void mapsList_free(void)
Frees the loaded map.
Definition: dev_mapedit.c:981
void mapedit_setGlobalLoadedInfos(mapOutfitsList_t *ns)
Set and display the global variables describing last loaded/saved file.
Definition: dev_mapedit.c:839
static void mapedit_loadMapMenu_open(void)
Opens the load map outfit menu.
Definition: dev_mapedit.c:605
static unsigned int mapedit_dragTime
Definition: dev_mapedit.c:83
static int mapedit_iLastClickedSystem
Definition: dev_mapedit.c:86
static void mapedit_clear(unsigned int wid_unused, const char *unused)
Closes the system editor widget.
Definition: dev_mapedit.c:308
#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:90
static void mapedit_deselect(void)
Deselects selected targets.
Definition: dev_mapedit.c:482
static double mapedit_ypos
Definition: dev_mapedit.c:80
#define BUTTON_WIDTH
Definition: dev_mapedit.c:42
static int mapedit_mouse(unsigned int wid, SDL_Event *event, double mx, double my, double w, double h, double xr, double yr, void *data)
System editor custom widget mouse handling.
Definition: dev_mapedit.c:376
static int mapedit_nsys
Definition: dev_mapedit.c:88
static void mapedit_render(double bx, double by, double w, double h, void *data)
System editor custom widget rendering.
Definition: dev_mapedit.c:332
#define MAPEDIT_ZOOM_STEP
Definition: dev_mapedit.c:51
static int mapedit_drag
Definition: dev_mapedit.c:84
static void mapedit_close(unsigned int wid, const char *wgt)
Closes the system editor widget.
Definition: dev_mapedit.c:289
static StarSystem ** uniedit_sys
Definition: dev_uniedit.c:92
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 asprintf(char **strp, const char *fmt,...)
Like sprintf(), but it allocates a large-enough string and returns the pointer in the first argument....
Definition: nstring.c:161
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:178
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:2671
StarSystem * system_getIndex(int id)
Get the system by its index.
Definition: space.c:944
char * dev_save_map
Definition: conf.h:172
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:696
void window_setFocus(unsigned int wid, const char *wgtname)
Sets the focused widget in a window.
Definition: toolkit.c:2460
void window_setAccept(unsigned int wid, void(*accept)(unsigned int, const char *))
Sets the default accept function of the window.
Definition: toolkit.c:879
void window_setCancel(unsigned int wid, void(*cancel)(unsigned int, const char *))
Sets the default cancel function of the window.
Definition: toolkit.c:900
void window_handleKeys(unsigned int wid, int(*keyhandler)(unsigned int, SDL_Keycode, SDL_Keymod))
Sets the key handler for the window.
Definition: toolkit.c:972
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition: toolkit.c:1031
void window_destroy(unsigned int wid)
Kills the window.
Definition: toolkit.c:1042
void diff_clear(void)
Removes all active diffs. (Call before economy_destroy().)
Definition: unidiff.c:1472