cyross-ruby-miyako 2.0.0 → 2.0.5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. data/README +106 -154
  2. data/defines.h +144 -0
  3. data/{miyako_no_katana/extconf.rb → extconf.rb} +10 -0
  4. data/extern.h +29 -0
  5. data/install_miyako.rb +26 -14
  6. data/lib/Miyako/API/audio.rb +2 -2
  7. data/lib/Miyako/API/basic_data.rb +183 -41
  8. data/lib/Miyako/API/bitmap.rb +474 -2
  9. data/lib/Miyako/API/choices.rb +215 -48
  10. data/lib/Miyako/API/collision.rb +267 -251
  11. data/lib/Miyako/API/diagram.rb +58 -70
  12. data/lib/Miyako/API/drawing.rb +93 -52
  13. data/lib/Miyako/API/fixedmap.rb +233 -120
  14. data/lib/Miyako/API/font.rb +59 -40
  15. data/lib/Miyako/API/input.rb +34 -27
  16. data/lib/Miyako/API/layout.rb +154 -172
  17. data/lib/Miyako/API/map.rb +285 -159
  18. data/lib/Miyako/API/map_event.rb +4 -4
  19. data/lib/Miyako/API/modules.rb +1 -1
  20. data/lib/Miyako/API/movie.rb +8 -5
  21. data/lib/Miyako/API/parts.rb +44 -9
  22. data/lib/Miyako/API/plane.rb +37 -2
  23. data/lib/Miyako/API/screen.rb +90 -22
  24. data/lib/Miyako/API/shape.rb +118 -37
  25. data/lib/Miyako/API/sprite.rb +475 -61
  26. data/lib/Miyako/API/sprite_animation.rb +83 -63
  27. data/lib/Miyako/API/spriteunit.rb +47 -13
  28. data/lib/Miyako/API/story.rb +123 -47
  29. data/lib/Miyako/API/textbox.rb +361 -132
  30. data/lib/Miyako/API/utility.rb +388 -0
  31. data/lib/Miyako/API/viewport.rb +54 -349
  32. data/lib/Miyako/API/yuki.rb +570 -353
  33. data/lib/Miyako/EXT/miyako_cairo.rb +5 -3
  34. data/lib/Miyako/EXT/slides.rb +22 -1
  35. data/lib/Miyako/miyako.rb +12 -13
  36. data/logo/EGSR_logo.png +0 -0
  37. data/logo/EGSR_logo_bg.png +0 -0
  38. data/logo/EGSR_logo_fg.png +0 -0
  39. data/logo/EGSR_title_banner.png +0 -0
  40. data/logo/EGSR_title_logo.png +0 -0
  41. data/logo/miyako.png +0 -0
  42. data/logo/miyako_banner.png +0 -0
  43. data/logo/space.png +0 -0
  44. data/miyako_basicdata.c +590 -0
  45. data/miyako_bitmap.c +1225 -0
  46. data/miyako_collision.c +403 -0
  47. data/miyako_drawing.c +187 -0
  48. data/miyako_font.c +334 -0
  49. data/miyako_hsv.c +830 -0
  50. data/miyako_layout.c +191 -0
  51. data/miyako_no_katana.c +1074 -0
  52. data/miyako_transform.c +438 -0
  53. data/miyako_utility.c +288 -0
  54. data/sample/Animation1/m1ku.rb +10 -31
  55. data/sample/Animation1/readme.txt +6 -6
  56. data/sample/Animation2/lex.rb +1 -0
  57. data/sample/Animation2/readme.txt +6 -6
  58. data/sample/Diagram_sample/diagram_sample_yuki2.rb +152 -48
  59. data/sample/Diagram_sample/readme.txt +9 -6
  60. data/sample/Room3/blue.rb +234 -187
  61. data/sample/Room3/ending.rb +68 -63
  62. data/sample/Room3/green.rb +159 -124
  63. data/sample/Room3/main.rb +50 -32
  64. data/sample/Room3/main_component.rb +3 -2
  65. data/sample/Room3/readme.txt +6 -6
  66. data/sample/Room3/red.rb +161 -134
  67. data/sample/Room3/room3.rb +1 -0
  68. data/sample/Room3/title.rb +75 -62
  69. data/sample/ball_action_sample.rb +204 -0
  70. data/sample/blit_rop.rb +70 -0
  71. data/sample/cairo_sample.rb +25 -0
  72. data/sample/circle_collision_test.rb +66 -0
  73. data/sample/collision_test.rb +33 -0
  74. data/sample/collision_test2.rb +108 -0
  75. data/sample/fixed_map_test/fixed_map_sample.rb +23 -32
  76. data/sample/fixed_map_test/readme.txt +38 -38
  77. data/sample/map_test/chara.rb +17 -9
  78. data/sample/map_test/main_parts.rb +30 -9
  79. data/sample/map_test/main_scene.rb +57 -41
  80. data/sample/map_test/map_manager.rb +13 -30
  81. data/sample/map_test/map_test.rb +2 -2
  82. data/sample/map_test/oasis.rb +17 -11
  83. data/sample/map_test/readme.txt +50 -48
  84. data/sample/map_test/route.rb +46 -33
  85. data/sample/map_test/town.rb +19 -13
  86. data/sample/polygon_test.rb +35 -0
  87. data/sample/rasterscroll.rb +25 -0
  88. data/sample/takahashi.rb +42 -0
  89. data/sample/text.png +0 -0
  90. data/sample/textbox_sample.rb +190 -0
  91. data/sample/transform.rb +54 -0
  92. data/sample/utility_test.rb +73 -0
  93. data/sample/utility_test2.rb +61 -0
  94. data/sample/utility_test3.rb +64 -0
  95. data/sample/utility_test4.rb +73 -0
  96. data/uninstall_miyako.rb +19 -0
  97. data/win/miyako_no_katana.so +0 -0
  98. metadata +165 -148
  99. data/miyako.png +0 -0
  100. data/miyako_banner.png +0 -0
  101. data/miyako_no_katana/miyako_no_katana.c +0 -3301
  102. data/sample/fixed_map_test/map_sample.rb +0 -121
@@ -2,7 +2,7 @@
2
2
  =begin
3
3
  --
4
4
  Miyako v2.0
5
- Copyright (C) 2007-2008 Cyross Makoto
5
+ Copyright (C) 2007-2009 Cyross Makoto
6
6
 
7
7
  This library is free software; you can redistribute it and/or
8
8
  modify it under the terms of the GNU Lesser General Public
@@ -20,99 +20,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
20
  ++
21
21
  =end
22
22
 
23
- require 'thread'
23
+ #lambdaの別名として、yuki_plotメソッドを追加
24
+ alias :yuki_plot :lambda
24
25
 
25
26
  #=シナリオ言語Yuki実装モジュール
26
27
  module Miyako
28
+
27
29
  #==Yuki本体クラス
28
30
  #Yukiの内容をオブジェクト化したクラス
29
31
  #Yukiのプロット処理を外部メソッドで管理可能
30
32
  #プロットは、引数を一つ(Yuki2クラスのインスタンス)を取ったメソッドもしくはブロック
31
33
  #として記述する。
32
34
  class Yuki
35
+
33
36
  #==キャンセルを示す構造体
34
37
  #コマンド選択がキャンセルされたときに生成される構造体
