Save as dialog, and confirm save dialog.
[cantaveria.git] / edit.c
blob352149039ebff271dac3e0dff4daae2faa5ab3ff
1 #include <stdio.h>
2 #include <stdlib.h>
4 #include <SDL/SDL.h>
8 #include <list.h>
9 #include <console.h>
10 #include <stage.h>
11 #include <loader.h>
12 #include <kernel.h>
13 #include <graphics.h>
14 #include <console.h>
16 struct edit {
17 int x;
18 int y;
19 char shape;
20 unsigned char fg;
21 unsigned char bg;
22 struct edit* next;
25 struct tile {
26 char shape;
27 unsigned char fg;
28 unsigned char bg;
31 struct undo_step {
32 struct tile* undo; /* writes to undo */
33 struct tile* redo; /* writes to redo */
34 struct edit* next;
35 struct edit* prev;
40 /* application state variables */
41 int toggle_background = 1;
42 int toggle_bgtiles = 1;
43 int toggle_fgtiles = 1;
44 int toggle_shapes = 0;
46 int origin_x = 0;
47 int origin_y = 0;
48 static int camera_x = 0;
49 static int camera_y = 0;
51 char my_file[256] = "";
52 char my_file_old[256] = "";
53 char bgimage_file[256] = "";
54 char fgtiles_file[256] = "";
55 char bgtiles_file[256] = "";
56 int bgimage = 0;
57 int fgtiles = 0;
58 int bgtiles = 0;
60 int select_enable = 0;
61 int select_x = 0;
62 int select_y = 0;
63 int select_w = 0;
64 int select_h = 0;
66 struct tile* raw_tiles = NULL;
67 int raw_w = 20;
68 int raw_h = 15;
70 int show_favorites = 0;
71 int bg_favorites[7] = {0,0,0,0,0,0,0};
72 int fg_favorites[7] = {0,0,0,0,0,0,0};
73 int brush_tile = 1;
74 int brush_layer = 1;
75 int brush_enable = 0;
77 int panic_flag = 0;
79 int dialog_flag = 0;
80 int brush_dialog = 0;
81 int background_dialog = 0;
82 int tileset_dialog = 0;
83 int quit_dialog = 0;
84 int save_as_dialog = 0;
85 int open_dialog = 0;
86 int confirm_save_dialog = 0;
90 char save_as_buf[256] = "";
91 int save_as_ptr = 0;
92 /* *** */
95 /* base access methods */
96 struct tile* initialize_raw(int w, int h){
97 int i;
98 int j;
99 struct tile blank = {'0', 0, 0};
100 struct tile* ptr = malloc(w*h*sizeof(struct tile));
101 for(j=0; j<h; j++){
102 for(i=0; i<w; i++){
103 *(ptr + i + j*w) = blank;
107 return ptr;
110 void unload_raw(){
111 free(raw_tiles);
114 struct tile raw_read(int x, int y){
115 struct tile blank = {'0', 0, 0};
116 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h){
117 return blank;
119 else{
120 return *(raw_tiles + x + raw_w*y);
124 void expand_raw(){
125 int new_w = raw_w * 3;
126 int new_h = raw_h * 3;
127 struct tile* new_tiles = initialize_raw(new_w, new_h);
128 struct tile* ptr;
129 struct tile t;
130 int i;
131 int j;
133 for(j=raw_h; j<2*raw_h; j++){
134 for(i=raw_w; i<2*raw_w; i++){
135 ptr = new_tiles + i + j*(3*raw_w);
136 t = raw_read(i-raw_w, j-raw_h);
137 *ptr = t;
141 origin_x += raw_w;
142 origin_y += raw_h;
143 raw_w *= 3;
144 raw_h *= 3;
145 free(raw_tiles);
146 raw_tiles = new_tiles;
149 int out_of_bounds(int x, int y){
150 if(x < 0 || y < 0 || x >= raw_w || y >= raw_h)
151 return 1;
152 else
153 return 0;
156 void detect_size(int* w, int* h){
157 //see the minimum size necessary for the area
158 //used for saving
161 void raw_write(int x, int y, int layer, int value){
162 while(out_of_bounds(x, y)){
163 printf("expanding\n");
164 expand_raw();
165 x += raw_w / 3;
166 y += raw_h / 3;
169 //expand if outside
170 //shift x y by expand shift
171 //shift x and y by origin
172 //do the write
173 struct tile* ptr = raw_tiles + x + raw_w*y;
174 if(layer == 1){
175 ptr->bg = value;
177 else if(layer == 2){
178 ptr->fg = value;
180 else if(layer == 3){
181 ptr->shape = value;
185 void draw_background(){
186 int W = gfx_width(bgimage);
187 int H = gfx_height(bgimage);
188 draw_gfx_raw(bgimage, 0, 0, 0, 0, W, H);
191 void draw_raw(){
192 int x0 = camera_x + origin_x;
193 int y0 = camera_y + origin_y;
194 int i;
195 int j;
196 int x;
197 int y;
198 struct tile t;
199 int gx;
200 int gy;
202 if(toggle_background)
203 draw_background();
205 for(j=0; j<(15+5); j++){
206 y = y0 + j;
207 for(i=0; i<(20+8); i++){
208 x = x0 + i;
209 t = raw_read(x, y);
210 gy = 16*(t.bg / 16);
211 gx = 16*(t.bg % 16);
212 if(toggle_bgtiles)
213 draw_gfx_raw(bgtiles, i*16, j*16, gx, gy, 16, 16);
214 gy = 16*(t.fg / 16);
215 gx = 16*(t.fg % 16);
216 if(toggle_fgtiles)
217 draw_gfx_raw(fgtiles, i*16, j*16, gx, gy, 16, 16);
223 /* *** */
227 void update_window_name(){
228 if(my_file[0] == 0){
229 SDL_WM_SetCaption("unnamed", NULL);
231 else{
232 SDL_WM_SetCaption(my_file, NULL);
238 struct undo_step* undo_stack;
239 struct undo_step* undo_ptr;
241 /* undo operations */
242 void undo(){
243 //do the undo_ptr->undo operations
244 //move undo_ptr down one
247 void redo(){
248 //if at top of stack, do nothing
250 //do the undo_ptr->redo operations
251 //move undo_ptr up one
254 void undo_record(struct edit* edits){
255 //eliminate undo_ptr->redo and all previous edit structs
256 //change the undo_stack
258 //store the edits in undo_ptr->redo
259 //calculate the undo operation XXX
260 //push a new edit struct
261 //move undo_ptr
262 //store the undo operation in undo_ptr->undo
264 /* *** */
269 /* medium level editting commands */
270 void write_one_tile(int x, int y, int layer, int value){
271 //write x y layer value
274 void write_many_tiles(struct edit* edits){
275 //for each tiles
276 //write one tile
279 void edit_one_tile(int x, int y, int layer, int value){
280 //write_one_tile
281 //create a tile struct
282 //call edit on it
285 void edit_many_tiles(struct edit* edits){
286 //write many tiles
287 //edit(tiles)
290 void add_to_clipboard(struct edit* edits){
291 //makes a tile struct and appends to clipboard
294 void clear_clipboard(){
295 //clear the clipboard
298 struct tile* read_tile(int x, int y){
299 //make a tile struct
301 /* *** */
305 /* high level gui commands */
306 void select_brush(int layer, int value){
310 void start_box(int x, int y){
314 void move_box(int x, int y){
318 void stop_box(){
322 void clear_box(){
326 void append_to_box(int x, int y){
330 struct tile* box_select(){
335 void move_paste(int x, int y){
339 void cancel_paste(){
343 void do_paste(){
348 void redraw_all(){
349 clear_video();
351 draw_raw();
353 //gui indicators
354 if(select_enable){
355 //draw green box
358 //dialogs
359 if(save_as_dialog){
360 console_printf("save as: %s", save_as_buf);
364 console_draw();
365 console_clear();
367 update_video();
370 char* onoff(int b){
371 if(b) return "on";
372 else return "off";
377 void save(char* path){
378 /* save current stage to a stage file */
379 /* overwrites if already exists, no confirmation */
380 FILE* f = fopen(path, "w");
381 if(f == NULL){
382 console_printf("error saving file");
383 return;
386 fprintf(f, "HELLO WORLD\n");
388 fclose(f);
391 /* *** */
396 /* dialog input handlers */
397 void confirm_save_press(SDLKey key, Uint16 c){
398 if(c == 'y' || c == 'Y'){
399 save(my_file);
400 update_window_name();
401 console_printf("You're the boss. %s was overwritten", my_file);
403 else{
404 strcpy(my_file, my_file_old); /* ! */
405 console_printf("Operation cancelled");
408 confirm_save_dialog = 0;
411 void save_as_press(SDLKey key, Uint16 c){
412 FILE* f;
413 if(c == 0){
415 else if(c == '\r'){
416 if(save_as_buf[0] == 0){
417 console_printf("No name? Nevermind then.");
419 else{
420 strcpy(my_file_old, my_file); /* ! */
421 strcpy(my_file, save_as_buf); /* ! */
423 /* see if file exists */
424 f = fopen(my_file, "r");
425 if(f != NULL){
426 console_printf("ALERT: really overwrite %s? (Y/N)", my_file);
427 confirm_save_dialog = 1;
428 fclose(f);
430 else{
431 update_window_name();
432 console_printf("%s saved", my_file);
433 save(my_file);
436 save_as_buf[0] = 0;
437 save_as_ptr = 0;
438 save_as_dialog = 0;
440 else if(c == 0x1b){
441 save_as_buf[0] = 0;
442 save_as_ptr = 0;
443 save_as_dialog = 0;
445 else if(c == '\b'){
446 if(save_as_ptr > 0){
447 save_as_ptr--;
448 save_as_buf[save_as_ptr] = 0;
451 else{
452 if(save_as_ptr < 255){
453 save_as_buf[save_as_ptr] = c;
454 save_as_ptr++;
455 save_as_buf[save_as_ptr] = 0;
465 void keydown(SDLKey key, SDLMod mod, Uint16 c){
467 if(save_as_dialog){
468 save_as_press(key, c);
469 redraw_all();
470 return;
473 if(confirm_save_dialog){
474 confirm_save_press(key, c);
475 redraw_all();
476 return;
479 switch(key){
480 case SDLK_u:
481 undo();
482 console_printf("undo"); break;
483 case SDLK_r:
484 redo();
485 console_printf("redo"); break;
486 case SDLK_1:
487 toggle_background = !toggle_background;
488 console_printf("background %s", onoff(toggle_background));
489 break;
490 case SDLK_2:
491 toggle_bgtiles = !toggle_bgtiles;
492 console_printf("bg tiles %s", onoff(toggle_bgtiles));
493 break;
494 case SDLK_3:
495 toggle_fgtiles = !toggle_fgtiles;
496 console_printf("fg tiles %s", onoff(toggle_fgtiles));
497 break;
498 case SDLK_4:
499 toggle_shapes = !toggle_shapes;
500 console_printf("shapes %s", onoff(toggle_shapes));
501 break;
502 case SDLK_s:
503 if(mod & (KMOD_LCTRL|KMOD_RCTRL)){
504 if(my_file[0] == 0){
505 save_as_dialog = 1;
507 else{
508 save(my_file);
509 console_printf("saved %s", my_file);
512 break;
513 case SDLK_w:
514 save_as_dialog = 1;
515 break;
516 case SDLK_o:
517 console_printf("open...");
518 break;
519 case SDLK_b:
520 console_printf("change background...");
521 break;
522 case SDLK_q:
523 if(dialog_flag == 0){
524 dialog_flag = 1;
525 quit_dialog = 1;
527 break;
528 case SDLK_ESCAPE:
529 panic_flag = 1;
530 if(dialog_flag == 0){
531 dialog_flag = 1;
532 quit_dialog = 1;
534 else{
535 dialog_flag = 0;
537 break;
538 case SDLK_RETURN:
539 console_printf("OK");
540 break;
541 case SDLK_y:
542 console_printf("yes");
543 break;
544 case SDLK_n:
545 console_printf("no");
546 break;
547 case SDLK_h:
548 case SDLK_F1:
549 case SDLK_SLASH:
550 console_printf("help...");
551 break;
552 case SDLK_F2:
553 console_printf("pick fg tileset...");
554 break;
555 case SDLK_F3:
556 console_printf("pick bg tileset...");
557 break;
558 case SDLK_LEFT: camera_x--; break;
559 case SDLK_RIGHT: camera_x++; break;
560 case SDLK_UP: camera_y--; break;
561 case SDLK_DOWN: camera_y++; break;
563 /* temporary controls */
564 case SDLK_9: brush_tile--; brush_tile %= 256; break;
565 case SDLK_0: brush_tile++; brush_tile %= 256; break;
566 case SDLK_8: brush_layer = 2; break;
567 case SDLK_7: brush_layer = 1; break;
570 redraw_all();
573 U - undo
574 R - redo
575 1 - toggle layer 1
576 2 - toggle layer 2
577 3 - toggle layer 3
578 4 - toggle layer 4
579 ctrl S - save
580 W - save as
581 O - open stage
582 B - change background
583 Q - quit
584 ESC - quit / cancel
585 ENTER - yes / OK
586 Y - yes
587 N - no
588 H - help
589 ? - help
590 F1 - help
591 F2 - change fg tileset
592 F3 - change bg tileset
593 ARROW KEYS - scroll
597 void translate_pointer(int mx, int my, int *x, int *y){
598 int a, b;
599 map_pixel(mx, my, &a, &b);
600 *x = a/16 + camera_x + origin_x;
601 *y = b/16 + camera_y + origin_y;
605 void mousedown(int mx, int my, int button){
607 hold LMB - draw single tiles / deselect
608 shift LMB - start box select
609 ctrl LMB - append single tiles to selection
610 RMB - display tilesets
611 hold MMB - choose where to paste (release to execute, esc to cancel)
613 SDLMod mod = SDL_GetModState();
615 int x, y;
616 translate_pointer(mx, my, &x, &y);
618 if(brush_dialog){
619 //change brush, maybe
620 brush_dialog = 0;
621 return;
627 if(button == 1){
628 raw_write(x, y, brush_layer, brush_tile);
629 brush_enable = 1;
630 redraw_all();
632 else if(button == 3){
633 brush_dialog = 1;
634 redraw_all();
639 void mouseup(int x, int y, int button){
641 LMB - stop drawing
642 shift LMB - append box to selection
643 MMB - execute paste
646 if(button == 1){
647 brush_enable = 0;
652 void mousemove(int mx, int my, int xrel, int yrel){
654 redraw cursor
655 redraw box select
656 redraw paste box
658 int x, y;
659 translate_pointer(mx, my, &x, &y);
661 if(brush_enable){
662 raw_write(x, y, brush_layer, brush_tile);
663 redraw_all();
667 int check_events(){
668 SDL_Event e;
670 if(SDL_WaitEvent(&e) == 0){
671 printf("SDL_WaitEvent encountered an error (%s)\n", SDL_GetError());
672 return 1;
675 switch(e.type){
676 case SDL_QUIT: return 1;
677 case SDL_KEYDOWN: keydown(e.key.keysym.sym, e.key.keysym.mod, e.key.keysym.unicode); return 0;
678 case SDL_MOUSEMOTION:
679 mousemove(e.motion.x, e.motion.y, e.motion.xrel, e.motion.yrel);
680 return 0;
681 case SDL_MOUSEBUTTONDOWN: mousedown(e.button.x, e.button.y, e.button.button); return 0;
682 case SDL_MOUSEBUTTONUP: mouseup(e.button.x, e.button.y, e.button.button); return 0;
683 default: return 0;
689 void terminate(){
690 loader_quit();
691 video_quit();
694 int main(int argc, char* argv[]){
695 video_init(argc, argv);
696 loader_init();
697 graphics_init();
699 raw_tiles = initialize_raw(raw_w, raw_h);
701 update_window_name();
703 loader_data_mode(0);
704 bgimage = load_bitmap("azone/gfx/background.tga");
705 // loader_data_mode(0);
706 // fgtiles = load_bitmap("barf.tga");
707 // loader_data_mode(1);
708 fgtiles = load_bitmap("azone/gfx/barf.tga");
709 bgtiles = load_bitmap("azone/gfx/test.tga");
711 raw_write(2, 2, 1, 3);
713 redraw_all();
715 SDL_ShowCursor(1);
716 SDL_EnableUNICODE(1);
717 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
719 atexit(terminate);
721 while(check_events() == 0 && panic_flag == 0);
723 return 0;