diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-05-23 03:14:37 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2009-05-23 03:14:37 +0800 |
commit | 4e99d190bd3613df80d09a9244fe964c15a8f1c9 (patch) | |
tree | 826f624cd678971264c4b4aa36ec0ba2810dc218 | |
parent | 80d2d9d294bbbc20c27cbe2f8f604854e9c4a045 (diff) | |
download | pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.tar pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.tar.gz pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.tar.bz2 pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.tar.lz pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.tar.xz pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.tar.zst pttbbs-4e99d190bd3613df80d09a9244fe964c15a8f1c9.zip |
pmore: add include/interrupt (LI) command
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4459 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | docs/pmore_movie.txt | 30 | ||||
-rw-r--r-- | mbbsd/pmore.c | 102 |
2 files changed, 121 insertions, 11 deletions
diff --git a/docs/pmore_movie.txt b/docs/pmore_movie.txt index 734412c8..d60c8c62 100644 --- a/docs/pmore_movie.txt +++ b/docs/pmore_movie.txt @@ -3,8 +3,8 @@ pmore 2007 互動式動畫系統技術手冊 - VERSION 1.4 - 最後更新: 2008/03/02 16:00 + VERSION 1.5 + 最後更新: 2009/05/23 03:00 本文為推廣用說明文件 歡迎自由轉錄 不需另行通知作者 @@ -400,6 +400,9 @@ - 跳頁失敗時會視情況變成改顯示下張畫面或是停止播放 - 跳頁失敗時請檢查 cmd 的 type 是否忘了寫,如 ^LG2 + ** 2009 修正: 在互動式播放時,跳頁的0.1秒中按一般鍵不會再中斷播放 + (只有按系統中斷鍵如 q,Q,^C 等才會中斷) + ----------------------------------------------------------------------------- 2.3 互動選項 @@ -464,7 +467,28 @@ 註: ^L# 在執行時會依順序判斷按鍵是否符合條件。也就是說, 若有熱鍵重複出現則是前面的會被執行。 適當排列並與特殊按鍵 (見 3.1) 如 @a 合用則可作出「按 XX 鍵執行 YY,其它所有鍵都執行 ZZ」的效果。 - + +----------------------------------------------------------------------------- + +2.4 引用 (*** 2009 新增 ***) + + ^LIcmd_from,cmd_to + + INCLUDE 引用 (or INTERRUPT) + + 有些動畫會想重複使用某些片段、並且在片段結束時跳回原處; + 這個指令就是為此設計的。 + cmd_from 與 cmd_to 的語法請參見 2.1 動畫編號方式。 + 實際執行效果是: + (1) 假設這個指令出現在第 n 張 frame + (1) 跳到 cmd_from 播放 + (2) 一直播放到 cmd_to 時(該張不顯示),跳回 n+1 處播放。 + + 注意目前的「引用」只有一層,若在 ^LI 執行中再使用 ^LI , + 則只有最後一次出現的 ^LI 有效。 + + 範例: + ^LI:my_start:,:my_end: (引用播放 :mystart: 到 :myend: 的部份) ============================================================================= diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index 2b447ede..96ca4534 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -622,6 +622,8 @@ typedef struct { struct timeval synctime; unsigned char *options, *optkeys; + unsigned char *intr_src; + unsigned int intr_dest_frame; unsigned char mode, compat24, interactive, @@ -645,6 +647,8 @@ MF_Movie mfmovie; mfmovie.mode = MFDISP_MOVIE_UNKNOWN; \ mfmovie.options = NULL; \ mfmovie.optkeys = NULL; \ + mfmovie.intr_src= NULL; \ + mfmovie.intr_dest_frame = 0; \ mfmovie.compat24 = 1; \ mfmovie.pause = 0; \ mfmovie.interactive = 0; \ @@ -661,7 +665,7 @@ unsigned char * void mf_float2tv(float f, struct timeval *ptv); -MFPROTO int pmore_wait_key(struct timeval *ptv, int dorefresh); +MFPROTO int mf_movieWaitKey(struct timeval *ptv, int dorefresh); MFPROTO int mf_movieNextFrame(); MFPROTO int mf_movieSyncFrame(); MFPROTO int mf_moviePromptPlaying(int type); @@ -3019,7 +3023,7 @@ mf_str2float(unsigned char *p, unsigned char *end, float *pf) * override if you have better methods. */ MFPROTO int -pmore_wait_key(struct timeval *ptv, int dorefresh) +mf_movieWaitKey(struct timeval *ptv, int dorefresh) { int sel = 0; fd_set readfds; @@ -3328,11 +3332,9 @@ mf_movieGotoNamedFrame(const unsigned char *name, const unsigned char *end) while (p < end && isalnum(*p)) p++; sz = p - name; - if (sz < 1) return 0; // now search entire file for frame - mf_goTop(); do @@ -3397,6 +3399,30 @@ mf_movieGotoFrame(int fno, int relative) return 1; } +// warning: getting current frame number is SLOW. +MFPROTO int +mf_movieCurrentFrameNo() +{ + int no = 0; + unsigned char *p = mf.disps; + mf_goTop(); + + do + { + if ( mf_movieFrameHeader(mf.disps, mf.end)) + no++; + + if (mf.disps >= p) + break; + + if (mf_forward(1) < 1) + break; + + } while ( 1 ); // mf.disps < p); + + return no; +} + MFPROTO int mf_parseOffsetCmd( unsigned char *s, unsigned char *end, @@ -3696,7 +3722,7 @@ mf_movieOptionHandler(unsigned char *opt, unsigned char *end) mfmovie.optkeys = NULL; mf_float2tv(optclk, &tv); - c = pmore_wait_key(&tv, 1); + c = mf_movieWaitKey(&tv, 1); mfmovie.optkeys = tmpopt; // if timeout, drop. @@ -3803,14 +3829,14 @@ mf_movieSyncFrame() if(dv.tv_sec < 0) return 1; - return !pmore_wait_key(&dv, 0); + return !mf_movieWaitKey(&dv, 0); } else { /* synchronize each frame clock model */ /* because Linux will change the timeval passed to select, * let's use a temp value here. */ struct timeval dv = mfmovie.frameclk; - return !pmore_wait_key(&dv, 0); + return !mf_movieWaitKey(&dv, 0); } } @@ -3845,6 +3871,50 @@ mf_movieProcessCommand(unsigned char *p, unsigned char *end) return p; } + else if (*p == 'I') + { + // INTERRUPT + // Syntax: Icmd_from,cmd_to + // Jump cmd_from, and execute until cmd_to, + // then back here for next frame. + unsigned char *pfs, *pfe, *pts, *pte; + int curr_fno; + + mfmovie.intr_src = NULL; + mfmovie.intr_dest_frame = 0; + + // find parameters + pfs = pfe = p+1; + while (pfe < end && *pfe > ' ' && *pfe != ',') + pfe++; + pts = pte = pfe+1; + while (pte < end && *pte > ' ' && *pte != ',') + pte++; + // check syntax + if ( pfe >= end || *pfe != ',' || + pts >= end) + { + MOVIECMD_SKIP_ALL(p,end); + return p; + } + + // get the address of next frame + curr_fno = mf_movieCurrentFrameNo(); + mfmovie.intr_dest_frame = curr_fno +1; + + // find interrupt source (cmd_to) + mf_movieExecuteOffsetCmd(pts, pte); + mfmovie.intr_src = mf.disps; + + // final execution + mf_movieGotoFrame(curr_fno, 0); + mf_movieExecuteOffsetCmd(pfs, pfe); + + // XXX what if jump to same location? + + MOVIECMD_SKIP_ALL(p,end); + return p; + } else if (*p == 'G') { // GOTO @@ -3979,6 +4049,15 @@ mf_movieNextFrame() float nf = 0; unsigned char *odisps = mf.disps; + // check if we reached interrupt breakpoint + if (odisps == mfmovie.intr_src) + { + mfmovie.intr_src = NULL; + mf_movieGotoFrame(mfmovie.intr_dest_frame, 0); + mfmovie.intr_dest_frame = 0; + continue; + } + /* process leading */ p = mf_movieProcessCommand(p, mf.end); @@ -3989,9 +4068,16 @@ mf_movieNextFrame() // support at least one frame pause // to allow user break struct timeval tv; + int c; mf_float2tv(MOVIE_MIN_FRAMECLK, &tv); - if (pmore_wait_key(&tv, 0)) + // XXX TODO when using interactive mode, + // allow only special keys to break. + c = mf_movieWaitKey(&tv, 0); + if (mfmovie.interactive && c != 1) // c == 1: unknown error + c = mf_movieIsSystemBreak(c); + + if (c) { STOP_MOVIE(); return 0; |