Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1581 lines (1280 sloc) 42.819 kB
/*
* See Licensing and Copyright notice in naev.h
*/
/**
* @file dev_uniedit.c
*
* @brief Handles the star system editor.
*/
#include "dev_uniedit.h"
#include "naev.h"
#include "SDL.h"
#include "space.h"
#include "toolkit.h"
#include "opengl.h"
#include "map.h"
#include "map_find.h"
#include "dev_system.h"
#include "dev_planet.h"
#include "unidiff.h"
#include "dialogue.h"
#include "tk/toolkit_priv.h"
#include "dev_sysedit.h"
#include "pause.h"
#include "nfile.h"
#include "nstring.h"
#include "conf.h"
#define BUTTON_WIDTH 80 /**< Map button width. */
#define BUTTON_HEIGHT 30 /**< Map button height. */
#define UNIEDIT_EDIT_WIDTH 400 /**< System editor width. */
#define UNIEDIT_EDIT_HEIGHT 450 /**< System editor height. */
#define UNIEDIT_FIND_WIDTH 400 /**< System editor width. */
#define UNIEDIT_FIND_HEIGHT 500 /**< System editor height. */
#define UNIEDIT_DRAG_THRESHOLD 300 /**< Drag threshold. */
#define UNIEDIT_MOVE_THRESHOLD 10 /**< Movement threshold. */
#define UNIEDIT_ZOOM_STEP 1.2 /**< Factor to zoom by for each zoom level. */
#define UNIEDIT_ZOOM_MAX 5 /**< Maximum uniedit zoom level (close). */
#define UNIEDIT_ZOOM_MIN -5 /**< Minimum uniedit zoom level (far). */
/*
* The editor modes.
*/
#define UNIEDIT_DEFAULT 0 /**< Default editor mode. */
#define UNIEDIT_JUMP 1 /**< Jump point toggle mode. */
#define UNIEDIT_NEWSYS 2 /**< New system editor mode. */
extern int systems_nstack;
static int uniedit_mode = UNIEDIT_DEFAULT; /**< Editor mode. */
static unsigned int uniedit_wid = 0; /**< Sysedit wid. */
static unsigned int uniedit_widEdit = 0; /**< Sysedit editor wid. */
static unsigned int uniedit_widFind = 0; /**< Sysedit find wid. */
static double uniedit_xpos = 0.; /**< Viewport X position. */
static double uniedit_ypos = 0.; /**< Viewport Y position. */
static double uniedit_zoom = 1.; /**< Viewport zoom level. */
static int uniedit_moved = 0; /**< Space moved since mouse down. */
static unsigned int uniedit_dragTime = 0; /**< Tick last started to drag. */
static int uniedit_drag = 0; /**< Dragging viewport around. */
static int uniedit_dragSys = 0; /**< Dragging system around. */
static StarSystem **uniedit_sys = NULL; /**< Selected systems. */
static StarSystem *uniedit_tsys = NULL; /**< Temporarily clicked system. */
static int uniedit_tadd = 0; /**< Temporarily clicked system should be added. */
static int uniedit_nsys = 0; /**< Number of selected systems. */
static int uniedit_msys = 0; /**< Memory allocated for selected systems. */
static double uniedit_mx = 0.; /**< X mouse position. */
static double uniedit_my = 0.; /**< Y mouse position. */
static map_find_t *found_cur = NULL; /**< Pointer to found stuff. */
static int found_ncur = 0; /**< Number of found stuff. */
/*
* Universe editor Prototypes.
*/
/* Selection. */
static void uniedit_deselect (void);
static void uniedit_selectAdd( StarSystem *sys );
static void uniedit_selectRm( StarSystem *sys );
/* System and asset search. */
static void uniedit_findSys (void);
static void uniedit_findSysClose( unsigned int wid, char *name );
static void uniedit_findSearch( unsigned int wid, char *str );
static void uniedit_findShowResults( unsigned int wid, map_find_t *found, int n );
static void uniedit_centerSystem( unsigned int wid, char *unused );
static int uniedit_sortCompare( const void *p1, const void *p2 );
/* System editing. */
static void uniedit_editSys (void);
static void uniedit_editSysClose( unsigned int wid, char *name );
static void uniedit_editGenList( unsigned int wid );
static void uniedit_btnEditRename( unsigned int wid, char *unused );
static void uniedit_btnEditRmAsset( unsigned int wid, char *unused );
static void uniedit_btnEditAddAsset( unsigned int wid, char *unused );
static void uniedit_btnEditAddAssetAdd( unsigned int wid, char *unused );
/* System renaming. */
static int uniedit_checkName( char *name );
static void uniedit_renameSys (void);
/* New system. */
static void uniedit_newSys( double x, double y );
/* Jump handling. */
static void uniedit_toggleJump( StarSystem *sys );
static void uniedit_jumpAdd( StarSystem *sys, StarSystem *targ );
static void uniedit_jumpRm( StarSystem *sys, StarSystem *targ );
/* Custom system editor widget. */
static void uniedit_buttonZoom( unsigned int wid, char* str );
static void uniedit_render( double bx, double by, double w, double h, void *data );
static void uniedit_renderOverlay( double bx, double by, double bw, double bh, void* data );
static int uniedit_mouse( unsigned int wid, SDL_Event* event, double mx, double my,
double w, double h, void *data );
/* Button functions. */
static void uniedit_close( unsigned int wid, char *wgt );
static void uniedit_save( unsigned int wid_unused, char *unused );
static void uniedit_saveMap( unsigned int wid_unused, char *unused );
static void uniedit_btnJump( unsigned int wid_unused, char *unused );
static void uniedit_btnRename( unsigned int wid_unused, char *unused );
static void uniedit_btnEdit( unsigned int wid_unused, char *unused );
static void uniedit_btnNew( unsigned int wid_unused, char *unused );
static void uniedit_btnOpen( unsigned int wid_unused, char *unused );
static void uniedit_btnFind( unsigned int wid_unused, char *unused );
/* Keybindings handling. */
static int uniedit_keys( unsigned int wid, SDLKey key, SDLMod mod );
/**
* @brief Opens the system editor interface.
*/
void uniedit_open( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
unsigned int wid;
int buttonPos = 0;
/* Pause. */
pause_game();
/* Needed to generate faction disk. */
map_setZoom( 1. );
/* Must have no diffs applied. */
diff_clear();
/* Reset some variables. */
uniedit_mode = UNIEDIT_DEFAULT;
uniedit_drag = 0;
uniedit_dragSys = 0;
uniedit_tsys = NULL;
uniedit_tadd = 0;
uniedit_zoom = 1.;
uniedit_xpos = 0.;
uniedit_ypos = 0.;
/* Create the window. */
wid = window_create( "Universe Editor", -1, -1, -1, -1 );
window_handleKeys( wid, uniedit_keys );
uniedit_wid = wid;
/* Close button. */
window_addButton( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnClose", "Close", uniedit_close );
buttonPos++;
/* Autosave toggle. */
window_addCheckbox( wid, -150, 25, 250, 20,
"chkEditAutoSave", "Automatically save changes", uniedit_autosave, conf.devautosave );
/* Save button. */
window_addButton( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnSave", "Save All", uniedit_save );
buttonPos++;
/* Save Map button. */
window_addButton( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnSaveMap", "Save Map", uniedit_saveMap );
buttonPos++;
/* Jump toggle. */
buttonPos++;
window_addButtonKey( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnJump", "Jump", uniedit_btnJump, SDLK_j );
buttonPos++;
/* Rename system. */
window_addButtonKey( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnRename", "Rename", uniedit_btnRename, SDLK_r );
buttonPos++;
/* Edit system. */
window_addButtonKey( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnEdit", "Edit", uniedit_btnEdit, SDLK_e );
buttonPos++;
/* New system. */
window_addButtonKey( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnNew", "New Sys", uniedit_btnNew, SDLK_n );
buttonPos++;
/* Open a system. */
window_addButtonKey( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnOpen", "Open", uniedit_btnOpen, SDLK_o );
buttonPos++;
/* Find a system or asset. */
window_addButtonKey( wid, -20, 20+(BUTTON_HEIGHT+20)*buttonPos, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnFind", "Find", uniedit_btnFind, SDLK_f );
buttonPos++;
/* Zoom buttons */
window_addButton( wid, 40, 20, 30, 30, "btnZoomIn", "+", uniedit_buttonZoom );
window_addButton( wid, 80, 20, 30, 30, "btnZoomOut", "-", uniedit_buttonZoom );
/* Presence. */
window_addText( wid, -20, -140, 100, 20, 0, "txtSPresence",
&gl_smallFont, &cDConsole, "Presence:" );
window_addText( wid, -10, -140-gl_smallFont.h-5, 110, 100, 0, "txtPresence",
&gl_smallFont, &cBlack, "N/A" );
/* Selected text. */
window_addText( wid, 140, 10, SCREEN_W - 80 - 30 - 30 - BUTTON_WIDTH - 20, 30, 0,
"txtSelected", &gl_smallFont, &cBlack, NULL );
/* Actual viewport. */
window_addCust( wid, 20, -40, SCREEN_W - 150, SCREEN_H - 100,
"cstSysEdit", 1, uniedit_render, uniedit_mouse, NULL );
window_custSetOverlay( wid, "cstSysEdit", uniedit_renderOverlay );
/* Deselect everything. */
uniedit_deselect();
}
/**
* @brief Handles keybindings.
*/
static int uniedit_keys( unsigned int wid, SDLKey key, SDLMod mod )
{
(void) wid;
(void) mod;
switch (key) {
/* Mode changes. */
case SDLK_ESCAPE:
uniedit_mode = UNIEDIT_DEFAULT;
return 1;
default:
return 0;
}
}
/**
* @brief Closes the system editor widget.
*/
static void uniedit_close( unsigned int wid, char *wgt )
{
/* Frees some memory. */
uniedit_deselect();
/* Reconstruct jumps. */
systems_reconstructJumps();
/* Unpause. */
unpause_game();
/* Close the window. */
window_close( wid, wgt );
}
/*
* @brief Saves the systems.
*/
static void uniedit_save( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
dsys_saveAll();
dpl_saveAll();
}
/*
* @brief Toggles autosave.
*/
void uniedit_autosave( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
conf.devautosave = window_checkboxState( wid_unused, "chkEditAutoSave" );
}
/*
* @brief Updates autosave check box.
*/
void uniedit_updateAutosave (void)
{
window_checkboxSet( uniedit_wid, "chkEditAutoSave", conf.devautosave );
}
/*
* @brief Saves a map.
*/
static void uniedit_saveMap( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
dsys_saveMap(uniedit_sys, uniedit_nsys);
}
/**
* @brief Enters the editor in new jump mode.
*/
static void uniedit_btnJump( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
uniedit_mode = UNIEDIT_JUMP;
}
/**
* @brief Renames selected systems.
*/
static void uniedit_btnRename( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
uniedit_renameSys();
}
/**
* @brief Enters the editor in new system mode.
*/
static void uniedit_btnNew( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
uniedit_mode = UNIEDIT_NEWSYS;
}
/**
* @brief Opens up a system.
*/
static void uniedit_btnOpen( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
if (uniedit_nsys != 1)
return;
sysedit_open( uniedit_sys[0] );
}
/**
* @brief Opens the system property editor.
*/
static void uniedit_btnFind( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
uniedit_findSys();
}
/**
* @brief Opens the system property editor.
*/
static void uniedit_btnEdit( unsigned int wid_unused, char *unused )
{
(void) wid_unused;
(void) unused;
uniedit_editSys();
}
/**
* @brief System editor custom widget rendering.
*/
static void uniedit_render( double bx, double by, double w, double h, void *data )
{
(void) data;
double x,y,r;
StarSystem *sys;
int i;
/* Parameters. */
map_renderParams( bx, by, uniedit_xpos, uniedit_ypos, w, h, uniedit_zoom, &x, &y, &r );
/* background */
gl_renderRect( bx, by, w, h, &cBlack );
/* Render faction disks. */
map_renderFactionDisks( x, y, 1 );
/* Render jump paths. */
map_renderJumps( x, y, 1 );
/* Render systems. */
map_renderSystems( bx, by, x, y, w, h, r, 1 );
/* Render system names. */
map_renderNames( bx, by, x, y, w, h, 1 );
/* Render the selected system selections. */
for (i=0; i<uniedit_nsys; i++) {
sys = uniedit_sys[i];
gl_drawCircleInRect( x + sys->pos.x * uniedit_zoom, y + sys->pos.y * uniedit_zoom,
1.5*r, bx, by, w, h, &cWhite, 0 );
}
}
/**
* @brief Renders the overlay.
*/
static void uniedit_renderOverlay( double bx, double by, double bw, double bh, void* data )
{
double x, y;
(void) bw;
(void) bh;
(void) data;
x = bx + uniedit_mx;
y = by + uniedit_my;
if (uniedit_mode == UNIEDIT_NEWSYS)
toolkit_drawAltText( x, y, "Click to add a new system");
else if (uniedit_mode == UNIEDIT_JUMP)
toolkit_drawAltText( x, y, "Click to toggle jump route");
}
/**
* @brief System editor custom widget mouse handling.
*/
static int uniedit_mouse( unsigned int wid, SDL_Event* event, double mx, double my,
double w, double h, void *data )
{
(void) wid;
(void) data;
int i;
double x,y, t;
StarSystem *sys;
SDLMod mod;
t = 15.*15.; /* threshold */
/* Handle modifiers. */
mod = SDL_GetModState();
switch (event->type) {
#if SDL_VERSION_ATLEAST(2,0,0)
case SDL_MOUSEWHEEL:
/* Must be in bounds. */
if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
return 0;
if (event->wheel.y > 0)
uniedit_buttonZoom( 0, "btnZoomIn" );
else
uniedit_buttonZoom( 0, "btnZoomOut" );
return 1;
#endif /* SDL_VERSION_ATLEAST(2,0,0) */
case SDL_MOUSEBUTTONDOWN:
/* Must be in bounds. */
if ((mx < 0.) || (mx > w) || (my < 0.) || (my > h))
return 0;
#if !SDL_VERSION_ATLEAST(2,0,0)
/* Zooming */
if (event->button.button == SDL_BUTTON_WHEELUP) {
uniedit_buttonZoom( 0, "btnZoomIn" );
return 1;
}
else if (event->button.button == SDL_BUTTON_WHEELDOWN) {
uniedit_buttonZoom( 0, "btnZoomOut" );
return 1;
}
#endif /* !SDL_VERSION_ATLEAST(2,0,0) */
/* selecting star system */
else {
mx -= w/2 - uniedit_xpos;
my -= h/2 - uniedit_ypos;
if (uniedit_mode == UNIEDIT_NEWSYS) {
uniedit_newSys( mx, my );
uniedit_mode = UNIEDIT_DEFAULT;
return 1;
}
for (i=0; i<systems_nstack; i++) {
sys = system_getIndex( i );
/* get position */
x = sys->pos.x * uniedit_zoom;
y = sys->pos.y * uniedit_zoom;
if ((pow2(mx-x)+pow2(my-y)) < t) {
/* Try to find in selected systems - begin drag move. */
for (i=0; i<uniedit_nsys; i++) {
/* Must match. */
if (uniedit_sys[i] != sys)
continue;
/* Detect double click to open system. */
if ((SDL_GetTicks() - uniedit_dragTime < UNIEDIT_DRAG_THRESHOLD*2)
&& (uniedit_moved < UNIEDIT_MOVE_THRESHOLD)) {
if (uniedit_nsys == 1) {
sysedit_open( uniedit_sys[0] );
return 1;
}
}
/* Handle normal click. */
if (uniedit_mode == UNIEDIT_DEFAULT) {
uniedit_dragSys = 1;
uniedit_tsys = sys;
/* Check modifier. */
if (mod & (KMOD_LCTRL | KMOD_RCTRL))
uniedit_tadd = 0;
else
uniedit_tadd = -1;
uniedit_dragTime = SDL_GetTicks();
uniedit_moved = 0;
}
return 1;
}
if (uniedit_mode == UNIEDIT_DEFAULT) {
/* Add the system if not selected. */
if (mod & (KMOD_LCTRL | KMOD_RCTRL))
uniedit_selectAdd( sys );
else {
uniedit_deselect();
uniedit_selectAdd( sys );
}
uniedit_tsys = NULL;
/* Start dragging anyway. */
uniedit_dragSys = 1;
uniedit_dragTime = SDL_GetTicks();
uniedit_moved = 0;
}
else if (uniedit_mode == UNIEDIT_JUMP) {
uniedit_toggleJump( sys );
uniedit_mode = UNIEDIT_DEFAULT;
}
return 1;
}
}
/* Start dragging. */
if ((uniedit_mode == UNIEDIT_DEFAULT) && !(mod & (KMOD_LCTRL | KMOD_RCTRL))) {
uniedit_drag = 1;
uniedit_dragTime = SDL_GetTicks();
uniedit_moved = 0;
uniedit_tsys = NULL;
}
return 1;
}
break;
case SDL_MOUSEBUTTONUP:
if (uniedit_drag) {
if ((SDL_GetTicks() - uniedit_dragTime < UNIEDIT_DRAG_THRESHOLD) && (uniedit_moved < UNIEDIT_MOVE_THRESHOLD)) {
if (uniedit_tsys == NULL)
uniedit_deselect();
else
uniedit_selectAdd( uniedit_tsys );
}
uniedit_drag = 0;
}
if (uniedit_dragSys) {
if ((SDL_GetTicks() - uniedit_dragTime < UNIEDIT_DRAG_THRESHOLD) &&
(uniedit_moved < UNIEDIT_MOVE_THRESHOLD) && (uniedit_tsys != NULL)) {
if (uniedit_tadd == 0)
uniedit_selectRm( uniedit_tsys );
else {
uniedit_deselect();
uniedit_selectAdd( uniedit_tsys );
}
}
uniedit_dragSys = 0;
if (conf.devautosave)
for (i=0; i<uniedit_nsys; i++)
dsys_saveSystem(uniedit_sys[i]);
}
break;
case SDL_MOUSEMOTION:
/* Update mouse positions. */
uniedit_mx = mx;
uniedit_my = my;
/* Handle dragging. */
if (uniedit_drag) {
/* axis is inverted */
uniedit_xpos -= event->motion.xrel;
uniedit_ypos += event->motion.yrel;
/* Update mouse movement. */
uniedit_moved += ABS( event->motion.xrel ) + ABS( event->motion.yrel );
}
else if (uniedit_dragSys && (uniedit_nsys > 0)) {
if ((uniedit_moved > UNIEDIT_MOVE_THRESHOLD) || (SDL_GetTicks() - uniedit_dragTime > UNIEDIT_DRAG_THRESHOLD)) {
for (i=0; i<uniedit_nsys; i++) {
uniedit_sys[i]->pos.x += ((double)event->motion.xrel) / uniedit_zoom;
uniedit_sys[i]->pos.y -= ((double)event->motion.yrel) / uniedit_zoom;
}
}
/* Update mouse movement. */
uniedit_moved += ABS( event->motion.xrel ) + ABS( event->motion.yrel );
}
break;
}
return 0;
}
/**
* @brief Checks to see if a system name is already in use.
*
* @return 1 if system name is already in use.
*/
static int uniedit_checkName( char *name )
{
int i;
/* Avoid name collisions. */
for (i=0; i<systems_nstack; i++) {
if (strcmp(name, system_getIndex(i)->name)==0) {
dialogue_alert( "The Star System '%s' already exists!", name );
return 1;
}
}
return 0;
}
char *uniedit_nameFilter( char *name )
{
int i, pos;
char *out;
out = calloc( 1, (strlen(name)+1) );
pos = 0;
for (i=0; i<(int)strlen(name); i++) {
if (!ispunct(name[i])) {
if (name[i] == ' ')
out[pos] = '_';
else
out[pos] = tolower(name[i]);
pos++;
}
}
return out;
}
/**
* @brief Renames all the currently selected systems.
*/
static void uniedit_renameSys (void)
{
int i, j;
char *name, *oldName, *newName, *filtered;
StarSystem *sys;
for (i=0; i<uniedit_nsys; i++) {
sys = uniedit_sys[i];
/* Get name. */
name = dialogue_input( "Rename Star System", 1, 32, "What do you want to rename \er%s\e0?", sys->name );
/* Keep current name. */
if (name == NULL)
continue;
/* Try again. */
if (uniedit_checkName( name )) {
free(name);
i--;
continue;
}
/* Change the name. */
filtered = uniedit_nameFilter(sys->name);
oldName = malloc(14 + strlen(filtered));
nsnprintf(oldName, 14 + strlen(filtered), "dat/ssys/%s.xml", filtered);
free(filtered);
filtered = uniedit_nameFilter(name);
newName = malloc(14 + strlen(filtered));
nsnprintf(newName, 14 + strlen(filtered), "dat/ssys/%s.xml", filtered);
free(filtered);
nfile_rename(oldName,newName);
free(oldName);
free(newName);
free(sys->name);
sys->name = name;
dsys_saveSystem(sys);
/* Re-save adjacent systems. */
for (j=0; j<sys->njumps; j++)
dsys_saveSystem( sys->jumps[j].target );
}
}
/**
* @brief Creates a new system.
*/
static void uniedit_newSys( double x, double y )
{
char *name;
StarSystem *sys;
/* Get name. */
name = dialogue_inputRaw( "New Star System Creation", 1, 32, "What do you want to name the new system?" );
/* Abort. */
if (name == NULL) {
dialogue_alert( "Star System creation aborted!" );
return;
}
/* Make sure there is no collision. */
if (uniedit_checkName( name )) {
free(name);
uniedit_newSys( x, y );
return;
}
/* Transform coordinates back to normal if zoomed */
x /= uniedit_zoom;
y /= uniedit_zoom;
/* Create the system. */
sys = system_new();
sys->name = name;
sys->pos.x = x;
sys->pos.y = y;
sys->stars = STARS_DENSITY_DEFAULT;
sys->radius = RADIUS_DEFAULT;
/* Select new system. */
uniedit_deselect();
uniedit_selectAdd( sys );
if (conf.devautosave)
dsys_saveSystem( sys );
}
/**
* @brief Toggles the jump point for the selected systems.
*/
static void uniedit_toggleJump( StarSystem *sys )
{
int i, j, rm;
StarSystem *isys, *target;
for (i=0; i<uniedit_nsys; i++) {
isys = uniedit_sys[i];
rm = 0;
for (j=0; j<isys->njumps; j++) {
target = isys->jumps[j].target;
/* Target already exists, remove. */
if (target == sys) {
uniedit_jumpRm( isys, sys );
uniedit_jumpRm( sys, isys );
rm = 1;
break;
}
}
/* Target doesn't exist, add. */
if (!rm) {
uniedit_jumpAdd( isys, sys );
uniedit_jumpAdd( sys, isys );
}
}
/* Reconstruct jumps just in case. */
systems_reconstructJumps();
/* Reconstruct universe presences. */
space_reconstructPresences();
if (conf.devautosave) {
dsys_saveSystem( sys );
dsys_saveSystem( isys );
}
/* Update sidebar text. */
uniedit_selectText();
}
/**
* @brief Adds a new Star System jump.
*/
static void uniedit_jumpAdd( StarSystem *sys, StarSystem *targ )
{
JumpPoint *jp;
/* Add the jump. */
sys->njumps++;
sys->jumps = realloc( sys->jumps, sizeof(JumpPoint) * sys->njumps );
jp = &sys->jumps[ sys->njumps-1 ];
memset( jp, 0, sizeof(JumpPoint) );
/* Fill it out with basics. */
jp->target = targ;
jp->targetid = targ->id;
jp->radius = 200.;
jp->flags = JP_AUTOPOS; /* Will automatically create position. */
jp->hide = pow2(HIDE_DEFAULT_JUMP);
}
/**
* @brief Removes a Star System jump.
*/
static void uniedit_jumpRm( StarSystem *sys, StarSystem *targ )
{
int i;
/* Find associated jump. */
for (i=0; i<sys->njumps; i++)
if (sys->jumps[i].target == targ)
break;
/* Not found. */
if (i >= sys->njumps) {
WARN("Jump for system '%s' not found in system '%s' for removal.", targ->name, sys->name);
return;
}
/* Remove the jump. */
sys->njumps--;
memmove( &sys->jumps[i], &sys->jumps[i+1], sizeof(JumpPoint) * (sys->njumps - i) );
}
/**
* @brief Deselects selected targets.
*/
static void uniedit_deselect (void)
{
if (uniedit_nsys > 0)
free( uniedit_sys );
uniedit_sys = NULL;
uniedit_nsys = 0;
uniedit_msys = 0;
/* Change window stuff. */
window_disableButton( uniedit_wid, "btnJump" );
window_disableButton( uniedit_wid, "btnRename" );
window_disableButton( uniedit_wid, "btnEdit" );
window_disableButton( uniedit_wid, "btnOpen" );
window_modifyText( uniedit_wid, "txtSelected", "No selection" );
window_modifyText( uniedit_wid, "txtPresence", "N/A" );
}
/**
* @brief Adds a system to the selection.
*/
static void uniedit_selectAdd( StarSystem *sys )
{
/* Allocate if needed. */
if (uniedit_msys < uniedit_nsys+1) {
if (uniedit_msys == 0)
uniedit_msys = 1;
uniedit_msys *= 2;
uniedit_sys = realloc( uniedit_sys, sizeof(StarSystem*) * uniedit_msys );
}
/* Add system. */
uniedit_sys[ uniedit_nsys ] = sys;
uniedit_nsys++;
/* Set text again. */
uniedit_selectText();
/* Enable buttons again. */
window_enableButton( uniedit_wid, "btnJump" );
window_enableButton( uniedit_wid, "btnRename" );
window_enableButton( uniedit_wid, "btnEdit" );
if (uniedit_nsys == 1)
window_enableButton( uniedit_wid, "btnOpen" );
else
window_disableButton( uniedit_wid, "btnOpen" );
}
/**
* @brief Removes a system from the selection.
*/
static void uniedit_selectRm( StarSystem *sys )
{
int i;
for (i=0; i<uniedit_nsys; i++) {
if (uniedit_sys[i] == sys) {
uniedit_nsys--;
memmove( &uniedit_sys[i], &uniedit_sys[i+1], sizeof(StarSystem*) * (uniedit_nsys - i) );
uniedit_selectText();
if (uniedit_nsys == 1)
window_enableButton( uniedit_wid, "btnOpen" );
else
window_disableButton( uniedit_wid, "btnOpen" );
return;
}
}
WARN("Trying to remove system '%s' from selection when not selected.", sys->name);
}
/**
* @brief Sets the selected system text.
*/
void uniedit_selectText (void)
{
int i, l;
char buf[1024];
StarSystem *sys;
int hasPresence;
l = 0;
for (i=0; i<uniedit_nsys; i++) {
l += nsnprintf( &buf[l], sizeof(buf)-l, "%s%s", uniedit_sys[i]->name,
(i == uniedit_nsys-1) ? "" : ", " );
}
if (l == 0)
uniedit_deselect();
else {
window_modifyText( uniedit_wid, "txtSelected", buf );
/* Presence text. */
if (uniedit_nsys == 1) {
sys = uniedit_sys[0];
buf[0] = '\0';
hasPresence = 0;
l = 0;
for (i=0; i < sys->npresence ; i++) {
/* Must have presence. */
if (sys->presence[i].value <= 0)
continue;
hasPresence = 1;
/* Use map grey instead of default neutral colour */
l += nsnprintf( &buf[l], sizeof(buf)-l, "%s\e0%s: %.0f",
(l==0)?"":"\n", faction_name(sys->presence[i].faction),
sys->presence[i].value);
}
if (hasPresence == 0)
nsnprintf( buf, sizeof(buf), "None" );
window_modifyText( uniedit_wid, "txtPresence", buf );
}
else
window_modifyText( uniedit_wid, "txtPresence", "Multiple selected" );
}
}
/**
* @brief Handles the button zoom clicks.
*
* @param wid Unused.
* @param str Name of the button creating the event.
*/
static void uniedit_buttonZoom( unsigned int wid, char* str )
{
(void) wid;
/* Transform coords to normal. */
uniedit_xpos /= uniedit_zoom;
uniedit_ypos /= uniedit_zoom;
/* Apply zoom. */
if (strcmp(str,"btnZoomIn")==0) {
uniedit_zoom *= UNIEDIT_ZOOM_STEP;
uniedit_zoom = MIN(pow(UNIEDIT_ZOOM_STEP, UNIEDIT_ZOOM_MAX), uniedit_zoom);
}
else if (strcmp(str,"btnZoomOut")==0) {
uniedit_zoom /= UNIEDIT_ZOOM_STEP;
uniedit_zoom = MAX(pow(UNIEDIT_ZOOM_STEP, UNIEDIT_ZOOM_MIN), uniedit_zoom);
}
/* Hack for the circles to work. */
map_setZoom(uniedit_zoom);
/* Transform coords back. */
uniedit_xpos *= uniedit_zoom;
uniedit_ypos *= uniedit_zoom;
}
/**
* @brief Finds systems and assets.
*/
static void uniedit_findSys (void)
{
unsigned int wid;
int x, y;
x = 40;
/* Create the window. */
wid = window_create( "Find Systems and Assets", x, -1, UNIEDIT_FIND_WIDTH, UNIEDIT_FIND_HEIGHT );
uniedit_widFind = wid;
x = 20;
/* Close button. */
window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnClose", "Close", uniedit_findSysClose );
/* Find input widget. */
y = -45;
window_addInput( wid, x, y, UNIEDIT_FIND_WIDTH - 40, 20,
"inpFind", 32, 1, NULL );
window_setInputCallback( wid, "inpFind", uniedit_findSearch );
/* Close when escape is pressed. */
window_setCancel( wid, uniedit_findSysClose );
/* Generate the list. */
uniedit_findSearch( wid, NULL );
/* Focus the input widget. */
window_setFocus( wid, "inpFind" );
}
/**
* @brief Searches for planets and systems.
*/
static void uniedit_findSearch( unsigned int wid, char *str )
{
(void) str;
int i, n, nplanets, nsystems;
char *name;
char **planets, **systems;
const char *sysname;
map_find_t *found;
StarSystem *sys;
Planet *pnt;
name = window_getInput( wid, "inpFind" );
if (name == NULL)
return;
/* Search for names. */
planets = planet_searchFuzzyCase( name, &nplanets );
systems = system_searchFuzzyCase( name, &nsystems );
if (found_cur != NULL)
free(found_cur);
/* Construct found table. */
found = malloc( sizeof(map_find_t) * (nplanets + nsystems) );
n = 0;
/* Add planets to the found table. */
for (i=0; i<nplanets; i++) {
/* Planet must be real. */
pnt = planet_get( planets[i] );
if (pnt == NULL)
continue;
if (pnt->real != ASSET_REAL)
continue;
sysname = planet_getSystem( planets[i] );
if (sysname == NULL)
continue;
sys = system_get( sysname );
if (sys == NULL)
continue;
/* Set some values. */
found[n].pnt = pnt;
found[n].sys = sys;
/* Set fancy name. */
nsnprintf( found[n].display, sizeof(found[n].display),
"%s (%s system)", planets[i], sys->name );
n++;
}
free(planets);
/* Add systems to the found table. */
for (i=0; i<nsystems; i++) {
sys = system_get( systems[i] );
/* Set some values. */
found[n].pnt = NULL;
found[n].sys = sys;
strncpy(found[n].display, sys->name, sizeof(found[n].display));
n++;
}
free(systems);
/* Globals. */
found_cur = found;
found_ncur = n;
/* Display results. */
uniedit_findShowResults( wid, found, n );
}
/**
* @brief Generates the virtual asset list.
*/
static void uniedit_findShowResults( unsigned int wid, map_find_t *found, int n )
{
int i, y, h;
char **str;
/* Destroy if exists. */
if (widget_exists( wid, "lstResults" ))
window_destroyWidget( wid, "lstResults" );
y = -45 - BUTTON_HEIGHT - 20;
if (n == 0) {
str = malloc( sizeof(char*) );
str[0] = strdup("None");
n = 1;
}
else {
qsort( found, n, sizeof(map_find_t), uniedit_sortCompare );
str = malloc( sizeof(char*) * n );
for (i=0; i<n; i++)
str[i] = strdup( found[i].display );
}
/* Add list. */
h = UNIEDIT_FIND_HEIGHT + y - BUTTON_HEIGHT - 30;
window_addList( wid, 20, y, UNIEDIT_FIND_WIDTH-40, h,
"lstResults", str, n, 0, uniedit_centerSystem );
}
/**
* @brief Closes the search dialogue.
*/
static void uniedit_findSysClose( unsigned int wid, char *name )
{
/* Clean up if necessary. */
if (found_cur != NULL)
free( found_cur );
found_cur = NULL;
/* Close the window. */
window_close( wid, name );
}
/**
* @brief Centers the selected system.
*/
static void uniedit_centerSystem( unsigned int wid, char *unused )
{
(void) unused;
StarSystem *sys;
int pos;
/* Make sure it's valid. */
if (found_ncur == 0 || found_cur == NULL)
return;
pos = toolkit_getListPos( wid, "lstResults" );
sys = found_cur[ pos ].sys;
if (sys == NULL)
return;
/* Center. */
uniedit_xpos = sys->pos.x * uniedit_zoom;
uniedit_ypos = sys->pos.y * uniedit_zoom;
}
/**
* @brief qsort compare function for map finds.
*/
static int uniedit_sortCompare( const void *p1, const void *p2 )
{
map_find_t *f1, *f2;
/* Convert pointer. */
f1 = (map_find_t*) p1;
f2 = (map_find_t*) p2;
/* Sort by name, nothing more. */
return strcasecmp( f1->sys->name, f2->sys->name );
}
/**
* @brief Edits an individual system or group of systems.
*/
static void uniedit_editSys (void)
{
unsigned int wid;
int x, y, l;
char buf[128], *s;
StarSystem *sys;
/* Must have a system. */
if (uniedit_nsys == 0)
return;
sys = uniedit_sys[0];
/* Create the window. */
wid = window_create( "Star System Property Editor", -1, -1, UNIEDIT_EDIT_WIDTH, UNIEDIT_EDIT_HEIGHT );
uniedit_widEdit = wid;
window_setCancel( wid, uniedit_editSysClose );
x = 20;
/* Close button. */
window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnClose", "Close", uniedit_editSysClose );
/* Rename button. */
y = -45;
nsnprintf( buf, sizeof(buf), "Name: \en%s", (uniedit_nsys > 1) ? "\ervarious" : uniedit_sys[0]->name );
window_addText( wid, x, y, 180, 15, 0, "txtName", &gl_smallFont, &cDConsole, buf );
window_addButton( wid, 200, y+3, BUTTON_WIDTH, 21, "btnRename", "Rename", uniedit_btnEditRename );
/* New row. */
y -= gl_defFont.h + 15;
/* Add general stats */
s = "Radius";
l = gl_printWidthRaw( NULL, s );
window_addText( wid, x, y, l, 20, 1, "txtRadius",
NULL, &cBlack, s );
window_addInput( wid, x += l + 7, y, 80, 20, "inpRadius", 10, 1, NULL );
window_setInputFilter( wid, "inpRadius",
"abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}()-=*/\\'\"~<>!@#$%^&|_`" );
x += 80 + 12;
s = "(Scales asset positions)";
l = gl_printWidthRaw( NULL, s );
window_addText( wid, x, y, l, 20, 1, "txtRadiusComment",
NULL, &cBlack, s );
/* New row. */
x = 20;
y -= gl_defFont.h + 15;
s = "Stars";
l = gl_printWidthRaw( NULL, s );
window_addText( wid, x, y, l, 20, 1, "txtStars",
NULL, &cBlack, s );
window_addInput( wid, x += l + 7, y, 50, 20, "inpStars", 4, 1, NULL );
window_setInputFilter( wid, "inpStars",
"abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}()-=*/\\'\"~<>!@#$%^&|_`" );
x += 50 + 12;
s = "Interference";
l = gl_printWidthRaw( NULL, s );
window_addText( wid, x, y, l, 20, 1, "txtInterference",
NULL, &cBlack, s );
window_addInput( wid, x += l + 7, y, 55, 20, "inpInterference", 5, 1, NULL );
window_setInputFilter( wid, "inpInterference",
"abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}()-=*/\\'\"~<>!@#$%^&|_`" );
/* New row. */
x = 20;
y -= gl_defFont.h + 15;
s = "Nebula";
l = gl_printWidthRaw( NULL, s );
window_addText( wid, x, y, l, 20, 1, "txtNebula",
NULL, &cBlack, s );
window_addInput( wid, x += l + 7, y, 50, 20, "inpNebula", 4, 1, NULL );
window_setInputFilter( wid, "inpNebula",
"abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}()-=*/\\'\"~<>!@#$%^&|_`" );
x += 50 + 12;
s = "Volatility";
l = gl_printWidthRaw( NULL, s );
window_addText( wid, x, y, l, 20, 1, "txtVolatility",
NULL, &cBlack, s );
window_addInput( wid, x += l + 7, y, 50, 20, "inpVolatility", 4, 1, NULL );
window_setInputFilter( wid, "inpVolatility",
"abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]{}()-=*/\\'\"~<>!@#$%^&|_`" );
x += 50 + 12;
/* Load values */
nsnprintf( buf, sizeof(buf), "%g", sys->radius );
window_setInput( wid, "inpRadius", buf );
nsnprintf( buf, sizeof(buf), "%d", sys->stars );
window_setInput( wid, "inpStars", buf );
nsnprintf( buf, sizeof(buf), "%g", sys->interference );
window_setInput( wid, "inpInterference", buf );
nsnprintf( buf, sizeof(buf), "%g", sys->nebu_density );
window_setInput( wid, "inpNebula", buf );
nsnprintf( buf, sizeof(buf), "%g", sys->nebu_volatility );
window_setInput( wid, "inpVolatility", buf );
/* Generate the list. */
uniedit_editGenList( wid );
}
/**
* @brief Generates the virtual asset list.
*/
static void uniedit_editGenList( unsigned int wid )
{
int i, j, n;
StarSystem *sys;
Planet *p;
char **str;
int y, h, has_assets;
/* Destroy if exists. */
if (widget_exists( wid, "lstAssets" ))
window_destroyWidget( wid, "lstAssets" );
y = -175;
/* Check to see if it actually has virtual assets. */
sys = uniedit_sys[0];
n = sys->nplanets;
has_assets = 0;
for (i=0; i<n; i++) {
p = sys->planets[i];
if (p->real == ASSET_VIRTUAL) {
has_assets = 1;
break;
}
}
/* Generate list. */
j = 0;
str = malloc( sizeof(char*) * (n+1) );
if (has_assets) {
/* Virtual asset button. */
for (i=0; i<n; i++) {
p = sys->planets[i];
if (p->real == ASSET_VIRTUAL)
str[j++] = strdup( p->name );
}
}
else
str[j++] = strdup("None");
/* Add list. */
h = UNIEDIT_EDIT_HEIGHT+y-20 - 2*(BUTTON_HEIGHT+20);
window_addList( wid, 20, y, UNIEDIT_EDIT_WIDTH-40, h,
"lstAssets", str, j, 0, NULL );
y -= h + 20;
/* Add buttons if needed. */
if (!widget_exists( wid, "btnRmAsset" ))
window_addButton( wid, -20, y+3, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnRmAsset", "Remove", uniedit_btnEditRmAsset );
if (!widget_exists( wid, "btnAddAsset" ))
window_addButton( wid, -40-BUTTON_WIDTH, y+3, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnAddAsset", "Add", uniedit_btnEditAddAsset );
}
/**
* @brief Closes the system property editor, saving the changes made.
*/
static void uniedit_editSysClose( unsigned int wid, char *name )
{
StarSystem *sys;
double scale;
/* We already know the system exists because we checked when opening the dialog. */
sys = uniedit_sys[0];
/* Changes in radius need to scale the system asset positions. */
scale = atof(window_getInput( wid, "inpRadius" )) / sys->radius;
sysedit_sysScale(sys, scale);
sys->stars = atoi(window_getInput( wid, "inpStars" ));
sys->interference = atof(window_getInput( wid, "inpInterference" ));
sys->nebu_density = atof(window_getInput( wid, "inpNebula" ));
sys->nebu_volatility = atof(window_getInput( wid, "inpVolatility" ));
/* Reconstruct universe presences. */
space_reconstructPresences();
/* Text might need changing. */
uniedit_selectText();
if (conf.devautosave)
dsys_saveSystem( uniedit_sys[0] );
/* Close the window. */
window_close( wid, name );
}
/**
* @brief Removes a selected asset.
*/
static void uniedit_btnEditRmAsset( unsigned int wid, char *unused )
{
(void) unused;
char *selected;
int ret;
/* Get selection. */
selected = toolkit_getList( wid, "lstAssets" );
/* Make sure it's valid. */
if ((selected==NULL) || (strcmp(selected,"None")==0))
return;
/* Remove the asset. */
ret = system_rmPlanet( uniedit_sys[0], selected );
if (ret != 0) {
dialogue_alert( "Failed to remove planet '%s'!", selected );
return;
}
/* Update economy due to galaxy modification. */
economy_execQueued();
uniedit_editGenList( wid );
}
/**
* @brief Adds a new virtual asset.
*/
static void uniedit_btnEditAddAsset( unsigned int parent, char *unused )
{
(void) parent;
(void) unused;
unsigned int wid;
int i, j, n;
Planet *p;
char **str;
int h;
/* Get all assets. */
p = planet_getAll( &n );
j = 0;
for (i=0; i<n; i++)
if (p[i].real == ASSET_VIRTUAL)
j = 1;
if (j==0) {
dialogue_alert( "No virtual assets to add! Please add virtual assets to dat/asset.xml first." );
return;
}
/* Create the window. */
wid = window_create( "Add a Virtual Asset", -1, -1, UNIEDIT_EDIT_WIDTH, UNIEDIT_EDIT_HEIGHT );
window_setCancel( wid, window_close );
/* Add virtual asset list. */
str = malloc( sizeof(char*) * n );
j = 0;
for (i=0; i<n; i++)
if (p[i].real == ASSET_VIRTUAL)
str[j++] = strdup( p[i].name );
h = UNIEDIT_EDIT_HEIGHT-60-(BUTTON_HEIGHT+20);
window_addList( wid, 20, -40, UNIEDIT_EDIT_WIDTH-40, h,
"lstAssets", str, j, 0, NULL );
/* Close button. */
window_addButton( wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnClose", "Close", window_close );
/* Add button. */
window_addButton( wid, -20-(BUTTON_WIDTH+20), 20, BUTTON_WIDTH, BUTTON_HEIGHT,
"btnAdd", "Add", uniedit_btnEditAddAssetAdd );
}
/**
* @brief Actually adds the virtual asset.
*/
static void uniedit_btnEditAddAssetAdd( unsigned int wid, char *unused )
{
char *selected;
int ret;
/* Get selection. */
selected = toolkit_getList( wid, "lstAssets" );
if (selected == NULL)
return;
/* Add virtual presence. */
ret = system_addPlanet( uniedit_sys[0], selected );
if (ret != 0) {
dialogue_alert( "Failed to add virtual asset '%s'!", selected );
return;
}
/* Update economy due to galaxy modification. */
economy_execQueued();
/* Regenerate the list. */
uniedit_editGenList( uniedit_widEdit );
if (conf.devautosave)
dsys_saveSystem( uniedit_sys[0] );
/* Close the window. */
window_close( wid, unused );
}
/**
* @brief Renames the systems in the system editor.
*/
static void uniedit_btnEditRename( unsigned int wid, char *unused )
{
(void) unused;
char buf[128];
/* Rename systems. */
uniedit_renameSys();
/* Update text. */
nsnprintf( buf, sizeof(buf), "Name: %s", (uniedit_nsys > 1) ? "\ervarious" : uniedit_sys[0]->name );
window_modifyText( wid, "txtName", buf );
}
Jump to Line
Something went wrong with that request. Please try again.