Added comments to collision code.
[cantaveria.git] / edit.c
blobdb3d93f8d966adba7d964861e37ff33c79d225b8
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <limits.h>
5 #include <SDL/SDL.h>
9 #include <util.h>
10 #include <list.h>
11 #include <console.h>
12 #include <stage.h>
13 #include <loader.h>
14 #include <kernel.h>
15 #include <graphics.h>
16 #include <console.h>
18 struct edit {
19 int x;
20 int y;
21 char shape;
22 unsigned char fg;
23 unsigned char bg;
24 struct edit* next;
27 struct tile {
28 char shape;
29 unsigned char fg;
30 unsigned char bg;
33 struct undo_step {
34 struct tile* undo; /* writes to undo */
35 struct tile* redo; /* writes to redo */
36 struct edit* next;
37 struct edit* prev;
42 /* application state variables */
43 int toggle_background = 1;
44 int toggle_bgtiles = 1;
45 int toggle_fgtiles = 1;
46 int toggle_shapes = 0;
48 int origin_x = 0;
49 int origin_y = 0;
50 static int camera_x = 0;
51 static int camera_y = 0;
53 const char shapechars[20] = "Mmw12345678abcd";
55 char my_file[256] = "";
56 char my_file_old[256] = "";
57 char bgimage_file[256] = "";
58 char fgtiles_file[256] = "";
59 char bgtiles_file[256] = "";
60 char zone_path[256] = "";
61 int bgimage = 0;
62 int fgtiles = 0;
63 int bgtiles = 0;
64 int shapes = 0;
65 int tools = 0;
67 int select_enable = 0;
68 int select_x = 0;
69 int select_y = 0;
70 int select_w = 0;
71 int select_h = 0;
73 struct tile* raw_tiles = NULL;
74 int raw_w = 20;
75 int raw_h = 15;
77 int show_favorites = 0;
78 int bg_favorites[7] = {0,1,2,3,4,5,6};
79 int fg_favorites[7] = {0,1,2,3,4,5,6};
80 int brush_tile = 1;
81 int brush_layer = 1;
82 int brush_enable = 0;
83 int erase_enable = 0;
84 int eyedrop_enable = 0;
87 int panic_flag = 0;
89 int dialog_flag = 0;
90 int background_dialog = 0;
91 int tileset_dialog = 0;
92 int quit_dialog = 0;
93 int save_as_dialog = 0;
94 int open_dialog = 0;
95 int confirm_save_dialog = 0;
96 int tools_dialog = 0;
97 int tile_panel = 0;
98 int zone_dialog = 0;
102 int tile_panel_set = 0;
103 int tile_panel_page = 0;
104 int tile_panel_offset = 0;
106 char save_as_buf[256] = "";
107 int save_as_ptr = 0;
108 char open_buf[256] = "";
109 int open_ptr = 0;
110 char generic_buf[256] = "";
111 int generic_ptr = 0;
113 char gfx_path_buf[256] = "";
114 char stage_path_buf[256] = "";
115 /* *** */
119 /* utility */
120 void update_window_name(){
121 if(my_file[0] == 0){
122 SDL_WM_SetCaption("unnamed", NULL);
124 else{
125 SDL_WM_SetCaption(my_file, NULL);
130 void select_bgfile(char* path){
131 strcpy(bgimage_file, path);
134 void set_zone_path(char* path){
135 strncpy(zone_path, path, 256);
136 zone_path[255] = 0;
137 if(zone_path[strlen(zone_path)-1] != '/'){
138 strncat(zone_path, "/", 256);
139 zone_path[255] = 0;
143 int file_exists(char* path){
144 FILE* f = fopen(path, "r");
145 if(f == NULL){
146 return 0;
148 else{
149 fclose(f);
150 return 1;
154 char* compute_stage_path(char* stage){
155 strcpy(stage_path_buf, zone_path);
156 strcat(stage_path_buf, "stages/");
157 strcat(stage_path_buf, stage);
158 return stage_path_buf;
161 char* compute_gfx_path(char* gfxfile){
162 strcpy(gfx_path_buf, zone_path);
163 strcat(gfx_path_buf, "gfx/");
164 strcat(gfx_path_buf, gfxfile);
165 return gfx_path_buf;
169 void reload_graphics_work(char* what, int* var, char* filename){
170 char* path = compute_gfx_path(filename);
171 if(filename[0] == 0){
172 *var = 0;
173 console_printf("blank filename for %s", what);
175 else if(!file_exists(path)){
176 console_printf("file not found %s", path);
177 *var = 0;
179 else {
180 *var = load_bitmap(path);
181 if(*var == 0){
182 console_printf("error loading %s", path);
187 void reload_graphics(){
188 clear_gfx();
190 loader_data_mode(1);
191 shapes = load_bitmap("gfx/shapes.tga");
192 tools = load_bitmap("gfx/tools.tga");
194 loader_data_mode(0);
195 reload_graphics_work("background", &bgimage, bgimage_file);
196 reload_graphics_work("bg tileset", &bgtiles, bgtiles_file);
197 reload_graphics_work("fg tileset", &fgtiles, fgtiles_file);
199 /* *** */
204 /* base access methods */
205 struct tile* initialize_raw(int w, int h){
206 int i;
207 int j;
208 struct tile blank = {'0', 0, 0};
209 struct tile* ptr = malloc(w*h*sizeof(struct tile));
210 for(j=0; j<h; j++){
211 for(i=0; i<w; i++){
212 *(ptr + i + j*w) = blank;
216 return ptr;
219 void unload_raw(){
220 free(raw_tiles);
223 void raw_new(){
224 unload_raw();
225 raw_tiles = initialize_raw(20, 15);
226 raw_w = 20;
227 raw_h = 15;
228 camera_x = 0;
229 camera_y = 0;
230 origin_x = 0;
231 origin_y = 0;
232 bgimage = 0;
233 fgtiles = 0;
234 bgtiles = 0;
235 strcpy(my_file, "");
236 update_window_name();
239 struct tile raw_read(int x, int y){
240 struct tile blank = {'0', 0, 0};
241 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h){
242 return blank;
244 else{
245 return *(raw_tiles + x + raw_w*y);
249 void expand_raw(){
250 int new_w = raw_w * 3;
251 int new_h = raw_h * 3;
252 struct tile* new_tiles = initialize_raw(new_w, new_h);
253 struct tile* ptr;
254 struct tile t;
255 int i;
256 int j;
258 for(j=raw_h; j<2*raw_h; j++){
259 for(i=raw_w; i<2*raw_w; i++){
260 ptr = new_tiles + i + j*(3*raw_w);
261 t = raw_read(i-raw_w, j-raw_h);
262 *ptr = t;
266 origin_x += raw_w;
267 origin_y += raw_h;
268 raw_w *= 3;
269 raw_h *= 3;
270 free(raw_tiles);
271 raw_tiles = new_tiles;
274 int out_of_bounds(int x, int y){
275 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h)
276 return 1;
277 else
278 return 0;
281 void detect_size(int* w, int* h){
282 //see the minimum size necessary for the area
283 //used for saving
286 void raw_write(int x, int y, int layer, int value){
287 while(out_of_bounds(x, y)){
288 expand_raw();
289 x += raw_w / 3;
290 y += raw_h / 3;
293 //expand if outside
294 //shift x y by expand shift
295 //shift x and y by origin
296 //do the write
297 struct tile* ptr = raw_tiles + x + raw_w*y;
298 if(layer == 1){
299 ptr->bg = value;
301 else if(layer == 2){
302 ptr->fg = value;
304 else if(layer == 3){
305 ptr->shape = value;
309 void draw_background(){
310 int W, H;
311 gfx_dimensions(bgimage, &W, &H);
312 draw_gfx_raw(bgimage, 0, 0, 0, 0, W, H);
315 void draw_raw(){
316 int x0 = camera_x + origin_x;
317 int y0 = camera_y + origin_y;
318 int i;
319 int j;
320 int x;
321 int y;
322 struct tile t;
323 int gx;
324 int gy;
326 if(toggle_background)
327 draw_background();
329 for(j=0; j<(15+5); j++){
330 y = y0 + j;
331 for(i=0; i<(20+8); i++){
332 x = x0 + i;
333 t = raw_read(x, y);
334 gy = 16*(t.bg / 16);
335 gx = 16*(t.bg % 16);
336 if(toggle_bgtiles)
337 draw_gfx_raw(bgtiles, i*16, j*16, gx, gy, 16, 16);
338 gy = 16*(t.fg / 16);
339 gx = 16*(t.fg % 16);
340 if(toggle_fgtiles)
341 draw_gfx_raw(fgtiles, i*16, j*16, gx, gy, 16, 16);
342 gy = 16*(t.shape / 16);
343 gx = 16*(t.shape % 16);
344 if(toggle_shapes)
345 draw_gfx_raw(shapes, i*16, j*16, gx, gy, 16, 16);
351 /* determine an optimal size for the stage */
352 void raw_optimize(int* ox, int* oy, int* ow, int* oh){
353 int i;
354 int xmax = 0;
355 int xmin = INT_MAX;
356 int ymax = 0;
357 int ymin = INT_MAX;
358 int x, y, fg, bg;
359 char shape;
360 int zero = 0;
362 for(i=0; i<(raw_w*raw_h); i++){
363 x = i % raw_w;
364 y = i / raw_w;
365 fg = raw_tiles[i].fg;
366 bg = raw_tiles[i].bg;
367 shape = raw_tiles[i].shape;
368 if((fg != 0 || bg != 0 || shape != '0')){
369 zero = 1;
370 if(x > xmax) xmax = x;
371 if(x < xmin) xmin = x;
372 if(y > ymax) ymax = y;
373 if(y < ymin) ymin = y;
377 if(ymax - ymin + 1 <= 15) *oh = 15;
378 else *oh = (ymax - ymin + 1);
380 if(xmax - xmin + 1 <= 20) *ow = 20;
381 else *ow = (xmax - xmin + 1);
383 if(zero != 0){
384 *ox = xmin;
385 *oy = ymin;
387 else{
388 *ox = 0;
389 *oy = 0;
393 int raw_save(char* path){
394 /* save current stage to a stage file */
395 /* overwrites if already exists, no confirmation */
396 int x, y, bg, fg;
397 char shape;
398 int i;
399 struct tile* ptr = raw_tiles;
400 int opt_ox, opt_oy;
401 int opt_x, opt_y, opt_w, opt_h;
404 FILE* f = fopen(path, "w");
405 if(f == NULL){
406 console_printf("error saving file");
407 return -1;
410 raw_optimize(&opt_x, &opt_y, &opt_w, &opt_h);
412 fprintf(f, "%d %d %d %d\n", opt_w, opt_h, origin_x-opt_x, origin_y-opt_y);
413 fprintf(f, "%s\n", bgimage_file);
414 fprintf(f, "%s\n", fgtiles_file);
415 fprintf(f, "%s\n", bgtiles_file);
417 for(i=0; i<(raw_w*raw_h); i++){
418 x = (i % raw_w) - origin_x;
419 y = (i / raw_w) - origin_y;
420 fg = ptr[i].fg;
421 bg = ptr[i].bg;
422 shape = ptr[i].shape;
424 if(fg != 0 || bg != 0 || shape != '0'){
425 fprintf(f, "%d %d %d %d %c\n", x, y, fg, bg, shape);
430 fclose(f);
431 return 0;
434 void save(char* stagename){
435 char* path = compute_stage_path(stagename);
436 if(raw_save(path) < 0){
437 console_printf("%s NOT saved", stagename);
439 else{
440 console_printf("%s saved", stagename);
445 int raw_open(char* stagename){
446 reader* r;
447 int w, h, ox, oy;
448 int x, y, fg, bg;
449 char shape;
450 char file1[256] = "";
451 char file2[256] = "";
452 char file3[256] = "";
453 struct tile* new_tiles = NULL;
454 struct tile* ptr;
455 char* path = compute_stage_path(stagename);
457 r = loader_open(path);
458 if(r == NULL){
459 console_printf("Can't open %s", path);
460 return -1;
463 if(loader_scanline(r, "%d %d %d %d", &w, &h, &ox, &oy) < 4){
464 printf("scan error\n");
465 loader_close(r);
466 return -1;
470 loader_readline(r, file1, 256) ||
471 loader_readline(r, file2, 256) ||
472 loader_readline(r, file3, 256)
474 printf("scan error\n");
475 loader_close(r);
476 return -1;
479 new_tiles = initialize_raw(w, h);
480 while(loader_scanline(r, "%d %d %d %d %c", &x, &y, &fg, &bg, &shape) == 5){
481 ptr = new_tiles + (x+ox) + (y+oy)*w;
482 ptr->fg = fg;
483 ptr->bg = bg;
484 ptr->shape = shape;
487 /* load the graphics */
488 path = compute_gfx_path(file1);
489 if(file1[0] != 0 && file_exists(path)) bgimage = load_bitmap(path);
490 else bgimage = 0;
492 path = compute_gfx_path(file2);
493 if(file2[0] != 0 && file_exists(path)) bgtiles = load_bitmap(path);
494 else bgtiles = 0;
496 path = compute_gfx_path(file3);
497 if(file3[0] != 0 && file_exists(path)) fgtiles = load_bitmap(path);
498 else fgtiles = 0;
500 /* finalize */
501 origin_x = ox;
502 origin_y = oy;
503 raw_w = w;
504 raw_h = h;
505 free(raw_tiles);
506 raw_tiles = new_tiles;
508 strcpy(bgimage_file, file1);
509 strcpy(bgtiles_file, file2);
510 strcpy(fgtiles_file, file3);
512 strcpy(my_file, stagename);
514 return 0;
517 /* *** */
522 struct undo_step* undo_stack;
523 struct undo_step* undo_ptr;
525 /* undo operations */
526 void undo(){
527 //do the undo_ptr->undo operations
528 //move undo_ptr down one
531 void redo(){
532 //if at top of stack, do nothing
534 //do the undo_ptr->redo operations
535 //move undo_ptr up one
538 void undo_record(struct edit* edits){
539 //eliminate undo_ptr->redo and all previous edit structs
540 //change the undo_stack
542 //store the edits in undo_ptr->redo
543 //calculate the undo operation XXX
544 //push a new edit struct
545 //move undo_ptr
546 //store the undo operation in undo_ptr->undo
548 /* *** */
553 /* medium level editting commands */
554 void write_one_tile(int x, int y, int layer, int value){
555 //write x y layer value
558 void write_many_tiles(struct edit* edits){
559 //for each tiles
560 //write one tile
563 void edit_one_tile(int x, int y, int layer, int value){
564 //write_one_tile
565 //create a tile struct
566 //call edit on it
569 void edit_many_tiles(struct edit* edits){
570 //write many tiles
571 //edit(tiles)
574 void add_to_clipboard(struct edit* edits){
575 //makes a tile struct and appends to clipboard
578 void clear_clipboard(){
579 //clear the clipboard
582 struct tile* read_tile(int x, int y){
583 //make a tile struct
585 /* *** */
589 /* high level gui commands */
590 void update_favs(){
591 int a, b, c, d, e;
592 int *favs;
593 int already = 0;
594 int x = 0;
595 int i = 0;
596 int tmp;
597 int value = brush_tile;
598 int layer = brush_layer;
600 if(layer == 1) favs = bg_favorites;
601 if(layer == 2) favs = fg_favorites;
603 for(i=0; i<7; i++){
604 if(favs[i] == value){
605 already = 1;
606 x = i;
610 if(already){
611 if(x > 0){
612 tmp = favs[x-1];
613 favs[x-1] = favs[x];
614 favs[x] = tmp;
617 else{
618 favs[6] = value;
624 void start_box(int x, int y){
628 void move_box(int x, int y){
632 void stop_box(){
636 void clear_box(){
640 void append_to_box(int x, int y){
644 struct tile* box_select(){
649 void move_paste(int x, int y){
653 void cancel_paste(){
657 void do_paste(){
662 char* onoff(int b){
663 if(b) return "on";
664 else return "off";
668 /* *** */
672 /* dialog drawing */
674 void draw_tile_panel(){
675 int i, j;
676 int x, y;
677 int gx, gy;
678 int gfx;
680 draw_black_rect(0,0,9*16,20*16);
681 draw_gfx_raw(tools, 0, 14*16, 4*16, 0, 16, 16);
682 draw_gfx_raw(tools, 16, 14*16, 5*16, 0, 16, 16);
683 draw_gfx_raw(tools, 2*16, 14*16, 6*16, 0, 16, 16);
684 draw_gfx_raw(tools, 7*16, 14*16, 7*16, 0, 16, 16);
686 if(tile_panel_page == 0) tile_panel_offset = 0;
687 if(tile_panel_page == 1) tile_panel_offset = 112;
688 if(tile_panel_page == 2) tile_panel_offset = 144;
690 if(tile_panel_set == 0) gfx = fgtiles;
691 if(tile_panel_set == 1) gfx = bgtiles;
693 for(i=0; i<112; i++){
694 j = i + tile_panel_offset;
695 x = 16*(i % 8);
696 y = 16*(i / 8);
697 gx = 16*((j%8) + (j/128)*8);
698 gy = 16*((j/8) % (128/8));
700 draw_gfx_raw(gfx, x, y, gx, gy, 16, 16);
704 void draw_tools(){
705 int i;
706 int gx, gy;
708 draw_black_rect(16, 16, 17*16, 11*16);
710 /* fg tile tool and favorites */
711 draw_gfx_raw(tools, 2*16, 2*16, 0, 0, 16, 16);
713 for(i=0; i<7; i++){
714 gx = 16*(fg_favorites[i] % 16);
715 gy = 16*(fg_favorites[i] / 16);
716 draw_gfx_raw(fgtiles, 16*(i+4), 2*16, gx, gy, 16, 16);
719 /* bg tile tool and favorites */
720 draw_gfx_raw(tools, 2*16, 4*16, 16, 0, 16, 16);
722 for(i=0; i<7; i++){
723 gx = 16*(bg_favorites[i] % 16);
724 gy = 16*(bg_favorites[i] / 16);
725 draw_gfx_raw(bgtiles, 16*(i+4), 4*16, gx, gy, 16, 16);
728 /* shapes */
729 for(i=0; i<15; i++){
730 gx = 16*(shapechars[i] % 16);
731 gy = 16*(shapechars[i] / 16);
732 draw_gfx_raw(shapes, 16*(i+2), 6*16, gx, gy, 16, 16);
735 draw_gfx_raw(tools, 2*16, 8*16, 2*16, 0, 16, 16);
736 draw_gfx_raw(tools, 4*16, 8*16, 3*16, 0, 16, 16);
740 void redraw_all(){
741 clear_video();
743 draw_raw();
745 //gui indicators
746 if(select_enable){
747 //draw green box
750 //dialogs
751 if(save_as_dialog){
752 console_printf("save as: %s", save_as_buf);
755 if(open_dialog){
756 console_printf("open file: %s", open_buf);
759 if(tools_dialog){
760 draw_tools();
763 if(tile_panel){
764 draw_tile_panel();
767 if(tileset_dialog){
768 if(brush_layer == 1){
769 console_printf("bg tileset: %s", generic_buf);
771 else if(brush_layer == 2){
772 console_printf("fg tileset: %s", generic_buf);
776 if(background_dialog){
777 console_printf("background image: %s", generic_buf);
780 if(zone_dialog){
781 console_printf("path to zone: %s", generic_buf);
784 console_draw();
785 console_clear();
787 update_video();
789 /* *** */
795 /* dialog input handlers */
796 void pixel_to_tile(int mx, int my, int* x, int* y){
797 map_pixel(mx, my, x, y);
798 *x /= 16;
799 *y /= 16;
802 void zone_press(SDLKey key, Uint16 c){
803 if(c == '\r'){
804 if(generic_buf[0] == 0){
805 console_printf("No name? Nevermind then.");
807 else{
808 set_zone_path(generic_buf);
809 console_printf("zone set to %s", zone_path);
811 generic_buf[0] = 0;
812 generic_ptr = 0;
813 zone_dialog = 0;
815 else if(c == 0x1b){
816 generic_buf[0] = 0;
817 generic_ptr = 0;
818 zone_dialog = 0;
820 else if(c == '\b'){
821 if(generic_ptr > 0){
822 generic_ptr--;
823 generic_buf[generic_ptr] = 0;
826 else if(c == 0){
828 else{
829 if(generic_ptr < 255){
830 generic_buf[generic_ptr] = c;
831 generic_ptr++;
832 generic_buf[generic_ptr] = 0;
838 void tileset_press(SDLKey key, Uint16 c){
839 if(c == '\r'){
840 if(generic_buf[0] == 0){
841 console_printf("No name? Nevermind then.");
843 else{
844 char* path = compute_gfx_path(generic_buf);
845 int gfx = load_bitmap(path);
846 if(gfx == 0){
847 console_printf("file not found");
849 else{
850 if(brush_layer == 1){
851 strcpy(bgtiles_file, generic_buf);
852 bgtiles = load_bitmap(path);
854 else if(brush_layer == 2){
855 strcpy(fgtiles_file, generic_buf);
856 fgtiles = load_bitmap(path);
860 generic_buf[0] = 0;
861 generic_ptr = 0;
862 tileset_dialog = 0;
864 else if(c == 0x1b){
865 generic_buf[0] = 0;
866 generic_ptr = 0;
867 tileset_dialog = 0;
869 else if(c == '\b'){
870 if(generic_ptr > 0){
871 generic_ptr--;
872 generic_buf[generic_ptr] = 0;
875 else if(c == 0){
877 else{
878 if(generic_ptr < 255){
879 generic_buf[generic_ptr] = c;
880 generic_ptr++;
881 generic_buf[generic_ptr] = 0;
886 void background_press(SDLKey key, Uint16 c){
887 if(c == '\r'){
888 if(generic_buf[0] == 0){
889 console_printf("No name? Nevermind then.");
891 else{
892 char* path = compute_gfx_path(generic_buf);
893 int gfx = load_bitmap(path);
894 if(gfx == 0){
895 console_printf("file not found");
897 else{
898 strcpy(bgimage_file, generic_buf);
899 bgimage = load_bitmap(path);
902 generic_buf[0] = 0;
903 generic_ptr = 0;
904 background_dialog = 0;
906 else if(c == 0x1b){
907 generic_buf[0] = 0;
908 generic_ptr = 0;
909 background_dialog = 0;
911 else if(c == '\b'){
912 if(generic_ptr > 0){
913 generic_ptr--;
914 generic_buf[generic_ptr] = 0;
917 else if(c == 0){
919 else{
920 if(generic_ptr < 255){
921 generic_buf[generic_ptr] = c;
922 generic_ptr++;
923 generic_buf[generic_ptr] = 0;
929 int tile_panel_click(int mx, int my){
930 int x, y, i;
932 pixel_to_tile(mx, my, &x, &y);
934 if(x >= 9){
935 return 0;
938 if(y == 14){
939 if(x == 0){
940 tile_panel_page = 0;
942 if(x == 1){
943 tile_panel_page = 1;
945 if(x == 2){
946 tile_panel_page = 2;
948 if(x == 7){
949 tile_panel = 0;
953 if(y >= 0 && y < 14){
954 if(x >= 0 && x <=7){
955 i = x + y*8 + tile_panel_offset;
956 brush_tile = (i%8) + (i/8)*16 + (i/128)*8;
957 update_favs();
961 redraw_all();
962 return 1;
965 void tile_panel_press(SDLKey key, Uint16 c){
966 switch(key){
967 case SDLK_LEFT:
968 case SDLK_RIGHT:
969 case SDLK_UP:
970 case SDLK_DOWN:
971 return;
972 default:
973 tile_panel = 0;
974 return;
978 void tools_press(SDLKey key, Uint16 c){
979 tools_dialog = 0;
982 void tools_click(int mx, int my){
983 int x;
984 int y;
986 pixel_to_tile(mx, my, &x, &y);
988 if(y == 2){
989 if(x == 2){
990 tile_panel = 1;
991 tile_panel_set = 0;
992 brush_layer = 2;
994 if(x >= 4 && x <= 10){
995 brush_layer = 2;
996 toggle_fgtiles = 1;
997 toggle_shapes = 0;
998 brush_tile = fg_favorites[x-4];
999 update_favs();
1003 if(y == 4){
1004 if(x == 2){
1005 tile_panel = 1;
1006 tile_panel_set = 1;
1007 brush_layer = 1;
1009 if(x >= 4 && x <= 10){
1010 brush_layer = 1;
1011 toggle_bgtiles = 1;
1012 toggle_shapes = 0;
1013 brush_tile = bg_favorites[x-4];
1014 update_favs();
1018 if(y == 6){
1019 if(x >= 2 && x <= 16){
1020 brush_layer = 3;
1021 toggle_shapes = 1;
1022 brush_tile = shapechars[x-2];
1026 if(y == 8){
1027 if(x == 2){
1028 printf("big eraser\n");
1030 if(x == 4){
1031 eyedrop_enable = 1;
1032 console_printf("eyedropper\n");
1036 tools_dialog = 0;
1037 redraw_all();
1040 void open_press(SDLKey key, Uint16 c){
1041 if(c == 0){
1043 else if(c == '\r'){
1044 if(open_buf[0] == 0){
1045 console_printf("No name? Nevermind then.");
1047 else{
1048 if(raw_open(open_buf) < 0){
1049 console_printf("ERROR when opening %s", open_buf);
1051 else {
1052 console_printf("%s opened", open_buf);
1053 update_window_name();
1056 open_buf[0] = 0;
1057 open_ptr = 0;
1058 open_dialog = 0;
1060 else if(c == 0x1b){
1061 open_buf[0] = 0;
1062 open_ptr = 0;
1063 open_dialog = 0;
1065 else if(c == '\b'){
1066 if(open_ptr > 0){
1067 open_ptr--;
1068 open_buf[open_ptr] = 0;
1071 else{
1072 if(open_ptr < 255){
1073 open_buf[open_ptr] = c;
1074 open_ptr++;
1075 open_buf[open_ptr] = 0;
1081 void confirm_save_press(SDLKey key, Uint16 c){
1082 if(c == 'y' || c == 'Y'){
1083 console_printf("You're the boss. Overwriting %s", my_file);
1084 save(my_file);
1085 update_window_name();
1087 else{
1088 strcpy(my_file, my_file_old); /* ! */
1089 console_printf("Operation cancelled");
1092 confirm_save_dialog = 0;
1095 void save_as_press(SDLKey key, Uint16 c){
1096 char* path;
1097 if(c == 0){
1099 else if(c == '\r'){
1100 if(save_as_buf[0] == 0){
1101 console_printf("No name? Nevermind then.");
1103 else{
1104 strcpy(my_file_old, my_file); /* ! */
1105 strcpy(my_file, save_as_buf); /* ! */
1107 /* see if file exists */
1108 path = compute_stage_path(save_as_buf);
1109 if(file_exists(path)){
1110 console_printf("ALERT: really overwrite %s? (Y/N)", my_file);
1111 confirm_save_dialog = 1;
1113 else{
1114 update_window_name();
1115 save(my_file);
1118 save_as_buf[0] = 0;
1119 save_as_ptr = 0;
1120 save_as_dialog = 0;
1122 else if(c == 0x1b){
1123 save_as_buf[0] = 0;
1124 save_as_ptr = 0;
1125 save_as_dialog = 0;
1127 else if(c == '\b'){
1128 if(save_as_ptr > 0){
1129 save_as_ptr--;
1130 save_as_buf[save_as_ptr] = 0;
1133 else{
1134 if(save_as_ptr < 255){
1135 save_as_buf[save_as_ptr] = c;
1136 save_as_ptr++;
1137 save_as_buf[save_as_ptr] = 0;
1142 void quit_press(SDLKey key, Uint16 c){
1143 if(c == 'y' || c == 'Y'){
1144 panic_flag = 1;
1146 else{
1147 console_printf("OK");
1150 quit_dialog = 0;
1157 void keydown(SDLKey key, SDLMod mod, Uint16 c){
1159 if(save_as_dialog){
1160 save_as_press(key, c);
1161 redraw_all();
1162 return;
1165 if(confirm_save_dialog){
1166 confirm_save_press(key, c);
1167 redraw_all();
1168 return;
1171 if(open_dialog){
1172 open_press(key, c);
1173 redraw_all();
1174 return;
1177 if(quit_dialog){
1178 quit_press(key, c);
1179 redraw_all();
1180 return;
1183 if(tools_dialog){
1184 tools_press(key, c);
1185 redraw_all();
1186 return;
1189 if(tile_panel){
1190 tile_panel_press(key, c);
1191 redraw_all();
1194 if(tileset_dialog){
1195 tileset_press(key, c);
1196 redraw_all();
1197 return;
1200 if(background_dialog){
1201 background_press(key, c);
1202 redraw_all();
1203 return;
1206 if(zone_dialog){
1207 zone_press(key, c);
1208 redraw_all();
1209 return;
1212 switch(key){
1213 case SDLK_u:
1214 undo();
1215 console_printf("undo"); break;
1216 case SDLK_r:
1217 redo();
1218 console_printf("redo"); break;
1219 case SDLK_1:
1220 toggle_background = !toggle_background;
1221 console_printf("background %s", onoff(toggle_background));
1222 break;
1223 case SDLK_2:
1224 toggle_bgtiles = !toggle_bgtiles;
1225 console_printf("bg tiles %s", onoff(toggle_bgtiles));
1226 break;
1227 case SDLK_3:
1228 toggle_fgtiles = !toggle_fgtiles;
1229 console_printf("fg tiles %s", onoff(toggle_fgtiles));
1230 break;
1231 case SDLK_4:
1232 toggle_shapes = !toggle_shapes;
1233 console_printf("shapes %s", onoff(toggle_shapes));
1234 break;
1235 case SDLK_s:
1236 if(mod & (KMOD_LCTRL|KMOD_RCTRL)){
1237 if(my_file[0] == 0){
1238 save_as_dialog = 1;
1240 else{
1241 save(my_file);
1244 break;
1245 case SDLK_w:
1246 save_as_dialog = 1;
1247 break;
1248 case SDLK_o:
1249 open_dialog = 1;
1250 break;
1251 case SDLK_z:
1252 zone_dialog = 1;
1253 break;
1254 case SDLK_e:
1255 eyedrop_enable = 1;
1256 console_printf("eyedropper");
1257 break;
1258 case SDLK_l:
1259 reload_graphics();
1260 console_printf("graphics reloaded");
1261 break;
1262 case SDLK_i:
1263 console_printf("name: %s", my_file);
1264 console_printf("zone: %s", zone_path);
1265 console_printf("size: %d x %d", raw_w, raw_h);
1266 console_printf("origin: %d x %d", origin_x, origin_y);
1267 console_printf("background: %s", bgimage_file);
1268 console_printf("bg tileset: %s", bgtiles_file);
1269 console_printf("fg tileset: %s", fgtiles_file);
1270 break;
1271 case SDLK_q:
1272 case SDLK_ESCAPE:
1273 console_printf("Really quit? (Y/N)");
1274 quit_dialog = 1;
1275 break;
1276 case SDLK_n:
1277 raw_new();
1278 break;
1279 case SDLK_h:
1280 case SDLK_F1:
1281 case SDLK_SLASH:
1282 console_printf("arrow keys - move");
1283 console_printf("left mouse - draw");
1284 console_printf("right mouse - erase");
1285 console_printf("space - open toolbox");
1286 console_printf("ctrl+s - save");
1287 console_printf("w - save as");
1288 console_printf("o - open");
1289 console_printf("n - new file");
1290 console_printf("z - change zone");
1291 console_printf("l - reload graphics");
1292 console_printf("1 2 3 4 - toggle layers");
1293 console_printf("i - file info");
1294 console_printf("F1 h ? - this help");
1295 console_printf("ESCAPE q - quit / cancel");
1296 console_printf("F5 - select background");
1297 console_printf("F6 - select bg tileset");
1298 console_printf("F7 - select fg tileset");
1299 console_printf("e - choose eyedropper");
1300 console_printf("x - choose megaeraser (not yet)");
1301 break;
1302 case SDLK_F5:
1303 background_dialog = 1;
1304 break;
1305 case SDLK_F6:
1306 tileset_dialog = 1;
1307 brush_layer = 1;
1308 break;
1309 case SDLK_F7:
1310 tileset_dialog = 1;
1311 brush_layer = 2;
1312 break;
1313 case SDLK_LEFT: camera_x--; break;
1314 case SDLK_RIGHT: camera_x++; break;
1315 case SDLK_UP: camera_y--; break;
1316 case SDLK_DOWN: camera_y++; break;
1318 case SDLK_SPACE:
1319 tools_dialog = 1;
1320 break;
1322 /* temporary controls */
1323 case SDLK_9: brush_tile--; brush_tile %= 256; break;
1324 case SDLK_0: brush_tile++; brush_tile %= 256; break;
1325 case SDLK_8: brush_layer = 2; break;
1326 case SDLK_7: brush_layer = 1; break;
1329 redraw_all();
1332 U - undo
1333 R - redo
1334 1 - toggle layer 1
1335 2 - toggle layer 2
1336 3 - toggle layer 3
1337 4 - toggle layer 4
1338 ctrl S - save
1339 W - save as
1340 O - open stage
1341 B - change background
1342 Q - quit
1343 ESC - quit / cancel
1344 ENTER - yes / OK
1345 Y - yes
1346 N - no
1347 H - help
1348 ? - help
1349 F1 - help
1350 F2 - change fg tileset
1351 F3 - change bg tileset
1352 ARROW KEYS - scroll
1356 void translate_pointer(int mx, int my, int *x, int *y){
1357 int a, b;
1358 map_pixel(mx, my, &a, &b);
1359 *x = a/16 + camera_x + origin_x;
1360 *y = b/16 + camera_y + origin_y;
1364 void mousedown(int mx, int my, int button){
1366 hold LMB - draw single tiles / deselect
1367 shift LMB - start box select
1368 ctrl LMB - append single tiles to selection
1369 RMB - display tilesets
1370 hold MMB - choose where to paste (release to execute, esc to cancel)
1372 SDLMod mod = SDL_GetModState();
1374 int x, y;
1375 struct tile t;
1376 translate_pointer(mx, my, &x, &y);
1378 if(tools_dialog){
1379 tools_click(mx, my);
1380 return;
1383 if(tile_panel){
1384 if(tile_panel_click(mx, my)){
1385 return;
1390 if(button == 1){
1391 if(eyedrop_enable){
1392 t = raw_read(x, y);
1393 if(brush_layer == 1){
1394 brush_tile = t.bg;
1396 else if(brush_layer == 2){
1397 brush_tile = t.fg;
1399 else if(brush_layer == 3){
1400 brush_tile = t.shape;
1402 eyedrop_enable = 0;
1404 else{
1405 raw_write(x, y, brush_layer, brush_tile);
1406 brush_enable = 1;
1407 redraw_all();
1410 else if(button == 3){
1411 erase_enable = 1;
1412 if(brush_layer == 3){
1413 raw_write(x, y, 3, '0');
1415 else{
1416 raw_write(x, y, brush_layer, 0);
1418 redraw_all();
1423 void mouseup(int x, int y, int button){
1425 LMB - stop drawing
1426 shift LMB - append box to selection
1427 MMB - execute paste
1430 if(button == 1){
1431 brush_enable = 0;
1434 if(button == 3){
1435 erase_enable = 0;
1440 void mousemove(int mx, int my, int xrel, int yrel){
1442 redraw cursor
1443 redraw box select
1444 redraw paste box
1446 int x, y;
1447 translate_pointer(mx, my, &x, &y);
1449 if(brush_enable){
1450 raw_write(x, y, brush_layer, brush_tile);
1451 redraw_all();
1453 if(erase_enable){
1454 if(brush_layer == 3){
1455 raw_write(x, y, 3, '0');
1457 else{
1458 raw_write(x, y, brush_layer, 0);
1460 redraw_all();
1464 int check_events(){
1465 SDL_Event e;
1467 if(SDL_WaitEvent(&e) == 0){
1468 printf("SDL_WaitEvent encountered an error (%s)\n", SDL_GetError());
1469 return 1;
1472 switch(e.type){
1473 case SDL_QUIT: return 1;
1474 case SDL_KEYDOWN: keydown(e.key.keysym.sym, e.key.keysym.mod, e.key.keysym.unicode); return 0;
1475 case SDL_MOUSEMOTION:
1476 mousemove(e.motion.x, e.motion.y, e.motion.xrel, e.motion.yrel);
1477 return 0;
1478 case SDL_MOUSEBUTTONDOWN: mousedown(e.button.x, e.button.y, e.button.button); return 0;
1479 case SDL_MOUSEBUTTONUP: mouseup(e.button.x, e.button.y, e.button.button); return 0;
1480 case SDL_VIDEOEXPOSE: redraw_all();
1481 default: return 0;
1487 void terminate(){
1488 loader_quit();
1489 video_quit();
1492 int main(int argc, char* argv[]){
1493 video_init(argc, argv);
1494 loader_init();
1495 graphics_init();
1497 raw_tiles = initialize_raw(raw_w, raw_h);
1499 update_window_name();
1501 shapes = load_bitmap("gfx/shapes.tga");
1502 tools = load_bitmap("gfx/tools.tga");
1504 loader_data_mode(0);
1506 zone_dialog = 1;
1508 redraw_all();
1510 SDL_ShowCursor(1);
1511 SDL_EnableUNICODE(1);
1512 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1514 atexit(terminate);
1516 while(check_events() == 0 && panic_flag == 0);
1518 return 0;