Eyedropper.
[cantaveria.git] / edit.c
blobed0b2b13fdb0456bbce187d8249dce79e647310e
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <limits.h>
5 #include <SDL/SDL.h>
9 #include <list.h>
10 #include <console.h>
11 #include <stage.h>
12 #include <loader.h>
13 #include <kernel.h>
14 #include <graphics.h>
15 #include <console.h>
17 struct edit {
18 int x;
19 int y;
20 char shape;
21 unsigned char fg;
22 unsigned char bg;
23 struct edit* next;
26 struct tile {
27 char shape;
28 unsigned char fg;
29 unsigned char bg;
32 struct undo_step {
33 struct tile* undo; /* writes to undo */
34 struct tile* redo; /* writes to redo */
35 struct edit* next;
36 struct edit* prev;
41 /* application state variables */
42 int toggle_background = 1;
43 int toggle_bgtiles = 1;
44 int toggle_fgtiles = 1;
45 int toggle_shapes = 0;
47 int origin_x = 0;
48 int origin_y = 0;
49 static int camera_x = 0;
50 static int camera_y = 0;
52 const char shapechars[20] = "Mmw12345678abcd";
54 char my_file[256] = "";
55 char my_file_old[256] = "";
56 char bgimage_file[256] = "";
57 char fgtiles_file[256] = "";
58 char bgtiles_file[256] = "";
59 char zone_path[256] = "";
60 int bgimage = 0;
61 int fgtiles = 0;
62 int bgtiles = 0;
63 int shapes = 0;
64 int tools = 0;
66 int select_enable = 0;
67 int select_x = 0;
68 int select_y = 0;
69 int select_w = 0;
70 int select_h = 0;
72 struct tile* raw_tiles = NULL;
73 int raw_w = 20;
74 int raw_h = 15;
76 int show_favorites = 0;
77 int bg_favorites[7] = {0,1,2,3,4,5,6};
78 int fg_favorites[7] = {0,1,2,3,4,5,6};
79 int brush_tile = 1;
80 int brush_layer = 1;
81 int brush_enable = 0;
82 int erase_enable = 0;
83 int eyedrop_enable = 0;
86 int panic_flag = 0;
88 int dialog_flag = 0;
89 int background_dialog = 0;
90 int tileset_dialog = 0;
91 int quit_dialog = 0;
92 int save_as_dialog = 0;
93 int open_dialog = 0;
94 int confirm_save_dialog = 0;
95 int tools_dialog = 0;
96 int tile_panel = 0;
97 int zone_dialog = 0;
101 int tile_panel_set = 0;
102 int tile_panel_page = 0;
103 int tile_panel_offset = 0;
105 char save_as_buf[256] = "";
106 int save_as_ptr = 0;
107 char open_buf[256] = "";
108 int open_ptr = 0;
109 char generic_buf[256] = "";
110 int generic_ptr = 0;
112 char gfx_path_buf[256] = "";
113 char stage_path_buf[256] = "";
114 /* *** */
118 /* utility */
119 void update_window_name(){
120 if(my_file[0] == 0){
121 SDL_WM_SetCaption("unnamed", NULL);
123 else{
124 SDL_WM_SetCaption(my_file, NULL);
129 void select_bgfile(char* path){
130 strcpy(bgimage_file, path);
133 void set_zone_path(char* path){
134 strncpy(zone_path, path, 256);
135 zone_path[255] = 0;
136 if(zone_path[strlen(zone_path)-1] != '/'){
137 strncat(zone_path, "/", 256);
138 zone_path[255] = 0;
142 int file_exists(char* path){
143 FILE* f = fopen(path, "r");
144 if(f == NULL){
145 return 0;
147 else{
148 fclose(f);
149 return 1;
153 char* compute_stage_path(char* stage){
154 strcpy(stage_path_buf, zone_path);
155 strcat(stage_path_buf, "stages/");
156 strcat(stage_path_buf, stage);
157 return stage_path_buf;
160 char* compute_gfx_path(char* gfxfile){
161 strcpy(gfx_path_buf, zone_path);
162 strcat(gfx_path_buf, "gfx/");
163 strcat(gfx_path_buf, gfxfile);
164 return gfx_path_buf;
166 /* *** */
171 /* base access methods */
172 struct tile* initialize_raw(int w, int h){
173 int i;
174 int j;
175 struct tile blank = {'0', 0, 0};
176 struct tile* ptr = malloc(w*h*sizeof(struct tile));
177 for(j=0; j<h; j++){
178 for(i=0; i<w; i++){
179 *(ptr + i + j*w) = blank;
183 return ptr;
186 void unload_raw(){
187 free(raw_tiles);
190 void raw_new(){
191 unload_raw();
192 raw_tiles = initialize_raw(20, 15);
193 raw_w = 20;
194 raw_h = 15;
195 camera_x = 0;
196 camera_y = 0;
197 origin_x = 0;
198 origin_y = 0;
199 bgimage = 0;
200 fgtiles = 0;
201 bgtiles = 0;
202 strcpy(my_file, "");
203 update_window_name();
206 struct tile raw_read(int x, int y){
207 struct tile blank = {'0', 0, 0};
208 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h){
209 return blank;
211 else{
212 return *(raw_tiles + x + raw_w*y);
216 void expand_raw(){
217 int new_w = raw_w * 3;
218 int new_h = raw_h * 3;
219 struct tile* new_tiles = initialize_raw(new_w, new_h);
220 struct tile* ptr;
221 struct tile t;
222 int i;
223 int j;
225 for(j=raw_h; j<2*raw_h; j++){
226 for(i=raw_w; i<2*raw_w; i++){
227 ptr = new_tiles + i + j*(3*raw_w);
228 t = raw_read(i-raw_w, j-raw_h);
229 *ptr = t;
233 origin_x += raw_w;
234 origin_y += raw_h;
235 raw_w *= 3;
236 raw_h *= 3;
237 free(raw_tiles);
238 raw_tiles = new_tiles;
241 int out_of_bounds(int x, int y){
242 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h)
243 return 1;
244 else
245 return 0;
248 void detect_size(int* w, int* h){
249 //see the minimum size necessary for the area
250 //used for saving
253 void raw_write(int x, int y, int layer, int value){
254 while(out_of_bounds(x, y)){
255 expand_raw();
256 x += raw_w / 3;
257 y += raw_h / 3;
260 //expand if outside
261 //shift x y by expand shift
262 //shift x and y by origin
263 //do the write
264 struct tile* ptr = raw_tiles + x + raw_w*y;
265 if(layer == 1){
266 ptr->bg = value;
268 else if(layer == 2){
269 ptr->fg = value;
271 else if(layer == 3){
272 ptr->shape = value;
276 void draw_background(){
277 int W = gfx_width(bgimage);
278 int H = gfx_height(bgimage);
279 draw_gfx_raw(bgimage, 0, 0, 0, 0, W, H);
282 void draw_raw(){
283 int x0 = camera_x + origin_x;
284 int y0 = camera_y + origin_y;
285 int i;
286 int j;
287 int x;
288 int y;
289 struct tile t;
290 int gx;
291 int gy;
293 if(toggle_background)
294 draw_background();
296 for(j=0; j<(15+5); j++){
297 y = y0 + j;
298 for(i=0; i<(20+8); i++){
299 x = x0 + i;
300 t = raw_read(x, y);
301 gy = 16*(t.bg / 16);
302 gx = 16*(t.bg % 16);
303 if(toggle_bgtiles)
304 draw_gfx_raw(bgtiles, i*16, j*16, gx, gy, 16, 16);
305 gy = 16*(t.fg / 16);
306 gx = 16*(t.fg % 16);
307 if(toggle_fgtiles)
308 draw_gfx_raw(fgtiles, i*16, j*16, gx, gy, 16, 16);
309 gy = 16*(t.shape / 16);
310 gx = 16*(t.shape % 16);
311 if(toggle_shapes)
312 draw_gfx_raw(shapes, i*16, j*16, gx, gy, 16, 16);
318 /* determine an optimal size for the stage */
319 void raw_optimize(int* ox, int* oy, int* ow, int* oh){
320 int i;
321 int xmax = 0;
322 int xmin = INT_MAX;
323 int ymax = 0;
324 int ymin = INT_MAX;
325 int x, y, fg, bg;
326 char shape;
328 for(i=0; i<(raw_w*raw_h); i++){
329 x = i % raw_w;
330 y = i / raw_w;
331 fg = raw_tiles[i].fg;
332 bg = raw_tiles[i].bg;
333 shape = raw_tiles[i].shape;
334 if((fg != 0 || bg != 0 || shape != '0')){
335 if(x > xmax) xmax = x;
336 if(x < xmin) xmin = x;
337 if(y > ymax) ymax = y;
338 if(y < ymin) ymin = y;
342 if(ymax - ymin + 1 <= 15) *oh = 15;
343 else *oh = (ymax - ymin + 1);
345 if(xmax - xmin + 1 <= 20) *ow = 20;
346 else *ow = (xmax - xmin + 1);
348 *ox = xmin;
349 *oy = ymin;
352 int raw_save(char* path){
353 /* save current stage to a stage file */
354 /* overwrites if already exists, no confirmation */
355 int x, y, bg, fg;
356 char shape;
357 int i;
358 struct tile* ptr = raw_tiles;
359 int opt_ox, opt_oy;
360 int opt_x, opt_y, opt_w, opt_h;
363 FILE* f = fopen(path, "w");
364 if(f == NULL){
365 console_printf("error saving file");
366 return -1;
369 raw_optimize(&opt_x, &opt_y, &opt_w, &opt_h);
371 fprintf(f, "%d %d %d %d\n", opt_w, opt_h, origin_x-opt_x, origin_y-opt_y);
372 fprintf(f, "%s\n", bgimage_file);
373 fprintf(f, "%s\n", fgtiles_file);
374 fprintf(f, "%s\n", bgtiles_file);
376 for(i=0; i<(raw_w*raw_h); i++){
377 x = (i % raw_w) - origin_x;
378 y = (i / raw_w) - origin_y;
379 fg = ptr[i].fg;
380 bg = ptr[i].bg;
381 shape = ptr[i].shape;
383 if(fg != 0 || bg != 0 || shape != '0'){
384 fprintf(f, "%d %d %d %d %c\n", x, y, fg, bg, shape);
389 fclose(f);
390 return 0;
393 void save(char* stagename){
394 char* path = compute_stage_path(stagename);
395 if(raw_save(path) < 0){
396 console_printf("%s NOT saved", stagename);
398 else{
399 console_printf("%s saved", stagename);
404 int raw_open(char* stagename){
405 reader* r;
406 int w, h, ox, oy;
407 int x, y, fg, bg;
408 char shape;
409 char file1[256] = "";
410 char file2[256] = "";
411 char file3[256] = "";
412 struct tile* new_tiles = NULL;
413 struct tile* ptr;
414 char* path = compute_stage_path(stagename);
416 r = loader_open(path);
417 if(r == NULL){
418 console_printf("Can't open %s", path);
419 return -1;
422 if(loader_scanline(r, "%d %d %d %d", &w, &h, &ox, &oy) < 4){
423 printf("scan error\n");
424 loader_close(r);
425 return -1;
429 loader_readline(r, file1, 256) ||
430 loader_readline(r, file2, 256) ||
431 loader_readline(r, file3, 256)
433 printf("scan error\n");
434 loader_close(r);
435 return -1;
438 new_tiles = initialize_raw(w, h);
439 while(loader_scanline(r, "%d %d %d %d %c", &x, &y, &fg, &bg, &shape) == 5){
440 ptr = new_tiles + (x+ox) + (y+oy)*w;
441 ptr->fg = fg;
442 ptr->bg = bg;
443 ptr->shape = shape;
446 /* load the graphics */
447 path = compute_gfx_path(file1);
448 if(file1[0] != 0 && file_exists(path)) bgimage = load_bitmap(path);
449 else bgimage = 0;
451 path = compute_gfx_path(file2);
452 if(file2[0] != 0 && file_exists(path)) bgtiles = load_bitmap(path);
453 else bgtiles = 0;
455 path = compute_gfx_path(file3);
456 if(file3[0] != 0 && file_exists(path)) fgtiles = load_bitmap(path);
457 else fgtiles = 0;
459 /* finalize */
460 origin_x = ox;
461 origin_y = oy;
462 raw_w = w;
463 raw_h = h;
464 free(raw_tiles);
465 raw_tiles = new_tiles;
467 strcpy(bgimage_file, file1);
468 strcpy(bgtiles_file, file2);
469 strcpy(fgtiles_file, file3);
471 strcpy(my_file, stagename);
473 return 0;
476 /* *** */
481 struct undo_step* undo_stack;
482 struct undo_step* undo_ptr;
484 /* undo operations */
485 void undo(){
486 //do the undo_ptr->undo operations
487 //move undo_ptr down one
490 void redo(){
491 //if at top of stack, do nothing
493 //do the undo_ptr->redo operations
494 //move undo_ptr up one
497 void undo_record(struct edit* edits){
498 //eliminate undo_ptr->redo and all previous edit structs
499 //change the undo_stack
501 //store the edits in undo_ptr->redo
502 //calculate the undo operation XXX
503 //push a new edit struct
504 //move undo_ptr
505 //store the undo operation in undo_ptr->undo
507 /* *** */
512 /* medium level editting commands */
513 void write_one_tile(int x, int y, int layer, int value){
514 //write x y layer value
517 void write_many_tiles(struct edit* edits){
518 //for each tiles
519 //write one tile
522 void edit_one_tile(int x, int y, int layer, int value){
523 //write_one_tile
524 //create a tile struct
525 //call edit on it
528 void edit_many_tiles(struct edit* edits){
529 //write many tiles
530 //edit(tiles)
533 void add_to_clipboard(struct edit* edits){
534 //makes a tile struct and appends to clipboard
537 void clear_clipboard(){
538 //clear the clipboard
541 struct tile* read_tile(int x, int y){
542 //make a tile struct
544 /* *** */
548 /* high level gui commands */
549 void update_favs(){
550 int a, b, c, d, e;
551 int *favs;
552 int already = 0;
553 int x = 0;
554 int i = 0;
555 int tmp;
556 int value = brush_tile;
557 int layer = brush_layer;
559 if(layer == 1) favs = bg_favorites;
560 if(layer == 2) favs = fg_favorites;
562 for(i=0; i<7; i++){
563 if(favs[i] == value){
564 already = 1;
565 x = i;
569 if(already){
570 if(x > 0){
571 tmp = favs[x-1];
572 favs[x-1] = favs[x];
573 favs[x] = tmp;
576 else{
577 favs[6] = value;
583 void start_box(int x, int y){
587 void move_box(int x, int y){
591 void stop_box(){
595 void clear_box(){
599 void append_to_box(int x, int y){
603 struct tile* box_select(){
608 void move_paste(int x, int y){
612 void cancel_paste(){
616 void do_paste(){
621 char* onoff(int b){
622 if(b) return "on";
623 else return "off";
627 /* *** */
631 /* dialog drawing */
633 void draw_tile_panel(){
634 int i;
635 int x, y;
636 int gx, gy;
637 int gfx;
639 draw_black_rect(0,0,9*16,20*16);
640 draw_gfx_raw(tools, 0, 14*16, 4*16, 0, 16, 16);
641 draw_gfx_raw(tools, 16, 14*16, 5*16, 0, 16, 16);
642 draw_gfx_raw(tools, 2*16, 14*16, 6*16, 0, 16, 16);
643 draw_gfx_raw(tools, 7*16, 14*16, 7*16, 0, 16, 16);
645 if(tile_panel_page == 0) tile_panel_offset = 0;
646 if(tile_panel_page == 1) tile_panel_offset = 112;
647 if(tile_panel_page == 2) tile_panel_offset = 144;
649 if(tile_panel_set == 0) gfx = fgtiles;
650 if(tile_panel_set == 1) gfx = bgtiles;
652 for(i=0; i<112; i++){
653 x = 16*(i % 8);
654 y = 16*(i / 8);
655 gx = 16*(i % 16);
656 gy = 16*(i / 16);
658 draw_gfx_raw(gfx, x, y, gx, gy+tile_panel_offset, 16, 16);
662 void draw_tools(){
663 int i;
664 int gx, gy;
666 draw_black_rect(16, 16, 17*16, 11*16);
668 /* fg tile tool and favorites */
669 draw_gfx_raw(tools, 2*16, 2*16, 0, 0, 16, 16);
671 for(i=0; i<7; i++){
672 gx = 16*(fg_favorites[i] % 16);
673 gy = 16*(fg_favorites[i] / 16);
674 draw_gfx_raw(fgtiles, 16*(i+4), 2*16, gx, gy, 16, 16);
677 /* bg tile tool and favorites */
678 draw_gfx_raw(tools, 2*16, 4*16, 16, 0, 16, 16);
680 for(i=0; i<7; i++){
681 gx = 16*(bg_favorites[i] % 16);
682 gy = 16*(bg_favorites[i] / 16);
683 draw_gfx_raw(bgtiles, 16*(i+4), 4*16, gx, gy, 16, 16);
686 /* shapes */
687 for(i=0; i<15; i++){
688 gx = 16*(shapechars[i] % 16);
689 gy = 16*(shapechars[i] / 16);
690 draw_gfx_raw(shapes, 16*(i+2), 6*16, gx, gy, 16, 16);
693 draw_gfx_raw(tools, 2*16, 8*16, 2*16, 0, 16, 16);
694 draw_gfx_raw(tools, 4*16, 8*16, 3*16, 0, 16, 16);
698 void redraw_all(){
699 clear_video();
701 draw_raw();
703 //gui indicators
704 if(select_enable){
705 //draw green box
708 //dialogs
709 if(save_as_dialog){
710 console_printf("save as: %s", save_as_buf);
713 if(open_dialog){
714 console_printf("open file: %s", open_buf);
717 if(tools_dialog){
718 draw_tools();
721 if(tile_panel){
722 draw_tile_panel();
725 if(tileset_dialog){
726 if(brush_layer == 1){
727 console_printf("bg tileset: %s", generic_buf);
729 else if(brush_layer == 2){
730 console_printf("fg tileset: %s", generic_buf);
734 if(background_dialog){
735 console_printf("background image: %s", generic_buf);
738 if(zone_dialog){
739 console_printf("path to zone: %s", generic_buf);
742 console_draw();
743 console_clear();
745 update_video();
747 /* *** */
753 /* dialog input handlers */
754 void pixel_to_tile(int mx, int my, int* x, int* y){
755 map_pixel(mx, my, x, y);
756 *x /= 16;
757 *y /= 16;
760 void zone_press(SDLKey key, Uint16 c){
761 if(c == '\r'){
762 if(generic_buf[0] == 0){
763 console_printf("No name? Nevermind then.");
765 else{
766 set_zone_path(generic_buf);
767 console_printf("zone set to %s", zone_path);
769 generic_buf[0] = 0;
770 generic_ptr = 0;
771 zone_dialog = 0;
773 else if(c == 0x1b){
774 generic_buf[0] = 0;
775 generic_ptr = 0;
776 zone_dialog = 0;
778 else if(c == '\b'){
779 if(generic_ptr > 0){
780 generic_ptr--;
781 generic_buf[generic_ptr] = 0;
784 else if(c == 0){
786 else{
787 if(generic_ptr < 255){
788 generic_buf[generic_ptr] = c;
789 generic_ptr++;
790 generic_buf[generic_ptr] = 0;
796 void tileset_press(SDLKey key, Uint16 c){
797 if(c == '\r'){
798 if(generic_buf[0] == 0){
799 console_printf("No name? Nevermind then.");
801 else{
802 char* path = compute_gfx_path(generic_buf);
803 int gfx = load_bitmap(path);
804 if(gfx == 0){
805 console_printf("file not found");
807 else{
808 if(brush_layer == 1){
809 strcpy(bgtiles_file, generic_buf);
810 bgtiles = load_bitmap(path);
812 else if(brush_layer == 2){
813 strcpy(fgtiles_file, generic_buf);
814 fgtiles = load_bitmap(path);
818 generic_buf[0] = 0;
819 generic_ptr = 0;
820 tileset_dialog = 0;
822 else if(c == 0x1b){
823 generic_buf[0] = 0;
824 generic_ptr = 0;
825 tileset_dialog = 0;
827 else if(c == '\b'){
828 if(generic_ptr > 0){
829 generic_ptr--;
830 generic_buf[generic_ptr] = 0;
833 else if(c == 0){
835 else{
836 if(generic_ptr < 255){
837 generic_buf[generic_ptr] = c;
838 generic_ptr++;
839 generic_buf[generic_ptr] = 0;
844 void background_press(SDLKey key, Uint16 c){
845 if(c == '\r'){
846 if(generic_buf[0] == 0){
847 console_printf("No name? Nevermind then.");
849 else{
850 char* path = compute_gfx_path(generic_buf);
851 int gfx = load_bitmap(path);
852 if(gfx == 0){
853 console_printf("file not found");
855 else{
856 strcpy(bgimage_file, generic_buf);
857 bgimage = load_bitmap(path);
860 generic_buf[0] = 0;
861 generic_ptr = 0;
862 background_dialog = 0;
864 else if(c == 0x1b){
865 generic_buf[0] = 0;
866 generic_ptr = 0;
867 background_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;
887 int tile_panel_click(int mx, int my){
888 int x, y;
890 pixel_to_tile(mx, my, &x, &y);
892 if(x >= 9){
893 return 0;
896 if(y == 14){
897 if(x == 0){
898 tile_panel_page = 0;
900 if(x == 1){
901 tile_panel_page = 1;
903 if(x == 2){
904 tile_panel_page = 2;
906 if(x == 7){
907 tile_panel = 0;
911 if(y >= 0 && y < 14){
912 if(x >= 0 && x <=7){
913 brush_tile = x + y*8 + tile_panel_offset;
914 update_favs();
918 redraw_all();
919 return 1;
922 void tile_panel_press(SDLKey key, Uint16 c){
923 switch(key){
924 case SDLK_LEFT:
925 case SDLK_RIGHT:
926 case SDLK_UP:
927 case SDLK_DOWN:
928 return;
929 default:
930 tile_panel = 0;
931 return;
935 void tools_press(SDLKey key, Uint16 c){
936 tools_dialog = 0;
939 void tools_click(int mx, int my){
940 int x;
941 int y;
943 pixel_to_tile(mx, my, &x, &y);
945 if(y == 2){
946 if(x == 2){
947 tile_panel = 1;
948 tile_panel_set = 0;
949 brush_layer = 2;
951 if(x >= 4 && x <= 10){
952 brush_layer = 2;
953 toggle_fgtiles = 1;
954 toggle_shapes = 0;
955 brush_tile = fg_favorites[x-4];
956 update_favs();
960 if(y == 4){
961 if(x == 2){
962 tile_panel = 1;
963 tile_panel_set = 1;
964 brush_layer = 1;
966 if(x >= 4 && x <= 10){
967 brush_layer = 1;
968 toggle_bgtiles = 1;
969 toggle_shapes = 0;
970 brush_tile = bg_favorites[x-4];
971 update_favs();
975 if(y == 6){
976 if(x >= 2 && x <= 16){
977 brush_layer = 3;
978 toggle_shapes = 1;
979 brush_tile = shapechars[x-2];
983 if(y == 8){
984 if(x == 2){
985 printf("big eraser\n");
987 if(x == 4){
988 eyedrop_enable = 1;
989 console_printf("eyedropper\n");
993 tools_dialog = 0;
994 redraw_all();
997 void open_press(SDLKey key, Uint16 c){
998 if(c == 0){
1000 else if(c == '\r'){
1001 if(open_buf[0] == 0){
1002 console_printf("No name? Nevermind then.");
1004 else{
1005 if(raw_open(open_buf) < 0){
1006 console_printf("ERROR when opening %s", open_buf);
1008 else {
1009 console_printf("%s opened", open_buf);
1010 update_window_name();
1013 open_buf[0] = 0;
1014 open_ptr = 0;
1015 open_dialog = 0;
1017 else if(c == 0x1b){
1018 open_buf[0] = 0;
1019 open_ptr = 0;
1020 open_dialog = 0;
1022 else if(c == '\b'){
1023 if(open_ptr > 0){
1024 open_ptr--;
1025 open_buf[open_ptr] = 0;
1028 else{
1029 if(open_ptr < 255){
1030 open_buf[open_ptr] = c;
1031 open_ptr++;
1032 open_buf[open_ptr] = 0;
1038 void confirm_save_press(SDLKey key, Uint16 c){
1039 if(c == 'y' || c == 'Y'){
1040 console_printf("You're the boss. Overwriting %s", my_file);
1041 save(my_file);
1042 update_window_name();
1044 else{
1045 strcpy(my_file, my_file_old); /* ! */
1046 console_printf("Operation cancelled");
1049 confirm_save_dialog = 0;
1052 void save_as_press(SDLKey key, Uint16 c){
1053 char* path;
1054 if(c == 0){
1056 else if(c == '\r'){
1057 if(save_as_buf[0] == 0){
1058 console_printf("No name? Nevermind then.");
1060 else{
1061 strcpy(my_file_old, my_file); /* ! */
1062 strcpy(my_file, save_as_buf); /* ! */
1064 /* see if file exists */
1065 path = compute_stage_path(save_as_buf);
1066 if(file_exists(path)){
1067 console_printf("ALERT: really overwrite %s? (Y/N)", my_file);
1068 confirm_save_dialog = 1;
1070 else{
1071 update_window_name();
1072 save(my_file);
1075 save_as_buf[0] = 0;
1076 save_as_ptr = 0;
1077 save_as_dialog = 0;
1079 else if(c == 0x1b){
1080 save_as_buf[0] = 0;
1081 save_as_ptr = 0;
1082 save_as_dialog = 0;
1084 else if(c == '\b'){
1085 if(save_as_ptr > 0){
1086 save_as_ptr--;
1087 save_as_buf[save_as_ptr] = 0;
1090 else{
1091 if(save_as_ptr < 255){
1092 save_as_buf[save_as_ptr] = c;
1093 save_as_ptr++;
1094 save_as_buf[save_as_ptr] = 0;
1099 void quit_press(SDLKey key, Uint16 c){
1100 if(c == 'y' || c == 'Y'){
1101 panic_flag = 1;
1103 else{
1104 console_printf("OK");
1107 quit_dialog = 0;
1114 void keydown(SDLKey key, SDLMod mod, Uint16 c){
1116 if(save_as_dialog){
1117 save_as_press(key, c);
1118 redraw_all();
1119 return;
1122 if(confirm_save_dialog){
1123 confirm_save_press(key, c);
1124 redraw_all();
1125 return;
1128 if(open_dialog){
1129 open_press(key, c);
1130 redraw_all();
1131 return;
1134 if(quit_dialog){
1135 quit_press(key, c);
1136 redraw_all();
1137 return;
1140 if(tools_dialog){
1141 tools_press(key, c);
1142 redraw_all();
1143 return;
1146 if(tile_panel){
1147 tile_panel_press(key, c);
1148 redraw_all();
1151 if(tileset_dialog){
1152 tileset_press(key, c);
1153 redraw_all();
1154 return;
1157 if(background_dialog){
1158 background_press(key, c);
1159 redraw_all();
1160 return;
1163 if(zone_dialog){
1164 zone_press(key, c);
1165 redraw_all();
1166 return;
1169 switch(key){
1170 case SDLK_u:
1171 undo();
1172 console_printf("undo"); break;
1173 case SDLK_r:
1174 redo();
1175 console_printf("redo"); break;
1176 case SDLK_1:
1177 toggle_background = !toggle_background;
1178 console_printf("background %s", onoff(toggle_background));
1179 break;
1180 case SDLK_2:
1181 toggle_bgtiles = !toggle_bgtiles;
1182 console_printf("bg tiles %s", onoff(toggle_bgtiles));
1183 break;
1184 case SDLK_3:
1185 toggle_fgtiles = !toggle_fgtiles;
1186 console_printf("fg tiles %s", onoff(toggle_fgtiles));
1187 break;
1188 case SDLK_4:
1189 toggle_shapes = !toggle_shapes;
1190 console_printf("shapes %s", onoff(toggle_shapes));
1191 break;
1192 case SDLK_s:
1193 if(mod & (KMOD_LCTRL|KMOD_RCTRL)){
1194 if(my_file[0] == 0){
1195 save_as_dialog = 1;
1197 else{
1198 save(my_file);
1201 break;
1202 case SDLK_w:
1203 save_as_dialog = 1;
1204 break;
1205 case SDLK_o:
1206 open_dialog = 1;
1207 break;
1208 case SDLK_z:
1209 zone_dialog = 1;
1210 break;
1211 case SDLK_e:
1212 eyedrop_enable = 1;
1213 console_printf("eyedropper");
1214 break;
1215 case SDLK_i:
1216 console_printf("name: %s", my_file);
1217 console_printf("zone: %s", zone_path);
1218 console_printf("size: %d x %d", raw_w, raw_h);
1219 console_printf("background: %s", bgimage_file);
1220 console_printf("bg tileset: %s", bgtiles_file);
1221 console_printf("fg tileset: %s", fgtiles_file);
1222 break;
1223 case SDLK_q:
1224 case SDLK_ESCAPE:
1225 console_printf("Really quit? (Y/N)");
1226 quit_dialog = 1;
1227 break;
1228 case SDLK_n:
1229 raw_new();
1230 break;
1231 case SDLK_h:
1232 case SDLK_F1:
1233 case SDLK_SLASH:
1234 console_printf("arrow keys - move");
1235 console_printf("left mouse - draw");
1236 console_printf("right mouse - erase");
1237 console_printf("space - open toolbox");
1238 console_printf("ctrl+s - save");
1239 console_printf("w - save as");
1240 console_printf("o - open");
1241 console_printf("n - new file");
1242 console_printf("z - change zone");
1243 console_printf("1 2 3 4 - toggle layers");
1244 console_printf("i - file info");
1245 console_printf("F1 h ? - this help");
1246 console_printf("ESCAPE q - quit / cancel");
1247 console_printf("F5 - select background");
1248 console_printf("F6 - select bg tileset");
1249 console_printf("F7 - select fg tileset");
1250 console_printf("e - choose eyedropper");
1251 console_printf("x - choose eraser");
1252 break;
1253 case SDLK_F5:
1254 background_dialog = 1;
1255 break;
1256 case SDLK_F6:
1257 tileset_dialog = 1;
1258 brush_layer = 1;
1259 break;
1260 case SDLK_F7:
1261 tileset_dialog = 1;
1262 brush_layer = 2;
1263 break;
1264 case SDLK_LEFT: camera_x--; break;
1265 case SDLK_RIGHT: camera_x++; break;
1266 case SDLK_UP: camera_y--; break;
1267 case SDLK_DOWN: camera_y++; break;
1269 case SDLK_SPACE:
1270 tools_dialog = 1;
1271 break;
1273 /* temporary controls */
1274 case SDLK_9: brush_tile--; brush_tile %= 256; break;
1275 case SDLK_0: brush_tile++; brush_tile %= 256; break;
1276 case SDLK_8: brush_layer = 2; break;
1277 case SDLK_7: brush_layer = 1; break;
1280 redraw_all();
1283 U - undo
1284 R - redo
1285 1 - toggle layer 1
1286 2 - toggle layer 2
1287 3 - toggle layer 3
1288 4 - toggle layer 4
1289 ctrl S - save
1290 W - save as
1291 O - open stage
1292 B - change background
1293 Q - quit
1294 ESC - quit / cancel
1295 ENTER - yes / OK
1296 Y - yes
1297 N - no
1298 H - help
1299 ? - help
1300 F1 - help
1301 F2 - change fg tileset
1302 F3 - change bg tileset
1303 ARROW KEYS - scroll
1307 void translate_pointer(int mx, int my, int *x, int *y){
1308 int a, b;
1309 map_pixel(mx, my, &a, &b);
1310 *x = a/16 + camera_x + origin_x;
1311 *y = b/16 + camera_y + origin_y;
1315 void mousedown(int mx, int my, int button){
1317 hold LMB - draw single tiles / deselect
1318 shift LMB - start box select
1319 ctrl LMB - append single tiles to selection
1320 RMB - display tilesets
1321 hold MMB - choose where to paste (release to execute, esc to cancel)
1323 SDLMod mod = SDL_GetModState();
1325 int x, y;
1326 struct tile t;
1327 translate_pointer(mx, my, &x, &y);
1329 if(tools_dialog){
1330 tools_click(mx, my);
1331 return;
1334 if(tile_panel){
1335 if(tile_panel_click(mx, my)){
1336 return;
1341 if(button == 1){
1342 if(eyedrop_enable){
1343 t = raw_read(x, y);
1344 if(brush_layer == 1){
1345 brush_tile = t.bg;
1347 else if(brush_layer == 2){
1348 brush_tile = t.fg;
1350 else if(brush_layer == 3){
1351 brush_tile = t.shape;
1353 eyedrop_enable = 0;
1355 else{
1356 raw_write(x, y, brush_layer, brush_tile);
1357 brush_enable = 1;
1358 redraw_all();
1361 else if(button == 3){
1362 erase_enable = 1;
1363 if(brush_layer == 3){
1364 raw_write(x, y, 3, '0');
1366 else{
1367 raw_write(x, y, brush_layer, 0);
1369 redraw_all();
1374 void mouseup(int x, int y, int button){
1376 LMB - stop drawing
1377 shift LMB - append box to selection
1378 MMB - execute paste
1381 if(button == 1){
1382 brush_enable = 0;
1385 if(button == 3){
1386 erase_enable = 0;
1391 void mousemove(int mx, int my, int xrel, int yrel){
1393 redraw cursor
1394 redraw box select
1395 redraw paste box
1397 int x, y;
1398 translate_pointer(mx, my, &x, &y);
1400 if(brush_enable){
1401 raw_write(x, y, brush_layer, brush_tile);
1402 redraw_all();
1404 if(erase_enable){
1405 if(brush_layer == 3){
1406 raw_write(x, y, 3, '0');
1408 else{
1409 raw_write(x, y, brush_layer, 0);
1411 redraw_all();
1415 int check_events(){
1416 SDL_Event e;
1418 if(SDL_WaitEvent(&e) == 0){
1419 printf("SDL_WaitEvent encountered an error (%s)\n", SDL_GetError());
1420 return 1;
1423 switch(e.type){
1424 case SDL_QUIT: return 1;
1425 case SDL_KEYDOWN: keydown(e.key.keysym.sym, e.key.keysym.mod, e.key.keysym.unicode); return 0;
1426 case SDL_MOUSEMOTION:
1427 mousemove(e.motion.x, e.motion.y, e.motion.xrel, e.motion.yrel);
1428 return 0;
1429 case SDL_MOUSEBUTTONDOWN: mousedown(e.button.x, e.button.y, e.button.button); return 0;
1430 case SDL_MOUSEBUTTONUP: mouseup(e.button.x, e.button.y, e.button.button); return 0;
1431 case SDL_VIDEOEXPOSE: redraw_all();
1432 default: return 0;
1438 void terminate(){
1439 loader_quit();
1440 video_quit();
1443 int main(int argc, char* argv[]){
1444 video_init(argc, argv);
1445 loader_init();
1446 graphics_init();
1448 raw_tiles = initialize_raw(raw_w, raw_h);
1450 update_window_name();
1452 shapes = load_bitmap("gfx/shapes.tga");
1453 tools = load_bitmap("gfx/tools.tga");
1455 loader_data_mode(0);
1456 // bgimage = load_bitmap("azone/gfx/background.tga");
1457 // loader_data_mode(0);
1458 // fgtiles = load_bitmap("barf.tga");
1459 // loader_data_mode(1);
1460 // fgtiles = load_bitmap("azone/gfx/barf.tga");
1461 // bgtiles = load_bitmap("azone/gfx/test.tga");
1463 set_zone_path("azone");
1465 redraw_all();
1467 SDL_ShowCursor(1);
1468 SDL_EnableUNICODE(1);
1469 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1471 atexit(terminate);
1473 while(check_events() == 0 && panic_flag == 0);
1475 return 0;