35
- Canseled = Struct.new(:dummy)
36
-
37
- #==Yuki実行管理クラス(外部クラスからの管理用)
38
- #実行中のYukiの管理を行うためのクラス
39
- #インスタンスは、Yuki#getmanager メソッドを呼ぶことで取得する
40
- class Manager
41
- #===インスタンスの作成
42
- #実際にインスタンスを生成するときは、Yuki#manager メソッドを呼ぶこと
43
- #_yuki_:: 管理対象の Yuki モジュールを mixin したクラスのインスタンス
44
- #_plot_proc_:: プロットメソッド・プロシージャインスタンス。デフォルトは nil
45
- #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
46
- #_use_thread_:: スレッドを使ったポーズやタイマー待ちの監視を行うかを示すフラグ。デフォルトはfalse
47
- def initialize(yuki, plot_proc, with_update_input = true, use_thread = false)
48
- @with_update_input = with_update_input
49
- @use_thread = use_thread
50
- @yuki_instance = yuki
51
- @yuki_plot = plot_proc
52
- end
53
-
54
- #===プロット処理を開始する
55
- def start
56
- @yuki_instance.start_plot(@yuki_plot, @with_update_input, @use_thread)
57
- end
58
-
59
- #===入力更新処理を呼び出す
60
- def update_input
61
- @yuki_instance.update_plot_input
62
- end
63
-
64
- #===更新処理を呼び出す
65
- def update
66
- @yuki_instance.update
67
- end
68
-
69
- #===描画処理を呼び出す
70
- def render
71
- @yuki_instance.render
72
- end
73
-
74
- #===プロットの実行結果を返す
75
- #返却値:: 実行結果を示すインスタンス。デフォルトは、現在実行しているシーンのインスタンス
76
- def result
77
- @yuki_instance.result
78
- end
79
-
80
- #===コマンド選択がキャンセルされたときの結果を返す
81
- #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
82
- def canseled?
83
- return @yuki_instance.canseled?
84
- end
85
-
86
- #===プロット処理が実行中かの問い合わせメソッド
87
- #返却値:: 実行中の時は true を返す
88
- def executing?
89
- return @yuki_instance.executing?
90
- end
91
-
92
- #===コマンド選択中の問い合わせメソッド
93
- #返却値:: コマンド選択中の時はtrueを返す
94
- def selecting?
95
- return @yuki_instance.selecting?
96
- end
97
-
98
- #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
99
- #返却値:: 処理待ちの時はtrueを返す
100
- def waiting?
101
- return @yuki_instance.waiting?
102
- end
103
-
104
- #===メッセージ送り待ちの問い合わせメソッド
105
- #返却値:: メッセージ送り待ちの時はtrueを返す
106
- def pausing?
107
- return @yuki_instance.pausing?
108
- end
109
-
110
- #===Yukiオブジェクトが使用しているオブジェクトを解放する
111
- def dispose
112
- @yuki_instance.dispose
113
- @yuki_instance = nil
114
- end
115
- end
38
+ Canceled = Struct.new(:dummy)
116
39
 
117
40
  #==コマンド構造体
118
41
  #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
@@ -120,54 +43,149 @@ module Miyako
120
43
  #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
121
44
  #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
122
45
  Command = Struct.new(:body, :body_selected, :condition, :result)
123
-
124
- attr_accessor :update_inner, :update_text
125
- attr_reader :parts, :diagrams, :vars
46
+
47
+ #==コマンド構造体
48
+ #_body_:: コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)
49
+ #_body_selected_:: 選択時コマンドの名称(移動する、調べるなど、アイコンなどの画像も可)(省略時は、bodyと同一)
50
+ #_condition_:: 表示条件(ブロック)。評価の結果、trueのときのみ表示
51
+ #_result_:: 選択結果(移動先シーンクラス名、シナリオ(メソッド)名他のオブジェクト)
52
+ #_end_select_proc_:: この選択肢を選択したときに優先的に処理するブロック。
53
+ #ブロックは1つの引数を取る(コマンド選択テキストボックス))。デフォルトはnil
54
+ CommandEX = Struct.new(:body, :body_selected, :condition, :result, :end_select_proc)
55
+
56
+ #===Yuki#update実行中に行わせる処理を実装するテンプレートメソッド
57
+ #但し、メソッド本体は、update_inner=メソッドで設定する必要がある
58
+ #_yuki_:: 実行中のYukiクラスインスタンス
59
+ def update_inner(yuki)
60
+ end
61
+
62
+ #===Yuki#text実行中に行わせる処理を実装するテンプレートメソッド
63
+ #update_textテンプレートメソッドは、textメソッドで渡した文字列全体ではなく、
64
+ #内部で1文字ずつ分割して、その字が処理されるごとに呼ばれる。
65
+ #そのため、引数chで入ってくるのは、分割された1文字となる。
66
+ #但し、メソッド本体は、update_text=メソッドで設定する必要がある
67
+ #_yuki_:: 実行中のYukiクラスインスタンス
68
+ #_ch_:: textメソッドで処理中の文字(分割済みの1文字)
69
+ def update_text(yuki, ch)
70
+ end
71
+
72
+ #===Yuki#cr呼び出し時に行わせる処理を実装するテンプレートメソッド
73
+ #但し、メソッド本体は、update_cr=メソッドで設定する必要がある
74
+ #_yuki_:: 実行中のYukiクラスインスタンス
75
+ def update_cr(yuki)
76
+ end
77
+
78
+ #===Yuki#clear呼び出し時に行わせる処理を実装するテンプレートメソッド
79
+ #但し、メソッド本体は、update_clear=メソッドで設定する必要がある
80
+ #_yuki_:: 実行中のYukiクラスインスタンス
81
+ def update_clear(yuki)
82
+ end
83
+
84
+ attr_accessor :visible
85
+ attr_accessor :update_inner, :update_text, :update_cr, :update_clear
86
+ attr_reader :parts, :vars, :valign
87
+ #release_checks:: ポーズ解除を問い合わせるブロックの配列。
88
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
89
+ #ok_checks:: コマンド選択決定を問い合わせるブロックの配列。
90
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
91
+ #cancel_checks:: コマンド選択解除(キャンセル)を問い合わせるブロックの配列。
92
+ #callメソッドを持ち、true/falseを返すインスタンスを配列操作で追加・削除できる。
93
+ attr_reader :release_checks, :ok_checks, :cancel_checks
94
+ attr_reader :pre_pause, :pre_command, :pre_cancel, :post_pause, :post_command, :post_cancel
95
+ #selecting_procs:: コマンド選択時に行うブロックの配列。
96
+ #ブロックは4つの引数を取る必要がある。
97
+ #(1)コマンド決定ボタンを押した?(true/false)
98
+ #(2)キャンセルボタンを押した?(true/false)
99
+ #(3)キーパッドの移動量を示す配列([dx,dy])
100
+ #(4)マウスの位置を示す配列([x,y])
101
+ #callメソッドを持つブロックが使用可能。
102
+ attr_reader :selecting_procs
126
103
 
127
104
  #===Yukiを初期化する
128
- def initialize
105
+ #
106
+ #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
107
+ #引数の数とブロック引数の数が違っていれば例外が発生する
108
+ #_params_:: ブロックに渡す引数リスト
109
+ def initialize(*params, &proc)
129
110
  @yuki = { }
130
- @yuki[:text_box] = nil
131
- @yuki[:command_box] = nil
132
-
133
- @yuki[:btn] = {:ok => :btn1, :cansel => :btn2, :release => :btn1 }
111
+ @text_box = nil
112
+ @command_box = nil
134
113
 
135
- @yuki[:plot_thread] = nil
114
+ @executing = false
115
+ @with_update_input = true
136
116
 
137
- @yuki[:exec_plot] = false
138
- @yuki[:with_update_input] = true
139
-
140
- @yuki[:pausing] = false
141
- @yuki[:selecting] = false
142
- @yuki[:waiting] = false
117
+ @exec_plot = nil
118
+
119
+ @pausing = false
120
+ @selecting = false
121
+ @waiting = false
143
122
 
144
- @yuki[:pause_release] = false
145
- @yuki[:select_ok] = false
146
- @yuki[:select_cansel] = false
147
- @yuki[:select_amount] = [0, 0]
123
+ @pause_release = false
124
+ @select_ok = false
125
+ @select_cancel = false
126
+ @select_amount = [0, 0]
127
+ @mouse_amount = nil
148
128
 
149
- @yuki[:result] = nil
150
- @yuki[:plot_result] = nil
129
+ @result = nil
130
+ @plot_result = nil
151
131
 
152
132
  @update_inner = lambda{|yuki|}
153
- @update_text = lambda{|yuki|}
154
- @mutex = Mutex.new
133
+ @update_text = lambda{|yuki, ch|}
134
+ @update_cr = lambda{|yuki|}
135
+ @update_clear = lambda{|yuki|}
155
136
 
