Can change zone.
[cantaveria.git] / edit.c
blob6b3a69cb6450dde03eae3fd04cca5f9b1565169e
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;
85 int panic_flag = 0;
87 int dialog_flag = 0;
88 int background_dialog = 0;
89 int tileset_dialog = 0;
90 int quit_dialog = 0;
91 int save_as_dialog = 0;
92 int open_dialog = 0;
93 int confirm_save_dialog = 0;
94 int tools_dialog = 0;
95 int tile_panel = 0;
96 int zone_dialog = 0;
100 int tile_panel_set = 0;
101 int tile_panel_page = 0;
102 int tile_panel_offset = 0;
104 char save_as_buf[256] = "";
105 int save_as_ptr = 0;
106 char open_buf[256] = "";
107 int open_ptr = 0;
108 char generic_buf[256] = "";
109 int generic_ptr = 0;
111 char gfx_path_buf[256] = "";
112 char stage_path_buf[256] = "";
113 /* *** */
117 /* utility */
118 void update_window_name(){
119 if(my_file[0] == 0){
120 SDL_WM_SetCaption("unnamed", NULL);
122 else{
123 SDL_WM_SetCaption(my_file, NULL);
128 void select_bgfile(char* path){
129 strcpy(bgimage_file, path);
132 void set_zone_path(char* path){
133 strncpy(zone_path, path, 256);
134 zone_path[255] = 0;
135 if(zone_path[strlen(zone_path)-1] != '/'){
136 strncat(zone_path, "/", 256);
137 zone_path[255] = 0;
141 int file_exists(char* path){
142 FILE* f = fopen(path, "r");
143 if(f == NULL){
144 return 0;
146 else{
147 fclose(f);
148 return 1;
152 char* compute_stage_path(char* stage){
153 strcpy(stage_path_buf, zone_path);
154 strcat(stage_path_buf, "stages/");
155 strcat(stage_path_buf, stage);
156 return stage_path_buf;
159 char* compute_gfx_path(char* gfxfile){
160 strcpy(gfx_path_buf, zone_path);
161 strcat(gfx_path_buf, "gfx/");
162 strcat(gfx_path_buf, gfxfile);
163 return gfx_path_buf;
165 /* *** */
170 /* base access methods */
171 struct tile* initialize_raw(int w, int h){
172 int i;
173 int j;
174 struct tile blank = {'0', 0, 0};
175 struct tile* ptr = malloc(w*h*sizeof(struct tile));
176 for(j=0; j<h; j++){
177 for(i=0; i<w; i++){
178 *(ptr + i + j*w) = blank;
182 return ptr;
185 void unload_raw(){
186 free(raw_tiles);
189 void raw_new(){
190 unload_raw();
191 raw_tiles = initialize_raw(20, 15);
192 raw_w = 20;
193 raw_h = 15;
194 camera_x = 0;
195 camera_y = 0;
196 origin_x = 0;
197 origin_y = 0;
198 bgimage = 0;
199 fgtiles = 0;
200 bgtiles = 0;
201 strcpy(my_file, "");
202 update_window_name();
205 struct tile raw_read(int x, int y){
206 struct tile blank = {'0', 0, 0};
207 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h){
208 return blank;
210 else{
211 return *(raw_tiles + x + raw_w*y);
215 void expand_raw(){
216 int new_w = raw_w * 3;
217 int new_h = raw_h * 3;
218 struct tile* new_tiles = initialize_raw(new_w, new_h);
219 struct tile* ptr;
220 struct tile t;
221 int i;
222 int j;
224 for(j=raw_h; j<2*raw_h; j++){
225 for(i=raw_w; i<2*raw_w; i++){
226 ptr = new_tiles + i + j*(3*raw_w);
227 t = raw_read(i-raw_w, j-raw_h);
228 *ptr = t;
232 origin_x += raw_w;
233 origin_y += raw_h;
234 raw_w *= 3;
235 raw_h *= 3;
236 free(raw_tiles);
237 raw_tiles = new_tiles;
240 int out_of_bounds(int x, int y){
241 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h)
242 return 1;
243 else
244 return 0;
247 void detect_size(int* w, int* h){
248 //see the minimum size necessary for the area
249 //used for saving
252 void raw_write(int x, int y, int layer, int value){
253 while(out_of_bounds(x, y)){
254 expand_raw();
255 x += raw_w / 3;
256 y += raw_h / 3;
259 //expand if outside
260 //shift x y by expand shift
261 //shift x and y by origin
262 //do the write
263 struct tile* ptr = raw_tiles + x + raw_w*y;
264 if(layer == 1){
265 ptr->bg = value;
267 else if(layer == 2){
268 ptr->fg = value;
270 else if(layer == 3){
271 ptr->shape = value;
275 void draw_background(){
276 int W = gfx_width(bgimage);
277 int H = gfx_height(bgimage);
278 draw_gfx_raw(bgimage, 0, 0, 0, 0, W, H);
281 void draw_raw(){
282 int x0 = camera_x + origin_x;
283 int y0 = camera_y + origin_y;
284 int i;
285 int j;
286 int x;
287 int y;
288 struct tile t;
289 int gx;
290 int gy;
292 if(toggle_background)
293 draw_background();
295 for(j=0; j<(15+5); j++){
296 y = y0 + j;
297 for(i=0; i<(20+8); i++){
298 x = x0 + i;
299 t = raw_read(x, y);
300 gy = 16*(t.bg / 16);
301 gx = 16*(t.bg % 16);
302 if(toggle_bgtiles)
303 draw_gfx_raw(bgtiles, i*16, j*16, gx, gy, 16, 16);
304 gy = 16*(t.fg / 16);
305 gx = 16*(t.fg % 16);
306 if(toggle_fgtiles)
307 draw_gfx_raw(fgtiles, i*16, j*16, gx, gy, 16, 16);
308 gy = 16*(t.shape / 16);
309 gx = 16*(t.shape % 16);
310 if(toggle_shapes)
311 draw_gfx_raw(shapes, i*16, j*16, gx, gy, 16, 16);
317 /* determine an optimal size for the stage */
318 void raw_optimize(int* ox, int* oy, int* ow, int* oh){
319 int i;
320 int xmax = 0;
321 int xmin = INT_MAX;
322 int ymax = 0;
323 int ymin = INT_MAX;
324 int x, y, fg, bg;
325 char shape;
327 for(i=0; i<(raw_w*raw_h); i++){
328 x = i % raw_w;
329 y = i / raw_w;
330 fg = raw_tiles[i].fg;
331 bg = raw_tiles[i].bg;
332 shape = raw_tiles[i].shape;
333 if((fg != 0 || bg != 0 || shape != '0')){
334 if(x > xmax) xmax = x;
335 if(x < xmin) xmin = x;
336 if(y > ymax) ymax = y;
337 if(y < ymin) ymin = y;
341 if(ymax - ymin + 1 <= 15) *oh = 15;
342 else *oh = (ymax - ymin + 1);
344 if(xmax - xmin + 1 <= 20) *ow = 20;
345 else *ow = (xmax - xmin + 1);
347 *ox = xmin;
348 *oy = ymin;
351 int raw_save(char* path){
352 /* save current stage to a stage file */
353 /* overwrites if already exists, no confirmation */
354 int x, y, bg, fg;
355 char shape;
356 int i;
357 struct tile* ptr = raw_tiles;
358 int opt_ox, opt_oy;
359 int opt_x, opt_y, opt_w, opt_h;
362 FILE* f = fopen(path, "w");
363 if(f == NULL){
364 console_printf("error saving file");
365 return -1;
368 raw_optimize(&opt_x, &opt_y, &opt_w, &opt_h);
370 fprintf(f, "%d %d %d %d\n", opt_w, opt_h, origin_x-opt_x, origin_y-opt_y);
371 fprintf(f, "%s\n", bgimage_file);
372 fprintf(f, "%s\n", fgtiles_file);
373 fprintf(f, "%s\n", bgtiles_file);
375 for(i=0; i<(raw_w*raw_h); i++){
376 x = (i % raw_w) - origin_x;
377 y = (i / raw_w) - origin_y;
378 fg = ptr[i].fg;
379 bg = ptr[i].bg;
380 shape = ptr[i].shape;
382 if(fg != 0 || bg != 0 || shape != '0'){
383 fprintf(f, "%d %d %d %d %c\n", x, y, fg, bg, shape);
388 fclose(f);
389 return 0;
392 void save(char* stagename){
393 char* path = compute_stage_path(stagename);
394 if(raw_save(path) < 0){
395 console_printf("%s NOT saved", stagename);
397 else{
398 console_printf("%s saved", stagename);
403 int raw_open(char* stagename){
404 reader* r;
405 int w, h, ox, oy;
406 int x, y, fg, bg;
407 char shape;
408 char file1[256] = "";
409 char file2[256] = "";
410 char file3[256] = "";
411 struct tile* new_tiles = NULL;
412 struct tile* ptr;
413 char* path = compute_stage_path(stagename);
415 r = loader_open(path);
416 if(r == NULL){
417 console_printf("Can't open %s", path);
418 return -1;
421 if(loader_scanline(r, "%d %d %d %d", &w, &h, &ox, &oy) < 4){
422 printf("scan error\n");
423 loader_close(r);
424 return -1;
428 loader_readline(r, file1, 256) ||
429 loader_readline(r, file2, 256) ||
430 loader_readline(r, file3, 256)
432 printf("scan error\n");
433 loader_close(r);
434 return -1;
437 new_tiles = initialize_raw(w, h);
438 while(loader_scanline(r, "%d %d %d %d %c", &x, &y, &fg, &bg, &shape) == 5){
439 ptr = new_tiles + (x+ox) + (y+oy)*w;
440 ptr->fg = fg;
441 ptr->bg = bg;
442 ptr->shape = shape;
445 /* load the graphics */
446 path = compute_gfx_path(file1);
447 if(file1[0] != 0 && file_exists(path)) bgimage = load_bitmap(path);
448 else bgimage = 0;
450 path = compute_gfx_path(file2);
451 if(file2[0] != 0 && file_exists(path)) bgtiles = load_bitmap(path);
452 else bgtiles = 0;
454 path = compute_gfx_path(file3);
455 if(file3[0] != 0 && file_exists(path)) fgtiles = load_bitmap(path);
456 else fgtiles = 0;
458 /* finalize */
459 origin_x = ox;
460 origin_y = oy;
461 raw_w = w;
462 raw_h = h;
463 free(raw_tiles);
464 raw_tiles = new_tiles;
466 strcpy(bgimage_file, file1);
467 strcpy(bgtiles_file, file2);
468 strcpy(fgtiles_file, file3);
470 strcpy(my_file, stagename);
472 return 0;
475 /* *** */
480 struct undo_step* undo_stack;
481 struct undo_step* undo_ptr;
483 /* undo operations */
484 void undo(){
485 //do the undo_ptr->undo operations
486 //move undo_ptr down one
489 void redo(){
490 //if at top of stack, do nothing
492 //do the undo_ptr->redo operations
493 //move undo_ptr up one
496 void undo_record(struct edit* edits){
497 //eliminate undo_ptr->redo and all previous edit structs
498 //change the undo_stack
500 //store the edits in undo_ptr->redo
501 //calculate the undo operation XXX
502 //push a new edit struct
503 //move undo_ptr
504 //store the undo operation in undo_ptr->undo
506 /* *** */
511 /* medium level editting commands */
512 void write_one_tile(int x, int y, int layer, int value){
513 //write x y layer value
516 void write_many_tiles(struct edit* edits){
517 //for each tiles
518 //write one tile
521 void edit_one_tile(int x, int y, int layer, int value){
522 //write_one_tile
523 //create a tile struct
524 //call edit on it
527 void edit_many_tiles(struct edit* edits){
528 //write many tiles
529 //edit(tiles)
532 void add_to_clipboard(struct edit* edits){
533 //makes a tile struct and appends to clipboard
536 void clear_clipboard(){
537 //clear the clipboard
540 struct tile* read_tile(int x, int y){
541 //make a tile struct
543 /* *** */
547 /* high level gui commands */
548 void update_favs(){
549 int a, b, c, d, e;
550 int *favs;
551 int already = 0;
552 int x = 0;
553 int i = 0;
554 int tmp;
555 int value = brush_tile;
556 int layer = brush_layer;
558 if(layer == 1) favs = bg_favorites;
559 if(layer == 2) favs = fg_favorites;
561 for(i=0; i<7; i++){
562 if(favs[i] == value){
563 already = 1;
564 x = i;
568 if(already){
569 if(x > 0){
570 tmp = favs[x-1];
571 favs[x-1] = favs[x];
572 favs[x] = tmp;
575 else{
576 favs[6] = value;
582 void start_box(int x, int y){
586 void move_box(int x, int y){
590 void stop_box(){
594 void clear_box(){
598 void append_to_box(int x, int y){
602 struct tile* box_select(){
607 void move_paste(int x, int y){
611 void cancel_paste(){
615 void do_paste(){
620 char* onoff(int b){
621 if(b) return "on";
622 else return "off";
626 /* *** */
630 /* dialog drawing */
632 void draw_tile_panel(){
633 int i;
634 int x, y;
635 int gx, gy;
636 int gfx;
638 draw_black_rect(0,0,9*16,20*16);
639 draw_gfx_raw(tools, 0, 14*16, 4*16, 0, 16, 16);
640 draw_gfx_raw(tools, 16, 14*16, 5*16, 0, 16, 16);
641 draw_gfx_raw(tools, 2*16, 14*16, 6*16, 0, 16, 16);
642 draw_gfx_raw(tools, 7*16, 14*16, 7*16, 0, 16, 16);
644 if(tile_panel_page == 0) tile_panel_offset = 0;
645 if(tile_panel_page == 1) tile_panel_offset = 112;
646 if(tile_panel_page == 2) tile_panel_offset = 144;
648 if(tile_panel_set == 0) gfx = fgtiles;
649 if(tile_panel_set == 1) gfx = bgtiles;
651 for(i=0; i<112; i++){
652 x = 16*(i % 8);
653 y = 16*(i / 8);
654 gx = 16*(i % 16);
655 gy = 16*(i / 16);
657 draw_gfx_raw(gfx, x, y, gx, gy+tile_panel_offset, 16, 16);
661 void draw_tools(){
662 int i;
663 int gx, gy;
665 draw_black_rect(16, 16, 17*16, 11*16);
667 /* fg tile tool and favorites */
668 draw_gfx_raw(tools, 2*16, 2*16, 0, 0, 16, 16);
670 for(i=0; i<7; i++){
671 gx = 16*(fg_favorites[i] % 16);
672 gy = 16*(fg_favorites[i] / 16);
673 draw_gfx_raw(fgtiles, 16*(i+4), 2*16, gx, gy, 16, 16);
676 /* bg tile tool and favorites */
677 draw_gfx_raw(tools, 2*16, 4*16, 16, 0, 16, 16);
679 for(i=0; i<7; i++){
680 gx = 16*(bg_favorites[i] % 16);
681 gy = 16*(bg_favorites[i] / 16);
682 draw_gfx_raw(bgtiles, 16*(i+4), 4*16, gx, gy, 16, 16);
685 /* shapes */
686 for(i=0; i<15; i++){
687 gx = 16*(shapechars[i] % 16);
688 gy = 16*(shapechars[i] / 16);
689 draw_gfx_raw(shapes, 16*(i+2), 6*16, gx, gy, 16, 16);
692 draw_gfx_raw(tools, 2*16, 8*16, 2*16, 0, 16, 16);
693 draw_gfx_raw(tools, 4*16, 8*16, 3*16, 0, 16, 16);
697 void redraw_all(){
698 clear_video();
700 draw_raw();
702 //gui indicators
703 if(select_enable){
704 //draw green box
707 //dialogs
708 if(save_as_dialog){
709 console_printf("save as: %s", save_as_buf);
712 if(open_dialog){
713 console_printf("open file: %s", open_buf);
716 if(tools_dialog){
717 draw_tools();
720 if(tile_panel){
721 draw_tile_panel();
724 if(tileset_dialog){
725 if(brush_layer == 1){
726 console_printf("bg tileset: %s", generic_buf);
728 else if(brush_layer == 2){
729 console_printf("fg tileset: %s", generic_buf);
733 if(background_dialog){
734 console_printf("background image: %s", generic_buf);
737 if(zone_dialog){
738 console_printf("path to zone: %s", generic_buf);
741 console_draw();
742 console_clear();
744 update_video();
746 /* *** */
752 /* dialog input handlers */
753 void pixel_to_tile(int mx, int my, int* x, int* y){
754 map_pixel(mx, my, x, y);
755 *x /= 16;
756 *y /= 16;
759 void zone_press(SDLKey key, Uint16 c){
760 if(c == '\r'){
761 if(generic_buf[0] == 0){
762 console_printf("No name? Nevermind then.");
764 else{
765 set_zone_path(generic_buf);
766 console_printf("zone set to %s", zone_path);
768 generic_buf[0] = 0;
769 generic_ptr = 0;
770 zone_dialog = 0;
772 else if(c == 0x1b){
773 generic_buf[0] = 0;
774 generic_ptr = 0;
775 zone_dialog = 0;
777 else if(c == '\b'){
778 if(generic_ptr > 0){
779 generic_ptr--;
780 generic_buf[generic_ptr] = 0;
783 else if(c == 0){
785 else{
786 if(generic_ptr < 255){
787 generic_buf[generic_ptr] = c;
788 generic_ptr++;
789 generic_buf[generic_ptr] = 0;
795 void tileset_press(SDLKey key, Uint16 c){
796 if(c == '\r'){
797 if(generic_buf[0] == 0){
798 console_printf("No name? Nevermind then.");
800 else{
801 char* path = compute_gfx_path(generic_buf);
802 int gfx = load_bitmap(path);
803 if(gfx == 0){
804 console_printf("file not found");
806 else{
807 if(brush_layer == 1){
808 strcpy(bgtiles_file, generic_buf);
809 bgtiles = load_bitmap(path);
811 else if(brush_layer == 2){
812 strcpy(fgtiles_file, generic_buf);
813 fgtiles = load_bitmap(path);
817 generic_buf[0] = 0;
818 generic_ptr = 0;
819 tileset_dialog = 0;
821 else if(c == 0x1b){
822 generic_buf[0] = 0;
823 generic_ptr = 0;
824 tileset_dialog = 0;
826 else if(c == '\b'){
827 if(generic_ptr > 0){
828 generic_ptr--;
829 generic_buf[generic_ptr] = 0;
832 else if(c == 0){
834 else{
835 if(generic_ptr < 255){
836 generic_buf[generic_ptr] = c;
837 generic_ptr++;
838 generic_buf[generic_ptr] = 0;
843 void background_press(SDLKey key, Uint16 c){
844 if(c == '\r'){
845 if(generic_buf[0] == 0){
846 console_printf("No name? Nevermind then.");
848 else{
849 char* path = compute_gfx_path(generic_buf);
850 int gfx = load_bitmap(path);
851 if(gfx == 0){
852 console_printf("file not found");
854 else{
855 strcpy(bgimage_file, generic_buf);
856 bgimage = load_bitmap(path);
859 generic_buf[0] = 0;
860 generic_ptr = 0;
861 background_dialog = 0;
863 else if(c == 0x1b){
864 generic_buf[0] = 0;
865 generic_ptr = 0;
866 background_dialog = 0;
868 else if(c == '\b'){
869 if(generic_ptr > 0){
870 generic_ptr--;
871 generic_buf[generic_ptr] = 0;
874 else if(c == 0){
876 else{
877 if(generic_ptr < 255){
878 generic_buf[generic_ptr] = c;
879 generic_ptr++;
880 generic_buf[generic_ptr] = 0;
886 int tile_panel_click(int mx, int my){
887 int x, y;
889 pixel_to_tile(mx, my, &x, &y);
891 if(x >= 9){
892 return 0;
895 if(y == 14){
896 if(x == 0){
897 tile_panel_page = 0;
899 if(x == 1){
900 tile_panel_page = 1;
902 if(x == 2){
903 tile_panel_page = 2;
905 if(x == 7){
906 tile_panel = 0;
910 if(y >= 0 && y < 14){
911 if(x >= 0 && x <=7){
912 brush_tile = x + y*8 + tile_panel_offset;
913 update_favs();
917 redraw_all();
918 return 1;
921 void tile_panel_press(SDLKey key, Uint16 c){
922 switch(key){
923 case SDLK_LEFT:
924 case SDLK_RIGHT:
925 case SDLK_UP:
926 case SDLK_DOWN:
927 return;
928 default:
929 tile_panel = 0;
930 return;
934 void tools_press(SDLKey key, Uint16 c){
935 tools_dialog = 0;
938 void tools_click(int mx, int my){
939 int x;
940 int y;
942 pixel_to_tile(mx, my, &x, &y);
944 if(y == 2){
945 if(x == 2){
946 tile_panel = 1;
947 tile_panel_set = 0;
948 brush_layer = 2;
950 if(x >= 4 && x <= 10){
951 brush_layer = 2;
952 toggle_fgtiles = 1;
953 toggle_shapes = 0;
954 brush_tile = fg_favorites[x-4];
955 update_favs();
959 if(y == 4){
960 if(x == 2){
961 tile_panel = 1;
962 tile_panel_set = 1;
963 brush_layer = 1;
965 if(x >= 4 && x <= 10){
966 brush_layer = 1;
967 toggle_bgtiles = 1;
968 toggle_shapes = 0;
969 brush_tile = bg_favorites[x-4];
970 update_favs();
974 if(y == 6){
975 if(x >= 2 && x <= 16){
976 brush_layer = 3;
977 toggle_shapes = 1;
978 brush_tile = shapechars[x-2];
982 if(y == 8){
983 if(x == 2) printf("big eraser\n");
984 if(x == 4) printf("eye dropper\n");
987 tools_dialog = 0;
988 redraw_all();
991 void open_press(SDLKey key, Uint16 c){
992 if(c == 0){
994 else if(c == '\r'){
995 if(open_buf[0] == 0){
996 console_printf("No name? Nevermind then.");
998 else{
999 if(raw_open(open_buf) < 0){
1000 console_printf("ERROR when opening %s", open_buf);
1002 else {
1003 console_printf("%s opened", open_buf);
1004 update_window_name();
1007 open_buf[0] = 0;
1008 open_ptr = 0;
1009 open_dialog = 0;
1011 else if(c == 0x1b){
1012 open_buf[0] = 0;
1013 open_ptr = 0;
1014 open_dialog = 0;
1016 else if(c == '\b'){
1017 if(open_ptr > 0){
1018 open_ptr--;
1019 open_buf[open_ptr] = 0;
1022 else{
1023 if(open_ptr < 255){
1024 open_buf[open_ptr] = c;
1025 open_ptr++;
1026 open_buf[open_ptr] = 0;
1032 void confirm_save_press(SDLKey key, Uint16 c){
1033 if(c == 'y' || c == 'Y'){
1034 console_printf("You're the boss. Overwriting %s", my_file);
1035 save(my_file);
1036 update_window_name();
1038 else{
1039 strcpy(my_file, my_file_old); /* ! */
1040 console_printf("Operation cancelled");
1043 confirm_save_dialog = 0;
1046 void save_as_press(SDLKey key, Uint16 c){
1047 char* path;
1048 if(c == 0){
1050 else if(c == '\r'){
1051 if(save_as_buf[0] == 0){
1052 console_printf("No name? Nevermind then.");
1054 else{
1055 strcpy(my_file_old, my_file); /* ! */
1056 strcpy(my_file, save_as_buf); /* ! */
1058 /* see if file exists */
1059 path = compute_stage_path(save_as_buf);
1060 if(file_exists(path)){
1061 console_printf("ALERT: really overwrite %s? (Y/N)", my_file);
1062 confirm_save_dialog = 1;
1064 else{
1065 update_window_name();
1066 save(my_file);
1069 save_as_buf[0] = 0;
1070 save_as_ptr = 0;
1071 save_as_dialog = 0;
1073 else if(c == 0x1b){
1074 save_as_buf[0] = 0;
1075 save_as_ptr = 0;
1076 save_as_dialog = 0;
1078 else if(c == '\b'){
1079 if(save_as_ptr > 0){
1080 save_as_ptr--;
1081 save_as_buf[save_as_ptr] = 0;
1084 else{
1085 if(save_as_ptr < 255){
1086 save_as_buf[save_as_ptr] = c;
1087 save_as_ptr++;
1088 save_as_buf[save_as_ptr] = 0;
1093 void quit_press(SDLKey key, Uint16 c){
1094 if(c == 'y' || c == 'Y'){
1095 panic_flag = 1;
1097 else{
1098 console_printf("OK");
1101 quit_dialog = 0;
1108 void keydown(SDLKey key, SDLMod mod, Uint16 c){
1110 if(save_as_dialog){
1111 save_as_press(key, c);
1112 redraw_all();
1113 return;
1116 if(confirm_save_dialog){
1117 confirm_save_press(key, c);
1118 redraw_all();
1119 return;
1122 if(open_dialog){
1123 open_press(key, c);
1124 redraw_all();
1125 return;
1128 if(quit_dialog){
1129 quit_press(key, c);
1130 redraw_all();
1131 return;
1134 if(tools_dialog){
1135 tools_press(key, c);
1136 redraw_all();
1137 return;
1140 if(tile_panel){
1141 tile_panel_press(key, c);
1142 redraw_all();
1145 if(tileset_dialog){
1146 tileset_press(key, c);
1147 redraw_all();
1148 return;
1151 if(background_dialog){
1152 background_press(key, c);
1153 redraw_all();
1154 return;
1157 if(zone_dialog){
1158 zone_press(key, c);
1159 redraw_all();
1160 return;
1163 switch(key){
1164 case SDLK_u:
1165 undo();
1166 console_printf("undo"); break;
1167 case SDLK_r:
1168 redo();
1169 console_printf("redo"); break;
1170 case SDLK_1:
1171 toggle_background = !toggle_background;
1172 console_printf("background %s", onoff(toggle_background));
1173 break;
1174 case SDLK_2:
1175 toggle_bgtiles = !toggle_bgtiles;
1176 console_printf("bg tiles %s", onoff(toggle_bgtiles));
1177 break;
1178 case SDLK_3:
1179 toggle_fgtiles = !toggle_fgtiles;
1180 console_printf("fg tiles %s", onoff(toggle_fgtiles));
1181 break;
1182 case SDLK_4:
1183 toggle_shapes = !toggle_shapes;
1184 console_printf("shapes %s", onoff(toggle_shapes));
1185 break;
1186 case SDLK_s:
1187 if(mod & (KMOD_LCTRL|KMOD_RCTRL)){
1188 if(my_file[0] == 0){
1189 save_as_dialog = 1;
1191 else{
1192 save(my_file);
1195 break;
1196 case SDLK_w:
1197 save_as_dialog = 1;
1198 break;
1199 case SDLK_o:
1200 open_dialog = 1;
1201 break;
1202 case SDLK_z:
1203 zone_dialog = 1;
1204 break;
1205 case SDLK_i:
1206 console_printf("name: %s", my_file);
1207 console_printf("zone: %s", zone_path);
1208 console_printf("size: %d x %d", raw_w, raw_h);
1209 console_printf("background: %s", bgimage_file);
1210 console_printf("bg tileset: %s", bgtiles_file);
1211 console_printf("fg tileset: %s", fgtiles_file);
1212 break;
1213 case SDLK_q:
1214 case SDLK_ESCAPE:
1215 console_printf("Really quit? (Y/N)");
1216 quit_dialog = 1;
1217 break;
1218 case SDLK_n:
1219 raw_new();
1220 break;
1221 case SDLK_h:
1222 case SDLK_F1:
1223 case SDLK_SLASH:
1224 console_printf("arrow keys - move");
1225 console_printf("left mouse - draw");
1226 console_printf("right mouse - erase");
1227 console_printf("space - open toolbox");
1228 console_printf("ctrl+s - save");
1229 console_printf("w - save as");
1230 console_printf("o - open");
1231 console_printf("n - new file");
1232 console_printf("z - change zone");
1233 console_printf("1 2 3 4 - toggle layers");
1234 console_printf("i - file info");
1235 console_printf("F1 h ? - this help");
1236 console_printf("ESCAPE q - quit / cancel");
1237 console_printf("F5 - select background");
1238 console_printf("F6 - select bg tileset");
1239 console_printf("F7 - select fg tileset");
1240 console_printf("e - choose eyedropper");
1241 console_printf("x - choose eraser");
1242 break;
1243 case SDLK_F5:
1244 background_dialog = 1;
1245 break;
1246 case SDLK_F6:
1247 tileset_dialog = 1;
1248 brush_layer = 1;
1249 break;
1250 case SDLK_F7:
1251 tileset_dialog = 1;
1252 brush_layer = 2;
1253 break;
1254 case SDLK_LEFT: camera_x--; break;
1255 case SDLK_RIGHT: camera_x++; break;
1256 case SDLK_UP: camera_y--; break;
1257 case SDLK_DOWN: camera_y++; break;
1259 case SDLK_SPACE:
1260 tools_dialog = 1;
1261 break;
1263 /* temporary controls */
1264 case SDLK_9: brush_tile--; brush_tile %= 256; break;
1265 case SDLK_0: brush_tile++; brush_tile %= 256; break;
1266 case SDLK_8: brush_layer = 2; break;
1267 case SDLK_7: brush_layer = 1; break;
1270 redraw_all();
1273 U - undo
1274 R - redo
1275 1 - toggle layer 1
1276 2 - toggle layer 2
1277 3 - toggle layer 3
1278 4 - toggle layer 4
1279 ctrl S - save
1280 W - save as
1281 O - open stage
1282 B - change background
1283 Q - quit
1284 ESC - quit / cancel
1285 ENTER - yes / OK
1286 Y - yes
1287 N - no
1288 H - help
1289 ? - help
1290 F1 - help
1291 F2 - change fg tileset
1292 F3 - change bg tileset
1293 ARROW KEYS - scroll
1297 void translate_pointer(int mx, int my, int *x, int *y){
1298 int a, b;
1299 map_pixel(mx, my, &a, &b);
1300 *x = a/16 + camera_x + origin_x;
1301 *y = b/16 + camera_y + origin_y;
1305 void mousedown(int mx, int my, int button){
1307 hold LMB - draw single tiles / deselect
1308 shift LMB - start box select
1309 ctrl LMB - append single tiles to selection
1310 RMB - display tilesets
1311 hold MMB - choose where to paste (release to execute, esc to cancel)
1313 SDLMod mod = SDL_GetModState();
1315 int x, y;
1316 translate_pointer(mx, my, &x, &y);
1318 if(tools_dialog){
1319 tools_click(mx, my);
1320 return;
1323 if(tile_panel){
1324 if(tile_panel_click(mx, my)){
1325 return;
1330 if(button == 1){
1331 raw_write(x, y, brush_layer, brush_tile);
1332 brush_enable = 1;
1333 redraw_all();
1335 else if(button == 3){
1336 erase_enable = 1;
1337 if(brush_layer == 3){
1338 raw_write(x, y, 3, '0');
1340 else{
1341 raw_write(x, y, brush_layer, 0);
1343 redraw_all();
1348 void mouseup(int x, int y, int button){
1350 LMB - stop drawing
1351 shift LMB - append box to selection
1352 MMB - execute paste
1355 if(button == 1){
1356 brush_enable = 0;
1359 if(button == 3){
1360 erase_enable = 0;
1365 void mousemove(int mx, int my, int xrel, int yrel){
1367 redraw cursor
1368 redraw box select
1369 redraw paste box
1371 int x, y;
1372 translate_pointer(mx, my, &x, &y);
1374 if(brush_enable){
1375 raw_write(x, y, brush_layer, brush_tile);
1376 redraw_all();
1378 if(erase_enable){
1379 if(brush_layer == 3){
1380 raw_write(x, y, 3, '0');
1382 else{
1383 raw_write(x, y, brush_layer, 0);
1385 redraw_all();
1389 int check_events(){
1390 SDL_Event e;
1392 if(SDL_WaitEvent(&e) == 0){
1393 printf("SDL_WaitEvent encountered an error (%s)\n", SDL_GetError());
1394 return 1;
1397 switch(e.type){
1398 case SDL_QUIT: return 1;
1399 case SDL_KEYDOWN: keydown(e.key.keysym.sym, e.key.keysym.mod, e.key.keysym.unicode); return 0;
1400 case SDL_MOUSEMOTION:
1401 mousemove(e.motion.x, e.motion.y, e.motion.xrel, e.motion.yrel);
1402 return 0;
1403 case SDL_MOUSEBUTTONDOWN: mousedown(e.button.x, e.button.y, e.button.button); return 0;
1404 case SDL_MOUSEBUTTONUP: mouseup(e.button.x, e.button.y, e.button.button); return 0;
1405 default: return 0;
1411 void terminate(){
1412 loader_quit();
1413 video_quit();
1416 int main(int argc, char* argv[]){
1417 video_init(argc, argv);
1418 loader_init();
1419 graphics_init();
1421 raw_tiles = initialize_raw(raw_w, raw_h);
1423 update_window_name();
1425 shapes = load_bitmap("gfx/shapes.tga");
1426 tools = load_bitmap("gfx/tools.tga");
1428 loader_data_mode(0);
1429 // bgimage = load_bitmap("azone/gfx/background.tga");
1430 // loader_data_mode(0);
1431 // fgtiles = load_bitmap("barf.tga");
1432 // loader_data_mode(1);
1433 // fgtiles = load_bitmap("azone/gfx/barf.tga");
1434 // bgtiles = load_bitmap("azone/gfx/test.tga");
1436 set_zone_path("azone");
1438 redraw_all();
1440 SDL_ShowCursor(1);
1441 SDL_EnableUNICODE(1);
1442 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
1444 atexit(terminate);
1446 while(check_events() == 0 && panic_flag == 0);
1448 return 0;