Files
commandergenius/project/jni/application/lbreakout2/client/editor.c

823 lines
31 KiB
C

/***************************************************************************
editor.c - description
-------------------
begin : Fri Oct 12 2001
copyright : (C) 2001 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "lbreakout.h"
#include "../game/game.h"
#include "game.h"
#include "config.h"
#include "bricks.h"
#include "frame.h"
#include "editor.h"
SDL_Surface *sel_frame = 0, *buttons = 0;
SDL_Surface *editor_bkgnd = 0; /* background (black with frame) of editor */
char edit_file_name[512]; /* full path of edited file */
Level *edit_levels[MAX_LEVELS]; /* editor levels */
char edit_version[16]; /* version of edited set */
int edit_level_count; /* how many levels currently used? */
int edit_cur_level_id;
Level *edit_cur_level; /* current level modified */
enum { EDITOR_BRICK, EDITOR_EXTRA };
int edit_sel_type; /* type of selected tile */
int edit_sel_id; /* brick or extra id */
int edit_sel_x, edit_sel_y; /* position in map of selected tile */
int edit_tile_x = 1, edit_tile_y = 20, edit_tile_w = MAP_WIDTH - 2, edit_tile_h = 3; /* part where either bricks ro bonuses
are displayed */
int extra_vis; /* extras currently shown? blinks. */
int first_swap_level = -1; /* if not -1 this and the current level will be swapped
next time the button is pressed */
enum {
/* tiles */
BUTTON_NONE = 0,
BUTTON_FIRST_BRICK,
BUTTON_LAST_BRICK = BUTTON_FIRST_BRICK + ( BRICK_COUNT ),
BUTTON_FIRST_EXTRA,
BUTTON_LAST_EXTRA = BUTTON_FIRST_EXTRA + ( EX_NUMBER -1 ),
BUTTON_EDIT,
BUTTON_EDIT_AUTHOR,
BUTTON_EDIT_NAME,
/* buttons */
BUTTON_FIRST,
BUTTON_NEXT,
BUTTON_PREV,
BUTTON_CLEAR,
BUTTON_SWAP,
BUTTON_ADD,
BUTTON_INSERT,
BUTTON_DELETE,
BUTTON_VERSION,
BUTTON_LOAD,
BUTTON_SAVE,
BUTTON_PLAY
};
int edit_buttons[MAP_WIDTH][MAP_HEIGHT]; /* an action is assigned to each map tile */
/* externals */
extern SDL_Surface *stk_display;
extern SDL_Surface *frame;
extern SDL_Surface *extra_pic;
extern SDL_Surface *brick_pic;
extern StkFont *mfont; /* use menu's font to draw status */
extern StkFont *font; /* use game's font to confirm */
extern Config config;
extern int stk_quit_request;
/* extra conversion table may be found in bricks.c */
extern Extra_Conv extra_conv_table[EX_NUMBER];
extern Brick_Conv brick_conv_table[BRICK_COUNT];
/*
====================================================================
Locals
====================================================================
*/
/*
====================================================================
We had a right click into the tile region so check and change the
bricks displayed there. We select the first new tile and set
edit_sel_id, edit_sel_x, edit_sel_y. The full update is initated
by editor_handle_click().
====================================================================
*/
void editor_switch_tiles()
{
int x_off = 2, y_off = 20, len = MAP_WIDTH - x_off * 2; /* offset in map of tiles, len is the number of tiles in one line */
int i, j;
/* clear edit buttons */
for ( i = edit_tile_x; i < edit_tile_x + edit_tile_w; i++ )
for ( j = edit_tile_y; j < edit_tile_y + edit_tile_h; j++ )
edit_buttons[i][j] = BUTTON_NONE;
/* clear this part of the editor bkjgnd */
stk_surface_fill( editor_bkgnd,
edit_tile_x * BRICK_WIDTH, edit_tile_y * BRICK_HEIGHT,
edit_tile_w * BRICK_WIDTH, edit_tile_h * BRICK_HEIGHT, 0x0 );
/* switch */
if ( edit_sel_type == EDITOR_BRICK ) {
/* flag */
edit_sel_type = EDITOR_EXTRA;
/* button map & background */
i = 0; j = 0;
while ( i + j * len < EX_NUMBER ) {
edit_buttons[x_off + i][y_off + j] = BUTTON_FIRST_EXTRA + i + j * len;
stk_surface_blit( extra_pic, ( i + j * len ) * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
editor_bkgnd, ( i + x_off ) * BRICK_WIDTH, ( j + y_off ) * BRICK_HEIGHT );
i++;
if ( i == len ) {
i = 0;
j++;
}
}
/* select first tile */
edit_sel_id = 0;
edit_sel_x = x_off;
edit_sel_y = y_off;
}
else {
/* flag */
edit_sel_type = EDITOR_BRICK;
/* button map & background */
i = 0; j = 0;
while ( i + j * len < BRICK_COUNT ) {
edit_buttons[x_off + i][y_off + j] = BUTTON_FIRST_BRICK + i + j * len;
stk_surface_blit( brick_pic, ( i + j * len ) * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
editor_bkgnd, ( i + x_off ) * BRICK_WIDTH, ( j + y_off ) * BRICK_HEIGHT );
i++;
if ( i == len ) {
i = 0;
j++;
}
}
/* select first tile */
edit_sel_id = 0;
edit_sel_x = x_off;
edit_sel_y = y_off;
}
}
/*
====================================================================
Draw a helping grid.
====================================================================
*/
void editor_draw_grid()
{
SDL_Surface *buffer;
int i, alpha;
buffer = stk_surface_create( SDL_SWSURFACE, EDIT_WIDTH * BRICK_WIDTH, 1 );
stk_surface_fill( buffer, 0,0,-1,-1, 0xffffff );
stk_surface_blit( buffer, 0,0,-1,-1, editor_bkgnd, BRICK_WIDTH, BRICK_HEIGHT );
stk_surface_blit( buffer, 0,0,-1,-1, editor_bkgnd, BRICK_WIDTH,
( EDIT_HEIGHT + 1 ) * BRICK_HEIGHT - 1 );
for ( i = 0; i < EDIT_HEIGHT - 1; i++ ) {
if ( i == EDIT_HEIGHT / 2 - 1 )
alpha = 192;
else
if ( i % (EDIT_HEIGHT/4) == 0 )
alpha = 128;
else
alpha = 64;
stk_surface_alpha_blit( buffer, 0,0,-1,-1, editor_bkgnd,
BRICK_WIDTH, ( i + 1 ) * BRICK_HEIGHT + BRICK_HEIGHT - 1,
alpha );
}
SDL_FreeSurface( buffer );
buffer = stk_surface_create( SDL_SWSURFACE, 1, EDIT_HEIGHT * BRICK_HEIGHT );
stk_surface_fill( buffer, 0,0,-1,-1, 0xffffff );
stk_surface_blit( buffer, 0,0,-1,-1, editor_bkgnd, BRICK_WIDTH, BRICK_HEIGHT );
stk_surface_blit( buffer, 0,0,-1,-1, editor_bkgnd,
( EDIT_WIDTH + 1 ) * BRICK_WIDTH - 1, BRICK_HEIGHT );
for ( i = 0; i < EDIT_WIDTH - 1; i++ ) {
if ( i == EDIT_WIDTH / 2 - 1 )
alpha = 192;
else
if ( i % (EDIT_WIDTH/4) == 0 )
alpha = 128;
else
alpha = 64;
stk_surface_alpha_blit( buffer, 0,0,-1,-1, editor_bkgnd,
( i + 1 ) * BRICK_WIDTH + BRICK_WIDTH- 1, BRICK_HEIGHT,
alpha );
}
SDL_FreeSurface( buffer );
}
/*
====================================================================
Translate the saved character strings into extra and brick indices
for the editor.
====================================================================
*/
enum { INDICES_2_CHAR, CHAR_2_INDICES };
void editor_translate_level( Level *level, int type )
{
int i, j, k;
if ( type == CHAR_2_INDICES ) {
for ( i = 0; i < EDIT_WIDTH; i++ )
for ( j = 0; j < EDIT_HEIGHT; j++ ) {
/* bricks */
for ( k = 0; k < BRICK_COUNT; k++ )
if ( brick_conv_table[k].c == level->bricks[i][j] ) {
level->bricks[i][j] = brick_conv_table[k].id;
break;
}
if ( k == BRICK_COUNT ) level->bricks[i][j] = -1;
/* extras */
for ( k = 0; k < EX_NUMBER; k++ )
if ( extra_conv_table[k].c == level->extras[i][j] ) {
level->extras[i][j] = extra_conv_table[k].type;
break;
}
if ( k == EX_NUMBER ) level->extras[i][j] = EX_NONE;
}
}
else {
/* indices to characters */
for ( i = 0; i < EDIT_WIDTH; i++ )
for ( j = 0; j < EDIT_HEIGHT; j++ ) {
/* bricks */
if ( level->bricks[i][j] == -1 )
level->bricks[i][j] = '.';
else
for ( k = 0; k < BRICK_COUNT; k++ )
if ( level->bricks[i][j] == brick_conv_table[k].id ) {
level->bricks[i][j] = brick_conv_table[k].c;
break;
}
/* extras */
if ( level->extras[i][j] == EX_NONE )
level->extras[i][j] = '.';
else
for ( k = 0; k < EX_NUMBER; k++ )
if ( level->extras[i][j] == extra_conv_table[k].type ) {
level->extras[i][j] = extra_conv_table[k].c;
break;
}
}
}
}
/*
====================================================================
Draw name of set file, current level, current count, remaining
levels, and other info stuff.
====================================================================
*/
void editor_draw_status()
{
char str[512];
int x = BRICK_WIDTH, y = ( MAP_HEIGHT - 1 ) * BRICK_HEIGHT - 2;
int height = 10;
/* locartion */
sprintf( str, _("Location: %s"), edit_file_name );
mfont->align = STK_FONT_ALIGN_LEFT | STK_FONT_ALIGN_TOP;
stk_font_write( mfont, stk_display, x, y, STK_OPAQUE, str );
/* current level */
sprintf( str, _("Current Level: %i/%i (Free: %i)"), edit_cur_level_id + 1, edit_level_count, MAX_LEVELS - edit_level_count );
mfont->align = STK_FONT_ALIGN_LEFT | STK_FONT_ALIGN_TOP;
stk_font_write( mfont, stk_display, x, y + height, STK_OPAQUE, str );
/* swap */
mfont->align = STK_FONT_ALIGN_RIGHT | STK_FONT_ALIGN_TOP;
if ( first_swap_level != -1 ) {
sprintf( str, _("*** Level %i Marked For Swap ***"), first_swap_level + 1 );
stk_font_write( mfont, stk_display, stk_display->w - BRICK_WIDTH, y + height, STK_OPAQUE, str );
}
else {
/* version */
sprintf( str, _("Version: %s "), edit_version );
stk_font_write( mfont, stk_display, stk_display->w - BRICK_WIDTH, y + height, STK_OPAQUE, str );
}
/* name and author */
mfont->align = STK_FONT_ALIGN_LEFT | STK_FONT_ALIGN_TOP;
sprintf( str, _("Title: %s"), edit_cur_level->name );
stk_font_write( mfont, stk_display, BRICK_WIDTH + 2, ( MAP_HEIGHT - 5 ) * BRICK_HEIGHT + 5, STK_OPAQUE, str );
mfont->align = STK_FONT_ALIGN_RIGHT | STK_FONT_ALIGN_TOP;
sprintf( str, _("Author: %s"), edit_cur_level->author );
stk_font_write( mfont, stk_display, stk_display->w - BRICK_WIDTH - 2, ( MAP_HEIGHT - 5 ) * BRICK_HEIGHT + 5, STK_OPAQUE, str );
}
/*
====================================================================
Draw brick and extra (if any) from screen map pos
so it fits the editable field (no frame, no bottom).
====================================================================
*/
void editor_draw_brick( int edit_map_x, int edit_map_y )
{
/* brick */
if ( edit_cur_level->bricks[edit_map_x][edit_map_y] != -1 ) {
if ( edit_cur_level->bricks[edit_map_x][edit_map_y] != INVIS_BRICK_ID )
stk_surface_blit( brick_pic,
edit_cur_level->bricks[edit_map_x][edit_map_y] * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
stk_display, (edit_map_x + 1) * BRICK_WIDTH, (edit_map_y + 1) * BRICK_HEIGHT );
else
stk_surface_fill( stk_display,
(edit_map_x + 1) * BRICK_WIDTH, (edit_map_y + 1) * BRICK_HEIGHT,
BRICK_WIDTH, BRICK_HEIGHT, 0x777777 );
}
else {
stk_surface_blit( editor_bkgnd,
(edit_map_x + 1) * BRICK_WIDTH, (edit_map_y + 1) * BRICK_HEIGHT,
BRICK_WIDTH, BRICK_HEIGHT, stk_display,
(edit_map_x + 1) * BRICK_WIDTH, (edit_map_y + 1) * BRICK_HEIGHT );
}
/* extra */
if ( ( extra_vis || edit_sel_type == EDITOR_EXTRA ) && edit_cur_level->extras[edit_map_x][edit_map_y] != EX_NONE) {
stk_surface_blit( extra_pic,
( edit_cur_level->extras[edit_map_x][edit_map_y] ) * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
stk_display, (edit_map_x + 1) * BRICK_WIDTH, (edit_map_y + 1) * BRICK_HEIGHT );
}
stk_display_store_drect();
}
/*
====================================================================
Redraw and refresh full screen
====================================================================
*/
void editor_full_update()
{
int i, j;
/* background */
stk_surface_blit( editor_bkgnd, 0,0,-1,-1, stk_display, 0,0 );
/* bricks&extras */
for ( i = 0; i < EDIT_WIDTH; i++ )
for ( j = 0; j < EDIT_HEIGHT; j++ )
editor_draw_brick( i, j );
/* selection frame */
stk_surface_blit( sel_frame, 0,0,-1,-1,
stk_display, edit_sel_x * BRICK_WIDTH, edit_sel_y * BRICK_HEIGHT );
/* status */
editor_draw_status();
/* refresh */
stk_display_update( STK_UPDATE_ALL );
}
/*
====================================================================
Do only redraw and refresh those bricks with an extra
====================================================================
*/
void editor_update_extra_bricks()
{
int i, j;
for ( i = 0; i < EDIT_WIDTH; i++ )
for ( j = 0; j < EDIT_HEIGHT; j++ )
if ( edit_cur_level->extras[i][j] != EX_NONE )
editor_draw_brick( i, j );
stk_display_update( STK_UPDATE_RECTS );
}
/*
====================================================================
Free all editor levels
====================================================================
*/
void editor_clear_levels()
{
int i;
for ( i = 0; i < MAX_LEVELS; i++ )
if ( edit_levels[i] ) level_delete( edit_levels[i] );
memset( edit_levels, 0, sizeof( Level* ) * MAX_LEVELS );
edit_level_count = 0;
}
/*
====================================================================
Save/load levels to/from editor file.
====================================================================
*/
void editor_load_levels()
{
int i, version, update;
Level *level;
FILE *file = 0;
/* clear levels first */
editor_clear_levels();
/* read levels while there are some in it */
edit_level_count = 0;
if ( ( file = fopen( edit_file_name, "rb" ) ) != 0 ) {
levelset_get_version( file, &version, &update );
sprintf( edit_version, "%i.%02i", version, update );
while ( ( level = level_load( file ) ) != 0 )
edit_levels[edit_level_count++] = level;
fclose( file );
}
/* if we got no level at all create an empty one */
if ( edit_level_count == 0 ) {
edit_level_count = 1;
edit_levels[0] = level_create_empty( _("noname"), _("untitled") );
}
/* translate the character strings to editor info */
for ( i = 0; i < edit_level_count; i++ )
editor_translate_level( edit_levels[i], CHAR_2_INDICES );
}
void editor_save_levels()
{
FILE *file = 0;
int i, j, k;
Level *level = 0;
/* convert */
for ( i = 0; i < edit_level_count; i++ )
editor_translate_level( edit_levels[i], INDICES_2_CHAR );
/* save */
if ( ( file = fopen( edit_file_name, "w" ) ) != 0 ) {
fprintf( file, "Version: %s\n", edit_version );
for ( i = 0; i < edit_level_count; i++ ) {
level = edit_levels[i];
/* save level */
fprintf( file, "Level:\n%s\n%s\nBricks:\n", level->author, level->name );
for ( j = 0; j < EDIT_HEIGHT; j++ ) {
for ( k = 0; k < EDIT_WIDTH; k++ )
fprintf( file, "%c", level->bricks[k][j] );
fprintf( file, "\n" );
}
fprintf( file, "Bonus:\n" );
for ( j = 0; j < EDIT_HEIGHT; j++ ) {
for ( k = 0; k < EDIT_WIDTH; k++ )
fprintf( file, "%c", level->extras[k][j] );
fprintf( file, "\n" );
}
}
fclose( file );
}
/* convert back */
for ( i = 0; i < edit_level_count; i++ )
editor_translate_level( edit_levels[i], CHAR_2_INDICES );
}
/*
====================================================================
Handle button action
====================================================================
*/
void editor_handle_button( int type, int *full_update ) {
Level *dummy_ptr;
int old_pos;
int version, update;
char *name, *author;
int i;
switch ( type ) {
case BUTTON_FIRST:
edit_cur_level_id = 0;
edit_cur_level = edit_levels[0];
*full_update = 1;
break;
case BUTTON_NEXT:
edit_cur_level_id++;
if ( edit_cur_level_id == edit_level_count ) edit_cur_level_id = 0;
edit_cur_level = edit_levels[edit_cur_level_id];
*full_update = 1;
break;
case BUTTON_PREV:
edit_cur_level_id--;
if ( edit_cur_level_id == -1 ) edit_cur_level_id = edit_level_count - 1;
edit_cur_level = edit_levels[edit_cur_level_id];
*full_update = 1;
break;
case BUTTON_SWAP:
if ( first_swap_level == -1 ) {
first_swap_level = edit_cur_level_id;
*full_update = 1;
}
else {
/* swap current and marked level */
dummy_ptr = edit_levels[first_swap_level];
edit_levels[first_swap_level] = edit_levels[edit_cur_level_id];
edit_levels[edit_cur_level_id] = dummy_ptr;
edit_cur_level = edit_levels[edit_cur_level_id];
first_swap_level = -1;
*full_update = 1;
}
break;
case BUTTON_LOAD:
if ( !confirm( font, _("Discard All Changes? y/n"), CONFIRM_YES_NO ) ) break;
/* load levels and reset position if level doesn't exist */
old_pos = edit_cur_level_id;
editor_load_levels();
if ( old_pos >= edit_level_count ) edit_cur_level_id = 0;
edit_cur_level = edit_levels[edit_cur_level_id];
first_swap_level = -1;
*full_update = 1;
break;
case BUTTON_SAVE:
if ( !confirm( font, _("Save Changes? y/n"), CONFIRM_YES_NO ) ) break;
editor_save_levels();
break;
case BUTTON_CLEAR:
if ( !confirm( font, _("Clear Level? y/n"), CONFIRM_YES_NO ) ) break;
author = strdup( edit_cur_level->author );
name = strdup( edit_cur_level->name );
level_delete( edit_levels[edit_cur_level_id] );
edit_levels[edit_cur_level_id] = level_create_empty( author, name );
edit_cur_level = edit_levels[edit_cur_level_id];
free( name ); free( author );
*full_update = 1;
break;
case BUTTON_ADD:
if ( edit_level_count == MAX_LEVELS ) break;
if ( !confirm( font, _("Add Level? y/n"), CONFIRM_YES_NO ) ) break;
edit_levels[edit_level_count] = level_create_empty( edit_levels[edit_level_count - 1]->author, edit_levels[edit_level_count - 1]->name );
edit_level_count++;
*full_update = 1;
break;
case BUTTON_INSERT:
if ( edit_level_count == MAX_LEVELS ) break;
if ( !confirm( font, _("Insert Level? y/n"), CONFIRM_YES_NO ) ) break;
for ( i = edit_level_count; i > edit_cur_level_id; i-- )
edit_levels[i] = edit_levels[i - 1];
edit_level_count++;
edit_levels[edit_cur_level_id] = level_create_empty( edit_cur_level->author, edit_cur_level->name );
edit_cur_level = edit_levels[edit_cur_level_id];
*full_update = 1;
break;
case BUTTON_DELETE:
if ( edit_level_count == 1 ) break; /* last level may not be removed */
if ( !confirm( font, _("Delete Level? y/n"), CONFIRM_YES_NO ) ) break;
level_delete( edit_levels[edit_cur_level_id] );
for ( i = edit_cur_level_id; i < edit_level_count - 1; i++ )
edit_levels[i] = edit_levels[i + 1];
edit_levels[i] = 0;
edit_level_count--;
if ( edit_cur_level_id >= edit_level_count )
edit_cur_level_id = edit_level_count - 1;
edit_cur_level = edit_levels[edit_cur_level_id];
*full_update = 1;
break;
case BUTTON_PLAY:
stk_display_fade( STK_FADE_OUT, STK_FADE_DEFAULT_TIME );
/* translate */
editor_translate_level( edit_cur_level, INDICES_2_CHAR );
/* run */
client_game_test_level( edit_cur_level );
/* translate back */
editor_translate_level( edit_cur_level, CHAR_2_INDICES );
*full_update = 1;
break;
case BUTTON_VERSION:
if ( enter_string( font, _("Levelset Version:"), edit_version, 8 ) ) {
parse_version( edit_version, &version, &update );
sprintf( edit_version, "%i.%02i", version, update );
*full_update = 1;
}
break;
}
}
/*
====================================================================
Handle a click on a map tile.
If set is False a remove action was requested (only for
editing)
====================================================================
*/
int near_grow_brick( int x, int y ) {
int i, j;
for ( i = x - 1; i <= x + 1; i++ )
for ( j = y - 1; j <= y + 1; j++ )
if ( i != x || j != y )
if ( i >= 0 && j >= 0 && i < EDIT_WIDTH && j < EDIT_HEIGHT )
if ( edit_cur_level->bricks[i][j] == GROW_BRICK_ID )
return 1;
return 0;
}
void editor_handle_click( int x, int y, int set, int *full_update )
{
int sel = 0;
int edit_x, edit_y;
char str[32];
/* if !set and within the tile field we perform a switch */
if ( !set ) {
if ( x >= edit_tile_x && y >= edit_tile_y && x < edit_tile_x + edit_tile_w && y < edit_tile_y + edit_tile_h ) {
editor_switch_tiles();
*full_update = 1;
return;
}
}
/* the remaining stuff requires a tile at the position */
if ( edit_buttons[x][y] == BUTTON_NONE ) return; /* no action */
/* bricks */
if ( edit_buttons[x][y] >= BUTTON_FIRST_BRICK && edit_buttons[x][y] <= BUTTON_LAST_BRICK ) {
sel = 1;
edit_sel_type = EDITOR_BRICK;
edit_sel_id = edit_buttons[x][y] - BUTTON_FIRST_BRICK;
}
/* extras */
if ( edit_buttons[x][y] >= BUTTON_FIRST_EXTRA && edit_buttons[x][y] <= BUTTON_LAST_EXTRA ) {
sel = 1;
edit_sel_type = EDITOR_EXTRA;
edit_sel_id = edit_buttons[x][y] - BUTTON_FIRST_EXTRA;
}
/* edit field */
if ( edit_buttons[x][y] == BUTTON_EDIT ) {
edit_x = x - 1;
edit_y = y - 1;
if ( edit_sel_type == EDITOR_BRICK ) {
if ( set ) {
/* set brick */
edit_cur_level->bricks[edit_x][edit_y] = edit_sel_id;
*full_update = 1;
}
else {
/* remove brick and extra if any */
if ( edit_cur_level->bricks[edit_x][edit_y] != -1 ) {
edit_cur_level->bricks[edit_x][edit_y] = -1;
edit_cur_level->extras[edit_x][edit_y] = EX_NONE;
*full_update = 1;
}
}
}
else {
if ( set ) {
/* set extra - must be on a brick or beside a grow brick */
if ( edit_cur_level->bricks[edit_x][edit_y] != -1 || near_grow_brick( edit_x, edit_y ) ) {
edit_cur_level->extras[edit_x][edit_y] = edit_sel_id;
*full_update = 1;
}
}
else {
/* remove extra */
if ( edit_cur_level->extras[edit_x][edit_y] != EX_NONE ) {
edit_cur_level->extras[edit_x][edit_y] = EX_NONE;
*full_update = 1;
}
}
}
}
/* buttons */
editor_handle_button( edit_buttons[x][y], full_update );
/* name&author */
strcpy( str, "" );
if ( edit_buttons[x][y] == BUTTON_EDIT_AUTHOR )
if ( enter_string( font, _("Author's Name:"), str, 24 ) ) {
snprintf( edit_cur_level->author, 31, "%s", str );
*full_update = 1;
}
if ( edit_buttons[x][y] == BUTTON_EDIT_NAME )
if ( enter_string( font, _("Title:"), str, 24 ) ) {
snprintf( edit_cur_level->name, 31, "%s", str );
*full_update = 1;
}
/* sel frame tile position */
if ( sel ) {
edit_sel_x = x;
edit_sel_y = y;
*full_update = 1;
}
}
/*
====================================================================
Publics
====================================================================
*/
/*
====================================================================
Create/delete editor resources
====================================================================
*/
void editor_create()
{
int i, j;
/* clear all level pointers */
memset( edit_levels, 0, sizeof( Level* ) * MAX_LEVELS );
/* load sel frame */
sel_frame = stk_surface_load( SDL_SWSURFACE, "sel_frame.png" );
/* load buttons */
buttons = stk_surface_load( SDL_SWSURFACE, "buttons.png" );
/* background is black + frame */
editor_bkgnd = stk_surface_create( SDL_SWSURFACE, stk_display->w, stk_display->h );
SDL_SetColorKey( editor_bkgnd, 0, 0 );
stk_surface_fill( editor_bkgnd, 0,0,-1,-1, 0x0 );
/* add helping grid */
editor_draw_grid();
/* set actions */
/* editable part */
for ( i = 0; i < EDIT_WIDTH; i++ )
for ( j = 0; j < EDIT_HEIGHT; j++ )
edit_buttons[i + 1][j + 1] = BUTTON_EDIT;
/* buttons */
for ( i = 0; i < 11; i++ )
edit_buttons[0][MAP_HEIGHT - 11 + i] = BUTTON_FIRST + i;
edit_buttons[MAP_WIDTH - 1][MAP_HEIGHT - 1] = BUTTON_PLAY;
/* name&author */
for ( i = 1; i < MAP_WIDTH / 2; i++ )
edit_buttons[i][MAP_HEIGHT - 5] = BUTTON_EDIT_NAME;
for ( i = MAP_WIDTH / 2; i < MAP_WIDTH - 1; i++ )
edit_buttons[i][MAP_HEIGHT - 5] = BUTTON_EDIT_AUTHOR;
/* draw buttons */
for ( i = 0; i < 11; i++ ) {
stk_surface_blit( buttons, i * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
editor_bkgnd, 0, ( MAP_HEIGHT - 11 + i ) * BRICK_HEIGHT );
}
stk_surface_blit( buttons, 11 * BRICK_WIDTH, 0,
BRICK_WIDTH, BRICK_HEIGHT,
editor_bkgnd,
( MAP_WIDTH - 1 ) * BRICK_WIDTH,
( MAP_HEIGHT - 1 ) * BRICK_HEIGHT );
}
void editor_delete()
{
stk_surface_free( &editor_bkgnd );
stk_surface_free( &sel_frame );
stk_surface_free( &buttons );
}
/*
====================================================================
Initiate and clear stuff for each editor call.
file_name is the name of the edited file in home directory.
====================================================================
*/
int editor_init( char *file_name )
{
FILE *file = 0;
/* set full file name */
snprintf( edit_file_name, sizeof(edit_file_name)-1, "%s/%s/lbreakout2-levels/%s", (getenv( "HOME" )?getenv( "HOME" ):"."), CONFIG_DIR_NAME, file_name );
/* test this file for write access. use append to keep contents */
if ( ( file = fopen( edit_file_name, "a" ) ) == 0 ) {
fprintf( stderr, "Permission to write to file '%s' denied.\n", edit_file_name );
return 0;
}
else
fclose( file );
/* load levels */
editor_load_levels();
/* select first level */
edit_cur_level_id = 0;
edit_cur_level = edit_levels[0];
/* select first brick */
edit_sel_type = EDITOR_EXTRA;
editor_switch_tiles();
/* clear other flags */
extra_vis = 0;
first_swap_level = -1;
return 1;
}
void editor_clear()
{
/* free all levels */
editor_clear_levels();
}
/*
====================================================================
Run the editor
====================================================================
*/
void editor_run()
{
SDL_Event event;
int leave = 0;
int ms;
int last_switch_time = 0;
int full_update = 0, set;
int x, y, xoff,yoff;
Uint8 buttonstate;
/* reset any alpha keys */
SDL_SetAlpha( extra_pic, 0,0 );
/* draw first time */
editor_full_update();
/* main loop */
stk_timer_reset();
while ( !leave && !stk_quit_request ) {
if ( SDL_PollEvent( &event ) ) {
switch ( event.type ) {
case SDL_QUIT: leave = 1; stk_quit_request = 1; break;
case SDL_MOUSEBUTTONDOWN:
editor_handle_click( event.button.x / BRICK_WIDTH,
event.button.y / BRICK_HEIGHT,
(event.button.button == STK_BUTTON_LEFT),
&full_update );
break;
case SDL_KEYDOWN:
switch ( event.key.keysym.sym ) {
case SDLK_ESCAPE:
if ( confirm( font, _("Quit Editor? y/n"), CONFIRM_YES_NO ) ) leave = 1;
break;
case SDLK_LEFT: editor_handle_button( BUTTON_PREV, &full_update ); break;
case SDLK_RIGHT: editor_handle_button( BUTTON_NEXT, &full_update ); break;
case SDLK_UP: editor_handle_button( BUTTON_FIRST, &full_update ); break;
case SDLK_f:
config.fullscreen = !config.fullscreen;
stk_display_apply_fullscreen( config.fullscreen );
full_update = 1;
break;
default: break;
}
break;
default: break;
}
}
/* mouse motion is handled directly */
buttonstate = SDL_GetRelativeMouseState( &xoff, &yoff );
if ( (xoff || yoff) && buttonstate ) {
buttonstate = SDL_GetMouseState( &x, &y );
set = 0; if ( buttonstate & SDL_BUTTON(1) ) set = 1;
editor_handle_click( x / BRICK_WIDTH, y / BRICK_HEIGHT, set, &full_update );
}
ms = stk_timer_get_time();
if ( ( last_switch_time -= ms ) <= 0 ) {
extra_vis = !extra_vis;
last_switch_time = 500;
editor_update_extra_bricks();
}
/* full update? */
if ( full_update ) {
editor_full_update();
full_update = 0;
}
/* don't consume all CPU time */
SDL_Delay( 5 );
}
}