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)
77 /* values for counter gadgets */
78 #define ED_COUNT_VALUE_XOFFSET 5
79 #define ED_COUNT_VALUE_YOFFSET 3
80 #define ED_COUNT_SCORE_XPOS ED_PROPERTIES_XPOS
81 #define ED_COUNT_SCORE_YPOS (14 * MINI_TILEY)
82 #define ED_COUNT_ELEMCONT_XPOS ED_PROPERTIES_XPOS
83 #define ED_COUNT_ELEMCONT_YPOS (17 * MINI_TILEY)
85 /* values for element content drawing areas */
86 #define ED_AREA_ELEMCONT_XPOS (TILEX)
87 #define ED_AREA_ELEMCONT_YPOS (10 * TILEY)
89 /* values for scrolling gadgets */
90 #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
91 #define ED_SCROLL_UP_YPOS (0)
92 #define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
93 #define ED_SCROLL_DOWN_YPOS (SYSIZE - TILEX - ED_SCROLLBUTTON_YSIZE)
94 #define ED_SCROLL_LEFT_XPOS (0)
95 #define ED_SCROLL_LEFT_YPOS (SYSIZE - ED_SCROLLBUTTON_YSIZE)
96 #define ED_SCROLL_RIGHT_XPOS (SXSIZE - TILEX - ED_SCROLLBUTTON_XSIZE)
97 #define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
98 #define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
99 #define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + 20)
100 #define ED_SCROLL_VERTICAL_XSIZE 30
101 #define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - TILEY - 2 * 20)
102 #define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + 30)
103 #define ED_SCROLL_HORIZONTAL_YPOS (SYSIZE - 30)
104 #define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - TILEX - 2*30)
105 #define ED_SCROLL_HORIZONTAL_YSIZE 30
107 /* control button identifiers */
108 #define ED_CTRL_ID_SINGLE_ITEMS 0
109 #define ED_CTRL_ID_CONNECTED_ITEMS 1
110 #define ED_CTRL_ID_LINE 2
111 #define ED_CTRL_ID_TEXT 3
112 #define ED_CTRL_ID_RECTANGLE 4
113 #define ED_CTRL_ID_FILLED_BOX 5
114 #define ED_CTRL_ID_WRAP_UP 6
115 #define ED_CTRL_ID_PROPERTIES 7
116 #define ED_CTRL_ID_FLOOD_FILL 8
117 #define ED_CTRL_ID_WRAP_LEFT 9
118 #define ED_CTRL_ID_UNUSED1 10
119 #define ED_CTRL_ID_WRAP_RIGHT 11
120 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
121 #define ED_CTRL_ID_BRUSH 13
122 #define ED_CTRL_ID_WRAP_DOWN 14
123 #define ED_CTRL_ID_PICK_ELEMENT 15
124 #define ED_CTRL_ID_UNDO 16
125 #define ED_CTRL_ID_INFO 17
126 #define ED_CTRL_ID_SAVE 18
127 #define ED_CTRL_ID_CLEAR 19
128 #define ED_CTRL_ID_TEST 20
129 #define ED_CTRL_ID_EXIT 21
131 /* counter button identifiers */
132 #define ED_CTRL_ID_SCORE_DOWN 22
133 #define ED_CTRL_ID_SCORE_UP 23
134 #define ED_CTRL_ID_ELEMCONT_DOWN 24
135 #define ED_CTRL_ID_ELEMCONT_UP 25
137 /* drawing area identifiers */
138 #define ED_CTRL_ID_DRAWING_LEVEL 26
139 #define ED_CTRL_ID_ELEMCONT_0 27
140 #define ED_CTRL_ID_ELEMCONT_7 34
141 #define ED_CTRL_ID_AMOEBA_CONTENT 35
143 /* text input identifiers */
144 #define ED_CTRL_ID_LEVEL_NAME 36
146 /* gadgets for scrolling of drawing area */
147 #define ED_CTRL_ID_SCROLL_UP 37
148 #define ED_CTRL_ID_SCROLL_DOWN 38
149 #define ED_CTRL_ID_SCROLL_LEFT 39
150 #define ED_CTRL_ID_SCROLL_RIGHT 40
151 #define ED_CTRL_ID_SCROLL_VERTICAL 41
152 #define ED_CTRL_ID_SCROLL_HORIZONTAL 42
154 #define ED_NUM_GADGETS 43
156 /* values for counter gadgets */
157 #define ED_COUNTER_SCORE 0
158 #define ED_COUNTER_ELEMCONT 1
160 #define ED_NUM_COUNTERBUTTONS 2
161 #define ED_NUM_SCROLLBUTTONS 4
162 #define ED_NUM_SCROLLBARS 2
164 /* values for CopyLevelToUndoBuffer() */
165 #define UNDO_IMMEDIATE 0
166 #define UNDO_ACCUMULATE 1
172 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
174 { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN },
175 { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, ED_CTRL_ID_ELEMCONT_DOWN }
183 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
185 { ED_BUTTON_UP_XPOS, ED_BUTTON_UP_YPOS,
186 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP },
187 { ED_BUTTON_DOWN_XPOS, ED_BUTTON_DOWN_YPOS,
188 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN },
189 { ED_BUTTON_LEFT_XPOS, ED_BUTTON_LEFT_YPOS,
190 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT },
191 { ED_BUTTON_RIGHT_XPOS, ED_BUTTON_RIGHT_YPOS,
192 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT }
202 } scrollbar_info[ED_NUM_SCROLLBARS] =
204 { GAME_CONTROL_XPOS, GAME_CONTROL_YPOS - GAME_BUTTON_YSIZE,
205 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
206 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
207 GD_TYPE_SCROLLBAR_VERTICAL,
208 ED_CTRL_ID_SCROLL_VERTICAL },
209 { GAME_CONTROL_XPOS, GAME_CONTROL_YPOS - GAME_BUTTON_YSIZE,
210 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
211 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
212 GD_TYPE_SCROLLBAR_HORIZONTAL,
213 ED_CTRL_ID_SCROLL_HORIZONTAL },
217 /* forward declaration for internal use */
218 static void DrawDrawingWindow();
219 static void DrawPropertiesWindow();
220 static void CopyLevelToUndoBuffer(int);
221 static void HandleControlButtons(struct GadgetInfo *);
222 static void HandleCounterButtons(struct GadgetInfo *);
223 static void HandleDrawingAreas(struct GadgetInfo *);
224 static void HandleTextInputGadgets(struct GadgetInfo *);
226 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
227 static boolean level_editor_gadgets_created = FALSE;
229 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
230 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
231 static int properties_element = 0;
233 static short ElementContent[MAX_ELEMCONT][3][3];
234 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
235 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
236 static int undo_buffer_position = 0;
237 static int undo_buffer_steps = 0;
239 static int random_placement_percentage = 10;
240 static int random_placement_num_objects = 10;
242 static int random_placement_method = RANDOM_USE_PERCENTAGE;
244 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
247 /* pointer to score value */
248 static int *gadget_score_value;
249 static int *gadget_areas_value;
251 static int level_xpos,level_ypos;
252 static int edit_mode;
253 static boolean name_typing;
254 static int new_element1 = EL_MAUERWERK;
255 static int new_element2 = EL_LEERRAUM;
256 static int new_element3 = EL_ERDREICH;
258 int element_shift = 0;
260 int editor_element[] =
262 EL_CHAR_A + ('B' - 'A'),
263 EL_CHAR_A + ('O' - 'A'),
264 EL_CHAR_A + ('U' - 'A'),
265 EL_CHAR_A + ('L' - 'A'),
268 EL_CHAR_A + ('D' - 'A'),
269 EL_CHAR_A + ('E' - 'A'),
270 EL_CHAR_A + ('R' - 'A'),
272 EL_CHAR_A + ('D' - 'A'),
273 EL_CHAR_A + ('A' - 'A'),
274 EL_CHAR_A + ('S' - 'A'),
275 EL_CHAR_A + ('H' - 'A'),
302 EL_CHAR_A + ('E' - 'A'),
303 EL_CHAR_A + ('M' - 'A'),
304 EL_CHAR_A + ('E' - 'A'),
307 EL_CHAR_A + ('R' - 'A'),
308 EL_CHAR_A + ('A' - 'A'),
309 EL_CHAR_A + ('L' - 'A'),
310 EL_CHAR_A + ('D' - 'A'),
312 EL_CHAR_A + ('M' - 'A'),
313 EL_CHAR_A + ('I' - 'A'),
314 EL_CHAR_A + ('N' - 'A'),
315 EL_CHAR_A + ('E' - 'A'),
392 EL_CHAR_A + ('M' - 'A'),
393 EL_CHAR_A + ('O' - 'A'),
394 EL_CHAR_A + ('R' - 'A'),
395 EL_CHAR_A + ('E' - 'A'),
447 EL_CHAR_A + ('S' - 'A'),
448 EL_CHAR_A + ('O' - 'A'),
449 EL_CHAR_A + ('K' - 'A'),
450 EL_CHAR_A + ('O' - 'A'),
453 EL_CHAR_A + ('B' - 'A'),
454 EL_CHAR_A + ('A' - 'A'),
455 EL_CHAR_A + ('N' - 'A'),
458 EL_SOKOBAN_FELD_LEER,
459 EL_SOKOBAN_FELD_VOLL,
528 EL_CHAR_A + ('D' - 'A'),
529 EL_CHAR_A + ('Y' - 'A'),
530 EL_CHAR_A + ('N' - 'A'),
531 EL_CHAR_A + ('A' - 'A'),
533 EL_CHAR_A + ('B' - 'A'),
534 EL_CHAR_A + ('L' - 'A'),
535 EL_CHAR_A + ('A' - 'A'),
536 EL_CHAR_A + ('S' - 'A'),
539 EL_CHAR_A + ('T' - 'A'),
540 EL_CHAR_A + ('E' - 'A'),
541 EL_CHAR_A + ('R' - 'A'),
624 int elements_in_list = sizeof(editor_element)/sizeof(int);
626 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
629 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
630 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
632 XCopyArea(display, drawto, drawto, gc,
633 SX + (dx == -1 ? MINI_TILEX : 0),
634 SY + (dy == -1 ? MINI_TILEY : 0),
635 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
636 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
637 SX + (dx == +1 ? MINI_TILEX : 0),
638 SY + (dy == +1 ? MINI_TILEY : 0));
641 x = (dx == 1 ? 0 : ED_FIELDX - 1);
642 for(y=0; y<ED_FIELDY; y++)
643 DrawMiniElementOrWall(x, y, from_x, from_y);
647 y = (dy == 1 ? 0 : ED_FIELDY - 1);
648 for(x=0; x<ED_FIELDX; x++)
649 DrawMiniElementOrWall(x, y, from_x, from_y);
652 redraw_mask |= REDRAW_FIELD;
656 void InitLevelEditorGadgets()
660 for (i=0; i<ED_NUM_GADGETS; i++)
661 level_editor_gadget[i] = NULL;
664 static void CreateControlButtons()
666 Pixmap gd_pixmap = pix[PIX_DOOR];
667 struct GadgetInfo *gi;
668 unsigned long event_mask;
671 /* create toolbox buttons */
672 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
676 int gd_xoffset, gd_yoffset;
677 int gd_x1, gd_x2, gd_y1, gd_y2;
680 boolean radio_button_pressed;
682 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
683 id == ED_CTRL_ID_CONNECTED_ITEMS ||
684 id == ED_CTRL_ID_LINE ||
685 id == ED_CTRL_ID_TEXT ||
686 id == ED_CTRL_ID_RECTANGLE ||
687 id == ED_CTRL_ID_FILLED_BOX ||
688 id == ED_CTRL_ID_FLOOD_FILL ||
689 id == ED_CTRL_ID_BRUSH ||
690 id == ED_CTRL_ID_PICK_ELEMENT)
692 button_type = GD_TYPE_RADIO_BUTTON;
694 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
695 event_mask = GD_EVENT_PRESSED;
699 button_type = GD_TYPE_NORMAL_BUTTON;
701 radio_button_pressed = FALSE;
703 if (id == ED_CTRL_ID_WRAP_LEFT ||
704 id == ED_CTRL_ID_WRAP_RIGHT ||
705 id == ED_CTRL_ID_WRAP_UP ||
706 id == ED_CTRL_ID_WRAP_DOWN)
707 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
709 event_mask = GD_EVENT_RELEASED;
712 if (id < ED_NUM_CTRL1_BUTTONS)
714 int x = i % ED_CTRL1_BUTTONS_HORIZ;
715 int y = i / ED_CTRL1_BUTTONS_HORIZ;
717 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
718 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
719 width = ED_CTRL1_BUTTON_XSIZE;
720 height = ED_CTRL1_BUTTON_YSIZE;
724 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
725 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
727 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
728 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
729 width = ED_CTRL2_BUTTON_XSIZE;
730 height = ED_CTRL2_BUTTON_YSIZE;
733 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
734 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
735 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
736 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
738 gi = CreateGadget(GDI_CUSTOM_ID, id,
739 GDI_X, EX + gd_xoffset,
740 GDI_Y, EY + gd_yoffset,
743 GDI_TYPE, button_type,
744 GDI_STATE, GD_BUTTON_UNPRESSED,
745 GDI_RADIO_NR, radio_button_nr,
746 GDI_RADIO_PRESSED, radio_button_pressed,
747 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
748 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
749 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
750 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
751 GDI_EVENT_MASK, event_mask,
752 GDI_CALLBACK, HandleControlButtons,
756 Error(ERR_EXIT, "cannot create gadget");
758 level_editor_gadget[id] = gi;
761 /* create buttons for scrolling of drawing area */
762 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
764 int id = scrollbutton_info[i].gadget_id;
765 int gd_x1, gd_x2, gd_y;
767 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
769 gd_x1 = DOOR_GFX_PAGEX6 + scrollbutton_info[i].xpos;
770 gd_x2 = DOOR_GFX_PAGEX5 + scrollbutton_info[i].xpos;
771 gd_y = DOOR_GFX_PAGEY2 + scrollbutton_info[i].ypos;
773 gi = CreateGadget(GDI_CUSTOM_ID, id,
774 GDI_X, SX + scrollbutton_info[i].x,
775 GDI_Y, SY + scrollbutton_info[i].y,
776 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
777 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
778 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
779 GDI_STATE, GD_BUTTON_UNPRESSED,
780 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
781 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
782 GDI_EVENT_MASK, event_mask,
783 GDI_CALLBACK, HandleControlButtons,
787 Error(ERR_EXIT, "cannot create gadget");
789 level_editor_gadget[id] = gi;
793 static void CreateCounterButtons()
797 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
801 Pixmap gd_pixmap = pix[PIX_DOOR];
802 struct GadgetInfo *gi;
803 int id = counterbutton_info[i].gadget_id + j;
805 int gd_x1, gd_x2, gd_y;
806 unsigned long event_mask;
808 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
810 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
811 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
812 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
813 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
815 gi = CreateGadget(GDI_CUSTOM_ID, id,
816 GDI_X, SX + counterbutton_info[i].x + gd_xoffset,
817 GDI_Y, SY + counterbutton_info[i].y,
818 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
819 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
820 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
821 GDI_STATE, GD_BUTTON_UNPRESSED,
822 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
823 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
824 GDI_EVENT_MASK, event_mask,
825 GDI_CALLBACK, HandleCounterButtons,
829 Error(ERR_EXIT, "cannot create gadget");
831 level_editor_gadget[id] = gi;
836 static void CreateDrawingAreas()
838 struct GadgetInfo *gi;
839 unsigned long event_mask;
844 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
845 GD_EVENT_OFF_BORDERS;
847 /* one for the level drawing area ... */
848 id = ED_CTRL_ID_DRAWING_LEVEL;
849 gi = CreateGadget(GDI_CUSTOM_ID, id,
858 GDI_TYPE, GD_TYPE_DRAWING_AREA,
859 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
860 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
861 GDI_EVENT_MASK, event_mask,
862 GDI_CALLBACK, HandleDrawingAreas,
866 Error(ERR_EXIT, "cannot create gadget");
868 level_editor_gadget[id] = gi;
870 /* ... up to eight areas for element content ... */
871 for (i=0; i<MAX_ELEMCONT; i++)
873 int gx = SX + ED_AREA_ELEMCONT_XPOS + 5 * (i % 4) * MINI_TILEX;
874 int gy = SX + ED_AREA_ELEMCONT_YPOS + 6 * (i / 4) * MINI_TILEY;
876 id = ED_CTRL_ID_ELEMCONT_0 + i;
877 gi = CreateGadget(GDI_CUSTOM_ID, id,
880 GDI_WIDTH, 3 * MINI_TILEX,
881 GDI_HEIGHT, 3 * MINI_TILEY,
882 GDI_TYPE, GD_TYPE_DRAWING_AREA,
883 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
884 GDI_EVENT_MASK, event_mask,
885 GDI_CALLBACK, HandleDrawingAreas,
889 Error(ERR_EXIT, "cannot create gadget");
891 level_editor_gadget[id] = gi;
894 /* ... and one for the amoeba content */
895 id = ED_CTRL_ID_AMOEBA_CONTENT;
896 gi = CreateGadget(GDI_CUSTOM_ID, id,
897 GDI_X, SX + ED_AREA_ELEMCONT_XPOS,
898 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS,
899 GDI_WIDTH, MINI_TILEX,
900 GDI_HEIGHT, MINI_TILEY,
901 GDI_TYPE, GD_TYPE_DRAWING_AREA,
902 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
903 GDI_EVENT_MASK, event_mask,
904 GDI_CALLBACK, HandleDrawingAreas,
908 Error(ERR_EXIT, "cannot create gadget");
910 level_editor_gadget[id] = gi;
913 static void CreateTextInputGadgets()
915 Pixmap gd_pixmap = pix[PIX_DOOR];
917 struct GadgetInfo *gi;
918 unsigned long event_mask;
921 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
922 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
923 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
925 /* text input gadget for the level name */
926 id = ED_CTRL_ID_LEVEL_NAME;
927 gi = CreateGadget(GDI_CUSTOM_ID, id,
928 GDI_X, SX + ED_COUNT_ELEMCONT_XPOS,
929 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX,
930 GDI_TYPE, GD_TYPE_TEXTINPUT,
931 GDI_TEXT_VALUE, level.name,
933 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
934 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
935 GDI_DESIGN_BORDER, 3,
936 GDI_EVENT_MASK, event_mask,
937 GDI_CALLBACK, HandleTextInputGadgets,
941 Error(ERR_EXIT, "cannot create gadget");
943 level_editor_gadget[id] = gi;
946 static void CreateScrollbarGadgets()
950 for (i=0; i<ED_NUM_SCROLLBARS; i++)
952 int id = scrollbar_info[i].gadget_id;
953 Pixmap gd_pixmap = pix[PIX_DOOR];
954 int gd_x1, gd_x2, gd_y;
955 struct GadgetInfo *gi;
956 int items_max, items_visible, item_position;
957 unsigned long event_mask;
959 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
961 items_max = lev_fieldx + 2;
962 items_visible = ED_FIELDX;
967 items_max = lev_fieldy + 2;
968 items_visible = ED_FIELDY;
972 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
974 gd_x1 = DOOR_GFX_PAGEX4 + scrollbar_info[i].xpos;
975 gd_x2 = DOOR_GFX_PAGEX3 + scrollbar_info[i].xpos;
976 gd_y = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
978 gi = CreateGadget(GDI_CUSTOM_ID, id,
979 GDI_X, SX + scrollbar_info[i].x,
980 GDI_Y, SY + scrollbar_info[i].y,
981 GDI_WIDTH, scrollbar_info[i].width,
982 GDI_HEIGHT, scrollbar_info[i].height,
983 GDI_TYPE, scrollbar_info[i].type,
984 GDI_SCROLLBAR_ITEMS_MAX, items_max,
985 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
986 GDI_SCROLLBAR_ITEM_POSITION, item_position,
987 GDI_STATE, GD_BUTTON_UNPRESSED,
988 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
989 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
990 GDI_DESIGN_BORDER, 3,
991 GDI_EVENT_MASK, event_mask,
992 GDI_CALLBACK, HandleControlButtons,
996 Error(ERR_EXIT, "cannot create gadget");
998 level_editor_gadget[id] = gi;
1002 static void CreateLevelEditorGadgets()
1004 if (level_editor_gadgets_created)
1007 CreateControlButtons();
1008 CreateCounterButtons();
1009 CreateDrawingAreas();
1010 CreateTextInputGadgets();
1011 CreateScrollbarGadgets();
1013 level_editor_gadgets_created = TRUE;
1016 static void MapControlButtons()
1020 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1021 MapGadget(level_editor_gadget[i]);
1024 static void MapCounterButtons(int id)
1029 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id + i]);
1032 static void MapDrawingArea(int id)
1034 MapGadget(level_editor_gadget[id]);
1037 static void MapTextInputGadget(int id)
1039 MapGadget(level_editor_gadget[id]);
1042 static void MapMainDrawingArea()
1046 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1047 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1049 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1050 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1052 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1055 static void UnmapDrawingArea(int id)
1057 UnmapGadget(level_editor_gadget[id]);
1060 void UnmapLevelEditorWindowGadgets()
1064 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1065 UnmapGadget(level_editor_gadget[i]);
1068 void UnmapLevelEditorGadgets()
1072 for (i=0; i<ED_NUM_GADGETS; i++)
1073 UnmapGadget(level_editor_gadget[i]);
1078 int i, x, y, graphic;
1082 edit_mode = ED_MODE_DRAWING;
1083 name_typing = FALSE;
1085 CloseDoor(DOOR_CLOSE_ALL);
1087 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1089 if (level_editor_test_game)
1091 for(x=0; x<lev_fieldx; x++)
1092 for(y=0; y<lev_fieldy; y++)
1093 Feld[x][y] = Ur[x][y];
1095 for(x=0; x<lev_fieldx; x++)
1096 for(y=0; y<lev_fieldy; y++)
1097 Ur[x][y] = FieldBackup[x][y];
1099 level_editor_test_game = FALSE;
1103 undo_buffer_position = -1;
1104 undo_buffer_steps = -1;
1105 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1109 DrawMiniLevel(level_xpos, level_ypos);
1113 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1114 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1116 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1117 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1118 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1119 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1120 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1121 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1122 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1124 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1126 if (i < elements_in_list)
1127 graphic = el2gfx(editor_element[i + element_shift]);
1129 graphic = GFX_LEERRAUM;
1131 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1132 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1133 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1134 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1135 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1139 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1140 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1141 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1142 el2gfx(new_element1));
1143 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1144 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1145 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1146 el2gfx(new_element2));
1147 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1148 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1149 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1150 el2gfx(new_element3));
1151 DrawTextExt(pix[PIX_DB_DOOR],gc,
1152 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1153 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1154 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1155 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1156 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1157 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1159 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1160 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1161 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1162 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1163 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1165 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1166 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1168 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1169 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1171 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1173 /* draw bigger door */
1174 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1179 /* draw new control window */
1180 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1181 DOOR_GFX_PAGEX8, 236,
1185 redraw_mask |= REDRAW_ALL;
1187 OpenDoor(DOOR_OPEN_1);
1189 if (!level_editor_gadgets_created)
1190 CreateLevelEditorGadgets();
1192 MapControlButtons();
1195 MapMainDrawingArea();
1198 DrawDrawingWindow();
1202 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1206 void DrawControlWindow()
1211 UnmapLevelEditorWindowGadgets();
1213 /* Inhalt der Mampfer */
1214 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1215 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1216 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1218 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1219 XFillRectangle(display,drawto,gc,
1220 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1221 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1222 3*MINI_TILEX+2,3*MINI_TILEY+2);
1224 XCopyArea(display,drawto,drawto,gc,
1225 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1226 4*5*MINI_TILEX,5*MINI_TILEY,
1227 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1230 for(y=0;y<3;y++) for(x=0;x<3;x++)
1231 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1233 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1234 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1235 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1238 /* Inhalt der Amöbe */
1239 for(y=0;y<2;y++) for(x=0;x<2;x++)
1241 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1242 XFillRectangle(display,drawto,gc,
1243 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1244 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1245 MINI_TILEX+2,MINI_TILEY+2);
1247 XCopyArea(display,drawto,drawto,gc,
1248 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1249 3*MINI_TILEX,3*MINI_TILEY,
1250 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1251 DrawMiniElement(29,26,level.amoebe_inhalt);
1253 for(i=0;i<11+3+2;i++)
1255 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1256 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1257 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1258 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1259 ED_COUNT_GADGET_XPOS,
1260 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1263 DrawText(ED_COUNT_VALUE_XPOS,
1264 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1265 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1267 DrawText(ED_COUNT_VALUE_XPOS,
1268 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1269 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1271 DrawText(ED_COUNT_VALUE_XPOS,
1272 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1273 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1275 DrawText(ED_COUNT_VALUE_XPOS,
1276 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1277 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1279 DrawText(ED_COUNT_VALUE_XPOS,
1280 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1281 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1283 DrawText(ED_COUNT_VALUE_XPOS,
1284 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1285 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1288 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1289 "Score for Emerald",FS_SMALL,FC_YELLOW);
1290 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1291 "Score for Diamond",FS_SMALL,FC_YELLOW);
1292 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1293 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1294 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1295 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1296 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1297 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1298 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1299 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1300 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1301 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1302 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1303 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1304 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1305 "Score for dynamite",FS_SMALL,FC_YELLOW);
1306 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1307 "Score for key",FS_SMALL,FC_YELLOW);
1308 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1309 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1310 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1311 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1312 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1313 "Time for magic wall",FS_SMALL,FC_YELLOW);
1314 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1315 "Time for wheel",FS_SMALL,FC_YELLOW);
1316 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1317 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1318 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1319 "Time available for this level",FS_SMALL,FC_YELLOW);
1321 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1322 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1323 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1324 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1325 ED_COUNT_GADGET_XPOS,
1326 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1328 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1329 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1330 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1331 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1332 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1333 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1334 DrawText(ED_COUNT_GADGET_XPOS+5,
1335 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1336 level.name,FS_SMALL,FC_YELLOW);
1337 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1338 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1339 "Title",FS_SMALL,FC_YELLOW);
1341 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1342 "Playfield size:",FS_SMALL,FC_YELLOW);
1343 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1344 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1345 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1346 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1347 ED_SIZE_GADGET_XPOS,
1348 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1349 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1350 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1351 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1352 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1353 ED_SIZE_GADGET_XPOS,
1354 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1355 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1356 "Width",FS_SMALL,FC_YELLOW);
1357 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1358 "Height",FS_SMALL,FC_YELLOW);
1359 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1360 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1361 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1362 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1365 void AdjustLevelScrollPosition()
1367 if (level_xpos < -1)
1369 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1370 level_xpos = lev_fieldx - ED_FIELDX + 1;
1371 if (lev_fieldx < ED_FIELDX - 2)
1374 if (level_ypos < -1)
1376 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1377 level_ypos = lev_fieldy - ED_FIELDY + 1;
1378 if (lev_fieldy < ED_FIELDY - 2)
1382 static void PickDrawingElement(int button, int element)
1384 if (button < 1 || button > 3)
1389 new_element1 = element;
1390 DrawMiniGraphicExt(drawto, gc,
1391 DX + ED_WIN_MB_LEFT_XPOS,
1392 DY + ED_WIN_MB_LEFT_YPOS,
1393 el2gfx(new_element1));
1395 else if (button == 2)
1397 new_element2 = element;
1398 DrawMiniGraphicExt(drawto, gc,
1399 DX + ED_WIN_MB_MIDDLE_XPOS,
1400 DY + ED_WIN_MB_MIDDLE_YPOS,
1401 el2gfx(new_element2));
1405 new_element3 = element;
1406 DrawMiniGraphicExt(drawto, gc,
1407 DX + ED_WIN_MB_RIGHT_XPOS,
1408 DY + ED_WIN_MB_RIGHT_YPOS,
1409 el2gfx(new_element3));
1412 redraw_mask |= REDRAW_DOOR_1;
1415 void LevelEd(int mx, int my, int button)
1417 static int last_button = 0;
1418 static int in_field_pressed = FALSE;
1419 static boolean use_floodfill = FALSE;
1423 int x = (mx-SX)/MINI_TILEX;
1424 int y = (my-SY)/MINI_TILEY;
1428 HandlePressedControlButtons();
1429 HandleDrawingFunctions(mx, my, button);
1432 if (use_floodfill) /********** FLOOD FILL **********/
1440 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1445 if (x>lev_fieldx || y>lev_fieldy ||
1446 (x==0 && level_xpos<0) ||
1447 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1448 (y==0 && level_ypos<0) ||
1449 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1452 from_x = x+level_xpos;
1453 from_y = y+level_ypos;
1454 fill_element = (button==1 ? new_element1 :
1455 button==2 ? new_element2 :
1456 button==3 ? new_element3 : 0);
1458 FloodFill(from_x,from_y,fill_element);
1459 DrawMiniLevel(level_xpos,level_ypos);
1462 use_floodfill = FALSE;
1463 CloseDoor(DOOR_CLOSE_1);
1464 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1473 else /********** EDIT/CTRL-FENSTER **********/
1475 static unsigned long choice_delay = 0;
1476 int choice = CheckElemButtons(mx,my,button);
1477 int elem_pos = choice-ED_BUTTON_ELEM;
1479 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1480 (choice == ED_BUTTON_EDOWN &&
1481 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1482 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1484 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1488 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1490 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1492 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1493 element_shift += step;
1496 if (element_shift<0)
1498 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1499 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1500 if (element_shift % MAX_ELEM_X)
1501 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1503 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1504 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1506 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1510 if (elem_pos+element_shift < elements_in_list)
1511 new_element = editor_element[elem_pos+element_shift];
1513 new_element = EL_LEERRAUM;
1515 PickDrawingElement(last_button, new_element);
1517 if (!HAS_CONTENT(properties_element))
1519 properties_element = new_element;
1520 if (edit_mode == ED_MODE_PROPERTIES)
1521 DrawPropertiesWindow();
1525 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1532 switch(CheckEditButtons(mx,my,button))
1534 case ED_BUTTON_CTRL:
1535 CloseDoor(DOOR_CLOSE_2);
1536 DrawControlWindow();
1537 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1538 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1540 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1541 OpenDoor(DOOR_OPEN_2);
1542 edit_mode = ED_MODE_INFO;
1544 case ED_BUTTON_FILL:
1545 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1546 use_floodfill = TRUE;
1549 case ED_BUTTON_LEFT:
1552 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1554 if (lev_fieldx<ED_FIELDX-2)
1557 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1561 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1563 DrawMiniLevel(level_xpos,level_ypos);
1566 case ED_BUTTON_RIGHT:
1567 if (level_xpos<=lev_fieldx-ED_FIELDX)
1569 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1571 if (lev_fieldx<ED_FIELDX-2)
1574 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1575 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1576 level_xpos = lev_fieldx-ED_FIELDX+1;
1578 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1580 DrawMiniLevel(level_xpos,level_ypos);
1586 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1588 if (lev_fieldy<ED_FIELDY-2)
1591 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1595 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1597 DrawMiniLevel(level_xpos,level_ypos);
1600 case ED_BUTTON_DOWN:
1601 if (level_ypos<=lev_fieldy-ED_FIELDY)
1603 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1605 if (lev_fieldy<ED_FIELDY-2)
1608 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1609 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1610 level_ypos = lev_fieldy-ED_FIELDY+1;
1612 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1614 DrawMiniLevel(level_xpos,level_ypos);
1627 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1631 if (button && !motion_status)
1632 in_field_pressed = TRUE;
1634 if (!button || !in_field_pressed || button<1 || button>3 ||
1635 (y==0 && level_ypos<0) ||
1636 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1637 (x==0 && level_xpos<0) ||
1638 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1639 x>lev_fieldx || y>lev_fieldy)
1642 new_element = (button==1 ? new_element1 :
1643 button==2 ? new_element2 :
1644 button==3 ? new_element3 : 0);
1646 if (new_element != Feld[x+level_xpos][y+level_ypos])
1648 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1652 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1654 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1656 Feld[x][y] = EL_LEERRAUM;
1657 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1658 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1659 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1664 Feld[x+level_xpos][y+level_ypos] = new_element;
1665 DrawMiniElement(x,y,new_element);
1668 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1669 in_field_pressed = FALSE;
1676 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1678 int choice = CheckCountButtons(mx,my,button);
1679 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1681 if (choice >= 0 && choice < 36 &&
1682 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1691 level.score[choice] += step;
1692 if (level.score[choice]<0)
1693 level.score[choice] = 0;
1694 else if (level.score[choice]>255)
1695 level.score[choice] = 255;
1697 else if (choice==11)
1699 level.tempo_amoebe += step;
1700 if (level.tempo_amoebe<0)
1701 level.tempo_amoebe = 0;
1702 else if (level.tempo_amoebe>255)
1703 level.tempo_amoebe = 255;
1705 else if (choice==12)
1707 level.dauer_sieb += step;
1708 if (level.dauer_sieb<0)
1709 level.dauer_sieb = 0;
1710 else if (level.dauer_sieb>255)
1711 level.dauer_sieb = 255;
1713 else if (choice==13)
1715 level.dauer_ablenk += step;
1716 if (level.dauer_ablenk<0)
1717 level.dauer_ablenk = 0;
1718 else if (level.dauer_ablenk>255)
1719 level.dauer_ablenk = 255;
1721 else if (choice==14)
1723 level.edelsteine += step;
1724 if (level.edelsteine<0)
1725 level.edelsteine = 0;
1726 else if (level.edelsteine>999)
1727 level.edelsteine = 999;
1729 else if (choice==15)
1734 else if (level.time>999)
1737 else if (choice==16)
1740 if (lev_fieldx<MIN_LEV_FIELDX)
1741 lev_fieldx = MIN_LEV_FIELDX;
1742 else if (lev_fieldx>MAX_LEV_FIELDX)
1743 lev_fieldx = MAX_LEV_FIELDX;
1744 level.fieldx = lev_fieldx;
1746 else if (choice==17)
1749 if (lev_fieldy<MIN_LEV_FIELDY)
1750 lev_fieldy = MIN_LEV_FIELDY;
1751 else if (lev_fieldy>MAX_LEV_FIELDY)
1752 lev_fieldy = MAX_LEV_FIELDY;
1753 level.fieldy = lev_fieldy;
1757 DrawText(ED_COUNT_VALUE_XPOS,
1758 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1759 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1760 else if (choice==11)
1761 DrawText(ED_COUNT_VALUE_XPOS,
1762 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1763 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1764 else if (choice==12)
1765 DrawText(ED_COUNT_VALUE_XPOS,
1766 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1767 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1768 else if (choice==13)
1769 DrawText(ED_COUNT_VALUE_XPOS,
1770 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1771 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1772 else if (choice==14)
1773 DrawText(ED_COUNT_VALUE_XPOS,
1774 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1775 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1776 else if (choice==15)
1777 DrawText(ED_COUNT_VALUE_XPOS,
1778 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1779 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1780 else if (choice==16)
1781 DrawText(ED_SIZE_VALUE_XPOS,
1782 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1783 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1784 else if (choice==17)
1785 DrawText(ED_SIZE_VALUE_XPOS,
1786 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1787 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1789 redraw_mask &= ~REDRAW_FIELD;
1791 XCopyArea(display,drawto,window,gc,
1792 ED_COUNT_VALUE_XPOS,
1793 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1794 3*FONT2_XSIZE,FONT2_YSIZE,
1795 ED_COUNT_VALUE_XPOS,
1796 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1798 XCopyArea(display,drawto,window,gc,
1800 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1801 3*FONT2_XSIZE,FONT2_YSIZE,
1803 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1811 switch(CheckCtrlButtons(mx,my,button))
1813 case ED_BUTTON_EDIT:
1814 CloseDoor(DOOR_CLOSE_2);
1815 AdjustLevelScrollPosition();
1816 DrawMiniLevel(level_xpos,level_ypos);
1817 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1818 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1820 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1821 OpenDoor(DOOR_OPEN_2);
1822 edit_mode = ED_MODE_DRAWING;
1824 case ED_BUTTON_CLEAR:
1825 if (Request("Are you sure to clear this level ?",REQ_ASK))
1827 for(x=0;x<MAX_LEV_FIELDX;x++)
1828 for(y=0;y<MAX_LEV_FIELDY;y++)
1829 Feld[x][y] = EL_ERDREICH;
1830 DrawMiniLevel(level_xpos,level_ypos);
1833 case ED_BUTTON_UNDO:
1834 if (leveldir[leveldir_nr].readonly ||
1835 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1837 CloseDoor(DOOR_CLOSE_ALL);
1838 game_status=MAINMENU;
1843 CloseDoor(DOOR_CLOSE_1);
1844 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1847 case ED_BUTTON_EXIT:
1849 int figur_vorhanden = FALSE;
1851 if (leveldir[leveldir_nr].readonly)
1853 Request("This level is read only !",REQ_CONFIRM);
1857 for(y=0;y<lev_fieldy;y++)
1858 for(x=0;x<lev_fieldx;x++)
1859 if (Feld[x][y] == EL_SPIELFIGUR ||
1860 Feld[x][y] == EL_SPIELER1 ||
1861 Feld[x][y] == EL_SP_MURPHY)
1862 figur_vorhanden = TRUE;
1864 if (!figur_vorhanden)
1865 Request("No Level without Gregor Mc Duffin please !",
1869 if (Request("Save this level and kill the old ?",
1870 REQ_ASK | REQ_STAY_OPEN))
1872 for(x=0;x<lev_fieldx;x++)
1873 for(y=0;y<lev_fieldy;y++)
1874 Ur[x][y]=Feld[x][y];
1875 SaveLevel(level_nr);
1877 CloseDoor(DOOR_CLOSE_ALL);
1878 game_status=MAINMENU;
1891 if (mx>=ED_COUNT_GADGET_XPOS &&
1892 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1893 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1894 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1899 DrawText(ED_COUNT_GADGET_XPOS+5,
1900 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1901 level.name,FS_SMALL,FC_GREEN);
1902 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1903 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1904 "<",FS_SMALL,FC_RED);
1911 name_typing = FALSE;
1912 DrawText(ED_COUNT_GADGET_XPOS+5,
1913 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1914 level.name,FS_SMALL,FC_YELLOW);
1915 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1916 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1917 " ",FS_SMALL,FC_RED);
1921 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
1922 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
1926 if (!button || button<1 || button>3)
1929 new_element = (button==1 ? new_element1 :
1930 button==2 ? new_element2 :
1931 button==3 ? new_element3 : 0);
1933 if (new_element != level.amoebe_inhalt)
1935 level.amoebe_inhalt = new_element;
1936 DrawMiniElement(29,26,new_element);
1940 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
1941 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
1943 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
1944 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
1949 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
1951 if (button && !motion_status)
1952 in_field_pressed = TRUE;
1954 if (!button || !in_field_pressed || button<1 || button>3)
1957 new_element = (button==1 ? new_element1 :
1958 button==2 ? new_element2 :
1959 button==3 ? new_element3 : 0);
1961 if (new_element != level.mampfer_inhalt[i][x][y])
1963 level.mampfer_inhalt[i][x][y] = new_element;
1964 DrawMiniElement(1+5*i+x,2+y,new_element);
1967 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
1968 in_field_pressed = FALSE;
1970 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
1971 in_field_pressed = FALSE;
1975 last_button = button;
1980 void LevelNameTyping(KeySym key)
1982 unsigned char ascii = 0;
1983 int len = strlen(level.name);
1988 if (key>=XK_A && key<=XK_Z)
1989 ascii = 'A'+(char)(key-XK_A);
1990 else if (key>=XK_a && key<=XK_z)
1991 ascii = 'a'+(char)(key-XK_a);
1992 else if (key>=XK_0 && key<=XK_9)
1993 ascii = '0'+(char)(key-XK_0);
1995 else if (key>=XK_space && key<=XK_at)
1996 ascii = ' '+(char)(key-XK_space);
1997 else if (key==XK_Adiaeresis)
1999 else if (key==XK_Odiaeresis)
2001 else if (key==XK_Udiaeresis)
2003 else if (key==XK_adiaeresis)
2005 else if (key==XK_odiaeresis)
2007 else if (key==XK_udiaeresis)
2009 else if (key==XK_underscore)
2013 if (ascii && len<MAX_LEVNAMLEN-2)
2015 level.name[len] = ascii;
2016 level.name[len+1] = 0;
2019 DrawTextExt(drawto,gc,
2020 ED_COUNT_GADGET_XPOS+5,
2021 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2022 level.name,FS_SMALL,FC_GREEN);
2023 DrawTextExt(window,gc,
2024 ED_COUNT_GADGET_XPOS+5,
2025 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2026 level.name,FS_SMALL,FC_GREEN);
2027 DrawTextExt(drawto,gc,
2028 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2029 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2030 "<",FS_SMALL,FC_RED);
2031 DrawTextExt(window,gc,
2032 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2033 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2034 "<",FS_SMALL,FC_RED);
2036 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2038 level.name[len-1] = 0;
2041 DrawTextExt(drawto,gc,
2042 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2043 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2044 "< ",FS_SMALL,FC_GREEN);
2045 DrawTextExt(window,gc,
2046 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2047 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2048 "< ",FS_SMALL,FC_GREEN);
2050 else if (key==XK_Return)
2052 DrawTextExt(drawto,gc,
2053 ED_COUNT_GADGET_XPOS+5,
2054 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2055 level.name,FS_SMALL,FC_YELLOW);
2056 DrawTextExt(window,gc,
2057 ED_COUNT_GADGET_XPOS+5,
2058 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2059 level.name,FS_SMALL,FC_YELLOW);
2060 DrawTextExt(drawto,gc,
2061 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2062 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2063 " ",FS_SMALL,FC_YELLOW);
2064 DrawTextExt(window,gc,
2065 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2066 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2067 " ",FS_SMALL,FC_YELLOW);
2069 name_typing = FALSE;
2073 static void DrawCounterValueField(int counter_id, int value)
2075 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2076 int y = SY + counterbutton_info[counter_id].y;
2078 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2079 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2080 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2081 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2084 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2085 int2str(value, 3), FS_SMALL, FC_YELLOW);
2088 static void DrawDrawingWindow()
2091 UnmapLevelEditorWindowGadgets();
2092 MapMainDrawingArea();
2093 AdjustLevelScrollPosition();
2094 DrawMiniLevel(level_xpos, level_ypos);
2097 static void DrawElementContentAreas()
2099 int *num_areas = &MampferMax;
2100 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2101 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2102 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2103 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2106 for (i=0; i<MAX_ELEMCONT; i++)
2109 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2111 for (i=0; i<MAX_ELEMCONT; i++)
2112 UnmapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2114 /* display counter to choose number of element content areas */
2115 gadget_areas_value = num_areas;
2116 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2117 x = counterbutton_info[ED_COUNTER_ELEMCONT].x + DXSIZE;
2118 y = counterbutton_info[ED_COUNTER_ELEMCONT].y;
2119 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2120 FC_YELLOW, "number of content areas");
2121 MapCounterButtons(ED_COUNTER_ELEMCONT);
2123 /* delete content areas in case of reducing number of them */
2124 XFillRectangle(display, backbuffer, gc,
2125 SX, area_sy - MINI_TILEX,
2126 SXSIZE, 12 * MINI_TILEY);
2128 /* draw some decorative border for the objects */
2129 for (i=0; i<*num_areas; i++)
2133 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2136 XFillRectangle(display, drawto, gc,
2137 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2138 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2139 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2142 /* copy border to the right location */
2143 XCopyArea(display, drawto, drawto, gc,
2144 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2145 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2147 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2148 "Content", FS_SMALL, FC_YELLOW);
2149 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2150 "when", FS_SMALL, FC_YELLOW);
2151 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2152 "smashed", FS_SMALL, FC_YELLOW);
2154 for (i=0; i<*num_areas; i++)
2158 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2159 ElementContent[i][x][y]);
2161 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2162 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2163 FC_YELLOW, "%d", i + 1);
2166 for (i=0; i<*num_areas; i++)
2167 MapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2170 static void DrawAmoebaContentArea()
2172 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2173 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2174 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2175 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2178 ElementContent[0][0][0] = level.amoebe_inhalt;
2180 /* draw decorative border for the object */
2183 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2185 XFillRectangle(display, drawto, gc,
2186 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2187 MINI_TILEX + 2, MINI_TILEY + 2);
2189 /* copy border to the right location */
2190 XCopyArea(display, drawto, drawto, gc,
2191 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2192 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2194 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2195 FS_SMALL, FC_YELLOW);
2197 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2199 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2202 #define TEXT_COLLECTING "Score for collecting"
2203 #define TEXT_SMASHING "Score for smashing"
2204 #define TEXT_CRACKING "Score for cracking"
2205 #define TEXT_SPEED "Speed of amoeba growth"
2206 #define TEXT_DURATION "Duration when activated"
2208 static void DrawPropertiesWindow()
2211 int num_elements_in_level;
2217 } elements_with_counter[] =
2219 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2220 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2221 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2222 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2223 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2224 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2225 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2226 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2227 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2228 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2229 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2230 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2231 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2232 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2233 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2234 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2235 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2236 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2237 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2238 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2239 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2240 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2241 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2242 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2243 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2244 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2245 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2246 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2247 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2248 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2249 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2250 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2251 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2252 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2253 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2254 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2255 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2256 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2257 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2258 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2259 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2264 UnmapLevelEditorWindowGadgets();
2266 /* draw some decorative border for the object */
2269 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2271 XFillRectangle(display, drawto, gc,
2272 SX + TILEX + MINI_TILEX/2 - 1,
2273 SY + TILEY + MINI_TILEY/2 - 1,
2274 TILEX + 2, TILEY + 2);
2276 /* copy border to the right location */
2277 XCopyArea(display, drawto, drawto, gc,
2278 SX + TILEX, SY + TILEY,
2279 2 * TILEX, 2 * TILEY,
2280 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2282 DrawGraphic(1, 1, el2gfx(properties_element));
2283 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2284 FS_SMALL, FC_YELLOW);
2286 num_elements_in_level = 0;
2287 for (y=0; y<lev_fieldy; y++)
2288 for (x=0; x<lev_fieldx; x++)
2289 if (Feld[x][y] == properties_element)
2290 num_elements_in_level++;
2292 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2293 num_elements_in_level);
2295 /* check if there are elements where a score can be chosen for */
2296 for (i=0; elements_with_counter[i].element != -1; i++)
2298 if (elements_with_counter[i].element == properties_element)
2300 int x = counterbutton_info[ED_COUNTER_SCORE].x + DXSIZE;
2301 int y = counterbutton_info[ED_COUNTER_SCORE].y;
2303 gadget_score_value = elements_with_counter[i].counter_value;
2304 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2305 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2306 FC_YELLOW, elements_with_counter[i].text);
2307 MapCounterButtons(ED_COUNTER_SCORE);
2312 if (HAS_CONTENT(properties_element))
2314 if (IS_AMOEBOID(properties_element))
2315 DrawAmoebaContentArea();
2317 DrawElementContentAreas();
2320 /* TEST ONLY: level name text input gadget */
2321 MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2324 static void swap_numbers(int *i1, int *i2)
2332 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2344 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2346 int lx = sx + level_xpos;
2347 int ly = sy + level_ypos;
2349 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2352 Feld[lx][ly] = element;
2355 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2356 int element, boolean change_level)
2358 if (from_y == to_y) /* horizontal line */
2364 swap_numbers(&from_x, &to_x);
2366 for (x=from_x; x<=to_x; x++)
2367 DrawLineElement(x, y, element, change_level);
2369 else if (from_x == to_x) /* vertical line */
2375 swap_numbers(&from_y, &to_y);
2377 for (y=from_y; y<=to_y; y++)
2378 DrawLineElement(x, y, element, change_level);
2380 else /* diagonal line */
2382 int len_x = ABS(to_x - from_x);
2383 int len_y = ABS(to_y - from_y);
2386 if (len_y < len_x) /* a < 1 */
2388 float a = (float)len_y / (float)len_x;
2391 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2393 for (x=0; x<=len_x; x++)
2395 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2397 DrawLineElement(from_x + x, from_y + y, element, change_level);
2402 float a = (float)len_x / (float)len_y;
2405 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2407 for (y=0; y<=len_y; y++)
2409 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2411 DrawLineElement(from_x + x, from_y + y, element, change_level);
2417 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2418 int element, boolean change_level)
2420 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2421 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2422 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2423 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2426 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2427 int element, boolean change_level)
2432 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2434 for (y=from_y; y<=to_y; y++)
2435 DrawLine(from_x, y, to_x, y, element, change_level);
2438 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2440 int from_sx, from_sy;
2444 swap_numbers(&from_x, &to_x);
2447 swap_numbers(&from_y, &to_y);
2449 from_sx = SX + from_x * MINI_TILEX;
2450 from_sy = SY + from_y * MINI_TILEY;
2451 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2452 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2454 XSetForeground(display, gc, WhitePixel(display, screen));
2456 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2457 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2458 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2459 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2461 XSetForeground(display, gc, BlackPixel(display, screen));
2463 if (from_x == to_x && from_y == to_y)
2464 MarkTileDirty(from_x/2, from_y/2);
2466 redraw_mask |= REDRAW_FIELD;
2469 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2470 int element, boolean change_level)
2472 if (element == -1 || change_level)
2473 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2475 DrawAreaBorder(from_x, from_y, to_x, to_y);
2478 /* values for CopyBrushExt() */
2479 #define CB_AREA_TO_BRUSH 0
2480 #define CB_BRUSH_TO_LEVEL 1
2482 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode)
2484 static short brush_buffer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
2485 static brush_from_x, brush_from_y;
2486 static brush_to_x, brush_to_y;
2490 swap_numbers(&from_x, &to_x);
2493 swap_numbers(&from_y, &to_y);
2495 if (mode == CB_AREA_TO_BRUSH)
2497 for (y=from_y; y<=to_y; y++)
2498 for (x=from_x; x<=to_x; x++)
2499 brush_buffer[x][y] = Feld[x][y];
2501 brush_from_x = from_x;
2502 brush_from_y = from_y;
2508 for (y=brush_from_y; y<=brush_to_y; y++)
2509 for (x=brush_from_x; x<=brush_to_x; x++)
2510 Feld[x][y] = brush_buffer[x][y];
2511 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2515 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y)
2517 CopyBrushExt(from_x, from_y, to_x, to_y, CB_AREA_TO_BRUSH);
2521 static void CopyBrushToLevel()
2523 CopyBrushExt(0, 0, 0, 0, CB_BRUSH_TO_LEVEL);
2527 static void FloodFill(int from_x, int from_y, int fill_element)
2531 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2532 static int safety = 0;
2534 /* check if starting field still has the desired content */
2535 if (Feld[from_x][from_y] == fill_element)
2540 if (safety > lev_fieldx*lev_fieldy)
2541 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2543 old_element = Feld[from_x][from_y];
2544 Feld[from_x][from_y] = fill_element;
2548 x = from_x + check[i][0];
2549 y = from_y + check[i][1];
2551 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2552 FloodFill(x, y, fill_element);
2558 /* values for DrawLevelText() modes */
2560 #define TEXT_SETCURSOR 1
2561 #define TEXT_WRITECHAR 2
2562 #define TEXT_BACKSPACE 3
2563 #define TEXT_NEWLINE 4
2566 static void DrawLevelText(int sx, int sy, char letter, int mode)
2568 static short delete_buffer[MAX_LEV_FIELDX];
2569 static int start_sx, start_sy;
2570 static int last_sx, last_sy;
2571 static boolean typing = FALSE;
2572 int letter_element = EL_CHAR_ASCII0 + letter;
2575 if (mode != TEXT_INIT)
2580 if (mode != TEXT_SETCURSOR)
2586 lx = last_sx + level_xpos;
2587 ly = last_sy + level_ypos;
2594 DrawLevelText(0, 0, 0, TEXT_END);
2597 start_sx = last_sx = sx;
2598 start_sy = last_sy = sy;
2599 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2602 case TEXT_SETCURSOR:
2603 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2604 DrawAreaBorder(sx, sy, sx, sy);
2609 case TEXT_WRITECHAR:
2610 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2612 delete_buffer[sx - start_sx] = Feld[lx][ly];
2613 Feld[lx][ly] = letter_element;
2615 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
2616 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2617 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
2618 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2620 DrawLevelText(0, 0, 0, TEXT_END);
2624 case TEXT_BACKSPACE:
2627 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2628 DrawMiniElement(sx - 1, sy, new_element3);
2629 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2634 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2635 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2637 DrawLevelText(0, 0, 0, TEXT_END);
2641 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2642 DrawMiniElement(sx, sy, Feld[lx][ly]);
2651 static void CopyLevelToUndoBuffer(int mode)
2653 static boolean accumulated_undo = FALSE;
2654 boolean new_undo_buffer_position = TRUE;
2659 case UNDO_IMMEDIATE:
2660 accumulated_undo = FALSE;
2663 case UNDO_ACCUMULATE:
2664 if (accumulated_undo)
2665 new_undo_buffer_position = FALSE;
2666 accumulated_undo = TRUE;
2673 if (new_undo_buffer_position)
2675 /* new position in undo buffer ring */
2676 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2678 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2679 undo_buffer_steps++;
2682 for(x=0; x<lev_fieldx; x++)
2683 for(y=0; y<lev_fieldy; y++)
2684 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2687 printf("level saved to undo buffer\n");
2692 static void RandomPlacement(int button)
2697 new_element = (button == 1 ? new_element1 :
2698 button == 2 ? new_element2 :
2699 button == 3 ? new_element3 : 0);
2701 if (random_placement_method == RANDOM_USE_PERCENTAGE)
2703 for(x=0; x<lev_fieldx; x++)
2704 for(y=0; y<lev_fieldy; y++)
2705 if (RND(100) < random_placement_percentage)
2706 Feld[x][y] = new_element;
2710 int elements_left = random_placement_num_objects;
2712 while (elements_left > 0)
2714 x = RND(lev_fieldx);
2715 y = RND(lev_fieldy);
2717 if (Feld[x][y] != new_element)
2719 Feld[x][y] = new_element;
2725 DrawMiniLevel(level_xpos, level_ypos);
2726 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2729 void WrapLevel(int dx, int dy)
2731 int wrap_dx = lev_fieldx - dx;
2732 int wrap_dy = lev_fieldy - dy;
2735 for(x=0; x<lev_fieldx; x++)
2736 for(y=0; y<lev_fieldy; y++)
2737 FieldBackup[x][y] = Feld[x][y];
2739 for(x=0; x<lev_fieldx; x++)
2740 for(y=0; y<lev_fieldy; y++)
2742 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
2744 DrawMiniLevel(level_xpos, level_ypos);
2745 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
2748 static void HandleDrawingAreas(struct GadgetInfo *gi)
2750 static boolean started_inside_drawing_area = FALSE;
2751 static boolean draw_with_brush = FALSE;
2752 int id = gi->custom_id;
2753 boolean inside_drawing_area = !gi->event.off_borders;
2754 boolean button_press_event;
2755 boolean button_release_event;
2756 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
2758 int button = gi->event.button;
2759 int sx = gi->event.x, sy = gi->event.y;
2760 int min_sx = 0, min_sy = 0;
2761 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
2763 int min_lx = 0, min_ly = 0;
2764 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
2768 if (edit_mode != ED_MODE_DRAWING)
2772 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2773 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2775 /* make sure to stay inside drawing area boundaries */
2776 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
2777 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
2781 /* get positions inside level field */
2782 lx = sx + level_xpos;
2783 ly = sy + level_ypos;
2785 /* make sure to stay inside level field boundaries */
2786 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
2787 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
2789 /* correct drawing area positions accordingly */
2790 sx = lx - level_xpos;
2791 sy = ly - level_ypos;
2794 if (button_press_event)
2795 started_inside_drawing_area = inside_drawing_area;
2797 if (!started_inside_drawing_area)
2800 if (!button && !button_release_event)
2803 new_element = (button == 1 ? new_element1 :
2804 button == 2 ? new_element2 :
2805 button == 3 ? new_element3 : 0);
2807 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
2810 switch (drawing_function)
2812 case ED_CTRL_ID_SINGLE_ITEMS:
2815 if (button_release_event)
2816 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2821 if (new_element != Feld[lx][ly])
2823 if (new_element == EL_SPIELFIGUR)
2825 /* remove player at old position */
2826 for(y=0; y<lev_fieldy; y++)
2828 for(x=0; x<lev_fieldx; x++)
2830 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
2832 Feld[x][y] = EL_LEERRAUM;
2833 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
2834 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
2835 DrawMiniElement(x - level_xpos, y - level_ypos,
2842 Feld[lx][ly] = new_element;
2843 DrawMiniElement(sx, sy, new_element);
2848 DrawMiniGraphicExt(drawto, gc,
2849 gi->x + sx * MINI_TILEX,
2850 gi->y + sy * MINI_TILEY,
2851 el2gfx(new_element));
2852 DrawMiniGraphicExt(window, gc,
2853 gi->x + sx * MINI_TILEX,
2854 gi->y + sy * MINI_TILEY,
2855 el2gfx(new_element));
2857 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
2858 level.amoebe_inhalt = new_element;
2859 else if (id >= ED_CTRL_ID_ELEMCONT_0 && id <= ED_CTRL_ID_ELEMCONT_7)
2860 level.mampfer_inhalt[id - ED_CTRL_ID_ELEMCONT_0][sx][sy] =
2865 case ED_CTRL_ID_CONNECTED_ITEMS:
2867 static int last_sx = -1;
2868 static int last_sy = -1;
2870 if (button_release_event)
2871 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2875 if (!button_press_event)
2876 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
2884 case ED_CTRL_ID_LINE:
2885 case ED_CTRL_ID_RECTANGLE:
2886 case ED_CTRL_ID_FILLED_BOX:
2887 case ED_CTRL_ID_BRUSH:
2889 static int last_sx = -1;
2890 static int last_sy = -1;
2891 static int start_sx = -1;
2892 static int start_sy = -1;
2893 void (*draw_func)(int, int, int, int, int, boolean);
2895 if (drawing_function == ED_CTRL_ID_LINE)
2896 draw_func = DrawLine;
2897 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
2898 draw_func = DrawRectangle;
2899 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
2900 draw_func = DrawFilledBox;
2902 draw_func = SelectArea;
2904 if (button_press_event)
2906 draw_func(sx, sy, sx, sy, new_element, FALSE);
2907 start_sx = last_sx = sx;
2908 start_sy = last_sy = sy;
2910 else if (button_release_event)
2912 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
2913 if (drawing_function == ED_CTRL_ID_BRUSH)
2915 CopyAreaToBrush(start_sx, start_sy, sx, sy);
2916 draw_with_brush = TRUE;
2919 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2921 else if (last_sx != sx || last_sy != sy)
2923 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
2924 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
2931 case ED_CTRL_ID_TEXT:
2932 if (button_press_event)
2933 DrawLevelText(sx, sy, 0, TEXT_INIT);
2936 case ED_CTRL_ID_FLOOD_FILL:
2937 if (button_press_event && Feld[lx][ly] != new_element)
2939 FloodFill(lx, ly, new_element);
2940 DrawMiniLevel(level_xpos, level_ypos);
2941 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2945 case ED_CTRL_ID_PICK_ELEMENT:
2946 if (button_press_event)
2947 PickDrawingElement(button, Feld[lx][ly]);
2948 if (button_release_event)
2949 ClickOnGadget(level_editor_gadget[last_drawing_function]);
2957 static void HandleCounterButtons(struct GadgetInfo *gi)
2959 int id = gi->custom_id;
2960 int button = gi->event.button;
2961 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
2965 case ED_CTRL_ID_SCORE_DOWN:
2966 case ED_CTRL_ID_SCORE_UP:
2967 *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
2968 if (*gadget_score_value < 0)
2969 *gadget_score_value = 0;
2970 else if (*gadget_score_value > 255)
2971 *gadget_score_value = 255;
2973 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2976 case ED_CTRL_ID_ELEMCONT_DOWN:
2977 case ED_CTRL_ID_ELEMCONT_UP:
2978 *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step);
2979 if (*gadget_areas_value < 1)
2980 *gadget_areas_value = 1;
2981 else if (*gadget_areas_value > MAX_ELEMCONT)
2982 *gadget_areas_value = MAX_ELEMCONT;
2984 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2985 DrawElementContentAreas();
2993 static void HandleControlButtons(struct GadgetInfo *gi)
2995 int id = gi->custom_id;
2996 int button = gi->event.button;
2997 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
2999 int player_present = FALSE;
3000 int level_changed = FALSE;
3003 new_element = (button == 1 ? new_element1 :
3004 button == 2 ? new_element2 :
3005 button == 3 ? new_element3 : 0);
3007 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3008 DrawLevelText(0, 0, 0, TEXT_END);
3010 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3011 edit_mode != ED_MODE_DRAWING)
3013 DrawDrawingWindow();
3014 edit_mode = ED_MODE_DRAWING;
3019 case ED_CTRL_ID_SCROLL_LEFT:
3020 if (level_xpos >= 0)
3022 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3023 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3024 struct GadgetScrollbar *gs = &gi->scrollbar;
3026 if (lev_fieldx < ED_FIELDX - 2)
3030 if (level_xpos < -1)
3033 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3035 DrawMiniLevel(level_xpos, level_ypos);
3037 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3041 case ED_CTRL_ID_SCROLL_RIGHT:
3042 if (level_xpos <= lev_fieldx - ED_FIELDX)
3044 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3045 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3046 struct GadgetScrollbar *gs = &gi->scrollbar;
3048 if (lev_fieldx < ED_FIELDX - 2)
3052 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3053 level_xpos = lev_fieldx - ED_FIELDX + 1;
3055 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3057 DrawMiniLevel(level_xpos, level_ypos);
3059 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3063 case ED_CTRL_ID_SCROLL_UP:
3064 if (level_ypos >= 0)
3066 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3067 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3068 struct GadgetScrollbar *gs = &gi->scrollbar;
3070 if (lev_fieldy < ED_FIELDY - 2)
3074 if (level_ypos < -1)
3077 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3079 DrawMiniLevel(level_xpos, level_ypos);
3081 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3085 case ED_CTRL_ID_SCROLL_DOWN:
3086 if (level_ypos <= lev_fieldy - ED_FIELDY)
3088 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3089 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3090 struct GadgetScrollbar *gs = &gi->scrollbar;
3092 if (lev_fieldy < ED_FIELDY - 2)
3096 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3097 level_ypos = lev_fieldy - ED_FIELDY + 1;
3099 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3101 DrawMiniLevel(level_xpos, level_ypos);
3103 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3107 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3108 level_xpos = gi->event.item_position - 1;
3109 DrawMiniLevel(level_xpos, level_ypos);
3112 case ED_CTRL_ID_SCROLL_VERTICAL:
3113 level_ypos = gi->event.item_position - 1;
3114 DrawMiniLevel(level_xpos, level_ypos);
3117 case ED_CTRL_ID_WRAP_LEFT:
3118 WrapLevel(-step, 0);
3121 case ED_CTRL_ID_WRAP_RIGHT:
3125 case ED_CTRL_ID_WRAP_UP:
3126 WrapLevel(0, -step);
3129 case ED_CTRL_ID_WRAP_DOWN:
3133 case ED_CTRL_ID_SINGLE_ITEMS:
3134 case ED_CTRL_ID_CONNECTED_ITEMS:
3135 case ED_CTRL_ID_LINE:
3136 case ED_CTRL_ID_TEXT:
3137 case ED_CTRL_ID_RECTANGLE:
3138 case ED_CTRL_ID_FILLED_BOX:
3139 case ED_CTRL_ID_FLOOD_FILL:
3140 case ED_CTRL_ID_BRUSH:
3141 case ED_CTRL_ID_PICK_ELEMENT:
3142 last_drawing_function = drawing_function;
3143 drawing_function = id;
3146 case ED_CTRL_ID_RANDOM_PLACEMENT:
3147 RandomPlacement(button);
3150 case ED_CTRL_ID_PROPERTIES:
3151 if (edit_mode != ED_MODE_PROPERTIES)
3153 properties_element = new_element;
3154 DrawPropertiesWindow();
3155 edit_mode = ED_MODE_PROPERTIES;
3159 DrawDrawingWindow();
3160 edit_mode = ED_MODE_DRAWING;
3164 case ED_CTRL_ID_UNDO:
3165 if (undo_buffer_steps == 0)
3167 Request("Undo buffer empty !", REQ_CONFIRM);
3171 undo_buffer_position =
3172 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3173 undo_buffer_steps--;
3175 for(x=0; x<lev_fieldx; x++)
3176 for(y=0; y<lev_fieldy; y++)
3177 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3178 DrawMiniLevel(level_xpos,level_ypos);
3181 case ED_CTRL_ID_INFO:
3182 if (edit_mode != ED_MODE_INFO)
3184 DrawControlWindow();
3185 edit_mode = ED_MODE_INFO;
3189 DrawDrawingWindow();
3190 edit_mode = ED_MODE_DRAWING;
3194 case ED_CTRL_ID_CLEAR:
3195 for(x=0; x<MAX_LEV_FIELDX; x++)
3196 for(y=0; y<MAX_LEV_FIELDY; y++)
3197 Feld[x][y] = new_element3;
3198 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3200 DrawMiniLevel(level_xpos, level_ypos);
3203 case ED_CTRL_ID_SAVE:
3204 if (leveldir[leveldir_nr].readonly)
3206 Request("This level is read only !", REQ_CONFIRM);
3210 for(y=0; y<lev_fieldy; y++)
3211 for(x=0; x<lev_fieldx; x++)
3212 if (Feld[x][y] != Ur[x][y])
3213 level_changed = TRUE;
3215 if (0 && !level_changed)
3217 Request("Level has not changed !", REQ_CONFIRM);
3221 for(y=0; y<lev_fieldy; y++)
3222 for(x=0; x<lev_fieldx; x++)
3223 if (Feld[x][y] == EL_SPIELFIGUR ||
3224 Feld[x][y] == EL_SPIELER1 ||
3225 Feld[x][y] == EL_SP_MURPHY)
3226 player_present = TRUE;
3228 if (!player_present)
3229 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3232 if (Request("Save this level and kill the old ?", REQ_ASK))
3234 for(x=0; x<lev_fieldx; x++)
3235 for(y=0; y<lev_fieldy; y++)
3236 Ur[x][y] = Feld[x][y];
3237 SaveLevel(level_nr);
3242 case ED_CTRL_ID_TEST:
3243 for(y=0; y<lev_fieldy; y++)
3244 for(x=0; x<lev_fieldx; x++)
3245 if (Feld[x][y] == EL_SPIELFIGUR ||
3246 Feld[x][y] == EL_SPIELER1 ||
3247 Feld[x][y] == EL_SP_MURPHY)
3248 player_present = TRUE;
3250 if (!player_present)
3251 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3254 for(x=0; x<lev_fieldx; x++)
3255 for(y=0; y<lev_fieldy; y++)
3256 FieldBackup[x][y] = Ur[x][y];
3258 for(x=0; x<lev_fieldx; x++)
3259 for(y=0; y<lev_fieldy; y++)
3260 Ur[x][y] = Feld[x][y];
3262 UnmapLevelEditorGadgets();
3264 /* draw smaller door */
3265 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3266 DOOR_GFX_PAGEX7, 64,
3269 redraw_mask |= REDRAW_ALL;
3271 CloseDoor(DOOR_CLOSE_ALL);
3273 DrawCompleteVideoDisplay();
3275 if (setup.autorecord)
3276 TapeStartRecording();
3278 level_editor_test_game = TRUE;
3279 game_status = PLAYING;
3285 case ED_CTRL_ID_EXIT:
3286 for(y=0; y<lev_fieldy; y++)
3287 for(x=0; x<lev_fieldx; x++)
3288 if (Feld[x][y] != Ur[x][y])
3289 level_changed = TRUE;
3291 if (!level_changed ||
3292 Request("Level has changed! Exit without saving ?",
3293 REQ_ASK | REQ_STAY_OPEN))
3295 CloseDoor(DOOR_CLOSE_1);
3298 CloseDoor(DOOR_CLOSE_ALL);
3301 /* draw smaller door */
3302 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3303 DOOR_GFX_PAGEX7, 64,
3306 redraw_mask |= REDRAW_ALL;
3308 game_status = MAINMENU;
3313 CloseDoor(DOOR_CLOSE_1);
3314 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3315 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3316 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3317 OpenDoor(DOOR_OPEN_1);
3323 if (gi->event.type == GD_EVENT_PRESSED)
3324 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3325 else if (gi->event.type == GD_EVENT_RELEASED)
3326 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3327 else if (gi->event.type == GD_EVENT_MOVING)
3328 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3330 printf("default: HandleControlButtons: ?\n");
3336 void HandleLevelEditorKeyInput(KeySym key)
3338 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3340 char letter = getCharFromKeySym(key);
3342 /* map lower case letters to upper case */
3343 if (letter >= 'a' && letter <= 'z')
3344 letter += (int)('A' - 'a');
3345 else if (letter == 'ä')
3347 else if (letter == 'ä')
3349 else if (letter == 'ä')
3353 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3354 else if (key == XK_Delete || key == XK_BackSpace)
3355 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3356 else if (key == XK_Return)
3357 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3361 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3363 int id = gi->custom_id;
3367 case ED_CTRL_ID_LEVEL_NAME:
3368 strcpy(level.name, gi->text_value);