naev 0.11.5
dev_sysedit.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_sysedit.h"
17
18#include "array.h"
19#include "conf.h"
20#include "dev_spob.h"
21#include "dev_system.h"
22#include "dev_uniedit.h"
23#include "dialogue.h"
24#include "economy.h"
25#include "map.h"
26#include "ndata.h"
27#include "nstring.h"
28#include "opengl.h"
29#include "opengl_render.h"
30#include "safelanes.h"
31#include "space.h"
32#include "tk/toolkit_priv.h"
33#include "toolkit.h"
34#include "unidiff.h"
35
36#define BUTTON_WIDTH 100
37#define BUTTON_HEIGHT 30
39#define SYSEDIT_EDIT_WIDTH 500
40#define SYSEDIT_EDIT_HEIGHT 400
42#define SYSEDIT_DRAG_THRESHOLD 300
43#define SYSEDIT_MOVE_THRESHOLD 10
45#define SYSEDIT_ZOOM_STEP 1.2
46#define SYSEDIT_ZOOM_MAX 1
47#define SYSEDIT_ZOOM_MIN -23
49/*
50 * Selection types.
51 */
52enum {
58};
59
63typedef struct Select_s {
64 int type;
65 union {
66 int spob;
67 int jump;
68 int asteroid;
69 int astexclude;
70 } u;
71} Select_t;
72static Select_t *sysedit_select = NULL;
73static int sysedit_nselect = 0;
74static int sysedit_mselect = 0;
76static int sysedit_tadd = 0;
77static char** sysedit_tagslist = NULL;
79/*
80 * System editor stuff.
81 */
82static StarSystem *sysedit_sys = NULL;
83static unsigned int sysedit_wid = 0;
84static unsigned int sysedit_widEdit = 0;
85static int sysedit_grid = 1;
86static double sysedit_xpos = 0.;
87static double sysedit_ypos = 0.;
88static double sysedit_zoom = 1.;
89static int sysedit_moved = 0;
90static unsigned int sysedit_dragTime = 0;
91static int sysedit_drag = 0;
92static int sysedit_dragSel = 0;
93static double sysedit_mx = 0.;
94static double sysedit_my = 0.;
96/* Stored checkbox values. */
97static int jp_hidden = 0;
98static int jp_exit = 0;
100/*
101 * System editor Prototypes.
102 */
103/* Custom system editor widget. */
104static void sysedit_buttonZoom( unsigned int wid, const char* str );
105static void sysedit_render( double bx, double by, double w, double h, void *data );
106static void sysedit_renderAsteroidsField( double bx, double by, const AsteroidAnchor *ast, int selected );
107static void sysedit_renderAsteroidExclusion( double bx, double by, const AsteroidExclusion *aexcl, int selected );
108static void sysedit_renderBG( double bx, double bw, double w, double h, double x, double y );
109static void sysedit_renderSprite( glTexture *gfx, double bx, double by, double x, double y,
110 int sx, int sy, const glColour *c, int selected, const char *caption );
111static void sysedit_focusLose( unsigned int wid, const char* wgtname );
112static int sysedit_mouseTrySelect( const Select_t *sel, double x, double y, double t, double mx, double my, SDL_Keymod mod, void (*func)(void) );
113static int sysedit_mouse( unsigned int wid, const SDL_Event* event, double mx, double my,
114 double w, double h, double xr, double yr, void *data );
115/* Button functions. */
116static void sysedit_close( unsigned int wid, const char *wgt );
117static void sysedit_btnNewSpob( unsigned int wid_unused, const char *unused );
118static void sysedit_btnNewAsteroids( unsigned int wid_unused, const char *unused );
119static void sysedit_btnRename( unsigned int wid_unused, const char *unused );
120static void sysedit_btnRemove( unsigned int wid_unused, const char *unused );
121static void sysedit_btnReset( unsigned int wid_unused, const char *unused );
122static void sysedit_btnScale( unsigned int wid_unused, const char *unused );
123static void sysedit_btnGrid( unsigned int wid_unused, const char *unused );
124static void sysedit_btnEdit( unsigned int wid_unused, const char *unused );
125/* Spob editing. */
126static void sysedit_editPnt (void);
127static void sysedit_editPntClose( unsigned int wid, const char *unused );
128static void sysedit_spobDesc( unsigned int wid, const char *unused );
129static void sysedit_spobDescReturn( unsigned int wid, const char *unused );
130static void sysedit_spobDescClose( unsigned int wid, const char *unused );
131static void sysedit_genServicesList( unsigned int wid );
132static void sysedit_btnTechEdit( unsigned int wid, const char *unused );
133static void sysedit_genTechList( unsigned int wid );
134static void sysedit_btnAddTech( unsigned int wid, const char *unused );
135static void sysedit_btnRmTech( unsigned int wid, const char *unused );
136static void sysedit_btnTagsEdit( unsigned int wid, const char *unused );
137static void sysedit_genTagsList( unsigned int wid );
138static void sysedit_btnAddTag( unsigned int wid, const char *unused );
139static void sysedit_btnRmTag( unsigned int wid, const char *unused );
140static void sysedit_btnNewTag( unsigned int wid, const char *unused );
141static void sysedit_btnTagsClose( unsigned int wid, const char *unused );
142static void sysedit_btnAddService( unsigned int wid, const char *unused );
143static void sysedit_btnRmService( unsigned int wid, const char *unused );
144static void sysedit_spobGFX( unsigned int wid_unused, const char *wgt );
145static void sysedit_btnGFXClose( unsigned int wid, const char *wgt );
146static void sysedit_btnGFXApply( unsigned int wid, const char *wgt );
147static void sysedit_btnFaction( unsigned int wid_unused, const char *unused );
148static void sysedit_btnFactionSet( unsigned int wid, const char *unused );
149/* Jump editing */
150static void sysedit_editJump (void);
151static void sysedit_editJumpClose( unsigned int wid, const char *unused );
152/* Asteroid editing. */
153static void sysedit_editAsteroids (void);
154static void sysedit_editAsteroidsClose( unsigned int wid, const char *unused );
155static void sysedit_genAsteroidsList( unsigned int wid );
156static void sysedit_btnAsteroidsDelete( unsigned int wid, const char *unused );
157static void sysedit_btnRmAsteroid( unsigned int wid, const char *unused );
158static void sysedit_btnAddAsteroid( unsigned int wid, const char *unused );
159/* Exclusion zone editing. */
160static void sysedit_editExclusion (void);
161static void sysedit_editExclusionClose( unsigned int wid, const char *unused );
162static void sysedit_btnExclusionDelete( unsigned int wid, const char *unused );
163/* Keybindings handling. */
164static int sysedit_keys( unsigned int wid, SDL_Keycode key, SDL_Keymod mod, int isrepeat );
165/* Selection. */
166static int sysedit_selectCmp( const Select_t *a, const Select_t *b );
167static int sysedit_isSelected( const Select_t *s );
168static void sysedit_checkButtons (void);
169static void sysedit_deselect (void);
170static void sysedit_selectAdd( const Select_t *sel );
171static void sysedit_selectRm( Select_t *sel );
172
176void sysedit_open( StarSystem *sys )
177{
178 unsigned int wid;
179 char buf[128];
180 int i;
181 const glColour cBG = { 0., 0., 0., 0.95 };
182
183 /* Reconstructs the jumps - just in case. */
185
186 /* Reset some variables. */
187 sysedit_sys = sys;
188 sysedit_drag = 0;
190 sysedit_xpos = 0.;
191 sysedit_ypos = 0.;
192
193 /* Load graphics. */
195
196 /* Create the window. */
197 snprintf( buf, sizeof(buf), _("%s - Star System Editor"), sys->name );
198 wid = window_create( "wdwSysEdit", buf, -1, -1, -1, -1 );
199 window_setDynamic( wid, 1 );
201 window_setBorder( wid, 0 );
202 sysedit_wid = wid;
203
205
206 /* Actual viewport, at the bottom. */
207 window_addCust( wid, 0, 0, SCREEN_W, SCREEN_H,
208 "cstSysEdit", 1, sysedit_render, sysedit_mouse, NULL, sysedit_focusLose, NULL );
209
210 /* Overlay background. */
211 window_addRect( wid, SCREEN_W-130, 0, 130, SCREEN_H, "rctRCol", &cBG, 0 );
212 window_addRect( wid, 0, 0, SCREEN_W, 60, "rctBBar", &cBG, 0 );
213
214 /* Close button. */
215 window_addButtonKey( wid, -15, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
216 "btnClose", _("Exit"), sysedit_close, SDLK_x );
217 i = 1;
218
219 /* Autosave toggle. */
220 window_addCheckbox( wid, -150, 25, SCREEN_W/2 - 150, 20,
221 "chkEditAutoSave", _("Automatically save changes"), uniedit_autosave, conf.devautosave );
222
223 /* Scale. */
224 window_addButton( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
225 "btnScale", _("Scale"), sysedit_btnScale );
226 i += 1;
227
228 /* Reset. */
229 window_addButtonKey( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
230 "btnReset", _("Reset Jumps"), sysedit_btnReset, SDLK_r );
231 i += 1;
232
233 /* Editing. */
234 window_addButtonKey( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
235 "btnEdit", _("Edit"), sysedit_btnEdit, SDLK_e );
236 i += 1;
237
238 /* Remove. */
239 window_addButton( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
240 "btnRemove", _("Remove"), sysedit_btnRemove );
241 i += 1;
242
243 /* Rename. */
244 window_addButton( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
245 "btnRename", _("Rename"), sysedit_btnRename );
246 i += 1;
247
248 /* New spob. */
249 window_addButtonKey( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
250 "btnNewSpob", _("New Spob"), sysedit_btnNewSpob, SDLK_n );
251 i += 1;
252
253 /* New asteroids. */
254 window_addButtonKey( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
255 "btnNewAsteroids", _("New Asteroids"), sysedit_btnNewAsteroids, SDLK_a );
256 i += 1;
257
258 /* Toggle Grid. */
259 window_addButtonKey( wid, -15, 20+(BUTTON_HEIGHT+20)*i, BUTTON_WIDTH, BUTTON_HEIGHT,
260 "btnGrid", _("Grid"), sysedit_btnGrid, SDLK_g );
261
262 /* Zoom buttons */
263 window_addButton( wid, 40, 20, 30, 30, "btnZoomIn", "+", sysedit_buttonZoom );
264 window_addButton( wid, 80, 20, 30, 30, "btnZoomOut", "-", sysedit_buttonZoom );
265
266 /* Selected text. */
267 snprintf( buf, sizeof(buf), _("Radius: %.0f"), sys->radius );
268 window_addText( wid, 140, 10, SCREEN_W/2-140, 30, 0,
269 "txtSelected", &gl_smallFont, NULL, buf );
270
271 /* Deselect everything. */
273}
274
278static int sysedit_keys( unsigned int wid, SDL_Keycode key, SDL_Keymod mod, int isrepeat )
279{
280 (void) wid;
281 (void) mod;
282 (void) isrepeat;
283
284 switch (key) {
285
286 default:
287 return 0;
288 }
289}
290
294static void sysedit_close( unsigned int wid, const char *wgt )
295{
296 /* Unload graphics. */
298
299 /* Remove selection. */
301
302 /* Set the dominant faction. */
304
305 /* Update asteroid info. */
307
308 /* Save the system */
309 if (conf.devautosave)
311
312 /* Reconstruct universe presences. */
315
316 /* Close the window. */
317 window_close( wid, wgt );
318
319 /* Update the universe editor's sidebar text. */
321
322 /* Propagate autosave checkbox state */
323 uniedit_updateAutosave();
324
325 /* Unset. */
326 sysedit_wid = 0;
327}
328
332static void sysedit_editPntClose( unsigned int wid, const char *unused )
333{
334 (void) unused;
335 const char *inp;
336 Spob *p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
337
338 p->population = (uint64_t)strtoull( window_getInput( sysedit_widEdit, "inpPop" ), 0, 10);
339
340 inp = window_getInput( sysedit_widEdit, "inpClass" );
341 free( p->class );
342
343 if (inp[0] == '\0')
344 p->class = NULL;
345 else
346 p->class = strdup( inp );
347
348 inp = window_getInput( sysedit_widEdit, "inpLua" );
349 free( p->lua_file );
350
351 if ((inp == NULL) || (strlen(inp) == 0))
352 p->lua_file = NULL;
353 else
354 p->lua_file = strdup( inp );
355
356 p->presence.base = atof(window_getInput( sysedit_widEdit, "inpPresenceBase" ));
357 p->presence.bonus = atof(window_getInput( sysedit_widEdit, "inpPresenceBonus" ));
358 p->presence.range = atoi(window_getInput( sysedit_widEdit, "inpPresenceRange" ));
359 p->hide = atof(window_getInput( sysedit_widEdit, "inpHide" ));
360
361 for (int i=0; i<array_size(sysedit_tagslist); i++)
362 free( sysedit_tagslist[i] );
364 sysedit_tagslist = NULL;
365
366 /* Have to recompute presences if stuff changed. */
368
369 if (conf.devautosave)
370 dpl_saveSpob( p );
371
372 /* Clean up presences. */
375
376 window_close( wid, unused );
377}
378
382static void sysedit_btnNewSpob( unsigned int wid_unused, const char *unused )
383{
384 (void) wid_unused;
385 (void) unused;
386 Spob *p, *b;
387 char *name;
388 int good;
389
390 /* Get new name. */
391 name = dialogue_inputRaw( _("New Spob Creation"), 1, 32, _("What do you want to name the new spob?") );
392 if (name == NULL)
393 return;
394
395 /* Check for collision. */
396 if (spob_exists( name )) {
397 dialogue_alert( _("Space object by the name of #r'%s'#0 already exists in the #r'%s'#0 system"),
398 name, spob_getSystem( name ) );
399 free(name);
400 sysedit_btnNewSpob( 0, NULL );
401 return;
402 }
403
404 /* Create the new spob. */
405 p = spob_new();
406 p->name = name;
407
408 /* Base spob data off another. */
409 good = 0;
410 while (!good) {
411 b = spob_get( space_getRndSpob(0, 0, NULL) );
412 good = !((b->class==NULL) ||
413 (b->gfx_spacePath==NULL) || (b->gfx_spaceName==NULL) ||
414 (b->gfx_exterior==NULL) || (b->gfx_exteriorPath==NULL));
415
416 }
417 p->class = strdup( b->class );
418 p->gfx_spacePath = strdup( b->gfx_spacePath );
419 p->gfx_spaceName = strdup( b->gfx_spaceName );
420 p->gfx_exterior = strdup( b->gfx_exterior );
421 p->gfx_exteriorPath = strdup( b->gfx_exteriorPath );
422 p->pos.x = sysedit_xpos / sysedit_zoom;
423 p->pos.y = sysedit_ypos / sysedit_zoom;
424 p->hide = HIDE_DEFAULT_SPOB;
425 p->radius = b->radius;
426
427 /* Add new spob. */
429
430 /* Run galaxy modifications. */
433
434 if (conf.devautosave) {
436 dpl_saveSpob( p );
437 }
438
439 /* Reload graphics. */
441}
442
443
447static void sysedit_btnNewAsteroids( unsigned int wid_unused, const char *unused )
448{
449 (void) wid_unused;
450 (void) unused;
451 const char *title, *caption;
452 char *ret;
453 const char *opts[] = {
454 _("Asteroid Field"),
455 _("Exclusion Zone"),
456 };
457
458 /* See if we want to make a field or exclusion zone. */
459 title = _("Add asteriod field or exclusion zone?");
460 caption = _("Do you wish to add an asteroid field or an asteroid exclusion zone that will remove all asteroids that will appear in it?");
461 dialogue_makeChoice( title, caption, 2 );
462 dialogue_addChoice( title, caption, opts[0] );
463 dialogue_addChoice( title, caption, opts[1] );
464 ret = dialogue_runChoice();
465 if (ret==NULL)
466 ret = strdup(opts[0]);
467
468 if (strcmp(ret, opts[0])==0) {
469 AsteroidAnchor *ast = &array_grow( &sysedit_sys->asteroids );
470 memset( ast, 0, sizeof(AsteroidAnchor) );
471 ast->density = ASTEROID_DEFAULT_DENSITY;
473 ast->groupsw = array_create( double );
474 ast->radius = 2500.;
475 ast->maxspeed = ASTEROID_DEFAULT_MAXSPEED;
476 ast->accel = ASTEROID_DEFAULT_ACCEL;
480 }
481 else {
482 AsteroidExclusion *exc = &array_grow( &sysedit_sys->astexclude );
483 memset( exc, 0, sizeof(AsteroidExclusion) );
484 exc->radius = 1000.;
487 }
488
489 if (conf.devautosave)
491
492 /* Must free. */
493 free(ret);
494}
495
496static void sysedit_btnRename( unsigned int wid_unused, const char *unused )
497{
498 (void) wid_unused;
499 (void) unused;
500 for (int i=0; i<sysedit_nselect; i++) {
501 Select_t *sel = &sysedit_select[i];
502 if (sel->type != SELECT_SPOB)
503 continue;
504
505 char *name, *oldName, *newName, *filtered;
506 Spob *p = sysedit_sys[i].spobs[ sel->u.spob ];
507
508 /* Get new name. */
509 name = dialogue_input( _("Rename Spob"), 1, 32,
510 _("What do you want to rename the spob #r%s#0?"), p->name );
511 if (name == NULL)
512 continue;
513
514 /* Check for collision. */
515 if (spob_exists( name )) {
516 dialogue_alert( _("Space object by the name of #r'%s'#0 already exists in the #r'%s'#0 system"),
517 name, spob_getSystem( name ) );
518 free(name);
519 continue;
520 }
521
522 /* Rename. */
523 filtered = uniedit_nameFilter(p->name);
524 SDL_asprintf(&oldName, "%s/%s.xml", conf.dev_save_spob, filtered);
525 free(filtered);
526
527 filtered = uniedit_nameFilter(name);
528 SDL_asprintf(&newName, "%s/%s.xml", conf.dev_save_spob, filtered);
529 free(filtered);
530
531 if (rename(oldName, newName))
532 WARN(_("Failed to rename '%s' to '%s'!"),oldName,newName);
533
534 /* Clean up. */
535 free(oldName);
536 free(newName);
537
538 /* Replace name in stack. */
539 spob_rename( p, name );
540
542 dpl_saveSpob( p );
543
544 /* Rename input if called from edit window. */
546 window_modifyText( sysedit_widEdit, "txtName", p->name );
547 }
548}
549
553static void sysedit_btnRemove( unsigned int wid_unused, const char *unused )
554{
555 (void) wid_unused;
556 (void) unused;
557 char *file, *filtered;
558
559 if (dialogue_YesNo( _("Remove selected objects (excluding jumps)?"), _("This can not be undone.") )) {
560 for (int i=0; i<sysedit_nselect; i++) {
561 Select_t *sel = &sysedit_select[i];
562 if (sel->type == SELECT_SPOB) {
563 Spob *sp = sysedit_sys->spobs[ sel->u.spob ];
564 filtered = uniedit_nameFilter( sp->name );
565 SDL_asprintf(&file, "%s/%s.xml", conf.dev_save_spob, filtered);
566 remove(file);
567
568 free(filtered);
569 free(file);
570
572 }
573 else if (sel->type == SELECT_ASTEROID) {
574 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sel->u.asteroid ];
575 asteroid_free( ast );
576 array_erase( &sysedit_sys->asteroids, ast, ast+1 );
577 }
578 else if (sel->type == SELECT_ASTEXCLUDE ){
579 AsteroidExclusion *exc = &sysedit_sys->astexclude[ sel->u.astexclude ];
580
581 array_erase( &sysedit_sys->astexclude, exc, exc+1 );
582 }
583 }
584
585 /* Run galaxy modifications. */
588 }
589}
590
594static void sysedit_btnReset( unsigned int wid_unused, const char *unused )
595{
596 (void) wid_unused;
597 (void) unused;
598 for (int i=0; i<sysedit_nselect; i++) {
599 Select_t *sel = &sysedit_select[i];
600 if (sel->type == SELECT_JUMPPOINT)
601 sysedit_sys[i].jumps[ sel->u.jump ].flags |= JP_AUTOPOS;
602 }
603
604 /* Must reconstruct jumps. */
606}
607
611static void sysedit_btnScale( unsigned int wid_unused, const char *unused )
612{
613 (void) wid_unused;
614 (void) unused;
615 char *str;
616 double s;
617 StarSystem *sys;
618
619 /* Prompt scale amount. */
620 str = dialogue_inputRaw( _("Scale Star System"), 1, 32, _("By how much do you want to scale the star system?") );
621 if (str == NULL)
622 return;
623
624 sys = sysedit_sys; /* Comfort. */
625 s = atof(str);
626 free(str);
627
628 /* In case screwed up. */
629 if ((s < 0.1) || (s > 10.)) {
630 int i = dialogue_YesNo( _("Scale Star System"), _("Are you sure you want to scale the star system by %.2f (from %.2f to %.2f)?"),
631 s, sys->radius, sys->radius*s );
632 if (i==0)
633 return;
634 }
635
636 sysedit_sysScale(sys, s);
637}
638
642void sysedit_sysScale( StarSystem *sys, double factor )
643{
644 char buf[STRMAX];
645
646 /* Scale radius. */
647 sys->radius *= factor;
648 snprintf( buf, sizeof(buf), _("Radius: %.0f"), sys->radius );
649 if (sysedit_wid > 0)
650 window_modifyText( sysedit_wid, "txtSelected", buf );
651
652 /* Scale spobs. */
653 for (int i=0; i<array_size(sys->spobs); i++) {
654 Spob *p = sys->spobs[i];
655 vec2_cset( &p->pos, p->pos.x*factor, p->pos.y*factor );
656 }
657
658 /* Scale jumps. */
659 for (int i=0; i<array_size(sys->jumps); i++) {
660 JumpPoint *jp = &sys->jumps[i];
661 vec2_cset( &jp->pos, jp->pos.x*factor, jp->pos.y*factor );
662 }
663
664 /* Scale asteroids. */
665 for (int i=0; i<array_size(sys->asteroids); i++) {
666 AsteroidAnchor *ast = &sys->asteroids[i];
667 vec2_cset( &ast->pos, ast->pos.x*factor, ast->pos.y*factor );
668 ast->radius *= factor;
669 }
670 for (int i=0; i<array_size(sys->astexclude); i++) {
671 AsteroidExclusion *exc = &sys->astexclude[i];
672 vec2_cset( &exc->pos, exc->pos.x*factor, exc->pos.y*factor );
673 exc->radius *= factor;
674 }
675
676 /* Must reconstruct jumps. */
678}
679
683static void sysedit_btnGrid( unsigned int wid_unused, const char *unused )
684{
685 (void) wid_unused;
686 (void) unused;
687
689}
690
694static void sysedit_render( double bx, double by, double w, double h, void *data )
695{
696 (void) data;
697 StarSystem *sys;
698 double x,y, z;
699
700 /* Comfort++. */
701 sys = sysedit_sys;
702 z = sysedit_zoom;
703
704 /* Coordinate translation. */
705 x = bx - sysedit_xpos + w/2;
706 y = by - sysedit_ypos + h/2;
707
708 /* First render background with lines. */
709 sysedit_renderBG( bx, by, w, h, x, y );
710
711 /* Render spobs. */
712 for (int i=0; i<array_size(sys->spobs); i++) {
713 Spob *p = sys->spobs[i];
714 const Select_t sel = {
715 .type = SELECT_SPOB,
716 .u.spob = i,
717 };
718 int selected = sysedit_isSelected( &sel );
719 /* TODO handle non-sprite rendering. */
720 if (p->gfx_space != NULL)
721 sysedit_renderSprite( p->gfx_space, x, y, p->pos.x, p->pos.y, 0, 0, NULL, selected, p->name );
722 }
723
724 /* Render jump points. */
725 for (int i=0; i<array_size(sys->jumps); i++) {
726 const glColour *c;
727 JumpPoint *jp = &sys->jumps[i];
728 const Select_t sel = {
729 .type = SELECT_JUMPPOINT,
730 .u.jump = i,
731 };
732 int selected = sysedit_isSelected( &sel );
733
734 /* Choose colour. */
735 c = (jp->flags & JP_AUTOPOS) ? &cGreen : NULL;
736
737 /* Render. */
738 sysedit_renderSprite( jumppoint_gfx, x, y, jp->pos.x, jp->pos.y,
739 jp->sx, jp->sy, c, selected, jp->target->name );
740 }
741
742 /* Render asteroids */
743 for (int i=0; i<array_size(sys->asteroids); i++) {
744 AsteroidAnchor *ast = &sys->asteroids[i];
745 const Select_t sel = {
746 .type = SELECT_ASTEROID,
747 .u.asteroid = i,
748 };
749 int selected = sysedit_isSelected( &sel );
750 sysedit_renderAsteroidsField( x, y, ast, selected );
751 }
752
753 /* Render asteroid exclusions */
754 for (int i=0; i<array_size(sys->astexclude); i++) {
755 AsteroidExclusion *aexcl = &sys->astexclude[i];
756 const Select_t sel = {
757 .type = SELECT_ASTEXCLUDE,
758 .u.astexclude = i,
759 };
760 int selected = sysedit_isSelected( &sel );
761 sysedit_renderAsteroidExclusion( x, y, aexcl, selected );
762 }
763
764 /* Render safe lanes. */
765 SafeLane* safelanes = safelanes_get( -1, 0, sys );
766 for (int i=0; i<array_size(safelanes); i++) {
767 vec2 *posns[2];
768 Spob *pnt;
769 JumpPoint *njp;
770 glColour col;
771 SafeLane *sf = &safelanes[i];
772
773 for (int j=0; j<2; j++) {
774 switch(sf->point_type[j]) {
775 case SAFELANE_LOC_SPOB:
776 pnt = spob_getIndex( sf->point_id[j] );
777 posns[j] = &pnt->pos;
778 break;
779 case SAFELANE_LOC_DEST_SYS:
780 njp = jump_getTarget( system_getIndex( sf->point_id[j] ), sys );
781 posns[j] = &njp->pos;
782 break;
783 default:
784 ERR( _("Invalid vertex type.") );
785 }
786 }
787
788 col = *faction_colour( sf->faction );
789 col.a = 0.3;
790
791 /* Get positions and stuff. */
792 double x1, y1, x2, y2, ry, rx, r, rw, rh;
793 x1 = x + posns[0]->x * z;
794 y1 = y + posns[0]->y * z;
795 x2 = x + posns[1]->x * z;
796 y2 = y + posns[1]->y * z;
797 rx = x2-x1;
798 ry = y2-y1;
799 r = atan2( ry, rx );
800 rw = MOD(rx,ry)/2.;
801 rh = 9.;
802
803 /* Render. */
804 glUseProgram(shaders.safelane.program);
805 gl_renderShader( (x1+x2)/2., (y1+y2)/2., rw, rh, r, &shaders.safelane, &col, 1 );
806 }
807 array_free( safelanes );
808
809 /* Render cursor position. */
810 gl_print( &gl_defFontMono, bx + 5., by + 65.,
811 &cWhite, "% 9.2f x % 9.2f",
812 (bx + sysedit_mx - x)/z,
813 (by + sysedit_my - y)/z );
814}
815
820static void sysedit_renderAsteroidsField( double bx, double by, const AsteroidAnchor *ast, int selected )
821{
822 double tx, ty, z;
823
824 /* Inits. */
825 z = sysedit_zoom;
826
827 /* Translate asteroid field center's coords. */
828 tx = bx + ast->pos.x*z;
829 ty = by + ast->pos.y*z;
830
831 if (selected) {
832 const glColour csel = COL_ALPHA( cFontBlue, 0.5 );
833 gl_renderCircle( tx, ty, ast->radius * sysedit_zoom, &csel, 1 );
834 }
835
836 gl_renderCircle( tx, ty, ast->radius * sysedit_zoom, &cOrange, 0 );
838 tx - 100, ty - gl_smallFont.h/2.,
839 (selected) ? &cRed : NULL, -1., _("Asteroid Field") );
840}
841
846static void sysedit_renderAsteroidExclusion( double bx, double by, const AsteroidExclusion *aexcl, int selected )
847{
848 double tx, ty, z, r, rr;
849 const glColour *col;
850
851 /* Inits. */
852 z = sysedit_zoom;
853
854 /* Translate asteroid field center's coords. */
855 tx = bx + aexcl->pos.x*z;
856 ty = by + aexcl->pos.y*z;
857 r = aexcl->radius * sysedit_zoom;
858 rr = r * sin(M_PI / 4.);
859
860 if (selected) {
861 const glColour csel = COL_ALPHA( cFontBlue, 0.5 );
862 gl_renderCircle( tx, ty, aexcl->radius * sysedit_zoom, &csel, 1 );
863 }
864
865 col = (selected) ? &cWhite : &cRed;
866
867 gl_renderCircle( tx, ty, r, col, 0 );
868 gl_renderCross( tx, ty, r, col );
869 gl_renderRectEmpty( tx - rr, ty - rr, rr * 2, rr * 2, col );
870}
871
875static void sysedit_renderBG( double bx, double by, double w, double h, double x, double y )
876{
877 /* Comfort. */
878 const double z = sysedit_zoom;
879 const double s = 1000.;
880
881 /* Vars */
882 double startx, starty, spacing;
883 int nx, ny;
884
885 /* Render blackness. */
886 gl_renderRect( bx, by, w, h, &cBlack );
887
888 /* Must have grid activated. */
889 if (!sysedit_grid)
890 return;
891
892 /* Draw lines that go through 0,0 */
893 gl_renderRect( x - 1., by, 3., h, &cLightBlue );
894 gl_renderRect( bx, y - 1., w, 3., &cLightBlue );
895
896 /* Render lines. */
897 spacing = s * z;
898 startx = bx + fmod( x - bx, spacing );
899 starty = by + fmod( y - by, spacing );
900
901 nx = lround( w / spacing );
902 ny = lround( h / spacing );
903
904 /* Vertical. */
905 for (int i=0; i<nx; i++) {
906 double d = startx + (i * spacing);
907 gl_renderLine( d, by, d, by + h, &cBlue );
908 }
909 /* Horizontal. */
910 for (int i=0; i<ny; i++) {
911 double d = starty + (i * spacing);
912 gl_renderLine( bx, d, bx + w, d, &cBlue );
913 }
914
915 gl_renderCircle( x, y, sysedit_sys->radius * z, &cLightBlue, 0 );
916}
917
921static void sysedit_renderSprite( glTexture *gfx, double bx, double by, double x, double y,
922 int sx, int sy, const glColour *c, int selected, const char *caption )
923{
924 double tx, ty, z;
925 const glColour *col;
926
927 /* Comfort. */
928 z = sysedit_zoom;
929
930 /* Selection graphic. */
931 if (selected) {
932 const glColour csel = COL_ALPHA( cFontBlue, 0.5 );
933 gl_renderCircle( bx + x*z, by + y*z, gfx->sw*z*1.1, &csel, 1 );
934 }
935
936 /* Translate coords. */
937 tx = bx + (x - gfx->sw/2.)*z;
938 ty = by + (y - gfx->sh/2.)*z;
939 /* Blit the spob. */
940 gl_renderScaleSprite( gfx, tx, ty, sx, sy, gfx->sw*z, gfx->sh*z, c );
941
942 /* Display caption. */
943 if (caption != NULL) {
944 if (selected)
945 col = &cRed;
946 else
947 col = c;
948 gl_printMidRaw( &gl_smallFont, gfx->sw*z+100,
949 tx - 50, ty - gl_smallFont.h - 5, col, -1., caption );
950 }
951}
952
956static void sysedit_focusLose( unsigned int wid, const char* wgtname )
957{
958 (void) wid;
959 (void) wgtname;
961}
962
963static int sysedit_mouseTrySelect( const Select_t *sel, double x, double y, double t, double mx, double my, SDL_Keymod mod, void (*func)(void) )
964{
965 x *= sysedit_zoom;
966 y *= sysedit_zoom;
967
968 if ((pow2(mx-x)+pow2(my-y)) > t)
969 return 0;
970
971 /* Check if already selected. */
972 for (int j=0; j<sysedit_nselect; j++) {
973 if (!sysedit_selectCmp( sel, &sysedit_select[j] ))
974 continue;
975
976 sysedit_dragSel = 1;
977 sysedit_tsel = *sel;
978
979 /* Check modifier. */
980 if (mod & (KMOD_LCTRL | KMOD_RCTRL))
981 sysedit_tadd = 0;
982 else {
983 /* Detect double click to open spob editor. */
984 if ((SDL_GetTicks() - sysedit_dragTime < SYSEDIT_DRAG_THRESHOLD*2)
986 if (func != NULL)
987 func();
988 sysedit_dragSel = 0;
989 return 1;
990 }
991 sysedit_tadd = -1;
992 }
993 sysedit_dragTime = SDL_GetTicks();
994 sysedit_moved = 0;
995 return 1;
996 }
997
998 /* Add the system if not selected. */
999 if (mod & (KMOD_LCTRL | KMOD_RCTRL))
1000 sysedit_selectAdd( sel );
1001 else {
1003 sysedit_selectAdd( sel );
1004 }
1006
1007 /* Start dragging anyway. */
1008 sysedit_dragSel = 1;
1009 sysedit_dragTime = SDL_GetTicks();
1010 sysedit_moved = 0;
1011 return 1;
1012}
1013
1017static int sysedit_mouse( unsigned int wid, const SDL_Event* event, double mx, double my,
1018 double w, double h, double xr, double yr, void *data )
1019{
1020 (void) data;
1021 StarSystem *sys = sysedit_sys;
1022 SDL_Keymod mod = SDL_GetModState();
1023
1024 switch (event->type) {
1025
1026 case SDL_MOUSEWHEEL:
1027 /* Must be in bounds. */
1028 if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
1029 return 0;
1030
1031 if (event->wheel.y > 0)
1032 sysedit_buttonZoom( 0, "btnZoomIn" );
1033 else if (event->wheel.y < 0)
1034 sysedit_buttonZoom( 0, "btnZoomOut" );
1035
1036 return 1;
1037
1038 case SDL_MOUSEBUTTONDOWN:
1039 /* Must be in bounds. */
1040 if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
1041 return 0;
1042 window_setFocus( wid, "cstSysEdit" );
1043
1044 /* selecting star system */
1045 mx -= w/2 - sysedit_xpos;
1046 my -= h/2 - sysedit_ypos;
1047
1048 /* Check spobs. */
1049 for (int i=0; i<array_size(sys->spobs); i++) {
1050 Spob *p = sys->spobs[i];
1051 const Select_t sel = {
1052 .type = SELECT_SPOB,
1053 .u.spob = i,
1054 };
1055
1056 /* Threshold. */
1057 double t = pow2(p->radius); /* Radius^2 */
1058 t *= pow2(2.*sysedit_zoom);
1059
1060 /* Try to select. */
1061 if (sysedit_mouseTrySelect( &sel, p->pos.x, p->pos.y, t, mx, my, mod, sysedit_editPnt ))
1062 return 1;
1063 }
1064
1065 /* Check jump points. */
1066 for (int i=0; i<array_size(sys->jumps); i++) {
1067 JumpPoint *jp = &sys->jumps[i];
1068 const Select_t sel = {
1069 .type = SELECT_JUMPPOINT,
1070 .u.jump = i,
1071 };
1072
1073 /* Threshold. */
1074 double t = jumppoint_gfx->sw * jumppoint_gfx->sh / 4.; /* Radius^2 */
1075 t *= pow2(2.*sysedit_zoom);
1076
1077 /* Try to select. */
1078 if (sysedit_mouseTrySelect( &sel, jp->pos.x, jp->pos.y, t, mx, my, mod, sysedit_editJump ))
1079 return 1;
1080 }
1081
1082 /* Check asteroids exclusions. */
1083 for (int i=0; i<array_size(sys->astexclude); i++) {
1084 AsteroidExclusion *exc = &sys->astexclude[i];
1085 const Select_t sel = {
1086 .type = SELECT_ASTEXCLUDE,
1087 .u.astexclude = i,
1088 };
1089 double t = pow2(exc->radius*sysedit_zoom);
1090
1091 /* Try to select. */
1092 if (sysedit_mouseTrySelect( &sel, exc->pos.x, exc->pos.y, t, mx, my, mod, sysedit_editExclusion ))
1093 return 1;
1094 }
1095
1096 /* Check asteroids. */
1097 for (int i=0; i<array_size(sys->asteroids); i++) {
1098 AsteroidAnchor *ast = &sys->asteroids[i];
1099 const Select_t sel = {
1100 .type = SELECT_ASTEROID,
1101 .u.asteroid = i,
1102 };
1103 double t = pow2(ast->radius*sysedit_zoom);
1104
1105 /* Try to select. */
1106 if (sysedit_mouseTrySelect( &sel, ast->pos.x, ast->pos.y, t, mx, my, mod, sysedit_editAsteroids ))
1107 return 1;
1108 }
1109
1110 /* Start dragging. */
1111 if (!(mod & (KMOD_LCTRL | KMOD_RCTRL))) {
1112 sysedit_drag = 1;
1113 sysedit_dragTime = SDL_GetTicks();
1114 sysedit_moved = 0;
1116 }
1117 return 1;
1118
1119 case SDL_MOUSEBUTTONUP:
1120 if (sysedit_drag) {
1124 else
1126 }
1127 sysedit_drag = 0;
1128
1129 if (conf.devautosave) {
1131 for (int i=0; i<sysedit_nselect; i++)
1132 if (sysedit_select[i].type == SELECT_SPOB)
1133 dpl_saveSpob( sys->spobs[ sysedit_select[i].u.spob ] );
1134 }
1135 }
1136 if (sysedit_dragSel) {
1137 if ((SDL_GetTicks() - sysedit_dragTime < SYSEDIT_DRAG_THRESHOLD) &&
1139 if (sysedit_tadd == 0)
1141 else {
1144 }
1145 }
1146 sysedit_dragSel = 0;
1147
1148 /* Save all spobs in our selection - their positions might have changed. */
1149 if (conf.devautosave) {
1151 for (int i=0; i<sysedit_nselect; i++)
1152 if (sysedit_select[i].type == SELECT_SPOB)
1153 dpl_saveSpob( sys->spobs[ sysedit_select[i].u.spob ] );
1154 }
1155 }
1156 break;
1157
1158 case SDL_MOUSEMOTION:
1159 /* Update mouse positions. */
1160 sysedit_mx = mx;
1161 sysedit_my = my;
1162
1163 /* Handle dragging. */
1164 if (sysedit_drag) {
1165 /* axis is inverted */
1166 sysedit_xpos -= xr;
1167 sysedit_ypos += yr;
1168
1169 /* Update mouse movement. */
1170 sysedit_moved += ABS(xr) + ABS(yr);
1171 }
1172 /* Dragging selection around. */
1173 else if (sysedit_dragSel && (sysedit_nselect > 0)) {
1175 double xmove = xr / sysedit_zoom;
1176 double ymove = -yr / sysedit_zoom;
1177 for (int i=0; i<sysedit_nselect; i++) {
1178 Spob *p;
1179 JumpPoint *jp;
1180 AsteroidAnchor *ast;
1181 AsteroidExclusion *exc;
1182 Select_t *sel = &sysedit_select[i];
1183
1184 switch (sel->type) {
1185 case SELECT_SPOB:
1186 p = sys->spobs[ sel->u.spob ];
1187 p->pos.x += xmove;
1188 p->pos.y += ymove;
1189 break;
1190
1191 case SELECT_JUMPPOINT:
1192 jp = &sys->jumps[ sel->u.jump ];
1193 jp->flags &= ~(JP_AUTOPOS);
1194 jp->pos.x += xmove;
1195 jp->pos.y += ymove;
1196 break;
1197
1198 case SELECT_ASTEROID:
1199 ast = &sys->asteroids[ sel->u.asteroid ];
1200 ast->pos.x += xmove;
1201 ast->pos.y += ymove;
1202 break;
1203
1204 case SELECT_ASTEXCLUDE:
1205 exc = &sys->astexclude[ sel->u.astexclude ];
1206 exc->pos.x += xmove;
1207 exc->pos.y += ymove;
1208 break;
1209 }
1210 }
1211 }
1212
1213 /* Update mouse movement. */
1214 sysedit_moved += ABS(xr) + ABS(yr);
1215 }
1216 break;
1217 }
1218
1219 return 0;
1220}
1221
1228static void sysedit_buttonZoom( unsigned int wid, const char* str )
1229{
1230 (void) wid;
1231
1232 /* Transform coords to normal. */
1235
1236 /* Apply zoom. */
1237 if (strcmp(str,"btnZoomIn")==0) {
1240 }
1241 else if (strcmp(str,"btnZoomOut")==0) {
1244 }
1245
1246 /* Transform coords back. */
1249}
1250
1254static void sysedit_deselect (void)
1255{
1256 if (sysedit_nselect > 0)
1257 free( sysedit_select );
1258 sysedit_select = NULL;
1259 sysedit_nselect = 0;
1260 sysedit_mselect = 0;
1261
1262 /* Button check. */
1264}
1265
1269static void sysedit_checkButtons (void)
1270{
1271 int sel_spob, sel_jump, sel_asteroid, sel_exclusion;
1272
1273 /* See if a spob or jump is selected. */
1274 sel_spob = 0;
1275 sel_jump = 0;
1276 sel_asteroid = 0;
1277 sel_exclusion = 0;
1278 for (int i=0; i<sysedit_nselect; i++) {
1279 Select_t *sel = &sysedit_select[i];
1280 switch (sel->type) {
1281 case SELECT_SPOB:
1282 sel_spob++;
1283 break;
1284 case SELECT_JUMPPOINT:
1285 sel_spob++;
1286 break;
1287 case SELECT_ASTEROID:
1288 sel_asteroid++;
1289 break;
1290 case SELECT_ASTEXCLUDE:
1291 sel_exclusion++;
1292 break;
1293 }
1294 }
1295
1296 /* Spob dependent. */
1297 if (sel_spob || sel_asteroid || sel_exclusion)
1298 window_enableButton( sysedit_wid, "btnRemove" );
1299 else
1300 window_disableButton( sysedit_wid, "btnRemove" );
1301 if (sel_spob && (sysedit_nselect==1))
1302 window_enableButton( sysedit_wid, "btnRename" );
1303 else
1304 window_disableButton( sysedit_wid, "btnRename" );
1305
1306 /* Jump dependent. */
1307 if (sel_jump)
1308 window_enableButton( sysedit_wid, "btnReset" );
1309 else
1310 window_disableButton( sysedit_wid, "btnReset" );
1311
1312 /* Editor - just one spob. */
1313 if (sysedit_nselect==1)
1314 window_enableButton( sysedit_wid, "btnEdit" );
1315 else
1316 window_disableButton( sysedit_wid, "btnEdit" );
1317}
1318
1322static void sysedit_selectAdd( const Select_t *sel )
1323{
1324 /* Allocate if needed. */
1326 if (sysedit_mselect == 0)
1327 sysedit_mselect = 1;
1328 sysedit_mselect *= 2;
1329 sysedit_select = realloc( sysedit_select,
1330 sizeof(Select_t) * sysedit_mselect );
1331 }
1332
1333 /* Add system. */
1336
1337 /* Button check. */
1339}
1340
1344static void sysedit_selectRm( Select_t *sel )
1345{
1346 for (int i=0; i<sysedit_nselect; i++) {
1347 if (sysedit_selectCmp( &sysedit_select[i], sel )) {
1349 memmove( &sysedit_select[i], &sysedit_select[i+1],
1350 sizeof(Select_t) * (sysedit_nselect - i) );
1351 /* Button check. */
1353 return;
1354 }
1355 }
1356 WARN(_("Trying to deselect item that is not in selection!"));
1357}
1358
1364static int sysedit_selectCmp( const Select_t *a, const Select_t *b )
1365{
1366 return (memcmp(a, b, sizeof(Select_t)) == 0);
1367}
1368
1372static int sysedit_isSelected( const Select_t *sel )
1373{
1374 for (int i=0; i<sysedit_nselect; i++)
1375 if (sysedit_selectCmp( sel, &sysedit_select[i] ))
1376 return 1;
1377 return 0;
1378}
1379
1383static void sysedit_editPnt (void)
1384{
1385 unsigned int wid;
1386 int x, y, w, l, bw;
1387 char buf[STRMAX_SHORT], title[128];
1388 const char *s;
1389 Spob *p;
1390
1391 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
1392
1393 /* Create the window. */
1394 snprintf(title, sizeof(title), _("Space Object Property Editor - %s"), p->name);
1395 wid = window_create( "wdwSysEditPnt", title, -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
1396 sysedit_widEdit = wid;
1397
1399
1400 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
1401
1402 /* Rename button. */
1403 y = -40;
1404 snprintf( buf, sizeof(buf), "%s ", _("Name:") );
1405 w = gl_printWidthRaw( NULL, buf );
1406 window_addText( wid, 20, y, 180, 15, 0, "txtNameLabel", &gl_smallFont, NULL, buf );
1407 snprintf( buf, sizeof(buf), "%s", p->name );
1408 window_addText( wid, 20 + w, y, 180, 15, 0, "txtName", &gl_smallFont, NULL, buf );
1409 window_addButton( wid, -20, y - gl_defFont.h/2. + BUTTON_HEIGHT/2., bw, BUTTON_HEIGHT, "btnRename",
1410 _("Rename"), sysedit_btnRename );
1411 window_addButton( wid, -20 - 15 - bw, y - gl_defFont.h/2. + BUTTON_HEIGHT/2., bw, BUTTON_HEIGHT, "btnFaction",
1412 _("Faction"), sysedit_btnFaction );
1413
1414 y -= gl_defFont.h + 5;
1415
1416 snprintf( buf, sizeof(buf), "%s ", _("Faction:") );
1417 w = gl_printWidthRaw( NULL, buf );
1418 window_addText( wid, 20, y, 180, 15, 0, "txtFactionLabel", &gl_smallFont, NULL, buf );
1419 snprintf( buf, sizeof(buf), "%s", p->presence.faction >= 0 ? faction_name( p->presence.faction ) : _("None") );
1420 window_addText( wid, 20 + w, y, 180, 15, 0, "txtFaction", &gl_smallFont, NULL, buf );
1421 y -= gl_defFont.h + 5;
1422
1423 /* Input widgets and labels. */
1424 x = 20;
1425 s = _("Population");
1426 l = gl_printWidthRaw( NULL, s );
1427 window_addText( wid, x, y, l, 20, 1, "txtPop",
1428 NULL, NULL, s );
1429 window_addInput( wid, x += l + 5, y, 80, 20, "inpPop", 12, 1, NULL );
1430 window_setInputFilter( wid, "inpPop", INPUT_FILTER_NUMBER );
1431 x += 80 + 10;
1432
1433 s = _("Class");
1434 l = gl_printWidthRaw( NULL, s );
1435 window_addText( wid, x, y, l, 20, 1, "txtClass",
1436 NULL, NULL, s );
1437 window_addInput( wid, x += l + 5, y, 30, 20, "inpClass", 1, 1, NULL );
1438 x += 30 + 10;
1439
1440 s = _("Lua");
1441 l = gl_printWidthRaw( NULL, s );
1442 window_addText( wid, x, y, l, 20, 1, "txtLua",
1443 NULL, NULL, s );
1444 window_addInput( wid, x += l + 5, y, 150, 20, "inpLua", 20, 1, NULL );
1445 y -= gl_defFont.h + 15;
1446
1447 /* Second row. */
1448 x = 20;
1449 s = _("Base Presence");
1450 l = gl_printWidthRaw( NULL, s );
1451 window_addText( wid, x, y, l, 20, 1, "txtPresenceBase",
1452 NULL, NULL, s );
1453 window_addInput( wid, x += l + 5, y, 50, 20, "inpPresenceBase", 5, 1, NULL );
1454 window_setInputFilter( wid, "inpPresenceBase", INPUT_FILTER_NUMBER );
1455 x += 50 + 10;
1456
1457 s = _("Bonus Presence");
1458 l = gl_printWidthRaw( NULL, s );
1459 window_addText( wid, x, y, l, 20, 1, "txtPresenceBonus",
1460 NULL, NULL, s );
1461 window_addInput( wid, x += l + 5, y, 50, 20, "inpPresenceBonus", 5, 1, NULL );
1462 window_setInputFilter( wid, "inpPresenceBonus", INPUT_FILTER_NUMBER );
1463 x += 50 + 10;
1464
1465 s = p_("sysedit", "Range");
1466 l = gl_printWidthRaw( NULL, s );
1467 window_addText( wid, x, y, l, 20, 1, "txtPresenceRange",
1468 NULL, NULL, s );
1469 window_addInput( wid, x += l + 5, y, 30, 20, "inpPresenceRange", 1, 1, NULL );
1470 window_setInputFilter( wid, "inpPresenceRange", INPUT_FILTER_NUMBER );
1471 //x += 30 + 10;
1472
1473 x = 250;
1474 y -= gl_defFont.h + 15;
1475 s = _("hide");
1476 l = gl_printWidthRaw( NULL, s );
1477 window_addText( wid, x, y, l, 20, 1, "txtHide",
1478 NULL, NULL, s );
1479 window_addInput( wid, x += l + 5, y, 50, 20, "inpHide", 4, 1, NULL );
1480 window_setInputFilter( wid, "inpHide", INPUT_FILTER_NUMBER );
1481 x += 50 + 10;
1482
1483 /* Tags. */
1484 x = 250;
1485 y -= gl_defFont.h + 20;
1486 l = scnprintf( buf, sizeof(buf), "#n%s#0", _("Tags:") );
1487 for (int i=0; i<array_size(p->tags); i++)
1488 l += scnprintf( &buf[l], sizeof(buf)-l, "%s %s", ((i>0) ? "," : ""), p->tags[i] );
1489 window_addText( wid, x, y, 300, 20, 0, "txtTags", NULL, NULL, buf );
1490
1491 /* Bottom buttons. */
1492 window_addButton( wid, -20 - bw*3 - 15*3, 35 + BUTTON_HEIGHT, bw, BUTTON_HEIGHT,
1493 "btnRmService", _("Rm Service"), sysedit_btnRmService );
1494 window_addButton( wid, -20 - bw*2 - 15*2, 35 + BUTTON_HEIGHT, bw, BUTTON_HEIGHT,
1495 "btnAddService", _("Add Service"), sysedit_btnAddService );
1496 window_addButton( wid, -20 - bw - 15, 35 + BUTTON_HEIGHT, bw, BUTTON_HEIGHT,
1497 "btnEditTech", _("Edit Tech"), sysedit_btnTechEdit );
1498 window_addButton( wid, -20, 35 + BUTTON_HEIGHT, bw, BUTTON_HEIGHT,
1499 "btnEditTags", _("Edit Tags"), sysedit_btnTagsEdit );
1500 window_addButton( wid, -20 - bw*3 - 15*3, 20, bw, BUTTON_HEIGHT,
1501 "btnDesc", _("Description"), sysedit_spobDesc );
1502 window_addButton( wid, -20 - bw*2 - 15*2, 20, bw, BUTTON_HEIGHT,
1503 "btnLandGFX", _("Land GFX"), sysedit_spobGFX );
1504 window_addButton( wid, -20 - bw - 15, 20, bw, BUTTON_HEIGHT,
1505 "btnSpaceGFX", _("Space GFX"), sysedit_spobGFX );
1506 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
1507 "btnClose", _("Close"), sysedit_editPntClose );
1508
1509 /* Load current values. */
1510 snprintf( buf, sizeof(buf), "%"PRIu64, p->population );
1511 window_setInput( wid, "inpPop", buf );
1512 snprintf( buf, sizeof(buf), "%s", p->class );
1513 window_setInput( wid, "inpClass", buf );
1514 window_setInput( wid, "inpLua", p->lua_file );
1515 snprintf( buf, sizeof(buf), "%g", p->presence.base );
1516 window_setInput( wid, "inpPresenceBase", buf );
1517 snprintf( buf, sizeof(buf), "%g", p->presence.bonus );
1518 window_setInput( wid, "inpPresenceBonus", buf );
1519 snprintf( buf, sizeof(buf), "%d", p->presence.range );
1520 window_setInput( wid, "inpPresenceRange", buf );
1521 snprintf( buf, sizeof(buf), "%g", p->hide );
1522 window_setInput( wid, "inpHide", buf );
1523
1524 /* Generate the list. */
1526}
1527
1531static void jp_type_check_hidden_update( unsigned int wid, const char* str )
1532{
1533 (void) str;
1534 if (jp_hidden == 0) {
1535 jp_hidden = 1;
1536 jp_exit = 0;
1537 }
1538 else
1539 jp_hidden = 0;
1540 window_checkboxSet( wid, "chkHidden", jp_hidden );
1541 window_checkboxSet( wid, "chkExit", jp_exit );
1542}
1543
1547static void jp_type_check_exit_update( unsigned int wid, const char* str )
1548{
1549 (void) str;
1550 if (jp_exit == 0) {
1551 jp_exit = 1;
1552 jp_hidden = 0;
1553 }
1554 else
1555 jp_exit = 0;
1556 window_checkboxSet( wid, "chkHidden", jp_hidden );
1557 window_checkboxSet( wid, "chkExit", jp_exit );
1558}
1559
1563static void jp_type_check_nolanes_update( unsigned int wid, const char* str )
1564{
1565 int s = window_checkboxState( wid, str );
1566 JumpPoint *j = &sysedit_sys->jumps[ sysedit_select[0].u.jump ];
1567 if (s)
1568 jp_setFlag( j, JP_NOLANES );
1569 else
1570 jp_rmFlag( j, JP_NOLANES );
1571}
1572
1576static void sysedit_editJump (void)
1577{
1578 unsigned int wid;
1579 int x, y, w, l, bw;
1580 char buf[STRMAX_SHORT];
1581 const char *s;
1582 JumpPoint *j = &sysedit_sys->jumps[ sysedit_select[0].u.jump ];
1583
1584 /* Create the window. */
1585 wid = window_create( "wdwJumpPointEditor", _("Jump Point Editor"), -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
1586 sysedit_widEdit = wid;
1587
1588 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
1589
1590 /* Target lable. */
1591 y = -40;
1592 snprintf( buf, sizeof(buf), _("Target: ") );
1593 w = gl_printWidthRaw( NULL, buf );
1594 window_addText( wid, 20, y, 180, 15, 0, "txtTargetLabel", &gl_smallFont, NULL, buf );
1595 snprintf( buf, sizeof(buf), "%s", j->target->name );
1596 window_addText( wid, 20 + w, y, 180, 15, 0, "txtName", &gl_smallFont, NULL, buf );
1597
1598 y -= gl_defFont.h + 10;
1599
1600 /* Input widgets and labels. */
1601 x = 20;
1602
1603 /* Initial checkbox state */
1604 jp_hidden = 0;
1605 jp_exit = 0;
1606 if (jp_isFlag( j, JP_HIDDEN ))
1607 jp_hidden = 1;
1608 else if (jp_isFlag( j, JP_EXITONLY ))
1609 jp_exit = 1;
1610 /* Create check boxes. */
1611 window_addCheckbox( wid, x, y, 100, 20,
1612 "chkHidden", _("Hidden"), jp_type_check_hidden_update, jp_hidden );
1613 y -= 20;
1614 window_addCheckbox( wid, x, y, 100, 20,
1615 "chkExit", _("Exit only"), jp_type_check_exit_update, jp_exit );
1616 y -= 20;
1617 window_addCheckbox( wid, x, y, 100, 20,
1618 "chkNolanes", _("No lanes"), jp_type_check_nolanes_update, jp_isFlag( j, JP_NOLANES ) );
1619 y -= 30;
1620
1621 s = _("Hide"); /* TODO: if inpType == 0 disable hide box */
1622 l = gl_printWidthRaw( NULL, s );
1623 window_addText( wid, x, y, l, 20, 1, "txtHide",
1624 NULL, NULL, s );
1625 window_addInput( wid, x + l + 8, y, 50, 20, "inpHide", 4, 1, NULL );
1626 window_setInputFilter( wid, "inpHide", INPUT_FILTER_NUMBER );
1627 x += 50 + 10;
1628
1629 /* Bottom buttons. */
1630 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
1631 "btnClose", _("Close"), sysedit_editJumpClose );
1632
1633 /* Load current values. */
1634 snprintf( buf, sizeof(buf), "%g", j->hide );
1635 window_setInput( wid, "inpHide", buf );
1636}
1637
1641static void sysedit_editJumpClose( unsigned int wid, const char *unused )
1642{
1643 (void) unused;
1644 JumpPoint *j = &sysedit_sys->jumps[ sysedit_select[0].u.jump ];
1645 if (jp_hidden == 1) {
1646 jp_setFlag( j, JP_HIDDEN );
1647 jp_rmFlag( j, JP_EXITONLY );
1648 }
1649 else if (jp_exit == 1) {
1650 jp_setFlag( j, JP_EXITONLY );
1651 jp_rmFlag( j, JP_HIDDEN );
1652 }
1653 else {
1654 jp_rmFlag( j, JP_HIDDEN );
1655 jp_rmFlag( j, JP_EXITONLY );
1656 }
1657 j->hide = atof(window_getInput( sysedit_widEdit, "inpHide" ));
1658
1659 window_close( wid, unused );
1660}
1661
1665static void sysedit_editAsteroids (void)
1666{
1667 unsigned int wid;
1668 int x, y, l, bw;
1669 char buf[STRMAX_SHORT];
1670 const char *s;
1671 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sysedit_select[0].u.asteroid ];
1672
1673 /* Create the window. */
1674 wid = window_create( "wdwAsteroidsEditor", _("Asteroid Field Editor"), -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
1675 sysedit_widEdit = wid;
1676 window_setCancel( wid, sysedit_editAsteroidsClose );
1677
1678 /* Input widgets and labels. */
1679 x = 20;
1680
1681 /* Add some inputs. */
1682 y = -40;
1683 s = _("Density: ");
1684 l = gl_printWidthRaw( NULL, s );
1685 window_addText( wid, x, y, l, 20, 1, "txtDensity", NULL, NULL, s );
1686 window_addInput( wid, x + l + 8, y, 80, 20, "inpDensity", 10, 1, NULL );
1687 window_setInputFilter( wid, "inpDensity", INPUT_FILTER_NUMBER );
1688 y -= 30;
1689 s = _("Radius: ");
1690 l = gl_printWidthRaw( NULL, s );
1691 window_addText( wid, x, y, l, 20, 1, "txtInput", NULL, NULL, s );
1692 window_addInput( wid, x + l + 8, y, 80, 20, "inpRadius", 10, 1, NULL );
1693 window_setInputFilter( wid, "inpRadius", INPUT_FILTER_NUMBER );
1694 x = 200;
1695 y = -40;
1696 s = _("Max Speed: ");
1697 l = gl_printWidthRaw( NULL, s );
1698 window_addText( wid, x, y, l, 20, 1, "txtMaxspeed", NULL, NULL, s );
1699 window_addInput( wid, x + l + 8, y, 80, 20, "inpMaxspeed", 10, 1, NULL );
1700 window_setInputFilter( wid, "inpMaxspeed", INPUT_FILTER_NUMBER );
1701 y -= 30;
1702 s = _("Accel: ");
1703 l = gl_printWidthRaw( NULL, s );
1704 window_addText( wid, x, y, l, 20, 1, "txtAccel", NULL, NULL, s );
1705 window_addInput( wid, x + l + 8, y, 80, 20, "inpAccel", 10, 1, NULL );
1706 window_setInputFilter( wid, "inpAccel", INPUT_FILTER_NUMBER );
1707
1708 /* List to choose the different asteroids that appear. */
1709 sysedit_genAsteroidsList( wid );
1710
1711 /* Button width. */
1712 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
1713
1714 /* List Captions. */
1715 window_addText( wid, 20, 20+BUTTON_HEIGHT+15+200+5, bw, gl_smallFont.h,
1716 1, "txtAsteroidsHave", NULL, NULL, _("Asteroids") );
1717 window_addText( wid, 20+bw+15, 20+BUTTON_HEIGHT+15+200+5, bw, gl_smallFont.h,
1718 1, "txtAsteroidsAvailable", NULL, NULL, _("Available") );
1719
1720 /* Bottom buttons. */
1721 window_addButton( wid, 20, 20, bw, BUTTON_HEIGHT,
1722 "btnRmAsteroid", _("Rm Asteroid"), sysedit_btnRmAsteroid );
1723 window_addButton( wid, 20 + bw + 15, 20, bw, BUTTON_HEIGHT,
1724 "btnAddAsteroid", _("Add Asteroid"), sysedit_btnAddAsteroid );
1725 window_addButton( wid, 20 + 2*(bw + 15), 20, bw, BUTTON_HEIGHT,
1726 "btnDelete", _("Delete"), sysedit_btnAsteroidsDelete );
1727 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
1728 "btnClose", _("Close"), sysedit_editAsteroidsClose );
1729
1730 /* Load current values. */
1731 snprintf( buf, sizeof(buf), "%g", ast->density );
1732 window_setInput( wid, "inpDensity", buf );
1733 snprintf( buf, sizeof(buf), "%g", ast->radius );
1734 window_setInput( wid, "inpRadius", buf );
1735 snprintf( buf, sizeof(buf), "%g", ast->maxspeed );
1736 window_setInput( wid, "inpMaxspeed", buf );
1737 snprintf( buf, sizeof(buf), "%g", ast->accel );
1738 window_setInput( wid, "inpAccel", buf );
1739}
1740
1741static void sysedit_genAsteroidsList( unsigned int wid )
1742{
1743 int hpos, apos, nhave, navail;
1744 int x, y, w, h;
1745 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sysedit_select[0].u.asteroid ];
1746 const AsteroidTypeGroup *astgroups;
1747 char **have, **available;
1748
1749 hpos = apos = -1;
1750 if (widget_exists( wid, "lstAsteroidsHave" ) &&
1751 widget_exists( wid, "lstAsteroidsAvailable" )) {
1752 hpos = toolkit_getListPos( wid, "lstAsteroidsHave" );
1753 apos = toolkit_getListPos( wid, "lstAsteroidsAvailable" );
1754 window_destroyWidget( wid, "lstAsteroidsHave" );
1755 window_destroyWidget( wid, "lstAsteroidsAvailable" );
1756 }
1757
1758 /* Set up positions. */
1759 x = 20;
1760 y = 20 + BUTTON_HEIGHT + 15;
1761 w = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4;
1762 h = 200;
1763
1764 /* Find and add used asteroids. */
1765 nhave = array_size(ast->groups);
1766 if (nhave > 0) {
1767 have = malloc( sizeof(char*) * nhave );
1768 for (int i=0; i<nhave; i++)
1769 have[i] = strdup( ast->groups[i]->name );
1770 }
1771 else
1772 have = NULL;
1773 window_addList( wid, x, y, w, h, "lstAsteroidsHave", have, nhave, 0, NULL, sysedit_btnRmAsteroid );
1774 x += w + 15;
1775
1776 /* Load all asteroid types. */
1777 astgroups = astgroup_getAll();
1778 navail = array_size(astgroups);
1779 if (navail > 0) {
1780 available = malloc( sizeof(char*) * navail );
1781 for (int i=0; i<navail; i++)
1782 available[i] = strdup( astgroups[i].name );
1783 qsort( available, navail, sizeof(char*), strsort );
1784 }
1785 else
1786 available = NULL;
1787 window_addList( wid, x, y, w, h, "lstAsteroidsAvailable", available, navail, 0, NULL, sysedit_btnAddAsteroid );
1788
1789 /* Restore positions. */
1790 if (hpos != -1 && apos != -1) {
1791 toolkit_setListPos( wid, "lstAsteroidsHave", hpos );
1792 toolkit_setListPos( wid, "lstAsteroidsAvailable", apos );
1793 }
1794}
1795
1796static void sysedit_btnRmAsteroid( unsigned int wid, const char *unused )
1797{
1798 (void) unused;
1799 int pos = toolkit_getListPos( wid, "lstAsteroidsHave" );
1800 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sysedit_select[0].u.asteroid ];
1801
1802 if (array_size(ast->groups) > 0)
1803 array_erase( &ast->groups, &ast->groups[pos], &ast->groups[pos+1] );
1804
1805 sysedit_genAsteroidsList( wid );
1806}
1807
1808static void sysedit_btnAddAsteroid( unsigned int wid, const char *unused )
1809{
1810 (void) unused;
1811 const char *selected = toolkit_getList( wid, "lstAsteroidsAvailable" );
1812 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sysedit_select[0].u.asteroid ];
1813
1814 array_push_back( &ast->groups, astgroup_getName( selected ) );
1815
1816 sysedit_genAsteroidsList( wid );
1817}
1818
1819static void sysedit_btnAsteroidsDelete( unsigned int wid, const char *unused )
1820{
1821 int i = dialogue_YesNo( _("Remove Asteroid Field"), _("Are you sure you want to remove this asteroid field?") );
1822 if (i==0)
1823 return;
1824
1825 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sysedit_select[0].u.asteroid ];
1826
1827 asteroid_free( ast );
1828 array_erase( &sysedit_sys->asteroids, ast, ast+1 );
1829
1830 if (conf.devautosave)
1832
1833 window_close( wid, unused );
1834}
1835
1836static void sysedit_editAsteroidsClose( unsigned int wid, const char *unused )
1837{
1838 AsteroidAnchor *ast = &sysedit_sys->asteroids[ sysedit_select[0].u.asteroid ];
1839
1840 ast->density = atof(window_getInput( sysedit_widEdit, "inpDensity" ));
1841 ast->radius = atof(window_getInput( sysedit_widEdit, "inpRadius" ));
1842 ast->maxspeed = atof(window_getInput( sysedit_widEdit, "inpMaxspeed" ));
1843 ast->accel = atof(window_getInput( sysedit_widEdit, "inpAccel" ));
1844
1845 /* Need to update some internals based on new values. */
1847
1848 if (conf.devautosave)
1850
1851 window_close( wid, unused );
1852}
1853
1854static void sysedit_editExclusion (void)
1855{
1856 unsigned int wid;
1857 int x, y, l, bw;
1858 char buf[STRMAX_SHORT];
1859 const char *s;
1860 AsteroidExclusion *exc = &sysedit_sys->astexclude[ sysedit_select[0].u.astexclude ];
1861
1862 /* Create the window. */
1863 wid = window_create( "wdwExclusionEditor", _("Asteroid Exclusion Zone Editor"), -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
1864 sysedit_widEdit = wid;
1865 window_setCancel( wid, sysedit_editExclusionClose );
1866
1867 /* Add some inputs. */
1868 x = 20;
1869 y = -40;
1870 s = _("Radius: ");
1871 l = gl_printWidthRaw( NULL, s );
1872 window_addText( wid, x, y, l, 20, 1, "txtInput", NULL, NULL, s );
1873 window_addInput( wid, x + l + 8, y, 80, 20, "inpRadius", 10, 1, NULL );
1874 window_setInputFilter( wid, "inpRadius", INPUT_FILTER_NUMBER );
1875
1876 /* Bottom buttons. */
1877 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
1878 window_addButton( wid, -20 - 15 - bw, 20, bw, BUTTON_HEIGHT,
1879 "btnDelete", _("Delete"), sysedit_btnExclusionDelete );
1880 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
1881 "btnClose", _("Close"), sysedit_editExclusionClose );
1882
1883 /* Load current values. */
1884 snprintf( buf, sizeof(buf), "%g", exc->radius );
1885 window_setInput( wid, "inpRadius", buf );
1886}
1887
1888static void sysedit_btnExclusionDelete( unsigned int wid, const char *unused )
1889{
1890 int i = dialogue_YesNo( _("Remove Asteroid Exclusion Zone"), _("Are you sure you want to remove this asteroid exclusion zone?") );
1891 if (i==0)
1892 return;
1893
1894 AsteroidExclusion *exc = &sysedit_sys->astexclude[ sysedit_select[0].u.astexclude ];
1895
1896 array_erase( &sysedit_sys->astexclude, exc, exc+1 );
1897
1898 if (conf.devautosave)
1900
1901 window_close( wid, unused );
1902}
1903
1904static void sysedit_editExclusionClose( unsigned int wid, const char *unused )
1905{
1906 AsteroidExclusion *exc = &sysedit_sys->astexclude[ sysedit_select[0].u.astexclude ];
1907
1908 exc->radius = atof(window_getInput( sysedit_widEdit, "inpRadius" ));
1909
1910 if (conf.devautosave)
1912
1913 window_close( wid, unused );
1914}
1915
1919static void sysedit_spobDesc( unsigned int wid, const char *unused )
1920{
1921 (void) unused;
1922 int x, y, h, w, bw;
1923 Spob *p;
1924 const char *desc, *bardesc;
1925 char title[128];
1926
1927 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
1928
1929 /* Create the window. */
1930 snprintf(title, sizeof(title), _("Space Object Information - %s"), p->name);
1931 wid = window_create( "wdwSpobDesc", title, -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
1933
1934 x = 20;
1935 y = -40;
1936 w = SYSEDIT_EDIT_WIDTH - 40;
1937 h = (SYSEDIT_EDIT_HEIGHT - gl_defFont.h * 2 - 30 - 60 - BUTTON_HEIGHT - 10) / 2.;
1938 desc = p->description ? p->description : _("None");
1939 bardesc = p->bar_description ? p->bar_description : _("None");
1940 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
1941
1942 window_addButton( wid, -20 - bw*3 - 15*3, 20, bw, BUTTON_HEIGHT,
1943 "btnProperties", _("Properties"), sysedit_spobDescReturn );
1944
1945 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
1946 "btnClose", _("Close"), sysedit_spobDescClose );
1947
1948 /* Description label and text. */
1949 window_addText( wid, x, y, w, gl_defFont.h, 0, "txtDescriptionLabel", &gl_defFont, NULL,
1950 _("Landing Description") );
1951 y -= gl_defFont.h + 10;
1952 window_addInput( wid, x, y, w, h, "txtDescription", 1024, 0,
1953 NULL );
1954 window_setInputFilter( wid, "txtDescription",
1955 "[]{}~<>@#$^|_" );
1956 y -= h + 10;
1957 /* Load current values. */
1958 window_setInput( wid, "txtDescription", desc );
1959
1960 /* Bar description label and text. */
1961 window_addText( wid, x, y, w, gl_defFont.h, 0, "txtBarDescriptionLabel", &gl_defFont, NULL,
1962 _("Bar Description") );
1963 y -= gl_defFont.h + 10;
1964 window_addInput( wid, x, y, w, h, "txtBarDescription", 1024, 0,
1965 NULL );
1966 window_setInputFilter( wid, "txtBarDescription",
1967 "[]{}~<>@#$^|_" );
1968 /* Load current values. */
1969 window_setInput( wid, "txtBarDescription", bardesc );
1970}
1971
1975static void sysedit_spobDescReturn( unsigned int wid, const char *unused )
1976{
1977 Spob *p;
1978 const char *mydesc, *mybardesc;
1979
1980 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
1981
1982 mydesc = window_getInput( wid, "txtDescription" );
1983 mybardesc = window_getInput( wid, "txtBarDescription" );
1984
1985 free(p->description);
1986 free(p->bar_description);
1987 p->description = NULL;
1988 p->bar_description = NULL;
1989
1990 if (mydesc != NULL)
1991 p->description = strdup( mydesc );
1992 if (mybardesc != NULL)
1993 p->bar_description = strdup( mybardesc );
1994
1995 window_close( wid, unused );
1996}
1997
2001static void sysedit_spobDescClose( unsigned int wid, const char *unused )
2002{
2003 sysedit_spobDescReturn( wid, unused );
2005}
2006
2010static void sysedit_genServicesList( unsigned int wid )
2011{
2012 int j, n, nservices;
2013 Spob *p;
2014 char **have, **lack;
2015 int x, y, w, h, hpos, lpos;
2016
2017 hpos = lpos = -1;
2018
2019 /* Destroy if exists. */
2020 if (widget_exists( wid, "lstServicesHave" ) &&
2021 widget_exists( wid, "lstServicesLacked" )) {
2022 hpos = toolkit_getListPos( wid, "lstServicesHave" );
2023 lpos = toolkit_getListPos( wid, "lstServicesLacked" );
2024 window_destroyWidget( wid, "lstServicesHave" );
2025 window_destroyWidget( wid, "lstServicesLacked" );
2026 }
2027
2028 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2029 x = 20;
2030 y = 20 + BUTTON_HEIGHT * 2 + 30;
2031 w = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
2032 h = SYSEDIT_EDIT_HEIGHT - y - 130;
2033
2034 /* Get all missing services. */
2035 n = nservices = 0;
2036 for (int i=1; i<SPOB_SERVICES_MAX; i<<=1) {
2037 if (!spob_hasService(p, i) && (i != SPOB_SERVICE_INHABITED))
2038 n++;
2039 nservices++; /* Cheaply track all service types. */
2040 }
2041
2042 /* Get all the services the spob has. */
2043 j = 0;
2044 have = malloc( sizeof(char*) * MAX(nservices - n, 1) );
2045 if (nservices == n)
2046 have[j++] = strdup(_("None"));
2047 else
2048 for (int i=1; i<SPOB_SERVICES_MAX; i<<=1)
2049 if (spob_hasService(p, i) && (i != SPOB_SERVICE_INHABITED))
2050 have[j++] = strdup( spob_getServiceName( i ) );
2051
2052 /* Add list. */
2053 window_addList( wid, x, y, w, h, "lstServicesHave", have, j, 0, NULL, sysedit_btnRmService );
2054 x += w + 15;
2055
2056 /* Add list of services the spob lacks. */
2057 j = 0;
2058 lack = malloc( sizeof(char*) * MAX(1, n) );
2059 if (!n)
2060 lack[j++] = strdup( _("None") );
2061 else
2062 for (int i=1; i<SPOB_SERVICES_MAX; i<<=1)
2063 if (!spob_hasService(p, i) && (i != SPOB_SERVICE_INHABITED))
2064 lack[j++] = strdup( spob_getServiceName(i) );
2065
2066 /* Add list. */
2067 window_addList( wid, x, y, w, h, "lstServicesLacked", lack, j, 0, NULL, sysedit_btnAddService );
2068
2069 /* Restore positions. */
2070 if (hpos != -1 && lpos != -1) {
2071 toolkit_setListPos( wid, "lstServicesHave", hpos );
2072 toolkit_setListPos( wid, "lstServicesLacked", lpos );
2073 }
2074}
2075
2079static void sysedit_btnAddService( unsigned int wid, const char *unused )
2080{
2081 (void) unused;
2082 const char *selected;
2083 Spob *p;
2084
2085 selected = toolkit_getList( wid, "lstServicesLacked" );
2086 if ((selected == NULL) || (strcmp(selected,_("None"))==0))
2087 return;
2088
2089 /* Enable the service. All services imply landability. */
2090 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2091 p->services |= spob_getService(selected) | SPOB_SERVICE_INHABITED | SPOB_SERVICE_LAND;
2092
2093 /* Regenerate the list. */
2095}
2096
2100static void sysedit_btnRmService( unsigned int wid, const char *unused )
2101{
2102 (void) unused;
2103 const char *selected;
2104 Spob *p;
2105
2106 selected = toolkit_getList( wid, "lstServicesHave" );
2107 if ((selected==NULL) || (strcmp(selected,_("None"))==0))
2108 return;
2109
2110 /* Flip the bit. Safe enough, as it's always 1 to start with. */
2111 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2112 p->services ^= spob_getService(selected);
2113
2114 /* If landability was removed, the rest must go, too. */
2115 if (strcmp(selected,"Land")==0)
2116 p->services = 0;
2117
2119}
2120
2124static void sysedit_btnTechEdit( unsigned int wid, const char *unused )
2125{
2126 (void) unused;
2127 int y, w, bw;
2128
2129 /* Create the window. */
2130 wid = window_create( "wdwSpobTechEditor", _("Space Object Tech Editor"), -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
2132
2133 w = (SYSEDIT_EDIT_WIDTH - 40 - 15) / 2.;
2134 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
2135
2136 /* Close button. */
2137 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
2138 "btnClose", _("Close"), window_close );
2139 y = 20 + BUTTON_HEIGHT + 15;
2140
2141 /* Remove button. */
2142 window_addButton( wid, -20-(w+15), y, w, BUTTON_HEIGHT,
2143 "btnRm", _("Rm Tech"), sysedit_btnRmTech );
2144
2145 /* Add button. */
2146 window_addButton( wid, -20, y, w, BUTTON_HEIGHT,
2147 "btnAdd", _("Add Tech"), sysedit_btnAddTech );
2148
2149 sysedit_genTechList( wid );
2150}
2151
2155static void sysedit_genTechList( unsigned int wid )
2156{
2157 Spob *p;
2158 char **have, **lack;
2159 int j, n, x, y, w, h, hpos, lpos;
2160
2161 hpos = lpos = -1;
2162
2163 /* Destroy if exists. */
2164 if (widget_exists( wid, "lstTechsHave" ) &&
2165 widget_exists( wid, "lstTechsLacked" )) {
2166 hpos = toolkit_getListPos( wid, "lstTechsHave" );
2167 lpos = toolkit_getListPos( wid, "lstTechsLacked" );
2168 window_destroyWidget( wid, "lstTechsHave" );
2169 window_destroyWidget( wid, "lstTechsLacked" );
2170 }
2171
2172 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2173 w = (SYSEDIT_EDIT_WIDTH - 40 - 15) / 2.;
2174 x = -20 - w - 15;
2175 y = 20 + BUTTON_HEIGHT * 2 + 30;
2176 h = SYSEDIT_EDIT_HEIGHT - y - 30;
2177
2178 /* Get all the techs the spob has. */
2179 n = 0;
2180 if (p->tech != NULL)
2181 have = tech_getItemNames( p->tech, &n );
2182 else {
2183 have = malloc( sizeof(char*) );
2184 have[n++] = strdup(_("None"));
2185 }
2186
2187 /* Add list. */
2188 window_addList( wid, x, y, w, h, "lstTechsHave", have, n, 0, NULL, sysedit_btnRmTech );
2189 x += w + 15;
2190
2191 /* Omit the techs that the spob already has from the list. */
2192 n = 0;
2193 if (p->tech != NULL) {
2194 char **tmp = tech_getAllItemNames( &j );
2195 for (int i=0; i<j; i++)
2196 if (!tech_hasItem( p->tech, tmp[i] ))
2197 n++;
2198
2199 if (!n) {
2200 lack = malloc( sizeof(char*) );
2201 lack[n++] = strdup(_("None"));
2202 }
2203 else {
2204 lack = malloc( sizeof(char*) * j );
2205 n = 0;
2206 for (int i=0; i<j; i++)
2207 if (!tech_hasItem( p->tech, tmp[i] ))
2208 lack[n++] = strdup( tmp[i] );
2209 }
2210
2211 /* Clean up. */
2212 for (int i=0; i<j; i++)
2213 free(tmp[i]);
2214
2215 free(tmp);
2216 }
2217 else
2218 lack = tech_getAllItemNames( &n );
2219
2220 /* Add list. */
2221 window_addList( wid, x, y, w, h, "lstTechsLacked", lack, n, 0, NULL, sysedit_btnAddTech );
2222
2223 /* Restore positions. */
2224 if (hpos != -1 && lpos != -1) {
2225 toolkit_setListPos( wid, "lstTechsHave", hpos );
2226 toolkit_setListPos( wid, "lstTechsLacked", lpos );
2227 }
2228}
2229
2233static void sysedit_btnAddTech( unsigned int wid, const char *unused )
2234{
2235 (void) unused;
2236 const char *selected;
2237 Spob *p;
2238
2239 selected = toolkit_getList( wid, "lstTechsLacked" );
2240 if ((selected == NULL) || (strcmp(selected,_("None"))==0))
2241 return;
2242
2243 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2244 if (p->tech == NULL)
2245 p->tech = tech_groupCreate();
2246 tech_addItemTech( p->tech, selected );
2247
2248 /* Regenerate the list. */
2249 sysedit_genTechList( wid );
2250}
2251
2255static void sysedit_btnRmTech( unsigned int wid, const char *unused )
2256{
2257 (void) unused;
2258 const char *selected;
2259 Spob *p;
2260 int n;
2261
2262 selected = toolkit_getList( wid, "lstTechsHave" );
2263 if ((selected == NULL) || (strcmp(selected,_("None"))==0))
2264 return;
2265
2266 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2267 if (tech_hasItem( p->tech, selected ))
2268 tech_rmItemTech( p->tech, selected );
2269
2270 n = tech_getItemCount( p->tech );
2271 if (!n)
2272 p->tech = NULL;
2273
2274 /* Regenerate the list. */
2275 sysedit_genTechList( wid );
2276}
2277
2278
2282static void sysedit_btnTagsEdit( unsigned int wid, const char *unused )
2283{
2284 (void) unused;
2285 int y, w, bw;
2286
2287 /* Create the window. */
2288 wid = window_create( "wdwSpobTagsEditor", _("Space Object Tags Editor"), -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
2289 window_setCancel( wid, sysedit_btnTagsClose );
2290
2291 w = (SYSEDIT_EDIT_WIDTH - 40 - 15) / 2.;
2292 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
2293
2294 /* Close button. */
2295 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
2296 "btnClose", _("Close"), sysedit_btnTagsClose );
2297 y = 20 + BUTTON_HEIGHT + 15;
2298
2299 /* Remove button. */
2300 window_addButton( wid, -20-(w+15), y, w, BUTTON_HEIGHT,
2301 "btnRm", _("Rm Tag"), sysedit_btnRmTag );
2302
2303 /* Add button. */
2304 window_addButton( wid, -20, y, w, BUTTON_HEIGHT,
2305 "btnAdd", _("Add Tag"), sysedit_btnAddTag );
2306
2307 /* New tag. */
2308 window_addButton( wid, -20-(w+15), 20, w, BUTTON_HEIGHT,
2309 "btnNew", _("New Tag"), sysedit_btnNewTag );
2310
2311 /* Generate list of tags. */
2312 if (sysedit_tagslist == NULL) {
2313 Spob *spob_all = spob_getAll();
2314 sysedit_tagslist = array_create( char* );
2315 for (int i=0; i<array_size(spob_all); i++) {
2316 Spob *s = &spob_all[i];
2317 for (int j=0; j<array_size(s->tags); j++) {
2318 char *t = s->tags[j];
2319 int found = 0;
2320 for (int k=0; k<array_size(sysedit_tagslist); k++)
2321 if (strcmp(sysedit_tagslist[k], t)==0) {
2322 found = 1;
2323 break;
2324 }
2325 if (!found)
2326 array_push_back( &sysedit_tagslist, strdup(t) );
2327 }
2328 }
2329 qsort( sysedit_tagslist, array_size(sysedit_tagslist), sizeof(char*), strsort );
2330 }
2331
2332 sysedit_genTagsList( wid );
2333}
2334
2335/*
2336 * Tags are closed so update tags.
2337 */
2338static void sysedit_btnTagsClose( unsigned int wid, const char *unused )
2339{
2340 char buf[STRMAX_SHORT];
2341 Spob *p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2342 int l = scnprintf( buf, sizeof(buf), "#n%s#0", _("Tags:") );
2343 for (int i=0; i<array_size(p->tags); i++)
2344 l += scnprintf( &buf[l], sizeof(buf)-l, "%s %s", ((i>0) ? "," : ""), p->tags[i] );
2345 window_modifyText( sysedit_widEdit, "txtTags", buf );
2346
2347 window_close( wid, unused );
2348}
2349
2353static void sysedit_genTagsList( unsigned int wid )
2354{
2355 Spob *p;
2356 char **have, **lack;
2357 int n, x, y, w, h, hpos, lpos, empty;
2358
2359 hpos = lpos = -1;
2360
2361 /* Destroy if exists. */
2362 if (widget_exists( wid, "lstTagsHave" ) &&
2363 widget_exists( wid, "lstTagsLacked" )) {
2364 hpos = toolkit_getListPos( wid, "lstTagsHave" );
2365 lpos = toolkit_getListPos( wid, "lstTagsLacked" );
2366 window_destroyWidget( wid, "lstTagsHave" );
2367 window_destroyWidget( wid, "lstTagsLacked" );
2368 }
2369
2370 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2371 w = (SYSEDIT_EDIT_WIDTH - 40 - 15) / 2.;
2372 x = -20 - w - 15;
2373 y = 20 + BUTTON_HEIGHT * 2 + 30;
2374 h = SYSEDIT_EDIT_HEIGHT - y - 30;
2375
2376 /* Get all the techs the spob has. */
2377 n = array_size(p->tags);
2378 if (n>0) {
2379 have = malloc( n * sizeof(char*) );
2380 for (int i=0; i<n; i++)
2381 have[i] = strdup(p->tags[i]);
2382 empty = 0;
2383 }
2384 else {
2385 have = malloc( sizeof(char*) );
2386 have[n++] = strdup(_("None"));
2387 empty = 1;
2388 }
2389
2390 /* Add list. */
2391 window_addList( wid, x, y, w, h, "lstTagsHave", have, n, 0, NULL, sysedit_btnRmTag );
2392 x += w + 15;
2393
2394 /* Omit the techs that the spob already has from the list. */
2395 n = 0;
2396 lack = malloc( array_size(sysedit_tagslist) * sizeof(char*) );
2397 for (int i=0; i<array_size(sysedit_tagslist); i++) {
2398 char *t = sysedit_tagslist[i];
2399 if (empty)
2400 lack[n++] = strdup(t);
2401 else {
2402 int found = 0;
2403 for (int j=0; j<array_size(p->tags); j++)
2404 if (strcmp( p->tags[j], t )==0) {
2405 found = 1;
2406 break;
2407 }
2408 if (!found)
2409 lack[n++] = strdup( t );
2410 }
2411 }
2412
2413 /* Add list. */
2414 window_addList( wid, x, y, w, h, "lstTagsLacked", lack, n, 0, NULL, sysedit_btnAddTag );
2415
2416 /* Restore positions. */
2417 if (hpos != -1 && lpos != -1) {
2418 toolkit_setListPos( wid, "lstTagsHave", hpos );
2419 toolkit_setListPos( wid, "lstTagsLacked", lpos );
2420 }
2421}
2422
2426static void sysedit_btnAddTag( unsigned int wid, const char *unused )
2427{
2428 (void) unused;
2429 const char *selected;
2430 Spob *p;
2431
2432 selected = toolkit_getList( wid, "lstTagsLacked" );
2433 if ((selected == NULL) || (strcmp(selected,_("None"))==0))
2434 return;
2435
2436 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2437 if (p->tags == NULL)
2438 p->tags = array_create( char* );
2439 array_push_back( &p->tags, strdup(selected) );
2440
2441 /* Regenerate the list. */
2442 sysedit_genTagsList( wid );
2443}
2444
2448static void sysedit_btnRmTag( unsigned int wid, const char *unused )
2449{
2450 (void) unused;
2451 const char *selected;
2452 Spob *p;
2453 int i;
2454
2455 selected = toolkit_getList( wid, "lstTagsHave" );
2456 if ((selected == NULL) || (strcmp(selected,_("None"))==0))
2457 return;
2458
2459 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2460
2461 for (i=0; i<array_size(p->tags); i++)
2462 if (strcmp( selected, p->tags[i] )==0)
2463 break;
2464 if (i >= array_size(p->tags))
2465 return;
2466 free( p->tags[i] );
2467 array_erase( &p->tags, &p->tags[i], &p->tags[i+1] );
2468
2469 /* Regenerate the list. */
2470 sysedit_genTagsList( wid );
2471}
2472
2476static void sysedit_btnNewTag( unsigned int wid, const char *unused )
2477{
2478 (void) unused;
2479 Spob *s;
2480
2481 char *tag = dialogue_input( _("Add New Spob Tag"), 1, 128, _("Please write the new tag to add to the spob.") );
2482 if (tag==NULL)
2483 return;
2484
2485 s = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2486 if (s->tags == NULL)
2487 s->tags = array_create( char* );
2488 array_push_back( &s->tags, tag ); /* gets freed later */
2489
2490 /* Also add to list of all tags. */
2491 array_push_back( &sysedit_tagslist, strdup(tag) );
2492
2493 /* Regenerate the list. */
2494 sysedit_genTagsList( wid );
2495}
2496
2500static void sysedit_btnFaction( unsigned int wid_unused, const char *unused )
2501{
2502 (void) wid_unused;
2503 (void) unused;
2504 unsigned int wid;
2505 int pos, j, y, h, bw, *factions;
2506 char **str;
2507 const char *s;
2508 Spob *p;
2509
2510 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2511
2512 /* Create the window. */
2513 wid = window_create( "wdwModifyFaction", _("Modify Faction"), -1, -1, SYSEDIT_EDIT_WIDTH, SYSEDIT_EDIT_HEIGHT );
2515
2516 /* Generate factions list. */
2517 factions = faction_getAll();
2518 str = malloc( sizeof(char*) * (array_size(factions) + 1) );
2519 str[0] = strdup(_("None"));
2520 j = 1;
2521 for (int i=0; i<array_size(factions); i++)
2522 str[j++] = strdup( faction_name( factions[i] ) ); /* Not translating so we can use faction_get */
2523 qsort( &str[1], j-1, sizeof(char*), strsort );
2524
2525 /* Get current faction. */
2526 if (p->presence.faction >= 0) {
2527 pos = 0;
2528 s = faction_name(p->presence.faction);
2529 for (int i=0; i<j; i++)
2530 if (strcmp(s,str[i])==0)
2531 pos = i;
2532 }
2533 else
2534 pos = -1;
2535
2536 bw = (SYSEDIT_EDIT_WIDTH - 40 - 15 * 3) / 4.;
2537 y = 20 + BUTTON_HEIGHT + 15;
2538 h = SYSEDIT_EDIT_HEIGHT - y - 30;
2539 window_addList( wid, 20, -40, SYSEDIT_EDIT_WIDTH-40, h,
2540 "lstFactions", str, j, pos, NULL, sysedit_btnFactionSet );
2541
2542 /* Close button. */
2543 window_addButton( wid, -20, 20, bw, BUTTON_HEIGHT,
2544 "btnClose", _("Close"), window_close );
2545
2546 /* Add button. */
2547 window_addButton( wid, -20-(bw+15), 20, bw, BUTTON_HEIGHT,
2548 "btnAdd", _("Set"), sysedit_btnFactionSet );
2549
2550 array_free( factions );
2551}
2552
2556static void sysedit_btnFactionSet( unsigned int wid, const char *unused )
2557{
2558 (void) unused;
2559 const char *selected;
2560 Spob *p;
2561
2562 selected = toolkit_getList( wid, "lstFactions" );
2563 if (selected == NULL)
2564 return;
2565 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2566
2567 /* "None" case. */
2568 if (toolkit_getListPos( wid, "lstFactions")==0) {
2569 p->presence.faction = -1;
2570 }
2571 else {
2572 /* Set the faction. */
2573 p->presence.faction = faction_get( selected );
2574 }
2575
2576 /* Update the editor window. */
2577 window_modifyText( sysedit_widEdit, "txtFaction", p->presence.faction >= 0 ? faction_name( p->presence.faction ) : _("None") );
2578
2579 window_close( wid, unused );
2580}
2581
2585static void sysedit_btnEdit( unsigned int wid_unused, const char *unused )
2586{
2587 (void) wid_unused;
2588 (void) unused;
2589 Select_t *sel = &sysedit_select[0];
2590 if (sel->type==SELECT_SPOB)
2592 else if (sel->type==SELECT_JUMPPOINT)
2594 else if (sel->type==SELECT_ASTEROID)
2596 else if (sel->type==SELECT_ASTEXCLUDE)
2597 sysedit_editExclusion();
2598}
2599
2603static void sysedit_spobGFX( unsigned int wid_unused, const char *wgt )
2604{
2605 (void) wid_unused;
2606 unsigned int wid;
2607 size_t nfiles, j;
2608 char *path, buf[STRMAX_SHORT];
2609 char **files;
2610 glTexture *t;
2611 ImageArrayCell *cells;
2612 int w, h, land;
2613 Spob *p;
2614 glColour c;
2615
2616 land = (strcmp(wgt,"btnLandGFX") == 0);
2617
2618 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2619 /* Create the window. */
2620 snprintf( buf, sizeof(buf), _("%s - Space Object Properties"), p->name );
2621 wid = window_create( "wdwSpobGFX", buf, -1, -1, -1, -1 );
2622 window_dimWindow( wid, &w, &h );
2623
2626
2627 /* Close button. */
2628 window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
2629 "btnClose", _("Close"), sysedit_btnGFXClose );
2630
2631 /* Apply button. */
2632 window_addButton( wid, -20, 20+(20+BUTTON_HEIGHT), BUTTON_WIDTH, BUTTON_HEIGHT,
2633 land ? "btnApplyLand" : "btnApplySpace", _("Apply"), sysedit_btnGFXApply );
2634
2635 /* Find images first. */
2636 path = land ? SPOB_GFX_EXTERIOR_PATH : SPOB_GFX_SPACE_PATH;
2637 files = PHYSFS_enumerateFiles( path );
2638 for (nfiles=0; files[nfiles]; nfiles++) {}
2639 cells = calloc( nfiles, sizeof(ImageArrayCell) );
2640
2641 j = 0;
2642 for (size_t i=0; i<nfiles; i++) {
2643 PHYSFS_Stat path_stat;
2644 const char *filepath;
2645 snprintf( buf, sizeof(buf), "%s/%s", path, files[i] );
2646 /* Ignore directories. */
2647 if (!PHYSFS_stat( buf, &path_stat )) {
2648 WARN(_("Unable to check file type for '%s'!"), buf);
2649 continue;
2650 }
2651 if (path_stat.filetype != PHYSFS_FILETYPE_REGULAR)
2652 continue;
2653
2654 t = gl_newImage( buf, OPENGL_TEX_MIPMAPS );
2655 if (t == NULL)
2656 continue;
2657 cells[j].image = t;
2658 cells[j].caption = strdup( files[i] );
2659 filepath = (land ? p->gfx_exteriorPath : p->gfx_spacePath);
2660 c = ((filepath==NULL) || strcmp(files[i], filepath)!=0) ? cBlack : cOrange;
2661 memcpy( &cells[j].bg, &c, sizeof(glColour) );
2662 j++;
2663 }
2664 PHYSFS_freeList( files );
2665
2666 /* Add image array. */
2667 window_addImageArray( wid, 20, 20, w-60-BUTTON_WIDTH, h-60, "iarGFX", 128, 128, cells, j, NULL, NULL, NULL );
2668 toolkit_setImageArray( wid, "iarGFX", path );
2669}
2670
2674static void sysedit_btnGFXClose( unsigned int wid, const char *wgt )
2675{
2676 window_close( wid, wgt );
2677}
2678
2682static void sysedit_btnGFXApply( unsigned int wid, const char *wgt )
2683{
2684 Spob *p;
2685 const char *str;
2686 char *path, buf[PATH_MAX];
2687 int land;
2688
2689 land = (strcmp(wgt,"btnApplyLand") == 0);
2690 p = sysedit_sys->spobs[ sysedit_select[0].u.spob ];
2691
2692 /* Get output. */
2693 str = toolkit_getImageArray( wid, "iarGFX" );
2694 if (str == NULL)
2695 return;
2696
2697 /* New path. */
2698 path = land ? SPOB_GFX_EXTERIOR_PATH : SPOB_GFX_SPACE_PATH;
2699 snprintf( buf, sizeof(buf), "%s/%s", path, str );
2700
2701 if (land) {
2702 free( p->gfx_exteriorPath );
2703 free( p->gfx_exterior );
2704 snprintf( buf, sizeof(buf), SPOB_GFX_EXTERIOR_PATH"%s", str );
2705 p->gfx_exteriorPath = strdup( str );
2706 p->gfx_exterior = strdup( buf );
2707 }
2708 else { /* Free old texture, load new. */
2709 free( p->gfx_spaceName );
2710 free( p->gfx_spacePath );
2711 p->gfx_spaceName = strdup( buf );
2712 p->gfx_spacePath = strdup( str );
2713 gl_freeTexture( p->gfx_space );
2714 p->gfx_space = NULL;
2715 p->radius = -1.; /* Reset radius. */
2716 spob_gfxLoad( p );
2717 }
2718
2719 /* For now we close. */
2720 sysedit_btnGFXClose( wid, wgt );
2721}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
Definition array.h:140
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_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:129
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
void asteroids_computeInternals(AsteroidAnchor *a)
Updates internal alues of an asteroid field.
Definition asteroid.c:439
const AsteroidTypeGroup * astgroup_getAll(void)
Gets all the asteroid type groups.
Definition asteroid.c:1046
void asteroid_free(AsteroidAnchor *ast)
Frees an asteroid anchor.
Definition asteroid.c:934
AsteroidTypeGroup * astgroup_getName(const char *name)
Gets an asteroid type group by name.
Definition asteroid.c:1057
int dpl_saveSpob(const Spob *p)
Saves a spob.
Definition dev_spob.c:31
static Select_t sysedit_tsel
Definition dev_sysedit.c:75
static void jp_type_check_nolanes_update(unsigned int wid, const char *str)
Updates the jump point checkboxes.
#define SYSEDIT_ZOOM_STEP
Definition dev_sysedit.c:45
static void sysedit_btnGFXApply(unsigned int wid, const char *wgt)
Apply new graphics.
static double sysedit_xpos
Definition dev_sysedit.c:86
static int sysedit_nselect
Definition dev_sysedit.c:73
static int jp_hidden
Definition dev_sysedit.c:97
static int sysedit_grid
Definition dev_sysedit.c:85
static unsigned int sysedit_wid
Definition dev_sysedit.c:83
static void jp_type_check_exit_update(unsigned int wid, const char *str)
Updates the jump point checkboxes.
static void sysedit_close(unsigned int wid, const char *wgt)
Closes the system editor widget.
static void sysedit_editPntClose(unsigned int wid, const char *unused)
Closes the spob editor, saving the changes made.
static int sysedit_drag
Definition dev_sysedit.c:91
static void sysedit_buttonZoom(unsigned int wid, const char *str)
Handles the button zoom clicks.
static int sysedit_tadd
Definition dev_sysedit.c:76
static void sysedit_selectAdd(const Select_t *sel)
Adds a system to the selection.
static void sysedit_focusLose(unsigned int wid, const char *wgtname)
Called when it's de-focused.
static void sysedit_btnGrid(unsigned int wid_unused, const char *unused)
Toggles the grid.
static void sysedit_btnNewSpob(unsigned int wid_unused, const char *unused)
Enters the editor in new spob mode.
static int sysedit_selectCmp(const Select_t *a, const Select_t *b)
Compares two selections to see if they are the same.
#define SYSEDIT_EDIT_WIDTH
Definition dev_sysedit.c:39
static void sysedit_btnReset(unsigned int wid_unused, const char *unused)
Resets jump points.
static int sysedit_keys(unsigned int wid, SDL_Keycode key, SDL_Keymod mod, int isrepeat)
Handles keybindings.
static void sysedit_render(double bx, double by, double w, double h, void *data)
System editor custom widget rendering.
static double sysedit_ypos
Definition dev_sysedit.c:87
static int sysedit_isSelected(const Select_t *s)
Check to see if something is selected.
static void sysedit_renderAsteroidsField(double bx, double by, const AsteroidAnchor *ast, int selected)
Draws an asteroid field on the map.
static void sysedit_btnRmTag(unsigned int wid, const char *unused)
Removes a tech from a spob.
@ SELECT_ASTEROID
Definition dev_sysedit.c:56
@ SELECT_ASTEXCLUDE
Definition dev_sysedit.c:57
@ SELECT_JUMPPOINT
Definition dev_sysedit.c:55
@ SELECT_NONE
Definition dev_sysedit.c:53
@ SELECT_SPOB
Definition dev_sysedit.c:54
static unsigned int sysedit_widEdit
Definition dev_sysedit.c:84
static void sysedit_renderSprite(glTexture *gfx, double bx, double by, double x, double y, int sx, int sy, const glColour *c, int selected, const char *caption)
Renders a sprite for the custom widget.
static void sysedit_genTagsList(unsigned int wid)
Generates the spob tech list.
static int jp_exit
Definition dev_sysedit.c:98
static void sysedit_btnAddService(unsigned int wid, const char *unused)
Adds a service to a spob.
static void sysedit_genTechList(unsigned int wid)
Generates the spob tech list.
static void sysedit_btnGFXClose(unsigned int wid, const char *wgt)
Closes the spob graphic editor.
static void sysedit_deselect(void)
Deselects everything.
static void sysedit_checkButtons(void)
Checks to see which buttons should be active and the likes.
static void sysedit_btnRmTech(unsigned int wid, const char *unused)
Removes a tech from a spob.
static double sysedit_zoom
Definition dev_sysedit.c:88
static void sysedit_btnFaction(unsigned int wid_unused, const char *unused)
Edits a spob's faction.
static void sysedit_spobGFX(unsigned int wid_unused, const char *wgt)
Opens the spob landing or space graphic editor.
static void sysedit_editAsteroids(void)
Opens the asteroid editor.
static void sysedit_selectRm(Select_t *sel)
Removes a system from the selection.
static char ** sysedit_tagslist
Definition dev_sysedit.c:77
static StarSystem * sysedit_sys
Definition dev_sysedit.c:82
#define SYSEDIT_DRAG_THRESHOLD
Definition dev_sysedit.c:42
static void sysedit_btnEdit(unsigned int wid_unused, const char *unused)
Opens the system property editor.
#define SYSEDIT_ZOOM_MIN
Definition dev_sysedit.c:47
static void sysedit_btnNewTag(unsigned int wid, const char *unused)
Adds a tech to a spob.
#define SYSEDIT_MOVE_THRESHOLD
Definition dev_sysedit.c:43
static void sysedit_renderAsteroidExclusion(double bx, double by, const AsteroidExclusion *aexcl, int selected)
Draws an asteroid exclusion zone on the map.
#define BUTTON_HEIGHT
Definition dev_sysedit.c:37
static void sysedit_spobDescClose(unsigned int wid, const char *unused)
Closes both the spob description window and the properties window.
static void sysedit_btnFactionSet(unsigned int wid, const char *unused)
Actually modifies the faction.
static unsigned int sysedit_dragTime
Definition dev_sysedit.c:90
#define SYSEDIT_EDIT_HEIGHT
Definition dev_sysedit.c:40
static void sysedit_spobDesc(unsigned int wid, const char *unused)
Displays the spob landing description and bar description in a separate window.
static void sysedit_editJumpClose(unsigned int wid, const char *unused)
Closes the jump editor, saving the changes made.
static void sysedit_btnScale(unsigned int wid_unused, const char *unused)
Interface for scaling a system from the system view.
static int sysedit_mselect
Definition dev_sysedit.c:74
static void sysedit_genServicesList(unsigned int wid)
Generates the spob services list.
static double sysedit_my
Definition dev_sysedit.c:94
static void sysedit_btnRemove(unsigned int wid_unused, const char *unused)
Removes spobs.
void sysedit_open(StarSystem *sys)
Opens the system editor interface.
static void sysedit_btnRmService(unsigned int wid, const char *unused)
Removes a service from a spob.
static void sysedit_renderBG(double bx, double bw, double w, double h, double x, double y)
Renders the custom widget background.
static void sysedit_btnAddTag(unsigned int wid, const char *unused)
Adds a tech to a spob.
static void sysedit_btnTagsEdit(unsigned int wid, const char *unused)
Edits a spob's tags.
static void sysedit_editPnt(void)
Edits a spob.
static int sysedit_moved
Definition dev_sysedit.c:89
static void sysedit_spobDescReturn(unsigned int wid, const char *unused)
Closes the spob description window and returns to the properties window.
static void sysedit_btnAddTech(unsigned int wid, const char *unused)
Adds a tech to a spob.
void sysedit_sysScale(StarSystem *sys, double factor)
Scales a system.
#define BUTTON_WIDTH
Definition dev_sysedit.c:36
static int sysedit_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 void jp_type_check_hidden_update(unsigned int wid, const char *str)
Updates the jump point checkboxes.
static double sysedit_mx
Definition dev_sysedit.c:93
static void sysedit_btnTechEdit(unsigned int wid, const char *unused)
Edits a spob's tech.
static int sysedit_dragSel
Definition dev_sysedit.c:92
static void sysedit_btnNewAsteroids(unsigned int wid_unused, const char *unused)
Enters the editor in new spob mode.
#define SYSEDIT_ZOOM_MAX
Definition dev_sysedit.c:46
static void sysedit_editJump(void)
Edits a jump.
static Select_t * sysedit_select
Definition dev_sysedit.c:72
int dsys_saveSystem(StarSystem *sys)
Saves a star system.
Definition dev_system.c:83
void uniedit_selectText(void)
Sets the selected system text.
char * dialogue_runChoice(void)
Run the dialog and return the clicked string.
Definition dialogue.c:795
char * dialogue_inputRaw(const char *title, int min, int max, const char *msg)
Creates a dialogue that allows the player to write a message.
Definition dialogue.c:469
void dialogue_alert(const char *fmt,...)
Displays an alert popup with only an ok button and a message.
Definition dialogue.c:132
char * dialogue_input(const char *title, int min, int max, const char *fmt,...)
Creates a dialogue that allows the player to write a message.
Definition dialogue.c:441
void dialogue_addChoice(const char *caption, const char *msg, const char *opt)
Add a choice to the dialog.
Definition dialogue.c:773
void dialogue_makeChoice(const char *caption, const char *msg, int opts)
Create the choice dialog. Need to add choices with below method.
Definition dialogue.c:751
int dialogue_YesNo(const char *caption, const char *fmt,...)
Runs a dialogue with both yes and no options.
Definition dialogue.c:352
int economy_execQueued(void)
Calls economy_refresh if an economy update is queued.
Definition economy.c:483
const char * faction_name(int f)
Gets a factions "real" (internal) name.
Definition faction.c:306
const glColour * faction_colour(int f)
Gets the colour of the faction.
Definition faction.c:469
int * faction_getAll(void)
Returns all faction IDs in an array (array.h).
Definition faction.c:195
int faction_get(const char *name)
Gets a faction ID by name.
Definition faction.c:184
glFont gl_smallFont
Definition font.c:154
int gl_printWidthRaw(const glFont *ft_font, const char *text)
Gets the width that it would take to print some text.
Definition font.c:961
glFont gl_defFont
Definition font.c:153
int gl_printMidRaw(const glFont *ft_font, int width, double x, double y, const glColour *c, double outlineR, const char *text)
Displays text centered in position and width.
Definition font.c:788
void gl_print(const glFont *ft_font, const double x, const double y, const glColour *c, const char *fmt,...)
Prints text on screen like printf.
Definition font.c:691
glFont gl_defFontMono
Definition font.c:155
void land(Spob *p, int load)
Opens up all the land dialogue stuff.
Definition land.c:1124
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
#define PATH_MAX
Definition naev.h:50
int strsort(const void *p1, const void *p2)
Sort function for sorting strings with qsort().
Definition nstring.c:81
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 gl_renderShader(double x, double y, double w, double h, double r, const SimpleShader *shd, const glColour *c, int center)
Renders a simple shader.
void gl_renderRect(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
void gl_renderLine(double x1, double y1, double x2, double y2, const glColour *c)
Draws a line.
void gl_renderScaleSprite(const glTexture *sprite, double bx, double by, int sx, int sy, double bw, double bh, const glColour *c)
Blits a scaled sprite, position is in absolute screen coordinates.
void gl_renderRectEmpty(double x, double y, double w, double h, const glColour *c)
Renders a rectangle.
void gl_renderCross(double x, double y, double r, const glColour *c)
Renders a cross at a given position.
void gl_renderCircle(double cx, double cy, double r, const glColour *c, int filled)
Draws a circle.
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
Definition opengl_tex.c:675
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:862
static const double c[]
Definition rng.c:264
static const double d[]
Definition rng.c:273
void safelanes_recalculate(void)
Update the safe lane locations in response to the universe changing (e.g., diff applied).
Definition safelanes.c:252
SafeLane * safelanes_get(int faction, int standing, const StarSystem *system)
Gets a set of safelanes for a faction and system.
Definition safelanes.c:190
void space_reconstructPresences(void)
Reset the presence of all systems.
Definition space.c:4263
int spob_exists(const char *spobname)
Check to see if a spob exists.
Definition space.c:1126
void systems_reconstructJumps(void)
Reconstructs the jumps.
Definition space.c:2738
Spob * spob_getAll(void)
Gets an array (array.h) of all spobs.
Definition space.c:1107
int spob_rename(Spob *p, char *newname)
Renames a spob.
Definition space.c:431
int spob_getService(const char *name)
Converts name to spob service flag.
Definition space.c:186
void system_setFaction(StarSystem *sys)
Sets the system faction based on the spobs it has.
Definition space.c:3091
Spob * spob_get(const char *spobname)
Gets a spob based on its name.
Definition space.c:1051
const char * space_getRndSpob(int landable, unsigned int services, int(*filter)(Spob *p))
Gets the name of a random spob.
Definition space.c:633
StarSystem * system_getIndex(int id)
Get the system by its index.
Definition space.c:989
JumpPoint * jump_getTarget(const StarSystem *target, const StarSystem *sys)
Less safe version of jump_get that works with pointers.
Definition space.c:1246
const char * spob_getSystem(const char *spobname)
Get the name of a system from a spobname.
Definition space.c:1025
void system_updateAsteroids(StarSystem *sys)
Updates some internal calculations about asteroids in a system.
Definition space.c:326
int system_addSpob(StarSystem *sys, const char *spobname)
Adds a spob to a star system.
Definition space.c:2452
void spob_gfxLoad(Spob *spob)
Loads a spob's graphics (and radius).
Definition space.c:2078
Spob * spob_getIndex(int ind)
Gets spob by index.
Definition space.c:1082
const char * spob_getServiceName(int service)
Gets the (English) name for a service code.
Definition space.c:167
Spob * spob_new(void)
Creates a new spob.
Definition space.c:1709
glTexture * jumppoint_gfx
Definition space.c:107
void space_gfxLoad(StarSystem *sys)
Loads all the graphics for a star system.
Definition space.c:2116
int system_rmSpob(StarSystem *sys, const char *spobname)
Removes a spob from a star system.
Definition space.c:2493
Represents an asteroid field anchor.
Definition asteroid.h:100
double radius
Definition asteroid.h:107
double density
Definition asteroid.h:104
double * groupsw
Definition asteroid.h:110
double maxspeed
Definition asteroid.h:112
Asteroid * asteroids
Definition asteroid.h:105
AsteroidTypeGroup ** groups
Definition asteroid.h:109
Represents an asteroid exclusion zone.
Definition asteroid.h:124
Represents a group of asteroids.
Definition asteroid.h:67
int devautosave
Definition conf.h:158
char * dev_save_spob
Definition conf.h:172
Describes a safe lane, patrolled by a faction, within a system.
Definition safelanes.h:24
int point_id[2]
Definition safelanes.h:27
int faction
Definition safelanes.h:25
SafeLaneLocType point_type[2]
Definition safelanes.h:26
Selection generic for stuff in a system.
Definition dev_sysedit.c:63
union Select_t::@29 u
Represents a Space Object (SPOB), including and not limited to planets, stations, wormholes,...
Definition space.h:89
char ** tags
Definition space.h:130
char * name
Definition space.h:91
vec2 pos
Definition space.h:94
int h
Definition font.h:18
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:36
double sw
Definition opengl_tex.h:46
double sh
Definition opengl_tex.h:47
double sx
Definition opengl_tex.h:44
Represents a 2d vector.
Definition vec2.h:32
double y
Definition vec2.h:34
double x
Definition vec2.h:33
int tech_rmItemTech(tech_group_t *tech, const char *value)
Removes an item from a tech.
Definition tech.c:488
tech_group_t * tech_groupCreate(void)
Creates a tech group.
Definition tech.c:176
int tech_getItemCount(const tech_group_t *tech)
Gets the number of techs within a given group.
Definition tech.c:674
int tech_hasItem(const tech_group_t *tech, const char *item)
Checks whether a given tech group has the specified item.
Definition tech.c:658
int tech_addItemTech(tech_group_t *tech, const char *value)
Adds an item to a tech.
Definition tech.c:468
char ** tech_getItemNames(const tech_group_t *tech, int *n)
Gets the names of all techs within a given group.
Definition tech.c:686
char ** tech_getAllItemNames(int *n)
Gets the names of all techs.
Definition tech.c:706
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_setDynamic(unsigned int wid, int dynamic)
Sets a window as dynamic, so that it is drawn every frame completely.
Definition toolkit.c:647
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_dimWindow(unsigned int wid, int *w, int *h)
Gets the dimensions of a window.
Definition toolkit.c:371
void window_setCancel(unsigned int wid, void(*cancel)(unsigned int, const char *))
Sets the default cancel function of the window.
Definition toolkit.c:868
int window_existsID(unsigned int wid)
Checks to see if a window with a certain ID exists.
Definition toolkit.c:612
void window_destroyWidget(unsigned int wid, const char *wgtname)
Destroys a widget in a window.
Definition toolkit.c:1165
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_setBorder(unsigned int wid, int enable)
Sets or removes the border of a window.
Definition toolkit.c:941
int widget_exists(unsigned int wid, const char *wgtname)
Checks to see if a widget exists.
Definition toolkit.c:1142
void window_close(unsigned int wid, const char *str)
Helper function to automatically close the window calling it.
Definition toolkit.c:1026