156
137
  @parts = {}
157
- @visible = []
158
- @diagrams = {}
138
+ @visibles = []
159
139
  @vars = {}
140
+ @visible = true
141
+
142
+ @executing_fiber = nil
143
+
144
+ @text_methods = {:char => self.method(:text_by_char),
145
+ :string => self.method(:text_by_str) }
146
+ @text_method_name = :char
160
147
 
148
+ @valign = :middle
149
+
150
+ @release_checks_default = [lambda{ Input.pushed_all?(:btn1) }, lambda{ Input.click?(:left) } ]
151
+ @release_checks = @release_checks_default.dup
152
+
153
+ @ok_checks_default = [lambda{ Input.pushed_all?(:btn1) },
154
+ lambda{ self.commandbox.attach_any_command?(*Input.get_mouse_position) && Input.click?(:left) } ]
155
+ @ok_checks = @ok_checks_default.dup
156
+
157
+ @cancel_checks_default = [lambda{ Input.pushed_all?(:btn2) },
158
+ lambda{ Input.click?(:right) } ]
159
+ @cancel_checks = @cancel_checks_default.dup
160
+
161
+ @key_amount_proc = lambda{ Input.pushed_amount }
162
+ @mouse_amount_proc = lambda{ Input.mouse_cursor_inner? ? Input.get_mouse_position : nil }
163
+
164
+ @pre_pause = []
165
+ @pre_command = []
166
+ @pre_cancel = []
167
+ @post_pause = []
168
+ @post_command = []
169
+ @post_cancel = []
170
+ @selecting_procs = []
171
+
161
172
  @is_outer_height = self.method(:is_outer_height)
162
- end
163
173
 
174
+ @now_page = nil
175
+ @first_page = nil
176
+
177
+ raise MiyakoError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
178
+ instance_exec(*params, &proc) if block_given?
179
+ end
180
+
164
181
  #===Yuki#showで表示指定した画像を描画する
165
182
  #描画順は、showメソッドで指定した順に描画される(先に指定した画像は後ろに表示される)
183
+ #なお、visibleの値がfalseの時は描画されない。
166
184
  #返却値:: 自分自身を返す
167
185
  def render
