summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-05-23 03:14:37 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2009-05-23 03:14:37 +0800
commit4e99d190bd3613df80d09a9244fe964c15a8f1c9 (patch)
tree826f624cd678971264c4b4aa36ec0ba2810dc218
parent80d2d9d294bbbc20c27cbe2f8f604854e9c4a045 (diff)
downloadpttbbs-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.txt30
-rw-r--r--mbbsd/pmore.c102
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;