X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Feditor.c;h=96718762f880db4f65f92143322db6eb5318033b;hb=4ec434ee1acb955d0e2e8c33558e5f9226904174;hp=fef23e2b5d3ba6fb172af8e1205a82aa10320606;hpb=c4baa69cc8d5e8398425e67498b49f4b77f8e477;p=rocksndiamonds.git diff --git a/src/editor.c b/src/editor.c index fef23e2b..96718762 100644 --- a/src/editor.c +++ b/src/editor.c @@ -1,13 +1,12 @@ /*********************************************************** * Rocks'n'Diamonds -- McDuffin Strikes Back! * *----------------------------------------------------------* -* ©1995 Artsoft Development * -* Holger Schemel * -* 33659 Bielefeld-Senne * -* Telefon: (0521) 493245 * -* eMail: aeglos@valinor.owl.de * -* aeglos@uni-paderborn.de * -* q99492@pbhrzx.uni-paderborn.de * +* (c) 1995-98 Artsoft Entertainment * +* Holger Schemel * +* Oststrasse 11a * +* 33604 Bielefeld * +* phone: ++49 +521 290471 * +* email: aeglos@valinor.owl.de * *----------------------------------------------------------* * editor.c * ***********************************************************/ @@ -19,11 +18,77 @@ #include "buttons.h" #include "files.h" +/* positions in the level editor */ +#define ED_WIN_MB_LEFT_XPOS 7 +#define ED_WIN_MB_LEFT_YPOS 6 +#define ED_WIN_LEVELNR_XPOS 77 +#define ED_WIN_LEVELNR_YPOS 7 +#define ED_WIN_MB_MIDDLE_XPOS 7 +#define ED_WIN_MB_MIDDLE_YPOS 258 +#define ED_WIN_MB_RIGHT_XPOS 77 +#define ED_WIN_MB_RIGHT_YPOS 258 + +/* other constants for the editor */ +#define ED_SCROLL_NO 0 +#define ED_SCROLL_LEFT 1 +#define ED_SCROLL_RIGHT 2 +#define ED_SCROLL_UP 4 +#define ED_SCROLL_DOWN 8 + +/* delay value to avoid too fast scrolling etc. */ #define CHOICE_DELAY_VALUE 100 +/* values for the control window */ +#define ED_CTRL_BUTTONS_GFX_YPOS 236 +#define ED_CTRL1_BUTTONS_HORIZ 4 +#define ED_CTRL1_BUTTONS_VERT 4 +#define ED_CTRL1_BUTTON_XSIZE 22 +#define ED_CTRL1_BUTTON_YSIZE 22 +#define ED_CTRL1_BUTTONS_XPOS 6 +#define ED_CTRL1_BUTTONS_YPOS 6 +#define ED_CTRL2_BUTTONS_HORIZ 3 +#define ED_CTRL2_BUTTONS_VERT 2 +#define ED_CTRL2_BUTTON_XSIZE 30 +#define ED_CTRL2_BUTTON_YSIZE 20 +#define ED_CTRL2_BUTTONS_XPOS 5 +#define ED_CTRL2_BUTTONS_YPOS 100 +#define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT) +#define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT) +#define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS) + +/* control button names */ +#define ED_CTRL_ID_SINGLE_ITEMS 0 +#define ED_CTRL_ID_CONNECTED_ITEMS 1 +#define ED_CTRL_ID_LINES 2 +#define ED_CTRL_ID_TEXT 3 +#define ED_CTRL_ID_RECTANGLE 4 +#define ED_CTRL_ID_BOX 5 +#define ED_CTRL_ID_WRAP_UP 6 +#define ED_CTRL_ID_ITEM_PROPERTIES 7 +#define ED_CTRL_ID_FLOOD_FILL 8 +#define ED_CTRL_ID_WRAP_LEFT 9 +#define ED_CTRL_ID_WRAP_RIGHT 11 +#define ED_CTRL_ID_RANDOM_PLACEMENT 12 +#define ED_CTRL_ID_BRUSH 13 +#define ED_CTRL_ID_WRAP_DOWN 14 +#define ED_CTRL_ID_UNDO 16 +#define ED_CTRL_ID_INFO 17 +#define ED_CTRL_ID_SAVE 18 +#define ED_CTRL_ID_CLEAR 19 +#define ED_CTRL_ID_TEST 20 +#define ED_CTRL_ID_EXIT 21 + +/* forward declaration for internal use */ +void HandleDrawingFunction(int, int, int); + +static struct GadgetInfo *control_button_gadget[ED_NUM_CTRL_BUTTONS]; +static boolean control_button_gadgets_created = FALSE; + +static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS; + static int level_xpos,level_ypos; -static BOOL edit_mode; -static BOOL name_typing; +static boolean edit_mode; +static boolean name_typing; static int new_element1 = EL_MAUERWERK; static int new_element2 = EL_LEERRAUM; static int new_element3 = EL_ERDREICH; @@ -86,6 +151,11 @@ int editor_element[] = EL_CHAR_A + ('N' - 'A'), EL_CHAR_A + ('E' - 'A'), + EL_SPIELER1, + EL_SPIELER2, + EL_SPIELER3, + EL_SPIELER4, + EL_SPIELFIGUR, EL_LEERRAUM, EL_ERDREICH, @@ -202,9 +272,9 @@ int editor_element[] = EL_DRACHE, EL_SONDE, - EL_LEERRAUM, - EL_LEERRAUM, - EL_LEERRAUM, + EL_MAUER_X, + EL_MAUER_Y, + EL_MAUER_XY, EL_CHAR_A + ('S' - 'A'), EL_CHAR_A + ('O' - 'A'), @@ -319,6 +389,336 @@ int editor_element[] = }; int elements_in_list = sizeof(editor_element)/sizeof(int); +void ScrollMiniLevel(int from_x, int from_y, int scroll) +{ + int x,y; + int dx = (scroll==ED_SCROLL_LEFT ? -1 : scroll==ED_SCROLL_RIGHT ? 1 : 0); + int dy = (scroll==ED_SCROLL_UP ? -1 : scroll==ED_SCROLL_DOWN ? 1 : 0); + + XCopyArea(display,drawto,drawto,gc, + SX+MINI_TILEX*(dx==-1),SY+MINI_TILEY*(dy==-1), + SXSIZE-MINI_TILEX*ABS(dx),SYSIZE-MINI_TILEY*ABS(dy), + SX+MINI_TILEX*(dx==+1),SY+MINI_TILEY*(dy==+1)); + if (dx) + { + x = (dx==1 ? 0 : 2*SCR_FIELDX-1); + for(y=0;y<2*SCR_FIELDY;y++) + DrawMiniElementOrWall(x,y,from_x,from_y); + } + else if (dy) + { + y = (dy==1 ? 0 : 2*SCR_FIELDY-1); + for(x=0;x<2*SCR_FIELDX;x++) + DrawMiniElementOrWall(x,y,from_x,from_y); + } + + redraw_mask |= REDRAW_FIELD; + BackToFront(); +} + +void HandlePressedControlButtons() +{ + static unsigned long button_delay = 0; + int i = 0; + + /* buttons with action when held pressed */ + int gadget_id[] = + { + ED_CTRL_ID_WRAP_UP, + ED_CTRL_ID_WRAP_LEFT, + ED_CTRL_ID_WRAP_RIGHT, + ED_CTRL_ID_WRAP_DOWN, + -1 + }; + + if (!DelayReached(&button_delay, CHOICE_DELAY_VALUE)) + return; + + while (gadget_id[i] != -1) + { + int id = gadget_id[i++]; + int state = control_button_gadget[id]->state; + int button = control_button_gadget[id]->event.button; + int step = (button == 1 ? 1 : button == 2 ? 5 : 10); + + if (state != GD_BUTTON_PRESSED) + continue; + + switch (id) + { + case ED_CTRL_ID_WRAP_LEFT: + if (level_xpos >= 0) + { + if (lev_fieldx < 2*SCR_FIELDX - 2) + break; + + level_xpos -= step; + if (level_xpos <- 1) + level_xpos = -1; + if (button == 1) + ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT); + else + DrawMiniLevel(level_xpos, level_ypos); + } + break; + + case ED_CTRL_ID_WRAP_RIGHT: + if (level_xpos <= lev_fieldx - 2*SCR_FIELDX) + { + if (lev_fieldx < 2*SCR_FIELDX - 2) + break; + + level_xpos += step; + if (level_xpos > lev_fieldx - 2*SCR_FIELDX + 1) + level_xpos = lev_fieldx - 2*SCR_FIELDX + 1; + if (button == 1) + ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT); + else + DrawMiniLevel(level_xpos, level_ypos); + } + break; + + case ED_CTRL_ID_WRAP_UP: + if (level_ypos >= 0) + { + if (lev_fieldy < 2*SCR_FIELDY - 2) + break; + + level_ypos -= step; + if (level_ypos < -1) + level_ypos = -1; + if (button == 1) + ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN); + else + DrawMiniLevel(level_xpos, level_ypos); + } + break; + + case ED_CTRL_ID_WRAP_DOWN: + if (level_ypos <= lev_fieldy - 2*SCR_FIELDY) + { + if (lev_fieldy < 2*SCR_FIELDY - 2) + break; + + level_ypos += step; + if (level_ypos > lev_fieldy - 2*SCR_FIELDY + 1) + level_ypos = lev_fieldy - 2*SCR_FIELDY + 1; + if (button == 1) + ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP); + else + DrawMiniLevel(level_xpos, level_ypos); + } + break; + + default: + break; + } + } +} + +void HandleLevelEditorControlButtons(struct GadgetInfo *gi) +{ + int event_type = gi->event.type; + + /* + int button = gi->event.button; + */ + + int id; + int i, x, y; + + /* get the button id */ + for (i=0; iid == control_button_gadget[i]->id) + id = i; + + switch (id) + { + case ED_CTRL_ID_SINGLE_ITEMS: + case ED_CTRL_ID_CONNECTED_ITEMS: + case ED_CTRL_ID_LINES: + case ED_CTRL_ID_TEXT: + case ED_CTRL_ID_RECTANGLE: + case ED_CTRL_ID_BOX: + case ED_CTRL_ID_FLOOD_FILL: + case ED_CTRL_ID_RANDOM_PLACEMENT: + case ED_CTRL_ID_BRUSH: + drawing_function = id; + break; + + case ED_CTRL_ID_CLEAR: + if (Request("Are you sure to clear this level ?", REQ_ASK)) + { + for(x=0; xlev_fieldx*lev_fieldy) - { - fprintf(stderr,"Something went wrong in 'FloodFill()'. Please debug.\n"); - exit(-1); - } - - old_element = Feld[from_x][from_y]; - Feld[from_x][from_y] = fill_element; - - for(i=0;i<4;i++) - { - x = from_x+check[i][0]; - y = from_y+check[i][1]; - - if (IN_LEV_FIELD(x,y) && Feld[x][y]==old_element) - FloodFill(x,y,fill_element); - } - - safety--; -} - void LevelEd(int mx, int my, int button) { static int last_button = 0; static int in_field_pressed = FALSE; - static BOOL use_floodfill = FALSE; + static boolean use_floodfill = FALSE; + + + /* int x = (mx-SX)/MINI_TILEX; int y = (my-SY)/MINI_TILEY; + */ + + + HandlePressedControlButtons(); + HandleDrawingFunction(mx, my, button); if (use_floodfill) /********** FLOOD FILL **********/ { + + +#if 0 + if (button) { if (mx>=SX && mx=SY && my=SX && mx=SY && my=ED_COUNT_GADGET_XPOS && mx=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE && @@ -1247,3 +1651,232 @@ void LevelNameTyping(KeySym key) name_typing = FALSE; } } + +static void swap_numbers(int *i1, int *i2) +{ + int help = *i1; + + *i1 = *i2; + *i2 = help; +} + +static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2) +{ + int help_x = *x1; + int help_y = *y1; + + *x1 = *x2; + *x2 = help_x; + + *y1 = *y2; + *y2 = help_y; +} + +static void DrawLineElement(int sx, int sy, int element) +{ + int lx = sx + level_xpos; + int ly = sy + level_ypos; + + if (element < 0) + DrawMiniElement(sx, sy, Feld[lx][ly]); + else + { + Feld[lx][ly] = element; + DrawMiniElement(sx, sy, element); + } +} + +void DrawLine(int from_x, int from_y, int to_x, int to_y, int element) +{ + if (from_y == to_y) /* horizontal line */ + { + int x; + int y = from_y; + + if (from_x > to_x) + swap_numbers(&from_x, &to_x); + + for (x=from_x; x<=to_x; x++) + DrawLineElement(x, y, element); + } + else if (from_x == to_x) /* vertical line */ + { + int x = from_x; + int y; + + if (from_y > to_y) + swap_numbers(&from_y, &to_y); + + for (y=from_y; y<=to_y; y++) + DrawLineElement(x, y, element); + } + else /* diagonal line */ + { + int len_x = ABS(to_x - from_x); + int len_y = ABS(to_y - from_y); + int x, y; + + if (len_y < len_x) /* < 45° */ + { + float a = (float)len_y / (float)len_x; + + if (from_x > to_x) + swap_number_pairs(&from_x, &from_y, &to_x, &to_y); + + for (x=0; x= 45° */ + { + float a = (float)len_x / (float)len_y; + + if (from_y > to_y) + swap_number_pairs(&from_x, &from_y, &to_x, &to_y); + + for (y=0; y lev_fieldx*lev_fieldy) + Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug."); + + old_element = Feld[from_x][from_y]; + Feld[from_x][from_y] = fill_element; + + for(i=0;i<4;i++) + { + x = from_x + check[i][0]; + y = from_y + check[i][1]; + + if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element) + FloodFill(x, y, fill_element); + } + + safety--; +} + +void HandleDrawingFunction(int mx, int my, int button) +{ + static int in_field_pressed = FALSE; + int new_element; + int sx = (mx - SX) / MINI_TILEX; + int sy = (my - SY) / MINI_TILEY; + int lx = sx + level_xpos; + int ly = sy + level_ypos; + int x, y; + + if (mx < SX || mx >= SX + SXSIZE || my < SY || my >= SY + SYSIZE) + { + /* pointer ouside drawing area */ + + if (!motion_status) /* button pressed or released outside drawing area */ + in_field_pressed = FALSE; + + return; + } + + if (button && !motion_status) + in_field_pressed = TRUE; + + if (!button || + !in_field_pressed || + button < 1 || button > 3 || + sx > lev_fieldx || sy > lev_fieldy || + (sx == 0 && level_xpos<0) || + (sx == 2*SCR_FIELDX - 1 && level_xpos > lev_fieldx - 2*SCR_FIELDX) || + (sy == 0 && level_ypos < 0) || + (sy == 2*SCR_FIELDY - 1 && level_ypos > lev_fieldy - 2*SCR_FIELDY)) + return; + + new_element = (button == 1 ? new_element1 : + button == 2 ? new_element2 : + button == 3 ? new_element3 : 0); + + switch (drawing_function) + { + case ED_CTRL_ID_SINGLE_ITEMS: + if (new_element != Feld[lx][ly]) + { + if (new_element == EL_SPIELFIGUR) + { + /* remove player at old position */ + for(y=0; y= 0 && x - level_xpos < 2*SCR_FIELDX && + y - level_ypos >= 0 && y - level_ypos < 2*SCR_FIELDY) + DrawMiniElement(x - level_xpos, y - level_ypos, EL_LEERRAUM); + } + } + } + } + + Feld[lx][ly] = new_element; + DrawMiniElement(sx, sy, new_element); + } + break; + + case ED_CTRL_ID_CONNECTED_ITEMS: + { + static int last_x = -1; + static int last_y = -1; + + if (last_x == -1) + { + Feld[lx][ly] = new_element; + DrawMiniElement(sx, sy, new_element); + + last_x = sx; + last_y = sy; + } + else if (last_x != sx || last_y != sy) + { + DrawLine(last_x, last_y, sx, sy, new_element); + + last_x = -1; + last_y = -1; + } + + /* + last_x = sx; + last_y = sy; + */ + } + break; + + case ED_CTRL_ID_FLOOD_FILL: + FloodFill(lx, ly, new_element); + DrawMiniLevel(level_xpos, level_ypos); + break; + + default: + break; + } +}