Index: bindings.doc ================================================================== --- bindings.doc +++ bindings.doc @@ -130,10 +130,13 @@ positive to make slower; zero leaves it unchanged). === Editor commands === +'^I' + Level index editor. + '^N' Add a new level (after the last one). The new level has the same dimensions as the current level, but contains no objects or strings, and the title is set to "New Level". Index: default.heromeshrc ================================================================== --- default.heromeshrc +++ default.heromeshrc @@ -155,10 +155,11 @@ ?.editKey.C: select 'lc',:level_code where :level_code=cast(:level_code as int); ?.editKey.E: ^s ?.editKey.F: with n(n) as (select 65 union all select n+1 h from n where h<=64*pfheight()+65) select '^a',n from n; ?.editKey.R: select 're',substr(:resize,1,instr(:resize,'x')-1),substr(:resize,instr(:resize,'x')+1) where length(:resize); ?.editKey.W: ^w +?.editKey.ctrl.I: ^I ?.editKey.ctrl.N: ^N ?.editKey.ctrl.P: ^P ?.editKey.ctrl.X: select 're',pfwidth(),pfheight(); ?.editKey.space: ^c ?.editKey.return: ^e Index: edit.c ================================================================== --- edit.c +++ edit.c @@ -1531,10 +1531,278 @@ exit(0); return -1; } } } + +typedef struct { + char*title; + Uint16 id,kind,mark; +} IndexItem; + +static void level_index_editor(void) { + SDL_Rect r; + SDL_Event ev; + char had_divisions=0; + FILE*out; + char*buf=0; + char b[32]; + size_t bufsize=0; + IndexItem*items; + IndexItem*items2; + IndexItem citem; + int nitems; + int nmark=0; + sqlite3_stmt*st=0; + int i,j,x,y; + int sel=0; + int scroll=0; + char rescroll=1; + const char*q; + if(sqlite3_prepare_v2(userdb,"SELECT COUNT() FROM `DIVISIONS`;",-1,&st,0) || sqlite3_step(st)!=SQLITE_ROW) { + screen_message(sqlite3_errmsg(userdb)); + sqlite3_finalize(st); + return; + } + had_divisions=sqlite3_column_int(st,0)?1:0; + nitems=level_nindex+sqlite3_column_int(st,0); + sqlite3_finalize(st); + if(sqlite3_prepare_v2(userdb,"SELECT 0,`FIRST`,0,`HEADING`,_ROWID_ FROM `DIVISIONS` UNION ALL SELECT 1,`ORD`,`ID`,`TITLE`,0 FROM `LEVELS` ORDER BY 2,1,5;",-1,&st,0)) { + screen_message(sqlite3_errmsg(userdb)); + return; + } + items=calloc(nitems,sizeof(IndexItem)); + if(!items) fatal("Allocation failed\n"); + for(i=0;i"); + if(!items[i].title) fatal("Allocation failed\n"); + } + sqlite3_finalize(st); + // Main editor loop (GUI) + set_cursor(XC_arrow); + redraw: + if(sel<0) sel=0; + if(sel>nitems) sel=nitems; + if(rescroll) { + if(scroll<0) scroll=0; + if(sel=scroll+screen->h/8-2) scroll=sel+3-screen->h/8; + rescroll=0; + } + SDL_FillRect(screen,0,0x02); + r.x=r.y=0; + r.w=screen->w; + r.h=16; + SDL_FillRect(screen,&r,0xF7); + SDL_LockSurface(screen); + draw_text(0,0,"<\x18\x19> Cursor Exchange Add Division Delete Division Save",0xF7,0xF0); + draw_text(0,8," Edit Title Mark Paste Show Title Unmark All Find Current",0xF7,0xF0); + for(y=16,i=scroll;yh-7 && i<=nitems;y+=8,i++) { + if(i==sel) { + r.x=16; r.y=y; + r.w=screen->w-16; r.h=8; + SDL_FillRect(screen,&r,0xF8); + draw_text(16,y,"\x10",x=0xF8,nmark?0xFD:0xFE); + } else { + draw_text(16,y,"\xB3",x=0x02,0xF8); + } + draw_text(6*8,y,"\xB3",x,x^0xFA); + draw_text(12*8,y,"\xB3",x,x^0xFA); + if(i==nitems) { + draw_text(4*8,y,"\x04 END \x04",x,0xFC); + } else if(items[i].kind) { + snprintf(b,8,"%5u",items[i].id); + draw_text(7*8,y,b,x,0xFA); + draw_text(13*8,y,items[i].title,x,0xFF); + } else { + draw_text(7*8,y,"\x07\x07\x07\x07\x07",x,0xF9); + draw_text(13*8,y,items[i].title,x,0xFE); + } + if(ih-16; + scrollbar(&scroll,screen->h/8-2,nitems+1,0,&r); + SDL_Flip(screen); + while(SDL_WaitEvent(&ev)) { + if(ev.type!=SDL_VIDEOEXPOSE && scrollbar(&scroll,screen->h/8-2,nitems+1,&ev,&r)) goto redraw; + switch(ev.type) { + case SDL_MOUSEMOTION: + set_cursor(XC_arrow); + break; + case SDL_MOUSEBUTTONDOWN: + if(ev.button.x>=15) sel=(ev.button.y-16)/8+scroll; + if(ev.button.button==2) goto paste; + if(ev.button.button==3) goto mark; + goto redraw; + case SDL_KEYDOWN: + switch(ev.key.keysym.sym) { + case SDLK_UP: case SDLK_k: case SDLK_KP8: + if(!sel) break; + sel--; + if(ev.key.keysym.mod&(KMOD_ALT|KMOD_META)) { + while(sel>0 && items[sel].kind) sel--; + } else if((ev.key.keysym.mod&KMOD_SHIFT) && sel+1=nitems) break; + sel++; + if(ev.key.keysym.mod&(KMOD_ALT|KMOD_META)) { + while(selh/8-2; + scroll-=screen->h/8-2; + rescroll=1; goto redraw; + case SDLK_PAGEDOWN: case SDLK_KP3: + sel+=screen->h/8-2; + scroll+=screen->h/8-2; + rescroll=1; goto redraw; + case SDLK_HOME: case SDLK_KP7: scroll=sel=0; goto redraw; + case SDLK_END: case SDLK_KP1: sel=nitems; rescroll=1; goto redraw; + case SDLK_INSERT: case SDLK_KP0: + if(nitems>=65535) { + screen_message("Too many items"); + goto redraw; + } + q=screen_prompt("Add division?"); + if(!q || !*q) goto redraw; + items=realloc(items,(nitems+1)*sizeof(IndexItem)); + if(!items) fatal("Allocation failed\n"); + memmove(items+sel+1,items+sel,(nitems-sel)*sizeof(IndexItem)); + items[sel].kind=items[sel].mark=0; + items[sel].title=strdup(q); + if(!items[sel].title) fatal("Allocation failed\n"); + ++nitems; + rescroll=1; goto redraw; + case SDLK_DELETE: case SDLK_KP_PERIOD: + if(sel==nitems || items[sel].kind) break; + if(items[sel].mark) { + --nmark; + for(i=0;iitems[sel].mark) --items[i].mark; + } + free(items[sel].title); + memmove(items+sel,items+sel+1,(nitems-sel-1)*sizeof(IndexItem)); + --nitems; + goto redraw; + case SDLK_F1: case SDLK_e: + if(sel==nitems || items[sel].kind) break; + q=screen_prompt("Edit division?"); + if(!q || !*q) goto redraw; + free(items[sel].title); + items[sel].title=strdup(q); + if(!items[sel].title) fatal("Allocation failed"); + goto redraw; + case SDLK_F2: case SDLK_m: mark: + if(sel==nitems || items[sel].mark || nmark==999) goto redraw; + items[sel].mark=++nmark; + goto redraw; + case SDLK_F3: case SDLK_p: paste: + if(!nmark) goto redraw; + x=sel; + if(x=x) items[j++]=items2[i]; + } + free(items2); + nmark=0; + rescroll=1; goto redraw; + case SDLK_F4: case SDLK_t: + if(sel==nitems) break; + modal_draw_popup(items[sel].title); + goto redraw; + case SDLK_F5: case SDLK_u: + for(i=0;i='0' && *q<='9') { + j=strtol(q,0,10); + for(i=0;i>8,out); + fwrite(items[i].title,1,strlen(items[i].title)+1,out); + } + } + sqlite3_finalize(st); + if(!ftell(out)) { + if(!had_divisions) goto nodiv; + fputc(0,out); + } + fclose(out); + if(!buf) fatal("Allocation failed"); + write_lump(FIL_LEVEL,LUMP_DIVISION_IDX,bufsize,buf); + nodiv: + free(buf); + // LEVEL.IDX lump + update_level_index(); + // Done + final: + for(i=0;i0xFFFE) return 0; new_level(); return 1; case '^P': // Play Index: edit.doc ================================================================== --- edit.doc +++ edit.doc @@ -189,16 +189,40 @@ type "xclip" to export to the primary selection; you will need to install xclip to use this). See export.doc for the file format. + +=== Level index editor === + +You can push CTRL+I to activate the level index editor, which can be used +for reordering levels and for inserting divisions into the list of levels. + +The display shows the level ID number followed by the title of that level; +if it is a division then there is no ID number. There may also be another +number to the left of the ID number which is the mark number, if there is +any mark (see below for information). + +You can move cursor by arrows, and you can then exchange an item with the +one above or below by shift and arrows. If you push alt and arrows, will +move the cursor to the next division in that direction. + +Push insert to add a division (just above the cursor), or delete to delete +a division (only divisions can be deleted in this way, not levels). + +Another way to reorder the items is to add marks by pushing F2 (or click +by right mouse button) on each one, and tghen push F3 (or click by middle +mouse button) at the point to be moved to; they are removed from where +they were before and put here in the order in which they were marked. + === Summary of default key/mouse bindings === Keyboard: CTRL+G Go to level (won't auto save) + CTRL+I Level index editor CTRL+N Add new level (after last one) CTRL+P Switch to play game (won't auto save) CTRL+Q Quit (won't auto save) CTRL+S Save level CTRL+T Edit level title