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 content */
53 #define MAX_ELEMCONT 8
55 /* values for the control window */
56 #define ED_CTRL_BUTTONS_GFX_YPOS 236
57 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142
59 #define ED_CTRL1_BUTTONS_HORIZ 4
60 #define ED_CTRL1_BUTTONS_VERT 4
61 #define ED_CTRL1_BUTTON_XSIZE 22
62 #define ED_CTRL1_BUTTON_YSIZE 22
63 #define ED_CTRL1_BUTTONS_XPOS 6
64 #define ED_CTRL1_BUTTONS_YPOS 6
65 #define ED_CTRL2_BUTTONS_HORIZ 3
66 #define ED_CTRL2_BUTTONS_VERT 2
67 #define ED_CTRL2_BUTTON_XSIZE 30
68 #define ED_CTRL2_BUTTON_YSIZE 20
69 #define ED_CTRL2_BUTTONS_XPOS 5
70 #define ED_CTRL2_BUTTONS_YPOS 100
71 #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
72 #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
73 #define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
75 /* values for properties window */
76 #define ED_PROPERTIES_XPOS (TILEX - MINI_TILEX/2)
78 /* values for counter gadgets */
79 #define ED_COUNT_VALUE_XOFFSET 5
80 #define ED_COUNT_VALUE_YOFFSET 3
81 #define ED_COUNT_SCORE_XPOS ED_PROPERTIES_XPOS
82 #define ED_COUNT_SCORE_YPOS (14 * MINI_TILEY)
83 #define ED_COUNT_ELEMCONT_XPOS ED_PROPERTIES_XPOS
84 #define ED_COUNT_ELEMCONT_YPOS (17 * MINI_TILEY)
86 /* values for element content drawing areas */
87 #define ED_AREA_ELEMCONT_XPOS (TILEX)
88 #define ED_AREA_ELEMCONT_YPOS (10 * TILEY)
90 /* values for scrolling gadgets */
91 #define ED_SCROLLBUTTON_XPOS 24
92 #define ED_SCROLLBUTTON_YPOS 0
93 #define ED_SCROLLBAR_XPOS 24
94 #define ED_SCROLLBAR_YPOS 64
96 #define ED_SCROLLBUTTON_XSIZE 16
97 #define ED_SCROLLBUTTON_YSIZE 16
99 #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
100 #define ED_SCROLL_UP_YPOS (0)
101 #define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
102 #define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE)
103 #define ED_SCROLL_LEFT_XPOS (0)
104 #define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
105 #define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
106 #define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
107 #define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
108 #define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
109 #define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
110 #define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
111 #define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
112 #define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
113 #define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
114 #define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
116 /* control button identifiers */
117 #define ED_CTRL_ID_NONE -1
119 #define ED_CTRL_ID_SINGLE_ITEMS 0
120 #define ED_CTRL_ID_CONNECTED_ITEMS 1
121 #define ED_CTRL_ID_LINE 2
122 #define ED_CTRL_ID_TEXT 3
123 #define ED_CTRL_ID_RECTANGLE 4
124 #define ED_CTRL_ID_FILLED_BOX 5
125 #define ED_CTRL_ID_WRAP_UP 6
126 #define ED_CTRL_ID_PROPERTIES 7
127 #define ED_CTRL_ID_FLOOD_FILL 8
128 #define ED_CTRL_ID_WRAP_LEFT 9
129 #define ED_CTRL_ID_UNUSED1 10
130 #define ED_CTRL_ID_WRAP_RIGHT 11
131 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
132 #define ED_CTRL_ID_GRAB_BRUSH 13
133 #define ED_CTRL_ID_WRAP_DOWN 14
134 #define ED_CTRL_ID_PICK_ELEMENT 15
135 #define ED_CTRL_ID_UNDO 16
136 #define ED_CTRL_ID_INFO 17
137 #define ED_CTRL_ID_SAVE 18
138 #define ED_CTRL_ID_CLEAR 19
139 #define ED_CTRL_ID_TEST 20
140 #define ED_CTRL_ID_EXIT 21
142 /* counter button identifiers */
143 #define ED_CTRL_ID_SCORE_DOWN 22
144 #define ED_CTRL_ID_SCORE_UP 23
145 #define ED_CTRL_ID_ELEMCONT_DOWN 24
146 #define ED_CTRL_ID_ELEMCONT_UP 25
148 /* drawing area identifiers */
149 #define ED_CTRL_ID_DRAWING_LEVEL 26
150 #define ED_CTRL_ID_ELEMCONT_0 27
151 #define ED_CTRL_ID_ELEMCONT_7 34
152 #define ED_CTRL_ID_AMOEBA_CONTENT 35
154 /* text input identifiers */
155 #define ED_CTRL_ID_LEVEL_NAME 36
157 /* gadgets for scrolling of drawing area */
158 #define ED_CTRL_ID_SCROLL_UP 37
159 #define ED_CTRL_ID_SCROLL_DOWN 38
160 #define ED_CTRL_ID_SCROLL_LEFT 39
161 #define ED_CTRL_ID_SCROLL_RIGHT 40
162 #define ED_CTRL_ID_SCROLL_VERTICAL 41
163 #define ED_CTRL_ID_SCROLL_HORIZONTAL 42
165 #define ED_NUM_GADGETS 43
167 /* values for counter gadgets */
168 #define ED_COUNTER_SCORE 0
169 #define ED_COUNTER_ELEMCONT 1
171 #define ED_NUM_COUNTERBUTTONS 2
172 #define ED_NUM_SCROLLBUTTONS 4
173 #define ED_NUM_SCROLLBARS 2
175 /* values for CopyLevelToUndoBuffer() */
176 #define UNDO_IMMEDIATE 0
177 #define UNDO_ACCUMULATE 1
183 } control_info[ED_NUM_CTRL_BUTTONS] =
185 { 's', "draw single items" },
186 { 'd', "draw connected items" },
187 { 'l', "draw lines" },
188 { 't', "enter text elements" },
189 { 'r', "draw outline rectangles" },
190 { 'R', "draw filled rectangles" },
191 { '\0', "wrap (rotate) level up" },
192 { '?', "properties of drawing element" },
193 { 'f', "flood fill" },
194 { '\0', "wrap (rotate) level left" },
196 { '\0', "wrap (rotate) level right" },
197 { '\0', "random element placement" },
198 { 'b', "grab brush" },
199 { '\0', "wrap (rotate) level down" },
200 { ',', "pick drawing element" },
201 { 'U', "undo last operation" },
202 { 'I', "level properties" },
203 { 'S', "save level" },
204 { 'C', "clear level" },
205 { 'T', "test level" },
206 { 'E', "exit level editor" }
213 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
215 { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN },
216 { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, ED_CTRL_ID_ELEMCONT_DOWN }
225 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
228 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
229 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
230 "scroll level editing area up"
233 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
234 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
235 "scroll level editing area down"
238 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
239 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
240 "scroll level editing area left"
243 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
244 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
245 "scroll level editing area right"
257 } scrollbar_info[ED_NUM_SCROLLBARS] =
260 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
261 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
262 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
263 GD_TYPE_SCROLLBAR_VERTICAL,
264 ED_CTRL_ID_SCROLL_VERTICAL,
265 "scroll level editing area vertically"
268 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
269 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
270 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
271 GD_TYPE_SCROLLBAR_HORIZONTAL,
272 ED_CTRL_ID_SCROLL_HORIZONTAL,
273 "scroll level editing area horizontally"
277 /* forward declaration for internal use */
278 static void DrawDrawingWindow();
279 static void DrawPropertiesWindow();
280 static void CopyLevelToUndoBuffer(int);
281 static void HandleControlButtons(struct GadgetInfo *);
282 static void HandleCounterButtons(struct GadgetInfo *);
283 static void HandleDrawingAreas(struct GadgetInfo *);
284 static void HandleDrawingAreaInfo(struct GadgetInfo *);
285 static void HandleTextInputGadgets(struct GadgetInfo *);
287 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
288 static boolean level_editor_gadgets_created = FALSE;
290 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
291 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
292 static boolean draw_with_brush = FALSE;
293 static int properties_element = 0;
295 static short ElementContent[MAX_ELEMCONT][3][3];
296 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
297 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
298 static int undo_buffer_position = 0;
299 static int undo_buffer_steps = 0;
301 static int random_placement_percentage = 10;
302 static int random_placement_num_objects = 10;
304 static int random_placement_method = RANDOM_USE_PERCENTAGE;
306 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
309 /* pointer to score value */
310 static int *gadget_score_value;
311 static int *gadget_areas_value;
313 static int level_xpos,level_ypos;
314 static int edit_mode;
315 static boolean name_typing;
316 static int new_element1 = EL_MAUERWERK;
317 static int new_element2 = EL_LEERRAUM;
318 static int new_element3 = EL_ERDREICH;
320 int element_shift = 0;
322 int editor_element[] =
324 EL_CHAR_A + ('B' - 'A'),
325 EL_CHAR_A + ('O' - 'A'),
326 EL_CHAR_A + ('U' - 'A'),
327 EL_CHAR_A + ('L' - 'A'),
330 EL_CHAR_A + ('D' - 'A'),
331 EL_CHAR_A + ('E' - 'A'),
332 EL_CHAR_A + ('R' - 'A'),
334 EL_CHAR_A + ('D' - 'A'),
335 EL_CHAR_A + ('A' - 'A'),
336 EL_CHAR_A + ('S' - 'A'),
337 EL_CHAR_A + ('H' - 'A'),
364 EL_CHAR_A + ('E' - 'A'),
365 EL_CHAR_A + ('M' - 'A'),
366 EL_CHAR_A + ('E' - 'A'),
369 EL_CHAR_A + ('R' - 'A'),
370 EL_CHAR_A + ('A' - 'A'),
371 EL_CHAR_A + ('L' - 'A'),
372 EL_CHAR_A + ('D' - 'A'),
374 EL_CHAR_A + ('M' - 'A'),
375 EL_CHAR_A + ('I' - 'A'),
376 EL_CHAR_A + ('N' - 'A'),
377 EL_CHAR_A + ('E' - 'A'),
454 EL_CHAR_A + ('M' - 'A'),
455 EL_CHAR_A + ('O' - 'A'),
456 EL_CHAR_A + ('R' - 'A'),
457 EL_CHAR_A + ('E' - 'A'),
509 EL_CHAR_A + ('S' - 'A'),
510 EL_CHAR_A + ('O' - 'A'),
511 EL_CHAR_A + ('K' - 'A'),
512 EL_CHAR_A + ('O' - 'A'),
515 EL_CHAR_A + ('B' - 'A'),
516 EL_CHAR_A + ('A' - 'A'),
517 EL_CHAR_A + ('N' - 'A'),
520 EL_SOKOBAN_FELD_LEER,
521 EL_SOKOBAN_FELD_VOLL,
590 EL_CHAR_A + ('D' - 'A'),
591 EL_CHAR_A + ('Y' - 'A'),
592 EL_CHAR_A + ('N' - 'A'),
593 EL_CHAR_A + ('A' - 'A'),
595 EL_CHAR_A + ('B' - 'A'),
596 EL_CHAR_A + ('L' - 'A'),
597 EL_CHAR_A + ('A' - 'A'),
598 EL_CHAR_A + ('S' - 'A'),
601 EL_CHAR_A + ('T' - 'A'),
602 EL_CHAR_A + ('E' - 'A'),
603 EL_CHAR_A + ('R' - 'A'),
686 int elements_in_list = sizeof(editor_element)/sizeof(int);
688 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
691 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
692 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
694 XCopyArea(display, drawto, drawto, gc,
695 SX + (dx == -1 ? MINI_TILEX : 0),
696 SY + (dy == -1 ? MINI_TILEY : 0),
697 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
698 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
699 SX + (dx == +1 ? MINI_TILEX : 0),
700 SY + (dy == +1 ? MINI_TILEY : 0));
703 x = (dx == 1 ? 0 : ED_FIELDX - 1);
704 for(y=0; y<ED_FIELDY; y++)
705 DrawMiniElementOrWall(x, y, from_x, from_y);
709 y = (dy == 1 ? 0 : ED_FIELDY - 1);
710 for(x=0; x<ED_FIELDX; x++)
711 DrawMiniElementOrWall(x, y, from_x, from_y);
714 redraw_mask |= REDRAW_FIELD;
718 void InitLevelEditorGadgets()
722 for (i=0; i<ED_NUM_GADGETS; i++)
723 level_editor_gadget[i] = NULL;
726 static void CreateControlButtons()
728 Pixmap gd_pixmap = pix[PIX_DOOR];
729 struct GadgetInfo *gi;
730 unsigned long event_mask;
733 /* create toolbox buttons */
734 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
738 int gd_xoffset, gd_yoffset;
739 int gd_x1, gd_x2, gd_y1, gd_y2;
742 boolean radio_button_pressed;
744 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
745 id == ED_CTRL_ID_CONNECTED_ITEMS ||
746 id == ED_CTRL_ID_LINE ||
747 id == ED_CTRL_ID_TEXT ||
748 id == ED_CTRL_ID_RECTANGLE ||
749 id == ED_CTRL_ID_FILLED_BOX ||
750 id == ED_CTRL_ID_FLOOD_FILL ||
751 id == ED_CTRL_ID_GRAB_BRUSH ||
752 id == ED_CTRL_ID_PICK_ELEMENT)
754 button_type = GD_TYPE_RADIO_BUTTON;
756 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
757 event_mask = GD_EVENT_PRESSED;
761 button_type = GD_TYPE_NORMAL_BUTTON;
763 radio_button_pressed = FALSE;
765 if (id == ED_CTRL_ID_WRAP_LEFT ||
766 id == ED_CTRL_ID_WRAP_RIGHT ||
767 id == ED_CTRL_ID_WRAP_UP ||
768 id == ED_CTRL_ID_WRAP_DOWN)
769 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
771 event_mask = GD_EVENT_RELEASED;
774 if (id < ED_NUM_CTRL1_BUTTONS)
776 int x = i % ED_CTRL1_BUTTONS_HORIZ;
777 int y = i / ED_CTRL1_BUTTONS_HORIZ;
779 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
780 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
781 width = ED_CTRL1_BUTTON_XSIZE;
782 height = ED_CTRL1_BUTTON_YSIZE;
786 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
787 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
789 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
790 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
791 width = ED_CTRL2_BUTTON_XSIZE;
792 height = ED_CTRL2_BUTTON_YSIZE;
795 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
796 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
797 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
798 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
800 gi = CreateGadget(GDI_CUSTOM_ID, id,
801 GDI_DESCRIPTION_TEXT, control_info[i].text,
802 GDI_X, EX + gd_xoffset,
803 GDI_Y, EY + gd_yoffset,
806 GDI_TYPE, button_type,
807 GDI_STATE, GD_BUTTON_UNPRESSED,
808 GDI_RADIO_NR, radio_button_nr,
809 GDI_RADIO_PRESSED, radio_button_pressed,
810 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
811 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
812 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
813 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
814 GDI_EVENT_MASK, event_mask,
815 GDI_CALLBACK_ACTION, HandleControlButtons,
819 Error(ERR_EXIT, "cannot create gadget");
821 level_editor_gadget[id] = gi;
824 /* create buttons for scrolling of drawing area */
825 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
827 int id = scrollbutton_info[i].gadget_id;
828 int gd_x1, gd_x2, gd_y;
830 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
832 gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
833 gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
834 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
836 gi = CreateGadget(GDI_CUSTOM_ID, id,
837 GDI_DESCRIPTION_TEXT, scrollbutton_info[i].text,
838 GDI_X, SX + scrollbutton_info[i].x,
839 GDI_Y, SY + scrollbutton_info[i].y,
840 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
841 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
842 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
843 GDI_STATE, GD_BUTTON_UNPRESSED,
844 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
845 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
846 GDI_EVENT_MASK, event_mask,
847 GDI_CALLBACK_ACTION, HandleControlButtons,
851 Error(ERR_EXIT, "cannot create gadget");
853 level_editor_gadget[id] = gi;
857 static void CreateCounterButtons()
861 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
865 Pixmap gd_pixmap = pix[PIX_DOOR];
866 struct GadgetInfo *gi;
867 int id = counterbutton_info[i].gadget_id + j;
869 int gd_x1, gd_x2, gd_y;
870 unsigned long event_mask;
872 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
874 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
875 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
876 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
877 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
879 gi = CreateGadget(GDI_CUSTOM_ID, id,
880 GDI_X, SX + counterbutton_info[i].x + gd_xoffset,
881 GDI_Y, SY + counterbutton_info[i].y,
882 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
883 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
884 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
885 GDI_STATE, GD_BUTTON_UNPRESSED,
886 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
887 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
888 GDI_EVENT_MASK, event_mask,
889 GDI_CALLBACK_ACTION, HandleCounterButtons,
893 Error(ERR_EXIT, "cannot create gadget");
895 level_editor_gadget[id] = gi;
900 static void CreateDrawingAreas()
902 struct GadgetInfo *gi;
903 unsigned long event_mask;
908 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
909 GD_EVENT_OFF_BORDERS;
911 /* one for the level drawing area ... */
912 id = ED_CTRL_ID_DRAWING_LEVEL;
913 gi = CreateGadget(GDI_CUSTOM_ID, id,
916 GDI_TYPE, GD_TYPE_DRAWING_AREA,
917 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
918 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
919 GDI_EVENT_MASK, event_mask,
920 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
921 GDI_CALLBACK_ACTION, HandleDrawingAreas,
925 Error(ERR_EXIT, "cannot create gadget");
927 level_editor_gadget[id] = gi;
929 /* ... up to eight areas for element content ... */
930 for (i=0; i<MAX_ELEMCONT; i++)
932 int gx = SX + ED_AREA_ELEMCONT_XPOS + 5 * (i % 4) * MINI_TILEX;
933 int gy = SX + ED_AREA_ELEMCONT_YPOS + 6 * (i / 4) * MINI_TILEY;
935 id = ED_CTRL_ID_ELEMCONT_0 + i;
936 gi = CreateGadget(GDI_CUSTOM_ID, id,
939 GDI_WIDTH, 3 * MINI_TILEX,
940 GDI_HEIGHT, 3 * MINI_TILEY,
941 GDI_TYPE, GD_TYPE_DRAWING_AREA,
942 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
943 GDI_EVENT_MASK, event_mask,
944 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
945 GDI_CALLBACK_ACTION, HandleDrawingAreas,
949 Error(ERR_EXIT, "cannot create gadget");
951 level_editor_gadget[id] = gi;
954 /* ... and one for the amoeba content */
955 id = ED_CTRL_ID_AMOEBA_CONTENT;
956 gi = CreateGadget(GDI_CUSTOM_ID, id,
957 GDI_X, SX + ED_AREA_ELEMCONT_XPOS,
958 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS,
959 GDI_WIDTH, MINI_TILEX,
960 GDI_HEIGHT, MINI_TILEY,
961 GDI_TYPE, GD_TYPE_DRAWING_AREA,
962 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
963 GDI_EVENT_MASK, event_mask,
964 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
965 GDI_CALLBACK_ACTION, HandleDrawingAreas,
969 Error(ERR_EXIT, "cannot create gadget");
971 level_editor_gadget[id] = gi;
974 static void CreateTextInputGadgets()
976 Pixmap gd_pixmap = pix[PIX_DOOR];
978 struct GadgetInfo *gi;
979 unsigned long event_mask;
982 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
983 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
984 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
986 /* text input gadget for the level name */
987 id = ED_CTRL_ID_LEVEL_NAME;
988 gi = CreateGadget(GDI_CUSTOM_ID, id,
989 GDI_X, SX + ED_COUNT_ELEMCONT_XPOS,
990 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX,
991 GDI_TYPE, GD_TYPE_TEXTINPUT,
992 GDI_TEXT_VALUE, level.name,
994 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
995 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
996 GDI_DESIGN_BORDER, 3,
997 GDI_EVENT_MASK, event_mask,
998 GDI_CALLBACK_ACTION, HandleTextInputGadgets,
1002 Error(ERR_EXIT, "cannot create gadget");
1004 level_editor_gadget[id] = gi;
1007 static void CreateScrollbarGadgets()
1011 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1013 int id = scrollbar_info[i].gadget_id;
1014 Pixmap gd_pixmap = pix[PIX_DOOR];
1015 int gd_x1, gd_x2, gd_y1, gd_y2;
1016 struct GadgetInfo *gi;
1017 int items_max, items_visible, item_position;
1018 unsigned long event_mask;
1020 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
1022 items_max = lev_fieldx + 2;
1023 items_visible = ED_FIELDX;
1028 items_max = lev_fieldy + 2;
1029 items_visible = ED_FIELDY;
1033 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
1035 gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
1036 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
1037 gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1038 gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1040 gi = CreateGadget(GDI_CUSTOM_ID, id,
1041 GDI_DESCRIPTION_TEXT, scrollbar_info[i].text,
1042 GDI_X, SX + scrollbar_info[i].x,
1043 GDI_Y, SY + scrollbar_info[i].y,
1044 GDI_WIDTH, scrollbar_info[i].width,
1045 GDI_HEIGHT, scrollbar_info[i].height,
1046 GDI_TYPE, scrollbar_info[i].type,
1047 GDI_SCROLLBAR_ITEMS_MAX, items_max,
1048 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
1049 GDI_SCROLLBAR_ITEM_POSITION, item_position,
1050 GDI_STATE, GD_BUTTON_UNPRESSED,
1051 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
1052 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
1053 GDI_DESIGN_BORDER, 3,
1054 GDI_EVENT_MASK, event_mask,
1055 GDI_CALLBACK_ACTION, HandleControlButtons,
1059 Error(ERR_EXIT, "cannot create gadget");
1061 level_editor_gadget[id] = gi;
1065 static void CreateLevelEditorGadgets()
1067 if (level_editor_gadgets_created)
1070 CreateControlButtons();
1071 CreateCounterButtons();
1072 CreateDrawingAreas();
1073 CreateTextInputGadgets();
1074 CreateScrollbarGadgets();
1076 level_editor_gadgets_created = TRUE;
1079 static void MapControlButtons()
1083 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1084 MapGadget(level_editor_gadget[i]);
1087 static void MapCounterButtons(int id)
1092 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id + i]);
1095 static void MapDrawingArea(int id)
1097 MapGadget(level_editor_gadget[id]);
1100 static void MapTextInputGadget(int id)
1102 MapGadget(level_editor_gadget[id]);
1105 static void MapMainDrawingArea()
1109 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1110 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1112 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1113 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1115 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1118 static void UnmapDrawingArea(int id)
1120 UnmapGadget(level_editor_gadget[id]);
1123 void UnmapLevelEditorWindowGadgets()
1127 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1128 UnmapGadget(level_editor_gadget[i]);
1131 void UnmapLevelEditorGadgets()
1135 for (i=0; i<ED_NUM_GADGETS; i++)
1136 UnmapGadget(level_editor_gadget[i]);
1141 int i, x, y, graphic;
1145 edit_mode = ED_MODE_DRAWING;
1146 name_typing = FALSE;
1148 CloseDoor(DOOR_CLOSE_ALL);
1150 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1152 if (level_editor_test_game)
1154 for(x=0; x<lev_fieldx; x++)
1155 for(y=0; y<lev_fieldy; y++)
1156 Feld[x][y] = Ur[x][y];
1158 for(x=0; x<lev_fieldx; x++)
1159 for(y=0; y<lev_fieldy; y++)
1160 Ur[x][y] = FieldBackup[x][y];
1162 level_editor_test_game = FALSE;
1166 undo_buffer_position = -1;
1167 undo_buffer_steps = -1;
1168 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1172 DrawMiniLevel(level_xpos, level_ypos);
1176 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1177 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1179 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1180 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1181 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1182 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1183 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1184 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1185 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1187 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1189 if (i < elements_in_list)
1190 graphic = el2gfx(editor_element[i + element_shift]);
1192 graphic = GFX_LEERRAUM;
1194 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1195 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1196 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1197 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1198 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1202 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1203 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1204 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1205 el2gfx(new_element1));
1206 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1207 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1208 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1209 el2gfx(new_element2));
1210 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1211 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1212 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1213 el2gfx(new_element3));
1214 DrawTextExt(pix[PIX_DB_DOOR],gc,
1215 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1216 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1217 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1218 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1219 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1220 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1222 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1223 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1224 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1225 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1226 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1228 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1229 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1231 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1232 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1234 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1236 /* draw bigger door */
1237 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1242 /* draw new control window */
1243 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1244 DOOR_GFX_PAGEX8, 236,
1248 redraw_mask |= REDRAW_ALL;
1250 OpenDoor(DOOR_OPEN_1);
1252 if (!level_editor_gadgets_created)
1253 CreateLevelEditorGadgets();
1255 strcpy(level_editor_gadget[ED_CTRL_ID_LEVEL_NAME]->text.value, level.name);
1257 MapControlButtons();
1260 MapMainDrawingArea();
1263 DrawDrawingWindow();
1267 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1271 void DrawControlWindow()
1276 UnmapLevelEditorWindowGadgets();
1278 /* Inhalt der Mampfer */
1279 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1280 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1281 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1283 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1284 XFillRectangle(display,drawto,gc,
1285 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1286 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1287 3*MINI_TILEX+2,3*MINI_TILEY+2);
1289 XCopyArea(display,drawto,drawto,gc,
1290 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1291 4*5*MINI_TILEX,5*MINI_TILEY,
1292 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1295 for(y=0;y<3;y++) for(x=0;x<3;x++)
1296 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1298 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1299 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1300 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1303 /* Inhalt der Amöbe */
1304 for(y=0;y<2;y++) for(x=0;x<2;x++)
1306 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1307 XFillRectangle(display,drawto,gc,
1308 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1309 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1310 MINI_TILEX+2,MINI_TILEY+2);
1312 XCopyArea(display,drawto,drawto,gc,
1313 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1314 3*MINI_TILEX,3*MINI_TILEY,
1315 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1316 DrawMiniElement(29,26,level.amoebe_inhalt);
1318 for(i=0;i<11+3+2;i++)
1320 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1321 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1322 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1323 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1324 ED_COUNT_GADGET_XPOS,
1325 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1328 DrawText(ED_COUNT_VALUE_XPOS,
1329 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1330 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1332 DrawText(ED_COUNT_VALUE_XPOS,
1333 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1334 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1336 DrawText(ED_COUNT_VALUE_XPOS,
1337 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1338 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1340 DrawText(ED_COUNT_VALUE_XPOS,
1341 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1342 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1344 DrawText(ED_COUNT_VALUE_XPOS,
1345 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1346 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1348 DrawText(ED_COUNT_VALUE_XPOS,
1349 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1350 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1353 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1354 "Score for Emerald",FS_SMALL,FC_YELLOW);
1355 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1356 "Score for Diamond",FS_SMALL,FC_YELLOW);
1357 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1358 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1359 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1360 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1361 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1362 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1363 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1364 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1365 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1366 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1367 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1368 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1369 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1370 "Score for dynamite",FS_SMALL,FC_YELLOW);
1371 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1372 "Score for key",FS_SMALL,FC_YELLOW);
1373 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1374 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1375 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1376 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1377 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1378 "Time for magic wall",FS_SMALL,FC_YELLOW);
1379 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1380 "Time for wheel",FS_SMALL,FC_YELLOW);
1381 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1382 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1383 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1384 "Time available for this level",FS_SMALL,FC_YELLOW);
1386 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1387 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1388 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1389 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1390 ED_COUNT_GADGET_XPOS,
1391 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1393 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1394 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1395 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1396 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1397 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1398 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1399 DrawText(ED_COUNT_GADGET_XPOS+5,
1400 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1401 level.name,FS_SMALL,FC_YELLOW);
1402 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1403 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1404 "Title",FS_SMALL,FC_YELLOW);
1406 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1407 "Playfield size:",FS_SMALL,FC_YELLOW);
1408 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1409 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1410 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1411 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1412 ED_SIZE_GADGET_XPOS,
1413 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1414 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1415 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1416 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1417 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1418 ED_SIZE_GADGET_XPOS,
1419 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1420 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1421 "Width",FS_SMALL,FC_YELLOW);
1422 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1423 "Height",FS_SMALL,FC_YELLOW);
1424 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1425 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1426 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1427 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1430 void AdjustLevelScrollPosition()
1432 if (level_xpos < -1)
1434 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1435 level_xpos = lev_fieldx - ED_FIELDX + 1;
1436 if (lev_fieldx < ED_FIELDX - 2)
1439 if (level_ypos < -1)
1441 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1442 level_ypos = lev_fieldy - ED_FIELDY + 1;
1443 if (lev_fieldy < ED_FIELDY - 2)
1447 void AdjustEditorScrollbar(int id)
1449 struct GadgetInfo *gi = level_editor_gadget[id];
1450 struct GadgetScrollbar *gs = &gi->scrollbar;
1451 int items_max, items_visible, item_position = gs->item_position;
1453 if (id == ED_CTRL_ID_SCROLL_HORIZONTAL)
1455 items_max = lev_fieldx + 2;
1456 items_visible = ED_FIELDX;
1460 items_max = lev_fieldy + 2;
1461 items_visible = ED_FIELDY;
1464 if (item_position > items_max - items_visible)
1465 item_position = items_max - items_visible;
1467 AdjustScrollbar(gi, items_max, item_position);
1470 static void PickDrawingElement(int button, int element)
1472 if (button < 1 || button > 3)
1477 new_element1 = element;
1478 DrawMiniGraphicExt(drawto, gc,
1479 DX + ED_WIN_MB_LEFT_XPOS,
1480 DY + ED_WIN_MB_LEFT_YPOS,
1481 el2gfx(new_element1));
1483 else if (button == 2)
1485 new_element2 = element;
1486 DrawMiniGraphicExt(drawto, gc,
1487 DX + ED_WIN_MB_MIDDLE_XPOS,
1488 DY + ED_WIN_MB_MIDDLE_YPOS,
1489 el2gfx(new_element2));
1493 new_element3 = element;
1494 DrawMiniGraphicExt(drawto, gc,
1495 DX + ED_WIN_MB_RIGHT_XPOS,
1496 DY + ED_WIN_MB_RIGHT_YPOS,
1497 el2gfx(new_element3));
1500 redraw_mask |= REDRAW_DOOR_1;
1503 void LevelEd(int mx, int my, int button)
1505 static int last_button = 0;
1506 static int in_field_pressed = FALSE;
1507 static boolean use_floodfill = FALSE;
1511 int x = (mx-SX)/MINI_TILEX;
1512 int y = (my-SY)/MINI_TILEY;
1516 HandlePressedControlButtons();
1517 HandleDrawingFunctions(mx, my, button);
1520 if (use_floodfill) /********** FLOOD FILL **********/
1528 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1533 if (x>lev_fieldx || y>lev_fieldy ||
1534 (x==0 && level_xpos<0) ||
1535 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1536 (y==0 && level_ypos<0) ||
1537 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1540 from_x = x+level_xpos;
1541 from_y = y+level_ypos;
1542 fill_element = (button==1 ? new_element1 :
1543 button==2 ? new_element2 :
1544 button==3 ? new_element3 : 0);
1546 FloodFill(from_x,from_y,fill_element);
1547 DrawMiniLevel(level_xpos,level_ypos);
1550 use_floodfill = FALSE;
1551 CloseDoor(DOOR_CLOSE_1);
1552 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1561 else /********** EDIT/CTRL-FENSTER **********/
1563 static unsigned long choice_delay = 0;
1564 int choice = CheckElemButtons(mx,my,button);
1565 int elem_pos = choice-ED_BUTTON_ELEM;
1567 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1568 (choice == ED_BUTTON_EDOWN &&
1569 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1570 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1572 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1576 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1578 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1580 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1581 element_shift += step;
1584 if (element_shift<0)
1586 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1587 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1588 if (element_shift % MAX_ELEM_X)
1589 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1591 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1592 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1594 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1598 if (elem_pos+element_shift < elements_in_list)
1599 new_element = editor_element[elem_pos+element_shift];
1601 new_element = EL_LEERRAUM;
1603 PickDrawingElement(last_button, new_element);
1605 if (!HAS_CONTENT(properties_element))
1607 properties_element = new_element;
1608 if (edit_mode == ED_MODE_PROPERTIES)
1609 DrawPropertiesWindow();
1613 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1620 switch(CheckEditButtons(mx,my,button))
1622 case ED_BUTTON_CTRL:
1623 CloseDoor(DOOR_CLOSE_2);
1624 DrawControlWindow();
1625 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1626 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1628 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1629 OpenDoor(DOOR_OPEN_2);
1630 edit_mode = ED_MODE_INFO;
1632 case ED_BUTTON_FILL:
1633 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1634 use_floodfill = TRUE;
1637 case ED_BUTTON_LEFT:
1640 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1642 if (lev_fieldx<ED_FIELDX-2)
1645 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1649 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1651 DrawMiniLevel(level_xpos,level_ypos);
1654 case ED_BUTTON_RIGHT:
1655 if (level_xpos<=lev_fieldx-ED_FIELDX)
1657 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1659 if (lev_fieldx<ED_FIELDX-2)
1662 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1663 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1664 level_xpos = lev_fieldx-ED_FIELDX+1;
1666 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1668 DrawMiniLevel(level_xpos,level_ypos);
1674 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1676 if (lev_fieldy<ED_FIELDY-2)
1679 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1683 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1685 DrawMiniLevel(level_xpos,level_ypos);
1688 case ED_BUTTON_DOWN:
1689 if (level_ypos<=lev_fieldy-ED_FIELDY)
1691 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1693 if (lev_fieldy<ED_FIELDY-2)
1696 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1697 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1698 level_ypos = lev_fieldy-ED_FIELDY+1;
1700 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1702 DrawMiniLevel(level_xpos,level_ypos);
1715 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1719 if (button && !motion_status)
1720 in_field_pressed = TRUE;
1722 if (!button || !in_field_pressed || button<1 || button>3 ||
1723 (y==0 && level_ypos<0) ||
1724 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1725 (x==0 && level_xpos<0) ||
1726 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1727 x>lev_fieldx || y>lev_fieldy)
1730 new_element = (button==1 ? new_element1 :
1731 button==2 ? new_element2 :
1732 button==3 ? new_element3 : 0);
1734 if (new_element != Feld[x+level_xpos][y+level_ypos])
1736 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1740 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1742 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1744 Feld[x][y] = EL_LEERRAUM;
1745 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1746 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1747 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1752 Feld[x+level_xpos][y+level_ypos] = new_element;
1753 DrawMiniElement(x,y,new_element);
1756 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1757 in_field_pressed = FALSE;
1764 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1766 int choice = CheckCountButtons(mx,my,button);
1767 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1769 if (choice >= 0 && choice < 36 &&
1770 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1779 level.score[choice] += step;
1780 if (level.score[choice]<0)
1781 level.score[choice] = 0;
1782 else if (level.score[choice]>255)
1783 level.score[choice] = 255;
1785 else if (choice==11)
1787 level.tempo_amoebe += step;
1788 if (level.tempo_amoebe<0)
1789 level.tempo_amoebe = 0;
1790 else if (level.tempo_amoebe>255)
1791 level.tempo_amoebe = 255;
1793 else if (choice==12)
1795 level.dauer_sieb += step;
1796 if (level.dauer_sieb<0)
1797 level.dauer_sieb = 0;
1798 else if (level.dauer_sieb>255)
1799 level.dauer_sieb = 255;
1801 else if (choice==13)
1803 level.dauer_ablenk += step;
1804 if (level.dauer_ablenk<0)
1805 level.dauer_ablenk = 0;
1806 else if (level.dauer_ablenk>255)
1807 level.dauer_ablenk = 255;
1809 else if (choice==14)
1811 level.edelsteine += step;
1812 if (level.edelsteine<0)
1813 level.edelsteine = 0;
1814 else if (level.edelsteine>999)
1815 level.edelsteine = 999;
1817 else if (choice==15)
1822 else if (level.time>999)
1825 else if (choice==16)
1828 if (lev_fieldx<MIN_LEV_FIELDX)
1829 lev_fieldx = MIN_LEV_FIELDX;
1830 else if (lev_fieldx>MAX_LEV_FIELDX)
1831 lev_fieldx = MAX_LEV_FIELDX;
1832 level.fieldx = lev_fieldx;
1834 else if (choice==17)
1837 if (lev_fieldy<MIN_LEV_FIELDY)
1838 lev_fieldy = MIN_LEV_FIELDY;
1839 else if (lev_fieldy>MAX_LEV_FIELDY)
1840 lev_fieldy = MAX_LEV_FIELDY;
1841 level.fieldy = lev_fieldy;
1845 DrawText(ED_COUNT_VALUE_XPOS,
1846 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1847 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1848 else if (choice==11)
1849 DrawText(ED_COUNT_VALUE_XPOS,
1850 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1851 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1852 else if (choice==12)
1853 DrawText(ED_COUNT_VALUE_XPOS,
1854 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1855 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1856 else if (choice==13)
1857 DrawText(ED_COUNT_VALUE_XPOS,
1858 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1859 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1860 else if (choice==14)
1861 DrawText(ED_COUNT_VALUE_XPOS,
1862 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1863 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1864 else if (choice==15)
1865 DrawText(ED_COUNT_VALUE_XPOS,
1866 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1867 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1868 else if (choice==16)
1869 DrawText(ED_SIZE_VALUE_XPOS,
1870 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1871 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1872 else if (choice==17)
1873 DrawText(ED_SIZE_VALUE_XPOS,
1874 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1875 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1877 redraw_mask &= ~REDRAW_FIELD;
1879 XCopyArea(display,drawto,window,gc,
1880 ED_COUNT_VALUE_XPOS,
1881 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1882 3*FONT2_XSIZE,FONT2_YSIZE,
1883 ED_COUNT_VALUE_XPOS,
1884 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1886 XCopyArea(display,drawto,window,gc,
1888 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1889 3*FONT2_XSIZE,FONT2_YSIZE,
1891 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1899 switch(CheckCtrlButtons(mx,my,button))
1901 case ED_BUTTON_EDIT:
1902 CloseDoor(DOOR_CLOSE_2);
1903 AdjustLevelScrollPosition();
1904 DrawMiniLevel(level_xpos,level_ypos);
1905 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1906 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1908 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1909 OpenDoor(DOOR_OPEN_2);
1910 edit_mode = ED_MODE_DRAWING;
1912 case ED_BUTTON_CLEAR:
1913 if (Request("Are you sure to clear this level ?",REQ_ASK))
1915 for(x=0;x<MAX_LEV_FIELDX;x++)
1916 for(y=0;y<MAX_LEV_FIELDY;y++)
1917 Feld[x][y] = EL_ERDREICH;
1918 DrawMiniLevel(level_xpos,level_ypos);
1921 case ED_BUTTON_UNDO:
1922 if (leveldir[leveldir_nr].readonly ||
1923 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1925 CloseDoor(DOOR_CLOSE_ALL);
1926 game_status=MAINMENU;
1931 CloseDoor(DOOR_CLOSE_1);
1932 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1935 case ED_BUTTON_EXIT:
1937 int figur_vorhanden = FALSE;
1939 if (leveldir[leveldir_nr].readonly)
1941 Request("This level is read only !",REQ_CONFIRM);
1945 for(y=0;y<lev_fieldy;y++)
1946 for(x=0;x<lev_fieldx;x++)
1947 if (Feld[x][y] == EL_SPIELFIGUR ||
1948 Feld[x][y] == EL_SPIELER1 ||
1949 Feld[x][y] == EL_SP_MURPHY)
1950 figur_vorhanden = TRUE;
1952 if (!figur_vorhanden)
1953 Request("No Level without Gregor Mc Duffin please !",
1957 if (Request("Save this level and kill the old ?",
1958 REQ_ASK | REQ_STAY_OPEN))
1960 for(x=0;x<lev_fieldx;x++)
1961 for(y=0;y<lev_fieldy;y++)
1962 Ur[x][y]=Feld[x][y];
1963 SaveLevel(level_nr);
1965 CloseDoor(DOOR_CLOSE_ALL);
1966 game_status=MAINMENU;
1979 if (mx>=ED_COUNT_GADGET_XPOS &&
1980 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1981 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1982 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1987 DrawText(ED_COUNT_GADGET_XPOS+5,
1988 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1989 level.name,FS_SMALL,FC_GREEN);
1990 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1991 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1992 "<",FS_SMALL,FC_RED);
1999 name_typing = FALSE;
2000 DrawText(ED_COUNT_GADGET_XPOS+5,
2001 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2002 level.name,FS_SMALL,FC_YELLOW);
2003 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
2004 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2005 " ",FS_SMALL,FC_RED);
2009 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
2010 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
2014 if (!button || button<1 || button>3)
2017 new_element = (button==1 ? new_element1 :
2018 button==2 ? new_element2 :
2019 button==3 ? new_element3 : 0);
2021 if (new_element != level.amoebe_inhalt)
2023 level.amoebe_inhalt = new_element;
2024 DrawMiniElement(29,26,new_element);
2028 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
2029 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
2031 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
2032 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
2037 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
2039 if (button && !motion_status)
2040 in_field_pressed = TRUE;
2042 if (!button || !in_field_pressed || button<1 || button>3)
2045 new_element = (button==1 ? new_element1 :
2046 button==2 ? new_element2 :
2047 button==3 ? new_element3 : 0);
2049 if (new_element != level.mampfer_inhalt[i][x][y])
2051 level.mampfer_inhalt[i][x][y] = new_element;
2052 DrawMiniElement(1+5*i+x,2+y,new_element);
2055 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
2056 in_field_pressed = FALSE;
2058 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
2059 in_field_pressed = FALSE;
2063 last_button = button;
2068 void LevelNameTyping(KeySym key)
2070 unsigned char ascii = 0;
2071 int len = strlen(level.name);
2076 if (key>=XK_A && key<=XK_Z)
2077 ascii = 'A'+(char)(key-XK_A);
2078 else if (key>=XK_a && key<=XK_z)
2079 ascii = 'a'+(char)(key-XK_a);
2080 else if (key>=XK_0 && key<=XK_9)
2081 ascii = '0'+(char)(key-XK_0);
2083 else if (key>=XK_space && key<=XK_at)
2084 ascii = ' '+(char)(key-XK_space);
2085 else if (key==XK_Adiaeresis)
2087 else if (key==XK_Odiaeresis)
2089 else if (key==XK_Udiaeresis)
2091 else if (key==XK_adiaeresis)
2093 else if (key==XK_odiaeresis)
2095 else if (key==XK_udiaeresis)
2097 else if (key==XK_underscore)
2101 if (ascii && len<MAX_LEVNAMLEN-2)
2103 level.name[len] = ascii;
2104 level.name[len+1] = 0;
2107 DrawTextExt(drawto,gc,
2108 ED_COUNT_GADGET_XPOS+5,
2109 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2110 level.name,FS_SMALL,FC_GREEN);
2111 DrawTextExt(window,gc,
2112 ED_COUNT_GADGET_XPOS+5,
2113 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2114 level.name,FS_SMALL,FC_GREEN);
2115 DrawTextExt(drawto,gc,
2116 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2117 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2118 "<",FS_SMALL,FC_RED);
2119 DrawTextExt(window,gc,
2120 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2121 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2122 "<",FS_SMALL,FC_RED);
2124 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2126 level.name[len-1] = 0;
2129 DrawTextExt(drawto,gc,
2130 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2131 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2132 "< ",FS_SMALL,FC_GREEN);
2133 DrawTextExt(window,gc,
2134 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2135 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2136 "< ",FS_SMALL,FC_GREEN);
2138 else if (key==XK_Return)
2140 DrawTextExt(drawto,gc,
2141 ED_COUNT_GADGET_XPOS+5,
2142 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2143 level.name,FS_SMALL,FC_YELLOW);
2144 DrawTextExt(window,gc,
2145 ED_COUNT_GADGET_XPOS+5,
2146 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2147 level.name,FS_SMALL,FC_YELLOW);
2148 DrawTextExt(drawto,gc,
2149 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2150 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2151 " ",FS_SMALL,FC_YELLOW);
2152 DrawTextExt(window,gc,
2153 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2154 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2155 " ",FS_SMALL,FC_YELLOW);
2157 name_typing = FALSE;
2161 static void DrawCounterValueField(int counter_id, int value)
2163 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2164 int y = SY + counterbutton_info[counter_id].y;
2166 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2167 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2168 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2169 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2172 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2173 int2str(value, 3), FS_SMALL, FC_YELLOW);
2176 static void DrawDrawingWindow()
2179 UnmapLevelEditorWindowGadgets();
2180 AdjustLevelScrollPosition();
2181 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL);
2182 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL);
2183 DrawMiniLevel(level_xpos, level_ypos);
2184 MapMainDrawingArea();
2187 static void DrawElementContentAreas()
2189 int *num_areas = &MampferMax;
2190 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2191 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2192 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2193 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2196 for (i=0; i<MAX_ELEMCONT; i++)
2199 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2201 for (i=0; i<MAX_ELEMCONT; i++)
2202 UnmapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2204 /* display counter to choose number of element content areas */
2205 gadget_areas_value = num_areas;
2206 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2207 x = counterbutton_info[ED_COUNTER_ELEMCONT].x + DXSIZE;
2208 y = counterbutton_info[ED_COUNTER_ELEMCONT].y;
2209 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2210 FC_YELLOW, "number of content areas");
2211 MapCounterButtons(ED_COUNTER_ELEMCONT);
2213 /* delete content areas in case of reducing number of them */
2214 XFillRectangle(display, backbuffer, gc,
2215 SX, area_sy - MINI_TILEX,
2216 SXSIZE, 12 * MINI_TILEY);
2218 /* draw some decorative border for the objects */
2219 for (i=0; i<*num_areas; i++)
2223 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2226 XFillRectangle(display, drawto, gc,
2227 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2228 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2229 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2232 /* copy border to the right location */
2233 XCopyArea(display, drawto, drawto, gc,
2234 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2235 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2237 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2238 "Content", FS_SMALL, FC_YELLOW);
2239 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2240 "when", FS_SMALL, FC_YELLOW);
2241 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2242 "smashed", FS_SMALL, FC_YELLOW);
2244 for (i=0; i<*num_areas; i++)
2248 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2249 ElementContent[i][x][y]);
2251 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2252 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2253 FC_YELLOW, "%d", i + 1);
2256 for (i=0; i<*num_areas; i++)
2257 MapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2260 static void DrawAmoebaContentArea()
2262 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2263 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2264 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2265 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2268 ElementContent[0][0][0] = level.amoebe_inhalt;
2270 /* draw decorative border for the object */
2273 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2275 XFillRectangle(display, drawto, gc,
2276 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2277 MINI_TILEX + 2, MINI_TILEY + 2);
2279 /* copy border to the right location */
2280 XCopyArea(display, drawto, drawto, gc,
2281 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2282 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2284 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2285 FS_SMALL, FC_YELLOW);
2287 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2289 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2292 #define TEXT_COLLECTING "Score for collecting"
2293 #define TEXT_SMASHING "Score for smashing"
2294 #define TEXT_CRACKING "Score for cracking"
2295 #define TEXT_SPEED "Speed of amoeba growth"
2296 #define TEXT_DURATION "Duration when activated"
2298 static void DrawPropertiesWindow()
2301 int num_elements_in_level;
2307 } elements_with_counter[] =
2309 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2310 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2311 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2312 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2313 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2314 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2315 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2316 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2317 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2318 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2319 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2320 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2321 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2322 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2323 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2324 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2325 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2326 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2327 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2328 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2329 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2330 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2331 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2332 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2333 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2334 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2335 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2336 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2337 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2338 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2339 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2340 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2341 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2342 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2343 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2344 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2345 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2346 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2347 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2348 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2349 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2354 UnmapLevelEditorWindowGadgets();
2356 /* draw some decorative border for the object */
2359 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2361 XFillRectangle(display, drawto, gc,
2362 SX + TILEX + MINI_TILEX/2 - 1,
2363 SY + TILEY + MINI_TILEY/2 - 1,
2364 TILEX + 2, TILEY + 2);
2366 /* copy border to the right location */
2367 XCopyArea(display, drawto, drawto, gc,
2368 SX + TILEX, SY + TILEY,
2369 2 * TILEX, 2 * TILEY,
2370 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2372 DrawGraphic(1, 1, el2gfx(properties_element));
2373 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2374 FS_SMALL, FC_YELLOW);
2376 num_elements_in_level = 0;
2377 for (y=0; y<lev_fieldy; y++)
2378 for (x=0; x<lev_fieldx; x++)
2379 if (Feld[x][y] == properties_element)
2380 num_elements_in_level++;
2382 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2383 num_elements_in_level);
2385 /* check if there are elements where a score can be chosen for */
2386 for (i=0; elements_with_counter[i].element != -1; i++)
2388 if (elements_with_counter[i].element == properties_element)
2390 int x = counterbutton_info[ED_COUNTER_SCORE].x + DXSIZE;
2391 int y = counterbutton_info[ED_COUNTER_SCORE].y;
2393 gadget_score_value = elements_with_counter[i].counter_value;
2394 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2395 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2396 FC_YELLOW, elements_with_counter[i].text);
2397 MapCounterButtons(ED_COUNTER_SCORE);
2402 if (HAS_CONTENT(properties_element))
2404 if (IS_AMOEBOID(properties_element))
2405 DrawAmoebaContentArea();
2407 DrawElementContentAreas();
2410 /* TEST ONLY: level name text input gadget */
2411 MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2414 static void swap_numbers(int *i1, int *i2)
2422 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2434 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2436 int lx = sx + level_xpos;
2437 int ly = sy + level_ypos;
2439 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2442 Feld[lx][ly] = element;
2445 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2446 int element, boolean change_level)
2448 if (from_y == to_y) /* horizontal line */
2454 swap_numbers(&from_x, &to_x);
2456 for (x=from_x; x<=to_x; x++)
2457 DrawLineElement(x, y, element, change_level);
2459 else if (from_x == to_x) /* vertical line */
2465 swap_numbers(&from_y, &to_y);
2467 for (y=from_y; y<=to_y; y++)
2468 DrawLineElement(x, y, element, change_level);
2470 else /* diagonal line */
2472 int len_x = ABS(to_x - from_x);
2473 int len_y = ABS(to_y - from_y);
2476 if (len_y < len_x) /* a < 1 */
2478 float a = (float)len_y / (float)len_x;
2481 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2483 for (x=0; x<=len_x; x++)
2485 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2487 DrawLineElement(from_x + x, from_y + y, element, change_level);
2492 float a = (float)len_x / (float)len_y;
2495 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2497 for (y=0; y<=len_y; y++)
2499 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2501 DrawLineElement(from_x + x, from_y + y, element, change_level);
2507 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2508 int element, boolean change_level)
2510 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2511 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2512 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2513 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2516 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2517 int element, boolean change_level)
2522 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2524 for (y=from_y; y<=to_y; y++)
2525 DrawLine(from_x, y, to_x, y, element, change_level);
2528 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2530 int from_sx, from_sy;
2534 swap_numbers(&from_x, &to_x);
2537 swap_numbers(&from_y, &to_y);
2539 from_sx = SX + from_x * MINI_TILEX;
2540 from_sy = SY + from_y * MINI_TILEY;
2541 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2542 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2544 XSetForeground(display, gc, WhitePixel(display, screen));
2546 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2547 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2548 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2549 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2551 XSetForeground(display, gc, BlackPixel(display, screen));
2553 if (from_x == to_x && from_y == to_y)
2554 MarkTileDirty(from_x/2, from_y/2);
2556 redraw_mask |= REDRAW_FIELD;
2559 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2560 int element, boolean change_level)
2562 if (element == -1 || change_level)
2563 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2565 DrawAreaBorder(from_x, from_y, to_x, to_y);
2568 /* values for CopyBrushExt() */
2569 #define CB_AREA_TO_BRUSH 0
2570 #define CB_BRUSH_TO_CURSOR 1
2571 #define CB_BRUSH_TO_LEVEL 2
2572 #define CB_DELETE_OLD_CURSOR 3
2574 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
2575 int button, int mode)
2577 static short brush_buffer[ED_FIELDX][ED_FIELDY];
2578 static int brush_width, brush_height;
2579 static int last_cursor_x = -1, last_cursor_y = -1;
2580 static boolean delete_old_brush;
2584 if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush)
2587 new_element = (button == 1 ? new_element1 :
2588 button == 2 ? new_element2 :
2589 button == 3 ? new_element3 : 0);
2591 if (mode == CB_AREA_TO_BRUSH)
2593 int from_lx, from_ly;
2596 swap_numbers(&from_x, &to_x);
2599 swap_numbers(&from_y, &to_y);
2601 brush_width = to_x - from_x + 1;
2602 brush_height = to_y - from_y + 1;
2604 from_lx = from_x + level_xpos;
2605 from_ly = from_y + level_ypos;
2607 for (y=0; y<brush_height; y++)
2609 for (x=0; x<brush_width; x++)
2611 brush_buffer[x][y] = Feld[from_lx + x][from_ly + y];
2614 DrawLineElement(from_x + x, from_y + y, new_element, TRUE);
2619 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2621 delete_old_brush = FALSE;
2623 else if (mode == CB_BRUSH_TO_CURSOR || mode == CB_DELETE_OLD_CURSOR ||
2624 mode == CB_BRUSH_TO_LEVEL)
2626 int cursor_x = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_x : from_x);
2627 int cursor_y = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_y : from_y);
2628 int cursor_from_x = cursor_x - brush_width / 2;
2629 int cursor_from_y = cursor_y - brush_height / 2;
2630 int border_from_x = cursor_x, border_from_y = cursor_y;
2631 int border_to_x = cursor_x, border_to_y = cursor_y;
2633 if (mode != CB_DELETE_OLD_CURSOR && delete_old_brush)
2634 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2636 if (!IN_LEV_FIELD(cursor_x + level_xpos, cursor_y + level_ypos))
2638 delete_old_brush = FALSE;
2642 for (y=0; y<brush_height; y++)
2644 for (x=0; x<brush_width; x++)
2646 int sx = cursor_from_x + x;
2647 int sy = cursor_from_y + y;
2648 int lx = sx + level_xpos;
2649 int ly = sy + level_ypos;
2650 boolean change_level = (mode == CB_BRUSH_TO_LEVEL);
2651 int element = (mode == CB_DELETE_OLD_CURSOR ? -1 :
2652 mode == CB_BRUSH_TO_CURSOR || button == 1 ?
2653 brush_buffer[x][y] : new_element);
2655 if (IN_LEV_FIELD(lx, ly) &&
2656 sx >=0 && sx < ED_FIELDX && sy >=0 && sy < ED_FIELDY)
2658 if (sx < border_from_x)
2660 else if (sx > border_to_x)
2662 if (sy < border_from_y)
2664 else if (sy > border_to_y)
2667 DrawLineElement(sx, sy, element, change_level);
2673 printf("%d, %d - %d, %d in level and screen\n",
2674 border_from_x, border_from_y, border_to_x, border_to_y);
2677 if (mode != CB_DELETE_OLD_CURSOR)
2678 DrawAreaBorder(border_from_x, border_from_y, border_to_x, border_to_y);
2681 if (mode == CB_BRUSH_TO_LEVEL)
2682 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2685 last_cursor_x = cursor_x;
2686 last_cursor_y = cursor_y;
2687 delete_old_brush = TRUE;
2691 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y,
2694 CopyBrushExt(from_x, from_y, to_x, to_y, button, CB_AREA_TO_BRUSH);
2697 static void CopyBrushToLevel(int x, int y, int button)
2699 CopyBrushExt(x, y, 0, 0, button, CB_BRUSH_TO_LEVEL);
2702 static void CopyBrushToCursor(int x, int y)
2704 CopyBrushExt(x, y, 0, 0, 0, CB_BRUSH_TO_CURSOR);
2707 static void DeleteBrushFromCursor()
2709 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2712 static void FloodFill(int from_x, int from_y, int fill_element)
2716 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2717 static int safety = 0;
2719 /* check if starting field still has the desired content */
2720 if (Feld[from_x][from_y] == fill_element)
2725 if (safety > lev_fieldx*lev_fieldy)
2726 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2728 old_element = Feld[from_x][from_y];
2729 Feld[from_x][from_y] = fill_element;
2733 x = from_x + check[i][0];
2734 y = from_y + check[i][1];
2736 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2737 FloodFill(x, y, fill_element);
2743 /* values for DrawLevelText() modes */
2745 #define TEXT_SETCURSOR 1
2746 #define TEXT_WRITECHAR 2
2747 #define TEXT_BACKSPACE 3
2748 #define TEXT_NEWLINE 4
2751 static void DrawLevelText(int sx, int sy, char letter, int mode)
2753 static short delete_buffer[MAX_LEV_FIELDX];
2754 static int start_sx, start_sy;
2755 static int last_sx, last_sy;
2756 static boolean typing = FALSE;
2757 int letter_element = EL_CHAR_ASCII0 + letter;
2760 /* map lower case letters to upper case and convert special characters */
2761 if (letter >= 'a' && letter <= 'z')
2762 letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
2763 else if (letter == 'ä' || letter == 'Ä')
2764 letter_element = EL_CHAR_AE;
2765 else if (letter == 'ö' || letter == 'Ö')
2766 letter_element = EL_CHAR_OE;
2767 else if (letter == 'ü' || letter == 'Ü')
2768 letter_element = EL_CHAR_UE;
2769 else if (letter == '^')
2770 letter_element = EL_CHAR_COPY;
2772 letter_element = EL_CHAR_ASCII0 + letter;
2774 if (mode != TEXT_INIT)
2779 if (mode != TEXT_SETCURSOR)
2785 lx = last_sx + level_xpos;
2786 ly = last_sy + level_ypos;
2793 DrawLevelText(0, 0, 0, TEXT_END);
2796 start_sx = last_sx = sx;
2797 start_sy = last_sy = sy;
2798 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2801 case TEXT_SETCURSOR:
2802 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2803 DrawAreaBorder(sx, sy, sx, sy);
2808 case TEXT_WRITECHAR:
2809 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2811 delete_buffer[sx - start_sx] = Feld[lx][ly];
2812 Feld[lx][ly] = letter_element;
2814 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
2815 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2816 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
2817 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2819 DrawLevelText(0, 0, 0, TEXT_END);
2823 case TEXT_BACKSPACE:
2826 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2827 DrawMiniElement(sx - 1, sy, new_element3);
2828 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2833 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2834 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2836 DrawLevelText(0, 0, 0, TEXT_END);
2840 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2841 DrawMiniElement(sx, sy, Feld[lx][ly]);
2850 static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
2851 int element, boolean change_level)
2853 int lx = sx + level_xpos;
2854 int ly = sy + level_ypos;
2857 DrawMiniElement(sx, sy, Feld[lx][ly]);
2859 DrawAreaBorder(sx, sy, sx, sy);
2862 static void CopyLevelToUndoBuffer(int mode)
2864 static boolean accumulated_undo = FALSE;
2865 boolean new_undo_buffer_position = TRUE;
2870 case UNDO_IMMEDIATE:
2871 accumulated_undo = FALSE;
2874 case UNDO_ACCUMULATE:
2875 if (accumulated_undo)
2876 new_undo_buffer_position = FALSE;
2877 accumulated_undo = TRUE;
2884 if (new_undo_buffer_position)
2886 /* new position in undo buffer ring */
2887 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2889 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2890 undo_buffer_steps++;
2893 for(x=0; x<lev_fieldx; x++)
2894 for(y=0; y<lev_fieldy; y++)
2895 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2898 printf("level saved to undo buffer\n");
2903 static void RandomPlacement(int button)
2908 new_element = (button == 1 ? new_element1 :
2909 button == 2 ? new_element2 :
2910 button == 3 ? new_element3 : 0);
2912 if (random_placement_method == RANDOM_USE_PERCENTAGE)
2914 for(x=0; x<lev_fieldx; x++)
2915 for(y=0; y<lev_fieldy; y++)
2916 if (RND(100) < random_placement_percentage)
2917 Feld[x][y] = new_element;
2921 int elements_left = random_placement_num_objects;
2923 while (elements_left > 0)
2925 x = RND(lev_fieldx);
2926 y = RND(lev_fieldy);
2928 if (Feld[x][y] != new_element)
2930 Feld[x][y] = new_element;
2936 DrawMiniLevel(level_xpos, level_ypos);
2937 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2940 void WrapLevel(int dx, int dy)
2942 int wrap_dx = lev_fieldx - dx;
2943 int wrap_dy = lev_fieldy - dy;
2946 for(x=0; x<lev_fieldx; x++)
2947 for(y=0; y<lev_fieldy; y++)
2948 FieldBackup[x][y] = Feld[x][y];
2950 for(x=0; x<lev_fieldx; x++)
2951 for(y=0; y<lev_fieldy; y++)
2953 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
2955 DrawMiniLevel(level_xpos, level_ypos);
2956 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
2959 static void HandleDrawingAreas(struct GadgetInfo *gi)
2961 static boolean started_inside_drawing_area = FALSE;
2962 int id = gi->custom_id;
2963 boolean inside_drawing_area = !gi->event.off_borders;
2964 boolean button_press_event;
2965 boolean button_release_event;
2966 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
2968 int button = gi->event.button;
2969 int sx = gi->event.x, sy = gi->event.y;
2970 int min_sx = 0, min_sy = 0;
2971 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
2973 int min_lx = 0, min_ly = 0;
2974 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
2977 /* handle info callback for each invocation of action callback */
2978 gi->callback_info(gi);
2981 if (edit_mode != ED_MODE_DRAWING)
2985 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2986 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2988 /* make sure to stay inside drawing area boundaries */
2989 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
2990 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
2994 /* get positions inside level field */
2995 lx = sx + level_xpos;
2996 ly = sy + level_ypos;
2998 /* make sure to stay inside level field boundaries */
2999 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
3000 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
3002 /* correct drawing area positions accordingly */
3003 sx = lx - level_xpos;
3004 sy = ly - level_ypos;
3007 if (button_press_event)
3008 started_inside_drawing_area = inside_drawing_area;
3010 if (!started_inside_drawing_area)
3013 if (!button && !button_release_event)
3016 new_element = (button == 1 ? new_element1 :
3017 button == 2 ? new_element2 :
3018 button == 3 ? new_element3 : 0);
3020 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
3023 switch (drawing_function)
3025 case ED_CTRL_ID_SINGLE_ITEMS:
3028 if (button_release_event)
3029 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3034 if (draw_with_brush)
3035 CopyBrushToLevel(sx, sy, button);
3036 else if (new_element != Feld[lx][ly])
3038 if (new_element == EL_SPIELFIGUR)
3040 /* remove player at old position */
3041 for(y=0; y<lev_fieldy; y++)
3043 for(x=0; x<lev_fieldx; x++)
3045 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
3047 Feld[x][y] = EL_LEERRAUM;
3048 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
3049 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
3050 DrawMiniElement(x - level_xpos, y - level_ypos,
3057 Feld[lx][ly] = new_element;
3058 DrawMiniElement(sx, sy, new_element);
3063 DrawMiniGraphicExt(drawto, gc,
3064 gi->x + sx * MINI_TILEX,
3065 gi->y + sy * MINI_TILEY,
3066 el2gfx(new_element));
3067 DrawMiniGraphicExt(window, gc,
3068 gi->x + sx * MINI_TILEX,
3069 gi->y + sy * MINI_TILEY,
3070 el2gfx(new_element));
3072 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3073 level.amoebe_inhalt = new_element;
3074 else if (id >= ED_CTRL_ID_ELEMCONT_0 && id <= ED_CTRL_ID_ELEMCONT_7)
3075 level.mampfer_inhalt[id - ED_CTRL_ID_ELEMCONT_0][sx][sy] =
3080 case ED_CTRL_ID_CONNECTED_ITEMS:
3082 static int last_sx = -1;
3083 static int last_sy = -1;
3085 if (button_release_event)
3086 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3090 if (!button_press_event)
3091 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
3099 case ED_CTRL_ID_LINE:
3100 case ED_CTRL_ID_RECTANGLE:
3101 case ED_CTRL_ID_FILLED_BOX:
3102 case ED_CTRL_ID_GRAB_BRUSH:
3103 case ED_CTRL_ID_TEXT:
3105 static int last_sx = -1;
3106 static int last_sy = -1;
3107 static int start_sx = -1;
3108 static int start_sy = -1;
3109 void (*draw_func)(int, int, int, int, int, boolean);
3111 if (drawing_function == ED_CTRL_ID_LINE)
3112 draw_func = DrawLine;
3113 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
3114 draw_func = DrawRectangle;
3115 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
3116 draw_func = DrawFilledBox;
3117 else if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3118 draw_func = SelectArea;
3119 else /* (drawing_function == ED_CTRL_ID_TEXT) */
3120 draw_func = SetTextCursor;
3122 if (button_press_event)
3124 draw_func(sx, sy, sx, sy, new_element, FALSE);
3125 start_sx = last_sx = sx;
3126 start_sy = last_sy = sy;
3128 if (drawing_function == ED_CTRL_ID_TEXT)
3129 DrawLevelText(0, 0, 0, TEXT_END);
3131 else if (button_release_event)
3133 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
3134 if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3136 CopyAreaToBrush(start_sx, start_sy, sx, sy, button);
3137 CopyBrushToCursor(sx, sy);
3138 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
3139 draw_with_brush = TRUE;
3141 else if (drawing_function == ED_CTRL_ID_TEXT)
3142 DrawLevelText(sx, sy, 0, TEXT_INIT);
3144 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3146 else if (last_sx != sx || last_sy != sy)
3148 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
3149 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
3159 case ED_CTRL_ID_TEXT:
3161 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3162 DrawAreaBorder(sx, sy, sx, sy);
3167 if (button_press_event)
3168 DrawLevelText(sx, sy, 0, TEXT_INIT);
3174 case ED_CTRL_ID_FLOOD_FILL:
3175 if (button_press_event && Feld[lx][ly] != new_element)
3177 FloodFill(lx, ly, new_element);
3178 DrawMiniLevel(level_xpos, level_ypos);
3179 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3183 case ED_CTRL_ID_PICK_ELEMENT:
3184 if (button_press_event)
3185 PickDrawingElement(button, Feld[lx][ly]);
3186 if (button_release_event)
3187 ClickOnGadget(level_editor_gadget[last_drawing_function]);
3195 static void HandleCounterButtons(struct GadgetInfo *gi)
3197 int id = gi->custom_id;
3198 int button = gi->event.button;
3199 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3203 case ED_CTRL_ID_SCORE_DOWN:
3204 case ED_CTRL_ID_SCORE_UP:
3205 *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
3206 if (*gadget_score_value < 0)
3207 *gadget_score_value = 0;
3208 else if (*gadget_score_value > 255)
3209 *gadget_score_value = 255;
3211 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
3214 case ED_CTRL_ID_ELEMCONT_DOWN:
3215 case ED_CTRL_ID_ELEMCONT_UP:
3216 *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step);
3217 if (*gadget_areas_value < 1)
3218 *gadget_areas_value = 1;
3219 else if (*gadget_areas_value > MAX_ELEMCONT)
3220 *gadget_areas_value = MAX_ELEMCONT;
3222 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
3223 DrawElementContentAreas();
3231 static void HandleControlButtons(struct GadgetInfo *gi)
3233 int id = gi->custom_id;
3234 int button = gi->event.button;
3235 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3237 int player_present = FALSE;
3238 int level_changed = FALSE;
3241 new_element = (button == 1 ? new_element1 :
3242 button == 2 ? new_element2 :
3243 button == 3 ? new_element3 : 0);
3245 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3246 DrawLevelText(0, 0, 0, TEXT_END);
3248 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3249 edit_mode != ED_MODE_DRAWING)
3251 DrawDrawingWindow();
3252 edit_mode = ED_MODE_DRAWING;
3257 case ED_CTRL_ID_SCROLL_LEFT:
3258 if (level_xpos >= 0)
3260 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3261 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3262 struct GadgetScrollbar *gs = &gi->scrollbar;
3264 if (lev_fieldx < ED_FIELDX - 2)
3268 if (level_xpos < -1)
3271 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3273 DrawMiniLevel(level_xpos, level_ypos);
3275 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3279 case ED_CTRL_ID_SCROLL_RIGHT:
3280 if (level_xpos <= lev_fieldx - ED_FIELDX)
3282 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3283 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3284 struct GadgetScrollbar *gs = &gi->scrollbar;
3286 if (lev_fieldx < ED_FIELDX - 2)
3290 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3291 level_xpos = lev_fieldx - ED_FIELDX + 1;
3293 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3295 DrawMiniLevel(level_xpos, level_ypos);
3297 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3301 case ED_CTRL_ID_SCROLL_UP:
3302 if (level_ypos >= 0)
3304 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3305 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3306 struct GadgetScrollbar *gs = &gi->scrollbar;
3308 if (lev_fieldy < ED_FIELDY - 2)
3312 if (level_ypos < -1)
3315 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3317 DrawMiniLevel(level_xpos, level_ypos);
3319 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3323 case ED_CTRL_ID_SCROLL_DOWN:
3324 if (level_ypos <= lev_fieldy - ED_FIELDY)
3326 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3327 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3328 struct GadgetScrollbar *gs = &gi->scrollbar;
3330 if (lev_fieldy < ED_FIELDY - 2)
3334 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3335 level_ypos = lev_fieldy - ED_FIELDY + 1;
3337 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3339 DrawMiniLevel(level_xpos, level_ypos);
3341 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3345 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3346 level_xpos = gi->event.item_position - 1;
3347 DrawMiniLevel(level_xpos, level_ypos);
3350 case ED_CTRL_ID_SCROLL_VERTICAL:
3351 level_ypos = gi->event.item_position - 1;
3352 DrawMiniLevel(level_xpos, level_ypos);
3355 case ED_CTRL_ID_WRAP_LEFT:
3356 WrapLevel(-step, 0);
3359 case ED_CTRL_ID_WRAP_RIGHT:
3363 case ED_CTRL_ID_WRAP_UP:
3364 WrapLevel(0, -step);
3367 case ED_CTRL_ID_WRAP_DOWN:
3371 case ED_CTRL_ID_SINGLE_ITEMS:
3372 case ED_CTRL_ID_CONNECTED_ITEMS:
3373 case ED_CTRL_ID_LINE:
3374 case ED_CTRL_ID_TEXT:
3375 case ED_CTRL_ID_RECTANGLE:
3376 case ED_CTRL_ID_FILLED_BOX:
3377 case ED_CTRL_ID_FLOOD_FILL:
3378 case ED_CTRL_ID_GRAB_BRUSH:
3379 case ED_CTRL_ID_PICK_ELEMENT:
3380 last_drawing_function = drawing_function;
3381 drawing_function = id;
3382 draw_with_brush = FALSE;
3385 case ED_CTRL_ID_RANDOM_PLACEMENT:
3386 RandomPlacement(button);
3389 case ED_CTRL_ID_PROPERTIES:
3390 if (edit_mode != ED_MODE_PROPERTIES)
3392 properties_element = new_element;
3393 DrawPropertiesWindow();
3394 edit_mode = ED_MODE_PROPERTIES;
3398 DrawDrawingWindow();
3399 edit_mode = ED_MODE_DRAWING;
3403 case ED_CTRL_ID_UNDO:
3404 if (undo_buffer_steps == 0)
3406 Request("Undo buffer empty !", REQ_CONFIRM);
3410 undo_buffer_position =
3411 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3412 undo_buffer_steps--;
3414 for(x=0; x<lev_fieldx; x++)
3415 for(y=0; y<lev_fieldy; y++)
3416 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3417 DrawMiniLevel(level_xpos,level_ypos);
3420 case ED_CTRL_ID_INFO:
3421 if (edit_mode != ED_MODE_INFO)
3423 DrawControlWindow();
3424 edit_mode = ED_MODE_INFO;
3428 DrawDrawingWindow();
3429 edit_mode = ED_MODE_DRAWING;
3433 case ED_CTRL_ID_CLEAR:
3434 for(x=0; x<MAX_LEV_FIELDX; x++)
3435 for(y=0; y<MAX_LEV_FIELDY; y++)
3436 Feld[x][y] = new_element3;
3437 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3439 DrawMiniLevel(level_xpos, level_ypos);
3442 case ED_CTRL_ID_SAVE:
3443 if (leveldir[leveldir_nr].readonly)
3445 Request("This level is read only !", REQ_CONFIRM);
3449 for(y=0; y<lev_fieldy; y++)
3450 for(x=0; x<lev_fieldx; x++)
3451 if (Feld[x][y] != Ur[x][y])
3452 level_changed = TRUE;
3454 if (0 && !level_changed)
3456 Request("Level has not changed !", REQ_CONFIRM);
3460 for(y=0; y<lev_fieldy; y++)
3461 for(x=0; x<lev_fieldx; x++)
3462 if (Feld[x][y] == EL_SPIELFIGUR ||
3463 Feld[x][y] == EL_SPIELER1 ||
3464 Feld[x][y] == EL_SP_MURPHY)
3465 player_present = TRUE;
3467 if (!player_present)
3468 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3471 if (Request("Save this level and kill the old ?", REQ_ASK))
3473 for(x=0; x<lev_fieldx; x++)
3474 for(y=0; y<lev_fieldy; y++)
3475 Ur[x][y] = Feld[x][y];
3476 SaveLevel(level_nr);
3481 case ED_CTRL_ID_TEST:
3482 for(y=0; y<lev_fieldy; y++)
3483 for(x=0; x<lev_fieldx; x++)
3484 if (Feld[x][y] == EL_SPIELFIGUR ||
3485 Feld[x][y] == EL_SPIELER1 ||
3486 Feld[x][y] == EL_SP_MURPHY)
3487 player_present = TRUE;
3489 if (!player_present)
3490 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3493 for(x=0; x<lev_fieldx; x++)
3494 for(y=0; y<lev_fieldy; y++)
3495 FieldBackup[x][y] = Ur[x][y];
3497 for(x=0; x<lev_fieldx; x++)
3498 for(y=0; y<lev_fieldy; y++)
3499 Ur[x][y] = Feld[x][y];
3501 UnmapLevelEditorGadgets();
3503 /* draw smaller door */
3504 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3505 DOOR_GFX_PAGEX7, 64,
3508 redraw_mask |= REDRAW_ALL;
3510 CloseDoor(DOOR_CLOSE_ALL);
3512 DrawCompleteVideoDisplay();
3514 if (setup.autorecord)
3515 TapeStartRecording();
3517 level_editor_test_game = TRUE;
3518 game_status = PLAYING;
3524 case ED_CTRL_ID_EXIT:
3525 for(y=0; y<lev_fieldy; y++)
3526 for(x=0; x<lev_fieldx; x++)
3527 if (Feld[x][y] != Ur[x][y])
3528 level_changed = TRUE;
3530 if (!level_changed ||
3531 Request("Level has changed! Exit without saving ?",
3532 REQ_ASK | REQ_STAY_OPEN))
3534 CloseDoor(DOOR_CLOSE_1);
3537 CloseDoor(DOOR_CLOSE_ALL);
3540 /* draw smaller door */
3541 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3542 DOOR_GFX_PAGEX7, 64,
3545 redraw_mask |= REDRAW_ALL;
3547 game_status = MAINMENU;
3552 CloseDoor(DOOR_CLOSE_1);
3553 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3554 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3555 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3556 OpenDoor(DOOR_OPEN_1);
3562 if (gi->event.type == GD_EVENT_PRESSED)
3563 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3564 else if (gi->event.type == GD_EVENT_RELEASED)
3565 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3566 else if (gi->event.type == GD_EVENT_MOVING)
3567 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3569 printf("default: HandleControlButtons: ?\n");
3575 void HandleLevelEditorKeyInput(KeySym key)
3577 if (edit_mode == ED_MODE_DRAWING)
3579 char letter = getCharFromKeySym(key);
3581 if (drawing_function == ED_CTRL_ID_TEXT)
3584 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3585 else if (key == XK_Delete || key == XK_BackSpace)
3586 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3587 else if (key == XK_Return)
3588 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3590 else if (button_status == MB_RELEASED)
3597 id = ED_CTRL_ID_SCROLL_LEFT;
3600 id = ED_CTRL_ID_SCROLL_RIGHT;
3603 id = ED_CTRL_ID_SCROLL_UP;
3606 id = ED_CTRL_ID_SCROLL_DOWN;
3610 id = ED_CTRL_ID_NONE;
3614 if (id != ED_CTRL_ID_NONE)
3615 ClickOnGadget(level_editor_gadget[id]);
3616 else if (letter == '.')
3617 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
3619 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
3620 if (letter && letter == control_info[i].shortcut)
3621 ClickOnGadget(level_editor_gadget[i]);
3626 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3628 int id = gi->custom_id;
3632 case ED_CTRL_ID_LEVEL_NAME:
3633 strcpy(level.name, gi->text.value);
3641 /* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
3642 #define INFOTEXT_XPOS SX
3643 #define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
3644 #define INFOTEXT_XSIZE SXSIZE
3645 #define INFOTEXT_YSIZE MINI_TILEX
3646 #define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
3648 void ClearEditorGadgetInfoText()
3650 XFillRectangle(display, drawto, gc,
3651 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
3652 redraw_mask |= REDRAW_FIELD;
3655 void HandleEditorGadgetInfoText(void *ptr)
3657 struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
3658 char infotext[MAX_INFOTEXT_LEN + 1];
3661 ClearEditorGadgetInfoText();
3663 /* misuse this function to delete brush cursor, if needed */
3664 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3665 DeleteBrushFromCursor();
3667 if (gi == NULL || gi->description_text == NULL)
3670 strncpy(infotext, gi->description_text, MAX_INFOTEXT_LEN);
3671 infotext[MAX_INFOTEXT_LEN] = '\0';
3673 if (gi->custom_id < ED_NUM_CTRL_BUTTONS)
3675 int key = control_info[gi->custom_id].shortcut;
3679 sprintf(shortcut, " ('%s%c')",
3680 (key >= 'A' && key <= 'Z' ? "Shift-" : ""), key);
3682 if (strlen(infotext) + strlen(shortcut) <= MAX_INFOTEXT_LEN)
3683 strcat(infotext, shortcut);
3687 DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW);
3690 static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
3692 static int start_lx, start_ly;
3694 int id = gi->custom_id;
3695 int sx = gi->event.x;
3696 int sy = gi->event.y;
3697 int lx = sx + level_xpos;
3698 int ly = sy + level_ypos;
3700 ClearEditorGadgetInfoText();
3702 if (id == ED_CTRL_ID_DRAWING_LEVEL)
3704 if (IN_LEV_FIELD(lx, ly))
3706 if (gi->state == GD_BUTTON_PRESSED)
3708 if (gi->event.type == GD_EVENT_PRESSED)
3714 switch (drawing_function)
3716 case ED_CTRL_ID_SINGLE_ITEMS:
3717 infotext = "Drawing single items";
3719 case ED_CTRL_ID_CONNECTED_ITEMS:
3720 infotext = "Drawing connected items";
3722 case ED_CTRL_ID_LINE:
3723 infotext = "Drawing line";
3725 case ED_CTRL_ID_TEXT:
3726 infotext = "Setting text cursor";
3728 case ED_CTRL_ID_RECTANGLE:
3729 infotext = "Drawing rectangle";
3731 case ED_CTRL_ID_FILLED_BOX:
3732 infotext = "Drawing filled box";
3734 case ED_CTRL_ID_FLOOD_FILL:
3735 infotext = "Flood fill";
3737 case ED_CTRL_ID_GRAB_BRUSH:
3738 infotext = "Grabbing brush";
3740 case ED_CTRL_ID_PICK_ELEMENT:
3741 infotext = "Picking element";
3745 infotext = "Drawing position";
3749 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3750 "%s: %d, %d", infotext,
3751 ABS(lx - start_lx) + 1,
3752 ABS(ly - start_ly) + 1);
3755 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3756 "Level position: %d, %d", lx, ly);
3759 /* misuse this function to draw brush cursor, if needed */
3760 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3761 CopyBrushToCursor(sx, sy);
3763 else if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3764 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3767 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3768 "Cruncher %d content: %d, %d", id - ED_CTRL_ID_ELEMCONT_0 + 1,