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)
95 /* standard distances */
96 #define ED_BORDER_SIZE 3
97 #define ED_GADGET_DISTANCE 2
99 /* values for element content drawing areas */
100 #define ED_AREA_ELEM_CONTENT_XPOS (TILEX)
101 #define ED_AREA_ELEM_CONTENT_YPOS (10 * TILEY)
103 /* values for scrolling gadgets */
104 #define ED_SCROLLBUTTON_XPOS 24
105 #define ED_SCROLLBUTTON_YPOS 0
106 #define ED_SCROLLBAR_XPOS 24
107 #define ED_SCROLLBAR_YPOS 64
109 #define ED_SCROLLBUTTON_XSIZE 16
110 #define ED_SCROLLBUTTON_YSIZE 16
112 #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
113 #define ED_SCROLL_UP_YPOS (0)
114 #define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
115 #define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE)
116 #define ED_SCROLL_LEFT_XPOS (0)
117 #define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
118 #define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
119 #define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
120 #define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
121 #define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
122 #define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
123 #define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
124 #define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
125 #define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
126 #define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
127 #define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
129 /* control button identifiers */
130 #define ED_CTRL_ID_NONE -1
132 #define ED_CTRL_ID_SINGLE_ITEMS 0
133 #define ED_CTRL_ID_CONNECTED_ITEMS 1
134 #define ED_CTRL_ID_LINE 2
135 #define ED_CTRL_ID_TEXT 3
136 #define ED_CTRL_ID_RECTANGLE 4
137 #define ED_CTRL_ID_FILLED_BOX 5
138 #define ED_CTRL_ID_WRAP_UP 6
139 #define ED_CTRL_ID_PROPERTIES 7
140 #define ED_CTRL_ID_FLOOD_FILL 8
141 #define ED_CTRL_ID_WRAP_LEFT 9
142 #define ED_CTRL_ID_UNUSED1 10
143 #define ED_CTRL_ID_WRAP_RIGHT 11
144 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
145 #define ED_CTRL_ID_GRAB_BRUSH 13
146 #define ED_CTRL_ID_WRAP_DOWN 14
147 #define ED_CTRL_ID_PICK_ELEMENT 15
148 #define ED_CTRL_ID_UNDO 16
149 #define ED_CTRL_ID_INFO 17
150 #define ED_CTRL_ID_SAVE 18
151 #define ED_CTRL_ID_CLEAR 19
152 #define ED_CTRL_ID_TEST 20
153 #define ED_CTRL_ID_EXIT 21
155 /* counter button identifiers */
156 #define ED_CTRL_ID_ELEM_SCORE_DOWN 22
157 #define ED_CTRL_ID_ELEM_SCORE_TEXT 23
158 #define ED_CTRL_ID_ELEM_SCORE_UP 24
159 #define ED_CTRL_ID_ELEM_CONTENT_DOWN 25
160 #define ED_CTRL_ID_ELEM_CONTENT_TEXT 26
161 #define ED_CTRL_ID_ELEM_CONTENT_UP 27
162 #define ED_CTRL_ID_LEVEL_XSIZE_DOWN 28
163 #define ED_CTRL_ID_LEVEL_XSIZE_TEXT 29
164 #define ED_CTRL_ID_LEVEL_XSIZE_UP 30
165 #define ED_CTRL_ID_LEVEL_YSIZE_DOWN 31
166 #define ED_CTRL_ID_LEVEL_YSIZE_TEXT 32
167 #define ED_CTRL_ID_LEVEL_YSIZE_UP 33
168 #define ED_CTRL_ID_LEVEL_COLLECT_DOWN 34
169 #define ED_CTRL_ID_LEVEL_COLLECT_TEXT 35
170 #define ED_CTRL_ID_LEVEL_COLLECT_UP 36
171 #define ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN 37
172 #define ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT 38
173 #define ED_CTRL_ID_LEVEL_TIMELIMIT_UP 39
174 #define ED_CTRL_ID_LEVEL_TIMESCORE_DOWN 40
175 #define ED_CTRL_ID_LEVEL_TIMESCORE_TEXT 41
176 #define ED_CTRL_ID_LEVEL_TIMESCORE_UP 42
178 /* drawing area identifiers */
179 #define ED_CTRL_ID_DRAWING_LEVEL 43
180 #define ED_CTRL_ID_ELEM_CONTENT_0 44
181 #define ED_CTRL_ID_ELEM_CONTENT_1 45
182 #define ED_CTRL_ID_ELEM_CONTENT_2 46
183 #define ED_CTRL_ID_ELEM_CONTENT_3 47
184 #define ED_CTRL_ID_ELEM_CONTENT_4 48
185 #define ED_CTRL_ID_ELEM_CONTENT_5 49
186 #define ED_CTRL_ID_ELEM_CONTENT_6 50
187 #define ED_CTRL_ID_ELEM_CONTENT_7 51
188 #define ED_CTRL_ID_AMOEBA_CONTENT 52
190 /* text input identifiers */
191 #define ED_CTRL_ID_LEVEL_NAME 53
193 /* gadgets for scrolling of drawing area */
194 #define ED_CTRL_ID_SCROLL_UP 54
195 #define ED_CTRL_ID_SCROLL_DOWN 55
196 #define ED_CTRL_ID_SCROLL_LEFT 56
197 #define ED_CTRL_ID_SCROLL_RIGHT 57
198 #define ED_CTRL_ID_SCROLL_VERTICAL 58
199 #define ED_CTRL_ID_SCROLL_HORIZONTAL 59
201 #define ED_NUM_GADGETS 60
203 /* values for counter gadgets */
204 #define ED_COUNTER_ID_ELEM_SCORE 0
205 #define ED_COUNTER_ID_ELEM_CONTENT 1
206 #define ED_COUNTER_ID_LEVEL_XSIZE 2
207 #define ED_COUNTER_ID_LEVEL_YSIZE 3
208 #define ED_COUNTER_ID_LEVEL_COLLECT 4
209 #define ED_COUNTER_ID_LEVEL_TIMELIMIT 5
210 #define ED_COUNTER_ID_LEVEL_TIMESCORE 6
212 /* values for text input gadgets */
213 #define ED_TEXTINPUT_ID_LEVEL_NAME 0
215 #define ED_NUM_COUNTERBUTTONS 7
216 #define ED_NUM_SCROLLBUTTONS 4
217 #define ED_NUM_SCROLLBARS 2
218 #define ED_NUM_TEXTINPUT 1
220 /* values for CopyLevelToUndoBuffer() */
221 #define UNDO_IMMEDIATE 0
222 #define UNDO_ACCUMULATE 1
224 /* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
225 #define INFOTEXT_XPOS SX
226 #define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
227 #define INFOTEXT_XSIZE SXSIZE
228 #define INFOTEXT_YSIZE MINI_TILEX
229 #define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
235 } control_info[ED_NUM_CTRL_BUTTONS] =
237 { 's', "draw single items" },
238 { 'd', "draw connected items" },
239 { 'l', "draw lines" },
240 { 't', "enter text elements" },
241 { 'r', "draw outline rectangles" },
242 { 'R', "draw filled rectangles" },
243 { '\0', "wrap (rotate) level up" },
244 { '?', "properties of drawing element" },
245 { 'f', "flood fill" },
246 { '\0', "wrap (rotate) level left" },
248 { '\0', "wrap (rotate) level right" },
249 { '\0', "random element placement" },
250 { 'b', "grab brush" },
251 { '\0', "wrap (rotate) level down" },
252 { ',', "pick drawing element" },
253 { 'U', "undo last operation" },
254 { 'I', "level properties" },
255 { 'S', "save level" },
256 { 'C', "clear level" },
257 { 'T', "test level" },
258 { 'E', "exit level editor" }
261 /* pointers to counter values */
262 static int *gadget_elem_score_value = NULL;
263 static int *gadget_elem_content_value = NULL;
264 static int *gadget_level_xsize_value = NULL;
265 static int *gadget_level_ysize_value = NULL;
266 static int *gadget_level_collect_value = NULL;
267 static int *gadget_level_timelimit_value = NULL;
268 static int *gadget_level_timescore_value = NULL;
273 int min_value, max_value;
274 int gadget_id_down, gadget_id_up;
278 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
281 ED_COUNT_ELEM_SCORE_XPOS, ED_COUNT_ELEM_SCORE_YPOS,
282 MIN_SCORE, MAX_SCORE,
283 ED_CTRL_ID_ELEM_SCORE_DOWN, ED_CTRL_ID_ELEM_SCORE_UP,
284 ED_CTRL_ID_ELEM_SCORE_TEXT,
285 &gadget_elem_score_value,
289 ED_COUNT_ELEM_CONTENT_XPOS, ED_COUNT_ELEM_CONTENT_YPOS,
290 MIN_ELEM_CONTENT, MAX_ELEM_CONTENT,
291 ED_CTRL_ID_ELEM_CONTENT_DOWN, ED_CTRL_ID_ELEM_CONTENT_UP,
292 ED_CTRL_ID_ELEM_CONTENT_TEXT,
293 &gadget_elem_content_value,
297 ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS + 6 * MINI_TILEY,
298 MIN_LEV_FIELDX, MAX_LEV_FIELDX,
299 ED_CTRL_ID_LEVEL_XSIZE_DOWN, ED_CTRL_ID_LEVEL_XSIZE_UP,
300 ED_CTRL_ID_LEVEL_XSIZE_TEXT,
301 &gadget_level_xsize_value,
305 ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS + 10 * MINI_TILEY,
306 MIN_LEV_FIELDY, MAX_LEV_FIELDY,
307 ED_CTRL_ID_LEVEL_YSIZE_DOWN, ED_CTRL_ID_LEVEL_YSIZE_UP,
308 ED_CTRL_ID_LEVEL_YSIZE_TEXT,
309 &gadget_level_ysize_value,
313 ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS + 14 * MINI_TILEY,
315 ED_CTRL_ID_LEVEL_COLLECT_DOWN, ED_CTRL_ID_LEVEL_COLLECT_UP,
316 ED_CTRL_ID_LEVEL_COLLECT_TEXT,
317 &gadget_level_collect_value,
318 "number of emeralds to collect"
321 ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS + 18 * MINI_TILEY,
323 ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN, ED_CTRL_ID_LEVEL_TIMELIMIT_UP,
324 ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT,
325 &gadget_level_timelimit_value,
326 "time available to solve level"
329 ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS + 22 * MINI_TILEY,
331 ED_CTRL_ID_LEVEL_TIMESCORE_DOWN, ED_CTRL_ID_LEVEL_TIMESCORE_UP,
332 ED_CTRL_ID_LEVEL_TIMESCORE_TEXT,
333 &gadget_level_timescore_value,
334 "score for each 10 seconds left"
344 } textinput_info[ED_NUM_TEXTINPUT] =
347 ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS + 26 * MINI_TILEY,
348 ED_CTRL_ID_LEVEL_NAME,
360 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
363 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
364 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
365 "scroll level editing area up"
368 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
369 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
370 "scroll level editing area down"
373 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
374 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
375 "scroll level editing area left"
378 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
379 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
380 "scroll level editing area right"
392 } scrollbar_info[ED_NUM_SCROLLBARS] =
395 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
396 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
397 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
398 GD_TYPE_SCROLLBAR_VERTICAL,
399 ED_CTRL_ID_SCROLL_VERTICAL,
400 "scroll level editing area vertically"
403 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
404 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
405 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
406 GD_TYPE_SCROLLBAR_HORIZONTAL,
407 ED_CTRL_ID_SCROLL_HORIZONTAL,
408 "scroll level editing area horizontally"
412 /* forward declaration for internal use */
413 static void DrawDrawingWindow();
414 static void DrawLevelInfoWindow();
415 static void DrawPropertiesWindow();
416 static void CopyLevelToUndoBuffer(int);
417 static void HandleControlButtons(struct GadgetInfo *);
418 static void HandleCounterButtons(struct GadgetInfo *);
419 static void HandleDrawingAreas(struct GadgetInfo *);
420 static void HandleDrawingAreaInfo(struct GadgetInfo *);
421 static void HandleTextInputGadgets(struct GadgetInfo *);
423 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
424 static boolean level_editor_gadgets_created = FALSE;
426 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
427 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
428 static boolean draw_with_brush = FALSE;
429 static int properties_element = 0;
431 static short ElementContent[MAX_ELEM_CONTENT][3][3];
432 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
433 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
434 static int undo_buffer_position = 0;
435 static int undo_buffer_steps = 0;
437 static int random_placement_percentage = 10;
438 static int random_placement_num_objects = 10;
440 static int random_placement_method = RANDOM_USE_PERCENTAGE;
442 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
445 static int level_xpos, level_ypos;
446 static int edit_mode;
447 static boolean name_typing;
448 static int new_element1 = EL_MAUERWERK;
449 static int new_element2 = EL_LEERRAUM;
450 static int new_element3 = EL_ERDREICH;
452 static int counter_xsize = DXSIZE + 20;
454 int element_shift = 0;
456 int editor_element[] =
458 EL_CHAR_A + ('B' - 'A'),
459 EL_CHAR_A + ('O' - 'A'),
460 EL_CHAR_A + ('U' - 'A'),
461 EL_CHAR_A + ('L' - 'A'),
464 EL_CHAR_A + ('D' - 'A'),
465 EL_CHAR_A + ('E' - 'A'),
466 EL_CHAR_A + ('R' - 'A'),
468 EL_CHAR_A + ('D' - 'A'),
469 EL_CHAR_A + ('A' - 'A'),
470 EL_CHAR_A + ('S' - 'A'),
471 EL_CHAR_A + ('H' - 'A'),
498 EL_CHAR_A + ('E' - 'A'),
499 EL_CHAR_A + ('M' - 'A'),
500 EL_CHAR_A + ('E' - 'A'),
503 EL_CHAR_A + ('R' - 'A'),
504 EL_CHAR_A + ('A' - 'A'),
505 EL_CHAR_A + ('L' - 'A'),
506 EL_CHAR_A + ('D' - 'A'),
508 EL_CHAR_A + ('M' - 'A'),
509 EL_CHAR_A + ('I' - 'A'),
510 EL_CHAR_A + ('N' - 'A'),
511 EL_CHAR_A + ('E' - 'A'),
588 EL_CHAR_A + ('M' - 'A'),
589 EL_CHAR_A + ('O' - 'A'),
590 EL_CHAR_A + ('R' - 'A'),
591 EL_CHAR_A + ('E' - 'A'),
643 EL_CHAR_A + ('S' - 'A'),
644 EL_CHAR_A + ('O' - 'A'),
645 EL_CHAR_A + ('K' - 'A'),
646 EL_CHAR_A + ('O' - 'A'),
649 EL_CHAR_A + ('B' - 'A'),
650 EL_CHAR_A + ('A' - 'A'),
651 EL_CHAR_A + ('N' - 'A'),
654 EL_SOKOBAN_FELD_LEER,
655 EL_SOKOBAN_FELD_VOLL,
724 EL_CHAR_A + ('D' - 'A'),
725 EL_CHAR_A + ('Y' - 'A'),
726 EL_CHAR_A + ('N' - 'A'),
727 EL_CHAR_A + ('A' - 'A'),
729 EL_CHAR_A + ('B' - 'A'),
730 EL_CHAR_A + ('L' - 'A'),
731 EL_CHAR_A + ('A' - 'A'),
732 EL_CHAR_A + ('S' - 'A'),
735 EL_CHAR_A + ('T' - 'A'),
736 EL_CHAR_A + ('E' - 'A'),
737 EL_CHAR_A + ('R' - 'A'),
820 int elements_in_list = sizeof(editor_element)/sizeof(int);
822 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
825 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
826 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
828 XCopyArea(display, drawto, drawto, gc,
829 SX + (dx == -1 ? MINI_TILEX : 0),
830 SY + (dy == -1 ? MINI_TILEY : 0),
831 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
832 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
833 SX + (dx == +1 ? MINI_TILEX : 0),
834 SY + (dy == +1 ? MINI_TILEY : 0));
837 x = (dx == 1 ? 0 : ED_FIELDX - 1);
838 for(y=0; y<ED_FIELDY; y++)
839 DrawMiniElementOrWall(x, y, from_x, from_y);
843 y = (dy == 1 ? 0 : ED_FIELDY - 1);
844 for(x=0; x<ED_FIELDX; x++)
845 DrawMiniElementOrWall(x, y, from_x, from_y);
848 redraw_mask |= REDRAW_FIELD;
852 void InitLevelEditorGadgets()
856 for (i=0; i<ED_NUM_GADGETS; i++)
857 level_editor_gadget[i] = NULL;
860 static void CreateControlButtons()
862 Pixmap gd_pixmap = pix[PIX_DOOR];
863 struct GadgetInfo *gi;
864 unsigned long event_mask;
867 /* create toolbox buttons */
868 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
872 int gd_xoffset, gd_yoffset;
873 int gd_x1, gd_x2, gd_y1, gd_y2;
876 boolean radio_button_pressed;
878 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
879 id == ED_CTRL_ID_CONNECTED_ITEMS ||
880 id == ED_CTRL_ID_LINE ||
881 id == ED_CTRL_ID_TEXT ||
882 id == ED_CTRL_ID_RECTANGLE ||
883 id == ED_CTRL_ID_FILLED_BOX ||
884 id == ED_CTRL_ID_FLOOD_FILL ||
885 id == ED_CTRL_ID_GRAB_BRUSH ||
886 id == ED_CTRL_ID_PICK_ELEMENT)
888 button_type = GD_TYPE_RADIO_BUTTON;
890 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
891 event_mask = GD_EVENT_PRESSED;
895 button_type = GD_TYPE_NORMAL_BUTTON;
897 radio_button_pressed = FALSE;
899 if (id == ED_CTRL_ID_WRAP_LEFT ||
900 id == ED_CTRL_ID_WRAP_RIGHT ||
901 id == ED_CTRL_ID_WRAP_UP ||
902 id == ED_CTRL_ID_WRAP_DOWN)
903 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
905 event_mask = GD_EVENT_RELEASED;
908 if (id < ED_NUM_CTRL1_BUTTONS)
910 int x = i % ED_CTRL1_BUTTONS_HORIZ;
911 int y = i / ED_CTRL1_BUTTONS_HORIZ;
913 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
914 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
915 width = ED_CTRL1_BUTTON_XSIZE;
916 height = ED_CTRL1_BUTTON_YSIZE;
920 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
921 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
923 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
924 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
925 width = ED_CTRL2_BUTTON_XSIZE;
926 height = ED_CTRL2_BUTTON_YSIZE;
929 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
930 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
931 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
932 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
934 gi = CreateGadget(GDI_CUSTOM_ID, id,
935 GDI_INFO_TEXT, control_info[i].text,
936 GDI_X, EX + gd_xoffset,
937 GDI_Y, EY + gd_yoffset,
940 GDI_TYPE, button_type,
941 GDI_STATE, GD_BUTTON_UNPRESSED,
942 GDI_RADIO_NR, radio_button_nr,
943 GDI_RADIO_PRESSED, radio_button_pressed,
944 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
945 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
946 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
947 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
948 GDI_EVENT_MASK, event_mask,
949 GDI_CALLBACK_ACTION, HandleControlButtons,
953 Error(ERR_EXIT, "cannot create gadget");
955 level_editor_gadget[id] = gi;
958 /* create buttons for scrolling of drawing area */
959 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
961 int id = scrollbutton_info[i].gadget_id;
962 int gd_x1, gd_x2, gd_y;
964 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
966 gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
967 gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
968 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
970 gi = CreateGadget(GDI_CUSTOM_ID, id,
971 GDI_INFO_TEXT, scrollbutton_info[i].infotext,
972 GDI_X, SX + scrollbutton_info[i].x,
973 GDI_Y, SY + scrollbutton_info[i].y,
974 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
975 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
976 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
977 GDI_STATE, GD_BUTTON_UNPRESSED,
978 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
979 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
980 GDI_EVENT_MASK, event_mask,
981 GDI_CALLBACK_ACTION, HandleControlButtons,
985 Error(ERR_EXIT, "cannot create gadget");
987 level_editor_gadget[id] = gi;
991 static void CreateCounterButtons()
995 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
998 int xpos = SX + counterbutton_info[i].x; /* xpos of down count button */
999 int ypos = SY + counterbutton_info[i].y;
1003 Pixmap gd_pixmap = pix[PIX_DOOR];
1004 struct GadgetInfo *gi;
1006 counterbutton_info[i].gadget_id_down :
1007 counterbutton_info[i].gadget_id_up);
1009 int gd_x, gd_x1, gd_x2, gd_y;
1010 unsigned long event_mask;
1011 char infotext[MAX_INFOTEXT_LEN + 1];
1013 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
1015 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
1016 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
1017 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
1018 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
1020 sprintf(infotext, "%s counter value by 1, 5 or 10",
1021 (j == 0 ? "decrease" : "increase"));
1023 gi = CreateGadget(GDI_CUSTOM_ID, id,
1024 GDI_INFO_TEXT, infotext,
1027 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
1028 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
1029 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
1030 GDI_STATE, GD_BUTTON_UNPRESSED,
1031 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
1032 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
1033 GDI_EVENT_MASK, event_mask,
1034 GDI_CALLBACK_ACTION, HandleCounterButtons,
1038 Error(ERR_EXIT, "cannot create gadget");
1040 level_editor_gadget[id] = gi;
1041 xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of text count button */
1045 id = counterbutton_info[i].gadget_id_text;
1046 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
1048 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
1049 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
1051 gi = CreateGadget(GDI_CUSTOM_ID, id,
1052 GDI_INFO_TEXT, "enter counter value",
1055 GDI_TYPE, GD_TYPE_TEXTINPUT_NUMERIC,
1056 GDI_NUMBER_VALUE, 0,
1057 GDI_NUMBER_MIN, counterbutton_info[i].min_value,
1058 GDI_NUMBER_MAX, counterbutton_info[i].max_value,
1060 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
1061 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
1062 GDI_DESIGN_BORDER, ED_BORDER_SIZE,
1063 GDI_EVENT_MASK, event_mask,
1064 GDI_CALLBACK_ACTION, HandleCounterButtons,
1068 Error(ERR_EXIT, "cannot create gadget");
1070 level_editor_gadget[id] = gi;
1071 xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of up count button */
1077 static void CreateDrawingAreas()
1079 struct GadgetInfo *gi;
1080 unsigned long event_mask;
1085 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
1086 GD_EVENT_OFF_BORDERS;
1088 /* one for the level drawing area ... */
1089 id = ED_CTRL_ID_DRAWING_LEVEL;
1090 gi = CreateGadget(GDI_CUSTOM_ID, id,
1093 GDI_TYPE, GD_TYPE_DRAWING_AREA,
1094 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
1095 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
1096 GDI_EVENT_MASK, event_mask,
1097 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
1098 GDI_CALLBACK_ACTION, HandleDrawingAreas,
1102 Error(ERR_EXIT, "cannot create gadget");
1104 level_editor_gadget[id] = gi;
1106 /* ... up to eight areas for element content ... */
1107 for (i=0; i<MAX_ELEM_CONTENT; i++)
1109 int gx = SX + ED_AREA_ELEM_CONTENT_XPOS + 5 * (i % 4) * MINI_TILEX;
1110 int gy = SX + ED_AREA_ELEM_CONTENT_YPOS + 6 * (i / 4) * MINI_TILEY;
1112 id = ED_CTRL_ID_ELEM_CONTENT_0 + i;
1113 gi = CreateGadget(GDI_CUSTOM_ID, id,
1116 GDI_WIDTH, 3 * MINI_TILEX,
1117 GDI_HEIGHT, 3 * MINI_TILEY,
1118 GDI_TYPE, GD_TYPE_DRAWING_AREA,
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;
1131 /* ... and one for the amoeba content */
1132 id = ED_CTRL_ID_AMOEBA_CONTENT;
1133 gi = CreateGadget(GDI_CUSTOM_ID, id,
1134 GDI_X, SX + ED_AREA_ELEM_CONTENT_XPOS,
1135 GDI_Y, SY + ED_AREA_ELEM_CONTENT_YPOS,
1136 GDI_WIDTH, MINI_TILEX,
1137 GDI_HEIGHT, MINI_TILEY,
1138 GDI_TYPE, GD_TYPE_DRAWING_AREA,
1139 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
1140 GDI_EVENT_MASK, event_mask,
1141 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
1142 GDI_CALLBACK_ACTION, HandleDrawingAreas,
1146 Error(ERR_EXIT, "cannot create gadget");
1148 level_editor_gadget[id] = gi;
1151 static void CreateTextInputGadgets()
1153 Pixmap gd_pixmap = pix[PIX_DOOR];
1155 struct GadgetInfo *gi;
1156 unsigned long event_mask;
1157 char infotext[MAX_INFOTEXT_LEN + 1];
1160 /* text input gadget for the level name */
1161 i = ED_TEXTINPUT_ID_LEVEL_NAME;
1162 id = ED_CTRL_ID_LEVEL_NAME;
1164 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
1166 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
1167 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
1169 sprintf(infotext, "Enter %s", textinput_info[i].infotext);
1171 gi = CreateGadget(GDI_CUSTOM_ID, id,
1172 GDI_INFO_TEXT, infotext,
1173 GDI_X, SX + textinput_info[i].x,
1174 GDI_Y, SY + textinput_info[i].y,
1175 GDI_TYPE, GD_TYPE_TEXTINPUT_ALPHANUMERIC,
1176 GDI_TEXT_VALUE, textinput_info[i].value,
1178 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
1179 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
1180 GDI_DESIGN_BORDER, ED_BORDER_SIZE,
1181 GDI_EVENT_MASK, event_mask,
1182 GDI_CALLBACK_ACTION, HandleTextInputGadgets,
1186 Error(ERR_EXIT, "cannot create gadget");
1188 level_editor_gadget[id] = gi;
1191 static void CreateScrollbarGadgets()
1195 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1197 int id = scrollbar_info[i].gadget_id;
1198 Pixmap gd_pixmap = pix[PIX_DOOR];
1199 int gd_x1, gd_x2, gd_y1, gd_y2;
1200 struct GadgetInfo *gi;
1201 int items_max, items_visible, item_position;
1202 unsigned long event_mask;
1204 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
1206 items_max = MAX(lev_fieldx + 2, ED_FIELDX);
1207 items_visible = ED_FIELDX;
1212 items_max = MAX(lev_fieldy + 2, ED_FIELDY);
1213 items_visible = ED_FIELDY;
1217 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
1219 gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
1220 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
1221 gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1222 gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1224 gi = CreateGadget(GDI_CUSTOM_ID, id,
1225 GDI_INFO_TEXT, scrollbar_info[i].text,
1226 GDI_X, SX + scrollbar_info[i].x,
1227 GDI_Y, SY + scrollbar_info[i].y,
1228 GDI_WIDTH, scrollbar_info[i].width,
1229 GDI_HEIGHT, scrollbar_info[i].height,
1230 GDI_TYPE, scrollbar_info[i].type,
1231 GDI_SCROLLBAR_ITEMS_MAX, items_max,
1232 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
1233 GDI_SCROLLBAR_ITEM_POSITION, item_position,
1234 GDI_STATE, GD_BUTTON_UNPRESSED,
1235 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
1236 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
1237 GDI_DESIGN_BORDER, ED_BORDER_SIZE,
1238 GDI_EVENT_MASK, event_mask,
1239 GDI_CALLBACK_ACTION, HandleControlButtons,
1243 Error(ERR_EXIT, "cannot create gadget");
1245 level_editor_gadget[id] = gi;
1249 static void CreateLevelEditorGadgets()
1251 if (level_editor_gadgets_created)
1254 CreateControlButtons();
1255 CreateCounterButtons();
1256 CreateDrawingAreas();
1257 CreateTextInputGadgets();
1258 CreateScrollbarGadgets();
1260 level_editor_gadgets_created = TRUE;
1263 static void MapControlButtons()
1267 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1268 MapGadget(level_editor_gadget[i]);
1271 static void MapCounterButtons(int cnt_id)
1273 MapGadget(level_editor_gadget[counterbutton_info[cnt_id].gadget_id_down]);
1274 MapGadget(level_editor_gadget[counterbutton_info[cnt_id].gadget_id_text]);
1275 MapGadget(level_editor_gadget[counterbutton_info[cnt_id].gadget_id_up]);
1278 static void MapDrawingArea(int id)
1280 MapGadget(level_editor_gadget[id]);
1283 static void MapTextInputGadget(int id)
1285 MapGadget(level_editor_gadget[id]);
1288 static void MapMainDrawingArea()
1292 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1293 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1295 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1296 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1298 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1301 static void UnmapDrawingArea(int id)
1303 UnmapGadget(level_editor_gadget[id]);
1306 void UnmapLevelEditorWindowGadgets()
1310 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1311 UnmapGadget(level_editor_gadget[i]);
1314 void UnmapLevelEditorGadgets()
1318 for (i=0; i<ED_NUM_GADGETS; i++)
1319 UnmapGadget(level_editor_gadget[i]);
1324 int i, x, y, graphic;
1326 edit_mode = ED_MODE_DRAWING;
1327 name_typing = FALSE;
1329 CloseDoor(DOOR_CLOSE_ALL);
1331 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1333 if (level_editor_test_game)
1335 for(x=0; x<lev_fieldx; x++)
1336 for(y=0; y<lev_fieldy; y++)
1337 Feld[x][y] = Ur[x][y];
1339 for(x=0; x<lev_fieldx; x++)
1340 for(y=0; y<lev_fieldy; y++)
1341 Ur[x][y] = FieldBackup[x][y];
1343 level_editor_test_game = FALSE;
1349 undo_buffer_position = -1;
1350 undo_buffer_steps = -1;
1351 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1355 DrawMiniLevel(level_xpos, level_ypos);
1359 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1360 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1362 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1363 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1364 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1365 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1366 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1367 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1368 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1370 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1372 if (i < elements_in_list)
1373 graphic = el2gfx(editor_element[i + element_shift]);
1375 graphic = GFX_LEERRAUM;
1377 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1378 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1379 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1380 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1381 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1385 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1386 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1387 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1388 el2gfx(new_element1));
1389 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1390 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1391 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1392 el2gfx(new_element2));
1393 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1394 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1395 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1396 el2gfx(new_element3));
1397 DrawTextExt(pix[PIX_DB_DOOR],gc,
1398 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1399 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1400 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1401 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1402 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1403 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1405 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1406 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1407 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1408 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1409 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1411 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1412 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1414 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1415 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1417 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1419 /* draw bigger door */
1420 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1425 /* draw new control window */
1426 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1427 DOOR_GFX_PAGEX8, 236,
1431 redraw_mask |= REDRAW_ALL;
1433 OpenDoor(DOOR_OPEN_1);
1435 if (!level_editor_gadgets_created)
1436 CreateLevelEditorGadgets();
1438 strcpy(level_editor_gadget[ED_CTRL_ID_LEVEL_NAME]->text.value, level.name);
1440 MapControlButtons();
1443 MapMainDrawingArea();
1446 DrawDrawingWindow();
1450 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1454 void DrawControlWindow()
1459 UnmapLevelEditorWindowGadgets();
1461 /* Inhalt der Mampfer */
1462 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1463 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1464 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1466 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1467 XFillRectangle(display,drawto,gc,
1468 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1469 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1470 3*MINI_TILEX+2,3*MINI_TILEY+2);
1472 XCopyArea(display,drawto,drawto,gc,
1473 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1474 4*5*MINI_TILEX,5*MINI_TILEY,
1475 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1478 for(y=0;y<3;y++) for(x=0;x<3;x++)
1479 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1481 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1482 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1483 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1486 /* Inhalt der Amöbe */
1487 for(y=0;y<2;y++) for(x=0;x<2;x++)
1489 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1490 XFillRectangle(display,drawto,gc,
1491 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1492 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1493 MINI_TILEX+2,MINI_TILEY+2);
1495 XCopyArea(display,drawto,drawto,gc,
1496 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1497 3*MINI_TILEX,3*MINI_TILEY,
1498 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1499 DrawMiniElement(29,26,level.amoebe_inhalt);
1501 for(i=0;i<11+3+2;i++)
1503 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1504 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1505 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1506 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1507 ED_COUNT_GADGET_XPOS,
1508 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1511 DrawText(ED_COUNT_VALUE_XPOS,
1512 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1513 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1515 DrawText(ED_COUNT_VALUE_XPOS,
1516 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1517 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1519 DrawText(ED_COUNT_VALUE_XPOS,
1520 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1521 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1523 DrawText(ED_COUNT_VALUE_XPOS,
1524 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1525 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1527 DrawText(ED_COUNT_VALUE_XPOS,
1528 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1529 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1531 DrawText(ED_COUNT_VALUE_XPOS,
1532 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1533 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1536 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1537 "Score for Emerald",FS_SMALL,FC_YELLOW);
1538 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1539 "Score for Diamond",FS_SMALL,FC_YELLOW);
1540 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1541 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1542 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1543 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1544 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1545 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1546 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1547 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1548 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1549 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1550 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1551 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1552 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1553 "Score for dynamite",FS_SMALL,FC_YELLOW);
1554 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1555 "Score for key",FS_SMALL,FC_YELLOW);
1556 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1557 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1558 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1559 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1560 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1561 "Time for magic wall",FS_SMALL,FC_YELLOW);
1562 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1563 "Time for wheel",FS_SMALL,FC_YELLOW);
1564 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1565 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1566 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1567 "Time available for this level",FS_SMALL,FC_YELLOW);
1569 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1570 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1571 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1572 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1573 ED_COUNT_GADGET_XPOS,
1574 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1576 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1577 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1578 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1579 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1580 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1581 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1582 DrawText(ED_COUNT_GADGET_XPOS+5,
1583 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1584 level.name,FS_SMALL,FC_YELLOW);
1585 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1586 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1587 "Title",FS_SMALL,FC_YELLOW);
1589 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1590 "Playfield size:",FS_SMALL,FC_YELLOW);
1591 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1592 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1593 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1594 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1595 ED_SIZE_GADGET_XPOS,
1596 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1597 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1598 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1599 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1600 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1601 ED_SIZE_GADGET_XPOS,
1602 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1603 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1604 "Width",FS_SMALL,FC_YELLOW);
1605 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1606 "Height",FS_SMALL,FC_YELLOW);
1607 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1608 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1609 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1610 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1613 void AdjustLevelScrollPosition()
1615 if (level_xpos < -1)
1617 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1618 level_xpos = lev_fieldx - ED_FIELDX + 1;
1619 if (lev_fieldx < ED_FIELDX - 2)
1622 if (level_ypos < -1)
1624 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1625 level_ypos = lev_fieldy - ED_FIELDY + 1;
1626 if (lev_fieldy < ED_FIELDY - 2)
1630 void AdjustEditorScrollbar(int id)
1632 struct GadgetInfo *gi = level_editor_gadget[id];
1633 int items_max, items_visible, item_position;
1635 if (id == ED_CTRL_ID_SCROLL_HORIZONTAL)
1637 items_max = MAX(lev_fieldx + 2, ED_FIELDX);
1638 items_visible = ED_FIELDX;
1639 item_position = level_xpos + 1;
1643 items_max = MAX(lev_fieldy + 2, ED_FIELDY);
1644 items_visible = ED_FIELDY;
1645 item_position = level_ypos + 1;
1648 if (item_position > items_max - items_visible)
1649 item_position = items_max - items_visible;
1651 AdjustScrollbar(gi, items_max, item_position);
1654 void ModifyEditorTextInput(int gadget_id, char *new_text)
1656 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
1658 ModifyTextInputTextValue(gi, new_text);
1661 void ModifyEditorCounter(int counter_id, int new_value)
1663 int *counter_value = *counterbutton_info[counter_id].counter_value;
1664 int gadget_id = counterbutton_info[counter_id].gadget_id_text;
1665 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
1667 ModifyTextInputNumberValue(gi, new_value);
1669 if (counter_value != NULL)
1670 *counter_value = gi->text.number_value;
1673 static void PickDrawingElement(int button, int element)
1675 if (button < 1 || button > 3)
1680 new_element1 = element;
1681 DrawMiniGraphicExt(drawto, gc,
1682 DX + ED_WIN_MB_LEFT_XPOS,
1683 DY + ED_WIN_MB_LEFT_YPOS,
1684 el2gfx(new_element1));
1686 else if (button == 2)
1688 new_element2 = element;
1689 DrawMiniGraphicExt(drawto, gc,
1690 DX + ED_WIN_MB_MIDDLE_XPOS,
1691 DY + ED_WIN_MB_MIDDLE_YPOS,
1692 el2gfx(new_element2));
1696 new_element3 = element;
1697 DrawMiniGraphicExt(drawto, gc,
1698 DX + ED_WIN_MB_RIGHT_XPOS,
1699 DY + ED_WIN_MB_RIGHT_YPOS,
1700 el2gfx(new_element3));
1703 redraw_mask |= REDRAW_DOOR_1;
1706 void LevelEd(int mx, int my, int button)
1708 static int last_button = 0;
1711 static int in_field_pressed = FALSE;
1714 static boolean use_floodfill = FALSE;
1718 int x = (mx-SX)/MINI_TILEX;
1719 int y = (my-SY)/MINI_TILEY;
1723 HandlePressedControlButtons();
1724 HandleDrawingFunctions(mx, my, button);
1727 if (use_floodfill) /********** FLOOD FILL **********/
1735 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1740 if (x>lev_fieldx || y>lev_fieldy ||
1741 (x==0 && level_xpos<0) ||
1742 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1743 (y==0 && level_ypos<0) ||
1744 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1747 from_x = x+level_xpos;
1748 from_y = y+level_ypos;
1749 fill_element = (button==1 ? new_element1 :
1750 button==2 ? new_element2 :
1751 button==3 ? new_element3 : 0);
1753 FloodFill(from_x,from_y,fill_element);
1754 DrawMiniLevel(level_xpos,level_ypos);
1757 use_floodfill = FALSE;
1758 CloseDoor(DOOR_CLOSE_1);
1759 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1768 else /********** EDIT/CTRL-FENSTER **********/
1770 static unsigned long choice_delay = 0;
1771 int choice = CheckElemButtons(mx,my,button);
1772 int elem_pos = choice-ED_BUTTON_ELEM;
1774 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1775 (choice == ED_BUTTON_EDOWN &&
1776 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1777 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1779 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1783 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1785 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1787 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1788 element_shift += step;
1791 if (element_shift<0)
1793 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1794 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1795 if (element_shift % MAX_ELEM_X)
1796 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1798 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1799 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1801 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1805 if (elem_pos+element_shift < elements_in_list)
1806 new_element = editor_element[elem_pos+element_shift];
1808 new_element = EL_LEERRAUM;
1810 PickDrawingElement(last_button, new_element);
1812 if (!HAS_CONTENT(properties_element))
1814 properties_element = new_element;
1815 if (edit_mode == ED_MODE_PROPERTIES)
1816 DrawPropertiesWindow();
1820 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1827 switch(CheckEditButtons(mx,my,button))
1829 case ED_BUTTON_CTRL:
1830 CloseDoor(DOOR_CLOSE_2);
1831 DrawControlWindow();
1832 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1833 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1835 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1836 OpenDoor(DOOR_OPEN_2);
1837 edit_mode = ED_MODE_INFO;
1839 case ED_BUTTON_FILL:
1840 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1841 use_floodfill = TRUE;
1844 case ED_BUTTON_LEFT:
1847 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1849 if (lev_fieldx<ED_FIELDX-2)
1852 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1856 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1858 DrawMiniLevel(level_xpos,level_ypos);
1861 case ED_BUTTON_RIGHT:
1862 if (level_xpos<=lev_fieldx-ED_FIELDX)
1864 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1866 if (lev_fieldx<ED_FIELDX-2)
1869 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1870 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1871 level_xpos = lev_fieldx-ED_FIELDX+1;
1873 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1875 DrawMiniLevel(level_xpos,level_ypos);
1881 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1883 if (lev_fieldy<ED_FIELDY-2)
1886 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1890 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1892 DrawMiniLevel(level_xpos,level_ypos);
1895 case ED_BUTTON_DOWN:
1896 if (level_ypos<=lev_fieldy-ED_FIELDY)
1898 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1900 if (lev_fieldy<ED_FIELDY-2)
1903 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1904 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1905 level_ypos = lev_fieldy-ED_FIELDY+1;
1907 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1909 DrawMiniLevel(level_xpos,level_ypos);
1922 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1926 if (button && !motion_status)
1927 in_field_pressed = TRUE;
1929 if (!button || !in_field_pressed || button<1 || button>3 ||
1930 (y==0 && level_ypos<0) ||
1931 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1932 (x==0 && level_xpos<0) ||
1933 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1934 x>lev_fieldx || y>lev_fieldy)
1937 new_element = (button==1 ? new_element1 :
1938 button==2 ? new_element2 :
1939 button==3 ? new_element3 : 0);
1941 if (new_element != Feld[x+level_xpos][y+level_ypos])
1943 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1947 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1949 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1951 Feld[x][y] = EL_LEERRAUM;
1952 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1953 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1954 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1959 Feld[x+level_xpos][y+level_ypos] = new_element;
1960 DrawMiniElement(x,y,new_element);
1963 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1964 in_field_pressed = FALSE;
1971 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1977 int choice = CheckCountButtons(mx,my,button);
1978 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1980 if (choice >= 0 && choice < 36 &&
1981 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1990 level.score[choice] += step;
1991 if (level.score[choice]<0)
1992 level.score[choice] = 0;
1993 else if (level.score[choice]>255)
1994 level.score[choice] = 255;
1996 else if (choice==11)
1998 level.tempo_amoebe += step;
1999 if (level.tempo_amoebe<0)
2000 level.tempo_amoebe = 0;
2001 else if (level.tempo_amoebe>255)
2002 level.tempo_amoebe = 255;
2004 else if (choice==12)
2006 level.dauer_sieb += step;
2007 if (level.dauer_sieb<0)
2008 level.dauer_sieb = 0;
2009 else if (level.dauer_sieb>255)
2010 level.dauer_sieb = 255;
2012 else if (choice==13)
2014 level.dauer_ablenk += step;
2015 if (level.dauer_ablenk<0)
2016 level.dauer_ablenk = 0;
2017 else if (level.dauer_ablenk>255)
2018 level.dauer_ablenk = 255;
2020 else if (choice==14)
2022 level.edelsteine += step;
2023 if (level.edelsteine<0)
2024 level.edelsteine = 0;
2025 else if (level.edelsteine>999)
2026 level.edelsteine = 999;
2028 else if (choice==15)
2033 else if (level.time>999)
2036 else if (choice==16)
2039 if (lev_fieldx<MIN_LEV_FIELDX)
2040 lev_fieldx = MIN_LEV_FIELDX;
2041 else if (lev_fieldx>MAX_LEV_FIELDX)
2042 lev_fieldx = MAX_LEV_FIELDX;
2043 level.fieldx = lev_fieldx;
2045 else if (choice==17)
2048 if (lev_fieldy<MIN_LEV_FIELDY)
2049 lev_fieldy = MIN_LEV_FIELDY;
2050 else if (lev_fieldy>MAX_LEV_FIELDY)
2051 lev_fieldy = MAX_LEV_FIELDY;
2052 level.fieldy = lev_fieldy;
2056 DrawText(ED_COUNT_VALUE_XPOS,
2057 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
2058 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
2059 else if (choice==11)
2060 DrawText(ED_COUNT_VALUE_XPOS,
2061 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
2062 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
2063 else if (choice==12)
2064 DrawText(ED_COUNT_VALUE_XPOS,
2065 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
2066 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
2067 else if (choice==13)
2068 DrawText(ED_COUNT_VALUE_XPOS,
2069 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
2070 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
2071 else if (choice==14)
2072 DrawText(ED_COUNT_VALUE_XPOS,
2073 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
2074 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
2075 else if (choice==15)
2076 DrawText(ED_COUNT_VALUE_XPOS,
2077 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
2078 int2str(level.time,3),FS_SMALL,FC_YELLOW);
2079 else if (choice==16)
2080 DrawText(ED_SIZE_VALUE_XPOS,
2081 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
2082 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
2083 else if (choice==17)
2084 DrawText(ED_SIZE_VALUE_XPOS,
2085 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
2086 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
2088 redraw_mask &= ~REDRAW_FIELD;
2090 XCopyArea(display,drawto,window,gc,
2091 ED_COUNT_VALUE_XPOS,
2092 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
2093 3*FONT2_XSIZE,FONT2_YSIZE,
2094 ED_COUNT_VALUE_XPOS,
2095 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
2097 XCopyArea(display,drawto,window,gc,
2099 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
2100 3*FONT2_XSIZE,FONT2_YSIZE,
2102 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
2106 switch(CheckCtrlButtons(mx,my,button))
2108 case ED_BUTTON_EDIT:
2109 CloseDoor(DOOR_CLOSE_2);
2110 AdjustLevelScrollPosition();
2111 DrawMiniLevel(level_xpos,level_ypos);
2112 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
2113 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
2115 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
2116 OpenDoor(DOOR_OPEN_2);
2117 edit_mode = ED_MODE_DRAWING;
2119 case ED_BUTTON_CLEAR:
2120 if (Request("Are you sure to clear this level ?",REQ_ASK))
2122 for(x=0;x<MAX_LEV_FIELDX;x++)
2123 for(y=0;y<MAX_LEV_FIELDY;y++)
2124 Feld[x][y] = EL_ERDREICH;
2125 DrawMiniLevel(level_xpos,level_ypos);
2128 case ED_BUTTON_UNDO:
2129 if (leveldir[leveldir_nr].readonly ||
2130 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
2132 CloseDoor(DOOR_CLOSE_ALL);
2133 game_status=MAINMENU;
2138 CloseDoor(DOOR_CLOSE_1);
2139 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2142 case ED_BUTTON_EXIT:
2144 int figur_vorhanden = FALSE;
2146 if (leveldir[leveldir_nr].readonly)
2148 Request("This level is read only !",REQ_CONFIRM);
2152 for(y=0;y<lev_fieldy;y++)
2153 for(x=0;x<lev_fieldx;x++)
2154 if (Feld[x][y] == EL_SPIELFIGUR ||
2155 Feld[x][y] == EL_SPIELER1 ||
2156 Feld[x][y] == EL_SP_MURPHY)
2157 figur_vorhanden = TRUE;
2159 if (!figur_vorhanden)
2160 Request("No Level without Gregor Mc Duffin please !",
2164 if (Request("Save this level and kill the old ?",
2165 REQ_ASK | REQ_STAY_OPEN))
2167 for(x=0;x<lev_fieldx;x++)
2168 for(y=0;y<lev_fieldy;y++)
2169 Ur[x][y]=Feld[x][y];
2170 SaveLevel(level_nr);
2172 CloseDoor(DOOR_CLOSE_ALL);
2173 game_status=MAINMENU;
2182 if (mx>=ED_COUNT_GADGET_XPOS &&
2183 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
2184 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
2185 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
2190 DrawText(ED_COUNT_GADGET_XPOS+5,
2191 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2192 level.name,FS_SMALL,FC_GREEN);
2193 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
2194 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2195 "<",FS_SMALL,FC_RED);
2202 name_typing = FALSE;
2203 DrawText(ED_COUNT_GADGET_XPOS+5,
2204 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2205 level.name,FS_SMALL,FC_YELLOW);
2206 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
2207 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2208 " ",FS_SMALL,FC_RED);
2212 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
2213 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
2217 if (!button || button<1 || button>3)
2220 new_element = (button==1 ? new_element1 :
2221 button==2 ? new_element2 :
2222 button==3 ? new_element3 : 0);
2224 if (new_element != level.amoebe_inhalt)
2226 level.amoebe_inhalt = new_element;
2227 DrawMiniElement(29,26,new_element);
2231 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
2232 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
2234 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
2235 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
2240 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
2242 if (button && !motion_status)
2243 in_field_pressed = TRUE;
2245 if (!button || !in_field_pressed || button<1 || button>3)
2248 new_element = (button==1 ? new_element1 :
2249 button==2 ? new_element2 :
2250 button==3 ? new_element3 : 0);
2252 if (new_element != level.mampfer_inhalt[i][x][y])
2254 level.mampfer_inhalt[i][x][y] = new_element;
2255 DrawMiniElement(1+5*i+x,2+y,new_element);
2258 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
2259 in_field_pressed = FALSE;
2261 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
2262 in_field_pressed = FALSE;
2271 last_button = button;
2276 void LevelNameTyping(KeySym key)
2278 unsigned char ascii = 0;
2279 int len = strlen(level.name);
2284 if (key>=XK_A && key<=XK_Z)
2285 ascii = 'A'+(char)(key-XK_A);
2286 else if (key>=XK_a && key<=XK_z)
2287 ascii = 'a'+(char)(key-XK_a);
2288 else if (key>=XK_0 && key<=XK_9)
2289 ascii = '0'+(char)(key-XK_0);
2291 else if (key>=XK_space && key<=XK_at)
2292 ascii = ' '+(char)(key-XK_space);
2293 else if (key==XK_Adiaeresis)
2295 else if (key==XK_Odiaeresis)
2297 else if (key==XK_Udiaeresis)
2299 else if (key==XK_adiaeresis)
2301 else if (key==XK_odiaeresis)
2303 else if (key==XK_udiaeresis)
2305 else if (key==XK_underscore)
2309 if (ascii && len<MAX_LEVNAMLEN-2)
2311 level.name[len] = ascii;
2312 level.name[len+1] = 0;
2315 DrawTextExt(drawto,gc,
2316 ED_COUNT_GADGET_XPOS+5,
2317 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2318 level.name,FS_SMALL,FC_GREEN);
2319 DrawTextExt(window,gc,
2320 ED_COUNT_GADGET_XPOS+5,
2321 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2322 level.name,FS_SMALL,FC_GREEN);
2323 DrawTextExt(drawto,gc,
2324 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2325 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2326 "<",FS_SMALL,FC_RED);
2327 DrawTextExt(window,gc,
2328 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2329 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2330 "<",FS_SMALL,FC_RED);
2332 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2334 level.name[len-1] = 0;
2337 DrawTextExt(drawto,gc,
2338 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2339 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2340 "< ",FS_SMALL,FC_GREEN);
2341 DrawTextExt(window,gc,
2342 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2343 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2344 "< ",FS_SMALL,FC_GREEN);
2346 else if (key==XK_Return)
2348 DrawTextExt(drawto,gc,
2349 ED_COUNT_GADGET_XPOS+5,
2350 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2351 level.name,FS_SMALL,FC_YELLOW);
2352 DrawTextExt(window,gc,
2353 ED_COUNT_GADGET_XPOS+5,
2354 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2355 level.name,FS_SMALL,FC_YELLOW);
2356 DrawTextExt(drawto,gc,
2357 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2358 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2359 " ",FS_SMALL,FC_YELLOW);
2360 DrawTextExt(window,gc,
2361 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2362 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2363 " ",FS_SMALL,FC_YELLOW);
2365 name_typing = FALSE;
2369 static void DrawCounterValueField(int counter_id, int value)
2371 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2372 int y = SY + counterbutton_info[counter_id].y;
2374 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2375 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2376 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2377 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2380 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2381 int2str(value, 3), FS_SMALL, FC_YELLOW);
2384 static void DrawDrawingWindow()
2387 UnmapLevelEditorWindowGadgets();
2388 AdjustLevelScrollPosition();
2389 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL);
2390 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL);
2391 DrawMiniLevel(level_xpos, level_ypos);
2392 MapMainDrawingArea();
2395 static void DrawLevelInfoWindow()
2397 char infotext[MAX_INFOTEXT_LEN + 1];
2398 int infotext_yoffset = MINI_TILEX + ED_GADGET_DISTANCE;
2402 UnmapLevelEditorWindowGadgets();
2404 DrawTextF(ED_LEVELINFO_XPOS, ED_LEVELINFO_YPOS, FC_YELLOW,
2405 "Level Information");
2407 gadget_level_xsize_value = &lev_fieldx;
2408 gadget_level_ysize_value = &lev_fieldy;
2409 gadget_level_collect_value = &level.edelsteine;
2410 gadget_level_timelimit_value = &level.time;
2411 gadget_level_timescore_value = &level.score[10];
2413 /* draw counter gadgets for level info */
2414 for (i=ED_COUNTER_ID_LEVEL_XSIZE; i<=ED_COUNTER_ID_LEVEL_TIMESCORE; i++)
2416 x = counterbutton_info[i].x;
2417 y = counterbutton_info[i].y - infotext_yoffset;
2419 sprintf(infotext, "%s:", counterbutton_info[i].infotext);
2420 DrawTextF(x, y, FC_YELLOW, infotext);
2422 ModifyEditorCounter(i, **counterbutton_info[i].counter_value);
2423 MapCounterButtons(i);
2426 /* draw level name text input gadget */
2427 x = textinput_info[ED_TEXTINPUT_ID_LEVEL_NAME].x;
2428 y = textinput_info[ED_TEXTINPUT_ID_LEVEL_NAME].y - infotext_yoffset;
2429 DrawTextF(x, y, FC_YELLOW, "Level Title:");
2430 MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2433 static void DrawElementContentAreas()
2435 int *num_areas = &MampferMax;
2436 int area_x = ED_AREA_ELEM_CONTENT_XPOS / MINI_TILEX;
2437 int area_y = ED_AREA_ELEM_CONTENT_YPOS / MINI_TILEY;
2438 int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
2439 int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
2442 for (i=0; i<MAX_ELEM_CONTENT; i++)
2445 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2447 for (i=0; i<MAX_ELEM_CONTENT; i++)
2448 UnmapDrawingArea(ED_CTRL_ID_ELEM_CONTENT_0 + i);
2450 /* display counter to choose number of element content areas */
2451 gadget_elem_content_value = num_areas;
2452 DrawCounterValueField(ED_COUNTER_ID_ELEM_CONTENT,*gadget_elem_content_value);
2453 x = counterbutton_info[ED_COUNTER_ID_ELEM_CONTENT].x + counter_xsize;
2454 y = counterbutton_info[ED_COUNTER_ID_ELEM_CONTENT].y;
2455 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2456 FC_YELLOW, "number of content areas");
2457 ModifyEditorCounter(ED_COUNTER_ID_ELEM_CONTENT, *gadget_elem_content_value);
2458 MapCounterButtons(ED_COUNTER_ID_ELEM_CONTENT);
2460 /* delete content areas in case of reducing number of them */
2461 XFillRectangle(display, backbuffer, gc,
2462 SX, area_sy - MINI_TILEX,
2463 SXSIZE, 12 * MINI_TILEY);
2465 /* draw some decorative border for the objects */
2466 for (i=0; i<*num_areas; i++)
2470 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2473 XFillRectangle(display, drawto, gc,
2474 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2475 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2476 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2479 /* copy border to the right location */
2480 XCopyArea(display, drawto, drawto, gc,
2481 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2482 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2484 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2485 "Content", FS_SMALL, FC_YELLOW);
2486 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2487 "when", FS_SMALL, FC_YELLOW);
2488 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2489 "smashed", FS_SMALL, FC_YELLOW);
2491 for (i=0; i<*num_areas; i++)
2495 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2496 ElementContent[i][x][y]);
2498 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2499 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2500 FC_YELLOW, "%d", i + 1);
2503 for (i=0; i<*num_areas; i++)
2504 MapDrawingArea(ED_CTRL_ID_ELEM_CONTENT_0 + i);
2507 static void DrawAmoebaContentArea()
2509 int area_x = ED_AREA_ELEM_CONTENT_XPOS / MINI_TILEX;
2510 int area_y = ED_AREA_ELEM_CONTENT_YPOS / MINI_TILEY;
2511 int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
2512 int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
2515 ElementContent[0][0][0] = level.amoebe_inhalt;
2517 /* draw decorative border for the object */
2520 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2522 XFillRectangle(display, drawto, gc,
2523 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2524 MINI_TILEX + 2, MINI_TILEY + 2);
2526 /* copy border to the right location */
2527 XCopyArea(display, drawto, drawto, gc,
2528 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2529 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2531 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2532 FS_SMALL, FC_YELLOW);
2534 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2536 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2539 #define TEXT_COLLECTING "Score for collecting"
2540 #define TEXT_SMASHING "Score for smashing"
2541 #define TEXT_CRACKING "Score for cracking"
2542 #define TEXT_SPEED "Speed of amoeba growth"
2543 #define TEXT_DURATION "Duration when activated"
2545 static void DrawPropertiesWindow()
2548 int num_elements_in_level;
2554 } elements_with_counter[] =
2556 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2557 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2558 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2559 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2560 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2561 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2562 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2563 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2564 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2565 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2566 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2567 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2568 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2569 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2570 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2571 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2572 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2573 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2574 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2575 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2576 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2577 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2578 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2579 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2580 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2581 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2582 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2583 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2584 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2585 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2586 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2587 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2588 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2589 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2590 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2591 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2592 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2593 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2594 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2595 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2596 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2601 UnmapLevelEditorWindowGadgets();
2603 /* draw some decorative border for the object */
2606 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2608 XFillRectangle(display, drawto, gc,
2609 SX + TILEX + MINI_TILEX/2 - 1,
2610 SY + TILEY + MINI_TILEY/2 - 1,
2611 TILEX + 2, TILEY + 2);
2613 /* copy border to the right location */
2614 XCopyArea(display, drawto, drawto, gc,
2615 SX + TILEX, SY + TILEY,
2616 2 * TILEX, 2 * TILEY,
2617 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2619 DrawGraphic(1, 1, el2gfx(properties_element));
2620 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2621 FS_SMALL, FC_YELLOW);
2623 num_elements_in_level = 0;
2624 for (y=0; y<lev_fieldy; y++)
2625 for (x=0; x<lev_fieldx; x++)
2626 if (Feld[x][y] == properties_element)
2627 num_elements_in_level++;
2629 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2630 num_elements_in_level);
2632 /* check if there are elements where a score can be chosen for */
2633 for (i=0; elements_with_counter[i].element != -1; i++)
2635 if (elements_with_counter[i].element == properties_element)
2637 int x = counterbutton_info[ED_COUNTER_ID_ELEM_SCORE].x + counter_xsize;
2638 int y = counterbutton_info[ED_COUNTER_ID_ELEM_SCORE].y;
2640 gadget_elem_score_value = elements_with_counter[i].counter_value;
2643 DrawCounterValueField(ED_COUNTER_ID_SCORE, *gadget_score_value);
2646 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2647 FC_YELLOW, elements_with_counter[i].text);
2648 ModifyEditorCounter(ED_COUNTER_ID_ELEM_SCORE, *gadget_elem_score_value);
2649 MapCounterButtons(ED_COUNTER_ID_ELEM_SCORE);
2654 if (HAS_CONTENT(properties_element))
2656 if (IS_AMOEBOID(properties_element))
2657 DrawAmoebaContentArea();
2659 DrawElementContentAreas();
2663 static void swap_numbers(int *i1, int *i2)
2671 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2683 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2685 int lx = sx + level_xpos;
2686 int ly = sy + level_ypos;
2688 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2691 Feld[lx][ly] = element;
2694 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2695 int element, boolean change_level)
2697 if (from_y == to_y) /* horizontal line */
2703 swap_numbers(&from_x, &to_x);
2705 for (x=from_x; x<=to_x; x++)
2706 DrawLineElement(x, y, element, change_level);
2708 else if (from_x == to_x) /* vertical line */
2714 swap_numbers(&from_y, &to_y);
2716 for (y=from_y; y<=to_y; y++)
2717 DrawLineElement(x, y, element, change_level);
2719 else /* diagonal line */
2721 int len_x = ABS(to_x - from_x);
2722 int len_y = ABS(to_y - from_y);
2725 if (len_y < len_x) /* a < 1 */
2727 float a = (float)len_y / (float)len_x;
2730 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2732 for (x=0; x<=len_x; x++)
2734 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2736 DrawLineElement(from_x + x, from_y + y, element, change_level);
2741 float a = (float)len_x / (float)len_y;
2744 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2746 for (y=0; y<=len_y; y++)
2748 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2750 DrawLineElement(from_x + x, from_y + y, element, change_level);
2756 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2757 int element, boolean change_level)
2759 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2760 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2761 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2762 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2765 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2766 int element, boolean change_level)
2771 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2773 for (y=from_y; y<=to_y; y++)
2774 DrawLine(from_x, y, to_x, y, element, change_level);
2777 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2779 int from_sx, from_sy;
2783 swap_numbers(&from_x, &to_x);
2786 swap_numbers(&from_y, &to_y);
2788 from_sx = SX + from_x * MINI_TILEX;
2789 from_sy = SY + from_y * MINI_TILEY;
2790 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2791 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2793 XSetForeground(display, gc, WhitePixel(display, screen));
2795 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2796 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2797 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2798 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2800 XSetForeground(display, gc, BlackPixel(display, screen));
2802 if (from_x == to_x && from_y == to_y)
2803 MarkTileDirty(from_x/2, from_y/2);
2805 redraw_mask |= REDRAW_FIELD;
2808 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2809 int element, boolean change_level)
2811 if (element == -1 || change_level)
2812 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2814 DrawAreaBorder(from_x, from_y, to_x, to_y);
2817 /* values for CopyBrushExt() */
2818 #define CB_AREA_TO_BRUSH 0
2819 #define CB_BRUSH_TO_CURSOR 1
2820 #define CB_BRUSH_TO_LEVEL 2
2821 #define CB_DELETE_OLD_CURSOR 3
2823 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
2824 int button, int mode)
2826 static short brush_buffer[ED_FIELDX][ED_FIELDY];
2827 static int brush_width, brush_height;
2828 static int last_cursor_x = -1, last_cursor_y = -1;
2829 static boolean delete_old_brush;
2833 if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush)
2836 new_element = (button == 1 ? new_element1 :
2837 button == 2 ? new_element2 :
2838 button == 3 ? new_element3 : 0);
2840 if (mode == CB_AREA_TO_BRUSH)
2842 int from_lx, from_ly;
2845 swap_numbers(&from_x, &to_x);
2848 swap_numbers(&from_y, &to_y);
2850 brush_width = to_x - from_x + 1;
2851 brush_height = to_y - from_y + 1;
2853 from_lx = from_x + level_xpos;
2854 from_ly = from_y + level_ypos;
2856 for (y=0; y<brush_height; y++)
2858 for (x=0; x<brush_width; x++)
2860 brush_buffer[x][y] = Feld[from_lx + x][from_ly + y];
2863 DrawLineElement(from_x + x, from_y + y, new_element, TRUE);
2868 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2870 delete_old_brush = FALSE;
2872 else if (mode == CB_BRUSH_TO_CURSOR || mode == CB_DELETE_OLD_CURSOR ||
2873 mode == CB_BRUSH_TO_LEVEL)
2875 int cursor_x = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_x : from_x);
2876 int cursor_y = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_y : from_y);
2877 int cursor_from_x = cursor_x - brush_width / 2;
2878 int cursor_from_y = cursor_y - brush_height / 2;
2879 int border_from_x = cursor_x, border_from_y = cursor_y;
2880 int border_to_x = cursor_x, border_to_y = cursor_y;
2882 if (mode != CB_DELETE_OLD_CURSOR && delete_old_brush)
2883 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2885 if (!IN_ED_FIELD(cursor_x, cursor_y) ||
2886 !IN_LEV_FIELD(cursor_x + level_xpos, cursor_y + level_ypos))
2888 delete_old_brush = FALSE;
2892 for (y=0; y<brush_height; y++)
2894 for (x=0; x<brush_width; x++)
2896 int sx = cursor_from_x + x;
2897 int sy = cursor_from_y + y;
2898 int lx = sx + level_xpos;
2899 int ly = sy + level_ypos;
2900 boolean change_level = (mode == CB_BRUSH_TO_LEVEL);
2901 int element = (mode == CB_DELETE_OLD_CURSOR ? -1 :
2902 mode == CB_BRUSH_TO_CURSOR || button == 1 ?
2903 brush_buffer[x][y] : new_element);
2905 if (IN_ED_FIELD(sx, sy) && IN_LEV_FIELD(lx, ly))
2907 if (sx < border_from_x)
2909 else if (sx > border_to_x)
2911 if (sy < border_from_y)
2913 else if (sy > border_to_y)
2916 DrawLineElement(sx, sy, element, change_level);
2922 printf("%d, %d - %d, %d in level and screen\n",
2923 border_from_x, border_from_y, border_to_x, border_to_y);
2926 if (mode != CB_DELETE_OLD_CURSOR)
2927 DrawAreaBorder(border_from_x, border_from_y, border_to_x, border_to_y);
2930 if (mode == CB_BRUSH_TO_LEVEL)
2931 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2934 last_cursor_x = cursor_x;
2935 last_cursor_y = cursor_y;
2936 delete_old_brush = TRUE;
2940 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y,
2943 CopyBrushExt(from_x, from_y, to_x, to_y, button, CB_AREA_TO_BRUSH);
2946 static void CopyBrushToLevel(int x, int y, int button)
2948 CopyBrushExt(x, y, 0, 0, button, CB_BRUSH_TO_LEVEL);
2951 static void CopyBrushToCursor(int x, int y)
2953 CopyBrushExt(x, y, 0, 0, 0, CB_BRUSH_TO_CURSOR);
2956 static void DeleteBrushFromCursor()
2958 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2961 static void FloodFill(int from_x, int from_y, int fill_element)
2965 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2966 static int safety = 0;
2968 /* check if starting field still has the desired content */
2969 if (Feld[from_x][from_y] == fill_element)
2974 if (safety > lev_fieldx*lev_fieldy)
2975 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2977 old_element = Feld[from_x][from_y];
2978 Feld[from_x][from_y] = fill_element;
2982 x = from_x + check[i][0];
2983 y = from_y + check[i][1];
2985 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2986 FloodFill(x, y, fill_element);
2992 /* values for DrawLevelText() modes */
2994 #define TEXT_SETCURSOR 1
2995 #define TEXT_WRITECHAR 2
2996 #define TEXT_BACKSPACE 3
2997 #define TEXT_NEWLINE 4
3000 static void DrawLevelText(int sx, int sy, char letter, int mode)
3002 static short delete_buffer[MAX_LEV_FIELDX];
3003 static int start_sx, start_sy;
3004 static int last_sx, last_sy;
3005 static boolean typing = FALSE;
3006 int letter_element = EL_CHAR_ASCII0 + letter;
3009 /* map lower case letters to upper case and convert special characters */
3010 if (letter >= 'a' && letter <= 'z')
3011 letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
3012 else if (letter == 'ä' || letter == 'Ä')
3013 letter_element = EL_CHAR_AE;
3014 else if (letter == 'ö' || letter == 'Ö')
3015 letter_element = EL_CHAR_OE;
3016 else if (letter == 'ü' || letter == 'Ü')
3017 letter_element = EL_CHAR_UE;
3018 else if (letter == '^')
3019 letter_element = EL_CHAR_COPY;
3021 letter_element = EL_CHAR_ASCII0 + letter;
3023 if (mode != TEXT_INIT)
3028 if (mode != TEXT_SETCURSOR)
3034 lx = last_sx + level_xpos;
3035 ly = last_sy + level_ypos;
3042 DrawLevelText(0, 0, 0, TEXT_END);
3045 start_sx = last_sx = sx;
3046 start_sy = last_sy = sy;
3047 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
3050 case TEXT_SETCURSOR:
3051 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3052 DrawAreaBorder(sx, sy, sx, sy);
3057 case TEXT_WRITECHAR:
3058 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
3060 delete_buffer[sx - start_sx] = Feld[lx][ly];
3061 Feld[lx][ly] = letter_element;
3063 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
3064 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
3065 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
3066 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
3068 DrawLevelText(0, 0, 0, TEXT_END);
3072 case TEXT_BACKSPACE:
3075 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
3076 DrawMiniElement(sx - 1, sy, new_element3);
3077 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
3082 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
3083 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
3085 DrawLevelText(0, 0, 0, TEXT_END);
3089 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3090 DrawMiniElement(sx, sy, Feld[lx][ly]);
3099 static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
3100 int element, boolean change_level)
3102 int lx = sx + level_xpos;
3103 int ly = sy + level_ypos;
3106 DrawMiniElement(sx, sy, Feld[lx][ly]);
3108 DrawAreaBorder(sx, sy, sx, sy);
3111 static void CopyLevelToUndoBuffer(int mode)
3113 static boolean accumulated_undo = FALSE;
3114 boolean new_undo_buffer_position = TRUE;
3119 case UNDO_IMMEDIATE:
3120 accumulated_undo = FALSE;
3123 case UNDO_ACCUMULATE:
3124 if (accumulated_undo)
3125 new_undo_buffer_position = FALSE;
3126 accumulated_undo = TRUE;
3133 if (new_undo_buffer_position)
3135 /* new position in undo buffer ring */
3136 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
3138 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
3139 undo_buffer_steps++;
3142 for(x=0; x<lev_fieldx; x++)
3143 for(y=0; y<lev_fieldy; y++)
3144 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
3147 printf("level saved to undo buffer\n");
3152 static void RandomPlacement(int button)
3157 new_element = (button == 1 ? new_element1 :
3158 button == 2 ? new_element2 :
3159 button == 3 ? new_element3 : 0);
3161 if (random_placement_method == RANDOM_USE_PERCENTAGE)
3163 for(x=0; x<lev_fieldx; x++)
3164 for(y=0; y<lev_fieldy; y++)
3165 if (RND(100) < random_placement_percentage)
3166 Feld[x][y] = new_element;
3170 int elements_left = random_placement_num_objects;
3172 while (elements_left > 0)
3174 x = RND(lev_fieldx);
3175 y = RND(lev_fieldy);
3177 if (Feld[x][y] != new_element)
3179 Feld[x][y] = new_element;
3185 DrawMiniLevel(level_xpos, level_ypos);
3186 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3189 void WrapLevel(int dx, int dy)
3191 int wrap_dx = lev_fieldx - dx;
3192 int wrap_dy = lev_fieldy - dy;
3195 for(x=0; x<lev_fieldx; x++)
3196 for(y=0; y<lev_fieldy; y++)
3197 FieldBackup[x][y] = Feld[x][y];
3199 for(x=0; x<lev_fieldx; x++)
3200 for(y=0; y<lev_fieldy; y++)
3202 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
3204 DrawMiniLevel(level_xpos, level_ypos);
3205 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
3208 static void HandleDrawingAreas(struct GadgetInfo *gi)
3210 static boolean started_inside_drawing_area = FALSE;
3211 int id = gi->custom_id;
3212 boolean inside_drawing_area = !gi->event.off_borders;
3213 boolean button_press_event;
3214 boolean button_release_event;
3215 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
3217 int button = gi->event.button;
3218 int sx = gi->event.x, sy = gi->event.y;
3219 int min_sx = 0, min_sy = 0;
3220 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
3222 int min_lx = 0, min_ly = 0;
3223 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
3226 /* handle info callback for each invocation of action callback */
3227 gi->callback_info(gi);
3230 if (edit_mode != ED_MODE_DRAWING)
3234 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
3235 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
3237 /* make sure to stay inside drawing area boundaries */
3238 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
3239 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
3243 /* get positions inside level field */
3244 lx = sx + level_xpos;
3245 ly = sy + level_ypos;
3247 /* make sure to stay inside level field boundaries */
3248 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
3249 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
3251 /* correct drawing area positions accordingly */
3252 sx = lx - level_xpos;
3253 sy = ly - level_ypos;
3256 if (button_press_event)
3257 started_inside_drawing_area = inside_drawing_area;
3259 if (!started_inside_drawing_area)
3262 if (!button && !button_release_event)
3265 new_element = (button == 1 ? new_element1 :
3266 button == 2 ? new_element2 :
3267 button == 3 ? new_element3 : 0);
3271 if (button_release_event)
3276 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
3279 switch (drawing_function)
3281 case ED_CTRL_ID_SINGLE_ITEMS:
3284 if (button_release_event)
3286 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3288 if (edit_mode == ED_MODE_DRAWING && draw_with_brush &&
3289 !inside_drawing_area)
3290 DeleteBrushFromCursor();
3296 if (draw_with_brush)
3298 if (!button_release_event)
3299 CopyBrushToLevel(sx, sy, button);
3301 else if (new_element != Feld[lx][ly])
3303 if (new_element == EL_SPIELFIGUR)
3305 /* remove player at old position */
3306 for(y=0; y<lev_fieldy; y++)
3308 for(x=0; x<lev_fieldx; x++)
3310 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
3312 Feld[x][y] = EL_LEERRAUM;
3313 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
3314 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
3315 DrawMiniElement(x - level_xpos, y - level_ypos,
3322 Feld[lx][ly] = new_element;
3323 DrawMiniElement(sx, sy, new_element);
3328 DrawMiniGraphicExt(drawto, gc,
3329 gi->x + sx * MINI_TILEX,
3330 gi->y + sy * MINI_TILEY,
3331 el2gfx(new_element));
3332 DrawMiniGraphicExt(window, gc,
3333 gi->x + sx * MINI_TILEX,
3334 gi->y + sy * MINI_TILEY,
3335 el2gfx(new_element));
3337 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3338 level.amoebe_inhalt = new_element;
3339 else if (id >= ED_CTRL_ID_ELEM_CONTENT_0 &&
3340 id <= ED_CTRL_ID_ELEM_CONTENT_7)
3341 level.mampfer_inhalt[id - ED_CTRL_ID_ELEM_CONTENT_0][sx][sy] =
3346 case ED_CTRL_ID_CONNECTED_ITEMS:
3348 static int last_sx = -1;
3349 static int last_sy = -1;
3351 if (button_release_event)
3352 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3356 if (!button_press_event)
3357 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
3365 case ED_CTRL_ID_LINE:
3366 case ED_CTRL_ID_RECTANGLE:
3367 case ED_CTRL_ID_FILLED_BOX:
3368 case ED_CTRL_ID_GRAB_BRUSH:
3369 case ED_CTRL_ID_TEXT:
3371 static int last_sx = -1;
3372 static int last_sy = -1;
3373 static int start_sx = -1;
3374 static int start_sy = -1;
3375 void (*draw_func)(int, int, int, int, int, boolean);
3377 if (drawing_function == ED_CTRL_ID_LINE)
3378 draw_func = DrawLine;
3379 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
3380 draw_func = DrawRectangle;
3381 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
3382 draw_func = DrawFilledBox;
3383 else if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3384 draw_func = SelectArea;
3385 else /* (drawing_function == ED_CTRL_ID_TEXT) */
3386 draw_func = SetTextCursor;
3388 if (button_press_event)
3390 draw_func(sx, sy, sx, sy, new_element, FALSE);
3391 start_sx = last_sx = sx;
3392 start_sy = last_sy = sy;
3394 if (drawing_function == ED_CTRL_ID_TEXT)
3395 DrawLevelText(0, 0, 0, TEXT_END);
3397 else if (button_release_event)
3399 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
3400 if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3402 CopyAreaToBrush(start_sx, start_sy, sx, sy, button);
3403 CopyBrushToCursor(sx, sy);
3404 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
3405 draw_with_brush = TRUE;
3407 else if (drawing_function == ED_CTRL_ID_TEXT)
3408 DrawLevelText(sx, sy, 0, TEXT_INIT);
3410 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3412 else if (last_sx != sx || last_sy != sy)
3414 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
3415 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
3425 case ED_CTRL_ID_TEXT:
3427 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3428 DrawAreaBorder(sx, sy, sx, sy);
3433 if (button_press_event)
3434 DrawLevelText(sx, sy, 0, TEXT_INIT);
3440 case ED_CTRL_ID_FLOOD_FILL:
3441 if (button_press_event && Feld[lx][ly] != new_element)
3443 FloodFill(lx, ly, new_element);
3444 DrawMiniLevel(level_xpos, level_ypos);
3445 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3449 case ED_CTRL_ID_PICK_ELEMENT:
3450 if (button_press_event)
3451 PickDrawingElement(button, Feld[lx][ly]);
3452 if (button_release_event)
3453 ClickOnGadget(level_editor_gadget[last_drawing_function]);
3461 static void HandleCounterButtons(struct GadgetInfo *gi)
3463 int id = gi->custom_id;
3464 int button = gi->event.button;
3465 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3469 case ED_CTRL_ID_ELEM_SCORE_DOWN:
3470 case ED_CTRL_ID_ELEM_SCORE_UP:
3471 step *= (id == ED_CTRL_ID_ELEM_SCORE_DOWN ? -1 : 1);
3472 ModifyEditorCounter(ED_COUNTER_ID_ELEM_SCORE,
3473 *gadget_elem_score_value + step);
3475 case ED_CTRL_ID_ELEM_SCORE_TEXT:
3476 *gadget_elem_score_value = gi->text.number_value;
3479 case ED_CTRL_ID_ELEM_CONTENT_DOWN:
3480 case ED_CTRL_ID_ELEM_CONTENT_UP:
3481 step *= (id == ED_CTRL_ID_ELEM_CONTENT_DOWN ? -1 : 1);
3482 ModifyEditorCounter(ED_COUNTER_ID_ELEM_CONTENT,
3483 *gadget_elem_content_value + step);
3484 DrawElementContentAreas();
3486 case ED_CTRL_ID_ELEM_CONTENT_TEXT:
3487 *gadget_elem_content_value = gi->text.number_value;
3488 DrawElementContentAreas();
3491 case ED_CTRL_ID_LEVEL_XSIZE_DOWN:
3492 case ED_CTRL_ID_LEVEL_XSIZE_UP:
3493 step *= (id == ED_CTRL_ID_LEVEL_XSIZE_DOWN ? -1 : 1);
3494 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_XSIZE,
3495 *gadget_level_xsize_value + step);
3496 level.fieldx = lev_fieldx;
3498 case ED_CTRL_ID_LEVEL_XSIZE_TEXT:
3499 *gadget_level_xsize_value = gi->text.number_value;
3500 level.fieldx = lev_fieldx;
3503 case ED_CTRL_ID_LEVEL_YSIZE_DOWN:
3504 case ED_CTRL_ID_LEVEL_YSIZE_UP:
3505 step *= (id == ED_CTRL_ID_LEVEL_YSIZE_DOWN ? -1 : 1);
3506 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_YSIZE,
3507 *gadget_level_ysize_value + step);
3508 level.fieldy = lev_fieldy;
3510 case ED_CTRL_ID_LEVEL_YSIZE_TEXT:
3511 *gadget_level_ysize_value = gi->text.number_value;
3512 level.fieldy = lev_fieldy;
3515 case ED_CTRL_ID_LEVEL_COLLECT_DOWN:
3516 case ED_CTRL_ID_LEVEL_COLLECT_UP:
3517 step *= (id == ED_CTRL_ID_LEVEL_COLLECT_DOWN ? -1 : 1);
3518 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_COLLECT,
3519 *gadget_level_collect_value + step);
3521 case ED_CTRL_ID_LEVEL_COLLECT_TEXT:
3522 *gadget_level_collect_value = gi->text.number_value;
3525 case ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN:
3526 case ED_CTRL_ID_LEVEL_TIMELIMIT_UP:
3527 step *= (id == ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN ? -1 : 1);
3528 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_TIMELIMIT,
3529 *gadget_level_timelimit_value + step);
3531 case ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT:
3532 *gadget_level_timelimit_value = gi->text.number_value;
3535 case ED_CTRL_ID_LEVEL_TIMESCORE_DOWN:
3536 case ED_CTRL_ID_LEVEL_TIMESCORE_UP:
3537 step *= (id == ED_CTRL_ID_LEVEL_TIMESCORE_DOWN ? -1 : 1);
3538 ModifyEditorCounter(ED_COUNTER_ID_LEVEL_TIMESCORE,
3539 *gadget_level_timescore_value + step);
3541 case ED_CTRL_ID_LEVEL_TIMESCORE_TEXT:
3542 *gadget_level_timescore_value = gi->text.number_value;
3550 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3552 int id = gi->custom_id;
3556 case ED_CTRL_ID_LEVEL_NAME:
3557 strcpy(level.name, gi->text.value);
3565 static void HandleControlButtons(struct GadgetInfo *gi)
3567 int id = gi->custom_id;
3568 int button = gi->event.button;
3569 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3571 int player_present = FALSE;
3572 int level_changed = FALSE;
3575 new_element = (button == 1 ? new_element1 :
3576 button == 2 ? new_element2 :
3577 button == 3 ? new_element3 : 0);
3579 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3580 DrawLevelText(0, 0, 0, TEXT_END);
3582 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3583 edit_mode != ED_MODE_DRAWING)
3585 DrawDrawingWindow();
3586 edit_mode = ED_MODE_DRAWING;
3591 case ED_CTRL_ID_SCROLL_LEFT:
3592 if (level_xpos >= 0)
3594 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3595 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3596 struct GadgetScrollbar *gs = &gi->scrollbar;
3598 if (lev_fieldx < ED_FIELDX - 2)
3602 if (level_xpos < -1)
3605 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3607 DrawMiniLevel(level_xpos, level_ypos);
3609 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3613 case ED_CTRL_ID_SCROLL_RIGHT:
3614 if (level_xpos <= lev_fieldx - ED_FIELDX)
3616 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3617 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3618 struct GadgetScrollbar *gs = &gi->scrollbar;
3620 if (lev_fieldx < ED_FIELDX - 2)
3624 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3625 level_xpos = lev_fieldx - ED_FIELDX + 1;
3627 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3629 DrawMiniLevel(level_xpos, level_ypos);
3631 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3635 case ED_CTRL_ID_SCROLL_UP:
3636 if (level_ypos >= 0)
3638 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3639 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3640 struct GadgetScrollbar *gs = &gi->scrollbar;
3642 if (lev_fieldy < ED_FIELDY - 2)
3646 if (level_ypos < -1)
3649 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3651 DrawMiniLevel(level_xpos, level_ypos);
3653 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3657 case ED_CTRL_ID_SCROLL_DOWN:
3658 if (level_ypos <= lev_fieldy - ED_FIELDY)
3660 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3661 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3662 struct GadgetScrollbar *gs = &gi->scrollbar;
3664 if (lev_fieldy < ED_FIELDY - 2)
3668 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3669 level_ypos = lev_fieldy - ED_FIELDY + 1;
3671 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3673 DrawMiniLevel(level_xpos, level_ypos);
3675 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3679 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3680 level_xpos = gi->event.item_position - 1;
3681 DrawMiniLevel(level_xpos, level_ypos);
3684 case ED_CTRL_ID_SCROLL_VERTICAL:
3685 level_ypos = gi->event.item_position - 1;
3686 DrawMiniLevel(level_xpos, level_ypos);
3689 case ED_CTRL_ID_WRAP_LEFT:
3690 WrapLevel(-step, 0);
3693 case ED_CTRL_ID_WRAP_RIGHT:
3697 case ED_CTRL_ID_WRAP_UP:
3698 WrapLevel(0, -step);
3701 case ED_CTRL_ID_WRAP_DOWN:
3705 case ED_CTRL_ID_SINGLE_ITEMS:
3706 case ED_CTRL_ID_CONNECTED_ITEMS:
3707 case ED_CTRL_ID_LINE:
3708 case ED_CTRL_ID_TEXT:
3709 case ED_CTRL_ID_RECTANGLE:
3710 case ED_CTRL_ID_FILLED_BOX:
3711 case ED_CTRL_ID_FLOOD_FILL:
3712 case ED_CTRL_ID_GRAB_BRUSH:
3713 case ED_CTRL_ID_PICK_ELEMENT:
3714 last_drawing_function = drawing_function;
3715 drawing_function = id;
3716 draw_with_brush = FALSE;
3719 case ED_CTRL_ID_RANDOM_PLACEMENT:
3720 RandomPlacement(button);
3723 case ED_CTRL_ID_PROPERTIES:
3724 if (edit_mode != ED_MODE_PROPERTIES)
3726 properties_element = new_element;
3727 DrawPropertiesWindow();
3728 edit_mode = ED_MODE_PROPERTIES;
3732 DrawDrawingWindow();
3733 edit_mode = ED_MODE_DRAWING;
3737 case ED_CTRL_ID_UNDO:
3738 if (undo_buffer_steps == 0)
3740 Request("Undo buffer empty !", REQ_CONFIRM);
3744 undo_buffer_position =
3745 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3746 undo_buffer_steps--;
3748 for(x=0; x<lev_fieldx; x++)
3749 for(y=0; y<lev_fieldy; y++)
3750 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3751 DrawMiniLevel(level_xpos,level_ypos);
3754 case ED_CTRL_ID_INFO:
3755 if (edit_mode != ED_MODE_INFO)
3757 DrawLevelInfoWindow();
3758 edit_mode = ED_MODE_INFO;
3762 DrawDrawingWindow();
3763 edit_mode = ED_MODE_DRAWING;
3767 case ED_CTRL_ID_CLEAR:
3768 for(x=0; x<MAX_LEV_FIELDX; x++)
3769 for(y=0; y<MAX_LEV_FIELDY; y++)
3770 Feld[x][y] = new_element3;
3771 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3773 DrawMiniLevel(level_xpos, level_ypos);
3776 case ED_CTRL_ID_SAVE:
3777 if (leveldir[leveldir_nr].readonly)
3779 Request("This level is read only !", REQ_CONFIRM);
3783 for(y=0; y<lev_fieldy; y++)
3784 for(x=0; x<lev_fieldx; x++)
3785 if (Feld[x][y] != Ur[x][y])
3786 level_changed = TRUE;
3788 if (0 && !level_changed)
3790 Request("Level has not changed !", REQ_CONFIRM);
3794 for(y=0; y<lev_fieldy; y++)
3795 for(x=0; x<lev_fieldx; x++)
3796 if (Feld[x][y] == EL_SPIELFIGUR ||
3797 Feld[x][y] == EL_SPIELER1 ||
3798 Feld[x][y] == EL_SP_MURPHY)
3799 player_present = TRUE;
3801 if (!player_present)
3802 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3805 if (Request("Save this level and kill the old ?", REQ_ASK))
3807 for(x=0; x<lev_fieldx; x++)
3808 for(y=0; y<lev_fieldy; y++)
3809 Ur[x][y] = Feld[x][y];
3810 SaveLevel(level_nr);
3815 case ED_CTRL_ID_TEST:
3816 for(y=0; y<lev_fieldy; y++)
3817 for(x=0; x<lev_fieldx; x++)
3818 if (Feld[x][y] == EL_SPIELFIGUR ||
3819 Feld[x][y] == EL_SPIELER1 ||
3820 Feld[x][y] == EL_SP_MURPHY)
3821 player_present = TRUE;
3823 if (!player_present)
3824 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3827 for(x=0; x<lev_fieldx; x++)
3828 for(y=0; y<lev_fieldy; y++)
3829 FieldBackup[x][y] = Ur[x][y];
3831 for(x=0; x<lev_fieldx; x++)
3832 for(y=0; y<lev_fieldy; y++)
3833 Ur[x][y] = Feld[x][y];
3835 UnmapLevelEditorGadgets();
3837 /* draw smaller door */
3838 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3839 DOOR_GFX_PAGEX7, 64,
3842 redraw_mask |= REDRAW_ALL;
3844 CloseDoor(DOOR_CLOSE_ALL);
3846 DrawCompleteVideoDisplay();
3848 if (setup.autorecord)
3849 TapeStartRecording();
3851 level_editor_test_game = TRUE;
3852 game_status = PLAYING;
3858 case ED_CTRL_ID_EXIT:
3859 for(y=0; y<lev_fieldy; y++)
3860 for(x=0; x<lev_fieldx; x++)
3861 if (Feld[x][y] != Ur[x][y])
3862 level_changed = TRUE;
3864 if (!level_changed ||
3865 Request("Level has changed! Exit without saving ?",
3866 REQ_ASK | REQ_STAY_OPEN))
3868 CloseDoor(DOOR_CLOSE_1);
3871 CloseDoor(DOOR_CLOSE_ALL);
3874 /* draw smaller door */
3875 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3876 DOOR_GFX_PAGEX7, 64,
3879 redraw_mask |= REDRAW_ALL;
3881 game_status = MAINMENU;
3886 CloseDoor(DOOR_CLOSE_1);
3887 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3888 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3889 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3890 OpenDoor(DOOR_OPEN_1);
3896 if (gi->event.type == GD_EVENT_PRESSED)
3897 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3898 else if (gi->event.type == GD_EVENT_RELEASED)
3899 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3900 else if (gi->event.type == GD_EVENT_MOVING)
3901 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3903 printf("default: HandleControlButtons: ?\n");
3909 void HandleLevelEditorKeyInput(KeySym key)
3911 if (edit_mode == ED_MODE_DRAWING)
3913 char letter = getCharFromKeySym(key);
3915 if (drawing_function == ED_CTRL_ID_TEXT)
3918 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3919 else if (key == XK_Delete || key == XK_BackSpace)
3920 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3921 else if (key == XK_Return)
3922 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3924 else if (button_status == MB_RELEASED)
3931 id = ED_CTRL_ID_SCROLL_LEFT;
3934 id = ED_CTRL_ID_SCROLL_RIGHT;
3937 id = ED_CTRL_ID_SCROLL_UP;
3940 id = ED_CTRL_ID_SCROLL_DOWN;
3944 id = ED_CTRL_ID_NONE;
3948 if (id != ED_CTRL_ID_NONE)
3949 ClickOnGadget(level_editor_gadget[id]);
3950 else if (letter == '.')
3951 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
3953 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
3954 if (letter && letter == control_info[i].shortcut)
3955 ClickOnGadget(level_editor_gadget[i]);
3960 void ClearEditorGadgetInfoText()
3962 XFillRectangle(display, drawto, gc,
3963 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
3964 redraw_mask |= REDRAW_FIELD;
3967 void HandleEditorGadgetInfoText(void *ptr)
3969 struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
3970 char infotext[MAX_INFOTEXT_LEN + 1];
3973 ClearEditorGadgetInfoText();
3975 /* misuse this function to delete brush cursor, if needed */
3976 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3977 DeleteBrushFromCursor();
3979 if (gi == NULL || gi->info_text == NULL)
3982 strncpy(infotext, gi->info_text, MAX_INFOTEXT_LEN);
3983 infotext[MAX_INFOTEXT_LEN] = '\0';
3985 if (gi->custom_id < ED_NUM_CTRL_BUTTONS)
3987 int key = control_info[gi->custom_id].shortcut;
3991 sprintf(shortcut, " ('%s%c')",
3992 (key >= 'A' && key <= 'Z' ? "Shift-" :
3993 gi->custom_id == ED_CTRL_ID_SINGLE_ITEMS ? ".' or '" : ""),
3996 if (strlen(infotext) + strlen(shortcut) <= MAX_INFOTEXT_LEN)
3997 strcat(infotext, shortcut);
4001 DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW);
4004 static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
4006 static int start_lx, start_ly;
4008 int id = gi->custom_id;
4009 int sx = gi->event.x;
4010 int sy = gi->event.y;
4011 int lx = sx + level_xpos;
4012 int ly = sy + level_ypos;
4014 ClearEditorGadgetInfoText();
4016 if (id == ED_CTRL_ID_DRAWING_LEVEL)
4020 int min_sx = 0, min_sy = 0;
4021 int max_sx = gi->drawing.area_xsize - 1;
4022 int max_sy = gi->drawing.area_ysize - 1;
4023 int min_lx = 0, min_ly = 0;
4024 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
4026 /* make sure to stay inside drawing area boundaries */
4027 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
4028 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
4030 /* get positions inside level field */
4031 lx = sx + level_xpos;
4032 ly = sy + level_ypos;
4034 /* make sure to stay inside level field boundaries */
4035 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
4036 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
4038 /* correct drawing area positions accordingly */
4039 sx = lx - level_xpos;
4040 sy = ly - level_ypos;
4043 if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly))
4045 if (button_status) /* if (gi->state == GD_BUTTON_PRESSED) */
4047 if (gi->event.type == GD_EVENT_PRESSED)
4053 switch (drawing_function)
4055 case ED_CTRL_ID_SINGLE_ITEMS:
4056 infotext = "Drawing single items";
4058 case ED_CTRL_ID_CONNECTED_ITEMS:
4059 infotext = "Drawing connected items";
4061 case ED_CTRL_ID_LINE:
4062 infotext = "Drawing line";
4064 case ED_CTRL_ID_TEXT:
4065 infotext = "Setting text cursor";
4067 case ED_CTRL_ID_RECTANGLE:
4068 infotext = "Drawing rectangle";
4070 case ED_CTRL_ID_FILLED_BOX:
4071 infotext = "Drawing filled box";
4073 case ED_CTRL_ID_FLOOD_FILL:
4074 infotext = "Flood fill";
4076 case ED_CTRL_ID_GRAB_BRUSH:
4077 infotext = "Grabbing brush";
4079 case ED_CTRL_ID_PICK_ELEMENT:
4080 infotext = "Picking element";
4084 infotext = "Drawing position";
4088 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4089 "%s: %d, %d", infotext,
4090 ABS(lx - start_lx) + 1,
4091 ABS(ly - start_ly) + 1);
4094 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4095 "Level position: %d, %d", lx, ly);
4098 /* misuse this function to draw brush cursor, if needed */
4099 if (edit_mode == ED_MODE_DRAWING && draw_with_brush && !button_status)
4101 if (IN_ED_FIELD(sx,sy) && IN_LEV_FIELD(lx, ly))
4102 CopyBrushToCursor(sx, sy);
4104 DeleteBrushFromCursor();
4107 else if (id == ED_CTRL_ID_AMOEBA_CONTENT)
4108 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4111 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
4112 "Cruncher %d content: %d, %d",
4113 id - ED_CTRL_ID_ELEM_CONTENT_0 + 1, sx, sy);