1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
23 /* positions in the level editor */
24 #define ED_WIN_MB_LEFT_XPOS 7
25 #define ED_WIN_MB_LEFT_YPOS 6
26 #define ED_WIN_LEVELNR_XPOS 77
27 #define ED_WIN_LEVELNR_YPOS 7
28 #define ED_WIN_MB_MIDDLE_XPOS 7
29 #define ED_WIN_MB_MIDDLE_YPOS 258
30 #define ED_WIN_MB_RIGHT_XPOS 77
31 #define ED_WIN_MB_RIGHT_YPOS 258
33 /* other constants for the editor */
34 #define ED_SCROLL_NO 0
35 #define ED_SCROLL_LEFT 1
36 #define ED_SCROLL_RIGHT 2
37 #define ED_SCROLL_UP 4
38 #define ED_SCROLL_DOWN 8
40 /* screens in the level editor */
41 #define ED_MODE_DRAWING 0
42 #define ED_MODE_INFO 1
43 #define ED_MODE_PROPERTIES 2
45 /* how many steps can be cancelled */
46 #define NUM_UNDO_STEPS (10 + 1)
48 /* values for random placement */
49 #define RANDOM_USE_PERCENTAGE 0
50 #define RANDOM_USE_NUM_OBJECTS 1
52 /* values for elements with score */
56 /* values for elements with content */
57 #define MIN_ELEM_CONTENT 1
58 #define MAX_ELEM_CONTENT 8
60 /* values for the control window */
61 #define ED_CTRL_BUTTONS_GFX_YPOS 236
62 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142
64 #define ED_CTRL1_BUTTONS_HORIZ 4
65 #define ED_CTRL1_BUTTONS_VERT 4
66 #define ED_CTRL1_BUTTON_XSIZE 22
67 #define ED_CTRL1_BUTTON_YSIZE 22
68 #define ED_CTRL1_BUTTONS_XPOS 6
69 #define ED_CTRL1_BUTTONS_YPOS 6
70 #define ED_CTRL2_BUTTONS_HORIZ 3
71 #define ED_CTRL2_BUTTONS_VERT 2
72 #define ED_CTRL2_BUTTON_XSIZE 30
73 #define ED_CTRL2_BUTTON_YSIZE 20
74 #define ED_CTRL2_BUTTONS_XPOS 5
75 #define ED_CTRL2_BUTTONS_YPOS 100
76 #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
77 #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
78 #define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
80 /* values for element properties window */
81 #define ED_PROPERTIES_XPOS (TILEX - MINI_TILEX/2)
83 /* values for level information window */
84 #define ED_LEVELINFO_XPOS (TILEX - MINI_TILEX/2)
85 #define ED_LEVELINFO_YPOS (TILEY - MINI_TILEY/2)
87 /* values for counter gadgets */
88 #define ED_COUNT_VALUE_XOFFSET 5
89 #define ED_COUNT_VALUE_YOFFSET 3
90 #define ED_COUNT_ELEM_SCORE_XPOS ED_PROPERTIES_XPOS
91 #define ED_COUNT_ELEM_SCORE_YPOS (14 * MINI_TILEY)
92 #define ED_COUNT_ELEM_CONTENT_XPOS ED_PROPERTIES_XPOS
93 #define ED_COUNT_ELEM_CONTENT_YPOS (17 * MINI_TILEY)
94 #define ED_COUNTER_YSTART (ED_LEVELINFO_YPOS + 3 * TILEY)
95 #define ED_COUNTER_YDISTANCE (3 * MINI_TILEY)
96 #define ED_COUNTER_YPOS(n) (ED_COUNTER_YSTART + \
97 n * ED_COUNTER_YDISTANCE)
98 /* standard distances */
99 #define ED_BORDER_SIZE 3
100 #define ED_GADGET_DISTANCE 2
102 /* values for element content drawing areas */
103 #define ED_AREA_ELEM_CONTENT_XPOS (TILEX)
104 #define ED_AREA_ELEM_CONTENT_YPOS (10 * TILEY)
106 /* values for scrolling gadgets */
107 #define ED_SCROLLBUTTON_XPOS 24
108 #define ED_SCROLLBUTTON_YPOS 0
109 #define ED_SCROLLBAR_XPOS 24
110 #define ED_SCROLLBAR_YPOS 64
112 #define ED_SCROLLBUTTON_XSIZE 16
113 #define ED_SCROLLBUTTON_YSIZE 16
115 #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
116 #define ED_SCROLL_UP_YPOS (0)
117 #define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
118 #define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE)
119 #define ED_SCROLL_LEFT_XPOS (0)
120 #define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
121 #define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
122 #define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
123 #define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
124 #define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
125 #define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
126 #define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
127 #define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
128 #define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
129 #define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
130 #define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
132 /* control button identifiers */
133 #define ED_CTRL_ID_NONE -1
135 #define ED_CTRL_ID_SINGLE_ITEMS 0
136 #define ED_CTRL_ID_CONNECTED_ITEMS 1
137 #define ED_CTRL_ID_LINE 2
138 #define ED_CTRL_ID_TEXT 3
139 #define ED_CTRL_ID_RECTANGLE 4
140 #define ED_CTRL_ID_FILLED_BOX 5
141 #define ED_CTRL_ID_WRAP_UP 6
142 #define ED_CTRL_ID_PROPERTIES 7
143 #define ED_CTRL_ID_FLOOD_FILL 8
144 #define ED_CTRL_ID_WRAP_LEFT 9
145 #define ED_CTRL_ID_UNUSED1 10
146 #define ED_CTRL_ID_WRAP_RIGHT 11
147 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
148 #define ED_CTRL_ID_GRAB_BRUSH 13
149 #define ED_CTRL_ID_WRAP_DOWN 14
150 #define ED_CTRL_ID_PICK_ELEMENT 15
151 #define ED_CTRL_ID_UNDO 16
152 #define ED_CTRL_ID_INFO 17
153 #define ED_CTRL_ID_SAVE 18
154 #define ED_CTRL_ID_CLEAR 19
155 #define ED_CTRL_ID_TEST 20
156 #define ED_CTRL_ID_EXIT 21
158 /* counter button identifiers */
159 #define ED_CTRL_ID_ELEM_SCORE_DOWN 22
160 #define ED_CTRL_ID_ELEM_SCORE_TEXT 23
161 #define ED_CTRL_ID_ELEM_SCORE_UP 24
162 #define ED_CTRL_ID_ELEM_CONTENT_DOWN 25
163 #define ED_CTRL_ID_ELEM_CONTENT_TEXT 26
164 #define ED_CTRL_ID_ELEM_CONTENT_UP 27
165 #define ED_CTRL_ID_LEVEL_XSIZE_DOWN 28
166 #define ED_CTRL_ID_LEVEL_XSIZE_TEXT 29
167 #define ED_CTRL_ID_LEVEL_XSIZE_UP 30
168 #define ED_CTRL_ID_LEVEL_YSIZE_DOWN 31
169 #define ED_CTRL_ID_LEVEL_YSIZE_TEXT 32
170 #define ED_CTRL_ID_LEVEL_YSIZE_UP 33
171 #define ED_CTRL_ID_LEVEL_RANDOM_DOWN 34
172 #define ED_CTRL_ID_LEVEL_RANDOM_TEXT 35
173 #define ED_CTRL_ID_LEVEL_RANDOM_UP 36
174 #define ED_CTRL_ID_LEVEL_COLLECT_DOWN 37
175 #define ED_CTRL_ID_LEVEL_COLLECT_TEXT 38
176 #define ED_CTRL_ID_LEVEL_COLLECT_UP 39
177 #define ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN 40
178 #define ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT 41
179 #define ED_CTRL_ID_LEVEL_TIMELIMIT_UP 42
180 #define ED_CTRL_ID_LEVEL_TIMESCORE_DOWN 43
181 #define ED_CTRL_ID_LEVEL_TIMESCORE_TEXT 44
182 #define ED_CTRL_ID_LEVEL_TIMESCORE_UP 45
184 /* drawing area identifiers */
185 #define ED_CTRL_ID_DRAWING_LEVEL 46
186 #define ED_CTRL_ID_ELEM_CONTENT_0 47
187 #define ED_CTRL_ID_ELEM_CONTENT_1 48
188 #define ED_CTRL_ID_ELEM_CONTENT_2 49
189 #define ED_CTRL_ID_ELEM_CONTENT_3 50
190 #define ED_CTRL_ID_ELEM_CONTENT_4 51
191 #define ED_CTRL_ID_ELEM_CONTENT_5 52
192 #define ED_CTRL_ID_ELEM_CONTENT_6 53
193 #define ED_CTRL_ID_ELEM_CONTENT_7 54
194 #define ED_CTRL_ID_AMOEBA_CONTENT 55
196 /* text input identifiers */
197 #define ED_CTRL_ID_LEVEL_NAME 56
198 #define ED_CTRL_ID_LEVEL_AUTHOR 57
200 /* gadgets for scrolling of drawing area */
201 #define ED_CTRL_ID_SCROLL_UP 58
202 #define ED_CTRL_ID_SCROLL_DOWN 59
203 #define ED_CTRL_ID_SCROLL_LEFT 60
204 #define ED_CTRL_ID_SCROLL_RIGHT 61
205 #define ED_CTRL_ID_SCROLL_VERTICAL 62
206 #define ED_CTRL_ID_SCROLL_HORIZONTAL 63
208 #define ED_NUM_GADGETS 64
210 /* values for counter gadgets */
211 #define ED_COUNTER_ID_ELEM_SCORE 0
212 #define ED_COUNTER_ID_ELEM_CONTENT 1
213 #define ED_COUNTER_ID_LEVEL_XSIZE 2
214 #define ED_COUNTER_ID_LEVEL_YSIZE 3
215 #define ED_COUNTER_ID_LEVEL_RANDOM 4
216 #define ED_COUNTER_ID_LEVEL_COLLECT 5
217 #define ED_COUNTER_ID_LEVEL_TIMELIMIT 6
218 #define ED_COUNTER_ID_LEVEL_TIMESCORE 7
220 /* values for text input gadgets */
221 #define ED_TEXTINPUT_ID_LEVEL_NAME 0
222 #define ED_TEXTINPUT_ID_LEVEL_AUTHOR 1
224 #define ED_NUM_COUNTERBUTTONS 8
225 #define ED_NUM_SCROLLBUTTONS 4
226 #define ED_NUM_SCROLLBARS 2
227 #define ED_NUM_TEXTINPUT 2
229 /* values for CopyLevelToUndoBuffer() */
230 #define UNDO_IMMEDIATE 0
231 #define UNDO_ACCUMULATE 1
233 /* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
234 #define INFOTEXT_XPOS SX
235 #define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
236 #define INFOTEXT_XSIZE SXSIZE
237 #define INFOTEXT_YSIZE MINI_TILEX
238 #define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
244 } control_info[ED_NUM_CTRL_BUTTONS] =
246 { 's', "draw single items" },
247 { 'd', "draw connected items" },
248 { 'l', "draw lines" },
249 { 't', "enter text elements" },
250 { 'r', "draw outline rectangles" },
251 { 'R', "draw filled rectangles" },
252 { '\0', "wrap (rotate) level up" },
253 { '?', "properties of drawing element" },
254 { 'f', "flood fill" },
255 { '\0', "wrap (rotate) level left" },
257 { '\0', "wrap (rotate) level right" },
258 { '\0', "random element placement" },
259 { 'b', "grab brush" },
260 { '\0', "wrap (rotate) level down" },
261 { ',', "pick drawing element" },
262 { 'U', "undo last operation" },
263 { 'I', "level properties" },
264 { 'S', "save level" },
265 { 'C', "clear level" },
266 { 'T', "test level" },
267 { 'E', "exit level editor" }
270 /* pointers to counter values */
271 static int *gadget_elem_score_value = NULL;
272 static int *gadget_elem_content_value = NULL;
273 static int *gadget_level_xsize_value = NULL;
274 static int *gadget_level_ysize_value = NULL;
275 static int *gadget_level_random_value = NULL;
276 static int *gadget_level_collect_value = NULL;
277 static int *gadget_level_timelimit_value = NULL;
278 static int *gadget_level_timescore_value = NULL;
283 int min_value, max_value;
284 int gadget_id_down, gadget_id_up;
288 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
291 ED_COUNT_ELEM_SCORE_XPOS, ED_COUNT_ELEM_SCORE_YPOS,
292 MIN_SCORE, MAX_SCORE,
293 ED_CTRL_ID_ELEM_SCORE_DOWN, ED_CTRL_ID_ELEM_SCORE_UP,
294 ED_CTRL_ID_ELEM_SCORE_TEXT,
295 &gadget_elem_score_value,
299 ED_COUNT_ELEM_CONTENT_XPOS, ED_COUNT_ELEM_CONTENT_YPOS,
300 MIN_ELEM_CONTENT, MAX_ELEM_CONTENT,
301 ED_CTRL_ID_ELEM_CONTENT_DOWN, ED_CTRL_ID_ELEM_CONTENT_UP,
302 ED_CTRL_ID_ELEM_CONTENT_TEXT,
303 &gadget_elem_content_value,
307 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(0),
308 MIN_LEV_FIELDX, MAX_LEV_FIELDX,
309 ED_CTRL_ID_LEVEL_XSIZE_DOWN, ED_CTRL_ID_LEVEL_XSIZE_UP,
310 ED_CTRL_ID_LEVEL_XSIZE_TEXT,
311 &gadget_level_xsize_value,
315 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(1),
316 MIN_LEV_FIELDY, MAX_LEV_FIELDY,
317 ED_CTRL_ID_LEVEL_YSIZE_DOWN, ED_CTRL_ID_LEVEL_YSIZE_UP,
318 ED_CTRL_ID_LEVEL_YSIZE_TEXT,
319 &gadget_level_ysize_value,
323 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(2),
325 ED_CTRL_ID_LEVEL_RANDOM_DOWN, ED_CTRL_ID_LEVEL_RANDOM_UP,
326 ED_CTRL_ID_LEVEL_RANDOM_TEXT,
327 &gadget_level_random_value,
328 "number of random elements"
331 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(3),
333 ED_CTRL_ID_LEVEL_COLLECT_DOWN, ED_CTRL_ID_LEVEL_COLLECT_UP,
334 ED_CTRL_ID_LEVEL_COLLECT_TEXT,
335 &gadget_level_collect_value,
336 "number of emeralds to collect"
339 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(4),
341 ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN, ED_CTRL_ID_LEVEL_TIMELIMIT_UP,
342 ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT,
343 &gadget_level_timelimit_value,
344 "time available to solve level"
347 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(5),
349 ED_CTRL_ID_LEVEL_TIMESCORE_DOWN, ED_CTRL_ID_LEVEL_TIMESCORE_UP,
350 ED_CTRL_ID_LEVEL_TIMESCORE_TEXT,
351 &gadget_level_timescore_value,
352 "score for each 10 seconds left"
362 } textinput_info[ED_NUM_TEXTINPUT] =
365 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(6),
366 ED_CTRL_ID_LEVEL_NAME,
371 ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(7),
372 ED_CTRL_ID_LEVEL_AUTHOR,
384 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
387 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
388 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
389 "scroll level editing area up"
392 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
393 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
394 "scroll level editing area down"
397 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
398 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
399 "scroll level editing area left"
402 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
403 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
404 "scroll level editing area right"
416 } scrollbar_info[ED_NUM_SCROLLBARS] =
419 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
420 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
421 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
422 GD_TYPE_SCROLLBAR_VERTICAL,
423 ED_CTRL_ID_SCROLL_VERTICAL,
424 "scroll level editing area vertically"
427 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
428 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
429 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
430 GD_TYPE_SCROLLBAR_HORIZONTAL,
431 ED_CTRL_ID_SCROLL_HORIZONTAL,
432 "scroll level editing area horizontally"
436 /* forward declaration for internal use */
437 static void DrawDrawingWindow();
438 static void DrawLevelInfoWindow();
439 static void DrawPropertiesWindow();
440 static void CopyLevelToUndoBuffer(int);
441 static void HandleControlButtons(struct GadgetInfo *);
442 static void HandleCounterButtons(struct GadgetInfo *);
443 static void HandleDrawingAreas(struct GadgetInfo *);
444 static void HandleDrawingAreaInfo(struct GadgetInfo *);
445 static void HandleTextInputGadgets(struct GadgetInfo *);
447 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
448 static boolean level_editor_gadgets_created = FALSE;
450 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
451 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
452 static boolean draw_with_brush = FALSE;
453 static int properties_element = 0;
455 static short ElementContent[MAX_ELEM_CONTENT][3][3];
456 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
457 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
458 static int undo_buffer_position = 0;
459 static int undo_buffer_steps = 0;
461 static int random_placement_percentage = 10;
462 static int random_placement_num_objects = 10;
464 static int random_placement_method = RANDOM_USE_PERCENTAGE;
466 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
469 static int level_xpos, level_ypos;
470 static int edit_mode;
471 static boolean name_typing;
472 static int new_element1 = EL_MAUERWERK;
473 static int new_element2 = EL_LEERRAUM;
474 static int new_element3 = EL_ERDREICH;
476 static int counter_xsize = DXSIZE + 20;
478 int element_shift = 0;
480 int editor_element[] =
482 EL_CHAR_A + ('B' - 'A'),
483 EL_CHAR_A + ('O' - 'A'),
484 EL_CHAR_A + ('U' - 'A'),
485 EL_CHAR_A + ('L' - 'A'),
488 EL_CHAR_A + ('D' - 'A'),
489 EL_CHAR_A + ('E' - 'A'),
490 EL_CHAR_A + ('R' - 'A'),
492 EL_CHAR_A + ('D' - 'A'),
493 EL_CHAR_A + ('A' - 'A'),
494 EL_CHAR_A + ('S' - 'A'),
495 EL_CHAR_A + ('H' - 'A'),
522 EL_CHAR_A + ('E' - 'A'),
523 EL_CHAR_A + ('M' - 'A'),
524 EL_CHAR_A + ('E' - 'A'),
527 EL_CHAR_A + ('R' - 'A'),
528 EL_CHAR_A + ('A' - 'A'),
529 EL_CHAR_A + ('L' - 'A'),
530 EL_CHAR_A + ('D' - 'A'),
532 EL_CHAR_A + ('M' - 'A'),
533 EL_CHAR_A + ('I' - 'A'),
534 EL_CHAR_A + ('N' - 'A'),
535 EL_CHAR_A + ('E' - 'A'),
612 EL_CHAR_A + ('M' - 'A'),
613 EL_CHAR_A + ('O' - 'A'),
614 EL_CHAR_A + ('R' - 'A'),
615 EL_CHAR_A + ('E' - 'A'),
667 EL_CHAR_A + ('S' - 'A'),
668 EL_CHAR_A + ('O' - 'A'),
669 EL_CHAR_A + ('K' - 'A'),
670 EL_CHAR_A + ('O' - 'A'),
673 EL_CHAR_A + ('B' - 'A'),
674 EL_CHAR_A + ('A' - 'A'),
675 EL_CHAR_A + ('N' - 'A'),
678 EL_SOKOBAN_FELD_LEER,
679 EL_SOKOBAN_FELD_VOLL,
748 EL_CHAR_A + ('D' - 'A'),
749 EL_CHAR_A + ('Y' - 'A'),
750 EL_CHAR_A + ('N' - 'A'),
751 EL_CHAR_A + ('A' - 'A'),
753 EL_CHAR_A + ('B' - 'A'),
754 EL_CHAR_A + ('L' - 'A'),
755 EL_CHAR_A + ('A' - 'A'),
756 EL_CHAR_A + ('S' - 'A'),
759 EL_CHAR_A + ('T' - 'A'),
760 EL_CHAR_A + ('E' - 'A'),
761 EL_CHAR_A + ('R' - 'A'),
844 int elements_in_list = sizeof(editor_element)/sizeof(int);
846 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
849 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
850 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
852 XCopyArea(display, drawto, drawto, gc,
853 SX + (dx == -1 ? MINI_TILEX : 0),
854 SY + (dy == -1 ? MINI_TILEY : 0),
855 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
856 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
857 SX + (dx == +1 ? MINI_TILEX : 0),
858 SY + (dy == +1 ? MINI_TILEY : 0));
861 x = (dx == 1 ? 0 : ED_FIELDX - 1);
862 for(y=0; y<ED_FIELDY; y++)
863 DrawMiniElementOrWall(x, y, from_x, from_y);
867 y = (dy == 1 ? 0 : ED_FIELDY - 1);
868 for(x=0; x<ED_FIELDX; x++)
869 DrawMiniElementOrWall(x, y, from_x, from_y);
872 redraw_mask |= REDRAW_FIELD;
876 void InitLevelEditorGadgets()
880 for (i=0; i<ED_NUM_GADGETS; i++)
881 level_editor_gadget[i] = NULL;
884 static void CreateControlButtons()
886 Pixmap gd_pixmap = pix[PIX_DOOR];
887 struct GadgetInfo *gi;
888 unsigned long event_mask;
891 /* create toolbox buttons */
892 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
896 int gd_xoffset, gd_yoffset;
897 int gd_x1, gd_x2, gd_y1, gd_y2;
900 boolean radio_button_pressed;
902 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
903 id == ED_CTRL_ID_CONNECTED_ITEMS ||
904 id == ED_CTRL_ID_LINE ||
905 id == ED_CTRL_ID_TEXT ||
906 id == ED_CTRL_ID_RECTANGLE ||
907 id == ED_CTRL_ID_FILLED_BOX ||
908 id == ED_CTRL_ID_FLOOD_FILL ||
909 id == ED_CTRL_ID_GRAB_BRUSH ||
910 id == ED_CTRL_ID_PICK_ELEMENT)
912 button_type = GD_TYPE_RADIO_BUTTON;
914 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
915 event_mask = GD_EVENT_PRESSED;
919 button_type = GD_TYPE_NORMAL_BUTTON;
921 radio_button_pressed = FALSE;
923 if (id == ED_CTRL_ID_WRAP_LEFT ||
924 id == ED_CTRL_ID_WRAP_RIGHT ||
925 id == ED_CTRL_ID_WRAP_UP ||
926 id == ED_CTRL_ID_WRAP_DOWN)
927 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
929 event_mask = GD_EVENT_RELEASED;
932 if (id < ED_NUM_CTRL1_BUTTONS)
934 int x = i % ED_CTRL1_BUTTONS_HORIZ;
935 int y = i / ED_CTRL1_BUTTONS_HORIZ;
937 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
938 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
939 width = ED_CTRL1_BUTTON_XSIZE;
940 height = ED_CTRL1_BUTTON_YSIZE;
944 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
945 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
947 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
948 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
949 width = ED_CTRL2_BUTTON_XSIZE;
950 height = ED_CTRL2_BUTTON_YSIZE;
953 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
954 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
955 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
956 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
958 gi = CreateGadget(GDI_CUSTOM_ID, id,
959 GDI_INFO_TEXT, control_info[i].text,
960 GDI_X, EX + gd_xoffset,
961 GDI_Y, EY + gd_yoffset,
964 GDI_TYPE, button_type,
965 GDI_STATE, GD_BUTTON_UNPRESSED,
966 GDI_RADIO_NR, radio_button_nr,
967 GDI_RADIO_PRESSED, radio_button_pressed,
968 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
969 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
970 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
971 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
972 GDI_EVENT_MASK, event_mask,
973 GDI_CALLBACK_ACTION, HandleControlButtons,
977 Error(ERR_EXIT, "cannot create gadget");
979 level_editor_gadget[id] = gi;
982 /* create buttons for scrolling of drawing area */
983 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
985 int id = scrollbutton_info[i].gadget_id;
986 int gd_x1, gd_x2, gd_y;
988 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
990 gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
991 gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
992 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
994 gi = CreateGadget(GDI_CUSTOM_ID, id,
995 GDI_INFO_TEXT, scrollbutton_info[i].infotext,
996 GDI_X, SX + scrollbutton_info[i].x,
997 GDI_Y, SY + scrollbutton_info[i].y,
998 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
999 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
1000 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
1001 GDI_STATE, GD_BUTTON_UNPRESSED,
1002 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
1003 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
1004 GDI_EVENT_MASK, event_mask,
1005 GDI_CALLBACK_ACTION, HandleControlButtons,
1009 Error(ERR_EXIT, "cannot create gadget");
1011 level_editor_gadget[id] = gi;
1015 static void CreateCounterButtons()
1019 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
1022 int xpos = SX + counterbutton_info[i].x; /* xpos of down count button */
1023 int ypos = SY + counterbutton_info[i].y;
1027 Pixmap gd_pixmap = pix[PIX_DOOR];
1028 struct GadgetInfo *gi;
1030 counterbutton_info[i].gadget_id_down :
1031 counterbutton_info[i].gadget_id_up);
1033 int gd_x, gd_x1, gd_x2, gd_y;
1034 unsigned long event_mask;
1035 char infotext[MAX_INFOTEXT_LEN + 1];
1037 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
1039 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
1040 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
1041 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
1042 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
1044 sprintf(infotext, "%s counter value by 1, 5 or 10",
1045 (j == 0 ? "decrease" : "increase"));
1047 gi = CreateGadget(GDI_CUSTOM_ID, id,
1048 GDI_INFO_TEXT, infotext,
1051 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
1052 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
1053 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
1054 GDI_STATE, GD_BUTTON_UNPRESSED,
1055 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
1056 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
1057 GDI_EVENT_MASK, event_mask,
1058 GDI_CALLBACK_ACTION, HandleCounterButtons,
1062 Error(ERR_EXIT, "cannot create gadget");
1064 level_editor_gadget[id] = gi;
1065 xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of text count button */
1069 id = counterbutton_info[i].gadget_id_text;
1070 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
1072 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
1073 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
1075 gi = CreateGadget(GDI_CUSTOM_ID, id,
1076 GDI_INFO_TEXT, "enter counter value",
1079 GDI_TYPE, GD_TYPE_TEXTINPUT_NUMERIC,
1080 GDI_NUMBER_VALUE, 0,
1081 GDI_NUMBER_MIN, counterbutton_info[i].min_value,
1082 GDI_NUMBER_MAX, counterbutton_info[i].max_value,
1084 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
1085 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
1086 GDI_DESIGN_BORDER, ED_BORDER_SIZE,
1087 GDI_EVENT_MASK, event_mask,
1088 GDI_CALLBACK_ACTION, HandleCounterButtons,
1092 Error(ERR_EXIT, "cannot create gadget");
1094 level_editor_gadget[id] = gi;
1095 xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of up count button */
1101 static void CreateDrawingAreas()
1103 struct GadgetInfo *gi;
1104 unsigned long event_mask;
1109 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
1110 GD_EVENT_OFF_BORDERS;
1112 /* one for the level drawing area ... */
1113 id = ED_CTRL_ID_DRAWING_LEVEL;
1114 gi = CreateGadget(GDI_CUSTOM_ID, id,
1117 GDI_TYPE, GD_TYPE_DRAWING_AREA,
1118 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
1119 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
1120 GDI_EVENT_MASK, event_mask,
1121 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
1122 GDI_CALLBACK_ACTION, HandleDrawingAreas,
1126 Error(ERR_EXIT, "cannot create gadget");
1128 level_editor_gadget[id] = gi;
1130 /* ... up to eight areas for element content ... */
1131 for (i=0; i<MAX_ELEM_CONTENT; i++)
1133 int gx = SX + ED_AREA_ELEM_CONTENT_XPOS + 5 * (i % 4) * MINI_TILEX;
1134 int gy = SX + ED_AREA_ELEM_CONTENT_YPOS + 6 * (i / 4) * MINI_TILEY;
1136 id = ED_CTRL_ID_ELEM_CONTENT_0 + i;
1137 gi = CreateGadget(GDI_CUSTOM_ID, id,
1140 GDI_WIDTH, 3 * MINI_TILEX,
1141 GDI_HEIGHT, 3 * MINI_TILEY,
1142 GDI_TYPE, GD_TYPE_DRAWING_AREA,
1143 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
1144 GDI_EVENT_MASK, event_mask,
1145 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
1146 GDI_CALLBACK_ACTION, HandleDrawingAreas,
1150 Error(ERR_EXIT, "cannot create gadget");
1152 level_editor_gadget[id] = gi;
1155 /* ... and one for the amoeba content */
1156 id = ED_CTRL_ID_AMOEBA_CONTENT;
1157 gi = CreateGadget(GDI_CUSTOM_ID, id,
1158 GDI_X, SX + ED_AREA_ELEM_CONTENT_XPOS,
1159 GDI_Y, SY + ED_AREA_ELEM_CONTENT_YPOS,
1160 GDI_WIDTH, MINI_TILEX,
1161 GDI_HEIGHT, MINI_TILEY,
1162 GDI_TYPE, GD_TYPE_DRAWING_AREA,
1163 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
1164 GDI_EVENT_MASK, event_mask,
1165 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
1166 GDI_CALLBACK_ACTION, HandleDrawingAreas,
1170 Error(ERR_EXIT, "cannot create gadget");
1172 level_editor_gadget[id] = gi;
1175 static void CreateTextInputGadgets()
1179 for (i=0; i<ED_NUM_TEXTINPUT; i++)
1181 Pixmap gd_pixmap = pix[PIX_DOOR];
1183 struct GadgetInfo *gi;
1184 unsigned long event_mask;
1185 char infotext[1024];
1186 int id = ED_CTRL_ID_LEVEL_NAME + i;
1188 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
1190 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
1191 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
1193 sprintf(infotext, "Enter %s", textinput_info[i].infotext);
1194 infotext[MAX_INFOTEXT_LEN] = '\0';
1196 gi = CreateGadget(GDI_CUSTOM_ID, id,
1197 GDI_INFO_TEXT, infotext,
1198 GDI_X, SX + textinput_info[i].x,
1199 GDI_Y, SY + textinput_info[i].y,
1200 GDI_TYPE, GD_TYPE_TEXTINPUT_ALPHANUMERIC,
1201 GDI_TEXT_VALUE, textinput_info[i].value,
1203 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
1204 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
1205 GDI_DESIGN_BORDER, ED_BORDER_SIZE,
1206 GDI_EVENT_MASK, event_mask,
1207 GDI_CALLBACK_ACTION, HandleTextInputGadgets,
1211 Error(ERR_EXIT, "cannot create gadget");
1213 level_editor_gadget[id] = gi;
1217 static void CreateScrollbarGadgets()
1221 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1223 int id = scrollbar_info[i].gadget_id;
1224 Pixmap gd_pixmap = pix[PIX_DOOR];
1225 int gd_x1, gd_x2, gd_y1, gd_y2;
1226 struct GadgetInfo *gi;
1227 int items_max, items_visible, item_position;
1228 unsigned long event_mask;
1230 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
1232 items_max = MAX(lev_fieldx + 2, ED_FIELDX);
1233 items_visible = ED_FIELDX;
1238 items_max = MAX(lev_fieldy + 2, ED_FIELDY);
1239 items_visible = ED_FIELDY;
1243 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
1245 gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
1246 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
1247 gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1248 gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1250 gi = CreateGadget(GDI_CUSTOM_ID, id,
1251 GDI_INFO_TEXT, scrollbar_info[i].text,
1252 GDI_X, SX + scrollbar_info[i].x,
1253 GDI_Y, SY + scrollbar_info[i].y,
1254 GDI_WIDTH, scrollbar_info[i].width,
1255 GDI_HEIGHT, scrollbar_info[i].height,
1256 GDI_TYPE, scrollbar_info[i].type,
1257 GDI_SCROLLBAR_ITEMS_MAX, items_max,
1258 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
1259 GDI_SCROLLBAR_ITEM_POSITION, item_position,
1260 GDI_STATE, GD_BUTTON_UNPRESSED,
1261 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
1262 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
1263 GDI_DESIGN_BORDER, ED_BORDER_SIZE,
1264 GDI_EVENT_MASK, event_mask,
1265 GDI_CALLBACK_ACTION, HandleControlButtons,
1269 Error(ERR_EXIT, "cannot create gadget");
1271 level_editor_gadget[id] = gi;
1275 static void CreateLevelEditorGadgets()
1277 if (level_editor_gadgets_created)
1280 CreateControlButtons();
1281 CreateCounterButtons();
1282 CreateDrawingAreas();
1283 CreateTextInputGadgets();
1284 CreateScrollbarGadgets();
1286 level_editor_gadgets_created = TRUE;
1289 static void MapControlButtons()
1293 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1294 MapGadget(level_editor_gadget[i]);
1297 static void MapCounterButtons(int id)
1299 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_down]);
1300 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_text]);
1301 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_up]);
1304 static void MapDrawingArea(int id)
1306 MapGadget(level_editor_gadget[id]);
1309 static void MapTextInputGadget(int id)
1311 MapGadget(level_editor_gadget[textinput_info[id].gadget_id]);
1314 static void MapMainDrawingArea()
1318 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1319 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1321 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1322 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1324 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1327 static void UnmapDrawingArea(int id)
1329 UnmapGadget(level_editor_gadget[id]);
1332 void UnmapLevelEditorWindowGadgets()
1336 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1337 UnmapGadget(level_editor_gadget[i]);
1340 void UnmapLevelEditorGadgets()
1344 for (i=0; i<ED_NUM_GADGETS; i++)
1345 UnmapGadget(level_editor_gadget[i]);
1350 int i, x, y, graphic;
1352 edit_mode = ED_MODE_DRAWING;
1353 name_typing = FALSE;
1355 CloseDoor(DOOR_CLOSE_ALL);
1357 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1359 if (level_editor_test_game)
1361 for(x=0; x<lev_fieldx; x++)
1362 for(y=0; y<lev_fieldy; y++)
1363 Feld[x][y] = Ur[x][y];
1365 for(x=0; x<lev_fieldx; x++)
1366 for(y=0; y<lev_fieldy; y++)
1367 Ur[x][y] = FieldBackup[x][y];
1369 level_editor_test_game = FALSE;
1375 undo_buffer_position = -1;
1376 undo_buffer_steps = -1;
1377 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1381 DrawMiniLevel(level_xpos, level_ypos);
1385 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1386 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1388 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1389 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1390 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1391 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1392 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1393 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1394 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1396 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1398 if (i < elements_in_list)
1399 graphic = el2gfx(editor_element[i + element_shift]);
1401 graphic = GFX_LEERRAUM;
1403 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1404 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1405 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1406 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1407 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1411 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1412 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1413 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1414 el2gfx(new_element1));
1415 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1416 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1417 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1418 el2gfx(new_element2));
1419 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1420 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1421 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1422 el2gfx(new_element3));
1423 DrawTextExt(pix[PIX_DB_DOOR],gc,
1424 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1425 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1426 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1427 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1428 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1429 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1431 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1432 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1433 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1434 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1435 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1437 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1438 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1440 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1441 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1443 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1445 /* draw bigger door */
1446 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1451 /* draw new control window */
1452 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1453 DOOR_GFX_PAGEX8, 236,
1457 redraw_mask |= REDRAW_ALL;
1459 OpenDoor(DOOR_OPEN_1);
1461 if (!level_editor_gadgets_created)
1462 CreateLevelEditorGadgets();
1464 strcpy(level_editor_gadget[ED_CTRL_ID_LEVEL_NAME]->text.value, level.name);
1466 MapControlButtons();
1469 MapMainDrawingArea();
1472 DrawDrawingWindow();
1476 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1480 void DrawControlWindow()
1485 UnmapLevelEditorWindowGadgets();
1487 /* Inhalt der Mampfer */
1488 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1489 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1490 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1492 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1493 XFillRectangle(display,drawto,gc,
1494 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1495 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1496 3*MINI_TILEX+2,3*MINI_TILEY+2);
1498 XCopyArea(display,drawto,drawto,gc,
1499 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1500 4*5*MINI_TILEX,5*MINI_TILEY,
1501 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1504 for(y=0;y<3;y++) for(x=0;x<3;x++)
1505 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1507 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1508 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1509 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1512 /* Inhalt der Amöbe */
1513 for(y=0;y<2;y++) for(x=0;x<2;x++)
1515 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1516 XFillRectangle(display,drawto,gc,
1517 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1518 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1519 MINI_TILEX+2,MINI_TILEY+2);
1521 XCopyArea(display,drawto,drawto,gc,
1522 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1523 3*MINI_TILEX,3*MINI_TILEY,
1524 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1525 DrawMiniElement(29,26,level.amoebe_inhalt);
1527 for(i=0;i<11+3+2;i++)
1529 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1530 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1531 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1532 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1533 ED_COUNT_GADGET_XPOS,
1534 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1537 DrawText(ED_COUNT_VALUE_XPOS,
1538 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1539 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1541 DrawText(ED_COUNT_VALUE_XPOS,
1542 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1543 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1545 DrawText(ED_COUNT_VALUE_XPOS,
1546 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1547 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1549 DrawText(ED_COUNT_VALUE_XPOS,
1550 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1551 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1553 DrawText(ED_COUNT_VALUE_XPOS,
1554 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1555 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1557 DrawText(ED_COUNT_VALUE_XPOS,
1558 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1559 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1562 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1563 "Score for Emerald",FS_SMALL,FC_YELLOW);
1564 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1565 "Score for Diamond",FS_SMALL,FC_YELLOW);
1566 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1567 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1568 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1569 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1570 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1571 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1572 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1573 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1574 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1575 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1576 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1577 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1578 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1579 "Score for dynamite",FS_SMALL,FC_YELLOW);
1580 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1581 "Score for key",FS_SMALL,FC_YELLOW);
1582 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1583 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1584 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1585 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1586 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1587 "Time for magic wall",FS_SMALL,FC_YELLOW);
1588 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1589 "Time for wheel",FS_SMALL,FC_YELLOW);
1590 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1591 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1592 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1593 "Time available for this level",FS_SMALL,FC_YELLOW);
1595 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1596 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1597 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1598 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1599 ED_COUNT_GADGET_XPOS,
1600 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1602 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1603 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1604 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1605 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1606 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1607 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1608 DrawText(ED_COUNT_GADGET_XPOS+5,
1609 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1610 level.name,FS_SMALL,FC_YELLOW);
1611 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1612 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1613 "Title",FS_SMALL,FC_YELLOW);
1615 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1616 "Playfield size:",FS_SMALL,FC_YELLOW);
1617 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1618 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1619 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1620 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1621 ED_SIZE_GADGET_XPOS,
1622 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1623 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1624 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1625 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1626 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1627 ED_SIZE_GADGET_XPOS,
1628 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1629 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1630 "Width",FS_SMALL,FC_YELLOW);
1631 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1632 "Height",FS_SMALL,FC_YELLOW);
1633 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1634 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1635 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1636 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1639 void AdjustLevelScrollPosition()
1641 if (level_xpos < -1)
1643 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1644 level_xpos = lev_fieldx - ED_FIELDX + 1;
1645 if (lev_fieldx < ED_FIELDX - 2)
1648 if (level_ypos < -1)
1650 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1651 level_ypos = lev_fieldy - ED_FIELDY + 1;
1652 if (lev_fieldy < ED_FIELDY - 2)
1656 void AdjustEditorScrollbar(int id)
1658 struct GadgetInfo *gi = level_editor_gadget[id];
1659 int items_max, items_visible, item_position;
1661 if (id == ED_CTRL_ID_SCROLL_HORIZONTAL)
1663 items_max = MAX(lev_fieldx + 2, ED_FIELDX);
1664 items_visible = ED_FIELDX;
1665 item_position = level_xpos + 1;
1669 items_max = MAX(lev_fieldy + 2, ED_FIELDY);
1670 items_visible = ED_FIELDY;
1671 item_position = level_ypos + 1;
1674 if (item_position > items_max - items_visible)
1675 item_position = items_max - items_visible;
1677 AdjustScrollbar(gi, items_max, item_position);
1680 void ModifyEditorTextInput(int textinput_id, char *new_text)
1682 int gadget_id = textinput_info[textinput_id].gadget_id;
1683 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
1685 ModifyTextInputTextValue(gi, new_text);
1688 void ModifyEditorCounter(int counter_id, int new_value)
1690 int *counter_value = *counterbutton_info[counter_id].counter_value;
1691 int gadget_id = counterbutton_info[counter_id].gadget_id_text;
1692 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
1694 ModifyTextInputNumberValue(gi, new_value);
1696 if (counter_value != NULL)
1697 *counter_value = gi->text.number_value;
1700 static void PickDrawingElement(int button, int element)
1702 if (button < 1 || button > 3)
1707 new_element1 = element;
1708 DrawMiniGraphicExt(drawto, gc,
1709 DX + ED_WIN_MB_LEFT_XPOS,
1710 DY + ED_WIN_MB_LEFT_YPOS,
1711 el2gfx(new_element1));
1713 else if (button == 2)
1715 new_element2 = element;
1716 DrawMiniGraphicExt(drawto, gc,
1717 DX + ED_WIN_MB_MIDDLE_XPOS,
1718 DY + ED_WIN_MB_MIDDLE_YPOS,
1719 el2gfx(new_element2));
1723 new_element3 = element;
1724 DrawMiniGraphicExt(drawto, gc,
1725 DX + ED_WIN_MB_RIGHT_XPOS,
1726 DY + ED_WIN_MB_RIGHT_YPOS,
1727 el2gfx(new_element3));
1730 redraw_mask |= REDRAW_DOOR_1;
1733 void LevelEd(int mx, int my, int button)
1735 static int last_button = 0;
1738 static int in_field_pressed = FALSE;
1741 static boolean use_floodfill = FALSE;
1745 int x = (mx-SX)/MINI_TILEX;
1746 int y = (my-SY)/MINI_TILEY;
1750 HandlePressedControlButtons();
1751 HandleDrawingFunctions(mx, my, button);
1754 if (use_floodfill) /********** FLOOD FILL **********/
1762 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1767 if (x>lev_fieldx || y>lev_fieldy ||
1768 (x==0 && level_xpos<0) ||
1769 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1770 (y==0 && level_ypos<0) ||
1771 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1774 from_x = x+level_xpos;
1775 from_y = y+level_ypos;
1776 fill_element = (button==1 ? new_element1 :
1777 button==2 ? new_element2 :
1778 button==3 ? new_element3 : 0);
1780 FloodFill(from_x,from_y,fill_element);
1781 DrawMiniLevel(level_xpos,level_ypos);
1784 use_floodfill = FALSE;
1785 CloseDoor(DOOR_CLOSE_1);
1786 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1795 else /********** EDIT/CTRL-FENSTER **********/
1797 static unsigned long choice_delay = 0;
1798 int choice = CheckElemButtons(mx,my,button);
1799 int elem_pos = choice-ED_BUTTON_ELEM;
1801 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1802 (choice == ED_BUTTON_EDOWN &&
1803 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1804 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1806 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1810 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1812 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1814 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1815 element_shift += step;
1818 if (element_shift<0)
1820 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1821 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1822 if (element_shift % MAX_ELEM_X)
1823 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1825 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1826 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1828 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1832 if (elem_pos+element_shift < elements_in_list)
1833 new_element = editor_element[elem_pos+element_shift];
1835 new_element = EL_LEERRAUM;
1837 PickDrawingElement(last_button, new_element);
1839 if (!HAS_CONTENT(properties_element))
1841 properties_element = new_element;
1842 if (edit_mode == ED_MODE_PROPERTIES)
1843 DrawPropertiesWindow();
1847 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1854 switch(CheckEditButtons(mx,my,button))
1856 case ED_BUTTON_CTRL:
1857 CloseDoor(DOOR_CLOSE_2);
1858 DrawControlWindow();
1859 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1860 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1862 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1863 OpenDoor(DOOR_OPEN_2);
1864 edit_mode = ED_MODE_INFO;
1866 case ED_BUTTON_FILL:
1867 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1868 use_floodfill = TRUE;
1871 case ED_BUTTON_LEFT:
1874 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1876 if (lev_fieldx<ED_FIELDX-2)
1879 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1883 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1885 DrawMiniLevel(level_xpos,level_ypos);
1888 case ED_BUTTON_RIGHT:
1889 if (level_xpos<=lev_fieldx-ED_FIELDX)
1891 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1893 if (lev_fieldx<ED_FIELDX-2)
1896 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1897 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1898 level_xpos = lev_fieldx-ED_FIELDX+1;
1900 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1902 DrawMiniLevel(level_xpos,level_ypos);
1908 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1910 if (lev_fieldy<ED_FIELDY-2)
1913 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1917 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1919 DrawMiniLevel(level_xpos,level_ypos);
1922 case ED_BUTTON_DOWN:
1923 if (level_ypos<=lev_fieldy-ED_FIELDY)
1925 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1927 if (lev_fieldy<ED_FIELDY-2)
1930 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1931 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1932 level_ypos = lev_fieldy-ED_FIELDY+1;
1934 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1936 DrawMiniLevel(level_xpos,level_ypos);
1949 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1953 if (button && !motion_status)
1954 in_field_pressed = TRUE;
1956 if (!button || !in_field_pressed || button<1 || button>3 ||
1957 (y==0 && level_ypos<0) ||
1958 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1959 (x==0 && level_xpos<0) ||
1960 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1961 x>lev_fieldx || y>lev_fieldy)
1964 new_element = (button==1 ? new_element1 :
1965 button==2 ? new_element2 :
1966 button==3 ? new_element3 : 0);
1968 if (new_element != Feld[x+level_xpos][y+level_ypos])
1970 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1974 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1976 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1978 Feld[x][y] = EL_LEERRAUM;
1979 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1980 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1981 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1986 Feld[x+level_xpos][y+level_ypos] = new_element;
1987 DrawMiniElement(x,y,new_element);
1990 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1991 in_field_pressed = FALSE;
1998 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
2004 int choice = CheckCountButtons(mx,my,button);
2005 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
2007 if (choice >= 0 && choice < 36 &&
2008 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
2017 level.score[choice] += step;
2018 if (level.score[choice]<0)
2019 level.score[choice] = 0;
2020 else if (level.score[choice]>255)
2021 level.score[choice] = 255;
2023 else if (choice==11)
2025 level.tempo_amoebe += step;
2026 if (level.tempo_amoebe<0)
2027 level.tempo_amoebe = 0;
2028 else if (level.tempo_amoebe>255)
2029 level.tempo_amoebe = 255;
2031 else if (choice==12)
2033 level.dauer_sieb += step;
2034 if (level.dauer_sieb<0)
2035 level.dauer_sieb = 0;
2036 else if (level.dauer_sieb>255)
2037 level.dauer_sieb = 255;
2039 else if (choice==13)
2041 level.dauer_ablenk += step;
2042 if (level.dauer_ablenk<0)
2043 level.dauer_ablenk = 0;
2044 else if (level.dauer_ablenk>255)
2045 level.dauer_ablenk = 255;
2047 else if (choice==14)
2049 level.edelsteine += step;
2050 if (level.edelsteine<0)
2051 level.edelsteine = 0;
2052 else if (level.edelsteine>999)
2053 level.edelsteine = 999;
2055 else if (choice==15)
2060 else if (level.time>999)
2063 else if (choice==16)
2066 if (lev_fieldx<MIN_LEV_FIELDX)
2067 lev_fieldx = MIN_LEV_FIELDX;
2068 else if (lev_fieldx>MAX_LEV_FIELDX)
2069 lev_fieldx = MAX_LEV_FIELDX;
2070 level.fieldx = lev_fieldx;
2072 else if (choice==17)
2075 if (lev_fieldy<MIN_LEV_FIELDY)
2076 lev_fieldy = MIN_LEV_FIELDY;
2077 else if (lev_fieldy>MAX_LEV_FIELDY)
2078 lev_fieldy = MAX_LEV_FIELDY;
2079 level.fieldy = lev_fieldy;
2083 DrawText(ED_COUNT_VALUE_XPOS,
2084 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
2085 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
2086 else if (choice==11)
2087 DrawText(ED_COUNT_VALUE_XPOS,
2088 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
2089 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
2090 else if (choice==12)
2091 DrawText(ED_COUNT_VALUE_XPOS,
2092 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
2093 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
2094 else if (choice==13)
2095 DrawText(ED_COUNT_VALUE_XPOS,
2096 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
2097 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
2098 else if (choice==14)
2099 DrawText(ED_COUNT_VALUE_XPOS,
2100 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
2101 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
2102 else if (choice==15)
2103 DrawText(ED_COUNT_VALUE_XPOS,
2104 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
2105 int2str(level.time,3),FS_SMALL,FC_YELLOW);
2106 else if (choice==16)
2107 DrawText(ED_SIZE_VALUE_XPOS,
2108 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
2109 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
2110 else if (choice==17)
2111 DrawText(ED_SIZE_VALUE_XPOS,
2112 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
2113 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
2115 redraw_mask &= ~REDRAW_FIELD;
2117 XCopyArea(display,drawto,window,gc,
2118 ED_COUNT_VALUE_XPOS,
2119 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
2120 3*FONT2_XSIZE,FONT2_YSIZE,
2121 ED_COUNT_VALUE_XPOS,
2122 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
2124 XCopyArea(display,drawto,window,gc,
2126 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
2127 3*FONT2_XSIZE,FONT2_YSIZE,
2129 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
2133 switch(CheckCtrlButtons(mx,my,button))
2135 case ED_BUTTON_EDIT:
2136 CloseDoor(DOOR_CLOSE_2);
2137 AdjustLevelScrollPosition();
2138 DrawMiniLevel(level_xpos,level_ypos);
2139 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
2140 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
2142 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
2143 OpenDoor(DOOR_OPEN_2);
2144 edit_mode = ED_MODE_DRAWING;
2146 case ED_BUTTON_CLEAR:
2147 if (Request("Are you sure to clear this level ?",REQ_ASK))
2149 for(x=0;x<MAX_LEV_FIELDX;x++)
2150 for(y=0;y<MAX_LEV_FIELDY;y++)
2151 Feld[x][y] = EL_ERDREICH;
2152 DrawMiniLevel(level_xpos,level_ypos);
2155 case ED_BUTTON_UNDO:
2156 if (leveldir[leveldir_nr].readonly ||
2157 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
2159 CloseDoor(DOOR_CLOSE_ALL);
2160 game_status=MAINMENU;
2165 CloseDoor(DOOR_CLOSE_1);
2166 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2169 case ED_BUTTON_EXIT:
2171 int figur_vorhanden = FALSE;
2173 if (leveldir[leveldir_nr].readonly)
2175 Request("This level is read only !",REQ_CONFIRM);
2179 for(y=0;y<lev_fieldy;y++)
2180 for(x=0;x<lev_fieldx;x++)
2181 if (Feld[x][y] == EL_SPIELFIGUR ||
2182 Feld[x][y] == EL_SPIELER1 ||
2183 Feld[x][y] == EL_SP_MURPHY)
2184 figur_vorhanden = TRUE;
2186 if (!figur_vorhanden)
2187 Request("No Level without Gregor Mc Duffin please !",
2191 if (Request("Save this level and kill the old ?",
2192 REQ_ASK | REQ_STAY_OPEN))
2194 for(x=0;x<lev_fieldx;x++)
2195 for(y=0;y<lev_fieldy;y++)
2196 Ur[x][y]=Feld[x][y];
2197 SaveLevel(level_nr);
2199 CloseDoor(DOOR_CLOSE_ALL);
2200 game_status=MAINMENU;
2209 if (mx>=ED_COUNT_GADGET_XPOS &&
2210 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
2211 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
2212 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
2217 DrawText(ED_COUNT_GADGET_XPOS+5,
2218 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2219 level.name,FS_SMALL,FC_GREEN);
2220 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
2221 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2222 "<",FS_SMALL,FC_RED);
2229 name_typing = FALSE;
2230 DrawText(ED_COUNT_GADGET_XPOS+5,
2231 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2232 level.name,FS_SMALL,FC_YELLOW);
2233 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
2234 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2235 " ",FS_SMALL,FC_RED);
2239 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
2240 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
2244 if (!button || button<1 || button>3)
2247 new_element = (button==1 ? new_element1 :
2248 button==2 ? new_element2 :
2249 button==3 ? new_element3 : 0);
2251 if (new_element != level.amoebe_inhalt)
2253 level.amoebe_inhalt = new_element;
2254 DrawMiniElement(29,26,new_element);
2258 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
2259 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
2261 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
2262 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
2267 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
2269 if (button && !motion_status)
2270 in_field_pressed = TRUE;
2272 if (!button || !in_field_pressed || button<1 || button>3)
2275 new_element = (button==1 ? new_element1 :
2276 button==2 ? new_element2 :
2277 button==3 ? new_element3 : 0);
2279 if (new_element != level.mampfer_inhalt[i][x][y])
2281 level.mampfer_inhalt[i][x][y] = new_element;
2282 DrawMiniElement(1+5*i+x,2+y,new_element);
2285 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
2286 in_field_pressed = FALSE;
2288 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
2289 in_field_pressed = FALSE;
2298 last_button = button;
2303 void LevelNameTyping(KeySym key)
2305 unsigned char ascii = 0;
2306 int len = strlen(level.name);
2311 if (key>=XK_A && key<=XK_Z)
2312 ascii = 'A'+(char)(key-XK_A);
2313 else if (key>=XK_a && key<=XK_z)
2314 ascii = 'a'+(char)(key-XK_a);
2315 else if (key>=XK_0 && key<=XK_9)
2316 ascii = '0'+(char)(key-XK_0);
2318 else if (key>=XK_space && key<=XK_at)
2319 ascii = ' '+(char)(key-XK_space);
2320 else if (key==XK_Adiaeresis)
2322 else if (key==XK_Odiaeresis)
2324 else if (key==XK_Udiaeresis)
2326 else if (key==XK_adiaeresis)
2328 else if (key==XK_odiaeresis)
2330 else if (key==XK_udiaeresis)
2332 else if (key==XK_underscore)
2336 if (ascii && len<MAX_LEVEL_NAME_LEN-2)
2338 level.name[len] = ascii;
2339 level.name[len+1] = 0;
2342 DrawTextExt(drawto,gc,
2343 ED_COUNT_GADGET_XPOS+5,
2344 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2345 level.name,FS_SMALL,FC_GREEN);
2346 DrawTextExt(window,gc,
2347 ED_COUNT_GADGET_XPOS+5,
2348 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2349 level.name,FS_SMALL,FC_GREEN);
2350 DrawTextExt(drawto,gc,
2351 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2352 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2353 "<",FS_SMALL,FC_RED);
2354 DrawTextExt(window,gc,
2355 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2356 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2357 "<",FS_SMALL,FC_RED);
2359 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2361 level.name[len-1] = 0;
2364 DrawTextExt(drawto,gc,
2365 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2366 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2367 "< ",FS_SMALL,FC_GREEN);
2368 DrawTextExt(window,gc,
2369 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2370 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2371 "< ",FS_SMALL,FC_GREEN);
2373 else if (key==XK_Return)
2375 DrawTextExt(drawto,gc,
2376 ED_COUNT_GADGET_XPOS+5,
2377 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2378 level.name,FS_SMALL,FC_YELLOW);
2379 DrawTextExt(window,gc,
2380 ED_COUNT_GADGET_XPOS+5,
2381 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2382 level.name,FS_SMALL,FC_YELLOW);
2383 DrawTextExt(drawto,gc,
2384 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2385 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2386 " ",FS_SMALL,FC_YELLOW);
2387 DrawTextExt(window,gc,
2388 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2389 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2390 " ",FS_SMALL,FC_YELLOW);
2392 name_typing = FALSE;
2396 static void DrawCounterValueField(int counter_id, int value)
2398 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2399 int y = SY + counterbutton_info[counter_id].y;
2401 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2402 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2403 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2404 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2407 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2408 int2str(value, 3), FS_SMALL, FC_YELLOW);
2411 static void DrawDrawingWindow()
2414 UnmapLevelEditorWindowGadgets();
2415 AdjustLevelScrollPosition();
2416 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL);
2417 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL);
2418 DrawMiniLevel(level_xpos, level_ypos);
2419 MapMainDrawingArea();
2422 static void DrawLevelInfoWindow()
2424 char infotext[1024];
2425 int infotext_yoffset = MINI_TILEX + ED_GADGET_DISTANCE;
2429 UnmapLevelEditorWindowGadgets();
2431 DrawTextF(ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS, FC_YELLOW,
2432 "Level Information");
2434 gadget_level_xsize_value = &lev_fieldx;
2435 gadget_level_ysize_value = &lev_fieldy;
2436 gadget_level_random_value = &random_placement_num_objects;
2437 gadget_level_collect_value = &level.edelsteine;
2438 gadget_level_timelimit_value = &level.time;
2439 gadget_level_timescore_value = &level.score[10];
2441 /* draw counter gadgets for level info */
2442 for (i=ED_COUNTER_ID_LEVEL_XSIZE; i<=ED_COUNTER_ID_LEVEL_TIMESCORE; i++)
2444 x = counterbutton_info[i].x;
2445 y = counterbutton_info[i].y - infotext_yoffset;
2447 sprintf(infotext, "%s:", counterbutton_info[i].infotext);
2448 infotext[MAX_INFOTEXT_LEN] = '\0';
2450 DrawTextF(x, y, FC_YELLOW, infotext);
2451 ModifyEditorCounter(i, **counterbutton_info[i].counter_value);
2452 MapCounterButtons(i);
2455 /* draw text input gadgets for level info */
2456 for (i=ED_TEXTINPUT_ID_LEVEL_NAME; i<=ED_TEXTINPUT_ID_LEVEL_AUTHOR; i++)
2458 x = textinput_info[i].x;
2459 y = textinput_info[i].y - infotext_yoffset;
2461 sprintf(infotext, "%s:", textinput_info[i].infotext);
2462 infotext[MAX_INFOTEXT_LEN] = '\0';
2464 DrawTextF(x, y, FC_YELLOW, infotext);
2465 ModifyEditorTextInput(i, textinput_info[i].value);
2466 MapTextInputGadget(i);
2470 static void DrawElementContentAreas()
2472 int *num_areas = &MampferMax;
2473 int area_x = ED_AREA_ELEM_CONTENT_XPOS / MINI_TILEX;
2474 int area_y = ED_AREA_ELEM_CONTENT_YPOS / MINI_TILEY;
2475 int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
2476 int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
2479 for (i=0; i<MAX_ELEM_CONTENT; i++)
2482 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2484 for (i=0; i<MAX_ELEM_CONTENT; i++)
2485 UnmapDrawingArea(ED_CTRL_ID_ELEM_CONTENT_0 + i);
2487 /* display counter to choose number of element content areas */
2488 gadget_elem_content_value = num_areas;
2489 DrawCounterValueField(ED_COUNTER_ID_ELEM_CONTENT,*gadget_elem_content_value);
2490 x = counterbutton_info[ED_COUNTER_ID_ELEM_CONTENT].x + counter_xsize;
2491 y = counterbutton_info[ED_COUNTER_ID_ELEM_CONTENT].y;
2492 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2493 FC_YELLOW, "number of content areas");
2494 ModifyEditorCounter(ED_COUNTER_ID_ELEM_CONTENT, *gadget_elem_content_value);
2495 MapCounterButtons(ED_COUNTER_ID_ELEM_CONTENT);
2497 /* delete content areas in case of reducing number of them */
2498 XFillRectangle(display, backbuffer, gc,
2499 SX, area_sy - MINI_TILEX,
2500 SXSIZE, 12 * MINI_TILEY);
2502 /* draw some decorative border for the objects */
2503 for (i=0; i<*num_areas; i++)
2507 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2510 XFillRectangle(display, drawto, gc,
2511 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2512 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2513 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2516 /* copy border to the right location */
2517 XCopyArea(display, drawto, drawto, gc,
2518 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2519 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2521 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2522 "Content", FS_SMALL, FC_YELLOW);
2523 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2524 "when", FS_SMALL, FC_YELLOW);
2525 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2526 "smashed", FS_SMALL, FC_YELLOW);
2528 for (i=0; i<*num_areas; i++)
2532 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2533 ElementContent[i][x][y]);
2535 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2536 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2537 FC_YELLOW, "%d", i + 1);
2540 for (i=0; i<*num_areas; i++)
2541 MapDrawingArea(ED_CTRL_ID_ELEM_CONTENT_0 + i);
2544 static void DrawAmoebaContentArea()
2546 int area_x = ED_AREA_ELEM_CONTENT_XPOS / MINI_TILEX;
2547 int area_y = ED_AREA_ELEM_CONTENT_YPOS / MINI_TILEY;
2548 int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
2549 int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
2552 ElementContent[0][0][0] = level.amoebe_inhalt;
2554 /* draw decorative border for the object */
2557 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2559 XFillRectangle(display, drawto, gc,
2560 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2561 MINI_TILEX + 2, MINI_TILEY + 2);
2563 /* copy border to the right location */
2564 XCopyArea(display, drawto, drawto, gc,
2565 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2566 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2568 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2569 FS_SMALL, FC_YELLOW);
2571 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2573 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2576 #define TEXT_COLLECTING "Score for collecting"
2577 #define TEXT_SMASHING "Score for smashing"
2578 #define TEXT_CRACKING "Score for cracking"
2579 #define TEXT_SPEED "Speed of amoeba growth"
2580 #define TEXT_DURATION "Duration when activated"
2582 static void DrawPropertiesWindow()
2585 int num_elements_in_level;
2591 } elements_with_counter[] =
2593 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2594 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2595 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2596 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2597 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2598 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2599 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2600 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2601 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2602 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2603 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2604 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2605 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2606 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2607 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2608 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2609 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2610 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2611 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2612 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2613 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2614 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2615 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2616 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2617 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2618 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2619 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2620 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2621 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2622 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2623 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2624 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2625 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2626 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2627 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2628 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2629 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2630 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2631 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2632 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2633 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2638 UnmapLevelEditorWindowGadgets();
2640 /* draw some decorative border for the object */
2643 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2645 XFillRectangle(display, drawto, gc,
2646 SX + TILEX + MINI_TILEX/2 - 1,
2647 SY + TILEY + MINI_TILEY/2 - 1,
2648 TILEX + 2, TILEY + 2);
2650 /* copy border to the right location */
2651 XCopyArea(display, drawto, drawto, gc,
2652 SX + TILEX, SY + TILEY,
2653 2 * TILEX, 2 * TILEY,
2654 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2656 DrawGraphic(1, 1, el2gfx(properties_element));
2657 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2658 FS_SMALL, FC_YELLOW);
2660 num_elements_in_level = 0;
2661 for (y=0; y<lev_fieldy; y++)
2662 for (x=0; x<lev_fieldx; x++)
2663 if (Feld[x][y] == properties_element)
2664 num_elements_in_level++;
2666 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2667 num_elements_in_level);
2669 /* check if there are elements where a score can be chosen for */
2670 for (i=0; elements_with_counter[i].element != -1; i++)
2672 if (elements_with_counter[i].element == properties_element)
2674 int x = counterbutton_info[ED_COUNTER_ID_ELEM_SCORE].x + counter_xsize;
2675 int y = counterbutton_info[ED_COUNTER_ID_ELEM_SCORE].y;
2677 gadget_elem_score_value = elements_with_counter[i].counter_value;
2680 DrawCounterValueField(ED_COUNTER_ID_SCORE, *gadget_score_value);
2683 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2684 FC_YELLOW, elements_with_counter[i].text);
2685 ModifyEditorCounter(ED_COUNTER_ID_ELEM_SCORE, *gadget_elem_score_value);
2686 MapCounterButtons(ED_COUNTER_ID_ELEM_SCORE);
2691 if (HAS_CONTENT(properties_element))
2693 if (IS_AMOEBOID(properties_element))
2694 DrawAmoebaContentArea();
2696 DrawElementContentAreas();
2700 static void swap_numbers(int *i1, int *i2)
2708 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2720 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2722 int lx = sx + level_xpos;
2723 int ly = sy + level_ypos;
2725 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2728 Feld[lx][ly] = element;
2731 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2732 int element, boolean change_level)
2734 if (from_y == to_y) /* horizontal line */
2740 swap_numbers(&from_x, &to_x);
2742 for (x=from_x; x<=to_x; x++)
2743 DrawLineElement(x, y, element, change_level);
2745 else if (from_x == to_x) /* vertical line */
2751 swap_numbers(&from_y, &to_y);
2753 for (y=from_y; y<=to_y; y++)
2754 DrawLineElement(x, y, element, change_level);
2756 else /* diagonal line */
2758 int len_x = ABS(to_x - from_x);
2759 int len_y = ABS(to_y - from_y);
2762 if (len_y < len_x) /* a < 1 */
2764 float a = (float)len_y / (float)len_x;
2767 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2769 for (x=0; x<=len_x; x++)
2771 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2773 DrawLineElement(from_x + x, from_y + y, element, change_level);
2778 float a = (float)len_x / (float)len_y;
2781 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2783 for (y=0; y<=len_y; y++)
2785 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2787 DrawLineElement(from_x + x, from_y + y, element, change_level);
2793 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2794 int element, boolean change_level)
2796 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2797 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2798 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2799 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2802 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2803 int element, boolean change_level)
2808 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2810 for (y=from_y; y<=to_y; y++)
2811 DrawLine(from_x, y, to_x, y, element, change_level);
2814 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2816 int from_sx, from_sy;
2820 swap_numbers(&from_x, &to_x);
2823 swap_numbers(&from_y, &to_y);
2825 from_sx = SX + from_x * MINI_TILEX;
2826 from_sy = SY + from_y * MINI_TILEY;
2827 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2828 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2830 XSetForeground(display, gc, WhitePixel(display, screen));
2832 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2833 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2834 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2835 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2837 XSetForeground(display, gc, BlackPixel(display, screen));
2839 if (from_x == to_x && from_y == to_y)
2840 MarkTileDirty(from_x/2, from_y/2);
2842 redraw_mask |= REDRAW_FIELD;
2845 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2846 int element, boolean change_level)
2848 if (element == -1 || change_level)
2849 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2851 DrawAreaBorder(from_x, from_y, to_x, to_y);
2854 /* values for CopyBrushExt() */
2855 #define CB_AREA_TO_BRUSH 0
2856 #define CB_BRUSH_TO_CURSOR 1
2857 #define CB_BRUSH_TO_LEVEL 2
2858 #define CB_DELETE_OLD_CURSOR 3
2860 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
2861 int button, int mode)
2863 static short brush_buffer[ED_FIELDX][ED_FIELDY];
2864 static int brush_width, brush_height;
2865 static int last_cursor_x = -1, last_cursor_y = -1;
2866 static boolean delete_old_brush;
2870 if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush)
2873 new_element = (button == 1 ? new_element1 :
2874 button == 2 ? new_element2 :
2875 button == 3 ? new_element3 : 0);
2877 if (mode == CB_AREA_TO_BRUSH)
2879 int from_lx, from_ly;
2882 swap_numbers(&from_x, &to_x);
2885 swap_numbers(&from_y, &to_y);
2887 brush_width = to_x - from_x + 1;
2888 brush_height = to_y - from_y + 1;
2890 from_lx = from_x + level_xpos;
2891 from_ly = from_y + level_ypos;
2893 for (y=0; y<brush_height; y++)
2895 for (x=0; x<brush_width; x++)
2897 brush_buffer[x][y] = Feld[from_lx + x][from_ly + y];
2900 DrawLineElement(from_x + x, from_y + y, new_element, TRUE);
2905 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2907 delete_old_brush = FALSE;
2909 else if (mode == CB_BRUSH_TO_CURSOR || mode == CB_DELETE_OLD_CURSOR ||
2910 mode == CB_BRUSH_TO_LEVEL)
2912 int cursor_x = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_x : from_x);
2913 int cursor_y = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_y : from_y);
2914 int cursor_from_x = cursor_x - brush_width / 2;
2915 int cursor_from_y = cursor_y - brush_height / 2;
2916 int border_from_x = cursor_x, border_from_y = cursor_y;
2917 int border_to_x = cursor_x, border_to_y = cursor_y;
2919 if (mode != CB_DELETE_OLD_CURSOR && delete_old_brush)
2920 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2922 if (!IN_ED_FIELD(cursor_x, cursor_y) ||
2923 !IN_LEV_FIELD(cursor_x + level_xpos, cursor_y + level_ypos))
2925 delete_old_brush = FALSE;
2929 for (y=0; y<brush_height; y++)
2931 for (x=0; x<brush_width; x++)
2933 int sx = cursor_from_x + x;
2934 int sy = cursor_from_y + y;
2935 int lx = sx + level_xpos;
2936 int ly = sy + level_ypos;
2937 boolean change_level = (mode == CB_BRUSH_TO_LEVEL);
2938 int element = (mode == CB_DELETE_OLD_CURSOR ? -1 :
2939 mode == CB_BRUSH_TO_CURSOR || button == 1 ?
2940 brush_buffer[x][y] : new_element);
2942 if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly))
2944 if (sx < border_from_x)
2946 else if (sx > border_to_x)
2948 if (sy < border_from_y)
2950 else if (sy > border_to_y)
2953 DrawLineElement(sx, sy, element, change_level);
2959 printf("%d, %d - %d, %d in level and screen\n",
2960 border_from_x, border_from_y, border_to_x, border_to_y);
2963 if (mode != CB_DELETE_OLD_CURSOR)
2964 DrawAreaBorder(border_from_x, border_from_y, border_to_x, border_to_y);
2967 if (mode == CB_BRUSH_TO_LEVEL)
2968 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2971 last_cursor_x = cursor_x;
2972 last_cursor_y = cursor_y;
2973 delete_old_brush = TRUE;
2977 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y,
2980 CopyBrushExt(from_x, from_y, to_x, to_y, button, CB_AREA_TO_BRUSH);
2983 static void CopyBrushToLevel(int x, int y, int button)
2985 CopyBrushExt(x, y, 0, 0, button, CB_BRUSH_TO_LEVEL);
2988 static void CopyBrushToCursor(int x, int y)
2990 CopyBrushExt(x, y, 0, 0, 0, CB_BRUSH_TO_CURSOR);
2993 static void DeleteBrushFromCursor()
2995 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2998 static void FloodFill(int from_x, int from_y, int fill_element)
3002 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
3003 static int safety = 0;
3005 /* check if starting field still has the desired content */
3006 if (Feld[from_x][from_y] == fill_element)
3011 if (safety > lev_fieldx*lev_fieldy)
3012 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
3014 old_element = Feld[from_x][from_y];
3015 Feld[from_x][from_y] = fill_element;
3019 x = from_x + check[i][0];
3020 y = from_y + check[i][1];
3022 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
3023 FloodFill(x, y, fill_element);
3029 /* values for DrawLevelText() modes */
3031 #define TEXT_SETCURSOR 1
3032 #define TEXT_WRITECHAR 2
3033 #define TEXT_BACKSPACE 3
3034 #define TEXT_NEWLINE 4
3037 static void DrawLevelText(int sx, int sy, char letter, int mode)
3039 static short delete_buffer[MAX_LEV_FIELDX];
3040 static int start_sx, start_sy;
3041 static int last_sx, last_sy;
3042 static boolean typing = FALSE;
3043 int letter_element = EL_CHAR_ASCII0 + letter;
3046 /* map lower case letters to upper case and convert special characters */
3047 if (letter >= 'a' && letter <= 'z')
3048 letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
3049 else if (letter == 'ä' || letter == 'Ä')
3050 letter_element = EL_CHAR_AE;
3051 else if (letter == 'ö' || letter == 'Ö')
3052 letter_element = EL_CHAR_OE;
3053 else if (letter == 'ü' || letter == 'Ü')
3054 letter_element = EL_CHAR_UE;
3055 else if (letter == '^')
3056 letter_element = EL_CHAR_COPY;
3058 letter_element = EL_CHAR_ASCII0 + letter;
3060 if (mode != TEXT_INIT)
3065 if (mode != TEXT_SETCURSOR)
3071 lx = last_sx + level_xpos;
3072 ly = last_sy + level_ypos;
3079 DrawLevelText(0, 0, 0, TEXT_END);
3082 start_sx = last_sx = sx;
3083 start_sy = last_sy = sy;
3084 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
3087 case TEXT_SETCURSOR:
3088 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3089 DrawAreaBorder(sx, sy, sx, sy);
3094 case TEXT_WRITECHAR:
3095 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
3097 delete_buffer[sx - start_sx] = Feld[lx][ly];
3098 Feld[lx][ly] = letter_element;
3100 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
3101 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
3102 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
3103 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
3105 DrawLevelText(0, 0, 0, TEXT_END);
3109 case TEXT_BACKSPACE:
3112 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
3113 DrawMiniElement(sx - 1, sy, new_element3);
3114 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
3119 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
3120 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
3122 DrawLevelText(0, 0, 0, TEXT_END);
3126 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3127 DrawMiniElement(sx, sy, Feld[lx][ly]);
3136 static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
3137 int element, boolean change_level)
3139 int lx = sx + level_xpos;
3140 int ly = sy + level_ypos;
3143 DrawMiniElement(sx, sy, Feld[lx][ly]);
3145 DrawAreaBorder(sx, sy, sx, sy);
3148 static void CopyLevelToUndoBuffer(int mode)
3150 static boolean accumulated_undo = FALSE;
3151 boolean new_undo_buffer_position = TRUE;
3156 case UNDO_IMMEDIATE:
3157 accumulated_undo = FALSE;
3160 case UNDO_ACCUMULATE:
3161 if (accumulated_undo)
3162 new_undo_buffer_position = FALSE;
3163 accumulated_undo = TRUE;
3170 if (new_undo_buffer_position)
3172 /* new position in undo buffer ring */
3173 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
3175 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
3176 undo_buffer_steps++;
3179 for(x=0; x<lev_fieldx; x++)
3180 for(y=0; y<lev_fieldy; y++)
3181 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
3184 printf("level saved to undo buffer\n");
3189 static void RandomPlacement(int button)
3194 new_element = (button == 1 ? new_element1 :
3195 button == 2 ? new_element2 :
3196 button == 3 ? new_element3 : 0);
3198 if (random_placement_method == RANDOM_USE_PERCENTAGE)
3200 for(x=0; x<lev_fieldx; x++)
3201 for(y=0; y<lev_fieldy; y++)
3202 if (RND(100) < random_placement_percentage)
3203 Feld[x][y] = new_element;
3207 int elements_left = random_placement_num_objects;
3209 while (elements_left > 0)
3211 x = RND(lev_fieldx);
3212 y = RND(lev_fieldy);
3214 if (Feld[x][y] != new_element)
3216 Feld[x][y] = new_element;
3222 DrawMiniLevel(level_xpos, level_ypos);
3223 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3226 void WrapLevel(int dx, int dy)
3228 int wrap_dx = lev_fieldx - dx;
3229 int wrap_dy = lev_fieldy - dy;
3232 for(x=0; x<lev_fieldx; x++)
3233 for(y=0; y<lev_fieldy; y++)
3234 FieldBackup[x][y] = Feld[x][y];
3236 for(x=0; x<lev_fieldx; x++)
3237 for(y=0; y<lev_fieldy; y++)
3239 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
3241 DrawMiniLevel(level_xpos, level_ypos);
3242 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
3245 static void HandleDrawingAreas(struct GadgetInfo *gi)
3247 static boolean started_inside_drawing_area = FALSE;
3248 int id = gi->custom_id;
3249 boolean inside_drawing_area = !gi->event.off_borders;
3250 boolean button_press_event;
3251 boolean button_release_event;
3252 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
3254 int button = gi->event.button;
3255 int sx = gi->event.x, sy = gi->event.y;
3256 int min_sx = 0, min_sy = 0;
3257 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
3259 int min_lx = 0, min_ly = 0;
3260 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
3263 /* handle info callback for each invocation of action callback */
3264 gi->callback_info(gi);
3267 if (edit_mode != ED_MODE_DRAWING)
3271 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
3272 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
3274 /* make sure to stay inside drawing area boundaries */
3275 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
3276 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
3280 /* get positions inside level field */
3281 lx = sx + level_xpos;
3282 ly = sy + level_ypos;
3284 /* make sure to stay inside level field boundaries */
3285 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
3286 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
3288 /* correct drawing area positions accordingly */
3289 sx = lx - level_xpos;
3290 sy = ly - level_ypos;
3293 if (button_press_event)
3294 started_inside_drawing_area = inside_drawing_area;
3296 if (!started_inside_drawing_area)
3299 if (!button && !button_release_event)
3302 new_element = (button == 1 ? new_element1 :
3303 button == 2 ? new_element2 :
3304 button == 3 ? new_element3 : 0);
3308 if (button_release_event)
3313 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
3316 switch (drawing_function)
3318 case ED_CTRL_ID_SINGLE_ITEMS:
3321 if (button_release_event)
3323 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3325 if (edit_mode == ED_MODE_DRAWING && draw_with_brush &&
3326 !inside_drawing_area)
3327 DeleteBrushFromCursor();
3333 if (draw_with_brush)
3335 if (!button_release_event)
3336 CopyBrushToLevel(sx, sy, button);
3338 else if (new_element != Feld[lx][ly])
3340 if (new_element == EL_SPIELFIGUR)
3342 /* remove player at old position */
3343 for(y=0; y<lev_fieldy; y++)
3345 for(x=0; x<lev_fieldx; x++)
3347 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
3349 Feld[x][y] = EL_LEERRAUM;
3350 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
3351 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
3352 DrawMiniElement(x - level_xpos, y - level_ypos,
3359 Feld[lx][ly] = new_element;
3360 DrawMiniElement(sx, sy, new_element);
3365 DrawMiniGraphicExt(drawto, gc,
3366 gi->x + sx * MINI_TILEX,
3367 gi->y + sy * MINI_TILEY,
3368 el2gfx(new_element));
3369 DrawMiniGraphicExt(window, gc,
3370 gi->x + sx * MINI_TILEX,
3371 gi->y + sy * MINI_TILEY,
3372 el2gfx(new_element));
3374 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3375 level.amoebe_inhalt = new_element;
3376 else if (id >= ED_CTRL_ID_ELEM_CONTENT_0 &&
3377 id <= ED_CTRL_ID_ELEM_CONTENT_7)
3378 level.mampfer_inhalt[id - ED_CTRL_ID_ELEM_CONTENT_0][sx][sy] =
3383 case ED_CTRL_ID_CONNECTED_ITEMS:
3385 static int last_sx = -1;
3386 static int last_sy = -1;
3388 if (button_release_event)
3389 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3393 if (!button_press_event)
3394 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
3402 case ED_CTRL_ID_LINE:
3403 case ED_CTRL_ID_RECTANGLE:
3404 case ED_CTRL_ID_FILLED_BOX:
3405 case ED_CTRL_ID_GRAB_BRUSH:
3406 case ED_CTRL_ID_TEXT:
3408 static int last_sx = -1;
3409 static int last_sy = -1;
3410 static int start_sx = -1;
3411 static int start_sy = -1;
3412 void (*draw_func)(int, int, int, int, int, boolean);
3414 if (drawing_function == ED_CTRL_ID_LINE)
3415 draw_func = DrawLine;
3416 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
3417 draw_func = DrawRectangle;
3418 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
3419 draw_func = DrawFilledBox;
3420 else if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3421 draw_func = SelectArea;
3422 else /* (drawing_function == ED_CTRL_ID_TEXT) */
3423 draw_func = SetTextCursor;
3425 if (button_press_event)
3427 draw_func(sx, sy, sx, sy, new_element, FALSE);
3428 start_sx = last_sx = sx;
3429 start_sy = last_sy = sy;
3431 if (drawing_function == ED_CTRL_ID_TEXT)
3432 DrawLevelText(0, 0, 0, TEXT_END);
3434 else if (button_release_event)
3436 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
3437 if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3439 CopyAreaToBrush(start_sx, start_sy, sx, sy, button);
3440 CopyBrushToCursor(sx, sy);
3441 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
3442 draw_with_brush = TRUE;
3444 else if (drawing_function == ED_CTRL_ID_TEXT)
3445 DrawLevelText(sx, sy, 0, TEXT_INIT);
3447 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3449 else if (last_sx != sx || last_sy != sy)
3451 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
3452 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
3462 case ED_CTRL_ID_TEXT:
3464 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3465 DrawAreaBorder(sx, sy, sx, sy);
3470 if (button_press_event)
3471 DrawLevelText(sx, sy, 0, TEXT_INIT);
3477 case ED_CTRL_ID_FLOOD_FILL:
3478 if (button_press_event && Feld[lx][ly] != new_element)
3480 FloodFill(lx, ly, new_element);
3481 DrawMiniLevel(level_xpos, level_ypos);
3482 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3486 case ED_CTRL_ID_PICK_ELEMENT:
3487 if (button_press_event)
3488 PickDrawingElement(button, Feld[lx][ly]);
3489 if (button_release_event)
3490 ClickOnGadget(level_editor_gadget[last_drawing_function]);
3498 static void HandleCounterButtons(struct GadgetInfo *gi)
3500 int id = gi->custom_id;
3501 int button = gi->event.button;
3502 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3506 case ED_CTRL_ID_ELEM_SCORE_DOWN:
3507 case ED_CTRL_ID_ELEM_SCORE_UP:
3508 step *= (id == ED_CTRL_ID_ELEM_SCORE_DOWN ? -1 : 1);
3509 ModifyEditorCounter(ED_COUNTER_ID_ELEM_SCORE,
3510 *gadget_elem_score_value + step);
3512 case ED_CTRL_ID_ELEM_SCORE_TEXT:
3513 *gadget_elem_score_value = gi->text.number_value;
3516 case ED_CTRL_ID_ELEM_CONTENT_DOWN:
3517 case ED_CTRL_ID_ELEM_CONTENT_UP:
3518 step *= (id == ED_CTRL_ID_ELEM_CONTENT_DOWN ? -1 : 1);
3519 ModifyEditorCounter(ED_COUNTER_ID_ELEM_CONTENT,
3520 *gadget_elem_content_value + step);
3521 DrawElementContentAreas();
3523 case ED_CTRL_ID_ELEM_CONTENT_TEXT:
3524 *gadget_elem_content_value = gi->text.number_value;
3525 DrawElementContentAreas();
3528 case ED_CTRL_ID_LEVEL_XSIZE_DOWN:
3529 case ED_CTRL_ID_LEVEL_XSIZE_UP:
3530 step *= (id == ED_CTRL_ID_LEVEL_XSIZE_DOWN ? -1 : 1);
3531 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_XSIZE,
3532 *gadget_level_xsize_value + step);
3533 level.fieldx = lev_fieldx;
3535 case ED_CTRL_ID_LEVEL_XSIZE_TEXT:
3536 *gadget_level_xsize_value = gi->text.number_value;
3537 level.fieldx = lev_fieldx;
3540 case ED_CTRL_ID_LEVEL_YSIZE_DOWN:
3541 case ED_CTRL_ID_LEVEL_YSIZE_UP:
3542 step *= (id == ED_CTRL_ID_LEVEL_YSIZE_DOWN ? -1 : 1);
3543 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_YSIZE,
3544 *gadget_level_ysize_value + step);
3545 level.fieldy = lev_fieldy;
3547 case ED_CTRL_ID_LEVEL_YSIZE_TEXT:
3548 *gadget_level_ysize_value = gi->text.number_value;
3549 level.fieldy = lev_fieldy;
3552 case ED_CTRL_ID_LEVEL_RANDOM_DOWN:
3553 case ED_CTRL_ID_LEVEL_RANDOM_UP:
3554 step *= (id == ED_CTRL_ID_LEVEL_RANDOM_DOWN ? -1 : 1);
3555 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_RANDOM,
3556 *gadget_level_random_value + step);
3558 case ED_CTRL_ID_LEVEL_RANDOM_TEXT:
3559 *gadget_level_random_value = gi->text.number_value;
3562 case ED_CTRL_ID_LEVEL_COLLECT_DOWN:
3563 case ED_CTRL_ID_LEVEL_COLLECT_UP:
3564 step *= (id == ED_CTRL_ID_LEVEL_COLLECT_DOWN ? -1 : 1);
3565 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_COLLECT,
3566 *gadget_level_collect_value + step);
3568 case ED_CTRL_ID_LEVEL_COLLECT_TEXT:
3569 *gadget_level_collect_value = gi->text.number_value;
3572 case ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN:
3573 case ED_CTRL_ID_LEVEL_TIMELIMIT_UP:
3574 step *= (id == ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN ? -1 : 1);
3575 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_TIMELIMIT,
3576 *gadget_level_timelimit_value + step);
3578 case ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT:
3579 *gadget_level_timelimit_value = gi->text.number_value;
3582 case ED_CTRL_ID_LEVEL_TIMESCORE_DOWN:
3583 case ED_CTRL_ID_LEVEL_TIMESCORE_UP:
3584 step *= (id == ED_CTRL_ID_LEVEL_TIMESCORE_DOWN ? -1 : 1);
3585 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_TIMESCORE,
3586 *gadget_level_timescore_value + step);
3588 case ED_CTRL_ID_LEVEL_TIMESCORE_TEXT:
3589 *gadget_level_timescore_value = gi->text.number_value;
3597 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3599 int id = gi->custom_id;
3603 case ED_CTRL_ID_LEVEL_NAME:
3604 strcpy(level.name, gi->text.value);
3607 case ED_CTRL_ID_LEVEL_AUTHOR:
3608 strcpy(level.author, gi->text.value);
3616 static void HandleControlButtons(struct GadgetInfo *gi)
3618 int id = gi->custom_id;
3619 int button = gi->event.button;
3620 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3622 int player_present = FALSE;
3623 int level_changed = FALSE;
3626 new_element = (button == 1 ? new_element1 :
3627 button == 2 ? new_element2 :
3628 button == 3 ? new_element3 : 0);
3630 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3631 DrawLevelText(0, 0, 0, TEXT_END);
3633 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3634 edit_mode != ED_MODE_DRAWING)
3636 DrawDrawingWindow();
3637 edit_mode = ED_MODE_DRAWING;
3642 case ED_CTRL_ID_SCROLL_LEFT:
3643 if (level_xpos >= 0)
3645 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3646 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3647 struct GadgetScrollbar *gs = &gi->scrollbar;
3649 if (lev_fieldx < ED_FIELDX - 2)
3653 if (level_xpos < -1)
3656 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3658 DrawMiniLevel(level_xpos, level_ypos);
3660 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3664 case ED_CTRL_ID_SCROLL_RIGHT:
3665 if (level_xpos <= lev_fieldx - ED_FIELDX)
3667 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3668 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3669 struct GadgetScrollbar *gs = &gi->scrollbar;
3671 if (lev_fieldx < ED_FIELDX - 2)
3675 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3676 level_xpos = lev_fieldx - ED_FIELDX + 1;
3678 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3680 DrawMiniLevel(level_xpos, level_ypos);
3682 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3686 case ED_CTRL_ID_SCROLL_UP:
3687 if (level_ypos >= 0)
3689 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3690 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3691 struct GadgetScrollbar *gs = &gi->scrollbar;
3693 if (lev_fieldy < ED_FIELDY - 2)
3697 if (level_ypos < -1)
3700 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3702 DrawMiniLevel(level_xpos, level_ypos);
3704 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3708 case ED_CTRL_ID_SCROLL_DOWN:
3709 if (level_ypos <= lev_fieldy - ED_FIELDY)
3711 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3712 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3713 struct GadgetScrollbar *gs = &gi->scrollbar;
3715 if (lev_fieldy < ED_FIELDY - 2)
3719 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3720 level_ypos = lev_fieldy - ED_FIELDY + 1;
3722 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3724 DrawMiniLevel(level_xpos, level_ypos);
3726 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3730 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3731 level_xpos = gi->event.item_position - 1;
3732 DrawMiniLevel(level_xpos, level_ypos);
3735 case ED_CTRL_ID_SCROLL_VERTICAL:
3736 level_ypos = gi->event.item_position - 1;
3737 DrawMiniLevel(level_xpos, level_ypos);
3740 case ED_CTRL_ID_WRAP_LEFT:
3741 WrapLevel(-step, 0);
3744 case ED_CTRL_ID_WRAP_RIGHT:
3748 case ED_CTRL_ID_WRAP_UP:
3749 WrapLevel(0, -step);
3752 case ED_CTRL_ID_WRAP_DOWN:
3756 case ED_CTRL_ID_SINGLE_ITEMS:
3757 case ED_CTRL_ID_CONNECTED_ITEMS:
3758 case ED_CTRL_ID_LINE:
3759 case ED_CTRL_ID_TEXT:
3760 case ED_CTRL_ID_RECTANGLE:
3761 case ED_CTRL_ID_FILLED_BOX:
3762 case ED_CTRL_ID_FLOOD_FILL:
3763 case ED_CTRL_ID_GRAB_BRUSH:
3764 case ED_CTRL_ID_PICK_ELEMENT:
3765 last_drawing_function = drawing_function;
3766 drawing_function = id;
3767 draw_with_brush = FALSE;
3770 case ED_CTRL_ID_RANDOM_PLACEMENT:
3771 RandomPlacement(button);
3774 case ED_CTRL_ID_PROPERTIES:
3775 if (edit_mode != ED_MODE_PROPERTIES)
3777 properties_element = new_element;
3778 DrawPropertiesWindow();
3779 edit_mode = ED_MODE_PROPERTIES;
3783 DrawDrawingWindow();
3784 edit_mode = ED_MODE_DRAWING;
3788 case ED_CTRL_ID_UNDO:
3789 if (undo_buffer_steps == 0)
3791 Request("Undo buffer empty !", REQ_CONFIRM);
3795 undo_buffer_position =
3796 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3797 undo_buffer_steps--;
3799 for(x=0; x<lev_fieldx; x++)
3800 for(y=0; y<lev_fieldy; y++)
3801 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3802 DrawMiniLevel(level_xpos,level_ypos);
3805 case ED_CTRL_ID_INFO:
3806 if (edit_mode != ED_MODE_INFO)
3808 DrawLevelInfoWindow();
3809 edit_mode = ED_MODE_INFO;
3813 DrawDrawingWindow();
3814 edit_mode = ED_MODE_DRAWING;
3818 case ED_CTRL_ID_CLEAR:
3819 for(x=0; x<MAX_LEV_FIELDX; x++)
3820 for(y=0; y<MAX_LEV_FIELDY; y++)
3821 Feld[x][y] = new_element3;
3822 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3824 DrawMiniLevel(level_xpos, level_ypos);
3827 case ED_CTRL_ID_SAVE:
3828 if (leveldir[leveldir_nr].readonly)
3830 Request("This level is read only !", REQ_CONFIRM);
3834 for(y=0; y<lev_fieldy; y++)
3835 for(x=0; x<lev_fieldx; x++)
3836 if (Feld[x][y] != Ur[x][y])
3837 level_changed = TRUE;
3839 if (0 && !level_changed)
3841 Request("Level has not changed !", REQ_CONFIRM);
3845 for(y=0; y<lev_fieldy; y++)
3846 for(x=0; x<lev_fieldx; x++)
3847 if (Feld[x][y] == EL_SPIELFIGUR ||
3848 Feld[x][y] == EL_SPIELER1 ||
3849 Feld[x][y] == EL_SP_MURPHY)
3850 player_present = TRUE;
3852 if (!player_present)
3853 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3856 if (Request("Save this level and kill the old ?", REQ_ASK))
3858 for(x=0; x<lev_fieldx; x++)
3859 for(y=0; y<lev_fieldy; y++)
3860 Ur[x][y] = Feld[x][y];
3861 SaveLevel(level_nr);
3866 case ED_CTRL_ID_TEST:
3867 for(y=0; y<lev_fieldy; y++)
3868 for(x=0; x<lev_fieldx; x++)
3869 if (Feld[x][y] == EL_SPIELFIGUR ||
3870 Feld[x][y] == EL_SPIELER1 ||
3871 Feld[x][y] == EL_SP_MURPHY)
3872 player_present = TRUE;
3874 if (!player_present)
3875 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3878 for(x=0; x<lev_fieldx; x++)
3879 for(y=0; y<lev_fieldy; y++)
3880 FieldBackup[x][y] = Ur[x][y];
3882 for(x=0; x<lev_fieldx; x++)
3883 for(y=0; y<lev_fieldy; y++)
3884 Ur[x][y] = Feld[x][y];
3886 UnmapLevelEditorGadgets();
3888 /* draw smaller door */
3889 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3890 DOOR_GFX_PAGEX7, 64,
3893 redraw_mask |= REDRAW_ALL;
3895 CloseDoor(DOOR_CLOSE_ALL);
3897 DrawCompleteVideoDisplay();
3899 if (setup.autorecord)
3900 TapeStartRecording();
3902 level_editor_test_game = TRUE;
3903 game_status = PLAYING;
3909 case ED_CTRL_ID_EXIT:
3910 for(y=0; y<lev_fieldy; y++)
3911 for(x=0; x<lev_fieldx; x++)
3912 if (Feld[x][y] != Ur[x][y])
3913 level_changed = TRUE;
3915 if (!level_changed ||
3916 Request("Level has changed! Exit without saving ?",
3917 REQ_ASK | REQ_STAY_OPEN))
3919 CloseDoor(DOOR_CLOSE_1);
3922 CloseDoor(DOOR_CLOSE_ALL);
3925 /* draw smaller door */
3926 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3927 DOOR_GFX_PAGEX7, 64,
3930 redraw_mask |= REDRAW_ALL;
3932 game_status = MAINMENU;
3937 CloseDoor(DOOR_CLOSE_1);
3938 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3939 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3940 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3941 OpenDoor(DOOR_OPEN_1);
3947 if (gi->event.type == GD_EVENT_PRESSED)
3948 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3949 else if (gi->event.type == GD_EVENT_RELEASED)
3950 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3951 else if (gi->event.type == GD_EVENT_MOVING)
3952 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3954 printf("default: HandleControlButtons: ?\n");
3960 void HandleLevelEditorKeyInput(KeySym key)
3962 if (edit_mode == ED_MODE_DRAWING)
3964 char letter = getCharFromKeySym(key);
3966 if (drawing_function == ED_CTRL_ID_TEXT)
3969 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3970 else if (key == XK_Delete || key == XK_BackSpace)
3971 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3972 else if (key == XK_Return)
3973 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3975 else if (button_status == MB_RELEASED)
3982 id = ED_CTRL_ID_SCROLL_LEFT;
3985 id = ED_CTRL_ID_SCROLL_RIGHT;
3988 id = ED_CTRL_ID_SCROLL_UP;
3991 id = ED_CTRL_ID_SCROLL_DOWN;
3995 id = ED_CTRL_ID_NONE;
3999 if (id != ED_CTRL_ID_NONE)
4000 ClickOnGadget(level_editor_gadget[id]);
4001 else if (letter == '.')
4002 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
4004 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
4005 if (letter && letter == control_info[i].shortcut)
4006 ClickOnGadget(level_editor_gadget[i]);
4011 void ClearEditorGadgetInfoText()
4013 XFillRectangle(display, drawto, gc,
4014 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
4015 redraw_mask |= REDRAW_FIELD;
4018 void HandleEditorGadgetInfoText(void *ptr)
4020 struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
4021 char infotext[MAX_INFOTEXT_LEN + 1];
4024 ClearEditorGadgetInfoText();
4026 /* misuse this function to delete brush cursor, if needed */
4027 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
4028 DeleteBrushFromCursor();
4030 if (gi == NULL || gi->info_text == NULL)
4033 strncpy(infotext, gi->info_text, MAX_INFOTEXT_LEN);
4034 infotext[MAX_INFOTEXT_LEN] = '\0';
4036 if (gi->custom_id < ED_NUM_CTRL_BUTTONS)
4038 int key = control_info[gi->custom_id].shortcut;
4042 sprintf(shortcut, " ('%s%c')",
4043 (key >= 'A' && key <= 'Z' ? "Shift-" :
4044 gi->custom_id == ED_CTRL_ID_SINGLE_ITEMS ? ".' or '" : ""),
4047 if (strlen(infotext) + strlen(shortcut) <= MAX_INFOTEXT_LEN)
4048 strcat(infotext, shortcut);
4052 DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW);
4055 static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
4057 static int start_lx, start_ly;
4059 int id = gi->custom_id;
4060 int sx = gi->event.x;
4061 int sy = gi->event.y;
4062 int lx = sx + level_xpos;
4063 int ly = sy + level_ypos;
4065 ClearEditorGadgetInfoText();
4067 if (id == ED_CTRL_ID_DRAWING_LEVEL)
4071 int min_sx = 0, min_sy = 0;
4072 int max_sx = gi->drawing.area_xsize - 1;
4073 int max_sy = gi->drawing.area_ysize - 1;
4074 int min_lx = 0, min_ly = 0;
4075 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
4077 /* make sure to stay inside drawing area boundaries */
4078 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
4079 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
4081 /* get positions inside level field */
4082 lx = sx + level_xpos;
4083 ly = sy + level_ypos;
4085 /* make sure to stay inside level field boundaries */
4086 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
4087 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
4089 /* correct drawing area positions accordingly */
4090 sx = lx - level_xpos;
4091 sy = ly - level_ypos;
4094 if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly))
4096 if (button_status) /* if (gi->state == GD_BUTTON_PRESSED) */
4098 if (gi->event.type == GD_EVENT_PRESSED)
4104 switch (drawing_function)
4106 case ED_CTRL_ID_SINGLE_ITEMS:
4107 infotext = "Drawing single items";
4109 case ED_CTRL_ID_CONNECTED_ITEMS:
4110 infotext = "Drawing connected items";
4112 case ED_CTRL_ID_LINE:
4113 infotext = "Drawing line";
4115 case ED_CTRL_ID_TEXT:
4116 infotext = "Setting text cursor";
4118 case ED_CTRL_ID_RECTANGLE:
4119 infotext = "Drawing rectangle";
4121 case ED_CTRL_ID_FILLED_BOX:
4122 infotext = "Drawing filled box";
4124 case ED_CTRL_ID_FLOOD_FILL:
4125 infotext = "Flood fill";
4127 case ED_CTRL_ID_GRAB_BRUSH:
4128 infotext = "Grabbing brush";
4130 case ED_CTRL_ID_PICK_ELEMENT:
4131 infotext = "Picking element";
4135 infotext = "Drawing position";
4139 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4140 "%s: %d, %d", infotext,
4141 ABS(lx - start_lx) + 1,
4142 ABS(ly - start_ly) + 1);
4145 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4146 "Level position: %d, %d", lx, ly);
4149 /* misuse this function to draw brush cursor, if needed */
4150 if (edit_mode == ED_MODE_DRAWING && draw_with_brush && !button_status)
4152 if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly))
4153 CopyBrushToCursor(sx, sy);
4155 DeleteBrushFromCursor();
4158 else if (id == ED_CTRL_ID_AMOEBA_CONTENT)
4159 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4162 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4163 "Cruncher %d content: %d, %d",
4164 id - ED_CTRL_ID_ELEM_CONTENT_0 + 1, sx, sy);