0
|
1 /*
|
|
2 TODO:
|
|
3 日付のラベルが画面切り替え時に欠けるのを修正
|
|
4 画像効果 : 人間の入れ換わりなど
|
|
5 kcursor の操作を WidText クラスに任せる
|
|
6 WidText クラスには新たに以下の操作を加える
|
|
7 ・ウェイト終了後、クリアなしに新たなテキストを追加、新たにstart-waitする
|
|
8 ・文字の描画 (Start) と Wait(カーソル表示待ち)の分離。
|
|
9 Start すると文字を描画開始する。クリックで全描画。
|
|
10 Flush するとバッファ内の文字をすべて描画する
|
|
11 Wait すると全描画後、クリックされるまでカーソルを表示するまで待つ
|
|
12 TextImpl 側の状態としては Wait のみを持つ (PREPAREに戻るのを待つ)
|
|
13 ただし、Skip の権利はどっちがもつ?(現状は?)
|
|
14
|
|
15 GrpObj: NextObj と GrpObj を分離。CreateObj は現状通り、Visible=1 時に行う。
|
|
16 それぞれ num=0 (screen) の枝leaf として実装。delete時は親のdeleteのみを
|
|
17 行い、子はGrpObjの実体だけを削除する
|
|
18 Visible 後のhide は実際に hide とする
|
|
19 ExecReservedCmd() はなくせるはず。Delete() もなくなる。
|
|
20 カノギ:ReBlit() がうまくいかないせいで名前ウィンドウが消えた時の背景がなくなる
|
|
21
|
|
22 くら:回想表示
|
|
23 SEL画像効果
|
|
24 DONE:
|
|
25 ともよのテキストウィンドウ実装、ボタン実装
|
|
26 shake の画像効果
|
|
27 オブジェクト内のテキスト色の実装
|
|
28 画像効果の改善
|
|
29 */
|
|
30
|
|
31 /*
|
|
32 * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno
|
|
33 * All rights reserved.
|
|
34 *
|
|
35 * Redistribution and use in source and binary forms, with or without
|
|
36 * modification, are permitted provided that the following conditions
|
|
37 * are met:
|
|
38 * 1. Redistributions of source code must retain the above copyright
|
|
39 * notice, this list of conditions and the following disclaimer.
|
|
40 * 2. Redistributions in binary form must reproduce the above copyright
|
|
41 * notice, this list of conditions and the following disclaimer in the
|
|
42 * documentation and/or other materials provided with the distribution.
|
|
43 * 3. The name of the author may not be used to endorse or promote products
|
|
44 * derived from this software without specific prior written permission.
|
|
45 *
|
|
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
56 */
|
|
57
|
|
58 #include"window/event.h"
|
|
59 #include"window/picture.h"
|
|
60 #include"window/widget.h"
|
|
61 #include"system/file.h"
|
|
62 #include"system/system_config.h"
|
|
63 #include"scn2k.h"
|
|
64
|
|
65 #include<string>
|
|
66 using namespace std;
|
|
67
|
|
68 // kanji conv : デバッグ表示用
|
|
69 void kconv(const unsigned char* src, unsigned char* dest);
|
|
70 void kconv_rev(const unsigned char* src, unsigned char* dest);
|
|
71 string kconv(const string& s);
|
|
72 string kconv_rev(const string& s);
|
|
73 // render.cc
|
|
74 void DSurfaceFillA(Surface* src, const Rect& rect, int r, int g, int b, int a); // テキストウィンドウ背景の設定
|
|
75 void DSurfaceMove(Surface* src_o, const Rect& srcrect, Surface* dst_o, const Rect& dstrect); // コピー
|
|
76
|
|
77 /**************************************************************::
|
|
78 **
|
|
79 ** TextImpl(interface)
|
|
80 */
|
|
81 struct TimerAtom {
|
|
82 int from;
|
|
83 int to;
|
|
84 unsigned int start_time;
|
|
85 unsigned int total_time;
|
|
86 };
|
|
87
|
|
88 struct TextWindow {
|
|
89 /* @@@ : SetWindowColor での surface 再設定に注意 */
|
|
90 WidText* wid;
|
|
91 bool name_visible;
|
|
92 WidLabel* name;
|
|
93 PicContainer* name_container;
|
|
94 PicBase* face;
|
|
95 PicBase* face_pics[8];
|
|
96 TextWindow(PicContainer& parent, Event::Container& event, int window_no, const AyuSysConfig& config, void* callback);
|
|
97 ~TextWindow() {
|
|
98 if (name_container) delete name_container;
|
|
99 int i; for (i=0; i<8; i++) {
|
|
100 if (face_pics[i]) delete face_pics[i];
|
|
101 }
|
|
102 if (wid) delete wid;
|
|
103 }
|
|
104 Rect WakuSize(PicContainer& pic, int waku_no, const AyuSysConfig& config);
|
|
105 void MakeWaku(PicContainer& pic, Event::Container& event, int waku_no,int window_no, bool* use_btn, const AyuSysConfig& config, void* callback);
|
|
106 void show(void) {
|
|
107 wid->show();
|
|
108 if (name_container && name_visible) name_container->show();
|
|
109 if (face) face->show();
|
|
110 }
|
|
111 void hide(void) {
|
|
112 wid->hide();
|
|
113 if (name_container) name_container->hide();
|
|
114 if (face) face->hide();
|
|
115 }
|
|
116 void ShowFace(const char* path) {
|
|
117 if (!face) return;
|
|
118 face->SetSurface( path, 0,0);
|
|
119 }
|
|
120 void ResetFace(void) {
|
|
121 if (!face) return;
|
|
122 face->SetSurface( (Surface*)0, 0,0);
|
|
123 }
|
|
124 void StartText(const TextStream& _stream) {
|
|
125 wid->Clear();
|
|
126 wid->stream = _stream;
|
|
127 if (name_container) {
|
|
128 char namestr[1024];
|
|
129 namestr[0] = 0;
|
|
130 wid->stream.RemoveName(namestr, 1024);
|
|
131 if (namestr[0] == 0) {
|
|
132 name_container->hide();
|
|
133 } else {
|
|
134 if (name) {
|
|
135 name_container->show_all();
|
|
136 name->SetText(namestr);
|
|
137 }
|
|
138 }
|
|
139 }
|
|
140 wid->Start();
|
|
141 }
|
|
142 void SetName(const char* n) {
|
|
143 if (name_container && name) {
|
|
144 if (n[0]) {
|
|
145 name_container->show();
|
|
146 name->SetText(n);
|
|
147 name_visible = true;
|
|
148 } else {
|
|
149 name_container->hide();
|
|
150 name_visible = false;
|
|
151 }
|
|
152 }
|
|
153 }
|
|
154 };
|
|
155
|
|
156 class TextImpl {
|
|
157 private:
|
|
158 public:
|
|
159 TextWindow* text;
|
|
160 typedef enum {NORMAL=0, WAIT_TEXT=1, WAIT=2, WAIT_CLICK=3, WAIT_ABORT=4, WAIT_CLICK_MOUSEPOS = 5, WAIT_CLICK_MOUSEPOSEND_L = 6, WAIT_CLICK_MOUSEPOSEND_R = 7,
|
|
161 WAIT_SELECT_INBOX = 10, WAIT_SELECT_OUTBOX=11, WAIT_SELECT_VALUE = 12,
|
|
162 WAIT_EXTRN_MASK = 64, SAVEMASK = 128, LOADMASK = 256, SKIPMASK = 512,
|
|
163 CLEARSCR_MASK = 1024, STATSAVE_MASK = 2048, CLEARSCR_WAIT_MASK=(1<<12),
|
|
164 SKIPEND_MASK = (1<<13), BACKLOG_MASK=(1<<14), BACKLOG_MASK_FWD=(1<<15), BACKLOG_MASK_KOE=(1<<16), BACKLOG_WAIT_MASK=(1<<17),
|
|
165 ALLMASK = (CLEARSCR_MASK | WAIT_EXTRN_MASK | SAVEMASK | LOADMASK | SKIPMASK | BACKLOG_MASK | BACKLOG_MASK_FWD | BACKLOG_MASK_KOE | BACKLOG_WAIT_MASK | STATSAVE_MASK | CLEARSCR_WAIT_MASK | SKIPEND_MASK)
|
|
166 } Status;
|
|
167 Status status, status_saved, status_mask;
|
|
168 private:
|
|
169 std::string ruby_text;
|
|
170 bool ruby_text_flag;
|
|
171 unsigned int wait_time;
|
|
172 unsigned int old_time;
|
|
173 unsigned int base_time;
|
|
174 int text_window_number;
|
|
175 bool text_parsing;
|
|
176 TextStream text_stream;
|
|
177 SkipMode skip_mode;
|
|
178 int save_selectcount;
|
|
179
|
|
180 std::map<int, TimerAtom> timer_var;
|
|
181 std::vector<WidTextButton*> selects;
|
|
182 std::vector<int> sel_backlog_pos;
|
|
183 string replace_name[26];
|
|
184 string replace_name2[26];
|
|
185 PicContainer* sel_widget;
|
|
186 PicWidget* backlog_widget;
|
|
187
|
|
188 vector<BacklogItem>& backlog;
|
|
189 BacklogItem& backlog_item;
|
|
190 BacklogItem cur_backlog_item;
|
|
191 BacklogItem drawn_backlog_item;
|
|
192
|
|
193 public:
|
|
194 PicContainer& parent;
|
|
195 Event::Container& event;
|
|
196 AyuSysConfig& config;
|
|
197 private:
|
|
198 TextWindow* widgets[32];
|
|
199 WidTimeCursor* kcursor;
|
|
200 Surface* sel_bg1;
|
|
201 Surface* sel_bg2;
|
|
202 Rect sel_bg_rect;
|
|
203
|
|
204 void SetCursor(int num);
|
|
205 VarInfo wait_savedvar[2];
|
|
206
|
|
207 public:
|
|
208 void AddText(const char* str);
|
|
209
|
|
210 static void PressFuncSkip(void* pointer, WidButton* from);
|
|
211 static void PressFuncLoad(void* pointer, WidButton* from);
|
|
212 static void PressFuncSave(void* pointer, WidButton* from);
|
|
213 static void PressFuncBacklog(void* pointer, WidButton* from);
|
|
214 static void PressFuncBacklogFwd(void* pointer, WidButton* from);
|
|
215 private:
|
|
216 static void PressFuncButton(void* pointer, WidButton* from);
|
|
217 static bool PressFunc(int x, int y, void* pointer);
|
|
218
|
|
219 public:
|
|
220 TextImpl(Event::Container& _event, PicContainer& _parent, AyuSysConfig& config, vector<BacklogItem>& parent_backlog, BacklogItem& parent_backlog_item);
|
|
221 ~TextImpl();
|
|
222 void InitWindow(void);
|
|
223 void SetWindowColor(int r, int g, int b, int a, bool is_transparent);
|
|
224 void SetTextSpeed(int new_speed);
|
|
225 void SetTextWait(int new_wait);
|
|
226 void CreateSelect(Cmd& cmd);
|
|
227 void Exec(Cmd& cmd);
|
|
228 bool Wait(unsigned int current_time, Cmd& cmd);
|
|
229 void hide(void);
|
|
230 void show(void) { show(text_window_number); }
|
|
231 void show(int num);
|
|
232 void DrawBacklog(BacklogItem& item, Cmd& cmd);
|
|
233 void Save(std::string& str, bool select_save);
|
|
234 void Load(const char* str);
|
|
235 void SetSkipMode(SkipMode _mode);
|
|
236 void CreateSelBG(void);
|
|
237 };
|
|
238
|
|
239 /**************************************************************::
|
|
240 **
|
|
241 ** TextImpl(implementation)
|
|
242 */
|
|
243 TextImpl::TextImpl(Event::Container& _event, PicContainer& _parent, AyuSysConfig& _config, vector<BacklogItem>& parent_backlog, BacklogItem& parent_backlog_item) :
|
|
244 text(0),status(TextImpl::NORMAL), status_saved(TextImpl::NORMAL), status_mask(TextImpl::NORMAL), ruby_text_flag(false),
|
|
245 old_time(0), base_time(0), text_window_number(0), text_parsing(false), skip_mode(SKIP_NO), save_selectcount(0), sel_widget(0),
|
|
246 backlog_widget(0), backlog(parent_backlog), backlog_item(parent_backlog_item), parent(_parent), event(_event), config(_config),
|
|
247 kcursor(0), sel_bg1(0), sel_bg2(0), sel_bg_rect(0,0,0,0) {
|
|
248 int i;
|
|
249 for (i=0; i<32; i++) {
|
|
250 widgets[i] = 0;
|
|
251 }
|
|
252 text_stream.kanji_type = TextStream::sjis;
|
|
253 event.RegisterGlobalPressFunc(&PressFunc, (void*)this);
|
|
254 }
|
|
255
|
|
256 TextImpl::~TextImpl() {
|
|
257 if (sel_widget) delete sel_widget;
|
|
258 int i;
|
|
259 for (i=0; i<32; i++) {
|
|
260 if (widgets[i]) delete widgets[i];
|
|
261 }
|
|
262 if (backlog_widget) delete backlog_widget;
|
|
263 if (sel_bg1) parent.Root().DeleteSurface(sel_bg1);
|
|
264 if (sel_bg2) parent.Root().DeleteSurface(sel_bg2);
|
|
265 event.DeleteGlobalPressFunc(&PressFunc, (void*)this);
|
|
266 }
|
|
267
|
|
268 bool TextImpl::PressFunc(int x, int y, void* pointer) {
|
|
269 TextImpl* t = (TextImpl*)pointer;
|
|
270 if (t->status == WAIT_CLICK) {
|
|
271 t->status = WAIT_ABORT;
|
|
272 } else if (t->status == WAIT_CLICK_MOUSEPOS) {
|
|
273 t->status = WAIT_CLICK_MOUSEPOSEND_L;
|
|
274 } else if (t->status_mask & CLEARSCR_WAIT_MASK) {
|
|
275 t->status_mask = Status(t->status_mask & (~CLEARSCR_WAIT_MASK));
|
|
276 if (t->text) t->text->show();
|
|
277 if (t->kcursor) {
|
|
278 if (t->status == WAIT_TEXT) t->kcursor->show();
|
|
279 }
|
|
280 if (t->sel_widget) t->sel_widget->show();
|
|
281 if (t->backlog_widget) t->backlog_widget->show();
|
|
282 } else if (t->status_mask & BACKLOG_WAIT_MASK) {
|
|
283 t->status_mask = Status(t->status_mask | BACKLOG_MASK_KOE);
|
|
284 } else if ( (t->skip_mode & SKIP_TEXT) && (!(t->skip_mode & SKIP_IN_MENU)) ) {
|
|
285 if (t->status == WAIT_SELECT_INBOX) ;
|
|
286 else if (t->status == WAIT_SELECT_OUTBOX) ;
|
|
287 else if (t->status == WAIT_SELECT_VALUE) ;
|
|
288 else t->status_mask = Status(t->status_mask | SKIPEND_MASK);
|
|
289 }
|
|
290 return true; // event not deleted
|
|
291 }
|
|
292 void TextImpl::PressFuncButton(void* pointer, WidButton* from) {
|
|
293 TextImpl* t = (TextImpl*)pointer;
|
|
294 if (t->status != WAIT_SELECT_INBOX && t->status != WAIT_SELECT_OUTBOX) return;
|
|
295 vector<WidTextButton*>::iterator it;
|
|
296 int sel = 0;
|
|
297 for (it=t->selects.begin(); it != t->selects.end(); it++, sel++) {
|
|
298 if (from == *it) break;
|
|
299 }
|
|
300 if (it == t->selects.end()) {
|
|
301 fprintf(stderr,"TextImpl::PressFuncButton: Cannot find select widget\n");
|
|
302 return;
|
|
303 }
|
|
304 t->status = Status(WAIT_SELECT_VALUE + sel);
|
|
305 return;
|
|
306 }
|
|
307
|
|
308 void TextImpl::SetSkipMode(SkipMode _mode) {
|
|
309 if ( (skip_mode & SKIP_IN_MENU) && (_mode & SKIP_IN_MENU) == 0) {
|
|
310 if (status_mask & BACKLOG_WAIT_MASK) { // backlog mode から復帰
|
|
311 status_mask = Status(status_mask & (~(BACKLOG_MASK|BACKLOG_MASK_FWD|BACKLOG_MASK_KOE|BACKLOG_WAIT_MASK)));
|
|
312 text->wid->Clear();
|
|
313 if (status == WAIT_TEXT && text != 0) {
|
|
314 text->StartText(text_stream);
|
|
315 text->ShowFace(backlog_item.face.c_str());
|
|
316 text->wid->Flush();
|
|
317 if (kcursor) kcursor->show();
|
|
318 }
|
|
319 drawn_backlog_item.Clear();
|
|
320 }
|
|
321 if (text) text->wid->activate();
|
|
322 if (sel_widget) {
|
|
323 sel_widget->show();
|
|
324 if (kcursor) kcursor->hide();
|
|
325 }
|
|
326 if (backlog_widget) backlog_widget->show();
|
|
327 if (status_mask & STATSAVE_MASK) {
|
|
328 status_mask = Status(status_mask & (~STATSAVE_MASK));
|
|
329 status = status_saved;
|
|
330 }
|
|
331 } else if ( (skip_mode & SKIP_IN_MENU) == 0 && (_mode & SKIP_IN_MENU) ) {
|
|
332 if (text) text->wid->deactivate();
|
|
333 if (sel_widget) sel_widget->hide();
|
|
334 if (backlog_widget) backlog_widget->hide();
|
|
335 }
|
|
336 skip_mode = _mode;
|
|
337 }
|
|
338
|
|
339 /* hash_map が欲しい……*/
|
|
340 #include<map>
|
|
341 #include<list>
|
|
342 struct SaveFaceHash { // バックログセーブ時の顔画像管理を行う
|
|
343 map<string, int> facetonum;
|
|
344 typedef pair<string,int> Node;
|
|
345 typedef list<Node> List;
|
|
346 List container;
|
|
347 int id_max;
|
|
348 static int size_max;
|
|
349 SaveFaceHash() : id_max(0) {
|
|
350 }
|
|
351 void NewNode(string face, int face_id) {
|
|
352 facetonum[face] = face_id;
|
|
353 container.push_front(Node(face, face_id));
|
|
354 if (container.size() > size_max) {
|
|
355 Node remove = container.back();
|
|
356 container.pop_back();
|
|
357 facetonum.erase(remove.first);
|
|
358 }
|
|
359 }
|
|
360 int Add(string face) {
|
|
361 int id; int ret = -1;
|
|
362 int i; List::iterator it;
|
|
363 if (face.empty()) return -1;
|
|
364 if (facetonum.find(face) == facetonum.end()) {
|
|
365 id = ++id_max;
|
|
366 NewNode(face, id);
|
|
367 ret = -1;
|
|
368 } else {
|
|
369 id = facetonum[face];
|
|
370 for (i=0, it=container.begin(); it != container.end(); i++, it++) {
|
|
371 if (it->second == id) {
|
|
372 ret = i;
|
|
373 Node n = *it;
|
|
374 container.erase(it);
|
|
375 container.push_front(n);
|
|
376 break;
|
|
377 }
|
|
378 }
|
|
379 }
|
|
380 return ret;
|
|
381 }
|
|
382 string Get(int num) {
|
|
383 if (num < 0) return "";
|
|
384 List::iterator it = container.begin();
|
|
385 for (; it != container.end(); it++) {
|
|
386 if (num == 0) return it->first;
|
|
387 num--;
|
|
388 }
|
|
389 return "";
|
|
390 }
|
|
391 };
|
|
392 int SaveFaceHash::size_max = 20;
|
|
393
|
|
394 void TextImpl::Save(string& str, bool rollback_save) {
|
|
395 char buf[1024];
|
|
396 str = "\n";
|
|
397 str += "[TextImpl Window]\n";
|
|
398 sprintf(buf, "TextImplWindow=%d\n",text_window_number);
|
|
399 str += buf;
|
|
400 if (rollback_save) {
|
|
401 ++save_selectcount;
|
|
402 BacklogItem save_item;
|
|
403 save_item.SetSavepos(save_selectcount);
|
|
404 backlog.push_back(save_item);
|
|
405 }
|
|
406 sprintf(buf, "SaveSelectCount=%d\n",save_selectcount);
|
|
407
|
|
408 str += buf;
|
|
409 int i;
|
|
410 for (i=0; i<26; i++) {
|
|
411 if (replace_name2[i].empty()) continue;
|
|
412 sprintf(buf, "RName.%c=%s\n",i+'A',replace_name2[i].c_str());
|
|
413 str += buf;
|
|
414 }
|
|
415 int cnt = 0;
|
|
416 vector<BacklogItem>::iterator it;
|
|
417 it = backlog.begin();
|
|
418 if (!rollback_save) {
|
|
419 SaveFaceHash face_log;
|
|
420 do {
|
|
421 int cur_scn = -1; int cur_pos = -1;
|
|
422 sprintf(buf, "Backlog.%d=",++cnt);
|
|
423 str += buf;
|
|
424 for (; it != backlog.end(); it++) {
|
|
425 buf[0] = 0; int buflen = 0;
|
|
426 if (it->scn == -1) continue;
|
|
427 if (it->pos == -1 && it->scn != 0) continue;
|
|
428
|
|
429 buf[buflen++] = ';';
|
|
430 if (it->scn == 0 && it->pos == -1) {
|
|
431 buflen += snprintf(buf+buflen, 1000-buflen, "\"%s\".", it->text.Save().c_str());
|
|
432 } else {
|
|
433 if (cur_scn != -1 && cur_scn != it->scn) break; // scn change
|
|
434 if (cur_pos != -1 && cur_pos/5000 != it->pos/5000) break; // pos exceeded
|
|
435 if (!it->text.container.empty()) {
|
|
436 buflen += snprintf(buf+buflen, 1000-buflen, "\"%s\"", it->text.Save().c_str());
|
|
437 }
|
|
438 if (cur_scn == -1) { // scene change
|
|
439 buflen += snprintf(buf+buflen, 1000-buflen, ":%d:%d",it->scn,it->pos);
|
|
440 cur_scn = it->scn;
|
|
441 } else {
|
|
442 buflen += snprintf(buf+buflen, 1000-buflen, "%d",it->pos);
|
|
443 }
|
|
444 cur_pos = it->pos;
|
|
445 }
|
|
446 if (it->koe != -1)
|
|
447 buflen += snprintf(buf+buflen, 1000-buflen, ",%d",it->koe);
|
|
448 if (!it->face.empty()) {
|
|
449 if (it->koe == -1) buf[buflen++] = ',';
|
|
450 int face_num = face_log.Add(it->face);
|
|
451 if (face_num >= 0 && face_num < 20)
|
|
452 buflen += snprintf(buf+buflen, 1000-buflen, ",%c", 'A'+face_num);
|
|
453 else
|
|
454 buflen += snprintf(buf+buflen, 1000-buflen, ",\"%s\"", it->face.c_str());
|
|
455 }
|
|
456 buf[buflen++] = '\0';
|
|
457 if (buflen >= 1000) { // 万が一、バックログ1アイテムの大きさが 1000byte を越えるとき
|
|
458 fprintf(stderr,"Fatal : Cannot save backlog crrectly; Please send bug report to the author.\n");
|
|
459 } else str += buf;
|
|
460 }
|
|
461 str += "\n";
|
|
462 } while(it != backlog.end());
|
|
463 }
|
|
464 return;
|
|
465 }
|
|
466 void TextImpl::Load(const char* str) {
|
|
467 if (text) text->wid->Clear();
|
|
468 hide();
|
|
469 text_window_number = 0;
|
|
470 save_selectcount = 0;
|
|
471 if (sel_widget) {
|
|
472 selects.clear();
|
|
473 sel_backlog_pos.clear();
|
|
474 delete sel_widget;
|
|
475 sel_widget = 0;
|
|
476 }
|
|
477 if (backlog_widget) {
|
|
478 delete backlog_widget;
|
|
479 backlog_widget = 0;
|
|
480 }
|
|
481 status = NORMAL;
|
|
482 status_mask = NORMAL;
|
|
483 status_saved = NORMAL;
|
|
484 text_parsing = false;
|
|
485 text_stream.Clear();
|
|
486 // backlog.clear();
|
|
487 vector<BacklogItem> new_backlog;
|
|
488 backlog_item.Clear();
|
|
489 cur_backlog_item.Clear();
|
|
490 drawn_backlog_item.Clear();
|
|
491
|
|
492 str = strstr(str, "\n[TextImpl Window]\n");
|
|
493
|
|
494 if (str) {
|
|
495 SaveFaceHash face_log;
|
|
496 str += strlen("\n[TextImpl Window]\n");
|
|
497 const char* strend = str;
|
|
498 do {
|
|
499 str = strend;
|
|
500
|
|
501 strend = strchr(str, '\n');
|
|
502 if (strend == 0) strend = str + strlen(str);
|
|
503 else strend++;
|
|
504
|
|
505 if (str[0] == '[') break; // next section
|
|
506 if (strncmp(str, "TextImplWindow=",15) == 0) {
|
|
507 str += 15;
|
|
508 sscanf(str, "%d", &text_window_number);
|
|
509 } else if (strncmp(str, "SaveSelectCount=",16) == 0) {
|
|
510 str += 16;
|
|
511 sscanf(str, "%d", &save_selectcount);
|
|
512 } else if (strncmp(str, "RName.", 6) == 0) {
|
|
513 int n = str[6]-'A';
|
|
514 if (n >= 0 && n < 26 && str[7] == '=') {
|
|
515 const char* s = strchr(str, '\n');
|
|
516 int len = -1;
|
|
517 if (s) len = s-(str+8);
|
|
518 if (len > 0) {
|
|
519 replace_name2[n].assign(str+8, len);
|
|
520 }
|
|
521 }
|
|
522 } else if (strncmp(str, "Backlog.", 8) == 0) {
|
|
523 int cur_scn = -1;
|
|
524 int n = -1;
|
|
525 sscanf(str+8, "%d", &n); /* not used */
|
|
526 const char* next_str = strchr(str, ';');
|
|
527 while(next_str != 0 && next_str < strend) {
|
|
528 str = next_str + 1;
|
|
529 next_str = strchr(str, ';');
|
|
530 if (next_str == 0) next_str = strend;
|
|
531
|
|
532 BacklogItem item;
|
|
533 if (str[0] == '"') {
|
|
534 const char* send = strchr(str+1, '"');
|
|
535 if (send == 0 || send > next_str) continue;
|
|
536 string tmp_str; tmp_str.assign(str+1, send-str-1);
|
|
537 item.DeleteTextPos();
|
|
538 item.text.Load(tmp_str);
|
|
539 str = send + 1;
|
|
540 }
|
|
541 if (str[0] == '.') {
|
|
542 item.DeleteTextPos();
|
|
543 str++;
|
|
544 } else if (str[0] == ':') {
|
|
545 sscanf(str, ":%d:%d", &item.scn, &item.pos);
|
|
546 cur_scn = item.scn;
|
|
547
|
|
548 } else {
|
|
549 item.scn = cur_scn;
|
|
550 sscanf(str, "%d", &item.pos);
|
|
551 }
|
|
552 str = strchr(str, ',');
|
|
553 if (str == 0 || str > next_str) goto backlog_store;
|
|
554 str++;
|
|
555 if (str[0] == ';' || str[0] == ',')
|
|
556 item.koe = -1;
|
|
557 else
|
|
558 sscanf(str, "%d", &item.koe);
|
|
559 str = strchr(str, ',');
|
|
560 if (str == 0 || str > next_str) goto backlog_store;
|
|
561 str++;
|
|
562 if (*str == '"') {
|
|
563 const char* send = strchr(str+1, '"');
|
|
564 if (send) {
|
|
565 item.face.assign(str+1, send-str-1);
|
|
566 }
|
|
567 } else if (*str >= 'A' && *str <= 'Z') {
|
|
568 item.face = face_log.Get(*str - 'A');
|
|
569 }
|
|
570 face_log.Add(item.face);
|
|
571 backlog_store:
|
|
572 new_backlog.push_back(item);
|
|
573 }
|
|
574 }
|
|
575 } while (*strend != 0);
|
|
576 }
|
|
577 if (new_backlog.empty() && (!backlog.empty())) { // empty なら save_selectcount まで backlog を巻き戻す
|
|
578 vector<BacklogItem>::iterator it = backlog.end();
|
|
579 do {
|
|
580 it--;
|
|
581 if (it->scn == BacklogItem::SaveSelect && it->pos == save_selectcount) {
|
|
582 // Save 位置を見つけたらそれ以降を erase
|
|
583 backlog.erase(it, backlog.end());
|
|
584 break;
|
|
585 }
|
|
586 } while(it != backlog.begin());
|
|
587 --save_selectcount;
|
|
588 } else {
|
|
589 backlog.swap(new_backlog);
|
|
590 }
|
|
591 // backlog.clear();
|
|
592 return;
|
|
593 }
|
|
594
|
|
595 void TextImpl::hide(void) {
|
|
596 if (text) text->hide();
|
|
597 if (kcursor) kcursor->hide();
|
|
598 text = 0;
|
|
599 }
|
|
600 void TextImpl::show(int num) {
|
|
601 if (num != text_window_number) {
|
|
602 hide();
|
|
603 if (num >= 0 && num < 32 && widgets[num] != 0) {
|
|
604 text_window_number = num;
|
|
605 }
|
|
606 }
|
|
607 text = widgets[text_window_number];
|
|
608 text->show();
|
|
609 if (kcursor) {
|
|
610 int kx, ky, d;
|
|
611 char key[1024];
|
|
612 sprintf(key, "#WINDOW.%03d.KEYCUR_MOD", text_window_number);
|
|
613 config.GetParam(key, 3, &d, &kx, &ky);
|
|
614 // 正しくない気がする
|
|
615 kx += text->wid->Pic()->PosX();
|
|
616 ky += text->wid->Pic()->PosY();
|
|
617 // 微妙に下にする
|
|
618 ky += 8;
|
|
619 kcursor->Pic()->Move(kx, ky);
|
|
620 }
|
|
621 }
|
|
622 void TextImpl::DrawBacklog(BacklogItem& item, Cmd& cmd) {
|
18
|
623 show();
|
0
|
624 text->wid->deactivate();
|
|
625 status_mask = Status(status_mask | BACKLOG_WAIT_MASK);
|
|
626 drawn_backlog_item = item;
|
|
627 if (item.text.container.empty()) {
|
|
628 // cmd から text 内容を再構成
|
|
629 TextStream saved_text = text_stream;
|
|
630 text_stream.Clear();
|
|
631 AddText(cmd.Str(cmd.args[0]));
|
|
632 item.text = text_stream;
|
|
633 text_stream = saved_text;
|
|
634 }
|
18
|
635 item.text.InsertColor(0, item.text.container.size(), 0xff,0xff,0);
|
17
|
636 text->StartText(item.text);
|
0
|
637 text->wid->Flush();
|
|
638 if (item.face.empty()) text->ResetFace();
|
|
639 else text->ShowFace(item.face.c_str());
|
|
640 if (kcursor) kcursor->hide();
|
|
641 }
|
|
642
|
|
643 void TextImpl::CreateSelBG(void) {
|
|
644 if (sel_bg1 != 0 || sel_bg2 != 0) return;
|
|
645
|
|
646 const char* btnfile1 = config.GetParaStr("#SELBTN.000.NAME");
|
|
647 const char* btnfile2 = config.GetParaStr("#SELBTN.000.BACK");
|
|
648 char path[1024];
|
|
649 strcpy(path, btnfile1);
|
|
650 sel_bg1 = parent.Root().NewSurface(path);
|
|
651 if (sel_bg1 == 0) {
|
|
652 sprintf(path,"%s.g00",btnfile1);
|
|
653 sel_bg1 = parent.Root().NewSurface(path);
|
|
654 }
|
|
655 strcpy(path, btnfile2);
|
|
656 sel_bg2 = parent.Root().NewSurface(path);
|
|
657 if (sel_bg2 == 0) {
|
|
658 sprintf(path,"%s.g00",btnfile2);
|
|
659 sel_bg2 = parent.Root().NewSurface(path);
|
|
660 }
|
|
661 sel_bg_rect = Rect(0,0,0,0);
|
|
662 if (sel_bg1) sel_bg_rect.join(Rect(*sel_bg1));
|
|
663 if (sel_bg2) sel_bg_rect.join(Rect(*sel_bg2));
|
|
664 return;
|
|
665 }
|
|
666
|
|
667 void TextImpl::CreateSelect(Cmd& cmd) {
|
|
668 char key[1024];
|
|
669 sprintf(key, "#WINDOW.%03d.SELCOM_USE",text_window_number);
|
|
670 int sel_type = 0;
|
|
671 config.GetParam(key, 1, &sel_type);
|
|
672
|
|
673 int sel_size = cmd.args.size() / 2;
|
|
674 int i;
|
|
675 // cur_backlog_item に次にbacklogに入るべき内容を作成
|
|
676 // CreateSelect() 後、SAVEPOINT なので現在のbacklogの内容(前のメッセージ)が
|
|
677 // backlog に代入される。その後、backlog_item に cur_backlog_item の内容がセットされる(Wait()内)
|
|
678 char backlog_sel_text[11] = {0x81,0x69,0x91,0x49,0x91,0xf0,0x8e,0x88,0x81,0x6a,0x00};
|
|
679 cur_backlog_item.Clear();
|
|
680 cur_backlog_item.AddTextPos(cmd);
|
|
681 cur_backlog_item.text.Add(backlog_sel_text);
|
|
682 cur_backlog_item.text.AddReturn();
|
|
683 sel_backlog_pos.clear();
|
|
684 for (i=0; i<sel_size; i++) {
|
|
685 sel_backlog_pos.push_back(cur_backlog_item.text.container.size());
|
|
686 cur_backlog_item.text.Add(cmd.Str(cmd.args[i*2]));
|
|
687 cur_backlog_item.text.AddReturn();
|
|
688 }
|
|
689 sel_backlog_pos.push_back(cur_backlog_item.text.container.size());
|
|
690
|
|
691 if (sel_type == 0) { // Princess Bride: 選択ウィンドウを別表示
|
|
692 External_select:
|
|
693 CreateSelBG();
|
|
694 hide(); // なので、テキストウィンドウは消去
|
|
695 int baseposx, baseposy, repposx, repposy;
|
|
696 int mojisize, col1, col2;
|
|
697 config.GetParam("#SELBTN.000.BASEPOS", 2, &baseposx, &baseposy);
|
|
698 config.GetParam("#SELBTN.000.REPPOS", 2, &repposx, &repposy);
|
|
699 config.GetParam("#SELBTN.000.MOJISIZE", 1, &mojisize);
|
|
700 config.GetParam("#SELBTN.000.MOJIDEFAULTCOL", 1, &col1);
|
|
701 config.GetParam("#SELBTN.000.MOJISELECTCOL", 1, &col2);
|
|
702 if (col1 == col2) col2 = 1; // CLANNAD でとりあえず。
|
|
703 int r, g, b;
|
|
704 sprintf(key, "#COLOR_TABLE.%03d", col1);
|
|
705 config.GetParam(key, 3, &r, &g, &b);
|
|
706 Color fore(r,g,b);
|
|
707 sprintf(key, "#COLOR_TABLE.%03d", col2);
|
|
708 config.GetParam(key, 3, &r, &g, &b);
|
|
709 Color seled(r,g,b);
|
|
710
|
|
711 /* ウィジット作成 */
|
|
712 /* ウィンドウ背景の大きさを求める */
|
|
713 if (baseposx == 0 && sel_bg_rect.width() != 0)
|
|
714 baseposx = (parent.Width()-sel_bg_rect.width()) / 2; // ボタン位置をセンタリング
|
|
715
|
|
716 sel_widget = parent.create_node( Rect(0, 0, parent.Width(), parent.Height()),0);
|
|
717
|
|
718 for (i=0; i<sel_size; i++) {
|
|
719 PicBase* p;
|
|
720 // 背景作成
|
|
721 if (sel_bg2) {
|
|
722 p = sel_widget->create_node(Rect(baseposx, baseposy, baseposx+sel_bg_rect.width(), baseposy+sel_bg_rect.height()),0);
|
|
723 p->SetSurface(sel_bg2, 0, 0);
|
|
724 }
|
|
725 if (sel_bg1) {
|
|
726 p = sel_widget->create_node(Rect(baseposx, baseposy, baseposx+sel_bg_rect.width(), baseposy+sel_bg_rect.height()),0);
|
|
727 p->SetSurface(sel_bg1, 0, 0);
|
|
728 }
|
|
729 /* ボタン作成 */
|
|
730 const char* str = cmd.Str(cmd.args[i*2]);
|
|
731 int value = cmd.args[i*2+1].value;
|
|
732 while(selects.size() <= value) selects.push_back(0); // vector の大きさを広げる
|
|
733
|
|
734 kconv( (const unsigned char*)str, (unsigned char*)key);
|
|
735 selects[value] = new WidTextButton(event, sel_widget, key, mojisize, WidTextButton::CENTER,
|
|
736 Rect(baseposx, baseposy, baseposx+sel_bg_rect.width(), baseposy+sel_bg_rect.height()), 1, fore, seled, Color(0,0,0,0));
|
|
737 selects[value]->press_func = &PressFuncButton;
|
|
738 selects[value]->press_pointer = (void*)this;
|
|
739
|
|
740 baseposx += repposx;
|
|
741 baseposy += repposy;
|
|
742 }
|
|
743 sel_widget->show_all();
|
|
744 status = WAIT_SELECT_OUTBOX;
|
|
745 } else { // CLANNAD: テキストウィンドウ内に選択肢表示
|
|
746 int mojisize;
|
|
747 config.GetParam("#SELBTN.000.MOJISIZE", 1, &mojisize);
|
|
748 Color fore(0xff,0xff,0xff);
|
|
749 Color seled(0xff,0xff,0xff);
|
|
750
|
|
751 show();
|
|
752 if (text == 0) goto External_select; // テキスト・ウィンドウを表示できなければ外部選択肢にする
|
|
753 text->wid->Clear();
|
|
754 if (kcursor) kcursor->hide();
|
|
755 /* ウィジット作成 : テキスト表示範囲と同じ*/
|
|
756 int posx = text->wid->pictext->PosX();
|
|
757 int posy = text->wid->pictext->PosY();
|
|
758 int sel_w = text->wid->pictext->Width();
|
|
759 int sel_h = text->wid->pictext->Height();
|
|
760 sel_widget = text->wid->PicNode()->create_node(Rect(posx, posy, posx+sel_w, posy+sel_h), 0);
|
|
761
|
|
762 int sel_y = 0;
|
|
763 for (i=0; i<sel_size; i++) {
|
|
764 PicBase* p;
|
|
765 /* ボタン作成 */
|
|
766 const char* str = cmd.Str(cmd.args[i*2]);
|
|
767 int value = cmd.args[i*2+1].value;
|
|
768 while(selects.size() <= value) selects.push_back(0); // vector の大きさを広げる
|
|
769
|
|
770 kconv( (const unsigned char*)str, (unsigned char*)key);
|
|
771 selects[value] = new WidTextButton(event, sel_widget, key, mojisize, WidTextButton::Attribute(WidTextButton::REVERSE | WidTextButton::NOPADDING),
|
|
772 Rect(0, sel_y, sel_w, sel_y), 1, fore, seled, Color(0,0,0,0));
|
|
773 selects[value]->press_func = &PressFuncButton;
|
|
774 selects[value]->press_pointer = (void*)this;
|
|
775
|
|
776 sel_y += selects[value]->Pic()->Height() + 1;
|
|
777 }
|
|
778 sel_widget->show_all();
|
|
779 status = WAIT_SELECT_INBOX;
|
|
780 }
|
|
781 }
|
|
782
|
|
783 void TextImpl::AddText(const char* str_o) {
|
|
784 char str[10001];
|
|
785 if (text == 0) return;
|
|
786 /* まず、replace string を変換 */
|
|
787 int i;
|
|
788 int cnt = 0;
|
|
789 /* * = 81 96 A-Z = 0x82 [0x60-0x79] */
|
|
790 /* % = 81 93 A-Z = 0x82 [0x60-0x79] */
|
|
791 for (i=0; cnt<10000 && str_o[i] != 0; i++) {
|
|
792 if (str_o[i] < 0) {
|
|
793 if ( (unsigned char)str_o[i] == 0x81 && (unsigned char)str_o[i+1] == 0x96 && (unsigned char)str_o[i+2] == 0x82) {
|
|
794 int c = str_o[i+3];
|
|
795 if (c >= 0x60 && c <= 0x79 && replace_name[c-0x60].length() != 0) { // 名前変換
|
|
796 i += 3;
|
|
797 strcpy(str+cnt, replace_name[c-0x60].c_str());
|
|
798 cnt += replace_name[c-0x60].length();
|
|
799 continue;
|
|
800 }
|
|
801 } else if ( (unsigned char)str_o[i] == 0x81 && (unsigned char)str_o[i+1] == 0x93 && (unsigned char)str_o[i+2] == 0x82) {
|
|
802 int c = str_o[i+3];
|
|
803 if (c >= 0x60 && c <= 0x79 && replace_name2[c-0x60].length() != 0) { // 名前変換2
|
|
804 i += 3;
|
|
805 strcpy(str+cnt, replace_name2[c-0x60].c_str());
|
|
806 cnt += replace_name2[c-0x60].length();
|
|
807 continue;
|
|
808 }
|
|
809 }
|
|
810 str[cnt++] = str_o[i++];
|
|
811 }
|
|
812 str[cnt++] = str_o[i];
|
|
813 }
|
|
814 str[cnt] = 0;
|
|
815 str[10000] = 0;
|
|
816 char* str_top = str;
|
|
817
|
|
818 for (char* s = str_top; *s != 0; s++) {
|
|
819 // if (*(unsigned char*)s == 0xa1 && *(unsigned char*)(s+1) == 0xda) { /* euc */
|
|
820 if (*(unsigned char*)s == 0x81 && *(unsigned char*)(s+1) == 0x79) { /* sjis */
|
|
821 // 名前
|
|
822 *s = 0;
|
|
823 if (s != str_top) text_stream.Add(str_top);
|
|
824 s += 2;
|
|
825 char* name_top = s;
|
|
826 for (; *s != 0; s++) {
|
|
827 // if (*(unsigned char*)s == 0xa1 && *(unsigned char*)(s+1) == 0xdb) { /* euc */
|
|
828 if (*(unsigned char*)s == 0x81 && *(unsigned char*)(s+1) == 0x7a) { /* sjis */
|
|
829 *s = 0;
|
|
830 s += 2;
|
|
831 text_stream.AddName(name_top);
|
|
832 break;
|
|
833 }
|
|
834 if (*s < 0 && s[1] != 0) s++; // 全角文字なら2字飛ばす
|
|
835 }
|
|
836 str_top = s;
|
|
837 }
|
|
838 if (*s == 0x0a) {
|
|
839 *s = 0;
|
|
840 text_stream.Add(str_top);
|
|
841 text_stream.AddReturn();
|
|
842 str_top = s;
|
|
843 } else if (*s < 0 && s[1] != 0) s++;
|
|
844 }
|
|
845 text_stream.Add(str_top);
|
|
846 return;
|
|
847 }
|
|
848
|
|
849 void TextImpl::Exec(Cmd& cmd) {
|
|
850 if (cmd.cmd_type == CMD_TEXT) {
|
|
851 if (text == 0) {
|
|
852 show();
|
|
853 }
|
|
854 if (cmd.args.size() != 1) return;
|
|
855 if (ruby_text_flag) {
|
|
856 ruby_text = cmd.Str(cmd.args[0]);
|
|
857 ruby_text_flag = 0;
|
|
858 cmd.clear();
|
|
859 return;
|
|
860 }
|
|
861 cur_backlog_item.AddTextPos(cmd);
|
|
862 AddText(cmd.Str(cmd.args[0]));
|
|
863 char debug[1024];
|
|
864 kconv( (unsigned char*)cmd.Str(cmd.args[0]), (unsigned char*)debug);
|
|
865 eprintf("text: %s\n",debug);
|
|
866 if (text_parsing)
|
|
867 cmd.clear();
|
|
868 else
|
|
869 cmd.cmd_type = CMD_SAVEPOINT;
|
|
870 text_parsing = true; /* テキスト待ち直後のテキスト位置=セーブ位置 */
|
|
871 return;
|
|
872 }
|
|
873 if (cmd.cmd_type != CMD_OTHER) return;
|
|
874 /* テキストウィンドウを消去するコマンド類をチェックする */
|
|
875 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x21) {
|
|
876 if (cmd.cmd3 == 0x49 || cmd.cmd3 == 0x4b || cmd.cmd3 == 0x4c) {
|
|
877 if (text) text->ResetFace();
|
|
878 cur_backlog_item.face = "";
|
|
879 hide();
|
|
880 }
|
|
881 }
|
|
882 if (cmd.cmd1 == 1 && cmd.cmd2 == 0x17 && cmd.cmd3 == 0 && cmd.cmd4 == 1) {
|
|
883 // PlayKoe ; 声出力コマンドをチェックする */
|
|
884 cur_backlog_item.koe = cmd.args[0].value;
|
|
885 }
|
|
886 if (cmd.cmd1 == 0 && cmd.cmd2 == 3 && cmd.cmd3 == 0x97) { // いいのかなー
|
|
887
|
|
888 if (text) {
|
|
889 text->ResetFace();
|
|
890 text->wid->Clear();
|
|
891 }
|
|
892 cur_backlog_item.face = "";
|
|
893 text_stream.Clear();
|
|
894 hide();
|
|
895 }
|
|
896 if (cmd.cmd1 == 0 && cmd.cmd2 == 3) {
|
|
897 if (cmd.cmd3 == 0x11) { // テキスト表示、クリック待ち
|
|
898 if (text) {
|
|
899 eprintf("start\n");
|
|
900 text->StartText(text_stream);
|
|
901 if (skip_mode & SKIP_TEXT) text->wid->Flush();
|
|
902 else if (kcursor) kcursor->show();
|
|
903 status = WAIT_TEXT;
|
|
904 text_parsing = false;
|
|
905 }
|
|
906 backlog_item = cur_backlog_item;
|
|
907 if (cur_backlog_item.scn == 0 && cur_backlog_item.pos == -1) backlog_item.text = text_stream;
|
|
908 cur_backlog_item.Clear();
|
|
909
|
|
910 cmd.clear();
|
|
911 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
|
|
912 // これだと1フレーム1テキストしか表示されなくなるので注意
|
|
913 } else if (cmd.cmd3 == 3 || cmd.cmd3 == 0xc9) { // リターン挿入
|
|
914 text_stream.AddReturn();
|
|
915 cur_backlog_item.DeleteTextPos();
|
|
916 cmd.clear();
|
|
917 } else if (cmd.cmd3 == 0x3e8 || cmd.cmd3 == 0x3e9) { // 顔グラフィック変更
|
|
918 if (text == 0) {
|
|
919 show();
|
|
920 }
|
|
921 if (cmd.cmd3 == 0x3e8) {
|
|
922 string s = cmd.Str(cmd.args[0]);
|
|
923 s += ".g00";
|
|
924 if (text) text->ShowFace(s.c_str());
|
|
925 cur_backlog_item.face = s;
|
|
926 cmd.cmd_type = CMD_SAVECMD_ONCE;
|
|
927 } else if (cmd.cmd3 == 0x3e9) { // 顔グラフィック消去
|
|
928 if (text) text->ResetFace();
|
|
929 cur_backlog_item.face = "";
|
|
930 cmd.cmd_type = CMD_SAVECMD_ONCE;
|
|
931 }
|
|
932 } else if (cmd.cmd3 == 0x78) { // ルビ関連
|
|
933 if (text == 0) {
|
|
934 show();
|
|
935 }
|
|
936 if (cmd.cmd4 == 1) {
|
|
937 ruby_text_flag = true;
|
|
938 eprintf("SetRubyTextImpl.");
|
|
939 cmd.clear();
|
|
940 } else if (cmd.cmd4 == 0) {
|
|
941 if (ruby_text.length() == 0) { // ルビを振るテキストがない
|
|
942 eprintf("Cannot find ruby text.\n");
|
|
943 return;
|
|
944 }
|
|
945 if (cmd.args.size() != 1) return;
|
|
946 char debug1[1024], debug2[1024];
|
|
947 kconv( (unsigned char*)ruby_text.c_str(), (unsigned char*)debug1);
|
|
948 kconv( (unsigned char*)cmd.Str(cmd.args[0]), (unsigned char*)debug2);
|
|
949 eprintf("SetRuby. %s, %s",debug1, debug2);
|
|
950 text_stream.AddRuby(ruby_text.c_str(), cmd.Str(cmd.args[0]));
|
|
951 cur_backlog_item.DeleteTextPos();
|
|
952 cmd.clear();
|
|
953 }
|
|
954 } else if (cmd.cmd3 == 0x66) { // テキストウィンドウの形
|
|
955 if (cmd.cmd4 == 0) {
|
|
956 eprintf("set text window <- %d\n",cmd.args[0].value);
|
|
957 if (text) show(cmd.args[0].value);
|
|
958 else text_window_number = cmd.args[0].value;
|
|
959 } else if (cmd.cmd4 == 1) { // default value
|
|
960 eprintf("set text window <- default\n");
|
|
961 if (text) show(0);
|
|
962 else text_window_number = 0;
|
|
963 }
|
|
964 cmd.clear();
|
|
965 } else if (cmd.cmd3 == 0x67) { // テキストウィンドウ表示?
|
|
966 show();
|
|
967 // 表示の際はテキストをクリアしない?
|
|
968 // if (text) text->wid->Clear();
|
|
969 // text_stream.Clear();
|
|
970 cmd.clear();
|
|
971 } else if (cmd.cmd3 == 0x68) { // テキスト表示?
|
|
972 // 全テキスト表示
|
|
973 if (text) {
|
|
974 text->StartText(text_stream);
|
|
975 text->wid->Flush();
|
|
976 }
|
|
977 cmd.clear();
|
|
978 } else if (cmd.cmd3 == 0x98) { // テキストウィンドウクリア?
|
|
979 show();
|
|
980 if (text) text->wid->Clear();
|
|
981 text_stream.Clear();
|
|
982 cmd.clear();
|
|
983 }
|
|
984 } else if (cmd.cmd1 == 0 && cmd.cmd2 == 2 && (cmd.cmd3 == 1 || cmd.cmd3 == 3) && cmd.cmd4 == 0) {
|
|
985 // 選択肢
|
|
986 CreateSelect(cmd);
|
|
987 cmd.cmd_type = CMD_ROLLBACKPOINT; /* 選択肢はセーブ位置 / シナリオ巻き戻し位置 */
|
|
988 // cmd.clear();
|
|
989 } else if (cmd.cmd1 == 0 && cmd.cmd2 == 4) {
|
|
990 if (cmd.cmd3 == 0x44c) { // テキストスキップ開始
|
|
991 status_mask = Status(SKIPMASK | status_mask);
|
|
992 cmd.clear();
|
|
993 } else if (cmd.cmd3 == 0x3e8) { // ウィンドウ消去
|
|
994 status_mask = Status(CLEARSCR_MASK | status_mask);
|
|
995 cmd.clear();
|
|
996 }
|
|
997 } else if (cmd.cmd1 == 1 && cmd.cmd2 == 0x04) {
|
|
998 /* ウェイト関連命令 */
|
|
999 if (cmd.cmd3 == 0x64 || cmd.cmd3 == 0x6f || cmd.cmd3 == 0x79) {
|
|
1000 eprintf("wait %dmsec\n",cmd.args[0].value);
|
|
1001 if (cmd.cmd3 == 0x64 && text) {
|
|
1002 /* 0x64 だと文字描画中の待ちに使うことがある */
|
|
1003 text->StartText(text_stream);
|
|
1004 text->wid->Flush();
|
|
1005 }
|
|
1006 if (cmd.cmd3 == 0x6f || cmd.cmd3 == 0x79) wait_time = base_time + cmd.args[0].value;
|
|
1007 else wait_time = old_time + cmd.args[0].value;
|
|
1008 status = WAIT;
|
|
1009 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
|
|
1010 } else if (cmd.cmd3 == 0x65 || cmd.cmd3 == 0x70) {
|
|
1011 eprintf("wait %dmsec(click stop)\n",cmd.args[0].value);
|
|
1012 if (cmd.cmd3 == 0x70) wait_time = base_time + cmd.args[0].value;
|
|
1013 else wait_time = old_time + cmd.args[0].value;
|
|
1014 status = WAIT_CLICK;
|
|
1015 cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため)
|
|
1016 } else if (cmd.cmd3 == 0x83) {
|
|
1017 /* マウスがクリックされるまで待つ */
|
|
1018 eprintf("wait and get mouse pos at click\n");
|
|
1019 wait_time = old_time + 1000 * 1000;
|
|
1020 status = WAIT_CLICK_MOUSEPOS;
|
|
1021 wait_savedvar[0] = cmd.args[0];
|
|
1022 wait_savedvar[1] = cmd.args[1];
|
|
1023 cmd.clear();
|
|
1024 } else if (cmd.cmd3 == 0x1fe) {
|
|
1025 eprintf("get timer value[%d]\n",cmd.args[0].value);
|
|
1026 if (timer_var.find(cmd.args[0].value) == timer_var.end()) {
|
|
1027 cmd.SetSysvar(0);
|
|
1028 } else {
|
|
1029 TimerAtom& atom = timer_var[cmd.args[0].value];
|
|
1030 if (atom.total_time <= 0) atom.total_time = 1;
|
|
1031 int cur_tm = old_time - atom.start_time;
|
|
1032 if (cur_tm < 0) cur_tm = atom.total_time; // エラーなら最終時間に合わせる
|
|
1033 if (cur_tm > atom.total_time) cur_tm = atom.total_time;
|
|
1034 // use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
|
|
1035 int v = atom.from + (long long)(atom.to-atom.from)*cur_tm/int(atom.total_time);
|
|
1036 cmd.SetSysvar(v);
|
|
1037 }
|
|
1038 /* From rldev-1.40, reallive.kfn
|
|
1039 0x72 fun Timer (store) <1:Sys:00114, 1> ('counter') ()
|
|
1040 0x73 fun CmpTimer (store) <1:Sys:00115, 1> ('time') ('time', 'counter')
|
|
1041 0x74 fun SetTimer <1:Sys:00116, 1> ('time') ('time', 'counter')
|
|
1042
|
|
1043 0x78 fun ResetExTimer <1:Sys:00120, 1> ('counter') ()
|
|
1044 0x79 fun timeEx <1:Sys:00121, 1> ('time') ('time', 'counter')
|
|
1045 0x7a fun timeExC (store) <1:Sys:00122, 1> ('time') ('time', 'counter')
|
|
1046 0x7b fun timeExC2 (store) <1:Sys:00123, 1> ('time') ('time', 'counter') // UNDOCUMENTED
|
|
1047 0x7c fun ExTimer (store) <1:Sys:00124, 1> ('counter') ()
|
|
1048 0x7d fun CmpExTimer (store) <1:Sys:00125, 1> ('time') ('time', 'counter')
|
|
1049 0x7e fun SetExTimer <1:Sys:00126, 1> ('time') ('time', 'counter')
|
|
1050 */
|
|
1051
|
|
1052 } else if (cmd.cmd3 == 0x6e || cmd.cmd3 == 0x78) { // set basetime
|
|
1053 if (cmd.cmd4 == 1) {
|
|
1054 eprintf("set basetime\n");
|
|
1055 base_time = old_time;
|
|
1056 cmd.clear();
|
|
1057 } else if (cmd.cmd4 == 0) { // n-th base time
|
|
1058 int index = cmd.args[0].value;
|
|
1059 eprintf("set basetime (%d)\n",index);
|
|
1060 TimerAtom& atom = timer_var[index];
|
|
1061 atom.from = 0;
|
|
1062 atom.to = 0;
|
|
1063 atom.total_time = 0;
|
|
1064 atom.start_time = old_time;
|
|
1065 cmd.clear();
|
|
1066 }
|
|
1067 } else if (cmd.cmd3 == 0x72 || cmd.cmd3 == 0x7c) { // get time
|
|
1068 if (cmd.cmd4 == 1) { // get time
|
|
1069 eprintf("get time\n");
|
|
1070 cmd.SetSysvar(old_time - base_time);
|
|
1071 } else if (cmd.cmd4 == 0) { // n-th get time
|
|
1072 int index = cmd.args[0].value;
|
|
1073 eprintf("get time %dth\n",index);
|
|
1074 if (timer_var.find(index) == timer_var.end()) cmd.SetSysvar(0);
|
|
1075 else cmd.SetSysvar(old_time - timer_var[index].start_time);
|
|
1076 }
|
|
1077 } else if (cmd.cmd3 == 0x26c || cmd.cmd3 == 0x270) { // set basetime(multi)
|
|
1078 int j = 0;
|
|
1079 eprintf("set basetime\n");
|
|
1080 int i; for (i=0; i<cmd.argc; i++) {
|
|
1081 int cnt = cmd.args[j++].value; // 3なので無視
|
|
1082 int num = cmd.args[j++].value;
|
|
1083 TimerAtom& atom = timer_var[num];
|
|
1084 atom.from = cmd.args[j++].value;
|
|
1085 atom.to = cmd.args[j++].value;
|
|
1086 atom.total_time = cmd.args[j++].value;
|
|
1087 atom.start_time = old_time;
|
|
1088 }
|
|
1089 cmd.clear();
|
|
1090 } else if (cmd.cmd3 == 0x276) { // get time (multi)
|
|
1091 int j = 0;
|
|
1092 eprintf("get timer value\n");
|
|
1093 vector<VarInfo> args = cmd.args;
|
|
1094 vector<VarInfo>::iterator it = args.begin();
|
|
1095 int argc = cmd.argc;
|
|
1096 int active_timers = 0;
|
|
1097 int i; for (i=0; i<argc; i++) {
|
|
1098 int cnt = (it++)->value;
|
|
1099 int num = (it++)->value;
|
|
1100
|
|
1101 if (timer_var.find(num) == timer_var.end()) {
|
|
1102 cmd.SetFlagvar(*it++, 0);
|
|
1103 } else {
|
|
1104 TimerAtom& atom = timer_var[num];
|
|
1105 if (atom.total_time <= 0) atom.total_time = 1;
|
|
1106 int cur_tm = old_time - atom.start_time;
|
|
1107 if (cur_tm < 0) cur_tm = atom.total_time; // エラーなら最終時間に合わせる
|
|
1108 if (cur_tm > atom.total_time) cur_tm = atom.total_time;
|
|
1109 // use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
|
|
1110 int v = atom.from + (long long)(atom.to-atom.from)*cur_tm/int(atom.total_time);
|
|
1111 cmd.SetFlagvar(*it++, v);
|
|
1112 if (atom.total_time != -1 && cur_tm < atom.total_time) active_timers++;
|
|
1113 }
|
|
1114 }
|
|
1115 if (active_timers) active_timers = 1;
|
|
1116 cmd.SetSysvar(active_timers);
|
|
1117 } else if (cmd.cmd3 == 0x1f4) {
|
|
1118 TimerAtom& atom = timer_var[cmd.args[0].value];
|
|
1119 atom.from = cmd.args[1].value;
|
|
1120 atom.to = cmd.args[2].value;
|
|
1121 atom.total_time = cmd.args[3].value;
|
|
1122 atom.start_time = old_time;
|
|
1123 cmd.clear();
|
|
1124 } else if (cmd.cmd3 == 0x3e8) {
|
|
1125 /* rand() */
|
|
1126 int min = 0, max;
|
|
1127 if (cmd.args.size() == 2) {
|
|
1128 min = cmd.args[0].value;
|
|
1129 max = cmd.args[1].value;
|
|
1130 } else {
|
|
1131 max = cmd.args[1].value;
|
|
1132 }
|
|
1133 if (min > max) {
|
|
1134 int tmp = max;
|
|
1135 max = min;
|
|
1136 min = tmp;
|
|
1137 }
|
|
1138 int r = random();
|
|
1139 if (min == max) r = min;
|
|
1140 else r = (r % (max-min)) + min;
|
|
1141 cmd.SetSysvar(r);
|
|
1142 } else if (cmd.cmd3 == 0x3ea) {
|
|
1143 int val = cmd.args[0].value;
|
|
1144 if (val < 0) val = -val;
|
|
1145 cmd.SetSysvar(val);
|
|
1146 } else if (cmd.cmd3 == 0x3ec) {
|
|
1147 /* min だよなあ・・・*/
|
|
1148 int min = cmd.args[0].value;
|
|
1149 int max = cmd.args[1].value;
|
|
1150 if (max < min) min = max;
|
|
1151 cmd.SetSysvar(min);
|
|
1152 } else if (cmd.cmd3 == 0x3ef) {
|
|
1153 /* min */
|
|
1154 int min = cmd.args[0].value;
|
|
1155 int max = cmd.args[1].value;
|
|
1156 if (max < min) min = max;
|
|
1157 cmd.SetSysvar(min);
|
|
1158 } else if (cmd.cmd3 == 0x320) {
|
|
1159 /* range conversion : 比率に丸める */
|
|
1160 // アルゴリズムは間違えてるような気がする
|
|
1161 //
|
|
1162 if (cmd.args.size() >= 7) {
|
|
1163 int val = cmd.args[0].value;
|
|
1164 int offset = cmd.args[1].value;
|
|
1165 int r_min = cmd.args[2].value;
|
|
1166 int v_min = cmd.args[3].value;
|
|
1167 int v_max = cmd.args[4].value;
|
|
1168 int r_max = cmd.args[5].value;
|
|
1169 int mode = cmd.args[6].value;
|
|
1170 // rldev : mode == 1,3 : 'acceralating curve', 2,3: 'decelerating curve'
|
|
1171 // 複数の引数リスト(r_minからmodeまでのリスト)もつこともあり、その場合は
|
|
1172 // "cancel out in some way" らしい
|
|
1173 if (mode == 1 || mode == 3) val += offset;
|
|
1174 else if (mode == 2 || mode == 4) val -= offset;
|
|
1175 if (cmd.args.size() != 7)
|
|
1176 fprintf(stderr,"\n%d/%d: cmd 01-04:0320 : XXXX NOT SUPPORTED LIST : DOUBLE RANGE CONVERSION! XXXXXXXXXXX\n",cmd.scn,cmd.pos);
|
|
1177 if (val < v_min) val = v_min;
|
|
1178 if (val > v_max) val = v_max;
|
|
1179 val = (r_max-r_min)*(val-v_min)/(v_max-v_min) + r_min;
|
|
1180 cmd.SetSysvar(val);
|
|
1181 }
|
|
1182 } else if (cmd.cmd3 == 0x3f1) {
|
|
1183 /* range 内に丸める */
|
|
1184 int min = cmd.args[0].value;
|
|
1185 int val = cmd.args[1].value;
|
|
1186 int max = cmd.args[2].value;
|
|
1187 if (min > max) {
|
|
1188 int tmp = max;
|
|
1189 max = min;
|
|
1190 min = tmp;
|
|
1191 }
|
|
1192 if (val < min) val = min;
|
|
1193 if (val > max) val = max;
|
|
1194 cmd.SetSysvar(val);
|
|
1195 } else if (cmd.cmd3 == 0x16c && cmd.cmd4 == 0) {
|
|
1196 /* なんかよくわからないけどカーソル形状変更にしとく */
|
|
1197 SetCursor(cmd.args[0].value);
|
|
1198 cmd.clear();
|
|
1199 } else if (cmd.cmd3 == 0x0bc1) { // メニューからのロード
|
|
1200 cmd.cmd_type = CMD_LOADREQ;
|
|
1201 } else if ( (cmd.cmd3 >= 0x8d4 && cmd.cmd3 <= 0x8d8) || cmd.cmd3 == 0x8db || cmd.cmd3 == 0x93f || cmd.cmd3 == 0xa39) {
|
|
1202 // テキストウィンドウの色設定
|
|
1203 int r, g, b, a, flag;
|
|
1204 if (cmd.cmd3 == 0xa39) { // 元設定を取り出す
|
|
1205 config.GetOriginalParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
|
|
1206 } else {
|
|
1207 config.GetParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
|
|
1208 }
|
|
1209 if (cmd.cmd3 == 0xa39 || cmd.cmd3 == 0x93f) { // 設定を変数に取り出す
|
|
1210 if (cmd.args.size() != 5) {
|
|
1211 fprintf(stderr,"cmd 01-04:%4d : invalid arg size\n", cmd.cmd3);
|
|
1212 } else {
|
|
1213 vector<VarInfo> args(cmd.args);
|
|
1214 cmd.SetFlagvar(args[0], r);
|
|
1215 cmd.SetFlagvar(args[1], g);
|
|
1216 cmd.SetFlagvar(args[2], b);
|
|
1217 cmd.SetFlagvar(args[3], a);
|
|
1218 cmd.SetFlagvar(args[4], flag);
|
|
1219 }
|
|
1220 } else {
|
|
1221 switch(cmd.cmd3) {
|
|
1222 case 0x8d4: r = cmd.args[0].value; break;
|
|
1223 case 0x8d5: g = cmd.args[0].value; break;
|
|
1224 case 0x8d6: b = cmd.args[0].value; break;
|
|
1225 case 0x8d7: a = cmd.args[0].value; break;
|
|
1226 case 0x8d8: flag = cmd.args[0].value; break;
|
|
1227 case 0x8db:
|
|
1228 r = cmd.args[0].value;
|
|
1229 g = cmd.args[1].value;
|
|
1230 b = cmd.args[2].value;
|
|
1231 a = cmd.args[3].value;
|
|
1232 flag = cmd.args[4].value;
|
|
1233 break;
|
|
1234 }
|
|
1235 config.SetParam("#WINDOW_ATTR", 5, r, g, b, a, flag);
|
|
1236 SetWindowColor(r, g, b, a, flag);
|
|
1237 cmd.clear();
|
|
1238 }
|
|
1239 } else if (cmd.cmd3 == 0xa28 || cmd.cmd3 == 0xa29 || cmd.cmd3 == 0xa2c || cmd.cmd3 == 0xa2d || cmd.cmd3 == 0xa2e) {
|
|
1240 int v = 0;
|
|
1241 switch(cmd.cmd3) {
|
|
1242 case 0xa28: case 0xa2d: config.GetOriginalParam("#INIT_MESSAGE_SPEED", 1, &v); break;
|
|
1243 case 0xa29: config.GetOriginalParam("#INIT_MESSAGE_SPEED_MOD", 1, &v); break;
|
|
1244 case 0xa2c: config.GetOriginalParam("#MESSAGE_KEY_WAIT_USE", 1, &v); break;
|
|
1245 case 0xa2e: config.GetOriginalParam("#MESSAGE_KEY_WAIT_TIME", 1, &v); break;
|
|
1246 }
|
|
1247 cmd.SetSysvar(v);
|
|
1248 } else if (cmd.cmd3 == 0x913 || cmd.cmd3 == 0x914 || cmd.cmd3 == 0x92f || cmd.cmd3 == 0x8af || cmd.cmd3 == 0x8b0 || cmd.cmd3 == 0x8cb) {
|
|
1249 // テキスト表示速度関連
|
|
1250 int m, speed;
|
|
1251 config.GetParam("#INIT_MESSAGE_SPEED", 1, &speed);
|
|
1252 config.GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &m);
|
|
1253 if (cmd.cmd3 == 0x913 || cmd.cmd3 == 0x92f) fprintf(stderr,"TEXT speed %d\n",speed);
|
|
1254 else if (cmd.cmd3 == 0x914) fprintf(stderr,"TEXT mode %d\n",m);
|
|
1255 else if (cmd.cmd3 == 0x8af || cmd.cmd3 == 0x8cb) fprintf(stderr,"TEXT %d, %d <- speed %d\n",m,speed,cmd.args[0].value);
|
|
1256 else fprintf(stderr,"TEXT %d, %d <- mode %d\n",m,speed,cmd.args[0].value);
|
|
1257 if (cmd.cmd3 == 0x913 || cmd.cmd3 == 0x92f) cmd.SetSysvar(speed);
|
|
1258 else if (cmd.cmd3 == 0x914) cmd.SetSysvar(m);
|
|
1259 else {
|
|
1260 if (cmd.cmd3 == 0x8af || cmd.cmd3 == 0x8cb) speed = cmd.args[0].value;
|
|
1261 else m = cmd.args[0].value;
|
|
1262 if (speed < 10) speed = 10;
|
|
1263 else if (speed > 1000) speed = 1000;
|
|
1264 config.SetParam("#INIT_MESSAGE_SPEED", 1, speed);
|
|
1265 config.SetParam("#INIT_MESSAGE_SPEED_MOD", 1, m);
|
|
1266 if (m) speed = -1;
|
|
1267 SetTextSpeed(speed);
|
|
1268 cmd.clear();
|
|
1269 }
|
|
1270 } else if (cmd.cmd3 == 0x92e || cmd.cmd3 == 0x930 || cmd.cmd3 == 0x8ca || cmd.cmd3 == 0x8cc) {
|
|
1271 // テキストオートモード関連
|
|
1272 int m, wait;
|
|
1273 config.GetParam("#MESSAGE_KEY_WAIT_USE", 1, &m);
|
|
1274 config.GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait);
|
|
1275 if (cmd.cmd3 == 0x92e) fprintf(stderr,"AUTO mode %d\n",m);
|
|
1276 else if (cmd.cmd3 == 0x930) fprintf(stderr,"AUTO wait %d\n",wait);
|
|
1277 else if (cmd.cmd3 == 0x8ca) fprintf(stderr,"AUTO %d,%d <- mode %d\n",m,wait,cmd.args[0].value);
|
|
1278 else fprintf(stderr,"AUTO %d,%d <- wait %d\n",m,wait,cmd.args[0].value);
|
|
1279
|
|
1280 if (cmd.cmd3 == 0x92e) cmd.SetSysvar(m);
|
|
1281 else if (cmd.cmd3 == 0x930) cmd.SetSysvar(wait);
|
|
1282 else {
|
|
1283 if (cmd.cmd3 == 0x8ca) m = cmd.args[0].value;
|
|
1284 else wait = cmd.args[1].value;
|
|
1285 if (wait < 0) wait = 0;
|
|
1286 else if (wait > 60000) wait = 60000;
|
|
1287 config.SetParam("#MESSAGE_KEY_WAIT_USE", 1, m);
|
|
1288 config.SetParam("#MESSAGE_KEY_WAIT_TIME", 1, wait);
|
|
1289 if (m) SetTextWait(wait);
|
|
1290 else SetTextWait(-1);
|
|
1291 cmd.clear();
|
|
1292 }
|
|
1293 } else if (cmd.cmd3 == 0x51f && cmd.cmd4 == 0) { // replace_name2 の設定
|
|
1294 int n = cmd.args[0].value;
|
|
1295 if (n>=0 && n<26) {
|
|
1296 replace_name2[n] = cmd.Str(cmd.args[1]);
|
|
1297 }
|
|
1298 cmd.clear();
|
|
1299 } else if (cmd.cmd3 == 0x51e && cmd.cmd4 == 0) { // replace_name2 を得る
|
|
1300 int n = cmd.args[0].value;
|
|
1301 if (n >= 0 && n < 26) {
|
|
1302 cmd.SetStrvar(cmd.args[1], replace_name2[n]);
|
|
1303 } else {
|
|
1304 cmd.SetStrvar(cmd.args[1], "");
|
|
1305 }
|
|
1306 } else if (cmd.cmd3 == 0x514 && cmd.cmd4 == 0) { // replace_name を得る
|
|
1307 int n = cmd.args[0].value;
|
|
1308 if (n >= 0 && n < 26) {
|
|
1309 cmd.SetStrvar(cmd.args[1], replace_name[n]);
|
|
1310 } else {
|
|
1311 cmd.SetStrvar(cmd.args[1], "");
|
|
1312 }
|
|
1313 }
|
|
1314 }
|
|
1315
|
|
1316 return;
|
|
1317 }
|
|
1318 extern int print_blit;
|
|
1319 bool TextImpl::Wait(unsigned int current_time, Cmd& cmd) {
|
|
1320 if (current_time != 0xffffffffUL) old_time = current_time;
|
|
1321 /*
|
|
1322 if (event.presscount(MOUSE_UP)) {
|
|
1323 if (text) text->Pic()->ReBlit();
|
|
1324 }
|
|
1325 if (event.presscount(MOUSE_DOWN)) {
|
|
1326 print_blit^=1;
|
|
1327 }
|
|
1328 */
|
|
1329
|
|
1330 if (status == NORMAL && status_mask == NORMAL) return false;
|
|
1331
|
|
1332 if (status_mask & WAIT_EXTRN_MASK) return true;
|
|
1333 if (status_mask & (BACKLOG_MASK|BACKLOG_MASK_FWD) ) {
|
|
1334 if (status_mask & BACKLOG_WAIT_MASK) ;
|
|
1335 else {
|
|
1336 if ( (status == WAIT_TEXT && text != 0) || status == WAIT_SELECT_INBOX || status == WAIT_SELECT_OUTBOX) {
|
|
1337 if(text && text->wid->status != WidText::PREPARE && text->wid->status != WidText::WAIT && text->wid->status != WidText::WAIT2) {
|
|
1338 text->wid->Flush(); // 表示を最後の状態にする
|
|
1339 }
|
|
1340 if (status == WAIT_TEXT && text != 0 && kcursor) kcursor->show();
|
|
1341 }
|
|
1342 }
|
|
1343 if (status_mask & BACKLOG_MASK) {
|
|
1344 cmd.cmd_type = CMD_BACKLOGREQ;
|
|
1345 } else {
|
|
1346 cmd.cmd_type = CMD_BACKLOGREQ_FWD;
|
|
1347 }
|
|
1348 status_mask = Status(status_mask & ~(BACKLOG_MASK|BACKLOG_MASK_FWD));
|
|
1349 return false;
|
|
1350 }
|
|
1351 if ( (status_mask & BACKLOG_WAIT_MASK) && (status_mask & BACKLOG_MASK_KOE)) {
|
|
1352 if (drawn_backlog_item.koe != -1) {
|
|
1353 cmd.cmd_type = CMD_OTHER;
|
|
1354 cmd.cmd1 = 1;
|
|
1355 cmd.cmd2 = 0x17;
|
|
1356 cmd.cmd3 = 0;
|
|
1357 cmd.cmd4 = 1;
|
|
1358 cmd.args.clear();
|
|
1359 cmd.args.push_back(VarInfo(drawn_backlog_item.koe));
|
|
1360 cmd.args.push_back(VarInfo(0));
|
|
1361 }
|
|
1362 status_mask = Status(status_mask & ~BACKLOG_MASK_KOE);
|
|
1363 return false;
|
|
1364 }
|
|
1365 if (skip_mode & SKIP_IN_MENU) return false;
|
|
1366 if (status_mask & SAVEMASK) {
|
|
1367 cmd.cmd_type = CMD_SAVEREQ;
|
|
1368 status_mask = Status(status_mask & ~SAVEMASK);
|
|
1369 return false;
|
|
1370 }
|
|
1371 if (status_mask & LOADMASK) {
|
|
1372 cmd.cmd_type = CMD_LOADREQ;
|
|
1373 status_mask = Status(status_mask & ~LOADMASK);
|
|
1374 return false;
|
|
1375 }
|
|
1376 if (status_mask & SKIPEND_MASK) {
|
|
1377 if ( (skip_mode & SKIP_TEXT) && (skip_mode & SKIPEND_TEXT)) {
|
|
1378 if (skip_mode & SKIPEND_KEY) { // shift skip 中
|
|
1379 SkipMode new_mode = SkipMode(skip_mode & (~SKIPEND_TEXT));
|
|
1380 if (new_mode & (SKIP_GRP_NOEFFEC || SKIP_GRP_NODRAW))
|
|
1381 new_mode = SkipMode(new_mode & (~SKIP_GRP_FAST));
|
|
1382 cmd.SetSysvar(TYPE_SYS_SKIPMODE, new_mode);
|
|
1383 } else {
|
|
1384 cmd.SetSysvar(TYPE_SYS_SKIPMODE, SKIP_NO);
|
|
1385 }
|
|
1386 }
|
|
1387 status_mask = Status(status_mask & ~SKIPEND_MASK);
|
|
1388 }
|
|
1389 if (status_mask & SKIPMASK) {
|
|
1390 if (skip_mode != SKIP_NO) {
|
|
1391 cmd.SetSysvar(TYPE_SYS_SKIPMODE, skip_mode | SKIPEND_TEXT);
|
|
1392 } else {
|
|
1393 cmd.SetSysvar(TYPE_SYS_SKIPMODE, SKIP_TEXT | SKIP_GRP_FAST | SKIPEND_TEXT);
|
|
1394 }
|
|
1395 status_mask = Status(status_mask & ~SKIPMASK);
|
|
1396 return false;
|
|
1397 }
|
|
1398 if (event.presscount(MOUSE_RIGHT)) {
|
|
1399 if ( (status == WAIT_TEXT && text != 0) || status == WAIT_SELECT_INBOX || status == WAIT_SELECT_OUTBOX) {
|
|
1400 if(text && text->wid->status != WidText::PREPARE && text->wid->status != WidText::WAIT && text->wid->status != WidText::WAIT2) {
|
|
1401 text->wid->Flush(); // 表示を最後の状態にする
|
|
1402 }
|
|
1403 cmd.cmd_type = CMD_MENUREQ;
|
|
1404 if (!(status_mask & STATSAVE_MASK)) {
|
|
1405 status_saved = status;
|
|
1406 status_mask = Status(status_mask | STATSAVE_MASK);
|
|
1407 }
|
|
1408 return false;
|
|
1409 } else if (status == WAIT_CLICK_MOUSEPOS) {
|
|
1410 status = WAIT_CLICK_MOUSEPOSEND_R;
|
|
1411 }
|
|
1412 }
|
|
1413 if (event.presscount(MOUSE_UP)) {
|
|
1414 if ( (status == WAIT_TEXT && text != 0) || status == WAIT_SELECT_INBOX || status == WAIT_SELECT_OUTBOX) {
|
|
1415 if(text && text->wid->status != WidText::PREPARE && text->wid->status != WidText::WAIT && text->wid->status != WidText::WAIT2) {
|
|
1416 text->wid->Flush(); // 表示を最後の状態にする
|
|
1417 }
|
|
1418 cmd.cmd_type = CMD_BACKLOGREQ;
|
|
1419 if (!(status_mask & STATSAVE_MASK)) {
|
|
1420 status_saved = status;
|
|
1421 status_mask = Status(status_mask | STATSAVE_MASK);
|
|
1422 }
|
|
1423 return false;
|
|
1424 }
|
|
1425 }
|
|
1426 if (status_mask & CLEARSCR_MASK) {
|
|
1427 if ( (status == WAIT_TEXT && text != 0 ) || status == WAIT_SELECT_INBOX || status == WAIT_SELECT_OUTBOX) {
|
|
1428 if (skip_mode) skip_mode = SKIP_NO;
|
|
1429 if (text && text->wid->status != WidText::PREPARE && text->wid->status != WidText::WAIT && text->wid->status != WidText::WAIT2) {
|
|
1430 text->wid->Flush(); // 表示を最後の状態にする
|
|
1431 return true;
|
|
1432 }
|
|
1433 status_mask = Status(status_mask & (~CLEARSCR_MASK) | CLEARSCR_WAIT_MASK);
|
|
1434 if (text) text->hide();
|
|
1435 if (kcursor) kcursor->hide();
|
|
1436 if (sel_widget) sel_widget->hide();
|
|
1437 if (backlog_widget) backlog_widget->hide();
|
|
1438 return true;
|
|
1439 }
|
|
1440 status_mask = Status(status_mask & (~CLEARSCR_MASK));
|
|
1441 return false;
|
|
1442 }
|
|
1443 if (status_mask & CLEARSCR_WAIT_MASK) {
|
|
1444 return true;
|
|
1445 }
|
|
1446 if (status == WAIT_TEXT) {
|
|
1447 if (text == 0) { status = NORMAL; return false;}
|
|
1448 if (skip_mode & SKIP_TEXT) {
|
|
1449 } else if (text->wid->status != WidText::PREPARE) {
|
|
1450 return true;
|
|
1451 }
|
|
1452 if (kcursor) kcursor->hide();
|
|
1453 text_stream.Clear();
|
|
1454 status = NORMAL;
|
|
1455 cmd.cmd_type = CMD_TEXTEND;
|
|
1456 return false;
|
|
1457 }
|
|
1458 if (status == WAIT) {
|
|
1459 if (skip_mode & SKIP_TEXT) ;
|
|
1460 else if (wait_time > current_time) return true;
|
|
1461 status = NORMAL;
|
|
1462 } else if (status == WAIT_CLICK) {
|
|
1463 if (skip_mode & SKIP_TEXT) ;
|
|
1464 else if (wait_time > current_time) return true;
|
|
1465 status = NORMAL;
|
|
1466 cmd.SetSysvar(0);
|
|
1467 } else if (status == WAIT_ABORT) {
|
|
1468 cmd.SetSysvar(1);
|
|
1469 status = NORMAL;
|
|
1470 } else if (status == WAIT_CLICK_MOUSEPOS || status == WAIT_CLICK_MOUSEPOSEND_L || status == WAIT_CLICK_MOUSEPOSEND_R) {
|
|
1471 if (status == WAIT_CLICK_MOUSEPOS && (skip_mode & SKIP_TEXT) == 0) return true; // keep wait
|
|
1472 else {
|
|
1473 int x, y;
|
|
1474 event.MousePos(x,y);
|
|
1475 if (status == WAIT_CLICK_MOUSEPOS) x = y = 0; // skip mode
|
|
1476 cmd.clear();
|
|
1477 cmd.SetFlagvar(wait_savedvar[0], x);
|
|
1478 cmd.SetFlagvar(wait_savedvar[1], y);
|
|
1479 if (status == WAIT_CLICK_MOUSEPOSEND_R) cmd.SetSysvar(-1);
|
|
1480 else cmd.SetSysvar(0);
|
|
1481 status = NORMAL;
|
|
1482 }
|
|
1483 } else if (status == WAIT_SELECT_INBOX || status == WAIT_SELECT_OUTBOX) {
|
|
1484 return true;
|
|
1485 } else if ( int(status) >= WAIT_SELECT_VALUE) {
|
|
1486 int sel_val = int(status) - WAIT_SELECT_VALUE;
|
|
1487 cmd.SetSysvar(sel_val);
|
|
1488 selects.clear();
|
|
1489 delete sel_widget;
|
|
1490 sel_widget = 0;
|
|
1491 status = NORMAL;
|
|
1492 // CreateSelect() で作成された cur_backlog_item を backlog_item へ反映させる
|
|
1493 cur_backlog_item.text.InsertColor(sel_backlog_pos[sel_val], sel_backlog_pos[sel_val+1], 0xff, 0, 0);
|
|
1494 backlog_item = cur_backlog_item;
|
|
1495 cur_backlog_item.Clear();
|
|
1496 }
|
|
1497 return false;
|
|
1498 }
|
|
1499
|
|
1500 void clearbtn_press(void* pointer, WidButton* button) {
|
|
1501 if (pointer == 0) return;
|
|
1502 TextImpl* t = (TextImpl*)pointer;
|
|
1503 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::CLEARSCR_MASK);
|
|
1504 return;
|
|
1505 }
|
|
1506 void TextImpl::PressFuncSkip(void* pointer, WidButton* from) {
|
|
1507 if (pointer == 0) return;
|
|
1508 TextImpl* t = (TextImpl*)pointer;
|
|
1509 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::SKIPMASK);
|
|
1510 return;
|
|
1511 }
|
|
1512 void TextImpl::PressFuncLoad(void* pointer, WidButton* from) {
|
|
1513 if (pointer == 0) return;
|
|
1514 TextImpl* t = (TextImpl*)pointer;
|
|
1515 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::LOADMASK);
|
|
1516 return;
|
|
1517 }
|
|
1518 void TextImpl::PressFuncSave(void* pointer, WidButton* from) {
|
|
1519 if (pointer == 0) return;
|
|
1520 TextImpl* t = (TextImpl*)pointer;
|
|
1521 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::SAVEMASK);
|
|
1522 return;
|
|
1523 }
|
|
1524 void TextImpl::PressFuncBacklog(void* pointer, WidButton* from) {
|
|
1525 if (pointer == 0) return;
|
|
1526 TextImpl* t = (TextImpl*)pointer;
|
|
1527 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::BACKLOG_MASK);
|
|
1528 return;
|
|
1529 }
|
|
1530 void TextImpl::PressFuncBacklogFwd(void* pointer, WidButton* from) {
|
|
1531 if (pointer == 0) return;
|
|
1532 TextImpl* t = (TextImpl*)pointer;
|
|
1533 t->status_mask = TextImpl::Status(t->status_mask | TextImpl::BACKLOG_MASK_FWD);
|
|
1534 return;
|
|
1535 }
|
|
1536 void movebtn_drag(int from_x, int from_y, int x, int y, void* pointer, WidButton* button) {
|
|
1537 if (pointer == 0) return;
|
|
1538 fprintf(stderr,"drag.\n");
|
|
1539 }
|
|
1540 #define BTNCNT 10
|
|
1541 static char* btnname[BTNCNT] = {
|
|
1542 "MOVE",
|
|
1543 "CLEAR",
|
|
1544 "READJUMP",
|
|
1545 "AUTOMODE",
|
|
1546 "MSGBK",
|
|
1547 "MSGBKLEFT",
|
|
1548 "MSGBKRIGHT",
|
|
1549 "EXBTN_000",
|
|
1550 "EXBTN_001",
|
|
1551 "EXBTN_002"
|
|
1552 };
|
|
1553 static int btnpos[BTNCNT] = { // g00 ファイル内のボタン情報の位置
|
|
1554 // 0, 1, 13, 12, 2, 3, 4, 5, 6, 7 // princess bride?
|
|
1555 0, 1, 13, 14, 2, 3, 4, 5, 6, 7 // tomoyo after?
|
|
1556 };
|
|
1557 static WidButton::PressFunc btnpress[BTNCNT] = {
|
|
1558 0, clearbtn_press, &TextImpl::PressFuncSkip,0,&TextImpl::PressFuncBacklogFwd,&TextImpl::PressFuncBacklog,&TextImpl::PressFuncBacklogFwd,&TextImpl::PressFuncSave,&TextImpl::PressFuncLoad,0
|
|
1559 };
|
|
1560 static WidButton::DragFunc btndrag[BTNCNT] = {
|
|
1561 movebtn_drag, 0,0,0,0, 0,0,0,0, 0
|
|
1562 };
|
|
1563
|
|
1564 void TextImpl::SetTextSpeed(int speed) {
|
|
1565 // 100 : 10char / sec
|
|
1566 // 10 : 100char / sec
|
|
1567 // text widget:
|
|
1568 if (speed <= 0) speed = -1;
|
|
1569 else if (speed > 1000) speed = 1;
|
|
1570 else speed = 1000 / speed;
|
|
1571 int i;
|
|
1572 for (i=0; i<32; i++)
|
|
1573 if (widgets[i]) widgets[i]->wid->SetSpeed(speed);
|
|
1574 }
|
|
1575 void TextImpl::SetTextWait(int wait) {
|
|
1576 int i;
|
|
1577 for (i=0; i<32; i++)
|
|
1578 if (widgets[i]) widgets[i]->wid->SetWait(wait);
|
|
1579 }
|
|
1580
|
|
1581 void TextImpl::SetWindowColor(int r, int g, int b, int a, bool is_transparent) {
|
|
1582 char key[1024];
|
|
1583 int w;
|
|
1584
|
|
1585 for (w=0; w<32; w++) {
|
|
1586 if (widgets[w] == 0) continue;
|
|
1587 sprintf(key, "#WAKU.%03d.000.BACK", w);
|
|
1588 const char* back = config.GetParaStr(key);
|
|
1589 if (back == 0 || back[0] == 0) continue;
|
|
1590 sprintf(key, "%s.g00", back);
|
|
1591 Surface* back_s = parent.Root().NewSurface(key);
|
|
1592 if (back_s == 0) continue;
|
|
1593 Rect rect(*back_s);
|
|
1594 Surface* new_s = parent.Root().NewSurface(rect.width(), rect.height(), ALPHA_MASK);
|
|
1595 DSurfaceMove(back_s, rect, new_s, rect);
|
|
1596 DSurfaceFillA(new_s, rect, r, g, b, a);
|
|
1597 widgets[w]->wid->Pic()->SetSurface(new_s, 0, 0);
|
|
1598 widgets[w]->wid->Pic()->SetSurfaceFreeFlag(1);
|
|
1599 if (!is_transparent)
|
|
1600 widgets[w]->wid->Pic()->SetSurfaceAttribute(PicBase::BLIT_MULTIPLY);
|
|
1601 parent.Root().DeleteSurface(back_s);
|
|
1602 }
|
|
1603 return;
|
|
1604 }
|
|
1605
|
|
1606 void TextImpl::SetCursor(int cursor_no) {
|
|
1607 char key[1024];
|
|
1608 sprintf(key, "#CURSOR.%03d.NAME", cursor_no);
|
|
1609 string path = config.GetParaStr(key);
|
|
1610 if (path.length() == 0) return; // 名前なし
|
|
1611 path += ".pdt";
|
|
1612 int w,h,cont,speed;
|
|
1613 sprintf(key, "#CURSOR.%03d.SIZE", cursor_no);
|
|
1614 config.GetParam(key, 2, &w, &h);
|
|
1615 sprintf(key, "#CURSOR.%03d.CONT", cursor_no);
|
|
1616 config.GetParam(key, 1, &cont);
|
|
1617 sprintf(key, "#CURSOR.%03d.SPEED", cursor_no);
|
|
1618 config.GetParam(key, 1, &speed);
|
|
1619
|
|
1620 // speed で1周、cont 回変化
|
|
1621 if (kcursor) delete kcursor;
|
|
1622
|
|
1623 kcursor = new WidTimeCursor(event, speed/cont, &parent, path.c_str(), 0, 0, w, 0, cont, Rect(0,0,w,h));
|
|
1624 int i;
|
|
1625 for (i=0; i<32; i++) {
|
|
1626 if (widgets[i]) widgets[i]->wid->SetCursor(kcursor);
|
|
1627 }
|
|
1628 }
|
|
1629
|
|
1630 void kconv(const unsigned char* src, unsigned char* dest) {
|
|
1631 /* input : sjis output: euc */
|
|
1632 while(*src) {
|
|
1633 unsigned int high = *src++;
|
|
1634 if (high < 0x80) {
|
|
1635 /* ASCII */
|
|
1636 *dest++ = high; continue;
|
|
1637 } else if (high < 0xa0) {
|
|
1638 /* SJIS */
|
|
1639 high -= 0x71;
|
|
1640 } else if (high < 0xe0) {
|
|
1641 /* hankaku KANA */
|
|
1642 *dest++ = 0x8e; *dest++ = high;
|
|
1643 continue;
|
|
1644 } else { /* high >= 0xe0 : SJIS */
|
|
1645 high -= 0xb1;
|
|
1646 }
|
|
1647 /* SJIS convert */
|
|
1648 high = (high<<1) + 1;
|
|
1649
|
|
1650 unsigned int low = *src++;
|
|
1651 if (low == 0) break; /* incorrect code */
|
|
1652 if (low > 0x7f) low--;
|
|
1653 if (low >= 0x9e) {
|
|
1654 low -= 0x7d;
|
|
1655 high++;
|
|
1656 } else {
|
|
1657 low -= 0x1f;
|
|
1658 }
|
|
1659 *dest++ = high | 0x80; *dest++ = low | 0x80;
|
|
1660 }
|
|
1661 *dest = 0;
|
|
1662 }
|
|
1663 void kconv_rev(const unsigned char* src, unsigned char* dest) {
|
|
1664 /* input : euc output: sjis */
|
|
1665 while(*src) {
|
|
1666 unsigned int high = *src++;
|
|
1667 if (high < 0x80) {
|
|
1668 /* ASCII */
|
|
1669 *dest++ = high; continue;
|
|
1670 } else if (high == 0x8e) { /* hankaku KANA */
|
|
1671 high = *src;
|
|
1672 if (high >= 0xa0 && high < 0xe0)
|
|
1673 *dest++ = *src++;
|
|
1674 continue;
|
|
1675 } else {
|
|
1676 unsigned int low = *src++;
|
|
1677 if (low == 0) break; /* incorrect code , EOS */
|
|
1678 if (low < 0x80) continue; /* incorrect code */
|
|
1679 /* convert */
|
|
1680 low &= 0x7f; high &= 0x7f;
|
|
1681 low += (high & 1) ? 0x1f : 0x7d;
|
|
1682 high = (high-0x21)>>1;
|
|
1683 high += (high > 0x1e) ? 0xc1 : 0x81;
|
|
1684 *dest++ = high;
|
|
1685 if (low > 0x7f) low++;
|
|
1686 *dest++ = low;
|
|
1687 }
|
|
1688 }
|
|
1689 *dest = 0;
|
|
1690 }
|
|
1691 string kconv(const string& s) {
|
|
1692 char* out = new char[s.length()*2+100];
|
|
1693 kconv((const unsigned char*)s.c_str(), (unsigned char*)out);
|
|
1694 string ret = out;
|
|
1695 delete[] out;
|
|
1696 return ret;
|
|
1697 }
|
|
1698 string kconv_rev(const string& s) {
|
|
1699 char* out = new char[s.length()*2+100];
|
|
1700 kconv_rev((const unsigned char*)s.c_str(), (unsigned char*)out);
|
|
1701 string ret = out;
|
|
1702 delete[] out;
|
|
1703 return ret;
|
|
1704 }
|
|
1705
|
|
1706 /**************************************************************::
|
|
1707 **
|
|
1708 ** Text
|
|
1709 */
|
|
1710 Text::Text(Event::Container& _event, PicContainer& _parent, AyuSysConfig& config) {
|
|
1711 pimpl = new TextImpl(_event, _parent, config, backlog, backlog_item);
|
|
1712 }
|
|
1713 Text::~Text() {
|
|
1714 delete pimpl;
|
|
1715 }
|
|
1716 void Text::InitWindow(void) {
|
|
1717 pimpl->InitWindow();
|
|
1718 }
|
|
1719 void Text::Exec(Cmd& cmd) {
|
|
1720 pimpl->Exec(cmd);
|
|
1721 }
|
|
1722 bool Text::Wait(unsigned int current_time, Cmd& cmd) {
|
|
1723 return pimpl->Wait(current_time, cmd);
|
|
1724 }
|
|
1725 void Text::SetSkipMode(SkipMode mode) {
|
|
1726 pimpl->SetSkipMode(mode);
|
|
1727 }
|
|
1728 void Text::Save(std::string& str, bool select_save) {
|
|
1729 pimpl->Save(str, select_save);
|
|
1730 }
|
|
1731 void Text::Load(const char* str) {
|
|
1732 pimpl->Load(str);
|
|
1733 }
|
|
1734
|
|
1735 void Text::hide(void) {
|
|
1736 pimpl->hide();
|
|
1737 }
|
|
1738 void Text::show(void) {
|
|
1739 pimpl->show();
|
|
1740 }
|
|
1741 void Text::show(int num) {
|
|
1742 pimpl->show(num);
|
|
1743 }
|
|
1744 void Text::DrawBacklog(BacklogItem& item, Cmd& cmd) {
|
|
1745 pimpl->DrawBacklog(item, cmd);
|
|
1746 }
|
|
1747 /**************************************************************::
|
|
1748 **
|
|
1749 ** BacklogItem
|
|
1750 */
|
|
1751
|
|
1752 BacklogItem::BacklogItem(void) {
|
|
1753 scn = -1;
|
|
1754 pos = -1;
|
|
1755 koe = -1;
|
|
1756 face = "";
|
|
1757 text.kanji_type = TextStream::sjis;
|
|
1758 }
|
|
1759 void BacklogItem::Clear(void) {
|
|
1760 scn = -1;
|
|
1761 pos = -1;
|
|
1762 koe = -1;
|
|
1763 text.Clear();
|
|
1764 }
|
|
1765 void BacklogItem::AddTextPos(Cmd& cmd) {
|
|
1766 if (scn == -1 && pos == -1) {
|
|
1767 scn = cmd.scn;
|
|
1768 pos = cmd.pos;
|
|
1769 return;
|
|
1770 }
|
|
1771 DeleteTextPos();
|
|
1772 }
|
|
1773 void BacklogItem::DeleteTextPos(void) {
|
|
1774 scn = 0;
|
|
1775 pos = -1;
|
|
1776 }
|
|
1777 BacklogItem& BacklogItem::operator =(const BacklogItem& p) {
|
|
1778 scn = p.scn;
|
|
1779 pos = p.pos;
|
|
1780 koe = p.koe;
|
|
1781 face = p.face;
|
|
1782 text = p.text;
|
|
1783 }
|
|
1784 void BacklogItem::SetSavepos(int p) {
|
|
1785 Clear();
|
|
1786 scn = SaveSelect;
|
|
1787 pos = p;
|
|
1788 }
|
|
1789
|
|
1790 Rect TextWindow::WakuSize(PicContainer& pic, int waku_no, const AyuSysConfig& config) {
|
|
1791 char key[1024];
|
|
1792 sprintf(key, "#WAKU.%03d.000.NAME", waku_no);
|
|
1793 const char* name = config.GetParaStr(key);
|
|
1794 if (!name) return Rect(0,0,0,0);
|
|
1795 std::string str = name; str += ".g00";
|
|
1796 Surface* s = pic.Root().NewSurface(str.c_str());
|
|
1797 if (!s) return Rect(0,0,0,0);
|
|
1798 Rect r(*s);
|
|
1799 pic.Root().DeleteSurface(s);
|
|
1800 return r;
|
|
1801 }
|
|
1802 void TextWindow::MakeWaku(PicContainer& pic, Event::Container& event, int waku_no, int window_no, bool* use_btn, const AyuSysConfig& config, void* callback) {
|
|
1803 char key[1024];
|
|
1804 std::string str;
|
|
1805 /* 枠を作成 */
|
|
1806 sprintf(key, "#WAKU.%03d.000.NAME", waku_no);
|
|
1807 const char* name = config.GetParaStr(key);
|
|
1808 if (name && name[0] == 0) name = 0;
|
|
1809 sprintf(key, "#WAKU.%03d.000.BACK", waku_no);
|
|
1810 const char* back = config.GetParaStr(key);
|
|
1811 if (back && back[0] == 0) back = 0;
|
|
1812 sprintf(key, "#WAKU.%03d.000.BTN", waku_no);
|
|
1813 const char* btn = config.GetParaStr(key);
|
|
1814 if (btn && btn[0] == 0) btn = 0;
|
|
1815
|
|
1816 if (name == 0 && back == 0 && btn == 0) return;
|
|
1817
|
|
1818 /* まず、テキスト背景を設定 */
|
|
1819 if (back) {
|
|
1820 str = back; str += ".g00";
|
|
1821 int rc,gc,bc,ac, flag;
|
|
1822 char key[1024];
|
|
1823 sprintf(key, "#WINDOW.%03d.ATTR", window_no);
|
|
1824 if (config.GetParam(key, 5, &rc, &gc, &bc, &ac, &flag) == -1) {
|
|
1825 config.GetParam("#WINDOW_ATTR", 5, &rc, &gc, &bc, &ac, &flag);
|
|
1826 }
|
|
1827 Surface* back_s = pic.Root().NewSurface(str.c_str());
|
|
1828 if (back_s) {
|
|
1829 Rect rect(*back_s);
|
|
1830 Surface* s = pic.Root().NewSurface(rect.width(), rect.height(), ALPHA_MASK);
|
|
1831 DSurfaceMove(back_s, rect, s, rect);
|
|
1832 DSurfaceFillA(s, rect, rc, gc, bc, ac); // 透明度設定
|
|
1833 pic.SetSurface(s, 0, 0);
|
|
1834 pic.SetSurfaceFreeFlag(1);
|
|
1835 if (flag == 0) wid->Pic()->SetSurfaceAttribute(PicBase::BLIT_MULTIPLY);
|
|
1836 pic.Root().DeleteSurface(back_s);
|
|
1837 }
|
|
1838 }
|
|
1839 /* その前に枠飾りを設定 */
|
|
1840 if (name) {
|
|
1841 str = name; str += ".g00";
|
|
1842 Surface* s = pic.Root().NewSurface(str.c_str());
|
|
1843 if (s) {
|
|
1844 Rect rect(*s);
|
|
1845 pic.Root().DeleteSurface(s);
|
|
1846 PicBase* p = pic.create_leaf(Rect(0, 0, rect.width(), rect.height()),0);
|
|
1847 p->SetSurface(str.c_str(), 0, 0);
|
|
1848 p->ZMove(ZMOVE_BOTTOM);
|
|
1849 p->show();
|
|
1850 }
|
|
1851 }
|
|
1852 if (btn == 0) return;
|
|
1853 if (use_btn == 0) return;
|
|
1854 // ボタンの作成
|
|
1855 // 使用するボタンについては、必要に応じて show() すること
|
|
1856
|
|
1857 /* ボタンの位置情報を求める */
|
|
1858 str = btn; str += ".g00";
|
|
1859 ARCINFO* info = file_searcher.Find(FILESEARCH::PDT, str.c_str(), "g00");
|
|
1860 if (info == 0) return; // cannot find file
|
|
1861 const char* data = info->Read();
|
|
1862 /* g00 ファイルのヘッダ部分に位置情報は入っている */
|
|
1863 /* 存在しなければボタン画像ではない */
|
|
1864 if (data == 0 || *data != 2) {
|
|
1865 delete info;
|
|
1866 return;
|
|
1867 }
|
|
1868 int index_count = read_little_endian_int(data+5); // 0x70 == 112 ( 8 個ずつグループなので、14個のボタン ) が標準
|
|
1869 int i;
|
|
1870 for (i=0; i<BTNCNT; i++) {
|
|
1871 if (!use_btn[i]) continue;
|
|
1872 if (btnpos[i]*8 >= index_count) {
|
|
1873 continue; // ボタンが存在しない
|
|
1874 }
|
|
1875 int x, y, w, h;
|
|
1876 sprintf(key, "#WAKU.%03d.000.%s_BOX", waku_no, btnname[i]);
|
|
1877 if (config.GetParam(key, 5, 0, &x, &y, &w, &h) == -1) continue;
|
|
1878 int sx, sy, sdx, sdy, cnt;
|
|
1879 const char* d = data + 9 + btnpos[i]*24*8;
|
|
1880 sx = read_little_endian_int(d);
|
|
1881 sy = read_little_endian_int(d+4);
|
|
1882 sdx = read_little_endian_int(d+24) - sx;
|
|
1883 sdy = read_little_endian_int(d+24 + 4) - sy;
|
|
1884 cnt = 2;
|
|
1885 if (sx+sdx*2 == read_little_endian_int(d+2*24) && sy+sdy*2 == read_little_endian_int(d+2*24+4)) cnt = 3;
|
|
1886 WidButton* wid = new WidButton(event, &pic, str.c_str(), sx, sy, sdx, sdy, cnt, Rect(x, y, x+w, y+h), 1);
|
|
1887 if (btnpress[i]) { wid->press_func = btnpress[i]; wid->press_pointer = callback;}
|
|
1888 if (btndrag[i]) { wid->drag_func = btndrag[i]; wid->drag_pointer = callback;}
|
|
1889 }
|
|
1890 delete info;
|
|
1891 return;
|
|
1892 }
|
|
1893
|
|
1894 TextWindow::TextWindow(PicContainer& parent, Event::Container& event, int win_no, const AyuSysConfig& config, void* callback) :
|
|
1895 wid(0), name_visible(true),name(0),name_container(0), face(0) {
|
|
1896 int i; for (i=0; i<8; i++) face_pics[i]=0;
|
|
1897 char key[1024];
|
|
1898 bool use_btn[BTNCNT];
|
|
1899 int size, rep1, rep2, cntw, cnth, mposx, mposy, posd, posx, posy, minx, miny, waku_no, ruby;
|
|
1900 sprintf(key, "#WINDOW.%03d.MOJI_SIZE", win_no); if (config.GetParam(key, 1, &size) == -1) return;
|
|
1901 sprintf(key, "#WINDOW.%03d.MOJI_REP", win_no); if (config.GetParam(key, 2, &rep1, &rep2) == -1) return;
|
|
1902 sprintf(key, "#WINDOW.%03d.MOJI_CNT", win_no); if (config.GetParam(key, 2, &cntw, &cnth) == -1) return;
|
|
1903 sprintf(key, "#WINDOW.%03d.POS", win_no); if (config.GetParam(key, 3, &posd, &posx, &posy) == -1) return;
|
|
1904 sprintf(key, "#WINDOW.%03d.MOJI_POS", win_no); if (config.GetParam(key, 4, &mposy, 0, &mposx, 0) == -1) return;
|
|
1905 sprintf(key, "#WINDOW.%03d.MOJI_MIN", win_no); if (config.GetParam(key, 2, &minx, &miny) == -1) return;
|
|
1906 sprintf(key, "#WINDOW.%03d.WAKU_SETNO", win_no);if (config.GetParam(key, 1, &waku_no) == -1) return;
|
|
1907 sprintf(key, "#WINDOW.%03d.LUBY_SIZE", win_no); if (config.GetParam(key, 1, &ruby) == -1) return;
|
|
1908
|
|
1909 /* テキストウィジット:画面の右下一杯まで使用 */
|
|
1910 /* posd == 2 なら画面下にひっつくように配置 */
|
|
1911 Rect r(0,0);
|
|
1912 if (posd == 2) {
|
|
1913 r = WakuSize(parent, waku_no, config);
|
|
1914 r = Rect(0, parent.Height()-r.height(), r.width(), parent.Height());
|
|
1915 posx = 0;
|
|
1916 posy = parent.Height()-r.height();
|
|
1917 } else /* posd == 0 ? */
|
|
1918 r = Rect(posx, posy, parent.Width(), parent.Height());
|
|
1919
|
|
1920 /* テキストウィンドウの作成 */
|
|
1921 int w = size*cntw; int h = (size+ruby+2)*cnth;
|
|
1922 wid = new WidText(event, &parent, r, Rect(mposx, mposy, mposx+w, mposy+h), size);
|
|
1923 wid->stream.kanji_type = TextStream::sjis;
|
|
1924 /* 顔ウィンドウの作成 */
|
|
1925 for (i=0; i<8; i++) {
|
|
1926 int x,y;
|
|
1927 sprintf(key, "#WINDOW.%03d.FACE.%03d", win_no, i);
|
|
1928 if (config.GetParam(key, 2, &x, &y) == -1) continue;
|
|
1929 /* 顔ウィンドウを作成する */
|
|
1930 if (x >= 0 && y >= 0) {
|
|
1931 face_pics[i] = wid->PicNode()->create_leaf(Rect(x,y), PicBase::FIT_SURFACE);
|
|
1932 } else {
|
|
1933 face_pics[i] = parent.create_leaf(Rect(x+posx,y+posy), PicBase::FIT_SURFACE);
|
|
1934 }
|
|
1935 face_pics[i]->show();
|
|
1936 }
|
|
1937 face = face_pics[0];
|
|
1938 // ボタンの設定
|
|
1939 for (i=0; i<BTNCNT; i++) {
|
|
1940 int num;
|
|
1941 sprintf(key, "#WINDOW.%03d.%s_USE", win_no, btnname[i]);
|
|
1942 config.GetParam(key, 1, &num);
|
|
1943 use_btn[i] = (num==0) ? false : true;
|
|
1944 }
|
|
1945 // make name window
|
|
1946 int shadow, name_mod, name_size, name_min, name_center, name_posx, name_posy, name_mposx, name_mposy;
|
|
1947 sprintf(key, "#WINDOW.%03d.MOJI_SHADOW", win_no); config.GetParam(key, 1, &shadow);
|
|
1948 sprintf(key, "#WINDOW.%03d.NAME_MOD", win_no); config.GetParam(key, 1, &name_mod);
|
|
1949 sprintf(key, "#WINDOW.%03d.NAME_MOJI_SIZE", win_no); config.GetParam(key, 1, &name_size);
|
|
1950 sprintf(key, "#WINDOW.%03d.NAME_MOJI_MIN", win_no); config.GetParam(key, 1, &name_min);
|
|
1951 sprintf(key, "#WINDOW.%03d.NAME_MOJI_POS", win_no); config.GetParam(key, 2, &name_mposx, &name_mposy);
|
|
1952 sprintf(key, "#WINDOW.%03d.NAME_CENTERING", win_no); config.GetParam(key, 1, &name_center);
|
|
1953 sprintf(key, "#WINDOW.%03d.NAME_POS", win_no); config.GetParam(key, 2, &name_posx, &name_posy);
|
|
1954 // if name_mode==0 name is in the text window
|
|
1955 // if name_mode == 1 open name window
|
|
1956 // if name_mode == 2 name is not used
|
|
1957 if (name_mod) {
|
|
1958 if (name_mod == 1) {
|
|
1959 int w = name_size*name_min; int h = name_size;
|
|
1960 int name_waku;
|
|
1961 sprintf(key, "#WINDOW.%03d.NAME_WAKU_SETNO", win_no);
|
|
1962 if (config.GetParam(key, 1, &name_waku) != -1 && name_waku != -1) {
|
|
1963 Rect waku_r = WakuSize(parent, name_waku, config);
|
|
1964 waku_r.rmove(r.lx, r.ty); // テキストウィンドウ位置に動かす
|
|
1965 waku_r.rmove(name_posx, name_posy-waku_r.height()); // NAME_POS へ位置補正
|
|
1966 name_container = parent.create_node(waku_r, 0);
|
|
1967 MakeWaku(*name_container, event, name_waku, win_no, 0, config, callback);
|
|
1968 Rect name_r(0,0,w,h);
|
|
1969 name_r.rmove(name_mposx, name_mposy);
|
|
1970 name = new WidLabel(name_container, name_r, true, 0, name_size);
|
|
1971 name->show();
|
|
1972 } else { // 名前専用枠なし
|
|
1973 Rect name_r(0, 0, w, h);
|
|
1974 name_r.rmove(r.lx, r.ty);
|
|
1975 name_r.rmove(name_posx, name_posy-name_size);
|
|
1976 name_container = parent.create_node(name_r, 0);
|
|
1977 name = new WidLabel(name_container, Rect(0,0,w,h), true, 0, name_size);
|
|
1978 name->show();
|
|
1979 name_container->show();
|
|
1980 }
|
|
1981 } else { // name_mod == 2 or 3
|
|
1982 name_container = parent.create_node( Rect(0,0,1,1), 0);
|
|
1983 }
|
|
1984 }
|
|
1985 MakeWaku(*wid->PicNode(), event,waku_no, win_no, use_btn, config, callback);
|
|
1986 }
|
|
1987 void TextImpl::InitWindow(void) {
|
|
1988 int i,j,k;
|
|
1989 int w;
|
|
1990 std::string str;
|
|
1991
|
|
1992 for (w=0; w<32; w++) {
|
|
1993 widgets[w] = new TextWindow(parent, event, w, config, (void*)this);
|
|
1994 if (widgets[w]->wid == 0) {
|
|
1995 delete widgets[w];
|
|
1996 widgets[w] = 0;
|
|
1997 }
|
|
1998 }
|
|
1999 SetCursor(0);
|
|
2000 for (i=0; i<26; i++) {
|
|
2001 char buf[1024];
|
|
2002 sprintf(buf, "#NAME.%c", i+'A');
|
|
2003 const char* s = config.GetParaStr(buf);
|
|
2004 if (s) replace_name[i] = s;
|
|
2005 }
|
|
2006 // replace_name2 : 初期設定
|
|
2007 // 渚、秋生、渚 (CLANNAD)
|
|
2008 char name_nagisa[3] = {0x8f,0x8d,0};
|
|
2009 char name_akio[5] = {0x8f, 0x48, 0x90, 0xb6, 0};
|
|
2010 replace_name2[0] = name_nagisa;
|
|
2011 replace_name2[1] = name_akio;
|
|
2012 replace_name2[2] = name_nagisa;
|
|
2013 text = 0;
|
|
2014 /* テキスト速度の設定 */
|
|
2015 int speed, mod, wait, auto_mod;
|
|
2016 config.GetParam("#INIT_MESSAGE_SPEED", 1, &speed);
|
|
2017 config.GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &mod);
|
|
2018 config.GetParam("#MESSAGE_KEY_WAIT_USE", 1, &auto_mod);
|
|
2019 config.GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait);
|
|
2020 if (mod) speed = -1;
|
|
2021 if (!auto_mod) wait = -1;
|
|
2022 SetTextSpeed(speed);
|
|
2023 SetTextWait(wait);
|
|
2024 return;
|
|
2025 }
|