#define ED_ELEMENTLIST_YPOS (editor.palette.y)
#define ED_ELEMENTLIST_XSIZE (graphic_info[IMG_EDITOR_PALETTE_BUTTON].width)
#define ED_ELEMENTLIST_YSIZE (graphic_info[IMG_EDITOR_PALETTE_BUTTON].height)
-#define ED_ELEMENTLIST_BUTTONS_HORIZ (editor.palette.cols)
-#define ED_ELEMENTLIST_BUTTONS_VERT (editor.palette.rows)
+#define ED_ELEMENTLIST_COLS MAX(1, editor.palette.cols)
+#define ED_ELEMENTLIST_ROWS MAX(1, editor.palette.rows)
+#define ED_ELEMENTLIST_BUTTONS_HORIZ (ED_ELEMENTLIST_COLS)
+#define ED_ELEMENTLIST_BUTTONS_VERT (ED_ELEMENTLIST_ROWS)
#define ED_NUM_ELEMENTLIST_BUTTONS (ED_ELEMENTLIST_BUTTONS_HORIZ * \
ED_ELEMENTLIST_BUTTONS_VERT)
{
// required for correct padding of palette headline buttons
if (*editor_elements_info[i].headline_list_size > 0)
- num_editor_elements += editor.palette.cols;
+ num_editor_elements += ED_ELEMENTLIST_COLS;
for (j = 0; j < *editor_elements_info[i].headline_list_size; j++)
{
// required for correct padding of palette element buttons
int element_list_size = *editor_elements_info[i].element_list_size;
int element_rows =
- (element_list_size + editor.palette.cols - 1) / editor.palette.cols;
- int element_buttons = editor.palette.cols * element_rows;
+ (element_list_size + ED_ELEMENTLIST_COLS - 1) / ED_ELEMENTLIST_COLS;
+ int element_buttons = ED_ELEMENTLIST_COLS * element_rows;
num_editor_elements += element_buttons;
}
{
// required for correct padding of palette headline buttons
int headline_size = (*editor_elements_info[i].headline_list_size > 0 ?
- editor.palette.cols : 0);
+ ED_ELEMENTLIST_COLS : 0);
for (j = 0; j < headline_size; j++)
{
// required for correct padding of palette element buttons
int element_list_size = *editor_elements_info[i].element_list_size;
int element_rows =
- (element_list_size + editor.palette.cols - 1) / editor.palette.cols;
- int element_buttons = editor.palette.cols * element_rows;
+ (element_list_size + ED_ELEMENTLIST_COLS - 1) / ED_ELEMENTLIST_COLS;
+ int element_buttons = ED_ELEMENTLIST_COLS * element_rows;
// copy all elements from element list
for (j = 0; j < element_list_size; j++)
right_gadget_border =
checked_calloc(num_editor_gadgets * sizeof(int));
- editor_el_empty = checked_calloc(ED_NUM_ELEMENTLIST_BUTTONS * sizeof(int));
+ // set number of empty (padding) element buttons to maximum number of buttons
+ num_editor_el_empty = ED_NUM_ELEMENTLIST_BUTTONS;
+
+ editor_el_empty = checked_calloc(num_editor_el_empty * sizeof(int));
editor_el_empty_ptr = editor_el_empty;
use_permanent_palette = !editor.palette.show_as_separate_screen;
ed_tilesize = setup.auto_setup.editor_zoom_tilesize;
ed_tilesize_default = DEFAULT_EDITOR_TILESIZE;
+ // make sure that tile size is always a power of 2
+ ed_tilesize = (1 << log_2(ed_tilesize));
+
if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
{
ed_tilesize = DEFAULT_EDITOR_TILESIZE_MM;
return (door_1_viewport_unchanged && door_1_contains_toolbox);
}
+static void DrawEditorDoorBackground(int graphic, int x, int y,
+ int width, int height)
+{
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ if (g->bitmap != NULL)
+ BlitBitmap(g->bitmap, drawto, g->src_x, g->src_y,
+ MIN(width, g->width), MIN(height, g->height), x, y);
+ else
+ ClearRectangle(drawto, x, y, width, height);
+}
+
static void DrawEditorDoorContent(void)
{
// needed for gadgets drawn on background (like palette scrollbar)
SetDoorBackgroundImage(IMG_UNDEFINED);
// copy default editor door content to main double buffer
- BlitBitmap(graphic_info[IMG_BACKGROUND_PALETTE].bitmap, drawto,
- graphic_info[IMG_BACKGROUND_PALETTE].src_x,
- graphic_info[IMG_BACKGROUND_PALETTE].src_y,
- MIN(DXSIZE, graphic_info[IMG_BACKGROUND_PALETTE].width),
- MIN(DYSIZE, graphic_info[IMG_BACKGROUND_PALETTE].height),
- DX, DY);
+ DrawEditorDoorBackground(IMG_BACKGROUND_PALETTE, DX, DY, DXSIZE, DYSIZE);
// draw bigger door
DrawSpecialEditorDoor();
// draw new control window
- BlitBitmap(graphic_info[IMG_BACKGROUND_TOOLBOX].bitmap, drawto,
- graphic_info[IMG_BACKGROUND_TOOLBOX].src_x,
- graphic_info[IMG_BACKGROUND_TOOLBOX].src_y,
- MIN(EXSIZE, graphic_info[IMG_BACKGROUND_TOOLBOX].width),
- MIN(EYSIZE, graphic_info[IMG_BACKGROUND_TOOLBOX].height),
- EX, EY);
+ DrawEditorDoorBackground(IMG_BACKGROUND_TOOLBOX, EX, EY, EXSIZE, EYSIZE);
// draw all toolbox gadgets to editor doors
MapControlButtons();
FadeSoundsAndMusic();
- if (CheckIfGlobalBorderOrPlayfieldViewportHasChanged())
+ if (CheckFadeAll())
fade_mask = REDRAW_ALL;
FadeOut(fade_mask);
{
int element = Feld[x][y];
- if (IS_GEM(element) ||
- element == EL_MM_KETTLE ||
- element == EL_DF_CELL)
- level.gems_needed++;
+ switch (element)
+ {
+ case EL_EMERALD:
+ case EL_EMERALD_YELLOW:
+ case EL_EMERALD_RED:
+ case EL_EMERALD_PURPLE:
+ case EL_BD_DIAMOND:
+ case EL_WALL_EMERALD:
+ case EL_WALL_EMERALD_YELLOW:
+ case EL_WALL_EMERALD_RED:
+ case EL_WALL_EMERALD_PURPLE:
+ case EL_WALL_BD_DIAMOND:
+ case EL_NUT:
+ case EL_SP_INFOTRON:
+ case EL_MM_KETTLE:
+ case EL_DF_CELL:
+ level.gems_needed++;
+ break;
+
+ case EL_DIAMOND:
+ case EL_WALL_DIAMOND:
+ level.gems_needed += 3;
+ break;
+
+ case EL_PEARL:
+ case EL_WALL_PEARL:
+ level.gems_needed += 5;
+ break;
+
+ case EL_CRYSTAL:
+ case EL_WALL_CRYSTAL:
+ level.gems_needed += 8;
+ break;
+
+ default:
+ break;
+ }
}
}
};
static int last_x = -1;
static int last_y = -1;
- int old_element = IntelliDrawBuffer[x][y];
if (new_element == EL_UNDEFINED)
{
return;
}
+ int old_element = IntelliDrawBuffer[x][y];
+
if (IS_TUBE(new_element))
{
int last_element_new = EL_UNDEFINED;
static boolean draw_mode_hires = FALSE;
+static boolean isHiresTileElement(int element)
+{
+ return (IS_MM_WALL(element) || element == EL_EMPTY);
+}
+
+static boolean isHiresDrawElement(int element)
+{
+ return (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY);
+}
+
static void SetDrawModeHiRes(int element)
{
draw_mode_hires =
(level.game_engine_type == GAME_ENGINE_TYPE_MM &&
- (IS_MM_WALL_EDITOR(element) || element == EL_EMPTY));
+ isHiresDrawElement(element));
}
static boolean getDrawModeHiRes(void)
char text[MAX_CB_TEXT_SIZE + 1] = "";
int width = (draw_with_brush ? brush_width : lev_fieldx);
int height = (draw_with_brush ? brush_height : lev_fieldy);
+ char *format = "%s%03d";
+
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++)
+ if ((draw_with_brush ? brush_buffer[x][y] : Feld[x][y]) > 999)
+ format = "%s%04d";
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
int element = (draw_with_brush ? brush_buffer[x][y] : Feld[x][y]);
- int element_mapped = element;
char *prefix = (mode == CB_DUMP_BRUSH ||
mode == CB_BRUSH_TO_CLIPBOARD ? "`" : "¸");
- if (IS_CUSTOM_ELEMENT(element))
- element_mapped = EL_CUSTOM_START;
- else if (IS_GROUP_ELEMENT(element))
- element_mapped = EL_GROUP_START;
- else if (element >= NUM_FILE_ELEMENTS)
- element_mapped = EL_UNKNOWN;
+ if (element >= NUM_FILE_ELEMENTS)
+ element = EL_UNKNOWN;
// copy brush to level sketch text buffer for the R'n'D forum:
- // - large tiles: `xxx (0x60 ASCII)
- // - small tiles: ¸xxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8)
- snprintf(part, MAX_CB_PART_SIZE + 1, "%s%03d", prefix, element_mapped);
+ // - large tiles: `xxx or `xxxx (0x60 ASCII)
+ // - small tiles: ¸xxx or ¸xxxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8)
+ snprintf(part, MAX_CB_PART_SIZE + 1, format, prefix, element);
strcat(text, part);
}
char *clipboard_text = SDL_GetClipboardText();
char *ptr = clipboard_text;
+ boolean allow_new_row = FALSE;
boolean stop = FALSE;
while (*ptr && !stop)
{
boolean prefix_found = FALSE;
+ boolean start_new_row = FALSE;
// level sketch element number prefixes (may be multi-byte characters)
char *prefix_list[] = { "`", "¸" };
}
}
- // continue with next character if prefix not found
- if (!prefix_found)
- {
- ptr++; // !!! FIX THIS for real UTF-8 handling !!!
-
- continue;
- }
-
- // continue with next character if prefix not found
- if (strlen(ptr) < 3)
- break;
-
- if (ptr[0] >= '0' && ptr[0] <= '9' &&
+ // check if prefix found and followed by (at least) three digits
+ if (prefix_found &&
+ strlen(ptr) >= 3 &&
+ ptr[0] >= '0' && ptr[0] <= '9' &&
ptr[1] >= '0' && ptr[1] <= '9' &&
ptr[2] >= '0' && ptr[2] <= '9')
{
ptr += 3;
+ // level sketch element number might consist of four digits
+ if (ptr[0] >= '0' && ptr[0] <= '9')
+ {
+ element = element * 10 + (ptr[0] - '0');
+ ptr++;
+ }
+
if (element >= NUM_FILE_ELEMENTS)
element = EL_UNKNOWN;
x++;
- if (x >= MAX_LEV_FIELDX || *ptr == '\n')
- {
- x = 0;
- y++;
+ if (x >= MAX_LEV_FIELDX)
+ start_new_row = TRUE;
- if (y >= MAX_LEV_FIELDY)
- stop = TRUE;
- }
+ allow_new_row = TRUE;
+ }
+ else
+ {
+ if ((*ptr == '\n' || *ptr == '\r') && allow_new_row)
+ start_new_row = TRUE;
+
+ ptr++; // !!! FIX THIS for real UTF-8 handling !!!
+ }
+
+ if (start_new_row)
+ {
+ x = 0;
+ y++;
+
+ if (y >= MAX_LEV_FIELDY)
+ stop = TRUE;
+
+ allow_new_row = FALSE;
}
}
case TEXT_SETCURSOR:
DrawEditorElement(last_sx, last_sy, Feld[lx][ly]);
DrawAreaBorder(sx, sy, sx, sy);
+ StartTextInput(SX + sx * ed_tilesize, SY + sy * ed_tilesize,
+ ed_tilesize, ed_tilesize);
last_sx = sx;
last_sy = sy;
break;
case TEXT_END:
CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
DrawEditorElement(sx, sy, Feld[lx][ly]);
+ StopTextInput();
typing = FALSE;
break;
}
else if (!button_press_event)
{
+ int old_element = (IN_LEV_FIELD(lx, ly) ? Feld[lx][ly] : EL_UNDEFINED);
+ boolean hires_drawing = (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
+ isHiresTileElement(old_element) &&
+ isHiresDrawElement(new_element));
+
// prevent handling events for every pixel position when moving mouse
- if ((sx == last_sx && sy == last_sy &&
- !IS_MM_WALL_EDITOR(new_element) && new_element != EL_EMPTY) ||
+ if ((sx == last_sx && sy == last_sy && !hires_drawing) ||
(sx2 == last_sx2 && sy2 == last_sy2))
return;
}
{
SetDrawModeHiRes(new_element);
- if (new_element == EL_PLAYER_1)
+ if (ELEM_IS_PLAYER(new_element))
{
// remove player at old position
for (y = 0; y < lev_fieldy; y++)
+ {
for (x = 0; x < lev_fieldx; x++)
- if (Feld[x][y] == EL_PLAYER_1)
- SetElement(x, y, EL_EMPTY);
+ {
+ int old_element = Feld[x][y];
+
+ if (ELEM_IS_PLAYER(old_element))
+ {
+ int replaced_with_element =
+ (old_element == EL_SOKOBAN_FIELD_PLAYER &&
+ new_element == EL_PLAYER_1 ? EL_SOKOBAN_FIELD_EMPTY :
+
+ old_element == EL_SOKOBAN_FIELD_PLAYER &&
+ new_element == old_element ? EL_SOKOBAN_FIELD_EMPTY :
+
+ new_element == EL_SOKOBAN_FIELD_PLAYER &&
+ old_element == EL_PLAYER_1 ? EL_EMPTY :
+
+ new_element >= EL_PLAYER_1 &&
+ new_element <= EL_PLAYER_4 &&
+ new_element == old_element ? EL_EMPTY :
+
+ old_element);
+
+ SetElement(x, y, replaced_with_element);
+ }
+ }
+ }
}
SetElementButton(lx, ly, dx, dy, new_element, button);
button == 2 ? ed_tilesize_default :
button == 3 ? ed_tilesize / 2 : ed_tilesize);
+ // when using touch device, cycle through all zoom tilesizes
+ if (runtime.uses_touch_device && ed_tilesize > TILESIZE)
+ ed_tilesize = MICRO_TILESIZE;
+
// limit zoom level by upper and lower bound
ed_tilesize = MIN(MAX(MICRO_TILESIZE, ed_tilesize), TILESIZE);