168
- @visible.each{|name|
186
+ return self unless @visible
187
+ @visibles.each{|name|
169
188
  @parts[name].render if @parts.has_key?(name)
170
- @diagrams[name].render if @diagrams.has_key?(name)
171
189
  }
172
190
  return self
173
191
  end
@@ -175,8 +193,8 @@ module Miyako
175
193
  #===オブジェクトを登録する
176
194
  #オブジェクトをパーツnameとして登録する。
177
195
  #Yuki::parts[name]で参照可能
178
- #:name:: パーツ名(シンボル)
179
- #:parts:: 登録対象のインスタンス
196
+ #_name_:: パーツ名(シンボル)
197
+ #_parts_:: 登録対象のインスタンス
180
198
  #
181
199
  #返却値:: 自分自身を返す
182
200
  def regist_parts(name, parts)
@@ -185,40 +203,40 @@ module Miyako
185
203
  end
186
204
 
187
205
  #===表示・描画対象のテキストボックスを選択する
188
- #:box:: テキストボックスのインスタンス
206
+ #_box_:: テキストボックスのインスタンス
189
207
  #
190
208
  #返却値:: 自分自身を返す
191
209
  def select_textbox(box)
192
- @yuki[:text_box] = box
210
+ @text_box = box
193
211
  return self
194
212
  end
195
213
 
196
214
  #===表示・描画対象のコマンドボックスを選択する
197
- #:box:: テキストボックスのインスタンス
215
+ #_box_:: テキストボックスのインスタンス
198
216
  #
199
217
  #返却値:: 自分自身を返す
200
218
  def select_commandbox(box)
201
- @yuki[:command_box] = box
219
+ @command_box = box
202
220
  return self
203
221
  end
204
222
 
205
- #===遷移図を登録する
206
- #遷移図をパーツnameとして登録する。
207
- #遷移図を登録すると、update_inputメソッドがYuki2::update_plotメソッドを呼び出した時に
208
- #自動的に呼び出される(renderメソッドは呼ばれないことに注意!)。
209
- #Yuki::diagrams[name]で参照可能
210
- #:name:: パーツ名(シンボル)
211
- #:diagram:: 登録対象の遷移図インスタンス
212
- #
213
- #返却値:: 自分自身を返す
214
- def regist_diagram(name, diagram)
215
- @diagrams[name] = diagram
216
- return self
223
+ #===テキストボックスを取得する
224
+ #テキストボックスが登録されていないときはnilを返す
225
+ #返却値:: テキストボックスのインスタンス
226
+ def textbox
227
+ return @text_box
228
+ end
229
+
230
+ #===コマンドボックスを取得する
231
+ #コマンドボックスが登録されていないときはnilを返す
232
+ #返却値:: コマンドボックスのインスタンス
233
+ def commandbox
234
+ return @command_box
217
235
  end
218
236
 
219
237
  #===オブジェクトの登録を解除する
220
238
  #パーツnameとして登録されているオブジェクトを登録から解除する。
221
- #:name:: パーツ名(シンボル)
239
+ #_name_:: パーツ名(シンボル)
222
240
  #
223
241
  #返却値:: 自分自身を返す
224
242
  def remove_parts(name)
@@ -226,42 +244,32 @@ module Miyako
226
244
  return self
227
245
  end
228
246
 
229
- #===遷移図の登録を解除する
230
- #パーツnameとして登録されている遷移図を登録から解除する。
231
- #:name:: パーツ名(シンボル)
232
- #
233
- #返却値:: 自分自身を返す
234
- def remove_diagram(name)
235
- @diagrams.delete(@parts[name])
236
- return self
237
- end
238
-
239
247
  #===パーツで指定したオブジェクトを先頭に表示する
240
248
  #描画時に、指定したパーツを描画する
241
249
  #すでにshowメソッドで表示指定している場合は、先頭に表示させる
242
- #:names:: パーツ名(シンボル)、複数指定可能(指定した順番に描画される)
250
+ #_names_:: パーツ名(シンボル)、複数指定可能(指定した順番に描画される)
243
251
  #返却値:: 自分自身を返す
244
252
  def show(*names)
245
253
  names.each{|name|
246
- @visible.delete(name)
247
- @visible << name
254
+ @visibles.delete(name)
255
+ @visibles << name
248
256
  }
249
257
  return self
250
258
  end
251
259
 
252
260
  #===パーツで指定したオブジェクトを隠蔽する
253
261
  #描画時に、指定したパーツを描画させないよう指定する
254
- #:names:: パーツ名(シンボル)、複数指定可能
262
+ #_names_:: パーツ名(シンボル)、複数指定可能
255
263
  #返却値:: 自分自身を返す
256
264
  def hide(*names)
257
- names.each{|name| @visible.delete(name) }
265
+ names.each{|name| @visibles.delete(name) }
258
266
  return self
259
267
  end
260
268
 
261
269
  #===パーツで指定したオブジェクトの処理を開始する
262
270
  #nameで指定したパーツが持つ処理を隠蔽する。
263
271
  #(但し、パーツで指定したオブジェクトがstartメソッドを持つことが条件)
264
- #:name:: パーツ名(シンボル)
272
+ #_name_:: パーツ名(シンボル)
265
273
  #返却値:: 自分自身を返す
266
274
  def start(name)
267
275
  @parts[name].start
@@ -271,7 +279,7 @@ module Miyako
271
279
  #===パーツで指定したオブジェクトを再生する
272
280
  #nameで指定したパーツを再生する。
273
281
  #(但し、パーツで指定したオブジェクトがplayメソッドを持つことが条件)
274
- #:name:: パーツ名(シンボル)
282
+ #_name_:: パーツ名(シンボル)
275
283
  #返却値:: 自分自身を返す
276
284
  def play(name)
277
285
  @parts[name].play
@@ -281,7 +289,7 @@ module Miyako
281
289
  #===パーツで指定したオブジェクトの処理を停止する
282
290
  #nameで指定したパーツが持つ処理を停止する。
283
291
  #(但し、パーツで指定したオブジェクトがstopメソッドを持つことが条件)
284
- #:name:: パーツ名(シンボル)
292
+ #_name_:: パーツ名(シンボル)
285
293
  #返却値:: 自分自身を返す
286
294
  def stop(name)
287
295
  @parts[name].stop
@@ -290,71 +298,77 @@ module Miyako
290
298
 
291
299
  #===遷移図の処理が終了するまで待つ
292
300
  #nameで指定した遷移図の処理が終了するまで、プロットを停止する
293
- #:name:: 遷移図名(シンボル)
301
+ #_name_: 遷移図名(シンボル)
294
302
  #返却値:: 自分自身を返す
295
303
  def wait_by_finish(name)
296
304
  until @parts[name].finish?
297
305
  @update_inner.call(self)
298
- Thread.pass unless Thread.current.eql?(Thread.main)
299
306
  end
300
307
  return self
301
308
  end
302
309
 
303
- #===各ボタンの設定リストを出力する
304
- #コマンド決定・キャンセル時に使用するボタンの一覧をシンボルのハッシュとして返す。ハッシュの内容は以下の通り
305
- #ハッシュキー:: 説明:: デフォルト
306
- #:release:: メッセージ待ちを終了するときに押すボタン:: :btn1
307
- #:ok:: コマンド選択で「決定」するときに押すボタン:: btn1
308
- #:cansel:: コマンド選択で「キャンセル」するときに押すボタン:: btn2
309
- #
310
- #返却値:: ボタンの設定リスト
311
- def button
312
- return @yuki[:btn]
313
- end
314
-
315
310
  #===シーンのセットアップ時に実行する処理
316
311
  #
317
- #返却値:: あとで書く
318
- def setup
319
- @yuki[:plot_result] = nil
312
+ #ブロック引数として、テキストボックスの変更などの処理をブロック内に記述することが出来る。
313
+ #引数の数とブロック引数の数が違っていれば例外が発生する
314
+ #_params_:: ブロックに渡す引数リスト
315
+ #返却値:: 自分自身を返す
316
+ def setup(*params, &proc)
317
+ @exec_plot = nil
318
+
319
+ @executing = false
320
320
 
321
- @yuki[:exec_plot] = false
321
+ @pausing = false
322
+ @selecting = false
323
+ @waiting = false
322
324
 
323
- @yuki[:pausing] = false
324
- @yuki[:selecting] = false
325
- @yuki[:waiting] = false
325
+ @pause_release = false
326
+ @select_ok = false
327
+ @select_cancel = false
328
+ @select_amount = [0, 0]
329
+ @mouse_amount = nil
326
330
 
327
- @yuki[:pause_release] = false
328
- @yuki[:select_ok] = false
329
- @yuki[:select_cansel] = false
330
- @yuki[:select_amount] = [0, 0]
331
+ @result = nil
332
+ @plot_result = nil
331
333
 
332
- @yuki[:result] = nil
333
- @yuki[:plot_result] = nil
334
+ @now_page = nil
335
+ @first_page = nil
336
+
337
+ raise MiyakoError, "Aagument count is not same block parameter count!" if proc && proc.arity.abs != params.length
338
+ instance_exec(*params, &proc) if block_given?
339
+
340
+ return self
334
341
  end
335
342
 
343
+ #===実行するプロットと登録する
344
+ #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
345
+ #返却値:: 自分自身を返す
346
+ def select_plot(plot_proc)
347
+ @exec_plot = plot_proc
348
+ return self
349
+ end
350
+
336
351
  #===プロット処理を実行する(明示的に呼び出す必要がある場合)
337
352
  #引数もしくはブロックで指定したプロット処理を非同期に実行する。
338
353
  #呼び出し可能なプロットは以下の3種類。(上から優先度が高い順)
354
+ #プロットが見つからなければ例外が発生する
339
355
  #
340
356
  #1)引数prot_proc(Procクラスのインスタンス)
341
357
  #
342
- #2)ブロック引数
358
+ #2)引数として渡したブロック
343
359
  #
344
- #3)Yuki#plotメソッド
360
+ #3)select_plotメソッドで登録したブロック(Procクラスのインスタンス)
345
361
  #
346
362
  #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
347
363
  #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
348
- #_use_thread_:: スレッドを使ったポーズやタイマー待ちの監視を行うかを示すフラグ。デフォルトはfalse
349
- #返却値:: あとで書く
350
- def start_plot(plot_proc = nil, with_update_input = true, use_thread = false, &plot_block)
351
- raise MiyakoError, "Yuki Error! Textbox is not selected!" unless @yuki[:text_box]
352
- raise MiyakoError, "Yuki Error! Plot must have one parameter!" if plot_proc && plot_proc.arity != 1
353
- raise MiyakoError, "Yuki Error! Plot must have one parameter!" if plot_block && plot_block.arity != 1
354
- @yuki[:text_box].exec{ plot_facade(plot_proc, &plot_block) }
355
- until @yuki[:exec_plot] do; end
356
- @yuki[:plot_thread] = Thread.new{ update_plot_thread } if use_thread
357
- @yuki[:with_update_input] = with_update_input
364
+ #返却値:: 自分自身を返す
365
+ def start_plot(plot_proc = nil, with_update_input = true, &plot_block)
366
+ raise MiyakoError, "Yuki Error! Textbox is not selected!" unless @text_box
367
+ raise MiyakoError, "Yuki Error! Plot must not have any parameters!" if plot_proc && plot_proc.arity != 0
368
+ raise MiyakoError, "Yuki Error! Plot must not have any parameters!" if plot_block && plot_block.arity != 0
369
+ @with_update_input = with_update_input
370
+ @executing_fiber = Fiber.new{ plot_facade(plot_proc, &plot_block) }
371
+ @executing_fiber.resume
358
372
  return self
359
373
  end
360
374
 
@@ -362,43 +376,24 @@ module Miyako
362
376
  #ポーズ中、コマンド選択中、 Yuki#wait メソッドによるウェイトの状態確認を行う。
363
377
  #プロット処理の実行確認は出来ない
364
378
  def update
365
- return unless @yuki[:exec_plot]
366
- update_plot_input if @yuki[:with_update_input]
367
- unless @yuki[:plot_thread]
368
- pausing if @yuki[:pausing]
369
- selecting if @yuki[:selecting]
370
- waiting if @yuki[:waiting]
371
- end
372
- @diagrams.each_value{|dia|
373
- dia.update_input
374
- dia.update if dia.sync?
375
- }
376
- @mutex.lock
377
- @yuki[:pause_release] = false
378
- @yuki[:select_ok] = false
379
- @yuki[:select_cansel] = false
380
- @yuki[:select_amount] = [0, 0]
381
- @mutex.unlock
379
+ return unless @executing
380
+ update_plot_input if @with_update_input
381
+ pausing if @pausing
382
+ selecting if @selecting
383
+ waiting if @waiting
384
+ @pause_release = false
385
+ @select_ok = false
386
+ @select_cancel = false
387
+ @select_amount = [0, 0]
388
+ @executing_fiber.resume
382
389
  end
383
390
 
384
- def update_plot_thread #:nodoc:
385
- while @yuki[:exec_plot]
386
- pausing if @yuki[:pausing]
387
- selecting if @yuki[:selecting]
388
- waiting if @yuki[:waiting]
389
- Thread.pass
390
- end
391
- end
392
-
393
- #===プロット用メソッドをYukiへ渡すためのインスタンスを作成する
394
- #プロット用に用意したメソッド(引数一つのメソッド)を、Yukiでの選択結果や移動先として利用できる
391
+ #===プロット用ブロックをYukiへ渡すためのインスタンスを作成する
392
+ #プロット用に用意したブロック(ブロック引数無し)を、Yukiでの選択結果や移動先として利用できる
395
393
  #インスタンスに変換する
396
- #(指定のメソッドをMethodクラスのインスタンスに変換する)
397
- #_instance_:: 対象のメソッドが含まれているインスタンス(レシーバ)
398
- #_method_:: メソッド名(シンボルまたは文字列)
399
- #返却値:: 生成したインスタンスを返す
400
- def to_plot(instance, method)
401
- return instance.method(method.to_sym)
394
+ #返却値:: ブロックをオブジェクトに変換したものを返す
395
+ def to_plot(&plot)
396
+ return plot
402
397
  end
403
398
 
404
399
  #===プロット処理に使用する入力情報を更新する
@@ -408,53 +403,143 @@ module Miyako
408
403
  #プロット処理の場合は、メインスレッドから明示的に呼び出す必要がある
409
404
  #返却値:: nil を返す
410
405
  def update_plot_input
411
- return nil unless @yuki[:exec_plot]
412
- if @yuki[:pausing] && Input.pushed_all?(@yuki[:btn][:ok])
413
- @yuki[:pause_release] = true
414
- elsif @yuki[:selecting]
415
- @yuki[:select_ok] = true if Input.pushed_all?(@yuki[:btn][:ok])
416
- @yuki[:select_cansel] = true if Input.pushed_all?(@yuki[:btn][:cansel])
417
- @yuki[:select_amount] = Input.pushed_amount
406
+ return nil unless @executing
407
+ if @pausing && @release_checks.inject(false){|r, c| r |= c.call }
408
+ @pause_release = true
409
+ elsif @selecting
410
+ @select_ok = true if @ok_checks.inject(false){|r, c| r |= c.call }
411
+ @select_cancel = true if @cancel_checks.inject(false){|r, c| r |= c.call }
412
+ @select_amount = @key_amount_proc.call
413
+ @mouse_amount = @mouse_amount_proc.call
418
414
  end
419
415
  return nil
420
416
  end
421
417
 
422
- #===プロット処理を外部クラスから管理するインスタンスを取得する
418
+ def plot_facade(plot_proc = nil, &plot_block) #:nodoc:
419
+ @plot_result = nil
420
+ @executing = true
421
+ exec_plot = @exec_plot
422
+ @plot_result = plot_proc ? self.instance_exec(&plot_proc) :
423
+ block_given? ? self.instance_exec(&plot_block) :
424
+ exec_plot ? self.instance_exec(&exec_plot) :
425
+ raise(MiyakoError, "Cannot find plot!")
426
+ @executing = false
427
+ end
428
+
429
+ #===プロット処理中に別のプロットを呼び出す
430
+ #呼び出し可能なプロットは以下の2種類。(上から優先度が高い順)
423
431
  #
424
432
  #1)引数prot_proc(Procクラスのインスタンス)
425
433
  #
426
- #2)ブロック引数
427
- #
428
- #3)Yuki#plotメソッド
434
+ #2)引数として渡したブロック
429
435
  #
430
436
  #_plot_proc_:: プロットの実行部をインスタンス化したオブジェクト
431
- #_with_update_input_:: Yuki#updateメソッドを呼び出した時、同時にYuki#update_plot_inputメソッドを呼び出すかどうかを示すフラグ。デフォルトはfalse
432
- #_use_thread_:: スレッドを使ったポーズやタイマー待ちの監視を行うかを示すフラグ。デフォルトはfalse
433
- #返却値:: YukiManager クラスのインスタンス
434
- def manager(plot_proc = nil, with_update_input = true, use_thread = false, &plot_block)
435
- return Manager.new(self, plot_proc || plot_block, with_update_input, use_thread)
436
- end
437
-
438
- def plot_facade(plot_proc = nil, &plot_block) #:nodoc:
439
- @mutex.lock
440
- @yuki[:plot_result] = nil
441
- @yuki[:exec_plot] = true
442
- @mutex.unlock
443
- @yuki[:plot_result] = plot_proc ? plot_proc.call(self) : plot_block.call(self)
444
- @diagrams.each_value{|dia| dia.stop }
445
- @mutex.lock
446
- @yuki[:exec_plot] = false
447
- if @yuki[:plot_thread]
448
- @yuki[:plot_thread].join
449
- @yuki[:plot_thread] = nil
450
- end
451
- @mutex.unlock
437
+ #返却値:: プロットの実行結果を返す
438
+ def call_plot(plot_proc = nil, &plot_block)
439
+ return plot_proc ? self.instance_exec(&plot_proc) :
440
+ self.instance_exec(&plot_block)
452
441
  end
453
442
 
454
443
  #===プロット処理が実行中かどうかを確認する
455
444
  #返却値:: プロット処理実行中の時はtrueを返す
456
445
  def executing?
457
- return @yuki[:exec_plot]
446
+ return @executing
447
+ end
448
+
449
+ #===ポーズ解除問い合わせメソッド配列を初期状態に戻す
450
+ #返却値:: 自分自身を返す
451
+ def reset_release_checks
452
+ @release_checks = @release_checks_default.dup
453
+ return self
454
+ end
455
+
456
+ #===コマンド選択決定問い合わせメソッド配列を初期状態に戻す
457
+ #返却値:: 自分自身を返す
458
+ def reset_ok_checks
459
+ @ok_checks = @ok_checks_default.dup
460
+ return self
461
+ end
462
+
463
+ #===コマンド選択キャンセル問い合わせメソッド配列を初期状態に戻す
464
+ #返却値:: 自分自身を返す
465
+ def reset_cancel_checks
466
+ @cancel_checks = @cancel_checks_default.dup
467
+ return self
468
+ end
469
+
470
+ #===ポーズ前後処理メソッド配列を初期状態に戻す
471
+ #pre_pause/post_pauseの処理を初期状態([])に戻す
472
+ #返却値:: 自分自身を返す
473
+ def reset_pre_post_release
474
+ @pre_pause = []
475
+ @post_pause = []
476
+ return self
477
+ end
478
+
479
+ #===コマンド選択前後処理メソッド配列を初期状態に戻す
480
+ #pre_command/post_commandの処理を初期状態([])に戻す
481
+ #返却値:: 自分自身を返す
482
+ def reset_pre_post_command
483
+ @pre_command = []
484
+ @post_command = []
485
+ return self
486
+ end
487
+
488
+ #===コマンド選択キャンセル前後処理メソッド配列を初期状態に戻す
489
+ #pre_cancel/post_cancelの処理を初期状態([])に戻す
490
+ #返却値:: 自分自身を返す
491
+ def reset_pre_post_cancel
492
+ @pre_acncel = []
493
+ @post_cancel = []
494
+ return self
495
+ end
496
+
497
+ #===ブロック評価中、ポーズ解除問い合わせメソッド配列を置き換える
498
+ #同時に、ポーズ時処理(Yuki#pre_pause)、ポーズ解除時処理(Yuki#post_pause)を引数で設定できる。
499
+ #ブロックの評価が終われば、メソッド配列・ポーズ時処理・ポーズ解除時処理を元に戻す
500
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
501
+ #pre_proc:: ポーズ開始時に実行させるProc(デフォルトは[](何もしない))
502
+ #post_proc:: ポーズ解除時に実行させるProc(デフォルトは[](何もしない))
503
+ #返却値:: 自分自身を返す
504
+ def release_checks_during(procs, pre_procs = [], post_procs = [])
505
+ raise MiyakoError, "Can't find block!" unless block_given?
506
+ backup = [@release_checks, @pre_pause, @post_pause]
507
+ @release_checks, @pre_pause, @post_pause = procs, pre_proc, post_proc
508
+ yield
509
+ @release_checks, @pre_pause, @post_pause = backup.pop(3)
510
+ return self
511
+ end
512
+
513
+ #===ブロック評価中、コマンド選択決定問い合わせメソッド配列を置き換える
514
+ #同時に、コマンド選択開始時処理(Yuki#pre_command)、コマンド選択終了時処理(Yuki#post_command)を引数で設定できる。
515
+ #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
516
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
517
+ #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
518
+ #post_proc:: コマンド選択決定時に実行させるProc(デフォルトは[](何もしない))
519
+ #返却値:: 自分自身を返す
520
+ def ok_checks_during(procs, pre_procs = [], post_procs = [])
521
+ raise MiyakoError, "Can't find block!" unless block_given?
522
+ backup = [@ok_checks, @pre_command, @post_command]
523
+ @ok_checks, @pre_command, @post_command = procs, pre_proc, post_proc
524
+ yield
525
+ @ok_checks, @pre_command, @post_command = backup.pop(3)
526
+ return self
527
+ end
528
+
529
+ #===ブロック評価中、コマンド選択キャンセル問い合わせメソッド配列を置き換える
530
+ #同時に、コマンド選択開始時処理(Yuki#pre_cancel)、コマンド選択終了時処理(Yuki#post_cancel)を引数で設定できる。
531
+ #ブロックの評価が終われば、メソッド配列・コマンド選択開始時処理・コマンド選択終了時処理を元に戻す
532
+ #procs:: 置き換えるメソッド配列(callメソッドを持ち、true/falseを返すメソッドの配列)
533
+ #pre_proc:: コマンド選択開始時に実行させるProc(デフォルトは[](何もしない))
534
+ #post_proc:: コマンド選択キャンセル時に実行させるProc(デフォルトは[](何もしない))
535
+ #返却値:: 自分自身を返す
536
+ def cancel_checks_during(procs, pre_procs = [], post_procs = [])
537
+ raise MiyakoError, "Can't find block!" unless block_given?
538
+ backup = [@cancel_checks, @pre_cancel, @post_cancel]
539
+ @cancel_checks, @pre_cancel, @post_cancel = procs, pre_proc, post_proc
540
+ yield
541
+ @cancel_checks, @pre_cancel, @post_cancel = backup.pop(3)
542
+ return self
458
543
  end
459
544
 
460
545
  #===プロットの処理結果を返す
@@ -463,14 +548,14 @@ module Miyako
463
548
  #プロット処理が終了していないのに結果を得られるので注意!
464
549
  #返却値:: プロットの処理結果
465
550
  def result
466
- return @yuki[:plot_result]
551
+ return @plot_result
467
552
  end
468
553
 
469
554
  #===プロット処理の結果を設定する
470
555
  #_ret_:: 設定する結果。デフォルトはnil
471
556
  #返却値:: 自分自身を返す
472
557
  def result=(ret = nil)
473
- @yuki[:plot_result] = ret
558
+ @plot_result = ret
474
559
  return self
475
560
  end
476
561
 
@@ -492,8 +577,8 @@ module Miyako
492
577
 
493
578
  #===コマンド選択がキャンセルされたときの結果を返す
494
579
  #返却値:: キャンセルされたときはtrue、されていないときはfalseを返す
495
- def canseled?
496
- return result == @yuki[:cansel]
580
+ def canceled?
581
+ return result == @cancel
497
582
  end
498
583
 
499
584
  #===ブロックを条件として設定する
@@ -507,19 +592,19 @@ module Miyako
507
592
  #===コマンド選択中の問い合わせメソッド
508
593
  #返却値:: コマンド選択中の時はtrueを返す
509
594
  def selecting?
510
- return @yuki[:selecting]
595
+ return @selecting
511
596
  end
512
597
 
513
598
  #===Yuki#waitメソッドによる処理待ちの問い合わせメソッド
514
599
  #返却値:: 処理待ちの時はtrueを返す
515
600
  def waiting?
516
- return @yuki[:waiting]
601
+ return @waiting
517
602
  end
518
603
 
519
604
  #===メッセージ送り待ちの問い合わせメソッド
520
605
  #返却値:: メッセージ送り待ちの時はtrueを返す
521
606
  def pausing?
522
- return @yuki[:pausing]
607
+ return @pausing
523
608
  end
524
609
 
525
610
  #===条件に合っていればポーズをかける
@@ -534,27 +619,99 @@ module Miyako
534
619
  return self
535
620
  end
536
621
 
622
+ #===テキストボックスに文字を表示する方法を指定する
623
+ #引数に、:charを渡すと1文字ごと、:stringを渡すと文字列ごとに表示される。それ以外を指定したときは例外が発生
624
+ #ブロックを渡せば、ブロックの評価中のみ設定が有効になる。
625
+ #ブロック評価終了後、呼び出し前の設定に戻る
626
+ #_mode_:: テキストの表示方法。:charのときは文字ごと、:stringのときは文字列ごとに表示される。それ以外を指定したときは例外が発生
627
+ #返却値:: 自分自身を返す
628
+ def text_method(mode)
629
+ raise MiyakoError, "undefined text_mode! #{mode}" unless [:char,:string].include?(mode)
630
+ backup = @text_method_name
631
+ @text_method_name = mode
632
+ if block_given?
633
+ yield
634
+ @text_method_name = backup
635
+ end
636
+ return self
637
+ end
638
+
537
639
  #===テキストボックスに文字を表示する
640
+ #テキストボックスとして用意している画像に文字を描画する。
641
+ #描画する単位(文字単位、文字列単位)によって、挙動が違う。
642
+ #(文字単位の時)
643
+ #Yuki#text_by_charメソッドと同じ挙動。
644
+ #(文字列単位の時)
645
+ #Yuki#text_by_strメソッドと同じ挙動。
646
+ #デフォルトは文字単位。
647
+ #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
648
+ #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
538
649
  #_txt_:: 表示させるテキスト
539
650
  #返却値:: 自分自身を返す
540
651
  def text(txt)
652
+ return self if txt.eql?(self)
653
+ return self if txt.empty?
654
+ return @text_methods[@text_method_name].call(txt)
655
+ end
656
+
657
+ #===テキストボックスに文字を1文字ずつ表示する
658
+ #引数txtの値は、内部で1文字ずつ分割され、1文字描画されるごとに、
659
+ #update_textメソッドが呼び出され、続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
660
+ #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
661
+ #_txt_:: 表示させるテキスト
662
+ #返却値:: 自分自身を返す
663
+ def text_by_char(txt)
541
664
  return self if txt.eql?(self)
542
665
  txt.chars{|ch|
543
666
  if /[\n\r]/.match(ch)
544
667
  next wait_by_cond(@is_outer_height)
545
- elsif @yuki[:text_box].locate.x + @yuki[:text_box].font.text_size(ch)[0] >= @yuki[:text_box].textarea.w
668
+ elsif @text_box.locate.x + @text_box.font.text_size(ch)[0] >= @text_box.textarea.w
546
669
  wait_by_cond(@is_outer_height)
547
670
  elsif /[\t\f]/.match(ch)
548
671
  next nil
549
672
  end
550
- @yuki[:text_box].draw_text(ch)
551
- @update_text.call(self)
673
+ @text_box.draw_text(ch)
674
+ @update_text.call(self, ch)
675
+ Fiber.yield
552
676
  }
553
677
  return self
554
678
  end
679
+
680
+ #===テキストボックスに文字を表示する
681
+ #文字列が描画されるごとに、update_textメソッドが呼び出され、
682
+ #続けてYuki#start_plotもしくはYuki#updateメソッド呼び出し直後に戻る
683
+ #注意として、改行が文字列中にあれば改行、タブやフィードが文字列中にあれば、nilを返す。
684
+ #_txt_:: 表示させるテキスト
685
+ #返却値:: 自分自身を返す
686
+ def text_by_str(txt)
687
+ return self if txt.eql?(self)
688
+ use_cr = false
689
+ until txt.empty? do
690
+ if /[\n\r]/.match(txt)
691
+ tmp = Regexp.last_match.pre_match
692
+ txt = Regexp.last_match.post_match
693
+ use_cr = true
694
+ elsif @text_box.locate.x + @text_box.font.text_size(txt)[0] >= @text_box.textarea.w
695
+ w = (@text_box.textarea.w - @text_box.locate.x) / @text_box.font.size
696
+ tmp = txt.slice!(0,w)
697
+ use_cr = true
698
+ elsif /[\t\f]/.match(txt)
699
+ next nil
700
+ else
701
+ tmp = txt
702
+ txt = ""
703
+ end
704
+ @text_box.draw_text(tmp)
705
+ self.cr if use_cr
706
+ @update_text.call(self, tmp)
707
+ Fiber.yield
708
+ use_cr = false
709
+ end
710
+ return self
711
+ end
555
712
 
556
713
  def is_outer_height #:nodoc:
557
- return @yuki[:text_box].locate.y + @yuki[:text_box].max_height >= @yuki[:text_box].textarea.h
714
+ return @text_box.locate.y + @text_box.max_height >= @text_box.textarea.h
558
715
  end
559
716
 
560
717
  private :is_outer_height
@@ -564,17 +721,32 @@ module Miyako
564
721
  #_color_:: 文字色
565
722
  #返却値:: 自分自身を返す
566
723
  def color(color, &block)
567
- @yuki[:text_box].color_during(Color.to_rgb(color)){ text block.call }
724
+ @text_box.color_during(Color.to_rgb(color)){ text block.call }
725
+ return self
726
+ end
727
+
728
+ #===ブロック評価中、行中の表示位置を変更する
729
+ #ブロックを評価している間だけ、デフォルトの縦の表示位置を変更する
730
+ #変更できる値は、:top、:middle、:bottomの3種類。
731
+ #ブロックを渡していないときはエラーを返す
732
+ #_valign_:: 文字の縦の位置(top, middle, bottom)
733
+ #返却値:: 自分自身を返す
734
+ def valign_during(valign)
735
+ raise MiyakoError, "Can't find block!" unless block_given?
736
+ oalign, @valign = @valign, valign
737
+ yield
738
+ @valign = oalign
568
739
  return self
569
740
  end
570
741
 
571
742
  #===文字の大きさを変更する
572
743
  #ブロック内で指定した文字列を、指定の大きさで描画する
573
744
  #_size_:: 文字の大きさ(整数)
745
+ #_valign_:: 文字の縦の位置(top, middle, bottom)。デフォルトは:middle(Yuki#valign=,Yuki#valign_duringで変更可能)
574
746
  #返却値:: 自分自身を返す
575
- def size(size, &block)
576
- @yuki[:text_box].font_size(size){
577
- @yuki[:text_box].margin_during(@yuki[:text_box].margin_height(:middle)){ text block.call }
747
+ def size(size, valign = @valign, &block)
748
+ @text_box.font_size_during(size){
749
+ @text_box.margin_during(@text_box.margin_height(valign)){ text block.call }
578
750
  }
579
751
  return self
580
752
  end
@@ -584,7 +756,7 @@ module Miyako
584
756
  #(使用すると文字の端が切れてしまう場合あり!)
585
757
  #返却値:: 自分自身を返す
586
758
  def bold(&block)
587
- @yuki[:text_box].font_bold{ text block.call }
759
+ @text_box.font_bold{ text block.call }
588
760
  return self
589
761
  end
590
762
 
@@ -593,7 +765,7 @@ module Miyako
593
765
  #(使用すると文字の端が切れてしまう場合あり!)
594
766
  #返却値:: 自分自身を返す
595
767
  def italic(&block)
596
- @yuki[:text_box].font_italic{ text block.call }
768
+ @text_box.font_italic{ text block.call }
597
769
  return self
598
770
  end
599
771
 
@@ -601,21 +773,28 @@ module Miyako
601
773
  #ブロック内で指定した文字列を下線付きで表示する
602
774
  #返却値:: 自分自身を返す
603
775
  def under_line(&block)
604
- @yuki[:text_box].font_under_line{ text block.call }
776
+ @text_box.font_under_line{ text block.call }
605
777
  return self
606
778
  end
607
779
 
608
780
  #===改行を行う
781
+ #開業後にupdate_crテンプレートメソッドが1回呼ばれる
782
+ #_tm_:: 改行回数。デフォルトは1
609
783
  #返却値:: 自分自身を返す
610
- def cr
611
- @yuki[:text_box].cr
784
+ def cr(tm = 1)
785
+ tm.times{|n|
786
+ @text_box.cr
787
+ @update_cr.call(self)
788
+ }
612
789
  return self
613
790
  end
614
791
 
615
792
  #===テキストボックスの内容を消去する
793
+ #開業後にupdate_clearテンプレートメソッドが1回呼ばれる
616
794
  #返却値:: 自分自身を返す
617
795
  def clear
618
- @yuki[:text_box].clear
796
+ @text_box.clear
797
+ @update_clear.call(self)
619
798
  return self
620
799
  end
621
800
 
@@ -623,26 +802,29 @@ module Miyako
623
802
  #ポーズが行われると、ポーズ用のカーソルが表示される
624
803
  #所定のボタンを押すとポーズが解除され、カーソルが消える
625
804
  #解除後は、プロットの続きを処理する
805
+ #引数無しのブロックを渡せば、ポーズ開始前に行いたい処理を施すことが出来る
806
+ #ポーズ中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
807
+ #Yuki#updateが呼び出されてもポーズ中の場合は、再び上記の処理を繰り返す
808
+ #(たとえば、一定時間後に自動的にポーズ解除する場合、そのタイマーを開始させるなど)
626
809
  #返却値:: 自分自身を返す
627
810
  def pause
628
- @yuki[:text_box].pause
629
- @mutex.lock
630
- @yuki[:pausing] = true
631
- @mutex.unlock
632
- while @yuki[:pausing]
811
+ @pre_pause.each{|proc| proc.call}
812
+ yield if block_given?
813
+ @text_box.pause
814
+ @pausing = true
815
+ while @pausing
633
816
  @update_inner.call(self)
634
- Thread.pass unless Thread.current.eql?(Thread.main)
817
+ Fiber.yield
635
818
  end
819
+ @post_pause.each{|proc| proc.call}
636
820
  return self
637
821
  end
638
822
 
639
823
  def pausing #:nodoc:
640
- return unless @yuki[:pause_release]
641
- @yuki[:text_box].release
642
- @mutex.lock
643
- @yuki[:pausing] = false
644
- @yuki[:pause_release] = false
645
- @mutex.unlock
824
+ return unless @pause_release
825
+ @text_box.release
826
+ @pausing = false
827
+ @pause_release = false
646
828
  end
647
829
 
648
830
  #===ポーズをかけて、テキストボックスの内容を消去する
@@ -657,67 +839,74 @@ module Miyako
657
839
  #キャンセルのときの結果も指定可能(既定ではキャンセル不可状態)
658
840
  #body_selectedをnilにした場合は、bodyと同一となる
659
841
  #body_selectedを文字列を指定した場合は、文字色が赤色になることに注意
842
+ #引数無しのブロックを渡せば、コマンド選択開始前に、決定判別・キャンセル判別に必要な前処理を施すことが出来る
843
+ #選択中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
844
+ #Yuki#updateが呼び出されても選択中の場合は、再び上記の処理を繰り返す
660
845
  #_command_list_:: 表示するコマンド群。各要素はCommand構造体の配列
661
- #_cansel_to_:: キャンセルボタンを押したときの結果。デフォルトはnil(キャンセル無効)
662
- #_chain_block_:: コマンドの表示方法。あとで書く
846
+ #_cancel_to_:: キャンセルボタンを押したときの結果。デフォルトはnil(キャンセル無効)
847
+ #_chain_block_:: コマンドの表示方法。TextBox#create_choices_chainメソッド参照
663
848
  #返却値:: 自分自身を返す
664
- def command(command_list, cansel_to = Canseled, &chain_block)
665
- raise MiyakoError, "Yuki Error! Commandbox is not selected!" unless @yuki[:command_box]
666
- @yuki[:cansel] = cansel_to
849
+ def command(command_list, cancel_to = Canceled, &chain_block)
850
+ raise MiyakoError, "Yuki Error! Commandbox is not selected!" unless @command_box
851
+ @cancel = cancel_to
667
852
 
668
853
  choices = []
669
- command_list.each{|cm| choices.push([cm[:body], cm[:body_selected], cm[:result]]) if (cm[:condition] == nil || cm[:condition].call) }
854
+ command_list.each{|cm|
855
+ if (cm[:condition] == nil || cm[:condition].call)
856
+ cm_array = [cm[:body], cm[:body_selected], cm[:result]]
857
+ methods = cm.methods
858
+ cm_array << (methods.include?(:end_select_proc) ? cm[:end_select_proc] : nil)
859
+ choices.push(cm_array)
860
+ end
861
+ }
670
862
  return self if choices.length == 0
671
863
 
672
- @yuki[:command_box].command(@yuki[:command_box].create_choices_chain(choices, &chain_block))
673
- @mutex.lock
674
- @yuki[:result] = nil
675
- @yuki[:selecting] = true
676
- @mutex.unlock
677
- while @yuki[:selecting]
864
+ @pre_command.each{|proc| proc.call}
865
+ @pre_cancel.each{|proc| proc.call}
866
+ yield if block_given?
867
+ @command_box.command(@command_box.create_choices_chain(choices, &chain_block))
868
+ @result = nil
869
+ @selecting = true
870
+ while @selecting
678
871
  @update_inner.call(self)
679
- Thread.pass unless Thread.current.eql?(Thread.main)
872
+ Fiber.yield
680
873
  end
874
+ @post_cancel.each{|proc| proc.call}
875
+ @post_command.each{|proc| proc.call}
681
876
  return self
682
877
  end
683
878
 
684
879
  def selecting #:nodoc:
685
- return unless @yuki[:selecting]
686
- exit if $miyako_debug_mode && Input.quit_or_escape?
687
- if @yuki[:command_box].selecting?
688
- if @yuki[:select_ok]
689
- @mutex.lock
690
- @yuki[:result] = @yuki[:command_box].result
691
- @mutex.unlock
692
- @yuki[:command_box].finish_command
693
- @yuki[:text_box].release
694
- @mutex.lock
695
- @yuki[:selecting] = false
696
- @mutex.unlock
697
- reset_selecting
698
- elsif @yuki[:select_cansel]
699
- @mutex.lock
700
- @yuki[:result] = @yuki[:cansel]
701
- @mutex.unlock
702
- @yuki[:command_box].finish_command
703
- @yuki[:text_box].release
704
- @mutex.lock
705
- @yuki[:selecting] = false
706
- @mutex.unlock
707
- reset_selecting
708
- elsif @yuki[:select_amount] != [0,0]
709
- @yuki[:command_box].move_cursor(*@yuki[:select_amount])
710
- reset_selecting
711
- end
880
+ return unless @selecting
881
+ return unless @command_box.selecting?
882
+ @selecting_procs.each{|sp|
883
+ sp.call(@select_ok, @select_cansel, @select_amount, @mouse_amount)
884
+ }
885
+ if @select_ok
886
+ @result = @command_box.result
887
+ @command_box.finish_command
888
+ @text_box.release
889
+ @selecting = false
890
+ reset_selecting
891
+ elsif @select_cancel
892
+ @result = @cancel
893
+ @command_box.finish_command
894
+ @text_box.release
895
+ @selecting = false
896
+ reset_selecting
897
+ elsif @select_amount != [0,0]
898
+ @command_box.move_cursor(*@select_amount)
899
+ reset_selecting
900
+ elsif @mouse_amount
901
+ @command_box.attach_cursor(*@mouse_amount.to_a)
902
+ reset_selecting
712
903
  end
713
904
  end
714
905
 
715
906
  def reset_selecting #:nodoc:
716
- @mutex.lock
717
- @yuki[:select_ok] = false
718
- @yuki[:select_cansel] = false
719
- @yuki[:select_amount] = [0, 0]
720
- @mutex.unlock
907
+ @select_ok = false
908
+ @select_cancel = false
909
+ @select_amount = [0, 0]
721
910
  end
722
911
 
723
912
  #===コマンドの選択結果を返す
@@ -726,54 +915,82 @@ module Miyako
726
915
  #プロット処理・コマンド選択が終了していないのに結果を得られるので注意!
727
916
  #返却値:: コマンドの選択結果
728
917
  def select_result
729
- return @yuki[:result]
918
+ return @result
730
919
  end
731
920
 
732
921
  #===プロットの処理を待機する
733
922
  #指定の秒数(少数可)、プロットの処理を待機する。
923
+ #待機中、update_innerメソッドを呼び出し、続けて、処理をYuki#startもしくはYuki#update呼び出し直後に戻す
924
+ #Yuki#updateが呼び出されても待機中の場合は、再び上記の処理を繰り返す
734
925
  #_length_:: 待機する長さ。単位は秒。少数可。
735
926
  #返却値:: 自分自身を返す
736
927
  def wait(length)
737
928
  @waiting_timer = WaitCounter.new(length)
738
929
  @waiting_timer.start
739
- @mutex.lock
740
- @yuki[:waiting] = true
741
- @mutex.unlock
742
- while @yuki[:waiting]
930
+ @waiting = true
931
+ while @waiting
743
932
  @update_inner.call(self)
744
- Thread.pass unless Thread.current.eql?(Thread.main)
933
+ Fiber.yield
745
934
  end
746
935
  return self
747
936
  end
748
937
 
749
938
  def waiting #:nodoc:
750
939
  return if @waiting_timer.waiting?
751
- @mutex.lock
752
- @yuki[:waiting] = false
753
- @mutex.unlock
940
+ @waiting = false
941
+ end
942
+
943
+ #===シナリオ上の括り(ページ)を実装する
944
+ #シナリオ上、「このプロットの明示的な範囲」を示すために使用する(セーブ時の再現位置の指定など)
945
+ #Yuki#select_first_pageメソッドで開始位置が指定されている場合、以下の処理を行う。
946
+ #(1)select_first_pageメソッドで指定されたページから処理する。それまでのページは無視される
947
+ #(2)開始ページを処理する前に、select_first_pageメソッドの内容をクリアする(nilに変更する)
948
+ #このメソッドはブロックが必須。ブロックがないと例外が発生する。
949
+ #_name_:: ページ名。select_first_pageメソッドは、この名前を検索する。また、now_pageメソッドの返却値でもある
950
+ #_use_pause_::ページの処理が終了した後、必ずpauseメソッドを呼び出すかどうかのフラグ。デフォルトはtrue
951
+ #返却値:: select_first_pageメソッドで指定されていないページのときはnil、指定されているページの場合は引数nameの値
952
+ def page(name, use_pause = true)
953
+ raise MiyakoError, "Yuki#page needs block!" unless block_given?
954
+ return nil if (@first_page && name != @first_page)
955
+ @first_page = nil
956
+ @now_page = name
957
+ yield
958
+ pause if use_pause
959
+ @now_page = nil
960
+ return name
754
961
  end
755
-
962
+
963
+ #===シナリオ上の現在のページを返す
964
+ #呼び出し当時、シナリオ上、pageメソッドでくくられていない場合は、nilを返す
965
+ #返却値:: ページ名
966
+ def now_page
967
+ return @now_page
968
+ end
969
+
970
+ #===プロット上の最初に実行するページを指定知る
971
+ #但し、ページ名を指定しないときはnilを指定する。
972
+ #_name_:: 最初に実行するページ名
973
+ def select_first_page(name)
974
+ @first_page = name
975
+ end
976
+
756
977
  #===インスタンスで使用しているオブジェクトを解放する
757
978
  def dispose
758
- @yuki.clear
759
- @yuki = nil
760
-
761
- @update_inner = nil
979
+ @update_inner = nil
762
980
  @update_text = nil
763
- @mutex = nil
981
+ @update_cr = nil
982
+ @update_clear = nil
983
+
984
+ @executing_fiber = nil
764
985
 
765
986
  @parts.clear
766
987
  @parts = nil
767
- @visible.clear
768
- @visible = nil
769
- @diagrams.clear
770
- @diagrams = nil
988
+ @visibles.clear
989
+ @visibles = nil
771
990
  @vars.clear
772
991
  @vars = nil
773
992
 
774
993
  @is_outer_height = nil
775
994
  end
776
-
777
- private :button
778
995
  end
779
996
  end